Ignore:
Timestamp:
08/28/18 09:45:51 (7 years ago)
Author:
Mathieu Morlighem
Message:

merged trunk-jpl and trunk for revision 23187

Location:
issm/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk

  • issm/trunk/src

  • issm/trunk/src/c/modules/SurfaceMassBalancex/Gembx.cpp

    r22758 r23189  
    2424const double LS = 2.8295E6;             // latent heat of sublimation (J kg-1)
    2525const double SB = 5.67E-8;                // Stefan-Boltzmann constant (W m-2 K-4)
    26 const double CA = 1005.0;                    // heat capacity of air (J kg-1 k-1)
    27 const double R = 8.314;                      // gas constant (mol-1 K-1)
     26const double CA = 1005.0;                    // heat capacity of air (J kg-1 K-1)
     27const double R = 8.314;                      // gas constant (J mol-1 K-1)
    2828
    2929void Gembx(FemModel* femmodel){  /*{{{*/
     
    107107        xDelete(dzT);
    108108        xDelete(dzB);
    109        
     109
    110110        //---------NEED TO IMPLEMENT A PROPER GRID STRECHING ALGORITHM------------
    111111
     
    202202        gdn=*pgdn;
    203203        gsp=*pgsp;
    204        
     204
    205205        /*only when aIdx = 1 or 2 do we run grainGrowth: */
    206206        if(aIdx!=1 & aIdx!=2){
     
    220220        //set maximum water content by mass to 9 percent (Brun, 1980)
    221221        for(int i=0;i<m;i++)if(lwc[i]>9.0-Wtol) lwc[i]=9.0;
    222 
    223222
    224223        /* Calculate temperature gradiant across grid cells
     
    244243        // take absolute value of temperature gradient
    245244        for(int i=0;i<m;i++)dT[i]=fabs(dT[i]);
    246        
     245
    247246        /*Snow metamorphism. Depends on value of snow dendricity and wetness of the snowpack: */
    248247        for(int i=0;i<m;i++){
     
    324323                re[i]=gsz[i]/2.0;
    325324        }
    326        
     325
    327326        /*Free ressources:*/
    328327        xDelete<IssmDouble>(gsz);
     
    348347        //// Inputs
    349348        // aIdx      = albedo method to use
    350        
     349
    351350        // Method 0
    352351        //  aValue   = direct input value for albedo, override all changes to albedo
     
    397396        /*Recover pointers: */
    398397        a=*pa;
    399        
     398
    400399        //some constants:
    401400        const IssmDouble dSnow = 300;   // density of fresh snow [kg m-3]       
     
    513512
    514513        /* ENGLACIAL THERMODYNAMICS*/
    515          
     514
    516515        /* Description:
    517516           computes new temperature profile accounting for energy absorption and
     
    537536        // T: grid cell temperature [k]
    538537        // EC: evaporation/condensation [kg]
    539        
     538
    540539        /*intermediary: */
    541540        IssmDouble* K = NULL;
     
    580579        IssmDouble dlw=0.0;
    581580        IssmDouble dT_dlw=0.0;
    582        
     581
    583582        /*outputs:*/
    584583        IssmDouble EC=0.0;
     
    597596        //initialize Evaporation - Condenstation
    598597        EC = 0.0;
    599        
     598
    600599        // check if all SW applied to surface or distributed throught subsurface
    601600        // swIdx = length(swf) > 1
     
    609608        // if V = 0 goes to infinity therfore if V = 0 change
    610609        if(V<0.01-Dtol)V=0.01;
    611        
     610
    612611        // Bulk-transfer coefficient for turbulent fluxes
    613612        An =  pow(0.4,2) / pow(log(Tz/z0),2);     // Bulk-transfer coefficient
     
    627626
    628627        // THERMAL DIFFUSION COEFFICIENTS
    629  
     628
    630629        // A discretization scheme which truncates the Taylor-Series expansion
    631630        // after the 3rd term is used. See Patankar 1980, Ch. 3&4
    632  
     631
    633632        // discretized heat equation:
    634  
     633
    635634        //                 Tp = (Au*Tu° + Ad*Td° + (Ap-Au-Ad)Tp° + S) / Ap
    636  
     635
    637636        // where neighbor coefficients Au, Ap, & Ad are
    638  
     637
    639638        //                   Au = [dz_u/2KP + dz_p/2KE]^-1
    640639        //                   Ad = [dz_d/2KP + dz_d/2KD]^-1
     
    649648        KD = xNew<IssmDouble>(m);
    650649        KP = xNew<IssmDouble>(m);
    651        
     650
    652651        KU[0] = UNDEF;
    653652        KD[m-1] = UNDEF;
     
    661660        dzU[0]=UNDEF;
    662661        dzD[m-1]=UNDEF;
    663        
     662
    664663        for(int i=1;i<m;i++) dzU[i]= dz[i-1];
    665664        for(int i=0;i<m-1;i++) dzD[i] = dz[i+1];
     
    693692                Ap[i] = (d[i]*dz[i]*CI)/dt;
    694693        }
    695        
     694
    696695        // create "neighbor" coefficient matrix
    697696        Nu = xNew<IssmDouble>(m);
     
    703702                Np[i]= 1.0 - Nu[i] - Nd[i];
    704703        }
    705        
     704
    706705        // specify boundary conditions: constant flux at bottom
    707706        Nu[m-1] = 0.0;
    708707        Np[m-1] = 1.0;
    709        
     708
    710709        // zero flux at surface
    711710        Np[0] = 1.0 - Nd[0];
    712        
     711
    713712        // Create neighbor arrays for diffusion calculations instead of a tridiagonal matrix
    714713        Nu[0] = 0.0;
    715714        Nd[m-1] = 0.0;
    716        
     715
    717716        /* RADIATIVE FLUXES*/
    718717
     
    720719        sw = xNew<IssmDouble>(m);
    721720        for(int i=0;i<m;i++) sw[i]= swf[i] * dt;
    722        
     721
    723722        // temperature change due to SW
    724723        dT_sw = xNew<IssmDouble>(m);
     
    746745                // store initial temperature
    747746                //T_init = T;
    748    
     747
    749748                // calculate temperature of snow surface (Ts)
    750749                // when incoming SW radition is allowed to penetrate the surface,
     
    754753                Ts = (T[0] + T[1])/2.0;
    755754                Ts = fmin(CtoK,Ts);    // don't allow Ts to exceed 273.15 K (0 degC)
    756                
     755
    757756                //TURBULENT HEAT FLUX
    758    
     757
    759758                // Monin-Obukhov Stability Correction
    760759                // Reference:
     
    764763                // calculate the Bulk Richardson Number (Ri)
    765764                Ri = (2.0*9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2.0));
    766                
     765
    767766                // calculate Monin-Obukhov stability factors 'coefM' and 'coefH'
    768    
     767
    769768                // do not allow Ri to exceed 0.19
    770769                Ri = fmin(Ri, 0.19);
     
    778777                        coefM =pow (1.0-18*Ri,-0.25);
    779778                }
    780                
     779
    781780                // calculate heat/wind 'coef_H' stability factor
    782781                if (Ri <= -0.03+Ttol) coefH = coefM/1.3;
    783782                else coefH = coefM;
    784                
     783
    785784                //// Sensible Heat
    786785                // calculate the sensible heat flux [W m-2](Patterson, 1998)
     
    801800                else{
    802801                        L = LS; // latent heat of sublimation
    803                        
     802
    804803                        // for an ice surface Murphy and Koop, 2005 [Equation 7]
    805804                        eS = exp(9.550426 - 5723.265/Ts + 3.53068 * log(Ts) - 0.00728332 * Ts);
     
    823822                ulw = - (SB * pow(Ts,4.0)* teValue) * dt ;
    824823                dT_ulw = ulw / TCs;
    825                
     824
    826825                // new grid point temperature
    827    
     826
    828827                //SW penetrates surface
    829828                for(int j=0;j<m;j++) T[j] = T[j] + dT_sw[j];
    830829                T[0] = T[0] + dT_dlw + dT_ulw + dT_turb;
    831                
     830
    832831                // temperature diffusion
    833832                for(int j=0;j<m;j++) T0[1+j]=T[j];
     
    835834                for(int j=0;j<m;j++) Td[j] = T0[2+j];
    836835                for(int j=0;j<m;j++) T[j] = (Np[j] * T[j]) + (Nu[j] * Tu[j]) + (Nd[j] * Td[j]);
    837                
     836
    838837                // calculate cumulative evaporation (+)/condensation(-)
    839838                EC = EC + (EC_day/dts)*dt;
     
    873872        xDelete<IssmDouble>(Td);
    874873
    875 
    876874        /*Assign output pointers:*/
    877875        *pEC=EC;
     
    901899        //   swf     = absorbed shortwave radiation [W m-2]
    902900        //
    903        
     901
    904902        /*outputs: */
    905903        IssmDouble* swf=NULL;
     
    910908        swf=xNewZeroInit<IssmDouble>(m);
    911909
    912 
    913910        // SHORTWAVE FUNCTION
    914911        if (swIdx == 0) {// all sw radation is absorbed in by the top grid cell
    915        
     912
    916913                // calculate surface shortwave radiation fluxes [W m-2]
    917914                swf[0] = (1.0 - as) * dsw;
     
    948945                        }
    949946
    950 
    951947                        // spectral albedos:
    952948                        // 0.3 - 0.8um
     
    988984                                B2_cum[i+1]=cum2;
    989985                        }
    990 
    991986
    992987                        // flux across grid cell boundaries
     
    10151010                        xDelete<IssmDouble>(Qs1);
    10161011                        xDelete<IssmDouble>(Qs2);
    1017                        
    1018                        
     1012
    10191013                }
    10201014                else{  //function of grid cell density
     
    11441138
    11451139        if (P > 0.0+Dtol){
    1146                        
    11471140
    11481141                if (T_air <= CtoK+Ttol){ // if snow
     
    12101203
    12111204                mass_diff = mass - massinit - P;
    1212                
     1205
    12131206                #ifndef _HAVE_ADOLC_  //avoid round operation. only check in forward mode.
    12141207                mass_diff = round(mass_diff * 100.0)/100.0;
     
    12531246        IssmDouble* M=NULL;
    12541247        int*       D=NULL;
    1255        
     1248
    12561249        IssmDouble sumM=0.0;
    12571250        IssmDouble sumER=0.0;
     
    12651258        IssmDouble X=0.0;
    12661259        IssmDouble Wi=0.0;
    1267    
     1260
    12681261        IssmDouble Ztot=0.0;
    12691262        IssmDouble T_bot=0.0;
     
    12791272        IssmDouble EW_bot=0.0;
    12801273        bool        top=false;
    1281    
     1274
    12821275        IssmDouble* Zcum=NULL;
    12831276        IssmDouble* dzMin2=NULL;
     
    12861279        int X1=0;
    12871280        int X2=0;
    1288    
     1281
    12891282        int        D_size = 0;
    12901283
     
    13031296        int         n=*pn;
    13041297        IssmDouble* R=NULL;
    1305        
     1298
    13061299        if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_("   melt module\n");
    13071300
     
    13351328        // for(int i=0;i<n;i++) T[i]-=exsT[i];
    13361329        for(int i=0;i<n;i++) T[i]=fmin(T[i],CtoK);
    1337        
     1330
    13381331        // specify irreducible water content saturation [fraction]
    13391332        const IssmDouble Swi = 0.07;                     // assumed constant after Colbeck, 1974
     
    14931486                                T[i] = T[i] + ((F1+F2)*(LF+(CtoK - T[i])*CI)/(m[i]*CI));// change in temperature
    14941487
    1495 
    14961488                                // check if an ice layer forms
    14971489                                if (fabs(d[i] - dIce) < Dtol){
     
    15051497                }
    15061498
    1507 
    15081499                //// GRID CELL SPACING AND MODEL DEPTH
    15091500                for(int i=0;i<n;i++)if (W[i] < 0.0 - Wtol) _error_("negative pore water generated in melt equations");
    1510                
     1501
    15111502                // delete all cells with zero mass
    15121503                // adjust pore water
     
    15331524                n=D_size;
    15341525                xDelete<int>(D);
    1535        
     1526
    15361527                // calculate new grid lengths
    15371528                for(int i=0;i<n;i++)dz[i] = m[i] / d[i];
     
    15451536        Zcum=xNew<IssmDouble>(n);
    15461537        dzMin2=xNew<IssmDouble>(n);
    1547    
     1538
    15481539        Zcum[0]=dz[0]; // Compute a cumulative depth vector
    1549    
     1540
    15501541        for (int i=1;i<n;i++){
    15511542                Zcum[i]=Zcum[i-1]+dz[i];
    15521543        }
    1553    
     1544
    15541545        for (int i=0;i<n;i++){
    15551546                if (Zcum[i]<=zTop+Dtol){
     
    15691560                }
    15701561        }
    1571    
     1562
    15721563        //Last cell has to be treated separately if has to be merged (no underlying cell so need to merge with overlying cell)
    15731564        if(X==n-1){
     
    15891580                        gdn[i+1] = (gdn[i]*m[i] + gdn[i+1]*m[i+1]) / m_new;
    15901581                        gsp[i+1] = (gsp[i]*m[i] + gsp[i+1]*m[i+1]) / m_new;
    1591            
     1582
    15921583                        // merge with underlying grid cell and delete old cell
    15931584                        dz[i+1] = dz[i] + dz[i+1];                 // combine cell depths
     
    15951586                        W[i+1] = W[i+1] + W[i];                     // combine liquid water
    15961587                        m[i+1] = m_new;                             // combine top masses
    1597            
     1588
    15981589                        // set cell to 99999 for deletion
    15991590                        m[i] = -99999;
     
    16111602                        }
    16121603                }
    1613        
     1604
    16141605                // adjust variables as a linearly weighted function of mass
    16151606                IssmDouble m_new = m[X2] + m[X1];
     
    16191610                gdn[X1] = (gdn[X2]*m[X2] + gdn[X1]*m[X1]) / m_new;
    16201611                gsp[X1] = (gsp[X2]*m[X2] + gsp[X1]*m[X1]) / m_new;
    1621        
     1612
    16221613                // merge with underlying grid cell and delete old cell
    16231614                dz[X1] = dz[X2] + dz[X1];                 // combine cell depths
     
    16251616                W[X1] = W[X1] + W[X2];                     // combine liquid water
    16261617                m[X1] = m_new;                             // combine top masses
    1627        
     1618
    16281619                // set cell to 99999 for deletion
    16291620                m[X2] = -99999;
     
    16481639        n=D_size;
    16491640        xDelete<int>(D);
    1650    
     1641
    16511642        // check if any of the top 10 cell depths are too large
    16521643        X=0;
     
    16571648                }
    16581649        }
    1659        
     1650
    16601651        int j=0;
    16611652        while(j<=X){
     
    16861677        // calculate total model depth
    16871678        Ztot = cellsum(dz,n);
    1688    
     1679
    16891680        if (Ztot < zMin-Dtol){
    16901681                // printf("Total depth < zMin %f \n", Ztot);
     
    16921683                mAdd = m[n-1]+W[n-1];
    16931684                addE = T[n-1]*m[n-1]*CI + W[n-1]*(LF+CtoK*CI);
    1694        
     1685
    16951686                // add a grid cell of the same size and temperature to the bottom
    16961687                dz_bot=dz[n-1];
     
    17051696                EI_bot=EI[n-1];
    17061697                EW_bot=EW[n-1];
    1707        
     1698
    17081699                dz_add=dz_bot;
    1709        
     1700
    17101701                newcell(&dz,dz_bot,top,n);
    17111702                newcell(&T,T_bot,top,n);
     
    17271718                addE = -(T[n-1]*m[n-1]*CI) - (W[n-1]*(LF+CtoK*CI));
    17281719                dz_add=-(dz[n-1]);
    1729        
     1720
    17301721                // remove a grid cell from the bottom
    17311722                D_size=n-1;
    17321723                D=xNew<int>(D_size);
    1733        
     1724
    17341725                for(int i=0;i<n-1;i++) D[i]=i;
    17351726                celldelete(&dz,n,D,D_size);
     
    17681759                        << "dm: " << dm << " dE: " << dE << "\n");
    17691760        #endif
    1770        
     1761
    17711762        /*Free ressources:*/
    17721763        if(m)xDelete<IssmDouble>(m);
     
    17841775        xDelete<IssmDouble>(Zcum);
    17851776        xDelete<IssmDouble>(dzMin2);
    1786    
     1777
    17871778        /*Assign output pointers:*/
    17881779        *pM=sumM;
     
    18541845        IssmDouble c1=0.0;
    18551846        IssmDouble H=0.0;
     1847        IssmDouble M0=0.0;
     1848        IssmDouble M1=0.0;
     1849        IssmDouble c0arth=0.0;
     1850        IssmDouble c1arth=0.0;
    18561851
    18571852        /*output: */
    18581853        IssmDouble* dz=NULL;
    18591854        IssmDouble* d=NULL;
    1860        
     1855
    18611856        if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_("   densification module\n");
    18621857
     
    18671862        // initial mass
    18681863        IssmDouble* mass_init = xNew<IssmDouble>(m);for(int i=0;i<m;i++) mass_init[i]=d[i] * dz[i];
    1869        
     1864
    18701865        /*allocations and initialization of overburden pressure and factor H: */
    18711866        IssmDouble* cumdz = xNew<IssmDouble>(m-1);
     
    18761871        obp[0]=0.0;
    18771872        for(int i=1;i<m;i++)obp[i]=cumdz[i-1]*d[i-1];
    1878        
     1873
    18791874        // calculate new snow/firn density for:
    18801875        //   snow with densities <= 550 [kg m-3]
    18811876        //   snow with densities > 550 [kg m-3]
    1882                
    1883        
     1877
    18841878        for(int i=0;i<m;i++){
    18851879                switch (denIdx){
    18861880                        case 1: // Herron and Langway (1980)
    1887                                 c0 = (11.0 * exp(-10160.0 / (T[i] * 8.314))) * C/1000.0;
    1888                                 c1 = (575.0 * exp(-21400.0 / (T[i]* 8.314))) * pow(C/1000.0,.5);
     1881                                c0 = (11.0 * exp(-10160.0 / (T[i] * R))) * C/1000.0;
     1882                                c1 = (575.0 * exp(-21400.0 / (T[i]* R))) * pow(C/1000.0,.5);
    18891883                                break;
     1884
    18901885                        case 2: // Arthern et al. (2010) [semi-emperical]
    18911886                                // common variable
    18921887                                // NOTE: Ec=60000, Eg=42400 (i.e. should be in J not kJ)
    1893                                 H = exp((-60000.0/(T[i] * 8.314)) + (42400.0/(Tmean * 8.314))) * (C * 9.81);
     1888                                H = exp((-60000.0/(T[i] * R)) + (42400.0/(Tmean * R))) * (C * 9.81);
    18941889                                c0 = 0.07 * H;
    18951890                                c1 = 0.03 * H;
     
    18991894
    19001895                                // common variable
    1901                                 H = exp((-60.0/(T[i] * 8.314))) * obp[i] / pow(re[i]/1000.0,2.0);
     1896                                H = exp((-60000.0/(T[i] * R))) * obp[i] / pow(re[i]/1000.0,2.0);
    19021897                                c0 = 9.2e-9 * H;
    19031898                                c1 = 3.7e-9 * H;
     
    19131908                                c0 = (C/dIce) * (76.138 - 0.28965*Tmean)*8.36*pow(CtoK - T[i],-2.061);
    19141909                                c1 = c0;
     1910                                break;
     1911
     1912                        case 6: // Ligtenberg and others (2011) [semi-emperical], Antarctica
     1913                                // common variable
     1914                                H = exp((-60000.0/(Tmean * R)) + (42400.0/(Tmean * R))) * (C * 9.81);
     1915                                c0arth = 0.07 * H;
     1916                                c1arth = 0.03 * H;
     1917                                M0 = fmax(1.435 - (0.151 * log(C)),0.25);
     1918                                M1 = fmax(2.366 - (0.293 * log(C)),0.25);
     1919                                c0 = M0*c0arth;
     1920                                c1 = M1*c1arth;
     1921                                break;
     1922
     1923                        case 7: // Kuipers Munneke and others (2015) [semi-emperical], Greenland
     1924                                // common variable
     1925                                H = exp((-60000.0/(T[i] * R)) + (42400.0/(T[i] * R))) * (C * 9.81);
     1926                                c0arth = 0.07 * H;
     1927                                c1arth = 0.03 * H;
     1928                                M0 = fmax(1.042 - (0.0916 * log(C)),0.25);
     1929                                M1 = fmax(1.734 - (0.2039 * log(C)),0.25);
     1930                                c0 = M0*c0arth;
     1931                                c1 = M1*c1arth;
    19151932                                break;
    19161933                }
     
    19771994        IssmDouble lhf=0.0;
    19781995        IssmDouble EC=0.0;
    1979        
     1996
    19801997        if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_("   turbulentFlux module\n");
    19811998
     
    20022019
    20032020        // calculate Monin-Obukhov stability factors 'coef_M' and 'coef_H'
    2004        
     2021
    20052022        // do not allow Ri to exceed 0.19
    20062023        Ri = fmin(Ri, 0.19);
     
    20462063        }
    20472064
    2048 
    20492065        // Latent heat flux [W m-2]
    20502066        lhf = C * L * (eAir - eS) * 0.622 / pAir;
Note: See TracChangeset for help on using the changeset viewer.