Changeset 24313 for issm/trunk/src/c/analyses/MasstransportAnalysis.cpp
- Timestamp:
- 11/01/19 12:01:57 (5 years ago)
- Location:
- issm/trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk
-
issm/trunk/src
- Property svn:mergeinfo changed
-
issm/trunk/src/c
- Property svn:ignore
-
issm/trunk/src/c/analyses/MasstransportAnalysis.cpp
r23394 r24313 5 5 #include "../modules/modules.h" 6 6 7 #define FINITEELEMENT P1Enum 8 7 9 /*Model processing*/ 8 10 void MasstransportAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ … … 14 16 /*Do not add constraints in DG, they are weakly imposed*/ 15 17 if(stabilization!=3){ 16 IoModelToConstraintsx(constraints,iomodel,"md.masstransport.spcthickness",MasstransportAnalysisEnum, P1Enum);18 IoModelToConstraintsx(constraints,iomodel,"md.masstransport.spcthickness",MasstransportAnalysisEnum,FINITEELEMENT); 17 19 } 18 20 … … 25 27 26 28 /*Intermediaries*/ 27 int element;28 29 int penpair_ids[2]; 29 30 int count=0; … … 35 36 36 37 /*Loads only in DG*/ 37 if 38 if(stabilization==3){ 38 39 39 40 /*Get faces and elements*/ … … 45 46 46 47 /*Get left and right elements*/ 47 element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]48 int element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2] 48 49 49 50 /*Now, if this element is not in the partition, pass: */ 50 51 if(!iomodel->my_elements[element]) continue; 51 52 /* Add load */ 53 loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,MasstransportAnalysisEnum)); 52 loads->AddObject(new Numericalflux(i+1,i,i,iomodel)); 54 53 } 55 54 … … 77 76 78 77 /*Get node ids*/ 79 penpair_ids[0]= iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+0]);80 penpair_ids[1]= iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+1]);78 penpair_ids[0]=reCast<int>(vertex_pairing[2*i+0]); 79 penpair_ids[1]=reCast<int>(vertex_pairing[2*i+1]); 81 80 82 81 /*Create Load*/ 83 loads->AddObject(new Penpair( 84 iomodel->loadcounter+count+1, 85 &penpair_ids[0], 86 MasstransportAnalysisEnum)); 82 loads->AddObject(new Penpair(count+1,&penpair_ids[0])); 87 83 count++; 88 84 } … … 92 88 iomodel->DeleteData(vertex_pairing,"md.masstransport.vertex_pairing"); 93 89 iomodel->DeleteData(nodeonbase,"md.mesh.vertexonbase"); 94 95 }/*}}}*/ 96 void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 90 }/*}}}*/ 91 void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel,bool isamr){/*{{{*/ 97 92 98 93 /*Fetch parameters: */ … … 106 101 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,"md.mesh.vertexonbase","md.mesh.vertexonsurface"); 107 102 if(stabilization!=3){ 108 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum, P1Enum);103 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,FINITEELEMENT,isamr); 109 104 } 110 105 else{ 111 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum );106 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum,isamr); 112 107 } 113 108 iomodel->DeleteData(2,"md.mesh.vertexonbase","md.mesh.vertexonsurface"); … … 134 129 135 130 /*Finite element type*/ 136 finiteelement = P1Enum;131 finiteelement = FINITEELEMENT; 137 132 if(stabilization==3){ 138 133 finiteelement = P1DGEnum; 134 //finiteelement = P0DGEnum; 139 135 } 140 136 … … 158 154 iomodel->FetchDataToInput(elements,"md.initialization.vx",VxEnum); 159 155 iomodel->FetchDataToInput(elements,"md.initialization.vy",VyEnum); 160 156 if(isgroundingline) iomodel->FetchDataToInput(elements,"md.geometry.bed",BedEnum); 161 157 /*Initialize cumdeltalthickness input*/ 162 158 InputUpdateFromConstantx(elements,0.,SealevelriseCumDeltathicknessEnum); 159 /*Initialize ThicknessResidual input*/ 160 InputUpdateFromConstantx(elements,0.,ThicknessResidualEnum); 163 161 164 162 /*Get what we need for ocean-induced basal melting*/ … … 183 181 iomodel->FetchDataToInput(elements,"md.basalforcings.basin_id",BasalforcingsPicoBasinIdEnum); 184 182 break; 183 case BasalforcingsIsmip6Enum:{ 184 iomodel->FetchDataToInput(elements,"md.basalforcings.basin_id",BasalforcingsIsmip6BasinIdEnum); 185 iomodel->FetchDataToInput(elements,"md.basalforcings.melt_anomaly",BasalforcingsIsmip6MeltAnomalyEnum,0.); 186 IssmDouble** array3d = NULL; int* Ms = NULL; int* Ns = NULL; int K; 187 iomodel->FetchData(&array3d,&Ms,&Ns,&K,"md.basalforcings.tf"); 188 if(!array3d) _error_("md.basalforcings.tf not found in binary file"); 189 for(int i=0;i<elements->Size();i++){ 190 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 191 if(iomodel->domaintype!=Domain2DhorizontalEnum && !element->IsOnBase()) continue; 192 for(int kk=0;kk<K;kk++){ 193 element->DatasetInputAdd(BasalforcingsIsmip6TfEnum,array3d[kk],iomodel,Ms[kk],Ns[kk],1,BasalforcingsIsmip6TfEnum,7,kk); 194 } 195 } 196 xDelete<int>(Ms); xDelete<int>(Ns); 197 for(int i=0;i<K;i++) xDelete<IssmDouble>(array3d[i]); 198 xDelete<IssmDouble*>(array3d); 199 } 200 break; 201 case BeckmannGoosseFloatingMeltRateEnum: 202 iomodel->FetchDataToInput(elements,"md.basalforcings.ocean_salinity",BasalforcingsOceanSalinityEnum); 203 iomodel->FetchDataToInput(elements,"md.basalforcings.ocean_temp",BasalforcingsOceanTempEnum); 204 break; 185 205 default: 186 206 _error_("Basal forcing model "<<EnumToStringx(basalforcing_model)<<" not supported yet"); … … 246 266 Ke = CreateKMatrixCG(basalelement); 247 267 break; 268 case P0DGEnum: 248 269 case P1DGEnum: 249 270 Ke = CreateKMatrixDG(basalelement); … … 268 289 IssmDouble Jdet,D_scalar,dt,h; 269 290 IssmDouble vel,vx,vy,dvxdx,dvydy; 291 IssmDouble xi,tau; 270 292 IssmDouble dvx[2],dvy[2]; 271 293 IssmDouble* xyz_list = NULL; … … 286 308 ElementMatrix* Ke = element->NewElementMatrix(); 287 309 IssmDouble* basis = xNew<IssmDouble>(numnodes); 310 IssmDouble* dbasis = xNew<IssmDouble>(dim*numnodes); 288 311 IssmDouble* B = xNew<IssmDouble>(dim*numnodes); 289 312 IssmDouble* Bprime = xNew<IssmDouble>(dim*numnodes); … … 349 372 switch(stabilization){ 350 373 case 0: 351 /*Nothing to be onde*/374 /*Nothing to be done*/ 352 375 break; 353 376 case 1: … … 359 382 break; 360 383 case 2: 384 /*Streamline upwinding*/ 385 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 386 vxaverage_input->GetInputAverage(&vx); 361 387 if(dim==1){ 362 388 vel=fabs(vx)+1.e-8; 363 D[0]=h/(2*vel)*vx*vx;364 389 } 365 390 else{ 366 /*Streamline upwinding*/391 vyaverage_input->GetInputAverage(&vy); 367 392 vel=sqrt(vx*vx+vy*vy)+1.e-8; 368 D[0*dim+0]=h/(2*vel)*vx*vx;369 D[1*dim+0]=h/(2*vel)*vy*vx;370 D[0*dim+1]=h/(2*vel)*vx*vy;371 D[1*dim+1]=h/(2*vel)*vy*vy;372 393 } 394 tau=h/(2*vel); 395 break; 396 case 5: 397 /*SUPG*/ 398 if(dim!=2) _error_("Stabilization "<<stabilization<<" not supported yet for dim != 2"); 399 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 400 vxaverage_input->GetInputAverage(&vx); 401 vyaverage_input->GetInputAverage(&vy); 402 vel=sqrt(vx*vx+vy*vy)+1.e-8; 403 //xi=0.3130; 404 xi=1; 405 tau=xi*h/(2*vel); 373 406 break; 374 407 default: 375 408 _error_("Stabilization "<<stabilization<<" not supported yet"); 376 409 } 377 if(stabilization==1 || stabilization==2){ 410 if(stabilization==1){ 411 /*SSA*/ 378 412 if(dim==1) D[0]=D_scalar*D[0]; 379 413 else{ … … 389 423 &Ke->values[0],1); 390 424 } 425 if(stabilization==2){ 426 /*Streamline upwind*/ 427 for(int i=0;i<numnodes;i++){ 428 for(int j=0;j<numnodes;j++){ 429 Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(vx*dbasis[0*numnodes+i]+vy*dbasis[1*numnodes+i])*(vx*dbasis[0*numnodes+j]+vy*dbasis[1*numnodes+j]); 430 } 431 } 432 } 433 if(stabilization==5){/*{{{*/ 434 /*Mass matrix - part 2*/ 435 for(int i=0;i<numnodes;i++){ 436 for(int j=0;j<numnodes;j++){ 437 Ke->values[i*numnodes+j]+=gauss->weight*Jdet*tau*basis[j]*(vx*dbasis[0*numnodes+i]+vy*dbasis[1*numnodes+i]); 438 } 439 } 440 /*Mass matrix - part 3*/ 441 for(int i=0;i<numnodes;i++){ 442 for(int j=0;j<numnodes;j++){ 443 Ke->values[i*numnodes+j]+=gauss->weight*Jdet*tau*basis[j]*(basis[i]*dvxdx+basis[i]*dvydy); 444 } 445 } 446 447 /*Advection matrix - part 2, A*/ 448 for(int i=0;i<numnodes;i++){ 449 for(int j=0;j<numnodes;j++){ 450 Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(vx*dbasis[0*numnodes+j]+vy*dbasis[1*numnodes+j])*(vx*dbasis[0*numnodes+i]+vy*dbasis[1*numnodes+i]); 451 } 452 } 453 /*Advection matrix - part 3, A*/ 454 for(int i=0;i<numnodes;i++){ 455 for(int j=0;j<numnodes;j++){ 456 Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(vx*dbasis[0*numnodes+j]+vy*dbasis[1*numnodes+j])*(basis[i]*dvxdx+basis[i]*dvydy); 457 } 458 } 459 460 /*Advection matrix - part 2, B*/ 461 for(int i=0;i<numnodes;i++){ 462 for(int j=0;j<numnodes;j++){ 463 Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(basis[j]*dvxdx+basis[j]*dvydy)*(vx*dbasis[0*numnodes+i]+vy*dbasis[1*numnodes+i]); 464 } 465 } 466 /*Advection matrix - part 3, B*/ 467 for(int i=0;i<numnodes;i++){ 468 for(int j=0;j<numnodes;j++){ 469 Ke->values[i*numnodes+j]+=dt*gauss->weight*Jdet*tau*(basis[j]*dvxdx+basis[j]*dvydy)*(basis[i]*dvxdx+basis[i]*dvydy); 470 } 471 } 472 }/*}}}*/ 391 473 } 392 474 … … 394 476 xDelete<IssmDouble>(xyz_list); 395 477 xDelete<IssmDouble>(basis); 478 xDelete<IssmDouble>(dbasis); 396 479 xDelete<IssmDouble>(B); 397 480 xDelete<IssmDouble>(Bprime); … … 481 564 pe = CreatePVectorCG(basalelement); 482 565 break; 566 case P0DGEnum: 483 567 case P1DGEnum: 484 568 pe = CreatePVectorDG(basalelement); … … 499 583 500 584 /*Intermediaries */ 585 int stabilization,dim,domaintype; 501 586 int melt_style,point1; 502 587 bool mainlyfloating; … … 504 589 IssmDouble Jdet,dt; 505 590 IssmDouble ms,mb,gmb,fmb,thickness; 591 IssmDouble vx,vy,vel,dvxdx,dvydy,xi,h,tau; 592 IssmDouble dvx[2],dvy[2]; 506 593 IssmDouble gllevelset,phi=1.; 507 594 IssmDouble* xyz_list = NULL; 508 595 Gauss* gauss = NULL; 509 596 597 /*Get problem dimension*/ 598 element->FindParam(&domaintype,DomainTypeEnum); 599 switch(domaintype){ 600 case Domain2DverticalEnum: dim = 1; break; 601 case Domain2DhorizontalEnum: dim = 2; break; 602 case Domain3DEnum: dim = 2; break; 603 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 604 } 605 510 606 /*Fetch number of nodes and dof for this finite element*/ 511 607 int numnodes = element->GetNumberOfNodes(); … … 514 610 ElementVector* pe = element->NewElementVector(); 515 611 IssmDouble* basis = xNew<IssmDouble>(numnodes); 612 IssmDouble* dbasis= xNew<IssmDouble>(dim*numnodes); 516 613 517 614 /*Retrieve all inputs and parameters*/ … … 519 616 element->FindParam(&melt_style,GroundinglineMeltInterpolationEnum); 520 617 element->FindParam(&dt,TimesteppingTimeStepEnum); 521 Input* gmb_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(gmb_input); 522 Input* fmb_input = element->GetInput(BasalforcingsFloatingiceMeltingRateEnum); _assert_(fmb_input); 523 Input* gllevelset_input = element->GetInput(MaskGroundediceLevelsetEnum); _assert_(gllevelset_input); 524 Input* ms_input = element->GetInput(SmbMassBalanceEnum); _assert_(ms_input); 525 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 526 618 element->FindParam(&stabilization,MasstransportStabilizationEnum); 619 Input* gmb_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(gmb_input); 620 Input* fmb_input = element->GetInput(BasalforcingsFloatingiceMeltingRateEnum); _assert_(fmb_input); 621 Input* gllevelset_input = element->GetInput(MaskGroundediceLevelsetEnum); _assert_(gllevelset_input); 622 Input* ms_input = element->GetInput(SmbMassBalanceEnum); _assert_(ms_input); 623 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 624 Input* vxaverage_input = element->GetInput(VxAverageEnum); _assert_(vxaverage_input); 625 Input* vyaverage_input = element->GetInput(VyAverageEnum); _assert_(vyaverage_input); 626 627 h=element->CharacteristicLength(); 628 527 629 /*Recover portion of element that is grounded*/ 528 630 phi=element->GetGroundedPortion(xyz_list); 529 631 if(melt_style==SubelementMelt2Enum){ 530 gllevelset_input=element->GetInput(MaskGroundediceLevelsetEnum); _assert_(gllevelset_input);531 632 element->GetGroundedPart(&point1,&fraction1,&fraction2,&mainlyfloating); 532 633 gauss = element->NewGauss(point1,fraction1,fraction2,3); … … 563 664 else if(melt_style==FullMeltOnPartiallyFloatingEnum){ 564 665 if (phi<0.99999999) mb=fmb; 565 else mb= fmb;666 else mb=gmb; 566 667 } 567 668 else _error_("melt interpolation "<<EnumToStringx(melt_style)<<" not implemented yet"); 568 669 569 670 for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(thickness+dt*(ms-mb))*basis[i]; 671 672 if(stabilization==5){ //SUPG 673 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 674 vxaverage_input->GetInputAverage(&vx); 675 vyaverage_input->GetInputAverage(&vy); 676 vxaverage_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss); 677 vyaverage_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss); 678 vel=sqrt(vx*vx+vy*vy)+1.e-8; 679 dvxdx=dvx[0]; 680 dvydy=dvy[1]; 681 //xi=0.3130; 682 xi=1; 683 tau=xi*h/(2*vel); 684 685 /*Force vector - part 2*/ 686 for(int i=0;i<numnodes;i++){ 687 pe->values[i]+=Jdet*gauss->weight*(thickness+dt*(ms-mb))*(tau*vx*dbasis[0*numnodes+i]+tau*vy*dbasis[1*numnodes+i]); 688 } 689 /*Force vector - part 3*/ 690 for(int i=0;i<numnodes;i++){ 691 pe->values[i]+=Jdet*gauss->weight*(thickness+dt*(ms-mb))*(tau*basis[i]*dvxdx+tau*basis[i]*dvydy); 692 } 693 } 694 570 695 } 571 696 … … 573 698 xDelete<IssmDouble>(xyz_list); 574 699 xDelete<IssmDouble>(basis); 700 xDelete<IssmDouble>(dbasis); 575 701 delete gauss; 576 702 return pe; … … 582 708 583 709 /*Intermediaries */ 710 int melt_style, point1; 711 bool mainlyfloating; 712 IssmDouble fraction1,fraction2,gllevelset; 584 713 IssmDouble Jdet,dt; 585 714 IssmDouble ms,mb,gmb,fmb,thickness,phi=1.; … … 596 725 element->GetVerticesCoordinates(&xyz_list); 597 726 element->FindParam(&dt,TimesteppingTimeStepEnum); 598 Input* gmb_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(gmb_input); 599 Input* fmb_input = element->GetInput(BasalforcingsFloatingiceMeltingRateEnum); _assert_(fmb_input); 600 Input* ms_input = element->GetInput(SmbMassBalanceEnum); _assert_(ms_input); 601 Input* gllevelset_input = element->GetInput(MaskGroundediceLevelsetEnum); _assert_(gllevelset_input); 602 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 727 element->FindParam(&melt_style,GroundinglineMeltInterpolationEnum); 728 Input* gmb_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(gmb_input); 729 Input* fmb_input = element->GetInput(BasalforcingsFloatingiceMeltingRateEnum); _assert_(fmb_input); 730 Input* ms_input = element->GetInput(SmbMassBalanceEnum); _assert_(ms_input); 731 Input* gllevelset_input = element->GetInput(MaskGroundediceLevelsetEnum); _assert_(gllevelset_input); 732 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 733 734 /*Recover portion of element that is grounded*/ 735 Gauss* gauss=NULL; 736 phi=element->GetGroundedPortion(xyz_list); 737 if(melt_style==SubelementMelt2Enum){ 738 element->GetGroundedPart(&point1,&fraction1,&fraction2,&mainlyfloating); 739 gauss = element->NewGauss(point1,fraction1,fraction2,3); 740 } 741 else{ 742 gauss = element->NewGauss(3); 743 } 603 744 604 745 /* Start looping on the number of gaussian points: */ 605 Gauss* gauss=element->NewGauss(2);606 746 for(int ig=gauss->begin();ig<gauss->end();ig++){ 607 747 gauss->GaussPoint(ig); … … 613 753 gmb_input->GetInputValue(&gmb,gauss); 614 754 fmb_input->GetInputValue(&fmb,gauss); 615 gllevelset_input->GetInputValue(& phi,gauss);755 gllevelset_input->GetInputValue(&gllevelset,gauss); 616 756 thickness_input->GetInputValue(&thickness,gauss); 617 757 618 if(phi>0.) mb=gmb; 619 else mb=fmb; 758 if(melt_style==SubelementMelt1Enum){ 759 if (phi>0.999999999) mb=gmb; 760 else mb=(1-phi)*fmb+phi*gmb; // phi is the fraction of grounded ice so (1-phi) is floating 761 } 762 else if(melt_style==SubelementMelt2Enum){ 763 if(gllevelset>0.) mb=gmb; 764 else mb=fmb; 765 } 766 else if(melt_style==NoMeltOnPartiallyFloatingEnum){ 767 if (phi<0.00000001) mb=fmb; 768 else mb=gmb; 769 } 770 else if(melt_style==FullMeltOnPartiallyFloatingEnum){ 771 if (phi<0.99999999) mb=fmb; 772 else mb=gmb; 773 } 774 else _error_("melt interpolation "<<EnumToStringx(melt_style)<<" not implemented yet"); 620 775 621 776 for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(thickness+dt*(ms-mb))*basis[i]; … … 693 848 void MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 694 849 695 int i,hydroadjustment,domaintype; 696 int* doflist=NULL; 697 IssmDouble rho_ice,rho_water,minthickness; 698 Element* basalelement=NULL; 699 bool isgroundingline=0; 700 701 element->FindParam(&domaintype,DomainTypeEnum); 702 if(domaintype!=Domain2DhorizontalEnum){ 703 if(!element->IsOnBase()) return; 704 basalelement=element->SpawnBasalElement(); 705 } 706 else{ 707 basalelement = element; 708 } 709 710 /*Fetch number of nodes for this finite element*/ 711 int numnodes = basalelement->GetNumberOfNodes(); 850 /*Only update if on base*/ 851 if(!element->IsOnBase()) return; 712 852 713 853 /*Fetch dof list and allocate solution vector*/ 714 basalelement->GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 715 IssmDouble* newthickness = xNew<IssmDouble>(numnodes); 716 IssmDouble* cumdeltathickness = xNew<IssmDouble>(numnodes); 717 IssmDouble* deltathickness = xNew<IssmDouble>(numnodes); 718 IssmDouble* newbase = xNew<IssmDouble>(numnodes); 719 IssmDouble* bed = xNew<IssmDouble>(numnodes); 720 IssmDouble* newsurface = xNew<IssmDouble>(numnodes); 721 IssmDouble* oldthickness = xNew<IssmDouble>(numnodes); 722 IssmDouble* oldbase = xNew<IssmDouble>(numnodes); 723 IssmDouble* oldsurface = xNew<IssmDouble>(numnodes); 724 IssmDouble* phi = xNew<IssmDouble>(numnodes); 725 IssmDouble* sealevel = xNew<IssmDouble>(numnodes); 854 int *doflist = NULL; 855 element->GetDofListLocal(&doflist,NoneApproximationEnum,GsetEnum); 856 857 int numnodes = element->GetNumberOfNodes(); 858 IssmDouble* newthickness = xNew<IssmDouble>(numnodes); 859 IssmDouble* thicknessresidual = xNew<IssmDouble>(numnodes); 726 860 727 861 /*Use the dof list to index into the solution vector: */ 728 basalelement->FindParam(&minthickness,MasstransportMinThicknessEnum);729 for(i =0;i<numnodes;i++){862 IssmDouble minthickness = element->FindParam(MasstransportMinThicknessEnum); 863 for(int i=0;i<numnodes;i++){ 730 864 newthickness[i]=solution[doflist[i]]; 865 thicknessresidual[i]=0.; 866 /*Check solution*/ 731 867 if(xIsNan<IssmDouble>(newthickness[i])) _error_("NaN found in solution vector"); 732 868 if(xIsInf<IssmDouble>(newthickness[i])) _error_("Inf found in solution vector"); 733 /*Constrain thickness to be at least 1m*/ 734 if(newthickness[i]<minthickness) newthickness[i]=minthickness; 735 } 869 if(newthickness[i]<minthickness){ 870 thicknessresidual[i]=minthickness-newthickness[i]; 871 newthickness[i]=minthickness; 872 } 873 } 874 element->AddBasalInput(ThicknessEnum,newthickness,element->GetElementType()); 875 element->AddBasalInput(ThicknessResidualEnum,thicknessresidual,element->GetElementType()); 876 877 xDelete<int>(doflist); 878 xDelete<IssmDouble>(newthickness); 879 xDelete<IssmDouble>(thicknessresidual); 880 881 /*Update bed and surface accordingly*/ 882 883 /*Get basal element*/ 884 int domaintype; element->FindParam(&domaintype,DomainTypeEnum); 885 Element* basalelement=element; 886 if(domaintype!=Domain2DhorizontalEnum) basalelement = element->SpawnBasalElement(); 887 888 /*Fetch number of nodes and dof for this finite element*/ 889 int numvertices = basalelement->GetNumberOfVertices(); 890 891 /*Now, we need to do some "processing"*/ 892 newthickness = xNew<IssmDouble>(numvertices); 893 IssmDouble* oldthickness = xNew<IssmDouble>(numvertices); 894 IssmDouble* cumdeltathickness = xNew<IssmDouble>(numvertices); 895 IssmDouble* deltathickness = xNew<IssmDouble>(numvertices); 896 IssmDouble* newbase = xNew<IssmDouble>(numvertices); 897 IssmDouble* bed = xNew<IssmDouble>(numvertices); 898 IssmDouble* newsurface = xNew<IssmDouble>(numvertices); 899 IssmDouble* oldbase = xNew<IssmDouble>(numvertices); 900 IssmDouble* oldsurface = xNew<IssmDouble>(numvertices); 901 IssmDouble* phi = xNew<IssmDouble>(numvertices); 902 IssmDouble* sealevel = xNew<IssmDouble>(numvertices); 736 903 737 904 /*Get previous base, thickness, surfac and current sealevel and bed:*/ 738 basalelement->GetInputListOnNodes(&oldbase[0],BaseEnum); 739 basalelement->GetInputListOnNodes(&oldsurface[0],SurfaceEnum); 740 basalelement->GetInputListOnNodes(&oldthickness[0],ThicknessEnum); 741 basalelement->GetInputListOnNodes(&phi[0],MaskGroundediceLevelsetEnum); 742 basalelement->GetInputListOnNodes(&sealevel[0],SealevelEnum); 743 basalelement->GetInputListOnNodes(&cumdeltathickness[0],SealevelriseCumDeltathicknessEnum); 744 905 basalelement->GetInputListOnVertices(&newthickness[0],ThicknessEnum); 906 basalelement->GetInputListOnVertices(&oldthickness[0],ThicknessOldEnum); 907 basalelement->GetInputListOnVertices(&oldbase[0],BaseEnum); 908 basalelement->GetInputListOnVertices(&oldsurface[0],SurfaceEnum); 909 basalelement->GetInputListOnVertices(&phi[0],MaskGroundediceLevelsetEnum); 910 basalelement->GetInputListOnVertices(&sealevel[0],SealevelEnum); 911 basalelement->GetInputListOnVertices(&cumdeltathickness[0],SealevelriseCumDeltathicknessEnum); 912 913 /*Do we do grounding line migration?*/ 914 bool isgroundingline; 745 915 element->FindParam(&isgroundingline,TransientIsgroundinglineEnum); 746 if(isgroundingline) basalelement->GetInputListOn Nodes(&bed[0],BedEnum);916 if(isgroundingline) basalelement->GetInputListOnVertices(&bed[0],BedEnum); 747 917 748 918 /*What is the delta thickness forcing the sea-level rise core: cumulated over time, hence the +=:*/ 749 for(i =0;i<numnodes;i++){750 cumdeltathickness[i] +=newthickness[i]-oldthickness[i];751 deltathickness[i] =newthickness[i]-oldthickness[i];919 for(int i=0;i<numvertices;i++){ 920 cumdeltathickness[i] += newthickness[i]-oldthickness[i]; 921 deltathickness[i] = newthickness[i]-oldthickness[i]; 752 922 } 753 923 754 924 /*Find MasstransportHydrostaticAdjustment to figure out how to update the geometry:*/ 925 int hydroadjustment; 755 926 basalelement->FindParam(&hydroadjustment,MasstransportHydrostaticAdjustmentEnum); 756 rho_ice = basalelement->GetMaterialParameter(MaterialsRhoIceEnum); 757 rho_water = basalelement->GetMaterialParameter(MaterialsRhoSeawaterEnum); 758 759 for(i=0;i<numnodes;i++) { 760 if (phi[i]>0.){ //this is an ice sheet: just add thickness to base. 761 /*Update! actually, the bed has moved too!:*/ 927 IssmDouble rho_ice = basalelement->FindParam(MaterialsRhoIceEnum); 928 IssmDouble rho_water = basalelement->FindParam(MaterialsRhoSeawaterEnum); 929 930 for(int i=0;i<numvertices;i++) { 931 if (phi[i]>0.){ //this is grounded ice: just add thickness to base. 762 932 if(isgroundingline){ 763 933 newsurface[i] = bed[i]+newthickness[i]; //surface = bed + newthickness 764 newbase[i] 934 newbase[i] = bed[i]; //new base at new bed 765 935 } 766 936 else{ 767 937 newsurface[i] = oldbase[i]+newthickness[i]; //surface = oldbase + newthickness 768 newbase[i] 938 newbase[i] = oldbase[i]; //same base: do nothing 769 939 } 770 940 } 771 941 else{ //this is an ice shelf: hydrostatic equilibrium*/ 772 942 if(hydroadjustment==AbsoluteEnum){ 773 newsurface[i] = newthickness[i]*(1 -rho_ice/rho_water)+sealevel[i];774 newbase[i] 943 newsurface[i] = newthickness[i]*(1.-rho_ice/rho_water)+sealevel[i]; 944 newbase[i] = newthickness[i]*(-rho_ice/rho_water)+sealevel[i]; 775 945 } 776 946 else if(hydroadjustment==IncrementalEnum){ 777 947 newsurface[i] = oldsurface[i]+(1.0-rho_ice/rho_water)*(newthickness[i]-oldthickness[i])+sealevel[i]; //surface = oldsurface + (1-di) * dH 778 newbase[i] 948 newbase[i] = oldbase[i]-rho_ice/rho_water*(newthickness[i]-oldthickness[i])+sealevel[i]; //base = oldbed + di * dH 779 949 } 780 950 else _error_("Hydrostatic adjustment " << hydroadjustment << " (" << EnumToStringx(hydroadjustment) << ") not supported yet"); … … 783 953 784 954 /*Add input to the element: */ 785 element->AddBasalInput(ThicknessEnum,newthickness,P1Enum);786 955 element->AddBasalInput(SurfaceEnum,newsurface,P1Enum); 787 956 element->AddBasalInput(BaseEnum,newbase,P1Enum); … … 801 970 xDelete<IssmDouble>(sealevel); 802 971 xDelete<IssmDouble>(bed); 803 804 972 xDelete<int>(doflist); 805 973 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; … … 934 1102 void MasstransportAnalysis::LumpedMassMatrix(Vector<IssmDouble>** pMlff,FemModel* femmodel){/*{{{*/ 935 1103 936 /*Intermediaries*/937 int configuration_type;938 939 1104 /*Initialize Lumped mass matrix (actually we just save its diagonal)*/ 940 femmodel->parameters->FindParam(&configuration_type,ConfigurationTypeEnum); 941 int fsize = femmodel->nodes->NumberOfDofs(configuration_type,FsetEnum); 942 int flocalsize = femmodel->nodes->NumberOfDofsLocal(configuration_type,FsetEnum); 1105 int fsize = femmodel->nodes->NumberOfDofs(FsetEnum); 1106 int flocalsize = femmodel->nodes->NumberOfDofsLocal(FsetEnum); 943 1107 Vector<IssmDouble>* Mlff = new Vector<IssmDouble>(flocalsize,fsize); 944 1108
Note:
See TracChangeset
for help on using the changeset viewer.