Changeset 23189 for issm/trunk/src/c/modules/SurfaceMassBalancex/Gembx.cpp
- Timestamp:
- 08/28/18 09:45:51 (7 years ago)
- Location:
- issm/trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk
- Property svn:mergeinfo changed
/issm/trunk-jpl merged: 22823-22871,22873-22887,22894-22903,22905-23090,23092-23185,23187
- Property svn:mergeinfo changed
-
issm/trunk/src
- Property svn:mergeinfo changed
-
issm/trunk/src/c/modules/SurfaceMassBalancex/Gembx.cpp
r22758 r23189 24 24 const double LS = 2.8295E6; // latent heat of sublimation (J kg-1) 25 25 const 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)26 const double CA = 1005.0; // heat capacity of air (J kg-1 K-1) 27 const double R = 8.314; // gas constant (J mol-1 K-1) 28 28 29 29 void Gembx(FemModel* femmodel){ /*{{{*/ … … 107 107 xDelete(dzT); 108 108 xDelete(dzB); 109 109 110 110 //---------NEED TO IMPLEMENT A PROPER GRID STRECHING ALGORITHM------------ 111 111 … … 202 202 gdn=*pgdn; 203 203 gsp=*pgsp; 204 204 205 205 /*only when aIdx = 1 or 2 do we run grainGrowth: */ 206 206 if(aIdx!=1 & aIdx!=2){ … … 220 220 //set maximum water content by mass to 9 percent (Brun, 1980) 221 221 for(int i=0;i<m;i++)if(lwc[i]>9.0-Wtol) lwc[i]=9.0; 222 223 222 224 223 /* Calculate temperature gradiant across grid cells … … 244 243 // take absolute value of temperature gradient 245 244 for(int i=0;i<m;i++)dT[i]=fabs(dT[i]); 246 245 247 246 /*Snow metamorphism. Depends on value of snow dendricity and wetness of the snowpack: */ 248 247 for(int i=0;i<m;i++){ … … 324 323 re[i]=gsz[i]/2.0; 325 324 } 326 325 327 326 /*Free ressources:*/ 328 327 xDelete<IssmDouble>(gsz); … … 348 347 //// Inputs 349 348 // aIdx = albedo method to use 350 349 351 350 // Method 0 352 351 // aValue = direct input value for albedo, override all changes to albedo … … 397 396 /*Recover pointers: */ 398 397 a=*pa; 399 398 400 399 //some constants: 401 400 const IssmDouble dSnow = 300; // density of fresh snow [kg m-3] … … 513 512 514 513 /* ENGLACIAL THERMODYNAMICS*/ 515 514 516 515 /* Description: 517 516 computes new temperature profile accounting for energy absorption and … … 537 536 // T: grid cell temperature [k] 538 537 // EC: evaporation/condensation [kg] 539 538 540 539 /*intermediary: */ 541 540 IssmDouble* K = NULL; … … 580 579 IssmDouble dlw=0.0; 581 580 IssmDouble dT_dlw=0.0; 582 581 583 582 /*outputs:*/ 584 583 IssmDouble EC=0.0; … … 597 596 //initialize Evaporation - Condenstation 598 597 EC = 0.0; 599 598 600 599 // check if all SW applied to surface or distributed throught subsurface 601 600 // swIdx = length(swf) > 1 … … 609 608 // if V = 0 goes to infinity therfore if V = 0 change 610 609 if(V<0.01-Dtol)V=0.01; 611 610 612 611 // Bulk-transfer coefficient for turbulent fluxes 613 612 An = pow(0.4,2) / pow(log(Tz/z0),2); // Bulk-transfer coefficient … … 627 626 628 627 // THERMAL DIFFUSION COEFFICIENTS 629 628 630 629 // A discretization scheme which truncates the Taylor-Series expansion 631 630 // after the 3rd term is used. See Patankar 1980, Ch. 3&4 632 631 633 632 // discretized heat equation: 634 633 635 634 // Tp = (Au*Tu° + Ad*Td° + (Ap-Au-Ad)Tp° + S) / Ap 636 635 637 636 // where neighbor coefficients Au, Ap, & Ad are 638 637 639 638 // Au = [dz_u/2KP + dz_p/2KE]^-1 640 639 // Ad = [dz_d/2KP + dz_d/2KD]^-1 … … 649 648 KD = xNew<IssmDouble>(m); 650 649 KP = xNew<IssmDouble>(m); 651 650 652 651 KU[0] = UNDEF; 653 652 KD[m-1] = UNDEF; … … 661 660 dzU[0]=UNDEF; 662 661 dzD[m-1]=UNDEF; 663 662 664 663 for(int i=1;i<m;i++) dzU[i]= dz[i-1]; 665 664 for(int i=0;i<m-1;i++) dzD[i] = dz[i+1]; … … 693 692 Ap[i] = (d[i]*dz[i]*CI)/dt; 694 693 } 695 694 696 695 // create "neighbor" coefficient matrix 697 696 Nu = xNew<IssmDouble>(m); … … 703 702 Np[i]= 1.0 - Nu[i] - Nd[i]; 704 703 } 705 704 706 705 // specify boundary conditions: constant flux at bottom 707 706 Nu[m-1] = 0.0; 708 707 Np[m-1] = 1.0; 709 708 710 709 // zero flux at surface 711 710 Np[0] = 1.0 - Nd[0]; 712 711 713 712 // Create neighbor arrays for diffusion calculations instead of a tridiagonal matrix 714 713 Nu[0] = 0.0; 715 714 Nd[m-1] = 0.0; 716 715 717 716 /* RADIATIVE FLUXES*/ 718 717 … … 720 719 sw = xNew<IssmDouble>(m); 721 720 for(int i=0;i<m;i++) sw[i]= swf[i] * dt; 722 721 723 722 // temperature change due to SW 724 723 dT_sw = xNew<IssmDouble>(m); … … 746 745 // store initial temperature 747 746 //T_init = T; 748 747 749 748 // calculate temperature of snow surface (Ts) 750 749 // when incoming SW radition is allowed to penetrate the surface, … … 754 753 Ts = (T[0] + T[1])/2.0; 755 754 Ts = fmin(CtoK,Ts); // don't allow Ts to exceed 273.15 K (0 degC) 756 755 757 756 //TURBULENT HEAT FLUX 758 757 759 758 // Monin-Obukhov Stability Correction 760 759 // Reference: … … 764 763 // calculate the Bulk Richardson Number (Ri) 765 764 Ri = (2.0*9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2.0)); 766 765 767 766 // calculate Monin-Obukhov stability factors 'coefM' and 'coefH' 768 767 769 768 // do not allow Ri to exceed 0.19 770 769 Ri = fmin(Ri, 0.19); … … 778 777 coefM =pow (1.0-18*Ri,-0.25); 779 778 } 780 779 781 780 // calculate heat/wind 'coef_H' stability factor 782 781 if (Ri <= -0.03+Ttol) coefH = coefM/1.3; 783 782 else coefH = coefM; 784 783 785 784 //// Sensible Heat 786 785 // calculate the sensible heat flux [W m-2](Patterson, 1998) … … 801 800 else{ 802 801 L = LS; // latent heat of sublimation 803 802 804 803 // for an ice surface Murphy and Koop, 2005 [Equation 7] 805 804 eS = exp(9.550426 - 5723.265/Ts + 3.53068 * log(Ts) - 0.00728332 * Ts); … … 823 822 ulw = - (SB * pow(Ts,4.0)* teValue) * dt ; 824 823 dT_ulw = ulw / TCs; 825 824 826 825 // new grid point temperature 827 826 828 827 //SW penetrates surface 829 828 for(int j=0;j<m;j++) T[j] = T[j] + dT_sw[j]; 830 829 T[0] = T[0] + dT_dlw + dT_ulw + dT_turb; 831 830 832 831 // temperature diffusion 833 832 for(int j=0;j<m;j++) T0[1+j]=T[j]; … … 835 834 for(int j=0;j<m;j++) Td[j] = T0[2+j]; 836 835 for(int j=0;j<m;j++) T[j] = (Np[j] * T[j]) + (Nu[j] * Tu[j]) + (Nd[j] * Td[j]); 837 836 838 837 // calculate cumulative evaporation (+)/condensation(-) 839 838 EC = EC + (EC_day/dts)*dt; … … 873 872 xDelete<IssmDouble>(Td); 874 873 875 876 874 /*Assign output pointers:*/ 877 875 *pEC=EC; … … 901 899 // swf = absorbed shortwave radiation [W m-2] 902 900 // 903 901 904 902 /*outputs: */ 905 903 IssmDouble* swf=NULL; … … 910 908 swf=xNewZeroInit<IssmDouble>(m); 911 909 912 913 910 // SHORTWAVE FUNCTION 914 911 if (swIdx == 0) {// all sw radation is absorbed in by the top grid cell 915 912 916 913 // calculate surface shortwave radiation fluxes [W m-2] 917 914 swf[0] = (1.0 - as) * dsw; … … 948 945 } 949 946 950 951 947 // spectral albedos: 952 948 // 0.3 - 0.8um … … 988 984 B2_cum[i+1]=cum2; 989 985 } 990 991 986 992 987 // flux across grid cell boundaries … … 1015 1010 xDelete<IssmDouble>(Qs1); 1016 1011 xDelete<IssmDouble>(Qs2); 1017 1018 1012 1019 1013 } 1020 1014 else{ //function of grid cell density … … 1144 1138 1145 1139 if (P > 0.0+Dtol){ 1146 1147 1140 1148 1141 if (T_air <= CtoK+Ttol){ // if snow … … 1210 1203 1211 1204 mass_diff = mass - massinit - P; 1212 1205 1213 1206 #ifndef _HAVE_ADOLC_ //avoid round operation. only check in forward mode. 1214 1207 mass_diff = round(mass_diff * 100.0)/100.0; … … 1253 1246 IssmDouble* M=NULL; 1254 1247 int* D=NULL; 1255 1248 1256 1249 IssmDouble sumM=0.0; 1257 1250 IssmDouble sumER=0.0; … … 1265 1258 IssmDouble X=0.0; 1266 1259 IssmDouble Wi=0.0; 1267 1260 1268 1261 IssmDouble Ztot=0.0; 1269 1262 IssmDouble T_bot=0.0; … … 1279 1272 IssmDouble EW_bot=0.0; 1280 1273 bool top=false; 1281 1274 1282 1275 IssmDouble* Zcum=NULL; 1283 1276 IssmDouble* dzMin2=NULL; … … 1286 1279 int X1=0; 1287 1280 int X2=0; 1288 1281 1289 1282 int D_size = 0; 1290 1283 … … 1303 1296 int n=*pn; 1304 1297 IssmDouble* R=NULL; 1305 1298 1306 1299 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" melt module\n"); 1307 1300 … … 1335 1328 // for(int i=0;i<n;i++) T[i]-=exsT[i]; 1336 1329 for(int i=0;i<n;i++) T[i]=fmin(T[i],CtoK); 1337 1330 1338 1331 // specify irreducible water content saturation [fraction] 1339 1332 const IssmDouble Swi = 0.07; // assumed constant after Colbeck, 1974 … … 1493 1486 T[i] = T[i] + ((F1+F2)*(LF+(CtoK - T[i])*CI)/(m[i]*CI));// change in temperature 1494 1487 1495 1496 1488 // check if an ice layer forms 1497 1489 if (fabs(d[i] - dIce) < Dtol){ … … 1505 1497 } 1506 1498 1507 1508 1499 //// GRID CELL SPACING AND MODEL DEPTH 1509 1500 for(int i=0;i<n;i++)if (W[i] < 0.0 - Wtol) _error_("negative pore water generated in melt equations"); 1510 1501 1511 1502 // delete all cells with zero mass 1512 1503 // adjust pore water … … 1533 1524 n=D_size; 1534 1525 xDelete<int>(D); 1535 1526 1536 1527 // calculate new grid lengths 1537 1528 for(int i=0;i<n;i++)dz[i] = m[i] / d[i]; … … 1545 1536 Zcum=xNew<IssmDouble>(n); 1546 1537 dzMin2=xNew<IssmDouble>(n); 1547 1538 1548 1539 Zcum[0]=dz[0]; // Compute a cumulative depth vector 1549 1540 1550 1541 for (int i=1;i<n;i++){ 1551 1542 Zcum[i]=Zcum[i-1]+dz[i]; 1552 1543 } 1553 1544 1554 1545 for (int i=0;i<n;i++){ 1555 1546 if (Zcum[i]<=zTop+Dtol){ … … 1569 1560 } 1570 1561 } 1571 1562 1572 1563 //Last cell has to be treated separately if has to be merged (no underlying cell so need to merge with overlying cell) 1573 1564 if(X==n-1){ … … 1589 1580 gdn[i+1] = (gdn[i]*m[i] + gdn[i+1]*m[i+1]) / m_new; 1590 1581 gsp[i+1] = (gsp[i]*m[i] + gsp[i+1]*m[i+1]) / m_new; 1591 1582 1592 1583 // merge with underlying grid cell and delete old cell 1593 1584 dz[i+1] = dz[i] + dz[i+1]; // combine cell depths … … 1595 1586 W[i+1] = W[i+1] + W[i]; // combine liquid water 1596 1587 m[i+1] = m_new; // combine top masses 1597 1588 1598 1589 // set cell to 99999 for deletion 1599 1590 m[i] = -99999; … … 1611 1602 } 1612 1603 } 1613 1604 1614 1605 // adjust variables as a linearly weighted function of mass 1615 1606 IssmDouble m_new = m[X2] + m[X1]; … … 1619 1610 gdn[X1] = (gdn[X2]*m[X2] + gdn[X1]*m[X1]) / m_new; 1620 1611 gsp[X1] = (gsp[X2]*m[X2] + gsp[X1]*m[X1]) / m_new; 1621 1612 1622 1613 // merge with underlying grid cell and delete old cell 1623 1614 dz[X1] = dz[X2] + dz[X1]; // combine cell depths … … 1625 1616 W[X1] = W[X1] + W[X2]; // combine liquid water 1626 1617 m[X1] = m_new; // combine top masses 1627 1618 1628 1619 // set cell to 99999 for deletion 1629 1620 m[X2] = -99999; … … 1648 1639 n=D_size; 1649 1640 xDelete<int>(D); 1650 1641 1651 1642 // check if any of the top 10 cell depths are too large 1652 1643 X=0; … … 1657 1648 } 1658 1649 } 1659 1650 1660 1651 int j=0; 1661 1652 while(j<=X){ … … 1686 1677 // calculate total model depth 1687 1678 Ztot = cellsum(dz,n); 1688 1679 1689 1680 if (Ztot < zMin-Dtol){ 1690 1681 // printf("Total depth < zMin %f \n", Ztot); … … 1692 1683 mAdd = m[n-1]+W[n-1]; 1693 1684 addE = T[n-1]*m[n-1]*CI + W[n-1]*(LF+CtoK*CI); 1694 1685 1695 1686 // add a grid cell of the same size and temperature to the bottom 1696 1687 dz_bot=dz[n-1]; … … 1705 1696 EI_bot=EI[n-1]; 1706 1697 EW_bot=EW[n-1]; 1707 1698 1708 1699 dz_add=dz_bot; 1709 1700 1710 1701 newcell(&dz,dz_bot,top,n); 1711 1702 newcell(&T,T_bot,top,n); … … 1727 1718 addE = -(T[n-1]*m[n-1]*CI) - (W[n-1]*(LF+CtoK*CI)); 1728 1719 dz_add=-(dz[n-1]); 1729 1720 1730 1721 // remove a grid cell from the bottom 1731 1722 D_size=n-1; 1732 1723 D=xNew<int>(D_size); 1733 1724 1734 1725 for(int i=0;i<n-1;i++) D[i]=i; 1735 1726 celldelete(&dz,n,D,D_size); … … 1768 1759 << "dm: " << dm << " dE: " << dE << "\n"); 1769 1760 #endif 1770 1761 1771 1762 /*Free ressources:*/ 1772 1763 if(m)xDelete<IssmDouble>(m); … … 1784 1775 xDelete<IssmDouble>(Zcum); 1785 1776 xDelete<IssmDouble>(dzMin2); 1786 1777 1787 1778 /*Assign output pointers:*/ 1788 1779 *pM=sumM; … … 1854 1845 IssmDouble c1=0.0; 1855 1846 IssmDouble H=0.0; 1847 IssmDouble M0=0.0; 1848 IssmDouble M1=0.0; 1849 IssmDouble c0arth=0.0; 1850 IssmDouble c1arth=0.0; 1856 1851 1857 1852 /*output: */ 1858 1853 IssmDouble* dz=NULL; 1859 1854 IssmDouble* d=NULL; 1860 1855 1861 1856 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" densification module\n"); 1862 1857 … … 1867 1862 // initial mass 1868 1863 IssmDouble* mass_init = xNew<IssmDouble>(m);for(int i=0;i<m;i++) mass_init[i]=d[i] * dz[i]; 1869 1864 1870 1865 /*allocations and initialization of overburden pressure and factor H: */ 1871 1866 IssmDouble* cumdz = xNew<IssmDouble>(m-1); … … 1876 1871 obp[0]=0.0; 1877 1872 for(int i=1;i<m;i++)obp[i]=cumdz[i-1]*d[i-1]; 1878 1873 1879 1874 // calculate new snow/firn density for: 1880 1875 // snow with densities <= 550 [kg m-3] 1881 1876 // snow with densities > 550 [kg m-3] 1882 1883 1877 1884 1878 for(int i=0;i<m;i++){ 1885 1879 switch (denIdx){ 1886 1880 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); 1889 1883 break; 1884 1890 1885 case 2: // Arthern et al. (2010) [semi-emperical] 1891 1886 // common variable 1892 1887 // 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); 1894 1889 c0 = 0.07 * H; 1895 1890 c1 = 0.03 * H; … … 1899 1894 1900 1895 // 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); 1902 1897 c0 = 9.2e-9 * H; 1903 1898 c1 = 3.7e-9 * H; … … 1913 1908 c0 = (C/dIce) * (76.138 - 0.28965*Tmean)*8.36*pow(CtoK - T[i],-2.061); 1914 1909 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; 1915 1932 break; 1916 1933 } … … 1977 1994 IssmDouble lhf=0.0; 1978 1995 IssmDouble EC=0.0; 1979 1996 1980 1997 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" turbulentFlux module\n"); 1981 1998 … … 2002 2019 2003 2020 // calculate Monin-Obukhov stability factors 'coef_M' and 'coef_H' 2004 2021 2005 2022 // do not allow Ri to exceed 0.19 2006 2023 Ri = fmin(Ri, 0.19); … … 2046 2063 } 2047 2064 2048 2049 2065 // Latent heat flux [W m-2] 2050 2066 lhf = C * L * (eAir - eS) * 0.622 / pAir;
Note:
See TracChangeset
for help on using the changeset viewer.