/* file: PddSurfaceMassBlanceSicopolis.cpp Calculating the surface mass balance using the adapted PDD routine from SICOPOLIS. */ #include "./elements.h" #include "../Numerics/numerics.h" #include "../Exceptions/exceptions.h" #include IssmDouble PddSurfaceMassBalanceSicopolis(IssmDouble* monthlytemperatures, IssmDouble* monthlyprec, IssmDouble* melt, IssmDouble* accu, IssmDouble* melt_star, IssmDouble* t_ampl, IssmDouble* p_ampl, IssmDouble yts, IssmDouble s, IssmDouble desfac, IssmDouble s0t, IssmDouble s0p, IssmDouble rlaps, IssmDouble rho_water,IssmDouble rho_ice){ int imonth; // month counter IssmDouble B; // output: surface mass balance (m/a IE), melt+accumulation IssmDouble frac_solid, snowfall, rainfall, runoff; IssmDouble saccu; // yearly surface accumulation (m/a IE) IssmDouble smelt; // yearly melt (m/a IE) IssmDouble smelt_star; // yearly ... IssmDouble precip; // total precipitation during 1 year IssmDouble sconv; //rhow_rain/rhoi / 12 months IssmDouble st; // elevation between altitude of the temp record and current altitude IssmDouble sp; // elevation between altitude of the prec record and current altitude IssmDouble q; // q is desert/elev. fact IssmDouble pdd; // pdd factor (a * degC) IssmDouble tstar; // monthly temp. after lapse rate correction (degC) IssmDouble precip_star; // monthly precip after correction (m/a IE) IssmDouble beta1 = 2.73; // 3 mm IE/(d*deg C), ablation factor for snow per positive degree day. IssmDouble beta2 = 7.28; // 8 mm IE/(d*deg C), ablation factor for ice per pdd (Braithwaite 1995 from tarasov 2002). IssmDouble Pmax = 0.6; IssmDouble inv_twelve=1./12.; sconv=(rho_water/rho_ice); //rhow_rain/rhoi /* FIXME betas shoud be user input */ beta1=beta1*(0.001*365)*sconv; // (mm WE)/(d*deg C) --> (m IE)/(a*deg C) beta2=beta2*(0.001*365)*sconv; // (mm WE)/(d*deg C) --> (m IE)/(a*deg C) /* initalize fields */ precip=0.0; tstar=0.0; snowfall=0.0; pdd=0.0; /* seasonal loop */ for(imonth=0;imonth<12;imonth++){ /********* Surface temperature correction *******/ st=(s-s0t)/1000.; // FIXME rlaps ?? rlaps=-6.309e-03+(-5.426e-03-(-6.309e-03))*sin((imonth+1-4)*PI/6.0)*1000.0; monthlytemperatures[imonth]=monthlytemperatures[imonth]-rlaps*st;//*max(st,1e-3); tstar=monthlytemperatures[imonth]+t_ampl[0]; /********* Precipitation correction *************/ /* Ref: Vizcaino et al 2010; DOI 10.1007/s00382-009-0591-y */ if(s0p<2000.0) q=exp(desfac*(max(s,2000.0)-2000.0)); else q=exp(desfac*(max(s,2000.0)-s0p)); precip_star=q*monthlyprec[imonth]*sconv*p_ampl[0]*yts; // convert precip from m/s -> m/a precip=precip+precip_star*inv_twelve; /********* compute PDD **************************/ /* Ref: Calov & Greve 2005 Journal of Glaciology, Vol. 51, No. 172, 2005, Correspondence */ IssmDouble s_stat=5.0; IssmDouble inv_sqrt2pi =1.0/sqrt(2.0*PI); IssmDouble inv_s_stat =1.0/s_stat; IssmDouble inv_sqrt2 =1.0/sqrt(2.0); #if !defined(_HAVE_ADOLC_) pdd=pdd+(s_stat*inv_sqrt2pi*exp(-0.5*pow(tstar*inv_s_stat,2)) +0.5*tstar*erfc(-tstar*inv_s_stat*inv_sqrt2))*inv_twelve; #else _error_("Cannot differentiate erfc, talk to ADOLC folks (http://functions.wolfram.com/GammaBetaErf/Erfc/20/01/)"); #endif /*Partition of precip in solid and liquid parts, Bales et al. (2009) */ IssmDouble temp_rain=7.2; // Threshold monthly mean temperature for // precipitation = 101% rain, in deg C IssmDouble temp_snow=-11.6; // Threshold monthly mean temperature for // precipitation = 100% snow, in deg C IssmDouble coeff1=5.4714e-01; // Coefficients IssmDouble coeff2=-9.1603e-02; // of IssmDouble coeff3=-3.314e-03; // the IssmDouble coeff4= 4.66e-04; // fifth-order IssmDouble coeff5=3.8e-05; // polynomial IssmDouble coeff6=6.0e-07; // fit if(tstar>=temp_rain) frac_solid = 0.0; else if(tstar<=temp_snow) frac_solid = 1.0; else{ frac_solid=coeff1+tstar*(coeff2 +tstar*(coeff3+tstar*(coeff4+tstar*(coeff5+tstar*coeff6)))); } snowfall=snowfall+precip_star*frac_solid*inv_twelve; } /* end of seasonal loop */ rainfall=precip-snowfall; if(snowfall<0.0) snowfall=0.0; // correction of if(rainfall<0.0) rainfall=0.0; // negative values if(rainfall<=(Pmax*snowfall)){ if((rainfall+beta1*pdd)<=(Pmax*snowfall)) { smelt_star = rainfall+beta1*pdd; smelt = 0.0; runoff = smelt; } else{ smelt_star = Pmax*snowfall; smelt = beta2*(pdd-(smelt_star-rainfall)/beta1); runoff = smelt; } } else{ smelt_star = Pmax*snowfall; smelt = beta2*pdd; runoff = smelt+rainfall-Pmax*snowfall; } saccu = precip; /* asign output*/ melt[0]=runoff/yts; accu[0]=saccu/yts; melt_star[0]=smelt_star/yts; B=(saccu-runoff)/yts; return B; }