#include "./SealevelriseAnalysis.h" #include "../toolkits/toolkits.h" #include "../classes/classes.h" #include "../classes/Inputs2/TransientInput2.h" #include "../shared/shared.h" #include "../modules/modules.h" /*Model processing*/ void SealevelriseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ /*No constraints*/ }/*}}}*/ void SealevelriseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ /*No loads*/ }/*}}}*/ void SealevelriseAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel,bool isamr){/*{{{*/ ::CreateNodes(nodes,iomodel,SealevelriseAnalysisEnum,P1Enum); }/*}}}*/ int SealevelriseAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ return 1; }/*}}}*/ void SealevelriseAnalysis::UpdateElements(Elements* elements,Inputs2* inputs2,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ int geodetic=0; int dslmodel=0; /*Update elements: */ int counter=0; for(int i=0;inumberofelements;i++){ if(iomodel->my_elements[i]){ Element* element=(Element*)elements->GetObjectByOffset(counter); element->Update(inputs2,i,iomodel,analysis_counter,analysis_type,P1Enum); counter++; } } /*Create inputs: */ iomodel->FetchDataToInput(inputs2,elements,"md.mask.ocean_levelset",MaskOceanLevelsetEnum); iomodel->FetchDataToInput(inputs2,elements,"md.mask.ice_levelset",MaskIceLevelsetEnum); iomodel->FetchData(&geodetic,"md.slr.geodetic"); iomodel->FetchDataToInput(inputs2,elements,"md.slr.deltathickness",SealevelriseDeltathicknessEnum); iomodel->FetchDataToInput(inputs2,elements,"md.slr.spcthickness",SealevelriseSpcthicknessEnum); iomodel->FetchDataToInput(inputs2,elements,"md.slr.sealevel",SealevelEnum,0); iomodel->FetchDataToInput(inputs2,elements,"md.geometry.bed",BedEnum); iomodel->FetchDataToInput(inputs2,elements,"md.slr.Ngia",SealevelNGiaRateEnum); iomodel->FetchDataToInput(inputs2,elements,"md.slr.Ugia",SealevelUGiaRateEnum); iomodel->FetchDataToInput(inputs2,elements,"md.slr.hydro_rate",SealevelriseHydroRateEnum); /*dynamic sea level: */ iomodel->FetchData(&dslmodel,"md.dsl.model"); if (dslmodel==1){ /*standard dsl model:{{{*/ /*deal with global mean steric rate: */ IssmDouble* str=NULL; IssmDouble* times = NULL; int M,N; /*fetch str vector:*/ iomodel->FetchData(&str,&M,&N,"md.dsl.global_average_thermosteric_sea_level_change"); _assert_(M==2); //recover time vector: times=xNew(N); for(int t=0;tSetTransientInput(DslGlobalAverageThermostericSeaLevelChangeEnum,times,N); TransientInput2* transientinput = inputs2->GetTransientInput(DslGlobalAverageThermostericSeaLevelChangeEnum); for(int i=0;iSize();i++){ Element* element=xDynamicCast(elements->GetObjectByOffset(i)); for(int t=0;tObjectEnum()){ case TriaEnum: transientinput->AddTriaTimeInput( t,1,&element->lid,&str[t],P0Enum); break; case PentaEnum: transientinput->AddPentaTimeInput(t,1,&element->lid,&str[t],P0Enum); break; default: _error_("Not implemented yet"); } } } /*cleanup:*/ xDelete(times); iomodel->DeleteData(str,"md.dsl.global_average_thermosteric_sea_level_change"); /*deal with dynamic sea level fields: */ iomodel->FetchDataToInput(inputs2,elements,"md.dsl.sea_surface_height_change_above_geoid", DslSeaSurfaceHeightChangeAboveGeoidEnum); iomodel->FetchDataToInput(inputs2,elements,"md.dsl.sea_water_pressure_change_at_sea_floor", DslSeaWaterPressureChangeAtSeaFloor); } /*}}}*/ else if (dslmodel==2){ /*multi-model ensemble dsl model:{{{*/ /*variables:*/ int nummodels; IssmDouble** pstr=NULL; IssmDouble* str=NULL; IssmDouble* times = NULL; int* pM = NULL; int* pN = NULL; int M,N; /*deal with dsl.sea_surface_height_change_above_geoid {{{*/ iomodel->FetchData(&pstr,&pM,&pN,&nummodels,"md.dsl.global_average_thermosteric_sea_level_change"); /*go through the mat array and create a dataset of transient inputs:*/ for (int i=0;i(N); for(int t=0;tSetDatasetTransientInput(DslGlobalAverageThermostericSeaLevelChangeEnum,i, times,N); for(int j=0;jSize();j++){ Element* element=xDynamicCast(elements->GetObjectByOffset(j)); for(int t=0;tObjectEnum()){ case TriaEnum: transientinput->AddTriaTimeInput( t,1,&element->lid,&str[t],P0Enum); break; case PentaEnum: transientinput->AddPentaTimeInput(t,1,&element->lid,&str[t],P0Enum); break; default: _error_("Not implemented yet"); } } } xDelete(times); } /*Delete data:*/ for(int i=0;i(str); } xDelete(pstr); xDelete(pM); xDelete(pN); /*}}}*/ /*now do the same with the dsl.sea_surface_height_change_above_geoid field:{{{ */ iomodel->FetchData(&pstr,&pM,&pN,&nummodels,"md.dsl.sea_surface_height_change_above_geoid"); for (int i=0;i(N); for(int t=0;tSetDatasetTransientInput(DslSeaSurfaceHeightChangeAboveGeoidEnum,i, times,N); for(int j=0;jSize();j++){ /*Get the right transient input*/ Element* element=xDynamicCast(elements->GetObjectByOffset(j)); /*Get values and lid list*/ const int numvertices = element->GetNumberOfVertices(); int *vertexlids = xNew(numvertices); int *vertexsids = xNew(numvertices); /*Recover vertices ids needed to initialize inputs*/ _assert_(iomodel->elements); for(int k=0;k(iomodel->elements[numvertices*element->Sid()+k]); //ids for vertices are in the elements array from Matlab vertexlids[k]=iomodel->my_vertices_lids[vertexsids[k]-1]; } //element->GetVerticesLidList(vertexlids); //element->GetVerticesSidList(vertexsids); IssmDouble* values=xNew(numvertices); for(int t=0;tObjectEnum()){ case TriaEnum: transientinput->AddTriaTimeInput( t,numvertices,vertexlids,values,P1Enum); break; case PentaEnum: transientinput->AddPentaTimeInput(t,numvertices,vertexlids,values,P1Enum); break; default: _error_("Not implemented yet"); } } xDelete(values); xDelete(vertexlids); xDelete(vertexsids); } xDelete(times); } /*Delete data:*/ for(int i=0;i(str); } xDelete(pstr); xDelete(pM); xDelete(pN); /*}}}*/ /*now do the same with the dsl.sea_water_pressure_change_at_sea_floor field:{{{ */ iomodel->FetchData(&pstr,&pM,&pN,&nummodels,"md.dsl.sea_water_pressure_change_at_sea_floor"); for (int i=0;i(N); for(int t=0;tSetDatasetTransientInput(DslSeaWaterPressureChangeAtSeaFloor,i, times,N); for(int j=0;jSize();j++){ /*Get the right transient input*/ Element* element=xDynamicCast(elements->GetObjectByOffset(j)); /*Get values and lid list*/ const int numvertices = element->GetNumberOfVertices(); int *vertexlids = xNew(numvertices); int *vertexsids = xNew(numvertices); /*Recover vertices ids needed to initialize inputs*/ _assert_(iomodel->elements); for(int k=0;k(iomodel->elements[numvertices*element->Sid()+k]); //ids for vertices are in the elements array from Matlab vertexlids[k]=iomodel->my_vertices_lids[vertexsids[k]-1]; } //element->GetVerticesLidList(vertexlids); //element->GetVerticesSidList(vertexsids); IssmDouble* values=xNew(numvertices); for(int t=0;tObjectEnum()){ case TriaEnum: transientinput->AddTriaTimeInput( t,numvertices,vertexlids,values,P1Enum); break; case PentaEnum: transientinput->AddPentaTimeInput(t,numvertices,vertexlids,values,P1Enum); break; default: _error_("Not implemented yet"); } } xDelete(values); xDelete(vertexlids); xDelete(vertexsids); } xDelete(times); } /*Delete data:*/ for(int i=0;i(str); } xDelete(pstr); xDelete(pM); xDelete(pN); /*}}}*/ } /*}}}*/ else _error_("Dsl model " << dslmodel << " not implemented yet!"); /*Initialize cumdeltalthickness and sealevel rise rate input*/ InputUpdateFromConstantx(inputs2,elements,0.,SealevelriseCumDeltathicknessEnum); InputUpdateFromConstantx(inputs2,elements,0.,SealevelNEsaRateEnum); InputUpdateFromConstantx(inputs2,elements,0.,SealevelUEsaRateEnum); InputUpdateFromConstantx(inputs2,elements,0.,SealevelRSLRateEnum); InputUpdateFromConstantx(inputs2,elements,0.,SealevelEustaticMaskEnum); InputUpdateFromConstantx(inputs2,elements,0.,SealevelEustaticOceanMaskEnum); }/*}}}*/ void SealevelriseAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ int nl; IssmDouble* love_h=NULL; IssmDouble* love_k=NULL; IssmDouble* love_l=NULL; int dslmodel=0; IssmDouble* G_rigid = NULL; IssmDouble* G_rigid_local = NULL; IssmDouble* G_elastic = NULL; IssmDouble* G_elastic_local = NULL; IssmDouble* U_elastic = NULL; IssmDouble* U_elastic_local = NULL; IssmDouble* H_elastic = NULL; IssmDouble* H_elastic_local = NULL; int M,m,lower_row,upper_row; IssmDouble degacc=.01; int numoutputs; char** requestedoutputs = NULL; /*transition vectors: */ IssmDouble **transitions = NULL; int *transitions_M = NULL; int *transitions_N = NULL; int ntransitions; /*some constant parameters: */ parameters->AddObject(iomodel->CopyConstantObject("md.dsl.model",DslModelEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.geodetic_run_frequency",SealevelriseGeodeticRunFrequencyEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.reltol",SealevelriseReltolEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.abstol",SealevelriseAbstolEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.maxiter",SealevelriseMaxiterEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.loop_increment",SealevelriseLoopIncrementEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.rigid",SealevelriseRigidEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.horiz",SealevelriseHorizEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.elastic",SealevelriseElasticEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.rotation",SealevelriseRotationEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.tide_love_h",SealevelriseTidalLoveHEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.tide_love_k",SealevelriseTidalLoveKEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.fluid_love",SealevelriseFluidLoveEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.equatorial_moi",SealevelriseEquatorialMoiEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.polar_moi",SealevelrisePolarMoiEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.angular_velocity",SealevelriseAngularVelocityEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.ocean_area_scaling",SealevelriseOceanAreaScalingEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.slr.geodetic",SealevelriseGeodeticEnum)); /*Deal with dsl multi-model ensembles: {{{*/ iomodel->FetchData(&dslmodel,"md.dsl.model"); parameters->AddObject(iomodel->CopyConstantObject("md.dsl.compute_fingerprints",DslComputeFingerprintsEnum)); if(dslmodel==2){ int modelid; int nummodels; parameters->AddObject(iomodel->CopyConstantObject("md.dsl.modelid",DslModelidEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.dsl.nummodels",DslNummodelsEnum)); iomodel->FetchData(&modelid,"md.dsl.modelid"); iomodel->FetchData(&nummodels,"md.dsl.nummodels"); /*quick checks: */ if(nummodels<=0)_error_("dslmme object in md.dsl field should contain at least 1 ensemble model!"); if(modelid<=0 || modelid>nummodels)_error_("modelid field in dslmme object of md.dsl field should be between 1 and the number of ensemble runs!"); } /*}}}*/ /*Deal with elasticity {{{*/ /*love numbers: */ iomodel->FetchData(&love_h,&nl,NULL,"md.slr.love_h"); iomodel->FetchData(&love_k,&nl,NULL,"md.slr.love_k"); iomodel->FetchData(&love_l,&nl,NULL,"md.slr.love_l"); /*compute elastic green function for a range of angles*/ iomodel->FetchData(°acc,"md.slr.degacc"); M=reCast(180./degacc+1.); // AD performance is sensitive to calls to ensurecontiguous. // // Providing "t" will cause ensurecontiguous to be called. #ifdef _HAVE_AD_ G_rigid=xNew(M,"t"); G_elastic=xNew(M,"t"); U_elastic=xNew(M,"t"); H_elastic=xNew(M,"t"); #else G_rigid=xNew(M); G_elastic=xNew(M); U_elastic=xNew(M); H_elastic=xNew(M); #endif /*compute combined legendre + love number (elastic green function:*/ m=DetermineLocalSize(M,IssmComm::GetComm()); GetOwnershipBoundariesFromRange(&lower_row,&upper_row,m,IssmComm::GetComm()); // AD performance is sensitive to calls to ensurecontiguous. // // Providing "t" will cause ensurecontiguous to be called. #ifdef _HAVE_AD_ G_elastic_local=xNew(m,"t"); G_rigid_local=xNew(m,"t"); U_elastic_local=xNew(m,"t"); H_elastic_local=xNew(m,"t"); #else G_elastic_local=xNew(m); G_rigid_local=xNew(m); U_elastic_local=xNew(m); H_elastic_local=xNew(m); #endif for(int i=lower_row;i(i)*degacc * PI / 180.0; G_rigid_local[i-lower_row]= .5/sin(alpha/2.0); G_elastic_local[i-lower_row]= (love_k[nl-1]-love_h[nl-1])*G_rigid_local[i-lower_row]; U_elastic_local[i-lower_row]= (love_h[nl-1])*G_rigid_local[i-lower_row]; H_elastic_local[i-lower_row]= 0; IssmDouble Pn = 0.; IssmDouble Pn1 = 0.; IssmDouble Pn2 = 0.; IssmDouble Pn_p = 0.; IssmDouble Pn_p1 = 0.; IssmDouble Pn_p2 = 0.; for (int n=0;n(IssmComm::GetSize()); int* displs=xNew(IssmComm::GetSize()); //recvcounts: ISSM_MPI_Allgather(&m,1,ISSM_MPI_INT,recvcounts,1,ISSM_MPI_INT,IssmComm::GetComm()); /*displs: */ ISSM_MPI_Allgather(&lower_row,1,ISSM_MPI_INT,displs,1,ISSM_MPI_INT,IssmComm::GetComm()); /*All gather:*/ ISSM_MPI_Allgatherv(G_rigid_local, m, ISSM_MPI_DOUBLE, G_rigid, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); ISSM_MPI_Allgatherv(G_elastic_local, m, ISSM_MPI_DOUBLE, G_elastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); ISSM_MPI_Allgatherv(U_elastic_local, m, ISSM_MPI_DOUBLE, U_elastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); ISSM_MPI_Allgatherv(H_elastic_local, m, ISSM_MPI_DOUBLE, H_elastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); /*free ressources: */ xDelete(recvcounts); xDelete(displs); /*}}}*/ /*Avoid singularity at 0: */ G_rigid[0]=G_rigid[1]; parameters->AddObject(new DoubleVecParam(SealevelriseGRigidEnum,G_rigid,M)); G_elastic[0]=G_elastic[1]; parameters->AddObject(new DoubleVecParam(SealevelriseGElasticEnum,G_elastic,M)); U_elastic[0]=U_elastic[1]; parameters->AddObject(new DoubleVecParam(SealevelriseUElasticEnum,U_elastic,M)); H_elastic[0]=H_elastic[1]; parameters->AddObject(new DoubleVecParam(SealevelriseHElasticEnum,H_elastic,M)); /*free ressources: */ xDelete(love_h); xDelete(love_k); xDelete(love_l); xDelete(G_rigid); xDelete(G_rigid_local); xDelete(G_elastic); xDelete(G_elastic_local); xDelete(U_elastic); xDelete(U_elastic_local); xDelete(H_elastic); xDelete(H_elastic_local); /*}}}*/ /*Transitions:{{{ */ iomodel->FetchData(&transitions,&transitions_M,&transitions_N,&ntransitions,"md.slr.transitions"); if(transitions){ parameters->AddObject(new DoubleMatArrayParam(SealevelriseTransitionsEnum,transitions,ntransitions,transitions_M,transitions_N)); for(int i=0;i(transition); } xDelete(transitions); xDelete(transitions_M); xDelete(transitions_N); } /*}}}*/ /*Requested outputs {{{*/ iomodel->FindConstant(&requestedoutputs,&numoutputs,"md.slr.requested_outputs"); if(numoutputs)parameters->AddObject(new StringArrayParam(SealevelriseRequestedOutputsEnum,requestedoutputs,numoutputs)); iomodel->DeleteData(&requestedoutputs,numoutputs,"md.slr.requested_outputs"); /*}}}*/ }/*}}}*/ /*Finite Element Analysis*/ void SealevelriseAnalysis::Core(FemModel* femmodel){/*{{{*/ _error_("not implemented"); }/*}}}*/ ElementVector* SealevelriseAnalysis::CreateDVector(Element* element){/*{{{*/ /*Default, return NULL*/ return NULL; }/*}}}*/ ElementMatrix* SealevelriseAnalysis::CreateJacobianMatrix(Element* element){/*{{{*/ _error_("Not implemented"); }/*}}}*/ ElementMatrix* SealevelriseAnalysis::CreateKMatrix(Element* element){/*{{{*/ _error_("not implemented yet"); }/*}}}*/ ElementVector* SealevelriseAnalysis::CreatePVector(Element* element){/*{{{*/ _error_("not implemented yet"); }/*}}}*/ void SealevelriseAnalysis::GetSolutionFromInputs(Vector* solution,Element* element){/*{{{*/ _error_("not implemented yet"); }/*}}}*/ void SealevelriseAnalysis::GradientJ(Vector* gradient,Element* element,int control_type,int control_index){/*{{{*/ _error_("Not implemented yet"); }/*}}}*/ void SealevelriseAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ _error_("not implemeneted yet!"); }/*}}}*/ void SealevelriseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ /*Default, do nothing*/ return; }/*}}}*/