#include "./SamplingAnalysis.h" // #include "../toolkits/toolkits.h" #include "../classes/classes.h" #include "../shared/shared.h" #include "../modules/modules.h" #include #define FINITEELEMENT P1Enum #define NUMVERTICES 3 /* Reimplementation of IsFaceOnBoundary with two edges on boundary supported */ bool IsFaceOnBoundary(Element* element) { IssmDouble values[NUMVERTICES]; IssmDouble sum; /*Retrieve all inputs and parameters*/ element->GetInputListOnVertices(&values[0],MeshVertexonboundaryEnum); sum = values[0]+values[1]+values[2]; _assert_(sum==0. || sum==1. || sum==2. || sum==3.); if(sum>1.){ return true; } else{ return false; } } /*Model processing*/ void SamplingAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ /*Default, do nothing*/ return; }/*}}}*/ void SamplingAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ /*Default, do nothing*/ return; }/*}}}*/ void SamplingAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel,bool isamr){/*{{{*/ int finiteelement; finiteelement = FINITEELEMENT; /*Check in 2d*/ if(iomodel->domaintype!=Domain2DhorizontalEnum) _error_("Only 2D horizontal domain is implemented."); ::CreateNodes(nodes,iomodel,SamplingAnalysisEnum,finiteelement); }/*}}}*/ int SamplingAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ return 1; }/*}}}*/ void SamplingAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ int finiteelement; /*Finite element type*/ finiteelement = FINITEELEMENT; /*Update elements: */ int counter=0; for(int i=0;inumberofelements;i++){ if(iomodel->my_elements[i]){ Element* element=(Element*)elements->GetObjectByOffset(counter); element->Update(inputs,i,iomodel,analysis_counter,analysis_type,finiteelement); counter++; } } /*Create inputs: */ iomodel->FetchDataToInput(inputs,elements,"md.mask.ice_levelset",MaskIceLevelsetEnum); iomodel->FetchDataToInput(inputs,elements,"md.mesh.vertexonboundary",MeshVertexonboundaryEnum); iomodel->FetchDataToInput(inputs,elements,"md.sampling.kappa",SamplingKappaEnum); iomodel->FetchDataToInput(inputs,elements,"md.sampling.beta",SamplingBetaEnum,0.); iomodel->FetchDataToInput(inputs,elements,"md.sampling.tau",SamplingTauEnum); iomodel->FetchDataToInput(inputs,elements,"md.initialization.sample",SampleEnum,0.); iomodel->FetchDataToInput(inputs,elements,"md.initialization.sample",SampleNoiseEnum,0.); if(iomodel->solution_enum==TransientSolutionEnum) iomodel->FetchDataToInput(inputs,elements,"md.sampling.phi",SamplingPhiEnum,0.); }/*}}}*/ void SamplingAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ int numoutputs; char** requestedoutputs = NULL; parameters->AddObject(iomodel->CopyConstantObject("md.sampling.alpha",SamplingAlphaEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.sampling.robin",SamplingRobinEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.sampling.seed",SamplingSeedEnum)); iomodel->FindConstant(&requestedoutputs,&numoutputs,"md.sampling.requested_outputs"); parameters->AddObject(new IntParam(SamplingNumRequestedOutputsEnum,numoutputs)); if(numoutputs)parameters->AddObject(new StringArrayParam(SamplingRequestedOutputsEnum,requestedoutputs,numoutputs)); iomodel->DeleteData(&requestedoutputs,numoutputs,"md.sampling.requested_outputs"); }/*}}}*/ /*Finite Element Analysis*/ void SamplingAnalysis::Core(FemModel* femmodel){/*{{{*/ _error_("not implemented"); }/*}}}*/ void SamplingAnalysis::PreCore(FemModel* femmodel){/*{{{*/ _error_("not implemented"); }/*}}}*/ ElementVector* SamplingAnalysis::CreateDVector(Element* element){/*{{{*/ /*Default, return NULL*/ return NULL; }/*}}}*/ ElementMatrix* SamplingAnalysis::CreateJacobianMatrix(Element* element){/*{{{*/ _error_("not implemented"); }/*}}}*/ ElementMatrix* SamplingAnalysis::CreateKMatrix(Element* element){/*{{{*/ /* Check if ice in element */ //if(!element->IsIceInElement()) return NULL; // Ice in element not required for sampling capability /*Intermediaries*/ bool robin; int domaintype; /*compute all stiffness matrices for this element*/ ElementMatrix* Ke = NULL; element->FindParam(&robin,SamplingRobinEnum); if(!robin) Ke=CreateKMatrixModifiedHelmholtz(element); else{ ElementMatrix* Ke1=CreateKMatrixModifiedHelmholtz(element); ElementMatrix* Ke2=CreateKMatrixRobinBC(element); Ke =new ElementMatrix(Ke1,Ke2); delete Ke1; delete Ke2; } /*clean-up and return*/ return Ke; }/*}}}*/ ElementMatrix* SamplingAnalysis::CreateKMatrixModifiedHelmholtz(Element* element){/*{{{*/ /* Check if ice in element */ //if(!element->IsIceInElement()) return NULL; /*Intermediaries*/ int dim; IssmDouble D,Jdet; IssmDouble* xyz_list = NULL; IssmDouble kappa; /*Get problem dimension*/ dim=2; // Only 2D horizontal domain is implemented so far /*Fetch number of nodes and dof for this finite element*/ int numnodes = element->GetNumberOfNodes(); /*Initialize Element vector and other vectors*/ ElementMatrix* Ke = element->NewElementMatrix(); IssmDouble* basis = xNew(numnodes); IssmDouble* dbasis = xNew(dim*numnodes); /*Retrieve all inputs and parameters*/ element->GetVerticesCoordinates(&xyz_list); Input* kappa_input=element->GetInput(SamplingKappaEnum); _assert_(kappa_input); /* Start looping on the number of gaussian points: */ Gauss* gauss=element->NewGauss(2); while(gauss->next()){ element->JacobianDeterminant(&Jdet,xyz_list,gauss); element->NodalFunctions(basis,gauss); element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); kappa_input->GetInputValue(&kappa,gauss); _assert_(kappa>0); D=gauss->weight*Jdet; /* Laplacian operator */ for(int i=0;ivalues[i*numnodes+j] += D*(dbasis[0*numnodes+j]*dbasis[0*numnodes+i] + dbasis[1*numnodes+j]*dbasis[1*numnodes+i]); } } /* Identity identity */ for(int i=0;ivalues[i*numnodes+j] += D*kappa*kappa*(basis[j]*basis[i]); } } } /*Clean up and return*/ xDelete(xyz_list); xDelete(basis); xDelete(dbasis); delete gauss; return Ke; }/*}}}*/ ElementMatrix* SamplingAnalysis::CreateKMatrixRobinBC(Element* element){/*{{{*/ /* Check if ice in element */ //if(!element->IsIceInElement()) return NULL; /*If no boundary, return NULL*/ if(!IsFaceOnBoundary(element)) return NULL; /*Intermediaries*/ IssmDouble D,Jdet; IssmDouble* xyz_list = NULL; IssmDouble* xyz_list_boundary = NULL; IssmDouble beta; /*Fetch number of nodes and dof for this finite element*/ int numnodes = element->GetNumberOfNodes(); /*Initialize Element vector and other vectors*/ ElementMatrix* Ke = element->NewElementMatrix(); IssmDouble* basis = xNew(numnodes); /*Retrieve all inputs and parameters*/ element->GetVerticesCoordinates(&xyz_list); element->GetLevelCoordinates(&xyz_list_boundary,xyz_list,MeshVertexonboundaryEnum,1.); Input* beta_input=element->GetInput(SamplingBetaEnum); _assert_(beta_input); /* Start looping on the number of gaussian points: */ Gauss* gauss=element->NewGauss(xyz_list,xyz_list_boundary,3); while(gauss->next()){ element->JacobianDeterminantSurface(&Jdet,xyz_list_boundary,gauss); element->NodalFunctions(basis,gauss); beta_input->GetInputValue(&beta,gauss); _assert_(beta>=0); D=gauss->weight*Jdet; for(int i=0;ivalues[i*numnodes+j] += D*beta*(basis[j]*basis[i]); } } } /*Clean up and return*/ xDelete(xyz_list); xDelete(xyz_list_boundary); xDelete(basis); delete gauss; return Ke; }/*}}}*/ ElementVector* SamplingAnalysis::CreatePVector(Element* element){/*{{{*/ //_error_("not supported"); return NULL; }/*}}}*/ void SamplingAnalysis::GetSolutionFromInputs(Vector* solution,Element* element){/*{{{*/ element->GetSolutionFromInputsOneDof(solution,SampleEnum); }/*}}}*/ void SamplingAnalysis::GradientJ(Vector* gradient,Element* element,int control_type,int control_interp,int control_index){/*{{{*/ _error_("not supported"); }/*}}}*/ void SamplingAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ /*Fetch number of nodes and dof for this finite element*/ int numnodes = element->GetNumberOfNodes(); /*Fetch dof list and allocate solution vector*/ int* doflist=NULL; element->GetDofListLocal(&doflist,NoneApproximationEnum,GsetEnum); IssmDouble* newsample = xNew(numnodes); IssmDouble* tau = xNew(numnodes); element->GetInputListOnNodes(&tau[0],SamplingTauEnum); /*Use the dof list to index into the solution vector: */ for(int i=0;i(newsample[i])) _error_("NaN found in solution vector"); if(xIsInf(newsample[i])) _error_("Inf found in solution vector"); } /*Add sample inputs to the tria element: */ element->AddInput(SampleEnum,newsample,element->GetElementType()); /*Free resources:*/ xDelete(newsample); xDelete(tau); xDelete(doflist); }/*}}}*/ void SamplingAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ /*Default, do nothing*/ return; }/*}}}*/ ElementMatrix* SamplingAnalysis::CreateMassMatrix(Element* element){/*{{{*/ /* Check if ice in element */ //if(!element->IsIceInElement()) return NULL; /*Intermediaries*/ IssmDouble D,Jdet; IssmDouble* xyz_list = NULL; /*Fetch number of nodes and dof for this finite element*/ int numnodes = element->GetNumberOfNodes(); /*Initialize Element vector and other vectors*/ ElementMatrix* Me = element->NewElementMatrix(); IssmDouble* basis = xNew(numnodes); /*Retrieve all inputs and parameters*/ element->GetVerticesCoordinates(&xyz_list); /* Start looping on the number of gaussian points: */ Gauss* gauss=element->NewGauss(2); while(gauss->next()){ element->JacobianDeterminant(&Jdet,xyz_list,gauss); element->NodalFunctions(basis,gauss); D=gauss->weight*Jdet; TripleMultiply(basis,1,numnodes,1, &D,1,1,0, basis,1,numnodes,0, &Me->values[0],1); } /*Clean up and return*/ xDelete(xyz_list); xDelete(basis); delete gauss; return Me; }/*}}}*/ void SamplingAnalysis::LumpedKMatrix(Vector** pKlff,FemModel* femmodel){/*{{{*/ /*Initialize Lumped mass matrix (actually we just save its diagonal)*/ int fsize = femmodel->nodes->NumberOfDofs(FsetEnum); int flocalsize = femmodel->nodes->NumberOfDofsLocal(FsetEnum); Vector* Klff = new Vector(flocalsize,fsize); /*Create and assemble matrix*/ for(int i=0;ielements->Size();i++){ Element* element = xDynamicCast(femmodel->elements->GetObjectByOffset(i)); ElementMatrix* KLe = this->CreateKMatrix(element); if(KLe){ KLe->Lump(); KLe->AddDiagonalToGlobal(Klff); } delete KLe; } Klff->Assemble(); /*Assign output pointer*/ *pKlff=Klff; }/*}}}*/ void SamplingAnalysis::KMatrix(Matrix** pKff,FemModel* femmodel){/*{{{*/ /*Initialize K matrix*/ Matrix *Kff = NULL; AllocateSystemMatricesx(&Kff,NULL,NULL,NULL,femmodel); /*Create and assemble matrix*/ for(int i=0;ielements->Size();i++){ Element* element = xDynamicCast(femmodel->elements->GetObjectByOffset(i)); ElementMatrix* Ke = this->CreateKMatrix(element); if(Ke){ Ke->AddToGlobal(Kff); } delete Ke; } Kff->Assemble(); /*Assign output pointer*/ *pKff=Kff; }/*}}}*/ void SamplingAnalysis::LumpedMassMatrix(Vector** pMlff,FemModel* femmodel){/*{{{*/ /*Initialize Lumped mass matrix (actually we just save its diagonal)*/ int fsize = femmodel->nodes->NumberOfDofs(FsetEnum); int flocalsize = femmodel->nodes->NumberOfDofsLocal(FsetEnum); Vector* Mlff = new Vector(flocalsize,fsize); /*Create and assemble matrix*/ for(int i=0;ielements->Size();i++){ Element* element = xDynamicCast(femmodel->elements->GetObjectByOffset(i)); ElementMatrix* MLe = this->CreateMassMatrix(element); if(MLe){ MLe->Lump(); MLe->AddDiagonalToGlobal(Mlff); } delete MLe; } Mlff->Assemble(); /*Assign output pointer*/ *pMlff=Mlff; }/*}}}*/ void SamplingAnalysis::MassMatrix(Matrix** pMff,FemModel* femmodel){/*{{{*/ /*Initialize Mass matrix*/ Matrix *Mff = NULL; AllocateSystemMatricesx(&Mff,NULL,NULL,NULL,femmodel); /*Create and assemble matrix*/ for(int i=0;ielements->Size();i++){ Element* element = xDynamicCast(femmodel->elements->GetObjectByOffset(i)); ElementMatrix* MLe = this->CreateMassMatrix(element); if(MLe){ MLe->AddToGlobal(Mff); } delete MLe; } Mff->Assemble(); /*Assign output pointer*/ *pMff=Mff; }/*}}}*/ void SamplingAnalysis::UpdateTransientSample(FemModel * femmodel){ for(int j=0;jelements->Size();j++){ Element* element=(Element*)femmodel->elements->GetObjectByOffset(j); UpdateTransientSample(element); } } void SamplingAnalysis::UpdateTransientSample(Element * element){ /*Intermediaries */ IssmDouble phi, sample, noise; /*Fetch number vertices for this element*/ int numvertices = element->GetNumberOfVertices(); /*Initialize new sample*/ IssmDouble* sample_new = xNew(numvertices); /*Retrieve all inputs and parameters*/ Input* sample_input=element->GetInput(SampleOldEnum); _assert_(sample_input); Input* noise_input=element->GetInput(SampleNoiseEnum); _assert_(noise_input); Input* phi_input=element->GetInput(SamplingPhiEnum); _assert_(phi_input); /* Start looping on the number of gaussian points: */ Gauss* gauss=element->NewGauss(); for(int iv=0;ivGaussVertex(iv); /*Get input values at gauss points*/ sample_input->GetInputValue(&sample,gauss); noise_input->GetInputValue(&noise,gauss); phi_input->GetInputValue(&phi,gauss); /*Get new sample*/ sample_new[iv] = phi*sample + noise; } element->AddInput(SampleEnum,sample_new,element->GetElementType()); /*Clean up and return*/ xDelete(sample_new); delete gauss; }