Skip to content

Commit c8cf662

Browse files
CHG: added Buttressing as potential output
1 parent 1ba1588 commit c8cf662

File tree

5 files changed

+179
-1
lines changed

5 files changed

+179
-1
lines changed

src/c/classes/Elements/Element.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ class Element: public Object{
241241
virtual void AddBasalInput(int input_enum, IssmDouble* values, int interpolation_enum){_error_("not implemented");};
242242
virtual void AddInput(int input_enum, IssmDouble* values, int interpolation_enum){_error_("not implemented");};
243243
virtual void AddControlInput(int input_enum,Inputs* inputs,IoModel* iomodel,IssmDouble* values,IssmDouble* values_min,IssmDouble* values_max, int interpolation_enum,int id){_error_("not supported yet");};
244+
virtual bool Buttressing(IssmDouble* ptheta, IssmDouble* plength){_error_("not implemented");};
244245
virtual void DatasetInputCreate(IssmDouble* array,int M,int N,int* individual_enums,int num_inputs,Inputs* inputs,IoModel* iomodel,int input_enum){_error_("not supported");};
245246
virtual void AverageOntoPartition(Vector<IssmDouble>* partition_contributions,Vector<IssmDouble>* partition_areas,IssmDouble* vertex_response,IssmDouble* qmu_part)=0;
246247
virtual void BasalNodeIndices(int* pnumindices,int** pindices,int finiteelement){_error_("not implemented yet");};

src/c/classes/Elements/Tria.cpp

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,156 @@ void Tria::AverageOntoPartition(Vector<IssmDouble>* partition_contribution
310310
}
311311
}
312312
/*}}}*/
313+
bool Tria::Buttressing(IssmDouble* ptheta, IssmDouble* plength){/*{{{*/
314+
315+
/*Make sure there is a grounding line here*/
316+
if(!IsIceInElement()) return false;
317+
if(!IsZeroLevelset(MaskOceanLevelsetEnum)) return true;
318+
319+
int domaintype,index1,index2;
320+
const IssmPDouble epsilon = 1.e-15;
321+
IssmDouble s1,s2,s_xx,s_yy,s_xy;
322+
IssmDouble gl[NUMVERTICES];
323+
IssmDouble xyz_front[2][3];
324+
325+
IssmDouble xyz_list[NUMVERTICES][3];
326+
::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES);
327+
328+
/*Recover parameters and values*/
329+
parameters->FindParam(&domaintype,DomainTypeEnum);
330+
Element::GetInputListOnVertices(&gl[0],MaskOceanLevelsetEnum);
331+
332+
/*Be sure that values are not zero*/
333+
if(gl[0]==0.) gl[0]=gl[0]+epsilon;
334+
if(gl[1]==0.) gl[1]=gl[1]+epsilon;
335+
if(gl[2]==0.) gl[2]=gl[2]+epsilon;
336+
337+
if(domaintype==Domain2DverticalEnum){
338+
_error_("not implemented");
339+
}
340+
else if(domaintype==Domain2DhorizontalEnum || domaintype==Domain3DEnum || domaintype==Domain3DsurfaceEnum){
341+
int pt1 = 0;
342+
int pt2 = 1;
343+
if(gl[0]*gl[1]>0){ //Nodes 0 and 1 are similar, so points must be found on segment 0-2 and 1-2
344+
345+
/*Portion of the segments*/
346+
s1=gl[2]/(gl[2]-gl[1]);
347+
s2=gl[2]/(gl[2]-gl[0]);
348+
if(gl[2]<0.){
349+
pt1 = 1; pt2 = 0;
350+
}
351+
xyz_front[pt2][0]=xyz_list[2][0]+s1*(xyz_list[1][0]-xyz_list[2][0]);
352+
xyz_front[pt2][1]=xyz_list[2][1]+s1*(xyz_list[1][1]-xyz_list[2][1]);
353+
xyz_front[pt2][2]=xyz_list[2][2]+s1*(xyz_list[1][2]-xyz_list[2][2]);
354+
xyz_front[pt1][0]=xyz_list[2][0]+s2*(xyz_list[0][0]-xyz_list[2][0]);
355+
xyz_front[pt1][1]=xyz_list[2][1]+s2*(xyz_list[0][1]-xyz_list[2][1]);
356+
xyz_front[pt1][2]=xyz_list[2][2]+s2*(xyz_list[0][2]-xyz_list[2][2]);
357+
}
358+
else if(gl[1]*gl[2]>0){ //Nodes 1 and 2 are similar, so points must be found on segment 0-1 and 0-2
359+
360+
/*Portion of the segments*/
361+
s1=gl[0]/(gl[0]-gl[1]);
362+
s2=gl[0]/(gl[0]-gl[2]);
363+
if(gl[0]<0.){
364+
pt1 = 1; pt2 = 0;
365+
}
366+
367+
xyz_front[pt1][0]=xyz_list[0][0]+s1*(xyz_list[1][0]-xyz_list[0][0]);
368+
xyz_front[pt1][1]=xyz_list[0][1]+s1*(xyz_list[1][1]-xyz_list[0][1]);
369+
xyz_front[pt1][2]=xyz_list[0][2]+s1*(xyz_list[1][2]-xyz_list[0][2]);
370+
xyz_front[pt2][0]=xyz_list[0][0]+s2*(xyz_list[2][0]-xyz_list[0][0]);
371+
xyz_front[pt2][1]=xyz_list[0][1]+s2*(xyz_list[2][1]-xyz_list[0][1]);
372+
xyz_front[pt2][2]=xyz_list[0][2]+s2*(xyz_list[2][2]-xyz_list[0][2]);
373+
}
374+
else if(gl[0]*gl[2]>0){ //Nodes 0 and 2 are similar, so points must be found on segment 1-0 and 1-2
375+
376+
/*Portion of the segments*/
377+
s1=gl[1]/(gl[1]-gl[0]);
378+
s2=gl[1]/(gl[1]-gl[2]);
379+
if(gl[1]<0.){
380+
pt1 = 1; pt2 = 0;
381+
}
382+
383+
xyz_front[pt2][0]=xyz_list[1][0]+s1*(xyz_list[0][0]-xyz_list[1][0]);
384+
xyz_front[pt2][1]=xyz_list[1][1]+s1*(xyz_list[0][1]-xyz_list[1][1]);
385+
xyz_front[pt2][2]=xyz_list[1][2]+s1*(xyz_list[0][2]-xyz_list[1][2]);
386+
xyz_front[pt1][0]=xyz_list[1][0]+s2*(xyz_list[2][0]-xyz_list[1][0]);
387+
xyz_front[pt1][1]=xyz_list[1][1]+s2*(xyz_list[2][1]-xyz_list[1][1]);
388+
xyz_front[pt1][2]=xyz_list[1][2]+s2*(xyz_list[2][2]-xyz_list[1][2]);
389+
}
390+
else{
391+
_error_("case not possible");
392+
}
393+
394+
}
395+
else _error_("mesh type "<<EnumToStringx(domaintype)<<"not supported yet ");
396+
397+
/*Some checks in debugging mode*/
398+
_assert_(s1>=0 && s1<=1.);
399+
_assert_(s2>=0 && s2<=1.);
400+
401+
/*Get normal vector*/
402+
IssmDouble normal[3];
403+
this->NormalSection(&normal[0],&xyz_front[0][0]);
404+
405+
/*Get deviatoric stress tensor*/
406+
this->ComputeDeviatoricStressTensor();
407+
408+
/*Get inputs*/
409+
IssmDouble flux = 0.;
410+
IssmDouble vx,vy,thickness,Jdet;
411+
IssmDouble rho_ice = this->FindParam(MaterialsRhoIceEnum);
412+
IssmDouble rho_seawater = this->FindParam(MaterialsRhoSeawaterEnum);
413+
IssmDouble constant_g = this->FindParam(ConstantsGEnum);
414+
Input* vx_input=NULL;
415+
Input* vy_input=NULL;
416+
if(domaintype==Domain2DhorizontalEnum){
417+
vx_input=this->GetInput(VxEnum); _assert_(vx_input);
418+
vy_input=this->GetInput(VyEnum); _assert_(vy_input);
419+
}
420+
else{
421+
vx_input=this->GetInput(VxAverageEnum); _assert_(vx_input);
422+
vy_input=this->GetInput(VyAverageEnum); _assert_(vy_input);
423+
}
424+
Input *s_xx_input = this->GetInput(DeviatoricStressxxEnum); _assert_(s_xx_input);
425+
Input *s_xy_input = this->GetInput(DeviatoricStressxyEnum); _assert_(s_xy_input);
426+
Input *s_yy_input = this->GetInput(DeviatoricStressyyEnum); _assert_(s_yy_input);
427+
Input *thickness_input = this->GetInput(ThicknessEnum); _assert_(thickness_input);
428+
429+
IssmDouble theta = 0.;
430+
IssmDouble length = 0.;
431+
Gauss* gauss=this->NewGauss(&xyz_list[0][0],&xyz_front[0][0],3);
432+
while(gauss->next()){
433+
thickness_input->GetInputValue(&thickness,gauss);
434+
vx_input->GetInputValue(&vx,gauss);
435+
vy_input->GetInputValue(&vy,gauss);
436+
s_xx_input->GetInputValue(&s_xx,gauss);
437+
s_xy_input->GetInputValue(&s_xy,gauss);
438+
s_yy_input->GetInputValue(&s_yy,gauss);
439+
this->JacobianDeterminantSurface(&Jdet,&xyz_front[0][0],gauss);
440+
441+
IssmDouble R[2][2];
442+
R[0][0] = 2*s_xx+s_yy;
443+
R[1][0] = s_xy;
444+
R[0][1] = s_xy;
445+
R[1][1] = 2*s_yy+s_xx;
446+
447+
IssmDouble N = normal[0]*(R[0][0]*normal[0]+R[0][1]*normal[1]) + normal[1]*(R[1][0]*normal[0]+R[1][1]*normal[1]);
448+
IssmDouble N0 = 0.5*constant_g*rho_ice*(1-rho_ice/rho_seawater)*thickness;
449+
450+
theta += Jdet*gauss->weight*N/N0;
451+
length += Jdet*gauss->weight;
452+
}
453+
454+
/*Cleanup and return*/
455+
delete gauss;
456+
_assert_(theta>0.);
457+
_assert_(length>0.);
458+
*ptheta = theta;
459+
*plength = length;
460+
return true;
461+
}
462+
/*}}}*/
313463
void Tria::CalvingRateVonmises(){/*{{{*/
314464

315465
/*First, compute Von Mises Stress*/

src/c/classes/Elements/Tria.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class Tria: public Element,public ElementHook,public TriaRef{
5353
/*}}}*/
5454
/*Element virtual functions definitions: {{{*/
5555
void AverageOntoPartition(Vector<IssmDouble>* partition_contributions,Vector<IssmDouble>* partition_areas,IssmDouble* vertex_response,IssmDouble* qmu_part);
56+
57+
bool Buttressing(IssmDouble* ptheta, IssmDouble* plength);
5658
void CalvingRateVonmises();
5759
void CalvingRateVonmisesAD();
5860
void CalvingRateTest();

src/c/classes/FemModel.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,29 @@ void FemModel::Solve(void){/*{{{*/
10531053
/*}}}*/
10541054

10551055
/*Modules:*/
1056+
void FemModel::AverageButtressingx(IssmDouble* pTheta){/*{{{*/
1057+
1058+
IssmDouble local_theta = 0.;
1059+
IssmDouble local_length = 0.;
1060+
IssmDouble total_theta,total_length,element_theta,element_length;
1061+
1062+
for(Object* & object : this->elements->objects){
1063+
Element* element = xDynamicCast<Element*>(object);
1064+
if(element->Buttressing(&element_theta, &element_length)){
1065+
local_theta += element_theta;
1066+
local_length += element_length;
1067+
}
1068+
}
1069+
ISSM_MPI_Reduce(&local_theta,&total_theta,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );
1070+
ISSM_MPI_Bcast(&total_theta,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());
1071+
ISSM_MPI_Reduce(&local_length,&total_length,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );
1072+
ISSM_MPI_Bcast(&total_length,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());
1073+
_assert_(total_length>0.);
1074+
1075+
/*Assign output pointers: */
1076+
*pTheta=total_theta/total_length;
1077+
1078+
}/*}}}*/
10561079
void FemModel::BalancethicknessMisfitx(IssmDouble* presponse){/*{{{*/
10571080

10581081
/*output: */
@@ -2447,11 +2470,12 @@ void FemModel::RequestedOutputsx(Results **presults,char** requested_outputs, in
24472470
switch(output_enum){
24482471

24492472
/*Scalar output*/
2473+
case AverageButtressingEnum: this->AverageButtressingx(&double_result); break;
24502474
case DivergenceEnum: this->Divergencex(&double_result); break;
24512475
case MaxDivergenceEnum: this->MaxDivergencex(&double_result); break;
24522476
case IceMassEnum: this->IceMassx(&double_result,false); break;
24532477
case IcefrontMassFluxEnum: this->IcefrontMassFluxx(&double_result,false); break;
2454-
case IcefrontMassFluxLevelsetEnum: this->IcefrontMassFluxLevelsetx(&double_result,false); break;
2478+
case IcefrontMassFluxLevelsetEnum: this->IcefrontMassFluxLevelsetx(&double_result,false); break;
24552479
case IceMassScaledEnum: this->IceMassx(&double_result,true); break;
24562480
case IceVolumeEnum: this->IceVolumex(&double_result,false); break;
24572481
case IceVolumeScaledEnum: this->IceVolumex(&double_result,true); break;

src/c/classes/FemModel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class FemModel {
9191
void Solve(void);
9292

9393
/*Modules*/
94+
void AverageButtressingx(IssmDouble* ptheta);
9495
void BalancethicknessMisfitx(IssmDouble* pV);
9596
void CalvingRateVonmisesx();
9697
void CalvingRateLevermannx();

0 commit comments

Comments
 (0)