source: issm/trunk/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp@ 22758

Last change on this file since 22758 was 22758, checked in by Mathieu Morlighem, 7 years ago

merged trunk-jpl and trunk for revision 22757

File size: 14.4 KB
Line 
1/*!\file SurfaceMassBalancex
2 * \brief: calculates SMB
3 */
4
5#include "./SurfaceMassBalancex.h"
6#include "../../shared/shared.h"
7#include "../../toolkits/toolkits.h"
8
9
10void SmbGradientsx(FemModel* femmodel){/*{{{*/
11
12 // void SurfaceMassBalancex(hd,agd,ni){
13 // INPUT parameters: ni: working size of arrays
14 // INPUT: surface elevation (m): hd(NA)
15 // OUTPUT: mass-balance (m/yr ice): agd(NA)
16 int v;
17 IssmDouble rho_water; // density of fresh water
18 IssmDouble rho_ice; // density of ice
19 IssmDouble yts; // conversion factor year to second
20
21 /*Loop over all the elements of this partition*/
22 for(int i=0;i<femmodel->elements->Size();i++){
23 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
24
25 /*Allocate all arrays*/
26 int numvertices = element->GetNumberOfVertices();
27 IssmDouble* Href = xNew<IssmDouble>(numvertices); // reference elevation from which deviations are used to calculate the SMB adjustment
28 IssmDouble* Smbref = xNew<IssmDouble>(numvertices); // reference SMB to which deviations are added
29 IssmDouble* b_pos = xNew<IssmDouble>(numvertices); // Hs-SMB relation parameter
30 IssmDouble* b_neg = xNew<IssmDouble>(numvertices); // Hs-SMB relation paremeter
31 IssmDouble* s = xNew<IssmDouble>(numvertices); // surface elevation (m)
32 IssmDouble* smb = xNew<IssmDouble>(numvertices);
33
34 /*Recover SmbGradients*/
35 element->GetInputListOnVertices(Href,SmbHrefEnum);
36 element->GetInputListOnVertices(Smbref,SmbSmbrefEnum);
37 element->GetInputListOnVertices(b_pos,SmbBPosEnum);
38 element->GetInputListOnVertices(b_neg,SmbBNegEnum);
39
40 /*Recover surface elevation at vertices: */
41 element->GetInputListOnVertices(s,SurfaceEnum);
42
43 /*Get material parameters :*/
44 rho_ice=element->matpar->GetMaterialParameter(MaterialsRhoIceEnum);
45 rho_water=element->matpar->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
46
47 /* Get constants */
48 femmodel->parameters->FindParam(&yts,ConstantsYtsEnum);
49
50 // loop over all vertices
51 for(v=0;v<numvertices;v++){
52 if(Smbref[v]>0){
53 smb[v]=Smbref[v]+b_pos[v]*(s[v]-Href[v]);
54 }
55 else{
56 smb[v]=Smbref[v]+b_neg[v]*(s[v]-Href[v]);
57 }
58
59 smb[v]=smb[v]/1000*rho_water/rho_ice; // SMB in m/y ice
60 } //end of the loop over the vertices
61
62 /*Add input to element and Free memory*/
63 element->AddInput(SmbMassBalanceEnum,smb,P1Enum);
64 xDelete<IssmDouble>(Href);
65 xDelete<IssmDouble>(Smbref);
66 xDelete<IssmDouble>(b_pos);
67 xDelete<IssmDouble>(b_neg);
68 xDelete<IssmDouble>(s);
69 xDelete<IssmDouble>(smb);
70 }
71
72}/*}}}*/
73void SmbGradientsElax(FemModel* femmodel){/*{{{*/
74
75 // void SurfaceMassBalancex(hd,agd,ni){
76 // INPUT parameters: ni: working size of arrays
77 // INPUT: surface elevation (m): hd(NA)
78 // OUTPUT: surface mass-balance (m/yr ice): agd(NA)
79 int v;
80
81 /*Loop over all the elements of this partition*/
82 for(int i=0;i<femmodel->elements->Size();i++){
83 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
84
85 /*Allocate all arrays*/
86 int numvertices = element->GetNumberOfVertices();
87 IssmDouble* ela = xNew<IssmDouble>(numvertices); // Equilibrium Line Altitude (m a.s.l) to which deviations are used to calculate the SMB
88 IssmDouble* b_pos = xNew<IssmDouble>(numvertices); // SMB gradient above ELA (m ice eq. per m elevation change)
89 IssmDouble* b_neg = xNew<IssmDouble>(numvertices); // SMB gradient below ELA (m ice eq. per m elevation change)
90 IssmDouble* b_max = xNew<IssmDouble>(numvertices); // Upper cap on SMB rate (m/y ice eq.)
91 IssmDouble* b_min = xNew<IssmDouble>(numvertices); // Lower cap on SMB rate (m/y ice eq.)
92 IssmDouble* s = xNew<IssmDouble>(numvertices); // Surface elevation (m a.s.l.)
93 IssmDouble* smb = xNew<IssmDouble>(numvertices); // SMB (m/y ice eq.)
94
95 /*Recover ELA, SMB gradients, and caps*/
96 element->GetInputListOnVertices(ela,SmbElaEnum);
97 element->GetInputListOnVertices(b_pos,SmbBPosEnum);
98 element->GetInputListOnVertices(b_neg,SmbBNegEnum);
99 element->GetInputListOnVertices(b_max,SmbBMaxEnum);
100 element->GetInputListOnVertices(b_min,SmbBMinEnum);
101
102 /*Recover surface elevation at vertices: */
103 element->GetInputListOnVertices(s,SurfaceEnum);
104
105 /*Loop over all vertices, calculate SMB*/
106 for(v=0;v<numvertices;v++){
107 // if surface is above the ELA
108 if(s[v]>ela[v]){
109 smb[v]=b_pos[v]*(s[v]-ela[v]);
110 }
111 // if surface is below or equal to the ELA
112 else{
113 smb[v]=b_neg[v]*(s[v]-ela[v]);
114 }
115
116 // if SMB is larger than upper cap, set SMB to upper cap
117 if(smb[v]>b_max[v]){
118 smb[v]=b_max[v];
119 }
120 // if SMB is smaller than lower cap, set SMB to lower cap
121 if(smb[v]<b_min[v]){
122 smb[v]=b_min[v];
123 }
124 } //end of the loop over the vertices
125
126 /*Add input to element and Free memory*/
127 element->AddInput(SmbMassBalanceEnum,smb,P1Enum);
128 xDelete<IssmDouble>(ela);
129 xDelete<IssmDouble>(b_pos);
130 xDelete<IssmDouble>(b_neg);
131 xDelete<IssmDouble>(b_max);
132 xDelete<IssmDouble>(b_min);
133 xDelete<IssmDouble>(s);
134 xDelete<IssmDouble>(smb);
135
136 }
137
138}/*}}}*/
139void Delta18oParameterizationx(FemModel* femmodel){/*{{{*/
140
141 for(int i=0;i<femmodel->elements->Size();i++){
142 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
143 element->Delta18oParameterization();
144 }
145
146}/*}}}*/
147void MungsmtpParameterizationx(FemModel* femmodel){/*{{{*/
148
149 for(int i=0;i<femmodel->elements->Size();i++){
150 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
151 element->MungsmtpParameterization();
152 }
153
154}/*}}}*/
155void Delta18opdParameterizationx(FemModel* femmodel){/*{{{*/
156
157 for(int i=0;i<femmodel->elements->Size();i++){
158 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
159 element->Delta18opdParameterization();
160 }
161
162}/*}}}*/
163void PositiveDegreeDayx(FemModel* femmodel){/*{{{*/
164
165 // void PositiveDegreeDayx(hd,vTempsea,vPrec,agd,Tsurf,ni){
166 // note "v" prefix means 12 monthly means, ie time dimension
167 // INPUT parameters: ni: working size of arrays
168 // INPUT: surface elevation (m): hd(NA)
169 // monthly mean surface sealevel temperature (degrees C): vTempsea(NA
170 // ,NTIME)
171 // monthly mean precip rate (m/yr water equivalent): vPrec(NA,NTIME)
172 // OUTPUT: mass-balance (m/yr ice): agd(NA)
173 // mean annual surface temperature (degrees C): Tsurf(NA)
174
175 int i, it, jj, itm;
176 IssmDouble DT = 0.02, sigfac, snormfac;
177 IssmDouble signorm = 5.5; // signorm : sigma of the temperature distribution for a normal day
178 IssmDouble siglim; // sigma limit for the integration which is equal to 2.5 sigmanorm
179 IssmDouble signormc = signorm - 0.5; // sigma of the temperature distribution for cloudy day
180 IssmDouble siglimc, siglim0, siglim0c;
181 IssmDouble tstep, tsint, tint, tstepc;
182 int NPDMAX = 1504, NPDCMAX = 1454;
183 //IssmDouble pdds[NPDMAX]={0};
184 //IssmDouble pds[NPDCMAX]={0};
185 IssmDouble pddt, pd ; // pd : snow/precip fraction, precipitation falling as snow
186 IssmDouble PDup, PDCUT = 2.0; // PDcut: rain/snow cutoff temperature (C)
187 IssmDouble tstar; // monthly mean surface temp
188
189 bool ismungsm;
190 bool issetpddfac;
191
192 IssmDouble *pdds = NULL;
193 IssmDouble *pds = NULL;
194 Element *element = NULL;
195
196 pdds=xNew<IssmDouble>(NPDMAX+1);
197 pds=xNew<IssmDouble>(NPDCMAX+1);
198
199 // Get ismungsm parameter
200 femmodel->parameters->FindParam(&ismungsm,SmbIsmungsmEnum);
201
202 // Get issetpddfac parameter
203 femmodel->parameters->FindParam(&issetpddfac,SmbIssetpddfacEnum);
204
205 /* initialize PDD (creation of a lookup table)*/
206 tstep = 0.1;
207 tsint = tstep*0.5;
208 sigfac = -1.0/(2.0*pow(signorm,2));
209 snormfac = 1.0/(signorm*sqrt(2.0*acos(-1.0)));
210 siglim = 2.5*signorm;
211 siglimc = 2.5*signormc;
212 siglim0 = siglim/DT + 0.5;
213 siglim0c = siglimc/DT + 0.5;
214 PDup = siglimc+PDCUT;
215
216 itm = reCast<int,IssmDouble>((2*siglim/DT + 1.5));
217
218 if(itm >= NPDMAX) _error_("increase NPDMAX in massBalance.cpp");
219 for(it = 0; it < itm; it++){
220 // tstar = REAL(it)*DT-siglim;
221 tstar = it*DT-siglim;
222 tint = tsint;
223 pddt = 0.;
224 for ( jj = 0; jj < 600; jj++){
225 if (tint > (tstar+siglim)){break;}
226 pddt = pddt + tint*exp(sigfac*(pow((tint-tstar),2)))*tstep;
227 tint = tint+tstep;
228 }
229 pdds[it] = pddt*snormfac;
230 }
231 pdds[itm+1] = siglim + DT;
232
233 //*********compute PD(T) : snow/precip fraction. precipitation falling as snow
234 tstepc = 0.1;
235 tsint = PDCUT-tstepc*0.5;
236 signormc = signorm - 0.5;
237 sigfac = -1.0/(2.0*pow(signormc,2));
238 snormfac = 1.0/(signormc*sqrt(2.0*acos(-1.0)));
239 siglimc = 2.5*signormc ;
240 itm = reCast<int,IssmDouble>((PDCUT+2.*siglimc)/DT + 1.5);
241 if(itm >= NPDCMAX) _error_("increase NPDCMAX in p35com");
242 for(it = 0; it < itm; it++ ){
243 tstar = it*DT-siglimc;
244 // tstar = REAL(it)*DT-siglimc;
245 tint = tsint; // start against upper bound
246 pd = 0.;
247 for (jj = 0; jj < 600; jj++){
248 if (tint<(tstar-siglimc)) {break;}
249 pd = pd + exp(sigfac*(pow((tint-tstar),2)))*tstepc;
250 tint = tint-tstepc;
251 }
252 pds[it] = pd*snormfac; // gaussian integral lookup table for snow fraction
253 }
254 pds[itm+1] = 0.;
255 // *******END initialize PDD
256
257 for(i=0;i<femmodel->elements->Size();i++){
258 element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
259 element->PositiveDegreeDay(pdds,pds,signorm,ismungsm,issetpddfac);
260 }
261 /*free ressouces: */
262 xDelete<IssmDouble>(pdds);
263 xDelete<IssmDouble>(pds);
264}/*}}}*/
265void SmbHenningx(FemModel* femmodel){/*{{{*/
266
267 /*Intermediaries*/
268 IssmDouble z_critical = 1675.;
269 IssmDouble dz = 0;
270 IssmDouble a = -15.86;
271 IssmDouble b = 0.00969;
272 IssmDouble c = -0.235;
273 IssmDouble f = 1.;
274 IssmDouble g = -0.0011;
275 IssmDouble h = -1.54e-5;
276 IssmDouble smb,smbref,anomaly,yts,z;
277
278 /* Get constants */
279 femmodel->parameters->FindParam(&yts,ConstantsYtsEnum);
280 /*iomodel->FindConstant(&yts,"md.constants.yts");*/
281 /*this->parameters->FindParam(&yts,ConstantsYtsEnum);*/
282 /*Mathieu original*/
283 /*IssmDouble smb,smbref,z;*/
284
285 /*Loop over all the elements of this partition*/
286 for(int i=0;i<femmodel->elements->Size();i++){
287 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
288
289 /*Get reference SMB (uncorrected) and allocate all arrays*/
290 int numvertices = element->GetNumberOfVertices();
291 IssmDouble* surfacelist = xNew<IssmDouble>(numvertices);
292 IssmDouble* smblistref = xNew<IssmDouble>(numvertices);
293 IssmDouble* smblist = xNew<IssmDouble>(numvertices);
294 element->GetInputListOnVertices(surfacelist,SurfaceEnum);
295 element->GetInputListOnVertices(smblistref,SmbSmbrefEnum);
296
297 /*Loop over all vertices of element and correct SMB as a function of altitude z*/
298 for(int v=0;v<numvertices;v++){
299
300 /*Get vertex elevation, anoma smb*/
301 z = surfacelist[v];
302 anomaly = smblistref[v];
303
304 /* Henning edited acc. to Riannes equations*/
305 /* Set SMB maximum elevation, if dz = 0 -> z_critical = 1675 */
306 z_critical = z_critical + dz;
307
308 /* Calculate smb acc. to the surface elevation z */
309 if(z<z_critical){
310 smb = a + b*z + c;
311 }
312 else{
313 smb = (a + b*z)*(f + g*(z-z_critical) + h*(z-z_critical)*(z-z_critical)) + c;
314 }
315
316 /* Compute smb including anomaly,
317 correct for number of seconds in a year [s/yr]*/
318 smb = smb/yts + anomaly;
319
320
321 /*Update array accordingly*/
322 smblist[v] = smb;
323
324 }
325
326 /*Add input to element and Free memory*/
327 element->AddInput(SmbMassBalanceEnum,smblist,P1Enum);
328 xDelete<IssmDouble>(surfacelist);
329 xDelete<IssmDouble>(smblistref);
330 xDelete<IssmDouble>(smblist);
331 }
332
333}/*}}}*/
334void SmbComponentsx(FemModel* femmodel){/*{{{*/
335
336 // void SmbComponentsx(acc,evap,runoff,ni){
337 // INPUT parameters: ni: working size of arrays
338 // INPUT: surface accumulation (m/yr water equivalent): acc
339 // surface evaporation (m/yr water equivalent): evap
340 // surface runoff (m/yr water equivalent): runoff
341 // OUTPUT: mass-balance (m/yr ice): agd(NA)
342 int v;
343
344 /*Loop over all the elements of this partition*/
345 for(int i=0;i<femmodel->elements->Size();i++){
346 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
347
348 /*Allocate all arrays*/
349 int numvertices = element->GetNumberOfVertices();
350 IssmDouble* acc = xNew<IssmDouble>(numvertices);
351 IssmDouble* evap = xNew<IssmDouble>(numvertices);
352 IssmDouble* runoff = xNew<IssmDouble>(numvertices);
353 IssmDouble* smb = xNew<IssmDouble>(numvertices);
354
355 /*Recover Smb Components*/
356 element->GetInputListOnVertices(acc,SmbAccumulationEnum);
357 element->GetInputListOnVertices(evap,SmbEvaporationEnum);
358 element->GetInputListOnVertices(runoff,SmbRunoffEnum);
359
360 // loop over all vertices
361 for(v=0;v<numvertices;v++){
362 smb[v]=acc[v]-evap[v]-runoff[v];
363 } //end of the loop over the vertices
364
365 /*Add input to element and Free memory*/
366 element->AddInput(SmbMassBalanceEnum,smb,P1Enum);
367 xDelete<IssmDouble>(acc);
368 xDelete<IssmDouble>(evap);
369 xDelete<IssmDouble>(runoff);
370 xDelete<IssmDouble>(smb);
371 }
372
373}/*}}}*/
374void SmbMeltComponentsx(FemModel* femmodel){/*{{{*/
375
376 // void SmbMeltComponentsx(acc,evap,melt,refreeze,ni){
377 // INPUT parameters: ni: working size of arrays
378 // INPUT: surface accumulation (m/yr water equivalent): acc
379 // surface evaporation (m/yr water equivalent): evap
380 // surface melt (m/yr water equivalent): melt
381 // refreeze of surface melt (m/yr water equivalent): refreeze
382 // OUTPUT: mass-balance (m/yr ice): agd(NA)
383 int v;
384
385 /*Loop over all the elements of this partition*/
386 for(int i=0;i<femmodel->elements->Size();i++){
387 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
388
389 /*Allocate all arrays*/
390 int numvertices = element->GetNumberOfVertices();
391 IssmDouble* acc = xNew<IssmDouble>(numvertices);
392 IssmDouble* evap = xNew<IssmDouble>(numvertices);
393 IssmDouble* melt = xNew<IssmDouble>(numvertices);
394 IssmDouble* refreeze = xNew<IssmDouble>(numvertices);
395 IssmDouble* smb = xNew<IssmDouble>(numvertices);
396
397 /*Recover Smb Components*/
398 element->GetInputListOnVertices(acc,SmbAccumulationEnum);
399 element->GetInputListOnVertices(evap,SmbEvaporationEnum);
400 element->GetInputListOnVertices(melt,SmbMeltEnum);
401 element->GetInputListOnVertices(refreeze,SmbRefreezeEnum);
402
403 // loop over all vertices
404 for(v=0;v<numvertices;v++){
405 smb[v]=acc[v]-evap[v]-melt[v]+refreeze[v];
406 } //end of the loop over the vertices
407
408 /*Add input to element and Free memory*/
409 element->AddInput(SmbMassBalanceEnum,smb,P1Enum);
410 xDelete<IssmDouble>(acc);
411 xDelete<IssmDouble>(evap);
412 xDelete<IssmDouble>(melt);
413 xDelete<IssmDouble>(refreeze);
414 xDelete<IssmDouble>(smb);
415 }
416
417}/*}}}*/
Note: See TracBrowser for help on using the repository browser.