source:
issm/oecreview/Archive/18296-19100/ISSM-18910-18911.diff@
19102
Last change on this file since 19102 was 19102, checked in by , 10 years ago | |
---|---|
File size: 109.9 KB |
-
../trunk-jpl/src/c/classes/Elements/Tria.cpp
154 154 this->inputs->AddInput(new TriaInput(input_enum,values,interpolation_enum)); 155 155 } 156 156 /*}}}*/ 157 void Tria::AverageOntoPartition(Vector<IssmDouble>* partition_contributions,Vector<IssmDouble>* partition_areas,IssmDouble* vertex_response,IssmDouble* qmu_part){/*{{{*/ 158 159 bool already = false; 160 int i,j; 161 int partition[NUMVERTICES]; 162 int offsetsid[NUMVERTICES]; 163 int offsetdof[NUMVERTICES]; 164 IssmDouble area; 165 IssmDouble mean; 166 167 /*First, get the area: */ 168 area=this->GetArea(); 169 170 /*Figure out the average for this element: */ 171 this->GetVerticesSidList(&offsetsid[0]); 172 this->GetVertexPidList(&offsetdof[0]); 173 mean=0; 174 for(i=0;i<NUMVERTICES;i++){ 175 partition[i]=reCast<int>(qmu_part[offsetsid[i]]); 176 mean=mean+1.0/NUMVERTICES*vertex_response[offsetdof[i]]; 177 } 178 179 /*Add contribution: */ 180 for(i=0;i<NUMVERTICES;i++){ 181 already=false; 182 for(j=0;j<i;j++){ 183 if (partition[i]==partition[j]){ 184 already=true; 185 break; 186 } 187 } 188 if(!already){ 189 partition_contributions->SetValue(partition[i],mean*area,ADD_VAL); 190 partition_areas->SetValue(partition[i],area,ADD_VAL); 191 }; 192 } 193 } 194 /*}}}*/ 195 void Tria::CalvingRateLevermann(){/*{{{*/ 196 197 IssmDouble xyz_list[NUMVERTICES][3]; 198 GaussTria* gauss=NULL; 199 IssmDouble vx,vy,vel; 200 IssmDouble strainparallel; 201 IssmDouble propcoeff; 202 IssmDouble strainperpendicular; 203 IssmDouble calvingratex[NUMVERTICES]; 204 IssmDouble calvingratey[NUMVERTICES]; 205 IssmDouble calvingrate[NUMVERTICES]; 206 207 208 /* Get node coordinates and dof list: */ 209 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 210 211 /*Retrieve all inputs and parameters we will need*/ 212 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 213 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 214 Input* strainparallel_input=inputs->GetInput(StrainRateparallelEnum); _assert_(strainparallel_input); 215 Input* strainperpendicular_input=inputs->GetInput(StrainRateperpendicularEnum); _assert_(strainperpendicular_input); 216 Input* levermanncoeff_input=inputs->GetInput(CalvinglevermannCoeffEnum); _assert_(levermanncoeff_input); 217 218 /* Start looping on the number of vertices: */ 219 gauss=new GaussTria(); 220 for (int iv=0;iv<NUMVERTICES;iv++){ 221 gauss->GaussVertex(iv); 222 223 /* Get the value we need*/ 224 vx_input->GetInputValue(&vx,gauss); 225 vy_input->GetInputValue(&vy,gauss); 226 vel=vx*vx+vy*vy; 227 strainparallel_input->GetInputValue(&strainparallel,gauss); 228 strainperpendicular_input->GetInputValue(&strainperpendicular,gauss); 229 levermanncoeff_input->GetInputValue(&propcoeff,gauss); 230 231 /*Calving rate proportionnal to the positive product of the strain rate along the ice flow direction and the strain rate perpendicular to the ice flow */ 232 calvingrate[iv]=propcoeff*strainparallel*strainperpendicular; 233 if(calvingrate[iv]<0){ 234 calvingrate[iv]=0; 235 } 236 calvingratex[iv]=calvingrate[iv]*vx/(vel+1.e-6); 237 calvingratey[iv]=calvingrate[iv]*vy/(vel+1.e-6); 238 } 239 240 /*Add input*/ 241 this->inputs->AddInput(new TriaInput(CalvingratexEnum,&calvingratex[0],P1Enum)); 242 this->inputs->AddInput(new TriaInput(CalvingrateyEnum,&calvingratey[0],P1Enum)); 243 this->inputs->AddInput(new TriaInput(CalvingCalvingrateEnum,&calvingrate[0],P1Enum)); 244 245 /*Clean up and return*/ 246 delete gauss; 247 248 } 249 /*}}}*/ 157 250 IssmDouble Tria::CharacteristicLength(void){/*{{{*/ 158 251 159 252 return sqrt(2*this->GetArea()); … … 163 256 _error_("Not Implemented yet"); 164 257 } 165 258 /*}}}*/ 259 void Tria::ComputeDeviatoricStressTensor(){/*{{{*/ 260 261 IssmDouble xyz_list[NUMVERTICES][3]; 262 IssmDouble viscosity; 263 IssmDouble epsilon[3]; /* epsilon=[exx,eyy,exy];*/ 264 IssmDouble tau_xx[NUMVERTICES]; 265 IssmDouble tau_yy[NUMVERTICES]; 266 IssmDouble tau_zz[NUMVERTICES]={0,0,0}; 267 IssmDouble tau_xy[NUMVERTICES]; 268 IssmDouble tau_xz[NUMVERTICES]={0,0,0}; 269 IssmDouble tau_yz[NUMVERTICES]={0,0,0}; 270 GaussTria* gauss=NULL; 271 int domaintype,dim=2; 272 273 /* Get node coordinates and dof list: */ 274 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 275 276 /*Retrieve all inputs we will be needing: */ 277 this->FindParam(&domaintype,DomainTypeEnum); 278 if(domaintype!=Domain2DhorizontalEnum) _error_("deviatoric stress tensor calculation not implemented for mesh of type " <<EnumToStringx(domaintype)); 279 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 280 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 281 282 /* Start looping on the number of vertices: */ 283 gauss=new GaussTria(); 284 for (int iv=0;iv<NUMVERTICES;iv++){ 285 gauss->GaussVertex(iv); 286 287 /*Compute strain rate and viscosity: */ 288 this->StrainRateSSA(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input); 289 this->ViscositySSA(&viscosity,dim,&xyz_list[0][0],gauss,vx_input,vy_input); 290 291 /*Compute Stress*/ 292 tau_xx[iv]=2*viscosity*epsilon[0]; // tau = nu eps 293 tau_yy[iv]=2*viscosity*epsilon[1]; 294 tau_xy[iv]=2*viscosity*epsilon[2]; 295 } 296 297 /*Add Stress tensor components into inputs*/ 298 this->inputs->AddInput(new TriaInput(DeviatoricStressxxEnum,&tau_xx[0],P1Enum)); 299 this->inputs->AddInput(new TriaInput(DeviatoricStressxyEnum,&tau_xy[0],P1Enum)); 300 this->inputs->AddInput(new TriaInput(DeviatoricStressxzEnum,&tau_xz[0],P1Enum)); 301 this->inputs->AddInput(new TriaInput(DeviatoricStressyyEnum,&tau_yy[0],P1Enum)); 302 this->inputs->AddInput(new TriaInput(DeviatoricStressyzEnum,&tau_yz[0],P1Enum)); 303 this->inputs->AddInput(new TriaInput(DeviatoricStresszzEnum,&tau_zz[0],P1Enum)); 304 305 /*Clean up and return*/ 306 delete gauss; 307 } 308 /*}}}*/ 166 309 void Tria::ComputeSigmaNN(){/*{{{*/ 167 310 168 311 if(!IsOnBase()){ … … 275 418 delete gauss; 276 419 } 277 420 /*}}}*/ 278 void Tria::ComputeDeviatoricStressTensor(){/*{{{*/279 280 IssmDouble xyz_list[NUMVERTICES][3];281 IssmDouble viscosity;282 IssmDouble epsilon[3]; /* epsilon=[exx,eyy,exy];*/283 IssmDouble tau_xx[NUMVERTICES];284 IssmDouble tau_yy[NUMVERTICES];285 IssmDouble tau_zz[NUMVERTICES]={0,0,0};286 IssmDouble tau_xy[NUMVERTICES];287 IssmDouble tau_xz[NUMVERTICES]={0,0,0};288 IssmDouble tau_yz[NUMVERTICES]={0,0,0};289 GaussTria* gauss=NULL;290 int domaintype,dim=2;291 292 /* Get node coordinates and dof list: */293 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES);294 295 /*Retrieve all inputs we will be needing: */296 this->FindParam(&domaintype,DomainTypeEnum);297 if(domaintype!=Domain2DhorizontalEnum) _error_("deviatoric stress tensor calculation not implemented for mesh of type " <<EnumToStringx(domaintype));298 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);299 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);300 301 /* Start looping on the number of vertices: */302 gauss=new GaussTria();303 for (int iv=0;iv<NUMVERTICES;iv++){304 gauss->GaussVertex(iv);305 306 /*Compute strain rate and viscosity: */307 this->StrainRateSSA(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);308 this->ViscositySSA(&viscosity,dim,&xyz_list[0][0],gauss,vx_input,vy_input);309 310 /*Compute Stress*/311 tau_xx[iv]=2*viscosity*epsilon[0]; // tau = nu eps312 tau_yy[iv]=2*viscosity*epsilon[1];313 tau_xy[iv]=2*viscosity*epsilon[2];314 }315 316 /*Add Stress tensor components into inputs*/317 this->inputs->AddInput(new TriaInput(DeviatoricStressxxEnum,&tau_xx[0],P1Enum));318 this->inputs->AddInput(new TriaInput(DeviatoricStressxyEnum,&tau_xy[0],P1Enum));319 this->inputs->AddInput(new TriaInput(DeviatoricStressxzEnum,&tau_xz[0],P1Enum));320 this->inputs->AddInput(new TriaInput(DeviatoricStressyyEnum,&tau_yy[0],P1Enum));321 this->inputs->AddInput(new TriaInput(DeviatoricStressyzEnum,&tau_yz[0],P1Enum));322 this->inputs->AddInput(new TriaInput(DeviatoricStresszzEnum,&tau_zz[0],P1Enum));323 324 /*Clean up and return*/325 delete gauss;326 }327 /*}}}*/328 void Tria::StrainRateparallel(){/*{{{*/329 330 IssmDouble *xyz_list = NULL;331 IssmDouble epsilon[3];332 GaussTria* gauss=NULL;333 IssmDouble vx,vy,vel;334 IssmDouble strainxx;335 IssmDouble strainxy;336 IssmDouble strainyy;337 IssmDouble strainparallel[NUMVERTICES];338 339 /* Get node coordinates and dof list: */340 this->GetVerticesCoordinates(&xyz_list);341 342 /*Retrieve all inputs we will need*/343 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);344 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);345 346 /* Start looping on the number of vertices: */347 gauss=new GaussTria();348 for (int iv=0;iv<NUMVERTICES;iv++){349 gauss->GaussVertex(iv);350 351 /* Get the value we need*/352 vx_input->GetInputValue(&vx,gauss);353 vy_input->GetInputValue(&vy,gauss);354 vel=vx*vx+vy*vy;355 356 /*Compute strain rate viscosity and pressure: */357 this->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);358 strainxx=epsilon[0];359 strainyy=epsilon[1];360 strainxy=epsilon[2];361 362 /*strainparallel= Strain rate along the ice flow direction */363 strainparallel[iv]=(vx*vx*(strainxx)+vy*vy*(strainyy)+2*vy*vx*strainxy)/(vel+1.e-6);364 }365 366 /*Add input*/367 this->inputs->AddInput(new TriaInput(StrainRateparallelEnum,&strainparallel[0],P1Enum));368 369 /*Clean up and return*/370 delete gauss;371 xDelete<IssmDouble>(xyz_list);372 }373 /*}}}*/374 void Tria::StrainRateperpendicular(){/*{{{*/375 376 IssmDouble *xyz_list = NULL;377 GaussTria* gauss=NULL;378 IssmDouble epsilon[3];379 IssmDouble vx,vy,vel;380 IssmDouble strainxx;381 IssmDouble strainxy;382 IssmDouble strainyy;383 IssmDouble strainperpendicular[NUMVERTICES];384 385 /* Get node coordinates and dof list: */386 this->GetVerticesCoordinates(&xyz_list);387 388 /*Retrieve all inputs we will need*/389 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);390 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);391 392 /* Start looping on the number of vertices: */393 gauss=new GaussTria();394 for (int iv=0;iv<NUMVERTICES;iv++){395 gauss->GaussVertex(iv);396 397 /* Get the value we need*/398 vx_input->GetInputValue(&vx,gauss);399 vy_input->GetInputValue(&vy,gauss);400 vel=vx*vx+vy*vy;401 402 /*Compute strain rate viscosity and pressure: */403 this->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);404 strainxx=epsilon[0];405 strainyy=epsilon[1];406 strainxy=epsilon[2];407 408 /*strainperpendicular= Strain rate perpendicular to the ice flow direction */409 strainperpendicular[iv]=(vx*vx*(strainyy)+vy*vy*(strainxx)-2*vy*vx*strainxy)/(vel+1.e-6);410 }411 412 /*Add input*/413 this->inputs->AddInput(new TriaInput(StrainRateperpendicularEnum,&strainperpendicular[0],P1Enum));414 415 /*Clean up and return*/416 delete gauss;417 xDelete<IssmDouble>(xyz_list);418 }419 /*}}}*/420 void Tria::CalvingRateLevermann(){/*{{{*/421 422 IssmDouble xyz_list[NUMVERTICES][3];423 GaussTria* gauss=NULL;424 IssmDouble vx,vy,vel;425 IssmDouble strainparallel;426 IssmDouble propcoeff;427 IssmDouble strainperpendicular;428 IssmDouble calvingratex[NUMVERTICES];429 IssmDouble calvingratey[NUMVERTICES];430 IssmDouble calvingrate[NUMVERTICES];431 432 433 /* Get node coordinates and dof list: */434 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES);435 436 /*Retrieve all inputs and parameters we will need*/437 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);438 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);439 Input* strainparallel_input=inputs->GetInput(StrainRateparallelEnum); _assert_(strainparallel_input);440 Input* strainperpendicular_input=inputs->GetInput(StrainRateperpendicularEnum); _assert_(strainperpendicular_input);441 Input* levermanncoeff_input=inputs->GetInput(CalvinglevermannCoeffEnum); _assert_(levermanncoeff_input);442 443 /* Start looping on the number of vertices: */444 gauss=new GaussTria();445 for (int iv=0;iv<NUMVERTICES;iv++){446 gauss->GaussVertex(iv);447 448 /* Get the value we need*/449 vx_input->GetInputValue(&vx,gauss);450 vy_input->GetInputValue(&vy,gauss);451 vel=vx*vx+vy*vy;452 strainparallel_input->GetInputValue(&strainparallel,gauss);453 strainperpendicular_input->GetInputValue(&strainperpendicular,gauss);454 levermanncoeff_input->GetInputValue(&propcoeff,gauss);455 456 /*Calving rate proportionnal to the positive product of the strain rate along the ice flow direction and the strain rate perpendicular to the ice flow */457 calvingrate[iv]=propcoeff*strainparallel*strainperpendicular;458 if(calvingrate[iv]<0){459 calvingrate[iv]=0;460 }461 calvingratex[iv]=calvingrate[iv]*vx/(vel+1.e-6);462 calvingratey[iv]=calvingrate[iv]*vy/(vel+1.e-6);463 }464 465 /*Add input*/466 this->inputs->AddInput(new TriaInput(CalvingratexEnum,&calvingratex[0],P1Enum));467 this->inputs->AddInput(new TriaInput(CalvingrateyEnum,&calvingratey[0],P1Enum));468 this->inputs->AddInput(new TriaInput(CalvingCalvingrateEnum,&calvingrate[0],P1Enum));469 470 /*Clean up and return*/471 delete gauss;472 473 }474 /*}}}*/475 421 void Tria::Configure(Elements* elementsin, Loads* loadsin,Nodes* nodesin,Vertices *verticesin,Materials* materialsin, Parameters* parametersin){/*{{{*/ 476 422 477 423 /*go into parameters and get the analysis_counter: */ … … 507 453 508 454 } 509 455 /*}}}*/ 456 void Tria::ControlInputSetGradient(IssmDouble* gradient,int enum_type,int control_index){/*{{{*/ 457 458 int vertexpidlist[NUMVERTICES]; 459 IssmDouble grad_list[NUMVERTICES]; 460 Input* grad_input=NULL; 461 462 Input* input=inputs->GetInput(enum_type); 463 if (!input) _error_("Input " << EnumToStringx(enum_type) << " not found"); 464 if (input->ObjectEnum()!=ControlInputEnum) _error_("Input " << EnumToStringx(enum_type) << " is not a ControlInput"); 465 466 GradientIndexing(&vertexpidlist[0],control_index); 467 for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[vertexpidlist[i]]; 468 grad_input=new TriaInput(GradientEnum,grad_list,P1Enum); 469 470 ((ControlInput*)input)->SetGradient(grad_input); 471 472 }/*}}}*/ 473 void Tria::ControlToVectors(Vector<IssmPDouble>* vector_control, Vector<IssmPDouble>* vector_gradient,int control_enum){/*{{{*/ 474 475 Input* input=inputs->GetInput(control_enum); 476 if (!input) _error_("Input " << EnumToStringx(control_enum) << " not found"); 477 if (input->ObjectEnum()!=ControlInputEnum) _error_("Input " << EnumToStringx(control_enum) << " is not a ControlInput"); 478 479 int sidlist[NUMVERTICES]; 480 int connectivity[NUMVERTICES]; 481 IssmPDouble values[NUMVERTICES]; 482 IssmPDouble gradients[NUMVERTICES]; 483 IssmDouble value,gradient; 484 485 this->GetVerticesConnectivityList(&connectivity[0]); 486 this->GetVerticesSidList(&sidlist[0]); 487 488 GaussTria* gauss=new GaussTria(); 489 for (int iv=0;iv<NUMVERTICES;iv++){ 490 gauss->GaussVertex(iv); 491 492 ((ControlInput*)input)->GetInputValue(&value,gauss); 493 ((ControlInput*)input)->GetGradientValue(&gradient,gauss); 494 495 values[iv] = reCast<IssmPDouble>(value)/reCast<IssmPDouble>(connectivity[iv]); 496 gradients[iv] = reCast<IssmPDouble>(gradient)/reCast<IssmPDouble>(connectivity[iv]); 497 } 498 delete gauss; 499 500 vector_control->SetValues(NUMVERTICES,&sidlist[0],&values[0],ADD_VAL); 501 vector_gradient->SetValues(NUMVERTICES,&sidlist[0],&gradients[0],ADD_VAL); 502 503 }/*}}}*/ 510 504 void Tria::Delta18oParameterization(void){/*{{{*/ 511 505 512 506 int i; … … 577 571 delete gauss; 578 572 } 579 573 /*}}}*/ 574 int Tria::EdgeOnBaseIndex(void){/*{{{*/ 575 576 IssmDouble values[NUMVERTICES]; 577 int indices[3][2] = {{1,2},{2,0},{0,1}}; 578 579 /*Retrieve all inputs and parameters*/ 580 GetInputListOnVertices(&values[0],MeshVertexonbaseEnum); 581 582 for(int i=0;i<3;i++){ 583 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){ 584 return i; 585 } 586 } 587 588 _printf_("list of vertices on bed: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 589 _error_("Could not find 2 vertices on bed"); 590 } 591 /*}}}*/ 592 void Tria::EdgeOnBaseIndices(int* pindex1,int* pindex2){/*{{{*/ 593 594 IssmDouble values[NUMVERTICES]; 595 int indices[3][2] = {{1,2},{2,0},{0,1}}; 596 597 /*Retrieve all inputs and parameters*/ 598 GetInputListOnVertices(&values[0],MeshVertexonbaseEnum); 599 600 for(int i=0;i<3;i++){ 601 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){ 602 *pindex1 = indices[i][0]; 603 *pindex2 = indices[i][1]; 604 return; 605 } 606 } 607 608 _printf_("list of vertices on bed: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 609 _error_("Could not find 2 vertices on bed"); 610 } 611 /*}}}*/ 612 int Tria::EdgeOnSurfaceIndex(void){/*{{{*/ 613 614 IssmDouble values[NUMVERTICES]; 615 int indices[3][2] = {{1,2},{2,0},{0,1}}; 616 617 /*Retrieve all inputs and parameters*/ 618 GetInputListOnVertices(&values[0],MeshVertexonsurfaceEnum); 619 620 for(int i=0;i<3;i++){ 621 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){ 622 return i; 623 } 624 } 625 626 _printf_("list of vertices on surface: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 627 _error_("Could not find 2 vertices on surface"); 628 } 629 /*}}}*/ 630 void Tria::EdgeOnSurfaceIndices(int* pindex1,int* pindex2){/*{{{*/ 631 632 IssmDouble values[NUMVERTICES]; 633 int indices[3][2] = {{1,2},{2,0},{0,1}}; 634 635 /*Retrieve all inputs and parameters*/ 636 GetInputListOnVertices(&values[0],MeshVertexonsurfaceEnum); 637 638 for(int i=0;i<3;i++){ 639 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){ 640 *pindex1 = indices[i][0]; 641 *pindex2 = indices[i][1]; 642 return; 643 } 644 } 645 646 _printf_("list of vertices on surface: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 647 _error_("Could not find 2 vertices on surface"); 648 } 649 /*}}}*/ 650 void Tria::ElementResponse(IssmDouble* presponse,int response_enum){/*{{{*/ 651 652 switch(response_enum){ 653 case MaterialsRheologyBbarEnum: 654 *presponse=this->material->GetBbar(); 655 break; 656 657 case VelEnum:{ 658 659 /*Get input:*/ 660 IssmDouble vel; 661 Input* vel_input; 662 663 vel_input=this->inputs->GetInput(VelEnum); _assert_(vel_input); 664 vel_input->GetInputAverage(&vel); 665 666 /*Assign output pointers:*/ 667 *presponse=vel;} 668 break; 669 default: 670 _error_("Response type " << EnumToStringx(response_enum) << " not supported yet!"); 671 } 672 673 } 674 /*}}}*/ 580 675 void Tria::ElementSizes(IssmDouble* hx,IssmDouble* hy,IssmDouble* hz){/*{{{*/ 581 676 582 677 IssmDouble xyz_list[NUMVERTICES][3]; … … 604 699 return this->element_type; 605 700 } 606 701 /*}}}*/ 607 int Tria::ObjectEnum(void){/*{{{*/702 void Tria::FSContactMigration(Vector<IssmDouble>* vertexgrounded,Vector<IssmDouble>* vertexfloating){/*{{{*/ 608 703 609 return TriaEnum;704 if(!IsOnBase()) return; 610 705 706 int approximation; 707 inputs->GetInputValue(&approximation,ApproximationEnum); 708 709 if(approximation==HOApproximationEnum || approximation==SSAApproximationEnum || approximation==SSAHOApproximationEnum){ 710 for(int i=0;i<NUMVERTICES;i++){ 711 vertexgrounded->SetValue(vertices[i]->Pid(),+9999.,INS_VAL); 712 vertexfloating->SetValue(vertices[i]->Pid(),+9999.,INS_VAL); 713 } 714 } 715 else{ 716 /*Intermediaries*/ 717 IssmDouble* xyz_list = NULL; 718 IssmDouble* xyz_list_base = NULL; 719 IssmDouble pressure,water_pressure,sigma_nn,viscosity,bed,base; 720 IssmDouble bed_normal[2]; 721 IssmDouble epsilon[3]; /* epsilon=[exx,eyy,exy];*/ 722 IssmDouble surface=0,value=0; 723 bool grounded; 724 725 /* Get node coordinates and dof list: */ 726 GetVerticesCoordinates(&xyz_list); 727 GetVerticesCoordinatesBase(&xyz_list_base); 728 729 /*Retrieve all inputs we will be needing: */ 730 Input* pressure_input = inputs->GetInput(PressureEnum); _assert_(pressure_input); 731 Input* base_input = inputs->GetInput(BaseEnum); _assert_(base_input); 732 Input* bed_input = inputs->GetInput(BedEnum); _assert_(bed_input); 733 Input* vx_input = inputs->GetInput(VxEnum); _assert_(vx_input); 734 Input* vy_input = inputs->GetInput(VyEnum); _assert_(vy_input); 735 736 /*Create gauss point in the middle of the basal edge*/ 737 Gauss* gauss=NewGaussBase(1); 738 gauss->GaussPoint(0); 739 740 if(!IsFloating()){ 741 /*Check for basal force only if grounded and touching GL*/ 742 // if(this->inputs->Min(MaskGroundediceLevelsetEnum)==0.){ 743 this->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input); 744 this->ViscosityFS(&viscosity,2,xyz_list,gauss,vx_input,vy_input,NULL); 745 pressure_input->GetInputValue(&pressure, gauss); 746 base_input->GetInputValue(&base, gauss); 747 748 /*Compute Stress*/ 749 IssmDouble sigma_xx=2.*viscosity*epsilon[0]-pressure; 750 IssmDouble sigma_yy=2.*viscosity*epsilon[1]-pressure; 751 IssmDouble sigma_xy=2.*viscosity*epsilon[2]; 752 753 /*Get normal vector to the bed */ 754 NormalBase(&bed_normal[0],xyz_list_base); 755 756 /*basalforce*/ 757 sigma_nn = sigma_xx*bed_normal[0]*bed_normal[0] + sigma_yy*bed_normal[1]*bed_normal[1] + 2.*sigma_xy*bed_normal[0]*bed_normal[1]; 758 759 /*Compute water pressure*/ 760 IssmDouble rho_ice = matpar->GetRhoIce(); 761 IssmDouble rho_water = matpar->GetRhoWater(); 762 IssmDouble gravity = matpar->GetG(); 763 water_pressure=gravity*rho_water*base; 764 765 /*Compare basal stress to water pressure and determine whether it should ground*/ 766 if (sigma_nn<water_pressure) grounded=true; 767 else grounded=false; 768 } 769 else{ 770 /*Check for basal elevation if floating*/ 771 base_input->GetInputValue(&base, gauss); 772 bed_input->GetInputValue(&bed, gauss); 773 if(base<bed) grounded=true; 774 else grounded=false; 775 } 776 for(int i=0;i<NUMVERTICES;i++){ 777 if(grounded) vertexgrounded->SetValue(vertices[i]->Pid(),+1.,INS_VAL); 778 else vertexfloating->SetValue(vertices[i]->Pid(),+1.,INS_VAL); 779 } 780 781 /*clean up*/ 782 delete gauss; 783 xDelete<IssmDouble>(xyz_list); 784 xDelete<IssmDouble>(xyz_list_base); 785 } 611 786 } 612 787 /*}}}*/ 613 788 IssmDouble Tria::GetArea(void){/*{{{*/ … … 667 842 668 843 } 669 844 /*}}}*/ 670 void Tria::GetLevelsetPositivePart(int* point1,IssmDouble* fraction1,IssmDouble* fraction2, bool* mainlynegative,IssmDouble* gl){/*{{{*/671 672 /*Computeportion of the element that has a positive levelset*/673 674 bool negative=true;675 int point;676 const IssmPDouble epsilon= 1.e-15;677 IssmDouble f1,f2;678 679 /*Be sure that values are not zero*/680 if(gl[0]==0.) gl[0]=gl[0]+epsilon;681 if(gl[1]==0.) gl[1]=gl[1]+epsilon;682 if(gl[2]==0.) gl[2]=gl[2]+epsilon;683 684 /*Check that not all nodes are positive or negative*/685 if(gl[0]>0 && gl[1]>0 && gl[2]>0){ // All positive686 point=0;687 f1=1.;688 f2=1.;689 }690 else if(gl[0]<0 && gl[1]<0 && gl[2]<0){ //All negative691 point=0;692 f1=0.;693 f2=0.;694 }695 else{696 if(gl[0]*gl[1]*gl[2]<0) negative=false;697 698 if(gl[0]*gl[1]>0){ //Nodes 0 and 1 are similar, so points must be found on segment 0-2 and 1-2699 point=2;700 f1=gl[2]/(gl[2]-gl[0]);701 f2=gl[2]/(gl[2]-gl[1]);702 }703 else if(gl[1]*gl[2]>0){ //Nodes 1 and 2 are similar, so points must be found on segment 0-1 and 0-2704 point=0;705 f1=gl[0]/(gl[0]-gl[1]);706 f2=gl[0]/(gl[0]-gl[2]);707 }708 else if(gl[0]*gl[2]>0){ //Nodes 0 and 2 are similar, so points must be found on segment 1-0 and 1-2709 point=1;710 f1=gl[1]/(gl[1]-gl[2]);711 f2=gl[1]/(gl[1]-gl[0]);712 }713 }714 *point1=point;715 *fraction1=f1;716 *fraction2=f2;717 *mainlynegative=negative;718 }719 /*}}}*/720 845 void Tria::GetGroundedPart(int* point1,IssmDouble* fraction1,IssmDouble* fraction2, bool* mainlyfloating){/*{{{*/ 721 846 /*Computeportion of the element that is grounded*/ 722 847 … … 888 1013 return phi; 889 1014 } 890 1015 /*}}}*/ 891 void Tria::GetVerticesCoordinatesBase(IssmDouble** pxyz_list){/*{{{*/892 893 int indices[2];894 IssmDouble xyz_list[NUMVERTICES][3];895 896 /*Element XYZ list*/897 ::GetVerticesCoordinates(&xyz_list[0][0],this->vertices,NUMVERTICES);898 899 /*Allocate Output*/900 IssmDouble* xyz_list_edge = xNew<IssmDouble>(2*3);901 this->EdgeOnBaseIndices(&indices[0],&indices[1]);902 for(int i=0;i<2;i++) for(int j=0;j<2;j++) xyz_list_edge[i*3+j]=xyz_list[indices[i]][j];903 904 /*Assign output pointer*/905 *pxyz_list = xyz_list_edge;906 907 }/*}}}*/908 void Tria::GetVerticesCoordinatesTop(IssmDouble** pxyz_list){/*{{{*/909 910 int indices[2];911 IssmDouble xyz_list[NUMVERTICES][3];912 913 /*Element XYZ list*/914 ::GetVerticesCoordinates(&xyz_list[0][0],this->vertices,NUMVERTICES);915 916 /*Allocate Output*/917 IssmDouble* xyz_list_edge = xNew<IssmDouble>(2*3);918 this->EdgeOnSurfaceIndices(&indices[0],&indices[1]);919 for(int i=0;i<2;i++) for(int j=0;j<2;j++) xyz_list_edge[i*3+j]=xyz_list[indices[i]][j];920 921 /*Assign output pointer*/922 *pxyz_list = xyz_list_edge;923 924 }/*}}}*/925 void Tria::NormalSection(IssmDouble* normal,IssmDouble* xyz_list){/*{{{*/926 927 /*Build unit outward pointing vector*/928 IssmDouble vector[2];929 IssmDouble norm;930 931 vector[0]=xyz_list[1*3+0] - xyz_list[0*3+0];932 vector[1]=xyz_list[1*3+1] - xyz_list[0*3+1];933 934 norm=sqrt(vector[0]*vector[0] + vector[1]*vector[1]);935 936 normal[0]= + vector[1]/norm;937 normal[1]= - vector[0]/norm;938 }939 /*}}}*/940 void Tria::ZeroLevelsetCoordinates(IssmDouble** pxyz_zero,IssmDouble* xyz_list,int levelsetenum){/*{{{*/941 942 int normal_orientation=0;943 IssmDouble s1,s2;944 IssmDouble levelset[NUMVERTICES];945 946 /*Recover parameters and values*/947 IssmDouble* xyz_zero = xNew<IssmDouble>(2*3);948 GetInputListOnVertices(&levelset[0],levelsetenum);949 950 if(levelset[0]*levelset[1]>0.){ //Nodes 0 and 1 are similar, so points must be found on segment 0-2 and 1-2951 /*Portion of the segments*/952 s1=levelset[2]/(levelset[2]-levelset[1]);953 s2=levelset[2]/(levelset[2]-levelset[0]);954 955 if(levelset[2]<0.) normal_orientation=1; //orientation of quadrangle depending on distribution of levelsetfunction956 /*New point 1*/957 xyz_zero[3*normal_orientation+0]=xyz_list[2*3+0]+s1*(xyz_list[1*3+0]-xyz_list[2*3+0]);958 xyz_zero[3*normal_orientation+1]=xyz_list[2*3+1]+s1*(xyz_list[1*3+1]-xyz_list[2*3+1]);959 xyz_zero[3*normal_orientation+2]=xyz_list[2*3+2]+s1*(xyz_list[1*3+2]-xyz_list[2*3+2]);960 961 /*New point 0*/962 xyz_zero[3*(1-normal_orientation)+0]=xyz_list[2*3+0]+s2*(xyz_list[0*3+0]-xyz_list[2*3+0]);963 xyz_zero[3*(1-normal_orientation)+1]=xyz_list[2*3+1]+s2*(xyz_list[0*3+1]-xyz_list[2*3+1]);964 xyz_zero[3*(1-normal_orientation)+2]=xyz_list[2*3+2]+s2*(xyz_list[0*3+2]-xyz_list[2*3+2]);965 }966 else if(levelset[1]*levelset[2]>0.){ //Nodes 1 and 2 are similar, so points must be found on segment 0-1 and 0-2967 /*Portion of the segments*/968 s1=levelset[0]/(levelset[0]-levelset[2]);969 s2=levelset[0]/(levelset[0]-levelset[1]);970 971 if(levelset[0]<0.) normal_orientation=1;972 /*New point 1*/973 xyz_zero[3*normal_orientation+0]=xyz_list[0*3+0]+s1*(xyz_list[2*3+0]-xyz_list[0*3+0]);974 xyz_zero[3*normal_orientation+1]=xyz_list[0*3+1]+s1*(xyz_list[2*3+1]-xyz_list[0*3+1]);975 xyz_zero[3*normal_orientation+2]=xyz_list[0*3+2]+s1*(xyz_list[2*3+2]-xyz_list[0*3+2]);976 977 /*New point 2*/978 xyz_zero[3*(1-normal_orientation)+0]=xyz_list[0*3+0]+s2*(xyz_list[1*3+0]-xyz_list[0*3+0]);979 xyz_zero[3*(1-normal_orientation)+1]=xyz_list[0*3+1]+s2*(xyz_list[1*3+1]-xyz_list[0*3+1]);980 xyz_zero[3*(1-normal_orientation)+2]=xyz_list[0*3+2]+s2*(xyz_list[1*3+2]-xyz_list[0*3+2]);981 }982 else if(levelset[0]*levelset[2]>0.){ //Nodes 0 and 2 are similar, so points must be found on segment 1-0 and 1-2983 /*Portion of the segments*/984 s1=levelset[1]/(levelset[1]-levelset[0]);985 s2=levelset[1]/(levelset[1]-levelset[2]);986 987 if(levelset[1]<0.) normal_orientation=1;988 /*New point 0*/989 xyz_zero[3*normal_orientation+0]=xyz_list[1*3+0]+s1*(xyz_list[0*3+0]-xyz_list[1*3+0]);990 xyz_zero[3*normal_orientation+1]=xyz_list[1*3+1]+s1*(xyz_list[0*3+1]-xyz_list[1*3+1]);991 xyz_zero[3*normal_orientation+2]=xyz_list[1*3+2]+s1*(xyz_list[0*3+2]-xyz_list[1*3+2]);992 993 /*New point 2*/994 xyz_zero[3*(1-normal_orientation)+0]=xyz_list[1*3+0]+s2*(xyz_list[2*3+0]-xyz_list[1*3+0]);995 xyz_zero[3*(1-normal_orientation)+1]=xyz_list[1*3+1]+s2*(xyz_list[2*3+1]-xyz_list[1*3+1]);996 xyz_zero[3*(1-normal_orientation)+2]=xyz_list[1*3+2]+s2*(xyz_list[2*3+2]-xyz_list[1*3+2]);997 }998 else if(levelset[0]==0. && levelset[1]==0.){ //front is on point 0 and 1999 xyz_zero[3*0+0]=xyz_list[0*3+0];1000 xyz_zero[3*0+1]=xyz_list[0*3+1];1001 xyz_zero[3*0+2]=xyz_list[0*3+2];1002 1003 /*New point 2*/1004 xyz_zero[3*1+0]=xyz_list[1*3+0];1005 xyz_zero[3*1+1]=xyz_list[1*3+1];1006 xyz_zero[3*1+2]=xyz_list[1*3+2];1007 }1008 else if(levelset[0]==0. && levelset[2]==0.){ //front is on point 0 and 11009 xyz_zero[3*0+0]=xyz_list[2*3+0];1010 xyz_zero[3*0+1]=xyz_list[2*3+1];1011 xyz_zero[3*0+2]=xyz_list[2*3+2];1012 1013 /*New point 2*/1014 xyz_zero[3*1+0]=xyz_list[0*3+0];1015 xyz_zero[3*1+1]=xyz_list[0*3+1];1016 xyz_zero[3*1+2]=xyz_list[0*3+2];1017 }1018 else if(levelset[1]==0. && levelset[2]==0.){ //front is on point 0 and 11019 xyz_zero[3*0+0]=xyz_list[1*3+0];1020 xyz_zero[3*0+1]=xyz_list[1*3+1];1021 xyz_zero[3*0+2]=xyz_list[1*3+2];1022 1023 /*New point 2*/1024 xyz_zero[3*1+0]=xyz_list[2*3+0];1025 xyz_zero[3*1+1]=xyz_list[2*3+1];1026 xyz_zero[3*1+2]=xyz_list[2*3+2];1027 }1028 else _error_("Case not covered");1029 1030 /*Assign output pointer*/1031 *pxyz_zero= xyz_zero;1032 }1033 /*}}}*/1034 1016 void Tria::GetIcefrontCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum){/*{{{*/ 1035 1017 1036 1018 /* Intermediaries */ … … 1071 1053 1072 1054 xDelete<int>(indicesfront); 1073 1055 }/*}}}*/ 1056 void Tria::GetInputValue(IssmDouble* pvalue,Node* node,int enumtype){/*{{{*/ 1057 1058 Input* input=inputs->GetInput(enumtype); 1059 if(!input) _error_("No input of type " << EnumToStringx(enumtype) << " found in tria"); 1060 1061 GaussTria* gauss=new GaussTria(); 1062 gauss->GaussVertex(this->GetNodeIndex(node)); 1063 1064 input->GetInputValue(pvalue,gauss); 1065 delete gauss; 1066 } 1067 /*}}}*/ 1074 1068 void Tria::GetLevelCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum,IssmDouble level){/*{{{*/ 1075 1069 1076 1070 /* Intermediaries */ … … 1111 1105 1112 1106 xDelete<int>(indicesfront); 1113 1107 }/*}}}*/ 1108 void Tria::GetLevelsetPositivePart(int* point1,IssmDouble* fraction1,IssmDouble* fraction2, bool* mainlynegative,IssmDouble* gl){/*{{{*/ 1109 1110 /*Computeportion of the element that has a positive levelset*/ 1111 1112 bool negative=true; 1113 int point; 1114 const IssmPDouble epsilon= 1.e-15; 1115 IssmDouble f1,f2; 1116 1117 /*Be sure that values are not zero*/ 1118 if(gl[0]==0.) gl[0]=gl[0]+epsilon; 1119 if(gl[1]==0.) gl[1]=gl[1]+epsilon; 1120 if(gl[2]==0.) gl[2]=gl[2]+epsilon; 1121 1122 /*Check that not all nodes are positive or negative*/ 1123 if(gl[0]>0 && gl[1]>0 && gl[2]>0){ // All positive 1124 point=0; 1125 f1=1.; 1126 f2=1.; 1127 } 1128 else if(gl[0]<0 && gl[1]<0 && gl[2]<0){ //All negative 1129 point=0; 1130 f1=0.; 1131 f2=0.; 1132 } 1133 else{ 1134 if(gl[0]*gl[1]*gl[2]<0) negative=false; 1135 1136 if(gl[0]*gl[1]>0){ //Nodes 0 and 1 are similar, so points must be found on segment 0-2 and 1-2 1137 point=2; 1138 f1=gl[2]/(gl[2]-gl[0]); 1139 f2=gl[2]/(gl[2]-gl[1]); 1140 } 1141 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 1142 point=0; 1143 f1=gl[0]/(gl[0]-gl[1]); 1144 f2=gl[0]/(gl[0]-gl[2]); 1145 } 1146 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 1147 point=1; 1148 f1=gl[1]/(gl[1]-gl[2]); 1149 f2=gl[1]/(gl[1]-gl[0]); 1150 } 1151 } 1152 *point1=point; 1153 *fraction1=f1; 1154 *fraction2=f2; 1155 *mainlynegative=negative; 1156 } 1157 /*}}}*/ 1158 Node* Tria::GetNode(int node_number){/*{{{*/ 1159 _assert_(node_number>=0); 1160 _assert_(node_number<this->NumberofNodes(this->element_type)); 1161 return this->nodes[node_number]; 1162 1163 }/*}}}*/ 1114 1164 int Tria::GetNodeIndex(Node* node){/*{{{*/ 1115 1165 1116 1166 _assert_(nodes); … … 1134 1184 return NUMVERTICES; 1135 1185 } 1136 1186 /*}}}*/ 1137 void Tria::Get InputValue(IssmDouble* pvalue,Node* node,int enumtype){/*{{{*/1187 void Tria::GetSolutionFromInputsOneDof(Vector<IssmDouble>* solution, int enum_type){/*{{{*/ 1138 1188 1139 Input* input=inputs->GetInput(enumtype);1140 if(!input) _error_("No input of type " << EnumToStringx(enumtype) << " found in tria");1189 int *doflist = NULL; 1190 IssmDouble value; 1141 1191 1192 /*Fetch number of nodes for this finite element*/ 1193 int numnodes = this->NumberofNodes(this->element_type); 1194 1195 /*Fetch dof list and allocate solution vector*/ 1196 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 1197 IssmDouble* values = xNew<IssmDouble>(numnodes); 1198 1199 /*Get inputs*/ 1200 Input* enum_input=inputs->GetInput(enum_type); _assert_(enum_input); 1201 1202 /*Ok, we have the values, fill in the array: */ 1142 1203 GaussTria* gauss=new GaussTria(); 1143 gauss->GaussVertex(this->GetNodeIndex(node)); 1204 for(int i=0;i<numnodes;i++){ 1205 gauss->GaussNode(this->element_type,i); 1144 1206 1145 input->GetInputValue(pvalue,gauss); 1207 enum_input->GetInputValue(&value,gauss); 1208 values[i]=value; 1209 } 1210 1211 solution->SetValues(numnodes,doflist,values,INS_VAL); 1212 1213 /*Free ressources:*/ 1214 xDelete<int>(doflist); 1215 xDelete<IssmDouble>(values); 1146 1216 delete gauss; 1147 1217 } 1148 1218 /*}}}*/ 1149 Node* Tria::GetNode(int node_number){/*{{{*/ 1150 _assert_(node_number>=0); 1151 _assert_(node_number<this->NumberofNodes(this->element_type)); 1152 return this->nodes[node_number]; 1219 void Tria::GetVectorFromControlInputs(Vector<IssmDouble>* vector,int control_enum,int control_index,const char* data,bool onsid){/*{{{*/ 1153 1220 1221 int vertexidlist[NUMVERTICES]; 1222 Input *input=NULL; 1223 1224 /*Get out if this is not an element input*/ 1225 if(!IsInput(control_enum)) return; 1226 1227 /*Prepare index list*/ 1228 GradientIndexing(&vertexidlist[0],control_index,onsid); 1229 1230 /*Get input (either in element or material)*/ 1231 input=(Input*)this->inputs->GetInput(control_enum); _assert_(input); 1232 1233 /*Check that it is a ControlInput*/ 1234 if (input->ObjectEnum()!=ControlInputEnum){ 1235 _error_("input " << EnumToStringx(control_enum) << " is not a ControlInput"); 1236 } 1237 1238 ((ControlInput*)input)->GetVectorFromInputs(vector,&vertexidlist[0],data); 1239 } 1240 /*}}}*/ 1241 void Tria::GetVerticesCoordinatesBase(IssmDouble** pxyz_list){/*{{{*/ 1242 1243 int indices[2]; 1244 IssmDouble xyz_list[NUMVERTICES][3]; 1245 1246 /*Element XYZ list*/ 1247 ::GetVerticesCoordinates(&xyz_list[0][0],this->vertices,NUMVERTICES); 1248 1249 /*Allocate Output*/ 1250 IssmDouble* xyz_list_edge = xNew<IssmDouble>(2*3); 1251 this->EdgeOnBaseIndices(&indices[0],&indices[1]); 1252 for(int i=0;i<2;i++) for(int j=0;j<2;j++) xyz_list_edge[i*3+j]=xyz_list[indices[i]][j]; 1253 1254 /*Assign output pointer*/ 1255 *pxyz_list = xyz_list_edge; 1256 1154 1257 }/*}}}*/ 1258 void Tria::GetVerticesCoordinatesTop(IssmDouble** pxyz_list){/*{{{*/ 1259 1260 int indices[2]; 1261 IssmDouble xyz_list[NUMVERTICES][3]; 1262 1263 /*Element XYZ list*/ 1264 ::GetVerticesCoordinates(&xyz_list[0][0],this->vertices,NUMVERTICES); 1265 1266 /*Allocate Output*/ 1267 IssmDouble* xyz_list_edge = xNew<IssmDouble>(2*3); 1268 this->EdgeOnSurfaceIndices(&indices[0],&indices[1]); 1269 for(int i=0;i<2;i++) for(int j=0;j<2;j++) xyz_list_edge[i*3+j]=xyz_list[indices[i]][j]; 1270 1271 /*Assign output pointer*/ 1272 *pxyz_list = xyz_list_edge; 1273 1274 }/*}}}*/ 1275 bool Tria::HasEdgeOnBase(){/*{{{*/ 1276 1277 IssmDouble values[NUMVERTICES]; 1278 IssmDouble sum; 1279 1280 /*Retrieve all inputs and parameters*/ 1281 GetInputListOnVertices(&values[0],MeshVertexonbaseEnum); 1282 sum = values[0]+values[1]+values[2]; 1283 1284 _assert_(sum==0. || sum==1. || sum==2.); 1285 1286 if(sum==3.) _error_("Two edges on bed not supported yet..."); 1287 1288 if(sum>1.){ 1289 return true; 1290 } 1291 else{ 1292 return false; 1293 } 1294 } 1295 /*}}}*/ 1296 bool Tria::HasEdgeOnSurface(){/*{{{*/ 1297 1298 IssmDouble values[NUMVERTICES]; 1299 IssmDouble sum; 1300 1301 /*Retrieve all inputs and parameters*/ 1302 GetInputListOnVertices(&values[0],MeshVertexonsurfaceEnum); 1303 sum = values[0]+values[1]+values[2]; 1304 1305 _assert_(sum==0. || sum==1. || sum==2.); 1306 1307 if(sum==3.) _error_("Two edges on surface not supported yet..."); 1308 1309 if(sum>1.){ 1310 return true; 1311 } 1312 else{ 1313 return false; 1314 } 1315 } 1316 /*}}}*/ 1317 IssmDouble Tria::IceVolume(void){/*{{{*/ 1318 1319 /*The volume of a troncated prism is base * 1/3 sum(length of edges)*/ 1320 IssmDouble base,surface,bed; 1321 IssmDouble xyz_list[NUMVERTICES][3]; 1322 1323 if(!IsIceInElement())return 0; 1324 1325 /*First get back the area of the base*/ 1326 base=this->GetArea(); 1327 1328 /*Now get the average height*/ 1329 Input* surface_input = inputs->GetInput(SurfaceEnum); _assert_(surface_input); 1330 Input* base_input = inputs->GetInput(BaseEnum); _assert_(base_input); 1331 surface_input->GetInputAverage(&surface); 1332 base_input->GetInputAverage(&bed); 1333 1334 /*Return: */ 1335 int domaintype; 1336 parameters->FindParam(&domaintype,DomainTypeEnum); 1337 if(domaintype==Domain2DverticalEnum){ 1338 return base; 1339 } 1340 else{ 1341 return base*(surface-bed); 1342 } 1343 } 1344 /*}}}*/ 1345 IssmDouble Tria::IceVolumeAboveFloatation(void){/*{{{*/ 1346 1347 /*The volume above floatation: H + rho_water/rho_ice * bathymetry */ 1348 IssmDouble rho_ice,rho_water; 1349 IssmDouble base,surface,bed,bathymetry; 1350 IssmDouble xyz_list[NUMVERTICES][3]; 1351 1352 if(!IsIceInElement() || IsFloating())return 0; 1353 1354 rho_ice=matpar->GetRhoIce(); 1355 rho_water=matpar->GetRhoWater(); 1356 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 1357 1358 /*First calculate the area of the base (cross section triangle) 1359 * http://en.wikipedia.org/wiki/Triangle 1360 * base = 1/2 abs((xA-xC)(yB-yA)-(xA-xB)(yC-yA))*/ 1361 base = 1./2. * fabs((xyz_list[0][0]-xyz_list[2][0])*(xyz_list[1][1]-xyz_list[0][1]) - (xyz_list[0][0]-xyz_list[1][0])*(xyz_list[2][1]-xyz_list[0][1])); 1362 1363 /*Now get the average height and bathymetry*/ 1364 Input* surface_input = inputs->GetInput(SurfaceEnum); _assert_(surface_input); 1365 Input* base_input = inputs->GetInput(BaseEnum); _assert_(base_input); 1366 Input* bed_input = inputs->GetInput(BedEnum); _assert_(bed_input); 1367 surface_input->GetInputAverage(&surface); 1368 base_input->GetInputAverage(&bed); 1369 bed_input->GetInputAverage(&bathymetry); 1370 1371 /*Return: */ 1372 return base*(surface-bed+min(rho_water/rho_ice*bathymetry,0.)); 1373 } 1374 /*}}}*/ 1375 void Tria::InputControlUpdate(IssmDouble scalar,bool save_parameter){/*{{{*/ 1376 1377 /*Intermediary*/ 1378 int num_controls; 1379 int* control_type=NULL; 1380 Input* input=NULL; 1381 1382 /*retrieve some parameters: */ 1383 this->parameters->FindParam(&num_controls,InversionNumControlParametersEnum); 1384 this->parameters->FindParam(&control_type,NULL,InversionControlParametersEnum); 1385 1386 for(int i=0;i<num_controls;i++){ 1387 input=(Input*)this->inputs->GetInput(control_type[i]); _assert_(input); 1388 if (input->ObjectEnum()!=ControlInputEnum){ 1389 _error_("input " << EnumToStringx(control_type[i]) << " is not a ControlInput"); 1390 } 1391 1392 ((ControlInput*)input)->UpdateValue(scalar); 1393 ((ControlInput*)input)->Constrain(); 1394 if (save_parameter) ((ControlInput*)input)->SaveValue(); 1395 1396 } 1397 1398 /*Clean up and return*/ 1399 xDelete<int>(control_type); 1400 } 1401 /*}}}*/ 1155 1402 void Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type){/*{{{*/ 1156 1403 1157 1404 /*New input*/ … … 1370 1617 1371 1618 } 1372 1619 /*}}}*/ 1620 bool Tria::IsFaceOnBoundary(void){/*{{{*/ 1621 1622 IssmDouble values[NUMVERTICES]; 1623 IssmDouble sum; 1624 1625 /*Retrieve all inputs and parameters*/ 1626 GetInputListOnVertices(&values[0],MeshVertexonboundaryEnum); 1627 sum = values[0]+values[1]+values[2]; 1628 1629 _assert_(sum==0. || sum==1. || sum==2.); 1630 1631 if(sum==3.) _error_("Two edges on boundary not supported yet..."); 1632 1633 if(sum>1.){ 1634 return true; 1635 } 1636 else{ 1637 return false; 1638 } 1639 }/*}}}*/ 1640 bool Tria::IsIcefront(void){/*{{{*/ 1641 1642 bool isicefront; 1643 int i,nrice; 1644 IssmDouble ls[NUMVERTICES]; 1645 1646 /*Retrieve all inputs and parameters*/ 1647 GetInputListOnVertices(&ls[0],MaskIceLevelsetEnum); 1648 1649 /* If only one vertex has ice, there is an ice front here */ 1650 isicefront=false; 1651 if(IsIceInElement()){ 1652 nrice=0; 1653 for(i=0;i<NUMVERTICES;i++) 1654 if(ls[i]<0.) nrice++; 1655 if(nrice==1) isicefront= true; 1656 } 1657 return isicefront; 1658 }/*}}}*/ 1659 bool Tria::IsNodeOnShelfFromFlags(IssmDouble* flags){/*{{{*/ 1660 1661 int i; 1662 bool shelf=false; 1663 1664 for(i=0;i<NUMVERTICES;i++){ 1665 if (flags[vertices[i]->Pid()]<0.){ 1666 shelf=true; 1667 break; 1668 } 1669 } 1670 return shelf; 1671 } 1672 /*}}}*/ 1373 1673 bool Tria::IsOnBase(){/*{{{*/ 1374 1674 1375 1675 int domaintype; … … 1396 1696 } 1397 1697 } 1398 1698 /*}}}*/ 1699 bool Tria::IsZeroLevelset(int levelset_enum){/*{{{*/ 1700 1701 bool iszerols; 1702 IssmDouble ls[NUMVERTICES]; 1703 1704 /*Retrieve all inputs and parameters*/ 1705 GetInputListOnVertices(&ls[0],levelset_enum); 1706 1707 /*If the level set is awlays <0, there is no ice front here*/ 1708 iszerols= false; 1709 if(IsIceInElement()){ 1710 if(ls[0]*ls[1]<0. || ls[0]*ls[2]<0. || (ls[0]*ls[1]*ls[2]==0. && ls[0]*ls[1]+ls[0]*ls[2]+ls[1]*ls[2]<=0.)){ 1711 iszerols = true; 1712 } 1713 } 1714 1715 return iszerols; 1716 } 1717 /*}}}*/ 1399 1718 void Tria::JacobianDeterminant(IssmDouble* pJdet,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 1400 1719 1401 1720 _assert_(gauss->Enum()==GaussTriaEnum); … … 1424 1743 1425 1744 } 1426 1745 /*}}}*/ 1427 bool Tria::HasEdgeOnBase(){/*{{{*/1746 IssmDouble Tria::Masscon(IssmDouble* levelset){ /*{{{*/ 1428 1747 1429 IssmDouble values[NUMVERTICES];1430 IssmDouble sum;1431 1748 1432 /*Retrieve all inputs and parameters*/ 1433 GetInputListOnVertices(&values[0],MeshVertexonbaseEnum); 1434 sum = values[0]+values[1]+values[2]; 1749 /*intermediary: */ 1750 IssmDouble* values=NULL; 1751 Input* thickness_input=NULL; 1752 IssmDouble thickness; 1753 IssmDouble weight; 1754 IssmDouble Jdet; 1755 IssmDouble volume; 1756 IssmDouble rho_ice; 1757 IssmDouble* xyz_list=NULL; 1758 int point1; 1759 IssmDouble fraction1,fraction2; 1760 bool mainlynegative=true; 1761 1762 /*Output:*/ 1763 volume=0; 1435 1764 1436 _assert_(sum==0. || sum==1. || sum==2.); 1765 /* Get node coordinates and dof list: */ 1766 GetVerticesCoordinates(&xyz_list); 1437 1767 1438 if(sum==3.) _error_("Two edges on bed not supported yet..."); 1768 /*Retrieve inputs required:*/ 1769 thickness_input=this->GetInput(ThicknessEnum); _assert_(thickness_input); 1770 1771 /*Retrieve material parameters: */ 1772 rho_ice=matpar->GetRhoIce(); 1439 1773 1440 if(sum>1.){ 1441 return true; 1774 /*Retrieve values of the levelset defining the masscon: */ 1775 values = xNew<IssmDouble>(NUMVERTICES); 1776 for(int i=0;i<NUMVERTICES;i++){ 1777 values[i]=levelset[this->vertices[i]->Sid()]; 1442 1778 } 1443 else{ 1444 return false; 1779 1780 /*Ok, use the level set values to figure out where we put our gaussian points:*/ 1781 this->GetLevelsetPositivePart(&point1,&fraction1,&fraction2,&mainlynegative,values); 1782 Gauss* gauss = this->NewGauss(point1,fraction1,fraction2,mainlynegative,4); 1783 1784 volume=0; 1785 1786 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1787 gauss->GaussPoint(ig); 1788 1789 this->JacobianDeterminant(&Jdet,xyz_list,gauss); 1790 thickness_input->GetInputValue(&thickness, gauss); 1791 1792 volume+=thickness*gauss->weight*Jdet; 1445 1793 } 1794 1795 /* clean up and Return: */ 1796 xDelete<IssmDouble>(xyz_list); 1797 xDelete<IssmDouble>(values); 1798 delete gauss; 1799 return rho_ice*volume; 1446 1800 } 1447 1801 /*}}}*/ 1448 bool Tria::HasEdgeOnSurface(){/*{{{*/1802 IssmDouble Tria::MassFlux(IssmDouble x1, IssmDouble y1, IssmDouble x2, IssmDouble y2,int segment_id){/*{{{*/ 1449 1803 1450 IssmDouble values[NUMVERTICES]; 1451 IssmDouble sum; 1804 int domaintype; 1805 IssmDouble mass_flux=0.; 1806 IssmDouble xyz_list[NUMVERTICES][3]; 1807 IssmDouble normal[2]; 1808 IssmDouble length,rho_ice; 1809 IssmDouble h1,h2; 1810 IssmDouble vx1,vx2,vy1,vy2; 1811 GaussTria* gauss_1=NULL; 1812 GaussTria* gauss_2=NULL; 1452 1813 1453 /*Retrieve all inputs and parameters*/ 1454 GetInputListOnVertices(&values[0],MeshVertexonsurfaceEnum); 1455 sum = values[0]+values[1]+values[2]; 1814 /*Get material parameters :*/ 1815 rho_ice=matpar->GetRhoIce(); 1456 1816 1457 _assert_(sum==0. || sum==1. || sum==2.); 1817 /*First off, check that this segment belongs to this element: */ 1818 if (segment_id!=this->id)_error_("error message: segment with id " << segment_id << " does not belong to element with id:" << this->id); 1458 1819 1459 if(sum==3.) _error_("Two edges on surface not supported yet..."); 1820 /*Get xyz list: */ 1821 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 1460 1822 1461 if(sum>1.){ 1462 return true; 1823 /*get area coordinates of 0 and 1 locations: */ 1824 gauss_1=new GaussTria(); 1825 gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]); 1826 gauss_2=new GaussTria(); 1827 gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]); 1828 1829 normal[0]=cos(atan2(x1-x2,y2-y1)); 1830 normal[1]=sin(atan2(x1-x2,y2-y1)); 1831 1832 length=sqrt(pow(x2-x1,2)+pow(y2-y1,2)); 1833 1834 Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input); 1835 this->parameters->FindParam(&domaintype,DomainTypeEnum); 1836 Input* vx_input=NULL; 1837 Input* vy_input=NULL; 1838 if(domaintype==Domain2DhorizontalEnum){ 1839 vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 1840 vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 1463 1841 } 1464 1842 else{ 1465 return false; 1843 vx_input=inputs->GetInput(VxAverageEnum); _assert_(vx_input); 1844 vy_input=inputs->GetInput(VyAverageEnum); _assert_(vy_input); 1466 1845 } 1467 }1468 /*}}}*/1469 void Tria::EdgeOnBaseIndices(int* pindex1,int* pindex2){/*{{{*/1470 1846 1471 IssmDouble values[NUMVERTICES]; 1472 int indices[3][2] = {{1,2},{2,0},{0,1}}; 1847 thickness_input->GetInputValue(&h1, gauss_1); 1848 thickness_input->GetInputValue(&h2, gauss_2); 1849 vx_input->GetInputValue(&vx1,gauss_1); 1850 vx_input->GetInputValue(&vx2,gauss_2); 1851 vy_input->GetInputValue(&vy1,gauss_1); 1852 vy_input->GetInputValue(&vy2,gauss_2); 1473 1853 1474 /*Retrieve all inputs and parameters*/ 1475 GetInputListOnVertices(&values[0],MeshVertexonbaseEnum); 1854 mass_flux= rho_ice*length*( 1855 (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+ 1856 (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1] 1857 ); 1476 1858 1477 for(int i=0;i<3;i++){ 1478 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){ 1479 *pindex1 = indices[i][0]; 1480 *pindex2 = indices[i][1]; 1481 return; 1482 } 1483 } 1484 1485 _printf_("list of vertices on bed: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 1486 _error_("Could not find 2 vertices on bed"); 1859 /*clean up and return:*/ 1860 delete gauss_1; 1861 delete gauss_2; 1862 return mass_flux; 1487 1863 } 1488 1864 /*}}}*/ 1489 void Tria::EdgeOnSurfaceIndices(int* pindex1,int* pindex2){/*{{{*/1865 IssmDouble Tria::MassFlux(IssmDouble* segment){/*{{{*/ 1490 1866 1491 IssmDouble values[NUMVERTICES]; 1492 int indices[3][2] = {{1,2},{2,0},{0,1}}; 1867 int domaintype; 1868 IssmDouble mass_flux=0.; 1869 IssmDouble xyz_list[NUMVERTICES][3]; 1870 IssmDouble normal[2]; 1871 IssmDouble length,rho_ice; 1872 IssmDouble x1,y1,x2,y2,h1,h2; 1873 IssmDouble vx1,vx2,vy1,vy2; 1874 GaussTria* gauss_1=NULL; 1875 GaussTria* gauss_2=NULL; 1493 1876 1494 /* Retrieve all inputs and parameters*/1495 GetInputListOnVertices(&values[0],MeshVertexonsurfaceEnum);1877 /*Get material parameters :*/ 1878 rho_ice=matpar->GetRhoIce(); 1496 1879 1497 for(int i=0;i<3;i++){ 1498 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){ 1499 *pindex1 = indices[i][0]; 1500 *pindex2 = indices[i][1]; 1501 return; 1502 } 1503 } 1880 /*First off, check that this segment belongs to this element: */ 1881 if (reCast<int>(*(segment+4))!=this->id)_error_("error message: segment with id " << reCast<int>(*(segment+4)) << " does not belong to element with id:" << this->id); 1504 1882 1505 _printf_("list of vertices on surface: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 1506 _error_("Could not find 2 vertices on surface"); 1507 } 1508 /*}}}*/ 1509 int Tria::EdgeOnBaseIndex(void){/*{{{*/ 1883 /*Recover segment node locations: */ 1884 x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3); 1510 1885 1511 IssmDouble values[NUMVERTICES];1512 int indices[3][2] = {{1,2},{2,0},{0,1}};1886 /*Get xyz list: */ 1887 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 1513 1888 1514 /*Retrieve all inputs and parameters*/ 1515 GetInputListOnVertices(&values[0],MeshVertexonbaseEnum); 1889 /*get area coordinates of 0 and 1 locations: */ 1890 gauss_1=new GaussTria(); 1891 gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]); 1892 gauss_2=new GaussTria(); 1893 gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]); 1516 1894 1517 for(int i=0;i<3;i++){ 1518 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){ 1519 return i; 1520 } 1895 normal[0]=cos(atan2(x1-x2,y2-y1)); 1896 normal[1]=sin(atan2(x1-x2,y2-y1)); 1897 1898 length=sqrt(pow(x2-x1,2)+pow(y2-y1,2)); 1899 1900 Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input); 1901 this->parameters->FindParam(&domaintype,DomainTypeEnum); 1902 Input* vx_input=NULL; 1903 Input* vy_input=NULL; 1904 if(domaintype==Domain2DhorizontalEnum){ 1905 vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 1906 vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 1521 1907 } 1908 else{ 1909 vx_input=inputs->GetInput(VxAverageEnum); _assert_(vx_input); 1910 vy_input=inputs->GetInput(VyAverageEnum); _assert_(vy_input); 1911 } 1522 1912 1523 _printf_("list of vertices on bed: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 1524 _error_("Could not find 2 vertices on bed"); 1913 thickness_input->GetInputValue(&h1, gauss_1); 1914 thickness_input->GetInputValue(&h2, gauss_2); 1915 vx_input->GetInputValue(&vx1,gauss_1); 1916 vx_input->GetInputValue(&vx2,gauss_2); 1917 vy_input->GetInputValue(&vy1,gauss_1); 1918 vy_input->GetInputValue(&vy2,gauss_2); 1919 1920 mass_flux= rho_ice*length*( 1921 (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+ 1922 (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1] 1923 ); 1924 1925 /*clean up and return:*/ 1926 delete gauss_1; 1927 delete gauss_2; 1928 return mass_flux; 1525 1929 } 1526 1930 /*}}}*/ 1527 int Tria::EdgeOnSurfaceIndex(void){/*{{{*/1931 IssmDouble Tria::Misfit(int modelenum,int observationenum,int weightsenum){/*{{{*/ 1528 1932 1529 IssmDouble values[NUMVERTICES]; 1530 int indices[3][2] = {{1,2},{2,0},{0,1}}; 1933 /*Intermediaries*/ 1934 IssmDouble model,observation,weight; 1935 IssmDouble Jdet; 1936 IssmDouble Jelem = 0; 1937 IssmDouble xyz_list[NUMVERTICES][3]; 1938 GaussTria *gauss = NULL; 1531 1939 1532 /* Retrieve all inputs and parameters*/1533 GetInputListOnVertices(&values[0],MeshVertexonsurfaceEnum);1940 /*If on water, return 0: */ 1941 if(!IsIceInElement())return 0; 1534 1942 1535 for(int i=0;i<3;i++){1536 if(values[indices[i][0]] == 1. && values[indices[i][1]] == 1.){1537 return i;1538 }1539 }1943 /*Retrieve all inputs we will be needing: */ 1944 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 1945 Input* model_input=inputs->GetInput(modelenum); _assert_(model_input); 1946 Input* observation_input=inputs->GetInput(observationenum);_assert_(observation_input); 1947 Input* weights_input =inputs->GetInput(weightsenum); _assert_(weights_input); 1540 1948 1541 _printf_("list of vertices on surface: "<<values[0]<<" "<<values[1]<<" "<<values[2]); 1542 _error_("Could not find 2 vertices on surface"); 1543 } 1544 /*}}}*/ 1545 void Tria::FSContactMigration(Vector<IssmDouble>* vertexgrounded,Vector<IssmDouble>* vertexfloating){/*{{{*/ 1949 /* Start looping on the number of gaussian points: */ 1950 gauss=new GaussTria(2); 1951 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1546 1952 1547 if(!IsOnBase()) return;1953 gauss->GaussPoint(ig); 1548 1954 1549 int approximation;1550 inputs->GetInputValue(&approximation,ApproximationEnum);1955 /* Get Jacobian determinant: */ 1956 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 1551 1957 1552 if(approximation==HOApproximationEnum || approximation==SSAApproximationEnum || approximation==SSAHOApproximationEnum){ 1553 for(int i=0;i<NUMVERTICES;i++){ 1554 vertexgrounded->SetValue(vertices[i]->Pid(),+9999.,INS_VAL); 1555 vertexfloating->SetValue(vertices[i]->Pid(),+9999.,INS_VAL); 1556 } 1958 /*Get parameters at gauss point*/ 1959 model_input->GetInputValue(&model,gauss); 1960 observation_input->GetInputValue(&observation,gauss); 1961 weights_input->GetInputValue(&weight,gauss); 1962 1963 /*compute misfit between model and observation */ 1964 Jelem+=0.5*(model-observation)*(model-observation)*Jdet*weight*gauss->weight; 1557 1965 } 1558 else{1559 /*Intermediaries*/1560 IssmDouble* xyz_list = NULL;1561 IssmDouble* xyz_list_base = NULL;1562 IssmDouble pressure,water_pressure,sigma_nn,viscosity,bed,base;1563 IssmDouble bed_normal[2];1564 IssmDouble epsilon[3]; /* epsilon=[exx,eyy,exy];*/1565 IssmDouble surface=0,value=0;1566 bool grounded;1567 1966 1568 /* Get node coordinates and dof list: */ 1569 GetVerticesCoordinates(&xyz_list); 1570 GetVerticesCoordinatesBase(&xyz_list_base); 1967 /* clean up and Return: */ 1968 delete gauss; 1969 return Jelem; 1970 } 1971 /*}}}*/ 1972 IssmDouble Tria::MisfitArea(int weightsenum){/*{{{*/ 1571 1973 1572 /*Retrieve all inputs we will be needing:*/1573 Input* pressure_input = inputs->GetInput(PressureEnum); _assert_(pressure_input);1574 Input* base_input = inputs->GetInput(BaseEnum); _assert_(base_input);1575 Input* bed_input = inputs->GetInput(BedEnum); _assert_(bed_input);1576 Input* vx_input = inputs->GetInput(VxEnum); _assert_(vx_input);1577 Input* vy_input = inputs->GetInput(VyEnum); _assert_(vy_input);1974 /*Intermediaries*/ 1975 IssmDouble weight; 1976 IssmDouble Jdet; 1977 IssmDouble Jelem = 0; 1978 IssmDouble xyz_list[NUMVERTICES][3]; 1979 GaussTria *gauss = NULL; 1578 1980 1579 /*Create gauss point in the middle of the basal edge*/ 1580 Gauss* gauss=NewGaussBase(1); 1581 gauss->GaussPoint(0); 1981 /*If on water, return 0: */ 1982 if(!IsIceInElement())return 0; 1582 1983 1583 if(!IsFloating()){ 1584 /*Check for basal force only if grounded and touching GL*/ 1585 // if(this->inputs->Min(MaskGroundediceLevelsetEnum)==0.){ 1586 this->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input); 1587 this->ViscosityFS(&viscosity,2,xyz_list,gauss,vx_input,vy_input,NULL); 1588 pressure_input->GetInputValue(&pressure, gauss); 1589 base_input->GetInputValue(&base, gauss); 1984 /*Retrieve all inputs we will be needing: */ 1985 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 1986 Input* weights_input =inputs->GetInput(weightsenum); _assert_(weights_input); 1590 1987 1591 /*Compute Stress*/ 1592 IssmDouble sigma_xx=2.*viscosity*epsilon[0]-pressure; 1593 IssmDouble sigma_yy=2.*viscosity*epsilon[1]-pressure; 1594 IssmDouble sigma_xy=2.*viscosity*epsilon[2]; 1988 /* Start looping on the number of gaussian points: */ 1989 gauss=new GaussTria(2); 1990 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1595 1991 1596 /*Get normal vector to the bed */ 1597 NormalBase(&bed_normal[0],xyz_list_base); 1992 gauss->GaussPoint(ig); 1598 1993 1599 /*basalforce*/1600 sigma_nn = sigma_xx*bed_normal[0]*bed_normal[0] + sigma_yy*bed_normal[1]*bed_normal[1] + 2.*sigma_xy*bed_normal[0]*bed_normal[1];1994 /* Get Jacobian determinant: */ 1995 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 1601 1996 1602 /*Compute water pressure*/ 1603 IssmDouble rho_ice = matpar->GetRhoIce(); 1604 IssmDouble rho_water = matpar->GetRhoWater(); 1605 IssmDouble gravity = matpar->GetG(); 1606 water_pressure=gravity*rho_water*base; 1997 /*Get parameters at gauss point*/ 1998 weights_input->GetInputValue(&weight,gauss); 1607 1999 1608 /*Compare basal stress to water pressure and determine whether it should ground*/ 1609 if (sigma_nn<water_pressure) grounded=true; 1610 else grounded=false; 1611 } 1612 else{ 1613 /*Check for basal elevation if floating*/ 1614 base_input->GetInputValue(&base, gauss); 1615 bed_input->GetInputValue(&bed, gauss); 1616 if(base<bed) grounded=true; 1617 else grounded=false; 1618 } 1619 for(int i=0;i<NUMVERTICES;i++){ 1620 if(grounded) vertexgrounded->SetValue(vertices[i]->Pid(),+1.,INS_VAL); 1621 else vertexfloating->SetValue(vertices[i]->Pid(),+1.,INS_VAL); 1622 } 1623 1624 /*clean up*/ 1625 delete gauss; 1626 xDelete<IssmDouble>(xyz_list); 1627 xDelete<IssmDouble>(xyz_list_base); 2000 /*compute misfit between model and observation */ 2001 Jelem+=Jdet*weight*gauss->weight; 1628 2002 } 1629 }1630 /*}}}*/1631 bool Tria::IsNodeOnShelfFromFlags(IssmDouble* flags){/*{{{*/1632 2003 1633 int i; 1634 bool shelf=false; 1635 1636 for(i=0;i<NUMVERTICES;i++){ 1637 if (flags[vertices[i]->Pid()]<0.){ 1638 shelf=true; 1639 break; 1640 } 1641 } 1642 return shelf; 2004 /* clean up and Return: */ 2005 delete gauss; 2006 return Jelem; 1643 2007 } 1644 2008 /*}}}*/ 1645 2009 Gauss* Tria::NewGauss(void){/*{{{*/ … … 1690 2054 1691 2055 } 1692 2056 /*}}}*/ 1693 void Tria::NodalFunctions P1(IssmDouble* basis,Gauss* gauss){/*{{{*/2057 void Tria::NodalFunctionsDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 1694 2058 1695 2059 _assert_(gauss->Enum()==GaussTriaEnum); 1696 this->GetNodalFunctions (basis,(GaussTria*)gauss,P1Enum);2060 this->GetNodalFunctionsDerivatives(dbasis,xyz_list,(GaussTria*)gauss,this->element_type); 1697 2061 1698 2062 } 1699 2063 /*}}}*/ 1700 void Tria::NodalFunctions P2(IssmDouble* basis,Gauss* gauss){/*{{{*/2064 void Tria::NodalFunctionsDerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 1701 2065 1702 2066 _assert_(gauss->Enum()==GaussTriaEnum); 1703 this->GetNodalFunctions (basis,(GaussTria*)gauss,P2Enum);2067 this->GetNodalFunctionsDerivatives(dbasis,xyz_list,(GaussTria*)gauss,this->VelocityInterpolation()); 1704 2068 1705 2069 } 1706 2070 /*}}}*/ 1707 void Tria::NodalFunctions Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/2071 void Tria::NodalFunctionsPressure(IssmDouble* basis, Gauss* gauss){/*{{{*/ 1708 2072 1709 2073 _assert_(gauss->Enum()==GaussTriaEnum); 1710 this->GetNodalFunctions Derivatives(dbasis,xyz_list,(GaussTria*)gauss,this->element_type);2074 this->GetNodalFunctions(basis,(GaussTria*)gauss,this->PressureInterpolation()); 1711 2075 1712 2076 } 1713 2077 /*}}}*/ 1714 void Tria::NodalFunctionsP1 Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/2078 void Tria::NodalFunctionsP1(IssmDouble* basis, Gauss* gauss){/*{{{*/ 1715 2079 1716 2080 _assert_(gauss->Enum()==GaussTriaEnum); 1717 this->GetNodalFunctions Derivatives(dbasis,xyz_list,(GaussTria*)gauss,P1Enum);2081 this->GetNodalFunctions(basis,(GaussTria*)gauss,P1Enum); 1718 2082 1719 2083 } 1720 2084 /*}}}*/ 1721 void Tria::NodalFunctions DerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/2085 void Tria::NodalFunctionsP1Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 1722 2086 1723 2087 _assert_(gauss->Enum()==GaussTriaEnum); 1724 this->GetNodalFunctionsDerivatives(dbasis,xyz_list,(GaussTria*)gauss, this->VelocityInterpolation());2088 this->GetNodalFunctionsDerivatives(dbasis,xyz_list,(GaussTria*)gauss,P1Enum); 1725 2089 1726 2090 } 1727 2091 /*}}}*/ 1728 void Tria::NodalFunctions Velocity(IssmDouble* basis, Gauss* gauss){/*{{{*/2092 void Tria::NodalFunctionsP2(IssmDouble* basis, Gauss* gauss){/*{{{*/ 1729 2093 1730 2094 _assert_(gauss->Enum()==GaussTriaEnum); 1731 this->GetNodalFunctions(basis,(GaussTria*)gauss, this->VelocityInterpolation());2095 this->GetNodalFunctions(basis,(GaussTria*)gauss,P2Enum); 1732 2096 1733 2097 } 1734 2098 /*}}}*/ 1735 void Tria::NodalFunctions Pressure(IssmDouble* basis, Gauss* gauss){/*{{{*/2099 void Tria::NodalFunctionsTensor(IssmDouble* basis, Gauss* gauss){/*{{{*/ 1736 2100 1737 2101 _assert_(gauss->Enum()==GaussTriaEnum); 1738 this->GetNodalFunctions(basis,(GaussTria*)gauss,this-> PressureInterpolation());2102 this->GetNodalFunctions(basis,(GaussTria*)gauss,this->TensorInterpolation()); 1739 2103 1740 2104 } 1741 2105 /*}}}*/ 1742 void Tria::NodalFunctions Tensor(IssmDouble* basis, Gauss* gauss){/*{{{*/2106 void Tria::NodalFunctionsVelocity(IssmDouble* basis, Gauss* gauss){/*{{{*/ 1743 2107 1744 2108 _assert_(gauss->Enum()==GaussTriaEnum); 1745 this->GetNodalFunctions(basis,(GaussTria*)gauss,this-> TensorInterpolation());2109 this->GetNodalFunctions(basis,(GaussTria*)gauss,this->VelocityInterpolation()); 1746 2110 1747 2111 } 1748 2112 /*}}}*/ … … 1794 2158 _assert_(bed_normal[1]<0); 1795 2159 } 1796 2160 /*}}}*/ 2161 void Tria::NormalSection(IssmDouble* normal,IssmDouble* xyz_list){/*{{{*/ 2162 2163 /*Build unit outward pointing vector*/ 2164 IssmDouble vector[2]; 2165 IssmDouble norm; 2166 2167 vector[0]=xyz_list[1*3+0] - xyz_list[0*3+0]; 2168 vector[1]=xyz_list[1*3+1] - xyz_list[0*3+1]; 2169 2170 norm=sqrt(vector[0]*vector[0] + vector[1]*vector[1]); 2171 2172 normal[0]= + vector[1]/norm; 2173 normal[1]= - vector[0]/norm; 2174 } 2175 /*}}}*/ 1797 2176 void Tria::NormalTop(IssmDouble* top_normal,IssmDouble* xyz_list){/*{{{*/ 1798 2177 1799 2178 /*Build unit outward pointing vector*/ … … 1812 2191 _assert_(top_normal[1]>0); 1813 2192 } 1814 2193 /*}}}*/ 1815 int Tria::VelocityInterpolation(void){/*{{{*/ 1816 return TriaRef::VelocityInterpolation(this->element_type); 2194 int Tria::ObjectEnum(void){/*{{{*/ 2195 2196 return TriaEnum; 2197 1817 2198 } 1818 2199 /*}}}*/ 1819 2200 int Tria::PressureInterpolation(void){/*{{{*/ 1820 2201 return TriaRef::PressureInterpolation(this->element_type); 1821 2202 } 1822 2203 /*}}}*/ 1823 int Tria::TensorInterpolation(void){/*{{{*/1824 return TriaRef::TensorInterpolation(this->element_type);1825 }1826 /*}}}*/1827 2204 int Tria::NumberofNodesPressure(void){/*{{{*/ 1828 2205 return TriaRef::NumberofNodes(this->PressureInterpolation()); 1829 2206 } … … 1900 2277 delete gauss; 1901 2278 } 1902 2279 /*}}}*/ 2280 void Tria::PotentialUngrounding(Vector<IssmDouble>* potential_ungrounding){/*{{{*/ 2281 2282 IssmDouble h[NUMVERTICES],r[NUMVERTICES],gl[NUMVERTICES]; 2283 IssmDouble bed_hydro; 2284 IssmDouble rho_water,rho_ice,density; 2285 2286 /*material parameters: */ 2287 rho_water=matpar->GetRhoWater(); 2288 rho_ice=matpar->GetRhoIce(); 2289 density=rho_ice/rho_water; 2290 GetInputListOnVertices(&h[0],ThicknessEnum); 2291 GetInputListOnVertices(&r[0],BedEnum); 2292 GetInputListOnVertices(&gl[0],MaskGroundediceLevelsetEnum); 2293 2294 /*go through vertices, and figure out which ones are grounded and want to unground: */ 2295 for(int i=0;i<NUMVERTICES;i++){ 2296 /*Find if grounded vertices want to start floating*/ 2297 if (gl[i]>0.){ 2298 bed_hydro=-density*h[i]; 2299 if(bed_hydro>r[i]){ 2300 /*Vertex that could potentially unground, flag it*/ 2301 potential_ungrounding->SetValue(vertices[i]->Pid(),1,INS_VAL); 2302 } 2303 } 2304 } 2305 } 2306 /*}}}*/ 1903 2307 void Tria::ReduceMatrices(ElementMatrix* Ke,ElementVector* pe){/*{{{*/ 1904 2308 1905 2309 /*Static condensation if requested*/ … … 2010 2414 _error_("not implemented yet"); 2011 2415 } 2012 2416 /*}}}*/ 2417 void Tria::SetControlInputsFromVector(IssmDouble* vector,int control_enum,int control_index){/*{{{*/ 2418 2419 IssmDouble values[NUMVERTICES]; 2420 int vertexpidlist[NUMVERTICES],control_init; 2421 2422 2423 /*Get Domain type*/ 2424 int domaintype; 2425 parameters->FindParam(&domaintype,DomainTypeEnum); 2426 2427 /*Specific case for depth averaged quantities*/ 2428 control_init=control_enum; 2429 if(domaintype==Domain2DverticalEnum){ 2430 if(control_enum==MaterialsRheologyBbarEnum){ 2431 control_enum=MaterialsRheologyBEnum; 2432 if(!IsOnBase()) return; 2433 } 2434 if(control_enum==DamageDbarEnum){ 2435 control_enum=DamageDEnum; 2436 if(!IsOnBase()) return; 2437 } 2438 } 2439 2440 /*Get out if this is not an element input*/ 2441 if(!IsInput(control_enum)) return; 2442 2443 /*Prepare index list*/ 2444 GradientIndexing(&vertexpidlist[0],control_index); 2445 2446 /*Get values on vertices*/ 2447 for(int i=0;i<NUMVERTICES;i++){ 2448 values[i]=vector[vertexpidlist[i]]; 2449 } 2450 Input* new_input = new TriaInput(control_enum,values,P1Enum); 2451 Input* input = (Input*)this->inputs->GetInput(control_enum); _assert_(input); 2452 if(input->ObjectEnum()!=ControlInputEnum){ 2453 _error_("input " << EnumToStringx(control_enum) << " is not a ControlInput"); 2454 } 2455 2456 ((ControlInput*)input)->SetInput(new_input); 2457 } 2458 /*}}}*/ 2459 void Tria::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, Nodes* nodesin, Materials* materialsin, Parameters* parametersin){/*{{{*/ 2460 2461 /*go into parameters and get the analysis_counter: */ 2462 int analysis_counter; 2463 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 2464 2465 /*Get Element type*/ 2466 if(this->element_type_list) this->element_type=this->element_type_list[analysis_counter]; 2467 2468 /*Pick up nodes*/ 2469 if(this->hnodes && this->hnodes[analysis_counter]){ 2470 this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 2471 } 2472 2473 } 2474 /*}}}*/ 2475 Element* Tria::SpawnBasalElement(void){/*{{{*/ 2476 2477 int index1,index2; 2478 int domaintype; 2479 2480 this->parameters->FindParam(&domaintype,DomainTypeEnum); 2481 switch(domaintype){ 2482 case Domain2DhorizontalEnum: 2483 return this; 2484 case Domain2DverticalEnum: 2485 _assert_(HasEdgeOnBase()); 2486 this->EdgeOnBaseIndices(&index1,&index2); 2487 return SpawnSeg(index1,index2); 2488 default: 2489 _error_("not implemented yet"); 2490 } 2491 } 2492 /*}}}*/ 2013 2493 Seg* Tria::SpawnSeg(int index1,int index2){/*{{{*/ 2014 2494 2015 2495 int analysis_counter; … … 2037 2517 return seg; 2038 2518 } 2039 2519 /*}}}*/ 2040 Element* Tria::Spawn BasalElement(void){/*{{{*/2520 Element* Tria::SpawnTopElement(void){/*{{{*/ 2041 2521 2042 2522 int index1,index2; 2043 2523 int domaintype; … … 2047 2527 case Domain2DhorizontalEnum: 2048 2528 return this; 2049 2529 case Domain2DverticalEnum: 2050 _assert_(HasEdgeOn Base());2051 this->EdgeOn BaseIndices(&index1,&index2);2052 return SpawnSeg(index 1,index2);2530 _assert_(HasEdgeOnSurface()); 2531 this->EdgeOnSurfaceIndices(&index1,&index2); 2532 return SpawnSeg(index2,index1); //reverse order 2053 2533 default: 2054 2534 _error_("not implemented yet"); 2055 2535 } 2056 2536 } 2057 2537 /*}}}*/ 2058 Element* Tria::SpawnTopElement(void){/*{{{*/2538 void Tria::StrainRateparallel(){/*{{{*/ 2059 2539 2060 int index1,index2; 2061 int domaintype; 2540 IssmDouble *xyz_list = NULL; 2541 IssmDouble epsilon[3]; 2542 GaussTria* gauss=NULL; 2543 IssmDouble vx,vy,vel; 2544 IssmDouble strainxx; 2545 IssmDouble strainxy; 2546 IssmDouble strainyy; 2547 IssmDouble strainparallel[NUMVERTICES]; 2062 2548 2063 this->parameters->FindParam(&domaintype,DomainTypeEnum); 2064 switch(domaintype){ 2065 case Domain2DhorizontalEnum: 2066 return this; 2067 case Domain2DverticalEnum: 2068 _assert_(HasEdgeOnSurface()); 2069 this->EdgeOnSurfaceIndices(&index1,&index2); 2070 return SpawnSeg(index2,index1); //reverse order 2071 default: 2072 _error_("not implemented yet"); 2549 /* Get node coordinates and dof list: */ 2550 this->GetVerticesCoordinates(&xyz_list); 2551 2552 /*Retrieve all inputs we will need*/ 2553 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 2554 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 2555 2556 /* Start looping on the number of vertices: */ 2557 gauss=new GaussTria(); 2558 for (int iv=0;iv<NUMVERTICES;iv++){ 2559 gauss->GaussVertex(iv); 2560 2561 /* Get the value we need*/ 2562 vx_input->GetInputValue(&vx,gauss); 2563 vy_input->GetInputValue(&vy,gauss); 2564 vel=vx*vx+vy*vy; 2565 2566 /*Compute strain rate viscosity and pressure: */ 2567 this->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input); 2568 strainxx=epsilon[0]; 2569 strainyy=epsilon[1]; 2570 strainxy=epsilon[2]; 2571 2572 /*strainparallel= Strain rate along the ice flow direction */ 2573 strainparallel[iv]=(vx*vx*(strainxx)+vy*vy*(strainyy)+2*vy*vx*strainxy)/(vel+1.e-6); 2073 2574 } 2575 2576 /*Add input*/ 2577 this->inputs->AddInput(new TriaInput(StrainRateparallelEnum,&strainparallel[0],P1Enum)); 2578 2579 /*Clean up and return*/ 2580 delete gauss; 2581 xDelete<IssmDouble>(xyz_list); 2074 2582 } 2075 2583 /*}}}*/ 2076 void Tria::S etCurrentConfiguration(Elements* elementsin, Loads* loadsin, Nodes* nodesin, Materials* materialsin, Parameters* parametersin){/*{{{*/2584 void Tria::StrainRateperpendicular(){/*{{{*/ 2077 2585 2078 /*go into parameters and get the analysis_counter: */ 2079 int analysis_counter; 2080 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 2586 IssmDouble *xyz_list = NULL; 2587 GaussTria* gauss=NULL; 2588 IssmDouble epsilon[3]; 2589 IssmDouble vx,vy,vel; 2590 IssmDouble strainxx; 2591 IssmDouble strainxy; 2592 IssmDouble strainyy; 2593 IssmDouble strainperpendicular[NUMVERTICES]; 2081 2594 2082 /* Get Element type*/2083 if(this->element_type_list) this->element_type=this->element_type_list[analysis_counter];2595 /* Get node coordinates and dof list: */ 2596 this->GetVerticesCoordinates(&xyz_list); 2084 2597 2085 /*Pick up nodes*/ 2086 if(this->hnodes && this->hnodes[analysis_counter]){ 2087 this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 2598 /*Retrieve all inputs we will need*/ 2599 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 2600 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 2601 2602 /* Start looping on the number of vertices: */ 2603 gauss=new GaussTria(); 2604 for (int iv=0;iv<NUMVERTICES;iv++){ 2605 gauss->GaussVertex(iv); 2606 2607 /* Get the value we need*/ 2608 vx_input->GetInputValue(&vx,gauss); 2609 vy_input->GetInputValue(&vy,gauss); 2610 vel=vx*vx+vy*vy; 2611 2612 /*Compute strain rate viscosity and pressure: */ 2613 this->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input); 2614 strainxx=epsilon[0]; 2615 strainyy=epsilon[1]; 2616 strainxy=epsilon[2]; 2617 2618 /*strainperpendicular= Strain rate perpendicular to the ice flow direction */ 2619 strainperpendicular[iv]=(vx*vx*(strainyy)+vy*vy*(strainxx)-2*vy*vx*strainxy)/(vel+1.e-6); 2088 2620 } 2089 2621 2622 /*Add input*/ 2623 this->inputs->AddInput(new TriaInput(StrainRateperpendicularEnum,&strainperpendicular[0],P1Enum)); 2624 2625 /*Clean up and return*/ 2626 delete gauss; 2627 xDelete<IssmDouble>(xyz_list); 2090 2628 } 2091 2629 /*}}}*/ 2092 2630 IssmDouble Tria::SurfaceArea(void){/*{{{*/ … … 2116 2654 return S; 2117 2655 } 2118 2656 /*}}}*/ 2657 int Tria::TensorInterpolation(void){/*{{{*/ 2658 return TriaRef::TensorInterpolation(this->element_type); 2659 } 2660 /*}}}*/ 2119 2661 IssmDouble Tria::TimeAdapt(void){/*{{{*/ 2120 2662 2121 2663 /*intermediary: */ … … 2157 2699 return dt; 2158 2700 } 2159 2701 /*}}}*/ 2702 IssmDouble Tria::TotalSmb(void){/*{{{*/ 2703 2704 /*The smb[kg yr-1] of one element is area[m2] * smb [kg m^-2 yr^-1]*/ 2705 IssmDouble base,smb,rho_ice; 2706 IssmDouble Total_Smb=0; 2707 IssmDouble xyz_list[NUMVERTICES][3]; 2708 2709 /*Get material parameters :*/ 2710 rho_ice=matpar->GetRhoIce(); 2711 2712 if(!IsIceInElement())return 0; 2713 2714 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 2715 2716 /*First calculate the area of the base (cross section triangle) 2717 * http://en.wikipedia.org/wiki/Triangle 2718 * base = 1/2 abs((xA-xC)(yB-yA)-(xA-xB)(yC-yA))*/ 2719 base = 1./2. * fabs((xyz_list[0][0]-xyz_list[2][0])*(xyz_list[1][1]-xyz_list[0][1]) - (xyz_list[0][0]-xyz_list[1][0])*(xyz_list[2][1]-xyz_list[0][1])); // area of element in m2 2720 2721 /*Now get the average SMB over the element*/ 2722 Input* smb_input = inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(smb_input); 2723 smb_input->GetInputAverage(&smb); // average smb on element in m ice s-1 2724 Total_Smb=rho_ice*base*smb; // smb on element in kg s-1 2725 2726 /*Return: */ 2727 return Total_Smb; 2728 } 2729 /*}}}*/ 2160 2730 void Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type,int finiteelement_type){/*{{{*/ 2161 2731 2162 2732 /*Intermediaries*/ … … 2346 2916 2347 2917 } 2348 2918 /*}}}*/ 2349 void Tria::ValueP1OnGauss(IssmDouble* pvalue,IssmDouble* values,Gauss* gauss){/*{{{*/ 2350 TriaRef::GetInputValue(pvalue,values,gauss,P1Enum); 2351 } 2352 /*}}}*/ 2353 void Tria::ValueP1DerivativesOnGauss(IssmDouble* dvalue,IssmDouble* values,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 2354 TriaRef::GetInputDerivativeValue(dvalue,values,xyz_list,gauss,P1Enum); 2355 } 2356 /*}}}*/ 2357 int Tria::VertexConnectivity(int vertexindex){/*{{{*/ 2358 _assert_(this->vertices); 2359 return this->vertices[vertexindex]->Connectivity(); 2360 } 2361 /*}}}*/ 2362 bool Tria::IsZeroLevelset(int levelset_enum){/*{{{*/ 2919 int Tria::UpdatePotentialUngrounding(IssmDouble* vertices_potentially_ungrounding,Vector<IssmDouble>* vec_nodes_on_iceshelf,IssmDouble* nodes_on_iceshelf){/*{{{*/ 2363 2920 2364 bool iszerols;2365 IssmDouble ls[NUMVERTICES];2921 int i; 2922 int nflipped=0; 2366 2923 2367 /*Retrieve all inputs and parameters*/ 2368 GetInputListOnVertices(&ls[0],levelset_enum); 2924 /*Go through nodes, and whoever is on the potential_ungrounding, ends up in nodes_on_iceshelf: */ 2925 for(i=0;i<3;i++){ 2926 if (reCast<bool>(vertices_potentially_ungrounding[vertices[i]->Pid()])){ 2927 vec_nodes_on_iceshelf->SetValue(vertices[i]->Pid(),-1.,INS_VAL); 2369 2928 2370 /*If the level set is awlays <0, there is no ice front here*/ 2371 iszerols= false; 2372 if(IsIceInElement()){ 2373 if(ls[0]*ls[1]<0. || ls[0]*ls[2]<0. || (ls[0]*ls[1]*ls[2]==0. && ls[0]*ls[1]+ls[0]*ls[2]+ls[1]*ls[2]<=0.)){ 2374 iszerols = true; 2929 /*If node was not on ice shelf, we flipped*/ 2930 if(nodes_on_iceshelf[vertices[i]->Pid()]>=0.){ 2931 nflipped++; 2932 } 2375 2933 } 2376 2934 } 2377 2378 return iszerols; 2935 return nflipped; 2379 2936 } 2380 2937 /*}}}*/ 2381 bool Tria::IsIcefront(void){/*{{{*/ 2382 2383 bool isicefront; 2384 int i,nrice; 2385 IssmDouble ls[NUMVERTICES]; 2386 2387 /*Retrieve all inputs and parameters*/ 2388 GetInputListOnVertices(&ls[0],MaskIceLevelsetEnum); 2389 2390 /* If only one vertex has ice, there is an ice front here */ 2391 isicefront=false; 2392 if(IsIceInElement()){ 2393 nrice=0; 2394 for(i=0;i<NUMVERTICES;i++) 2395 if(ls[i]<0.) nrice++; 2396 if(nrice==1) isicefront= true; 2397 } 2398 return isicefront; 2399 }/*}}}*/ 2400 bool Tria::IsFaceOnBoundary(void){/*{{{*/ 2401 2402 IssmDouble values[NUMVERTICES]; 2403 IssmDouble sum; 2404 2405 /*Retrieve all inputs and parameters*/ 2406 GetInputListOnVertices(&values[0],MeshVertexonboundaryEnum); 2407 sum = values[0]+values[1]+values[2]; 2408 2409 _assert_(sum==0. || sum==1. || sum==2.); 2410 2411 if(sum==3.) _error_("Two edges on boundary not supported yet..."); 2412 2413 if(sum>1.){ 2414 return true; 2415 } 2416 else{ 2417 return false; 2418 } 2419 }/*}}}*/ 2420 void Tria::AverageOntoPartition(Vector<IssmDouble>* partition_contributions,Vector<IssmDouble>* partition_areas,IssmDouble* vertex_response,IssmDouble* qmu_part){/*{{{*/ 2421 2422 bool already = false; 2423 int i,j; 2424 int partition[NUMVERTICES]; 2425 int offsetsid[NUMVERTICES]; 2426 int offsetdof[NUMVERTICES]; 2427 IssmDouble area; 2428 IssmDouble mean; 2429 2430 /*First, get the area: */ 2431 area=this->GetArea(); 2432 2433 /*Figure out the average for this element: */ 2434 this->GetVerticesSidList(&offsetsid[0]); 2435 this->GetVertexPidList(&offsetdof[0]); 2436 mean=0; 2437 for(i=0;i<NUMVERTICES;i++){ 2438 partition[i]=reCast<int>(qmu_part[offsetsid[i]]); 2439 mean=mean+1.0/NUMVERTICES*vertex_response[offsetdof[i]]; 2440 } 2441 2442 /*Add contribution: */ 2443 for(i=0;i<NUMVERTICES;i++){ 2444 already=false; 2445 for(j=0;j<i;j++){ 2446 if (partition[i]==partition[j]){ 2447 already=true; 2448 break; 2449 } 2450 } 2451 if(!already){ 2452 partition_contributions->SetValue(partition[i],mean*area,ADD_VAL); 2453 partition_areas->SetValue(partition[i],area,ADD_VAL); 2454 }; 2455 } 2938 void Tria::ValueP1DerivativesOnGauss(IssmDouble* dvalue,IssmDouble* values,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 2939 TriaRef::GetInputDerivativeValue(dvalue,values,xyz_list,gauss,P1Enum); 2456 2940 } 2457 2941 /*}}}*/ 2458 IssmDouble Tria::IceVolume(void){/*{{{*/ 2459 2460 /*The volume of a troncated prism is base * 1/3 sum(length of edges)*/ 2461 IssmDouble base,surface,bed; 2462 IssmDouble xyz_list[NUMVERTICES][3]; 2463 2464 if(!IsIceInElement())return 0; 2465 2466 /*First get back the area of the base*/ 2467 base=this->GetArea(); 2468 2469 /*Now get the average height*/ 2470 Input* surface_input = inputs->GetInput(SurfaceEnum); _assert_(surface_input); 2471 Input* base_input = inputs->GetInput(BaseEnum); _assert_(base_input); 2472 surface_input->GetInputAverage(&surface); 2473 base_input->GetInputAverage(&bed); 2474 2475 /*Return: */ 2476 int domaintype; 2477 parameters->FindParam(&domaintype,DomainTypeEnum); 2478 if(domaintype==Domain2DverticalEnum){ 2479 return base; 2480 } 2481 else{ 2482 return base*(surface-bed); 2483 } 2942 void Tria::ValueP1OnGauss(IssmDouble* pvalue,IssmDouble* values,Gauss* gauss){/*{{{*/ 2943 TriaRef::GetInputValue(pvalue,values,gauss,P1Enum); 2484 2944 } 2485 2945 /*}}}*/ 2486 IssmDouble Tria::IceVolumeAboveFloatation(void){/*{{{*/ 2487 2488 /*The volume above floatation: H + rho_water/rho_ice * bathymetry */ 2489 IssmDouble rho_ice,rho_water; 2490 IssmDouble base,surface,bed,bathymetry; 2491 IssmDouble xyz_list[NUMVERTICES][3]; 2492 2493 if(!IsIceInElement() || IsFloating())return 0; 2494 2495 rho_ice=matpar->GetRhoIce(); 2496 rho_water=matpar->GetRhoWater(); 2497 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 2498 2499 /*First calculate the area of the base (cross section triangle) 2500 * http://en.wikipedia.org/wiki/Triangle 2501 * base = 1/2 abs((xA-xC)(yB-yA)-(xA-xB)(yC-yA))*/ 2502 base = 1./2. * fabs((xyz_list[0][0]-xyz_list[2][0])*(xyz_list[1][1]-xyz_list[0][1]) - (xyz_list[0][0]-xyz_list[1][0])*(xyz_list[2][1]-xyz_list[0][1])); 2503 2504 /*Now get the average height and bathymetry*/ 2505 Input* surface_input = inputs->GetInput(SurfaceEnum); _assert_(surface_input); 2506 Input* base_input = inputs->GetInput(BaseEnum); _assert_(base_input); 2507 Input* bed_input = inputs->GetInput(BedEnum); _assert_(bed_input); 2508 surface_input->GetInputAverage(&surface); 2509 base_input->GetInputAverage(&bed); 2510 bed_input->GetInputAverage(&bathymetry); 2511 2512 /*Return: */ 2513 return base*(surface-bed+min(rho_water/rho_ice*bathymetry,0.)); 2946 int Tria::VelocityInterpolation(void){/*{{{*/ 2947 return TriaRef::VelocityInterpolation(this->element_type); 2514 2948 } 2515 2949 /*}}}*/ 2516 IssmDouble Tria::MassFlux( IssmDouble x1, IssmDouble y1, IssmDouble x2, IssmDouble y2,int segment_id){/*{{{*/ 2517 2518 int domaintype; 2519 IssmDouble mass_flux=0.; 2520 IssmDouble xyz_list[NUMVERTICES][3]; 2521 IssmDouble normal[2]; 2522 IssmDouble length,rho_ice; 2523 IssmDouble h1,h2; 2524 IssmDouble vx1,vx2,vy1,vy2; 2525 GaussTria* gauss_1=NULL; 2526 GaussTria* gauss_2=NULL; 2527 2528 /*Get material parameters :*/ 2529 rho_ice=matpar->GetRhoIce(); 2530 2531 /*First off, check that this segment belongs to this element: */ 2532 if (segment_id!=this->id)_error_("error message: segment with id " << segment_id << " does not belong to element with id:" << this->id); 2533 2534 /*Get xyz list: */ 2535 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 2536 2537 /*get area coordinates of 0 and 1 locations: */ 2538 gauss_1=new GaussTria(); 2539 gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]); 2540 gauss_2=new GaussTria(); 2541 gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]); 2542 2543 normal[0]=cos(atan2(x1-x2,y2-y1)); 2544 normal[1]=sin(atan2(x1-x2,y2-y1)); 2545 2546 length=sqrt(pow(x2-x1,2)+pow(y2-y1,2)); 2547 2548 Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input); 2549 this->parameters->FindParam(&domaintype,DomainTypeEnum); 2550 Input* vx_input=NULL; 2551 Input* vy_input=NULL; 2552 if(domaintype==Domain2DhorizontalEnum){ 2553 vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 2554 vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 2555 } 2556 else{ 2557 vx_input=inputs->GetInput(VxAverageEnum); _assert_(vx_input); 2558 vy_input=inputs->GetInput(VyAverageEnum); _assert_(vy_input); 2559 } 2560 2561 thickness_input->GetInputValue(&h1, gauss_1); 2562 thickness_input->GetInputValue(&h2, gauss_2); 2563 vx_input->GetInputValue(&vx1,gauss_1); 2564 vx_input->GetInputValue(&vx2,gauss_2); 2565 vy_input->GetInputValue(&vy1,gauss_1); 2566 vy_input->GetInputValue(&vy2,gauss_2); 2567 2568 mass_flux= rho_ice*length*( 2569 (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+ 2570 (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1] 2571 ); 2572 2573 /*clean up and return:*/ 2574 delete gauss_1; 2575 delete gauss_2; 2576 return mass_flux; 2950 int Tria::VertexConnectivity(int vertexindex){/*{{{*/ 2951 _assert_(this->vertices); 2952 return this->vertices[vertexindex]->Connectivity(); 2577 2953 } 2578 2954 /*}}}*/ 2579 IssmDouble Tria::MassFlux( IssmDouble* segment){/*{{{*/2955 void Tria::ZeroLevelsetCoordinates(IssmDouble** pxyz_zero,IssmDouble* xyz_list,int levelsetenum){/*{{{*/ 2580 2956 2581 int domaintype; 2582 IssmDouble mass_flux=0.; 2583 IssmDouble xyz_list[NUMVERTICES][3]; 2584 IssmDouble normal[2]; 2585 IssmDouble length,rho_ice; 2586 IssmDouble x1,y1,x2,y2,h1,h2; 2587 IssmDouble vx1,vx2,vy1,vy2; 2588 GaussTria* gauss_1=NULL; 2589 GaussTria* gauss_2=NULL; 2957 int normal_orientation=0; 2958 IssmDouble s1,s2; 2959 IssmDouble levelset[NUMVERTICES]; 2590 2960 2591 /*Get material parameters :*/ 2592 rho_ice=matpar->GetRhoIce(); 2961 /*Recover parameters and values*/ 2962 IssmDouble* xyz_zero = xNew<IssmDouble>(2*3); 2963 GetInputListOnVertices(&levelset[0],levelsetenum); 2593 2964 2594 /*First off, check that this segment belongs to this element: */ 2595 if (reCast<int>(*(segment+4))!=this->id)_error_("error message: segment with id " << reCast<int>(*(segment+4)) << " does not belong to element with id:" << this->id); 2965 if(levelset[0]*levelset[1]>0.){ //Nodes 0 and 1 are similar, so points must be found on segment 0-2 and 1-2 2966 /*Portion of the segments*/ 2967 s1=levelset[2]/(levelset[2]-levelset[1]); 2968 s2=levelset[2]/(levelset[2]-levelset[0]); 2596 2969 2597 /*Recover segment node locations: */ 2598 x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3); 2970 if(levelset[2]<0.) normal_orientation=1; //orientation of quadrangle depending on distribution of levelsetfunction 2971 /*New point 1*/ 2972 xyz_zero[3*normal_orientation+0]=xyz_list[2*3+0]+s1*(xyz_list[1*3+0]-xyz_list[2*3+0]); 2973 xyz_zero[3*normal_orientation+1]=xyz_list[2*3+1]+s1*(xyz_list[1*3+1]-xyz_list[2*3+1]); 2974 xyz_zero[3*normal_orientation+2]=xyz_list[2*3+2]+s1*(xyz_list[1*3+2]-xyz_list[2*3+2]); 2599 2975 2600 /*Get xyz list: */ 2601 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 2602 2603 /*get area coordinates of 0 and 1 locations: */ 2604 gauss_1=new GaussTria(); 2605 gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]); 2606 gauss_2=new GaussTria(); 2607 gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]); 2608 2609 normal[0]=cos(atan2(x1-x2,y2-y1)); 2610 normal[1]=sin(atan2(x1-x2,y2-y1)); 2611 2612 length=sqrt(pow(x2-x1,2)+pow(y2-y1,2)); 2613 2614 Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input); 2615 this->parameters->FindParam(&domaintype,DomainTypeEnum); 2616 Input* vx_input=NULL; 2617 Input* vy_input=NULL; 2618 if(domaintype==Domain2DhorizontalEnum){ 2619 vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 2620 vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 2976 /*New point 0*/ 2977 xyz_zero[3*(1-normal_orientation)+0]=xyz_list[2*3+0]+s2*(xyz_list[0*3+0]-xyz_list[2*3+0]); 2978 xyz_zero[3*(1-normal_orientation)+1]=xyz_list[2*3+1]+s2*(xyz_list[0*3+1]-xyz_list[2*3+1]); 2979 xyz_zero[3*(1-normal_orientation)+2]=xyz_list[2*3+2]+s2*(xyz_list[0*3+2]-xyz_list[2*3+2]); 2621 2980 } 2622 else {2623 vx_input=inputs->GetInput(VxAverageEnum); _assert_(vx_input);2624 vy_input=inputs->GetInput(VyAverageEnum); _assert_(vy_input);2625 }2981 else if(levelset[1]*levelset[2]>0.){ //Nodes 1 and 2 are similar, so points must be found on segment 0-1 and 0-2 2982 /*Portion of the segments*/ 2983 s1=levelset[0]/(levelset[0]-levelset[2]); 2984 s2=levelset[0]/(levelset[0]-levelset[1]); 2626 2985 2627 thickness_input->GetInputValue(&h1, gauss_1); 2628 thickness_input->GetInputValue(&h2, gauss_2); 2629 vx_input->GetInputValue(&vx1,gauss_1); 2630 vx_input->GetInputValue(&vx2,gauss_2); 2631 vy_input->GetInputValue(&vy1,gauss_1); 2632 vy_input->GetInputValue(&vy2,gauss_2); 2986 if(levelset[0]<0.) normal_orientation=1; 2987 /*New point 1*/ 2988 xyz_zero[3*normal_orientation+0]=xyz_list[0*3+0]+s1*(xyz_list[2*3+0]-xyz_list[0*3+0]); 2989 xyz_zero[3*normal_orientation+1]=xyz_list[0*3+1]+s1*(xyz_list[2*3+1]-xyz_list[0*3+1]); 2990 xyz_zero[3*normal_orientation+2]=xyz_list[0*3+2]+s1*(xyz_list[2*3+2]-xyz_list[0*3+2]); 2633 2991 2634 mass_flux= rho_ice*length*( 2635 (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+ 2636 (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1] 2637 ); 2638 2639 /*clean up and return:*/ 2640 delete gauss_1; 2641 delete gauss_2; 2642 return mass_flux; 2643 } 2644 /*}}}*/ 2645 void Tria::ElementResponse(IssmDouble* presponse,int response_enum){/*{{{*/ 2646 2647 switch(response_enum){ 2648 case MaterialsRheologyBbarEnum: 2649 *presponse=this->material->GetBbar(); 2650 break; 2651 2652 case VelEnum:{ 2653 2654 /*Get input:*/ 2655 IssmDouble vel; 2656 Input* vel_input; 2657 2658 vel_input=this->inputs->GetInput(VelEnum); _assert_(vel_input); 2659 vel_input->GetInputAverage(&vel); 2660 2661 /*Assign output pointers:*/ 2662 *presponse=vel;} 2663 break; 2664 default: 2665 _error_("Response type " << EnumToStringx(response_enum) << " not supported yet!"); 2992 /*New point 2*/ 2993 xyz_zero[3*(1-normal_orientation)+0]=xyz_list[0*3+0]+s2*(xyz_list[1*3+0]-xyz_list[0*3+0]); 2994 xyz_zero[3*(1-normal_orientation)+1]=xyz_list[0*3+1]+s2*(xyz_list[1*3+1]-xyz_list[0*3+1]); 2995 xyz_zero[3*(1-normal_orientation)+2]=xyz_list[0*3+2]+s2*(xyz_list[1*3+2]-xyz_list[0*3+2]); 2666 2996 } 2997 else if(levelset[0]*levelset[2]>0.){ //Nodes 0 and 2 are similar, so points must be found on segment 1-0 and 1-2 2998 /*Portion of the segments*/ 2999 s1=levelset[1]/(levelset[1]-levelset[0]); 3000 s2=levelset[1]/(levelset[1]-levelset[2]); 2667 3001 2668 } 2669 /*}}}*/ 2670 IssmDouble Tria::TotalSmb(void){/*{{{*/ 3002 if(levelset[1]<0.) normal_orientation=1; 3003 /*New point 0*/ 3004 xyz_zero[3*normal_orientation+0]=xyz_list[1*3+0]+s1*(xyz_list[0*3+0]-xyz_list[1*3+0]); 3005 xyz_zero[3*normal_orientation+1]=xyz_list[1*3+1]+s1*(xyz_list[0*3+1]-xyz_list[1*3+1]); 3006 xyz_zero[3*normal_orientation+2]=xyz_list[1*3+2]+s1*(xyz_list[0*3+2]-xyz_list[1*3+2]); 2671 3007 2672 /*The smb[kg yr-1] of one element is area[m2] * smb [kg m^-2 yr^-1]*/ 2673 IssmDouble base,smb,rho_ice; 2674 IssmDouble Total_Smb=0; 2675 IssmDouble xyz_list[NUMVERTICES][3]; 2676 2677 /*Get material parameters :*/ 2678 rho_ice=matpar->GetRhoIce(); 2679 2680 if(!IsIceInElement())return 0; 2681 2682 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 2683 2684 /*First calculate the area of the base (cross section triangle) 2685 * http://en.wikipedia.org/wiki/Triangle 2686 * base = 1/2 abs((xA-xC)(yB-yA)-(xA-xB)(yC-yA))*/ 2687 base = 1./2. * fabs((xyz_list[0][0]-xyz_list[2][0])*(xyz_list[1][1]-xyz_list[0][1]) - (xyz_list[0][0]-xyz_list[1][0])*(xyz_list[2][1]-xyz_list[0][1])); // area of element in m2 2688 2689 /*Now get the average SMB over the element*/ 2690 Input* smb_input = inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(smb_input); 2691 smb_input->GetInputAverage(&smb); // average smb on element in m ice s-1 2692 Total_Smb=rho_ice*base*smb; // smb on element in kg s-1 2693 2694 /*Return: */ 2695 return Total_Smb; 2696 } 2697 /*}}}*/ 2698 IssmDouble Tria::MisfitArea(int weightsenum){/*{{{*/ 2699 2700 /*Intermediaries*/ 2701 IssmDouble weight; 2702 IssmDouble Jdet; 2703 IssmDouble Jelem = 0; 2704 IssmDouble xyz_list[NUMVERTICES][3]; 2705 GaussTria *gauss = NULL; 2706 2707 /*If on water, return 0: */ 2708 if(!IsIceInElement())return 0; 2709 2710 /*Retrieve all inputs we will be needing: */ 2711 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 2712 Input* weights_input =inputs->GetInput(weightsenum); _assert_(weights_input); 2713 2714 /* Start looping on the number of gaussian points: */ 2715 gauss=new GaussTria(2); 2716 for(int ig=gauss->begin();ig<gauss->end();ig++){ 2717 2718 gauss->GaussPoint(ig); 2719 2720 /* Get Jacobian determinant: */ 2721 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 2722 2723 /*Get parameters at gauss point*/ 2724 weights_input->GetInputValue(&weight,gauss); 2725 2726 /*compute misfit between model and observation */ 2727 Jelem+=Jdet*weight*gauss->weight; 3008 /*New point 2*/ 3009 xyz_zero[3*(1-normal_orientation)+0]=xyz_list[1*3+0]+s2*(xyz_list[2*3+0]-xyz_list[1*3+0]); 3010 xyz_zero[3*(1-normal_orientation)+1]=xyz_list[1*3+1]+s2*(xyz_list[2*3+1]-xyz_list[1*3+1]); 3011 xyz_zero[3*(1-normal_orientation)+2]=xyz_list[1*3+2]+s2*(xyz_list[2*3+2]-xyz_list[1*3+2]); 2728 3012 } 3013 else if(levelset[0]==0. && levelset[1]==0.){ //front is on point 0 and 1 3014 xyz_zero[3*0+0]=xyz_list[0*3+0]; 3015 xyz_zero[3*0+1]=xyz_list[0*3+1]; 3016 xyz_zero[3*0+2]=xyz_list[0*3+2]; 2729 3017 2730 /* clean up and Return: */ 2731 delete gauss; 2732 return Jelem; 2733 } 2734 /*}}}*/ 2735 IssmDouble Tria::Misfit(int modelenum,int observationenum,int weightsenum){/*{{{*/ 2736 2737 /*Intermediaries*/ 2738 IssmDouble model,observation,weight; 2739 IssmDouble Jdet; 2740 IssmDouble Jelem = 0; 2741 IssmDouble xyz_list[NUMVERTICES][3]; 2742 GaussTria *gauss = NULL; 2743 2744 /*If on water, return 0: */ 2745 if(!IsIceInElement())return 0; 2746 2747 /*Retrieve all inputs we will be needing: */ 2748 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 2749 Input* model_input=inputs->GetInput(modelenum); _assert_(model_input); 2750 Input* observation_input=inputs->GetInput(observationenum);_assert_(observation_input); 2751 Input* weights_input =inputs->GetInput(weightsenum); _assert_(weights_input); 2752 2753 /* Start looping on the number of gaussian points: */ 2754 gauss=new GaussTria(2); 2755 for(int ig=gauss->begin();ig<gauss->end();ig++){ 2756 2757 gauss->GaussPoint(ig); 2758 2759 /* Get Jacobian determinant: */ 2760 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 2761 2762 /*Get parameters at gauss point*/ 2763 model_input->GetInputValue(&model,gauss); 2764 observation_input->GetInputValue(&observation,gauss); 2765 weights_input->GetInputValue(&weight,gauss); 2766 2767 /*compute misfit between model and observation */ 2768 Jelem+=0.5*(model-observation)*(model-observation)*Jdet*weight*gauss->weight; 3018 /*New point 2*/ 3019 xyz_zero[3*1+0]=xyz_list[1*3+0]; 3020 xyz_zero[3*1+1]=xyz_list[1*3+1]; 3021 xyz_zero[3*1+2]=xyz_list[1*3+2]; 2769 3022 } 3023 else if(levelset[0]==0. && levelset[2]==0.){ //front is on point 0 and 1 3024 xyz_zero[3*0+0]=xyz_list[2*3+0]; 3025 xyz_zero[3*0+1]=xyz_list[2*3+1]; 3026 xyz_zero[3*0+2]=xyz_list[2*3+2]; 2770 3027 2771 /* clean up and Return: */ 2772 delete gauss; 2773 return Jelem; 2774 } 2775 /*}}}*/ 2776 IssmDouble Tria::Masscon(IssmDouble* levelset){ /*{{{*/ 2777 2778 2779 /*intermediary: */ 2780 IssmDouble* values=NULL; 2781 Input* thickness_input=NULL; 2782 IssmDouble thickness; 2783 IssmDouble weight; 2784 IssmDouble Jdet; 2785 IssmDouble volume; 2786 IssmDouble rho_ice; 2787 IssmDouble* xyz_list=NULL; 2788 int point1; 2789 IssmDouble fraction1,fraction2; 2790 bool mainlynegative=true; 2791 2792 /*Output:*/ 2793 volume=0; 2794 2795 /* Get node coordinates and dof list: */ 2796 GetVerticesCoordinates(&xyz_list); 2797 2798 /*Retrieve inputs required:*/ 2799 thickness_input=this->GetInput(ThicknessEnum); _assert_(thickness_input); 2800 2801 /*Retrieve material parameters: */ 2802 rho_ice=matpar->GetRhoIce(); 2803 2804 /*Retrieve values of the levelset defining the masscon: */ 2805 values = xNew<IssmDouble>(NUMVERTICES); 2806 for(int i=0;i<NUMVERTICES;i++){ 2807 values[i]=levelset[this->vertices[i]->Sid()]; 3028 /*New point 2*/ 3029 xyz_zero[3*1+0]=xyz_list[0*3+0]; 3030 xyz_zero[3*1+1]=xyz_list[0*3+1]; 3031 xyz_zero[3*1+2]=xyz_list[0*3+2]; 2808 3032 } 2809 2810 /*Ok, use the level set values to figure out where we put our gaussian points:*/2811 this->GetLevelsetPositivePart(&point1,&fraction1,&fraction2,&mainlynegative,values);2812 Gauss* gauss = this->NewGauss(point1,fraction1,fraction2,mainlynegative,4);3033 else if(levelset[1]==0. && levelset[2]==0.){ //front is on point 0 and 1 3034 xyz_zero[3*0+0]=xyz_list[1*3+0]; 3035 xyz_zero[3*0+1]=xyz_list[1*3+1]; 3036 xyz_zero[3*0+2]=xyz_list[1*3+2]; 2813 3037 2814 volume=0; 2815 2816 for(int ig=gauss->begin();ig<gauss->end();ig++){ 2817 gauss->GaussPoint(ig); 2818 2819 this->JacobianDeterminant(&Jdet,xyz_list,gauss); 2820 thickness_input->GetInputValue(&thickness, gauss); 2821 2822 volume+=thickness*gauss->weight*Jdet; 3038 /*New point 2*/ 3039 xyz_zero[3*1+0]=xyz_list[2*3+0]; 3040 xyz_zero[3*1+1]=xyz_list[2*3+1]; 3041 xyz_zero[3*1+2]=xyz_list[2*3+2]; 2823 3042 } 3043 else _error_("Case not covered"); 2824 3044 2825 /* clean up and Return: */ 2826 xDelete<IssmDouble>(xyz_list); 2827 xDelete<IssmDouble>(values); 2828 delete gauss; 2829 return rho_ice*volume; 3045 /*Assign output pointer*/ 3046 *pxyz_zero= xyz_zero; 2830 3047 } 2831 3048 /*}}}*/ 2832 3049 … … 2958 3175 /*}}}*/ 2959 3176 #endif 2960 3177 2961 void Tria::InputControlUpdate(IssmDouble scalar,bool save_parameter){/*{{{*/ 3178 #ifdef _HAVE_DAKOTA_ 3179 void Tria::InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){/*{{{*/ 2962 3180 2963 /*Intermediary*/2964 int num_controls;2965 int* control_type=NULL;2966 I nput* input=NULL;3181 int i,t,row; 3182 IssmDouble time; 3183 TransientInput *transientinput = NULL; 3184 IssmDouble values[3]; 2967 3185 2968 /*retrieve some parameters: */ 2969 this->parameters->FindParam(&num_controls,InversionNumControlParametersEnum); 2970 this->parameters->FindParam(&control_type,NULL,InversionControlParametersEnum); 3186 /*Check that name is an element input*/ 3187 if (!IsInput(name)) return; 2971 3188 2972 for(int i=0;i<num_controls;i++){ 2973 input=(Input*)this->inputs->GetInput(control_type[i]); _assert_(input); 2974 if (input->ObjectEnum()!=ControlInputEnum){ 2975 _error_("input " << EnumToStringx(control_type[i]) << " is not a ControlInput"); 2976 } 3189 switch(type){ 2977 3190 2978 ((ControlInput*)input)->UpdateValue(scalar);2979 ((ControlInput*)input)->Constrain();2980 if (save_parameter) ((ControlInput*)input)->SaveValue();3191 case VertexEnum: 3192 /*Create transient input: */ 3193 for(t=0;t<ncols;t++){ //ncols is the number of times 2981 3194 2982 } 3195 /*create input values: */ 3196 for(i=0;i<3;i++){ 3197 row=this->vertices[i]->Sid(); 3198 values[i]=matrix[ncols*row+t]; 3199 } 2983 3200 2984 /*Clean up and return*/ 2985 xDelete<int>(control_type); 2986 } 2987 /*}}}*/ 2988 void Tria::ControlInputSetGradient(IssmDouble* gradient,int enum_type,int control_index){/*{{{*/ 3201 /*time:*/ 3202 time=matrix[(nrows-1)*ncols+t]; 2989 3203 2990 int vertexpidlist[NUMVERTICES]; 2991 IssmDouble grad_list[NUMVERTICES]; 2992 Input* grad_input=NULL; 3204 if(t==0) transientinput=new TransientInput(name); 3205 transientinput->AddTimeInput(new TriaInput(name,values,P1Enum),time); 3206 transientinput->Configure(parameters); 3207 } 3208 this->inputs->AddInput(transientinput); 3209 break; 2993 3210 2994 Input* input=inputs->GetInput(enum_type); 2995 if (!input) _error_("Input " << EnumToStringx(enum_type) << " not found"); 2996 if (input->ObjectEnum()!=ControlInputEnum) _error_("Input " << EnumToStringx(enum_type) << " is not a ControlInput"); 2997 2998 GradientIndexing(&vertexpidlist[0],control_index); 2999 for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[vertexpidlist[i]]; 3000 grad_input=new TriaInput(GradientEnum,grad_list,P1Enum); 3001 3002 ((ControlInput*)input)->SetGradient(grad_input); 3003 3004 }/*}}}*/ 3005 void Tria::ControlToVectors(Vector<IssmPDouble>* vector_control, Vector<IssmPDouble>* vector_gradient,int control_enum){/*{{{*/ 3006 3007 Input* input=inputs->GetInput(control_enum); 3008 if (!input) _error_("Input " << EnumToStringx(control_enum) << " not found"); 3009 if (input->ObjectEnum()!=ControlInputEnum) _error_("Input " << EnumToStringx(control_enum) << " is not a ControlInput"); 3010 3011 int sidlist[NUMVERTICES]; 3012 int connectivity[NUMVERTICES]; 3013 IssmPDouble values[NUMVERTICES]; 3014 IssmPDouble gradients[NUMVERTICES]; 3015 IssmDouble value,gradient; 3016 3017 this->GetVerticesConnectivityList(&connectivity[0]); 3018 this->GetVerticesSidList(&sidlist[0]); 3019 3020 GaussTria* gauss=new GaussTria(); 3021 for (int iv=0;iv<NUMVERTICES;iv++){ 3022 gauss->GaussVertex(iv); 3023 3024 ((ControlInput*)input)->GetInputValue(&value,gauss); 3025 ((ControlInput*)input)->GetGradientValue(&gradient,gauss); 3026 3027 values[iv] = reCast<IssmPDouble>(value)/reCast<IssmPDouble>(connectivity[iv]); 3028 gradients[iv] = reCast<IssmPDouble>(gradient)/reCast<IssmPDouble>(connectivity[iv]); 3211 default: 3212 _error_("type " << type << " (" << EnumToStringx(type) << ") not implemented yet"); 3029 3213 } 3030 delete gauss;3031 3214 3032 vector_control->SetValues(NUMVERTICES,&sidlist[0],&values[0],ADD_VAL);3033 vector_gradient->SetValues(NUMVERTICES,&sidlist[0],&gradients[0],ADD_VAL);3034 3035 }/*}}}*/3036 void Tria::GetVectorFromControlInputs(Vector<IssmDouble>* vector,int control_enum,int control_index,const char* data,bool onsid){/*{{{*/3037 3038 int vertexidlist[NUMVERTICES];3039 Input *input=NULL;3040 3041 /*Get out if this is not an element input*/3042 if(!IsInput(control_enum)) return;3043 3044 /*Prepare index list*/3045 GradientIndexing(&vertexidlist[0],control_index,onsid);3046 3047 /*Get input (either in element or material)*/3048 input=(Input*)this->inputs->GetInput(control_enum); _assert_(input);3049 3050 /*Check that it is a ControlInput*/3051 if (input->ObjectEnum()!=ControlInputEnum){3052 _error_("input " << EnumToStringx(control_enum) << " is not a ControlInput");3053 }3054 3055 ((ControlInput*)input)->GetVectorFromInputs(vector,&vertexidlist[0],data);3056 3215 } 3057 3216 /*}}}*/ 3058 void Tria::SetControlInputsFromVector(IssmDouble* vector,int control_enum,int control_index){/*{{{*/3059 3060 IssmDouble values[NUMVERTICES];3061 int vertexpidlist[NUMVERTICES],control_init;3062 3063 3064 /*Get Domain type*/3065 int domaintype;3066 parameters->FindParam(&domaintype,DomainTypeEnum);3067 3068 /*Specific case for depth averaged quantities*/3069 control_init=control_enum;3070 if(domaintype==Domain2DverticalEnum){3071 if(control_enum==MaterialsRheologyBbarEnum){3072 control_enum=MaterialsRheologyBEnum;3073 if(!IsOnBase()) return;3074 }3075 if(control_enum==DamageDbarEnum){3076 control_enum=DamageDEnum;3077 if(!IsOnBase()) return;3078 }3079 }3080 3081 /*Get out if this is not an element input*/3082 if(!IsInput(control_enum)) return;3083 3084 /*Prepare index list*/3085 GradientIndexing(&vertexpidlist[0],control_index);3086 3087 /*Get values on vertices*/3088 for(int i=0;i<NUMVERTICES;i++){3089 values[i]=vector[vertexpidlist[i]];3090 }3091 Input* new_input = new TriaInput(control_enum,values,P1Enum);3092 Input* input = (Input*)this->inputs->GetInput(control_enum); _assert_(input);3093 if(input->ObjectEnum()!=ControlInputEnum){3094 _error_("input " << EnumToStringx(control_enum) << " is not a ControlInput");3095 }3096 3097 ((ControlInput*)input)->SetInput(new_input);3098 }3099 /*}}}*/3100 void Tria::GetSolutionFromInputsOneDof(Vector<IssmDouble>* solution, int enum_type){/*{{{*/3101 3102 int *doflist = NULL;3103 IssmDouble value;3104 3105 /*Fetch number of nodes for this finite element*/3106 int numnodes = this->NumberofNodes(this->element_type);3107 3108 /*Fetch dof list and allocate solution vector*/3109 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);3110 IssmDouble* values = xNew<IssmDouble>(numnodes);3111 3112 /*Get inputs*/3113 Input* enum_input=inputs->GetInput(enum_type); _assert_(enum_input);3114 3115 /*Ok, we have the values, fill in the array: */3116 GaussTria* gauss=new GaussTria();3117 for(int i=0;i<numnodes;i++){3118 gauss->GaussNode(this->element_type,i);3119 3120 enum_input->GetInputValue(&value,gauss);3121 values[i]=value;3122 }3123 3124 solution->SetValues(numnodes,doflist,values,INS_VAL);3125 3126 /*Free ressources:*/3127 xDelete<int>(doflist);3128 xDelete<IssmDouble>(values);3129 delete gauss;3130 }3131 /*}}}*/3132 3133 #ifdef _HAVE_DAKOTA_3134 3217 void Tria::InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){/*{{{*/ 3135 3218 3136 3219 int i,j; … … 3222 3305 3223 3306 } 3224 3307 /*}}}*/ 3225 void Tria::InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){/*{{{*/3226 3227 int i,t,row;3228 IssmDouble time;3229 TransientInput *transientinput = NULL;3230 IssmDouble values[3];3231 3232 /*Check that name is an element input*/3233 if (!IsInput(name)) return;3234 3235 switch(type){3236 3237 case VertexEnum:3238 /*Create transient input: */3239 for(t=0;t<ncols;t++){ //ncols is the number of times3240 3241 /*create input values: */3242 for(i=0;i<3;i++){3243 row=this->vertices[i]->Sid();3244 values[i]=matrix[ncols*row+t];3245 }3246 3247 /*time:*/3248 time=matrix[(nrows-1)*ncols+t];3249 3250 if(t==0) transientinput=new TransientInput(name);3251 transientinput->AddTimeInput(new TriaInput(name,values,P1Enum),time);3252 transientinput->Configure(parameters);3253 }3254 this->inputs->AddInput(transientinput);3255 break;3256 3257 default:3258 _error_("type " << type << " (" << EnumToStringx(type) << ") not implemented yet");3259 }3260 3261 }3262 /*}}}*/3263 3308 #endif 3264 3265 void Tria::PotentialUngrounding(Vector<IssmDouble>* potential_ungrounding){/*{{{*/3266 3267 IssmDouble h[NUMVERTICES],r[NUMVERTICES],gl[NUMVERTICES];3268 IssmDouble bed_hydro;3269 IssmDouble rho_water,rho_ice,density;3270 3271 /*material parameters: */3272 rho_water=matpar->GetRhoWater();3273 rho_ice=matpar->GetRhoIce();3274 density=rho_ice/rho_water;3275 GetInputListOnVertices(&h[0],ThicknessEnum);3276 GetInputListOnVertices(&r[0],BedEnum);3277 GetInputListOnVertices(&gl[0],MaskGroundediceLevelsetEnum);3278 3279 /*go through vertices, and figure out which ones are grounded and want to unground: */3280 for(int i=0;i<NUMVERTICES;i++){3281 /*Find if grounded vertices want to start floating*/3282 if (gl[i]>0.){3283 bed_hydro=-density*h[i];3284 if(bed_hydro>r[i]){3285 /*Vertex that could potentially unground, flag it*/3286 potential_ungrounding->SetValue(vertices[i]->Pid(),1,INS_VAL);3287 }3288 }3289 }3290 }3291 /*}}}*/3292 int Tria::UpdatePotentialUngrounding(IssmDouble* vertices_potentially_ungrounding,Vector<IssmDouble>* vec_nodes_on_iceshelf,IssmDouble* nodes_on_iceshelf){/*{{{*/3293 3294 int i;3295 int nflipped=0;3296 3297 /*Go through nodes, and whoever is on the potential_ungrounding, ends up in nodes_on_iceshelf: */3298 for(i=0;i<3;i++){3299 if (reCast<bool>(vertices_potentially_ungrounding[vertices[i]->Pid()])){3300 vec_nodes_on_iceshelf->SetValue(vertices[i]->Pid(),-1.,INS_VAL);3301 3302 /*If node was not on ice shelf, we flipped*/3303 if(nodes_on_iceshelf[vertices[i]->Pid()]>=0.){3304 nflipped++;3305 }3306 }3307 }3308 return nflipped;3309 }3310 /*}}}*/ -
../trunk-jpl/src/c/classes/Elements/Tria.h
41 41 Object *copy(); 42 42 /*}}}*/ 43 43 /*Update virtual functions resolution: {{{*/ 44 void InputUpdateFromVector(IssmDouble* vector, int name, int type);45 44 #ifdef _HAVE_DAKOTA_ 45 void InputUpdateFromMatrixDakota(IssmDouble* matrix, int nows, int ncols, int name, int type); 46 46 void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type); 47 void InputUpdateFromMatrixDakota(IssmDouble* matrix, int nows, int ncols, int name, int type);48 47 #endif 49 48 void InputUpdateFromIoModel(int index, IoModel* iomodel); 49 void InputUpdateFromVector(IssmDouble* vector, int name, int type); 50 50 /*}}}*/ 51 51 /*Element virtual functions definitions: {{{*/ 52 void AverageOntoPartition(Vector<IssmDouble>* partition_contributions,Vector<IssmDouble>* partition_areas,IssmDouble* vertex_response,IssmDouble* qmu_part); 53 void CalvingRateLevermann(); 52 54 IssmDouble CharacteristicLength(void); 53 55 void ComputeBasalStress(Vector<IssmDouble>* sigma_b); 56 void ComputeDeviatoricStressTensor(); 54 57 void ComputeSigmaNN(); 55 58 void ComputeStressTensor(); 56 void ComputeDeviatoricStressTensor();57 void StrainRateparallel();58 void StrainRateperpendicular();59 59 void ComputeSurfaceNormalVelocity(); 60 void StressIntensityFactor(void){_error_("not implemented yet");};61 void CalvingRateLevermann();62 60 void Configure(Elements* elements,Loads* loads,Nodes* nodesin,Vertices* verticesin,Materials* materials,Parameters* parameters); 63 void SetCurrentConfiguration(Elements* elements,Loads* loads,Nodes* nodes,Materials* materials,Parameters* parameters);64 void ResetHooks();61 void ControlInputSetGradient(IssmDouble* gradient,int enum_type,int control_index); 62 void ControlToVectors(Vector<IssmPDouble>* vector_control, Vector<IssmPDouble>* vector_gradient,int control_enum); 65 63 void Delta18oParameterization(void); 64 int EdgeOnBaseIndex(); 65 void EdgeOnBaseIndices(int* pindex1,int* pindex); 66 int EdgeOnSurfaceIndex(); 67 void EdgeOnSurfaceIndices(int* pindex1,int* pindex); 68 void ElementResponse(IssmDouble* presponse,int response_enum); 66 69 void ElementSizes(IssmDouble* hx,IssmDouble* hy,IssmDouble* hz); 70 int FiniteElement(void); 67 71 void FSContactMigration(Vector<IssmDouble>* vertexgrounded,Vector<IssmDouble>* vertexfloating); 68 int FiniteElement(void);69 Element* GetUpperElement(void){_error_("not implemented yet");};70 72 Element* GetBasalElement(void){_error_("not implemented yet");}; 71 73 void GetLevelsetPositivePart(int* point1,IssmDouble* fraction1,IssmDouble* fraction2, bool* mainlynegative,IssmDouble* levelsetvalues); 72 74 void GetGroundedPart(int* point1,IssmDouble* fraction1, IssmDouble* fraction2,bool* mainlyfloating); 73 75 IssmDouble GetGroundedPortion(IssmDouble* xyz_list); 76 void GetIcefrontCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum); 77 void GetLevelCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum,IssmDouble level); 74 78 int GetNodeIndex(Node* node); 75 79 int GetNumberOfNodes(void); 76 80 int GetNumberOfNodes(int enum_type); 77 81 int GetNumberOfVertices(void); 78 bool IsOnBase();79 bool IsOnSurface();80 bool HasEdgeOnBase();81 bool HasEdgeOnSurface();82 void EdgeOnSurfaceIndices(int* pindex1,int* pindex);83 void EdgeOnBaseIndices(int* pindex1,int* pindex);84 int EdgeOnBaseIndex();85 int EdgeOnSurfaceIndex();86 bool IsNodeOnShelfFromFlags(IssmDouble* flags);87 int NumberofNodesVelocity(void);88 int NumberofNodesPressure(void);89 82 void GetSolutionFromInputsOneDof(Vector<IssmDouble>* solution,int enum_type); 83 Element* GetUpperElement(void){_error_("not implemented yet");}; 84 void GetVectorFromControlInputs(Vector<IssmDouble>* gradient,int control_enum,int control_index,const char* data,bool onsid); 90 85 void GetVerticesCoordinatesBase(IssmDouble** pxyz_list); 91 86 void GetVerticesCoordinatesTop(IssmDouble** pxyz_list); 87 bool HasEdgeOnBase(); 88 bool HasEdgeOnSurface(); 89 IssmDouble IceVolume(void); 90 IssmDouble IceVolumeAboveFloatation(void); 91 void InputControlUpdate(IssmDouble scalar,bool save_parameter); 92 92 void InputDepthAverageAtBase(int enum_type,int average_enum_type); 93 93 void InputExtrude(int enum_type,int start){_error_("not implemented"); /*For penta only*/}; 94 94 void InputScale(int enum_type,IssmDouble scale_factor); 95 bool IsFaceOnBoundary(void); 96 bool IsIcefront(void); 97 bool IsNodeOnShelfFromFlags(IssmDouble* flags); 98 bool IsOnBase(); 99 bool IsOnSurface(); 100 bool IsZeroLevelset(int levelset_enum); 101 IssmDouble Masscon(IssmDouble* levelset); 102 IssmDouble MassFlux(IssmDouble* segment); 103 IssmDouble MassFlux(IssmDouble x1,IssmDouble y1, IssmDouble x2, IssmDouble y2,int segment_id); 95 104 void MaterialUpdateFromTemperature(void){_error_("not implemented yet");}; 105 IssmDouble Misfit(int modelenum,int observationenum,int weightsenum); 106 IssmDouble MisfitArea(int weightsenum); 96 107 int NodalValue(IssmDouble* pvalue, int index, int natureofdataenum); 108 int NumberofNodesPressure(void); 109 int NumberofNodesVelocity(void); 97 110 void PositiveDegreeDay(IssmDouble* pdds,IssmDouble* pds,IssmDouble signorm); 111 void PotentialUngrounding(Vector<IssmDouble>* potential_sheet_ungrounding); 112 int PressureInterpolation(); 98 113 void ReduceMatrices(ElementMatrix* Ke,ElementVector* pe); 99 114 void ResetFSBasalBoundaryCondition(void); 115 void ResetHooks(); 116 void SetControlInputsFromVector(IssmDouble* vector,int control_enum,int control_index); 117 void SetCurrentConfiguration(Elements* elements,Loads* loads,Nodes* nodes,Materials* materials,Parameters* parameters); 100 118 Element* SpawnBasalElement(void); 101 119 Element* SpawnTopElement(void); 102 int VelocityInterpolation(); 103 int PressureInterpolation(); 120 void StrainRateparallel(); 121 void StrainRateperpendicular(); 122 void StressIntensityFactor(void){_error_("not implemented yet");}; 123 IssmDouble SurfaceArea(void); 104 124 int TensorInterpolation(); 105 IssmDouble SurfaceArea(void); 125 IssmDouble TimeAdapt(); 126 IssmDouble TotalSmb(void); 106 127 void Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type,int finitelement); 107 IssmDouble TimeAdapt(); 128 int UpdatePotentialUngrounding(IssmDouble* vertices_potentially_ungrounding,Vector<IssmDouble>* vec_nodes_on_iceshelf,IssmDouble* nodes_on_iceshelf); 129 void ValueP1DerivativesOnGauss(IssmDouble* dvalue,IssmDouble* values,IssmDouble* xyz_list,Gauss* gauss); 108 130 void ValueP1OnGauss(IssmDouble* pvalue,IssmDouble* values,Gauss* gauss); 109 void ValueP1DerivativesOnGauss(IssmDouble* dvalue,IssmDouble* values,IssmDouble* xyz_list,Gauss* gauss);131 int VelocityInterpolation(); 110 132 int VertexConnectivity(int vertexindex); 111 133 void VerticalSegmentIndices(int** pindices,int* pnumseg){_error_("not implemented yet");}; 112 134 void ZeroLevelsetCoordinates(IssmDouble** pxyz_zero,IssmDouble* xyz_list,int levelsetenum); 113 void GetIcefrontCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum);114 void GetLevelCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum,IssmDouble level);115 bool IsZeroLevelset(int levelset_enum);116 bool IsIcefront(void);117 bool IsFaceOnBoundary(void);118 135 119 void AverageOntoPartition(Vector<IssmDouble>* partition_contributions,Vector<IssmDouble>* partition_areas,IssmDouble* vertex_response,IssmDouble* qmu_part);120 IssmDouble IceVolume(void);121 IssmDouble IceVolumeAboveFloatation(void);122 IssmDouble TotalSmb(void);123 IssmDouble MassFlux(IssmDouble* segment);124 IssmDouble MassFlux(IssmDouble x1,IssmDouble y1, IssmDouble x2, IssmDouble y2,int segment_id);125 void ElementResponse(IssmDouble* presponse,int response_enum);126 IssmDouble Masscon(IssmDouble* levelset);127 IssmDouble Misfit(int modelenum,int observationenum,int weightsenum);128 IssmDouble MisfitArea(int weightsenum);129 130 136 #ifdef _HAVE_GIA_ 131 137 void GiaDeflection(Vector<IssmDouble>* wg,Vector<IssmDouble>* dwgdt,IssmDouble* x,IssmDouble* y); 132 138 #endif 133 134 void GetVectorFromControlInputs(Vector<IssmDouble>* gradient,int control_enum,int control_index,const char* data,bool onsid);135 void SetControlInputsFromVector(IssmDouble* vector,int control_enum,int control_index);136 void ControlInputSetGradient(IssmDouble* gradient,int enum_type,int control_index);137 void ControlToVectors(Vector<IssmPDouble>* vector_control, Vector<IssmPDouble>* vector_gradient,int control_enum);138 void InputControlUpdate(IssmDouble scalar,bool save_parameter);139 140 void PotentialUngrounding(Vector<IssmDouble>* potential_sheet_ungrounding);141 int UpdatePotentialUngrounding(IssmDouble* vertices_potentially_ungrounding,Vector<IssmDouble>* vec_nodes_on_iceshelf,IssmDouble* nodes_on_iceshelf);142 143 139 /*}}}*/ 144 140 /*Tria specific routines:{{{*/ 145 141 void AddBasalInput(int input_enum, IssmDouble* values, int interpolation_enum); … … 147 143 IssmDouble GetArea(void); 148 144 void GetAreaCoordinates(IssmDouble *area_coordinates,IssmDouble* xyz_zero,IssmDouble* xyz_list,int numpoints); 149 145 int GetElementType(void); 150 void NormalSection(IssmDouble* normal,IssmDouble* xyz_list);151 void NormalTop(IssmDouble* normal,IssmDouble* xyz_list);152 void NormalBase(IssmDouble* normal,IssmDouble* xyz_list);153 146 void GetInputValue(IssmDouble* pvalue,Node* node,int enumtype); 154 147 void GetMaterialInputValue(IssmDouble* pvalue,Node* node,int enumtype); 155 148 Node* GetNode(int node_number); 156 149 void InputUpdateFromSolutionOneDof(IssmDouble* solution,int enum_type); 157 150 void InputUpdateFromSolutionOneDofCollapsed(IssmDouble* solution,int enum_type){_error_("not implemented yet");}; 158 151 void JacobianDeterminant(IssmDouble* pJdet, IssmDouble* xyz_list,Gauss* gauss); 152 void JacobianDeterminantBase(IssmDouble* pJdet,IssmDouble* xyz_list_base,Gauss* gauss); 159 153 void JacobianDeterminantLine(IssmDouble* Jdet, IssmDouble* xyz_list,Gauss* gauss){_error_("not implemented yet");}; 160 154 void JacobianDeterminantSurface(IssmDouble* pJdet, IssmDouble* xyz_list,Gauss* gauss); 161 void JacobianDeterminantBase(IssmDouble* pJdet,IssmDouble* xyz_list_base,Gauss* gauss);162 155 void JacobianDeterminantTop(IssmDouble* pJdet,IssmDouble* xyz_list_base,Gauss* gauss); 163 156 IssmDouble MinEdgeLength(IssmDouble* xyz_list){_error_("not implemented yet");}; 164 157 Gauss* NewGauss(void); … … 170 163 Gauss* NewGaussLine(int vertex1,int vertex2,int order){_error_("not implemented yet");}; 171 164 Gauss* NewGaussTop(int order); 172 165 void NodalFunctions(IssmDouble* basis,Gauss* gauss); 173 void NodalFunctionsP1(IssmDouble* basis,Gauss* gauss);174 void NodalFunctionsP2(IssmDouble* basis,Gauss* gauss);175 166 void NodalFunctionsDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss); 176 void NodalFunctions P1Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);167 void NodalFunctionsDerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss); 177 168 void NodalFunctionsMINIDerivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss){_error_("not implemented yet");}; 178 void NodalFunctionsDerivativesVelocity(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss);179 void NodalFunctionsVelocity(IssmDouble* basis,Gauss* gauss);180 169 void NodalFunctionsPressure(IssmDouble* basis,Gauss* gauss); 170 void NodalFunctionsP1(IssmDouble* basis,Gauss* gauss); 171 void NodalFunctionsP1Derivatives(IssmDouble* dbasis,IssmDouble* xyz_list,Gauss* gauss); 172 void NodalFunctionsP2(IssmDouble* basis,Gauss* gauss); 181 173 void NodalFunctionsTensor(IssmDouble* basis,Gauss* gauss); 174 void NodalFunctionsVelocity(IssmDouble* basis,Gauss* gauss); 175 void NormalBase(IssmDouble* normal,IssmDouble* xyz_list); 176 void NormalSection(IssmDouble* normal,IssmDouble* xyz_list); 177 void NormalTop(IssmDouble* normal,IssmDouble* xyz_list); 182 178 void SetClone(int* minranks); 183 179 void SetTemporaryElementType(int element_type_in){_error_("not implemented yet");}; 184 180 Seg* SpawnSeg(int index1,int index2); 185 181 IssmDouble StabilizationParameter(IssmDouble u, IssmDouble v, IssmDouble w, IssmDouble diameter, IssmDouble kappa){_error_("not implemented yet");}; 182 void UpdateConstraintsExtrudeFromBase(void); 183 void UpdateConstraintsExtrudeFromTop(void); 186 184 void ViscousHeating(IssmDouble* pphi,IssmDouble* xyz_list,Gauss* gauss,Input* vx_input,Input* vy_input,Input* vz_input){_error_("not implemented yet");}; 187 188 void UpdateConstraintsExtrudeFromBase(void);189 void UpdateConstraintsExtrudeFromTop(void);190 185 /*}}}*/ 191 186 192 187 };
Note:
See TracBrowser
for help on using the repository browser.