/*!\file SurfaceMassBalancex * \brief: calculates SMB */ #include "./SurfaceMassBalancex.h" #include "../../shared/shared.h" #include "../../toolkits/toolkits.h" void SurfaceMassBalancex(FemModel* femmodel){/*{{{*/ /*Intermediaties*/ int smb_model; bool isdelta18o; /*First, get SMB model from parameters*/ femmodel->parameters->FindParam(&smb_model,SurfaceforcingsEnum); /*branch to correct module*/ switch(smb_model){ case SMBEnum: /*Nothing to be done*/ break; case SMBpddEnum: femmodel->parameters->FindParam(&isdelta18o,SurfaceforcingsIsdelta18oEnum); if(isdelta18o){ if(VerboseSolution()) _printf0_(" call Delta18oParametrization module\n"); Delta18oParameterizationx(femmodel); } if(VerboseSolution()) _printf0_(" call positive degree day module\n"); PositiveDegreeDayx(femmodel); break; case SMBgradientsEnum: if(VerboseSolution())_printf0_(" call smb gradients module\n"); SmbGradientsx(femmodel); break; case SMBhenningEnum: if(VerboseSolution())_printf0_(" call smb Henning module\n"); SmbHenningx(femmodel); break; case SMBcomponentsEnum: if(VerboseSolution())_printf0_(" call smb Components module\n"); SmbComponentsx(femmodel); break; case SMBmeltcomponentsEnum: if(VerboseSolution())_printf0_(" call smb Melt Components module\n"); SmbMeltComponentsx(femmodel); break; default: _error_("Surface mass balance model "<elements->Size();i++){ Element* element=xDynamicCast(femmodel->elements->GetObjectByOffset(i)); /*Allocate all arrays*/ int numvertices = element->GetNumberOfVertices(); IssmDouble* Href = xNew(numvertices); // reference elevation from which deviations are used to calculate the SMB adjustment IssmDouble* Smbref = xNew(numvertices); // reference SMB to which deviations are added IssmDouble* b_pos = xNew(numvertices); // Hs-SMB relation parameter IssmDouble* b_neg = xNew(numvertices); // Hs-SMB relation paremeter IssmDouble* s = xNew(numvertices); // surface elevation (m) IssmDouble* smb = xNew(numvertices); /*Recover SmbGradients*/ element->GetInputListOnVertices(Href,SurfaceforcingsHrefEnum); element->GetInputListOnVertices(Smbref,SurfaceforcingsSmbrefEnum); element->GetInputListOnVertices(b_pos,SurfaceforcingsBPosEnum); element->GetInputListOnVertices(b_neg,SurfaceforcingsBNegEnum); /*Recover surface elevation at vertices: */ element->GetInputListOnVertices(s,SurfaceEnum); /*Get material parameters :*/ rho_ice=element->matpar->GetRhoIce(); rho_water=element->matpar->GetRhoFreshwater(); // loop over all vertices for(v=0;v0){ smb[v]=Smbref[v]+b_pos[v]*(s[v]-Href[v]); } else{ smb[v]=Smbref[v]+b_neg[v]*(s[v]-Href[v]); } smb[v]=smb[v]/1000*rho_water/rho_ice; // SMB in m/y ice } //end of the loop over the vertices /*Add input to element and Free memory*/ element->AddInput(SurfaceforcingsMassBalanceEnum,smb,P1Enum); xDelete(Href); xDelete(Smbref); xDelete(b_pos); xDelete(b_neg); xDelete(s); xDelete(smb); } }/*}}}*/ void Delta18oParameterizationx(FemModel* femmodel){/*{{{*/ for(int i=0;ielements->Size();i++){ Element* element=xDynamicCast(femmodel->elements->GetObjectByOffset(i)); element->Delta18oParameterization(); } }/*}}}*/ void PositiveDegreeDayx(FemModel* femmodel){/*{{{*/ // void PositiveDegreeDayx(hd,vTempsea,vPrec,agd,Tsurf,ni){ // note "v" prefix means 12 monthly means, ie time dimension // INPUT parameters: ni: working size of arrays // INPUT: surface elevation (m): hd(NA) // monthly mean surface sealevel temperature (degrees C): vTempsea(NA // ,NTIME) // monthly mean precip rate (m/yr water equivalent): vPrec(NA,NTIME) // OUTPUT: mass-balance (m/yr ice): agd(NA) // mean annual surface temperature (degrees C): Tsurf(NA) int i, it, jj, itm; IssmDouble DT = 0.02, sigfac, snormfac; IssmDouble signorm = 5.5; // signorm : sigma of the temperature distribution for a normal day IssmDouble siglim; // sigma limit for the integration which is equal to 2.5 sigmanorm IssmDouble signormc = signorm - 0.5; // sigma of the temperature distribution for cloudy day IssmDouble siglimc, siglim0, siglim0c; IssmDouble tstep, tsint, tint, tstepc; int NPDMAX = 1504, NPDCMAX = 1454; //IssmDouble pdds[NPDMAX]={0}; //IssmDouble pds[NPDCMAX]={0}; IssmDouble pddt, pd ; // pd : snow/precip fraction, precipitation falling as snow IssmDouble PDup, PDCUT = 2.0; // PDcut: rain/snow cutoff temperature (C) IssmDouble tstar; // monthly mean surface temp IssmDouble *pdds = NULL; IssmDouble *pds = NULL; Element *element = NULL; pdds=xNew(NPDMAX+1); pds=xNew(NPDCMAX+1); /* initialize PDD (creation of a lookup table)*/ tstep = 0.1; tsint = tstep*0.5; sigfac = -1.0/(2.0*pow(signorm,2)); snormfac = 1.0/(signorm*sqrt(2.0*acos(-1.0))); siglim = 2.5*signorm; siglimc = 2.5*signormc; siglim0 = siglim/DT + 0.5; siglim0c = siglimc/DT + 0.5; PDup = siglimc+PDCUT; itm = reCast((2*siglim/DT + 1.5)); if(itm >= NPDMAX) _error_("increase NPDMAX in massBalance.cpp"); for(it = 0; it < itm; it++){ // tstar = REAL(it)*DT-siglim; tstar = it*DT-siglim; tint = tsint; pddt = 0.; for ( jj = 0; jj < 600; jj++){ if (tint > (tstar+siglim)){break;} pddt = pddt + tint*exp(sigfac*(pow((tint-tstar),2)))*tstep; tint = tint+tstep; } pdds[it] = pddt*snormfac; } pdds[itm+1] = siglim + DT; //*********compute PD(T) : snow/precip fraction. precipitation falling as snow tstepc = 0.1; tsint = PDCUT-tstepc*0.5; signormc = signorm - 0.5; sigfac = -1.0/(2.0*pow(signormc,2)); snormfac = 1.0/(signormc*sqrt(2.0*acos(-1.0))); siglimc = 2.5*signormc ; itm = reCast((PDCUT+2.*siglimc)/DT + 1.5); if(itm >= NPDCMAX) _error_("increase NPDCMAX in p35com"); for(it = 0; it < itm; it++ ){ tstar = it*DT-siglimc; // tstar = REAL(it)*DT-siglimc; tint = tsint; // start against upper bound pd = 0.; for (jj = 0; jj < 600; jj++){ if (tint<(tstar-siglimc)) {break;} pd = pd + exp(sigfac*(pow((tint-tstar),2)))*tstepc; tint = tint-tstepc; } pds[it] = pd*snormfac; // gaussian integral lookup table for snow fraction } pds[itm+1] = 0.; // *******END initialize PDD for(i=0;ielements->Size();i++){ element=xDynamicCast(femmodel->elements->GetObjectByOffset(i)); element->PositiveDegreeDay(pdds,pds,signorm); } /*free ressouces: */ xDelete(pdds); xDelete(pds); }/*}}}*/ void SmbHenningx(FemModel* femmodel){/*{{{*/ /*Intermediaries*/ IssmDouble z_critical = 1675.; IssmDouble dz = 0; IssmDouble a = -15.86; IssmDouble b = 0.00969; IssmDouble c = -0.235; IssmDouble f = 1.; IssmDouble g = -0.0011; IssmDouble h = -1.54e-5; IssmDouble smb,smbref,anomaly,yts,z; /* Get constants */ femmodel->parameters->FindParam(&yts,ConstantsYtsEnum); /*iomodel->Constant(&yts,ConstantsYtsEnum);*/ /*this->parameters->FindParam(&yts,ConstantsYtsEnum);*/ /*Mathieu original*/ /*IssmDouble smb,smbref,z;*/ /*Loop over all the elements of this partition*/ for(int i=0;ielements->Size();i++){ Element* element=xDynamicCast(femmodel->elements->GetObjectByOffset(i)); /*Get reference SMB (uncorrected) and allocate all arrays*/ int numvertices = element->GetNumberOfVertices(); IssmDouble* surfacelist = xNew(numvertices); IssmDouble* smblistref = xNew(numvertices); IssmDouble* smblist = xNew(numvertices); element->GetInputListOnVertices(surfacelist,SurfaceEnum); element->GetInputListOnVertices(smblistref,SurfaceforcingsSmbrefEnum); /*Loop over all vertices of element and correct SMB as a function of altitude z*/ for(int v=0;v z_critical = 1675 */ z_critical = z_critical + dz; /* Calculate smb acc. to the surface elevation z */ if(zAddInput(SurfaceforcingsMassBalanceEnum,smblist,P1Enum); xDelete(surfacelist); xDelete(smblistref); xDelete(smblist); } }/*}}}*/ void SmbComponentsx(FemModel* femmodel){/*{{{*/ // void SmbComponentsx(acc,evap,runoff,ni){ // INPUT parameters: ni: working size of arrays // INPUT: surface accumulation (m/yr water equivalent): acc // surface evaporation (m/yr water equivalent): evap // surface runoff (m/yr water equivalent): runoff // OUTPUT: mass-balance (m/yr ice): agd(NA) int v; /*Loop over all the elements of this partition*/ for(int i=0;ielements->Size();i++){ Element* element=xDynamicCast(femmodel->elements->GetObjectByOffset(i)); /*Allocate all arrays*/ int numvertices = element->GetNumberOfVertices(); IssmDouble* acc = xNew(numvertices); IssmDouble* evap = xNew(numvertices); IssmDouble* runoff = xNew(numvertices); IssmDouble* smb = xNew(numvertices); /*Recover Smb Components*/ element->GetInputListOnVertices(acc,SurfaceforcingsAccumulationEnum); element->GetInputListOnVertices(evap,SurfaceforcingsEvaporationEnum); element->GetInputListOnVertices(runoff,SurfaceforcingsRunoffEnum); // loop over all vertices for(v=0;vAddInput(SurfaceforcingsMassBalanceEnum,smb,P1Enum); xDelete(acc); xDelete(evap); xDelete(runoff); xDelete(smb); } }/*}}}*/ void SmbMeltComponentsx(FemModel* femmodel){/*{{{*/ // void SmbMeltComponentsx(acc,evap,melt,refreeze,ni){ // INPUT parameters: ni: working size of arrays // INPUT: surface accumulation (m/yr water equivalent): acc // surface evaporation (m/yr water equivalent): evap // surface melt (m/yr water equivalent): melt // refreeze of surface melt (m/yr water equivalent): refreeze // OUTPUT: mass-balance (m/yr ice): agd(NA) int v; /*Loop over all the elements of this partition*/ for(int i=0;ielements->Size();i++){ Element* element=xDynamicCast(femmodel->elements->GetObjectByOffset(i)); /*Allocate all arrays*/ int numvertices = element->GetNumberOfVertices(); IssmDouble* acc = xNew(numvertices); IssmDouble* evap = xNew(numvertices); IssmDouble* melt = xNew(numvertices); IssmDouble* refreeze = xNew(numvertices); IssmDouble* smb = xNew(numvertices); /*Recover Smb Components*/ element->GetInputListOnVertices(acc,SurfaceforcingsAccumulationEnum); element->GetInputListOnVertices(evap,SurfaceforcingsEvaporationEnum); element->GetInputListOnVertices(melt,SurfaceforcingsMeltEnum); element->GetInputListOnVertices(refreeze,SurfaceforcingsRefreezeEnum); // loop over all vertices for(v=0;vAddInput(SurfaceforcingsMassBalanceEnum,smb,P1Enum); xDelete(acc); xDelete(evap); xDelete(melt); xDelete(refreeze); xDelete(smb); } }/*}}}*/