Changeset 22249
- Timestamp:
- 11/09/17 16:58:40 (7 years ago)
- Location:
- issm/trunk-jpl
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/classes/Elements/Element.cpp
r22239 r22249 2521 2521 2522 2522 /*Intermediary variables: {{{*/ 2523 IssmDouble isinitialized; 2524 IssmDouble zTop,dzTop,zMax,zMin,zY,dzMin; 2525 IssmDouble Tmean; 2526 IssmDouble C; 2527 IssmDouble Tz,Vz; 2523 IssmDouble isinitialized=0.0; 2524 IssmDouble zTop=0.0; 2525 IssmDouble dzTop=0.0; 2526 IssmDouble zMax=0.0; 2527 IssmDouble zMin=0.0; 2528 IssmDouble zY=0.0; 2529 IssmDouble dzMin=0.0; 2530 IssmDouble Tmean=0.0; 2531 IssmDouble C=0.0; 2532 IssmDouble Tz,Vz=0.0; 2528 2533 IssmDouble rho_ice, rho_water,aSnow,aIce; 2529 2534 IssmDouble time,dt; 2530 2535 IssmDouble t,smb_dt; 2531 2536 IssmDouble yts; 2532 IssmDouble Ta,V,dlw,dsw,P,eAir,pAir; 2537 IssmDouble Ta=0.0; 2538 IssmDouble V=0.0; 2539 IssmDouble dlw=0.0; 2540 IssmDouble dsw=0.0; 2541 IssmDouble P=0.0; 2542 IssmDouble eAir=0.0; 2543 IssmDouble pAir=0.0; 2533 2544 int aIdx=0; 2534 2545 int denIdx=0; 2535 2546 int swIdx=0; 2536 2547 IssmDouble cldFrac,t0wet, t0dry, K; 2537 IssmDouble ulw; 2538 IssmDouble netSW; 2539 IssmDouble netLW; 2540 IssmDouble lhf, shf, dayEC; 2541 IssmDouble initMass; 2542 IssmDouble sumR, sumM, sumEC, sumP, sumW,sumMassAdd; 2543 IssmDouble sumdz_add; 2544 IssmDouble sumMass,dMass; 2548 IssmDouble ulw=0.0; 2549 IssmDouble netSW=0.0; 2550 IssmDouble netLW=0.0; 2551 IssmDouble lhf=0.0; 2552 IssmDouble shf=0.0; 2553 IssmDouble dayEC=0.0; 2554 IssmDouble initMass=0.0; 2555 IssmDouble sumR=0.0; 2556 IssmDouble sumM=0.0; 2557 IssmDouble sumEC=0.0; 2558 IssmDouble sumP=0.0; 2559 IssmDouble sumW=0.0; 2560 IssmDouble sumMassAdd=0.0; 2561 IssmDouble sumdz_add=0.0; 2562 IssmDouble sumMass=0.0; 2563 IssmDouble dMass=0.0; 2545 2564 bool isgraingrowth,isalbedo,isshortwave,isthermal,isaccumulation,ismelt,isdensification,isturbulentflux; 2546 IssmDouble init_scaling ;2565 IssmDouble init_scaling=0.0; 2547 2566 2548 2567 /*}}}*/ … … 2553 2572 IssmDouble* gdn = NULL; 2554 2573 IssmDouble* gsp = NULL; 2555 IssmDouble EC = 0 ;2574 IssmDouble EC = 0.0; 2556 2575 IssmDouble* W = NULL; 2557 2576 IssmDouble* a = NULL; 2558 2577 IssmDouble* swf=NULL; 2559 2578 IssmDouble* T = NULL; 2560 IssmDouble T_bottom ;2561 IssmDouble M ;2562 IssmDouble R ;2563 IssmDouble mAdd ;2564 IssmDouble dz_add ;2565 2579 IssmDouble T_bottom = 0.0; 2580 IssmDouble M = 0.0; 2581 IssmDouble R = 0.0; 2582 IssmDouble mAdd = 0.0; 2583 IssmDouble dz_add = 0.0; 2584 2566 2585 IssmDouble* dzini=NULL; 2567 2586 IssmDouble* dini = NULL; … … 2572 2591 IssmDouble* aini = NULL; 2573 2592 IssmDouble* Tini = NULL; 2574 2575 int m ;2593 2594 int m=0; 2576 2595 int count=0; 2577 2596 /*}}}*/ … … 2606 2625 parameters->FindParam(&isturbulentflux,SmbIsturbulentfluxEnum); 2607 2626 parameters->FindParam(&init_scaling,SmbInitDensityScalingEnum); 2608 2627 2609 2628 /*}}}*/ 2610 2629 /*Retrieve inputs: {{{*/ … … 2645 2664 /*First, check that the initial structures have been setup in GEMB. If not, initialize profile variables: layer thickness dz, * density d, temperature T, etc. {{{*/ 2646 2665 if(isinitialized==0.0){ 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 // if(VerboseSmb() && this->Sid()==0)_printf0_("Snow properties initialized w DEFAULT values\n");2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 /* /!\ Default value of T can not be retrived from SMBgemb.m (like other snow properties) because don't know Tmean yet when set default values.2689 2690 2691 2692 2693 2694 2695 // if(VerboseSmb() && this->Sid()==0)_printf0_("Snow properties initialized w RESTART values\n");2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2666 if(VerboseSmb() && this->Sid()==0)_printf0_("smb core: Initializing grid\n"); 2667 //if(this->Sid()==1) for(int i=0;i<m;i++)_printf_("z[" << i << "]=" << 2668 //dz[i] << "\n"); 2669 2670 DoubleArrayInput* dz_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbDziniEnum)); _assert_(dz_input); 2671 DoubleArrayInput* d_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbDiniEnum));_assert_(d_input); 2672 DoubleArrayInput* re_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbReiniEnum));_assert_(re_input); 2673 DoubleArrayInput* gdn_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbGdniniEnum));_assert_(gdn_input); 2674 DoubleArrayInput* gsp_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbGspiniEnum));_assert_(gsp_input); 2675 DoubleInput* EC_input= dynamic_cast<DoubleInput*>(this->GetInput(SmbECiniEnum));_assert_(EC_input); 2676 DoubleArrayInput* W_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbWiniEnum));_assert_(W_input); 2677 DoubleArrayInput* a_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbAiniEnum));_assert_(a_input); 2678 DoubleArrayInput* T_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbTiniEnum));_assert_(T_input); 2679 2680 dz_input->GetValues(&dzini,&m); 2681 d_input->GetValues(&dini,&m); 2682 re_input->GetValues(&reini,&m); 2683 gdn_input->GetValues(&gdnini,&m); 2684 gsp_input->GetValues(&gspini,&m); 2685 EC_input->GetInputValue(&EC); 2686 W_input->GetValues(&Wini,&m); 2687 a_input->GetValues(&aini,&m); 2688 T_input->GetValues(&Tini,&m); 2689 2690 /*Retrive the correct value of m (without the zeroes at the end)*/ 2691 Input* Size_input=this->GetInput(SmbSizeiniEnum); _assert_(Size_input); 2692 Size_input->GetInputValue(&m); 2693 2694 if(m==2){ //Snow properties are initialized with default values. Vertical grid has to be initialized too 2695 // if(VerboseSmb() && this->Sid()==0)_printf0_("Snow properties initialized w DEFAULT values\n"); 2696 2697 /*initialize profile variables:*/ 2698 GembgridInitialize(&dz, &m, zTop, dzTop, zMax, zY); 2699 2700 d = xNewZeroInit<IssmDouble>(m); for(int i=0;i<m;i++)d[i]=dini[0]; //ice density [kg m-3] 2701 re = xNewZeroInit<IssmDouble>(m); for(int i=0;i<m;i++)re[i]=reini[0]; //set grain size to old snow [mm] 2702 gdn = xNewZeroInit<IssmDouble>(m); for(int i=0;i<m;i++)gdn[i]=gdnini[0]; //set grain dentricity to old snow 2703 gsp = xNewZeroInit<IssmDouble>(m); for(int i=0;i<m;i++)gsp[i]=gspini[0]; //set grain sphericity to old snow 2704 W = xNewZeroInit<IssmDouble>(m); for(int i=0;i<m;i++)W[i]=Wini[0]; //set water content to zero [kg m-2] 2705 a = xNewZeroInit<IssmDouble>(m); for(int i=0;i<m;i++)a[i]=aini[0]; //set albedo equal to fresh snow [fraction] 2706 T = xNewZeroInit<IssmDouble>(m); for(int i=0;i<m;i++)T[i]=Tmean; //set initial grid cell temperature to the annual mean temperature [K] 2707 /* /!\ Default value of T can not be retrived from SMBgemb.m (like other snow properties) because don't know Tmean yet when set default values. 2708 Default value of 0C given in SMBgemb.m is overwritten here with value of Tmean*/ 2709 2710 //fixed lower temperature bounday condition - T is fixed 2711 T_bottom=T[m-1]; 2712 } 2713 else{ //Retrieve snow properties from previous run. Need to provide values for all layers 2714 // if(VerboseSmb() && this->Sid()==0)_printf0_("Snow properties initialized w RESTART values\n"); 2715 2716 dz = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)dz[i]=dzini[i]; 2717 d = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)d[i]=dini[i]; 2718 re = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)re[i]=reini[i]; 2719 gdn = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)gdn[i]=gdnini[i]; 2720 gsp = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)gsp[i]=gspini[i]; 2721 W = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)W[i]=Wini[i]; 2722 a = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)a[i]=aini[i]; 2723 T = xNewZeroInit<IssmDouble>(m);for(int i=0;i<m;i++)T[i]=Tini[i]; 2724 2725 //fixed lower temperature bounday condition - T is fixed 2726 T_bottom=T[m-1]; 2727 } 2728 2729 /*Flag the initialization:*/ 2730 this->AddInput(new DoubleInput(SmbIsInitializedEnum,1.0)); 2731 } 2732 else{ 2733 /*Recover inputs: */ 2734 DoubleArrayInput* dz_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbDzEnum)); _assert_(dz_input); 2735 DoubleArrayInput* d_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbDEnum));_assert_(d_input); 2736 DoubleArrayInput* re_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbReEnum));_assert_(re_input); 2737 DoubleArrayInput* gdn_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbGdnEnum));_assert_(gdn_input); 2738 DoubleArrayInput* gsp_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbGspEnum));_assert_(gsp_input); 2739 DoubleInput* EC_input= dynamic_cast<DoubleInput*>(this->GetInput(SmbECEnum));_assert_(EC_input); 2740 DoubleArrayInput* W_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbWEnum));_assert_(W_input); 2741 DoubleArrayInput* a_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbAEnum));_assert_(a_input); 2742 DoubleArrayInput* T_input= dynamic_cast<DoubleArrayInput*>(this->GetInput(SmbTEnum));_assert_(T_input); 2743 2744 /*Recover arrays: */ 2745 dz_input->GetValues(&dz,&m); 2746 d_input->GetValues(&d,&m); 2747 re_input->GetValues(&re,&m); 2748 gdn_input->GetValues(&gdn,&m); 2749 gsp_input->GetValues(&gsp,&m); 2750 EC_input->GetInputValue(&EC); 2751 W_input->GetValues(&W,&m); 2752 a_input->GetValues(&a,&m); 2753 T_input->GetValues(&T,&m); 2754 2755 //fixed lower temperature bounday condition - T is fixed 2756 T_bottom=T[m-1]; 2757 2758 } /*}}}*/ 2740 2759 2741 2760 // determine initial mass [kg] 2742 2761 initMass=0; for(int i=0;i<m;i++) initMass += dz[i]*d[i] + W[i]; 2743 2744 2762 2763 // initialize cumulative variables 2745 2764 sumR = 0; sumM = 0; sumEC = 0; sumP = 0; sumMassAdd = 0; 2746 2765 sumdz_add=0; … … 2771 2790 2772 2791 /*Snow, firn and ice albedo:*/ 2773 if(isalbedo)albedo(a,aIdx,re,d,cldFrac,aIce, aSnow,T,W,P,EC,t0wet,t0dry,K,smb_dt, m,this->Sid());2774 2775 2792 if(isalbedo)albedo(a,aIdx,re,d,cldFrac,aIce, aSnow,T,W,P,EC,t0wet,t0dry,K,smb_dt,rho_ice,m,this->Sid()); 2793 2794 2776 2795 /*Distribution of absorbed short wave radation with depth:*/ 2777 if(isshortwave)shortwave(&swf, swIdx, aIdx, dsw, a[0], d, dz, re, m,this->Sid());2778 2796 if(isshortwave)shortwave(&swf, swIdx, aIdx, dsw, a[0], d, dz, re,rho_ice,m,this->Sid()); 2797 2779 2798 /*Calculate net shortwave [W m-2]*/ 2780 2799 netSW = cellsum(swf,m); 2781 2800 2782 2801 /*Thermal profile computation:*/ 2783 if(isthermal)thermo(&EC, T, dz, d, swf, dlw, Ta, V, eAir, pAir, W[0], smb_dt, m, Vz, Tz, this->Sid());2802 if(isthermal)thermo(&EC, T, dz, d, swf, dlw, Ta, V, eAir, pAir, W[0], smb_dt, m, Vz, Tz,rho_ice,this->Sid()); 2784 2803 2785 2804 /*Change in thickness of top cell due to evaporation/condensation assuming same density as top cell. 2786 2805 * need to fix this in case all or more of cell evaporates */ 2787 2806 dz[0] = dz[0] + EC / d[0]; 2788 2807 2789 2808 /*Add snow/rain to top grid cell adjusting cell depth, temperature and density*/ 2790 if(isaccumulation)accumulation(&T, &dz, &d, &W, &a, &re, &gdn, &gsp, &m, Ta, P, dzMin, aSnow, this->Sid());2809 if(isaccumulation)accumulation(&T, &dz, &d, &W, &a, &re, &gdn, &gsp, &m, Ta, P, dzMin, aSnow,rho_ice,this->Sid()); 2791 2810 2792 2811 /*Calculate water production, M [kg m-2] resulting from snow/ice temperature exceeding 273.15 deg K 2793 2812 * (> 0 deg C), runoff R [kg m-2] and resulting changes in density and determine wet compaction [m]*/ 2794 if(ismelt)melt(&M, &R, &mAdd, &dz_add, &T, &d, &dz, &W, &a, &re, &gdn, &gsp, &m, dzMin, zMax, zMin, zTop, this->Sid());2813 if(ismelt)melt(&M, &R, &mAdd, &dz_add, &T, &d, &dz, &W, &a, &re, &gdn, &gsp, &m, dzMin, zMax, zMin, zTop,rho_ice,this->Sid()); 2795 2814 2796 2815 /*Allow non-melt densification and determine compaction [m]*/ 2797 2816 if(isdensification)densification(d,dz, T, re, denIdx, C, smb_dt, Tmean,rho_ice,m,this->Sid()); 2798 2817 2799 2818 /*Calculate upward longwave radiation flux [W m-2] not used in energy balance. Calculated for every 2800 2819 * sub-time step in thermo equations*/ … … 2803 2822 /*Calculate net longwave [W m-2]*/ 2804 2823 netLW = dlw - ulw; 2805 2824 2806 2825 /*Calculate turbulent heat fluxes [W m-2]*/ 2807 if(isturbulentflux)turbulentFlux(&shf, &lhf, &dayEC, Ta, T[0], V, eAir, pAir, d[0], W[0], Vz, Tz, this->Sid());2808 2826 if(isturbulentflux)turbulentFlux(&shf, &lhf, &dayEC, Ta, T[0], V, eAir, pAir, d[0], W[0], Vz, Tz,rho_ice,this->Sid()); 2827 2809 2828 /*Verbose some resuls in debug mode: {{{*/ 2810 2829 if(VerboseSmb() && 0){ 2811 2830 _printf_("smb log: count[" << count << "] m[" << m << "] " 2812 << setprecision(16) << "T[" << cellsum(T,m) << "] "2813 2814 2815 2816 2817 2818 2819 2820 2821 2831 << setprecision(16) << "T[" << cellsum(T,m) << "] " 2832 << "d[" << cellsum(d,m) << "] " 2833 << "dz[" << cellsum(dz,m) << "] " 2834 << "a[" << cellsum(a,m) << "] " 2835 << "W[" << cellsum(W,m) << "] " 2836 << "re[" << cellsum(re,m) << "] " 2837 << "gdn[" << cellsum(gdn,m) << "] " 2838 << "gsp[" << cellsum(gsp,m) << "] " 2839 << "swf[" << netSW << "] " 2840 << "\n"); 2822 2841 } /*}}}*/ 2823 2842 2824 2843 /*Sum component mass changes [kg m-2]*/ 2825 2844 sumMassAdd = mAdd + sumMassAdd; … … 2841 2860 if (dMass != 0.0) _printf_("total system mass not conserved in MB function \n"); 2842 2861 #endif 2843 2862 2844 2863 /*Check bottom grid cell T is unchanged:*/ 2845 2864 if (T[m-1]!=T_bottom) _printf_("T(end)~=T_bottom" << "\n"); 2846 2865 2847 2866 /*Free ressources: */ 2848 2867 xDelete<IssmDouble>(swf); … … 2859 2878 this->AddInput(new DoubleArrayInput(SmbGspEnum,gsp,m)); 2860 2879 this->AddInput(new DoubleArrayInput(SmbTEnum,T,m)); 2861 this->AddInput(new DoubleInput(SmbECEnum,sumEC/ yts));2880 this->AddInput(new DoubleInput(SmbECEnum,sumEC/dt/rho_ice)); 2862 2881 this->AddInput(new DoubleArrayInput(SmbWEnum,W,m)); 2863 2882 this->AddInput(new DoubleArrayInput(SmbAEnum,a,m)); 2864 this->AddInput(new DoubleInput(SmbMassBalanceEnum,(sumP + sumEC -sumR)/yts)); 2865 this->AddInput(new DoubleInput(SmbRunoffEnum,sumR/yts)); 2866 this->AddInput(new DoubleInput(SmbPrecipitationEnum,sumP/yts)); 2883 this->AddInput(new DoubleInput(SmbMassBalanceEnum,(sumP + sumEC -sumR)/dt/rho_ice)); 2884 this->AddInput(new DoubleInput(SmbMeltEnum,sumM/dt/rho_ice)); 2885 this->AddInput(new DoubleInput(SmbRunoffEnum,sumR/dt/rho_ice)); 2886 this->AddInput(new DoubleInput(SmbPrecipitationEnum,sumP/dt/rho_ice)); 2867 2887 this->AddInput(new DoubleInput(SmbDz_addEnum,sumdz_add/yts)); 2868 this->AddInput(new DoubleInput(SmbM_addEnum,sumMassAdd/ yts));2888 this->AddInput(new DoubleInput(SmbM_addEnum,sumMassAdd/dt)); 2869 2889 2870 2890 /*Free allocations:{{{*/ -
issm/trunk-jpl/src/c/modules/SurfaceMassBalancex/Gembx.cpp
r22238 r22249 8 8 9 9 const double Pi = 3.141592653589793; 10 const double CtoK = 273.15; // Kelvin to Celcius conversion/ice melt. point T in K 11 const double dts = 86400.0; // Number of seconds in a day 12 13 /* Tolerances have to be defined for if loops involving some specific values 14 like densitiy of ice or melting point temp because values are "rounded" 15 (e.g rho ice = 909.99... instead of 910.0) and we don't always go into the right loop */ 16 const double Ttol = 1e-10; 17 const double Dtol = 1e-11; 18 const double Gdntol = 1e-10; 19 const double Wtol = 1e-13; 20 21 const double CI = 2102.0; // heat capacity of snow/ice (J kg-1 k-1) 22 const double LF = 0.3345E6; // latent heat of fusion (J kg-1) 23 const double LV = 2.495E6; // latent heat of vaporization (J kg-1) 24 const double LS = 2.8295E6; // latent heat of sublimation (J kg-1) 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) 10 28 11 29 void Gembx(FemModel* femmodel){ /*{{{*/ … … 25 43 26 44 /*intermediary:*/ 27 IssmDouble dgpTop; 28 int gpTop, gpBottom; 29 int i; 30 IssmDouble gp0,z0; 45 IssmDouble dgpTop=0.0; 46 int gpTop=0; 47 int gpBottom=0; 48 int i=0; 49 IssmDouble gp0=0.0; 50 IssmDouble z0=0.0; 31 51 IssmDouble* dzT=NULL; 32 52 IssmDouble* dzB=NULL; … … 101 121 102 122 // initialize 103 IssmDouble F = 0 , H=0, G=0;123 IssmDouble F = 0.0, H=0.0, G=0.0; 104 124 const IssmDouble E = 0.09; //[mm d-1] model time growth constant E 105 125 // convert T from K to ºC 106 T = T - 273.15;126 T = T - CtoK; 107 127 108 128 // temperature coefficient F 109 129 if(T>-6.0) F = 0.7 + ((T/-6.0) * 0.3); 110 if(T<=-6.0 && T>-22.0) F = 1 - ((T+6.0)/-16.0 * 0.8);130 if(T<=-6.0 && T>-22.0) F = 1.0 - ((T+6.0)/-16.0 * 0.8); 111 131 if(T<=-22.0 && T>-40.0) F = 0.2 - ((T+22.0)/-18.0 * 0.2); 112 132 … … 114 134 if(d<150.0) H=1.0; 115 135 116 if(d>=150.0 & d<400.0) H = 1 - ((d-150.0)/250.0);136 if(d>=150.0 & d<400.0) H = 1.0 - ((d-150.0)/250.0); 117 137 118 138 // temperature gradient coefficient G … … 121 141 if(dT >= 0.4 && dT < 0.5) G = 0.67 + (((dT - 0.4)/0.1) * 0.23); 122 142 if(dT >= 0.5 && dT < 0.7) G = 0.9 + (((dT - 0.5)/0.2) * 0.1); 123 if(dT >= .7 ) G = 1.0;143 if(dT >= 0.7 ) G = 1.0; 124 144 125 145 // grouped coefficient Q … … 164 184 165 185 /*intermediary: */ 166 IssmDouble dt ;186 IssmDouble dt=0.0; 167 187 IssmDouble* gsz=NULL; 168 188 IssmDouble* dT=NULL; 169 189 IssmDouble* zGPC=NULL; 170 190 IssmDouble* lwc=NULL; 171 IssmDouble Q=0 ;191 IssmDouble Q=0.0; 172 192 173 193 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" grain growth module\n"); … … 183 203 184 204 /*Convert dt from seconds to day: */ 185 dt=smb_dt/ 86400.0;205 dt=smb_dt/dts; 186 206 187 207 /*Determine liquid-water content in percentage: */ … … 189 209 190 210 //set maximum water content by mass to 9 percent (Brun, 1980) 191 for(int i=0;i<m;i++)if(lwc[i]>9.0 ) lwc[i]=9.0;211 for(int i=0;i<m;i++)if(lwc[i]>9.0-Wtol) lwc[i]=9.0; 192 212 193 213 … … 202 222 for(int i=0;i<m;i++){ 203 223 for (int j=0;j<=i;j++) zGPC[i]+=dz[j]; 204 zGPC[i]-= dz[i]/2;224 zGPC[i]-=(dz[i]/2.0); 205 225 } 206 226 … … 217 237 /*Snow metamorphism. Depends on value of snow dendricity and wetness of the snowpack: */ 218 238 for(int i=0;i<m;i++){ 219 if (gdn[i]>0 ){239 if (gdn[i]>0.0+Gdntol){ 220 240 221 241 //_printf_("Dendritic dry snow metamorphism\n"); 222 242 223 243 //index for dentricity > 0 and T gradients < 5 degC m-1 and >= 5 degC m-1 224 if(dT[i]<5.0 ){244 if(dT[i]<5.0-Ttol){ 225 245 //determine coefficients 226 246 IssmDouble A = - 2e8 * exp(-6e3 / T[i]) * dt; … … 240 260 241 261 // wet snow metamorphism 242 if(W[i]>0.0 ){262 if(W[i]>0.0+Wtol){ 243 263 244 264 //_printf_("D}ritic wet snow metamorphism\n"); … … 253 273 254 274 // dendricity and sphericity can not be > 1 or < 0 255 if (gdn[i]<0.0 )gdn[i]=0.0;256 if (gsp[i]<0.0 )gsp[i]=0.0;257 if (gdn[i]>1.0 )gdn[i]=1.0;258 if (gsp[i]>1.0 )gsp[i]=1.0;275 if (gdn[i]<0.0+Wtol)gdn[i]=0.0; 276 if (gsp[i]<0.0+Wtol)gsp[i]=0.0; 277 if (gdn[i]>1.0-Wtol)gdn[i]=1.0; 278 if (gsp[i]>1.0-Wtol)gsp[i]=1.0; 259 279 260 280 // determine new grain size (mm) 261 gsz[i] = 0.1 + (1 -gdn[i])*0.25 + (0.5-gsp[i])*0.1;281 gsz[i] = 0.1 + (1.0-gdn[i])*0.25 + (0.5-gsp[i])*0.1; 262 282 263 283 } … … 271 291 272 292 // calculate grain growth 273 gsz[i] += Q* dt;293 gsz[i] += (Q*dt); 274 294 275 295 //Wet snow metamorphism (Brun, 1989) 276 if(W[i]>0.0 ){296 if(W[i]>0.0+Wtol){ 277 297 //_printf_("Nond}ritic wet snow metamorphism\n"); 278 298 //wet rate of change coefficient 279 IssmDouble E = 1.28e-8 + (4.22e-10 * pow(lwc[i],3.0))* (dt * 86400.0); // [mm^3 s^-1]299 IssmDouble E = 1.28e-8 + (4.22e-10 * pow(lwc[i],3.0))* (dt *dts); // [mm^3 s^-1] 280 300 281 301 // calculate change in grain volume and convert to grain size … … 285 305 286 306 // grains with sphericity == 1 can not have grain sizes > 2 mm (Brun, 1992) 287 if ( gsp[i]==1.0 && gsz[i]>2.0) gsz[i]=2.0;307 if (fabs(gsp[i]-1.0)<Wtol && gsz[i]>2.0-Wtol) gsz[i]=2.0; 288 308 289 309 // grains with sphericity == 0 can not have grain sizes > 5 mm (Brun, 1992) 290 if ( gsp[i]!=1.0 && gsz[i]>5.0) gsz[i]=5.0;310 if (fabs(gsp[i]-1.0)>Wtol && gsz[i]>5.0-Wtol) gsz[i]=5.0; 291 311 } 292 312 … … 302 322 303 323 } /*}}}*/ 304 void albedo(IssmDouble* a, int aIdx, IssmDouble* re, IssmDouble* d, IssmDouble cldFrac, IssmDouble aIce, IssmDouble aSnow, IssmDouble* TK, IssmDouble* W, IssmDouble P, IssmDouble EC, IssmDouble t0wet, IssmDouble t0dry, IssmDouble K, IssmDouble dt, int m,int sid) { /*{{{*/324 void albedo(IssmDouble* a, int aIdx, IssmDouble* re, IssmDouble* d, IssmDouble cldFrac, IssmDouble aIce, IssmDouble aSnow, IssmDouble* TK, IssmDouble* W, IssmDouble P, IssmDouble EC, IssmDouble t0wet, IssmDouble t0dry, IssmDouble K, IssmDouble dt, IssmDouble dIce, int m,int sid) { /*{{{*/ 305 325 306 326 //// Calculates Snow, firn and ice albedo as a function of: … … 350 370 //some constants: 351 371 const IssmDouble dSnow = 300; // density of fresh snow [kg m-3] 352 const IssmDouble dIce = 910; // density of ice [kg m-3]353 372 354 373 if(aIdx==1){ … … 356 375 357 376 //convert effective radius to specific surface area [cm2 g-1] 358 IssmDouble S = 3.0 / ( .091 * re[0]);377 IssmDouble S = 3.0 / (0.091 * re[0]); 359 378 360 379 //determine broadband albedo 361 a[0]= 1.48 - pow(S,- .07);380 a[0]= 1.48 - pow(S,-0.07); 362 381 } 363 382 else if(aIdx==2){ … … 369 388 370 389 // convert effective radius to grain size in meters 371 IssmDouble gsz = (re[0] * 2 ) / 1000.0;390 IssmDouble gsz = (re[0] * 2.0) / 1000.0; 372 391 373 392 // spectral range: … … 398 417 // where: t0 = timescale for albedo decay 399 418 400 dt = dt / 86400; // convert from [s] to [d]419 dt = dt / dts; // convert from [s] to [d] 401 420 402 421 // initialize variables … … 414 433 // K = 7 // time scale temperature coef. (7) [d] 415 434 // W0 = 300; // 200 - 600 [mm] 416 const IssmDouble z_snow = 15 ; // 16 - 32 [mm]435 const IssmDouble z_snow = 15.0; // 16 - 32 [mm] 417 436 418 437 // determine timescale for albedo decay 419 for(int i=0;i<m;i++)if(W[i]>0 )t0[i]=t0wet; // wet snow timescale420 for(int i=0;i<m;i++)T[i]=TK[i] - 273.15; // change T from K to degC438 for(int i=0;i<m;i++)if(W[i]>0.0+Wtol)t0[i]=t0wet; // wet snow timescale 439 for(int i=0;i<m;i++)T[i]=TK[i] - CtoK; // change T from K to degC 421 440 for(int i=0;i<m;i++) t0warm[i]= fabs(T[i]) * K + t0dry; //// 'warm' snow timescale 422 for(int i=0;i<m;i++)if( W[i]==0.0 && T[i]>=-10)t0[i]= t0warm[i];423 for(int i=0;i<m;i++)if(T[i]<-10 ) t0[i] = 10 * K + t0dry; // 'cold' snow timescale441 for(int i=0;i<m;i++)if(fabs(W[i])<Wtol && T[i]>=-10.0-Ttol)t0[i]= t0warm[i]; 442 for(int i=0;i<m;i++)if(T[i]<-10.0-Ttol) t0[i] = 10.0 * K + t0dry; // 'cold' snow timescale 424 443 425 444 // calculate new albedo … … 431 450 432 451 // check if condensation occurs & if it is deposited in solid phase 433 if ( EC > 0 && T[0] < 0) P = P + (EC/dSnow) * 1000; // add cond to precip [mm]452 if ( EC > 0.0 + Dtol && T[0] < 0.0-Ttol) P = P + (EC/dSnow) * 1000.0; // add cond to precip [mm] 434 453 435 454 a[0] = aSnow - (aSnow - a[0]) * exp(-P/z_snow); … … 453 472 else if (xIsNan(a[0])) _error_("albedo == NAN\n"); 454 473 } /*}}}*/ 455 void thermo(IssmDouble* pEC, IssmDouble* T, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlwrf, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble Ws, IssmDouble dt0, int m, IssmDouble Vz, IssmDouble Tz, int sid) { /*{{{*/474 void thermo(IssmDouble* pEC, IssmDouble* T, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlwrf, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble Ws, IssmDouble dt0, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble dIce, int sid) { /*{{{*/ 456 475 457 476 /* ENGLACIAL THERMODYNAMICS*/ … … 495 514 IssmDouble* sw = NULL; 496 515 IssmDouble* dT_sw = NULL; 497 IssmDouble* lw = NULL;498 516 IssmDouble* T0 = NULL; 499 517 IssmDouble* Tu = NULL; 500 518 IssmDouble* Td = NULL; 501 519 502 IssmDouble z0; 503 IssmDouble dt; 504 IssmDouble max_fdt=0; 505 IssmDouble Ts=0; 506 IssmDouble L; 507 IssmDouble eS; 508 IssmDouble Ri=0; 509 IssmDouble coefM; 510 IssmDouble coefH; 511 IssmDouble An; 512 IssmDouble C; 513 IssmDouble shf; 514 IssmDouble SB; 515 IssmDouble CI; 516 IssmDouble ds; 517 IssmDouble dAir; 518 IssmDouble TCs; 519 IssmDouble lhf; 520 IssmDouble EC_day; 521 IssmDouble dT_turb; 522 IssmDouble turb; 523 IssmDouble ulw; 524 IssmDouble dT_ulw; 525 IssmDouble dlw; 526 IssmDouble dT_dlw; 520 IssmDouble z0=0.0; 521 IssmDouble dt=0.0; 522 IssmDouble max_fdt=0.0; 523 IssmDouble Ts=0.0; 524 IssmDouble L=0.0; 525 IssmDouble eS=0.0; 526 IssmDouble Ri=0.0; 527 IssmDouble coefM=0.0; 528 IssmDouble coefH=0.0; 529 IssmDouble An=0.0; 530 IssmDouble C=0.0; 531 IssmDouble shf=0.0; 532 IssmDouble ds=0.0; 533 IssmDouble dAir=0.0; 534 IssmDouble TCs=0.0; 535 IssmDouble lhf=0.0; 536 IssmDouble EC_day=0.0; 537 IssmDouble dT_turb=0.0; 538 IssmDouble turb=0.0; 539 IssmDouble ulw=0.0; 540 IssmDouble dT_ulw=0.0; 541 IssmDouble dlw=0.0; 542 IssmDouble dT_dlw=0.0; 527 543 528 544 /*outputs:*/ 529 IssmDouble EC ;545 IssmDouble EC=0.0; 530 546 531 547 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" thermal module\n"); 532 548 533 // INITIALIZE534 CI = 2102; // heat capacity of snow/ice (J kg-1 k-1)535 // CA = 1005; // heat capacity of air (J kg-1 k-1)536 // LF = 0.3345E6; // latent heat of fusion(J kg-1)537 // LV = 2.495E6; // latent heat of vaporization(J kg-1)538 // dIce = 910; // density of ice [kg m-3]539 // dSnow = 300; // density of snow [kg m-3]540 SB = 5.67E-8; // Stefan-Boltzmann constant [W m-2 K-4]541 542 549 ds = d[0]; // density of top grid cell 543 550 544 551 // calculated air density [kg/m3] 545 dAir = 0.029 * pAir /( 8.314* Ta);552 dAir = 0.029 * pAir /(R * Ta); 546 553 547 554 // thermal capacity of top grid cell [J/k] … … 549 556 550 557 //initialize Evaporation - Condenstation 551 EC = 0 ;558 EC = 0.0; 552 559 553 560 // check if all SW applied to surface or distributed throught subsurface … … 556 563 // SURFACE ROUGHNESS (Bougamont, 2006) 557 564 // wind/temperature surface roughness height [m] 558 if (ds < 910 && Ws == 0) z0 = 0.00012; // 0.12 mm for dry snow559 else if (ds >= 910) z0 = 0.0032; // 3.2 mm for ice565 if (ds < dIce-Dtol && fabs(Ws) < Wtol) z0 = 0.00012; // 0.12 mm for dry snow 566 else if (ds >= dIce-Dtol) z0 = 0.0032; // 3.2 mm for ice 560 567 else z0 = 0.0013; // 1.3 mm for wet snow 561 568 562 569 // if V = 0 goes to infinity therfore if V = 0 change 563 if(V< .01)V=.01;570 if(V<0.01+Dtol)V=0.01; 564 571 565 572 // Bulk-transfer coefficient for turbulent fluxes … … 574 581 575 582 // for snow and firn (density < 910 kg m-3) (Sturn et al, 1997) 576 for(int i=0;i<m;i++) if(d[i]< 910) K[i] = 0.138 - 1.01E-3 * d[i] + 3.233E-6 * (pow(d[i],2));583 for(int i=0;i<m;i++) if(d[i]<dIce-Dtol) K[i] = 0.138 - 1.01E-3 * d[i] + 3.233E-6 * (pow(d[i],2)); 577 584 578 585 // for ice (density >= 910 kg m-3) 579 for(int i=0;i<m;i++) if(d[i]>= 910) K[i] = 9.828 * exp(-5.7E-3*T[i]);586 for(int i=0;i<m;i++) if(d[i]>=dIce-Dtol) K[i] = 9.828 * exp(-5.7E-3*T[i]); 580 587 581 588 // THERMAL DIFFUSION COEFFICIENTS … … 632 639 max_fdt=f[0]; 633 640 for(int i=0;i<45;i++){ 634 if (f[i]<dt )if(f[i]>=max_fdt)max_fdt=f[i];641 if (f[i]<dt-Dtol)if(f[i]>=max_fdt-Dtol)max_fdt=f[i]; 635 642 } 636 643 dt=max_fdt; … … 641 648 Ap = xNew<IssmDouble>(m); 642 649 for(int i=0;i<m;i++){ 643 Au[i] = pow((dzU[i]/2 /KP[i] + dz[i]/2/KU[i]),-1);644 Ad[i] = pow((dzD[i]/2 /KP[i] + dz[i]/2/KD[i]),-1);650 Au[i] = pow((dzU[i]/2.0/KP[i] + dz[i]/2.0/KU[i]),-1.0); 651 Ad[i] = pow((dzD[i]/2.0/KP[i] + dz[i]/2.0/KD[i]),-1.0); 645 652 Ap[i] = (d[i]*dz[i]*CI)/dt; 646 653 } … … 653 660 Nu[i] = Au[i] / Ap[i]; 654 661 Nd[i] = Ad[i] / Ap[i]; 655 Np[i]= 1 - Nu[i] - Nd[i];662 Np[i]= 1.0 - Nu[i] - Nd[i]; 656 663 } 657 664 658 665 // specify boundary conditions: constant flux at bottom 659 Nu[m-1] = 0 ;660 Np[m-1] = 1 ;666 Nu[m-1] = 0.0; 667 Np[m-1] = 1.0; 661 668 662 669 // zero flux at surface 663 Np[0] = 1 - Nd[0];670 Np[0] = 1.0 - Nd[0]; 664 671 665 672 // Create neighbor arrays for diffusion calculations instead of a tridiagonal matrix 666 Nu[0] = 0 ;667 Nd[m-1] = 0 ;673 Nu[0] = 0.0; 674 Nd[m-1] = 0.0; 668 675 669 676 /* RADIATIVE FLUXES*/ … … 704 711 // calculated. The estimated enegy balance & melt are significanly 705 712 // less when Ts is taken as the mean of the x top grid cells. 706 Ts = (T[0] + T[1])/2 ;707 Ts = fmin( 273.15,Ts); // don't allow Ts to exceed 273.15 K (0°C)713 Ts = (T[0] + T[1])/2.0; 714 Ts = fmin(CtoK,Ts); // don't allow Ts to exceed 273.15 K (0 degC) 708 715 709 716 //TURBULENT HEAT FLUX 710 717 711 // Monin Obukhov Stability Correction718 // Monin-Obukhov Stability Correction 712 719 // Reference: 713 720 // Ohmura, A., 1982: Climate and Energy-Balance on the Arctic Tundra. … … 715 722 716 723 // calculate the Bulk Richardson Number (Ri) 717 Ri = (2 *9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2.0));724 Ri = (2.0*9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2.0)); 718 725 719 // calculate Monin- Obukhov stability factors 'coefM' and 'coefH'726 // calculate Monin-Obukhov stability factors 'coefM' and 'coefH' 720 727 721 728 // do not allow Ri to exceed 0.19 … … 723 730 724 731 // calculate momentum 'coefM' stability factor 725 if (Ri > 0 ){732 if (Ri > 0.0+Ttol){ 726 733 // if stable 727 coefM = 1 /(1-5.2*Ri);734 coefM = 1.0/(1.0-5.2*Ri); 728 735 } 729 736 else { 730 coefM =pow (1 -18*Ri,-0.25);737 coefM =pow (1.0-18*Ri,-0.25); 731 738 } 732 739 733 740 // calculate heat/wind 'coef_H' stability factor 734 if (Ri < -0.03 ) coefH = 1.3 * coefM;741 if (Ri < -0.03-Ttol) coefH = 1.3 * coefM; 735 742 else coefH = coefM; 736 743 737 744 //// Sensible Heat 738 745 // calculate the sensible heat flux [W m-2](Patterson, 1998) 739 shf = C * 1005* (Ta - Ts);746 shf = C * CA * (Ta - Ts); 740 747 741 748 // adjust using MoninObukhov stability theory … … 744 751 //// Latent Heat 745 752 // determine if snow pack is melting & calcualte surface vapour pressure over ice or liquid water 746 if (Ts >= 273.15){747 L = 2.495E6;753 if (Ts >= CtoK-Ttol){ 754 L = LV; 748 755 749 756 // for an ice surface Murphy and Koop, 2005 [Equation 7] … … 751 758 } 752 759 else{ 753 L = 2.8295E6; // latent heat of sublimation for liquid surface (assume liquid on surface when Ts == 0 deg C)760 L = LS; // latent heat of sublimation for liquid surface (assume liquid on surface when Ts == 0 deg C) 754 761 // Wright (1997), US Meteorological Handbook from Murphy and Koop, 2005 Appendix A 755 eS = 611.21 * exp(17.502 * (Ts - 273.15) / (240.97 + Ts - 273.15));762 eS = 611.21 * exp(17.502 * (Ts - CtoK) / (240.97 + Ts - CtoK)); 756 763 } 757 764 … … 759 766 lhf = C * L * (eAir - eS) * 0.622 / pAir; 760 767 761 // adjust using Monin Obukhov stability theory (if lhf '+' then there is energy and mass gained at the surface,768 // adjust using Monin-Obukhov stability theory (if lhf '+' then there is energy and mass gained at the surface, 762 769 // if '-' then there is mass and energy loss at the surface. 763 770 lhf = lhf / (coefM * coefH); 764 771 765 772 //mass loss (-)/acreation(+) due to evaporation/condensation [kg] 766 EC_day = lhf * 86400/ L;773 EC_day = lhf * dts / L; 767 774 768 775 // temperature change due turbulent fluxes … … 787 794 788 795 // calculate cumulative evaporation (+)/condensation(-) 789 EC = EC + (EC_day/ 86400)*dt;796 EC = EC + (EC_day/dts)*dt; 790 797 791 798 /* CHECK FOR ENERGY (E) CONSERVATION [UNITS: J] … … 819 826 xDelete<IssmDouble>(sw); 820 827 xDelete<IssmDouble>(dT_sw); 821 xDelete<IssmDouble>(lw);822 828 xDelete<IssmDouble>(T0); 823 829 xDelete<IssmDouble>(Tu); … … 829 835 830 836 } /*}}}*/ 831 void shortwave(IssmDouble** pswf, int swIdx, int aIdx, IssmDouble dsw, IssmDouble as, IssmDouble* d, IssmDouble* dz, IssmDouble* re, int m, int sid){ /*{{{*/837 void shortwave(IssmDouble** pswf, int swIdx, int aIdx, IssmDouble dsw, IssmDouble as, IssmDouble* d, IssmDouble* dz, IssmDouble* re, IssmDouble dIce, int m, int sid){ /*{{{*/ 832 838 833 839 // DISTRIBUTES ABSORBED SHORTWAVE RADIATION WITHIN SNOW/ICE … … 865 871 866 872 // calculate surface shortwave radiation fluxes [W m-2] 867 swf[0] = (1 - as) * dsw;873 swf[0] = (1.0 - as) * dsw; 868 874 } 869 875 else{ // sw radation is absorbed at depth within the glacier … … 884 890 // convert effective radius [mm] to grain size [m] 885 891 gsz=xNew<IssmDouble>(m); 886 for(int i=0;i<m;i++) gsz[i]= (re[i] * 2 ) / 1000;892 for(int i=0;i<m;i++) gsz[i]= (re[i] * 2.0) / 1000.0; 887 893 888 894 // Spectral fractions [0.3-0.8um 0.8-1.5um 1.5-2.8um] … … 894 900 B2_cum=xNew<IssmDouble>(m+1); 895 901 for(int i=0;i<m+1;i++){ 896 B1_cum[i]=1 ;897 B2_cum[i]=1 ;902 B1_cum[i]=1.0; 903 B2_cum[i]=1.0; 898 904 } 899 905 … … 901 907 // spectral albedos: 902 908 // 0.3 - 0.8um 903 IssmDouble a0 = fmin(0.98, 1 - 1.58 *pow(gsz[0],0.5));909 IssmDouble a0 = fmin(0.98, 1.0 - 1.58 *pow(gsz[0],0.5)); 904 910 // 0.8 - 1.5um 905 IssmDouble a1 = fmax(0 , 0.95 - 15.4 *pow(gsz[0],0.5));911 IssmDouble a1 = fmax(0.0, 0.95 - 15.4 *pow(gsz[0],0.5)); 906 912 // 1.5 - 2.8um 907 913 IssmDouble a2 = fmax(0.127, 0.88 + 346.3*gsz[0] - 32.31*pow(gsz[0],0.5)); … … 909 915 // separate net shortwave radiative flux into spectral ranges 910 916 IssmDouble swfS[3]; 911 swfS[0] = (sF[0] * dsw) * (1 - a0);912 swfS[1] = (sF[1] * dsw) * (1 - a1);913 swfS[2] = (sF[2] * dsw) * (1 - a2);917 swfS[0] = (sF[0] * dsw) * (1.0 - a0); 918 swfS[1] = (sF[1] * dsw) * (1.0 - a1); 919 swfS[2] = (sF[2] * dsw) * (1.0 - a2); 914 920 915 921 // absorption coeficient for spectral range: … … 918 924 B2 =xNew<IssmDouble>(m); 919 925 for(int i=0;i<m;i++) h[i]= d[i] /(pow(gsz[i],0.5)); 920 for(int i=0;i<m;i++) B1[i] = .0192 * h[i]; // 0.3 - 0.8um921 for(int i=0;i<m;i++) B2[i]= .1098 * h[i]; // 0.8 - 1.5um926 for(int i=0;i<m;i++) B1[i] = 0.0192 * h[i]; // 0.3 - 0.8um 927 for(int i=0;i<m;i++) B2[i]= 0.1098 * h[i]; // 0.8 - 1.5um 922 928 // B3 = +inf // 1.5 - 2.8um 923 929 … … 986 992 987 993 // calculate surface shortwave radiation fluxes [W m-2] 988 IssmDouble swf_s = SWs * (1 - as) * dsw;994 IssmDouble swf_s = SWs * (1.0 - as) * dsw; 989 995 990 996 // calculate surface shortwave radiation fluxes [W m-2] 991 IssmDouble swf_ss = (1 -SWs) * (1- as) * dsw;997 IssmDouble swf_ss = (1.0-SWs) * (1.0 - as) * dsw; 992 998 993 999 // SW allowed to penetrate into snowpack 994 IssmDouble Bs = 10 ; // snow SW extinction coefficient [m-1] (Bassford,2006)1000 IssmDouble Bs = 10.0; // snow SW extinction coefficient [m-1] (Bassford,2006) 995 1001 IssmDouble Bi = 1.3; // ice SW extinction coefficient [m-1] (Bassford,2006) 996 1002 997 1003 // calculate extinction coefficient B [m-1] vector 998 1004 B=xNew<IssmDouble>(m); 999 for(int i=0;i<m;i++) B[i] = Bs + (300 - d[i]) * ((Bs - Bi)/(910 - 300));1005 for(int i=0;i<m;i++) B[i] = Bs + (300.0 - d[i]) * ((Bs - Bi)/(dIce - 300.0)); 1000 1006 1001 1007 // cumulative extinction factor … … 1004 1010 for(int i=0;i<m;i++)exp_B[i]=exp(-B[i]*dz[i]); 1005 1011 1006 B_cum[0]=1 ;1012 B_cum[0]=1.0; 1007 1013 for(int i=0;i<m;i++){ 1008 1014 IssmDouble cum_B=exp_B[0]; … … 1032 1038 1033 1039 } /*}}}*/ 1034 void accumulation(IssmDouble** pT, IssmDouble** pdz, IssmDouble** pd, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pm, IssmDouble T_air, IssmDouble P, IssmDouble dzMin, IssmDouble aSnow, int sid){ /*{{{*/1040 void accumulation(IssmDouble** pT, IssmDouble** pdz, IssmDouble** pd, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pm, IssmDouble T_air, IssmDouble P, IssmDouble dzMin, IssmDouble aSnow, IssmDouble dIce, int sid){ /*{{{*/ 1035 1041 1036 1042 // Adds precipitation and deposition to the model grid … … 1051 1057 // MAIN FUNCTION 1052 1058 // specify constants 1053 const IssmDouble dIce = 910; // density of ice [kg m-3]1054 1059 const IssmDouble dSnow = 150; // density of snow [kg m-3] 1055 1060 const IssmDouble reNew = 0.1; // new snow grain size [mm] 1056 const IssmDouble gdnNew = 1 ; // new snow dendricity1061 const IssmDouble gdnNew = 1.0; // new snow dendricity 1057 1062 const IssmDouble gspNew = 0.5; // new snow sphericity 1058 1063 … … 1060 1065 IssmDouble* mInit=NULL; 1061 1066 bool top=true; 1062 IssmDouble mass, massinit, mass_diff; 1067 IssmDouble mass=0; 1068 IssmDouble massinit=0; 1069 IssmDouble mass_diff=0; 1063 1070 1064 1071 /*output: */ … … 1071 1078 IssmDouble* gdn=NULL; 1072 1079 IssmDouble* gsp=NULL; 1073 int m ;1080 int m=0; 1074 1081 1075 1082 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" accumulation module\n"); … … 1089 1096 mInit=xNew<IssmDouble>(m); 1090 1097 for(int i=0;i<m;i++) mInit[i]= d[i] * dz[i]; 1091 massinit=0; for(int i=0;i<m;i++)massinit+=mInit[i]; 1092 1093 if (P > 0){ 1098 massinit=0.0; 1099 for(int i=0;i<m;i++)massinit+=mInit[i]; 1100 1101 if (P > 0.0+Dtol){ 1094 1102 1095 1103 1096 if (T_air <= 273.15){ // if snow1104 if (T_air <= CtoK+Ttol){ // if snow 1097 1105 1098 1106 IssmDouble z_snow = P/dSnow; // depth of snow 1099 1107 1100 1108 // if snow depth is greater than specified min dz, new cell created 1101 if (z_snow > dzMin ){1109 if (z_snow > dzMin+Dtol){ 1102 1110 1103 1111 newcell(&T,T_air,top,m); //new cell T 1104 1112 newcell(&dz,z_snow,top,m); //new cell dz 1105 1113 newcell(&d,dSnow,top,m); //new cell d 1106 newcell(&W,0 ,top,m); //new cell W1114 newcell(&W,0.0,top,m); //new cell W 1107 1115 newcell(&a,aSnow,top,m); //new cell a 1108 1116 newcell(&re,reNew,top,m); //new cell grain size … … 1137 1145 makes the numerics easier.*/ 1138 1146 1139 IssmDouble LF = 0.3345E6; // latent heat of fusion(J kg-1)1140 IssmDouble CI = 2102; // specific heat capacity of snow/ice (J kg-1 k-1)1141 1142 1147 // grid cell adjust mass 1143 1148 mass = mInit[0] + P; … … 1151 1156 1152 1157 // if d > the density of ice, d = dIce 1153 if (d[0] > dIce ){1158 if (d[0] > dIce+Dtol){ 1154 1159 d[0] = dIce; // adjust d 1155 1160 dz[0] = mass / d[0]; // dz is adjusted to conserve mass … … 1163 1168 1164 1169 #ifndef _HAVE_ADOLC_ //avoid round operation. only check in forward mode. 1165 mass_diff = round(mass_diff * 100 )/100;1170 mass_diff = round(mass_diff * 100.0)/100.0; 1166 1171 if (mass_diff > 0) _error_("mass not conserved in accumulation function"); 1167 1172 #endif … … 1182 1187 *pm=m; 1183 1188 } /*}}}*/ 1184 void melt(IssmDouble* pM, IssmDouble* pR, IssmDouble* pmAdd, IssmDouble* pdz_add, IssmDouble** pT, IssmDouble** pd, IssmDouble** pdz, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pn, IssmDouble dzMin, IssmDouble zMax, IssmDouble zMin, IssmDouble zTop, int sid){ /*{{{*/1189 void melt(IssmDouble* pM, IssmDouble* pR, IssmDouble* pmAdd, IssmDouble* pdz_add, IssmDouble** pT, IssmDouble** pd, IssmDouble** pdz, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pn, IssmDouble dzMin, IssmDouble zMax, IssmDouble zMin, IssmDouble zTop, IssmDouble dIce, int sid){ /*{{{*/ 1185 1190 1186 1191 //// MELT ROUTINE … … 1200 1205 IssmDouble* F=NULL; 1201 1206 IssmDouble* flxDn=NULL; 1202 IssmDouble ER=0 ;1207 IssmDouble ER=0.0; 1203 1208 IssmDouble* EI=NULL; 1204 1209 IssmDouble* EW=NULL; … … 1206 1211 int* D=NULL; 1207 1212 1208 IssmDouble sumM ;1209 IssmDouble sumER ;1210 IssmDouble addE ;1211 IssmDouble mSum0 ;1212 IssmDouble sumE0 ;1213 IssmDouble mSum1 ;1214 IssmDouble sumE1 ;1215 IssmDouble dE ;1216 IssmDouble dm ;1217 IssmDouble X ;1218 IssmDouble Wi ;1213 IssmDouble sumM=0.0; 1214 IssmDouble sumER=0.0; 1215 IssmDouble addE=0.0; 1216 IssmDouble mSum0=0.0; 1217 IssmDouble sumE0=0.0; 1218 IssmDouble mSum1=0.0; 1219 IssmDouble sumE1=0.0; 1220 IssmDouble dE=0.0; 1221 IssmDouble dm=0.0; 1222 IssmDouble X=0.0; 1223 IssmDouble Wi=0.0; 1219 1224 1220 IssmDouble Ztot ;1221 IssmDouble T_bot ;1222 IssmDouble m_bot ;1223 IssmDouble dz_bot ;1224 IssmDouble d_bot ;1225 IssmDouble W_bot ;1226 IssmDouble a_bot ;1227 IssmDouble re_bot ;1228 IssmDouble gdn_bot ;1229 IssmDouble gsp_bot ;1230 IssmDouble EI_bot ;1231 IssmDouble EW_bot ;1225 IssmDouble Ztot=0.0; 1226 IssmDouble T_bot=0.0; 1227 IssmDouble m_bot=0.0; 1228 IssmDouble dz_bot=0.0; 1229 IssmDouble d_bot=0.0; 1230 IssmDouble W_bot=0.0; 1231 IssmDouble a_bot=0.0; 1232 IssmDouble re_bot=0.0; 1233 IssmDouble gdn_bot=0.0; 1234 IssmDouble gsp_bot=0.0; 1235 IssmDouble EI_bot=0.0; 1236 IssmDouble EW_bot=0.0; 1232 1237 bool top=false; 1233 1238 … … 1235 1240 IssmDouble* dzMin2=NULL; 1236 1241 IssmDouble zY2=1.025; 1237 bool lastCellFlag ;1242 bool lastCellFlag = false; 1238 1243 int X1=0; 1239 1244 int X2=0; 1240 1245 1241 int D_size ;1246 int D_size = 0; 1242 1247 1243 1248 /*outputs:*/ 1244 IssmDouble mAdd ;1245 IssmDouble dz_add ;1246 IssmDouble Rsum ;1249 IssmDouble mAdd = 0.0; 1250 IssmDouble dz_add = 0.0; 1251 IssmDouble Rsum = 0.0; 1247 1252 IssmDouble* T=*pT; 1248 1253 IssmDouble* d=*pd; … … 1254 1259 IssmDouble* gsp=*pgsp; 1255 1260 int n=*pn; 1256 IssmDouble* R= 0;1261 IssmDouble* R=NULL; 1257 1262 1258 1263 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" melt module\n"); … … 1265 1270 dW=xNew<IssmDouble>(n); 1266 1271 1267 // specify constants1268 const IssmDouble CtoK = 273.15; // clecius to Kelvin conversion1269 const IssmDouble CI = 2102; // specific heat capacity of snow/ice (J kg-1 k-1)1270 const IssmDouble LF = 0.3345E6; // latent heat of fusion(J kg-1)1271 const IssmDouble dPHC = 830; // pore hole close off density[kg m-3]1272 const IssmDouble dIce = 910; // density of ice [kg m-3]1273 1274 1272 // store initial mass [kg] and energy [J] 1275 1273 m=xNew<IssmDouble>(n); for(int i=0;i<n;i++) m[i] = dz[i]* d[i]; // grid cell mass [kg] … … 1281 1279 1282 1280 // initialize melt and runoff scalars 1283 Rsum = 0 ; // runoff [kg]1284 sumM = 0 ; // total melt [kg]1285 mAdd = 0 ; // mass added/removed to/from base of model [kg]1286 addE = 0 ; // energy added/removed to/from base of model [J]1287 dz_add=0 ; // thickness of the layer added/removed to/from base of model [m]1281 Rsum = 0.0; // runoff [kg] 1282 sumM = 0.0; // total melt [kg] 1283 mAdd = 0.0; // mass added/removed to/from base of model [kg] 1284 addE = 0.0; // energy added/removed to/from base of model [J] 1285 dz_add=0.0; // thickness of the layer added/removed to/from base of model [m] 1288 1286 1289 1287 // calculate temperature excess above 0 deg C 1290 1288 exsT=xNewZeroInit<IssmDouble>(n); 1291 for(int i=0;i<n;i++) exsT[i]= fmax(0 , T[i] - CtoK); // [K] to [°C]1289 for(int i=0;i<n;i++) exsT[i]= fmax(0.0, T[i] - CtoK); // [K] to [degC] 1292 1290 1293 1291 // new grid point center temperature, T [K] 1294 for(int i=0;i<n;i++) T[i]-=exsT[i]; 1295 1292 //for(int i=0;i<n;i++) T[i]-=exsT[i]; 1293 for(int i=0;i<n;i++) T[i]=fmin(T[i],CtoK); 1294 1296 1295 // specify irreducible water content saturation [fraction] 1297 1296 const IssmDouble Swi = 0.07; // assumed constant after Colbeck, 1974 … … 1299 1298 //// REFREEZE PORE WATER 1300 1299 // check if any pore water 1301 if (cellsum(W,n) > 0){1300 if (cellsum(W,n) >0.0+Wtol){ 1302 1301 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" pore water refreeze\n"); 1303 1302 // calculate maximum freeze amount, maxF [kg] 1304 for(int i=0;i<n;i++) maxF[i] = fmax(0 , -((T[i] - CtoK) * m[i] * CI) / LF);1303 for(int i=0;i<n;i++) maxF[i] = fmax(0.0, -((T[i] - CtoK) * m[i] * CI) / LF); 1305 1304 1306 1305 // freeze pore water and change snow/ice properties … … 1319 1318 exsW=xNew<IssmDouble>(n); 1320 1319 for(int i=0;i<n;i++){ 1321 Wi= ( 910- d[i]) * Swi * (m[i] / d[i]); // irreducible water content [kg]1322 exsW[i] = fmax(0 , W[i] - Wi); // water "squeezed" from snow [kg]1320 Wi= (dIce - d[i]) * Swi * (m[i] / d[i]); // irreducible water content [kg] 1321 exsW[i] = fmax(0.0, W[i] - Wi); // water "squeezed" from snow [kg] 1323 1322 } 1324 1323 … … 1326 1325 1327 1326 // run melt algorithm if there is melt water or excess pore water 1328 if ((cellsum(exsT,n) > 0 ) || (cellsum(exsW,n) > 0)){1327 if ((cellsum(exsT,n) > 0.0 + Ttol) || (cellsum(exsW,n) > 0.0 + Wtol)){ 1329 1328 // _printf_(""MELT OCCURS"); 1330 1329 // check to see if thermal energy exceeds energy to melt entire cell … … 1332 1331 // (maximum T of snow before entire grid cell melts is a constant 1333 1332 // LF/CI = 159.1342) 1334 surpT=xNew<IssmDouble>(n); for(int i=0;i<n;i++)surpT[i] = fmax(0 , exsT[i]- 159.1342);1335 1336 if (cellsum(surpT,n) > 0 ){1333 surpT=xNew<IssmDouble>(n); for(int i=0;i<n;i++)surpT[i] = fmax(0.0, exsT[i]- 159.1342); 1334 1335 if (cellsum(surpT,n) > 0.0 + Ttol ){ 1337 1336 // _printf_("T Surplus"); 1338 1337 // calculate surplus energy … … 1340 1339 1341 1340 int i = 0; 1342 while (cellsum(surpE,n) > 0 ){1341 while (cellsum(surpE,n) > 0.0 + Ttol){ 1343 1342 // use surplus energy to increase the temperature of lower cell 1344 1343 T[i+1] = surpE[i]/m[i+1]/CI + T[i+1]; 1345 1344 1346 exsT[i+1] = fmax(0 , T[i+1] - CtoK) + exsT[i+1];1345 exsT[i+1] = fmax(0.0, T[i+1] - CtoK) + exsT[i+1]; 1347 1346 T[i+1] = fmin(CtoK, T[i+1]); 1348 1347 1349 surpT[i+1] = fmax(0 , exsT[i+1] - 159.1342);1348 surpT[i+1] = fmax(0.0, exsT[i+1] - 159.1342); 1350 1349 surpE[i+1] = surpT[i+1] * CI * m[i+1]; 1351 1350 1352 1351 // adjust current cell properties (again 159.1342 is the max T) 1353 1352 exsT[i] = 159.1342; 1354 surpE[i] = 0 ;1353 surpE[i] = 0.0; 1355 1354 i = i + 1; 1356 1355 } … … 1362 1361 1363 1362 // calculate maximum refreeze amount, maxF [kg] 1364 for(int i=0;i<n;i++)maxF[i] = fmax(0 , -((T[i] - CtoK) * d[i] * dz[i] * CI)/ LF);1363 for(int i=0;i<n;i++)maxF[i] = fmax(0.0, -((T[i] - CtoK) * d[i] * dz[i] * CI)/ LF); 1365 1364 1366 1365 // initialize refreeze, runoff, flxDn and dW vectors [kg] … … 1368 1367 IssmDouble* R=xNewZeroInit<IssmDouble>(n); 1369 1368 1370 for(int i=0;i<n;i++)dW[i] = 0 ;1369 for(int i=0;i<n;i++)dW[i] = 0.0; 1371 1370 flxDn=xNewZeroInit<IssmDouble>(n+1); for(int i=0;i<n;i++)flxDn[i+1]=F[i]; 1372 1371 … … 1374 1373 X = 0; 1375 1374 for(int i=n-1;i>=0;i--){ 1376 if(M[i]>0 || reCast<int,IssmDouble>(exsW[i])){1375 if(M[i]>0.0+Wtol || exsW[i]>0.0+Wtol){ 1377 1376 X=i; 1378 1377 break; … … 1386 1385 1387 1386 // break loop if there is no meltwater and if depth is > mw_depth 1388 if (inM == 0 && i > X){1387 if (inM == 0.0 && i > X){ 1389 1388 break; 1390 1389 } 1391 1390 1392 1391 // if reaches impermeable ice layer all liquid water runs off (R) 1393 else if (d[i] >= dIce ){ // dPHC = pore hole close off [kg m-3]1392 else if (d[i] >= dIce-Dtol){ // dPHC = pore hole close off [kg m-3] 1394 1393 // _printf_("ICE LAYER"); 1395 1394 // no water freezes in this cell … … 1398 1397 1399 1398 m[i] = m[i] - M[i]; // mass after melt 1400 Wi = ( 910-d[i]) * Swi * (m[i]/d[i]); // irreducible water1399 Wi = (dIce-d[i]) * Swi * (m[i]/d[i]); // irreducible water 1401 1400 dW[i] = fmin(inM, Wi - W[i]); // change in pore water 1402 R[i] = fmax(0 , inM - dW[i]); // runoff1401 R[i] = fmax(0.0, inM - dW[i]); // runoff 1403 1402 } 1404 1403 // check if no energy to refreeze meltwater 1405 else if ( maxF[i] == 0){1404 else if (fabs(maxF[i]) < Dtol){ 1406 1405 // _printf_("REFREEZE == 0"); 1407 1406 // no water freezes in this cell … … 1409 1408 1410 1409 m[i] = m[i] - M[i]; // mass after melt 1411 Wi = ( 910-d[i]) * Swi * (m[i]/d[i]); // irreducible water1410 Wi = (dIce-d[i]) * Swi * (m[i]/d[i]); // irreducible water 1412 1411 dW[i] = fmin(inM, Wi-W[i]); // change in pore water 1413 flxDn[i+1] = fmax(0 , inM-dW[i]); // meltwater out1414 F[i] = 0 ; // no freeze1412 flxDn[i+1] = fmax(0.0, inM-dW[i]); // meltwater out 1413 F[i] = 0.0; // no freeze 1415 1414 } 1416 1415 // some or all meltwater refreezes … … 1426 1425 1427 1426 //-----------------------pore water----------------------------- 1428 Wi = ( 910-d[i])* Swi * dz_0; // irreducible water1427 Wi = (dIce-d[i])* Swi * dz_0; // irreducible water 1429 1428 dW[i] = fmin(inM - F1, Wi-W[i]); // change in pore water 1430 if (- dW[i]>W[i]){1431 dW[i]= W[i];1429 if (-1*dW[i]>W[i]-Wtol ){ 1430 dW[i]= -1*W[i]; 1432 1431 } 1433 IssmDouble F2 = 0 ;1434 1435 if (dW[i] < 0 ){ // excess pore water1432 IssmDouble F2 = 0.0; 1433 1434 if (dW[i] < 0.0-Wtol){ // excess pore water 1436 1435 dMax = (dIce - d[i])*dz_0; // maximum refreeze 1437 1436 IssmDouble maxF2 = fmin(dMax, maxF[i]-F1); // maximum refreeze 1438 F2 = fmin(- dW[i], maxF2); // pore water refreeze1437 F2 = fmin(-1*dW[i], maxF2); // pore water refreeze 1439 1438 m[i] = m[i] + F2; // mass after refreeze 1440 1439 d[i] = m[i]/dz_0; … … 1446 1445 1447 1446 // check if an ice layer forms 1448 if ( d[i] == dIce){1447 if (fabs(d[i] - dIce) < Dtol){ 1449 1448 // _printf_("ICE LAYER FORMS"); 1450 1449 // excess water runs off 1451 1450 R[i] = flxDn[i+1]; 1452 1451 // no water percolates to lower cell 1453 flxDn[i+1] = 0 ;1452 flxDn[i+1] = 0.0; 1454 1453 } 1455 1454 } … … 1458 1457 1459 1458 //// GRID CELL SPACING AND MODEL DEPTH 1460 for(int i=0;i<n;i++)if (W[i] < 0 ) _error_("negative pore water generated in melt equations");1459 for(int i=0;i<n;i++)if (W[i] < 0.0 - Wtol) _error_("negative pore water generated in melt equations"); 1461 1460 1462 1461 // delete all cells with zero mass … … 1465 1464 1466 1465 // delete all cells with zero mass 1467 D_size=0; for(int i=0;i<n;i++)if(m[i]!=0)D_size++; D=xNew<int>(D_size); 1466 D_size=0; for(int i=0;i<n;i++)if(m[i]!=0)D_size++; 1467 D=xNew<int>(D_size); 1468 1468 D_size=0; for(int i=0;i<n;i++)if(m[i]!=0){ D[D_size] = i; D_size++;} 1469 1469 … … 1504 1504 1505 1505 for (int i=0;i<n;i++){ 1506 if (Zcum[i]<=zTop ){1506 if (Zcum[i]<=zTop+Dtol){ 1507 1507 dzMin2[i]=dzMin; 1508 1508 } … … 1515 1515 X = 0; 1516 1516 for(int i=n-1;i>=0;i--){ 1517 if(dz[i]<dzMin2[i] ){1517 if(dz[i]<dzMin2[i]-Dtol){ 1518 1518 X=i; 1519 1519 break; … … 1531 1531 1532 1532 for (int i = 0; i<=X;i++){ 1533 if (dz [i] < dzMin2[i]){ // merge top cells1533 if (dz[i] < dzMin2[i]-Dtol){ // merge top cells 1534 1534 // _printf_("dz > dzMin * 2') 1535 1535 // adjust variables as a linearly weighted function of mass … … 1542 1542 1543 1543 // merge with underlying grid cell and delete old cell 1544 dz 1544 dz[i+1] = dz[i] + dz[i+1]; // combine cell depths 1545 1545 d[i+1] = m_new / dz[i+1]; // combine top densities 1546 1546 W[i+1] = W[i+1] + W[i]; // combine liquid water … … 1572 1572 1573 1573 // merge with underlying grid cell and delete old cell 1574 dz 1574 dz[X1] = dz[X2] + dz[X1]; // combine cell depths 1575 1575 d[X1] = m_new / dz[X1]; // combine top densities 1576 1576 W[X1] = W[X1] + W[X2]; // combine liquid water … … 1582 1582 1583 1583 // delete combined cells 1584 D_size=0; for(int i=0;i<n;i++)if(m[i]!=99999)D_size++; D=xNew<int>(D_size); 1584 D_size=0; for(int i=0;i<n;i++)if(m[i]!=99999)D_size++; 1585 D=xNew<int>(D_size); 1585 1586 D_size=0; for(int i=0;i<n;i++)if(m[i]!=99999){ D[D_size] = i; D_size++;} 1586 1587 … … 1602 1603 X=0; 1603 1604 for(int i=9;i>=0;i--){ 1604 if(dz[i]> 2 * dzMin){1605 if(dz[i]> 2.0*dzMin+Dtol){ 1605 1606 X=i; 1606 1607 break; … … 1608 1609 } 1609 1610 1610 int i=0;1611 while( i<=X){1612 if (dz [i] > dzMin *2){1611 int j=0; 1612 while(j<=X){ 1613 if (dz[j] > dzMin*2.0+Dtol){ 1613 1614 1614 1615 // _printf_("dz > dzMin * 2"); 1615 1616 // split in two 1616 cellsplit(&dz, n, i,.5);1617 cellsplit(&W, n, i,.5);1618 cellsplit(&m, n, i,.5);1619 cellsplit(&T, n, i,1.0);1620 cellsplit(&d, n, i,1.0);1621 cellsplit(&a, n, i,1.0);1622 cellsplit(&EI, n, i,1.0);1623 cellsplit(&EW, n, i,1.0);1624 cellsplit(&re, n, i,1.0);1625 cellsplit(&gdn, n, i,1.0);1626 cellsplit(&gsp, n, i,1.0);1617 cellsplit(&dz, n, j,.5); 1618 cellsplit(&W, n, j,.5); 1619 cellsplit(&m, n, j,.5); 1620 cellsplit(&T, n, j,1.0); 1621 cellsplit(&d, n, j,1.0); 1622 cellsplit(&a, n, j,1.0); 1623 cellsplit(&EI, n, j,1.0); 1624 cellsplit(&EW, n, j,1.0); 1625 cellsplit(&re, n, j,1.0); 1626 cellsplit(&gdn, n, j,1.0); 1627 cellsplit(&gsp, n, j,1.0); 1627 1628 n++; 1628 1629 X=X+1; 1629 1630 } 1630 else i++;1631 else j++; 1631 1632 } 1632 1633 … … 1637 1638 Ztot = cellsum(dz,n); 1638 1639 1639 if (Ztot < zMin ){1640 if (Ztot < zMin-Dtol){ 1640 1641 // printf("Total depth < zMin %f \n", Ztot); 1641 1642 // mass and energy to be added … … 1671 1672 n=n+1; 1672 1673 } 1673 else if (Ztot > zMax ){1674 else if (Ztot > zMax+Dtol){ 1674 1675 // printf("Total depth > zMax %f \n", Ztot); 1675 1676 // mass and energy loss … … 1710 1711 1711 1712 /*checks: */ 1712 for(int i=0;i<n;i++) if (W[i]<0 ) _error_("negative pore water generated in melt equations\n");1713 for(int i=0;i<n;i++) if (W[i]<0.0-Wtol) _error_("negative pore water generated in melt equations\n"); 1713 1714 1714 1715 /*only in forward mode! avoid round in AD mode as it is not differentiable: */ … … 1753 1754 1754 1755 } /*}}}*/ 1755 void densification(IssmDouble* d,IssmDouble* dz, IssmDouble* T, IssmDouble* re, int denIdx, IssmDouble C, IssmDouble dt, IssmDouble Tmean, IssmDouble dIce, int m, int sid){ /*{{{*/1756 void densification(IssmDouble* d,IssmDouble* dz, IssmDouble* T, IssmDouble* re, int denIdx, IssmDouble C, IssmDouble dt, IssmDouble Tmean, IssmDouble dIce, int m, int sid){ /*{{{*/ 1756 1757 1757 1758 //// THIS NEEDS TO BE DOUBLE CHECKED AS THERE SEAMS TO BE LITTLE DENSIFICATION IN THE MODEL OUTOUT [MAYBE COMPATION IS COMPNSATED FOR BY TRACES OF SNOW???] … … 1795 1796 //// MAIN FUNCTION 1796 1797 // specify constants 1797 dt = dt / 86400; // convert from [s] to [d]1798 dt = dt / dts; // convert from [s] to [d] 1798 1799 // R = 8.314 // gas constant [mol-1 K-1] 1799 1800 // Ec = 60 // activation energy for self-diffusion of water … … 1802 1803 1803 1804 /*intermediary: */ 1804 IssmDouble c0,c1,H; 1805 IssmDouble c0=0.0; 1806 IssmDouble c1=0.0; 1807 IssmDouble H=0.0; 1805 1808 1806 1809 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" densification module\n"); … … 1815 1818 1816 1819 IssmDouble* obp = xNew<IssmDouble>(m); 1817 obp[0]=0 ;1820 obp[0]=0.0; 1818 1821 for(int i=1;i<m;i++)obp[i]=cumdz[i-1]*d[i-1]; 1819 1822 … … 1826 1829 switch (denIdx){ 1827 1830 case 1: // Herron and Langway (1980) 1828 c0 = (11 * exp(-10160 / (T[i] * 8.314))) * C/1000;1829 c1 = (575 * exp(-21400 / (T[i]* 8.314))) * pow(C/1000,.5);1831 c0 = (11.0 * exp(-10160.0 / (T[i] * 8.314))) * C/1000.0; 1832 c1 = (575.0 * exp(-21400.0 / (T[i]* 8.314))) * pow(C/1000.0,.5); 1830 1833 break; 1831 1834 case 2: // Arthern et al. (2010) [semi-emperical] 1832 1835 // common variable 1833 1836 // NOTE: Ec=60000, Eg=42400 (i.e. should be in J not kJ) 1834 H = exp((-60000. /(T[i] * 8.314)) + (42400./(Tmean * 8.314))) * (C * 9.81);1837 H = exp((-60000.0/(T[i] * 8.314)) + (42400.0/(Tmean * 8.314))) * (C * 9.81); 1835 1838 c0 = 0.07 * H; 1836 1839 c1 = 0.03 * H; … … 1840 1843 1841 1844 // common variable 1842 H = exp((-60 /(T[i] * 8.314))) * obp[i] / pow(re[i]/1000,2.0);1845 H = exp((-60.0/(T[i] * 8.314))) * obp[i] / pow(re[i]/1000.0,2.0); 1843 1846 c0 = 9.2e-9 * H; 1844 1847 c1 = 3.7e-9 * H; … … 1846 1849 1847 1850 case 4: // Li and Zwally (2004) 1848 c0 = (C/dIce) * (139.21 - 0.542*Tmean)*8.36*pow( 273.15- T[i],-2.061);1851 c0 = (C/dIce) * (139.21 - 0.542*Tmean)*8.36*pow(CtoK - T[i],-2.061); 1849 1852 c1 = c0; 1850 1853 break; … … 1852 1855 case 5: // Helsen et al. (2008) 1853 1856 // common variable 1854 c0 = (C/dIce) * (76.138 - 0.28965*Tmean)*8.36*pow( 273.15- T[i],-2.061);1857 c0 = (C/dIce) * (76.138 - 0.28965*Tmean)*8.36*pow(CtoK - T[i],-2.061); 1855 1858 c1 = c0; 1856 1859 break; … … 1858 1861 1859 1862 // new snow density 1860 if(d[i] <= 550 ) d[i] = d[i] + (c0 * (dIce - d[i]) / 365* dt);1861 else d[i] = d[i] + (c1 * (dIce - d[i]) / 365 * dt);1863 if(d[i] <= 550.0+Dtol) d[i] = d[i] + (c0 * (dIce - d[i]) / 365.0 * dt); 1864 else d[i] = d[i] + (c1 * (dIce - d[i]) / 365.0 * dt); 1862 1865 1863 1866 //disp((num2str(nanmean(c0 .* (dIce - d(idx)) / 365 * dt)))) 1864 1867 1865 1868 // do not allow densities to exceed the density of ice 1866 if(d[i] >dIce)d[i]=dIce;1869 if(d[i] > dIce-Dtol) d[i]=dIce; 1867 1870 1868 1871 // calculate new grid cell length … … 1876 1879 1877 1880 } /*}}}*/ 1878 void turbulentFlux(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble Ta, IssmDouble Ts, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble ds, IssmDouble Ws, IssmDouble Vz, IssmDouble Tz, int sid){ /*{{{*/1881 void turbulentFlux(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble Ta, IssmDouble Ts, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble ds, IssmDouble Ws, IssmDouble Vz, IssmDouble Tz, IssmDouble dIce, int sid){ /*{{{*/ 1879 1882 1880 1883 //// TURBULENT HEAT FLUX … … 1899 1902 // Tz: height above ground at which temperature (T) was sampled [m] 1900 1903 1901 //// FUNCTION INITILIZATION1902 1903 // CA = 1005; // heat capacity of air (J kg-1 k-1)1904 // LF = 0.3345E6; // latent heat of fusion(J kg-1)1905 // LV = 2.495E6; // latent heat of vaporization(J kg-1)1906 // dIce = 910; // density of ice [kg m-3]1907 1908 1904 /*intermediary:*/ 1909 IssmDouble d_air; 1910 IssmDouble Ri; 1911 IssmDouble z0; 1912 IssmDouble coef_M,coef_H; 1913 IssmDouble An, C; 1914 IssmDouble L, eS; 1905 IssmDouble d_air=0.0; 1906 IssmDouble Ri=0.0; 1907 IssmDouble z0=0.0; 1908 IssmDouble coef_M=0.0; 1909 IssmDouble coef_H=0.0; 1910 IssmDouble An=0.0; 1911 IssmDouble C=0.0; 1912 IssmDouble L=0.0; 1913 IssmDouble eS=0.0; 1915 1914 1916 1915 /*output: */ 1917 IssmDouble shf, lhf, EC; 1916 IssmDouble shf=0.0; 1917 IssmDouble lhf=0.0; 1918 IssmDouble EC=0.0; 1918 1919 1919 1920 if(VerboseSmb() && sid==0 && IssmComm::GetRank()==0)_printf0_(" turbulentFlux module\n"); 1920 1921 1921 1922 // calculated air density [kg/m3] 1922 d_air = 0.029 * pAir /( 8.314* Ta);1923 d_air = 0.029 * pAir /(R * Ta); 1923 1924 1924 1925 //// Determine Surface Roughness 1925 1926 // Bougamont, 2006 1926 1927 // wind/temperature surface roughness height [m] 1927 if (ds < 910 && Ws == 0) z0 = 0.00012; // 0.12 mm for dry snow1928 else if (ds >= 910) z0 = 0.0032; // 3.2 mm for ice1928 if (ds < dIce-Dtol && fabs(Ws) < Wtol) z0 = 0.00012; // 0.12 mm for dry snow 1929 else if (ds >= dIce-Dtol) z0 = 0.0032; // 3.2 mm for ice 1929 1930 else z0 = 0.0013; // 1.3 mm for wet snow 1930 1931 1931 //// Monin Obukhov Stability Correction1932 //// Monin-Obukhov Stability Correction 1932 1933 // Reference: 1933 1934 // Ohmura, A., 1982: Climate and Energy-Balance on the Arctic Tundra. … … 1935 1936 1936 1937 // if V = 0 goes to infinity therfore if V = 0 change 1937 if(V < .01) V=.01;1938 if(V < 0.01) V=0.01; 1938 1939 1939 1940 // calculate the Bulk Richardson Number (Ri) 1940 Ri = (2 *9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2));1941 1942 // calculate Monin Obukhov stability factors 'coef_M' and 'coef_H'1941 Ri = (2.0*9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2)); 1942 1943 // calculate Monin-Obukhov stability factors 'coef_M' and 'coef_H' 1943 1944 1944 1945 // do not allow Ri to exceed 0.19 1945 if(Ri> .19)Ri= 0.19;1946 if(Ri>0.19-Ttol)Ri= 0.19; 1946 1947 1947 1948 // calculate momentum 'coef_M' stability factor 1948 if (Ri > 0 ) coef_M = pow(1-5.2*Ri,-1); // if stable1949 else coef_M = pow(1 -18*Ri,-0.25);1949 if (Ri > 0.0) coef_M = pow(1.0-5.2*Ri,-1.0); // if stable 1950 else coef_M = pow(1.0-18*Ri,-0.25); 1950 1951 1951 1952 // calculate heat/wind 'coef_H' stability factor … … 1959 1960 //// Sensible Heat 1960 1961 // calculate the sensible heat flux [W m-2](Patterson, 1998) 1961 shf = C * 1005* (Ta - Ts);1962 1963 // adjust using Monin Obukhov stability theory1962 shf = C * CA * (Ta - Ts); 1963 1964 // adjust using Monin-Obukhov stability theory 1964 1965 shf = shf / (coef_M * coef_H); 1965 1966 … … 1967 1968 // determine if snow pack is melting & calcualte surface vapour pressure 1968 1969 // over ice or liquid water 1969 if (Ts >= 273.15){1970 L = 2.495E6;1970 if (Ts >= CtoK-Ttol){ 1971 L = LV; 1971 1972 1972 1973 // for an ice surface Murphy and Koop, 2005 [Equation 7] … … 1974 1975 } 1975 1976 else{ 1976 L = 2.8295E6; // latent heat of sublimation1977 L = LS; // latent heat of sublimation 1977 1978 // for liquid surface (assume liquid on surface when Ts == 0 deg C) 1978 1979 // Wright (1997), US Meteorological Handbook from Murphy and Koop, 1979 1980 // 2005 Apendix A 1980 eS = 611.21 * exp(17.502 * (Ts - 273.15) / (240.97 + Ts - 273.15));1981 eS = 611.21 * exp(17.502 * (Ts - CtoK) / (240.97 + Ts - CtoK)); 1981 1982 } 1982 1983 … … 1984 1985 lhf = C * L * (eAir - eS) * 0.622 / pAir; 1985 1986 1986 // adjust using Monin Obukhov stability theory (if lhf '+' then there is1987 // adjust using Monin-Obukhov stability theory (if lhf '+' then there is 1987 1988 // energy and mass gained at the surface, if '-' then there is mass and 1988 1989 // energy loss at the surface. … … 1990 1991 1991 1992 // mass loss (-)/acreation(+) due to evaporation/condensation [kg] 1992 EC = lhf * 86400/ L;1993 EC = lhf * dts / L; 1993 1994 1994 1995 /*assign output poitners: */ -
issm/trunk-jpl/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp
r21469 r22249 271 271 IssmDouble h = -1.54e-5; 272 272 IssmDouble smb,smbref,anomaly,yts,z; 273 274 275 276 277 278 279 280 273 274 /* Get constants */ 275 femmodel->parameters->FindParam(&yts,ConstantsYtsEnum); 276 /*iomodel->FindConstant(&yts,"md.constants.yts");*/ 277 /*this->parameters->FindParam(&yts,ConstantsYtsEnum);*/ 278 /*Mathieu original*/ 279 /*IssmDouble smb,smbref,z;*/ 280 281 281 /*Loop over all the elements of this partition*/ 282 282 for(int i=0;i<femmodel->elements->Size();i++){ … … 298 298 anomaly = smblistref[v]; 299 299 300 301 302 303 304 305 300 /* Henning edited acc. to Riannes equations*/ 301 /* Set SMB maximum elevation, if dz = 0 -> z_critical = 1675 */ 302 z_critical = z_critical + dz; 303 304 /* Calculate smb acc. to the surface elevation z */ 305 if(z<z_critical){ 306 306 smb = a + b*z + c; 307 307 } 308 308 else{ 309 310 } 311 309 smb = (a + b*z)*(f + g*(z-z_critical) + h*(z-z_critical)*(z-z_critical)) + c; 310 } 311 312 312 /* Compute smb including anomaly, 313 313 correct for number of seconds in a year [s/yr]*/ -
issm/trunk-jpl/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h
r21469 r22249 25 25 IssmDouble Marbouty(IssmDouble T, IssmDouble d, IssmDouble dT); 26 26 void grainGrowth(IssmDouble* pre, IssmDouble* pgdn, IssmDouble* pgsp, IssmDouble* T,IssmDouble* dz,IssmDouble* d, IssmDouble* W,IssmDouble smb_dt,int m,int aIdx, int sid); 27 void albedo(IssmDouble* a,int aIdx, IssmDouble* re, IssmDouble* d, IssmDouble cldFrac, IssmDouble aIce, IssmDouble aSnow, IssmDouble* T, IssmDouble* W, IssmDouble P, IssmDouble EC, IssmDouble t0wet, IssmDouble t0dry, IssmDouble K, IssmDouble dt, int m, int sid);28 void shortwave(IssmDouble** pswf, int swIdx, int aIdx, IssmDouble dsw, IssmDouble as, IssmDouble* d, IssmDouble* dz, IssmDouble* re, int m, int sid);29 void thermo(IssmDouble* pEC, IssmDouble* T, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlw, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble Ws, IssmDouble dt0, int m, IssmDouble Vz, IssmDouble Tz, int sid);30 void accumulation(IssmDouble** pT, IssmDouble** pdz, IssmDouble** pd, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pm, IssmDouble Ta, IssmDouble P, IssmDouble dzMin, IssmDouble aSnow, int sid);31 void melt(IssmDouble* pM, IssmDouble* pR, IssmDouble* pmAdd, IssmDouble* pdz_add, IssmDouble** pT, IssmDouble** pd, IssmDouble** pdz, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pn, IssmDouble dzMin, IssmDouble zMax, IssmDouble zMin, IssmDouble zTop, int sid);32 void densification(IssmDouble* d,IssmDouble* dz, IssmDouble* T, IssmDouble* re, int denIdx, IssmDouble C, IssmDouble dt, IssmDouble Tmean, IssmDouble rho_ice,int m, int sid);33 void turbulentFlux(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble Ta, IssmDouble Ts, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble ds, IssmDouble Ws, IssmDouble Vz, IssmDouble Tz, int sid);27 void albedo(IssmDouble* a,int aIdx, IssmDouble* re, IssmDouble* d, IssmDouble cldFrac, IssmDouble aIce, IssmDouble aSnow, IssmDouble* T, IssmDouble* W, IssmDouble P, IssmDouble EC, IssmDouble t0wet, IssmDouble t0dry, IssmDouble K, IssmDouble dt, IssmDouble dIce, int m, int sid); 28 void shortwave(IssmDouble** pswf, int swIdx, int aIdx, IssmDouble dsw, IssmDouble as, IssmDouble* d, IssmDouble* dz, IssmDouble* re, IssmDouble dIce, int m, int sid); 29 void thermo(IssmDouble* pEC, IssmDouble* T, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlw, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble Ws, IssmDouble dt0, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble dIce, int sid); 30 void accumulation(IssmDouble** pT, IssmDouble** pdz, IssmDouble** pd, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pm, IssmDouble Ta, IssmDouble P, IssmDouble dzMin, IssmDouble aSnow, IssmDouble dIce, int sid); 31 void melt(IssmDouble* pM, IssmDouble* pR, IssmDouble* pmAdd, IssmDouble* pdz_add, IssmDouble** pT, IssmDouble** pd, IssmDouble** pdz, IssmDouble** pW, IssmDouble** pa, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pn, IssmDouble dzMin, IssmDouble zMax, IssmDouble zMin, IssmDouble zTop, IssmDouble dIce, int sid); 32 void densification(IssmDouble* d,IssmDouble* dz, IssmDouble* T, IssmDouble* re, int denIdx, IssmDouble C, IssmDouble dt, IssmDouble Tmean, IssmDouble dIce, int m, int sid); 33 void turbulentFlux(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble Ta, IssmDouble Ts, IssmDouble V, IssmDouble eAir, IssmDouble pAir, IssmDouble ds, IssmDouble Ws, IssmDouble Vz, IssmDouble Tz, IssmDouble dIce, int sid); 34 34 #endif /* _SurfaceMassBalancex_H*/ -
issm/trunk-jpl/test/NightlyRun/test243.m
r21222 r22249 45 45 %Fields and tolerances to track changes 46 46 field_names ={'SmbDz','SmbT' ,'SmbD' ,'SmbRe','SmbGdn','SmbGsp','SmbA' ,'SmbEC','SmbMassBalance'}; 47 field_tolerances ={ 5e-4,5e-5,0.0006,0.0002,1e-5,0.0003,2e-5,2e-7,1e-7};47 field_tolerances ={1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12}; 48 48 49 49 field_values={...
Note:
See TracChangeset
for help on using the changeset viewer.