Changeset 18930
- Timestamp:
- 12/04/14 10:34:36 (10 years ago)
- Location:
- issm/trunk-jpl/src/c/analyses
- Files:
-
- 44 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.cpp
r18715 r18930 6 6 7 7 /*Model processor*/ 8 void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 _error_("not implemented yet"); 10 }/*}}}*/ 11 void AdjointBalancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 12 _error_("not implemented yet"); 13 }/*}}}*/ 14 void AdjointBalancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 15 _error_("not implemented yet"); 16 }/*}}}*/ 8 17 int AdjointBalancethickness2Analysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 18 return 1; 10 19 }/*}}}*/ 20 void AdjointBalancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ 21 _error_("not implemented yet"); 22 }/*}}}*/ 11 23 void AdjointBalancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 12 _error_("not implemented yet");13 }/*}}}*/14 void AdjointBalancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/15 _error_("not implemented yet");16 }/*}}}*/17 void AdjointBalancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/18 _error_("not implemented yet");19 }/*}}}*/20 void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/21 _error_("not implemented yet");22 }/*}}}*/23 void AdjointBalancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/24 24 _error_("not implemented yet"); 25 25 }/*}}}*/ … … 106 106 107 107 }/*}}}*/ 108 void AdjointBalancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/109 _error_("not implemented yet"); 110 }/*}}}*/ 111 void AdjointBalancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/108 void AdjointBalancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 109 _error_("not implemented yet"); 110 }/*}}}*/ 111 void AdjointBalancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 112 112 /*The gradient of the cost function is calculated in 2 parts. 113 113 * … … 146 146 147 147 }/*}}}*/ 148 void AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 148 void AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 149 150 /*Intermediaries*/ 151 IssmDouble lambda,Jdet; 152 IssmDouble *xyz_list= NULL; 153 154 /*Fetch number of vertices for this finite element*/ 155 int numvertices = element->GetNumberOfVertices(); 156 157 /*Initialize some vectors*/ 158 IssmDouble* basis = xNew<IssmDouble>(numvertices); 159 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 160 int* vertexpidlist = xNew<int>(numvertices); 161 162 /*Retrieve all inputs we will be needing: */ 163 element->GetVerticesCoordinates(&xyz_list); 164 element->GradientIndexing(&vertexpidlist[0],control_index); 165 Input* adjoint_input = element->GetInput(AdjointEnum); _assert_(adjoint_input); 166 167 Gauss* gauss=element->NewGauss(2); 168 for(int ig=gauss->begin();ig<gauss->end();ig++){ 169 gauss->GaussPoint(ig); 170 171 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 172 element->NodalFunctionsP1(basis,gauss); 173 174 adjoint_input->GetInputValue(&lambda,gauss); 175 176 /*Build gradient vector (actually -dJ/da): */ 177 for(int i=0;i<numvertices;i++){ 178 ge[i]+= -Jdet*gauss->weight*basis[i]*lambda; 179 _assert_(!xIsNan<IssmDouble>(ge[i])); 180 } 181 } 182 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 183 184 /*Clean up and return*/ 185 xDelete<IssmDouble>(ge); 186 xDelete<IssmDouble>(xyz_list); 187 xDelete<IssmDouble>(basis); 188 xDelete<int>(vertexpidlist); 189 delete gauss; 190 }/*}}}*/ 191 void AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 149 192 150 193 /*Intermediaries*/ … … 195 238 delete gauss; 196 239 }/*}}}*/ 197 void AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 198 199 /*Intermediaries*/ 200 IssmDouble lambda,Jdet; 201 IssmDouble *xyz_list= NULL; 202 203 /*Fetch number of vertices for this finite element*/ 204 int numvertices = element->GetNumberOfVertices(); 205 206 /*Initialize some vectors*/ 207 IssmDouble* basis = xNew<IssmDouble>(numvertices); 208 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 209 int* vertexpidlist = xNew<int>(numvertices); 210 211 /*Retrieve all inputs we will be needing: */ 212 element->GetVerticesCoordinates(&xyz_list); 213 element->GradientIndexing(&vertexpidlist[0],control_index); 214 Input* adjoint_input = element->GetInput(AdjointEnum); _assert_(adjoint_input); 215 216 Gauss* gauss=element->NewGauss(2); 217 for(int ig=gauss->begin();ig<gauss->end();ig++){ 218 gauss->GaussPoint(ig); 219 220 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 221 element->NodalFunctionsP1(basis,gauss); 222 223 adjoint_input->GetInputValue(&lambda,gauss); 224 225 /*Build gradient vector (actually -dJ/da): */ 226 for(int i=0;i<numvertices;i++){ 227 ge[i]+= -Jdet*gauss->weight*basis[i]*lambda; 228 _assert_(!xIsNan<IssmDouble>(ge[i])); 229 } 230 } 231 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 232 233 /*Clean up and return*/ 234 xDelete<IssmDouble>(ge); 235 xDelete<IssmDouble>(xyz_list); 236 xDelete<IssmDouble>(basis); 237 xDelete<int>(vertexpidlist); 238 delete gauss; 239 }/*}}}*/ 240 void AdjointBalancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 240 void AdjointBalancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 241 241 element->InputUpdateFromSolutionOneDof(solution,AdjointEnum); 242 242 }/*}}}*/ 243 void AdjointBalancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/243 void AdjointBalancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 244 244 /*Default, do nothing*/ 245 245 return; -
issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h
r18569 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index);31 void GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index);32 void InputUpdateFromSolution(IssmDouble* solution,Element* element);33 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index); 31 void GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index); 32 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 33 void UpdateConstraints(FemModel* femmodel); 34 34 }; 35 35 #endif -
issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp
r18403 r18930 6 6 7 7 /*Model processor*/ 8 void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 _error_("not implemented yet"); 10 }/*}}}*/ 11 void AdjointBalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 12 _error_("not implemented yet"); 13 }/*}}}*/ 14 void AdjointBalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 15 _error_("not implemented yet"); 16 }/*}}}*/ 8 17 int AdjointBalancethicknessAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 18 return 1; 10 19 }/*}}}*/ 20 void AdjointBalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ 21 _error_("not implemented yet"); 22 }/*}}}*/ 11 23 void AdjointBalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 12 _error_("not implemented yet");13 }/*}}}*/14 void AdjointBalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/15 _error_("not implemented yet");16 }/*}}}*/17 void AdjointBalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/18 _error_("not implemented yet");19 }/*}}}*/20 void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/21 _error_("not implemented yet");22 }/*}}}*/23 void AdjointBalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/24 24 _error_("not implemented yet"); 25 25 }/*}}}*/ … … 147 147 return pe; 148 148 }/*}}}*/ 149 void AdjointBalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/150 _error_("not implemented yet"); 151 }/*}}}*/ 152 void AdjointBalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/149 void AdjointBalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 150 _error_("not implemented yet"); 151 }/*}}}*/ 152 void AdjointBalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 153 153 /*The gradient of the cost function is calculated in 2 parts. 154 154 * … … 196 196 197 197 }/*}}}*/ 198 void AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 199 200 /*Intermediaries*/ 201 IssmDouble thickness,Jdet,Dlambda[3],dp[3]; 202 IssmDouble *xyz_list= NULL; 203 204 /*Fetch number of vertices for this finite element*/ 205 int numvertices = element->GetNumberOfVertices(); 206 207 /*Initialize some vectors*/ 208 IssmDouble* basis = xNew<IssmDouble>(numvertices); 209 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 210 int* vertexpidlist = xNew<int>(numvertices); 211 212 /*Retrieve all inputs we will be needing: */ 213 element->GetVerticesCoordinates(&xyz_list); 214 element->GradientIndexing(&vertexpidlist[0],control_index); 215 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 216 Input* adjoint_input = element->GetInput(AdjointEnum); _assert_(adjoint_input); 217 218 /* Start looping on the number of gaussian points: */ 219 Gauss* gauss=element->NewGauss(4); 220 for(int ig=gauss->begin();ig<gauss->end();ig++){ 221 gauss->GaussPoint(ig); 222 223 adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss); 224 thickness_input->GetInputValue(&thickness, gauss); 225 thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss); 226 227 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 228 element->NodalFunctionsP1(basis,gauss); 229 230 /*Build gradient vector (actually -dJ/dD): */ 231 for(int i=0;i<numvertices;i++){ 232 ge[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i]; 233 _assert_(!xIsNan<IssmDouble>(ge[i])); 234 } 235 } 236 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 237 238 /*Clean up and return*/ 239 xDelete<IssmDouble>(xyz_list); 240 xDelete<IssmDouble>(basis); 241 xDelete<IssmDouble>(ge); 242 xDelete<int>(vertexpidlist); 243 delete gauss; 244 }/*}}}*/ 245 void AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 246 247 /*Intermediaries*/ 248 IssmDouble thickness,Jdet,Dlambda[3],dp[3]; 249 IssmDouble *xyz_list= NULL; 250 251 /*Fetch number of vertices for this finite element*/ 252 int numvertices = element->GetNumberOfVertices(); 253 254 /*Initialize some vectors*/ 255 IssmDouble* basis = xNew<IssmDouble>(numvertices); 256 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 257 int* vertexpidlist = xNew<int>(numvertices); 258 259 /*Retrieve all inputs we will be needing: */ 260 element->GetVerticesCoordinates(&xyz_list); 261 element->GradientIndexing(&vertexpidlist[0],control_index); 262 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 263 Input* adjoint_input = element->GetInput(AdjointEnum); _assert_(adjoint_input); 264 265 /* Start looping on the number of gaussian points: */ 266 Gauss* gauss=element->NewGauss(4); 267 for(int ig=gauss->begin();ig<gauss->end();ig++){ 268 gauss->GaussPoint(ig); 269 270 adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss); 271 thickness_input->GetInputValue(&thickness, gauss); 272 thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss); 273 274 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 275 element->NodalFunctionsP1(basis,gauss); 276 277 /*Build gradient vector (actually -dJ/dvy): */ 278 for(int i=0;i<numvertices;i++){ 279 ge[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i]; 280 _assert_(!xIsNan<IssmDouble>(ge[i])); 281 } 282 } 283 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 284 285 /*Clean up and return*/ 286 xDelete<IssmDouble>(xyz_list); 287 xDelete<IssmDouble>(basis); 288 xDelete<IssmDouble>(ge); 289 xDelete<int>(vertexpidlist); 290 delete gauss; 291 }/*}}}*/ 292 void AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 198 void AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 293 199 294 200 /*Fetch number of vertices for this finite element*/ … … 314 220 xDelete<int>(vertexpidlist); 315 221 }/*}}}*/ 316 void AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 222 void AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 223 224 /*Intermediaries*/ 225 IssmDouble thickness,Jdet,Dlambda[3],dp[3]; 226 IssmDouble *xyz_list= NULL; 227 228 /*Fetch number of vertices for this finite element*/ 229 int numvertices = element->GetNumberOfVertices(); 230 231 /*Initialize some vectors*/ 232 IssmDouble* basis = xNew<IssmDouble>(numvertices); 233 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 234 int* vertexpidlist = xNew<int>(numvertices); 235 236 /*Retrieve all inputs we will be needing: */ 237 element->GetVerticesCoordinates(&xyz_list); 238 element->GradientIndexing(&vertexpidlist[0],control_index); 239 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 240 Input* adjoint_input = element->GetInput(AdjointEnum); _assert_(adjoint_input); 241 242 /* Start looping on the number of gaussian points: */ 243 Gauss* gauss=element->NewGauss(4); 244 for(int ig=gauss->begin();ig<gauss->end();ig++){ 245 gauss->GaussPoint(ig); 246 247 adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss); 248 thickness_input->GetInputValue(&thickness, gauss); 249 thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss); 250 251 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 252 element->NodalFunctionsP1(basis,gauss); 253 254 /*Build gradient vector (actually -dJ/dD): */ 255 for(int i=0;i<numvertices;i++){ 256 ge[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i]; 257 _assert_(!xIsNan<IssmDouble>(ge[i])); 258 } 259 } 260 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 261 262 /*Clean up and return*/ 263 xDelete<IssmDouble>(xyz_list); 264 xDelete<IssmDouble>(basis); 265 xDelete<IssmDouble>(ge); 266 xDelete<int>(vertexpidlist); 267 delete gauss; 268 }/*}}}*/ 269 void AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 270 271 /*Intermediaries*/ 272 IssmDouble thickness,Jdet,Dlambda[3],dp[3]; 273 IssmDouble *xyz_list= NULL; 274 275 /*Fetch number of vertices for this finite element*/ 276 int numvertices = element->GetNumberOfVertices(); 277 278 /*Initialize some vectors*/ 279 IssmDouble* basis = xNew<IssmDouble>(numvertices); 280 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 281 int* vertexpidlist = xNew<int>(numvertices); 282 283 /*Retrieve all inputs we will be needing: */ 284 element->GetVerticesCoordinates(&xyz_list); 285 element->GradientIndexing(&vertexpidlist[0],control_index); 286 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 287 Input* adjoint_input = element->GetInput(AdjointEnum); _assert_(adjoint_input); 288 289 /* Start looping on the number of gaussian points: */ 290 Gauss* gauss=element->NewGauss(4); 291 for(int ig=gauss->begin();ig<gauss->end();ig++){ 292 gauss->GaussPoint(ig); 293 294 adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss); 295 thickness_input->GetInputValue(&thickness, gauss); 296 thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss); 297 298 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 299 element->NodalFunctionsP1(basis,gauss); 300 301 /*Build gradient vector (actually -dJ/dvy): */ 302 for(int i=0;i<numvertices;i++){ 303 ge[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i]; 304 _assert_(!xIsNan<IssmDouble>(ge[i])); 305 } 306 } 307 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 308 309 /*Clean up and return*/ 310 xDelete<IssmDouble>(xyz_list); 311 xDelete<IssmDouble>(basis); 312 xDelete<IssmDouble>(ge); 313 xDelete<int>(vertexpidlist); 314 delete gauss; 315 }/*}}}*/ 316 void AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 317 317 318 318 int domaintype; … … 328 328 } 329 329 }/*}}}*/ 330 void AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/330 void AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 331 331 /*Default, do nothing*/ 332 332 return; -
issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h
r18060 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index);31 void GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index);32 void GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index);33 void InputUpdateFromSolution(IssmDouble* solution,Element* element);34 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index); 31 void GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index); 32 void GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index); 33 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 34 void UpdateConstraints(FemModel* femmodel); 35 35 }; 36 36 #endif -
issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp
r18838 r18930 6 6 7 7 /*Model processing*/ 8 void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 _error_("not implemented yet"); 10 }/*}}}*/ 11 void AdjointHorizAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 12 _error_("not implemented yet"); 13 }/*}}}*/ 14 void AdjointHorizAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 15 _error_("not implemented yet"); 16 }/*}}}*/ 8 17 int AdjointHorizAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 18 _error_("not implemented"); 10 19 }/*}}}*/ 11 void AdjointHorizAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 _error_("not implemented yet");13 }/*}}}*/14 20 void AdjointHorizAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ 15 21 _error_("not implemented yet"); 16 22 }/*}}}*/ 17 void AdjointHorizAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 18 _error_("not implemented yet"); 19 }/*}}}*/ 20 void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 21 _error_("not implemented yet"); 22 }/*}}}*/ 23 void AdjointHorizAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 23 void AdjointHorizAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 24 24 _error_("not implemented yet"); 25 25 }/*}}}*/ … … 54 54 } 55 55 }/*}}}*/ 56 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/ 57 58 /*Intermediaries */ 59 bool incomplete_adjoint; 60 int dim,epssize; 61 IssmDouble Jdet,mu_prime; 62 IssmDouble eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij,eps3dotdphii,eps3dotdphij; 63 IssmDouble eps1[3],eps2[3],eps3[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/ 64 IssmDouble *xyz_list = NULL; 65 66 /*Get problem dimension*/ 67 element->FindParam(&dim,DomainDimensionEnum); 68 if(dim==2) epssize = 3; 69 else epssize = 6; 70 71 /*Fetch number of nodes and dof for this finite element*/ 72 int vnumnodes = element->NumberofNodesVelocity(); 73 int pnumnodes = element->NumberofNodesPressure(); 74 int numdof = vnumnodes*dim + pnumnodes; 75 76 /*Initialize Jacobian with regular FS (first part of the Gateau derivative)*/ 77 element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum); 78 StressbalanceAnalysis* analysis = new StressbalanceAnalysis(); 79 ElementMatrix* Ke=analysis->CreateKMatrix(element); 80 delete analysis; 81 if(incomplete_adjoint) return Ke; 82 83 /*Retrieve all inputs and parameters*/ 84 element->GetVerticesCoordinates(&xyz_list); 85 Input* vx_input = element->GetInput(VxEnum);_assert_(vx_input); 86 Input* vy_input = element->GetInput(VyEnum);_assert_(vy_input); 87 Input* vz_input = NULL; 88 if(dim==3){ 89 vz_input = element->GetInput(VzEnum); 90 } 91 else{ 92 _error_("Not implemented yet"); 93 } 94 95 /*Allocate dbasis*/ 96 IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes); 97 98 /* Start looping on the number of gaussian points: */ 99 Gauss* gauss=element->NewGauss(5); 100 for(int ig=gauss->begin();ig<gauss->end();ig++){ 101 gauss->GaussPoint(ig); 102 103 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 104 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 105 106 element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input); 107 element->ViscosityFSDerivativeEpsSquare(&mu_prime,&epsilon[0]); 108 eps1[0]=epsilon[0]; eps2[0]=epsilon[2]; eps3[0]=epsilon[3]; 109 eps1[1]=epsilon[2]; eps2[1]=epsilon[1]; eps3[1]=epsilon[4]; 110 eps1[2]=epsilon[3]; eps2[2]=epsilon[4]; eps3[2]= -epsilon[0] -epsilon[1]; 111 112 for(int i=0;i<vnumnodes;i++){ 113 for(int j=0;j<vnumnodes;j++){ 114 eps1dotdphii=eps1[0]*dbasis[0*vnumnodes+i]+eps1[1]*dbasis[1*vnumnodes+i]+eps1[2]*dbasis[2*vnumnodes+i]; 115 eps1dotdphij=eps1[0]*dbasis[0*vnumnodes+j]+eps1[1]*dbasis[1*vnumnodes+j]+eps1[2]*dbasis[2*vnumnodes+j]; 116 eps2dotdphii=eps2[0]*dbasis[0*vnumnodes+i]+eps2[1]*dbasis[1*vnumnodes+i]+eps2[2]*dbasis[2*vnumnodes+i]; 117 eps2dotdphij=eps2[0]*dbasis[0*vnumnodes+j]+eps2[1]*dbasis[1*vnumnodes+j]+eps2[2]*dbasis[2*vnumnodes+j]; 118 eps3dotdphii=eps3[0]*dbasis[0*vnumnodes+i]+eps3[1]*dbasis[1*vnumnodes+i]+eps3[2]*dbasis[2*vnumnodes+i]; 119 eps3dotdphij=eps3[0]*dbasis[0*vnumnodes+j]+eps3[1]*dbasis[1*vnumnodes+j]+eps3[2]*dbasis[2*vnumnodes+j]; 120 121 Ke->values[numdof*(4*i+0)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii; 122 Ke->values[numdof*(4*i+0)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii; 123 Ke->values[numdof*(4*i+0)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps1dotdphii; 124 125 Ke->values[numdof*(4*i+1)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii; 126 Ke->values[numdof*(4*i+1)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii; 127 Ke->values[numdof*(4*i+1)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps2dotdphii; 128 129 Ke->values[numdof*(4*i+2)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps3dotdphii; 130 Ke->values[numdof*(4*i+2)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps3dotdphii; 131 Ke->values[numdof*(4*i+2)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps3dotdphii; 132 } 133 } 134 } 135 136 /*Transform Coordinate System*/ 137 element->TransformStiffnessMatrixCoord(Ke,XYZEnum); 138 139 /*Clean up and return*/ 140 delete gauss; 141 xDelete<IssmDouble>(dbasis); 142 xDelete<IssmDouble>(xyz_list); 143 return Ke; 144 }/*}}}*/ 145 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixHO(Element* element){/*{{{*/ 146 147 /*Intermediaries */ 148 bool incomplete_adjoint; 149 IssmDouble Jdet,mu_prime; 150 IssmDouble eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij; 151 IssmDouble eps1[3],eps2[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/ 152 IssmDouble *xyz_list = NULL; 153 154 /*Fetch number of nodes and dof for this finite element*/ 155 int numnodes = element->GetNumberOfNodes(); 156 157 /*Initialize Jacobian with regular HO (first part of the Gateau derivative)*/ 158 element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum); 159 StressbalanceAnalysis* analysis = new StressbalanceAnalysis(); 160 ElementMatrix* Ke=analysis->CreateKMatrix(element); 161 delete analysis; 162 if(incomplete_adjoint) return Ke; 163 164 /*Retrieve all inputs and parameters*/ 165 element->GetVerticesCoordinates(&xyz_list); 166 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 167 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input); 168 169 /*Allocate dbasis*/ 170 IssmDouble* dbasis = xNew<IssmDouble>(3*numnodes); 171 172 /* Start looping on the number of gaussian points: */ 173 Gauss* gauss=element->NewGauss(5); 174 for(int ig=gauss->begin();ig<gauss->end();ig++){ 175 gauss->GaussPoint(ig); 176 177 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 178 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 179 180 element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input); 181 element->ViscosityHODerivativeEpsSquare(&mu_prime,&epsilon[0]); 182 eps1[0]=2.*epsilon[0]+epsilon[1]; eps2[0]=epsilon[2]; 183 eps1[1]=epsilon[2]; eps2[1]=epsilon[0]+2.*epsilon[1]; 184 eps1[2]=epsilon[3]; eps2[2]=epsilon[4]; 185 186 for(int i=0;i<numnodes;i++){ 187 for(int j=0;j<numnodes;j++){ 188 eps1dotdphii=eps1[0]*dbasis[0*numnodes+i]+eps1[1]*dbasis[1*numnodes+i]+eps1[2]*dbasis[2*numnodes+i]; 189 eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j]+eps1[2]*dbasis[2*numnodes+j]; 190 eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i]+eps2[2]*dbasis[2*numnodes+i]; 191 eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+j]+eps2[2]*dbasis[2*numnodes+j]; 192 193 Ke->values[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii; 194 Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii; 195 Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii; 196 Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii; 197 } 198 } 199 } 200 201 /*Transform Coordinate System*/ 202 element->TransformStiffnessMatrixCoord(Ke,XYEnum); 203 204 /*Clean up and return*/ 205 delete gauss; 206 xDelete<IssmDouble>(dbasis); 207 xDelete<IssmDouble>(xyz_list); 208 return Ke; 209 }/*}}}*/ 210 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixL1L2(Element* element){/*{{{*/ 211 212 /*Intermediaries*/ 213 bool incomplete_adjoint; 214 215 /*Initialize Jacobian with regular L1L2 (first part of the Gateau derivative)*/ 216 StressbalanceAnalysis* analysis = new StressbalanceAnalysis(); 217 ElementMatrix* Ke=analysis->CreateKMatrix(element); 218 delete analysis; 219 220 /*return*/ 221 element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum); 222 if(!incomplete_adjoint){ 223 _error_("Exact adjoint not supported yet for L1L2 model"); 224 } 225 return Ke; 226 }/*}}}*/ 56 227 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixSSA(Element* element){/*{{{*/ 57 228 … … 139 310 xDelete<IssmDouble>(xyz_list); 140 311 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 141 return Ke;142 }/*}}}*/143 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixL1L2(Element* element){/*{{{*/144 145 /*Intermediaries*/146 bool incomplete_adjoint;147 148 /*Initialize Jacobian with regular L1L2 (first part of the Gateau derivative)*/149 StressbalanceAnalysis* analysis = new StressbalanceAnalysis();150 ElementMatrix* Ke=analysis->CreateKMatrix(element);151 delete analysis;152 153 /*return*/154 element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);155 if(!incomplete_adjoint){156 _error_("Exact adjoint not supported yet for L1L2 model");157 }158 return Ke;159 }/*}}}*/160 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixHO(Element* element){/*{{{*/161 162 /*Intermediaries */163 bool incomplete_adjoint;164 IssmDouble Jdet,mu_prime;165 IssmDouble eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij;166 IssmDouble eps1[3],eps2[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/167 IssmDouble *xyz_list = NULL;168 169 /*Fetch number of nodes and dof for this finite element*/170 int numnodes = element->GetNumberOfNodes();171 172 /*Initialize Jacobian with regular HO (first part of the Gateau derivative)*/173 element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);174 StressbalanceAnalysis* analysis = new StressbalanceAnalysis();175 ElementMatrix* Ke=analysis->CreateKMatrix(element);176 delete analysis;177 if(incomplete_adjoint) return Ke;178 179 /*Retrieve all inputs and parameters*/180 element->GetVerticesCoordinates(&xyz_list);181 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);182 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);183 184 /*Allocate dbasis*/185 IssmDouble* dbasis = xNew<IssmDouble>(3*numnodes);186 187 /* Start looping on the number of gaussian points: */188 Gauss* gauss=element->NewGauss(5);189 for(int ig=gauss->begin();ig<gauss->end();ig++){190 gauss->GaussPoint(ig);191 192 element->JacobianDeterminant(&Jdet,xyz_list,gauss);193 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);194 195 element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);196 element->ViscosityHODerivativeEpsSquare(&mu_prime,&epsilon[0]);197 eps1[0]=2.*epsilon[0]+epsilon[1]; eps2[0]=epsilon[2];198 eps1[1]=epsilon[2]; eps2[1]=epsilon[0]+2.*epsilon[1];199 eps1[2]=epsilon[3]; eps2[2]=epsilon[4];200 201 for(int i=0;i<numnodes;i++){202 for(int j=0;j<numnodes;j++){203 eps1dotdphii=eps1[0]*dbasis[0*numnodes+i]+eps1[1]*dbasis[1*numnodes+i]+eps1[2]*dbasis[2*numnodes+i];204 eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j]+eps1[2]*dbasis[2*numnodes+j];205 eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i]+eps2[2]*dbasis[2*numnodes+i];206 eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+j]+eps2[2]*dbasis[2*numnodes+j];207 208 Ke->values[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;209 Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;210 Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;211 Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;212 }213 }214 }215 216 /*Transform Coordinate System*/217 element->TransformStiffnessMatrixCoord(Ke,XYEnum);218 219 /*Clean up and return*/220 delete gauss;221 xDelete<IssmDouble>(dbasis);222 xDelete<IssmDouble>(xyz_list);223 return Ke;224 }/*}}}*/225 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/226 227 /*Intermediaries */228 bool incomplete_adjoint;229 int dim,epssize;230 IssmDouble Jdet,mu_prime;231 IssmDouble eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij,eps3dotdphii,eps3dotdphij;232 IssmDouble eps1[3],eps2[3],eps3[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/233 IssmDouble *xyz_list = NULL;234 235 /*Get problem dimension*/236 element->FindParam(&dim,DomainDimensionEnum);237 if(dim==2) epssize = 3;238 else epssize = 6;239 240 /*Fetch number of nodes and dof for this finite element*/241 int vnumnodes = element->NumberofNodesVelocity();242 int pnumnodes = element->NumberofNodesPressure();243 int numdof = vnumnodes*dim + pnumnodes;244 245 /*Initialize Jacobian with regular FS (first part of the Gateau derivative)*/246 element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);247 StressbalanceAnalysis* analysis = new StressbalanceAnalysis();248 ElementMatrix* Ke=analysis->CreateKMatrix(element);249 delete analysis;250 if(incomplete_adjoint) return Ke;251 252 /*Retrieve all inputs and parameters*/253 element->GetVerticesCoordinates(&xyz_list);254 Input* vx_input = element->GetInput(VxEnum);_assert_(vx_input);255 Input* vy_input = element->GetInput(VyEnum);_assert_(vy_input);256 Input* vz_input = NULL;257 if(dim==3){258 vz_input = element->GetInput(VzEnum);259 }260 else{261 _error_("Not implemented yet");262 }263 264 /*Allocate dbasis*/265 IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes);266 267 /* Start looping on the number of gaussian points: */268 Gauss* gauss=element->NewGauss(5);269 for(int ig=gauss->begin();ig<gauss->end();ig++){270 gauss->GaussPoint(ig);271 272 element->JacobianDeterminant(&Jdet,xyz_list,gauss);273 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);274 275 element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);276 element->ViscosityFSDerivativeEpsSquare(&mu_prime,&epsilon[0]);277 eps1[0]=epsilon[0]; eps2[0]=epsilon[2]; eps3[0]=epsilon[3];278 eps1[1]=epsilon[2]; eps2[1]=epsilon[1]; eps3[1]=epsilon[4];279 eps1[2]=epsilon[3]; eps2[2]=epsilon[4]; eps3[2]= -epsilon[0] -epsilon[1];280 281 for(int i=0;i<vnumnodes;i++){282 for(int j=0;j<vnumnodes;j++){283 eps1dotdphii=eps1[0]*dbasis[0*vnumnodes+i]+eps1[1]*dbasis[1*vnumnodes+i]+eps1[2]*dbasis[2*vnumnodes+i];284 eps1dotdphij=eps1[0]*dbasis[0*vnumnodes+j]+eps1[1]*dbasis[1*vnumnodes+j]+eps1[2]*dbasis[2*vnumnodes+j];285 eps2dotdphii=eps2[0]*dbasis[0*vnumnodes+i]+eps2[1]*dbasis[1*vnumnodes+i]+eps2[2]*dbasis[2*vnumnodes+i];286 eps2dotdphij=eps2[0]*dbasis[0*vnumnodes+j]+eps2[1]*dbasis[1*vnumnodes+j]+eps2[2]*dbasis[2*vnumnodes+j];287 eps3dotdphii=eps3[0]*dbasis[0*vnumnodes+i]+eps3[1]*dbasis[1*vnumnodes+i]+eps3[2]*dbasis[2*vnumnodes+i];288 eps3dotdphij=eps3[0]*dbasis[0*vnumnodes+j]+eps3[1]*dbasis[1*vnumnodes+j]+eps3[2]*dbasis[2*vnumnodes+j];289 290 Ke->values[numdof*(4*i+0)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;291 Ke->values[numdof*(4*i+0)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;292 Ke->values[numdof*(4*i+0)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps1dotdphii;293 294 Ke->values[numdof*(4*i+1)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;295 Ke->values[numdof*(4*i+1)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;296 Ke->values[numdof*(4*i+1)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps2dotdphii;297 298 Ke->values[numdof*(4*i+2)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps3dotdphii;299 Ke->values[numdof*(4*i+2)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps3dotdphii;300 Ke->values[numdof*(4*i+2)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps3dotdphii;301 }302 }303 }304 305 /*Transform Coordinate System*/306 element->TransformStiffnessMatrixCoord(Ke,XYZEnum);307 308 /*Clean up and return*/309 delete gauss;310 xDelete<IssmDouble>(dbasis);311 xDelete<IssmDouble>(xyz_list);312 312 return Ke; 313 313 }/*}}}*/ … … 567 567 return pe; 568 568 }/*}}}*/ 569 ElementVector* AdjointHorizAnalysis::CreatePVectorL1L2(Element* element){/*{{{*/ 570 571 /*Same as SSA*/ 572 return this->CreatePVectorSSA(element); 573 }/*}}}*/ 569 574 ElementVector* AdjointHorizAnalysis::CreatePVectorHO(Element* element){/*{{{*/ 570 575 … … 1042 1047 return pe; 1043 1048 }/*}}}*/ 1044 ElementVector* AdjointHorizAnalysis::CreatePVectorL1L2(Element* element){/*{{{*/ 1045 1046 /*Same as SSA*/ 1047 return this->CreatePVectorSSA(element); 1048 }/*}}}*/ 1049 void AdjointHorizAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 1049 void AdjointHorizAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 1050 1050 _error_("not implemented yet"); 1051 1051 }/*}}}*/ 1052 void AdjointHorizAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/1052 void AdjointHorizAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 1053 1053 /*The gradient of the cost function is calculated in 2 parts. 1054 1054 * … … 1138 1138 1139 1139 }/*}}}*/ 1140 void AdjointHorizAnalysis::GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1141 1142 /*return if floating (gradient is 0)*/ 1143 if(element->IsFloating()) return; 1144 1145 /*Intermediaries*/ 1146 int domaintype,dim; 1147 Element* basalelement; 1148 1149 /*Get basal element*/ 1150 element->FindParam(&domaintype,DomainTypeEnum); 1151 switch(domaintype){ 1152 case Domain2DhorizontalEnum: 1153 basalelement = element; 1154 dim = 2; 1155 break; 1156 case Domain2DverticalEnum: 1157 if(!element->IsOnBase()) return; 1158 basalelement = element->SpawnBasalElement(); 1159 dim = 1; 1160 break; 1161 case Domain3DEnum: 1162 if(!element->IsOnBase()) return; 1163 basalelement = element->SpawnBasalElement(); 1164 dim = 2; 1165 break; 1166 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 1167 } 1168 1169 /*Intermediaries*/ 1170 IssmDouble Jdet,weight; 1171 IssmDouble dk[3]; 1172 IssmDouble *xyz_list= NULL; 1173 1174 /*Fetch number of vertices for this finite element*/ 1175 int numvertices = basalelement->GetNumberOfVertices(); 1176 1177 /*Initialize some vectors*/ 1178 IssmDouble* dbasis = xNew<IssmDouble>(2*numvertices); 1179 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1180 int* vertexpidlist = xNew<int>(numvertices); 1181 1182 /*Retrieve all inputs we will be needing: */ 1183 basalelement->GetVerticesCoordinates(&xyz_list); 1184 basalelement->GradientIndexing(&vertexpidlist[0],control_index); 1185 Input* dragcoefficient_input = basalelement->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input); 1186 Input* weights_input = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input); 1187 1188 /* Start looping on the number of gaussian points: */ 1189 Gauss* gauss=basalelement->NewGauss(2); 1190 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1191 gauss->GaussPoint(ig); 1192 1193 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1194 basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss); 1195 weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum); 1196 1197 /*Build alpha_complement_list: */ 1198 dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss); 1199 1200 /*Build gradient vector (actually -dJ/ddrag): */ 1201 for(int i=0;i<numvertices;i++){ 1202 if(dim==2){ 1203 ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]); 1204 } 1205 else{ 1206 ge[i]+=-weight*Jdet*gauss->weight*dbasis[0*numvertices+i]*dk[0]; 1207 } 1208 _assert_(!xIsNan<IssmDouble>(ge[i])); 1209 } 1210 } 1211 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1212 1213 /*Clean up and return*/ 1214 xDelete<IssmDouble>(xyz_list); 1215 xDelete<IssmDouble>(dbasis); 1216 xDelete<IssmDouble>(ge); 1217 xDelete<int>(vertexpidlist); 1218 delete gauss; 1219 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1220 1221 }/*}}}*/ 1222 void AdjointHorizAnalysis::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1140 void AdjointHorizAnalysis::GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1141 /*WARNING: We use SSA as an estimate for now*/ 1142 this->GradientJBbarSSA(element,gradient,control_index); 1143 }/*}}}*/ 1144 void AdjointHorizAnalysis::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1223 1145 1224 1146 /*Intermediaries*/ … … 1295 1217 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1296 1218 }/*}}}*/ 1297 void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1219 void AdjointHorizAnalysis::GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1220 1221 /*Same as SSA*/ 1222 return this->GradientJBbarSSA(element,gradient,control_index); 1223 }/*}}}*/ 1224 void AdjointHorizAnalysis::GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1225 1226 /*WARNING: We use SSA as an estimate for now*/ 1227 this->GradientJBbarSSA(element,gradient,control_index); 1228 }/*}}}*/ 1229 void AdjointHorizAnalysis::GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1230 1231 /*Intermediaries*/ 1232 int domaintype,dim; 1233 Element* basalelement; 1234 1235 /*Get basal element*/ 1236 element->FindParam(&domaintype,DomainTypeEnum); 1237 switch(domaintype){ 1238 case Domain2DhorizontalEnum: 1239 basalelement = element; 1240 dim = 2; 1241 break; 1242 case Domain2DverticalEnum: 1243 if(!element->IsOnBase()) return; 1244 basalelement = element->SpawnBasalElement(); 1245 dim = 1; 1246 break; 1247 case Domain3DEnum: 1248 if(!element->IsOnBase()) return; 1249 basalelement = element->SpawnBasalElement(); 1250 dim = 2; 1251 break; 1252 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 1253 } 1254 1255 /*Intermediaries*/ 1256 IssmDouble Jdet,weight; 1257 IssmDouble thickness,dmudB; 1258 IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 1259 IssmDouble *xyz_list= NULL; 1260 1261 /*Fetch number of vertices for this finite element*/ 1262 int numvertices = basalelement->GetNumberOfVertices(); 1263 1264 /*Initialize some vectors*/ 1265 IssmDouble* basis = xNew<IssmDouble>(numvertices); 1266 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1267 int* vertexpidlist = xNew<int>(numvertices); 1268 1269 /*Retrieve all inputs we will be needing: */ 1270 basalelement->GetVerticesCoordinates(&xyz_list); 1271 basalelement->GradientIndexing(&vertexpidlist[0],control_index); 1272 Input* thickness_input = basalelement->GetInput(ThicknessEnum); _assert_(thickness_input); 1273 Input* vx_input = basalelement->GetInput(VxEnum); _assert_(vx_input); 1274 Input* vy_input = basalelement->GetInput(VyEnum); _assert_(vy_input); 1275 Input* adjointx_input = basalelement->GetInput(AdjointxEnum); _assert_(adjointx_input); 1276 Input* adjointy_input = basalelement->GetInput(AdjointyEnum); _assert_(adjointy_input); 1277 Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input); 1278 1279 /* Start looping on the number of gaussian points: */ 1280 Gauss* gauss=basalelement->NewGauss(4); 1281 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1282 gauss->GaussPoint(ig); 1283 1284 thickness_input->GetInputValue(&thickness,gauss); 1285 vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss); 1286 vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss); 1287 adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss); 1288 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss); 1289 1290 basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input); 1291 1292 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1293 basalelement->NodalFunctionsP1(basis,gauss); 1294 1295 /*Build gradient vector (actually -dJ/dB): */ 1296 for(int i=0;i<numvertices;i++){ 1297 ge[i]+=-dmudB*thickness*( 1298 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1] 1299 )*Jdet*gauss->weight*basis[i]; 1300 _assert_(!xIsNan<IssmDouble>(ge[i])); 1301 } 1302 } 1303 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1304 1305 /*Clean up and return*/ 1306 xDelete<IssmDouble>(xyz_list); 1307 xDelete<IssmDouble>(basis); 1308 xDelete<IssmDouble>(ge); 1309 xDelete<int>(vertexpidlist); 1310 delete gauss; 1311 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1312 }/*}}}*/ 1313 void AdjointHorizAnalysis::GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1314 /*WARNING: We use HO as an estimate for now*/ 1315 this->GradientJBHO(element,gradient,control_index); 1316 }/*}}}*/ 1317 void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1298 1318 1299 1319 /*Intermediaries*/ … … 1361 1381 delete gauss; 1362 1382 }/*}}}*/ 1363 void AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1364 1365 /*return if floating (gradient is 0)*/ 1366 if(element->IsFloating()) return; 1383 void AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1384 /*Intermediaries*/ 1385 int domaintype,dim; 1386 1387 /*Get domaintype*/ 1388 element->FindParam(&domaintype,DomainTypeEnum); 1389 1390 /*Intermediaries*/ 1391 IssmDouble Jdet,weight; 1392 IssmDouble thickness,dmudB; 1393 IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 1394 IssmDouble *xyz_list= NULL; 1395 1396 /*Fetch number of vertices for this finite element*/ 1397 int numvertices = element->GetNumberOfVertices(); 1398 1399 /*Initialize some vectors*/ 1400 IssmDouble* basis = xNew<IssmDouble>(numvertices); 1401 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1402 int* vertexpidlist = xNew<int>(numvertices); 1403 1404 /*Retrieve all inputs we will be needing: */ 1405 element->GetVerticesCoordinates(&xyz_list); 1406 element->GradientIndexing(&vertexpidlist[0],control_index); 1407 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 1408 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 1409 Input* vy_input = NULL; 1410 Input* adjointx_input = element->GetInput(AdjointxEnum); _assert_(adjointx_input); 1411 Input* adjointy_input = NULL; 1412 Input* rheologyb_input = element->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input); 1413 if(domaintype!=Domain2DverticalEnum){ 1414 vy_input = element->GetInput(VyEnum); _assert_(vy_input); 1415 adjointy_input = element->GetInput(AdjointyEnum); _assert_(adjointy_input); 1416 } 1417 /* Start looping on the number of gaussian points: */ 1418 Gauss* gauss=element->NewGauss(4); 1419 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1420 gauss->GaussPoint(ig); 1421 1422 thickness_input->GetInputValue(&thickness,gauss); 1423 vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss); 1424 adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss); 1425 dim=2; 1426 if(domaintype!=Domain2DverticalEnum){ 1427 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list, gauss); 1428 vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss); 1429 dim=3; 1430 } 1431 1432 element->dViscositydBHO(&dmudB,dim,xyz_list,gauss,vx_input,vy_input); 1433 1434 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 1435 element->NodalFunctionsP1(basis,gauss); 1436 1437 /*Build gradient vector (actually -dJ/dB): */ 1438 for(int i=0;i<numvertices;i++){ 1439 if(domaintype!=Domain2DverticalEnum){ 1440 ge[i]+=-dmudB*thickness*( 1441 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1] 1442 )*Jdet*gauss->weight*basis[i]; 1443 } 1444 else{ 1445 ge[i]+=-dmudB*thickness*4*dvx[0]*dadjx[0]*Jdet*gauss->weight*basis[i]; 1446 } 1447 _assert_(!xIsNan<IssmDouble>(ge[i])); 1448 } 1449 } 1450 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1451 1452 /*Clean up and return*/ 1453 xDelete<IssmDouble>(xyz_list); 1454 xDelete<IssmDouble>(basis); 1455 xDelete<IssmDouble>(ge); 1456 xDelete<int>(vertexpidlist); 1457 delete gauss; 1458 }/*}}}*/ 1459 void AdjointHorizAnalysis::GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1367 1460 1368 1461 /*Intermediaries*/ … … 1392 1485 /*Intermediaries*/ 1393 1486 IssmDouble Jdet,weight; 1394 IssmDouble drag,dalpha2dk;1395 IssmDouble vx,vy,lambda,mu;1487 IssmDouble thickness,dmudB; 1488 IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 1396 1489 IssmDouble *xyz_list= NULL; 1397 1490 … … 1404 1497 int* vertexpidlist = xNew<int>(numvertices); 1405 1498 1406 /*Build friction element, needed later: */1407 Friction* friction=new Friction(basalelement,dim);1408 1409 1499 /*Retrieve all inputs we will be needing: */ 1410 1500 basalelement->GetVerticesCoordinates(&xyz_list); 1411 1501 basalelement->GradientIndexing(&vertexpidlist[0],control_index); 1412 Input* vx_input = basalelement->GetInput(VxEnum); _assert_(vx_input); 1413 Input* vy_input = basalelement->GetInput(VyEnum); _assert_(vy_input); 1414 Input* adjointx_input = basalelement->GetInput(AdjointxEnum); _assert_(adjointx_input); 1415 Input* adjointy_input = basalelement->GetInput(AdjointyEnum); _assert_(adjointy_input); 1416 Input* dragcoeff_input = basalelement->GetInput(FrictionCoefficientEnum); _assert_(dragcoeff_input); 1502 Input* thickness_input = basalelement->GetInput(ThicknessEnum); _assert_(thickness_input); 1503 Input* vx_input = basalelement->GetInput(VxEnum); _assert_(vx_input); 1504 Input* vy_input = basalelement->GetInput(VyEnum); _assert_(vy_input); 1505 Input* adjointx_input = basalelement->GetInput(AdjointxEnum); _assert_(adjointx_input); 1506 Input* adjointy_input = basalelement->GetInput(AdjointyEnum); _assert_(adjointy_input); 1507 Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input); 1417 1508 1418 1509 /* Start looping on the number of gaussian points: */ … … 1421 1512 gauss->GaussPoint(ig); 1422 1513 1423 adjointx_input->GetInputValue(&lambda,gauss);1424 adjointy_input->GetInputValue(&mu,gauss);1425 v x_input->GetInputValue(&vx,gauss);1426 vy_input->GetInputValue(&vy,gauss);1427 dragcoeff_input->GetInputValue(&drag,gauss);1428 1429 friction->GetAlphaComplement(&dalpha2dk,gauss);1514 thickness_input->GetInputValue(&thickness,gauss); 1515 vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss); 1516 vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss); 1517 adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss); 1518 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss); 1519 1520 basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input); 1430 1521 1431 1522 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1432 1523 basalelement->NodalFunctionsP1(basis,gauss); 1433 1524 1434 /*Build gradient vector (actually -dJ/d D): */1525 /*Build gradient vector (actually -dJ/dB): */ 1435 1526 for(int i=0;i<numvertices;i++){ 1436 ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; 1527 ge[i]+=-dmudB*thickness*( 1528 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1] 1529 )*Jdet*gauss->weight*basis[i]; 1437 1530 _assert_(!xIsNan<IssmDouble>(ge[i])); 1438 1531 } … … 1446 1539 xDelete<int>(vertexpidlist); 1447 1540 delete gauss; 1448 delete friction;1449 1541 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1450 1542 }/*}}}*/ 1451 void AdjointHorizAnalysis::GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1452 1453 /*Same as SSA*/ 1454 return this->GradientJDragSSA(element,gradient,control_index); 1455 }/*}}}*/ 1456 void AdjointHorizAnalysis::GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1457 1458 /*return if floating or not on bed (gradient is 0)*/ 1543 void AdjointHorizAnalysis::GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1544 1545 /*return if floating (gradient is 0)*/ 1459 1546 if(element->IsFloating()) return; 1460 if(!element->IsOnBase()) return; 1547 1548 /*Intermediaries*/ 1549 int domaintype,dim; 1550 Element* basalelement; 1551 1552 /*Get basal element*/ 1553 element->FindParam(&domaintype,DomainTypeEnum); 1554 switch(domaintype){ 1555 case Domain2DhorizontalEnum: 1556 basalelement = element; 1557 dim = 2; 1558 break; 1559 case Domain2DverticalEnum: 1560 if(!element->IsOnBase()) return; 1561 basalelement = element->SpawnBasalElement(); 1562 dim = 1; 1563 break; 1564 case Domain3DEnum: 1565 if(!element->IsOnBase()) return; 1566 basalelement = element->SpawnBasalElement(); 1567 dim = 2; 1568 break; 1569 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 1570 } 1461 1571 1462 1572 /*Intermediaries*/ 1463 1573 IssmDouble Jdet,weight; 1464 IssmDouble drag,dalpha2dk; 1465 IssmDouble vx,vy,lambda,mu; 1466 IssmDouble *xyz_list_base= NULL; 1467 1468 int domaintype,dim; 1469 element->FindParam(&domaintype,DomainTypeEnum); 1574 IssmDouble dk[3]; 1575 IssmDouble *xyz_list= NULL; 1576 1470 1577 /*Fetch number of vertices for this finite element*/ 1471 int numvertices = element->GetNumberOfVertices();1578 int numvertices = basalelement->GetNumberOfVertices(); 1472 1579 1473 1580 /*Initialize some vectors*/ 1474 IssmDouble* basis = xNew<IssmDouble>(numvertices);1581 IssmDouble* dbasis = xNew<IssmDouble>(2*numvertices); 1475 1582 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1476 1583 int* vertexpidlist = xNew<int>(numvertices); 1477 1584 1478 /*Build friction element, needed later: */1479 if(domaintype!=Domain2DverticalEnum) dim=3;1480 else dim=2;1481 Friction* friction=new Friction(element,dim);1482 1483 1585 /*Retrieve all inputs we will be needing: */ 1484 element->GetVerticesCoordinatesBase(&xyz_list_base); 1485 element->GradientIndexing(&vertexpidlist[0],control_index); 1486 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 1487 Input* vy_input = NULL; 1488 Input* adjointx_input = element->GetInput(AdjointxEnum); _assert_(adjointx_input); 1489 Input* adjointy_input = NULL; 1490 Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum); _assert_(dragcoeff_input); 1491 if(domaintype!=Domain2DverticalEnum){ 1492 vy_input = element->GetInput(VyEnum); _assert_(vy_input); 1493 adjointy_input = element->GetInput(AdjointyEnum); _assert_(adjointy_input); 1494 } 1586 basalelement->GetVerticesCoordinates(&xyz_list); 1587 basalelement->GradientIndexing(&vertexpidlist[0],control_index); 1588 Input* dragcoefficient_input = basalelement->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input); 1589 Input* weights_input = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input); 1590 1495 1591 /* Start looping on the number of gaussian points: */ 1496 Gauss* gauss= element->NewGaussBase(4);1592 Gauss* gauss=basalelement->NewGauss(2); 1497 1593 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1498 1594 gauss->GaussPoint(ig); 1499 1595 1500 adjointx_input->GetInputValue(&lambda, gauss); 1501 vx_input->GetInputValue(&vx,gauss); 1502 if(domaintype!=Domain2DverticalEnum){ 1503 adjointy_input->GetInputValue(&mu, gauss); 1504 vy_input->GetInputValue(&vy,gauss); 1505 } 1506 dragcoeff_input->GetInputValue(&drag, gauss); 1507 1508 friction->GetAlphaComplement(&dalpha2dk,gauss); 1509 1510 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss); 1511 element->NodalFunctionsP1(basis,gauss); 1512 1513 /*Build gradient vector (actually -dJ/dD): */ 1596 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1597 basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss); 1598 weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum); 1599 1600 /*Build alpha_complement_list: */ 1601 dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss); 1602 1603 /*Build gradient vector (actually -dJ/ddrag): */ 1514 1604 for(int i=0;i<numvertices;i++){ 1515 if(domaintype!=Domain2DverticalEnum) ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; 1516 else ge[i]+=-2.*drag*dalpha2dk*(lambda*vx)*Jdet*gauss->weight*basis[i]; 1605 if(dim==2){ 1606 ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]); 1607 } 1608 else{ 1609 ge[i]+=-weight*Jdet*gauss->weight*dbasis[0*numvertices+i]*dk[0]; 1610 } 1517 1611 _assert_(!xIsNan<IssmDouble>(ge[i])); 1518 1612 } … … 1521 1615 1522 1616 /*Clean up and return*/ 1523 xDelete<IssmDouble>(xyz_list _base);1524 xDelete<IssmDouble>( basis);1617 xDelete<IssmDouble>(xyz_list); 1618 xDelete<IssmDouble>(dbasis); 1525 1619 xDelete<IssmDouble>(ge); 1526 1620 xDelete<int>(vertexpidlist); 1527 1621 delete gauss; 1528 delete friction; 1529 }/*}}}*/ 1530 void AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1622 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1623 1624 }/*}}}*/ 1625 void AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1531 1626 1532 1627 /*return if floating or not on bed (gradient is 0)*/ … … 1624 1719 delete friction; 1625 1720 }/*}}}*/ 1626 void AdjointHorizAnalysis::GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1721 void AdjointHorizAnalysis::GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1722 1723 /*Same as SSA*/ 1724 return this->GradientJDragSSA(element,gradient,control_index); 1725 }/*}}}*/ 1726 void AdjointHorizAnalysis::GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1727 1728 /*return if floating or not on bed (gradient is 0)*/ 1729 if(element->IsFloating()) return; 1730 if(!element->IsOnBase()) return; 1731 1732 /*Intermediaries*/ 1733 IssmDouble Jdet,weight; 1734 IssmDouble drag,dalpha2dk; 1735 IssmDouble vx,vy,lambda,mu; 1736 IssmDouble *xyz_list_base= NULL; 1737 1738 int domaintype,dim; 1739 element->FindParam(&domaintype,DomainTypeEnum); 1740 /*Fetch number of vertices for this finite element*/ 1741 int numvertices = element->GetNumberOfVertices(); 1742 1743 /*Initialize some vectors*/ 1744 IssmDouble* basis = xNew<IssmDouble>(numvertices); 1745 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1746 int* vertexpidlist = xNew<int>(numvertices); 1747 1748 /*Build friction element, needed later: */ 1749 if(domaintype!=Domain2DverticalEnum) dim=3; 1750 else dim=2; 1751 Friction* friction=new Friction(element,dim); 1752 1753 /*Retrieve all inputs we will be needing: */ 1754 element->GetVerticesCoordinatesBase(&xyz_list_base); 1755 element->GradientIndexing(&vertexpidlist[0],control_index); 1756 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 1757 Input* vy_input = NULL; 1758 Input* adjointx_input = element->GetInput(AdjointxEnum); _assert_(adjointx_input); 1759 Input* adjointy_input = NULL; 1760 Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum); _assert_(dragcoeff_input); 1761 if(domaintype!=Domain2DverticalEnum){ 1762 vy_input = element->GetInput(VyEnum); _assert_(vy_input); 1763 adjointy_input = element->GetInput(AdjointyEnum); _assert_(adjointy_input); 1764 } 1765 /* Start looping on the number of gaussian points: */ 1766 Gauss* gauss=element->NewGaussBase(4); 1767 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1768 gauss->GaussPoint(ig); 1769 1770 adjointx_input->GetInputValue(&lambda, gauss); 1771 vx_input->GetInputValue(&vx,gauss); 1772 if(domaintype!=Domain2DverticalEnum){ 1773 adjointy_input->GetInputValue(&mu, gauss); 1774 vy_input->GetInputValue(&vy,gauss); 1775 } 1776 dragcoeff_input->GetInputValue(&drag, gauss); 1777 1778 friction->GetAlphaComplement(&dalpha2dk,gauss); 1779 1780 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss); 1781 element->NodalFunctionsP1(basis,gauss); 1782 1783 /*Build gradient vector (actually -dJ/dD): */ 1784 for(int i=0;i<numvertices;i++){ 1785 if(domaintype!=Domain2DverticalEnum) ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; 1786 else ge[i]+=-2.*drag*dalpha2dk*(lambda*vx)*Jdet*gauss->weight*basis[i]; 1787 _assert_(!xIsNan<IssmDouble>(ge[i])); 1788 } 1789 } 1790 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1791 1792 /*Clean up and return*/ 1793 xDelete<IssmDouble>(xyz_list_base); 1794 xDelete<IssmDouble>(basis); 1795 xDelete<IssmDouble>(ge); 1796 xDelete<int>(vertexpidlist); 1797 delete gauss; 1798 delete friction; 1799 }/*}}}*/ 1800 void AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1801 1802 /*return if floating (gradient is 0)*/ 1803 if(element->IsFloating()) return; 1627 1804 1628 1805 /*Intermediaries*/ … … 1652 1829 /*Intermediaries*/ 1653 1830 IssmDouble Jdet,weight; 1654 IssmDouble thickness,dmudB; 1831 IssmDouble drag,dalpha2dk; 1832 IssmDouble vx,vy,lambda,mu; 1833 IssmDouble *xyz_list= NULL; 1834 1835 /*Fetch number of vertices for this finite element*/ 1836 int numvertices = basalelement->GetNumberOfVertices(); 1837 1838 /*Initialize some vectors*/ 1839 IssmDouble* basis = xNew<IssmDouble>(numvertices); 1840 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1841 int* vertexpidlist = xNew<int>(numvertices); 1842 1843 /*Build friction element, needed later: */ 1844 Friction* friction=new Friction(basalelement,dim); 1845 1846 /*Retrieve all inputs we will be needing: */ 1847 basalelement->GetVerticesCoordinates(&xyz_list); 1848 basalelement->GradientIndexing(&vertexpidlist[0],control_index); 1849 Input* vx_input = basalelement->GetInput(VxEnum); _assert_(vx_input); 1850 Input* vy_input = basalelement->GetInput(VyEnum); _assert_(vy_input); 1851 Input* adjointx_input = basalelement->GetInput(AdjointxEnum); _assert_(adjointx_input); 1852 Input* adjointy_input = basalelement->GetInput(AdjointyEnum); _assert_(adjointy_input); 1853 Input* dragcoeff_input = basalelement->GetInput(FrictionCoefficientEnum); _assert_(dragcoeff_input); 1854 1855 /* Start looping on the number of gaussian points: */ 1856 Gauss* gauss=basalelement->NewGauss(4); 1857 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1858 gauss->GaussPoint(ig); 1859 1860 adjointx_input->GetInputValue(&lambda, gauss); 1861 adjointy_input->GetInputValue(&mu, gauss); 1862 vx_input->GetInputValue(&vx,gauss); 1863 vy_input->GetInputValue(&vy,gauss); 1864 dragcoeff_input->GetInputValue(&drag, gauss); 1865 1866 friction->GetAlphaComplement(&dalpha2dk,gauss); 1867 1868 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1869 basalelement->NodalFunctionsP1(basis,gauss); 1870 1871 /*Build gradient vector (actually -dJ/dD): */ 1872 for(int i=0;i<numvertices;i++){ 1873 ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; 1874 _assert_(!xIsNan<IssmDouble>(ge[i])); 1875 } 1876 } 1877 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1878 1879 /*Clean up and return*/ 1880 xDelete<IssmDouble>(xyz_list); 1881 xDelete<IssmDouble>(basis); 1882 xDelete<IssmDouble>(ge); 1883 xDelete<int>(vertexpidlist); 1884 delete gauss; 1885 delete friction; 1886 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1887 }/*}}}*/ 1888 void AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1889 1890 /*Intermediaries*/ 1891 int domaintype,dim; 1892 Element* basalelement; 1893 1894 /*Get basal element*/ 1895 element->FindParam(&domaintype,DomainTypeEnum); 1896 switch(domaintype){ 1897 case Domain2DhorizontalEnum: 1898 basalelement = element; 1899 dim = 2; 1900 break; 1901 case Domain2DverticalEnum: 1902 if(!element->IsOnBase()) return; 1903 basalelement = element->SpawnBasalElement(); 1904 dim = 1; 1905 break; 1906 case Domain3DEnum: 1907 if(!element->IsOnBase()) return; 1908 basalelement = element->SpawnBasalElement(); 1909 dim = 2; 1910 break; 1911 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 1912 } 1913 1914 /*Intermediaries*/ 1915 IssmDouble Jdet,weight; 1916 IssmDouble thickness,dmudD; 1655 1917 IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 1656 1918 IssmDouble *xyz_list= NULL; … … 1685 1947 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss); 1686 1948 1687 basalelement->dViscosityd BSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);1949 basalelement->dViscositydDSSA(&dmudD,dim,xyz_list,gauss,vx_input,vy_input); 1688 1950 1689 1951 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1690 1952 basalelement->NodalFunctionsP1(basis,gauss); 1691 1953 1692 /*Build gradient vector (actually -dJ/dB): */1693 1954 for(int i=0;i<numvertices;i++){ 1694 ge[i]+=-dmud B*thickness*(1955 ge[i]+=-dmudD*thickness*( 1695 1956 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1] 1696 1957 )*Jdet*gauss->weight*basis[i]; … … 1708 1969 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1709 1970 }/*}}}*/ 1710 void AdjointHorizAnalysis::GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1711 1712 /*Same as SSA*/ 1713 return this->GradientJBbarSSA(element,gradient,control_index); 1714 }/*}}}*/ 1715 void AdjointHorizAnalysis::GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1716 1717 /*WARNING: We use SSA as an estimate for now*/ 1718 this->GradientJBbarSSA(element,gradient,control_index); 1719 }/*}}}*/ 1720 void AdjointHorizAnalysis::GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1721 /*WARNING: We use SSA as an estimate for now*/ 1722 this->GradientJBbarSSA(element,gradient,control_index); 1723 }/*}}}*/ 1724 void AdjointHorizAnalysis::GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1725 1726 /*Intermediaries*/ 1727 int domaintype,dim; 1728 Element* basalelement; 1729 1730 /*Get basal element*/ 1731 element->FindParam(&domaintype,DomainTypeEnum); 1732 switch(domaintype){ 1733 case Domain2DhorizontalEnum: 1734 basalelement = element; 1735 dim = 2; 1736 break; 1737 case Domain2DverticalEnum: 1738 if(!element->IsOnBase()) return; 1739 basalelement = element->SpawnBasalElement(); 1740 dim = 1; 1741 break; 1742 case Domain3DEnum: 1743 if(!element->IsOnBase()) return; 1744 basalelement = element->SpawnBasalElement(); 1745 dim = 2; 1746 break; 1747 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 1748 } 1749 1750 /*Intermediaries*/ 1751 IssmDouble Jdet,weight; 1752 IssmDouble thickness,dmudB; 1753 IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 1754 IssmDouble *xyz_list= NULL; 1755 1756 /*Fetch number of vertices for this finite element*/ 1757 int numvertices = basalelement->GetNumberOfVertices(); 1758 1759 /*Initialize some vectors*/ 1760 IssmDouble* basis = xNew<IssmDouble>(numvertices); 1761 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1762 int* vertexpidlist = xNew<int>(numvertices); 1763 1764 /*Retrieve all inputs we will be needing: */ 1765 basalelement->GetVerticesCoordinates(&xyz_list); 1766 basalelement->GradientIndexing(&vertexpidlist[0],control_index); 1767 Input* thickness_input = basalelement->GetInput(ThicknessEnum); _assert_(thickness_input); 1768 Input* vx_input = basalelement->GetInput(VxEnum); _assert_(vx_input); 1769 Input* vy_input = basalelement->GetInput(VyEnum); _assert_(vy_input); 1770 Input* adjointx_input = basalelement->GetInput(AdjointxEnum); _assert_(adjointx_input); 1771 Input* adjointy_input = basalelement->GetInput(AdjointyEnum); _assert_(adjointy_input); 1772 Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input); 1773 1774 /* Start looping on the number of gaussian points: */ 1775 Gauss* gauss=basalelement->NewGauss(4); 1776 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1777 gauss->GaussPoint(ig); 1778 1779 thickness_input->GetInputValue(&thickness,gauss); 1780 vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss); 1781 vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss); 1782 adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss); 1783 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss); 1784 1785 basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input); 1786 1787 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1788 basalelement->NodalFunctionsP1(basis,gauss); 1789 1790 /*Build gradient vector (actually -dJ/dB): */ 1791 for(int i=0;i<numvertices;i++){ 1792 ge[i]+=-dmudB*thickness*( 1793 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1] 1794 )*Jdet*gauss->weight*basis[i]; 1795 _assert_(!xIsNan<IssmDouble>(ge[i])); 1796 } 1797 } 1798 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1799 1800 /*Clean up and return*/ 1801 xDelete<IssmDouble>(xyz_list); 1802 xDelete<IssmDouble>(basis); 1803 xDelete<IssmDouble>(ge); 1804 xDelete<int>(vertexpidlist); 1805 delete gauss; 1806 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1807 }/*}}}*/ 1808 void AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1809 /*Intermediaries*/ 1810 int domaintype,dim; 1811 1812 /*Get domaintype*/ 1813 element->FindParam(&domaintype,DomainTypeEnum); 1814 1815 /*Intermediaries*/ 1816 IssmDouble Jdet,weight; 1817 IssmDouble thickness,dmudB; 1818 IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 1819 IssmDouble *xyz_list= NULL; 1820 1821 /*Fetch number of vertices for this finite element*/ 1822 int numvertices = element->GetNumberOfVertices(); 1823 1824 /*Initialize some vectors*/ 1825 IssmDouble* basis = xNew<IssmDouble>(numvertices); 1826 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1827 int* vertexpidlist = xNew<int>(numvertices); 1828 1829 /*Retrieve all inputs we will be needing: */ 1830 element->GetVerticesCoordinates(&xyz_list); 1831 element->GradientIndexing(&vertexpidlist[0],control_index); 1832 Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input); 1833 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 1834 Input* vy_input = NULL; 1835 Input* adjointx_input = element->GetInput(AdjointxEnum); _assert_(adjointx_input); 1836 Input* adjointy_input = NULL; 1837 Input* rheologyb_input = element->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input); 1838 if(domaintype!=Domain2DverticalEnum){ 1839 vy_input = element->GetInput(VyEnum); _assert_(vy_input); 1840 adjointy_input = element->GetInput(AdjointyEnum); _assert_(adjointy_input); 1841 } 1842 /* Start looping on the number of gaussian points: */ 1843 Gauss* gauss=element->NewGauss(4); 1844 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1845 gauss->GaussPoint(ig); 1846 1847 thickness_input->GetInputValue(&thickness,gauss); 1848 vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss); 1849 adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss); 1850 dim=2; 1851 if(domaintype!=Domain2DverticalEnum){ 1852 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list, gauss); 1853 vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss); 1854 dim=3; 1855 } 1856 1857 element->dViscositydBHO(&dmudB,dim,xyz_list,gauss,vx_input,vy_input); 1858 1859 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 1860 element->NodalFunctionsP1(basis,gauss); 1861 1862 /*Build gradient vector (actually -dJ/dB): */ 1863 for(int i=0;i<numvertices;i++){ 1864 if(domaintype!=Domain2DverticalEnum){ 1865 ge[i]+=-dmudB*thickness*( 1866 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1] 1867 )*Jdet*gauss->weight*basis[i]; 1868 } 1869 else{ 1870 ge[i]+=-dmudB*thickness*4*dvx[0]*dadjx[0]*Jdet*gauss->weight*basis[i]; 1871 } 1872 _assert_(!xIsNan<IssmDouble>(ge[i])); 1873 } 1874 } 1875 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1876 1877 /*Clean up and return*/ 1878 xDelete<IssmDouble>(xyz_list); 1879 xDelete<IssmDouble>(basis); 1880 xDelete<IssmDouble>(ge); 1881 xDelete<int>(vertexpidlist); 1882 delete gauss; 1883 }/*}}}*/ 1884 void AdjointHorizAnalysis::GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1885 /*WARNING: We use HO as an estimate for now*/ 1886 this->GradientJBHO(element,gradient,control_index); 1887 }/*}}}*/ 1888 void AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/ 1889 1890 /*Intermediaries*/ 1891 int domaintype,dim; 1892 Element* basalelement; 1893 1894 /*Get basal element*/ 1895 element->FindParam(&domaintype,DomainTypeEnum); 1896 switch(domaintype){ 1897 case Domain2DhorizontalEnum: 1898 basalelement = element; 1899 dim = 2; 1900 break; 1901 case Domain2DverticalEnum: 1902 if(!element->IsOnBase()) return; 1903 basalelement = element->SpawnBasalElement(); 1904 dim = 1; 1905 break; 1906 case Domain3DEnum: 1907 if(!element->IsOnBase()) return; 1908 basalelement = element->SpawnBasalElement(); 1909 dim = 2; 1910 break; 1911 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 1912 } 1913 1914 /*Intermediaries*/ 1915 IssmDouble Jdet,weight; 1916 IssmDouble thickness,dmudD; 1917 IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 1918 IssmDouble *xyz_list= NULL; 1919 1920 /*Fetch number of vertices for this finite element*/ 1921 int numvertices = basalelement->GetNumberOfVertices(); 1922 1923 /*Initialize some vectors*/ 1924 IssmDouble* basis = xNew<IssmDouble>(numvertices); 1925 IssmDouble* ge = xNewZeroInit<IssmDouble>(numvertices); 1926 int* vertexpidlist = xNew<int>(numvertices); 1927 1928 /*Retrieve all inputs we will be needing: */ 1929 basalelement->GetVerticesCoordinates(&xyz_list); 1930 basalelement->GradientIndexing(&vertexpidlist[0],control_index); 1931 Input* thickness_input = basalelement->GetInput(ThicknessEnum); _assert_(thickness_input); 1932 Input* vx_input = basalelement->GetInput(VxEnum); _assert_(vx_input); 1933 Input* vy_input = basalelement->GetInput(VyEnum); _assert_(vy_input); 1934 Input* adjointx_input = basalelement->GetInput(AdjointxEnum); _assert_(adjointx_input); 1935 Input* adjointy_input = basalelement->GetInput(AdjointyEnum); _assert_(adjointy_input); 1936 Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input); 1937 1938 /* Start looping on the number of gaussian points: */ 1939 Gauss* gauss=basalelement->NewGauss(4); 1940 for(int ig=gauss->begin();ig<gauss->end();ig++){ 1941 gauss->GaussPoint(ig); 1942 1943 thickness_input->GetInputValue(&thickness,gauss); 1944 vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss); 1945 vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss); 1946 adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss); 1947 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss); 1948 1949 basalelement->dViscositydDSSA(&dmudD,dim,xyz_list,gauss,vx_input,vy_input); 1950 1951 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss); 1952 basalelement->NodalFunctionsP1(basis,gauss); 1953 1954 for(int i=0;i<numvertices;i++){ 1955 ge[i]+=-dmudD*thickness*( 1956 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1] 1957 )*Jdet*gauss->weight*basis[i]; 1958 _assert_(!xIsNan<IssmDouble>(ge[i])); 1959 } 1960 } 1961 gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL); 1962 1963 /*Clean up and return*/ 1964 xDelete<IssmDouble>(xyz_list); 1965 xDelete<IssmDouble>(basis); 1966 xDelete<IssmDouble>(ge); 1967 xDelete<int>(vertexpidlist); 1968 delete gauss; 1969 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 1970 }/*}}}*/ 1971 void AdjointHorizAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 1971 void AdjointHorizAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 1972 1972 int approximation; 1973 1973 element->GetInputValue(&approximation,ApproximationEnum); … … 1979 1979 } 1980 1980 }/*}}}*/ 1981 void AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/ 1981 void AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/ 1982 int i,fe_FS; 1983 int* vdoflist=NULL; 1984 int* pdoflist=NULL; 1985 IssmDouble FSreconditioning; 1986 1987 int domaintype,dim; 1988 element->FindParam(&domaintype,DomainTypeEnum); 1989 switch(domaintype){ 1990 case Domain2DhorizontalEnum: 1991 dim = 3; 1992 break; 1993 case Domain2DverticalEnum: 1994 dim = 2; 1995 break; 1996 case Domain3DEnum: 1997 dim = 3; 1998 break; 1999 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 2000 } 2001 2002 2003 /*Fetch number of nodes and dof for this finite element*/ 2004 int vnumnodes = element->NumberofNodesVelocity(); 2005 int pnumnodes = element->NumberofNodesPressure(); 2006 int vnumdof = vnumnodes*dim; 2007 int pnumdof = pnumnodes*1; 2008 2009 /*Initialize values*/ 2010 IssmDouble* values = xNew<IssmDouble>(vnumdof+pnumdof); 2011 IssmDouble* lambdax = xNew<IssmDouble>(vnumnodes); 2012 IssmDouble* lambday = xNew<IssmDouble>(vnumnodes); 2013 IssmDouble* lambdaz = xNew<IssmDouble>(vnumnodes); 2014 IssmDouble* lambdap = xNew<IssmDouble>(pnumnodes); 2015 2016 int* cs_list = xNew<int>(vnumnodes+pnumnodes); 2017 if(dim==2) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum; 2018 else for(i=0;i<vnumnodes;i++) cs_list[i] = XYZEnum; 2019 for(i=0;i<pnumnodes;i++) cs_list[vnumnodes+i] = PressureEnum; 2020 2021 /*Get dof list: */ 2022 element->GetDofListVelocity(&vdoflist,GsetEnum); 2023 element->GetDofListPressure(&pdoflist,GsetEnum); 2024 2025 /*Use the dof list to index into the solution vector: */ 2026 for(i=0;i<vnumdof;i++) values[i] =solution[vdoflist[i]]; 2027 for(i=0;i<pnumdof;i++) values[vnumdof+i]=solution[pdoflist[i]]; 2028 2029 /*Transform solution in Cartesian Space*/ 2030 element->TransformSolutionCoord(values,cs_list); 2031 2032 /*fill in all arrays: */ 2033 for(i=0;i<vnumnodes;i++){ 2034 lambdax[i] = values[i*dim+0]; if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector"); 2035 lambday[i] = values[i*dim+1]; if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector"); 2036 if(dim==3){ 2037 lambdaz[i] = values[i*dim+2]; if(xIsNan<IssmDouble>(lambdaz[i])) _error_("NaN found in solution vector"); 2038 } 2039 } 2040 for(i=0;i<pnumnodes;i++){ 2041 lambdap[i] = values[vnumdof+i]; if(xIsNan<IssmDouble>(lambdap[i])) _error_("NaN found in solution vector"); 2042 } 2043 2044 /*Recondition pressure and compute vel: */ 2045 element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum); 2046 for(i=0;i<pnumnodes;i++) lambdap[i]=lambdap[i]*FSreconditioning; 2047 2048 /*Add vx and vy as inputs to the tria element: */ 2049 element->AddInput(AdjointxEnum,lambdax,element->VelocityInterpolation()); 2050 element->AddInput(AdjointyEnum,lambday,element->VelocityInterpolation()); 2051 if(domaintype!=Domain2DverticalEnum) element->AddInput(AdjointzEnum,lambdaz,element->VelocityInterpolation()); 2052 2053 element->FindParam(&fe_FS,FlowequationFeFSEnum); 2054 if(fe_FS!=LATaylorHoodEnum && fe_FS!=LACrouzeixRaviartEnum) 2055 element->AddInput(AdjointpEnum,lambdap,element->PressureInterpolation()); 2056 2057 /*Free ressources:*/ 2058 xDelete<int>(vdoflist); 2059 xDelete<int>(pdoflist); 2060 xDelete<int>(cs_list); 2061 xDelete<IssmDouble>(lambdap); 2062 xDelete<IssmDouble>(lambdaz); 2063 xDelete<IssmDouble>(lambday); 2064 xDelete<IssmDouble>(lambdax); 2065 xDelete<IssmDouble>(values); 2066 }/*}}}*/ 2067 void AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/ 1982 2068 int i; 1983 2069 int* doflist=NULL; … … 2025 2111 xDelete<int>(doflist); 2026 2112 }/*}}}*/ 2027 void AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/ 2028 int i,fe_FS; 2029 int* vdoflist=NULL; 2030 int* pdoflist=NULL; 2031 IssmDouble FSreconditioning; 2032 2033 int domaintype,dim; 2034 element->FindParam(&domaintype,DomainTypeEnum); 2035 switch(domaintype){ 2036 case Domain2DhorizontalEnum: 2037 dim = 3; 2038 break; 2039 case Domain2DverticalEnum: 2040 dim = 2; 2041 break; 2042 case Domain3DEnum: 2043 dim = 3; 2044 break; 2045 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet"); 2046 } 2047 2048 2049 /*Fetch number of nodes and dof for this finite element*/ 2050 int vnumnodes = element->NumberofNodesVelocity(); 2051 int pnumnodes = element->NumberofNodesPressure(); 2052 int vnumdof = vnumnodes*dim; 2053 int pnumdof = pnumnodes*1; 2054 2055 /*Initialize values*/ 2056 IssmDouble* values = xNew<IssmDouble>(vnumdof+pnumdof); 2057 IssmDouble* lambdax = xNew<IssmDouble>(vnumnodes); 2058 IssmDouble* lambday = xNew<IssmDouble>(vnumnodes); 2059 IssmDouble* lambdaz = xNew<IssmDouble>(vnumnodes); 2060 IssmDouble* lambdap = xNew<IssmDouble>(pnumnodes); 2061 2062 int* cs_list = xNew<int>(vnumnodes+pnumnodes); 2063 if(dim==2) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum; 2064 else for(i=0;i<vnumnodes;i++) cs_list[i] = XYZEnum; 2065 for(i=0;i<pnumnodes;i++) cs_list[vnumnodes+i] = PressureEnum; 2066 2067 /*Get dof list: */ 2068 element->GetDofListVelocity(&vdoflist,GsetEnum); 2069 element->GetDofListPressure(&pdoflist,GsetEnum); 2070 2071 /*Use the dof list to index into the solution vector: */ 2072 for(i=0;i<vnumdof;i++) values[i] =solution[vdoflist[i]]; 2073 for(i=0;i<pnumdof;i++) values[vnumdof+i]=solution[pdoflist[i]]; 2074 2075 /*Transform solution in Cartesian Space*/ 2076 element->TransformSolutionCoord(values,cs_list); 2077 2078 /*fill in all arrays: */ 2079 for(i=0;i<vnumnodes;i++){ 2080 lambdax[i] = values[i*dim+0]; if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector"); 2081 lambday[i] = values[i*dim+1]; if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector"); 2082 if(dim==3){ 2083 lambdaz[i] = values[i*dim+2]; if(xIsNan<IssmDouble>(lambdaz[i])) _error_("NaN found in solution vector"); 2084 } 2085 } 2086 for(i=0;i<pnumnodes;i++){ 2087 lambdap[i] = values[vnumdof+i]; if(xIsNan<IssmDouble>(lambdap[i])) _error_("NaN found in solution vector"); 2088 } 2089 2090 /*Recondition pressure and compute vel: */ 2091 element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum); 2092 for(i=0;i<pnumnodes;i++) lambdap[i]=lambdap[i]*FSreconditioning; 2093 2094 /*Add vx and vy as inputs to the tria element: */ 2095 element->AddInput(AdjointxEnum,lambdax,element->VelocityInterpolation()); 2096 element->AddInput(AdjointyEnum,lambday,element->VelocityInterpolation()); 2097 if(domaintype!=Domain2DverticalEnum) element->AddInput(AdjointzEnum,lambdaz,element->VelocityInterpolation()); 2098 2099 element->FindParam(&fe_FS,FlowequationFeFSEnum); 2100 if(fe_FS!=LATaylorHoodEnum && fe_FS!=LACrouzeixRaviartEnum) 2101 element->AddInput(AdjointpEnum,lambdap,element->PressureInterpolation()); 2102 2103 /*Free ressources:*/ 2104 xDelete<int>(vdoflist); 2105 xDelete<int>(pdoflist); 2106 xDelete<int>(cs_list); 2107 xDelete<IssmDouble>(lambdap); 2108 xDelete<IssmDouble>(lambdaz); 2109 xDelete<IssmDouble>(lambday); 2110 xDelete<IssmDouble>(lambdax); 2111 xDelete<IssmDouble>(values); 2112 }/*}}}*/ 2113 void AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 2113 void AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 2114 2114 /*Default, do nothing*/ 2115 2115 return; -
issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h
r18835 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 25 25 ElementMatrix* CreateJacobianMatrix(Element* element); 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 ElementMatrix* CreateKMatrixFS(Element* element); 28 ElementMatrix* CreateKMatrixHO(Element* element); 29 ElementMatrix* CreateKMatrixL1L2(Element* element); 27 30 ElementMatrix* CreateKMatrixSSA(Element* element); 28 ElementMatrix* CreateKMatrixL1L2(Element* element);29 ElementMatrix* CreateKMatrixHO(Element* element);30 ElementMatrix* CreateKMatrixFS(Element* element);31 31 ElementVector* CreatePVector(Element* element); 32 ElementVector* CreatePVector SSA(Element* element);32 ElementVector* CreatePVectorFS(Element* element); 33 33 ElementVector* CreatePVectorL1L2(Element* element); 34 34 ElementVector* CreatePVectorHO(Element* element); 35 ElementVector* CreatePVector FS(Element* element);36 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);37 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);38 void GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);39 void GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);40 void GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);41 void GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);42 void GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);43 void GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index);44 void GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index);45 void GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);46 void GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);47 void GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index);48 void GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index);49 void GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);50 void GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index);51 void GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index);52 void GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);53 void InputUpdateFromSolution(IssmDouble* solution,Element* element);54 void UpdateConstraints(FemModel* femmodel);55 void InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element);56 void InputUpdateFromSolutionFS(IssmDouble* solution,Element* element);35 ElementVector* CreatePVectorSSA(Element* element); 36 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 37 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 38 void GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index); 39 void GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index); 40 void GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index); 41 void GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index); 42 void GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index); 43 void GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index); 44 void GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index); 45 void GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index); 46 void GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index); 47 void GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index); 48 void GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index); 49 void GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index); 50 void GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index); 51 void GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index); 52 void GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index); 53 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 54 void InputUpdateFromSolutionFS(IssmDouble* solution,Element* element); 55 void InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element); 56 void UpdateConstraints(FemModel* femmodel); 57 57 }; 58 58 #endif -
issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp
r18715 r18930 6 6 7 7 /*Model processing*/ 8 void Balancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 11 int finiteelement = P1Enum; 12 IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,Balancethickness2AnalysisEnum,finiteelement); 13 14 }/*}}}*/ 15 void Balancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 16 17 }/*}}}*/ 18 void Balancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 19 20 int finiteelement = P1Enum; 21 ::CreateNodes(nodes,iomodel,Balancethickness2AnalysisEnum,finiteelement); 22 }/*}}}*/ 8 23 int Balancethickness2Analysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 24 return 1; 10 }/*}}}*/11 void Balancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 25 }/*}}}*/ 13 26 void Balancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 38 51 39 52 }/*}}}*/ 40 void Balancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 41 42 int finiteelement = P1Enum; 43 ::CreateNodes(nodes,iomodel,Balancethickness2AnalysisEnum,finiteelement); 44 }/*}}}*/ 45 void Balancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 46 47 48 int finiteelement = P1Enum; 49 IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,Balancethickness2AnalysisEnum,finiteelement); 50 51 }/*}}}*/ 52 void Balancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 53 53 void Balancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 54 54 }/*}}}*/ 55 55 … … 62 62 return NULL; 63 63 }/*}}}*/ 64 ElementMatrix* Balancethickness2Analysis::CreateJacobianMatrix(Element* element){/*{{{*/ 65 _error_("Not implemented"); 66 }/*}}}*/ 67 ElementMatrix* Balancethickness2Analysis::CreateKMatrix(Element* element){/*{{{*/ 68 69 /*Intermediaries */ 70 IssmDouble Jdet,D0,omega; 71 IssmDouble* xyz_list = NULL; 72 73 /*Fetch number of nodes and dof for this finite element*/ 74 int numnodes = element->GetNumberOfNodes(); 75 76 /*Initialize Element vector and other vectors*/ 77 ElementMatrix* Ke = element->NewElementMatrix(); 78 IssmDouble* dbasis = xNew<IssmDouble>(2*numnodes); 79 80 /*Retrieve all inputs and parameters*/ 81 element->GetVerticesCoordinates(&xyz_list); 82 Input* omega_input = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input); 83 Input* D0_input = element->GetInput(BalancethicknessD0Enum); 84 if(!D0_input){ 85 this->CreateD0(element); 86 D0_input = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input); 87 } 88 89 /* Start looping on the number of gaussian points: */ 90 Gauss* gauss=element->NewGauss(2); 91 for(int ig=gauss->begin();ig<gauss->end();ig++){ 92 gauss->GaussPoint(ig); 93 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 94 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 95 D0_input->GetInputValue(&D0,gauss); 96 omega_input->GetInputValue(&omega,gauss); 97 98 for(int i=0;i<numnodes;i++){ 99 for(int j=0;j<numnodes;j++){ 100 Ke->values[i*numnodes+j] += D0*exp(omega)*gauss->weight*Jdet*(dbasis[0*numnodes+i]*dbasis[0*numnodes+j] + dbasis[1*numnodes+i]*dbasis[1*numnodes+j]); 101 } 102 } 103 } 104 105 /*Clean up and return*/ 106 xDelete<IssmDouble>(xyz_list); 107 xDelete<IssmDouble>(dbasis); 108 delete gauss; 109 return Ke; 110 }/*}}}*/ 111 ElementVector* Balancethickness2Analysis::CreatePVector(Element* element){/*{{{*/ 112 113 /*Intermediaries */ 114 IssmDouble dhdt,mb,ms,Jdet; 115 IssmDouble* xyz_list = NULL; 116 117 /*Fetch number of nodes and dof for this finite element*/ 118 int numnodes = element->GetNumberOfNodes(); 119 120 /*Initialize Element vector and other vectors*/ 121 ElementVector* pe = element->NewElementVector(); 122 IssmDouble* basis = xNew<IssmDouble>(numnodes); 123 124 /*Retrieve all inputs and parameters*/ 125 element->GetVerticesCoordinates(&xyz_list); 126 Input* ms_input = element->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(ms_input); 127 Input* mb_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(mb_input); 128 Input* dhdt_input = element->GetInput(BalancethicknessThickeningRateEnum); _assert_(dhdt_input); 129 130 /* Start looping on the number of gaussian points: */ 131 Gauss* gauss=element->NewGauss(2); 132 for(int ig=gauss->begin();ig<gauss->end();ig++){ 133 gauss->GaussPoint(ig); 134 135 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 136 element->NodalFunctions(basis,gauss); 137 138 ms_input->GetInputValue(&ms,gauss); 139 mb_input->GetInputValue(&mb,gauss); 140 dhdt_input->GetInputValue(&dhdt,gauss); 141 142 for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*( 143 (ms-mb-dhdt)*basis[i] 144 ); 145 } 146 147 /*Clean up and return*/ 148 xDelete<IssmDouble>(xyz_list); 149 xDelete<IssmDouble>(basis); 150 delete gauss; 151 return pe; 152 }/*}}}*/ 153 void Balancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 154 element->GetSolutionFromInputsOneDof(solution,SurfaceEnum); 155 }/*}}}*/ 156 void Balancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 157 _error_("Not implemented yet"); 158 }/*}}}*/ 159 void Balancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 160 161 /*Intermediaries*/ 162 IssmDouble ds[2],s,b,D; 163 IssmDouble* xyz_list = NULL; 164 165 //element->InputUpdateFromSolutionOneDof(solution,ThicknessEnum); 166 element->InputUpdateFromSolutionOneDof(solution,SurfaceEnum); 167 168 /*Fetch number of vertices and allocate velocity vectors*/ 169 int numvertices = element->GetNumberOfVertices(); 170 IssmDouble* vel_list = xNew<IssmDouble>(numvertices); 171 IssmDouble* vx_list = xNew<IssmDouble>(numvertices); 172 IssmDouble* vy_list = xNew<IssmDouble>(numvertices); 173 174 /*Retrieve all inputs and parameters*/ 175 element->GetVerticesCoordinates(&xyz_list); 176 Input* D_input = element->GetInput(BalancethicknessDiffusionCoefficientEnum); 177 Input* H_input = element->GetInput(ThicknessEnum); _assert_(H_input); 178 Input* s_input = element->GetInput(SurfaceEnum); _assert_(s_input); 179 Input* b_input = element->GetInput(BaseEnum); _assert_(b_input); 180 181 /*Calculate velocities*/ 182 Gauss* gauss=element->NewGauss(); 183 for(int iv=0;iv<numvertices;iv++){ 184 gauss->GaussVertex(iv); 185 186 if(D_input){ 187 D_input->GetInputValue(&D,gauss); 188 } 189 else{ 190 D = 0.; 191 } 192 b_input->GetInputValue(&b,gauss); 193 s_input->GetInputValue(&s,gauss); 194 s_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss); 195 196 vx_list[iv] = -1./(s-b)*D*ds[0]; 197 vy_list[iv] = -1./(s-b)*D*ds[1]; 198 vel_list[iv] = sqrt(pow(vx_list[iv],2) + pow(vy_list[iv],2)); 199 } 200 201 /*Add vx and vy as inputs to the tria element: */ 202 element->AddInput(VxEnum,vx_list,P1Enum); 203 element->AddInput(VyEnum,vy_list,P1Enum); 204 element->AddInput(VelEnum,vel_list,P1Enum); 205 206 /*Free ressources:*/ 207 delete gauss; 208 xDelete<IssmDouble>(vy_list); 209 xDelete<IssmDouble>(vx_list); 210 xDelete<IssmDouble>(vel_list); 211 xDelete<IssmDouble>(xyz_list); 212 }/*}}}*/ 213 void Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 214 /*Default, do nothing*/ 215 return; 216 }/*}}}*/ 217 218 /*Specifics*/ 219 void Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/ 64 void Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/ 220 65 221 66 /*Intermediaries */ … … 281 126 delete gauss; 282 127 }/*}}}*/ 128 ElementMatrix* Balancethickness2Analysis::CreateJacobianMatrix(Element* element){/*{{{*/ 129 _error_("Not implemented"); 130 }/*}}}*/ 131 ElementMatrix* Balancethickness2Analysis::CreateKMatrix(Element* element){/*{{{*/ 132 133 /*Intermediaries */ 134 IssmDouble Jdet,D0,omega; 135 IssmDouble* xyz_list = NULL; 136 137 /*Fetch number of nodes and dof for this finite element*/ 138 int numnodes = element->GetNumberOfNodes(); 139 140 /*Initialize Element vector and other vectors*/ 141 ElementMatrix* Ke = element->NewElementMatrix(); 142 IssmDouble* dbasis = xNew<IssmDouble>(2*numnodes); 143 144 /*Retrieve all inputs and parameters*/ 145 element->GetVerticesCoordinates(&xyz_list); 146 Input* omega_input = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input); 147 Input* D0_input = element->GetInput(BalancethicknessD0Enum); 148 if(!D0_input){ 149 this->CreateD0(element); 150 D0_input = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input); 151 } 152 153 /* Start looping on the number of gaussian points: */ 154 Gauss* gauss=element->NewGauss(2); 155 for(int ig=gauss->begin();ig<gauss->end();ig++){ 156 gauss->GaussPoint(ig); 157 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 158 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 159 D0_input->GetInputValue(&D0,gauss); 160 omega_input->GetInputValue(&omega,gauss); 161 162 for(int i=0;i<numnodes;i++){ 163 for(int j=0;j<numnodes;j++){ 164 Ke->values[i*numnodes+j] += D0*exp(omega)*gauss->weight*Jdet*(dbasis[0*numnodes+i]*dbasis[0*numnodes+j] + dbasis[1*numnodes+i]*dbasis[1*numnodes+j]); 165 } 166 } 167 } 168 169 /*Clean up and return*/ 170 xDelete<IssmDouble>(xyz_list); 171 xDelete<IssmDouble>(dbasis); 172 delete gauss; 173 return Ke; 174 }/*}}}*/ 175 ElementVector* Balancethickness2Analysis::CreatePVector(Element* element){/*{{{*/ 176 177 /*Intermediaries */ 178 IssmDouble dhdt,mb,ms,Jdet; 179 IssmDouble* xyz_list = NULL; 180 181 /*Fetch number of nodes and dof for this finite element*/ 182 int numnodes = element->GetNumberOfNodes(); 183 184 /*Initialize Element vector and other vectors*/ 185 ElementVector* pe = element->NewElementVector(); 186 IssmDouble* basis = xNew<IssmDouble>(numnodes); 187 188 /*Retrieve all inputs and parameters*/ 189 element->GetVerticesCoordinates(&xyz_list); 190 Input* ms_input = element->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(ms_input); 191 Input* mb_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(mb_input); 192 Input* dhdt_input = element->GetInput(BalancethicknessThickeningRateEnum); _assert_(dhdt_input); 193 194 /* Start looping on the number of gaussian points: */ 195 Gauss* gauss=element->NewGauss(2); 196 for(int ig=gauss->begin();ig<gauss->end();ig++){ 197 gauss->GaussPoint(ig); 198 199 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 200 element->NodalFunctions(basis,gauss); 201 202 ms_input->GetInputValue(&ms,gauss); 203 mb_input->GetInputValue(&mb,gauss); 204 dhdt_input->GetInputValue(&dhdt,gauss); 205 206 for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*( 207 (ms-mb-dhdt)*basis[i] 208 ); 209 } 210 211 /*Clean up and return*/ 212 xDelete<IssmDouble>(xyz_list); 213 xDelete<IssmDouble>(basis); 214 delete gauss; 215 return pe; 216 }/*}}}*/ 217 void Balancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 218 element->GetSolutionFromInputsOneDof(solution,SurfaceEnum); 219 }/*}}}*/ 220 void Balancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 221 _error_("Not implemented yet"); 222 }/*}}}*/ 223 void Balancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 224 225 /*Intermediaries*/ 226 IssmDouble ds[2],s,b,D; 227 IssmDouble* xyz_list = NULL; 228 229 //element->InputUpdateFromSolutionOneDof(solution,ThicknessEnum); 230 element->InputUpdateFromSolutionOneDof(solution,SurfaceEnum); 231 232 /*Fetch number of vertices and allocate velocity vectors*/ 233 int numvertices = element->GetNumberOfVertices(); 234 IssmDouble* vel_list = xNew<IssmDouble>(numvertices); 235 IssmDouble* vx_list = xNew<IssmDouble>(numvertices); 236 IssmDouble* vy_list = xNew<IssmDouble>(numvertices); 237 238 /*Retrieve all inputs and parameters*/ 239 element->GetVerticesCoordinates(&xyz_list); 240 Input* D_input = element->GetInput(BalancethicknessDiffusionCoefficientEnum); 241 Input* H_input = element->GetInput(ThicknessEnum); _assert_(H_input); 242 Input* s_input = element->GetInput(SurfaceEnum); _assert_(s_input); 243 Input* b_input = element->GetInput(BaseEnum); _assert_(b_input); 244 245 /*Calculate velocities*/ 246 Gauss* gauss=element->NewGauss(); 247 for(int iv=0;iv<numvertices;iv++){ 248 gauss->GaussVertex(iv); 249 250 if(D_input){ 251 D_input->GetInputValue(&D,gauss); 252 } 253 else{ 254 D = 0.; 255 } 256 b_input->GetInputValue(&b,gauss); 257 s_input->GetInputValue(&s,gauss); 258 s_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss); 259 260 vx_list[iv] = -1./(s-b)*D*ds[0]; 261 vy_list[iv] = -1./(s-b)*D*ds[1]; 262 vel_list[iv] = sqrt(pow(vx_list[iv],2) + pow(vy_list[iv],2)); 263 } 264 265 /*Add vx and vy as inputs to the tria element: */ 266 element->AddInput(VxEnum,vx_list,P1Enum); 267 element->AddInput(VyEnum,vy_list,P1Enum); 268 element->AddInput(VelEnum,vel_list,P1Enum); 269 270 /*Free ressources:*/ 271 delete gauss; 272 xDelete<IssmDouble>(vy_list); 273 xDelete<IssmDouble>(vx_list); 274 xDelete<IssmDouble>(vel_list); 275 xDelete<IssmDouble>(xyz_list); 276 }/*}}}*/ 277 void Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 278 /*Default, do nothing*/ 279 return; 280 }/*}}}*/ -
issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.h
r18565 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ 23 23 void Core(FemModel* femmodel); 24 24 ElementVector* CreateDVector(Element* element); 25 void CreateD0(Element* element); 25 26 ElementMatrix* CreateJacobianMatrix(Element* element); 26 27 ElementMatrix* CreateKMatrix(Element* element); 27 28 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 33 /*Specifics*/ 34 void CreateD0(Element* element); 29 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 30 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 31 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 32 void UpdateConstraints(FemModel* femmodel); 35 33 }; 36 34 #endif -
issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp
r18068 r18930 6 6 7 7 /*Model processing*/ 8 void BalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 /*Fetch parameters: */ 11 int stabilization; 12 iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum); 13 14 /*Do not add constraints in DG*/ 15 if(stabilization!=3){ 16 IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancethicknessAnalysisEnum,P1Enum); 17 } 18 19 }/*}}}*/ 20 void BalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 21 22 /*Intermediary*/ 23 int element; 24 int stabilization; 25 26 /*Fetch parameters: */ 27 iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum); 28 29 /*Loads only in DG*/ 30 if (stabilization==3){ 31 32 /*Get faces and elements*/ 33 CreateFaces(iomodel); 34 iomodel->FetchData(1,ThicknessEnum); 35 36 /*First load data:*/ 37 for(int i=0;i<iomodel->numberoffaces;i++){ 38 39 /*Get left and right elements*/ 40 element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2] 41 42 /*Now, if this element is not in the partition, pass: */ 43 if(!iomodel->my_elements[element]) continue; 44 45 /* Add load */ 46 loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,BalancethicknessAnalysisEnum)); 47 } 48 49 /*Free data: */ 50 iomodel->DeleteData(1,ThicknessEnum); 51 } 52 }/*}}}*/ 53 void BalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 54 55 int stabilization; 56 iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum); 57 58 /*Check in 3d*/ 59 if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet"); 60 61 /*First fetch data: */ 62 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 63 if(stabilization!=3){ 64 ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1Enum); 65 } 66 else{ 67 ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1DGEnum); 68 } 69 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 70 }/*}}}*/ 8 71 int BalancethicknessAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 72 return 1; 10 }/*}}}*/11 void BalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 parameters->AddObject(iomodel->CopyConstantObject(BalancethicknessStabilizationEnum));13 73 }/*}}}*/ 14 74 void BalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 50 110 } 51 111 }/*}}}*/ 52 void BalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 53 54 int stabilization; 55 iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum); 56 57 /*Check in 3d*/ 58 if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet"); 59 60 /*First fetch data: */ 61 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 62 if(stabilization!=3){ 63 ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1Enum); 64 } 65 else{ 66 ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1DGEnum); 67 } 68 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 69 }/*}}}*/ 70 void BalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 71 72 /*Fetch parameters: */ 73 int stabilization; 74 iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum); 75 76 /*Do not add constraints in DG*/ 77 if(stabilization!=3){ 78 IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancethicknessAnalysisEnum,P1Enum); 79 } 80 81 }/*}}}*/ 82 void BalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 83 84 /*Intermediary*/ 85 int element; 86 int stabilization; 87 88 /*Fetch parameters: */ 89 iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum); 90 91 /*Loads only in DG*/ 92 if (stabilization==3){ 93 94 /*Get faces and elements*/ 95 CreateFaces(iomodel); 96 iomodel->FetchData(1,ThicknessEnum); 97 98 /*First load data:*/ 99 for(int i=0;i<iomodel->numberoffaces;i++){ 100 101 /*Get left and right elements*/ 102 element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2] 103 104 /*Now, if this element is not in the partition, pass: */ 105 if(!iomodel->my_elements[element]) continue; 106 107 /* Add load */ 108 loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,BalancethicknessAnalysisEnum)); 109 } 110 111 /*Free data: */ 112 iomodel->DeleteData(1,ThicknessEnum); 113 } 112 void BalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 113 parameters->AddObject(iomodel->CopyConstantObject(BalancethicknessStabilizationEnum)); 114 114 }/*}}}*/ 115 115 … … 421 421 return pe; 422 422 }/*}}}*/ 423 void BalancethicknessAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/423 void BalancethicknessAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 424 424 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 425 425 * For node i, Bi can be expressed in the actual coordinate system … … 448 448 xDelete<IssmDouble>(basis); 449 449 }/*}}}*/ 450 void BalancethicknessAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/450 void BalancethicknessAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 451 451 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 452 452 * For node i, Bi' can be expressed in the actual coordinate system … … 476 476 477 477 }/*}}}*/ 478 void BalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/478 void BalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 479 479 _error_("not implemented yet"); 480 480 }/*}}}*/ 481 void BalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/481 void BalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 482 482 /* WARNING: this gradient is valid for Soft balance thickness only */ 483 483 … … 595 595 596 596 }/*}}}*/ 597 void BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/597 void BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 598 598 599 599 int domaintype; … … 609 609 } 610 610 }/*}}}*/ 611 void BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/611 void BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 612 612 /*Default, do nothing*/ 613 613 return; -
issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 30 30 ElementVector* CreatePVectorCG(Element* element); 31 31 ElementVector* CreatePVectorDG(Element* element); 32 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);33 void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);34 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);35 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);36 void InputUpdateFromSolution(IssmDouble* solution,Element* element);37 void UpdateConstraints(FemModel* femmodel);32 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 33 void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 34 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 35 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 36 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 37 void UpdateConstraints(FemModel* femmodel); 38 38 }; 39 39 #endif -
issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp
r18593 r18930 6 6 7 7 /*Model processing*/ 8 void BalancevelocityAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 /*No constraints for now*/ 11 //IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancevelocityAnalysisEnum,P1Enum); 12 }/*}}}*/ 13 void BalancevelocityAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 14 15 /*No loads*/ 16 }/*}}}*/ 17 void BalancevelocityAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 18 19 /*Check in 3d*/ 20 if(iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet"); 21 22 /*First fetch data: */ 23 ::CreateNodes(nodes,iomodel,BalancevelocityAnalysisEnum,P1Enum); 24 }/*}}}*/ 8 25 int BalancevelocityAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 26 return 1; 10 }/*}}}*/11 void BalancevelocityAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 27 }/*}}}*/ 13 28 void BalancevelocityAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 38 53 } 39 54 }/*}}}*/ 40 void BalancevelocityAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 41 42 /*Check in 3d*/ 43 if(iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet"); 44 45 /*First fetch data: */ 46 ::CreateNodes(nodes,iomodel,BalancevelocityAnalysisEnum,P1Enum); 47 }/*}}}*/ 48 void BalancevelocityAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 49 50 /*No constraints for now*/ 51 //IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancevelocityAnalysisEnum,P1Enum); 52 }/*}}}*/ 53 void BalancevelocityAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 54 55 /*No loads*/ 55 void BalancevelocityAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 56 56 }/*}}}*/ 57 57 … … 238 238 return pe; 239 239 }/*}}}*/ 240 void BalancevelocityAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/240 void BalancevelocityAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 241 241 _error_("not implemented yet"); 242 242 }/*}}}*/ 243 void BalancevelocityAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/243 void BalancevelocityAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 244 244 _error_("Not implemented yet"); 245 245 }/*}}}*/ 246 void BalancevelocityAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/246 void BalancevelocityAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 247 247 248 248 int domaintype; … … 258 258 } 259 259 }/*}}}*/ 260 void BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/260 void BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 261 261 /*Default, do nothing*/ 262 262 return; -
issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void InputUpdateFromSolution(IssmDouble* solution,Element* element);31 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 32 }; 33 33 #endif -
issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp
r18736 r18930 6 6 7 7 /*Model processing*/ 8 void DamageEvolutionAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 int finiteelement; 11 iomodel->Constant(&finiteelement,DamageElementinterpEnum); 12 13 IoModelToConstraintsx(constraints,iomodel,DamageSpcdamageEnum,DamageEvolutionAnalysisEnum,finiteelement); 14 15 }/*}}}*/ 16 void DamageEvolutionAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 17 18 /*Nothing for now*/ 19 20 }/*}}}*/ 21 void DamageEvolutionAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 22 23 int finiteelement; 24 25 iomodel->Constant(&finiteelement,DamageElementinterpEnum); 26 ::CreateNodes(nodes,iomodel,DamageEvolutionAnalysisEnum,finiteelement); 27 }/*}}}*/ 8 28 int DamageEvolutionAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 29 return 1; 30 }/*}}}*/ 31 void DamageEvolutionAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ 32 33 int finiteelement; 34 bool islevelset; 35 36 iomodel->Constant(&finiteelement,DamageElementinterpEnum); 37 iomodel->Constant(&islevelset,TransientIslevelsetEnum); 38 39 /*Update elements: */ 40 int counter=0; 41 for(int i=0;i<iomodel->numberofelements;i++){ 42 if(iomodel->my_elements[i]){ 43 Element* element=(Element*)elements->GetObjectByOffset(counter); 44 element->Update(i,iomodel,analysis_counter,analysis_type,finiteelement); 45 counter++; 46 } 47 } 48 49 /*What input do I need to run my damage evolution model?*/ 50 iomodel->FetchDataToInput(elements,VxEnum); 51 iomodel->FetchDataToInput(elements,VyEnum); 52 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchDataToInput(elements,VzEnum); 53 iomodel->FetchDataToInput(elements,DamageDEnum); 54 iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum); 55 iomodel->FetchDataToInput(elements,PressureEnum); 56 57 if(islevelset){ 58 iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum); 59 } 60 10 61 }/*}}}*/ 11 62 void DamageEvolutionAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ … … 45 96 46 97 }/*}}}*/ 47 void DamageEvolutionAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/48 49 int finiteelement;50 bool islevelset;51 52 iomodel->Constant(&finiteelement,DamageElementinterpEnum);53 iomodel->Constant(&islevelset,TransientIslevelsetEnum);54 55 /*Update elements: */56 int counter=0;57 for(int i=0;i<iomodel->numberofelements;i++){58 if(iomodel->my_elements[i]){59 Element* element=(Element*)elements->GetObjectByOffset(counter);60 element->Update(i,iomodel,analysis_counter,analysis_type,finiteelement);61 counter++;62 }63 }64 65 /*What input do I need to run my damage evolution model?*/66 iomodel->FetchDataToInput(elements,VxEnum);67 iomodel->FetchDataToInput(elements,VyEnum);68 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchDataToInput(elements,VzEnum);69 iomodel->FetchDataToInput(elements,DamageDEnum);70 iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);71 iomodel->FetchDataToInput(elements,PressureEnum);72 73 if(islevelset){74 iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);75 }76 77 }/*}}}*/78 void DamageEvolutionAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/79 80 int finiteelement;81 82 iomodel->Constant(&finiteelement,DamageElementinterpEnum);83 ::CreateNodes(nodes,iomodel,DamageEvolutionAnalysisEnum,finiteelement);84 }/*}}}*/85 void DamageEvolutionAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/86 87 int finiteelement;88 iomodel->Constant(&finiteelement,DamageElementinterpEnum);89 90 IoModelToConstraintsx(constraints,iomodel,DamageSpcdamageEnum,DamageEvolutionAnalysisEnum,finiteelement);91 92 }/*}}}*/93 void DamageEvolutionAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/94 95 /*Nothing for now*/96 97 }/*}}}*/98 98 99 99 /*Finite Element Analysis*/ 100 100 void DamageEvolutionAnalysis::Core(FemModel* femmodel){/*{{{*/ 101 101 _error_("not implemented"); 102 }/*}}}*/ 103 void DamageEvolutionAnalysis::CreateDamageFInputExp(Element* element){/*{{{*/ 104 105 /*Intermediaries */ 106 IssmDouble epsf,stress_threshold,eps0; 107 IssmDouble damage,B,n,epseff; 108 IssmDouble eps_xx,eps_yy,eps_xy,eps1,eps2,epstmp; 109 int domaintype,damagelaw; 110 111 /*Fetch number of vertices and allocate output*/ 112 int numnodes = element->GetNumberOfNodes(); 113 IssmDouble* f = xNew<IssmDouble>(numnodes); 114 115 /*retrieve parameters:*/ 116 element->FindParam(&epsf,DamageC1Enum); 117 element->FindParam(&stress_threshold,DamageStressThresholdEnum); 118 element->FindParam(&domaintype,DomainTypeEnum); 119 element->FindParam(&damagelaw,DamageLawEnum); 120 121 /*Compute stress tensor: */ 122 element->ComputeStrainRate(); 123 124 /*retrieve what we need: */ 125 Input* eps_xx_input = element->GetInput(StrainRatexxEnum); _assert_(eps_xx_input); 126 Input* eps_xy_input = element->GetInput(StrainRatexyEnum); _assert_(eps_xy_input); 127 Input* eps_yy_input = element->GetInput(StrainRateyyEnum); _assert_(eps_yy_input); 128 Input* n_input=element->GetInput(MaterialsRheologyNEnum); _assert_(n_input); 129 Input* damage_input = NULL; 130 Input* B_input = NULL; 131 if(domaintype==Domain2DhorizontalEnum){ 132 damage_input = element->GetInput(DamageDbarEnum); _assert_(damage_input); 133 B_input=element->GetInput(MaterialsRheologyBbarEnum); _assert_(B_input); 134 } 135 else{ 136 damage_input = element->GetInput(DamageDEnum); _assert_(damage_input); 137 B_input=element->GetInput(MaterialsRheologyBEnum); _assert_(B_input); 138 } 139 140 /*Calculate damage evolution source term: */ 141 Gauss* gauss=element->NewGauss(); 142 for (int i=0;i<numnodes;i++){ 143 gauss->GaussNode(element->GetElementType(),i); 144 145 eps_xx_input->GetInputValue(&eps_xx,gauss); 146 eps_xy_input->GetInputValue(&eps_xy,gauss); 147 eps_yy_input->GetInputValue(&eps_yy,gauss); 148 B_input->GetInputValue(&B,gauss); 149 n_input->GetInputValue(&n,gauss); 150 damage_input->GetInputValue(&damage,gauss); 151 152 /*Calculate principal effective strain rates*/ 153 eps1=(eps_xx+eps_yy)/2.+sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2)); 154 eps2=(eps_xx+eps_yy)/2.-sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2)); 155 if(fabs(eps2)>fabs(eps1)){epstmp=eps2; eps2=eps1; eps1=epstmp;} 156 157 /*Calculate effective strain rate and threshold strain rate*/ 158 epseff=1./sqrt(2.)*sqrt(eps1*eps1-eps1*eps2+eps2*eps2); 159 eps0=pow(stress_threshold/B,n); 160 161 if(epseff>eps0){ 162 f[i]=1.-pow(eps0/epseff,1./n)*exp(-(epseff-eps0)/(epsf-eps0))-damage; 163 } 164 else f[i]=0; 165 } 166 167 /*Add input*/ 168 element->AddInput(DamageFEnum,f,element->GetElementType()); 169 170 /*Clean up and return*/ 171 xDelete<IssmDouble>(f); 172 delete gauss; 173 }/*}}}*/ 174 void DamageEvolutionAnalysis::CreateDamageFInputPralong(Element* element){/*{{{*/ 175 176 /*Intermediaries */ 177 IssmDouble c1,c2,c3,healing,stress_threshold; 178 IssmDouble s_xx,s_xy,s_xz,s_yy,s_yz,s_zz,s1,s2,s3,stmp; 179 IssmDouble J2s,Chi,Psi,PosPsi,NegPsi; 180 IssmDouble damage,tau_xx,tau_xy,tau_xz,tau_yy,tau_yz,tau_zz,stressMaxPrincipal; 181 int equivstress,domaintype,damagelaw,dim; 182 183 /*Fetch number of vertices and allocate output*/ 184 int numnodes = element->GetNumberOfNodes(); 185 IssmDouble* f = xNew<IssmDouble>(numnodes); 186 187 /*retrieve parameters:*/ 188 element->FindParam(&c1,DamageC1Enum); 189 element->FindParam(&c2,DamageC2Enum); 190 element->FindParam(&c3,DamageC3Enum); 191 element->FindParam(&healing,DamageHealingEnum); 192 element->FindParam(&stress_threshold,DamageStressThresholdEnum); 193 element->FindParam(&domaintype,DomainTypeEnum); 194 element->FindParam(&damagelaw,DamageLawEnum); 195 196 /*Get problem dimension*/ 197 switch(domaintype){ 198 case Domain2DhorizontalEnum: dim = 2; break; 199 case Domain3DEnum: dim = 3; break; 200 default: _error_("not implemented"); 201 } 202 /*Compute stress tensor and Stress Max Principal: */ 203 element->ComputeDeviatoricStressTensor(); 204 if(dim==3){ 205 /*Only works in 3d because the pressure is defined*/ 206 element->StressMaxPrincipalCreateInput(); 207 } 208 /*retrieve what we need: */ 209 Input* tau_xx_input = element->GetInput(DeviatoricStressxxEnum); _assert_(tau_xx_input); 210 Input* tau_xy_input = element->GetInput(DeviatoricStressxyEnum); _assert_(tau_xy_input); 211 Input* tau_yy_input = element->GetInput(DeviatoricStressyyEnum); _assert_(tau_yy_input); 212 Input* tau_xz_input = NULL; 213 Input* tau_yz_input = NULL; 214 Input* tau_zz_input = NULL; 215 Input* stressMaxPrincipal_input = NULL; 216 if(dim==3){ 217 tau_xz_input = element->GetInput(DeviatoricStressxzEnum); _assert_(tau_xz_input); 218 tau_yz_input = element->GetInput(DeviatoricStressyzEnum); _assert_(tau_yz_input); 219 tau_zz_input = element->GetInput(DeviatoricStresszzEnum); _assert_(tau_zz_input); 220 stressMaxPrincipal_input = element->GetInput(StressMaxPrincipalEnum); _assert_(stressMaxPrincipal_input); 221 } 222 Input* damage_input = NULL; 223 if(domaintype==Domain2DhorizontalEnum){ 224 damage_input = element->GetInput(DamageDbarEnum); _assert_(damage_input); 225 } 226 else{ 227 damage_input = element->GetInput(DamageDEnum); _assert_(damage_input); 228 } 229 230 /*retrieve the desired type of equivalent stress*/ 231 element->FindParam(&equivstress,DamageEquivStressEnum); 232 233 /*Calculate damage evolution source term: */ 234 Gauss* gauss=element->NewGauss(); 235 for (int i=0;i<numnodes;i++){ 236 gauss->GaussNode(element->GetElementType(),i); 237 238 damage_input->GetInputValue(&damage,gauss); 239 tau_xx_input->GetInputValue(&tau_xx,gauss); 240 tau_xy_input->GetInputValue(&tau_xy,gauss); 241 tau_yy_input->GetInputValue(&tau_yy,gauss); 242 if(dim==3){ 243 tau_xz_input->GetInputValue(&tau_xz,gauss); 244 tau_yz_input->GetInputValue(&tau_yz,gauss); 245 tau_zz_input->GetInputValue(&tau_zz,gauss); 246 } 247 /*Calculate effective stress components*/ 248 s_xx=tau_xx/(1.-damage); 249 s_xy=tau_xy/(1.-damage); 250 s_yy=tau_yy/(1.-damage); 251 if(dim==3){ 252 s_xz=tau_xz/(1.-damage); 253 s_yz=tau_yz/(1.-damage); 254 s_zz=tau_zz/(1.-damage); 255 } 256 /*Calculate principal effective stresses*/ 257 if(dim==2){ 258 s1=(s_xx+s_yy)/2.+sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2)); 259 s2=(s_xx+s_yy)/2.-sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2)); 260 if(fabs(s2)>fabs(s1)){stmp=s2; s2=s1; s1=stmp;} 261 262 if(equivstress==0){ /* von Mises */ 263 Chi=sqrt(s1*s1-s1*s2+s2*s2); 264 } 265 else if(equivstress==1){ /* max principal stress */ 266 Chi=s1; 267 } 268 Psi=Chi-stress_threshold; 269 NegPsi=max(-Chi,0.); /* healing only for compressive stresses */ 270 271 if(damagelaw==1){ 272 PosPsi=max(Psi,0.); 273 f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3); 274 } 275 else if(damagelaw==2){ 276 PosPsi=max(Psi,1.); 277 f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3); 278 } 279 else _error_("damage law not supported"); 280 } 281 else{ 282 if(equivstress==1){/* max principal stress */ 283 stressMaxPrincipal_input->GetInputValue(&stressMaxPrincipal,gauss); 284 Chi=stressMaxPrincipal/(1.-damage); 285 } 286 else if(equivstress==0){/* von Mises */ 287 Chi=sqrt(((s_xx-s_yy)*(s_xx-s_yy)+(s_yy-s_zz)*(s_yy-s_zz)+(s_zz-s_xx)*(s_zz-s_xx)+6.*(s_xy*s_xy+s_yz*s_yz+s_xz*s_xz))/2.); 288 } 289 Psi=Chi-stress_threshold; 290 NegPsi=max(-Chi,0.); /* healing only for compressive stresses */ 291 if(damagelaw==1){ 292 PosPsi=max(Psi,0.); 293 f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3); 294 } 295 else if(damagelaw==2){ 296 PosPsi=max(Psi,1.); 297 f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3); 298 } 299 else _error_("damage law not supported"); 300 } 301 } 302 /*Add input*/ 303 element->AddInput(DamageFEnum,f,element->GetElementType()); 304 305 /*Clean up and return*/ 306 xDelete<IssmDouble>(f); 307 delete gauss; 102 308 }/*}}}*/ 103 309 ElementVector* DamageEvolutionAnalysis::CreateDVector(Element* element){/*{{{*/ … … 342 548 return pe; 343 549 }/*}}}*/ 344 void DamageEvolutionAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/550 void DamageEvolutionAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 345 551 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 346 552 * For node i, Bi can be expressed in the actual coordinate system … … 370 576 xDelete<IssmDouble>(basis); 371 577 }/*}}}*/ 372 void DamageEvolutionAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/578 void DamageEvolutionAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 373 579 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 374 580 * For node i, Bi' can be expressed in the actual coordinate system … … 399 605 400 606 }/*}}}*/ 401 void DamageEvolutionAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/607 void DamageEvolutionAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 402 608 _error_("not implemented yet"); 403 609 }/*}}}*/ 404 void DamageEvolutionAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/610 void DamageEvolutionAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 405 611 _error_("Not implemented yet"); 406 612 }/*}}}*/ 407 void DamageEvolutionAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/613 void DamageEvolutionAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 408 614 409 615 int domaintype; … … 445 651 xDelete<int>(doflist); 446 652 }/*}}}*/ 447 void DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/653 void DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 448 654 /*Default, do nothing*/ 449 655 bool islevelset; … … 454 660 return; 455 661 }/*}}}*/ 456 457 /*Intermediaries*/458 void DamageEvolutionAnalysis::CreateDamageFInputPralong(Element* element){/*{{{*/459 460 /*Intermediaries */461 IssmDouble c1,c2,c3,healing,stress_threshold;462 IssmDouble s_xx,s_xy,s_xz,s_yy,s_yz,s_zz,s1,s2,s3,stmp;463 IssmDouble J2s,Chi,Psi,PosPsi,NegPsi;464 IssmDouble damage,tau_xx,tau_xy,tau_xz,tau_yy,tau_yz,tau_zz,stressMaxPrincipal;465 int equivstress,domaintype,damagelaw,dim;466 467 /*Fetch number of vertices and allocate output*/468 int numnodes = element->GetNumberOfNodes();469 IssmDouble* f = xNew<IssmDouble>(numnodes);470 471 /*retrieve parameters:*/472 element->FindParam(&c1,DamageC1Enum);473 element->FindParam(&c2,DamageC2Enum);474 element->FindParam(&c3,DamageC3Enum);475 element->FindParam(&healing,DamageHealingEnum);476 element->FindParam(&stress_threshold,DamageStressThresholdEnum);477 element->FindParam(&domaintype,DomainTypeEnum);478 element->FindParam(&damagelaw,DamageLawEnum);479 480 /*Get problem dimension*/481 switch(domaintype){482 case Domain2DhorizontalEnum: dim = 2; break;483 case Domain3DEnum: dim = 3; break;484 default: _error_("not implemented");485 }486 /*Compute stress tensor and Stress Max Principal: */487 element->ComputeDeviatoricStressTensor();488 if(dim==3){489 /*Only works in 3d because the pressure is defined*/490 element->StressMaxPrincipalCreateInput();491 }492 /*retrieve what we need: */493 Input* tau_xx_input = element->GetInput(DeviatoricStressxxEnum); _assert_(tau_xx_input);494 Input* tau_xy_input = element->GetInput(DeviatoricStressxyEnum); _assert_(tau_xy_input);495 Input* tau_yy_input = element->GetInput(DeviatoricStressyyEnum); _assert_(tau_yy_input);496 Input* tau_xz_input = NULL;497 Input* tau_yz_input = NULL;498 Input* tau_zz_input = NULL;499 Input* stressMaxPrincipal_input = NULL;500 if(dim==3){501 tau_xz_input = element->GetInput(DeviatoricStressxzEnum); _assert_(tau_xz_input);502 tau_yz_input = element->GetInput(DeviatoricStressyzEnum); _assert_(tau_yz_input);503 tau_zz_input = element->GetInput(DeviatoricStresszzEnum); _assert_(tau_zz_input);504 stressMaxPrincipal_input = element->GetInput(StressMaxPrincipalEnum); _assert_(stressMaxPrincipal_input);505 }506 Input* damage_input = NULL;507 if(domaintype==Domain2DhorizontalEnum){508 damage_input = element->GetInput(DamageDbarEnum); _assert_(damage_input);509 }510 else{511 damage_input = element->GetInput(DamageDEnum); _assert_(damage_input);512 }513 514 /*retrieve the desired type of equivalent stress*/515 element->FindParam(&equivstress,DamageEquivStressEnum);516 517 /*Calculate damage evolution source term: */518 Gauss* gauss=element->NewGauss();519 for (int i=0;i<numnodes;i++){520 gauss->GaussNode(element->GetElementType(),i);521 522 damage_input->GetInputValue(&damage,gauss);523 tau_xx_input->GetInputValue(&tau_xx,gauss);524 tau_xy_input->GetInputValue(&tau_xy,gauss);525 tau_yy_input->GetInputValue(&tau_yy,gauss);526 if(dim==3){527 tau_xz_input->GetInputValue(&tau_xz,gauss);528 tau_yz_input->GetInputValue(&tau_yz,gauss);529 tau_zz_input->GetInputValue(&tau_zz,gauss);530 }531 /*Calculate effective stress components*/532 s_xx=tau_xx/(1.-damage);533 s_xy=tau_xy/(1.-damage);534 s_yy=tau_yy/(1.-damage);535 if(dim==3){536 s_xz=tau_xz/(1.-damage);537 s_yz=tau_yz/(1.-damage);538 s_zz=tau_zz/(1.-damage);539 }540 /*Calculate principal effective stresses*/541 if(dim==2){542 s1=(s_xx+s_yy)/2.+sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));543 s2=(s_xx+s_yy)/2.-sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));544 if(fabs(s2)>fabs(s1)){stmp=s2; s2=s1; s1=stmp;}545 546 if(equivstress==0){ /* von Mises */547 Chi=sqrt(s1*s1-s1*s2+s2*s2);548 }549 else if(equivstress==1){ /* max principal stress */550 Chi=s1;551 }552 Psi=Chi-stress_threshold;553 NegPsi=max(-Chi,0.); /* healing only for compressive stresses */554 555 if(damagelaw==1){556 PosPsi=max(Psi,0.);557 f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);558 }559 else if(damagelaw==2){560 PosPsi=max(Psi,1.);561 f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);562 }563 else _error_("damage law not supported");564 }565 else{566 if(equivstress==1){/* max principal stress */567 stressMaxPrincipal_input->GetInputValue(&stressMaxPrincipal,gauss);568 Chi=stressMaxPrincipal/(1.-damage);569 }570 else if(equivstress==0){/* von Mises */571 Chi=sqrt(((s_xx-s_yy)*(s_xx-s_yy)+(s_yy-s_zz)*(s_yy-s_zz)+(s_zz-s_xx)*(s_zz-s_xx)+6.*(s_xy*s_xy+s_yz*s_yz+s_xz*s_xz))/2.);572 }573 Psi=Chi-stress_threshold;574 NegPsi=max(-Chi,0.); /* healing only for compressive stresses */575 if(damagelaw==1){576 PosPsi=max(Psi,0.);577 f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);578 }579 else if(damagelaw==2){580 PosPsi=max(Psi,1.);581 f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);582 }583 else _error_("damage law not supported");584 }585 }586 /*Add input*/587 element->AddInput(DamageFEnum,f,element->GetElementType());588 589 /*Clean up and return*/590 xDelete<IssmDouble>(f);591 delete gauss;592 }/*}}}*/593 void DamageEvolutionAnalysis::CreateDamageFInputExp(Element* element){/*{{{*/594 595 /*Intermediaries */596 IssmDouble epsf,stress_threshold,eps0;597 IssmDouble damage,B,n,epseff;598 IssmDouble eps_xx,eps_yy,eps_xy,eps1,eps2,epstmp;599 int domaintype,damagelaw;600 601 /*Fetch number of vertices and allocate output*/602 int numnodes = element->GetNumberOfNodes();603 IssmDouble* f = xNew<IssmDouble>(numnodes);604 605 /*retrieve parameters:*/606 element->FindParam(&epsf,DamageC1Enum);607 element->FindParam(&stress_threshold,DamageStressThresholdEnum);608 element->FindParam(&domaintype,DomainTypeEnum);609 element->FindParam(&damagelaw,DamageLawEnum);610 611 /*Compute stress tensor: */612 element->ComputeStrainRate();613 614 /*retrieve what we need: */615 Input* eps_xx_input = element->GetInput(StrainRatexxEnum); _assert_(eps_xx_input);616 Input* eps_xy_input = element->GetInput(StrainRatexyEnum); _assert_(eps_xy_input);617 Input* eps_yy_input = element->GetInput(StrainRateyyEnum); _assert_(eps_yy_input);618 Input* n_input=element->GetInput(MaterialsRheologyNEnum); _assert_(n_input);619 Input* damage_input = NULL;620 Input* B_input = NULL;621 if(domaintype==Domain2DhorizontalEnum){622 damage_input = element->GetInput(DamageDbarEnum); _assert_(damage_input);623 B_input=element->GetInput(MaterialsRheologyBbarEnum); _assert_(B_input);624 }625 else{626 damage_input = element->GetInput(DamageDEnum); _assert_(damage_input);627 B_input=element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);628 }629 630 /*Calculate damage evolution source term: */631 Gauss* gauss=element->NewGauss();632 for (int i=0;i<numnodes;i++){633 gauss->GaussNode(element->GetElementType(),i);634 635 eps_xx_input->GetInputValue(&eps_xx,gauss);636 eps_xy_input->GetInputValue(&eps_xy,gauss);637 eps_yy_input->GetInputValue(&eps_yy,gauss);638 B_input->GetInputValue(&B,gauss);639 n_input->GetInputValue(&n,gauss);640 damage_input->GetInputValue(&damage,gauss);641 642 /*Calculate principal effective strain rates*/643 eps1=(eps_xx+eps_yy)/2.+sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));644 eps2=(eps_xx+eps_yy)/2.-sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));645 if(fabs(eps2)>fabs(eps1)){epstmp=eps2; eps2=eps1; eps1=epstmp;}646 647 /*Calculate effective strain rate and threshold strain rate*/648 epseff=1./sqrt(2.)*sqrt(eps1*eps1-eps1*eps2+eps2*eps2);649 eps0=pow(stress_threshold/B,n);650 651 if(epseff>eps0){652 f[i]=1.-pow(eps0/epseff,1./n)*exp(-(epseff-eps0)/(epsf-eps0))-damage;653 }654 else f[i]=0;655 }656 657 /*Add input*/658 element->AddInput(DamageFEnum,f,element->GetElementType());659 660 /*Clean up and return*/661 xDelete<IssmDouble>(f);662 delete gauss;663 }/*}}}*/ -
issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h
r18136 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ 23 23 void Core(FemModel* femmodel); 24 void CreateDamageFInputExp(Element* element); 25 void CreateDamageFInputPralong(Element* element); 24 26 ElementVector* CreateDVector(Element* element); 25 27 ElementMatrix* CreateJacobianMatrix(Element* element); 26 28 ElementMatrix* CreateKMatrix(Element* element); 27 29 ElementVector* CreatePVector(Element* element); 28 void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss); 29 void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss); 30 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 31 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 32 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 33 void UpdateConstraints(FemModel* femmodel); 34 35 /*Intermediaries*/ 36 void CreateDamageFInputPralong(Element* element); 37 void CreateDamageFInputExp(Element* element); 30 void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss); 31 void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss); 32 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 33 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 34 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 35 void UpdateConstraints(FemModel* femmodel); 38 36 }; 39 37 #endif -
issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp
r18804 r18930 7 7 8 8 /*Model processing*/ 9 void EnthalpyAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 10 11 /*Intermediary*/ 12 int count; 13 int M,N; 14 bool spcpresent = false; 15 IssmDouble heatcapacity; 16 IssmDouble referencetemperature; 17 18 /*Output*/ 19 IssmDouble *spcvector = NULL; 20 IssmDouble* times=NULL; 21 IssmDouble* values=NULL; 22 23 /*Fetch parameters: */ 24 iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum); 25 iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum); 26 27 /*return if 2d mesh*/ 28 if(iomodel->domaintype==Domain2DhorizontalEnum) return; 29 30 /*Fetch data: */ 31 iomodel->FetchData(&spcvector,&M,&N,ThermalSpctemperatureEnum); 32 33 //FIX ME: SHOULD USE IOMODELCREATECONSTRAINTS 34 /*Transient or static?:*/ 35 if(M==iomodel->numberofvertices){ 36 /*static: just create Constraints objects*/ 37 count=0; 38 39 for(int i=0;i<iomodel->numberofvertices;i++){ 40 /*keep only this partition's nodes:*/ 41 if((iomodel->my_vertices[i])){ 42 43 if (!xIsNan<IssmDouble>(spcvector[i])){ 44 45 constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,heatcapacity*(spcvector[i]-referencetemperature),EnthalpyAnalysisEnum)); 46 count++; 47 48 } 49 } 50 } 51 } 52 else if (M==(iomodel->numberofvertices+1)){ 53 /*transient: create transient SpcTransient objects. Same logic, except we need to retrieve 54 * various times and values to initialize an SpcTransient object: */ 55 count=0; 56 57 /*figure out times: */ 58 times=xNew<IssmDouble>(N); 59 for(int j=0;j<N;j++){ 60 times[j]=spcvector[(M-1)*N+j]; 61 } 62 63 /*Create constraints from x,y,z: */ 64 for(int i=0;i<iomodel->numberofvertices;i++){ 65 66 /*keep only this partition's nodes:*/ 67 if((iomodel->my_vertices[i])){ 68 69 /*figure out times and values: */ 70 values=xNew<IssmDouble>(N); 71 spcpresent=false; 72 for(int j=0;j<N;j++){ 73 values[j]=heatcapacity*(spcvector[i*N+j]-referencetemperature); 74 if(!xIsNan<IssmDouble>(values[j]))spcpresent=true; //NaN means no spc by default 75 } 76 77 if(spcpresent){ 78 constraints->AddObject(new SpcTransient(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,N,times,values,EnthalpyAnalysisEnum)); 79 count++; 80 } 81 xDelete<IssmDouble>(values); 82 } 83 } 84 } 85 else{ 86 _error_("Size of field " << EnumToStringx(ThermalSpctemperatureEnum) << " not supported"); 87 } 88 89 /*Free ressources:*/ 90 iomodel->DeleteData(spcvector,ThermalSpctemperatureEnum); 91 xDelete<IssmDouble>(times); 92 xDelete<IssmDouble>(values); 93 }/*}}}*/ 94 void EnthalpyAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 95 96 /*No loads */ 97 }/*}}}*/ 98 void EnthalpyAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 99 100 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 101 ::CreateNodes(nodes,iomodel,EnthalpyAnalysisEnum,P1Enum); 102 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 103 }/*}}}*/ 9 104 int EnthalpyAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 10 105 return 1; 11 }/*}}}*/12 void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/13 14 int numoutputs;15 char** requestedoutputs = NULL;16 17 parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));18 parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));19 parameters->AddObject(iomodel->CopyConstantObject(ThermalReltolEnum));20 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));21 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));22 parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));23 24 iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);25 parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));26 if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));27 iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);28 29 /*Deal with friction parameters*/30 int frictionlaw;31 iomodel->Constant(&frictionlaw,FrictionLawEnum);32 if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));33 106 }/*}}}*/ 34 107 void EnthalpyAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 132 205 iomodel->DeleteData(3,TemperatureEnum,WaterfractionEnum,PressureEnum); 133 206 }/*}}}*/ 134 void EnthalpyAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 135 136 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 137 ::CreateNodes(nodes,iomodel,EnthalpyAnalysisEnum,P1Enum); 138 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 139 }/*}}}*/ 140 void EnthalpyAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 207 void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 208 209 int numoutputs; 210 char** requestedoutputs = NULL; 211 212 parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum)); 213 parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum)); 214 parameters->AddObject(iomodel->CopyConstantObject(ThermalReltolEnum)); 215 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum)); 216 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum)); 217 parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum)); 218 219 iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum); 220 parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs)); 221 if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs)); 222 iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum); 223 224 /*Deal with friction parameters*/ 225 int frictionlaw; 226 iomodel->Constant(&frictionlaw,FrictionLawEnum); 227 if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum)); 228 }/*}}}*/ 229 230 /*Finite Element Analysis*/ 231 void EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/ 232 233 /* Check if ice in element */ 234 if(!element->IsIceInElement()) return; 235 236 /* Only update Constraints at the base of grounded ice*/ 237 if(!(element->IsOnBase()) || element->IsFloating()) return; 141 238 142 239 /*Intermediary*/ 143 int count; 144 int M,N; 145 bool spcpresent = false; 146 IssmDouble heatcapacity; 147 IssmDouble referencetemperature; 148 149 /*Output*/ 150 IssmDouble *spcvector = NULL; 151 IssmDouble* times=NULL; 152 IssmDouble* values=NULL; 153 154 /*Fetch parameters: */ 155 iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum); 156 iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum); 157 158 /*return if 2d mesh*/ 159 if(iomodel->domaintype==Domain2DhorizontalEnum) return; 160 161 /*Fetch data: */ 162 iomodel->FetchData(&spcvector,&M,&N,ThermalSpctemperatureEnum); 163 164 //FIX ME: SHOULD USE IOMODELCREATECONSTRAINTS 165 /*Transient or static?:*/ 166 if(M==iomodel->numberofvertices){ 167 /*static: just create Constraints objects*/ 168 count=0; 169 170 for(int i=0;i<iomodel->numberofvertices;i++){ 171 /*keep only this partition's nodes:*/ 172 if((iomodel->my_vertices[i])){ 173 174 if (!xIsNan<IssmDouble>(spcvector[i])){ 175 176 constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,heatcapacity*(spcvector[i]-referencetemperature),EnthalpyAnalysisEnum)); 177 count++; 178 179 } 240 bool isdynamicbasalspc; 241 int numindices; 242 int *indices = NULL; 243 Node* node = NULL; 244 IssmDouble pressure; 245 246 /*Check wether dynamic basal boundary conditions are activated */ 247 element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum); 248 if(!isdynamicbasalspc) return; 249 250 /*Get parameters and inputs: */ 251 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 252 253 /*Fetch indices of basal & surface nodes for this finite element*/ 254 Penta *penta = (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element* 255 penta->BasalNodeIndices(&numindices,&indices,element->GetElementType()); 256 257 GaussPenta* gauss=new GaussPenta(); 258 for(int i=0;i<numindices;i++){ 259 gauss->GaussNode(element->GetElementType(),indices[i]); 260 261 pressure_input->GetInputValue(&pressure,gauss); 262 263 /*apply or release spc*/ 264 node=element->GetNode(indices[i]); 265 if(serial_spc[node->Sid()]==1.){ 266 pressure_input->GetInputValue(&pressure, gauss); 267 node->ApplyConstraint(0,PureIceEnthalpy(element,pressure)); 268 } 269 else 270 node->DofInFSet(0); 271 } 272 273 /*Free ressources:*/ 274 xDelete<int>(indices); 275 delete gauss; 276 }/*}}}*/ 277 void EnthalpyAnalysis::ComputeBasalMeltingrate(FemModel* femmodel){/*{{{*/ 278 /*Compute basal melting rates: */ 279 for(int i=0;i<femmodel->elements->Size();i++){ 280 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 281 ComputeBasalMeltingrate(element); 282 } 283 }/*}}}*/ 284 void EnthalpyAnalysis::ComputeBasalMeltingrate(Element* element){/*{{{*/ 285 /*Calculate the basal melt rates of the enthalpy model after Aschwanden 2012*/ 286 /* melting rate is positive when melting, negative when refreezing*/ 287 288 /* Check if ice in element */ 289 if(!element->IsIceInElement()) return; 290 291 /* Only compute melt rates at the base of grounded ice*/ 292 if(!element->IsOnBase() || element->IsFloating()) return; 293 294 /* Intermediaries */ 295 bool converged; 296 const int dim=3; 297 int i,is,state; 298 int vertexdown,vertexup,numvertices,numsegments; 299 int enthalpy_enum; 300 IssmDouble vec_heatflux[dim],normal_base[dim],d1enthalpy[dim],d1pressure[dim]; 301 IssmDouble basalfriction,alpha2,geothermalflux,heatflux; 302 IssmDouble dt,yts; 303 IssmDouble melting_overshoot,lambda; 304 IssmDouble vx,vy,vz; 305 IssmDouble *xyz_list = NULL; 306 IssmDouble *xyz_list_base = NULL; 307 int *pairindices = NULL; 308 309 /*Fetch parameters*/ 310 element->GetVerticesCoordinates(&xyz_list); 311 element->GetVerticesCoordinatesBase(&xyz_list_base); 312 element->GetInputValue(&converged,ConvergedEnum); 313 element->FindParam(&dt,TimesteppingTimeStepEnum); 314 element->FindParam(&yts, ConstantsYtsEnum); 315 316 if(dt==0. && !converged) enthalpy_enum=EnthalpyPicardEnum; 317 else enthalpy_enum=EnthalpyEnum; 318 319 IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum); 320 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum); 321 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum); 322 IssmDouble beta = element->GetMaterialParameter(MaterialsBetaEnum); 323 IssmDouble kappa = EnthalpyDiffusionParameterVolume(element,enthalpy_enum); _assert_(kappa>=0.); 324 IssmDouble kappa_mix; 325 326 /*retrieve inputs*/ 327 Input* enthalpy_input = element->GetInput(enthalpy_enum); _assert_(enthalpy_input); 328 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 329 Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input); 330 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 331 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input); 332 Input* vz_input = element->GetInput(VzEnum); _assert_(vz_input); 333 334 /*Build friction element, needed later: */ 335 Friction* friction=new Friction(element,dim); 336 337 /******** MELTING RATES ************************************//*{{{*/ 338 element->NormalBase(&normal_base[0],xyz_list_base); 339 element->VerticalSegmentIndices(&pairindices,&numsegments); 340 IssmDouble* meltingrate_enthalpy = xNew<IssmDouble>(numsegments); 341 IssmDouble* heating = xNew<IssmDouble>(numsegments); 342 343 numvertices=element->GetNumberOfVertices(); 344 IssmDouble* enthalpies = xNew<IssmDouble>(numvertices); 345 IssmDouble* pressures = xNew<IssmDouble>(numvertices); 346 IssmDouble* watercolumns = xNew<IssmDouble>(numvertices); 347 IssmDouble* basalmeltingrates = xNew<IssmDouble>(numvertices); 348 element->GetInputListOnVertices(enthalpies,enthalpy_enum); 349 element->GetInputListOnVertices(pressures,PressureEnum); 350 element->GetInputListOnVertices(watercolumns,WatercolumnEnum); 351 element->GetInputListOnVertices(basalmeltingrates,BasalforcingsGroundediceMeltingRateEnum); 352 353 Gauss* gauss=element->NewGauss(); 354 for(is=0;is<numsegments;is++){ 355 vertexdown = pairindices[is*2+0]; 356 vertexup = pairindices[is*2+1]; 357 gauss->GaussVertex(vertexdown); 358 359 state=GetThermalBasalCondition(element, enthalpies[vertexdown], enthalpies[vertexup], pressures[vertexdown], pressures[vertexup], watercolumns[vertexdown], basalmeltingrates[vertexdown]); 360 switch (state) { 361 case 0: 362 // cold, dry base: apply basal surface forcing 363 for(i=0;i<3;i++) vec_heatflux[i]=0.; 364 break; 365 case 1: case 2: case 3: 366 // case 1 : cold, wet base: keep at pressure melting point 367 // case 2: temperate, thin refreezing base: release spc 368 // case 3: temperate, thin melting base: set spc 369 enthalpy_input->GetInputDerivativeValue(&d1enthalpy[0],xyz_list,gauss); 370 for(i=0;i<3;i++) vec_heatflux[i]=-kappa*d1enthalpy[i]; 371 break; 372 case 4: 373 // temperate, thick melting base: set grad H*n=0 374 kappa_mix=GetWetIceConductivity(element, enthalpies[vertexdown], pressures[vertexdown]); 375 pressure_input->GetInputDerivativeValue(&d1pressure[0],xyz_list,gauss); 376 for(i=0;i<3;i++) vec_heatflux[i]=kappa_mix*beta*d1pressure[i]; 377 break; 378 default: 379 _printf0_(" unknown thermal basal state found!"); 380 } 381 if(state==0) meltingrate_enthalpy[is]=0.; 382 else{ 383 /*heat flux along normal*/ 384 heatflux=0.; 385 for(i=0;i<3;i++) heatflux+=(vec_heatflux[i])*normal_base[i]; 386 387 /*basal friction*/ 388 friction->GetAlpha2(&alpha2,gauss); 389 vx_input->GetInputValue(&vx,gauss); vy_input->GetInputValue(&vy,gauss); vz_input->GetInputValue(&vz,gauss); 390 basalfriction=alpha2*(vx*vx + vy*vy + vz*vz); 391 geothermalflux_input->GetInputValue(&geothermalflux,gauss); 392 /* -Mb= Fb-(q-q_geo)/((1-w)*L*rho), and (1-w)*rho=rho_ice, cf Aschwanden 2012, eqs.1, 2, 66*/ 393 heating[is]=(heatflux+basalfriction+geothermalflux); 394 meltingrate_enthalpy[is]=heating[is]/(latentheat*rho_ice); // m/s water equivalent 395 } 396 }/*}}}*/ 397 398 /******** UPDATE MELTINGRATES AND WATERCOLUMN **************//*{{{*/ 399 for(is=0;is<numsegments;is++){ 400 vertexdown = pairindices[is*2+0]; 401 vertexup = pairindices[is*2+1]; 402 if(dt!=0.){ 403 if(watercolumns[vertexdown]+meltingrate_enthalpy[is]*dt<0.){ // prevent too much freeze on 404 lambda = -watercolumns[vertexdown]/(dt*meltingrate_enthalpy[is]); _assert_(lambda>=0.); _assert_(lambda<1.); 405 watercolumns[vertexdown]=0.; 406 basalmeltingrates[vertexdown]=lambda*meltingrate_enthalpy[is]; // restrict freeze on only to size of watercolumn 407 enthalpies[vertexdown]+=(1.-lambda)*dt/yts*meltingrate_enthalpy[is]*latentheat*rho_ice; // use rest of energy to cool down base: dE=L*m, m=(1-lambda)*meltingrate*rho_ice 180 408 } 181 } 182 } 183 else if (M==(iomodel->numberofvertices+1)){ 184 /*transient: create transient SpcTransient objects. Same logic, except we need to retrieve 185 * various times and values to initialize an SpcTransient object: */ 186 count=0; 187 188 /*figure out times: */ 189 times=xNew<IssmDouble>(N); 190 for(int j=0;j<N;j++){ 191 times[j]=spcvector[(M-1)*N+j]; 192 } 193 194 /*Create constraints from x,y,z: */ 195 for(int i=0;i<iomodel->numberofvertices;i++){ 196 197 /*keep only this partition's nodes:*/ 198 if((iomodel->my_vertices[i])){ 199 200 /*figure out times and values: */ 201 values=xNew<IssmDouble>(N); 202 spcpresent=false; 203 for(int j=0;j<N;j++){ 204 values[j]=heatcapacity*(spcvector[i*N+j]-referencetemperature); 205 if(!xIsNan<IssmDouble>(values[j]))spcpresent=true; //NaN means no spc by default 206 } 207 208 if(spcpresent){ 209 constraints->AddObject(new SpcTransient(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,N,times,values,EnthalpyAnalysisEnum)); 210 count++; 211 } 212 xDelete<IssmDouble>(values); 409 else{ 410 basalmeltingrates[vertexdown]=meltingrate_enthalpy[is]; 411 watercolumns[vertexdown]+=dt*meltingrate_enthalpy[is]; 213 412 } 214 413 } 215 } 216 else{ 217 _error_("Size of field " << EnumToStringx(ThermalSpctemperatureEnum) << " not supported"); 218 } 219 220 /*Free ressources:*/ 221 iomodel->DeleteData(spcvector,ThermalSpctemperatureEnum); 222 xDelete<IssmDouble>(times); 223 xDelete<IssmDouble>(values); 224 }/*}}}*/ 225 void EnthalpyAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 226 227 /*No loads */ 228 }/*}}}*/ 229 230 /*Finite Element Analysis*/ 231 void EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/ 414 else{ 415 basalmeltingrates[vertexdown]=meltingrate_enthalpy[is]; 416 if(watercolumns[vertexdown]+meltingrate_enthalpy[is]<0.) 417 watercolumns[vertexdown]=0.; 418 else 419 watercolumns[vertexdown]+=meltingrate_enthalpy[is]; 420 } 421 basalmeltingrates[vertexdown]*=rho_water/rho_ice; // convert meltingrate from water to ice equivalent 422 _assert_(watercolumns[vertexdown]>=0.); 423 }/*}}}*/ 424 425 /*feed updated variables back into model*/ 426 if(dt!=0.){ 427 element->AddInput(enthalpy_enum,enthalpies,P1Enum); //TODO: distinguis for steadystate and transient run 428 element->AddInput(WatercolumnEnum,watercolumns,P1Enum); 429 } 430 element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum); 431 432 /*Clean up and return*/ 433 delete gauss; 434 delete friction; 435 xDelete<int>(pairindices); 436 xDelete<IssmDouble>(enthalpies); 437 xDelete<IssmDouble>(pressures); 438 xDelete<IssmDouble>(watercolumns); 439 xDelete<IssmDouble>(basalmeltingrates); 440 xDelete<IssmDouble>(meltingrate_enthalpy); 441 xDelete<IssmDouble>(heating); 442 xDelete<IssmDouble>(xyz_list); 443 xDelete<IssmDouble>(xyz_list_base); 444 }/*}}}*/ 445 void EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/ 232 446 if(VerboseSolution()) _printf0_(" computing enthalpy\n"); 233 447 femmodel->SetCurrentConfiguration(EnthalpyAnalysisEnum); … … 741 955 return pe; 742 956 }/*}}}*/ 743 void EnthalpyAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 744 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 745 * For node i, Bi' can be expressed in the actual coordinate system 746 * by: 747 * Bi_conduct=[ dh/dx ] 748 * [ dh/dy ] 749 * [ dh/dz ] 750 * where h is the interpolation function for node i. 751 * 752 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes) 753 */ 754 755 /*Fetch number of nodes for this finite element*/ 756 int numnodes = element->GetNumberOfNodes(); 757 758 /*Get nodal functions derivatives*/ 759 IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes); 760 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 761 762 /*Build B: */ 763 for(int i=0;i<numnodes;i++){ 764 B[numnodes*0+i] = dbasis[0*numnodes+i]; 765 B[numnodes*1+i] = dbasis[1*numnodes+i]; 766 B[numnodes*2+i] = dbasis[2*numnodes+i]; 767 } 768 769 /*Clean-up*/ 770 xDelete<IssmDouble>(dbasis); 771 }/*}}}*/ 772 void EnthalpyAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 773 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 774 * For node i, Bi' can be expressed in the actual coordinate system 775 * by: 776 * Bi_advec =[ h ] 777 * [ h ] 778 * [ h ] 779 * where h is the interpolation function for node i. 780 * 781 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1) 782 */ 783 784 /*Fetch number of nodes for this finite element*/ 785 int numnodes = element->GetNumberOfNodes(); 786 787 /*Get nodal functions*/ 788 IssmDouble* basis=xNew<IssmDouble>(numnodes); 789 element->NodalFunctions(basis,gauss); 790 791 /*Build B: */ 792 for(int i=0;i<numnodes;i++){ 793 B[numnodes*0+i] = basis[i]; 794 B[numnodes*1+i] = basis[i]; 795 B[numnodes*2+i] = basis[i]; 796 } 797 798 /*Clean-up*/ 799 xDelete<IssmDouble>(basis); 800 }/*}}}*/ 801 void EnthalpyAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 802 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 803 * For node i, Bi' can be expressed in the actual coordinate system 804 * by: 805 * Biprime_advec=[ dh/dx ] 806 * [ dh/dy ] 807 * [ dh/dz ] 808 * where h is the interpolation function for node i. 809 * 810 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes) 811 */ 812 813 /*Fetch number of nodes for this finite element*/ 814 int numnodes = element->GetNumberOfNodes(); 815 816 /*Get nodal functions derivatives*/ 817 IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes); 818 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 819 820 /*Build B: */ 821 for(int i=0;i<numnodes;i++){ 822 B[numnodes*0+i] = dbasis[0*numnodes+i]; 823 B[numnodes*1+i] = dbasis[1*numnodes+i]; 824 B[numnodes*2+i] = dbasis[2*numnodes+i]; 825 } 826 827 /*Clean-up*/ 828 xDelete<IssmDouble>(dbasis); 829 }/*}}}*/ 830 void EnthalpyAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 831 element->GetSolutionFromInputsOneDof(solution,EnthalpyEnum); 832 }/*}}}*/ 833 void EnthalpyAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 834 _error_("Not implemented yet"); 835 }/*}}}*/ 836 void EnthalpyAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 837 838 bool converged; 839 int i,rheology_law; 840 IssmDouble B_average,s_average,T_average=0.,P_average=0.; 841 int *doflist = NULL; 842 IssmDouble *xyz_list = NULL; 843 844 /*Fetch number of nodes and dof for this finite element*/ 845 int numnodes = element->GetNumberOfNodes(); 846 847 /*Fetch dof list and allocate solution vector*/ 848 element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 849 IssmDouble* values = xNew<IssmDouble>(numnodes); 850 IssmDouble* pressure = xNew<IssmDouble>(numnodes); 851 IssmDouble* surface = xNew<IssmDouble>(numnodes); 852 IssmDouble* B = xNew<IssmDouble>(numnodes); 853 IssmDouble* temperature = xNew<IssmDouble>(numnodes); 854 IssmDouble* waterfraction = xNew<IssmDouble>(numnodes); 855 856 /*Use the dof list to index into the solution vector: */ 857 for(i=0;i<numnodes;i++){ 858 values[i]=solution[doflist[i]]; 859 860 /*Check solution*/ 861 if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector"); 862 } 863 864 /*Get all inputs and parameters*/ 865 element->GetInputValue(&converged,ConvergedEnum); 866 element->GetInputListOnNodes(&pressure[0],PressureEnum); 867 if(converged){ 868 for(i=0;i<numnodes;i++){ 869 element->EnthalpyToThermal(&temperature[i],&waterfraction[i],values[i],pressure[i]); 870 if(waterfraction[i]<0.) _error_("Negative water fraction found in solution vector"); 871 //if(waterfraction[i]>1.) _error_("Water fraction >1 found in solution vector"); 872 } 873 element->AddInput(EnthalpyEnum,values,element->GetElementType()); 874 element->AddInput(WaterfractionEnum,waterfraction,element->GetElementType()); 875 element->AddInput(TemperatureEnum,temperature,element->GetElementType()); 876 877 /*Update Rheology only if converged (we must make sure that the temperature is below melting point 878 * otherwise the rheology could be negative*/ 879 element->FindParam(&rheology_law,MaterialsRheologyLawEnum); 880 element->GetInputListOnNodes(&surface[0],SurfaceEnum); 881 switch(rheology_law){ 882 case NoneEnum: 883 /*Do nothing: B is not temperature dependent*/ 884 break; 885 case CuffeyEnum: 886 for(i=0;i<numnodes;i++) B[i]=Cuffey(temperature[i]); 887 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 888 break; 889 case PatersonEnum: 890 for(i=0;i<numnodes;i++) B[i]=Paterson(temperature[i]); 891 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 892 break; 893 case ArrheniusEnum: 894 element->GetVerticesCoordinates(&xyz_list); 895 for(i=0;i<numnodes;i++) B[i]=Arrhenius(temperature[i],surface[i]-xyz_list[i*3+2],element->GetMaterialParameter(MaterialsRheologyNEnum)); 896 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 897 break; 898 case LliboutryDuvalEnum: 899 for(i=0;i<numnodes;i++) B[i]=LliboutryDuval(values[i],pressure[i],element->GetMaterialParameter(MaterialsRheologyNEnum),element->GetMaterialParameter(MaterialsBetaEnum),element->GetMaterialParameter(ConstantsReferencetemperatureEnum),element->GetMaterialParameter(MaterialsHeatcapacityEnum),element->GetMaterialParameter(MaterialsLatentheatEnum)); 900 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 901 break; 902 default: _error_("Rheology law " << EnumToStringx(rheology_law) << " not supported yet"); 903 } 904 } 905 else{ 906 element->AddInput(EnthalpyPicardEnum,values,element->GetElementType()); 907 } 908 909 /*Free ressources:*/ 910 xDelete<IssmDouble>(values); 911 xDelete<IssmDouble>(pressure); 912 xDelete<IssmDouble>(surface); 913 xDelete<IssmDouble>(B); 914 xDelete<IssmDouble>(temperature); 915 xDelete<IssmDouble>(waterfraction); 916 xDelete<IssmDouble>(xyz_list); 917 xDelete<int>(doflist); 918 }/*}}}*/ 919 void EnthalpyAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 920 921 bool islevelset; 922 femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum); 923 if(islevelset){ 924 SetActiveNodesLSMx(femmodel); 925 } 926 return; 927 }/*}}}*/ 928 929 /*Modules*/ 930 void EnthalpyAnalysis::PostProcessing(FemModel* femmodel){/*{{{*/ 931 932 /*Intermediaries*/ 933 bool computebasalmeltingrates=true; 934 bool drainicecolumn=true; 935 bool isdynamicbasalspc; 936 IssmDouble dt; 937 938 femmodel->parameters->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum); 939 femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum); 940 941 //TODO: use dt to decide what to do 942 if(drainicecolumn) DrainWaterfraction(femmodel); 943 if(computebasalmeltingrates) ComputeBasalMeltingrate(femmodel); 944 if(isdynamicbasalspc) UpdateBasalConstraints(femmodel); 945 946 }/*}}}*/ 947 void EnthalpyAnalysis::ComputeBasalMeltingrate(FemModel* femmodel){/*{{{*/ 948 /*Compute basal melting rates: */ 949 for(int i=0;i<femmodel->elements->Size();i++){ 950 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 951 ComputeBasalMeltingrate(element); 952 } 953 }/*}}}*/ 954 void EnthalpyAnalysis::ComputeBasalMeltingrate(Element* element){/*{{{*/ 955 /*Calculate the basal melt rates of the enthalpy model after Aschwanden 2012*/ 956 /* melting rate is positive when melting, negative when refreezing*/ 957 958 /* Check if ice in element */ 959 if(!element->IsIceInElement()) return; 960 961 /* Only compute melt rates at the base of grounded ice*/ 962 if(!element->IsOnBase() || element->IsFloating()) return; 963 964 /* Intermediaries */ 965 bool converged; 966 const int dim=3; 967 int i,is,state; 968 int vertexdown,vertexup,numvertices,numsegments; 969 int enthalpy_enum; 970 IssmDouble vec_heatflux[dim],normal_base[dim],d1enthalpy[dim],d1pressure[dim]; 971 IssmDouble basalfriction,alpha2,geothermalflux,heatflux; 972 IssmDouble dt,yts; 973 IssmDouble melting_overshoot,lambda; 974 IssmDouble vx,vy,vz; 975 IssmDouble *xyz_list = NULL; 976 IssmDouble *xyz_list_base = NULL; 977 int *pairindices = NULL; 978 979 /*Fetch parameters*/ 980 element->GetVerticesCoordinates(&xyz_list); 981 element->GetVerticesCoordinatesBase(&xyz_list_base); 982 element->GetInputValue(&converged,ConvergedEnum); 983 element->FindParam(&dt,TimesteppingTimeStepEnum); 984 element->FindParam(&yts, ConstantsYtsEnum); 985 986 if(dt==0. && !converged) enthalpy_enum=EnthalpyPicardEnum; 987 else enthalpy_enum=EnthalpyEnum; 988 989 IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum); 990 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum); 991 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum); 992 IssmDouble beta = element->GetMaterialParameter(MaterialsBetaEnum); 993 IssmDouble kappa = EnthalpyDiffusionParameterVolume(element,enthalpy_enum); _assert_(kappa>=0.); 994 IssmDouble kappa_mix; 995 996 /*retrieve inputs*/ 997 Input* enthalpy_input = element->GetInput(enthalpy_enum); _assert_(enthalpy_input); 998 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 999 Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input); 1000 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 1001 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input); 1002 Input* vz_input = element->GetInput(VzEnum); _assert_(vz_input); 1003 1004 /*Build friction element, needed later: */ 1005 Friction* friction=new Friction(element,dim); 1006 1007 /******** MELTING RATES ************************************//*{{{*/ 1008 element->NormalBase(&normal_base[0],xyz_list_base); 1009 element->VerticalSegmentIndices(&pairindices,&numsegments); 1010 IssmDouble* meltingrate_enthalpy = xNew<IssmDouble>(numsegments); 1011 IssmDouble* heating = xNew<IssmDouble>(numsegments); 1012 1013 numvertices=element->GetNumberOfVertices(); 1014 IssmDouble* enthalpies = xNew<IssmDouble>(numvertices); 1015 IssmDouble* pressures = xNew<IssmDouble>(numvertices); 1016 IssmDouble* watercolumns = xNew<IssmDouble>(numvertices); 1017 IssmDouble* basalmeltingrates = xNew<IssmDouble>(numvertices); 1018 element->GetInputListOnVertices(enthalpies,enthalpy_enum); 1019 element->GetInputListOnVertices(pressures,PressureEnum); 1020 element->GetInputListOnVertices(watercolumns,WatercolumnEnum); 1021 element->GetInputListOnVertices(basalmeltingrates,BasalforcingsGroundediceMeltingRateEnum); 1022 1023 Gauss* gauss=element->NewGauss(); 1024 for(is=0;is<numsegments;is++){ 1025 vertexdown = pairindices[is*2+0]; 1026 vertexup = pairindices[is*2+1]; 1027 gauss->GaussVertex(vertexdown); 1028 1029 state=GetThermalBasalCondition(element, enthalpies[vertexdown], enthalpies[vertexup], pressures[vertexdown], pressures[vertexup], watercolumns[vertexdown], basalmeltingrates[vertexdown]); 1030 switch (state) { 1031 case 0: 1032 // cold, dry base: apply basal surface forcing 1033 for(i=0;i<3;i++) vec_heatflux[i]=0.; 1034 break; 1035 case 1: case 2: case 3: 1036 // case 1 : cold, wet base: keep at pressure melting point 1037 // case 2: temperate, thin refreezing base: release spc 1038 // case 3: temperate, thin melting base: set spc 1039 enthalpy_input->GetInputDerivativeValue(&d1enthalpy[0],xyz_list,gauss); 1040 for(i=0;i<3;i++) vec_heatflux[i]=-kappa*d1enthalpy[i]; 1041 break; 1042 case 4: 1043 // temperate, thick melting base: set grad H*n=0 1044 kappa_mix=GetWetIceConductivity(element, enthalpies[vertexdown], pressures[vertexdown]); 1045 pressure_input->GetInputDerivativeValue(&d1pressure[0],xyz_list,gauss); 1046 for(i=0;i<3;i++) vec_heatflux[i]=kappa_mix*beta*d1pressure[i]; 1047 break; 1048 default: 1049 _printf0_(" unknown thermal basal state found!"); 1050 } 1051 if(state==0) meltingrate_enthalpy[is]=0.; 1052 else{ 1053 /*heat flux along normal*/ 1054 heatflux=0.; 1055 for(i=0;i<3;i++) heatflux+=(vec_heatflux[i])*normal_base[i]; 1056 1057 /*basal friction*/ 1058 friction->GetAlpha2(&alpha2,gauss); 1059 vx_input->GetInputValue(&vx,gauss); vy_input->GetInputValue(&vy,gauss); vz_input->GetInputValue(&vz,gauss); 1060 basalfriction=alpha2*(vx*vx + vy*vy + vz*vz); 1061 geothermalflux_input->GetInputValue(&geothermalflux,gauss); 1062 /* -Mb= Fb-(q-q_geo)/((1-w)*L*rho), and (1-w)*rho=rho_ice, cf Aschwanden 2012, eqs.1, 2, 66*/ 1063 heating[is]=(heatflux+basalfriction+geothermalflux); 1064 meltingrate_enthalpy[is]=heating[is]/(latentheat*rho_ice); // m/s water equivalent 1065 } 1066 }/*}}}*/ 1067 1068 /******** UPDATE MELTINGRATES AND WATERCOLUMN **************//*{{{*/ 1069 for(is=0;is<numsegments;is++){ 1070 vertexdown = pairindices[is*2+0]; 1071 vertexup = pairindices[is*2+1]; 1072 if(dt!=0.){ 1073 if(watercolumns[vertexdown]+meltingrate_enthalpy[is]*dt<0.){ // prevent too much freeze on 1074 lambda = -watercolumns[vertexdown]/(dt*meltingrate_enthalpy[is]); _assert_(lambda>=0.); _assert_(lambda<1.); 1075 watercolumns[vertexdown]=0.; 1076 basalmeltingrates[vertexdown]=lambda*meltingrate_enthalpy[is]; // restrict freeze on only to size of watercolumn 1077 enthalpies[vertexdown]+=(1.-lambda)*dt/yts*meltingrate_enthalpy[is]*latentheat*rho_ice; // use rest of energy to cool down base: dE=L*m, m=(1-lambda)*meltingrate*rho_ice 1078 } 1079 else{ 1080 basalmeltingrates[vertexdown]=meltingrate_enthalpy[is]; 1081 watercolumns[vertexdown]+=dt*meltingrate_enthalpy[is]; 1082 } 1083 } 1084 else{ 1085 basalmeltingrates[vertexdown]=meltingrate_enthalpy[is]; 1086 if(watercolumns[vertexdown]+meltingrate_enthalpy[is]<0.) 1087 watercolumns[vertexdown]=0.; 1088 else 1089 watercolumns[vertexdown]+=meltingrate_enthalpy[is]; 1090 } 1091 basalmeltingrates[vertexdown]*=rho_water/rho_ice; // convert meltingrate from water to ice equivalent 1092 _assert_(watercolumns[vertexdown]>=0.); 1093 }/*}}}*/ 1094 1095 /*feed updated variables back into model*/ 1096 if(dt!=0.){ 1097 element->AddInput(enthalpy_enum,enthalpies,P1Enum); //TODO: distinguis for steadystate and transient run 1098 element->AddInput(WatercolumnEnum,watercolumns,P1Enum); 1099 } 1100 element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum); 1101 1102 /*Clean up and return*/ 1103 delete gauss; 1104 delete friction; 1105 xDelete<int>(pairindices); 1106 xDelete<IssmDouble>(enthalpies); 1107 xDelete<IssmDouble>(pressures); 1108 xDelete<IssmDouble>(watercolumns); 1109 xDelete<IssmDouble>(basalmeltingrates); 1110 xDelete<IssmDouble>(meltingrate_enthalpy); 1111 xDelete<IssmDouble>(heating); 1112 xDelete<IssmDouble>(xyz_list); 1113 xDelete<IssmDouble>(xyz_list_base); 1114 }/*}}}*/ 1115 void EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/ 957 void EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/ 1116 958 /*Drain excess water fraction in ice column: */ 1117 959 for(int i=0;i<femmodel->elements->Size();i++){ … … 1120 962 } 1121 963 }/*}}}*/ 1122 void EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/ 1123 1124 /* Check if ice in element */ 1125 if(!element->IsIceInElement()) return; 1126 1127 /* Only drain waterfraction of ice column from element at base*/ 1128 if(!element->IsOnBase()) return; //FIXME: allow freeze on for floating elements 1129 1130 /* Intermediaries*/ 1131 int is, numvertices, numsegments; 1132 int *pairindices = NULL; 1133 1134 numvertices=element->GetNumberOfVertices(); 1135 element->VerticalSegmentIndices(&pairindices,&numsegments); 1136 1137 IssmDouble* watercolumn = xNew<IssmDouble>(numvertices); 1138 IssmDouble* drainrate_column = xNew<IssmDouble>(numsegments); 1139 IssmDouble* drainrate_element = xNew<IssmDouble>(numsegments); 1140 1141 element->GetInputListOnVertices(watercolumn,WatercolumnEnum); 1142 1143 for(is=0;is<numsegments;is++) drainrate_column[is]=0.; 1144 Element* elementi = element; 1145 for(;;){ 1146 for(is=0;is<numsegments;is++) drainrate_element[is]=0.; 1147 DrainWaterfraction(elementi,drainrate_element); // TODO: make sure every vertex is only drained once 1148 for(is=0;is<numsegments;is++) drainrate_column[is]+=drainrate_element[is]; 1149 1150 if(elementi->IsOnSurface()) break; 1151 elementi=elementi->GetUpperElement(); 1152 } 1153 /* add drained water to water column*/ 1154 for(is=0;is<numsegments;is++) watercolumn[is]+=drainrate_column[is]; 1155 /* Feed updated water column back into model */ 1156 element->AddInput(WatercolumnEnum,watercolumn,P1Enum); 1157 1158 xDelete<int>(pairindices); 1159 xDelete<IssmDouble>(drainrate_column); 1160 xDelete<IssmDouble>(drainrate_element); 1161 xDelete<IssmDouble>(watercolumn); 1162 }/*}}}*/ 1163 void EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/ 964 void EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/ 1164 965 1165 966 /* Check if ice in element */ … … 1223 1024 xDelete<IssmDouble>(deltawaterfractions); 1224 1025 }/*}}}*/ 1225 void EnthalpyAnalysis::UpdateBasalConstraints(FemModel* femmodel){/*{{{*/ 1226 1227 /*Update basal dirichlet BCs for enthalpy: */ 1228 Vector<IssmDouble>* spc = NULL; 1229 IssmDouble* serial_spc = NULL; 1230 1231 spc=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(EnthalpyAnalysisEnum)); 1232 /*First create a vector to figure out what elements should be constrained*/ 1233 for(int i=0;i<femmodel->elements->Size();i++){ 1234 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 1235 GetBasalConstraints(spc,element); 1236 } 1237 1238 /*Assemble and serialize*/ 1239 spc->Assemble(); 1240 serial_spc=spc->ToMPISerial(); 1241 delete spc; 1242 1243 /*Then update basal constraints nodes accordingly*/ 1244 for(int i=0;i<femmodel->elements->Size();i++){ 1245 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 1246 ApplyBasalConstraints(serial_spc,element); 1247 } 1248 1249 femmodel->UpdateConstraintsx(); 1250 1251 /*Delete*/ 1252 xDelete<IssmDouble>(serial_spc); 1253 }/*}}}*/ 1254 void EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/ 1026 void EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/ 1255 1027 1256 1028 /* Check if ice in element */ 1257 1029 if(!element->IsIceInElement()) return; 1258 1030 1259 /* Only update Constraints at the base of grounded ice*/ 1260 if(!(element->IsOnBase()) || element->IsFloating()) return; 1261 1262 /*Intermediary*/ 1263 bool isdynamicbasalspc; 1264 int numindices; 1265 int *indices = NULL; 1266 Node* node = NULL; 1267 IssmDouble pressure; 1268 1269 /*Check wether dynamic basal boundary conditions are activated */ 1270 element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum); 1271 if(!isdynamicbasalspc) return; 1272 1273 /*Get parameters and inputs: */ 1274 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 1275 1276 /*Fetch indices of basal & surface nodes for this finite element*/ 1277 Penta *penta = (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element* 1278 penta->BasalNodeIndices(&numindices,&indices,element->GetElementType()); 1279 1280 GaussPenta* gauss=new GaussPenta(); 1281 for(int i=0;i<numindices;i++){ 1282 gauss->GaussNode(element->GetElementType(),indices[i]); 1283 1284 pressure_input->GetInputValue(&pressure,gauss); 1285 1286 /*apply or release spc*/ 1287 node=element->GetNode(indices[i]); 1288 if(serial_spc[node->Sid()]==1.){ 1289 pressure_input->GetInputValue(&pressure, gauss); 1290 node->ApplyConstraint(0,PureIceEnthalpy(element,pressure)); 1291 } 1292 else 1293 node->DofInFSet(0); 1294 } 1295 1296 /*Free ressources:*/ 1297 xDelete<int>(indices); 1298 delete gauss; 1299 }/*}}}*/ 1300 void EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/ 1301 1302 /* Check if ice in element */ 1303 if(!element->IsIceInElement()) return; 1304 1305 /* Only update Constraints at the base of grounded ice*/ 1306 if(!(element->IsOnBase()) || element->IsFloating()) return; 1307 1308 /*Intermediary*/ 1309 bool isdynamicbasalspc; 1310 IssmDouble dt; 1311 1312 /*Check wether dynamic basal boundary conditions are activated */ 1313 element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum); 1314 if(!isdynamicbasalspc) return; 1315 1316 element->FindParam(&dt,TimesteppingTimeStepEnum); 1317 if(dt==0.){ 1318 GetBasalConstraintsSteadystate(vec_spc,element); 1319 } 1320 else{ 1321 GetBasalConstraintsTransient(vec_spc,element); 1322 } 1323 }/*}}}*/ 1324 void EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/ 1325 1326 /* Check if ice in element */ 1327 if(!element->IsIceInElement()) return; 1328 1329 /* Only update Constraints at the base of grounded ice*/ 1330 if(!(element->IsOnBase()) || element->IsFloating()) return; 1331 1332 /*Intermediary*/ 1333 int numindices, numindicesup, state; 1334 int *indices = NULL, *indicesup = NULL; 1335 IssmDouble enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate; 1336 1337 /*Get parameters and inputs: */ 1338 Input* enthalpy_input = element->GetInput(EnthalpyEnum); _assert_(enthalpy_input); //TODO: check EnthalpyPicard? 1339 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 1340 Input* watercolumn_input = element->GetInput(WatercolumnEnum); _assert_(watercolumn_input); 1341 Input* meltingrate_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(meltingrate_input); 1342 1343 /*Fetch indices of basal & surface nodes for this finite element*/ 1344 Penta *penta = (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element* 1345 penta->BasalNodeIndices(&numindices,&indices,element->GetElementType()); 1346 penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType()); _assert_(numindices==numindicesup); 1347 1348 GaussPenta* gauss=new GaussPenta(); 1349 GaussPenta* gaussup=new GaussPenta(); 1350 1351 for(int i=0;i<numindices;i++){ 1352 gauss->GaussNode(element->GetElementType(),indices[i]); 1353 gaussup->GaussNode(element->GetElementType(),indicesup[i]); 1354 1355 enthalpy_input->GetInputValue(&enthalpy,gauss); 1356 enthalpy_input->GetInputValue(&enthalpyup,gaussup); 1357 pressure_input->GetInputValue(&pressure,gauss); 1358 pressure_input->GetInputValue(&pressureup,gaussup); 1359 watercolumn_input->GetInputValue(&watercolumn,gauss); 1360 meltingrate_input->GetInputValue(&meltingrate,gauss); 1361 1362 state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate); 1363 1364 switch (state) { 1365 case 0: 1366 // cold, dry base: apply basal surface forcing 1367 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1368 break; 1369 case 1: 1370 // cold, wet base: keep at pressure melting point 1371 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1372 break; 1373 case 2: 1374 // temperate, thin refreezing base: release spc 1375 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1376 break; 1377 case 3: 1378 // temperate, thin melting base: set spc 1379 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1380 break; 1381 case 4: 1382 // temperate, thick melting base: set grad H*n=0 1383 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1384 break; 1385 default: 1386 _printf0_(" unknown thermal basal state found!"); 1387 } 1388 1389 } 1390 1391 /*Free ressources:*/ 1392 xDelete<int>(indices); 1393 xDelete<int>(indicesup); 1394 delete gauss; 1395 delete gaussup; 1396 }/*}}}*/ 1397 void EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/ 1398 1399 /* Check if ice in element */ 1400 if(!element->IsIceInElement()) return; 1401 1402 /* Only update Constraints at the base of grounded ice*/ 1403 if(!(element->IsOnBase()) || element->IsFloating()) return; 1404 1405 /*Intermediary*/ 1406 int numindices, numindicesup, state; 1407 int *indices = NULL, *indicesup = NULL; 1408 IssmDouble enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate; 1409 1410 /*Get parameters and inputs: */ 1411 Input* enthalpy_input = element->GetInput(EnthalpyPicardEnum); _assert_(enthalpy_input); 1412 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 1413 Input* watercolumn_input = element->GetInput(WatercolumnEnum); _assert_(watercolumn_input); 1414 Input* meltingrate_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(meltingrate_input); 1415 1416 /*Fetch indices of basal & surface nodes for this finite element*/ 1417 Penta *penta = (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element* 1418 penta->BasalNodeIndices(&numindices,&indices,element->GetElementType()); 1419 penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType()); _assert_(numindices==numindicesup); 1420 1421 GaussPenta* gauss=new GaussPenta(); 1422 GaussPenta* gaussup=new GaussPenta(); 1423 for(int i=0;i<numindices;i++){ 1424 gauss->GaussNode(element->GetElementType(),indices[i]); 1425 gaussup->GaussNode(element->GetElementType(),indicesup[i]); 1426 1427 enthalpy_input->GetInputValue(&enthalpy,gauss); 1428 enthalpy_input->GetInputValue(&enthalpyup,gaussup); 1429 pressure_input->GetInputValue(&pressure,gauss); 1430 pressure_input->GetInputValue(&pressureup,gaussup); 1431 watercolumn_input->GetInputValue(&watercolumn,gauss); 1432 meltingrate_input->GetInputValue(&meltingrate,gauss); 1433 1434 state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate); 1435 switch (state) { 1436 case 0: 1437 // cold, dry base: apply basal surface forcing 1438 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1439 break; 1440 case 1: 1441 // cold, wet base: keep at pressure melting point 1442 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1443 break; 1444 case 2: 1445 // temperate, thin refreezing base: release spc 1446 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1447 break; 1448 case 3: 1449 // temperate, thin melting base: set spc 1450 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1451 break; 1452 case 4: 1453 // temperate, thick melting base: s 1454 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1455 break; 1456 default: 1457 _printf0_(" unknown thermal basal state found!"); 1458 } 1459 } 1460 1461 /*Free ressources:*/ 1462 xDelete<int>(indices); 1463 xDelete<int>(indicesup); 1464 delete gauss; 1465 delete gaussup; 1466 }/*}}}*/ 1467 int EnthalpyAnalysis::GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpyup, IssmDouble pressure, IssmDouble pressureup, IssmDouble watercolumn, IssmDouble meltingrate){/*{{{*/ 1468 1469 /* Check if ice in element */ 1470 if(!element->IsIceInElement()) return -1; 1471 1472 /* Only update Constraints at the base of grounded ice*/ 1473 if(!(element->IsOnBase())) return -1; 1474 1475 /*Intermediary*/ 1476 int state=-1; 1477 IssmDouble dt; 1478 1479 /*Get parameters and inputs: */ 1480 element->FindParam(&dt,TimesteppingTimeStepEnum); 1481 1482 if(enthalpy<PureIceEnthalpy(element,pressure)){ 1483 if(watercolumn<=0.) state=0; // cold, dry base 1484 else state=1; // cold, wet base (refreezing) 1485 } 1486 else{ 1487 if(enthalpyup<PureIceEnthalpy(element,pressureup)){ 1488 if((dt==0.) && (meltingrate<0.)) state=2; // refreezing temperate base (non-physical, only for steadystate solver) 1489 else state=3; // temperate base, but no temperate layer 1490 } 1491 else state=4; // temperate layer with positive thickness 1492 } 1493 1494 _assert_(state>=0); 1495 return state; 1496 }/*}}}*/ 1497 IssmDouble EnthalpyAnalysis::GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure){/*{{{*/ 1498 1499 IssmDouble temperature, waterfraction; 1500 IssmDouble kappa_w = 0.6; // thermal conductivity of water (in W/m/K) 1501 IssmDouble kappa_i = element->GetMaterialParameter(MaterialsThermalconductivityEnum); 1502 element->EnthalpyToThermal(&temperature, &waterfraction, enthalpy, pressure); 1503 1504 return (1.-waterfraction)*kappa_i + waterfraction*kappa_w; 1505 }/*}}}*/ 1506 1507 /*Intermediaries*/ 1508 IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/ 1031 /* Only drain waterfraction of ice column from element at base*/ 1032 if(!element->IsOnBase()) return; //FIXME: allow freeze on for floating elements 1033 1034 /* Intermediaries*/ 1035 int is, numvertices, numsegments; 1036 int *pairindices = NULL; 1037 1038 numvertices=element->GetNumberOfVertices(); 1039 element->VerticalSegmentIndices(&pairindices,&numsegments); 1040 1041 IssmDouble* watercolumn = xNew<IssmDouble>(numvertices); 1042 IssmDouble* drainrate_column = xNew<IssmDouble>(numsegments); 1043 IssmDouble* drainrate_element = xNew<IssmDouble>(numsegments); 1044 1045 element->GetInputListOnVertices(watercolumn,WatercolumnEnum); 1046 1047 for(is=0;is<numsegments;is++) drainrate_column[is]=0.; 1048 Element* elementi = element; 1049 for(;;){ 1050 for(is=0;is<numsegments;is++) drainrate_element[is]=0.; 1051 DrainWaterfraction(elementi,drainrate_element); // TODO: make sure every vertex is only drained once 1052 for(is=0;is<numsegments;is++) drainrate_column[is]+=drainrate_element[is]; 1053 1054 if(elementi->IsOnSurface()) break; 1055 elementi=elementi->GetUpperElement(); 1056 } 1057 /* add drained water to water column*/ 1058 for(is=0;is<numsegments;is++) watercolumn[is]+=drainrate_column[is]; 1059 /* Feed updated water column back into model */ 1060 element->AddInput(WatercolumnEnum,watercolumn,P1Enum); 1061 1062 xDelete<int>(pairindices); 1063 xDelete<IssmDouble>(drainrate_column); 1064 xDelete<IssmDouble>(drainrate_element); 1065 xDelete<IssmDouble>(watercolumn); 1066 }/*}}}*/ 1067 IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/ 1509 1068 1510 1069 IssmDouble heatcapacity = element->GetMaterialParameter(MaterialsHeatcapacityEnum); … … 1519 1078 } 1520 1079 }/*}}}*/ 1521 IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/1080 IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/ 1522 1081 1523 1082 int iv; … … 1574 1133 return kappa; 1575 1134 }/*}}}*/ 1576 IssmDouble EnthalpyAnalysis::PureIceEnthalpy(Element* element,IssmDouble pressure){/*{{{*/ 1135 void EnthalpyAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 1136 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 1137 * For node i, Bi' can be expressed in the actual coordinate system 1138 * by: 1139 * Bi_advec =[ h ] 1140 * [ h ] 1141 * [ h ] 1142 * where h is the interpolation function for node i. 1143 * 1144 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1) 1145 */ 1146 1147 /*Fetch number of nodes for this finite element*/ 1148 int numnodes = element->GetNumberOfNodes(); 1149 1150 /*Get nodal functions*/ 1151 IssmDouble* basis=xNew<IssmDouble>(numnodes); 1152 element->NodalFunctions(basis,gauss); 1153 1154 /*Build B: */ 1155 for(int i=0;i<numnodes;i++){ 1156 B[numnodes*0+i] = basis[i]; 1157 B[numnodes*1+i] = basis[i]; 1158 B[numnodes*2+i] = basis[i]; 1159 } 1160 1161 /*Clean-up*/ 1162 xDelete<IssmDouble>(basis); 1163 }/*}}}*/ 1164 void EnthalpyAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 1165 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 1166 * For node i, Bi' can be expressed in the actual coordinate system 1167 * by: 1168 * Biprime_advec=[ dh/dx ] 1169 * [ dh/dy ] 1170 * [ dh/dz ] 1171 * where h is the interpolation function for node i. 1172 * 1173 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes) 1174 */ 1175 1176 /*Fetch number of nodes for this finite element*/ 1177 int numnodes = element->GetNumberOfNodes(); 1178 1179 /*Get nodal functions derivatives*/ 1180 IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes); 1181 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 1182 1183 /*Build B: */ 1184 for(int i=0;i<numnodes;i++){ 1185 B[numnodes*0+i] = dbasis[0*numnodes+i]; 1186 B[numnodes*1+i] = dbasis[1*numnodes+i]; 1187 B[numnodes*2+i] = dbasis[2*numnodes+i]; 1188 } 1189 1190 /*Clean-up*/ 1191 xDelete<IssmDouble>(dbasis); 1192 }/*}}}*/ 1193 void EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/ 1194 1195 /* Check if ice in element */ 1196 if(!element->IsIceInElement()) return; 1197 1198 /* Only update Constraints at the base of grounded ice*/ 1199 if(!(element->IsOnBase()) || element->IsFloating()) return; 1200 1201 /*Intermediary*/ 1202 bool isdynamicbasalspc; 1203 IssmDouble dt; 1204 1205 /*Check wether dynamic basal boundary conditions are activated */ 1206 element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum); 1207 if(!isdynamicbasalspc) return; 1208 1209 element->FindParam(&dt,TimesteppingTimeStepEnum); 1210 if(dt==0.){ 1211 GetBasalConstraintsSteadystate(vec_spc,element); 1212 } 1213 else{ 1214 GetBasalConstraintsTransient(vec_spc,element); 1215 } 1216 }/*}}}*/ 1217 void EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/ 1218 1219 /* Check if ice in element */ 1220 if(!element->IsIceInElement()) return; 1221 1222 /* Only update Constraints at the base of grounded ice*/ 1223 if(!(element->IsOnBase()) || element->IsFloating()) return; 1224 1225 /*Intermediary*/ 1226 int numindices, numindicesup, state; 1227 int *indices = NULL, *indicesup = NULL; 1228 IssmDouble enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate; 1229 1230 /*Get parameters and inputs: */ 1231 Input* enthalpy_input = element->GetInput(EnthalpyPicardEnum); _assert_(enthalpy_input); 1232 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 1233 Input* watercolumn_input = element->GetInput(WatercolumnEnum); _assert_(watercolumn_input); 1234 Input* meltingrate_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(meltingrate_input); 1235 1236 /*Fetch indices of basal & surface nodes for this finite element*/ 1237 Penta *penta = (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element* 1238 penta->BasalNodeIndices(&numindices,&indices,element->GetElementType()); 1239 penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType()); _assert_(numindices==numindicesup); 1240 1241 GaussPenta* gauss=new GaussPenta(); 1242 GaussPenta* gaussup=new GaussPenta(); 1243 for(int i=0;i<numindices;i++){ 1244 gauss->GaussNode(element->GetElementType(),indices[i]); 1245 gaussup->GaussNode(element->GetElementType(),indicesup[i]); 1246 1247 enthalpy_input->GetInputValue(&enthalpy,gauss); 1248 enthalpy_input->GetInputValue(&enthalpyup,gaussup); 1249 pressure_input->GetInputValue(&pressure,gauss); 1250 pressure_input->GetInputValue(&pressureup,gaussup); 1251 watercolumn_input->GetInputValue(&watercolumn,gauss); 1252 meltingrate_input->GetInputValue(&meltingrate,gauss); 1253 1254 state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate); 1255 switch (state) { 1256 case 0: 1257 // cold, dry base: apply basal surface forcing 1258 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1259 break; 1260 case 1: 1261 // cold, wet base: keep at pressure melting point 1262 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1263 break; 1264 case 2: 1265 // temperate, thin refreezing base: release spc 1266 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1267 break; 1268 case 3: 1269 // temperate, thin melting base: set spc 1270 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1271 break; 1272 case 4: 1273 // temperate, thick melting base: s 1274 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1275 break; 1276 default: 1277 _printf0_(" unknown thermal basal state found!"); 1278 } 1279 } 1280 1281 /*Free ressources:*/ 1282 xDelete<int>(indices); 1283 xDelete<int>(indicesup); 1284 delete gauss; 1285 delete gaussup; 1286 }/*}}}*/ 1287 void EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/ 1288 1289 /* Check if ice in element */ 1290 if(!element->IsIceInElement()) return; 1291 1292 /* Only update Constraints at the base of grounded ice*/ 1293 if(!(element->IsOnBase()) || element->IsFloating()) return; 1294 1295 /*Intermediary*/ 1296 int numindices, numindicesup, state; 1297 int *indices = NULL, *indicesup = NULL; 1298 IssmDouble enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate; 1299 1300 /*Get parameters and inputs: */ 1301 Input* enthalpy_input = element->GetInput(EnthalpyEnum); _assert_(enthalpy_input); //TODO: check EnthalpyPicard? 1302 Input* pressure_input = element->GetInput(PressureEnum); _assert_(pressure_input); 1303 Input* watercolumn_input = element->GetInput(WatercolumnEnum); _assert_(watercolumn_input); 1304 Input* meltingrate_input = element->GetInput(BasalforcingsGroundediceMeltingRateEnum); _assert_(meltingrate_input); 1305 1306 /*Fetch indices of basal & surface nodes for this finite element*/ 1307 Penta *penta = (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element* 1308 penta->BasalNodeIndices(&numindices,&indices,element->GetElementType()); 1309 penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType()); _assert_(numindices==numindicesup); 1310 1311 GaussPenta* gauss=new GaussPenta(); 1312 GaussPenta* gaussup=new GaussPenta(); 1313 1314 for(int i=0;i<numindices;i++){ 1315 gauss->GaussNode(element->GetElementType(),indices[i]); 1316 gaussup->GaussNode(element->GetElementType(),indicesup[i]); 1317 1318 enthalpy_input->GetInputValue(&enthalpy,gauss); 1319 enthalpy_input->GetInputValue(&enthalpyup,gaussup); 1320 pressure_input->GetInputValue(&pressure,gauss); 1321 pressure_input->GetInputValue(&pressureup,gaussup); 1322 watercolumn_input->GetInputValue(&watercolumn,gauss); 1323 meltingrate_input->GetInputValue(&meltingrate,gauss); 1324 1325 state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate); 1326 1327 switch (state) { 1328 case 0: 1329 // cold, dry base: apply basal surface forcing 1330 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1331 break; 1332 case 1: 1333 // cold, wet base: keep at pressure melting point 1334 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1335 break; 1336 case 2: 1337 // temperate, thin refreezing base: release spc 1338 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1339 break; 1340 case 3: 1341 // temperate, thin melting base: set spc 1342 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL); 1343 break; 1344 case 4: 1345 // temperate, thick melting base: set grad H*n=0 1346 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL); 1347 break; 1348 default: 1349 _printf0_(" unknown thermal basal state found!"); 1350 } 1351 1352 } 1353 1354 /*Free ressources:*/ 1355 xDelete<int>(indices); 1356 xDelete<int>(indicesup); 1357 delete gauss; 1358 delete gaussup; 1359 }/*}}}*/ 1360 void EnthalpyAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 1361 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 1362 * For node i, Bi' can be expressed in the actual coordinate system 1363 * by: 1364 * Bi_conduct=[ dh/dx ] 1365 * [ dh/dy ] 1366 * [ dh/dz ] 1367 * where h is the interpolation function for node i. 1368 * 1369 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes) 1370 */ 1371 1372 /*Fetch number of nodes for this finite element*/ 1373 int numnodes = element->GetNumberOfNodes(); 1374 1375 /*Get nodal functions derivatives*/ 1376 IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes); 1377 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 1378 1379 /*Build B: */ 1380 for(int i=0;i<numnodes;i++){ 1381 B[numnodes*0+i] = dbasis[0*numnodes+i]; 1382 B[numnodes*1+i] = dbasis[1*numnodes+i]; 1383 B[numnodes*2+i] = dbasis[2*numnodes+i]; 1384 } 1385 1386 /*Clean-up*/ 1387 xDelete<IssmDouble>(dbasis); 1388 }/*}}}*/ 1389 void EnthalpyAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 1390 element->GetSolutionFromInputsOneDof(solution,EnthalpyEnum); 1391 }/*}}}*/ 1392 int EnthalpyAnalysis::GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpyup, IssmDouble pressure, IssmDouble pressureup, IssmDouble watercolumn, IssmDouble meltingrate){/*{{{*/ 1393 1394 /* Check if ice in element */ 1395 if(!element->IsIceInElement()) return -1; 1396 1397 /* Only update Constraints at the base of grounded ice*/ 1398 if(!(element->IsOnBase())) return -1; 1399 1400 /*Intermediary*/ 1401 int state=-1; 1402 IssmDouble dt; 1403 1404 /*Get parameters and inputs: */ 1405 element->FindParam(&dt,TimesteppingTimeStepEnum); 1406 1407 if(enthalpy<PureIceEnthalpy(element,pressure)){ 1408 if(watercolumn<=0.) state=0; // cold, dry base 1409 else state=1; // cold, wet base (refreezing) 1410 } 1411 else{ 1412 if(enthalpyup<PureIceEnthalpy(element,pressureup)){ 1413 if((dt==0.) && (meltingrate<0.)) state=2; // refreezing temperate base (non-physical, only for steadystate solver) 1414 else state=3; // temperate base, but no temperate layer 1415 } 1416 else state=4; // temperate layer with positive thickness 1417 } 1418 1419 _assert_(state>=0); 1420 return state; 1421 }/*}}}*/ 1422 IssmDouble EnthalpyAnalysis::GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure){/*{{{*/ 1423 1424 IssmDouble temperature, waterfraction; 1425 IssmDouble kappa_w = 0.6; // thermal conductivity of water (in W/m/K) 1426 IssmDouble kappa_i = element->GetMaterialParameter(MaterialsThermalconductivityEnum); 1427 element->EnthalpyToThermal(&temperature, &waterfraction, enthalpy, pressure); 1428 1429 return (1.-waterfraction)*kappa_i + waterfraction*kappa_w; 1430 }/*}}}*/ 1431 void EnthalpyAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 1432 _error_("Not implemented yet"); 1433 }/*}}}*/ 1434 void EnthalpyAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 1435 1436 bool converged; 1437 int i,rheology_law; 1438 IssmDouble B_average,s_average,T_average=0.,P_average=0.; 1439 int *doflist = NULL; 1440 IssmDouble *xyz_list = NULL; 1441 1442 /*Fetch number of nodes and dof for this finite element*/ 1443 int numnodes = element->GetNumberOfNodes(); 1444 1445 /*Fetch dof list and allocate solution vector*/ 1446 element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 1447 IssmDouble* values = xNew<IssmDouble>(numnodes); 1448 IssmDouble* pressure = xNew<IssmDouble>(numnodes); 1449 IssmDouble* surface = xNew<IssmDouble>(numnodes); 1450 IssmDouble* B = xNew<IssmDouble>(numnodes); 1451 IssmDouble* temperature = xNew<IssmDouble>(numnodes); 1452 IssmDouble* waterfraction = xNew<IssmDouble>(numnodes); 1453 1454 /*Use the dof list to index into the solution vector: */ 1455 for(i=0;i<numnodes;i++){ 1456 values[i]=solution[doflist[i]]; 1457 1458 /*Check solution*/ 1459 if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector"); 1460 } 1461 1462 /*Get all inputs and parameters*/ 1463 element->GetInputValue(&converged,ConvergedEnum); 1464 element->GetInputListOnNodes(&pressure[0],PressureEnum); 1465 if(converged){ 1466 for(i=0;i<numnodes;i++){ 1467 element->EnthalpyToThermal(&temperature[i],&waterfraction[i],values[i],pressure[i]); 1468 if(waterfraction[i]<0.) _error_("Negative water fraction found in solution vector"); 1469 //if(waterfraction[i]>1.) _error_("Water fraction >1 found in solution vector"); 1470 } 1471 element->AddInput(EnthalpyEnum,values,element->GetElementType()); 1472 element->AddInput(WaterfractionEnum,waterfraction,element->GetElementType()); 1473 element->AddInput(TemperatureEnum,temperature,element->GetElementType()); 1474 1475 /*Update Rheology only if converged (we must make sure that the temperature is below melting point 1476 * otherwise the rheology could be negative*/ 1477 element->FindParam(&rheology_law,MaterialsRheologyLawEnum); 1478 element->GetInputListOnNodes(&surface[0],SurfaceEnum); 1479 switch(rheology_law){ 1480 case NoneEnum: 1481 /*Do nothing: B is not temperature dependent*/ 1482 break; 1483 case CuffeyEnum: 1484 for(i=0;i<numnodes;i++) B[i]=Cuffey(temperature[i]); 1485 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 1486 break; 1487 case PatersonEnum: 1488 for(i=0;i<numnodes;i++) B[i]=Paterson(temperature[i]); 1489 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 1490 break; 1491 case ArrheniusEnum: 1492 element->GetVerticesCoordinates(&xyz_list); 1493 for(i=0;i<numnodes;i++) B[i]=Arrhenius(temperature[i],surface[i]-xyz_list[i*3+2],element->GetMaterialParameter(MaterialsRheologyNEnum)); 1494 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 1495 break; 1496 case LliboutryDuvalEnum: 1497 for(i=0;i<numnodes;i++) B[i]=LliboutryDuval(values[i],pressure[i],element->GetMaterialParameter(MaterialsRheologyNEnum),element->GetMaterialParameter(MaterialsBetaEnum),element->GetMaterialParameter(ConstantsReferencetemperatureEnum),element->GetMaterialParameter(MaterialsHeatcapacityEnum),element->GetMaterialParameter(MaterialsLatentheatEnum)); 1498 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 1499 break; 1500 default: _error_("Rheology law " << EnumToStringx(rheology_law) << " not supported yet"); 1501 } 1502 } 1503 else{ 1504 element->AddInput(EnthalpyPicardEnum,values,element->GetElementType()); 1505 } 1506 1507 /*Free ressources:*/ 1508 xDelete<IssmDouble>(values); 1509 xDelete<IssmDouble>(pressure); 1510 xDelete<IssmDouble>(surface); 1511 xDelete<IssmDouble>(B); 1512 xDelete<IssmDouble>(temperature); 1513 xDelete<IssmDouble>(waterfraction); 1514 xDelete<IssmDouble>(xyz_list); 1515 xDelete<int>(doflist); 1516 }/*}}}*/ 1517 void EnthalpyAnalysis::PostProcessing(FemModel* femmodel){/*{{{*/ 1518 1519 /*Intermediaries*/ 1520 bool computebasalmeltingrates=true; 1521 bool drainicecolumn=true; 1522 bool isdynamicbasalspc; 1523 IssmDouble dt; 1524 1525 femmodel->parameters->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum); 1526 femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum); 1527 1528 //TODO: use dt to decide what to do 1529 if(drainicecolumn) DrainWaterfraction(femmodel); 1530 if(computebasalmeltingrates) ComputeBasalMeltingrate(femmodel); 1531 if(isdynamicbasalspc) UpdateBasalConstraints(femmodel); 1532 1533 }/*}}}*/ 1534 IssmDouble EnthalpyAnalysis::PureIceEnthalpy(Element* element,IssmDouble pressure){/*{{{*/ 1577 1535 1578 1536 IssmDouble heatcapacity = element->GetMaterialParameter(MaterialsHeatcapacityEnum); … … 1581 1539 return heatcapacity*(TMeltingPoint(element,pressure)-referencetemperature); 1582 1540 }/*}}}*/ 1583 IssmDouble EnthalpyAnalysis::TMeltingPoint(Element* element,IssmDouble pressure){/*{{{*/1541 IssmDouble EnthalpyAnalysis::TMeltingPoint(Element* element,IssmDouble pressure){/*{{{*/ 1584 1542 1585 1543 IssmDouble meltingpoint = element->GetMaterialParameter(MaterialsMeltingpointEnum); … … 1588 1546 return meltingpoint-beta*pressure; 1589 1547 }/*}}}*/ 1548 void EnthalpyAnalysis::UpdateBasalConstraints(FemModel* femmodel){/*{{{*/ 1549 1550 /*Update basal dirichlet BCs for enthalpy: */ 1551 Vector<IssmDouble>* spc = NULL; 1552 IssmDouble* serial_spc = NULL; 1553 1554 spc=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(EnthalpyAnalysisEnum)); 1555 /*First create a vector to figure out what elements should be constrained*/ 1556 for(int i=0;i<femmodel->elements->Size();i++){ 1557 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 1558 GetBasalConstraints(spc,element); 1559 } 1560 1561 /*Assemble and serialize*/ 1562 spc->Assemble(); 1563 serial_spc=spc->ToMPISerial(); 1564 delete spc; 1565 1566 /*Then update basal constraints nodes accordingly*/ 1567 for(int i=0;i<femmodel->elements->Size();i++){ 1568 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 1569 ApplyBasalConstraints(serial_spc,element); 1570 } 1571 1572 femmodel->UpdateConstraintsx(); 1573 1574 /*Delete*/ 1575 xDelete<IssmDouble>(serial_spc); 1576 }/*}}}*/ 1577 void EnthalpyAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 1578 1579 bool islevelset; 1580 femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum); 1581 if(islevelset){ 1582 SetActiveNodesLSMx(femmodel); 1583 } 1584 return; 1585 }/*}}}*/ -
issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.h
r18659 r18930 14 14 public: 15 15 /*Model processing*/ 16 int DofsPerNode(int** doflist,int domaintype,int approximation);17 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);18 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);19 void CreateNodes(Nodes* nodes,IoModel* iomodel);20 16 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 21 17 void CreateLoads(Loads* loads, IoModel* iomodel); 18 void CreateNodes(Nodes* nodes,IoModel* iomodel); 19 int DofsPerNode(int** doflist,int domaintype,int approximation); 20 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 21 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 22 22 23 23 /*Finite element Analysis*/ 24 void Core(FemModel* femmodel); 25 ElementVector* CreateDVector(Element* element); 26 ElementMatrix* CreateJacobianMatrix(Element* element); 27 ElementMatrix* CreateKMatrix(Element* element); 28 ElementMatrix* CreateKMatrixVolume(Element* element); 29 ElementMatrix* CreateKMatrixShelf(Element* element); 30 ElementVector* CreatePVector(Element* element); 31 ElementVector* CreatePVectorVolume(Element* element); 32 ElementVector* CreatePVectorSheet(Element* element); 33 ElementVector* CreatePVectorShelf(Element* element); 34 void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 35 void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 36 void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 37 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 38 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 39 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 40 void UpdateConstraints(FemModel* femmodel); 41 42 /*Modules*/ 43 static void PostProcessing(FemModel* femmodel); 44 static void ComputeBasalMeltingrate(FemModel* femmodel); 45 static void ComputeBasalMeltingrate(Element* element); 46 static void DrainWaterfraction(FemModel* femmodel); 47 static void DrainWaterfractionIcecolumn(Element* element); 48 static void DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element); 49 static void UpdateBasalConstraints(FemModel* femmodel); 50 static void ApplyBasalConstraints(IssmDouble* serial_spc,Element* element); 51 static void GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element); 52 static void GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element); 53 static void GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element); 54 static int GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpy_up, IssmDouble pressure, IssmDouble pressure_up, IssmDouble watercolumn, IssmDouble meltingrate); 55 static IssmDouble GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure); 56 57 58 /*Intermediaries*/ 24 static void ApplyBasalConstraints(IssmDouble* serial_spc,Element* element); 25 static void ComputeBasalMeltingrate(FemModel* femmodel); 26 static void ComputeBasalMeltingrate(Element* element); 27 void Core(FemModel* femmodel); 28 ElementVector* CreateDVector(Element* element); 29 ElementMatrix* CreateJacobianMatrix(Element* element); 30 ElementMatrix* CreateKMatrix(Element* element); 31 ElementMatrix* CreateKMatrixVolume(Element* element); 32 ElementMatrix* CreateKMatrixShelf(Element* element); 33 ElementVector* CreatePVector(Element* element); 34 ElementVector* CreatePVectorVolume(Element* element); 35 ElementVector* CreatePVectorSheet(Element* element); 36 ElementVector* CreatePVectorShelf(Element* element); 37 static void DrainWaterfraction(FemModel* femmodel); 38 static void DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element); 39 static void DrainWaterfractionIcecolumn(Element* element); 59 40 static IssmDouble EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure); 60 41 static IssmDouble EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum); 42 void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 43 void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 44 static void GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element); 45 static void GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element); 46 static void GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element); 47 void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 48 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 49 static int GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpy_up, IssmDouble pressure, IssmDouble pressure_up, IssmDouble watercolumn, IssmDouble meltingrate); 50 static IssmDouble GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure); 51 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 52 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 53 static void PostProcessing(FemModel* femmodel); 61 54 static IssmDouble PureIceEnthalpy(Element* element,IssmDouble pressure); 62 55 static IssmDouble TMeltingPoint(Element* element,IssmDouble pressure); 56 static void UpdateBasalConstraints(FemModel* femmodel); 57 void UpdateConstraints(FemModel* femmodel); 63 58 }; 64 59 #endif -
issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp
r18068 r18930 6 6 7 7 /*Model processing*/ 8 void HydrologyShreveAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 /*retrieve some parameters: */ 11 int hydrology_model; 12 iomodel->Constant(&hydrology_model,HydrologyModelEnum); 13 14 if(hydrology_model!=HydrologyshreveEnum) return; 15 16 IoModelToConstraintsx(constraints,iomodel,HydrologyshreveSpcwatercolumnEnum,HydrologyShreveAnalysisEnum,P1Enum); 17 18 }/*}}}*/ 19 void HydrologyShreveAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 20 /*No loads*/ 21 }/*}}}*/ 22 void HydrologyShreveAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 23 24 /*Fetch parameters: */ 25 int hydrology_model; 26 iomodel->Constant(&hydrology_model,HydrologyModelEnum); 27 28 /*Now, do we really want Shreve?*/ 29 if(hydrology_model!=HydrologyshreveEnum) return; 30 31 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 32 ::CreateNodes(nodes,iomodel,HydrologyShreveAnalysisEnum,P1Enum); 33 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 34 }/*}}}*/ 8 35 int HydrologyShreveAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 36 return 1; 10 }/*}}}*/11 void HydrologyShreveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 13 /*retrieve some parameters: */14 int hydrology_model;15 iomodel->Constant(&hydrology_model,HydrologyModelEnum);16 17 /*Now, do we really want Shreve?*/18 if(hydrology_model!=HydrologyshreveEnum) return;19 20 parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));21 parameters->AddObject(iomodel->CopyConstantObject(HydrologyshreveStabilizationEnum));22 23 37 }/*}}}*/ 24 38 void HydrologyShreveAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 55 69 elements->InputDuplicate(WatercolumnEnum,WaterColumnOldEnum); 56 70 }/*}}}*/ 57 void HydrologyShreveAnalysis:: CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/58 59 /* Fetchparameters: */71 void HydrologyShreveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 72 73 /*retrieve some parameters: */ 60 74 int hydrology_model; 61 75 iomodel->Constant(&hydrology_model,HydrologyModelEnum); … … 64 78 if(hydrology_model!=HydrologyshreveEnum) return; 65 79 66 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 67 ::CreateNodes(nodes,iomodel,HydrologyShreveAnalysisEnum,P1Enum); 68 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 69 }/*}}}*/ 70 void HydrologyShreveAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 71 72 /*retrieve some parameters: */ 73 int hydrology_model; 74 iomodel->Constant(&hydrology_model,HydrologyModelEnum); 75 76 if(hydrology_model!=HydrologyshreveEnum) return; 77 78 IoModelToConstraintsx(constraints,iomodel,HydrologyshreveSpcwatercolumnEnum,HydrologyShreveAnalysisEnum,P1Enum); 79 80 }/*}}}*/ 81 void HydrologyShreveAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 82 /*No loads*/ 80 parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model)); 81 parameters->AddObject(iomodel->CopyConstantObject(HydrologyshreveStabilizationEnum)); 82 83 83 }/*}}}*/ 84 84 … … 90 90 /*Default, return NULL*/ 91 91 return NULL; 92 }/*}}}*/ 93 void HydrologyShreveAnalysis::CreateHydrologyWaterVelocityInput(Element* element){/*{{{*/ 94 95 /*Intermediaries*/ 96 IssmDouble dsdx,dsdy,dbdx,dbdy,w; 97 98 /*Retrieve all inputs and parameters*/ 99 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum); 100 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum); 101 IssmDouble g = element->GetMaterialParameter(ConstantsGEnum); 102 IssmDouble mu_water = element->GetMaterialParameter(MaterialsMuWaterEnum); 103 Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input); 104 Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input); 105 Input* bedslopex_input = element->GetInput(BedSlopeXEnum); _assert_(bedslopex_input); 106 Input* bedslopey_input = element->GetInput(BedSlopeYEnum); _assert_(bedslopey_input); 107 Input* watercolumn_input = element->GetInput(WatercolumnEnum); _assert_(watercolumn_input); 108 109 /*Fetch number of vertices and allocate output*/ 110 int numvertices = element->GetNumberOfVertices(); 111 IssmDouble* vx = xNew<IssmDouble>(numvertices); 112 IssmDouble* vy = xNew<IssmDouble>(numvertices); 113 114 Gauss* gauss=element->NewGauss(); 115 for(int iv=0;iv<numvertices;iv++){ 116 gauss->GaussVertex(iv); 117 surfaceslopex_input->GetInputValue(&dsdx,gauss); 118 surfaceslopey_input->GetInputValue(&dsdy,gauss); 119 bedslopex_input->GetInputValue(&dbdx,gauss); 120 bedslopey_input->GetInputValue(&dbdy,gauss); 121 watercolumn_input->GetInputValue(&w,gauss); 122 123 /* Water velocity x and y components */ 124 vx[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx); 125 vy[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy); 126 } 127 128 /*clean-up*/ 129 delete gauss; 130 131 /*Add to inputs*/ 132 element->AddInput(HydrologyWaterVxEnum,vx,P1Enum); 133 element->AddInput(HydrologyWaterVyEnum,vy,P1Enum); 134 xDelete<IssmDouble>(vx); 135 xDelete<IssmDouble>(vy); 92 136 }/*}}}*/ 93 137 ElementMatrix* HydrologyShreveAnalysis::CreateJacobianMatrix(Element* element){/*{{{*/ … … 234 278 return pe; 235 279 }/*}}}*/ 236 void HydrologyShreveAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/280 void HydrologyShreveAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 237 281 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 238 282 * For node i, Bi can be expressed in the actual coordinate system … … 261 305 xDelete<IssmDouble>(basis); 262 306 }/*}}}*/ 263 void HydrologyShreveAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/307 void HydrologyShreveAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 264 308 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 265 309 * For node i, Bi' can be expressed in the actual coordinate system … … 289 333 290 334 }/*}}}*/ 291 void HydrologyShreveAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/335 void HydrologyShreveAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 292 336 element->GetSolutionFromInputsOneDof(solution,WatercolumnEnum); 293 337 }/*}}}*/ 294 void HydrologyShreveAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/338 void HydrologyShreveAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 295 339 _error_("Not implemented yet"); 296 340 }/*}}}*/ 297 void HydrologyShreveAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/341 void HydrologyShreveAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 298 342 299 343 /*Intermediary*/ … … 321 365 xDelete<int>(doflist); 322 366 }/*}}}*/ 323 void HydrologyShreveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/367 void HydrologyShreveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 324 368 /*Default, do nothing*/ 325 369 return; 326 370 }/*}}}*/ 327 328 /*Intermediaries*/329 void HydrologyShreveAnalysis::CreateHydrologyWaterVelocityInput(Element* element){/*{{{*/330 331 /*Intermediaries*/332 IssmDouble dsdx,dsdy,dbdx,dbdy,w;333 334 /*Retrieve all inputs and parameters*/335 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum);336 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);337 IssmDouble g = element->GetMaterialParameter(ConstantsGEnum);338 IssmDouble mu_water = element->GetMaterialParameter(MaterialsMuWaterEnum);339 Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);340 Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);341 Input* bedslopex_input = element->GetInput(BedSlopeXEnum); _assert_(bedslopex_input);342 Input* bedslopey_input = element->GetInput(BedSlopeYEnum); _assert_(bedslopey_input);343 Input* watercolumn_input = element->GetInput(WatercolumnEnum); _assert_(watercolumn_input);344 345 /*Fetch number of vertices and allocate output*/346 int numvertices = element->GetNumberOfVertices();347 IssmDouble* vx = xNew<IssmDouble>(numvertices);348 IssmDouble* vy = xNew<IssmDouble>(numvertices);349 350 Gauss* gauss=element->NewGauss();351 for(int iv=0;iv<numvertices;iv++){352 gauss->GaussVertex(iv);353 surfaceslopex_input->GetInputValue(&dsdx,gauss);354 surfaceslopey_input->GetInputValue(&dsdy,gauss);355 bedslopex_input->GetInputValue(&dbdx,gauss);356 bedslopey_input->GetInputValue(&dbdy,gauss);357 watercolumn_input->GetInputValue(&w,gauss);358 359 /* Water velocity x and y components */360 vx[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);361 vy[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);362 }363 364 /*clean-up*/365 delete gauss;366 367 /*Add to inputs*/368 element->AddInput(HydrologyWaterVxEnum,vx,P1Enum);369 element->AddInput(HydrologyWaterVyEnum,vy,P1Enum);370 xDelete<IssmDouble>(vx);371 xDelete<IssmDouble>(vy);372 }/*}}}*/373 374 371 375 372 -
issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ 23 23 void Core(FemModel* femmodel); 24 24 ElementVector* CreateDVector(Element* element); 25 void CreateHydrologyWaterVelocityInput(Element* element); 25 26 ElementMatrix* CreateJacobianMatrix(Element* element); 26 27 ElementMatrix* CreateKMatrix(Element* element); 27 28 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 33 /*Intermediaries*/ 34 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 35 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss); 36 void CreateHydrologyWaterVelocityInput(Element* element); 29 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 30 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss); 31 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 32 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 33 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 34 void UpdateConstraints(FemModel* femmodel); 37 35 }; 38 36 #endif -
issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp
r18593 r18930 6 6 7 7 /*Model processing*/ 8 void L2ProjectionBaseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 /*No constraints*/ 11 }/*}}}*/ 12 void L2ProjectionBaseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 13 14 /*No loads*/ 15 }/*}}}*/ 16 void L2ProjectionBaseAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 17 18 if(iomodel->domaintype==Domain3DEnum){ 19 iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 20 } 21 else if(iomodel->domaintype==Domain2DverticalEnum){ 22 iomodel->FetchData(1,MeshVertexonbaseEnum); 23 } 24 ::CreateNodes(nodes,iomodel,L2ProjectionBaseAnalysisEnum,P1Enum); 25 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 26 }/*}}}*/ 8 27 int L2ProjectionBaseAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 28 return 1; 10 }/*}}}*/11 void L2ProjectionBaseAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 29 }/*}}}*/ 13 30 void L2ProjectionBaseAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 31 48 } 32 49 }/*}}}*/ 33 void L2ProjectionBaseAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 34 35 if(iomodel->domaintype==Domain3DEnum){ 36 iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 37 } 38 else if(iomodel->domaintype==Domain2DverticalEnum){ 39 iomodel->FetchData(1,MeshVertexonbaseEnum); 40 } 41 ::CreateNodes(nodes,iomodel,L2ProjectionBaseAnalysisEnum,P1Enum); 42 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 43 }/*}}}*/ 44 void L2ProjectionBaseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 45 46 /*No constraints*/ 47 }/*}}}*/ 48 void L2ProjectionBaseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 49 50 /*No loads*/ 50 void L2ProjectionBaseAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 51 51 }/*}}}*/ 52 52 … … 196 196 return pe; 197 197 }/*}}}*/ 198 void L2ProjectionBaseAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/198 void L2ProjectionBaseAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 199 199 _error_("not implemented yet"); 200 200 }/*}}}*/ 201 void L2ProjectionBaseAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/201 void L2ProjectionBaseAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 202 202 _error_("Not implemented yet"); 203 203 }/*}}}*/ 204 void L2ProjectionBaseAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/204 void L2ProjectionBaseAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 205 205 206 206 int inputenum,domaintype,elementtype; … … 225 225 } 226 226 }/*}}}*/ 227 void L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/227 void L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 228 228 /*Default, do nothing*/ 229 229 return; -
issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void InputUpdateFromSolution(IssmDouble* solution,Element* element);31 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 32 }; 33 33 #endif -
issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp
r18057 r18930 6 6 7 7 /*Model processing*/ 8 void L2ProjectionEPLAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 /*No constraints*/ 11 }/*}}}*/ 12 void L2ProjectionEPLAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 13 14 /*No loads*/ 15 }/*}}}*/ 16 void L2ProjectionEPLAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 17 /*Now, do we really want DC?*/ 18 int hydrology_model; 19 iomodel->Constant(&hydrology_model,HydrologyModelEnum); 20 if(hydrology_model!=HydrologydcEnum) return; 21 22 /*Do we want an efficient layer*/ 23 bool isefficientlayer; 24 iomodel->Constant(&isefficientlayer,HydrologydcIsefficientlayerEnum); 25 if(!isefficientlayer) return; 26 27 if(iomodel->domaintype==Domain3DEnum){ 28 iomodel->FetchData(1,MeshVertexonbaseEnum); 29 } 30 else if(iomodel->domaintype==Domain2DverticalEnum){ 31 iomodel->FetchData(1,MeshVertexonbaseEnum); 32 } 33 ::CreateNodes(nodes,iomodel,L2ProjectionEPLAnalysisEnum,P1Enum); 34 iomodel->DeleteData(1,MeshVertexonbaseEnum); 35 }/*}}}*/ 8 36 int L2ProjectionEPLAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 37 return 1; 10 }/*}}}*/11 void L2ProjectionEPLAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 38 }/*}}}*/ 13 39 void L2ProjectionEPLAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 41 67 } 42 68 }/*}}}*/ 43 void L2ProjectionEPLAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 44 /*Now, do we really want DC?*/ 45 int hydrology_model; 46 iomodel->Constant(&hydrology_model,HydrologyModelEnum); 47 if(hydrology_model!=HydrologydcEnum) return; 48 49 /*Do we want an efficient layer*/ 50 bool isefficientlayer; 51 iomodel->Constant(&isefficientlayer,HydrologydcIsefficientlayerEnum); 52 if(!isefficientlayer) return; 53 54 if(iomodel->domaintype==Domain3DEnum){ 55 iomodel->FetchData(1,MeshVertexonbaseEnum); 56 } 57 else if(iomodel->domaintype==Domain2DverticalEnum){ 58 iomodel->FetchData(1,MeshVertexonbaseEnum); 59 } 60 ::CreateNodes(nodes,iomodel,L2ProjectionEPLAnalysisEnum,P1Enum); 61 iomodel->DeleteData(1,MeshVertexonbaseEnum); 62 }/*}}}*/ 63 void L2ProjectionEPLAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 64 65 /*No constraints*/ 66 }/*}}}*/ 67 void L2ProjectionEPLAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 68 69 /*No loads*/ 69 void L2ProjectionEPLAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 70 70 }/*}}}*/ 71 71 … … 226 226 return pe; 227 227 }/*}}}*/ 228 void L2ProjectionEPLAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/228 void L2ProjectionEPLAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 229 229 _error_("not implemented yet"); 230 230 }/*}}}*/ 231 void L2ProjectionEPLAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/231 void L2ProjectionEPLAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 232 232 _error_("Not implemented yet"); 233 233 }/*}}}*/ 234 void L2ProjectionEPLAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/234 void L2ProjectionEPLAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 235 235 int inputenum,domaintype; 236 236 … … 250 250 } 251 251 }/*}}}*/ 252 void L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/252 void L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 253 253 /*Default, do nothing*/ 254 254 return; -
issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void InputUpdateFromSolution(IssmDouble* solution,Element* element);31 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 32 }; 33 33 #endif -
issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp
r18862 r18930 11 11 #include "../solutionsequences/solutionsequences.h" 12 12 13 int LevelsetAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/14 return 1;13 void LevelsetAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 14 return; 15 15 } 16 16 /*}}}*/ 17 void LevelsetAnalysis:: UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/17 void LevelsetAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 18 18 return; 19 }/*}}}*/ 20 void LevelsetAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 21 int finiteelement=P1Enum; 22 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 23 ::CreateNodes(nodes,iomodel,LevelsetAnalysisEnum,finiteelement); 24 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 25 } 26 /*}}}*/ 27 int LevelsetAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 28 return 1; 19 29 } 20 30 /*}}}*/ … … 60 70 } 61 71 /*}}}*/ 62 void LevelsetAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 63 int finiteelement=P1Enum; 64 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 65 ::CreateNodes(nodes,iomodel,LevelsetAnalysisEnum,finiteelement); 66 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 67 } 68 /*}}}*/ 69 void LevelsetAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 72 void LevelsetAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 70 73 return; 71 74 } 72 75 /*}}}*/ 73 void LevelsetAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/74 return;75 }/*}}}*/76 76 77 77 /*Finite element Analysis*/ 78 void LevelsetAnalysis::Core(FemModel* femmodel){/*{{{*/78 void LevelsetAnalysis::Core(FemModel* femmodel){/*{{{*/ 79 79 80 80 #if !defined(_DEVELOPMENT_) … … 404 404 return pe; 405 405 }/*}}}*/ 406 void LevelsetAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 406 void LevelsetAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 407 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 408 * For node i, Bi can be expressed in the actual coordinate system 409 * by: 410 * Bi=[ N ] 411 * [ N ] 412 * where N is the finiteelement function for node i. 413 * 414 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes) 415 */ 416 417 /*Fetch number of nodes for this finite element*/ 418 int numnodes = element->GetNumberOfNodes(); 419 420 /*Get nodal functions*/ 421 IssmDouble* basis=xNew<IssmDouble>(numnodes); 422 element->NodalFunctions(basis,gauss); 423 424 /*Build B: */ 425 for(int i=0;i<numnodes;i++){ 426 B[numnodes*0+i] = basis[i]; 427 B[numnodes*1+i] = basis[i]; 428 } 429 430 /*Clean-up*/ 431 xDelete<IssmDouble>(basis); 432 }/*}}}*/ 433 void LevelsetAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 434 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 435 * For node i, Bi' can be expressed in the actual coordinate system 436 * by: 437 * Bi_prime=[ dN/dx ] 438 * [ dN/dy ] 439 * where N is the finiteelement function for node i. 440 * 441 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes) 442 */ 443 444 /*Fetch number of nodes for this finite element*/ 445 int numnodes = element->GetNumberOfNodes(); 446 447 /*Get nodal functions derivatives*/ 448 IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes); 449 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 450 451 /*Build B': */ 452 for(int i=0;i<numnodes;i++){ 453 Bprime[numnodes*0+i] = dbasis[0*numnodes+i]; 454 Bprime[numnodes*1+i] = dbasis[1*numnodes+i]; 455 } 456 457 /*Clean-up*/ 458 xDelete<IssmDouble>(dbasis); 459 460 }/*}}}*/ 461 IssmDouble LevelsetAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/ 462 // returns distance d of point q to straight going through points s0, s1 463 // d=|a x b|/|b| 464 // with a=q-s0, b=s1-s0 465 466 /* Intermediaries */ 467 const int dim=2; 468 int i; 469 IssmDouble a[dim], b[dim]; 470 IssmDouble norm_b; 471 472 for(i=0;i<dim;i++){ 473 a[i]=q[i]-s0[i]; 474 b[i]=s1[i]-s0[i]; 475 } 476 477 norm_b=0.; 478 for(i=0;i<dim;i++) 479 norm_b+=b[i]*b[i]; 480 norm_b=sqrt(norm_b); 481 _assert_(norm_b>0.); 482 483 return fabs(a[0]*b[1]-a[1]*b[0])/norm_b; 484 }/*}}}*/ 485 void LevelsetAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 407 486 _error_("not implemented yet"); 408 487 }/*}}}*/ 409 void LevelsetAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/488 void LevelsetAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 410 489 _error_("Not implemented yet"); 411 490 }/*}}}*/ 412 void LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/491 void LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 413 492 414 493 int domaintype; … … 424 503 } 425 504 }/*}}}*/ 426 void LevelsetAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 427 /*Default, do nothing*/ 428 return; 429 }/*}}}*/ 430 void LevelsetAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 431 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 432 * For node i, Bi can be expressed in the actual coordinate system 433 * by: 434 * Bi=[ N ] 435 * [ N ] 436 * where N is the finiteelement function for node i. 437 * 438 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes) 439 */ 440 441 /*Fetch number of nodes for this finite element*/ 442 int numnodes = element->GetNumberOfNodes(); 443 444 /*Get nodal functions*/ 445 IssmDouble* basis=xNew<IssmDouble>(numnodes); 446 element->NodalFunctions(basis,gauss); 447 448 /*Build B: */ 449 for(int i=0;i<numnodes;i++){ 450 B[numnodes*0+i] = basis[i]; 451 B[numnodes*1+i] = basis[i]; 452 } 453 454 /*Clean-up*/ 455 xDelete<IssmDouble>(basis); 456 }/*}}}*/ 457 void LevelsetAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 458 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 459 * For node i, Bi' can be expressed in the actual coordinate system 460 * by: 461 * Bi_prime=[ dN/dx ] 462 * [ dN/dy ] 463 * where N is the finiteelement function for node i. 464 * 465 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes) 466 */ 467 468 /*Fetch number of nodes for this finite element*/ 469 int numnodes = element->GetNumberOfNodes(); 470 471 /*Get nodal functions derivatives*/ 472 IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes); 473 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 474 475 /*Build B': */ 476 for(int i=0;i<numnodes;i++){ 477 Bprime[numnodes*0+i] = dbasis[0*numnodes+i]; 478 Bprime[numnodes*1+i] = dbasis[1*numnodes+i]; 479 } 480 481 /*Clean-up*/ 482 xDelete<IssmDouble>(dbasis); 483 484 }/*}}}*/ 485 void LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/ 505 void LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/ 486 506 487 507 /* Intermediaries */ … … 539 559 delete dist_zerolevelset; 540 560 }/*}}}*/ 541 void LevelsetAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/561 void LevelsetAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/ 542 562 543 563 if(!element->IsZeroLevelset(MaskIceLevelsetEnum)) … … 592 612 xDelete<IssmDouble>(xyz_list_zero); 593 613 }/*}}}*/ 594 IssmDouble LevelsetAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/ 595 // returns distance d of point q to straight going through points s0, s1 596 // d=|a x b|/|b| 597 // with a=q-s0, b=s1-s0 598 599 /* Intermediaries */ 600 const int dim=2; 601 int i; 602 IssmDouble a[dim], b[dim]; 603 IssmDouble norm_b; 604 605 for(i=0;i<dim;i++){ 606 a[i]=q[i]-s0[i]; 607 b[i]=s1[i]-s0[i]; 608 } 609 610 norm_b=0.; 611 for(i=0;i<dim;i++) 612 norm_b+=b[i]*b[i]; 613 norm_b=sqrt(norm_b); 614 _assert_(norm_b>0.); 615 616 return fabs(a[0]*b[1]-a[1]*b[0])/norm_b; 617 }/*}}}*/ 614 void LevelsetAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 615 /*Default, do nothing*/ 616 return; 617 }/*}}}*/ -
issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void InputUpdateFromSolution(IssmDouble* solution,Element* element);31 void UpdateConstraints(FemModel* femmodel);32 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);33 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);34 void SetDistanceOnIntersectedElements(FemModel* femmodel);35 void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element);36 IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);28 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 29 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss); 30 IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1); 31 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 32 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 33 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 34 void SetDistanceOnIntersectedElements(FemModel* femmodel); 35 void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element); 36 void UpdateConstraints(FemModel* femmodel); 37 37 }; 38 38 #endif -
issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp
r18521 r18930 10 10 11 11 /*Model processing*/ 12 void LsfReinitializationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 13 /* Do nothing for now */ 14 }/*}}}*/ 15 void LsfReinitializationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 16 /* Do nothing for now */ 17 }/*}}}*/ 18 void LsfReinitializationAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 19 int finiteelement=P1Enum; 20 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 21 ::CreateNodes(nodes,iomodel,LsfReinitializationAnalysisEnum,finiteelement); 22 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 23 }/*}}}*/ 12 24 int LsfReinitializationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 13 25 return 1; 14 }/*}}}*/15 void LsfReinitializationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/16 /* Do nothing for now */17 26 }/*}}}*/ 18 27 void LsfReinitializationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 34 43 iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum); 35 44 }/*}}}*/ 36 void LsfReinitializationAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 37 int finiteelement=P1Enum; 38 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 39 ::CreateNodes(nodes,iomodel,LsfReinitializationAnalysisEnum,finiteelement); 40 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 41 }/*}}}*/ 42 void LsfReinitializationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 45 void LsfReinitializationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 43 46 /* Do nothing for now */ 44 47 }/*}}}*/ 45 void LsfReinitializationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/46 /* Do nothing for now */47 }/*}}}*/48 48 49 49 /*Finite element Analysis*/ 50 void LsfReinitializationAnalysis::Core(FemModel* femmodel){/*{{{*/50 void LsfReinitializationAnalysis::Core(FemModel* femmodel){/*{{{*/ 51 51 52 52 /*parameters: */ … … 249 249 return pe; 250 250 }/*}}}*/ 251 void LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 251 void LsfReinitializationAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 252 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 253 * For node i, Bi can be expressed in the actual coordinate system 254 * by: 255 * Bi=[ N ] 256 * [ N ] 257 * where N is the finiteelement function for node i. 258 * 259 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes) 260 */ 261 262 /*Fetch number of nodes for this finite element*/ 263 int numnodes = element->GetNumberOfNodes(); 264 265 /*Get nodal functions*/ 266 IssmDouble* basis=xNew<IssmDouble>(numnodes); 267 element->NodalFunctions(basis,gauss); 268 269 /*Build B: */ 270 for(int i=0;i<numnodes;i++){ 271 B[numnodes*0+i] = basis[i]; 272 B[numnodes*1+i] = basis[i]; 273 } 274 275 /*Clean-up*/ 276 xDelete<IssmDouble>(basis); 277 }/*}}}*/ 278 void LsfReinitializationAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 279 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 280 * For node i, Bi' can be expressed in the actual coordinate system 281 * by: 282 * Bi_prime=[ dN/dx ] 283 * [ dN/dy ] 284 * where N is the finiteelement function for node i. 285 * 286 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes) 287 */ 288 289 /*Fetch number of nodes for this finite element*/ 290 int numnodes = element->GetNumberOfNodes(); 291 292 /*Get nodal functions derivatives*/ 293 IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes); 294 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 295 296 /*Build B': */ 297 for(int i=0;i<numnodes;i++){ 298 Bprime[numnodes*0+i] = dbasis[0*numnodes+i]; 299 Bprime[numnodes*1+i] = dbasis[1*numnodes+i]; 300 } 301 302 /*Clean-up*/ 303 xDelete<IssmDouble>(dbasis); 304 305 }/*}}}*/ 306 IssmDouble LsfReinitializationAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/ 307 // returns distance d of point q to straight going through points s0, s1 308 // d=|a x b|/|b| 309 // with a=q-s0, b=s1-s0 310 311 /* Intermediaries */ 312 const int dim=2; 313 int i; 314 IssmDouble a[dim], b[dim]; 315 IssmDouble norm_b; 316 317 for(i=0;i<dim;i++){ 318 a[i]=q[i]-s0[i]; 319 b[i]=s1[i]-s0[i]; 320 } 321 322 norm_b=0.; 323 for(i=0;i<dim;i++) 324 norm_b+=b[i]*b[i]; 325 norm_b=sqrt(norm_b); 326 _assert_(norm_b>0.); 327 328 return fabs(a[0]*b[1]-a[1]*b[0])/norm_b; 329 }/*}}}*/ 330 void LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 252 331 253 332 IssmDouble lsf; … … 284 363 285 364 }/*}}}*/ 286 void LsfReinitializationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/365 void LsfReinitializationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 287 366 _error_("Not implemented yet"); 288 367 }/*}}}*/ 289 void LsfReinitializationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/368 void LsfReinitializationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 290 369 291 370 int domaintype; … … 301 380 } 302 381 }/*}}}*/ 303 void LsfReinitializationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 304 /* Do nothing for now */ 305 }/*}}}*/ 306 void LsfReinitializationAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 307 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 308 * For node i, Bi can be expressed in the actual coordinate system 309 * by: 310 * Bi=[ N ] 311 * [ N ] 312 * where N is the finiteelement function for node i. 313 * 314 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes) 315 */ 316 317 /*Fetch number of nodes for this finite element*/ 318 int numnodes = element->GetNumberOfNodes(); 319 320 /*Get nodal functions*/ 321 IssmDouble* basis=xNew<IssmDouble>(numnodes); 322 element->NodalFunctions(basis,gauss); 323 324 /*Build B: */ 325 for(int i=0;i<numnodes;i++){ 326 B[numnodes*0+i] = basis[i]; 327 B[numnodes*1+i] = basis[i]; 328 } 329 330 /*Clean-up*/ 331 xDelete<IssmDouble>(basis); 332 }/*}}}*/ 333 void LsfReinitializationAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 334 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 335 * For node i, Bi' can be expressed in the actual coordinate system 336 * by: 337 * Bi_prime=[ dN/dx ] 338 * [ dN/dy ] 339 * where N is the finiteelement function for node i. 340 * 341 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes) 342 */ 343 344 /*Fetch number of nodes for this finite element*/ 345 int numnodes = element->GetNumberOfNodes(); 346 347 /*Get nodal functions derivatives*/ 348 IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes); 349 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 350 351 /*Build B': */ 352 for(int i=0;i<numnodes;i++){ 353 Bprime[numnodes*0+i] = dbasis[0*numnodes+i]; 354 Bprime[numnodes*1+i] = dbasis[1*numnodes+i]; 355 } 356 357 /*Clean-up*/ 358 xDelete<IssmDouble>(dbasis); 359 360 }/*}}}*/ 361 362 /* Other */ 363 void LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/ 382 bool LsfReinitializationAnalysis::ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol){/*{{{*/ 383 384 /*Output*/ 385 bool converged = true; 386 387 /*Intermediary*/ 388 Vector<IssmDouble>* dlsfg = NULL; 389 IssmDouble norm_dlsf,norm_lsf; 390 391 /*compute norm(du)/norm(u)*/ 392 dlsfg=lsfg_old->Duplicate(); lsfg_old->Copy(dlsfg); dlsfg->AYPX(lsfg,-1.0); 393 norm_dlsf=dlsfg->Norm(NORM_TWO); norm_lsf=lsfg_old->Norm(NORM_TWO); 394 if (xIsNan<IssmDouble>(norm_dlsf) || xIsNan<IssmDouble>(norm_lsf)) _error_("convergence criterion is NaN!"); 395 if((norm_dlsf/norm_lsf)<reltol){ 396 if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<" Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" < "<<reltol*100<<" %\n"); 397 } 398 else{ 399 if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<" Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" > "<<reltol*100<<" %\n"); 400 converged=false; 401 } 402 403 /*Cleanup*/ 404 delete dlsfg; 405 406 return converged; 407 }/*}}}*/ 408 void LsfReinitializationAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/ 409 410 /* Intermediaries */ 411 int i; 412 IssmDouble dmaxp,dmaxm,val; 413 Element* element; 414 415 /*Initialize vector with number of vertices*/ 416 int numvertices=femmodel->vertices->NumberOfVertices(); 417 418 Vector<IssmDouble>* vec_dist_zerolevelset = NULL; 419 GetVectorFromInputsx(&vec_dist_zerolevelset, femmodel, MaskIceLevelsetEnum, VertexEnum); 420 421 /* set distance on elements intersected by zero levelset */ 422 for(i=0;i<femmodel->elements->Size();i++){ 423 element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 424 if(element->IsZeroLevelset(MaskIceLevelsetEnum)){ 425 SetDistanceToZeroLevelsetElement(vec_dist_zerolevelset, element); 426 } 427 } 428 vec_dist_zerolevelset->Assemble(); 429 430 /* Get maximum distance to interface along vertices */ 431 dmaxp=0.; dmaxm=0.; 432 for(i=0;i<numvertices;i++){ 433 vec_dist_zerolevelset->GetValue(&val,i); 434 if((val>0.) && (val>dmaxp)) 435 dmaxp=val; 436 else if((val<0.) && (val<dmaxm)) 437 dmaxm=val; 438 } 439 //wait until all values are computed 440 441 /* set all none intersected vertices to max/min distance */ 442 for(i=0;i<numvertices;i++){ 443 vec_dist_zerolevelset->GetValue(&val,i); 444 if(val==1.) //FIXME: improve check 445 vec_dist_zerolevelset->SetValue(i,3.*dmaxp,INS_VAL); 446 else if(val==-1.) 447 vec_dist_zerolevelset->SetValue(i,3.*dmaxm,INS_VAL); 448 } 449 450 /*Assemble vector and serialize */ 451 vec_dist_zerolevelset->Assemble(); 452 IssmDouble* dist_zerolevelset=vec_dist_zerolevelset->ToMPISerial(); 453 InputUpdateFromVectorx(femmodel,dist_zerolevelset,MaskIceLevelsetEnum,VertexSIdEnum); 454 455 /*Clean up and return*/ 456 delete vec_dist_zerolevelset; 457 delete dist_zerolevelset; 458 459 }/*}}}*/ 460 void LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/ 461 462 if(!element->IsZeroLevelset(MaskIceLevelsetEnum)) 463 return; 464 465 /* Intermediaries */ 466 int dim=3; 467 int i,d; 468 IssmDouble dist,lsf_old; 469 470 int numvertices=element->GetNumberOfVertices(); 471 472 IssmDouble* lsf = xNew<IssmDouble>(numvertices); 473 IssmDouble* sign_lsf = xNew<IssmDouble>(numvertices); 474 IssmDouble* signed_dist = xNew<IssmDouble>(numvertices); 475 IssmDouble* s0 = xNew<IssmDouble>(dim); 476 IssmDouble* s1 = xNew<IssmDouble>(dim); 477 IssmDouble* v = xNew<IssmDouble>(dim); 478 IssmDouble* xyz_list = NULL; 479 IssmDouble* xyz_list_zero = NULL; 480 481 /* retrieve inputs and parameters */ 482 element->GetVerticesCoordinates(&xyz_list); 483 element->GetInputListOnVertices(lsf,MaskIceLevelsetEnum); 484 485 /* get sign of levelset function */ 486 for(i=0;i<numvertices;i++) 487 sign_lsf[i]=(lsf[i]>=0.?1.:-1.); 488 489 element->ZeroLevelsetCoordinates(&xyz_list_zero, xyz_list, MaskIceLevelsetEnum); 490 for(i=0;i<dim;i++){ 491 s0[i]=xyz_list_zero[0+i]; 492 s1[i]=xyz_list_zero[3+i]; 493 } 494 495 /* get signed_distance of vertices to zero levelset straight */ 496 for(i=0;i<numvertices;i++){ 497 for(d=0;d<dim;d++) 498 v[d]=xyz_list[dim*i+d]; 499 dist=GetDistanceToStraight(&v[0],&s0[0],&s1[0]); 500 signed_dist[i]=sign_lsf[i]*dist; 501 } 502 503 /* insert signed_distance into vec_signed_dist, if computed distance is smaller */ 504 for(i=0;i<numvertices;i++){ 505 vec_signed_dist->GetValue(&lsf_old, element->vertices[i]->Sid()); 506 /* initial lsf values are +-1. Update those fields or if distance to interface smaller.*/ 507 if(fabs(lsf_old)==1. || fabs(signed_dist[i])<fabs(lsf_old)) 508 vec_signed_dist->SetValue(element->vertices[i]->Sid(),signed_dist[i],INS_VAL); 509 } 510 511 xDelete<IssmDouble>(lsf); 512 xDelete<IssmDouble>(sign_lsf); 513 xDelete<IssmDouble>(signed_dist); 514 xDelete<IssmDouble>(s0); 515 xDelete<IssmDouble>(s1); 516 xDelete<IssmDouble>(v); 517 518 }/*}}}*/ 519 void LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/ 364 520 365 521 int i,k, numnodes; … … 399 555 400 556 }/*}}}*/ 401 void LsfReinitializationAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/ 402 403 /* Intermediaries */ 404 int i; 405 IssmDouble dmaxp,dmaxm,val; 406 Element* element; 407 408 /*Initialize vector with number of vertices*/ 409 int numvertices=femmodel->vertices->NumberOfVertices(); 410 411 Vector<IssmDouble>* vec_dist_zerolevelset = NULL; 412 GetVectorFromInputsx(&vec_dist_zerolevelset, femmodel, MaskIceLevelsetEnum, VertexEnum); 413 414 /* set distance on elements intersected by zero levelset */ 415 for(i=0;i<femmodel->elements->Size();i++){ 416 element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 417 if(element->IsZeroLevelset(MaskIceLevelsetEnum)){ 418 SetDistanceToZeroLevelsetElement(vec_dist_zerolevelset, element); 419 } 420 } 421 vec_dist_zerolevelset->Assemble(); 422 423 /* Get maximum distance to interface along vertices */ 424 dmaxp=0.; dmaxm=0.; 425 for(i=0;i<numvertices;i++){ 426 vec_dist_zerolevelset->GetValue(&val,i); 427 if((val>0.) && (val>dmaxp)) 428 dmaxp=val; 429 else if((val<0.) && (val<dmaxm)) 430 dmaxm=val; 431 } 432 //wait until all values are computed 433 434 /* set all none intersected vertices to max/min distance */ 435 for(i=0;i<numvertices;i++){ 436 vec_dist_zerolevelset->GetValue(&val,i); 437 if(val==1.) //FIXME: improve check 438 vec_dist_zerolevelset->SetValue(i,3.*dmaxp,INS_VAL); 439 else if(val==-1.) 440 vec_dist_zerolevelset->SetValue(i,3.*dmaxm,INS_VAL); 441 } 442 443 /*Assemble vector and serialize */ 444 vec_dist_zerolevelset->Assemble(); 445 IssmDouble* dist_zerolevelset=vec_dist_zerolevelset->ToMPISerial(); 446 InputUpdateFromVectorx(femmodel,dist_zerolevelset,MaskIceLevelsetEnum,VertexSIdEnum); 447 448 /*Clean up and return*/ 449 delete vec_dist_zerolevelset; 450 delete dist_zerolevelset; 451 452 }/*}}}*/ 453 void LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/ 454 455 if(!element->IsZeroLevelset(MaskIceLevelsetEnum)) 456 return; 457 458 /* Intermediaries */ 459 int dim=3; 460 int i,d; 461 IssmDouble dist,lsf_old; 462 463 int numvertices=element->GetNumberOfVertices(); 464 465 IssmDouble* lsf = xNew<IssmDouble>(numvertices); 466 IssmDouble* sign_lsf = xNew<IssmDouble>(numvertices); 467 IssmDouble* signed_dist = xNew<IssmDouble>(numvertices); 468 IssmDouble* s0 = xNew<IssmDouble>(dim); 469 IssmDouble* s1 = xNew<IssmDouble>(dim); 470 IssmDouble* v = xNew<IssmDouble>(dim); 471 IssmDouble* xyz_list = NULL; 472 IssmDouble* xyz_list_zero = NULL; 473 474 /* retrieve inputs and parameters */ 475 element->GetVerticesCoordinates(&xyz_list); 476 element->GetInputListOnVertices(lsf,MaskIceLevelsetEnum); 477 478 /* get sign of levelset function */ 479 for(i=0;i<numvertices;i++) 480 sign_lsf[i]=(lsf[i]>=0.?1.:-1.); 481 482 element->ZeroLevelsetCoordinates(&xyz_list_zero, xyz_list, MaskIceLevelsetEnum); 483 for(i=0;i<dim;i++){ 484 s0[i]=xyz_list_zero[0+i]; 485 s1[i]=xyz_list_zero[3+i]; 486 } 487 488 /* get signed_distance of vertices to zero levelset straight */ 489 for(i=0;i<numvertices;i++){ 490 for(d=0;d<dim;d++) 491 v[d]=xyz_list[dim*i+d]; 492 dist=GetDistanceToStraight(&v[0],&s0[0],&s1[0]); 493 signed_dist[i]=sign_lsf[i]*dist; 494 } 495 496 /* insert signed_distance into vec_signed_dist, if computed distance is smaller */ 497 for(i=0;i<numvertices;i++){ 498 vec_signed_dist->GetValue(&lsf_old, element->vertices[i]->Sid()); 499 /* initial lsf values are +-1. Update those fields or if distance to interface smaller.*/ 500 if(fabs(lsf_old)==1. || fabs(signed_dist[i])<fabs(lsf_old)) 501 vec_signed_dist->SetValue(element->vertices[i]->Sid(),signed_dist[i],INS_VAL); 502 } 503 504 xDelete<IssmDouble>(lsf); 505 xDelete<IssmDouble>(sign_lsf); 506 xDelete<IssmDouble>(signed_dist); 507 xDelete<IssmDouble>(s0); 508 xDelete<IssmDouble>(s1); 509 xDelete<IssmDouble>(v); 510 511 }/*}}}*/ 512 IssmDouble LsfReinitializationAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/ 513 // returns distance d of point q to straight going through points s0, s1 514 // d=|a x b|/|b| 515 // with a=q-s0, b=s1-s0 516 517 /* Intermediaries */ 518 const int dim=2; 519 int i; 520 IssmDouble a[dim], b[dim]; 521 IssmDouble norm_b; 522 523 for(i=0;i<dim;i++){ 524 a[i]=q[i]-s0[i]; 525 b[i]=s1[i]-s0[i]; 526 } 527 528 norm_b=0.; 529 for(i=0;i<dim;i++) 530 norm_b+=b[i]*b[i]; 531 norm_b=sqrt(norm_b); 532 _assert_(norm_b>0.); 533 534 return fabs(a[0]*b[1]-a[1]*b[0])/norm_b; 535 }/*}}}*/ 536 bool LsfReinitializationAnalysis::ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol){/*{{{*/ 537 538 /*Output*/ 539 bool converged = true; 540 541 /*Intermediary*/ 542 Vector<IssmDouble>* dlsfg = NULL; 543 IssmDouble norm_dlsf,norm_lsf; 544 545 /*compute norm(du)/norm(u)*/ 546 dlsfg=lsfg_old->Duplicate(); lsfg_old->Copy(dlsfg); dlsfg->AYPX(lsfg,-1.0); 547 norm_dlsf=dlsfg->Norm(NORM_TWO); norm_lsf=lsfg_old->Norm(NORM_TWO); 548 if (xIsNan<IssmDouble>(norm_dlsf) || xIsNan<IssmDouble>(norm_lsf)) _error_("convergence criterion is NaN!"); 549 if((norm_dlsf/norm_lsf)<reltol){ 550 if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<" Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" < "<<reltol*100<<" %\n"); 551 } 552 else{ 553 if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<" Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" > "<<reltol*100<<" %\n"); 554 converged=false; 555 } 556 557 /*Cleanup*/ 558 delete dlsfg; 559 560 return converged; 561 }/*}}}*/ 557 void LsfReinitializationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 558 /* Do nothing for now */ 559 }/*}}}*/ -
issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 33 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss); 34 35 /* Other */ 36 void SetReinitSPCs(FemModel* femmodel); 37 void SetDistanceOnIntersectedElements(FemModel* femmodel); 38 void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_dist, Element* element); 39 IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1); 40 bool ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol); 28 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 29 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss); 30 IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1); 31 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 32 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 33 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 34 bool ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol); 35 void SetDistanceOnIntersectedElements(FemModel* femmodel); 36 void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_dist, Element* element); 37 void SetReinitSPCs(FemModel* femmodel); 38 void UpdateConstraints(FemModel* femmodel); 41 39 }; 42 40 #endif -
issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp
r18521 r18930 6 6 7 7 /*Model processing*/ 8 void MasstransportAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 /*Fetch parameters: */ 11 int stabilization; 12 iomodel->Constant(&stabilization,MasstransportStabilizationEnum); 13 14 /*Do not add constraints in DG, they are weakly imposed*/ 15 if(stabilization!=3){ 16 IoModelToConstraintsx(constraints,iomodel,MasstransportSpcthicknessEnum,MasstransportAnalysisEnum,P1Enum); 17 } 18 19 /*FCT, constraints are imposed using penalties*/ 20 if(stabilization==4){ 21 constraints->ActivatePenaltyMethod(MasstransportAnalysisEnum); 22 } 23 }/*}}}*/ 24 void MasstransportAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 25 26 /*Intermediaries*/ 27 int element; 28 int penpair_ids[2]; 29 int count=0; 30 int stabilization; 31 int numvertex_pairing; 32 33 /*Fetch parameters: */ 34 iomodel->Constant(&stabilization,MasstransportStabilizationEnum); 35 36 /*Loads only in DG*/ 37 if (stabilization==3){ 38 39 /*Get faces and elements*/ 40 CreateFaces(iomodel); 41 iomodel->FetchData(1,ThicknessEnum); 42 43 /*First load data:*/ 44 for(int i=0;i<iomodel->numberoffaces;i++){ 45 46 /*Get left and right elements*/ 47 element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2] 48 49 /*Now, if this element is not in the partition, pass: */ 50 if(!iomodel->my_elements[element]) continue; 51 52 /* Add load */ 53 loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,MasstransportAnalysisEnum)); 54 } 55 56 /*Free data: */ 57 iomodel->DeleteData(1,ThicknessEnum); 58 } 59 60 /*Create Penpair for vertex_pairing: */ 61 IssmDouble *vertex_pairing=NULL; 62 IssmDouble *nodeonbase=NULL; 63 iomodel->FetchData(&vertex_pairing,&numvertex_pairing,NULL,MasstransportVertexPairingEnum); 64 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(&nodeonbase,NULL,NULL,MeshVertexonbaseEnum); 65 66 for(int i=0;i<numvertex_pairing;i++){ 67 68 if(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+0])-1]){ 69 70 /*In debugging mode, check that the second node is in the same cpu*/ 71 _assert_(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+1])-1]); 72 73 /*Skip if one of the two is not on the bed*/ 74 if(iomodel->domaintype!=Domain2DhorizontalEnum){ 75 if(!(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+0])-1])) || !(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+1])-1]))) continue; 76 } 77 78 /*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]); 81 82 /*Create Load*/ 83 loads->AddObject(new Penpair( 84 iomodel->loadcounter+count+1, 85 &penpair_ids[0], 86 MasstransportAnalysisEnum)); 87 count++; 88 } 89 } 90 91 /*free ressources: */ 92 iomodel->DeleteData(vertex_pairing,MasstransportVertexPairingEnum); 93 iomodel->DeleteData(nodeonbase,MeshVertexonbaseEnum); 94 95 }/*}}}*/ 96 void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 97 98 /*Fetch parameters: */ 99 int stabilization; 100 iomodel->Constant(&stabilization,MasstransportStabilizationEnum); 101 102 /*Check in 3d*/ 103 if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet"); 104 105 /*Create Nodes either DG or CG depending on stabilization*/ 106 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 107 if(stabilization!=3){ 108 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1Enum); 109 } 110 else{ 111 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum); 112 } 113 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 114 }/*}}}*/ 8 115 int MasstransportAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 116 return 1; 10 }/*}}}*/11 void MasstransportAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 13 int numoutputs;14 char** requestedoutputs = NULL;15 16 parameters->AddObject(iomodel->CopyConstantObject(FlowequationIsFSEnum));17 parameters->AddObject(iomodel->CopyConstantObject(MasstransportIsfreesurfaceEnum));18 parameters->AddObject(iomodel->CopyConstantObject(MasstransportHydrostaticAdjustmentEnum));19 parameters->AddObject(iomodel->CopyConstantObject(MasstransportStabilizationEnum));20 parameters->AddObject(iomodel->CopyConstantObject(MasstransportMinThicknessEnum));21 parameters->AddObject(iomodel->CopyConstantObject(MasstransportPenaltyFactorEnum));22 23 iomodel->FetchData(&requestedoutputs,&numoutputs,MasstransportRequestedOutputsEnum);24 parameters->AddObject(new IntParam(MasstransportNumRequestedOutputsEnum,numoutputs));25 if(numoutputs)parameters->AddObject(new StringArrayParam(MasstransportRequestedOutputsEnum,requestedoutputs,numoutputs));26 iomodel->DeleteData(&requestedoutputs,numoutputs,MasstransportRequestedOutputsEnum);27 28 117 }/*}}}*/ 29 118 void MasstransportAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 126 215 127 216 }/*}}}*/ 128 void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 129 130 /*Fetch parameters: */ 131 int stabilization; 132 iomodel->Constant(&stabilization,MasstransportStabilizationEnum); 133 134 /*Check in 3d*/ 135 if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet"); 136 137 /*Create Nodes either DG or CG depending on stabilization*/ 138 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 139 if(stabilization!=3){ 140 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1Enum); 141 } 142 else{ 143 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum); 144 } 145 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 146 }/*}}}*/ 147 void MasstransportAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 148 149 /*Fetch parameters: */ 150 int stabilization; 151 iomodel->Constant(&stabilization,MasstransportStabilizationEnum); 152 153 /*Do not add constraints in DG, they are weakly imposed*/ 154 if(stabilization!=3){ 155 IoModelToConstraintsx(constraints,iomodel,MasstransportSpcthicknessEnum,MasstransportAnalysisEnum,P1Enum); 156 } 157 158 /*FCT, constraints are imposed using penalties*/ 159 if(stabilization==4){ 160 constraints->ActivatePenaltyMethod(MasstransportAnalysisEnum); 161 } 162 }/*}}}*/ 163 void MasstransportAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 164 165 /*Intermediaries*/ 166 int element; 167 int penpair_ids[2]; 168 int count=0; 169 int stabilization; 170 int numvertex_pairing; 171 172 /*Fetch parameters: */ 173 iomodel->Constant(&stabilization,MasstransportStabilizationEnum); 174 175 /*Loads only in DG*/ 176 if (stabilization==3){ 177 178 /*Get faces and elements*/ 179 CreateFaces(iomodel); 180 iomodel->FetchData(1,ThicknessEnum); 181 182 /*First load data:*/ 183 for(int i=0;i<iomodel->numberoffaces;i++){ 184 185 /*Get left and right elements*/ 186 element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2] 187 188 /*Now, if this element is not in the partition, pass: */ 189 if(!iomodel->my_elements[element]) continue; 190 191 /* Add load */ 192 loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,MasstransportAnalysisEnum)); 193 } 194 195 /*Free data: */ 196 iomodel->DeleteData(1,ThicknessEnum); 197 } 198 199 /*Create Penpair for vertex_pairing: */ 200 IssmDouble *vertex_pairing=NULL; 201 IssmDouble *nodeonbase=NULL; 202 iomodel->FetchData(&vertex_pairing,&numvertex_pairing,NULL,MasstransportVertexPairingEnum); 203 if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(&nodeonbase,NULL,NULL,MeshVertexonbaseEnum); 204 205 for(int i=0;i<numvertex_pairing;i++){ 206 207 if(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+0])-1]){ 208 209 /*In debugging mode, check that the second node is in the same cpu*/ 210 _assert_(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+1])-1]); 211 212 /*Skip if one of the two is not on the bed*/ 213 if(iomodel->domaintype!=Domain2DhorizontalEnum){ 214 if(!(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+0])-1])) || !(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+1])-1]))) continue; 215 } 216 217 /*Get node ids*/ 218 penpair_ids[0]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+0]); 219 penpair_ids[1]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+1]); 220 221 /*Create Load*/ 222 loads->AddObject(new Penpair( 223 iomodel->loadcounter+count+1, 224 &penpair_ids[0], 225 MasstransportAnalysisEnum)); 226 count++; 227 } 228 } 229 230 /*free ressources: */ 231 iomodel->DeleteData(vertex_pairing,MasstransportVertexPairingEnum); 232 iomodel->DeleteData(nodeonbase,MeshVertexonbaseEnum); 217 void MasstransportAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 218 219 int numoutputs; 220 char** requestedoutputs = NULL; 221 222 parameters->AddObject(iomodel->CopyConstantObject(FlowequationIsFSEnum)); 223 parameters->AddObject(iomodel->CopyConstantObject(MasstransportIsfreesurfaceEnum)); 224 parameters->AddObject(iomodel->CopyConstantObject(MasstransportHydrostaticAdjustmentEnum)); 225 parameters->AddObject(iomodel->CopyConstantObject(MasstransportStabilizationEnum)); 226 parameters->AddObject(iomodel->CopyConstantObject(MasstransportMinThicknessEnum)); 227 parameters->AddObject(iomodel->CopyConstantObject(MasstransportPenaltyFactorEnum)); 228 229 iomodel->FetchData(&requestedoutputs,&numoutputs,MasstransportRequestedOutputsEnum); 230 parameters->AddObject(new IntParam(MasstransportNumRequestedOutputsEnum,numoutputs)); 231 if(numoutputs)parameters->AddObject(new StringArrayParam(MasstransportRequestedOutputsEnum,requestedoutputs,numoutputs)); 232 iomodel->DeleteData(&requestedoutputs,numoutputs,MasstransportRequestedOutputsEnum); 233 233 234 234 }/*}}}*/ … … 625 625 return pe; 626 626 }/*}}}*/ 627 void MasstransportAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/627 void MasstransportAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 628 628 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 629 629 * For node i, Bi can be expressed in the actual coordinate system … … 653 653 xDelete<IssmDouble>(basis); 654 654 }/*}}}*/ 655 void MasstransportAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/655 void MasstransportAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 656 656 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 657 657 * For node i, Bi' can be expressed in the actual coordinate system … … 682 682 683 683 }/*}}}*/ 684 void MasstransportAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/684 void MasstransportAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 685 685 element->GetSolutionFromInputsOneDof(solution,ThicknessEnum); 686 686 }/*}}}*/ 687 void MasstransportAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/687 void MasstransportAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 688 688 _error_("Not implemented yet"); 689 689 }/*}}}*/ 690 void MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/690 void MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 691 691 692 692 int i,hydroadjustment,domaintype; … … 772 772 if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;}; 773 773 }/*}}}*/ 774 void MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/774 void MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 775 775 776 776 bool islevelset; … … 783 783 784 784 /*Flux Correction Transport*/ 785 ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/ 786 787 /* Check if ice in element */ 788 if(!element->IsIceInElement()) return NULL; 789 790 /*Intermediaries */ 791 IssmDouble Jdet; 792 IssmDouble vx,vy; 793 IssmDouble* xyz_list = NULL; 794 795 /*Fetch number of nodes and dof for this finite element*/ 796 int numnodes = element->GetNumberOfNodes(); 797 int dim = 2; 798 799 /*Initialize Element vector and other vectors*/ 800 ElementMatrix* Ke = element->NewElementMatrix(); 801 IssmDouble* B = xNew<IssmDouble>(dim*numnodes); 802 IssmDouble* Bprime = xNew<IssmDouble>(dim*numnodes); 803 IssmDouble* D = xNewZeroInit<IssmDouble>(dim*dim); 804 805 /*Retrieve all inputs and parameters*/ 806 element->GetVerticesCoordinates(&xyz_list); 807 Input* vxaverage_input=element->GetInput(VxEnum); _assert_(vxaverage_input); 808 Input* vyaverage_input=element->GetInput(VyEnum); _assert_(vyaverage_input); 809 810 /* Start looping on the number of gaussian points: */ 811 Gauss* gauss=element->NewGauss(2); 812 for(int ig=gauss->begin();ig<gauss->end();ig++){ 813 gauss->GaussPoint(ig); 814 815 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 816 GetB(B,element,dim,xyz_list,gauss); 817 GetBprime(Bprime,element,dim,xyz_list,gauss); 818 vxaverage_input->GetInputValue(&vx,gauss); 819 vyaverage_input->GetInputValue(&vy,gauss); 820 821 D[0*dim+0] = -gauss->weight*vx*Jdet; 822 D[1*dim+1] = -gauss->weight*vy*Jdet; 823 824 TripleMultiply(B,dim,numnodes,1, 825 D,dim,dim,0, 826 Bprime,dim,numnodes,0, 827 &Ke->values[0],1); 828 829 } 830 831 /*Clean up and return*/ 832 xDelete<IssmDouble>(xyz_list); 833 xDelete<IssmDouble>(B); 834 xDelete<IssmDouble>(Bprime); 835 xDelete<IssmDouble>(D); 836 delete gauss; 837 return Ke; 838 }/*}}}*/ 839 ElementMatrix* MasstransportAnalysis::CreateMassMatrix(Element* element){/*{{{*/ 840 841 /* Check if ice in element */ 842 if(!element->IsIceInElement()) return NULL; 843 844 /*Intermediaries*/ 845 IssmDouble D,Jdet; 846 IssmDouble* xyz_list = NULL; 847 848 /*Fetch number of nodes and dof for this finite element*/ 849 int numnodes = element->GetNumberOfNodes(); 850 851 /*Initialize Element vector and other vectors*/ 852 ElementMatrix* Me = element->NewElementMatrix(); 853 IssmDouble* basis = xNew<IssmDouble>(numnodes); 854 855 /*Retrieve all inputs and parameters*/ 856 element->GetVerticesCoordinates(&xyz_list); 857 858 /* Start looping on the number of gaussian points: */ 859 Gauss* gauss=element->NewGauss(2); 860 for(int ig=gauss->begin();ig<gauss->end();ig++){ 861 gauss->GaussPoint(ig); 862 863 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 864 element->NodalFunctions(basis,gauss); 865 866 D=gauss->weight*Jdet; 867 TripleMultiply(basis,1,numnodes,1, 868 &D,1,1,0, 869 basis,1,numnodes,0, 870 &Me->values[0],1); 871 } 872 873 /*Clean up and return*/ 874 xDelete<IssmDouble>(xyz_list); 875 xDelete<IssmDouble>(basis); 876 delete gauss; 877 return Me; 878 }/*}}}*/ 879 void MasstransportAnalysis::FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel){/*{{{*/ 880 881 /*Output*/ 882 Matrix<IssmDouble>* Kff = NULL; 883 Matrix<IssmDouble>* Kfs = NULL; 884 885 /*Initialize Jacobian Matrix*/ 886 AllocateSystemMatricesx(&Kff,&Kfs,NULL,NULL,femmodel); 887 888 /*Create and assemble matrix*/ 889 for(int i=0;i<femmodel->elements->Size();i++){ 890 Element* element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 891 ElementMatrix* Ke = this->CreateFctKMatrix(element); 892 if(Ke) Ke->AddToGlobal(Kff,Kfs); 893 delete Ke; 894 } 895 Kff->Assemble(); 896 Kfs->Assemble(); 897 898 /*Assign output pointer*/ 899 *pKff=Kff; 900 if(pKfs){ 901 *pKfs=Kfs; 902 } 903 else{ 904 delete Kfs; 905 } 906 }/*}}}*/ 785 907 void MasstransportAnalysis::LumpedMassMatrix(Vector<IssmDouble>** pMlff,FemModel* femmodel){/*{{{*/ 786 908 … … 829 951 *pMff=Mff; 830 952 }/*}}}*/ 831 ElementMatrix* MasstransportAnalysis::CreateMassMatrix(Element* element){/*{{{*/832 833 /* Check if ice in element */834 if(!element->IsIceInElement()) return NULL;835 836 /*Intermediaries*/837 IssmDouble D,Jdet;838 IssmDouble* xyz_list = NULL;839 840 /*Fetch number of nodes and dof for this finite element*/841 int numnodes = element->GetNumberOfNodes();842 843 /*Initialize Element vector and other vectors*/844 ElementMatrix* Me = element->NewElementMatrix();845 IssmDouble* basis = xNew<IssmDouble>(numnodes);846 847 /*Retrieve all inputs and parameters*/848 element->GetVerticesCoordinates(&xyz_list);849 850 /* Start looping on the number of gaussian points: */851 Gauss* gauss=element->NewGauss(2);852 for(int ig=gauss->begin();ig<gauss->end();ig++){853 gauss->GaussPoint(ig);854 855 element->JacobianDeterminant(&Jdet,xyz_list,gauss);856 element->NodalFunctions(basis,gauss);857 858 D=gauss->weight*Jdet;859 TripleMultiply(basis,1,numnodes,1,860 &D,1,1,0,861 basis,1,numnodes,0,862 &Me->values[0],1);863 }864 865 /*Clean up and return*/866 xDelete<IssmDouble>(xyz_list);867 xDelete<IssmDouble>(basis);868 delete gauss;869 return Me;870 }/*}}}*/871 void MasstransportAnalysis::FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel){/*{{{*/872 873 /*Output*/874 Matrix<IssmDouble>* Kff = NULL;875 Matrix<IssmDouble>* Kfs = NULL;876 877 /*Initialize Jacobian Matrix*/878 AllocateSystemMatricesx(&Kff,&Kfs,NULL,NULL,femmodel);879 880 /*Create and assemble matrix*/881 for(int i=0;i<femmodel->elements->Size();i++){882 Element* element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));883 ElementMatrix* Ke = this->CreateFctKMatrix(element);884 if(Ke) Ke->AddToGlobal(Kff,Kfs);885 delete Ke;886 }887 Kff->Assemble();888 Kfs->Assemble();889 890 /*Assign output pointer*/891 *pKff=Kff;892 if(pKfs){893 *pKfs=Kfs;894 }895 else{896 delete Kfs;897 }898 }/*}}}*/899 ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/900 901 /* Check if ice in element */902 if(!element->IsIceInElement()) return NULL;903 904 /*Intermediaries */905 IssmDouble Jdet;906 IssmDouble vx,vy;907 IssmDouble* xyz_list = NULL;908 909 /*Fetch number of nodes and dof for this finite element*/910 int numnodes = element->GetNumberOfNodes();911 int dim = 2;912 913 /*Initialize Element vector and other vectors*/914 ElementMatrix* Ke = element->NewElementMatrix();915 IssmDouble* B = xNew<IssmDouble>(dim*numnodes);916 IssmDouble* Bprime = xNew<IssmDouble>(dim*numnodes);917 IssmDouble* D = xNewZeroInit<IssmDouble>(dim*dim);918 919 /*Retrieve all inputs and parameters*/920 element->GetVerticesCoordinates(&xyz_list);921 Input* vxaverage_input=element->GetInput(VxEnum); _assert_(vxaverage_input);922 Input* vyaverage_input=element->GetInput(VyEnum); _assert_(vyaverage_input);923 924 /* Start looping on the number of gaussian points: */925 Gauss* gauss=element->NewGauss(2);926 for(int ig=gauss->begin();ig<gauss->end();ig++){927 gauss->GaussPoint(ig);928 929 element->JacobianDeterminant(&Jdet,xyz_list,gauss);930 GetB(B,element,dim,xyz_list,gauss);931 GetBprime(Bprime,element,dim,xyz_list,gauss);932 vxaverage_input->GetInputValue(&vx,gauss);933 vyaverage_input->GetInputValue(&vy,gauss);934 935 D[0*dim+0] = -gauss->weight*vx*Jdet;936 D[1*dim+1] = -gauss->weight*vy*Jdet;937 938 TripleMultiply(B,dim,numnodes,1,939 D,dim,dim,0,940 Bprime,dim,numnodes,0,941 &Ke->values[0],1);942 943 }944 945 /*Clean up and return*/946 xDelete<IssmDouble>(xyz_list);947 xDelete<IssmDouble>(B);948 xDelete<IssmDouble>(Bprime);949 xDelete<IssmDouble>(D);950 delete gauss;951 return Ke;952 }/*}}}*/ -
issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.h
r18345 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 30 30 ElementVector* CreatePVectorCG(Element* element); 31 31 ElementVector* CreatePVectorDG(Element* element); 32 void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);33 void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);34 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);35 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);36 void InputUpdateFromSolution(IssmDouble* solution,Element* element);37 void UpdateConstraints(FemModel* femmodel);32 void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss); 33 void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss); 34 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 35 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 36 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 37 void UpdateConstraints(FemModel* femmodel); 38 38 39 39 /*FCT*/ 40 ElementMatrix* CreateFctKMatrix(Element* element); 41 ElementMatrix* CreateMassMatrix(Element* element); 42 void FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel); 40 43 void LumpedMassMatrix(Vector<IssmDouble>** pMLff,FemModel* femmodel); 41 44 void MassMatrix(Matrix<IssmDouble>** pMff,FemModel* femmodel); 42 void FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel);43 ElementMatrix* CreateMassMatrix(Element* element);44 ElementMatrix* CreateFctKMatrix(Element* element);45 45 }; 46 46 #endif -
issm/trunk-jpl/src/c/analyses/MeltingAnalysis.cpp
r18729 r18930 6 6 7 7 /*Model processing*/ 8 void MeltingAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 /*No Constraints*/ 10 }/*}}}*/ 11 void MeltingAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 12 13 /*if 2d: Error*/ 14 if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet"); 15 16 //create penalties for nodes: no node can have a temperature over the melting point 17 iomodel->FetchData(1,MeshVertexonbaseEnum); 18 CreateSingleNodeToElementConnectivity(iomodel); 19 20 for(int i=0;i<iomodel->numberofvertices;i++){ 21 if(iomodel->my_vertices[i]){ 22 if (reCast<int>(iomodel->Data(MeshVertexonbaseEnum)[i])){ 23 loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,MeltingAnalysisEnum)); 24 } 25 } 26 } 27 iomodel->DeleteData(1,MeshVertexonbaseEnum); 28 29 }/*}}}*/ 30 void MeltingAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 31 32 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 33 ::CreateNodes(nodes,iomodel,MeltingAnalysisEnum,P1Enum); 34 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 35 }/*}}}*/ 8 36 int MeltingAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 37 return 1; 10 }/*}}}*/11 void MeltingAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 38 }/*}}}*/ 13 39 void MeltingAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 39 65 iomodel->FetchDataToInput(elements,PressureEnum); 40 66 }/*}}}*/ 41 void MeltingAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 42 43 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 44 ::CreateNodes(nodes,iomodel,MeltingAnalysisEnum,P1Enum); 45 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 46 }/*}}}*/ 47 void MeltingAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 48 /*No Constraints*/ 49 }/*}}}*/ 50 void MeltingAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 51 52 /*if 2d: Error*/ 53 if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet"); 54 55 //create penalties for nodes: no node can have a temperature over the melting point 56 iomodel->FetchData(1,MeshVertexonbaseEnum); 57 CreateSingleNodeToElementConnectivity(iomodel); 58 59 for(int i=0;i<iomodel->numberofvertices;i++){ 60 if(iomodel->my_vertices[i]){ 61 if (reCast<int>(iomodel->Data(MeshVertexonbaseEnum)[i])){ 62 loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,MeltingAnalysisEnum)); 63 } 64 } 65 } 66 iomodel->DeleteData(1,MeshVertexonbaseEnum); 67 67 void MeltingAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 68 68 }/*}}}*/ 69 69 … … 126 126 return NULL; 127 127 }/*}}}*/ 128 void MeltingAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/128 void MeltingAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 129 129 _error_("not implemented yet"); 130 130 }/*}}}*/ 131 void MeltingAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/131 void MeltingAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 132 132 _error_("Not implemented yet"); 133 133 }/*}}}*/ 134 void MeltingAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/134 void MeltingAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 135 135 element->InputUpdateFromSolutionOneDof(solution,BasalforcingsGroundediceMeltingRateEnum); 136 136 }/*}}}*/ 137 void MeltingAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/137 void MeltingAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 138 138 /*Default, do nothing*/ 139 139 return; -
issm/trunk-jpl/src/c/analyses/MeltingAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void InputUpdateFromSolution(IssmDouble* solution,Element* element);31 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 32 }; 33 33 #endif -
issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp
r18057 r18930 6 6 7 7 /*Model processing*/ 8 int MeshdeformationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 _error_("not implemented"); 10 }/*}}}*/ 11 void MeshdeformationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 8 void MeshdeformationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 12 9 _error_("not implemented yet"); 13 10 }/*}}}*/ 14 void MeshdeformationAnalysis:: UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/11 void MeshdeformationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 15 12 _error_("not implemented yet"); 16 13 }/*}}}*/ … … 18 15 _error_("not implemented yet"); 19 16 }/*}}}*/ 20 void MeshdeformationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 17 int MeshdeformationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 18 _error_("not implemented"); 19 }/*}}}*/ 20 void MeshdeformationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ 21 21 _error_("not implemented yet"); 22 22 }/*}}}*/ 23 void MeshdeformationAnalysis:: CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/23 void MeshdeformationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 24 24 _error_("not implemented yet"); 25 25 }/*}}}*/ … … 42 42 _error_("not implemented yet"); 43 43 }/*}}}*/ 44 void MeshdeformationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/44 void MeshdeformationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 45 45 _error_("not implemented yet"); 46 46 }/*}}}*/ 47 void MeshdeformationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/47 void MeshdeformationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 48 48 _error_("Not implemented yet"); 49 49 }/*}}}*/ 50 void MeshdeformationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/50 void MeshdeformationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 51 51 _error_("not implemented yet"); 52 52 }/*}}}*/ 53 void MeshdeformationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/53 void MeshdeformationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 54 54 /*Default, do nothing*/ 55 55 return; -
issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void InputUpdateFromSolution(IssmDouble* solution,Element* element);31 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 32 }; 33 33 #endif -
issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp
r18624 r18930 6 6 7 7 /*Model processing*/ 8 void SeaiceAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 const int finiteelement = P1Enum; 11 IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvxEnum,SeaiceAnalysisEnum,finiteelement,0); 12 IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvyEnum,SeaiceAnalysisEnum,finiteelement,1); 13 }/*}}}*/ 14 void SeaiceAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 15 return; 16 }/*}}}*/ 17 void SeaiceAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 18 19 ::CreateNodes(nodes,iomodel,SeaiceAnalysisEnum,P1Enum); 20 21 }/*}}}*/ 8 22 int SeaiceAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 23 return 2; 10 }/*}}}*/11 void SeaiceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinConcentrationEnum));13 parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinThicknessEnum));14 parameters->AddObject(iomodel->CopyConstantObject(SeaiceMaxThicknessEnum));15 24 }/*}}}*/ 16 25 void SeaiceAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 49 58 iomodel->FetchDataToInput(elements,MeshYEnum); 50 59 }/*}}}*/ 51 void SeaiceAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 52 53 ::CreateNodes(nodes,iomodel,SeaiceAnalysisEnum,P1Enum); 54 55 }/*}}}*/ 56 void SeaiceAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 57 58 const int finiteelement = P1Enum; 59 IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvxEnum,SeaiceAnalysisEnum,finiteelement,0); 60 IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvyEnum,SeaiceAnalysisEnum,finiteelement,1); 61 }/*}}}*/ 62 void SeaiceAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 63 return; 60 void SeaiceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 61 parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinConcentrationEnum)); 62 parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinThicknessEnum)); 63 parameters->AddObject(iomodel->CopyConstantObject(SeaiceMaxThicknessEnum)); 64 64 }/*}}}*/ 65 65 … … 312 312 return pe; 313 313 }/*}}}*/ 314 void SeaiceAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 314 void SeaiceAnalysis::CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss){/*{{{*/ 315 316 /*Intermediaries*/ 317 IssmDouble D[3][3]; 318 IssmDouble damage,concentration; 319 320 /*Get Material parameters*/ 321 IssmDouble poisson = element->GetMaterialParameter(MaterialsPoissonEnum); 322 IssmDouble young_modulus = element->GetMaterialParameter(MaterialsYoungModulusEnum); 323 IssmDouble ridging_exponent = element->GetMaterialParameter(MaterialsRidgingExponentEnum); 324 325 /*Get damage input at this location*/ 326 Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input); 327 Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input); 328 damage_input->GetInputValue(&damage,gauss); 329 concentration_input->GetInputValue(&concentration,gauss); 330 331 /*Build D tensor once for all*/ 332 D[0][0] = 1.; D[0][1] = poisson; D[0][2] = 0.; 333 D[1][0] = poisson; D[1][1] = 1.; D[1][2] = 0.; 334 D[2][0] = 0.; D[2][1] = 0; D[2][2] = (1.-poisson)/2.; 335 for(int i=0;i<3;i++){ 336 for(int j=0;j<3;j++){ 337 D[i][j] = D[i][j]/(1-poisson*poisson); 338 } 339 } 340 341 /*Get f(A), E*/ 342 IssmDouble f = exp(ridging_exponent*(1.-concentration)); 343 IssmDouble E = young_modulus*(1.-damage)*f; 344 345 /*Let's build C = E*D */ 346 for(int i=0;i<3;i++){ 347 for(int j=0;j<3;j++){ 348 C[i*3+j] = E*D[i][j]; 349 } 350 } 351 }/*}}}*/ 352 void SeaiceAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 353 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 354 * For node i, Bi can be expressed in the actual coordinate system 355 * by: 356 * Bi=[ dN/dx 0 ] 357 * [ 0 dN/dy ] 358 * [ 1/2*dN/dy 1/2*dN/dx ] 359 * where N is the basis function for node i. 360 * 361 * We assume B has been allocated already */ 362 363 /*Fetch number of nodes for this finite element*/ 364 int numnodes = element->GetNumberOfNodes(); 365 366 /*Get nodal functions derivatives*/ 367 IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes); 368 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 369 370 /*Build B: */ 371 for(int i=0;i<numnodes;i++){ 372 B[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i]; 373 B[2*numnodes*0+2*i+1] = 0.; 374 B[2*numnodes*1+2*i+0] = 0.; 375 B[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i]; 376 //B[2*numnodes*2+2*i+0] = .5*dbasis[1*numnodes+i]; 377 //B[2*numnodes*2+2*i+1] = .5*dbasis[0*numnodes+i]; 378 B[2*numnodes*2+2*i+0] = dbasis[1*numnodes+i]; 379 B[2*numnodes*2+2*i+1] = dbasis[0*numnodes+i]; 380 } 381 382 /*Clean-up*/ 383 xDelete<IssmDouble>(dbasis); 384 }/*}}}*/ 385 void SeaiceAnalysis::GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 386 /*Compute M matrix. M=[M1 M2 M3] where Mi is of size 3*NDOF2. 387 * For node i, Mi can be expressed in the actual coordinate system 388 * by: 389 * Mi=[ N N ] 390 * where N is the basis function for node i. 391 * 392 * We assume M has been allocated already */ 393 394 /*Fetch number of nodes for this finite element*/ 395 int numnodes = element->GetNumberOfNodes(); 396 397 /*Get nodal functions derivatives*/ 398 IssmDouble* basis=xNew<IssmDouble>(numnodes); 399 element->NodalFunctions(basis,gauss); 400 401 /*Build M: */ 402 for(int i=0;i<numnodes;i++){ 403 M[2*i+0] = basis[i]; 404 M[2*i+1] = basis[i]; 405 } 406 407 /*Clean-up*/ 408 xDelete<IssmDouble>(basis); 409 }/*}}}*/ 410 void SeaiceAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 315 411 _error_("not implemented yet"); 316 412 }/*}}}*/ 317 void SeaiceAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/413 void SeaiceAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 318 414 _error_("Not implemented yet"); 319 415 }/*}}}*/ 320 void SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/416 void SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 321 417 322 418 /*Intermediaries*/ … … 360 456 xDelete<int>(doflist); 361 457 }/*}}}*/ 362 void SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 458 void SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/ 459 460 /*Intermediaties*/ 461 IssmDouble *xyz_list = NULL; 462 IssmDouble *xyz_list_old = NULL; 463 IssmDouble *xyz_list_new = NULL; 464 IssmDouble dt,meshx,meshy,vx,vy,eps_xx,eps_yy,eps_zz,area_old,area_new; 465 IssmDouble time_relaxation_stress,time_relaxation_damage,damage,concentration,thickness; 466 IssmDouble sigma_dot_xx,sigma_dot_yy,sigma_dot_xy; 467 IssmDouble sigma_pred_xx,sigma_pred_yy,sigma_pred_xy; 468 IssmDouble sigma_xx,sigma_yy,sigma_xy; 469 IssmDouble min_c,min_h,max_h; 470 IssmDouble epsilon[3]; /*eps_xx,eps_yy,eps_xy*/ 471 IssmDouble C[3][3]; 472 473 /*Fetch the parameters once for all*/ 474 femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum); 475 femmodel->parameters->FindParam(&min_c,SeaiceMinConcentrationEnum); 476 femmodel->parameters->FindParam(&min_h,SeaiceMinThicknessEnum); 477 femmodel->parameters->FindParam(&max_h,SeaiceMaxThicknessEnum); 478 479 /*Loop over the elements of this partition and update accordingly*/ 480 for(int i=0;i<femmodel->elements->Size();i++){ 481 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 482 483 /*Get some inputs needed for the update*/ 484 element->GetVerticesCoordinates(&xyz_list); 485 time_relaxation_stress = element->GetMaterialParameter(MaterialsTimeRelaxationStressEnum); 486 time_relaxation_damage = element->GetMaterialParameter(MaterialsTimeRelaxationDamageEnum); 487 Input* meshx_input = element->GetInput(MeshXEnum); _assert_(meshx_input); 488 Input* meshy_input = element->GetInput(MeshYEnum); _assert_(meshy_input); 489 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 490 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input); 491 492 /*Preallocate future inputs*/ 493 int numvertices=element->GetNumberOfVertices(); 494 IssmDouble* meshx_new_list = xNew<IssmDouble>(numvertices); 495 IssmDouble* meshy_new_list = xNew<IssmDouble>(numvertices); 496 xyz_list_old = xNew<IssmDouble>(numvertices*3); 497 xyz_list_new = xNew<IssmDouble>(numvertices*3); 498 499 /*1. update vertex positions (using a Gauss object for convenience)*/ 500 Gauss* gauss=element->NewGauss(); 501 for (int iv=0;iv<numvertices;iv++){ 502 gauss->GaussVertex(iv); 503 504 meshx_input->GetInputValue(&meshx,gauss); 505 meshy_input->GetInputValue(&meshy,gauss); 506 vx_input->GetInputValue(&vx,gauss); 507 vy_input->GetInputValue(&vy,gauss); 508 509 meshx_new_list[iv] = meshx + vx*dt; 510 meshy_new_list[iv] = meshy + vy*dt; 511 512 xyz_list_old[iv*3+0] = meshx; 513 xyz_list_old[iv*3+1] = meshy; 514 xyz_list_old[iv*3+2] = 0.; 515 516 xyz_list_new[iv*3+0] = meshx_new_list[iv]; 517 xyz_list_new[iv*3+1] = meshy_new_list[iv]; 518 xyz_list_new[iv*3+2] = 0.; 519 } 520 element->AddInput(MeshXEnum,meshx_new_list,P1Enum); 521 element->AddInput(MeshYEnum,meshy_new_list,P1Enum); 522 523 /*Now we are going to use a point in the center of the element, because we are P0 for the stress*/ 524 gauss->GaussNode(P0Enum,0); 525 526 /*Calculate sigma_dot*/ 527 sigma_dot_xx=sigma_dot_yy=sigma_dot_xy=0.; 528 this->CreateCTensor(&C[0][0],element,gauss); 529 element->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input); 530 for(int j=0;j<3;j++){ 531 sigma_dot_xx += C[0][j]*epsilon[0]; 532 sigma_dot_yy += C[1][j]*epsilon[1]; 533 sigma_dot_xy += C[2][j]*epsilon[2]; 534 } 535 536 /*Get predicted stress state*/ 537 Input* sigma_xx_input = element->GetInput(StressTensorPredictorxxEnum); _assert_(sigma_xx_input); 538 Input* sigma_yy_input = element->GetInput(StressTensorPredictoryyEnum); _assert_(sigma_yy_input); 539 Input* sigma_xy_input = element->GetInput(StressTensorPredictorxyEnum); _assert_(sigma_xy_input); 540 sigma_xx_input->GetInputAverage(&sigma_xx); 541 sigma_yy_input->GetInputAverage(&sigma_yy); 542 sigma_xy_input->GetInputAverage(&sigma_xy); 543 544 /*Calculate new stress and push to element*/ 545 sigma_xx = sigma_xx + dt*(sigma_dot_xx - sigma_xx/time_relaxation_stress); 546 sigma_yy = sigma_yy + dt*(sigma_dot_yy - sigma_yy/time_relaxation_stress); 547 sigma_xy = sigma_xy + dt*(sigma_dot_xy - sigma_xy/time_relaxation_stress); 548 element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum); 549 element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum); 550 element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum); 551 552 /*Update Damage According*/ 553 Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input); 554 damage_input->GetInputAverage(&damage); 555 damage = damage*(1.-dt/time_relaxation_damage); 556 element->AddInput(DamageEnum,&damage,P0Enum); 557 558 /*Prepare new predictor*/ 559 this->CreateCTensor(&C[0][0],element,gauss); /*C is updated now that there is a new damage in inputs*/ 560 for(int j=0;j<3;j++){ 561 sigma_pred_xx += C[0][j]*epsilon[0]; 562 sigma_pred_yy += C[1][j]*epsilon[1]; 563 sigma_pred_xy += C[2][j]*epsilon[2]; 564 } 565 element->AddInput(StressTensorPredictorxxEnum,&sigma_pred_xx,P0Enum); 566 element->AddInput(StressTensorPredictoryyEnum,&sigma_pred_yy,P0Enum); 567 element->AddInput(StressTensorPredictorxyEnum,&sigma_pred_xy,P0Enum); 568 569 /*Calculate Old and new area (FIXME: for now we assume trianlges...)*/ 570 element->JacobianDeterminant(&area_old,xyz_list_old,gauss); 571 element->JacobianDeterminant(&area_new,xyz_list_new,gauss); 572 area_old = area_old/SQRT3; 573 area_new = area_new/SQRT3; 574 575 /*Update ice thickness and concentration using element distortion*/ 576 Input* thickness_input = element->GetInput(SeaiceThicknessEnum); _assert_(thickness_input); 577 Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input); 578 thickness_input->GetInputAverage(&thickness); 579 concentration_input->GetInputAverage(&concentration); 580 IssmDouble ice_area = concentration*area_old; 581 IssmDouble ice_volume = thickness*area_old; 582 if(concentration>min_c){ 583 concentration = ice_area /area_new; 584 thickness = ice_volume/area_new; 585 586 /* lower bounds */ 587 concentration = ((concentration>min_c)?(concentration):(min_c)); 588 thickness = ((thickness >min_h)?(thickness ):(min_h)); 589 590 /* upper bounds (only for the concentration) */ 591 concentration = ((concentration<1. )?(concentration):(1)); 592 thickness = ((thickness <max_h)?(thickness ):(max_h)); 593 } 594 element->AddInput(SeaiceConcentrationEnum,&concentration,P0Enum); 595 element->AddInput(SeaiceThicknessEnum,&thickness,P0Enum); 596 597 /*Clean up*/ 598 xDelete<IssmDouble>(meshx_new_list); 599 xDelete<IssmDouble>(meshy_new_list); 600 xDelete<IssmDouble>(xyz_list); 601 xDelete<IssmDouble>(xyz_list_old); 602 xDelete<IssmDouble>(xyz_list_new); 603 } 604 605 }/*}}}*/ 606 void SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 363 607 364 608 /*Intermediaries*/ … … 409 653 if(VerboseSolution()) _printf0_(" Number of active nodes: "<< sum_counter <<"\n"); 410 654 }/*}}}*/ 411 412 /*Intermediary functions*/ 413 void SeaiceAnalysis::CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss){/*{{{*/ 414 415 /*Intermediaries*/ 416 IssmDouble D[3][3]; 417 IssmDouble damage,concentration; 418 419 /*Get Material parameters*/ 420 IssmDouble poisson = element->GetMaterialParameter(MaterialsPoissonEnum); 421 IssmDouble young_modulus = element->GetMaterialParameter(MaterialsYoungModulusEnum); 422 IssmDouble ridging_exponent = element->GetMaterialParameter(MaterialsRidgingExponentEnum); 423 424 /*Get damage input at this location*/ 425 Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input); 426 Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input); 427 damage_input->GetInputValue(&damage,gauss); 428 concentration_input->GetInputValue(&concentration,gauss); 429 430 /*Build D tensor once for all*/ 431 D[0][0] = 1.; D[0][1] = poisson; D[0][2] = 0.; 432 D[1][0] = poisson; D[1][1] = 1.; D[1][2] = 0.; 433 D[2][0] = 0.; D[2][1] = 0; D[2][2] = (1.-poisson)/2.; 434 for(int i=0;i<3;i++){ 435 for(int j=0;j<3;j++){ 436 D[i][j] = D[i][j]/(1-poisson*poisson); 437 } 438 } 439 440 /*Get f(A), E*/ 441 IssmDouble f = exp(ridging_exponent*(1.-concentration)); 442 IssmDouble E = young_modulus*(1.-damage)*f; 443 444 /*Let's build C = E*D */ 445 for(int i=0;i<3;i++){ 446 for(int j=0;j<3;j++){ 447 C[i*3+j] = E*D[i][j]; 448 } 449 } 450 }/*}}}*/ 451 void SeaiceAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 452 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 453 * For node i, Bi can be expressed in the actual coordinate system 454 * by: 455 * Bi=[ dN/dx 0 ] 456 * [ 0 dN/dy ] 457 * [ 1/2*dN/dy 1/2*dN/dx ] 458 * where N is the basis function for node i. 459 * 460 * We assume B has been allocated already */ 461 462 /*Fetch number of nodes for this finite element*/ 463 int numnodes = element->GetNumberOfNodes(); 464 465 /*Get nodal functions derivatives*/ 466 IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes); 467 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 468 469 /*Build B: */ 470 for(int i=0;i<numnodes;i++){ 471 B[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i]; 472 B[2*numnodes*0+2*i+1] = 0.; 473 B[2*numnodes*1+2*i+0] = 0.; 474 B[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i]; 475 //B[2*numnodes*2+2*i+0] = .5*dbasis[1*numnodes+i]; 476 //B[2*numnodes*2+2*i+1] = .5*dbasis[0*numnodes+i]; 477 B[2*numnodes*2+2*i+0] = dbasis[1*numnodes+i]; 478 B[2*numnodes*2+2*i+1] = dbasis[0*numnodes+i]; 479 } 480 481 /*Clean-up*/ 482 xDelete<IssmDouble>(dbasis); 483 }/*}}}*/ 484 void SeaiceAnalysis::GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 485 /*Compute M matrix. M=[M1 M2 M3] where Mi is of size 3*NDOF2. 486 * For node i, Mi can be expressed in the actual coordinate system 487 * by: 488 * Mi=[ N N ] 489 * where N is the basis function for node i. 490 * 491 * We assume M has been allocated already */ 492 493 /*Fetch number of nodes for this finite element*/ 494 int numnodes = element->GetNumberOfNodes(); 495 496 /*Get nodal functions derivatives*/ 497 IssmDouble* basis=xNew<IssmDouble>(numnodes); 498 element->NodalFunctions(basis,gauss); 499 500 /*Build M: */ 501 for(int i=0;i<numnodes;i++){ 502 M[2*i+0] = basis[i]; 503 M[2*i+1] = basis[i]; 504 } 505 506 /*Clean-up*/ 507 xDelete<IssmDouble>(basis); 508 }/*}}}*/ 509 void SeaiceAnalysis::UpdateDamageAndStress(FemModel* femmodel){/*{{{*/ 655 void SeaiceAnalysis::UpdateDamageAndStress(FemModel* femmodel){/*{{{*/ 510 656 /* The damage variable is updated as a function of the actual elastic deformation 511 657 * In both cases, a Coulombic enveloppe is used, define by the cohesion C, tan(phi) and tract_coef. … … 622 768 } 623 769 }/*}}}*/ 624 void SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/625 626 /*Intermediaties*/627 IssmDouble *xyz_list = NULL;628 IssmDouble *xyz_list_old = NULL;629 IssmDouble *xyz_list_new = NULL;630 IssmDouble dt,meshx,meshy,vx,vy,eps_xx,eps_yy,eps_zz,area_old,area_new;631 IssmDouble time_relaxation_stress,time_relaxation_damage,damage,concentration,thickness;632 IssmDouble sigma_dot_xx,sigma_dot_yy,sigma_dot_xy;633 IssmDouble sigma_pred_xx,sigma_pred_yy,sigma_pred_xy;634 IssmDouble sigma_xx,sigma_yy,sigma_xy;635 IssmDouble min_c,min_h,max_h;636 IssmDouble epsilon[3]; /*eps_xx,eps_yy,eps_xy*/637 IssmDouble C[3][3];638 639 /*Fetch the parameters once for all*/640 femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);641 femmodel->parameters->FindParam(&min_c,SeaiceMinConcentrationEnum);642 femmodel->parameters->FindParam(&min_h,SeaiceMinThicknessEnum);643 femmodel->parameters->FindParam(&max_h,SeaiceMaxThicknessEnum);644 645 /*Loop over the elements of this partition and update accordingly*/646 for(int i=0;i<femmodel->elements->Size();i++){647 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));648 649 /*Get some inputs needed for the update*/650 element->GetVerticesCoordinates(&xyz_list);651 time_relaxation_stress = element->GetMaterialParameter(MaterialsTimeRelaxationStressEnum);652 time_relaxation_damage = element->GetMaterialParameter(MaterialsTimeRelaxationDamageEnum);653 Input* meshx_input = element->GetInput(MeshXEnum); _assert_(meshx_input);654 Input* meshy_input = element->GetInput(MeshYEnum); _assert_(meshy_input);655 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);656 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);657 658 /*Preallocate future inputs*/659 int numvertices=element->GetNumberOfVertices();660 IssmDouble* meshx_new_list = xNew<IssmDouble>(numvertices);661 IssmDouble* meshy_new_list = xNew<IssmDouble>(numvertices);662 xyz_list_old = xNew<IssmDouble>(numvertices*3);663 xyz_list_new = xNew<IssmDouble>(numvertices*3);664 665 /*1. update vertex positions (using a Gauss object for convenience)*/666 Gauss* gauss=element->NewGauss();667 for (int iv=0;iv<numvertices;iv++){668 gauss->GaussVertex(iv);669 670 meshx_input->GetInputValue(&meshx,gauss);671 meshy_input->GetInputValue(&meshy,gauss);672 vx_input->GetInputValue(&vx,gauss);673 vy_input->GetInputValue(&vy,gauss);674 675 meshx_new_list[iv] = meshx + vx*dt;676 meshy_new_list[iv] = meshy + vy*dt;677 678 xyz_list_old[iv*3+0] = meshx;679 xyz_list_old[iv*3+1] = meshy;680 xyz_list_old[iv*3+2] = 0.;681 682 xyz_list_new[iv*3+0] = meshx_new_list[iv];683 xyz_list_new[iv*3+1] = meshy_new_list[iv];684 xyz_list_new[iv*3+2] = 0.;685 }686 element->AddInput(MeshXEnum,meshx_new_list,P1Enum);687 element->AddInput(MeshYEnum,meshy_new_list,P1Enum);688 689 /*Now we are going to use a point in the center of the element, because we are P0 for the stress*/690 gauss->GaussNode(P0Enum,0);691 692 /*Calculate sigma_dot*/693 sigma_dot_xx=sigma_dot_yy=sigma_dot_xy=0.;694 this->CreateCTensor(&C[0][0],element,gauss);695 element->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);696 for(int j=0;j<3;j++){697 sigma_dot_xx += C[0][j]*epsilon[0];698 sigma_dot_yy += C[1][j]*epsilon[1];699 sigma_dot_xy += C[2][j]*epsilon[2];700 }701 702 /*Get predicted stress state*/703 Input* sigma_xx_input = element->GetInput(StressTensorPredictorxxEnum); _assert_(sigma_xx_input);704 Input* sigma_yy_input = element->GetInput(StressTensorPredictoryyEnum); _assert_(sigma_yy_input);705 Input* sigma_xy_input = element->GetInput(StressTensorPredictorxyEnum); _assert_(sigma_xy_input);706 sigma_xx_input->GetInputAverage(&sigma_xx);707 sigma_yy_input->GetInputAverage(&sigma_yy);708 sigma_xy_input->GetInputAverage(&sigma_xy);709 710 /*Calculate new stress and push to element*/711 sigma_xx = sigma_xx + dt*(sigma_dot_xx - sigma_xx/time_relaxation_stress);712 sigma_yy = sigma_yy + dt*(sigma_dot_yy - sigma_yy/time_relaxation_stress);713 sigma_xy = sigma_xy + dt*(sigma_dot_xy - sigma_xy/time_relaxation_stress);714 element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum);715 element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum);716 element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum);717 718 /*Update Damage According*/719 Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input);720 damage_input->GetInputAverage(&damage);721 damage = damage*(1.-dt/time_relaxation_damage);722 element->AddInput(DamageEnum,&damage,P0Enum);723 724 /*Prepare new predictor*/725 this->CreateCTensor(&C[0][0],element,gauss); /*C is updated now that there is a new damage in inputs*/726 for(int j=0;j<3;j++){727 sigma_pred_xx += C[0][j]*epsilon[0];728 sigma_pred_yy += C[1][j]*epsilon[1];729 sigma_pred_xy += C[2][j]*epsilon[2];730 }731 element->AddInput(StressTensorPredictorxxEnum,&sigma_pred_xx,P0Enum);732 element->AddInput(StressTensorPredictoryyEnum,&sigma_pred_yy,P0Enum);733 element->AddInput(StressTensorPredictorxyEnum,&sigma_pred_xy,P0Enum);734 735 /*Calculate Old and new area (FIXME: for now we assume trianlges...)*/736 element->JacobianDeterminant(&area_old,xyz_list_old,gauss);737 element->JacobianDeterminant(&area_new,xyz_list_new,gauss);738 area_old = area_old/SQRT3;739 area_new = area_new/SQRT3;740 741 /*Update ice thickness and concentration using element distortion*/742 Input* thickness_input = element->GetInput(SeaiceThicknessEnum); _assert_(thickness_input);743 Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);744 thickness_input->GetInputAverage(&thickness);745 concentration_input->GetInputAverage(&concentration);746 IssmDouble ice_area = concentration*area_old;747 IssmDouble ice_volume = thickness*area_old;748 if(concentration>min_c){749 concentration = ice_area /area_new;750 thickness = ice_volume/area_new;751 752 /* lower bounds */753 concentration = ((concentration>min_c)?(concentration):(min_c));754 thickness = ((thickness >min_h)?(thickness ):(min_h));755 756 /* upper bounds (only for the concentration) */757 concentration = ((concentration<1. )?(concentration):(1));758 thickness = ((thickness <max_h)?(thickness ):(max_h));759 }760 element->AddInput(SeaiceConcentrationEnum,&concentration,P0Enum);761 element->AddInput(SeaiceThicknessEnum,&thickness,P0Enum);762 763 /*Clean up*/764 xDelete<IssmDouble>(meshx_new_list);765 xDelete<IssmDouble>(meshy_new_list);766 xDelete<IssmDouble>(xyz_list);767 xDelete<IssmDouble>(xyz_list_old);768 xDelete<IssmDouble>(xyz_list_new);769 }770 771 }/*}}}*/ -
issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.h
r18505 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ 23 23 void Core(FemModel* femmodel); 24 void CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss); 24 25 ElementVector* CreateDVector(Element* element); 25 26 ElementMatrix* CreateJacobianMatrix(Element* element); 26 27 ElementMatrix* CreateKMatrix(Element* element); 27 28 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 33 /*Sea ice specifics*/ 34 void UpdateDamageAndStress(FemModel* femmodel); 35 void CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss); 36 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 37 void GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss); 38 void PostProcess(FemModel* femmodel); 29 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 30 void GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss); 31 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 32 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 33 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 34 void PostProcess(FemModel* femmodel); 35 void UpdateConstraints(FemModel* femmodel); 36 void UpdateDamageAndStress(FemModel* femmodel); 39 37 }; 40 38 #endif -
issm/trunk-jpl/src/c/analyses/SmoothAnalysis.cpp
r18604 r18930 6 6 7 7 /*Model processing*/ 8 void SmoothAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 }/*}}}*/ 10 void SmoothAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 11 }/*}}}*/ 12 void SmoothAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 13 14 ::CreateNodes(nodes,iomodel,SmoothAnalysisEnum,P1Enum); 15 16 }/*}}}*/ 8 17 int SmoothAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 18 return 1; 10 }/*}}}*/11 void SmoothAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 19 }/*}}}*/ 13 20 void SmoothAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 23 30 } 24 31 }/*}}}*/ 25 void SmoothAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 26 27 ::CreateNodes(nodes,iomodel,SmoothAnalysisEnum,P1Enum); 28 29 }/*}}}*/ 30 void SmoothAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 31 }/*}}}*/ 32 void SmoothAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 32 void SmoothAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 33 33 }/*}}}*/ 34 34 … … 205 205 return pe; 206 206 }/*}}}*/ 207 void SmoothAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/207 void SmoothAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 208 208 _error_("not implemented yet"); 209 209 }/*}}}*/ 210 void SmoothAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/210 void SmoothAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 211 211 _error_("Not implemented yet"); 212 212 }/*}}}*/ 213 void SmoothAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/213 void SmoothAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 214 214 int inputenum,domaintype,elementtype; 215 215 … … 223 223 } 224 224 }/*}}}*/ 225 void SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/225 void SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 226 226 /*Default, do nothing*/ 227 227 return; -
issm/trunk-jpl/src/c/analyses/SmoothAnalysis.h
r18593 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);30 void InputUpdateFromSolution(IssmDouble* solution,Element* element);31 void UpdateConstraints(FemModel* femmodel);28 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 29 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 30 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 31 void UpdateConstraints(FemModel* femmodel); 32 32 }; 33 33 #endif -
issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp
r18068 r18930 7 7 8 8 /*Model processing*/ 9 int StressbalanceSIAAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/10 return 2;11 }/*}}}*/12 void StressbalanceSIAAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/13 14 /*No specific parameters*/15 16 }/*}}}*/17 void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/18 19 /*Fetch data needed: */20 bool isSIA;21 bool islevelset;22 iomodel->Constant(&isSIA,FlowequationIsSIAEnum);23 iomodel->Constant(&islevelset,TransientIslevelsetEnum);24 25 /*Now, is the flag SIA on? otherwise, do nothing: */26 if (!isSIA)return;27 28 iomodel->FetchData(1,FlowequationElementEquationEnum);29 30 /*Update elements: */31 int counter=0;32 for(int i=0;i<iomodel->numberofelements;i++){33 if(iomodel->my_elements[i]){34 Element* element=(Element*)elements->GetObjectByOffset(counter);35 element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);36 counter++;37 }38 }39 40 iomodel->FetchDataToInput(elements,ThicknessEnum);41 iomodel->FetchDataToInput(elements,FrictionCoefficientEnum);42 iomodel->FetchDataToInput(elements,MaskGroundediceLevelsetEnum);43 if(islevelset){44 iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);45 if(iomodel->domaintype!=Domain2DhorizontalEnum)46 iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum); // required for updating active nodes47 }48 49 /*Free data: */50 iomodel->DeleteData(1,FlowequationElementEquationEnum);51 }/*}}}*/52 void StressbalanceSIAAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/53 54 /*Intermediaries*/55 bool isSIA;56 Node* node = NULL;57 58 /*Fetch parameters: */59 iomodel->Constant(&isSIA,FlowequationIsSIAEnum);60 61 /*Now, is the flag isSIA on? otherwise, do nothing: */62 if(!isSIA) return;63 64 /*First create nodes*/65 int lid=0;66 iomodel->FetchData(4,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,FlowequationVertexEquationEnum,StressbalanceReferentialEnum);67 if(iomodel->domaintype!=Domain2DhorizontalEnum){68 iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);69 }70 71 for(int i=0;i<iomodel->numberofvertices;i++){72 if(iomodel->my_vertices[i]){73 74 /*Create new node if is in this processor's partition*/75 node = new Node(iomodel->nodecounter+i+1,i,lid++,i,iomodel,StressbalanceSIAAnalysisEnum,reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i]));76 77 /*Deactivate node if not SIA*/78 if(reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){79 node->Deactivate();80 }81 82 /*Add to Nodes dataset*/83 nodes->AddObject(node);84 }85 }86 87 iomodel->DeleteData(6,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,88 FlowequationVertexEquationEnum,StressbalanceReferentialEnum);89 90 }/*}}}*/91 9 void StressbalanceSIAAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 92 10 … … 142 60 143 61 /*No loads*/ 62 63 }/*}}}*/ 64 void StressbalanceSIAAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 65 66 /*Intermediaries*/ 67 bool isSIA; 68 Node* node = NULL; 69 70 /*Fetch parameters: */ 71 iomodel->Constant(&isSIA,FlowequationIsSIAEnum); 72 73 /*Now, is the flag isSIA on? otherwise, do nothing: */ 74 if(!isSIA) return; 75 76 /*First create nodes*/ 77 int lid=0; 78 iomodel->FetchData(4,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,FlowequationVertexEquationEnum,StressbalanceReferentialEnum); 79 if(iomodel->domaintype!=Domain2DhorizontalEnum){ 80 iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 81 } 82 83 for(int i=0;i<iomodel->numberofvertices;i++){ 84 if(iomodel->my_vertices[i]){ 85 86 /*Create new node if is in this processor's partition*/ 87 node = new Node(iomodel->nodecounter+i+1,i,lid++,i,iomodel,StressbalanceSIAAnalysisEnum,reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i])); 88 89 /*Deactivate node if not SIA*/ 90 if(reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){ 91 node->Deactivate(); 92 } 93 94 /*Add to Nodes dataset*/ 95 nodes->AddObject(node); 96 } 97 } 98 99 iomodel->DeleteData(6,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationBorderSSAEnum,FlowequationBorderFSEnum, 100 FlowequationVertexEquationEnum,StressbalanceReferentialEnum); 101 102 }/*}}}*/ 103 int StressbalanceSIAAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 104 return 2; 105 }/*}}}*/ 106 void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ 107 108 /*Fetch data needed: */ 109 bool isSIA; 110 bool islevelset; 111 iomodel->Constant(&isSIA,FlowequationIsSIAEnum); 112 iomodel->Constant(&islevelset,TransientIslevelsetEnum); 113 114 /*Now, is the flag SIA on? otherwise, do nothing: */ 115 if (!isSIA)return; 116 117 iomodel->FetchData(1,FlowequationElementEquationEnum); 118 119 /*Update elements: */ 120 int counter=0; 121 for(int i=0;i<iomodel->numberofelements;i++){ 122 if(iomodel->my_elements[i]){ 123 Element* element=(Element*)elements->GetObjectByOffset(counter); 124 element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum); 125 counter++; 126 } 127 } 128 129 iomodel->FetchDataToInput(elements,ThicknessEnum); 130 iomodel->FetchDataToInput(elements,FrictionCoefficientEnum); 131 iomodel->FetchDataToInput(elements,MaskGroundediceLevelsetEnum); 132 if(islevelset){ 133 iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum); 134 if(iomodel->domaintype!=Domain2DhorizontalEnum) 135 iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum); // required for updating active nodes 136 } 137 138 /*Free data: */ 139 iomodel->DeleteData(1,FlowequationElementEquationEnum); 140 }/*}}}*/ 141 void StressbalanceSIAAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 142 143 /*No specific parameters*/ 144 144 145 145 }/*}}}*/ … … 461 461 462 462 }/*}}}*/ 463 void StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/463 void StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 464 464 465 465 IssmDouble vx,vy; … … 494 494 xDelete<IssmDouble>(values); 495 495 }/*}}}*/ 496 void StressbalanceSIAAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/496 void StressbalanceSIAAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 497 497 _error_("Not implemented yet"); 498 498 }/*}}}*/ 499 void StressbalanceSIAAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/499 void StressbalanceSIAAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 500 500 501 501 int i,domaintype; … … 581 581 xDelete<int>(doflist); 582 582 }/*}}}*/ 583 void StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/583 void StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 584 584 585 585 bool islevelset; -
issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 30 30 ElementVector* CreatePVector2D(Element* element); 31 31 ElementVector* CreatePVector3D(Element* element); 32 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);33 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);34 void InputUpdateFromSolution(IssmDouble* solution,Element* element);35 void UpdateConstraints(FemModel* femmodel);32 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 33 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 34 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 35 void UpdateConstraints(FemModel* femmodel); 36 36 }; 37 37 #endif -
issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp
r18074 r18930 7 7 8 8 /*Model processing*/ 9 int StressbalanceVerticalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/10 return 1;11 }/*}}}*/12 void StressbalanceVerticalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/13 14 /*No specific parameters*/15 16 }/*}}}*/17 void StressbalanceVerticalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/18 19 /*return if not 3d mesh*/20 if(iomodel->domaintype!=Domain3DEnum) return;21 22 /*Update elements: */23 int counter=0;24 for(int i=0;i<iomodel->numberofelements;i++){25 if(iomodel->my_elements[i]){26 Element* element=(Element*)elements->GetObjectByOffset(counter);27 element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);28 counter++;29 }30 }31 32 iomodel->FetchDataToInput(elements,ThicknessEnum);33 iomodel->FetchDataToInput(elements,SurfaceEnum);34 iomodel->FetchDataToInput(elements,BaseEnum);35 iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);36 if(iomodel->domaintype!=Domain2DhorizontalEnum){37 iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum);38 iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);39 }40 iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum);41 iomodel->FetchDataToInput(elements,BasalforcingsFloatingiceMeltingRateEnum);42 iomodel->FetchDataToInput(elements,VxEnum,0.);43 iomodel->FetchDataToInput(elements,VyEnum,0.);44 }/*}}}*/45 void StressbalanceVerticalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/46 47 /*return if not 3d mesh*/48 if(iomodel->domaintype!=Domain3DEnum) return;49 50 iomodel->FetchData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);51 ::CreateNodes(nodes,iomodel,StressbalanceVerticalAnalysisEnum,P1Enum);52 iomodel->DeleteData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);53 }/*}}}*/54 9 void StressbalanceVerticalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 55 10 … … 98 53 99 54 }/*}}}*/ 55 void StressbalanceVerticalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 56 57 /*return if not 3d mesh*/ 58 if(iomodel->domaintype!=Domain3DEnum) return; 59 60 iomodel->FetchData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum); 61 ::CreateNodes(nodes,iomodel,StressbalanceVerticalAnalysisEnum,P1Enum); 62 iomodel->DeleteData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum); 63 }/*}}}*/ 64 int StressbalanceVerticalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 65 return 1; 66 }/*}}}*/ 67 void StressbalanceVerticalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ 68 69 /*return if not 3d mesh*/ 70 if(iomodel->domaintype!=Domain3DEnum) return; 71 72 /*Update elements: */ 73 int counter=0; 74 for(int i=0;i<iomodel->numberofelements;i++){ 75 if(iomodel->my_elements[i]){ 76 Element* element=(Element*)elements->GetObjectByOffset(counter); 77 element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum); 78 counter++; 79 } 80 } 81 82 iomodel->FetchDataToInput(elements,ThicknessEnum); 83 iomodel->FetchDataToInput(elements,SurfaceEnum); 84 iomodel->FetchDataToInput(elements,BaseEnum); 85 iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum); 86 if(iomodel->domaintype!=Domain2DhorizontalEnum){ 87 iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum); 88 iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum); 89 } 90 iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum); 91 iomodel->FetchDataToInput(elements,BasalforcingsFloatingiceMeltingRateEnum); 92 iomodel->FetchDataToInput(elements,VxEnum,0.); 93 iomodel->FetchDataToInput(elements,VyEnum,0.); 94 }/*}}}*/ 95 void StressbalanceVerticalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 96 97 /*No specific parameters*/ 98 99 }/*}}}*/ 100 100 101 101 /*Finite Element Analysis*/ … … 125 125 return Ke; 126 126 127 }/*}}}*/ 128 ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixSurface(Element* element){/*{{{*/ 129 130 131 if(!element->IsOnSurface()) return NULL; 132 133 /*Intermediaries*/ 134 IssmDouble D,Jdet,normal[3]; 135 IssmDouble *xyz_list = NULL; 136 137 /*Fetch number of nodes and dof for this finite element*/ 138 int numnodes = element->GetNumberOfNodes(); 139 140 /*Initialize Element matrix and vectors*/ 141 ElementMatrix* Ke = element->NewElementMatrix(NoneApproximationEnum); 142 IssmDouble* basis = xNew<IssmDouble>(numnodes); 143 144 /*Retrieve all inputs and parameters*/ 145 element->GetVerticesCoordinatesTop(&xyz_list); 146 147 /* Start looping on the number of gaussian points: */ 148 Gauss* gauss = element->NewGaussTop(2); 149 element->NormalTop(&normal[0],xyz_list); 150 for(int ig=gauss->begin();ig<gauss->end();ig++){ 151 gauss->GaussPoint(ig); 152 153 element->JacobianDeterminantTop(&Jdet,xyz_list,gauss); 154 element->NodalFunctions(basis,gauss); 155 D = -gauss->weight*Jdet*normal[2]; 156 157 TripleMultiply( basis,1,numnodes,1, 158 &D,1,1,0, 159 basis,1,numnodes,0, 160 &Ke->values[0],1); 161 } 162 163 /*Clean up and return*/ 164 delete gauss; 165 xDelete<IssmDouble>(xyz_list); 166 xDelete<IssmDouble>(basis); 167 return Ke; 127 168 }/*}}}*/ 128 169 ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixVolume(Element* element){/*{{{*/ … … 167 208 168 209 }/*}}}*/ 169 ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixSurface(Element* element){/*{{{*/170 171 172 if(!element->IsOnSurface()) return NULL;173 174 /*Intermediaries*/175 IssmDouble D,Jdet,normal[3];176 IssmDouble *xyz_list = NULL;177 178 /*Fetch number of nodes and dof for this finite element*/179 int numnodes = element->GetNumberOfNodes();180 181 /*Initialize Element matrix and vectors*/182 ElementMatrix* Ke = element->NewElementMatrix(NoneApproximationEnum);183 IssmDouble* basis = xNew<IssmDouble>(numnodes);184 185 /*Retrieve all inputs and parameters*/186 element->GetVerticesCoordinatesTop(&xyz_list);187 188 /* Start looping on the number of gaussian points: */189 Gauss* gauss = element->NewGaussTop(2);190 element->NormalTop(&normal[0],xyz_list);191 for(int ig=gauss->begin();ig<gauss->end();ig++){192 gauss->GaussPoint(ig);193 194 element->JacobianDeterminantTop(&Jdet,xyz_list,gauss);195 element->NodalFunctions(basis,gauss);196 D = -gauss->weight*Jdet*normal[2];197 198 TripleMultiply( basis,1,numnodes,1,199 &D,1,1,0,200 basis,1,numnodes,0,201 &Ke->values[0],1);202 }203 204 /*Clean up and return*/205 delete gauss;206 xDelete<IssmDouble>(xyz_list);207 xDelete<IssmDouble>(basis);208 return Ke;209 }/*}}}*/210 210 ElementVector* StressbalanceVerticalAnalysis::CreatePVector(Element* element){/*{{{*/ 211 211 … … 218 218 delete pe1; 219 219 delete pe2; 220 return pe;221 }/*}}}*/222 ElementVector* StressbalanceVerticalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/223 224 /*Intermediaries*/225 int approximation;226 IssmDouble Jdet,dudx,dvdy,dwdz;227 IssmDouble du[3],dv[3],dw[3];228 IssmDouble* xyz_list = NULL;229 230 /*Fetch number of nodes for this finite element*/231 int numnodes = element->GetNumberOfNodes();232 233 /*Initialize Element vector and basis functions*/234 ElementVector* pe = element->NewElementVector();235 IssmDouble* basis = xNew<IssmDouble>(numnodes);236 237 /*Retrieve all inputs and parameters*/238 element->GetVerticesCoordinates(&xyz_list);239 element->GetInputValue(&approximation,ApproximationEnum);240 Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input);241 Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input);242 Input* vzFS_input=NULL;243 if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){244 vzFS_input=element->GetInput(VzFSEnum); _assert_(vzFS_input);245 }246 247 /* Start looping on the number of gaussian points: */248 Gauss* gauss=element->NewGauss(2);249 for(int ig=gauss->begin();ig<gauss->end();ig++){250 gauss->GaussPoint(ig);251 252 element->JacobianDeterminant(&Jdet,xyz_list,gauss);253 element->NodalFunctions(basis,gauss);254 255 vx_input->GetInputDerivativeValue(&du[0],xyz_list,gauss);256 vy_input->GetInputDerivativeValue(&dv[0],xyz_list,gauss);257 if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){258 vzFS_input->GetInputDerivativeValue(&dw[0],xyz_list,gauss);259 dwdz=dw[2];260 }261 else dwdz=0;262 dudx=du[0];263 dvdy=dv[1];264 265 for(int i=0;i<numnodes;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];266 }267 268 /*Clean up and return*/269 delete gauss;270 xDelete<IssmDouble>(basis);271 xDelete<IssmDouble>(xyz_list);272 220 return pe; 273 221 }/*}}}*/ … … 338 286 return pe; 339 287 }/*}}}*/ 340 void StressbalanceVerticalAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 288 ElementVector* StressbalanceVerticalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/ 289 290 /*Intermediaries*/ 291 int approximation; 292 IssmDouble Jdet,dudx,dvdy,dwdz; 293 IssmDouble du[3],dv[3],dw[3]; 294 IssmDouble* xyz_list = NULL; 295 296 /*Fetch number of nodes for this finite element*/ 297 int numnodes = element->GetNumberOfNodes(); 298 299 /*Initialize Element vector and basis functions*/ 300 ElementVector* pe = element->NewElementVector(); 301 IssmDouble* basis = xNew<IssmDouble>(numnodes); 302 303 /*Retrieve all inputs and parameters*/ 304 element->GetVerticesCoordinates(&xyz_list); 305 element->GetInputValue(&approximation,ApproximationEnum); 306 Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input); 307 Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input); 308 Input* vzFS_input=NULL; 309 if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){ 310 vzFS_input=element->GetInput(VzFSEnum); _assert_(vzFS_input); 311 } 312 313 /* Start looping on the number of gaussian points: */ 314 Gauss* gauss=element->NewGauss(2); 315 for(int ig=gauss->begin();ig<gauss->end();ig++){ 316 gauss->GaussPoint(ig); 317 318 element->JacobianDeterminant(&Jdet,xyz_list,gauss); 319 element->NodalFunctions(basis,gauss); 320 321 vx_input->GetInputDerivativeValue(&du[0],xyz_list,gauss); 322 vy_input->GetInputDerivativeValue(&dv[0],xyz_list,gauss); 323 if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){ 324 vzFS_input->GetInputDerivativeValue(&dw[0],xyz_list,gauss); 325 dwdz=dw[2]; 326 } 327 else dwdz=0; 328 dudx=du[0]; 329 dvdy=dv[1]; 330 331 for(int i=0;i<numnodes;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i]; 332 } 333 334 /*Clean up and return*/ 335 delete gauss; 336 xDelete<IssmDouble>(basis); 337 xDelete<IssmDouble>(xyz_list); 338 return pe; 339 }/*}}}*/ 340 void StressbalanceVerticalAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 341 341 /* Compute B matrix. B=[dh1/dz dh2/dz dh3/dz dh4/dz dh5/dz dh6/dz]; 342 342 where hi is the interpolation function for node i.*/ … … 357 357 xDelete<IssmDouble>(dbasis); 358 358 }/*}}}*/ 359 void StressbalanceVerticalAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/359 void StressbalanceVerticalAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 360 360 361 361 element->NodalFunctions(Bprime,gauss); 362 362 363 363 }/*}}}*/ 364 void StressbalanceVerticalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/364 void StressbalanceVerticalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 365 365 element->GetSolutionFromInputsOneDof(solution,VzEnum); 366 366 }/*}}}*/ 367 void StressbalanceVerticalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/367 void StressbalanceVerticalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 368 368 _error_("Not implemented yet"); 369 369 }/*}}}*/ 370 void StressbalanceVerticalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/370 void StressbalanceVerticalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 371 371 372 372 int numnodes = element->GetNumberOfNodes(); … … 481 481 xDelete<int>(doflist); 482 482 }/*}}}*/ 483 void StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/483 void StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 484 484 /*Default, do nothing*/ 485 485 return; -
issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 25 25 ElementMatrix* CreateJacobianMatrix(Element* element); 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 ElementMatrix* CreateKMatrixSurface(Element* element); 27 28 ElementMatrix* CreateKMatrixVolume(Element* element); 28 ElementMatrix* CreateKMatrixSurface(Element* element);29 29 ElementVector* CreatePVector(Element* element); 30 ElementVector* CreatePVectorBase(Element* element); 30 31 ElementVector* CreatePVectorVolume(Element* element); 31 ElementVector* CreatePVectorBase(Element* element); 32 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 33 void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 34 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 35 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 36 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 37 void UpdateConstraints(FemModel* femmodel); 32 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 33 void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 34 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 35 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 36 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 37 void UpdateConstraints(FemModel* femmodel); 38 38 }; 39 39 #endif -
issm/trunk-jpl/src/c/analyses/ThermalAnalysis.cpp
r18804 r18930 6 6 7 7 /*Model processing*/ 8 void ThermalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 10 /*Only 3d mesh supported*/ 11 int finiteelement = P1Enum; 12 if(iomodel->domaintype==Domain3DEnum){ 13 IoModelToConstraintsx(constraints,iomodel,ThermalSpctemperatureEnum,ThermalAnalysisEnum,finiteelement); 14 } 15 16 }/*}}}*/ 17 void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 18 19 if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet"); 20 21 /*create penalties for nodes: no node can have a temperature over the melting point*/ 22 iomodel->FetchData(1,ThermalSpctemperatureEnum); 23 CreateSingleNodeToElementConnectivity(iomodel); 24 25 for(int i=0;i<iomodel->numberofvertices;i++){ 26 27 /*keep only this partition's nodes:*/ 28 if(iomodel->my_vertices[i]){ 29 if (xIsNan<IssmDouble>(iomodel->Data(ThermalSpctemperatureEnum)[i])){ //No penalty applied on spc nodes! 30 loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,ThermalAnalysisEnum)); 31 } 32 } 33 } 34 iomodel->DeleteData(1,ThermalSpctemperatureEnum); 35 36 }/*}}}*/ 37 void ThermalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 38 39 int finiteelement = P1Enum; 40 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 41 ::CreateNodes(nodes,iomodel,ThermalAnalysisEnum,finiteelement); 42 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 43 }/*}}}*/ 8 44 int ThermalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 45 return 1; 10 }/*}}}*/11 void ThermalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 13 int numoutputs;14 char** requestedoutputs = NULL;15 16 parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));17 parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));18 parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyFactorEnum));19 parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyThresholdEnum));20 parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyLockEnum));21 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));22 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));23 parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));24 25 iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);26 parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));27 if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));28 iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);29 30 /*Deal with friction parameters*/31 int frictionlaw;32 iomodel->Constant(&frictionlaw,FrictionLawEnum);33 if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));34 46 }/*}}}*/ 35 47 void ThermalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 122 134 } 123 135 }/*}}}*/ 124 void ThermalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 125 126 int finiteelement = P1Enum; 127 if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 128 ::CreateNodes(nodes,iomodel,ThermalAnalysisEnum,finiteelement); 129 iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum); 130 }/*}}}*/ 131 void ThermalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 132 133 /*Only 3d mesh supported*/ 134 int finiteelement = P1Enum; 135 if(iomodel->domaintype==Domain3DEnum){ 136 IoModelToConstraintsx(constraints,iomodel,ThermalSpctemperatureEnum,ThermalAnalysisEnum,finiteelement); 137 } 138 139 }/*}}}*/ 140 void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 141 142 if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet"); 143 144 /*create penalties for nodes: no node can have a temperature over the melting point*/ 145 iomodel->FetchData(1,ThermalSpctemperatureEnum); 146 CreateSingleNodeToElementConnectivity(iomodel); 147 148 for(int i=0;i<iomodel->numberofvertices;i++){ 149 150 /*keep only this partition's nodes:*/ 151 if(iomodel->my_vertices[i]){ 152 if (xIsNan<IssmDouble>(iomodel->Data(ThermalSpctemperatureEnum)[i])){ //No penalty applied on spc nodes! 153 loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,ThermalAnalysisEnum)); 154 } 155 } 156 } 157 iomodel->DeleteData(1,ThermalSpctemperatureEnum); 158 136 void ThermalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 137 138 int numoutputs; 139 char** requestedoutputs = NULL; 140 141 parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum)); 142 parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum)); 143 parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyFactorEnum)); 144 parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyThresholdEnum)); 145 parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyLockEnum)); 146 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum)); 147 parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum)); 148 parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum)); 149 150 iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum); 151 parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs)); 152 if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs)); 153 iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum); 154 155 /*Deal with friction parameters*/ 156 int frictionlaw; 157 iomodel->Constant(&frictionlaw,FrictionLawEnum); 158 if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum)); 159 159 }/*}}}*/ 160 160 … … 183 183 delete Ke1; 184 184 delete Ke2; 185 return Ke; 186 }/*}}}*/ 187 ElementMatrix* ThermalAnalysis::CreateKMatrixShelf(Element* element){/*{{{*/ 188 189 /* Check if ice in element */ 190 if(!element->IsIceInElement()) return NULL; 191 192 /*Initialize Element matrix and return if necessary*/ 193 if(!element->IsOnBase() || !element->IsFloating()) return NULL; 194 195 IssmDouble dt,Jdet,D; 196 IssmDouble *xyz_list_base = NULL; 197 198 /*Get basal element*/ 199 if(!element->IsOnBase() || !element->IsFloating()) return NULL; 200 201 /*Fetch number of nodes for this finite element*/ 202 int numnodes = element->GetNumberOfNodes(); 203 204 /*Initialize vectors*/ 205 ElementMatrix* Ke = element->NewElementMatrix(); 206 IssmDouble* basis = xNew<IssmDouble>(numnodes); 207 208 /*Retrieve all inputs and parameters*/ 209 element->GetVerticesCoordinatesBase(&xyz_list_base); 210 element->FindParam(&dt,TimesteppingTimeStepEnum); 211 IssmDouble gravity = element->GetMaterialParameter(ConstantsGEnum); 212 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum); 213 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum); 214 IssmDouble heatcapacity = element->GetMaterialParameter(MaterialsHeatcapacityEnum); 215 IssmDouble mixed_layer_capacity= element->GetMaterialParameter(MaterialsMixedLayerCapacityEnum); 216 IssmDouble thermal_exchange_vel= element->GetMaterialParameter(MaterialsThermalExchangeVelocityEnum); 217 218 /* Start looping on the number of gaussian points: */ 219 Gauss* gauss=element->NewGaussBase(2); 220 for(int ig=gauss->begin();ig<gauss->end();ig++){ 221 gauss->GaussPoint(ig); 222 223 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss); 224 element->NodalFunctions(basis,gauss); 225 226 D=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel/(heatcapacity*rho_ice); 227 if(reCast<bool,IssmDouble>(dt)) D=dt*D; 228 TripleMultiply(basis,numnodes,1,0, 229 &D,1,1,0, 230 basis,1,numnodes,0, 231 &Ke->values[0],1); 232 233 } 234 235 /*Clean up and return*/ 236 delete gauss; 237 xDelete<IssmDouble>(basis); 238 xDelete<IssmDouble>(xyz_list_base); 185 239 return Ke; 186 240 }/*}}}*/ … … 318 372 return Ke; 319 373 }/*}}}*/ 320 Element Matrix* ThermalAnalysis::CreateKMatrixShelf(Element* element){/*{{{*/321 374 ElementVector* ThermalAnalysis::CreatePVector(Element* element){/*{{{*/ 375 322 376 /* Check if ice in element */ 323 377 if(!element->IsIceInElement()) return NULL; 324 378 325 /*Initialize Element matrix and return if necessary*/ 326 if(!element->IsOnBase() || !element->IsFloating()) return NULL; 327 328 IssmDouble dt,Jdet,D; 379 /*compute all load vectors for this element*/ 380 ElementVector* pe1=CreatePVectorVolume(element); 381 ElementVector* pe2=CreatePVectorSheet(element); 382 ElementVector* pe3=CreatePVectorShelf(element); 383 ElementVector* pe =new ElementVector(pe1,pe2,pe3); 384 385 /*clean-up and return*/ 386 delete pe1; 387 delete pe2; 388 delete pe3; 389 return pe; 390 }/*}}}*/ 391 ElementVector* ThermalAnalysis::CreatePVectorSheet(Element* element){/*{{{*/ 392 393 /* Check if ice in element */ 394 if(!element->IsIceInElement()) return NULL; 395 396 /* Geothermal flux on ice sheet base and basal friction */ 397 if(!element->IsOnBase() || element->IsFloating()) return NULL; 398 399 IssmDouble dt,Jdet,geothermalflux,vx,vy,vz; 400 IssmDouble alpha2,scalar,basalfriction,heatflux; 329 401 IssmDouble *xyz_list_base = NULL; 330 402 331 /*Get basal element*/332 if(!element->IsOnBase() || !element->IsFloating()) return NULL;333 334 403 /*Fetch number of nodes for this finite element*/ 335 404 int numnodes = element->GetNumberOfNodes(); 336 405 337 406 /*Initialize vectors*/ 338 Element Matrix* Ke = element->NewElementMatrix();407 ElementVector* pe = element->NewElementVector(); 339 408 IssmDouble* basis = xNew<IssmDouble>(numnodes); 340 409 … … 342 411 element->GetVerticesCoordinatesBase(&xyz_list_base); 343 412 element->FindParam(&dt,TimesteppingTimeStepEnum); 413 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 414 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input); 415 Input* vz_input = element->GetInput(VzEnum); _assert_(vz_input); 416 Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input); 417 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum); 418 IssmDouble heatcapacity = element->GetMaterialParameter(MaterialsHeatcapacityEnum); 419 420 /*Build friction element, needed later: */ 421 Friction* friction=new Friction(element,3); 422 423 /* Start looping on the number of gaussian points: */ 424 Gauss* gauss = element->NewGaussBase(2); 425 for(int ig=gauss->begin();ig<gauss->end();ig++){ 426 gauss->GaussPoint(ig); 427 428 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss); 429 element->NodalFunctions(basis,gauss); 430 431 geothermalflux_input->GetInputValue(&geothermalflux,gauss); 432 friction->GetAlpha2(&alpha2,gauss); 433 vx_input->GetInputValue(&vx,gauss); 434 vy_input->GetInputValue(&vy,gauss); 435 vz_input->GetInputValue(&vz,gauss); 436 vz = 0.;//FIXME 437 basalfriction = alpha2*(vx*vx + vy*vy + vz*vz); 438 heatflux = (basalfriction+geothermalflux)/(rho_ice*heatcapacity); 439 440 scalar = gauss->weight*Jdet*heatflux; 441 if(dt!=0.) scalar=dt*scalar; 442 443 for(int i=0;i<numnodes;i++) pe->values[i]+=scalar*basis[i]; 444 } 445 446 /*Clean up and return*/ 447 delete gauss; 448 delete friction; 449 xDelete<IssmDouble>(basis); 450 xDelete<IssmDouble>(xyz_list_base); 451 return pe; 452 }/*}}}*/ 453 ElementVector* ThermalAnalysis::CreatePVectorShelf(Element* element){/*{{{*/ 454 455 /* Check if ice in element */ 456 if(!element->IsIceInElement()) return NULL; 457 458 IssmDouble t_pmp,dt,Jdet,scalar_ocean,pressure; 459 IssmDouble *xyz_list_base = NULL; 460 461 /*Get basal element*/ 462 if(!element->IsOnBase() || !element->IsFloating()) return NULL; 463 464 /*Fetch number of nodes for this finite element*/ 465 int numnodes = element->GetNumberOfNodes(); 466 467 /*Initialize vectors*/ 468 ElementVector* pe = element->NewElementVector(); 469 IssmDouble* basis = xNew<IssmDouble>(numnodes); 470 471 /*Retrieve all inputs and parameters*/ 472 element->GetVerticesCoordinatesBase(&xyz_list_base); 473 element->FindParam(&dt,TimesteppingTimeStepEnum); 474 Input* pressure_input=element->GetInput(PressureEnum); _assert_(pressure_input); 344 475 IssmDouble gravity = element->GetMaterialParameter(ConstantsGEnum); 345 476 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum); … … 357 488 element->NodalFunctions(basis,gauss); 358 489 359 D=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel/(heatcapacity*rho_ice);360 if(reCast<bool,IssmDouble>(dt)) D=dt*D;361 TripleMultiply(basis,numnodes,1,0, 362 &D,1,1,0,363 basis,1,numnodes,0,364 &Ke->values[0],1); 365 490 pressure_input->GetInputValue(&pressure,gauss); 491 t_pmp=element->TMeltingPoint(pressure); 492 493 scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel*(t_pmp)/(heatcapacity*rho_ice); 494 if(reCast<bool,IssmDouble>(dt)) scalar_ocean=dt*scalar_ocean; 495 496 for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_ocean*basis[i]; 366 497 } 367 498 … … 370 501 xDelete<IssmDouble>(basis); 371 502 xDelete<IssmDouble>(xyz_list_base); 372 return Ke;373 }/*}}}*/374 ElementVector* ThermalAnalysis::CreatePVector(Element* element){/*{{{*/375 376 /* Check if ice in element */377 if(!element->IsIceInElement()) return NULL;378 379 /*compute all load vectors for this element*/380 ElementVector* pe1=CreatePVectorVolume(element);381 ElementVector* pe2=CreatePVectorSheet(element);382 ElementVector* pe3=CreatePVectorShelf(element);383 ElementVector* pe =new ElementVector(pe1,pe2,pe3);384 385 /*clean-up and return*/386 delete pe1;387 delete pe2;388 delete pe3;389 503 return pe; 390 504 }/*}}}*/ … … 471 585 472 586 }/*}}}*/ 473 ElementVector* ThermalAnalysis::CreatePVectorSheet(Element* element){/*{{{*/474 475 /* Check if ice in element */476 if(!element->IsIceInElement()) return NULL;477 478 /* Geothermal flux on ice sheet base and basal friction */479 if(!element->IsOnBase() || element->IsFloating()) return NULL;480 481 IssmDouble dt,Jdet,geothermalflux,vx,vy,vz;482 IssmDouble alpha2,scalar,basalfriction,heatflux;483 IssmDouble *xyz_list_base = NULL;587 void ThermalAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 588 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 589 * For node i, Bi' can be expressed in the actual coordinate system 590 * by: 591 * Bi_advec =[ h ] 592 * [ h ] 593 * [ h ] 594 * where h is the interpolation function for node i. 595 * 596 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1) 597 */ 484 598 485 599 /*Fetch number of nodes for this finite element*/ 486 600 int numnodes = element->GetNumberOfNodes(); 487 601 488 /*Initialize vectors*/ 489 ElementVector* pe = element->NewElementVector(); 490 IssmDouble* basis = xNew<IssmDouble>(numnodes); 491 492 /*Retrieve all inputs and parameters*/ 493 element->GetVerticesCoordinatesBase(&xyz_list_base); 494 element->FindParam(&dt,TimesteppingTimeStepEnum); 495 Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input); 496 Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input); 497 Input* vz_input = element->GetInput(VzEnum); _assert_(vz_input); 498 Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input); 499 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum); 500 IssmDouble heatcapacity = element->GetMaterialParameter(MaterialsHeatcapacityEnum); 501 502 /*Build friction element, needed later: */ 503 Friction* friction=new Friction(element,3); 504 505 /* Start looping on the number of gaussian points: */ 506 Gauss* gauss = element->NewGaussBase(2); 507 for(int ig=gauss->begin();ig<gauss->end();ig++){ 508 gauss->GaussPoint(ig); 509 510 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss); 511 element->NodalFunctions(basis,gauss); 512 513 geothermalflux_input->GetInputValue(&geothermalflux,gauss); 514 friction->GetAlpha2(&alpha2,gauss); 515 vx_input->GetInputValue(&vx,gauss); 516 vy_input->GetInputValue(&vy,gauss); 517 vz_input->GetInputValue(&vz,gauss); 518 vz = 0.;//FIXME 519 basalfriction = alpha2*(vx*vx + vy*vy + vz*vz); 520 heatflux = (basalfriction+geothermalflux)/(rho_ice*heatcapacity); 521 522 scalar = gauss->weight*Jdet*heatflux; 523 if(dt!=0.) scalar=dt*scalar; 524 525 for(int i=0;i<numnodes;i++) pe->values[i]+=scalar*basis[i]; 526 } 527 528 /*Clean up and return*/ 529 delete gauss; 530 delete friction; 602 /*Get nodal functions*/ 603 IssmDouble* basis=xNew<IssmDouble>(numnodes); 604 element->NodalFunctions(basis,gauss); 605 606 /*Build B: */ 607 for(int i=0;i<numnodes;i++){ 608 B[numnodes*0+i] = basis[i]; 609 B[numnodes*1+i] = basis[i]; 610 B[numnodes*2+i] = basis[i]; 611 } 612 613 /*Clean-up*/ 531 614 xDelete<IssmDouble>(basis); 532 xDelete<IssmDouble>(xyz_list_base); 533 return pe; 534 }/*}}}*/ 535 ElementVector* ThermalAnalysis::CreatePVectorShelf(Element* element){/*{{{*/ 536 537 /* Check if ice in element */ 538 if(!element->IsIceInElement()) return NULL; 539 540 IssmDouble t_pmp,dt,Jdet,scalar_ocean,pressure; 541 IssmDouble *xyz_list_base = NULL; 542 543 /*Get basal element*/ 544 if(!element->IsOnBase() || !element->IsFloating()) return NULL; 615 }/*}}}*/ 616 void ThermalAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 617 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 618 * For node i, Bi' can be expressed in the actual coordinate system 619 * by: 620 * Biprime_advec=[ dh/dx ] 621 * [ dh/dy ] 622 * [ dh/dz ] 623 * where h is the interpolation function for node i. 624 * 625 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes) 626 */ 545 627 546 628 /*Fetch number of nodes for this finite element*/ 547 629 int numnodes = element->GetNumberOfNodes(); 548 630 549 /*Initialize vectors*/ 550 ElementVector* pe = element->NewElementVector(); 551 IssmDouble* basis = xNew<IssmDouble>(numnodes); 552 553 /*Retrieve all inputs and parameters*/ 554 element->GetVerticesCoordinatesBase(&xyz_list_base); 555 element->FindParam(&dt,TimesteppingTimeStepEnum); 556 Input* pressure_input=element->GetInput(PressureEnum); _assert_(pressure_input); 557 IssmDouble gravity = element->GetMaterialParameter(ConstantsGEnum); 558 IssmDouble rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum); 559 IssmDouble rho_ice = element->GetMaterialParameter(MaterialsRhoIceEnum); 560 IssmDouble heatcapacity = element->GetMaterialParameter(MaterialsHeatcapacityEnum); 561 IssmDouble mixed_layer_capacity= element->GetMaterialParameter(MaterialsMixedLayerCapacityEnum); 562 IssmDouble thermal_exchange_vel= element->GetMaterialParameter(MaterialsThermalExchangeVelocityEnum); 563 564 /* Start looping on the number of gaussian points: */ 565 Gauss* gauss=element->NewGaussBase(2); 566 for(int ig=gauss->begin();ig<gauss->end();ig++){ 567 gauss->GaussPoint(ig); 568 569 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss); 570 element->NodalFunctions(basis,gauss); 571 572 pressure_input->GetInputValue(&pressure,gauss); 573 t_pmp=element->TMeltingPoint(pressure); 574 575 scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel*(t_pmp)/(heatcapacity*rho_ice); 576 if(reCast<bool,IssmDouble>(dt)) scalar_ocean=dt*scalar_ocean; 577 578 for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_ocean*basis[i]; 579 } 580 581 /*Clean up and return*/ 582 delete gauss; 583 xDelete<IssmDouble>(basis); 584 xDelete<IssmDouble>(xyz_list_base); 585 return pe; 586 }/*}}}*/ 587 void ThermalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 588 element->GetSolutionFromInputsOneDof(solution,TemperatureEnum); 589 }/*}}}*/ 590 void ThermalAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 631 /*Get nodal functions derivatives*/ 632 IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes); 633 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 634 635 /*Build B: */ 636 for(int i=0;i<numnodes;i++){ 637 B[numnodes*0+i] = dbasis[0*numnodes+i]; 638 B[numnodes*1+i] = dbasis[1*numnodes+i]; 639 B[numnodes*2+i] = dbasis[2*numnodes+i]; 640 } 641 642 /*Clean-up*/ 643 xDelete<IssmDouble>(dbasis); 644 }/*}}}*/ 645 void ThermalAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 591 646 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 592 647 * For node i, Bi' can be expressed in the actual coordinate system … … 617 672 xDelete<IssmDouble>(dbasis); 618 673 }/*}}}*/ 619 void ThermalAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 620 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 621 * For node i, Bi' can be expressed in the actual coordinate system 622 * by: 623 * Bi_advec =[ h ] 624 * [ h ] 625 * [ h ] 626 * where h is the interpolation function for node i. 627 * 628 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1) 629 */ 630 631 /*Fetch number of nodes for this finite element*/ 632 int numnodes = element->GetNumberOfNodes(); 633 634 /*Get nodal functions*/ 635 IssmDouble* basis=xNew<IssmDouble>(numnodes); 636 element->NodalFunctions(basis,gauss); 637 638 /*Build B: */ 639 for(int i=0;i<numnodes;i++){ 640 B[numnodes*0+i] = basis[i]; 641 B[numnodes*1+i] = basis[i]; 642 B[numnodes*2+i] = basis[i]; 643 } 644 645 /*Clean-up*/ 646 xDelete<IssmDouble>(basis); 647 }/*}}}*/ 648 void ThermalAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/ 649 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 650 * For node i, Bi' can be expressed in the actual coordinate system 651 * by: 652 * Biprime_advec=[ dh/dx ] 653 * [ dh/dy ] 654 * [ dh/dz ] 655 * where h is the interpolation function for node i. 656 * 657 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes) 658 */ 659 660 /*Fetch number of nodes for this finite element*/ 661 int numnodes = element->GetNumberOfNodes(); 662 663 /*Get nodal functions derivatives*/ 664 IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes); 665 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); 666 667 /*Build B: */ 668 for(int i=0;i<numnodes;i++){ 669 B[numnodes*0+i] = dbasis[0*numnodes+i]; 670 B[numnodes*1+i] = dbasis[1*numnodes+i]; 671 B[numnodes*2+i] = dbasis[2*numnodes+i]; 672 } 673 674 /*Clean-up*/ 675 xDelete<IssmDouble>(dbasis); 676 }/*}}}*/ 677 void ThermalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 674 void ThermalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 675 element->GetSolutionFromInputsOneDof(solution,TemperatureEnum); 676 }/*}}}*/ 677 void ThermalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 678 678 _error_("Not implemented yet"); 679 679 }/*}}}*/ 680 void ThermalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/680 void ThermalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 681 681 682 682 bool converged; … … 758 758 xDelete<int>(doflist); 759 759 }/*}}}*/ 760 void ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/760 void ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 761 761 762 762 bool islevelset; -
issm/trunk-jpl/src/c/analyses/ThermalAnalysis.h
r18057 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 25 25 ElementMatrix* CreateJacobianMatrix(Element* element); 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 ElementMatrix* CreateKMatrixShelf(Element* element); 27 28 ElementMatrix* CreateKMatrixVolume(Element* element); 28 ElementMatrix* CreateKMatrixShelf(Element* element);29 29 ElementVector* CreatePVector(Element* element); 30 ElementVector* CreatePVectorVolume(Element* element);31 30 ElementVector* CreatePVectorSheet(Element* element); 32 31 ElementVector* CreatePVectorShelf(Element* element); 33 void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 34 void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 35 void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 36 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 37 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 38 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 39 void UpdateConstraints(FemModel* femmodel); 32 ElementVector* CreatePVectorVolume(Element* element); 33 void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 34 void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 35 void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss); 36 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 37 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 38 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 39 void UpdateConstraints(FemModel* femmodel); 40 40 }; 41 41 #endif -
issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp
r18654 r18930 6 6 7 7 /*Model processing*/ 8 void UzawaPressureAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 9 return; 10 }/*}}}*/ 11 void UzawaPressureAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 12 return; 13 }/*}}}*/ 14 void UzawaPressureAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 15 16 int finiteelement; 17 int fe_FS; 18 19 iomodel->Constant(&fe_FS,FlowequationFeFSEnum); 20 if(fe_FS==LATaylorHoodEnum) finiteelement = P1Enum; 21 else if(fe_FS==LACrouzeixRaviartEnum) finiteelement = P1DGEnum; 22 else _error_("solution not supported yet"); 23 24 ::CreateNodes(nodes,iomodel,UzawaPressureAnalysisEnum,finiteelement); 25 }/*}}}*/ 8 26 int UzawaPressureAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/ 9 27 return 1; 10 }/*}}}*/11 void UzawaPressureAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/12 13 parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRhopEnum));14 parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRholambdaEnum));15 28 }/*}}}*/ 16 29 void UzawaPressureAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/ … … 40 53 InputUpdateFromConstantx(elements,0.,SigmaNNEnum); 41 54 }/*}}}*/ 42 void UzawaPressureAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/ 43 44 int finiteelement; 45 int fe_FS; 46 47 iomodel->Constant(&fe_FS,FlowequationFeFSEnum); 48 if(fe_FS==LATaylorHoodEnum) finiteelement = P1Enum; 49 else if(fe_FS==LACrouzeixRaviartEnum) finiteelement = P1DGEnum; 50 else _error_("solution not supported yet"); 51 52 ::CreateNodes(nodes,iomodel,UzawaPressureAnalysisEnum,finiteelement); 53 }/*}}}*/ 54 void UzawaPressureAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/ 55 return; 56 }/*}}}*/ 57 void UzawaPressureAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ 58 return; 55 void UzawaPressureAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ 56 57 parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRhopEnum)); 58 parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRholambdaEnum)); 59 59 }/*}}}*/ 60 60 … … 164 164 return pe; 165 165 }/*}}}*/ 166 void UzawaPressureAnalysis::GetM(IssmDouble* M,Element* element,Gauss* gauss){/*{{{*/166 void UzawaPressureAnalysis::GetM(IssmDouble* M,Element* element,Gauss* gauss){/*{{{*/ 167 167 /*Compute B matrix. M=[M1 M2 M3] */ 168 168 … … 182 182 xDelete<IssmDouble>(basis); 183 183 }/*}}}*/ 184 void UzawaPressureAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/184 void UzawaPressureAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/ 185 185 _error_("not implemented yet"); 186 186 }/*}}}*/ 187 void UzawaPressureAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/187 void UzawaPressureAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/ 188 188 _error_("Not implemented yet"); 189 189 }/*}}}*/ 190 void UzawaPressureAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/190 void UzawaPressureAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/ 191 191 192 192 int dim; … … 297 297 xDelete<int>(doflist); 298 298 }/*}}}*/ 299 void UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/299 void UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ 300 300 /*Default, do nothing*/ 301 301 return; -
issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h
r18179 r18930 13 13 public: 14 14 /*Model processing*/ 15 int DofsPerNode(int** doflist,int domaintype,int approximation);16 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);17 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);18 void CreateNodes(Nodes* nodes,IoModel* iomodel);19 15 void CreateConstraints(Constraints* constraints,IoModel* iomodel); 20 16 void CreateLoads(Loads* loads, IoModel* iomodel); 17 void CreateNodes(Nodes* nodes,IoModel* iomodel); 18 int DofsPerNode(int** doflist,int domaintype,int approximation); 19 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type); 20 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum); 21 21 22 22 /*Finite element Analysis*/ … … 26 26 ElementMatrix* CreateKMatrix(Element* element); 27 27 ElementVector* CreatePVector(Element* element); 28 void GetM(IssmDouble* M,Element* element,Gauss* gauss);29 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);30 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);31 void InputUpdateFromSolution(IssmDouble* solution,Element* element);32 void UpdateConstraints(FemModel* femmodel);28 void GetM(IssmDouble* M,Element* element,Gauss* gauss); 29 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element); 30 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index); 31 void InputUpdateFromSolution(IssmDouble* solution,Element* element); 32 void UpdateConstraints(FemModel* femmodel); 33 33 }; 34 34 #endif
Note:
See TracChangeset
for help on using the changeset viewer.