source: issm/trunk/src/c/analyses/HydrologySommersAnalysis.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: 23.6 KB
RevLine 
[19720]1#include "./HydrologySommersAnalysis.h"
2#include "../toolkits/toolkits.h"
3#include "../classes/classes.h"
4#include "../shared/shared.h"
5#include "../modules/modules.h"
6
[19725]7/*Define 2 hardcoded parameters*/
8#define OMEGA 0.001 // parameter controlling transition to nonlinear resistance in basal system (dimensionless)
9#define NU 1.787e-6 //kinematic water viscosity m^2/s
[21341]10#define CT 7.5e-8 // Clapeyron slope (K/Pa)
11#define CW 4.22e3 // specific heat capacity of water (J/kg/K)
[19725]12
[19720]13/*Model processing*/
14void HydrologySommersAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
15
16 /*retrieve some parameters: */
17 int hydrology_model;
[21341]18 iomodel->FindConstant(&hydrology_model,"md.hydrology.model");
[19720]19
20 if(hydrology_model!=HydrologysommersEnum) return;
21
[21341]22 IoModelToConstraintsx(constraints,iomodel,"md.hydrology.spchead",HydrologySommersAnalysisEnum,P1Enum);
[19720]23
24}/*}}}*/
25void HydrologySommersAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
[19744]26
27 /*Fetch parameters: */
28 int hydrology_model;
[21341]29 iomodel->FindConstant(&hydrology_model,"md.hydrology.model");
[19744]30
31 /*Now, do we really want Sommers?*/
32 if(hydrology_model!=HydrologysommersEnum) return;
33
[19749]34 /*Create discrete loads for Moulins*/
[19744]35 CreateSingleNodeToElementConnectivity(iomodel);
36 for(int i=0;i<iomodel->numberofvertices;i++){
37 if (iomodel->domaintype!=Domain3DEnum){
38 /*keep only this partition's nodes:*/
39 if(iomodel->my_vertices[i]){
40 loads->AddObject(new Moulin(iomodel->loadcounter+i+1,i,iomodel,HydrologySommersAnalysisEnum));
41 }
42 }
[21341]43 else if(reCast<int>(iomodel->Data("md.mesh.vertexonbase")[i])){
[19744]44 if(iomodel->my_vertices[i]){
45 loads->AddObject(new Moulin(iomodel->loadcounter+i+1,i,iomodel,HydrologySommersAnalysisEnum));
46 }
47 }
48 }
[21341]49 iomodel->DeleteData(1,"md.mesh.vertexonbase");
[19744]50
[19749]51 /*Deal with Neumann BC*/
52 int M,N;
53 int *segments = NULL;
[21341]54 iomodel->FetchData(&segments,&M,&N,"md.mesh.segments");
[19749]55
56 /*Check that the size seem right*/
57 _assert_(N==3); _assert_(M>=3);
58 for(int i=0;i<M;i++){
59 if(iomodel->my_elements[segments[i*3+2]-1]){
60 loads->AddObject(new Neumannflux(iomodel->loadcounter+i+1,i,iomodel,segments,HydrologySommersAnalysisEnum));
61 }
62 }
63
64 xDelete<int>(segments);
65
[19720]66}/*}}}*/
67void HydrologySommersAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
68
69 /*Fetch parameters: */
70 int hydrology_model;
[21341]71 iomodel->FindConstant(&hydrology_model,"md.hydrology.model");
[19720]72
73 /*Now, do we really want Sommers?*/
74 if(hydrology_model!=HydrologysommersEnum) return;
75
[21341]76 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,"md.mesh.vertexonbase","md.mesh.vertexonsurface");
[19720]77 ::CreateNodes(nodes,iomodel,HydrologySommersAnalysisEnum,P1Enum);
[21341]78 iomodel->DeleteData(2,"md.mesh.vertexonbase","md.mesh.vertexonsurface");
[19720]79}/*}}}*/
80int HydrologySommersAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
81 return 1;
82}/*}}}*/
83void HydrologySommersAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
84
85 /*Fetch data needed: */
[19740]86 int hydrology_model,frictionlaw;
[21341]87 iomodel->FindConstant(&hydrology_model,"md.hydrology.model");
[19720]88
89 /*Now, do we really want Sommers?*/
90 if(hydrology_model!=HydrologysommersEnum) return;
91
92 /*Update elements: */
93 int counter=0;
94 for(int i=0;i<iomodel->numberofelements;i++){
95 if(iomodel->my_elements[i]){
96 Element* element=(Element*)elements->GetObjectByOffset(counter);
97 element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
98 counter++;
99 }
100 }
101
[21341]102 iomodel->FetchDataToInput(elements,"md.geometry.thickness",ThicknessEnum);
103 iomodel->FetchDataToInput(elements,"md.geometry.base",BaseEnum);
[19720]104 if(iomodel->domaintype!=Domain2DhorizontalEnum){
[21341]105 iomodel->FetchDataToInput(elements,"md.mesh.vertexonbase",MeshVertexonbaseEnum);
106 iomodel->FetchDataToInput(elements,"md.mesh.vertexonsurface",MeshVertexonsurfaceEnum);
[19720]107 }
[21341]108 iomodel->FetchDataToInput(elements,"md.mask.ice_levelset",MaskIceLevelsetEnum);
109 iomodel->FetchDataToInput(elements,"md.mask.groundedice_levelset",MaskGroundediceLevelsetEnum);
110 iomodel->FetchDataToInput(elements,"md.basalforcings.groundedice_melting_rate",BasalforcingsGroundediceMeltingRateEnum);
111 iomodel->FetchDataToInput(elements,"md.basalforcings.geothermalflux",BasalforcingsGeothermalfluxEnum);
112 iomodel->FetchDataToInput(elements,"md.hydrology.head",HydrologyHeadEnum);
113 iomodel->FetchDataToInput(elements,"md.hydrology.gap_height",HydrologyGapHeightEnum);
114 iomodel->FetchDataToInput(elements,"md.hydrology.englacial_input",HydrologyEnglacialInputEnum);
115 iomodel->FetchDataToInput(elements,"md.hydrology.moulin_input",HydrologyMoulinInputEnum);
116 iomodel->FetchDataToInput(elements,"md.hydrology.bump_spacing",HydrologyBumpSpacingEnum);
117 iomodel->FetchDataToInput(elements,"md.hydrology.bump_height",HydrologyBumpHeightEnum);
118 iomodel->FetchDataToInput(elements,"md.hydrology.reynolds",HydrologyReynoldsEnum);
119 iomodel->FetchDataToInput(elements,"md.hydrology.neumannflux",HydrologyNeumannfluxEnum);
120 iomodel->FetchDataToInput(elements,"md.initialization.vx",VxEnum);
121 iomodel->FetchDataToInput(elements,"md.initialization.vy",VyEnum);
122 iomodel->FindConstant(&frictionlaw,"md.friction.law");
[21729]123
[19740]124 /*Friction law variables*/
125 switch(frictionlaw){
[19766]126 case 1:
[21341]127 iomodel->FetchDataToInput(elements,"md.friction.coefficient",FrictionCoefficientEnum);
128 iomodel->FetchDataToInput(elements,"md.friction.p",FrictionPEnum);
129 iomodel->FetchDataToInput(elements,"md.friction.q",FrictionQEnum);
[19766]130 break;
[19740]131 case 8:
[21341]132 iomodel->FetchDataToInput(elements,"md.friction.coefficient",FrictionCoefficientEnum);
[19740]133 break;
134 default:
135 _error_("Friction law "<< frictionlaw <<" not supported");
136 }
[19720]137}/*}}}*/
138void HydrologySommersAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
139
140 /*retrieve some parameters: */
[22758]141 int hydrology_model;
142 int numoutputs;
143 char** requestedoutputs = NULL;
[21341]144 iomodel->FindConstant(&hydrology_model,"md.hydrology.model");
[19720]145
146 /*Now, do we really want Sommers?*/
147 if(hydrology_model!=HydrologysommersEnum) return;
148
149 parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));
[21341]150 parameters->AddObject(iomodel->CopyConstantObject("md.friction.law",FrictionLawEnum));
[21729]151 parameters->AddObject(iomodel->CopyConstantObject("md.hydrology.relaxation",HydrologyRelaxationEnum));
152 parameters->AddObject(iomodel->CopyConstantObject("md.hydrology.storage",HydrologyStorageEnum));
[22758]153
154 /*Requested outputs*/
155 iomodel->FindConstant(&requestedoutputs,&numoutputs,"md.hydrology.requested_outputs");
156 parameters->AddObject(new IntParam(HydrologyNumRequestedOutputsEnum,numoutputs));
157 if(numoutputs)parameters->AddObject(new StringArrayParam(HydrologyRequestedOutputsEnum,requestedoutputs,numoutputs));
158 iomodel->DeleteData(&requestedoutputs,numoutputs,"md.hydrology.requested_outputs");
[19720]159}/*}}}*/
160
161/*Finite Element Analysis*/
162void HydrologySommersAnalysis::Core(FemModel* femmodel){/*{{{*/
163 _error_("not implemented");
164}/*}}}*/
165ElementVector* HydrologySommersAnalysis::CreateDVector(Element* element){/*{{{*/
166 /*Default, return NULL*/
167 return NULL;
168}/*}}}*/
169ElementMatrix* HydrologySommersAnalysis::CreateJacobianMatrix(Element* element){/*{{{*/
170_error_("Not implemented");
171}/*}}}*/
172ElementMatrix* HydrologySommersAnalysis::CreateKMatrix(Element* element){/*{{{*/
173
174 /*Intermediaries */
175 IssmDouble Jdet;
176 IssmDouble* xyz_list = NULL;
177
178 /*Fetch number of nodes and dof for this finite element*/
179 int numnodes = element->GetNumberOfNodes();
180
181 /*Initialize Element vector and other vectors*/
182 ElementMatrix* Ke = element->NewElementMatrix();
183 IssmDouble* dbasis = xNew<IssmDouble>(2*numnodes);
[21729]184 IssmDouble* basis = xNew<IssmDouble>(numnodes);
[19720]185
186 /*Retrieve all inputs and parameters*/
187 element->GetVerticesCoordinates(&xyz_list);
188
[19725]189 /*Get conductivity from inputs*/
190 IssmDouble conductivity = GetConductivity(element);
191
[21729]192 /*Get englacial storage coefficient*/
193 IssmDouble storage,dt;
194 element->FindParam(&storage,HydrologyStorageEnum);
195 element->FindParam(&dt,TimesteppingTimeStepEnum);
196
[19720]197 /* Start looping on the number of gaussian points: */
[19731]198 Gauss* gauss=element->NewGauss(1);
[19720]199 for(int ig=gauss->begin();ig<gauss->end();ig++){
200 gauss->GaussPoint(ig);
201
202 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
203 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
[21729]204 element->NodalFunctions(basis,gauss);
[19720]205
206 for(int i=0;i<numnodes;i++){
207 for(int j=0;j<numnodes;j++){
[21729]208 Ke->values[i*numnodes+j] += conductivity*gauss->weight*Jdet*(dbasis[0*numnodes+i]*dbasis[0*numnodes+j] + dbasis[1*numnodes+i]*dbasis[1*numnodes+j])
209 + gauss->weight*Jdet*storage/dt*basis[i]*basis[j];
[19720]210 }
211 }
212 }
213
214 /*Clean up and return*/
215 xDelete<IssmDouble>(xyz_list);
[22758]216 xDelete<IssmDouble>(basis);
[19720]217 xDelete<IssmDouble>(dbasis);
218 delete gauss;
219 return Ke;
220}/*}}}*/
221ElementVector* HydrologySommersAnalysis::CreatePVector(Element* element){/*{{{*/
222
223 /*Skip if water or ice shelf element*/
224 if(element->IsFloating()) return NULL;
225
226 /*Intermediaries */
[19725]227 IssmDouble Jdet,meltrate,G,dh[2],B,A,n;
[21341]228 IssmDouble gap,bed,thickness,head,ieb,head_old;
[19740]229 IssmDouble lr,br,vx,vy,beta;
230 IssmDouble alpha2,frictionheat;
[21341]231 IssmDouble PMPheat,dpressure_water[2],dbed[2];
[19720]232 IssmDouble* xyz_list = NULL;
233
234 /*Fetch number of nodes and dof for this finite element*/
235 int numnodes = element->GetNumberOfNodes();
236
237 /*Initialize Element vector and other vectors*/
238 ElementVector* pe = element->NewElementVector();
239 IssmDouble* basis = xNew<IssmDouble>(numnodes);
240
241 /*Retrieve all inputs and parameters*/
242 element->GetVerticesCoordinates(&xyz_list);
[19725]243 IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum);
244 IssmDouble g = element->GetMaterialParameter(ConstantsGEnum);
245 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum);
246 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
247 Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum);_assert_(geothermalflux_input);
248 Input* head_input = element->GetInput(HydrologyHeadEnum); _assert_(head_input);
249 Input* gap_input = element->GetInput(HydrologyGapHeightEnum); _assert_(gap_input);
250 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
251 Input* base_input = element->GetInput(BaseEnum); _assert_(base_input);
252 Input* B_input = element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
253 Input* n_input = element->GetInput(MaterialsRheologyNEnum); _assert_(n_input);
[19740]254 Input* englacial_input = element->GetInput(HydrologyEnglacialInputEnum); _assert_(englacial_input);
255 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);
256 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);
257 Input* lr_input = element->GetInput(HydrologyBumpSpacingEnum); _assert_(lr_input);
258 Input* br_input = element->GetInput(HydrologyBumpHeightEnum); _assert_(br_input);
[21341]259 Input* headold_input = element->GetInput(HydrologyHeadOldEnum); _assert_(headold_input);
[19720]260
[19725]261 /*Get conductivity from inputs*/
262 IssmDouble conductivity = GetConductivity(element);
263
[21729]264 /*Get englacial storage coefficient*/
265 IssmDouble storage,dt;
266 element->FindParam(&storage,HydrologyStorageEnum);
267 element->FindParam(&dt,TimesteppingTimeStepEnum);
268
[19740]269 /*Build friction element, needed later: */
[19926]270 Friction* friction=new Friction(element,2);
[19740]271
[19720]272 /* Start looping on the number of gaussian points: */
273 Gauss* gauss=element->NewGauss(2);
274 for(int ig=gauss->begin();ig<gauss->end();ig++){
275 gauss->GaussPoint(ig);
276
277 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
278 element->NodalFunctions(basis,gauss);
[19725]279 geothermalflux_input->GetInputValue(&G,gauss);
280 base_input->GetInputValue(&bed,gauss);
[21341]281 base_input->GetInputDerivativeValue(&dbed[0],xyz_list,gauss);
[19725]282 thickness_input->GetInputValue(&thickness,gauss);
283 gap_input->GetInputValue(&gap,gauss);
284 head_input->GetInputValue(&head,gauss);
285 head_input->GetInputDerivativeValue(&dh[0],xyz_list,gauss);
[19740]286 englacial_input->GetInputValue(&ieb,gauss);
287 lr_input->GetInputValue(&lr,gauss);
288 br_input->GetInputValue(&br,gauss);
289 vx_input->GetInputValue(&vx,gauss);
290 vy_input->GetInputValue(&vy,gauss);
[21341]291 headold_input->GetInputValue(&head_old,gauss);
[19720]292
[19725]293 /*Get ice A parameter*/
294 B_input->GetInputValue(&B,gauss);
295 n_input->GetInputValue(&n,gauss);
296 A=pow(B,-n);
[19740]297
298 /*Compute beta term*/
299 if(gap<br)
300 beta = (br-gap)/lr;
301 else
302 beta = 0.;
[19720]303
[19740]304 /*Compute frictional heat flux*/
305 friction->GetAlpha2(&alpha2,gauss);
306 vx_input->GetInputValue(&vx,gauss);
307 vy_input->GetInputValue(&vy,gauss);
308 frictionheat=alpha2*(vx*vx+vy*vy);
309
[19725]310 /*Get water and ice pressures*/
311 IssmDouble pressure_ice = rho_ice*g*thickness; _assert_(pressure_ice>0.);
312 IssmDouble pressure_water = rho_water*g*(head-bed);
[19749]313 if(pressure_water>pressure_ice) pressure_water = pressure_ice;
[19725]314
[21341]315 /*Get water pressure from previous time step to use in lagged creep term*/
316 IssmDouble pressure_water_old = rho_water*g*(head_old-bed);
317 if(pressure_water_old>pressure_ice) pressure_water_old = pressure_ice;
318
319 /*Compute change in sensible heat due to changes in pressure melting point*/
320 dpressure_water[0] = rho_water*g*(dh[0] - dbed[0]);
321 dpressure_water[1] = rho_water*g*(dh[1] - dbed[1]);
322 PMPheat=-CT*CW*conductivity*(dh[0]*dpressure_water[0]+dh[1]*dpressure_water[1]);
323
[22758]324 meltrate = 1/latentheat*(G+frictionheat+rho_water*g*conductivity*(dh[0]*dh[0]+dh[1]*dh[1])-PMPheat);
[19725]325 _assert_(meltrate>0.);
[21729]326
[19725]327 for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*
328 (
329 meltrate*(1/rho_water-1/rho_ice)
[21729]330 +A*pow(fabs(pressure_ice - pressure_water),n-1)*(pressure_ice - pressure_water)*gap
[19740]331 -beta*sqrt(vx*vx+vy*vy)
332 +ieb
[21729]333 +storage*head_old/dt
[21341]334 )*basis[i];
[19720]335 }
336 /*Clean up and return*/
337 xDelete<IssmDouble>(xyz_list);
338 xDelete<IssmDouble>(basis);
[19740]339 delete friction;
[19720]340 delete gauss;
341 return pe;
342}/*}}}*/
343void HydrologySommersAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
344 element->GetSolutionFromInputsOneDof(solution,HydrologyHeadEnum);
345}/*}}}*/
346void HydrologySommersAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
347 _error_("Not implemented yet");
348}/*}}}*/
349void HydrologySommersAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
350
351 /*Intermediary*/
[19725]352 IssmDouble dh[3];
[19720]353 int* doflist = NULL;
[19725]354 IssmDouble* xyz_list = NULL;
[19720]355
[21341]356 /*Get gravity from parameters*/
357 IssmDouble g = element->GetMaterialParameter(ConstantsGEnum);
358
[19720]359 /*Fetch number of nodes for this finite element*/
360 int numnodes = element->GetNumberOfNodes();
361
362 /*Fetch dof list and allocate solution vector*/
363 element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
364 IssmDouble* values = xNew<IssmDouble>(numnodes);
365
[19725]366 /*Get thickness and base on nodes to apply cap on water head*/
[21341]367 IssmDouble* eff_pressure = xNew<IssmDouble>(numnodes);
[19725]368 IssmDouble* thickness = xNew<IssmDouble>(numnodes);
369 IssmDouble* bed = xNew<IssmDouble>(numnodes);
370 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum);
371 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
372 element->GetInputListOnNodes(&thickness[0],ThicknessEnum);
373 element->GetInputListOnNodes(&bed[0],BaseEnum);
374
[21729]375 /*Get head from previous time-step and under-relaxation coefficient to use in under-relaxation for nonlinear convergence*/
376 IssmDouble* head_old = xNew<IssmDouble>(numnodes);
377 element->GetInputListOnNodes(&head_old[0],HydrologyHeadEnum);
378 IssmDouble relaxation;
379 element->FindParam(&relaxation,HydrologyRelaxationEnum);
380
[19720]381 /*Use the dof list to index into the solution vector: */
382 for(int i=0;i<numnodes;i++){
383 values[i]=solution[doflist[i]];
[19725]384
385 /*make sure that p_water<p_ice -> h<rho_i H/rho_w + zb*/
386 if(values[i]>rho_ice*thickness[i]/rho_water+bed[i]){
387 values[i] = rho_ice*thickness[i]/rho_water+bed[i];
388 }
389
[19926]390 /*Make sure that negative pressure is not allowed*/
[22758]391 // if(values[i]<bed[i]){
392 // values[i] = bed[i];
393 // }
[19926]394
[21729]395 /*Under-relaxation*/
396 values[i] = head_old[i] - relaxation*(head_old[i]-values[i]);
397
[21341]398 /*Calculate effective pressure*/
399 eff_pressure[i] = rho_ice*g*thickness[i] - rho_water*g*(values[i]-bed[i]);
400
[19720]401 if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector");
[21341]402 if(xIsInf<IssmDouble>(values[i])) _error_("Inf found in solution vector");
[19720]403 }
404
405 /*Add input to the element: */
406 element->AddInput(HydrologyHeadEnum,values,element->GetElementType());
[21341]407 element->AddInput(EffectivePressureEnum,eff_pressure,P1Enum);
[19720]408
[19725]409 /*Update reynolds number according to new solution*/
410 element->GetVerticesCoordinates(&xyz_list);
411 Input* head_input = element->GetInput(HydrologyHeadEnum);_assert_(head_input);
412 head_input->GetInputDerivativeAverageValue(&dh[0],xyz_list);
413 IssmDouble conductivity = GetConductivity(element);
[21341]414
[21729]415 IssmDouble reynolds = conductivity*sqrt(dh[0]*dh[0]+dh[1]*dh[1])/NU;
[19725]416 element->AddInput(HydrologyReynoldsEnum,&reynolds,P0Enum);
417
[21729]418 /*Free resources:*/
[19720]419 xDelete<IssmDouble>(values);
[19725]420 xDelete<IssmDouble>(thickness);
421 xDelete<IssmDouble>(bed);
422 xDelete<IssmDouble>(xyz_list);
[19720]423 xDelete<int>(doflist);
[21341]424 xDelete<IssmDouble>(eff_pressure);
[21729]425 xDelete<IssmDouble>(head_old);
[19720]426}/*}}}*/
427void HydrologySommersAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
428 /*Default, do nothing*/
429 return;
430}/*}}}*/
[19725]431
432/*Additional methods*/
433IssmDouble HydrologySommersAnalysis::GetConductivity(Element* element){/*{{{*/
434
435 /*Intermediaries */
436 IssmDouble gap,reynolds;
437
438 /*Get gravity from parameters*/
439 IssmDouble g = element->GetMaterialParameter(ConstantsGEnum);
440
441 /*Get Reynolds and gap average values*/
442 Input* reynolds_input = element->GetInput(HydrologyReynoldsEnum); _assert_(reynolds_input);
443 Input* gap_input = element->GetInput(HydrologyGapHeightEnum); _assert_(gap_input);
444 reynolds_input->GetInputAverage(&reynolds);
445 gap_input->GetInputAverage(&gap);
[21341]446
[19725]447 /*Compute conductivity*/
448 IssmDouble conductivity = pow(gap,3)*g/(12.*NU*(1+OMEGA*reynolds));
449 _assert_(conductivity>0);
450
451 /*Clean up and return*/
452 return conductivity;
453}/*}}}*/
[19740]454void HydrologySommersAnalysis::UpdateGapHeight(FemModel* femmodel){/*{{{*/
455
456
457 for(int j=0;j<femmodel->elements->Size();j++){
458 Element* element=(Element*)femmodel->elements->GetObjectByOffset(j);
459 UpdateGapHeight(element);
460 }
461
462}/*}}}*/
463void HydrologySommersAnalysis::UpdateGapHeight(Element* element){/*{{{*/
464
465 /*Skip if water or ice shelf element*/
466 if(element->IsFloating()) return;
467
468 /*Intermediaries */
469 IssmDouble newgap = 0.;
470 IssmDouble Jdet,meltrate,G,dh[2],B,A,n,dt;
471 IssmDouble gap,bed,thickness,head,ieb;
472 IssmDouble lr,br,vx,vy,beta;
473 IssmDouble alpha2,frictionheat;
474 IssmDouble* xyz_list = NULL;
[21341]475 IssmDouble dpressure_water[2],dbed[2],PMPheat;
[21729]476 IssmDouble q = 0.;
[22758]477 IssmDouble channelization = 0.;
[19740]478
479 /*Retrieve all inputs and parameters*/
480 element->GetVerticesCoordinates(&xyz_list);
481 element->FindParam(&dt,TimesteppingTimeStepEnum);
482 IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum);
483 IssmDouble g = element->GetMaterialParameter(ConstantsGEnum);
484 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum);
485 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
486 Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum);_assert_(geothermalflux_input);
487 Input* head_input = element->GetInput(HydrologyHeadEnum); _assert_(head_input);
488 Input* gap_input = element->GetInput(HydrologyGapHeightEnum); _assert_(gap_input);
489 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
490 Input* base_input = element->GetInput(BaseEnum); _assert_(base_input);
491 Input* B_input = element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
492 Input* n_input = element->GetInput(MaterialsRheologyNEnum); _assert_(n_input);
493 Input* englacial_input = element->GetInput(HydrologyEnglacialInputEnum); _assert_(englacial_input);
494 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);
495 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);
496 Input* lr_input = element->GetInput(HydrologyBumpSpacingEnum); _assert_(lr_input);
497 Input* br_input = element->GetInput(HydrologyBumpHeightEnum); _assert_(br_input);
498
499 /*Get conductivity from inputs*/
500 IssmDouble conductivity = GetConductivity(element);
[21729]501
[19740]502 /*Build friction element, needed later: */
[19926]503 Friction* friction=new Friction(element,2);
[19740]504
505 /*Keep track of weights*/
506 IssmDouble totalweights=0.;
507
508 /* Start looping on the number of gaussian points: */
509 Gauss* gauss=element->NewGauss(2);
510 for(int ig=gauss->begin();ig<gauss->end();ig++){
511 gauss->GaussPoint(ig);
512
513 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
514
515 geothermalflux_input->GetInputValue(&G,gauss);
516 base_input->GetInputValue(&bed,gauss);
[21341]517 base_input->GetInputDerivativeValue(&dbed[0],xyz_list,gauss);
[19740]518 thickness_input->GetInputValue(&thickness,gauss);
519 gap_input->GetInputValue(&gap,gauss);
520 head_input->GetInputValue(&head,gauss);
521 head_input->GetInputDerivativeValue(&dh[0],xyz_list,gauss);
522 englacial_input->GetInputValue(&ieb,gauss);
523 lr_input->GetInputValue(&lr,gauss);
524 br_input->GetInputValue(&br,gauss);
525 vx_input->GetInputValue(&vx,gauss);
526 vy_input->GetInputValue(&vy,gauss);
527
528 /*Get ice A parameter*/
529 B_input->GetInputValue(&B,gauss);
530 n_input->GetInputValue(&n,gauss);
531 A=pow(B,-n);
532
533 /*Compute beta term*/
534 if(gap<br)
535 beta = (br-gap)/lr;
536 else
537 beta = 0.;
538
539 /*Compute frictional heat flux*/
540 friction->GetAlpha2(&alpha2,gauss);
541 vx_input->GetInputValue(&vx,gauss);
542 vy_input->GetInputValue(&vy,gauss);
543 frictionheat=alpha2*(vx*vx+vy*vy);
544
545 /*Get water and ice pressures*/
546 IssmDouble pressure_ice = rho_ice*g*thickness; _assert_(pressure_ice>0.);
547 IssmDouble pressure_water = rho_water*g*(head-bed);
[19749]548 if(pressure_water>pressure_ice) pressure_water = pressure_ice;
[19931]549
[21341]550 /* Compute change in sensible heat due to changes in pressure melting point*/
551 dpressure_water[0] = rho_water*g*(dh[0] - dbed[0]);
552 dpressure_water[1] = rho_water*g*(dh[1] - dbed[1]);
553 PMPheat=-CT*CW*conductivity*(dh[0]*dpressure_water[0]+dh[1]*dpressure_water[1]);
[22758]554
[21341]555 meltrate = 1/latentheat*(G+frictionheat+rho_water*g*conductivity*(dh[0]*dh[0]+dh[1]*dh[1])-PMPheat);
[19740]556 _assert_(meltrate>0.);
557
558 newgap += gauss->weight*Jdet*(gap+dt*(
559 meltrate/rho_ice
560 -A*pow(fabs(pressure_ice-pressure_water),n-1)*(pressure_ice-pressure_water)*gap
561 +beta*sqrt(vx*vx+vy*vy)
562 ));
563 totalweights +=gauss->weight*Jdet;
[21729]564
565 /* Compute basal water flux */
566 q += gauss->weight*Jdet*(conductivity*sqrt(dh[0]*dh[0]+dh[1]*dh[1]));
[22758]567
568 /* Compute "degree of channelization" (ratio of melt opening to opening by sliding) */
569 channelization += gauss->weight*Jdet*(meltrate/rho_ice/(meltrate/rho_ice+beta*sqrt(vx*vx+vy*vy)));
[19740]570 }
571
572 /*Divide by connectivity*/
573 newgap = newgap/totalweights;
[21729]574 IssmDouble mingap = 1e-6;
[19766]575 if(newgap<mingap) newgap=mingap;
[19740]576
[19931]577 /*Limit gap height to grow to surface*/
578 if(newgap>thickness)
579 newgap = thickness;
[22758]580
[19740]581 /*Add new gap as an input*/
582 element->AddInput(HydrologyGapHeightEnum,&newgap,P0Enum);
[21729]583
584 /*Divide by connectivity, add basal flux as an input*/
585 q = q/totalweights;
586 element->AddInput(HydrologyBasalFluxEnum,&q,P0Enum);
[19740]587
[22758]588 /* Divide by connectivity, add degree of channelization as an input */
589 channelization = channelization/totalweights;
590 element->AddInput(DegreeOfChannelizationEnum,&channelization,P0Enum);
591
[19740]592 /*Clean up and return*/
593 xDelete<IssmDouble>(xyz_list);
594 delete friction;
595 delete gauss;
596}/*}}}*/
Note: See TracBrowser for help on using the repository browser.