6 #include "../../shared/shared.h"
7 #include "../../toolkits/toolkits.h"
8 #include "../modules.h"
9 #include "../../classes/Inputs2/TransientInput2.h"
11 const double Pi = 3.141592653589793;
12 const double CtoK = 273.15;
13 const double dts = 86400.0;
24 const double CI = 2102.0;
25 const double LF = 0.3345E6;
26 const double LV = 2.495E6;
27 const double LS = 2.8295E6;
28 const double SB = 5.67E-8;
29 const double CA = 1005.0;
30 const double R = 8.314;
41 bool isclimatology=
false;
42 bool linear_interp=
true;
59 for (t=time;t<=time+dt-smb_dt;t=t+smb_dt){
73 timeend = ceil(timeend/dt)*dt;
74 if (time>time0 & timeend>time0){
75 delta=(time-time0) - (timeend-time0)*(reCast<int,IssmDouble>((time-time0)/(timeend-time0)));
79 if (linear_interp) timeinputs = t-time+timeclim;
80 else timeinputs = t-time+timeclim+smb_dt/2;
81 element->
SmbGemb(timeinputs,count);
114 #ifndef _HAVE_AD_ //avoid the round operation check!
115 if (dgpTop != round(dgpTop)){
116 _error_(
"top grid cell structure length does not go evenly into specified top structure depth, adjust dzTop or zTop\n");
120 _printf_(
"initial top grid cell length (dzTop) is < 0.05 m\n");
122 gpTop=reCast<int,IssmDouble>(dgpTop);
125 dzT = xNew<IssmDouble>(gpTop);
126 for (i=0;i<gpTop;i++)dzT[i]=dzTop;
139 dzB = xNewZeroInit<IssmDouble>(gpBottom);
142 for(i=0;i<gpBottom;i++){
148 dz = xNew<IssmDouble>(gpTop+gpBottom);
149 for(i=0;i<gpTop;i++){
152 for(i=0;i<gpBottom;i++){
164 *psize=gpTop+gpBottom;
179 if(T> -6.0+
Ttol) F = 0.7 + ((T/-6.0) * 0.3);
180 if(T<= -6.0+Ttol && T> -22.0+
Ttol) F = 1.0 - ((T+6.0)/-16.0 * 0.8);
181 if(T<= -22.0+Ttol && T> -40.0+
Ttol) F = 0.2 - ((T+22.0)/-18.0 * 0.2);
184 if(d< 150.0-
Dtol) H=1.0;
186 if(d>= 150.0-
Dtol && d <400.0-
Dtol) H = 1.0 - ((d-150.0)/250.0);
189 if(dT >= 0.16-
Ttol && dT < 0.25-
Ttol) G = ((dT - 0.16)/0.09) * 0.1;
190 if(dT >= 0.25-
Ttol && dT < 0.4-
Ttol) G = 0.1 + (((dT - 0.25)/0.15) * 0.57);
191 if(dT >= 0.4-
Ttol && dT < 0.5-
Ttol) G = 0.67 + (((dT - 0.4)/0.1) * 0.23);
192 if(dT >= 0.5-
Ttol && dT < 0.7-
Ttol) G = 0.9 + (((dT - 0.5)/0.2) * 0.1);
193 if(dT >= 0.7-
Ttol) G = 1.0;
199 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){
256 if(aIdx!=1 && aIdx!=2){
262 gsz=xNew<IssmDouble>(m);
for(
int i=0;i<m;i++)gsz[i]=re[i]*2.0;
268 lwc=xNew<IssmDouble>(m);
for(
int i=0;i<m;i++)lwc[i]= W[i] / (d[i]*dz[i])*100.0;
271 for(
int i=0;i<m;i++)
if(lwc[i]>9.0+
Wtol) lwc[i]=9.0;
277 dT=xNewZeroInit<IssmDouble>(m);
280 zGPC=xNewZeroInit<IssmDouble>(m);
281 for(
int i=0;i<m;i++){
282 for (
int j=0;j<=i;j++) zGPC[i]+=dz[j];
283 zGPC[i]-=(dz[i]/2.0);
288 dT[0] = (T[1] - T[0])/(zGPC[1]-zGPC[0]);
289 dT[m-1] = (T[m-1] - T[m-2])/(zGPC[m-1]-zGPC[m-2]);
293 for(
int i=1;i<m-1;i++) dT[i] = (T[i+1]-T[i-1])/(zGPC[i+1]-zGPC[i-1]);
296 for(
int i=0;i<m;i++)dT[i]=fabs(dT[i]);
299 for(
int i=0;i<m;i++){
317 IssmDouble C = (-2e8 * exp(-6e3 / T[i]) * dt) * pow(dT[i],.4);
327 IssmDouble D = (1.0/16.0) * pow(lwc[i],3.0) * dt;
335 if (gdn[i]<0.0+
Gdntol)gdn[i]=0.0;
336 if (gsp[i]<0.0+
Gdntol)gsp[i]=0.0;
337 if (gdn[i]>1.0-
Gdntol)gdn[i]=1.0;
338 if (gsp[i]>1.0-
Gdntol)gsp[i]=1.0;
341 gsz[i] = 0.1 + (1.0-gdn[i])*0.25 + (0.5-gsp[i])*0.1;
356 IssmDouble C = (-2e8 * exp(-6e3 / T[i]) * dt) * pow(dT[i],.4);
358 if (gsp[i]<0.0+
Gdntol)gsp[i]=0.0;
360 gsz[i] = 0.35 + (0.5-gsp[i])*0.1;
375 IssmDouble E = (1.28e-8 + 4.22e-10 * pow(lwc[i],3.0))* (dt *
dts);
378 gsz[i] = 2.0 * pow(3.0/(
Pi * 4.0)*((4.0/ 3.0)*
Pi*pow(gsz[i]/2.0,3.0) + E),1.0/3.0);
382 if (fabs(gsp[i]-1.0)<
Wtol && gsz[i]>2.0-
Wtol) gsz[i]=2.0;
385 if (fabs(gsp[i]-1.0)>=
Wtol && gsz[i]>5.0-
Wtol) gsz[i]=5.0;
393 xDelete<IssmDouble>(gsz);
394 xDelete<IssmDouble>(dT);
395 xDelete<IssmDouble>(zGPC);
396 xDelete<IssmDouble>(lwc);
404 void albedo(
IssmDouble** pa,
int aIdx,
IssmDouble* re,
IssmDouble* dz,
IssmDouble* d,
IssmDouble cldFrac,
IssmDouble aIce,
IssmDouble aSnow,
IssmDouble aValue,
IssmDouble adThresh,
IssmDouble* TK,
IssmDouble* W,
IssmDouble P,
IssmDouble EC,
IssmDouble Msurf,
IssmDouble t0wet,
IssmDouble t0dry,
IssmDouble K,
IssmDouble dt,
IssmDouble dIce,
int m,
int sid) {
472 if(aIdx==0 || (adThresh - d[0])<
Dtol){
483 a[0]= 1.48 - pow(S,-0.07);
502 IssmDouble a2 =
max(0.127, 0.88 + 346.3*gsz - 32.31*pow(gsz,0.5));
505 a[0] = sF[0]*a0 + sF[1]*a1 + sF[2]*a2;
512 for(
int l=0;(l<m & d[l]<dPHC-
Dtol);l++){
513 depthsnow=depthsnow+dz[l];
516 if (depthsnow<=0.1+
Dtol & lice<m & d[lice]>=dPHC-
Dtol){
517 aice = ai_max + (as_min - ai_max)*(d[lice]-dIce)/(dPHC-dIce);
518 a[0]= aice +
max(a[0]-aice,0.0)*(depthsnow/0.1);
521 else if (d[0]<dIce-
Dtol){
527 a[0] = ai_max + (as_min - ai_max)*(d[0]-dIce)/(dPHC-dIce);
538 a[0]=
max(ai_min + (ai_max - ai_min)*exp(-1*(M/200)), ai_min);
547 a[0] = aIce + (d[0] - dIce)*(aSnow - aIce) / (dSnow - dIce) + (0.05 * (cldFrac - 0.5));
576 for(
int i=0;i<m;i++)
if(W[i]>0.0+
Wtol)t0[i]=t0wet;
577 for(
int i=0;i<m;i++)T[i]=TK[i] -
CtoK;
578 for(
int i=0;i<m;i++) t0warm[i]= fabs(T[i]) * K + t0dry;
579 for(
int i=0;i<m;i++)
if(fabs(W[i])<
Wtol && T[i]>=-10.0-
Ttol)t0[i]= t0warm[i];
580 for(
int i=0;i<m;i++)
if(T[i]<-10.0-
Ttol) t0[i] = 10.0 * K + t0dry;
583 for(
int i=0;i<m;i++)d_a[i] = (a[i] - aIce) / t0[i] * dt;
584 for(
int i=0;i<m;i++)a[i] -= d_a[i];
590 if ( EC > 0.0 +
Dtol && T[0] < 0.0-
Ttol) P = P + (EC/dSnow) * 1000.0;
592 a[0] = aSnow - (aSnow - a[0]) * exp(-P/z_snow);
599 xDelete<IssmDouble>(t0);
600 xDelete<IssmDouble>(T);
601 xDelete<IssmDouble>(t0warm);
602 xDelete<IssmDouble>(d_a);
605 else _error_(
"albedo method switch should range from 0 to 4!");
609 if (a[0] > 1)
_printf_(
"albedo > 1.0\n");
610 else if (a[0] < 0)
_printf_(
"albedo is negative\n");
617 void thermo(
IssmDouble* pEC,
IssmDouble** pT,
IssmDouble* pulwrf,
IssmDouble* dz,
IssmDouble* d,
IssmDouble* swf,
IssmDouble dlwrf,
IssmDouble Ta,
IssmDouble V,
IssmDouble eAir,
IssmDouble pAir,
IssmDouble teValue,
IssmDouble Ws,
IssmDouble dt0,
int m,
IssmDouble Vz,
IssmDouble Tz,
IssmDouble thermo_scaling,
IssmDouble dIce,
int sid,
bool isconstrainsurfaceT) {
699 dAir = 0.029 * pAir /(
R * Ta);
712 if (ds < dIce-
Dtol && fabs(Ws) <
Wtol) z0 = 0.00012;
713 else if (ds >= dIce-
Dtol) z0 = 0.0032;
717 if(V<0.01-
Dtol)V=0.01;
721 An = pow(0.4,2) / (log(Tz/z0)*log(Vz/z0));
728 K= xNewZeroInit<IssmDouble>(m);
731 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));
734 for(
int i=0;i<m;i++)
if(d[i]>=dIce-
Dtol) K[i] = 9.828 * exp(-5.7E-3*T[i]);
755 KU = xNew<IssmDouble>(m);
756 KD = xNew<IssmDouble>(m);
757 KP = xNew<IssmDouble>(m);
761 for(
int i=1;i<m;i++) KU[i]= K[i-1];
762 for(
int i=0;i<m-1;i++) KD[i] = K[i+1];
763 for(
int i=0;i<m;i++) KP[i] = K[i];
766 dzU = xNew<IssmDouble>(m);
767 dzD = xNew<IssmDouble>(m);
771 for(
int i=1;i<m;i++) dzU[i]= dz[i-1];
772 for(
int i=0;i<m-1;i++) dzD[i] = dz[i+1];
777 for(
int i=0;i<m;i++)dt =
min(dt,
CI * pow(dz[i],2) * d[i] / (3 * K[i]) * thermo_scaling);
783 int f[45] = {1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 30, 36, 40, 45, 48, 50, 60,
784 72, 75, 80, 90, 100, 120, 144, 150, 180, 200, 225, 240, 300, 360, 400, 450, 600, 720, 900, 1200, 1800, 3600};
788 for(
int i=0;i<45;i++){
789 if (f[i]<dt-
Dtol)
if(f[i]>=max_fdt-
Dtol)max_fdt=f[i];
794 Au = xNew<IssmDouble>(m);
795 Ad = xNew<IssmDouble>(m);
796 Ap = xNew<IssmDouble>(m);
797 for(
int i=0;i<m;i++){
798 Au[i] = pow((dzU[i]/2.0/KP[i] + dz[i]/2.0/KU[i]),-1.0);
799 Ad[i] = pow((dzD[i]/2.0/KP[i] + dz[i]/2.0/KD[i]),-1.0);
800 Ap[i] = (d[i]*dz[i]*
CI)/dt;
804 Nu = xNew<IssmDouble>(m);
805 Nd = xNew<IssmDouble>(m);
806 Np = xNew<IssmDouble>(m);
807 for(
int i=0;i<m;i++){
808 Nu[i] = Au[i] / Ap[i];
809 Nd[i] = Ad[i] / Ap[i];
810 Np[i]= 1.0 - Nu[i] - Nd[i];
827 sw = xNew<IssmDouble>(m);
828 for(
int i=0;i<m;i++) sw[i]= swf[i] * dt;
831 dT_sw = xNew<IssmDouble>(m);
832 for(
int i=0;i<m;i++) dT_sw[i]= sw[i] / (
CI * d[i] * dz[i]);
845 T0 = xNewZeroInit<IssmDouble>(m+2);
846 Tu=xNew<IssmDouble>(m);
847 Td=xNew<IssmDouble>(m);
861 if(m>1) Ts = (T[0] + T[1])/2.0;
873 Ri = (2.0*9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2.0));
883 coefM = 1.0/(1.0-5.2*Ri);
886 coefM =pow (1.0-18*Ri,-0.25);
890 if (Ri <= -0.03+
Ttol) coefH = coefM/1.3;
895 shf = C *
CA * (Ta - Ts);
898 shf = shf / (coefM * coefH);
907 eS = 611.21 * exp(17.502 * (Ts -
CtoK) / (240.97 + Ts -
CtoK));
913 eS = exp(9.550426 - 5723.265/Ts + 3.53068 * log(Ts) - 0.00728332 * Ts);
917 lhf = C * L * (eAir - eS) * 0.622 / pAir;
921 lhf = lhf / (coefM * coefH);
924 EC_day = lhf *
dts / L;
927 turb = (shf + lhf)* dt;
928 dT_turb = turb / TCs;
931 ulw = - (
SB * pow(Ts,4.0)* teValue) * dt;
932 ulwrf = ulwrf - ulw/dt0;
939 if(!isconstrainsurfaceT)
for(
int j=0;j<m;j++) T[j] = T[j] + dT_sw[j];
940 if(!isconstrainsurfaceT) T[0] = T[0] + dT_dlw + dT_ulw + dT_turb;
943 for(
int j=0;j<m;j++) T0[1+j]=T[j];
944 for(
int j=0;j<m;j++) Tu[j] = T0[j];
945 for(
int j=0;j<m;j++) Td[j] = T0[2+j];
946 for(
int j=0;j<m;j++) T[j] = (Np[j] * T[j]) + (Nu[j] * Tu[j]) + (Nd[j] * Td[j]);
949 if(!isconstrainsurfaceT) EC = EC + (EC_day/
dts)*dt;
967 xDelete<IssmDouble>(K);
968 xDelete<IssmDouble>(KU);
969 xDelete<IssmDouble>(KD);
970 xDelete<IssmDouble>(KP);
971 xDelete<IssmDouble>(Au);
972 xDelete<IssmDouble>(Ad);
973 xDelete<IssmDouble>(Ap);
974 xDelete<IssmDouble>(Nu);
975 xDelete<IssmDouble>(Nd);
976 xDelete<IssmDouble>(Np);
977 xDelete<IssmDouble>(dzU);
978 xDelete<IssmDouble>(dzD);
979 xDelete<IssmDouble>(sw);
980 xDelete<IssmDouble>(dT_sw);
981 xDelete<IssmDouble>(T0);
982 xDelete<IssmDouble>(Tu);
983 xDelete<IssmDouble>(Td);
991 void shortwave(
IssmDouble** pswf,
int swIdx,
int aIdx,
IssmDouble dsw,
IssmDouble as,
IssmDouble* d,
IssmDouble* dz,
IssmDouble* re,
IssmDouble dIce,
int m,
int sid){
1020 swf=xNewZeroInit<IssmDouble>(m);
1026 swf[0] = (1.0 - as) * dsw;
1044 gsz=xNew<IssmDouble>(m);
1045 for(
int i=0;i<m;i++) gsz[i]= (re[i] * 2.0) / 1000.0;
1052 B1_cum=xNew<IssmDouble>(m+1);
1053 B2_cum=xNew<IssmDouble>(m+1);
1054 for(
int i=0;i<m+1;i++){
1065 IssmDouble a2 =
max(0.127, 0.88 + 346.3*gsz[0] - 32.31*pow(gsz[0],0.5));
1069 swfS[0] = (sF[0] * dsw) * (1.0 - a0);
1070 swfS[1] = (sF[1] * dsw) * (1.0 - a1);
1071 swfS[2] = (sF[2] * dsw) * (1.0 - a2);
1074 h =xNew<IssmDouble>(m);
1075 B1 =xNew<IssmDouble>(m);
1076 B2 =xNew<IssmDouble>(m);
1077 for(
int i=0;i<m;i++) h[i]= d[i] /(pow(gsz[i],0.5));
1078 for(
int i=0;i<m;i++) B1[i] = 0.0192 * h[i];
1079 for(
int i=0;i<m;i++) B2[i]= 0.1098 * h[i];
1083 exp1 = xNew<IssmDouble>(m);
1084 exp2 = xNew<IssmDouble>(m);
1085 for(
int i=0;i<m;i++) exp1[i]=exp(-B1[i]*dz[i]);
1086 for(
int i=0;i<m;i++) exp2[i]=exp(-B2[i]*dz[i]);
1088 for(
int i=0;i<m;i++){
1091 for(
int j=1;j<=i;j++){
1092 cum1 = cum1*exp1[j];
1093 cum2 = cum2*exp2[j];
1100 Qs1 = xNew<IssmDouble>(m+1);
1101 Qs2 = xNew<IssmDouble>(m+1);
1102 for(
int i=0;i<m+1;i++){
1103 Qs1[i] = swfS[0] * B1_cum[i];
1104 Qs2[i] = swfS[1] * B2_cum[i];
1108 for(
int i=0;i<m;i++) swf[i]= (Qs1[i]-Qs1[i+1]) + (Qs2[i]-Qs2[i+1]);
1111 swf[0] = swf[0]+ swfS[2];
1114 xDelete<IssmDouble>(gsz);
1115 xDelete<IssmDouble>(B1_cum);
1116 xDelete<IssmDouble>(B2_cum);
1117 xDelete<IssmDouble>(h);
1118 xDelete<IssmDouble>(B1);
1119 xDelete<IssmDouble>(B2);
1120 xDelete<IssmDouble>(exp1);
1121 xDelete<IssmDouble>(exp2);
1122 xDelete<IssmDouble>(Qs1);
1123 xDelete<IssmDouble>(Qs2);
1147 IssmDouble swf_ss = (1.0-SWs) * (1.0 - as) * dsw;
1154 B=xNew<IssmDouble>(m);
1155 for(
int i=0;i<m;i++) B[i] = Bs + (300.0 - d[i]) * ((Bs - Bi)/(dIce - 300.0));
1158 B_cum = xNew<IssmDouble>(m+1);
1159 exp_B = xNew<IssmDouble>(m);
1160 for(
int i=0;i<m;i++)exp_B[i]=exp(-B[i]*dz[i]);
1163 for(
int i=0;i<m;i++){
1165 for(
int j=1;j<=i;j++) cum_B=cum_B*exp_B[j];
1170 Qs=xNew<IssmDouble>(m+1);
1171 for(
int i=0;i<m+1;i++) Qs[i] = swf_ss * B_cum[i];
1174 for(
int i=0;i<m;i++) swf[i] = (Qs[i]-Qs[i+1]);
1180 xDelete<IssmDouble>(B_cum);
1181 xDelete<IssmDouble>(exp_B);
1182 xDelete<IssmDouble>(Qs);
1183 xDelete<IssmDouble>(B);
1190 void accumulation(
IssmDouble** pT,
IssmDouble** pdz,
IssmDouble** pd,
IssmDouble** pW,
IssmDouble** pa,
IssmDouble** pre,
IssmDouble** pgdn,
IssmDouble** pgsp,
int* pm,
int aIdx,
int dsnowIdx,
IssmDouble Tmean,
IssmDouble T_air,
IssmDouble P,
IssmDouble dzMin,
IssmDouble aSnow,
IssmDouble C,
IssmDouble V,
IssmDouble Vmean,
IssmDouble dIce,
int sid){
1265 dSnow=(7.36e-2 + 1.06e-3*
min(Tmean,
CtoK-
Ttol) + 6.69e-2*C/1000 + 4.77e-3*Vmean)*1000;
1269 dSnow = 481.0 + 4.834*(Tmean-
CtoK);
1274 mInit=xNew<IssmDouble>(m);
1275 for(
int i=0;i<m;i++) mInit[i]= d[i] * dz[i];
1277 for(
int i=0;i<m;i++)massinit+=mInit[i];
1289 dfall =
min(
max(1.29 - 0.17*V,0.20),1.0);
1290 sfall =
min(
max(0.08*V + 0.38,0.5),0.9);
1291 refall =
max((0.1 + (1.0-dfall)*0.25 + (0.5-sfall)*0.1)/2.0,
Gdntol);
1294 if (z_snow > dzMin+
Dtol){
1308 mass = mInit[0] + P;
1310 dz[0] = dz[0] + P/dSnow;
1311 d[0] = mass / dz[0];
1315 T[0] = (T_air * P + T[0] * mInit[0])/mass;
1318 if(aIdx>0)a[0] = (aSnow * P + a[0] * mInit[0])/mass;
1319 gdn[0] = (dfall * P + gdn[0] * mInit[0])/mass;
1320 gsp[0] = (sfall * P + gsp[0] * mInit[0])/mass;
1321 re[0] =
max((0.1 + (1.0-gdn[0])*0.25 + (0.5-gsp[0])*0.1)/2.0,
Gdntol);
1333 mass = mInit[0] + P;
1337 T[0] = (P *(T_air +
LF/
CI) + T[0] * mInit[0]) / mass;
1340 d[0] = mass / dz[0];
1343 if (d[0] > dIce-
Dtol){
1345 dz[0] = mass / d[0];
1350 mass=0;
for(
int i=0;i<m;i++)mass+=d[i]*dz[i];
1352 mass_diff = mass - massinit - P;
1354 #ifndef _HAVE_AD_ //avoid round operation. only check in forward mode.
1355 mass_diff = round(mass_diff * 100.0)/100.0;
1356 if (mass_diff > 0)
_error_(
"mass not conserved in accumulation function");
1361 if(mInit)xDelete<IssmDouble>(mInit);
1374 void melt(
IssmDouble* pM,
IssmDouble* pMs,
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 zY,
IssmDouble dIce,
int sid){
1427 bool lastCellFlag =
false;
1456 M=xNewZeroInit<IssmDouble>(n);
1457 maxF=xNewZeroInit<IssmDouble>(n);
1458 dW=xNewZeroInit<IssmDouble>(n);
1461 m=xNew<IssmDouble>(n);
for(
int i=0;i<n;i++) m[i] = dz[i]* d[i];
1462 EI=xNew<IssmDouble>(n);
for(
int i=0;i<n;i++)EI[i] = m[i] * T[i] *
CI;
1463 EW=xNew<IssmDouble>(n);
for(
int i=0;i<n;i++)EW[i]= W[i] * (
LF +
CtoK *
CI);
1476 exsT=xNewZeroInit<IssmDouble>(n);
1477 for(
int i=0;i<n;i++) exsT[i]=
max(0.0, T[i] -
CtoK);
1481 for(
int i=0;i<n;i++) T[i]=
min(T[i],
CtoK);
1492 for(
int i=0;i<n;i++) maxF[i] =
max(0.0, -((T[i] -
CtoK) * m[i] *
CI) /
LF);
1495 for(
int i=0;i<n;i++) dW[i] =
min(maxF[i], W[i]);
1496 for(
int i=0;i<n;i++) W[i] -= dW[i];
1497 for(
int i=0;i<n;i++) m[i] += dW[i];
1498 for(
int i=0;i<n;i++) d[i] = m[i] / dz[i];
1499 for(
int i=0;i<n;i++)
if(m[i]>
Wtol) T[i] = T[i] + (dW[i]*(
LF+(
CtoK - T[i])*
CI)/(m[i]*
CI));
1502 for(
int i=0;i<n;i++)
if(d[i]> dIce-
Dtol)d[i]=dIce;
1503 for(
int i=0;i<n;i++) dz[i]= m[i]/d[i];
1508 exsW=xNew<IssmDouble>(n);
1509 for(
int i=0;i<n;i++){
1510 Wi= (dIce - d[i]) * Swi * (m[i] / d[i]);
1511 exsW[i] =
max(0.0, W[i] - Wi);
1523 surpT=xNew<IssmDouble>(n);
for(
int i=0;i<n;i++)surpT[i] =
max(0.0, exsT[i]-
LF/
CI);
1528 surpE=xNew<IssmDouble>(n);
for(
int i=0;i<n;i++)surpE[i] = surpT[i] *
CI * m[i];
1535 T[i+1] = surpE[i]/m[i+1]/
CI + T[i+1];
1537 exsT[i+1] =
max(0.0, T[i+1] -
CtoK) + exsT[i+1];
1540 surpT[i+1] =
max(0.0, exsT[i+1] -
LF/
CI);
1541 surpE[i+1] = surpT[i+1] *
CI * m[i+1];
1544 surplusT=
max(0.0, exsT[i] -
LF/
CI);
1547 _printf0_(
" WARNING: surplus energy at the base of GEMB column\n");
1560 for(
int i=0;i<n;i++){
1561 Mmax=exsT[i] * d[i] * dz[i] *
CI /
LF;
1562 M[i] =
min(Mmax, m[i]);
1568 for(
int i=0;i<n;i++)maxF[i] =
max(0.0, -((T[i] -
CtoK) * d[i] * dz[i] *
CI)/
LF);
1574 for(
int i=0;i<n;i++)dW[i] = 0.0;
1575 flxDn=xNewZeroInit<IssmDouble>(n+1);
1579 for(
int i=n-1;i>=0;i--){
1580 if(M[i]> 0.0+
Wtol || exsW[i]> 0.0+
Wtol){
1588 for(
int i=0;i<n;i++){
1593 if (d[i] >= dPHC-
Dtol){
1594 for(
int l=i;(l<n && d[l]>=dPHC-
Dtol);l++) depthice=depthice+dz[l];
1598 if (fabs(inM) <
Wtol && i > X){
1602 else if (d[i] >= dIce-
Dtol || (d[i] >= dPHC-
Dtol && depthice>0.1)){
1609 Wi = (dIce-d[i]) * Swi * (m[i]/d[i]);
1610 dW[i] =
max(
min(inM, Wi - W[i]),-1*W[i]);
1611 R[i] =
max(0.0, inM - dW[i]);
1615 else if (fabs(maxF[i]) <
Dtol){
1621 Wi = (dIce-d[i]) * Swi * (m[i]/d[i]);
1622 dW[i] =
max(
min(inM, Wi - W[i]),-1*W[i]);
1623 flxDn[i+1] =
max(0.0, inM - dW[i]);
1640 Wi = (dIce-d[i])* Swi * dz_0;
1641 dW[i] =
min(inM - F1, Wi-W[i]);
1642 if (dW[i] < 0.0-
Wtol && -1*dW[i]> W[i]-
Wtol ){
1647 if (dW[i] < 0.0-
Wtol){
1648 dMax = (dIce - d[i])*dz_0;
1650 F2 =
min(-1*dW[i], maxF2);
1658 flxDn[i+1] = inM - F1 - dW[i];
1660 T[i] = T[i] + ((F1+F2)*(
LF+(
CtoK - T[i])*
CI)/(m[i]*
CI));
1664 if (fabs(d[i] - dIce) <
Dtol){
1675 for(
int i=0;i<n;i++)
if (W[i] < 0.0-
Wtol)
_error_(
"negative pore water generated in melt equations");
1679 for(
int i=0;i<n;i++)W[i] += dW[i];
1685 D_size=0;
for(
int i=0;i<n;i++)if(m[i]> (0.0+
Wtol))D_size++;
1686 D=xNew<int>(D_size);
1687 D_size=0;
for(
int i=0;i<n;i++)if(m[i]> (0.0+
Wtol)){ D[D_size] = i; D_size++;}
1704 for(
int i=0;i<n;i++)dz[i] = m[i] / d[i];
1707 xDelete<IssmDouble>(F);
1708 xDelete<IssmDouble>(
R);
1712 Zcum=xNew<IssmDouble>(n);
1713 dzMin2=xNew<IssmDouble>(n);
1714 dzMax2=xNew<IssmDouble>(n);
1718 for (
int i=0;i<n;i++){
1723 Zcum[i]=Zcum[i-1]+dz[i];
1724 if (Zcum[i]<=zTop+
Dtol){
1729 dzMin2[i]=zY2*dzMin2[i-1];
1735 for (
int i=0; i<n; i++){
1736 if ( (i<=X && dz[i]<dzMin-
Dtol) || (i>X && dz[i]<dzMin2[i]-
Dtol) ) {
1741 for(
int j=n-2;j>=0;j--){
1755 T[X1] = (T[X2]*m[X2] + T[X1]*m[X1]) / m_new;
1756 a[X1] = (a[X2]*m[X2] + a[X1]*m[X1]) / m_new;
1757 re[X1] = (re[X2]*m[X2] + re[X1]*m[X1]) / m_new;
1758 gdn[X1] = (gdn[X2]*m[X2] + gdn[X1]*m[X1]) / m_new;
1759 gsp[X1] = (gsp[X2]*m[X2] + gsp[X1]*m[X1]) / m_new;
1762 dz[X1] = dz[X2] + dz[X1];
1763 d[X1] = m_new / dz[X1];
1764 W[X1] = W[X1] + W[X2];
1773 D_size=0;
for(
int i=0;i<n;i++)
if(m[i]>
Delflag+
Wtol)D_size++;
1774 D=xNew<int>(D_size);
1775 D_size=0;
for(
int i=0;i<n;i++)
if(m[i]>
Delflag+
Wtol){ D[D_size] = i; D_size++;}
1794 for (
int i=0;i<n;i++){
1799 Zcum[i]=Zcum[i-1]+dz[i];
1800 if (Zcum[i]<=zTop+
Dtol){
1805 dzMax2[i]=
max(zY2*dzMin2[i-1],dzMin*2);
1810 for (
int j=n-1;j>=0;j--){
1811 if ((j<X && dz[j] > dzMax2[j]+
Dtol) || (dz[j] > dzMax2[j]*zY2+
Dtol)){
1835 if (Ztot < zMin-
Dtol){
1838 mAdd = m[n-1]+W[n-1];
1839 addE = T[n-1]*m[n-1]*
CI + W[n-1]*(
LF+
CtoK*
CI);
1869 else if (Ztot > zMax+
Dtol){
1872 mAdd = -(m[n-1]+W[n-1]);
1873 addE = -(T[n-1]*m[n-1]*
CI) - (W[n-1]*(
LF+
CtoK*
CI));
1878 D=xNew<int>(D_size);
1880 for(
int i=0;i<n-1;i++) D[i]=i;
1900 for(
int i=0;i<n;i++)EI[i] = m[i] * T[i] *
CI;
1901 for(
int i=0;i<n;i++)EW[i] = W[i] * (
LF +
CtoK *
CI);
1907 for(
int i=0;i<n;i++)
if (W[i]<0.0-
Wtol)
_error_(
"negative pore water generated in melt equations\n");
1911 dm = round((mSum0 - mSum1 + mAdd)*100.0)/100.0;
1912 dE = round(sumE0 - sumE1 - sumER + addE - surplusE);
1913 if (dm !=0 || dE !=0)
_error_(
"mass or energy are not conserved in melt equations\n"
1914 <<
"dm: " << dm <<
" dE: " << dE <<
"\n");
1918 if(m)xDelete<IssmDouble>(m);
1919 if(EI)xDelete<IssmDouble>(EI);
1920 if(EW)xDelete<IssmDouble>(EW);
1921 if(maxF)xDelete<IssmDouble>(maxF);
1922 if(dW)xDelete<IssmDouble>(dW);
1923 if(exsW)xDelete<IssmDouble>(exsW);
1924 if(exsT)xDelete<IssmDouble>(exsT);
1925 if(surpT)xDelete<IssmDouble>(surpT);
1926 if(surpE)xDelete<IssmDouble>(surpE);
1927 if(flxDn)xDelete<IssmDouble>(flxDn);
1928 if(D)xDelete<int>(D);
1929 if(M)xDelete<IssmDouble>(M);
1930 xDelete<IssmDouble>(Zcum);
1931 xDelete<IssmDouble>(dzMin2);
1951 void densification(
IssmDouble** pd,
IssmDouble** pdz,
IssmDouble* T,
IssmDouble* re,
int denIdx,
IssmDouble C,
IssmDouble dt,
IssmDouble Tmean,
IssmDouble dIce,
int m,
int sid){
2019 IssmDouble* mass_init = xNew<IssmDouble>(m);
for(
int i=0;i<m;i++) mass_init[i]=d[i] * dz[i];
2024 for(
int i=1;i<m-1;i++)cumdz[i]=cumdz[i-1]+dz[i];
2028 for(
int i=1;i<m;i++)obp[i]=cumdz[i-1]*d[i-1];
2034 for(
int i=0;i<m;i++){
2037 c0 = (11.0 * exp(-10160.0 / (T[i] *
R))) * C/1000.0;
2038 c1 = (575.0 * exp(-21400.0 / (T[i]*
R))) * pow(C/1000.0,.5);
2044 H = exp((-60000.0/(T[i] *
R)) + (42400.0/(Tmean *
R))) * (C * 9.81);
2052 H = exp((-60000.0/(T[i] *
R))) * obp[i] / pow(re[i]/1000.0,2.0);
2058 c0 = (C/dIce) * (139.21 - 0.542*Tmean)*8.36*pow(
CtoK - T[i],-2.061);
2064 c0 = (C/dIce) * (76.138 - 0.28965*Tmean)*8.36*pow(
CtoK - T[i],-2.061);
2071 H = exp((-60000.0/(T[i] *
R)) + (42400.0/(Tmean *
R))) * (C * 9.81);
2078 M0 =
max(1.6599 - (0.1724 * log(C)),0.25);
2079 M1 =
max(2.0102 - (0.2458 * log(C)),0.25);
2091 H = exp((-60000.0/(T[i] *
R)) + (42400.0/(Tmean *
R))) * (C * 9.81);
2098 M0 =
max(1.6201 - (0.1450 * log(C)),0.25);
2099 M1 =
max(2.5577 - (0.2899 * log(C)),0.25);
2109 if(d[i] <= 550.0+
Dtol) d[i] = d[i] + (c0 * (dIce - d[i]) / 365.0 * dt);
2110 else d[i] = d[i] + (c1 * (dIce - d[i]) / 365.0 * dt);
2115 if(d[i] > dIce-
Ptol) d[i]=dIce;
2118 dz[i] = mass_init[i] / d[i];
2122 xDelete<IssmDouble>(mass_init);
2123 xDelete<IssmDouble>(cumdz);
2124 xDelete<IssmDouble>(obp);
2131 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){
2173 d_air = 0.029 * pAir /(
R * Ta);
2178 if (ds < dIce-
Dtol && fabs(Ws) <
Wtol) z0 = 0.00012;
2179 else if (ds >= dIce-
Dtol) z0 = 0.0032;
2188 if(V< 0.01-
Dtol)V=0.01;
2191 Ri = (2.0*9.81* (Vz - z0) * (Ta - Ts)) / ((Ta + Ts)* pow(V,2.0));
2201 coef_M = 1.0/(1.0-5.2*Ri);
2204 coef_M =pow (1.0-18*Ri,-0.25);
2208 if (Ri <= -0.03+
Ttol) coef_H = coef_M/1.3;
2209 else coef_H = coef_M;
2213 An = pow(0.4,2) / (log(Tz/z0)*log(Vz/z0));
2218 shf = C *
CA * (Ta - Ts);
2221 shf = shf / (coef_M * coef_H);
2230 eS = 611.21 * exp(17.502 * (Ts -
CtoK) / (240.97 + Ts -
CtoK));
2236 eS = exp(9.550426 - 5723.265/Ts + 3.53068 * log(Ts) - 0.00728332 * Ts);
2240 lhf = C * L * (eAir - eS) * 0.622 / pAir;
2245 lhf = lhf / (coef_M * coef_H);