Changeset 6410
- Timestamp:
- 10/25/10 08:08:10 (14 years ago)
- Location:
- issm/trunk/src/c/objects/Elements
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk/src/c/objects/Elements/Penta.cpp
r6397 r6410 27 27 #define NDOF4 4 28 28 29 /* Penta constructors and destructor*/29 /*Constructors/destructor/copy*/ 30 30 /*FUNCTION Penta::Penta(){{{1*/ 31 31 Penta::Penta(){ … … 85 85 } 86 86 /*}}}*/ 87 88 /*Object virtual functions definitions: */89 87 /*FUNCTION Penta::copy {{{1*/ 90 88 Object* Penta::copy() { … … 135 133 } 136 134 /*}}}*/ 137 /*FUNCTION Penta::DeepEcho{{{1*/ 138 void Penta::DeepEcho(void){ 139 140 int i; 141 142 printf("Penta:\n"); 143 printf(" id: %i\n",id); 144 nodes[0]->DeepEcho(); 145 nodes[1]->DeepEcho(); 146 nodes[2]->DeepEcho(); 147 nodes[3]->DeepEcho(); 148 nodes[4]->DeepEcho(); 149 nodes[5]->DeepEcho(); 150 matice->DeepEcho(); 151 matpar->DeepEcho(); 152 printf(" neighbor ids: %i-%i\n",neighbors[0]->Id(),neighbors[1]->Id()); 153 printf(" parameters\n"); 154 parameters->DeepEcho(); 155 printf(" inputs\n"); 156 inputs->DeepEcho(); 157 printf(" results\n"); 158 results->DeepEcho(); 159 return; 160 } 161 /*}}}*/ 162 /*FUNCTION Penta::Demarshall {{{1*/ 163 void Penta::Demarshall(char** pmarshalled_dataset){ 164 165 char* marshalled_dataset=NULL; 166 int i; 167 int flaghook; 168 169 /*recover marshalled_dataset: */ 170 marshalled_dataset=*pmarshalled_dataset; 171 172 /*this time, no need to get enum type, the pointer directly points to the beginning of the 173 *object data (thanks to DataSet::Demarshall):*/ 174 memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id); 175 memcpy(&numanalyses,marshalled_dataset,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses); 176 177 /*demarshall Ref: */ 178 this->element_type_list=(int*)xmalloc(this->numanalyses*sizeof(int)); 179 for(i=0;i<numanalyses;i++){ memcpy(&element_type_list[i],marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);} 180 181 /*allocate dynamic memory: */ 182 this->hnodes=new Hook*[this->numanalyses]; 183 /*demarshall hooks: */ 184 for(i=0;i<numanalyses;i++){ 185 memcpy(&flaghook,marshalled_dataset,sizeof(flaghook));marshalled_dataset+=sizeof(flaghook); 186 if(flaghook){ // there is a hook so demarshall it 187 hnodes[i]=new Hook(); 188 hnodes[i]->Demarshall(&marshalled_dataset); 189 } 190 else hnodes[i]=NULL; //There is no hook so it is NULL 191 } 192 hmatice=new Hook(); hmatice->Demarshall(&marshalled_dataset); 193 hmatpar=new Hook(); hmatpar->Demarshall(&marshalled_dataset); 194 hneighbors=new Hook(); hneighbors->Demarshall(&marshalled_dataset); 195 196 /*pointers are garbage, until configuration is carried out: */ 197 nodes=NULL; 198 matice=NULL; 199 matpar=NULL; 200 neighbors=NULL; 201 202 /*demarshall inputs and results: */ 203 inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 204 results=(Results*)DataSetDemarshallRaw(&marshalled_dataset); 205 206 /*parameters: may not exist even yet, so let Configure handle it: */ 207 this->parameters=NULL; 208 209 /*return: */ 210 *pmarshalled_dataset=marshalled_dataset; 211 return; 212 } 213 /*}}}*/ 214 /*FUNCTION Penta::Echo{{{1*/ 215 216 void Penta::Echo(void){ 217 this->DeepEcho(); 218 } 219 /*}}}*/ 220 /*FUNCTION Penta::Enum {{{1*/ 221 int Penta::Enum(void){ 222 223 return PentaEnum; 224 225 } 226 /*}}}*/ 227 /*FUNCTION Penta::Id {{{1*/ 228 int Penta::Id(void){ 229 return id; 230 } 231 /*}}}*/ 135 136 /*Marshall*/ 232 137 /*FUNCTION Penta::Marshall {{{1*/ 233 138 void Penta::Marshall(char** pmarshalled_dataset){ … … 321 226 } 322 227 /*}}}*/ 323 /*FUNCTION Penta::MyRank {{{1*/ 324 int Penta::MyRank(void){ 325 extern int my_rank; 326 return my_rank; 327 } 328 /*}}}*/ 329 330 /*Update virtual functions definitions: */ 331 /*FUNCTION Penta::InputUpdateFromConstant(bool value, int name);{{{1*/ 332 void Penta::InputUpdateFromConstant(bool constant, int name){ 333 334 /*Check that name is an element input*/ 335 if (!IsInput(name)) return; 336 337 /*update input*/ 338 this->inputs->AddInput(new BoolInput(name,constant)); 339 } 340 /*}}}*/ 341 /*FUNCTION Penta::InputUpdateFromConstant(double value, int name);{{{1*/ 342 void Penta::InputUpdateFromConstant(double constant, int name){ 343 /*Check that name is an element input*/ 344 if (!IsInput(name)) return; 345 346 /*update input*/ 347 this->inputs->AddInput(new DoubleInput(name,constant)); 348 } 349 /*}}}*/ 350 /*FUNCTION Penta::InputUpdateFromConstant(int value, int name);{{{1*/ 351 void Penta::InputUpdateFromConstant(int constant, int name){ 352 /*Check that name is an element input*/ 353 if (!IsInput(name)) return; 354 355 /*update input*/ 356 this->inputs->AddInput(new IntInput(name,constant)); 357 } 358 /*}}}*/ 359 /*FUNCTION Penta::InputUpdateFromSolution {{{1*/ 360 void Penta::InputUpdateFromSolution(double* solution){ 361 362 int analysis_type; 363 364 /*retreive parameters: */ 365 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 366 367 /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */ 368 if (analysis_type==DiagnosticHorizAnalysisEnum){ 369 InputUpdateFromSolutionDiagnosticHoriz( solution); 370 } 371 else if (analysis_type==DiagnosticHutterAnalysisEnum){ 372 InputUpdateFromSolutionDiagnosticHutter( solution); 373 } 374 else if (analysis_type==DiagnosticVertAnalysisEnum){ 375 InputUpdateFromSolutionDiagnosticVert( solution); 376 } 377 else if (analysis_type==AdjointHorizAnalysisEnum){ 378 int approximation; 379 inputs->GetParameterValue(&approximation,ApproximationEnum); 380 if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){ 381 InputUpdateFromSolutionAdjointStokes( solution); 382 } 383 else{ 384 InputUpdateFromSolutionAdjointHoriz( solution); 385 } 386 } 387 else if (analysis_type==BedSlopeXAnalysisEnum){ 388 InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeXEnum); 389 } 390 else if (analysis_type==BedSlopeYAnalysisEnum){ 391 InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeYEnum); 392 } 393 else if (analysis_type==SurfaceSlopeXAnalysisEnum){ 394 InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeXEnum); 395 } 396 else if (analysis_type==SurfaceSlopeYAnalysisEnum){ 397 InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeYEnum); 398 } 399 else if (analysis_type==PrognosticAnalysisEnum){ 400 InputUpdateFromSolutionOneDofCollapsed(solution,ThicknessEnum); 401 } 402 else if (analysis_type==BalancedthicknessAnalysisEnum){ 403 InputUpdateFromSolutionOneDofCollapsed(solution,ThicknessEnum); 404 } 405 else if (analysis_type==BalancedvelocitiesAnalysisEnum){ 406 InputUpdateFromSolutionOneDofCollapsed(solution,VelEnum); 407 } 408 else if (analysis_type==ThermalAnalysisEnum){ 409 InputUpdateFromSolutionThermal( solution); 410 } 411 else if (analysis_type==MeltingAnalysisEnum){ 412 InputUpdateFromSolutionOneDof(solution,MeltingRateEnum); 413 } 414 else{ 415 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumToString(analysis_type)); 416 } 417 } 418 /*}}}*/ 419 /*FUNCTION Penta::InputUpdateFromVector(double* vector, int name, int type);{{{1*/ 420 void Penta::InputUpdateFromVector(double* vector, int name, int type){ 421 422 /*Check that name is an element input*/ 423 if (!IsInput(name)) return; 424 425 /*Penta update B in InputUpdateFromSolutionThermal, so don't look for B update here.*/ 426 427 switch(type){ 428 429 case VertexEnum: 430 431 /*New PentaVertexInpu*/ 432 double values[6]; 433 434 /*Get values on the 6 vertices*/ 435 for (int i=0;i<6;i++){ 436 values[i]=vector[this->nodes[i]->GetVertexDof()]; 437 } 438 439 /*update input*/ 440 this->inputs->AddInput(new PentaVertexInput(name,values)); 441 return; 442 443 default: 444 445 ISSMERROR("type %i (%s) not implemented yet",type,EnumToString(type)); 446 } 447 } 448 /*}}}*/ 449 /*FUNCTION Penta::InputUpdateFromVector(int* vector, int name, int type);{{{1*/ 450 void Penta::InputUpdateFromVector(int* vector, int name, int type){ 451 ISSMERROR(" not supported yet!"); 452 } 453 /*}}}*/ 454 /*FUNCTION Penta::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/ 455 void Penta::InputUpdateFromVector(bool* vector, int name, int type){ 456 ISSMERROR(" not supported yet!"); 457 } 458 /*}}}*/ 459 /*FUNCTION Penta::InputUpdateFromVectorDakota(double* vector, int name, int type);{{{1*/ 460 void Penta::InputUpdateFromVectorDakota(double* vector, int name, int type){ 461 ISSMERROR(" not supported yet!"); 462 } 463 /*}}}*/ 464 /*FUNCTION Penta::InputUpdateFromVectorDakota(int* vector, int name, int type);{{{1*/ 465 void Penta::InputUpdateFromVectorDakota(int* vector, int name, int type){ 466 ISSMERROR(" not supported yet!"); 467 } 468 /*}}}*/ 469 /*FUNCTION Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type);{{{1*/ 470 void Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type){ 471 ISSMERROR(" not supported yet!"); 472 } 473 /*}}}*/ 474 /*FUNCTION Penta::InputUpdateFromIoModel(int index,IoModel* iomodel) {{{1*/ 475 void Penta::InputUpdateFromIoModel(int index,IoModel* iomodel){ 476 477 /*Intermediaries*/ 478 IssmInt i,j; 479 int penta_vertex_ids[6]; 480 double nodeinputs[6]; 481 482 /*Checks if debuging*/ 483 /*{{{2*/ 484 ISSMASSERT(iomodel->elements); 485 /*}}}*/ 486 487 /*Recover vertices ids needed to initialize inputs*/ 488 for(i=0;i<6;i++){ 489 penta_vertex_ids[i]=(int)iomodel->elements[6*index+i]; //ids for vertices are in the elements array from Matlab 490 } 491 492 //add as many inputs per element as requested: 493 if (iomodel->thickness) { 494 for(i=0;i<6;i++)nodeinputs[i]=iomodel->thickness[penta_vertex_ids[i]-1]; 495 this->inputs->AddInput(new PentaVertexInput(ThicknessEnum,nodeinputs)); 496 } 497 if (iomodel->surface) { 498 for(i=0;i<6;i++)nodeinputs[i]=iomodel->surface[penta_vertex_ids[i]-1]; 499 this->inputs->AddInput(new PentaVertexInput(SurfaceEnum,nodeinputs)); 500 } 501 if (iomodel->bed) { 502 for(i=0;i<6;i++)nodeinputs[i]=iomodel->bed[penta_vertex_ids[i]-1]; 503 this->inputs->AddInput(new PentaVertexInput(BedEnum,nodeinputs)); 504 } 505 if (iomodel->drag_coefficient) { 506 for(i=0;i<6;i++)nodeinputs[i]=iomodel->drag_coefficient[penta_vertex_ids[i]-1]; 507 this->inputs->AddInput(new PentaVertexInput(DragCoefficientEnum,nodeinputs)); 508 509 if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index])); 510 if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index])); 511 this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type)); 512 513 } 514 if (iomodel->melting_rate) { 515 for(i=0;i<6;i++)nodeinputs[i]=iomodel->melting_rate[penta_vertex_ids[i]-1]/iomodel->yts; 516 this->inputs->AddInput(new PentaVertexInput(MeltingRateEnum,nodeinputs)); 517 } 518 if (iomodel->accumulation_rate) { 519 for(i=0;i<6;i++)nodeinputs[i]=iomodel->accumulation_rate[penta_vertex_ids[i]-1]/iomodel->yts; 520 this->inputs->AddInput(new PentaVertexInput(AccumulationRateEnum,nodeinputs)); 521 } 522 if (iomodel->geothermalflux) { 523 for(i=0;i<6;i++)nodeinputs[i]=iomodel->geothermalflux[penta_vertex_ids[i]-1]; 524 this->inputs->AddInput(new PentaVertexInput(GeothermalFluxEnum,nodeinputs)); 525 } 526 if (iomodel->pressure) { 527 for(i=0;i<6;i++)nodeinputs[i]=iomodel->pressure[penta_vertex_ids[i]-1]; 528 this->inputs->AddInput(new PentaVertexInput(PressureEnum,nodeinputs)); 529 } 530 if (iomodel->temperature) { 531 for(i=0;i<6;i++)nodeinputs[i]=iomodel->temperature[penta_vertex_ids[i]-1]; 532 this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,nodeinputs)); 533 } 534 if (iomodel->dhdt) { 535 for(i=0;i<6;i++)nodeinputs[i]=iomodel->dhdt[penta_vertex_ids[i]-1]/iomodel->yts; 536 this->inputs->AddInput(new PentaVertexInput(DhDtEnum,nodeinputs)); 537 } 538 /*vx,vy and vz: */ 539 if (iomodel->vx) { 540 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vx[penta_vertex_ids[i]-1]/iomodel->yts; 541 this->inputs->AddInput(new PentaVertexInput(VxEnum,nodeinputs)); 542 this->inputs->AddInput(new PentaVertexInput(VxOldEnum,nodeinputs)); 543 if(iomodel->qmu_analysis)this->inputs->AddInput(new PentaVertexInput(QmuVxEnum,nodeinputs)); 544 } 545 if (iomodel->vy) { 546 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vy[penta_vertex_ids[i]-1]/iomodel->yts; 547 this->inputs->AddInput(new PentaVertexInput(VyEnum,nodeinputs)); 548 this->inputs->AddInput(new PentaVertexInput(VyOldEnum,nodeinputs)); 549 if(iomodel->qmu_analysis)this->inputs->AddInput(new PentaVertexInput(QmuVyEnum,nodeinputs)); 550 } 551 if (iomodel->vz) { 552 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vz[penta_vertex_ids[i]-1]/iomodel->yts; 553 this->inputs->AddInput(new PentaVertexInput(VzEnum,nodeinputs)); 554 this->inputs->AddInput(new PentaVertexInput(VzOldEnum,nodeinputs)); 555 if(iomodel->qmu_analysis)this->inputs->AddInput(new PentaVertexInput(QmuVzEnum,nodeinputs)); 556 } 557 if (iomodel->vx_obs) { 558 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vx_obs[penta_vertex_ids[i]-1]/iomodel->yts; 559 this->inputs->AddInput(new PentaVertexInput(VxObsEnum,nodeinputs)); 560 } 561 if (iomodel->vy_obs) { 562 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vy_obs[penta_vertex_ids[i]-1]/iomodel->yts; 563 this->inputs->AddInput(new PentaVertexInput(VyObsEnum,nodeinputs)); 564 } 565 if (iomodel->vz_obs) { 566 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vz_obs[penta_vertex_ids[i]-1]/iomodel->yts; 567 this->inputs->AddInput(new PentaVertexInput(VzObsEnum,nodeinputs)); 568 } 569 if (iomodel->weights) { 570 for(i=0;i<6;i++)nodeinputs[i]=iomodel->weights[penta_vertex_ids[i]-1]; 571 this->inputs->AddInput(new PentaVertexInput(WeightsEnum,nodeinputs)); 572 } 573 if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index])); 574 if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index])); 575 if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index])); 576 if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index])); 577 578 /*time: */ 579 this->inputs->AddInput(new DoubleInput(DtEnum,iomodel->dt*iomodel->yts)); 580 581 /*Control Inputs*/ 582 if (iomodel->control_analysis && iomodel->control_type){ 583 for(i=0;i<iomodel->num_control_type;i++){ 584 switch((int)iomodel->control_type[i]){ 585 case DhDtEnum: 586 if (iomodel->dhdt){ 587 for(j=0;j<6;j++)nodeinputs[j]=iomodel->dhdt[penta_vertex_ids[j]-1]/iomodel->yts; 588 this->inputs->AddInput(new ControlInput(DhDtEnum,PentaVertexInputEnum,nodeinputs,i+1)); 589 } 590 break; 591 case VxEnum: 592 if (iomodel->vx){ 593 for(j=0;j<6;j++)nodeinputs[j]=iomodel->vx[penta_vertex_ids[j]-1]/iomodel->yts; 594 this->inputs->AddInput(new ControlInput(VxEnum,PentaVertexInputEnum,nodeinputs,i+1)); 595 } 596 break; 597 case VyEnum: 598 if (iomodel->vy){ 599 for(j=0;j<6;j++)nodeinputs[j]=iomodel->vy[penta_vertex_ids[j]-1]/iomodel->yts; 600 this->inputs->AddInput(new ControlInput(VyEnum,PentaVertexInputEnum,nodeinputs,i+1)); 601 } 602 break; 603 case DragCoefficientEnum: 604 if (iomodel->drag_coefficient){ 605 for(j=0;j<6;j++)nodeinputs[j]=iomodel->drag_coefficient[penta_vertex_ids[j]-1]; 606 this->inputs->AddInput(new ControlInput(DragCoefficientEnum,PentaVertexInputEnum,nodeinputs,i+1)); 607 } 608 break; 609 case RheologyBbarEnum: 610 /*Matice will take care of it*/ break; 611 default: 612 ISSMERROR("Control %s not implemented yet",EnumToString((int)iomodel->control_type[i])); 613 } 614 } 615 } 616 617 //Need to know the type of approximation for this element 618 if(iomodel->elements_type){ 619 if (*(iomodel->elements_type+index)==MacAyealApproximationEnum){ 620 this->inputs->AddInput(new IntInput(ApproximationEnum,MacAyealApproximationEnum)); 621 } 622 else if (*(iomodel->elements_type+index)==PattynApproximationEnum){ 623 this->inputs->AddInput(new IntInput(ApproximationEnum,PattynApproximationEnum)); 624 } 625 else if (*(iomodel->elements_type+index)==MacAyealPattynApproximationEnum){ 626 this->inputs->AddInput(new IntInput(ApproximationEnum,MacAyealPattynApproximationEnum)); 627 } 628 else if (*(iomodel->elements_type+index)==HutterApproximationEnum){ 629 this->inputs->AddInput(new IntInput(ApproximationEnum,HutterApproximationEnum)); 630 } 631 else if (*(iomodel->elements_type+index)==StokesApproximationEnum){ 632 this->inputs->AddInput(new IntInput(ApproximationEnum,StokesApproximationEnum)); 633 } 634 else if (*(iomodel->elements_type+index)==PattynStokesApproximationEnum){ 635 this->inputs->AddInput(new IntInput(ApproximationEnum,PattynStokesApproximationEnum)); 636 } 637 else if (*(iomodel->elements_type+index)==NoneApproximationEnum){ 638 this->inputs->AddInput(new IntInput(ApproximationEnum,NoneApproximationEnum)); 639 } 640 else{ 641 ISSMERROR("Approximation type %s not supported yet",EnumToString((int)*(iomodel->elements_type+index))); 642 } 643 } 644 645 } 646 /*}}}*/ 647 648 /*Element virtual functions definitions: */ 228 /*FUNCTION Penta::Demarshall {{{1*/ 229 void Penta::Demarshall(char** pmarshalled_dataset){ 230 231 char* marshalled_dataset=NULL; 232 int i; 233 int flaghook; 234 235 /*recover marshalled_dataset: */ 236 marshalled_dataset=*pmarshalled_dataset; 237 238 /*this time, no need to get enum type, the pointer directly points to the beginning of the 239 *object data (thanks to DataSet::Demarshall):*/ 240 memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id); 241 memcpy(&numanalyses,marshalled_dataset,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses); 242 243 /*demarshall Ref: */ 244 this->element_type_list=(int*)xmalloc(this->numanalyses*sizeof(int)); 245 for(i=0;i<numanalyses;i++){ memcpy(&element_type_list[i],marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);} 246 247 /*allocate dynamic memory: */ 248 this->hnodes=new Hook*[this->numanalyses]; 249 /*demarshall hooks: */ 250 for(i=0;i<numanalyses;i++){ 251 memcpy(&flaghook,marshalled_dataset,sizeof(flaghook));marshalled_dataset+=sizeof(flaghook); 252 if(flaghook){ // there is a hook so demarshall it 253 hnodes[i]=new Hook(); 254 hnodes[i]->Demarshall(&marshalled_dataset); 255 } 256 else hnodes[i]=NULL; //There is no hook so it is NULL 257 } 258 hmatice=new Hook(); hmatice->Demarshall(&marshalled_dataset); 259 hmatpar=new Hook(); hmatpar->Demarshall(&marshalled_dataset); 260 hneighbors=new Hook(); hneighbors->Demarshall(&marshalled_dataset); 261 262 /*pointers are garbage, until configuration is carried out: */ 263 nodes=NULL; 264 matice=NULL; 265 matpar=NULL; 266 neighbors=NULL; 267 268 /*demarshall inputs and results: */ 269 inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 270 results=(Results*)DataSetDemarshallRaw(&marshalled_dataset); 271 272 /*parameters: may not exist even yet, so let Configure handle it: */ 273 this->parameters=NULL; 274 275 /*return: */ 276 *pmarshalled_dataset=marshalled_dataset; 277 return; 278 } 279 /*}}}*/ 280 281 /*Other*/ 649 282 /*FUNCTION Penta::AverageOntoPartition {{{1*/ 650 283 void Penta::AverageOntoPartition(Vec partition_contributions,Vec partition_areas,double* vertex_response,double* qmu_part){ 651 284 ISSMERROR("Not supported yet!"); 285 } 286 /*}}}*/ 287 /*FUNCTION Penta::BedNormal {{{1*/ 288 void Penta::BedNormal(double* bed_normal, double xyz_list[3][3]){ 289 290 int i; 291 double v13[3],v23[3]; 292 double normal[3]; 293 double normal_norm; 294 295 for (i=0;i<3;i++){ 296 v13[i]=xyz_list[0][i]-xyz_list[2][i]; 297 v23[i]=xyz_list[1][i]-xyz_list[2][i]; 298 } 299 300 normal[0]=v13[1]*v23[2]-v13[2]*v23[1]; 301 normal[1]=v13[2]*v23[0]-v13[0]*v23[2]; 302 normal[2]=v13[0]*v23[1]-v13[1]*v23[0]; 303 normal_norm=sqrt( pow(normal[0],2)+pow(normal[1],2)+pow(normal[2],2) ); 304 305 /*Bed normal is opposite to surface normal*/ 306 *(bed_normal)=-normal[0]/normal_norm; 307 *(bed_normal+1)=-normal[1]/normal_norm; 308 *(bed_normal+2)=-normal[2]/normal_norm; 652 309 } 653 310 /*}}}*/ … … 837 494 838 495 }/*}}}*/ 839 /*FUNCTION Penta::RegularizeInversion {{{1*/840 double Penta::RegularizeInversion(void){841 842 double J;843 Tria* tria=NULL;844 845 /*recover some inputs: */846 int approximation;847 inputs->GetParameterValue(&approximation,ApproximationEnum);848 849 /*If on water, return 0: */850 if(IsOnWater())return 0;851 852 /*Bail out if this element if:853 * -> Not MacAyeal and not on the surface854 * -> MacAyeal (2d model) and not on bed) */855 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){856 return 0;857 }858 else if (approximation==MacAyealApproximationEnum){859 860 /*This element should be collapsed into a tria element at its base. Create this tria element,861 * and compute RegularizeInversion*/862 863 /*Depth Average B*/864 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum);865 866 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).867 J=tria->RegularizeInversion();868 delete tria->matice; delete tria;869 870 /*delete B average*/871 this->matice->inputs->DeleteInput(RheologyBbarEnum);872 873 return J;874 }875 else{876 877 /*Depth Average B and put it in inputs*/878 Penta* penta=GetBasalElement();879 penta->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum);880 Input* B_input=penta->matice->inputs->GetInput(RheologyBbarEnum);881 Input* B_copy=(Input*)B_input->copy();882 this->matice->inputs->AddInput((Input*)B_copy);883 884 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).885 J=tria->RegularizeInversion();886 delete tria->matice; delete tria;887 888 /*delete B average*/889 this->matice->inputs->DeleteInput(RheologyBbarEnum);890 penta->matice->inputs->DeleteInput(RheologyBbarEnum);891 892 return J;893 }894 }895 /*}}}*/896 496 /*FUNCTION Penta::CreateKMatrix {{{1*/ 897 497 void Penta::CreateKMatrix(Mat Kgg, Mat Kff, Mat Kfs){ … … 944 544 delete Ke; 945 545 } 546 } 547 /*}}}*/ 548 /*FUNCTION Penta::CreateKMatrixBalancedthickness {{{1*/ 549 ElementMatrix* Penta::CreateKMatrixBalancedthickness(void){ 550 551 /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the 552 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build 553 the stiffness matrix. */ 554 if (!IsOnBed() || IsOnWater()) return NULL; 555 556 /*Depth Averaging Vx and Vy*/ 557 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum); 558 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum); 559 560 /*Spawn Tria element from the base of the Penta: */ 561 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 562 ElementMatrix* Ke=tria->CreateKMatrixBalancedthickness(); 563 delete tria->matice; delete tria; 564 565 /*Delete Vx and Vy averaged*/ 566 this->inputs->DeleteInput(VxAverageEnum); 567 this->inputs->DeleteInput(VyAverageEnum); 568 569 /*clean up and return*/ 570 return Ke; 571 } 572 /*}}}*/ 573 /*FUNCTION Penta::CreateKMatrixBalancedvelocities {{{1*/ 574 ElementMatrix* Penta::CreateKMatrixBalancedvelocities(void){ 575 576 /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the 577 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build 578 the stiffness matrix. */ 579 if (!IsOnBed() || IsOnWater()) return NULL; 580 581 /*Depth Averaging Vx and Vy*/ 582 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum); 583 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum); 584 585 /*Spawn Tria element from the base of the Penta: */ 586 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 587 ElementMatrix* Ke=tria->CreateKMatrixBalancedvelocities(); 588 delete tria->matice; delete tria; 589 590 /*Delete Vx and Vy averaged*/ 591 this->inputs->DeleteInput(VxAverageEnum); 592 this->inputs->DeleteInput(VyAverageEnum); 593 594 /*clean up and return*/ 595 return Ke; 596 } 597 /*}}}*/ 598 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattyn{{{1*/ 599 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattyn(void){ 600 601 /*compute all stiffness matrices for this element*/ 602 ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealPattynViscous(); 603 ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealPattynFriction(); 604 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2); 605 606 /*clean-up and return*/ 607 delete Ke1; 608 delete Ke2; 609 return Ke; 610 } 611 /*}}}*/ 612 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynViscous{{{1*/ 613 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynViscous(void){ 614 615 /*Constants*/ 616 const int numdofm=NDOF2*NUMVERTICES2D; 617 const int numdofp=NDOF2*NUMVERTICES; 618 const int numdoftotal=2*NDOF2*NUMVERTICES; 619 620 /*Intermediaries */ 621 int i,j,ig; 622 double Jdet; 623 double viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity 624 double epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/ 625 double xyz_list[NUMVERTICES][3]; 626 double B[3][numdofp]; 627 double Bprime[3][numdofm]; 628 double D[3][3]={0.0}; // material matrix, simple scalar matrix. 629 double D_scalar; 630 double Ke_gg[numdofp][numdofm]={0.0}; //local element stiffness matrix 631 double Ke_gg_gaussian[numdofp][numdofm]; //stiffness matrix evaluated at the gaussian point. 632 GaussPenta *gauss=NULL; 633 GaussTria *gauss_tria=NULL; 634 635 /*Find penta on bed as pattyn must be coupled to the dofs on the bed: */ 636 Penta* pentabase=GetBasalElement(); 637 Tria* tria=pentabase->SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 638 639 /*Initialize Element matrix and return if necessary*/ 640 if(IsOnWater()) return NULL; 641 ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum); 642 ElementMatrix* Ke2=new ElementMatrix(this->nodes ,NUMVERTICES,this->parameters,PattynApproximationEnum); 643 ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2); 644 delete Ke1; delete Ke2; 645 646 /* Get node coordinates and dof list: */ 647 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 648 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum); 649 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 650 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 651 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input); 652 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input); 653 654 /* Start looping on the number of gaussian points: */ 655 gauss=new GaussPenta(5,5); 656 gauss_tria=new GaussTria(); 657 for (ig=gauss->begin();ig<gauss->end();ig++){ 658 659 gauss->GaussPoint(ig); 660 gauss->SynchronizeGaussTria(gauss_tria); 661 662 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 663 GetBMacAyealPattyn(&B[0][0], &xyz_list[0][0], gauss); 664 tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria); 665 666 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input); 667 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input); 668 matice->GetViscosity3d(&viscosity, &epsilon[0]); 669 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]); 670 671 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity); 672 D_scalar=2*newviscosity*gauss->weight*Jdet; 673 for (i=0;i<3;i++) D[i][i]=D_scalar; 674 675 TripleMultiply( &B[0][0],3,numdofp,1, 676 &D[0][0],3,3,0, 677 &Bprime[0][0],3,numdofm,0, 678 &Ke_gg_gaussian[0][0],0); 679 680 for( i=0; i<numdofp; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j]; 681 } 682 for(i=0;i<numdofp;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j]; 683 for(i=0;i<numdofm;i++) for(j=0;j<numdofp;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg[j][i]; 684 685 /*Clean-up and return*/ 686 delete tria->matice; delete tria; 687 delete gauss; 688 delete gauss_tria; 689 return Ke; 690 } 691 /*}}}*/ 692 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynFriction{{{1*/ 693 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynFriction(void){ 694 695 /*Initialize Element matrix and return if necessary*/ 696 if(IsOnWater() || IsOnShelf() || !IsOnBed()) return NULL; 697 698 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 699 ElementMatrix* Ke=tria->CreateKMatrixCouplingMacAyealPattynFriction(); 700 delete tria->matice; delete tria; 701 702 return Ke; 703 } 704 /*}}}*/ 705 /*FUNCTION Penta::CreateKMatrixCouplingPattynStokes{{{1*/ 706 ElementMatrix* Penta::CreateKMatrixCouplingPattynStokes(void){ 707 708 /*compute all stiffness matrices for this element*/ 709 ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,PattynApproximationEnum); 710 ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 711 ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2); 712 delete Ke1; 713 delete Ke2; 714 Ke1=CreateKMatrixDiagnosticPattyn(); 715 Ke2=CreateKMatrixDiagnosticStokes(); 716 717 /*Constants*/ 718 const int numdofp=NDOF2*NUMVERTICES; 719 const int numdofs=NDOF4*NUMVERTICES; 720 const int numdoftotal=(NDOF2+NDOF4)*NUMVERTICES; 721 int i,j; 722 723 for(i=0;i<numdofs;i++) for(j=0;j<NUMVERTICES;j++){ 724 Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+0]+=Ke2->values[i*numdofs+NDOF4*j+0]; 725 Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+1]+=Ke2->values[i*numdofs+NDOF4*j+1]; 726 } 727 for(i=0;i<numdofp;i++) for(j=0;j<NUMVERTICES;j++){ 728 Ke->values[i*numdoftotal+numdofp+NDOF4*j+0]+=Ke1->values[i*numdofp+NDOF2*j+0]; 729 Ke->values[i*numdoftotal+numdofp+NDOF4*j+1]+=Ke1->values[i*numdofp+NDOF2*j+1]; 730 } 731 732 /*clean-up and return*/ 733 delete Ke1; 734 delete Ke2; 735 return Ke; 736 } 737 /*}}}*/ 738 /*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/ 739 ElementMatrix* Penta::CreateKMatrixDiagnosticHoriz(void){ 740 741 int approximation; 742 inputs->GetParameterValue(&approximation,ApproximationEnum); 743 744 switch(approximation){ 745 case MacAyealApproximationEnum: 746 return CreateKMatrixDiagnosticMacAyeal2d(); 747 case PattynApproximationEnum: 748 return CreateKMatrixDiagnosticPattyn(); 749 case StokesApproximationEnum: 750 return CreateKMatrixDiagnosticStokes(); 751 case HutterApproximationEnum: 752 return NULL; 753 case NoneApproximationEnum: 754 return NULL; 755 case MacAyealPattynApproximationEnum: 756 return CreateKMatrixDiagnosticMacAyealPattyn(); 757 case PattynStokesApproximationEnum: 758 return CreateKMatrixDiagnosticPattynStokes(); 759 default: 760 ISSMERROR("Approximation %s not supported yet",EnumToString(approximation)); 761 } 762 } 763 /*}}}*/ 764 /*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/ 765 ElementMatrix* Penta::CreateKMatrixDiagnosticHutter(void){ 766 767 /*Constants*/ 768 const int numdof=NDOF2*NUMVERTICES; 769 770 /*Intermediaries*/ 771 int connectivity[2]; 772 int i,i0,i1,j0,j1; 773 double one0,one1; 774 775 /*Initialize Element matrix and return if necessary*/ 776 if(IsOnWater()) return NULL; 777 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 778 779 /*Spawn 3 beam elements: */ 780 for(i=0;i<3;i++){ 781 /*2 dofs of first node*/ 782 i0=2*i; 783 i1=2*i+1; 784 /*2 dofs of second node*/ 785 j0=2*(i+3); 786 j1=2*(i+3)+1; 787 788 /*Find connectivity for the two nodes*/ 789 connectivity[0]=nodes[i]->GetConnectivity(); 790 connectivity[1]=nodes[i+3]->GetConnectivity(); 791 one0=1/(double)connectivity[0]; 792 one1=1/(double)connectivity[1]; 793 794 /*Create matrix for these two nodes*/ 795 if (IsOnBed() && IsOnSurface()){ 796 Ke->values[i0*numdof+i0]=one0; 797 Ke->values[i1*numdof+i1]=one0; 798 Ke->values[j0*numdof+i0]=-one1; 799 Ke->values[j0*numdof+j0]=one1; 800 Ke->values[j1*numdof+i1]=-one1; 801 Ke->values[j1*numdof+j1]=one1; 802 } 803 else if (IsOnBed()){ 804 Ke->values[i0*numdof+i0]=one0; 805 Ke->values[i1*numdof+i1]=one0; 806 Ke->values[j0*numdof+i0]=-2*one1; 807 Ke->values[j0*numdof+j0]=2*one1; 808 Ke->values[j1*numdof+i1]=-2*one1; 809 Ke->values[j1*numdof+j1]=2*one1; 810 } 811 else if (IsOnSurface()){ 812 Ke->values[j0*numdof+i0]=-one1; 813 Ke->values[j0*numdof+j0]=one1; 814 Ke->values[j1*numdof+i1]=-one1; 815 Ke->values[j1*numdof+j1]=one1; 816 } 817 else{ //node is on two horizontal layers and beams include the values only once, so the have to use half of the connectivity 818 Ke->values[j0*numdof+i0]=-2*one1; 819 Ke->values[j0*numdof+j0]=2*one1; 820 Ke->values[j1*numdof+i1]=-2*one1; 821 Ke->values[j1*numdof+j1]=2*one1; 822 } 823 } 824 825 /*Clean up and return*/ 826 return Ke; 827 } 828 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal2d{{{1*/ 829 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal2d(void){ 830 831 /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the 832 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build 833 the stiffness matrix. */ 834 if (!IsOnBed() || IsOnWater()) return NULL; 835 836 /*Depth Averaging B*/ 837 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum); 838 839 /*Call Tria function*/ 840 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 841 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyeal(); 842 delete tria->matice; delete tria; 843 844 /*Delete B averaged*/ 845 this->matice->inputs->DeleteInput(RheologyBbarEnum); 846 847 /*clean up and return*/ 848 return Ke; 849 } 850 /*}}}*/ 851 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3d{{{1*/ 852 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3d(void){ 853 854 /*compute all stiffness matrices for this element*/ 855 ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3dViscous(); 856 ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyeal3dFriction(); 857 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2); 858 859 /*clean-up and return*/ 860 delete Ke1; 861 delete Ke2; 862 return Ke; 863 } 864 /*}}}*/ 865 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dViscous{{{1*/ 866 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dViscous(void){ 867 868 /*Constants*/ 869 const int numdof2d=2*NUMVERTICES2D; 870 871 /*Intermediaries */ 872 int i,j,ig; 873 double Jdet; 874 double viscosity, oldviscosity, newviscosity, viscosity_overshoot; 875 double epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/ 876 double xyz_list[NUMVERTICES][3]; 877 double B[3][numdof2d]; 878 double Bprime[3][numdof2d]; 879 double D[3][3]={0.0}; // material matrix, simple scalar matrix. 880 double D_scalar; 881 double Ke_gg_gaussian[numdof2d][numdof2d]; //stiffness matrix evaluated at the gaussian point. 882 Tria* tria=NULL; 883 Penta* pentabase=NULL; 884 GaussPenta *gauss=NULL; 885 GaussTria *gauss_tria=NULL; 886 887 /*Find penta on bed as this is a macayeal elements: */ 888 pentabase=GetBasalElement(); 889 tria=pentabase->SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 890 891 /*Initialize Element matrix and return if necessary*/ 892 if(IsOnWater()) return NULL; 893 ElementMatrix* Ke=new ElementMatrix(tria->nodes,NUMVERTICES2D,this->parameters,MacAyealApproximationEnum); 894 895 /*Retrieve all inputs and parameters*/ 896 GetVerticesCoordinates(&xyz_list[0][0], nodes,NUMVERTICES); 897 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum); 898 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 899 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 900 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input); 901 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input); 902 903 /* Start looping on the number of gaussian points: */ 904 gauss=new GaussPenta(5,5); 905 gauss_tria=new GaussTria(); 906 for (ig=gauss->begin();ig<gauss->end();ig++){ 907 908 gauss->GaussPoint(ig); 909 gauss->SynchronizeGaussTria(gauss_tria); 910 911 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 912 tria->GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss_tria); 913 tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria); 914 915 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input); 916 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input); 917 matice->GetViscosity3d(&viscosity, &epsilon[0]); 918 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]); 919 920 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity); 921 D_scalar=2*newviscosity*gauss->weight*Jdet; 922 for (i=0;i<3;i++) D[i][i]=D_scalar; 923 924 TripleMultiply( &B[0][0],3,numdof2d,1, 925 &D[0][0],3,3,0, 926 &Bprime[0][0],3,numdof2d,0, 927 &Ke_gg_gaussian[0][0],0); 928 929 for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof2d+j]+=Ke_gg_gaussian[i][j]; 930 } 931 932 /*Clean up and return*/ 933 delete tria->matice; 934 delete tria; 935 delete gauss_tria; 936 delete gauss; 937 return Ke; 938 } 939 /*}}}*/ 940 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dFriction{{{1*/ 941 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dFriction(void){ 942 943 /*Initialize Element matrix and return if necessary*/ 944 if(IsOnWater() || IsOnShelf() || !IsOnBed()) return NULL; 945 946 /*Build a tria element using the 3 grids of the base of the penta. Then use 947 * the tria functionality to build a friction stiffness matrix on these 3 948 * grids: */ 949 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 950 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyealFriction(); 951 delete tria->matice; delete tria; 952 953 /*clean-up and return*/ 954 return Ke; 955 } 956 /*}}}*/ 957 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealPattyn{{{1*/ 958 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealPattyn(void){ 959 960 /*compute all stiffness matrices for this element*/ 961 ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d(); 962 ElementMatrix* Ke2=CreateKMatrixDiagnosticPattyn(); 963 ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealPattyn(); 964 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3); 965 966 /*clean-up and return*/ 967 delete Ke1; 968 delete Ke2; 969 delete Ke3; 970 return Ke; 971 } 972 /*}}}*/ 973 /*FUNCTION Penta::CreateKMatrixDiagnosticPattyn{{{1*/ 974 ElementMatrix* Penta::CreateKMatrixDiagnosticPattyn(void){ 975 976 /*compute all stiffness matrices for this element*/ 977 ElementMatrix* Ke1=CreateKMatrixDiagnosticPattynViscous(); 978 ElementMatrix* Ke2=CreateKMatrixDiagnosticPattynFriction(); 979 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2); 980 981 /*clean-up and return*/ 982 delete Ke1; 983 delete Ke2; 984 return Ke; 985 } 986 /*}}}*/ 987 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynViscous{{{1*/ 988 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynViscous(void){ 989 990 /*Constants*/ 991 const int numdof=NDOF2*NUMVERTICES; 992 993 /*Intermediaries */ 994 int i,j,ig; 995 int approximation; 996 double xyz_list[NUMVERTICES][3]; 997 double Jdet; 998 double viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity 999 double epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/ 1000 double D_scalar; 1001 double D[5][5]={0.0}; // material matrix, simple scalar matrix. 1002 double B[5][numdof]; 1003 double Bprime[5][numdof]; 1004 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point. 1005 Tria* tria=NULL; 1006 GaussPenta *gauss=NULL; 1007 1008 /*Initialize Element matrix and return if necessary*/ 1009 if(IsOnWater()) return NULL; 1010 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum); 1011 1012 /*Retrieve all inputs and parameters*/ 1013 inputs->GetParameterValue(&approximation,ApproximationEnum); 1014 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1015 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum); 1016 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1017 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1018 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input); 1019 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input); 1020 1021 /* Start looping on the number of gaussian points: */ 1022 gauss=new GaussPenta(5,5); 1023 for (ig=gauss->begin();ig<gauss->end();ig++){ 1024 1025 gauss->GaussPoint(ig); 1026 1027 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 1028 GetBPattyn(&B[0][0], &xyz_list[0][0], gauss); 1029 GetBprimePattyn(&Bprime[0][0], &xyz_list[0][0], gauss); 1030 1031 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input); 1032 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input); 1033 matice->GetViscosity3d(&viscosity, &epsilon[0]); 1034 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]); 1035 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity); 1036 1037 D_scalar=2*newviscosity*gauss->weight*Jdet; 1038 for (i=0;i<5;i++) D[i][i]=D_scalar; 1039 1040 TripleMultiply( &B[0][0],5,numdof,1, 1041 &D[0][0],5,5,0, 1042 &Bprime[0][0],5,numdof,0, 1043 &Ke_gg_gaussian[0][0],0); 1044 1045 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j]; 1046 } 1047 1048 /*Clean up and return*/ 1049 delete gauss; 1050 return Ke; 1051 } 1052 /*}}}*/ 1053 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynFriction{{{1*/ 1054 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynFriction(void){ 1055 1056 /*Initialize Element matrix and return if necessary*/ 1057 if(IsOnWater() || IsOnShelf() || !IsOnBed()) return NULL; 1058 1059 /*Build a tria element using the 3 grids of the base of the penta. Then use 1060 * the tria functionality to build a friction stiffness matrix on these 3 1061 * grids: */ 1062 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1063 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticPattynFriction(); 1064 delete tria->matice; delete tria; 1065 1066 /*clean-up and return*/ 1067 return Ke; 1068 } 1069 /*}}}*/ 1070 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynStokes{{{1*/ 1071 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynStokes(void){ 1072 1073 /*compute all stiffness matrices for this element*/ 1074 ElementMatrix* Ke1=CreateKMatrixDiagnosticPattyn(); 1075 ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes(); 1076 ElementMatrix* Ke3=CreateKMatrixCouplingPattynStokes(); 1077 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3); 1078 1079 /*clean-up and return*/ 1080 delete Ke1; 1081 delete Ke2; 1082 delete Ke3; 1083 return Ke; 1084 } 1085 /*}}}*/ 1086 /*FUNCTION Penta::CreateKMatrixDiagnosticStokes{{{1*/ 1087 ElementMatrix* Penta::CreateKMatrixDiagnosticStokes(void){ 1088 1089 /*compute all stiffness matrices for this element*/ 1090 ElementMatrix* Ke1=CreateKMatrixDiagnosticStokesViscous(); 1091 ElementMatrix* Ke2=CreateKMatrixDiagnosticStokesFriction(); 1092 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2); 1093 1094 /*clean-up and return*/ 1095 delete Ke1; 1096 delete Ke2; 1097 return Ke; 1098 } 1099 /*}}}*/ 1100 /*FUNCTION Penta::CreateKMatrixDiagnosticStokesViscous {{{1*/ 1101 ElementMatrix* Penta::CreateKMatrixDiagnosticStokesViscous(void){ 1102 1103 /*Intermediaries */ 1104 int i,j,ig,approximation; 1105 double Jdet,viscosity,stokesreconditioning; 1106 double xyz_list[NUMVERTICES][3]; 1107 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/ 1108 double B[8][27]; 1109 double B_prime[8][27]; 1110 double D_scalar; 1111 double D[8][8]={0.0}; 1112 double Ke_temp[27][27]={0.0}; //for the six nodes and the bubble 1113 double Ke_gaussian[27][27]; 1114 GaussPenta *gauss=NULL; 1115 1116 /*If on water or not Stokes, skip stiffness: */ 1117 inputs->GetParameterValue(&approximation,ApproximationEnum); 1118 if(IsOnWater() || (approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum)) return NULL; 1119 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 1120 1121 /*Retrieve all inputs and parameters*/ 1122 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1123 parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 1124 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1125 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1126 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 1127 1128 /* Start looping on the number of gaussian points: */ 1129 gauss=new GaussPenta(5,5); 1130 for (ig=gauss->begin();ig<gauss->end();ig++){ 1131 1132 gauss->GaussPoint(ig); 1133 1134 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 1135 GetBStokes(&B[0][0],&xyz_list[0][0],gauss); 1136 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0],gauss); 1137 1138 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input); 1139 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 1140 1141 D_scalar=gauss->weight*Jdet; 1142 for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity; 1143 for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning; 1144 1145 TripleMultiply( &B[0][0],8,27,1, 1146 &D[0][0],8,8,0, 1147 &B_prime[0][0],8,27,0, 1148 &Ke_gaussian[0][0],0); 1149 1150 for(i=0;i<27;i++) for(j=0;j<27;j++) Ke_temp[i][j]+=Ke_gaussian[i][j]; 1151 } 1152 1153 /*Condensation*/ 1154 ReduceMatrixStokes(Ke->values, &Ke_temp[0][0]); 1155 1156 /*Clean up and return*/ 1157 delete gauss; 1158 return Ke; 1159 } 1160 /*}}}*/ 1161 /*FUNCTION Penta::CreateKMatrixDiagnosticStokesFriction {{{1*/ 1162 ElementMatrix* Penta::CreateKMatrixDiagnosticStokesFriction(void){ 1163 1164 /*Constants*/ 1165 const int numdof=NUMVERTICES*NDOF4; 1166 const int numdof2d=NUMVERTICES2D*NDOF4; 1167 1168 /*Intermediaries */ 1169 int i,j,ig; 1170 int analysis_type,approximation; 1171 double stokesreconditioning; 1172 double viscosity,alpha2_gauss,Jdet2d; 1173 double bed_normal[3]; 1174 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/ 1175 double xyz_list[NUMVERTICES][3]; 1176 double xyz_list_tria[NUMVERTICES2D][3]; 1177 double LStokes[14][numdof2d]; 1178 double LprimeStokes[14][numdof2d]; 1179 double DLStokes[14][14]={0.0}; 1180 double Ke_drag_gaussian[numdof2d][numdof2d]; 1181 Friction* friction=NULL; 1182 GaussPenta *gauss=NULL; 1183 1184 /*If on water or not Stokes, skip stiffness: */ 1185 inputs->GetParameterValue(&approximation,ApproximationEnum); 1186 if(IsOnWater() || IsOnShelf() || !IsOnBed() || (approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum)) return NULL; 1187 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 1188 1189 /*Retrieve all inputs and parameters*/ 1190 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1191 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 1192 parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 1193 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1194 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1195 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 1196 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j]; 1197 1198 /*build friction object, used later on: */ 1199 friction=new Friction("3d",inputs,matpar,analysis_type); 1200 1201 /* Start looping on the number of gaussian points: */ 1202 gauss=new GaussPenta(0,1,2,2); 1203 for (ig=gauss->begin();ig<gauss->end();ig++){ 1204 1205 gauss->GaussPoint(ig); 1206 1207 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss); 1208 GetLStokes(&LStokes[0][0], gauss); 1209 GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss); 1210 1211 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input); 1212 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 1213 1214 BedNormal(&bed_normal[0],xyz_list_tria); 1215 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum); 1216 1217 DLStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d; 1218 DLStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d; 1219 DLStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2]; 1220 DLStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2]; 1221 DLStokes[4][4]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2]; 1222 DLStokes[5][5]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2]; 1223 DLStokes[6][6]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0]; 1224 DLStokes[7][7]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1]; 1225 DLStokes[8][8]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[2]; 1226 DLStokes[9][9]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0]/2.0; 1227 DLStokes[10][10]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1]/2.0; 1228 DLStokes[11][11]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0]; 1229 DLStokes[12][12]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1]; 1230 DLStokes[13][13]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[2]; 1231 1232 TripleMultiply( &LStokes[0][0],14,numdof2d,1, 1233 &DLStokes[0][0],14,14,0, 1234 &LprimeStokes[0][0],14,numdof2d,0, 1235 &Ke_drag_gaussian[0][0],0); 1236 1237 for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof+j]+=Ke_drag_gaussian[i][j]; 1238 } 1239 1240 /*Clean up and return*/ 1241 delete gauss; 1242 delete friction; 1243 return Ke; 1244 } 1245 /*}}}*/ 1246 /*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/ 1247 ElementMatrix* Penta::CreateKMatrixDiagnosticVert(void){ 1248 1249 /*compute all stiffness matrices for this element*/ 1250 ElementMatrix* Ke1=CreateKMatrixDiagnosticVertVolume(); 1251 ElementMatrix* Ke2=CreateKMatrixDiagnosticVertSurface(); 1252 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2); 1253 1254 /*clean-up and return*/ 1255 delete Ke1; 1256 delete Ke2; 1257 return Ke; 1258 } 1259 /*}}}*/ 1260 /*FUNCTION Penta::CreateKMatrixDiagnosticVertVolume {{{1*/ 1261 ElementMatrix* Penta::CreateKMatrixDiagnosticVertVolume(void){ 1262 1263 /*Constants*/ 1264 const int numdof=NDOF1*NUMVERTICES; 1265 1266 /*Intermediaries */ 1267 int i,j,ig; 1268 double Jdet; 1269 double xyz_list[NUMVERTICES][3]; 1270 double B[NDOF1][NUMVERTICES]; 1271 double Bprime[NDOF1][NUMVERTICES]; 1272 double DL_scalar; 1273 double Ke_gg[numdof][numdof]={0.0}; 1274 GaussPenta *gauss=NULL; 1275 1276 /*Initialize Element matrix and return if necessary*/ 1277 if(IsOnWater()) return NULL; 1278 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1279 1280 /*Retrieve all inputs and parameters*/ 1281 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1282 1283 /* Start looping on the number of gaussian points: */ 1284 gauss=new GaussPenta(2,2); 1285 for (ig=gauss->begin();ig<gauss->end();ig++){ 1286 1287 gauss->GaussPoint(ig); 1288 1289 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 1290 GetBVert(&B[0][0], &xyz_list[0][0], gauss); 1291 GetBprimeVert(&Bprime[0][0], &xyz_list[0][0], gauss); 1292 1293 DL_scalar=gauss->weight*Jdet; 1294 1295 TripleMultiply( &B[0][0],1,NUMVERTICES,1, 1296 &DL_scalar,1,1,0, 1297 &Bprime[0][0],1,NUMVERTICES,0, 1298 &Ke_gg[0][0],0); 1299 1300 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg[i][j]; 1301 } 1302 1303 /*Clean up and return*/ 1304 delete gauss; 1305 return Ke; 1306 } 1307 /*}}}*/ 1308 /*FUNCTION Penta::CreateKMatrixDiagnosticVertSurface {{{1*/ 1309 ElementMatrix* Penta::CreateKMatrixDiagnosticVertSurface(void){ 1310 1311 if (!IsOnSurface() || IsOnWater()) return NULL; 1312 1313 /*Call Tria function*/ 1314 Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3,4 and 5 are on the surface 1315 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticVertSurface(); 1316 delete tria->matice; delete tria; 1317 1318 /*clean up and return*/ 1319 return Ke; 1320 } 1321 /*}}}*/ 1322 /*FUNCTION Penta::CreateKMatrixMelting {{{1*/ 1323 ElementMatrix* Penta::CreateKMatrixMelting(void){ 1324 1325 if (!IsOnBed() || IsOnWater()) return NULL; 1326 1327 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1328 ElementMatrix* Ke=tria->CreateKMatrixMelting(); 1329 1330 delete tria->matice; delete tria; 1331 return Ke; 1332 } 1333 /*}}}*/ 1334 /*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/ 1335 ElementMatrix* Penta::CreateKMatrixPrognostic(void){ 1336 1337 if (!IsOnBed() || IsOnWater()) return NULL; 1338 1339 /*Depth Averaging Vx and Vy*/ 1340 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum); 1341 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum); 1342 1343 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1344 ElementMatrix* Ke=tria->CreateKMatrixPrognostic(); 1345 delete tria->matice; delete tria; 1346 1347 /*Delete Vx and Vy averaged*/ 1348 this->inputs->DeleteInput(VxAverageEnum); 1349 this->inputs->DeleteInput(VyAverageEnum); 1350 1351 /*clean up and return*/ 1352 return Ke; 1353 } 1354 /*}}}*/ 1355 /*FUNCTION Penta::CreateKMatrixSlope {{{1*/ 1356 ElementMatrix* Penta::CreateKMatrixSlope(void){ 1357 1358 if (!IsOnBed() || IsOnWater()) return NULL; 1359 1360 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1361 ElementMatrix* Ke=tria->CreateKMatrixSlope(); 1362 delete tria->matice; delete tria; 1363 1364 /*clean up and return*/ 1365 return Ke; 1366 } 1367 /*}}}*/ 1368 /*FUNCTION Penta::CreateKMatrixThermal {{{1*/ 1369 ElementMatrix* Penta::CreateKMatrixThermal(void){ 1370 1371 /*compute all stiffness matrices for this element*/ 1372 ElementMatrix* Ke1=CreateKMatrixThermalVolume(); 1373 ElementMatrix* Ke2=CreateKMatrixThermalShelf(); 1374 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2); 1375 1376 /*clean-up and return*/ 1377 delete Ke1; 1378 delete Ke2; 1379 return Ke; 1380 } 1381 /*}}}*/ 1382 /*FUNCTION Penta::CreateKMatrixThermalVolume {{{1*/ 1383 ElementMatrix* Penta::CreateKMatrixThermalVolume(void){ 1384 1385 /*Constants*/ 1386 const int numdof=NDOF1*NUMVERTICES; 1387 1388 /*Intermediaries */ 1389 int artdiff; 1390 int i,j,ig,found=0; 1391 double Jdet,u,v,w,epsvel; 1392 double gravity,rho_ice,rho_water; 1393 double heatcapacity,thermalconductivity,dt; 1394 double tau_parameter,diameter; 1395 double xyz_list[NUMVERTICES][3]; 1396 double B[3][numdof]; 1397 double Bprime[3][numdof]; 1398 double B_conduct[3][numdof]; 1399 double B_advec[3][numdof]; 1400 double B_artdiff[2][numdof]; 1401 double Bprime_advec[3][numdof]; 1402 double L[numdof]; 1403 double dh1dh6[3][6]; 1404 double D_scalar_conduct,D_scalar_advec; 1405 double D_scalar_trans,D_scalar_artdiff; 1406 double D[3][3]; 1407 double K[2][2]={0.0}; 1408 double Ke_gaussian_conduct[numdof][numdof]; 1409 double Ke_gaussian_advec[numdof][numdof]; 1410 double Ke_gaussian_artdiff[numdof][numdof]; 1411 double Ke_gaussian_transient[numdof][numdof]; 1412 Tria* tria=NULL; 1413 GaussPenta *gauss=NULL; 1414 1415 /*Initialize Element matrix and return if necessary*/ 1416 if(IsOnWater()) return NULL; 1417 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1418 1419 /*Retrieve all inputs and parameters*/ 1420 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1421 rho_water=matpar->GetRhoWater(); 1422 rho_ice=matpar->GetRhoIce(); 1423 gravity=matpar->GetG(); 1424 heatcapacity=matpar->GetHeatCapacity(); 1425 thermalconductivity=matpar->GetThermalConductivity(); 1426 this->inputs->GetParameterValue(&dt,DtEnum); 1427 this->parameters->FindParam(&artdiff,ArtDiffEnum); 1428 this->parameters->FindParam(&epsvel,EpsVelEnum); 1429 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1430 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1431 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 1432 if (artdiff==2) diameter=MinEdgeLength(xyz_list); 1433 1434 /* Start looping on the number of gaussian points: */ 1435 gauss=new GaussPenta(2,2); 1436 for (ig=gauss->begin();ig<gauss->end();ig++){ 1437 1438 gauss->GaussPoint(ig); 1439 1440 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 1441 1442 /*Conduction: */ 1443 1444 GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss); 1445 1446 D_scalar_conduct=gauss->weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity)); 1447 if(dt) D_scalar_conduct=D_scalar_conduct*dt; 1448 1449 D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0; 1450 D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0; 1451 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct; 1452 1453 TripleMultiply(&B_conduct[0][0],3,numdof,1, 1454 &D[0][0],3,3,0, 1455 &B_conduct[0][0],3,numdof,0, 1456 &Ke_gaussian_conduct[0][0],0); 1457 1458 /*Advection: */ 1459 1460 GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss); 1461 GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss); 1462 1463 vx_input->GetParameterValue(&u, gauss); 1464 vy_input->GetParameterValue(&v, gauss); 1465 vz_input->GetParameterValue(&w, gauss); 1466 1467 D_scalar_advec=gauss->weight*Jdet; 1468 if(dt) D_scalar_advec=D_scalar_advec*dt; 1469 1470 D[0][0]=D_scalar_advec*u;D[0][1]=0; D[0][2]=0; 1471 D[1][0]=0; D[1][1]=D_scalar_advec*v;D[1][2]=0; 1472 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_advec*w; 1473 1474 TripleMultiply(&B_advec[0][0],3,numdof,1, 1475 &D[0][0],3,3,0, 1476 &Bprime_advec[0][0],3,numdof,0, 1477 &Ke_gaussian_advec[0][0],0); 1478 1479 /*Transient: */ 1480 1481 if(dt){ 1482 GetNodalFunctionsP1(&L[0], gauss); 1483 D_scalar_trans=gauss->weight*Jdet; 1484 D_scalar_trans=D_scalar_trans; 1485 1486 TripleMultiply(&L[0],numdof,1,0, 1487 &D_scalar_trans,1,1,0, 1488 &L[0],1,numdof,0, 1489 &Ke_gaussian_transient[0][0],0); 1490 } 1491 else{ 1492 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gaussian_transient[i][j]=0; 1493 } 1494 1495 /*Artifficial diffusivity*/ 1496 1497 if(artdiff==1){ 1498 /*Build K: */ 1499 D_scalar_artdiff=gauss->weight*Jdet/(pow(u,2)+pow(v,2)+epsvel); 1500 if(dt) D_scalar_artdiff=D_scalar_artdiff*dt; 1501 K[0][0]=D_scalar_artdiff*pow(u,2); K[0][1]=D_scalar_artdiff*fabs(u)*fabs(v); 1502 K[1][0]=D_scalar_artdiff*fabs(u)*fabs(v);K[1][1]=D_scalar_artdiff*pow(v,2); 1503 1504 GetBArtdiff(&B_artdiff[0][0],&xyz_list[0][0],gauss); 1505 1506 TripleMultiply(&B_artdiff[0][0],2,numdof,1, 1507 &K[0][0],2,2,0, 1508 &B_artdiff[0][0],2,numdof,0, 1509 &Ke_gaussian_artdiff[0][0],0); 1510 } 1511 else if(artdiff==2){ 1512 1513 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],&xyz_list[0][0], gauss); 1514 1515 tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity); 1516 1517 for(i=0;i<numdof;i++){ 1518 for(j=0;j<numdof;j++){ 1519 Ke_gaussian_artdiff[i][j]=tau_parameter*D_scalar_advec*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i])*(u*dh1dh6[0][j]+v*dh1dh6[1][j]+w*dh1dh6[2][j]); 1520 } 1521 } 1522 if(dt){ 1523 for(i=0;i<numdof;i++){ 1524 for(j=0;j<numdof;j++){ 1525 Ke_gaussian_artdiff[i][j]+=tau_parameter*D_scalar_trans*L[j]*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i]); 1526 } 1527 } 1528 } 1529 } 1530 else{ 1531 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gaussian_artdiff[i][j]=0; 1532 } 1533 1534 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gaussian_conduct[i][j]+Ke_gaussian_advec[i][j]+Ke_gaussian_transient[i][j]+Ke_gaussian_artdiff[i][j]; 1535 } 1536 1537 /*Clean up and return*/ 1538 delete gauss; 1539 return Ke; 1540 } 1541 /*}}}*/ 1542 /*FUNCTION Penta::CreateKMatrixThermalShelf {{{1*/ 1543 ElementMatrix* Penta::CreateKMatrixThermalShelf(void){ 1544 1545 if (!IsOnBed() || !IsOnShelf() || IsOnWater()) return NULL; 1546 1547 /*Call Tria function*/ 1548 Tria* tria=(Tria*)SpawnTria(0,1,2); 1549 ElementMatrix* Ke=tria->CreateKMatrixThermal(); 1550 delete tria->matice; delete tria; 1551 1552 return Ke; 946 1553 } 947 1554 /*}}}*/ … … 1001 1608 } 1002 1609 /*}}}*/ 1610 /*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/ 1611 ElementVector* Penta::CreatePVectorAdjointHoriz(void){ 1612 1613 int approximation; 1614 inputs->GetParameterValue(&approximation,ApproximationEnum); 1615 1616 switch(approximation){ 1617 case MacAyealApproximationEnum: 1618 return CreatePVectorAdjointMacAyeal(); 1619 case PattynApproximationEnum: 1620 return CreatePVectorAdjointPattyn(); 1621 case NoneApproximationEnum: 1622 return NULL; 1623 case StokesApproximationEnum: 1624 return CreatePVectorAdjointStokes(); 1625 default: 1626 ISSMERROR("Approximation %s not supported yet",EnumToString(approximation)); 1627 } 1628 } 1629 /*}}}*/ 1630 /*FUNCTION Penta::CreatePVectorAdjointMacAyeal{{{1*/ 1631 ElementVector* Penta::CreatePVectorAdjointMacAyeal(){ 1632 1633 if (!IsOnBed() || IsOnWater()) return NULL; 1634 1635 /*Call Tria function*/ 1636 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1637 ElementVector* pe=tria->CreatePVectorAdjointHoriz(); 1638 delete tria->matice; delete tria; 1639 1640 /*clean up and return*/ 1641 return pe; 1642 } 1643 /*}}}*/ 1644 /*FUNCTION Penta::CreatePVectorAdjointPattyn{{{1*/ 1645 ElementVector* Penta::CreatePVectorAdjointPattyn(void){ 1646 1647 if (!IsOnSurface() || IsOnWater()) return NULL; 1648 1649 /*Call Tria function*/ 1650 Tria* tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 1651 ElementVector* pe=tria->CreatePVectorAdjointHoriz(); 1652 delete tria->matice; delete tria; 1653 1654 /*clean up and return*/ 1655 return pe; 1656 } 1657 /*}}}*/ 1658 /*FUNCTION Penta::CreatePVectorBalancedthickness {{{1*/ 1659 ElementVector* Penta::CreatePVectorBalancedthickness(void){ 1660 1661 if (!IsOnBed() || IsOnWater()) return NULL; 1662 1663 /*Depth Averaging Vx and Vy*/ 1664 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum); 1665 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum); 1666 1667 /*Call Tria function*/ 1668 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1669 ElementVector* pe=tria->CreatePVectorBalancedthickness(); 1670 delete tria->matice; delete tria; 1671 1672 /*Delete Vx and Vy averaged*/ 1673 this->inputs->DeleteInput(VxAverageEnum); 1674 this->inputs->DeleteInput(VyAverageEnum); 1675 1676 /*Clean up and return*/ 1677 return pe; 1678 } 1679 /*}}}*/ 1680 /*FUNCTION Penta::CreatePVectorBalancedvelocities {{{1*/ 1681 ElementVector* Penta::CreatePVectorBalancedvelocities(void){ 1682 1683 if (!IsOnBed() || IsOnWater()) return NULL; 1684 1685 /*Depth Averaging Vx and Vy*/ 1686 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum); 1687 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum); 1688 1689 /*Call Tria function*/ 1690 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1691 ElementVector* pe=tria->CreatePVectorBalancedvelocities(); 1692 delete tria->matice; delete tria; 1693 1694 /*Delete Vx and Vy averaged*/ 1695 this->inputs->DeleteInput(VxAverageEnum); 1696 this->inputs->DeleteInput(VyAverageEnum); 1697 1698 /*Clean up and return*/ 1699 return pe; 1700 } 1701 /*}}}*/ 1702 /*FUNCTION Penta::CreatePVectorCouplingPattynStokes {{{1*/ 1703 ElementVector* Penta::CreatePVectorCouplingPattynStokes(void){ 1704 1705 /*compute all load vectors for this element*/ 1706 ElementVector* pe1=CreatePVectorCouplingPattynStokesViscous(); 1707 ElementVector* pe2=CreatePVectorCouplingPattynStokesFriction(); 1708 ElementVector* pe =new ElementVector(pe1,pe2); 1709 1710 /*clean-up and return*/ 1711 delete pe1; 1712 delete pe2; 1713 return pe; 1714 } 1715 /*}}}*/ 1716 /*FUNCTION Penta::CreatePVectorCouplingPattynStokesViscous {{{1*/ 1717 ElementVector* Penta::CreatePVectorCouplingPattynStokesViscous(void){ 1718 1719 /*Constants*/ 1720 const int numdof=NUMVERTICES*NDOF4; 1721 1722 /*Intermediaries */ 1723 int i,j,ig; 1724 int approximation; 1725 double viscosity,Jdet; 1726 double stokesreconditioning; 1727 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/ 1728 double dw[3]; 1729 double xyz_list[NUMVERTICES][3]; 1730 double l1l6[6]; //for the six nodes of the penta 1731 double dh1dh6[3][6]; //for the six nodes of the penta 1732 GaussPenta *gauss=NULL; 1733 1734 /*Initialize Element vector and return if necessary*/ 1735 if(IsOnWater()) return NULL; 1736 inputs->GetParameterValue(&approximation,ApproximationEnum); 1737 if(approximation!=PattynStokesApproximationEnum) return NULL; 1738 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 1739 1740 /*Retrieve all inputs and parameters*/ 1741 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1742 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 1743 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1744 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1745 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 1746 Input* vzpattyn_input=inputs->GetInput(VzPattynEnum); ISSMASSERT(vzpattyn_input); 1747 1748 /* Start looping on the number of gaussian points: */ 1749 gauss=new GaussPenta(5,5); 1750 for (ig=gauss->begin();ig<gauss->end();ig++){ 1751 1752 gauss->GaussPoint(ig); 1753 1754 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 1755 GetNodalFunctionsP1(&l1l6[0], gauss); 1756 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],&xyz_list[0][0], gauss); 1757 1758 vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss); 1759 1760 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input); 1761 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 1762 1763 for(i=0;i<NUMVERTICES;i++){ 1764 pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dh1dh6[2][i]; 1765 pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dh1dh6[2][i]; 1766 pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dh1dh6[0][i]+dw[1]*dh1dh6[1][i]+2*dw[2]*dh1dh6[2][i]); 1767 pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*l1l6[i]; 1768 } 1769 } 1770 1771 /*Clean up and return*/ 1772 delete gauss; 1773 return pe; 1774 } 1775 /*}}}*/ 1776 /*FUNCTION Penta::CreatePVectorCouplingPattynStokesFriction{{{1*/ 1777 ElementVector* Penta::CreatePVectorCouplingPattynStokesFriction(void){ 1778 1779 /*Constants*/ 1780 const int numdof=NUMVERTICES*NDOF4; 1781 1782 /*Intermediaries*/ 1783 int i,j,ig; 1784 int approximation,analysis_type; 1785 double Jdet,Jdet2d; 1786 double stokesreconditioning; 1787 double bed_normal[3]; 1788 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/ 1789 double viscosity, w, alpha2_gauss; 1790 double dw[3]; 1791 double xyz_list_tria[NUMVERTICES2D][3]; 1792 double xyz_list[NUMVERTICES][3]; 1793 double l1l6[6]; //for the six nodes of the penta 1794 Tria* tria=NULL; 1795 Friction* friction=NULL; 1796 GaussPenta *gauss=NULL; 1797 1798 /*Initialize Element vector and return if necessary*/ 1799 if(IsOnWater() || !IsOnBed() || IsOnShelf()) return NULL; 1800 inputs->GetParameterValue(&approximation,ApproximationEnum); 1801 if(approximation!=PattynStokesApproximationEnum) return NULL; 1802 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 1803 1804 /*Retrieve all inputs and parameters*/ 1805 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1806 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 1807 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 1808 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1809 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1810 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 1811 Input* vzpattyn_input=inputs->GetInput(VzPattynEnum); ISSMASSERT(vzpattyn_input); 1812 1813 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j]; 1814 1815 /*build friction object, used later on: */ 1816 friction=new Friction("3d",inputs,matpar,analysis_type); 1817 1818 /* Start looping on the number of gauss 2d (nodes on the bedrock) */ 1819 gauss=new GaussPenta(0,1,2,2); 1820 for(ig=gauss->begin();ig<gauss->end();ig++){ 1821 1822 gauss->GaussPoint(ig); 1823 1824 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss); 1825 GetNodalFunctionsP1(l1l6, gauss); 1826 1827 vzpattyn_input->GetParameterValue(&w, gauss); 1828 vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss); 1829 1830 BedNormal(&bed_normal[0],xyz_list_tria); 1831 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input); 1832 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 1833 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum); 1834 1835 for(i=0;i<NUMVERTICES2D;i++){ 1836 pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*l1l6[i]; 1837 pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*l1l6[i]; 1838 pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*l1l6[i]; 1839 } 1840 } 1841 1842 /*Clean up and return*/ 1843 delete gauss; 1844 return pe; 1845 } 1846 /*}}}*/ 1847 /*FUNCTION Penta::CreatePVectorDiagnosticHoriz{{{1*/ 1848 ElementVector* Penta::CreatePVectorDiagnosticHoriz(void){ 1849 1850 int approximation; 1851 inputs->GetParameterValue(&approximation,ApproximationEnum); 1852 1853 switch(approximation){ 1854 case MacAyealApproximationEnum: 1855 return CreatePVectorDiagnosticMacAyeal(); 1856 case PattynApproximationEnum: 1857 return CreatePVectorDiagnosticPattyn(); 1858 case HutterApproximationEnum: 1859 return NULL; 1860 case NoneApproximationEnum: 1861 return NULL; 1862 case StokesApproximationEnum: 1863 return CreatePVectorDiagnosticStokes(); 1864 case MacAyealPattynApproximationEnum: 1865 return CreatePVectorDiagnosticMacAyealPattyn(); 1866 case PattynStokesApproximationEnum: 1867 return CreatePVectorDiagnosticPattynStokes(); 1868 default: 1869 ISSMERROR("Approximation %s not supported yet",EnumToString(approximation)); 1870 } 1871 } 1872 /*}}}*/ 1873 /*FUNCTION Penta::CreatePVectorDiagnosticMacAyealPattyn{{{1*/ 1874 ElementVector* Penta::CreatePVectorDiagnosticMacAyealPattyn(void){ 1875 1876 /*compute all load vectors for this element*/ 1877 ElementVector* pe1=CreatePVectorDiagnosticMacAyeal(); 1878 ElementVector* pe2=CreatePVectorDiagnosticPattyn(); 1879 ElementVector* pe =new ElementVector(pe1,pe2); 1880 1881 /*clean-up and return*/ 1882 delete pe1; 1883 delete pe2; 1884 return pe; 1885 } 1886 /*}}}*/ 1887 /*FUNCTION Penta::CreatePVectorDiagnosticPattynStokes{{{1*/ 1888 ElementVector* Penta::CreatePVectorDiagnosticPattynStokes(void){ 1889 1890 /*compute all load vectors for this element*/ 1891 ElementVector* pe1=CreatePVectorDiagnosticPattyn(); 1892 ElementVector* pe2=CreatePVectorDiagnosticStokes(); 1893 ElementVector* pe3=CreatePVectorCouplingPattynStokes(); 1894 ElementVector* pe =new ElementVector(pe1,pe2,pe3); 1895 1896 /*clean-up and return*/ 1897 delete pe1; 1898 delete pe2; 1899 delete pe3; 1900 return pe; 1901 } 1902 /*}}}*/ 1903 /*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/ 1904 ElementVector* Penta::CreatePVectorDiagnosticHutter(void){ 1905 1906 /*Constants*/ 1907 const int numdofs=NDOF2*NUMVERTICES; 1908 1909 /*Intermediaries*/ 1910 int i,j,k,ig; 1911 int node0,node1; 1912 int connectivity[2]; 1913 double Jdet; 1914 double xyz_list[NUMVERTICES][3]; 1915 double xyz_list_segment[2][3]; 1916 double z_list[NUMVERTICES]; 1917 double z_segment[2],slope[2]; 1918 double slope2,constant_part; 1919 double rho_ice,gravity,n,B; 1920 double ub,vb,z_g,surface,thickness; 1921 GaussPenta* gauss=NULL; 1922 1923 /*Initialize Element vector and return if necessary*/ 1924 if(IsOnWater()) return NULL; 1925 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 1926 1927 /*Retrieve all inputs and parameters*/ 1928 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1929 rho_ice=matpar->GetRhoIce(); 1930 gravity=matpar->GetG(); 1931 n=matice->GetN(); 1932 B=matice->GetB(); 1933 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1934 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input); 1935 Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); ISSMASSERT(slopex_input); 1936 Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); ISSMASSERT(slopey_input); 1937 for(i=0;i<NUMVERTICES;i++)z_list[i]=xyz_list[i][2]; 1938 1939 /*Loop on the three segments*/ 1940 for(i=0;i<3;i++){ 1941 node0=i; 1942 node1=i+3; 1943 1944 for(j=0;j<3;j++){ 1945 xyz_list_segment[0][j]=xyz_list[node0][j]; 1946 xyz_list_segment[1][j]=xyz_list[node1][j]; 1947 } 1948 1949 connectivity[0]=nodes[node0]->GetConnectivity(); 1950 connectivity[1]=nodes[node1]->GetConnectivity(); 1951 1952 /*Loop on the Gauss points: */ 1953 gauss=new GaussPenta(node0,node1,3); 1954 for(ig=gauss->begin();ig<gauss->end();ig++){ 1955 gauss->GaussPoint(ig); 1956 1957 slopex_input->GetParameterValue(&slope[0],gauss); 1958 slopey_input->GetParameterValue(&slope[1],gauss); 1959 surface_input->GetParameterValue(&surface,gauss); 1960 thickness_input->GetParameterValue(&thickness,gauss); 1961 1962 slope2=pow(slope[0],2)+pow(slope[1],2); 1963 constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2)); 1964 1965 PentaRef::GetParameterValue(&z_g,&z_list[0],gauss); 1966 GetSegmentJacobianDeterminant(&Jdet,&xyz_list_segment[0][0],gauss); 1967 1968 if (IsOnSurface()){ 1969 for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight/(double)connectivity[1]; 1970 } 1971 else{//connectivity is too large, should take only half on it 1972 for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight*2/(double)connectivity[1]; 1973 } 1974 } 1975 delete gauss; 1976 1977 //Deal with lower surface 1978 if (IsOnBed()){ 1979 constant_part=-1.58*pow((double)10.0,-(double)10.0)*rho_ice*gravity*thickness; 1980 ub=constant_part*slope[0]; 1981 vb=constant_part*slope[1]; 1982 1983 pe->values[2*node0]+=ub/(double)connectivity[0]; 1984 pe->values[2*node0+1]+=vb/(double)connectivity[0]; 1985 } 1986 } 1987 1988 /*Clean up and return*/ 1989 return pe; 1990 } 1991 /*}}}*/ 1992 /*FUNCTION Penta::CreatePVectorDiagnosticMacAyeal{{{1*/ 1993 ElementVector* Penta::CreatePVectorDiagnosticMacAyeal(void){ 1994 1995 if (!IsOnBed() || IsOnWater()) return NULL; 1996 1997 /*Call Tria function*/ 1998 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1999 ElementVector* pe=tria->CreatePVectorDiagnosticMacAyeal(); 2000 delete tria->matice; delete tria; 2001 2002 /*Clean up and return*/ 2003 return pe; 2004 } 2005 /*}}}*/ 2006 /*FUNCTION Penta::CreatePVectorDiagnosticPattyn{{{1*/ 2007 ElementVector* Penta::CreatePVectorDiagnosticPattyn(void){ 2008 2009 /*Constants*/ 2010 const int numdof=NDOF2*NUMVERTICES; 2011 2012 /*Intermediaries*/ 2013 int i,j,ig; 2014 double Jdet; 2015 double slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also! 2016 double driving_stress_baseline,thickness; 2017 double xyz_list[NUMVERTICES][3]; 2018 double l1l6[6]; 2019 GaussPenta *gauss=NULL; 2020 2021 /*Initialize Element vector and return if necessary*/ 2022 if(IsOnWater()) return NULL; 2023 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum); 2024 2025 /*Retrieve all inputs and parameters*/ 2026 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2027 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 2028 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input); 2029 2030 /* Start looping on the number of gaussian points: */ 2031 gauss=new GaussPenta(2,3); 2032 for (ig=gauss->begin();ig<gauss->end();ig++){ 2033 2034 gauss->GaussPoint(ig); 2035 2036 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 2037 GetNodalFunctionsP1(l1l6, gauss); 2038 2039 thickness_input->GetParameterValue(&thickness, gauss); 2040 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss); 2041 2042 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG(); 2043 2044 for(i=0;i<NUMVERTICES;i++) for(j=0;j<NDOF2;j++) pe->values[i*NDOF2+j]+= -driving_stress_baseline*slope[j]*Jdet*gauss->weight*l1l6[i]; 2045 } 2046 2047 /*Clean up and return*/ 2048 delete gauss; 2049 return pe; 2050 } 2051 /*}}}*/ 2052 /*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/ 2053 ElementVector* Penta::CreatePVectorDiagnosticStokes(void){ 2054 2055 /*compute all load vectors for this element*/ 2056 ElementVector* pe1=CreatePVectorDiagnosticStokesViscous(); 2057 ElementVector* pe2=CreatePVectorDiagnosticStokesShelf(); 2058 ElementVector* pe =new ElementVector(pe1,pe2); 2059 2060 /*clean-up and return*/ 2061 delete pe1; 2062 delete pe2; 2063 return pe; 2064 } 2065 /*}}}*/ 2066 /*FUNCTION Penta::CreatePVectorDiagnosticStokesViscous {{{1*/ 2067 ElementVector* Penta::CreatePVectorDiagnosticStokesViscous(void){ 2068 2069 /*Constants*/ 2070 const int numdofbubble=NDOF4*NUMVERTICES+NDOF3*1; 2071 2072 /*Intermediaries*/ 2073 int i,j,ig; 2074 int approximation; 2075 double Jdet,viscosity; 2076 double gravity,rho_ice,stokesreconditioning; 2077 double xyz_list[NUMVERTICES][3]; 2078 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/ 2079 double l1l7[7]; //for the six nodes and the bubble 2080 double B[8][numdofbubble]; 2081 double B_prime[8][numdofbubble]; 2082 double B_prime_bubble[8][3]; 2083 double D[8][8]={0.0}; 2084 double D_scalar; 2085 double Pe_gaussian[numdofbubble]={0.0}; //for the six nodes and the bubble 2086 double Ke_temp[numdofbubble][3]={0.0}; //for the six nodes and the bubble 2087 double Ke_gaussian[numdofbubble][3]; 2088 GaussPenta *gauss=NULL; 2089 2090 /*Initialize Element vector and return if necessary*/ 2091 if(IsOnWater()) return NULL; 2092 inputs->GetParameterValue(&approximation,ApproximationEnum); 2093 if(approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL; 2094 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 2095 2096 /*Retrieve all inputs and parameters*/ 2097 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 2098 rho_ice=matpar->GetRhoIce(); 2099 gravity=matpar->GetG(); 2100 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2101 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2102 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2103 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 2104 2105 /* Start looping on the number of gaussian points: */ 2106 gauss=new GaussPenta(5,5); 2107 for (ig=gauss->begin();ig<gauss->end();ig++){ 2108 2109 gauss->GaussPoint(ig); 2110 2111 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 2112 GetBStokes(&B[0][0],&xyz_list[0][0],gauss); 2113 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss); 2114 GetNodalFunctionsMINI(&l1l7[0], gauss); 2115 2116 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input); 2117 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 2118 2119 for(i=0;i<NUMVERTICES+1;i++){ 2120 Pe_gaussian[i*NDOF4+2]+=-rho_ice*gravity*Jdet*gauss->weight*l1l7[i]; 2121 } 2122 2123 /*Get bubble part of Bprime */ 2124 for(i=0;i<8;i++) for(j=0;j<3;j++) B_prime_bubble[i][j]=B_prime[i][j+24]; 2125 2126 D_scalar=gauss->weight*Jdet; 2127 for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity; 2128 for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning; 2129 2130 TripleMultiply(&B[0][0],8,numdofbubble,1, 2131 &D[0][0],8,8,0, 2132 &B_prime_bubble[0][0],8,3,0, 2133 &Ke_gaussian[0][0],0); 2134 2135 for(i=0;i<numdofbubble;i++) for(j=0;j<NDOF3;j++) Ke_temp[i][j]+=Ke_gaussian[i][j]; 2136 } 2137 2138 /*Condensation*/ 2139 ReduceVectorStokes(pe->values, &Ke_temp[0][0], &Pe_gaussian[0]); 2140 2141 /*Clean up and return*/ 2142 delete gauss; 2143 return pe; 2144 } 2145 /*}}}*/ 2146 /*FUNCTION Penta::CreatePVectorDiagnosticStokesShelf{{{1*/ 2147 ElementVector* Penta::CreatePVectorDiagnosticStokesShelf(void){ 2148 2149 /*Intermediaries*/ 2150 int i,j,ig; 2151 int approximation; 2152 double gravity,rho_water,bed,water_pressure; 2153 double xyz_list_tria[NUMVERTICES2D][3]; 2154 double xyz_list[NUMVERTICES][3]; 2155 double bed_normal[3]; 2156 double l1l6[6]; //for the six nodes of the penta 2157 double Jdet2d; 2158 GaussPenta *gauss=NULL; 2159 2160 /*Initialize Element vector and return if necessary*/ 2161 if(IsOnWater() || !IsOnBed() || !IsOnShelf()) return NULL; 2162 inputs->GetParameterValue(&approximation,ApproximationEnum); 2163 if(approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL; 2164 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 2165 2166 /*Retrieve all inputs and parameters*/ 2167 rho_water=matpar->GetRhoWater(); 2168 gravity=matpar->GetG(); 2169 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2170 Input* bed_input=inputs->GetInput(BedEnum); ISSMASSERT(bed_input); 2171 2172 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j]; 2173 2174 /* Start looping on the number of gauss 2d (nodes on the bedrock) */ 2175 gauss=new GaussPenta(0,1,2,2); 2176 for(ig=gauss->begin();ig<gauss->end();ig++){ 2177 2178 gauss->GaussPoint(ig); 2179 2180 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss); 2181 GetNodalFunctionsP1(l1l6, gauss); 2182 2183 bed_input->GetParameterValue(&bed, gauss); 2184 BedNormal(&bed_normal[0],xyz_list_tria); 2185 water_pressure=gravity*rho_water*bed; 2186 2187 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) pe->values[i*NDOF4+j]+=water_pressure*gauss->weight*Jdet2d*l1l6[i]*bed_normal[j]; 2188 } 2189 2190 /*Clean up and return*/ 2191 delete gauss; 2192 return pe; 2193 } 2194 /*}}}*/ 2195 /*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/ 2196 ElementVector* Penta::CreatePVectorAdjointStokes(void){ 2197 2198 if (!IsOnSurface() || IsOnWater()) return NULL; 2199 2200 /*Call Tria function*/ 2201 Tria* tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 2202 ElementVector* pe=tria->CreatePVectorAdjointStokes(); 2203 delete tria->matice; delete tria; 2204 2205 /*clean up and return*/ 2206 return pe; 2207 } 2208 /*}}}*/ 2209 /*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/ 2210 ElementVector* Penta::CreatePVectorDiagnosticVert(void){ 2211 2212 /*compute all load vectors for this element*/ 2213 ElementVector* pe1=CreatePVectorDiagnosticVertVolume(); 2214 ElementVector* pe2=CreatePVectorDiagnosticVertBase(); 2215 ElementVector* pe =new ElementVector(pe1,pe2); 2216 2217 /*clean-up and return*/ 2218 delete pe1; 2219 delete pe2; 2220 return pe; 2221 } 2222 /*}}}*/ 2223 /*FUNCTION Penta::CreatePVectorDiagnosticVertVolume {{{1*/ 2224 ElementVector* Penta::CreatePVectorDiagnosticVertVolume(void){ 2225 2226 /*Constants*/ 2227 const int numdof=NDOF1*NUMVERTICES; 2228 2229 /*Intermediaries*/ 2230 int i,ig; 2231 int approximation; 2232 double Jdet; 2233 double xyz_list[NUMVERTICES][3]; 2234 double dudx,dvdy,dwdz; 2235 double du[3],dv[3],dw[3]; 2236 double l1l6[6]; 2237 GaussPenta *gauss=NULL; 2238 2239 /*Initialize Element vector and return if necessary*/ 2240 if(IsOnWater()) return NULL; 2241 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2242 2243 /*Retrieve all inputs and parameters*/ 2244 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2245 inputs->GetParameterValue(&approximation,ApproximationEnum); 2246 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2247 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2248 Input* vzstokes_input=NULL; 2249 if(approximation==PattynStokesApproximationEnum){ 2250 vzstokes_input=inputs->GetInput(VzStokesEnum); ISSMASSERT(vzstokes_input); 2251 } 2252 2253 /* Start looping on the number of gaussian points: */ 2254 gauss=new GaussPenta(2,2); 2255 for (ig=gauss->begin();ig<gauss->end();ig++){ 2256 2257 gauss->GaussPoint(ig); 2258 2259 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 2260 GetNodalFunctionsP1(l1l6, gauss); 2261 2262 vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss); 2263 vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss); 2264 if(approximation==PattynStokesApproximationEnum){ 2265 vzstokes_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss); 2266 dwdz=dw[2]; 2267 } 2268 else dwdz=0; 2269 dudx=du[0]; 2270 dvdy=dv[1]; 2271 2272 for (i=0;i<numdof;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*l1l6[i]; 2273 } 2274 2275 /*Clean up and return*/ 2276 delete gauss; 2277 return pe; 2278 } 2279 /*}}}*/ 2280 /*FUNCTION Penta::CreatePVectorDiagnosticVertBase {{{1*/ 2281 ElementVector* Penta::CreatePVectorDiagnosticVertBase(void){ 2282 2283 if (!IsOnBed() || IsOnWater()) return NULL; 2284 2285 /*Call Tria function*/ 2286 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2287 ElementVector* pe=tria->CreatePVectorDiagnosticBaseVert(); 2288 delete tria->matice; delete tria; 2289 2290 /*Clean up and return*/ 2291 return pe; 2292 } 2293 /*}}}*/ 2294 /*FUNCTION Penta::CreatePVectorMelting {{{1*/ 2295 ElementVector* Penta::CreatePVectorMelting(void){ 2296 return NULL; 2297 } 2298 /*}}}*/ 2299 /*FUNCTION Penta::CreatePVectorPrognostic {{{1*/ 2300 ElementVector* Penta::CreatePVectorPrognostic(void){ 2301 2302 if (!IsOnBed() || IsOnWater()) return NULL; 2303 2304 /*Depth Averaging Vx and Vy*/ 2305 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum); 2306 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum); 2307 2308 /*Call Tria function*/ 2309 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2310 ElementVector* pe=tria->CreatePVectorPrognostic(); 2311 delete tria->matice; delete tria; 2312 2313 /*Delete Vx and Vy averaged*/ 2314 this->inputs->DeleteInput(VxAverageEnum); 2315 this->inputs->DeleteInput(VyAverageEnum); 2316 2317 /*Clean up and return*/ 2318 return pe; 2319 } 2320 /*}}}*/ 2321 /*FUNCTION Penta::CreatePVectorSlope {{{1*/ 2322 ElementVector* Penta::CreatePVectorSlope(void){ 2323 2324 if (!IsOnBed() || IsOnWater()) return NULL; 2325 2326 /*Call Tria function*/ 2327 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2328 ElementVector* pe=tria->CreatePVectorSlope(); 2329 delete tria->matice; delete tria; 2330 2331 /*clean up and return*/ 2332 return pe; 2333 } 2334 /*}}}*/ 2335 /*FUNCTION Penta::CreatePVectorThermal {{{1*/ 2336 ElementVector* Penta::CreatePVectorThermal(void){ 2337 2338 /*compute all load vectors for this element*/ 2339 ElementVector* pe1=CreatePVectorThermalVolume(); 2340 ElementVector* pe2=CreatePVectorThermalSheet(); 2341 ElementVector* pe3=CreatePVectorThermalShelf(); 2342 ElementVector* pe =new ElementVector(pe1,pe2,pe3); 2343 2344 /*clean-up and return*/ 2345 delete pe1; 2346 delete pe2; 2347 delete pe3; 2348 return pe; 2349 } 2350 /*}}}*/ 2351 /*FUNCTION Penta::CreatePVectorThermalVolume {{{1*/ 2352 ElementVector* Penta::CreatePVectorThermalVolume(void){ 2353 2354 /*Constants*/ 2355 const int numdof=NUMVERTICES*NDOF1; 2356 2357 /*Intermediaries*/ 2358 int i,j,ig,found=0; 2359 int friction_type,artdiff; 2360 double Jdet,phi,dt; 2361 double rho_ice,heatcapacity; 2362 double thermalconductivity; 2363 double viscosity,temperature; 2364 double tau_parameter,diameter; 2365 double u,v,w; 2366 double scalar_def,scalar_transient; 2367 double temperature_list[NUMVERTICES]; 2368 double xyz_list[NUMVERTICES][3]; 2369 double L[numdof]; 2370 double dh1dh6[3][6]; 2371 double epsilon[6]; 2372 GaussPenta *gauss=NULL; 2373 2374 /*Initialize Element vector and return if necessary*/ 2375 if(IsOnWater()) return NULL; 2376 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2377 2378 /*Retrieve all inputs and parameters*/ 2379 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2380 rho_ice=matpar->GetRhoIce(); 2381 heatcapacity=matpar->GetHeatCapacity(); 2382 thermalconductivity=matpar->GetThermalConductivity(); 2383 this->inputs->GetParameterValue(&dt,DtEnum); 2384 this->parameters->FindParam(&artdiff,ArtDiffEnum); 2385 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2386 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2387 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 2388 Input* temperature_input=NULL; 2389 if (dt) temperature_input=inputs->GetInput(TemperatureEnum); ISSMASSERT(inputs); 2390 if (artdiff==2) diameter=MinEdgeLength(xyz_list); 2391 2392 /* Start looping on the number of gaussian points: */ 2393 gauss=new GaussPenta(2,3); 2394 for (ig=gauss->begin();ig<gauss->end();ig++){ 2395 2396 gauss->GaussPoint(ig); 2397 2398 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss); 2399 GetNodalFunctionsP1(&L[0], gauss); 2400 2401 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input); 2402 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 2403 GetPhi(&phi, &epsilon[0], viscosity); 2404 2405 scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight; 2406 if(dt) scalar_def=scalar_def*dt; 2407 2408 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=scalar_def*L[i]; 2409 2410 /* Build transient now */ 2411 if(dt){ 2412 temperature_input->GetParameterValue(&temperature, gauss); 2413 scalar_transient=temperature*Jdet*gauss->weight; 2414 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=scalar_transient*L[i]; 2415 } 2416 2417 if(artdiff==2){ 2418 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],&xyz_list[0][0], gauss); 2419 2420 vx_input->GetParameterValue(&u, gauss); 2421 vy_input->GetParameterValue(&v, gauss); 2422 vz_input->GetParameterValue(&w, gauss); 2423 2424 tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity); 2425 2426 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=tau_parameter*scalar_def*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i]); 2427 if(dt){ 2428 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=tau_parameter*scalar_transient*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i]); 2429 } 2430 } 2431 } 2432 2433 /*Clean up and return*/ 2434 delete gauss; 2435 return pe; 2436 } 2437 /*}}}*/ 2438 /*FUNCTION Penta::CreatePVectorThermalShelf {{{1*/ 2439 ElementVector* Penta::CreatePVectorThermalShelf(void){ 2440 2441 /* Ice/ocean heat exchange flux on ice shelf base */ 2442 if (!IsOnBed() || !IsOnShelf() || IsOnWater()) return NULL; 2443 2444 /*Call Tria function*/ 2445 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2446 ElementVector* pe=tria->CreatePVectorThermalShelf(); 2447 delete tria->matice; delete tria; 2448 2449 /*Clean up and return*/ 2450 return pe; 2451 } 2452 /*}}}*/ 2453 /*FUNCTION Penta::CreatePVectorThermalSheet {{{1*/ 2454 ElementVector* Penta::CreatePVectorThermalSheet(void){ 2455 2456 /* Geothermal flux on ice sheet base and basal friction */ 2457 if (!IsOnBed() || IsOnShelf() || IsOnWater()) return NULL; 2458 2459 /*Call Tria function*/ 2460 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2461 ElementVector* pe=tria->CreatePVectorThermalSheet(); 2462 delete tria->matice; delete tria; 2463 2464 /*Clean up and return*/ 2465 return pe; 2466 } 2467 /*}}}*/ 2468 /*FUNCTION Penta::DeepEcho{{{1*/ 2469 void Penta::DeepEcho(void){ 2470 2471 int i; 2472 2473 printf("Penta:\n"); 2474 printf(" id: %i\n",id); 2475 nodes[0]->DeepEcho(); 2476 nodes[1]->DeepEcho(); 2477 nodes[2]->DeepEcho(); 2478 nodes[3]->DeepEcho(); 2479 nodes[4]->DeepEcho(); 2480 nodes[5]->DeepEcho(); 2481 matice->DeepEcho(); 2482 matpar->DeepEcho(); 2483 printf(" neighbor ids: %i-%i\n",neighbors[0]->Id(),neighbors[1]->Id()); 2484 printf(" parameters\n"); 2485 parameters->DeepEcho(); 2486 printf(" inputs\n"); 2487 inputs->DeepEcho(); 2488 printf(" results\n"); 2489 results->DeepEcho(); 2490 return; 2491 } 2492 /*}}}*/ 1003 2493 /*FUNCTION Penta::DeleteResults {{{1*/ 1004 2494 void Penta::DeleteResults(void){ … … 1008 2498 this->results=new Results(); 1009 2499 2500 } 2501 /*}}}*/ 2502 /*FUNCTION Penta::Echo{{{1*/ 2503 2504 void Penta::Echo(void){ 2505 this->DeepEcho(); 2506 } 2507 /*}}}*/ 2508 /*FUNCTION Penta::Enum {{{1*/ 2509 int Penta::Enum(void){ 2510 2511 return PentaEnum; 2512 2513 } 2514 /*}}}*/ 2515 /*FUNCTION Penta::Gradj {{{1*/ 2516 void Penta::Gradj(Vec gradient,int control_type){ 2517 2518 /*If on water, skip grad (=0): */ 2519 if(IsOnWater())return; 2520 2521 if (control_type==DragCoefficientEnum){ 2522 GradjDrag(gradient); 2523 } 2524 else if (control_type==RheologyBbarEnum){ 2525 GradjB(gradient); 2526 } 2527 else ISSMERROR("control type %s not supported yet: ",EnumToString(control_type)); 2528 } 2529 /*}}}*/ 2530 /*FUNCTION Penta::GradjB {{{1*/ 2531 void Penta::GradjB(Vec gradient){ 2532 2533 int i; 2534 int approximation; 2535 Tria* tria =NULL; 2536 TriaVertexInput* triavertexinput=NULL; 2537 2538 /*If on water, skip: */ 2539 if(IsOnWater())return; 2540 inputs->GetParameterValue(&approximation,ApproximationEnum); 2541 2542 if (approximation==MacAyealApproximationEnum){ 2543 /*Bail out element if MacAyeal (2d) and not on bed*/ 2544 if (!IsOnBed()) return; 2545 2546 /*This element should be collapsed into a tria element at its base. Create this tria element, 2547 * and compute gardj*/ 2548 2549 /*Depth Average B*/ 2550 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum); 2551 2552 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 2553 tria->GradjB(gradient); 2554 delete tria->matice; delete tria; 2555 2556 /*delete B average*/ 2557 this->matice->inputs->DeleteInput(RheologyBbarEnum); 2558 } 2559 else{ 2560 /*Gradient is computed on bed only (Bbar)*/ 2561 if (!IsOnBed()) return; 2562 2563 /*Depth Average B*/ 2564 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum); 2565 2566 /*B is a 2d field, use MacAyeal(2d) gradient even if it is Stokes or Pattyn*/ 2567 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 2568 tria->GradjB(gradient); 2569 delete tria->matice; delete tria; 2570 2571 /*delete B average*/ 2572 this->matice->inputs->DeleteInput(RheologyBbarEnum); 2573 } 2574 } 2575 /*}}}*/ 2576 /*FUNCTION Penta::GradjDrag {{{1*/ 2577 void Penta::GradjDrag(Vec gradient){ 2578 2579 int i,approximation; 2580 double temp_gradient[6]={0,0,0,0,0,0}; 2581 Tria* tria=NULL; 2582 TriaVertexInput* triavertexinput=NULL; 2583 2584 /*retrieve inputs :*/ 2585 inputs->GetParameterValue(&approximation,ApproximationEnum); 2586 2587 /*If on water, on shelf or not on bed, skip: */ 2588 if(IsOnWater()|| IsOnShelf() || !IsOnBed())return; 2589 2590 if (approximation==MacAyealApproximationEnum || approximation==PattynApproximationEnum){ 2591 /*MacAyeal or Pattyn*/ 2592 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2593 tria->GradjDrag(gradient); 2594 delete tria->matice; delete tria; 2595 } 2596 else if (approximation==StokesApproximationEnum){ 2597 /*Stokes*/ 2598 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2599 tria->GradjDragStokes(gradient); 2600 delete tria->matice; delete tria; 2601 } 2602 else if (approximation==NoneApproximationEnum){ 2603 return; 2604 } 2605 else ISSMERROR("approximation %s not supported yet",EnumToString(approximation)); 2606 } 2607 /*}}}*/ 2608 /*FUNCTION Penta::GetBasalElement{{{1*/ 2609 Penta* Penta::GetBasalElement(void){ 2610 2611 /*Output*/ 2612 Penta* penta=NULL; 2613 2614 /*Go through all elements till the bed is reached*/ 2615 penta=this; 2616 for(;;){ 2617 /*Stop if we have reached the surface, else, take lower penta*/ 2618 if (penta->IsOnBed()) break; 2619 2620 /* get lower Penta*/ 2621 penta=penta->GetLowerElement(); 2622 ISSMASSERT(penta->Id()!=this->id); 2623 } 2624 2625 /*return output*/ 2626 return penta; 2627 } 2628 /*}}}*/ 2629 /*FUNCTION Penta::GetDofList {{{1*/ 2630 void Penta::GetDofList(int** pdoflist,int approximation_enum,int setenum){ 2631 2632 int i,j,count=0; 2633 int numberofdofs=0; 2634 int* doflist=NULL; 2635 2636 /*First, figure out size of doflist: */ 2637 for(i=0;i<6;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum); 2638 2639 /*Allocate: */ 2640 doflist=(int*)xmalloc(numberofdofs*sizeof(int)); 2641 2642 /*Populate: */ 2643 count=0; 2644 for(i=0;i<6;i++){ 2645 nodes[i]->GetDofList(doflist+count,approximation_enum,setenum); 2646 count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum); 2647 } 2648 2649 /*Assign output pointers:*/ 2650 *pdoflist=doflist; 2651 } 2652 /*}}}*/ 2653 /*FUNCTION Penta::GetDofList1 {{{1*/ 2654 void Penta::GetDofList1(int* doflist){ 2655 2656 int i; 2657 for(i=0;i<6;i++) doflist[i]=nodes[i]->GetDofList1(); 2658 2659 } 2660 /*}}}*/ 2661 /*FUNCTION Penta::GetElementType {{{1*/ 2662 int Penta::GetElementType(){ 2663 2664 /*return PentaRef field*/ 2665 return this->element_type; 2666 } 2667 /*}}}*/ 2668 /*FUNCTION Penta::GetLowerElement{{{1*/ 2669 Penta* Penta::GetLowerElement(void){ 2670 2671 Penta* upper_penta=NULL; 2672 2673 upper_penta=(Penta*)neighbors[0]; //first one (0) under, second one (1) above 2674 2675 return upper_penta; 1010 2676 } 1011 2677 /*}}}*/ … … 1019 2685 } 1020 2686 ISSMERROR("Node provided not found among element nodes"); 2687 2688 } 2689 /*}}}*/ 2690 /*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/ 2691 void Penta::GetParameterListOnVertices(double* pvalue,int enumtype){ 2692 2693 /*Intermediaries*/ 2694 double value[NUMVERTICES]; 2695 GaussPenta *gauss = NULL; 2696 2697 /*Recover input*/ 2698 Input* input=inputs->GetInput(enumtype); 2699 if (!input) ISSMERROR("Input %s not found in element",EnumToString(enumtype)); 2700 2701 /*Checks in debugging mode*/ 2702 ISSMASSERT(pvalue); 2703 2704 /* Start looping on the number of vertices: */ 2705 gauss=new GaussPenta(); 2706 for (int iv=0;iv<NUMVERTICES;iv++){ 2707 gauss->GaussVertex(iv); 2708 input->GetParameterValue(&pvalue[iv],gauss); 2709 } 2710 2711 /*clean-up*/ 2712 delete gauss; 2713 } 2714 /*}}}*/ 2715 /*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/ 2716 void Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){ 2717 2718 /*Intermediaries*/ 2719 double value[NUMVERTICES]; 2720 GaussPenta *gauss = NULL; 2721 2722 /*Recover input*/ 2723 Input* input=inputs->GetInput(enumtype); 2724 2725 /*Checks in debugging mode*/ 2726 ISSMASSERT(pvalue); 2727 2728 /* Start looping on the number of vertices: */ 2729 if (input){ 2730 gauss=new GaussPenta(); 2731 for (int iv=0;iv<NUMVERTICES;iv++){ 2732 gauss->GaussVertex(iv); 2733 input->GetParameterValue(&pvalue[iv],gauss); 2734 } 2735 } 2736 else{ 2737 for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue; 2738 } 2739 2740 /*clean-up*/ 2741 delete gauss; 2742 } 2743 /*}}}*/ 2744 /*FUNCTION Penta::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/ 2745 void Penta::GetParameterValue(double* pvalue,Node* node,int enumtype){ 2746 2747 Input* input=inputs->GetInput(enumtype); 2748 if(!input) ISSMERROR("No input of type %s found in tria",EnumToString(enumtype)); 2749 2750 GaussPenta* gauss=new GaussPenta(); 2751 gauss->GaussVertex(this->GetNodeIndex(node)); 2752 2753 input->GetParameterValue(pvalue,gauss); 2754 delete gauss; 2755 } 2756 /*}}}*/ 2757 /*FUNCTION Penta::GetPhi {{{1*/ 2758 void Penta::GetPhi(double* phi, double* epsilon, double viscosity){ 2759 /*Compute deformational heating from epsilon and viscosity */ 2760 2761 double epsilon_matrix[3][3]; 2762 double epsilon_eff; 2763 double epsilon_sqr[3][3]; 2764 2765 /* Build epsilon matrix */ 2766 epsilon_matrix[0][0]=*(epsilon+0); 2767 epsilon_matrix[1][0]=*(epsilon+3); 2768 epsilon_matrix[2][0]=*(epsilon+4); 2769 epsilon_matrix[0][1]=*(epsilon+3); 2770 epsilon_matrix[1][1]=*(epsilon+1); 2771 epsilon_matrix[2][1]=*(epsilon+5); 2772 epsilon_matrix[0][2]=*(epsilon+4); 2773 epsilon_matrix[1][2]=*(epsilon+5); 2774 epsilon_matrix[2][2]=*(epsilon+2); 2775 2776 /* Effective value of epsilon_matrix */ 2777 epsilon_sqr[0][0]=pow(epsilon_matrix[0][0],2); 2778 epsilon_sqr[1][0]=pow(epsilon_matrix[1][0],2); 2779 epsilon_sqr[2][0]=pow(epsilon_matrix[2][0],2); 2780 epsilon_sqr[0][1]=pow(epsilon_matrix[0][1],2); 2781 epsilon_sqr[1][1]=pow(epsilon_matrix[1][1],2); 2782 epsilon_sqr[2][1]=pow(epsilon_matrix[2][1],2); 2783 epsilon_sqr[0][2]=pow(epsilon_matrix[0][2],2); 2784 epsilon_sqr[1][2]=pow(epsilon_matrix[1][2],2); 2785 epsilon_sqr[2][2]=pow(epsilon_matrix[2][2],2); 2786 epsilon_eff=1/pow(2,0.5)*pow((epsilon_sqr[0][0]+epsilon_sqr[0][1]+ epsilon_sqr[0][2]+ epsilon_sqr[1][0]+ epsilon_sqr[1][1]+ epsilon_sqr[1][2]+ epsilon_sqr[2][0]+ epsilon_sqr[2][1]+ epsilon_sqr[2][2]),0.5); 2787 2788 /*Phi = Tr(sigma * eps) 2789 * = Tr(sigma'* eps) 2790 * = 2 * eps_eff * sigma'_eff 2791 * = 4 * eps_eff ^2*/ 2792 *phi=4*pow(epsilon_eff,2.0)*viscosity; 2793 } 2794 /*}}}*/ 2795 /*FUNCTION Penta::GetSidList{{{1*/ 2796 void Penta::GetSidList(int* sidlist){ 2797 2798 int i; 2799 for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList(); 1021 2800 1022 2801 } … … 1056 2835 ISSMERROR("analysis: %i (%s) not supported yet",analysis_type,EnumToString(analysis_type)); 1057 2836 } 2837 } 2838 /*}}}*/ 2839 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/ 2840 void Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){ 2841 2842 const int numdof=NDOF2*NUMVERTICES; 2843 2844 int i; 2845 int approximation; 2846 int* doflist=NULL; 2847 double vx,vy; 2848 double values[numdof]; 2849 GaussPenta* gauss; 2850 2851 /*Get approximation enum and dof list: */ 2852 inputs->GetParameterValue(&approximation,ApproximationEnum); 2853 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2854 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2855 2856 /*If the element is a coupling, do nothing: every grid is also on an other elements 2857 * (as coupling is between MacAyeal and Pattyn) so the other element will take care of it*/ 2858 GetDofList(&doflist,approximation,GsetEnum); 2859 2860 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 2861 /*P1 element only for now*/ 2862 gauss=new GaussPenta(); 2863 for(i=0;i<NUMVERTICES;i++){ 2864 2865 /*Recover vx and vy*/ 2866 gauss->GaussVertex(i); 2867 vx_input->GetParameterValue(&vx,gauss); 2868 vy_input->GetParameterValue(&vy,gauss); 2869 values[i*NDOF2+0]=vx; 2870 values[i*NDOF2+1]=vy; 2871 } 2872 2873 /*Add value to global vector*/ 2874 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 2875 2876 /*Free ressources:*/ 2877 delete gauss; 2878 xfree((void**)&doflist); 2879 } 2880 /*}}}*/ 2881 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/ 2882 void Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){ 2883 2884 const int numdof=NDOF2*NUMVERTICES; 2885 2886 int i; 2887 int* doflist=NULL; 2888 double vx,vy; 2889 double values[numdof]; 2890 GaussPenta* gauss=NULL; 2891 2892 /*Get dof list: */ 2893 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 2894 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2895 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2896 2897 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 2898 /*P1 element only for now*/ 2899 gauss=new GaussPenta(); 2900 for(i=0;i<NUMVERTICES;i++){ 2901 /*Recover vx and vy*/ 2902 gauss->GaussVertex(i); 2903 vx_input->GetParameterValue(&vx,gauss); 2904 vy_input->GetParameterValue(&vy,gauss); 2905 values[i*NDOF2+0]=vx; 2906 values[i*NDOF2+1]=vy; 2907 } 2908 2909 /*Add value to global vector*/ 2910 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 2911 2912 /*Free ressources:*/ 2913 delete gauss; 2914 xfree((void**)&doflist); 2915 } 2916 /*}}}*/ 2917 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/ 2918 void Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){ 2919 2920 const int numdof=NDOF1*NUMVERTICES; 2921 2922 int i; 2923 int* doflist=NULL; 2924 double vz; 2925 double values[numdof]; 2926 GaussPenta* gauss=NULL; 2927 2928 /*Get dof list: */ 2929 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 2930 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 2931 2932 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 2933 /*P1 element only for now*/ 2934 gauss=new GaussPenta(); 2935 for(i=0;i<NUMVERTICES;i++){ 2936 /*Recover vz */ 2937 gauss->GaussVertex(i); 2938 vz_input->GetParameterValue(&vz,gauss); 2939 values[i]=vz; 2940 } 2941 2942 /*Add value to global vector*/ 2943 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 2944 2945 /*Free ressources:*/ 2946 delete gauss; 2947 xfree((void**)&doflist); 2948 } 2949 /*}}}*/ 2950 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/ 2951 void Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){ 2952 2953 const int numdof=NDOF4*NUMVERTICES; 2954 2955 int i; 2956 int* doflist=NULL; 2957 double vx,vy,vz,p; 2958 double stokesreconditioning; 2959 double values[numdof]; 2960 GaussPenta *gauss; 2961 2962 /*Get dof list: */ 2963 GetDofList(&doflist,StokesApproximationEnum,GsetEnum); 2964 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2965 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2966 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 2967 Input* p_input =inputs->GetInput(PressureEnum); ISSMASSERT(p_input); 2968 2969 /*Recondition pressure: */ 2970 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 2971 2972 /*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */ 2973 /*P1 element only for now*/ 2974 gauss=new GaussPenta(); 2975 for(i=0;i<NUMVERTICES;i++){ 2976 gauss->GaussVertex(i); 2977 vx_input->GetParameterValue(&vx,gauss); 2978 vy_input->GetParameterValue(&vy,gauss); 2979 vz_input->GetParameterValue(&vz,gauss); 2980 p_input ->GetParameterValue(&p ,gauss); 2981 values[i*NDOF4+0]=vx; 2982 values[i*NDOF4+1]=vy; 2983 values[i*NDOF4+2]=vz; 2984 values[i*NDOF4+3]=p/stokesreconditioning; 2985 } 2986 2987 /*Add value to global vector*/ 2988 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 2989 2990 /*Free ressources:*/ 2991 delete gauss; 2992 xfree((void**)&doflist); 2993 } 2994 /*}}}*/ 2995 /*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/ 2996 void Penta::GetSolutionFromInputsThermal(Vec solution){ 2997 2998 const int numdof=NDOF1*NUMVERTICES; 2999 3000 int i; 3001 int* doflist=NULL; 3002 double values[numdof]; 3003 double temp; 3004 GaussPenta *gauss=NULL; 3005 3006 /*Get dof list: */ 3007 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 3008 Input* t_input=inputs->GetInput(TemperatureEnum); ISSMASSERT(t_input); 3009 3010 gauss=new GaussPenta(); 3011 for(i=0;i<NUMVERTICES;i++){ 3012 /*Recover temperature*/ 3013 gauss->GaussVertex(i); 3014 t_input->GetParameterValue(&temp,gauss); 3015 values[i]=temp; 3016 } 3017 3018 /*Add value to global vector*/ 3019 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 3020 3021 /*Free ressources:*/ 3022 delete gauss; 3023 xfree((void**)&doflist); 3024 } 3025 /*}}}*/ 3026 /*FUNCTION Penta::GetStabilizationParameter {{{1*/ 3027 double Penta::GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity){ 3028 /*Compute stabilization parameter*/ 3029 3030 double normu; 3031 double tau_parameter; 3032 3033 normu=pow(pow(u,2)+pow(v,2)+pow(w,2),0.5); 3034 if(normu*diameter/(3*2*thermalconductivity/(rho_ice*heatcapacity))<1){ 3035 tau_parameter=pow(diameter,2)/(3*2*2*thermalconductivity/(rho_ice*heatcapacity)); 3036 } 3037 else tau_parameter=diameter/(2*normu); 3038 3039 return tau_parameter; 3040 } 3041 /*}}}*/ 3042 /*FUNCTION Penta::GetStrainRate3dPattyn{{{1*/ 3043 void Penta::GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input){ 3044 /*Compute the 3d Blatter/PattynStrain Rate (5 components): 3045 * 3046 * epsilon=[exx eyy exy exz eyz] 3047 * 3048 * with exz=1/2 du/dz 3049 * eyz=1/2 dv/dz 3050 * 3051 * the contribution of vz is neglected 3052 */ 3053 3054 int i; 3055 double epsilonvx[5]; 3056 double epsilonvy[5]; 3057 3058 /*Check that both inputs have been found*/ 3059 if (!vx_input || !vy_input){ 3060 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input); 3061 } 3062 3063 /*Get strain rate assuming that epsilon has been allocated*/ 3064 vx_input->GetVxStrainRate3dPattyn(epsilonvx,xyz_list,gauss); 3065 vy_input->GetVyStrainRate3dPattyn(epsilonvy,xyz_list,gauss); 3066 3067 /*Sum all contributions*/ 3068 for(i=0;i<5;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]; 3069 } 3070 /*}}}*/ 3071 /*FUNCTION Penta::GetStrainRate3d{{{1*/ 3072 void Penta::GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input){ 3073 /*Compute the 3d Strain Rate (6 components): 3074 * 3075 * epsilon=[exx eyy ezz exy exz eyz] 3076 */ 3077 3078 int i; 3079 double epsilonvx[6]; 3080 double epsilonvy[6]; 3081 double epsilonvz[6]; 3082 3083 /*Check that both inputs have been found*/ 3084 if (!vx_input || !vy_input || !vz_input){ 3085 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p, vz: %p\n",vx_input,vy_input,vz_input); 3086 } 3087 3088 /*Get strain rate assuming that epsilon has been allocated*/ 3089 vx_input->GetVxStrainRate3d(epsilonvx,xyz_list,gauss); 3090 vy_input->GetVyStrainRate3d(epsilonvy,xyz_list,gauss); 3091 vz_input->GetVzStrainRate3d(epsilonvz,xyz_list,gauss); 3092 3093 /*Sum all contributions*/ 3094 for(i=0;i<6;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]+epsilonvz[i]; 3095 } 3096 /*}}}*/ 3097 /*FUNCTION Penta::GetUpperElement{{{1*/ 3098 Penta* Penta::GetUpperElement(void){ 3099 3100 Penta* upper_penta=NULL; 3101 3102 upper_penta=(Penta*)neighbors[1]; //first one under, second one above 3103 3104 return upper_penta; 1058 3105 } 1059 3106 /*}}}*/ … … 1076 3123 } 1077 3124 /*}}}*/ 1078 /*FUNCTION Penta::Gradj {{{1*/ 1079 void Penta::Gradj(Vec gradient,int control_type){ 1080 1081 /*If on water, skip grad (=0): */ 1082 if(IsOnWater())return; 1083 1084 if (control_type==DragCoefficientEnum){ 1085 GradjDrag(gradient); 1086 } 1087 else if (control_type==RheologyBbarEnum){ 1088 GradjB(gradient); 1089 } 1090 else ISSMERROR("control type %s not supported yet: ",EnumToString(control_type)); 3125 /*FUNCTION Penta::GetZcoord {{{1*/ 3126 double Penta::GetZcoord(GaussPenta* gauss){ 3127 3128 int i; 3129 double z; 3130 double xyz_list[NUMVERTICES][3]; 3131 double z_list[NUMVERTICES]; 3132 3133 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 3134 for(i=0;i<NUMVERTICES;i++) z_list[i]=xyz_list[i][2]; 3135 PentaRef::GetParameterValue(&z,z_list,gauss); 3136 3137 return z; 3138 } 3139 /*}}}*/ 3140 /*FUNCTION Penta::Id {{{1*/ 3141 int Penta::Id(void){ 3142 return id; 3143 } 3144 /*}}}*/ 3145 /*FUNCTION Penta::InputArtificialNoise{{{1*/ 3146 void Penta::InputArtificialNoise(int enum_type,double min,double max){ 3147 3148 Input* input=NULL; 3149 3150 /*Make a copy of the original input: */ 3151 input=(Input*)this->inputs->GetInput(enum_type); 3152 if(!input)ISSMERROR(" could not find old input with enum: %s",EnumToString(enum_type)); 3153 3154 /*ArtificialNoise: */ 3155 input->ArtificialNoise(min,max); 1091 3156 } 1092 3157 /*}}}*/ … … 1271 3336 } 1272 3337 /*}}}*/ 1273 /*FUNCTION Penta::InputArtificialNoise{{{1*/ 1274 void Penta::InputArtificialNoise(int enum_type,double min,double max){ 1275 1276 Input* input=NULL; 1277 1278 /*Make a copy of the original input: */ 1279 input=(Input*)this->inputs->GetInput(enum_type); 1280 if(!input)ISSMERROR(" could not find old input with enum: %s",EnumToString(enum_type)); 1281 1282 /*ArtificialNoise: */ 1283 input->ArtificialNoise(min,max); 3338 /*FUNCTION Penta::InputExtrude {{{1*/ 3339 void Penta::InputExtrude(int enum_type,int object_type){ 3340 3341 Penta *penta = NULL; 3342 Input *original_input = NULL; 3343 3344 /*Are we on the base, not on the surface?:*/ 3345 if(IsOnBed()){ 3346 /*OK, we are on bed. we will follow the steps: 3347 * 1: find input and extrude it. 3348 * 2: follow the upper element until we reach the surface 3349 * 3: for each element, we will add a copy of the extruded input*/ 3350 3351 /*Step1: Extrude the original input: */ 3352 if (object_type==ElementsEnum) 3353 original_input=(Input*)this->inputs->GetInput(enum_type); 3354 else if (object_type==MaterialsEnum) 3355 original_input=(Input*)matice->inputs->GetInput(enum_type); 3356 else 3357 ISSMERROR("object of type %s not supported yet",EnumToString(object_type)); 3358 if(!original_input) ISSMERROR("%s%s"," could not find input with enum:",EnumToString(enum_type)); 3359 original_input->Extrude(); 3360 3361 /*Stop if there is only one layer of element*/ 3362 if (this->IsOnSurface()) return; 3363 3364 /*Step 2: this input has been extruded for this element, now follow the upper element*/ 3365 penta=this; 3366 for(;;){ 3367 3368 /* get upper Penta*/ 3369 penta=penta->GetUpperElement(); 3370 ISSMASSERT(penta->Id()!=this->id); 3371 3372 /*Add input of the basal element to penta->inputs*/ 3373 Input* copy=NULL; 3374 copy=(Input*)original_input->copy(); 3375 if (object_type==ElementsEnum) 3376 penta->inputs->AddInput((Input*)copy); 3377 else if (object_type==MaterialsEnum) 3378 penta->matice->inputs->AddInput((Input*)copy); 3379 else 3380 ISSMERROR("object of type %s not supported yet",EnumToString(object_type)); 3381 3382 /*Stop if we have reached the surface*/ 3383 if (penta->IsOnSurface()) break; 3384 } 3385 } 3386 3387 return; 1284 3388 } 1285 3389 /*}}}*/ … … 1316 3420 } 1317 3421 /*}}}*/ 3422 /*FUNCTION Penta::InputUpdateFromConstant(bool value, int name);{{{1*/ 3423 void Penta::InputUpdateFromConstant(bool constant, int name){ 3424 3425 /*Check that name is an element input*/ 3426 if (!IsInput(name)) return; 3427 3428 /*update input*/ 3429 this->inputs->AddInput(new BoolInput(name,constant)); 3430 } 3431 /*}}}*/ 3432 /*FUNCTION Penta::InputUpdateFromConstant(double value, int name);{{{1*/ 3433 void Penta::InputUpdateFromConstant(double constant, int name){ 3434 /*Check that name is an element input*/ 3435 if (!IsInput(name)) return; 3436 3437 /*update input*/ 3438 this->inputs->AddInput(new DoubleInput(name,constant)); 3439 } 3440 /*}}}*/ 3441 /*FUNCTION Penta::InputUpdateFromConstant(int value, int name);{{{1*/ 3442 void Penta::InputUpdateFromConstant(int constant, int name){ 3443 /*Check that name is an element input*/ 3444 if (!IsInput(name)) return; 3445 3446 /*update input*/ 3447 this->inputs->AddInput(new IntInput(name,constant)); 3448 } 3449 /*}}}*/ 3450 /*FUNCTION Penta::InputUpdateFromIoModel {{{1*/ 3451 void Penta::InputUpdateFromIoModel(int index,IoModel* iomodel){ 3452 3453 /*Intermediaries*/ 3454 IssmInt i,j; 3455 int penta_vertex_ids[6]; 3456 double nodeinputs[6]; 3457 3458 /*Checks if debuging*/ 3459 /*{{{2*/ 3460 ISSMASSERT(iomodel->elements); 3461 /*}}}*/ 3462 3463 /*Recover vertices ids needed to initialize inputs*/ 3464 for(i=0;i<6;i++){ 3465 penta_vertex_ids[i]=(int)iomodel->elements[6*index+i]; //ids for vertices are in the elements array from Matlab 3466 } 3467 3468 //add as many inputs per element as requested: 3469 if (iomodel->thickness) { 3470 for(i=0;i<6;i++)nodeinputs[i]=iomodel->thickness[penta_vertex_ids[i]-1]; 3471 this->inputs->AddInput(new PentaVertexInput(ThicknessEnum,nodeinputs)); 3472 } 3473 if (iomodel->surface) { 3474 for(i=0;i<6;i++)nodeinputs[i]=iomodel->surface[penta_vertex_ids[i]-1]; 3475 this->inputs->AddInput(new PentaVertexInput(SurfaceEnum,nodeinputs)); 3476 } 3477 if (iomodel->bed) { 3478 for(i=0;i<6;i++)nodeinputs[i]=iomodel->bed[penta_vertex_ids[i]-1]; 3479 this->inputs->AddInput(new PentaVertexInput(BedEnum,nodeinputs)); 3480 } 3481 if (iomodel->drag_coefficient) { 3482 for(i=0;i<6;i++)nodeinputs[i]=iomodel->drag_coefficient[penta_vertex_ids[i]-1]; 3483 this->inputs->AddInput(new PentaVertexInput(DragCoefficientEnum,nodeinputs)); 3484 3485 if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index])); 3486 if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index])); 3487 this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type)); 3488 3489 } 3490 if (iomodel->melting_rate) { 3491 for(i=0;i<6;i++)nodeinputs[i]=iomodel->melting_rate[penta_vertex_ids[i]-1]/iomodel->yts; 3492 this->inputs->AddInput(new PentaVertexInput(MeltingRateEnum,nodeinputs)); 3493 } 3494 if (iomodel->accumulation_rate) { 3495 for(i=0;i<6;i++)nodeinputs[i]=iomodel->accumulation_rate[penta_vertex_ids[i]-1]/iomodel->yts; 3496 this->inputs->AddInput(new PentaVertexInput(AccumulationRateEnum,nodeinputs)); 3497 } 3498 if (iomodel->geothermalflux) { 3499 for(i=0;i<6;i++)nodeinputs[i]=iomodel->geothermalflux[penta_vertex_ids[i]-1]; 3500 this->inputs->AddInput(new PentaVertexInput(GeothermalFluxEnum,nodeinputs)); 3501 } 3502 if (iomodel->pressure) { 3503 for(i=0;i<6;i++)nodeinputs[i]=iomodel->pressure[penta_vertex_ids[i]-1]; 3504 this->inputs->AddInput(new PentaVertexInput(PressureEnum,nodeinputs)); 3505 } 3506 if (iomodel->temperature) { 3507 for(i=0;i<6;i++)nodeinputs[i]=iomodel->temperature[penta_vertex_ids[i]-1]; 3508 this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,nodeinputs)); 3509 } 3510 if (iomodel->dhdt) { 3511 for(i=0;i<6;i++)nodeinputs[i]=iomodel->dhdt[penta_vertex_ids[i]-1]/iomodel->yts; 3512 this->inputs->AddInput(new PentaVertexInput(DhDtEnum,nodeinputs)); 3513 } 3514 /*vx,vy and vz: */ 3515 if (iomodel->vx) { 3516 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vx[penta_vertex_ids[i]-1]/iomodel->yts; 3517 this->inputs->AddInput(new PentaVertexInput(VxEnum,nodeinputs)); 3518 this->inputs->AddInput(new PentaVertexInput(VxOldEnum,nodeinputs)); 3519 if(iomodel->qmu_analysis)this->inputs->AddInput(new PentaVertexInput(QmuVxEnum,nodeinputs)); 3520 } 3521 if (iomodel->vy) { 3522 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vy[penta_vertex_ids[i]-1]/iomodel->yts; 3523 this->inputs->AddInput(new PentaVertexInput(VyEnum,nodeinputs)); 3524 this->inputs->AddInput(new PentaVertexInput(VyOldEnum,nodeinputs)); 3525 if(iomodel->qmu_analysis)this->inputs->AddInput(new PentaVertexInput(QmuVyEnum,nodeinputs)); 3526 } 3527 if (iomodel->vz) { 3528 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vz[penta_vertex_ids[i]-1]/iomodel->yts; 3529 this->inputs->AddInput(new PentaVertexInput(VzEnum,nodeinputs)); 3530 this->inputs->AddInput(new PentaVertexInput(VzOldEnum,nodeinputs)); 3531 if(iomodel->qmu_analysis)this->inputs->AddInput(new PentaVertexInput(QmuVzEnum,nodeinputs)); 3532 } 3533 if (iomodel->vx_obs) { 3534 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vx_obs[penta_vertex_ids[i]-1]/iomodel->yts; 3535 this->inputs->AddInput(new PentaVertexInput(VxObsEnum,nodeinputs)); 3536 } 3537 if (iomodel->vy_obs) { 3538 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vy_obs[penta_vertex_ids[i]-1]/iomodel->yts; 3539 this->inputs->AddInput(new PentaVertexInput(VyObsEnum,nodeinputs)); 3540 } 3541 if (iomodel->vz_obs) { 3542 for(i=0;i<6;i++)nodeinputs[i]=iomodel->vz_obs[penta_vertex_ids[i]-1]/iomodel->yts; 3543 this->inputs->AddInput(new PentaVertexInput(VzObsEnum,nodeinputs)); 3544 } 3545 if (iomodel->weights) { 3546 for(i=0;i<6;i++)nodeinputs[i]=iomodel->weights[penta_vertex_ids[i]-1]; 3547 this->inputs->AddInput(new PentaVertexInput(WeightsEnum,nodeinputs)); 3548 } 3549 if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index])); 3550 if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index])); 3551 if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index])); 3552 if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index])); 3553 3554 /*time: */ 3555 this->inputs->AddInput(new DoubleInput(DtEnum,iomodel->dt*iomodel->yts)); 3556 3557 /*Control Inputs*/ 3558 if (iomodel->control_analysis && iomodel->control_type){ 3559 for(i=0;i<iomodel->num_control_type;i++){ 3560 switch((int)iomodel->control_type[i]){ 3561 case DhDtEnum: 3562 if (iomodel->dhdt){ 3563 for(j=0;j<6;j++)nodeinputs[j]=iomodel->dhdt[penta_vertex_ids[j]-1]/iomodel->yts; 3564 this->inputs->AddInput(new ControlInput(DhDtEnum,PentaVertexInputEnum,nodeinputs,i+1)); 3565 } 3566 break; 3567 case VxEnum: 3568 if (iomodel->vx){ 3569 for(j=0;j<6;j++)nodeinputs[j]=iomodel->vx[penta_vertex_ids[j]-1]/iomodel->yts; 3570 this->inputs->AddInput(new ControlInput(VxEnum,PentaVertexInputEnum,nodeinputs,i+1)); 3571 } 3572 break; 3573 case VyEnum: 3574 if (iomodel->vy){ 3575 for(j=0;j<6;j++)nodeinputs[j]=iomodel->vy[penta_vertex_ids[j]-1]/iomodel->yts; 3576 this->inputs->AddInput(new ControlInput(VyEnum,PentaVertexInputEnum,nodeinputs,i+1)); 3577 } 3578 break; 3579 case DragCoefficientEnum: 3580 if (iomodel->drag_coefficient){ 3581 for(j=0;j<6;j++)nodeinputs[j]=iomodel->drag_coefficient[penta_vertex_ids[j]-1]; 3582 this->inputs->AddInput(new ControlInput(DragCoefficientEnum,PentaVertexInputEnum,nodeinputs,i+1)); 3583 } 3584 break; 3585 case RheologyBbarEnum: 3586 /*Matice will take care of it*/ break; 3587 default: 3588 ISSMERROR("Control %s not implemented yet",EnumToString((int)iomodel->control_type[i])); 3589 } 3590 } 3591 } 3592 3593 //Need to know the type of approximation for this element 3594 if(iomodel->elements_type){ 3595 if (*(iomodel->elements_type+index)==MacAyealApproximationEnum){ 3596 this->inputs->AddInput(new IntInput(ApproximationEnum,MacAyealApproximationEnum)); 3597 } 3598 else if (*(iomodel->elements_type+index)==PattynApproximationEnum){ 3599 this->inputs->AddInput(new IntInput(ApproximationEnum,PattynApproximationEnum)); 3600 } 3601 else if (*(iomodel->elements_type+index)==MacAyealPattynApproximationEnum){ 3602 this->inputs->AddInput(new IntInput(ApproximationEnum,MacAyealPattynApproximationEnum)); 3603 } 3604 else if (*(iomodel->elements_type+index)==HutterApproximationEnum){ 3605 this->inputs->AddInput(new IntInput(ApproximationEnum,HutterApproximationEnum)); 3606 } 3607 else if (*(iomodel->elements_type+index)==StokesApproximationEnum){ 3608 this->inputs->AddInput(new IntInput(ApproximationEnum,StokesApproximationEnum)); 3609 } 3610 else if (*(iomodel->elements_type+index)==PattynStokesApproximationEnum){ 3611 this->inputs->AddInput(new IntInput(ApproximationEnum,PattynStokesApproximationEnum)); 3612 } 3613 else if (*(iomodel->elements_type+index)==NoneApproximationEnum){ 3614 this->inputs->AddInput(new IntInput(ApproximationEnum,NoneApproximationEnum)); 3615 } 3616 else{ 3617 ISSMERROR("Approximation type %s not supported yet",EnumToString((int)*(iomodel->elements_type+index))); 3618 } 3619 } 3620 3621 } 3622 /*}}}*/ 3623 /*FUNCTION Penta::InputUpdateFromSolution {{{1*/ 3624 void Penta::InputUpdateFromSolution(double* solution){ 3625 3626 int analysis_type; 3627 3628 /*retreive parameters: */ 3629 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 3630 3631 /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */ 3632 if (analysis_type==DiagnosticHorizAnalysisEnum){ 3633 InputUpdateFromSolutionDiagnosticHoriz( solution); 3634 } 3635 else if (analysis_type==DiagnosticHutterAnalysisEnum){ 3636 InputUpdateFromSolutionDiagnosticHutter( solution); 3637 } 3638 else if (analysis_type==DiagnosticVertAnalysisEnum){ 3639 InputUpdateFromSolutionDiagnosticVert( solution); 3640 } 3641 else if (analysis_type==AdjointHorizAnalysisEnum){ 3642 int approximation; 3643 inputs->GetParameterValue(&approximation,ApproximationEnum); 3644 if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){ 3645 InputUpdateFromSolutionAdjointStokes( solution); 3646 } 3647 else{ 3648 InputUpdateFromSolutionAdjointHoriz( solution); 3649 } 3650 } 3651 else if (analysis_type==BedSlopeXAnalysisEnum){ 3652 InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeXEnum); 3653 } 3654 else if (analysis_type==BedSlopeYAnalysisEnum){ 3655 InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeYEnum); 3656 } 3657 else if (analysis_type==SurfaceSlopeXAnalysisEnum){ 3658 InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeXEnum); 3659 } 3660 else if (analysis_type==SurfaceSlopeYAnalysisEnum){ 3661 InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeYEnum); 3662 } 3663 else if (analysis_type==PrognosticAnalysisEnum){ 3664 InputUpdateFromSolutionOneDofCollapsed(solution,ThicknessEnum); 3665 } 3666 else if (analysis_type==BalancedthicknessAnalysisEnum){ 3667 InputUpdateFromSolutionOneDofCollapsed(solution,ThicknessEnum); 3668 } 3669 else if (analysis_type==BalancedvelocitiesAnalysisEnum){ 3670 InputUpdateFromSolutionOneDofCollapsed(solution,VelEnum); 3671 } 3672 else if (analysis_type==ThermalAnalysisEnum){ 3673 InputUpdateFromSolutionThermal( solution); 3674 } 3675 else if (analysis_type==MeltingAnalysisEnum){ 3676 InputUpdateFromSolutionOneDof(solution,MeltingRateEnum); 3677 } 3678 else{ 3679 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumToString(analysis_type)); 3680 } 3681 } 3682 /*}}}*/ 3683 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHoriz {{{1*/ 3684 void Penta::InputUpdateFromSolutionDiagnosticHoriz(double* solution){ 3685 3686 int approximation; 3687 3688 /*Recover inputs*/ 3689 inputs->GetParameterValue(&approximation,ApproximationEnum); 3690 3691 /*MacAyeal, everything is done by the element on bed*/ 3692 if (approximation==MacAyealApproximationEnum){ 3693 if (!IsOnBed()){ 3694 /*Do nothing. Element on bed will take care of it*/ 3695 return; 3696 } 3697 else{ 3698 InputUpdateFromSolutionDiagnosticMacAyeal(solution); 3699 return; 3700 } 3701 } 3702 else if (approximation==PattynApproximationEnum){ 3703 InputUpdateFromSolutionDiagnosticPattyn(solution); 3704 } 3705 else if (approximation==PattynStokesApproximationEnum){ 3706 InputUpdateFromSolutionDiagnosticPattynStokes(solution); 3707 } 3708 else if (approximation==MacAyealStokesApproximationEnum){ 3709 InputUpdateFromSolutionDiagnosticMacAyealStokes(solution); 3710 } 3711 else if (approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){ 3712 InputUpdateFromSolutionDiagnosticStokes(solution); 3713 } 3714 else if (approximation==MacAyealPattynApproximationEnum){ 3715 InputUpdateFromSolutionDiagnosticMacAyealPattyn(solution); 3716 } 3717 } 3718 /*}}}*/ 3719 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyeal {{{1*/ 3720 void Penta::InputUpdateFromSolutionDiagnosticMacAyeal(double* solution){ 3721 3722 const int numdof=NDOF2*NUMVERTICES; 3723 3724 int i,dummy; 3725 double rho_ice,g; 3726 double values[numdof]; 3727 double vx[NUMVERTICES]; 3728 double vy[NUMVERTICES]; 3729 double vz[NUMVERTICES]; 3730 double vel[NUMVERTICES]; 3731 double pressure[NUMVERTICES]; 3732 double surface[NUMVERTICES]; 3733 double xyz_list[NUMVERTICES][3]; 3734 int *doflist = NULL; 3735 double *vz_ptr = NULL; 3736 Penta *penta = NULL; 3737 3738 /*Get dof list: */ 3739 GetDofList(&doflist,MacAyealApproximationEnum,GsetEnum); 3740 3741 /*Use the dof list to index into the solution vector: */ 3742 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 3743 3744 /*Ok, we have vx and vy in values, fill in vx and vy arrays and extrude */ 3745 for(i=0;i<3;i++){ 3746 vx[i] =values[i*NDOF2+0]; 3747 vy[i] =values[i*NDOF2+1]; 3748 vx[i+3]=vx[i]; 3749 vy[i+3]=vy[i]; 3750 } 3751 3752 /*Get parameters fro pressure computation*/ 3753 rho_ice=matpar->GetRhoIce(); 3754 g=matpar->GetG(); 3755 3756 /*Start looping over all elements above current element and update all inputs*/ 3757 penta=this; 3758 for(;;){ 3759 3760 /*Get node data: */ 3761 GetVerticesCoordinates(&xyz_list[0][0],penta->nodes,NUMVERTICES); 3762 3763 /*Now Compute vel*/ 3764 Input* vz_input=inputs->GetInput(VzEnum); 3765 if (vz_input){ 3766 if (vz_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum())); 3767 vz_input->GetValuesPtr(&vz_ptr,&dummy); 3768 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i]; 3769 } 3770 else{for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;} 3771 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 3772 3773 /*Now compute pressure*/ 3774 GetParameterListOnVertices(&surface[0],SurfaceEnum); 3775 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]); 3776 3777 /*Now, we have to move the previous Vx and Vy inputs to old 3778 * status, otherwise, we'll wipe them off: */ 3779 penta->inputs->ChangeEnum(VxEnum,VxOldEnum); 3780 penta->inputs->ChangeEnum(VyEnum,VyOldEnum); 3781 penta->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 3782 3783 /*Add vx and vy as inputs to the tria element: */ 3784 penta->inputs->AddInput(new PentaVertexInput(VxEnum,vx)); 3785 penta->inputs->AddInput(new PentaVertexInput(VyEnum,vy)); 3786 penta->inputs->AddInput(new PentaVertexInput(VelEnum,vel)); 3787 penta->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 3788 3789 /*Stop if we have reached the surface*/ 3790 if (penta->IsOnSurface()) break; 3791 3792 /* get upper Penta*/ 3793 penta=penta->GetUpperElement(); ISSMASSERT(penta->Id()!=this->id); 3794 } 3795 3796 /*Free ressources:*/ 3797 xfree((void**)&doflist); 3798 } 3799 /*}}}*/ 3800 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn {{{1*/ 3801 void Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn(double* solution){ 3802 3803 const int numdof=NDOF2*NUMVERTICES; 3804 const int numdof2d=NDOF2*NUMVERTICES2D; 3805 3806 int i,dummy; 3807 double rho_ice,g; 3808 double macayeal_values[numdof]; 3809 double pattyn_values[numdof]; 3810 double vx[NUMVERTICES]; 3811 double vy[NUMVERTICES]; 3812 double vz[NUMVERTICES]; 3813 double vel[NUMVERTICES]; 3814 double pressure[NUMVERTICES]; 3815 double surface[NUMVERTICES]; 3816 double xyz_list[NUMVERTICES][3]; 3817 int* doflistp = NULL; 3818 int* doflistm = NULL; 3819 double *vz_ptr = NULL; 3820 Penta *penta = NULL; 3821 3822 /*OK, we have to add results of this element for pattyn 3823 * and results from the penta at base for macayeal. Now recover results*/ 3824 penta=GetBasalElement(); 3825 3826 /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */ 3827 GetDofList(&doflistp,PattynApproximationEnum,GsetEnum); 3828 penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum); 3829 3830 /*Get node data: */ 3831 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 3832 3833 /*Use the dof list to index into the solution vector: */ 3834 for(i=0;i<numdof2d;i++){ 3835 pattyn_values[i]=solution[doflistp[i]]; 3836 macayeal_values[i]=solution[doflistm[i]]; 3837 } 3838 for(i=numdof2d;i<numdof;i++){ 3839 pattyn_values[i]=solution[doflistp[i]]; 3840 macayeal_values[i]=macayeal_values[i-numdof2d]; 3841 } 3842 3843 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 3844 for(i=0;i<NUMVERTICES;i++){ 3845 vx[i]=macayeal_values[i*NDOF2+0]+pattyn_values[i*NDOF2+0]; 3846 vy[i]=macayeal_values[i*NDOF2+1]+pattyn_values[i*NDOF2+1]; 3847 } 3848 3849 /*Get Vz*/ 3850 Input* vz_input=inputs->GetInput(VzEnum); 3851 if (vz_input){ 3852 if (vz_input->Enum()!=PentaVertexInputEnum){ 3853 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum())); 3854 } 3855 vz_input->GetValuesPtr(&vz_ptr,&dummy); 3856 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i]; 3857 } 3858 else{ 3859 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0; 3860 } 3861 3862 /*Now Compute vel*/ 3863 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 3864 3865 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 3866 *so the pressure is just the pressure at the z elevation: */ 3867 rho_ice=matpar->GetRhoIce(); 3868 g=matpar->GetG(); 3869 GetParameterListOnVertices(&surface[0],SurfaceEnum); 3870 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]); 3871 3872 /*Now, we have to move the previous Vx and Vy inputs to old 3873 * status, otherwise, we'll wipe them off: */ 3874 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 3875 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 3876 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 3877 3878 /*Add vx and vy as inputs to the tria element: */ 3879 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx)); 3880 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy)); 3881 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel)); 3882 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 3883 3884 /*Free ressources:*/ 3885 xfree((void**)&doflistp); 3886 xfree((void**)&doflistm); 3887 } 3888 /*}}}*/ 3889 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes {{{1*/ 3890 void Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes(double* solution){ 3891 3892 const int numdofm=NDOF2*NUMVERTICES; 3893 const int numdofs=NDOF4*NUMVERTICES; 3894 const int numdof2d=NDOF2*NUMVERTICES2D; 3895 3896 int i,dummy; 3897 double stokesreconditioning; 3898 double macayeal_values[numdofm]; 3899 double stokes_values[numdofs]; 3900 double vx[NUMVERTICES]; 3901 double vy[NUMVERTICES]; 3902 double vz[NUMVERTICES]; 3903 double vzmacayeal[NUMVERTICES]; 3904 double vzstokes[NUMVERTICES]; 3905 double vel[NUMVERTICES]; 3906 double pressure[NUMVERTICES]; 3907 double xyz_list[NUMVERTICES][3]; 3908 int* doflistm = NULL; 3909 int* doflists = NULL; 3910 double *vzmacayeal_ptr = NULL; 3911 Penta *penta = NULL; 3912 3913 /*OK, we have to add results of this element for macayeal 3914 * and results from the penta at base for macayeal. Now recover results*/ 3915 penta=GetBasalElement(); 3916 3917 /*Get dof listof this element (macayeal dofs) and of the penta at base (macayeal dofs): */ 3918 penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum); 3919 GetDofList(&doflists,StokesApproximationEnum,GsetEnum); 3920 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 3921 3922 /*Get node data: */ 3923 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 3924 3925 /*Use the dof list to index into the solution vector: */ 3926 for(i=0;i<numdof2d;i++){ 3927 macayeal_values[i]=solution[doflistm[i]]; 3928 macayeal_values[i+numdof2d]=solution[doflistm[i]]; 3929 } 3930 for(i=0;i<numdofs;i++){ 3931 stokes_values[i]=solution[doflists[i]]; 3932 } 3933 3934 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 3935 for(i=0;i<NUMVERTICES;i++){ 3936 vx[i]=stokes_values[i*NDOF4+0]+macayeal_values[i*NDOF2+0]; 3937 vy[i]=stokes_values[i*NDOF4+1]+macayeal_values[i*NDOF2+1]; 3938 vzstokes[i]=stokes_values[i*NDOF4+2]; 3939 pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning; 3940 } 3941 3942 /*Get Vz*/ 3943 Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum); 3944 if (vzmacayeal_input){ 3945 if (vzmacayeal_input->Enum()!=PentaVertexInputEnum){ 3946 ISSMERROR("Cannot compute Vel as VzMacAyeal is of type %s",EnumToString(vzmacayeal_input->Enum())); 3947 } 3948 vzmacayeal_input->GetValuesPtr(&vzmacayeal_ptr,&dummy); 3949 for(i=0;i<NUMVERTICES;i++) vzmacayeal[i]=vzmacayeal_ptr[i]; 3950 } 3951 else{ 3952 ISSMERROR("Cannot update solution as VzMacAyeal is not present"); 3953 } 3954 3955 /*Now Compute vel*/ 3956 for(i=0;i<NUMVERTICES;i++) { 3957 vz[i]=vzmacayeal[i]+vzstokes[i]; 3958 vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 3959 } 3960 3961 /*Now, we have to move the previous Vx and Vy inputs to old 3962 * status, otherwise, we'll wipe them off: */ 3963 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 3964 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 3965 this->inputs->ChangeEnum(VzEnum,VzOldEnum); 3966 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 3967 3968 /*Add vx and vy as inputs to the tria element: */ 3969 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx)); 3970 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy)); 3971 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz)); 3972 this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes)); 3973 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel)); 3974 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 3975 3976 /*Free ressources:*/ 3977 xfree((void**)&doflistm); 3978 xfree((void**)&doflists); 3979 } 3980 /*}}}*/ 3981 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattyn {{{1*/ 3982 void Penta::InputUpdateFromSolutionDiagnosticPattyn(double* solution){ 3983 3984 const int numdof=NDOF2*NUMVERTICES; 3985 3986 int i,dummy; 3987 double rho_ice,g; 3988 double values[numdof]; 3989 double vx[NUMVERTICES]; 3990 double vy[NUMVERTICES]; 3991 double vz[NUMVERTICES]; 3992 double vel[NUMVERTICES]; 3993 double pressure[NUMVERTICES]; 3994 double surface[NUMVERTICES]; 3995 double xyz_list[NUMVERTICES][3]; 3996 int* doflist = NULL; 3997 double *vz_ptr = NULL; 3998 3999 /*Get dof list: */ 4000 GetDofList(&doflist,PattynApproximationEnum,GsetEnum); 4001 4002 /*Get node data: */ 4003 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 4004 4005 /*Use the dof list to index into the solution vector: */ 4006 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4007 4008 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4009 for(i=0;i<NUMVERTICES;i++){ 4010 vx[i]=values[i*NDOF2+0]; 4011 vy[i]=values[i*NDOF2+1]; 4012 } 4013 4014 /*Get Vz*/ 4015 Input* vz_input=inputs->GetInput(VzEnum); 4016 if (vz_input){ 4017 if (vz_input->Enum()!=PentaVertexInputEnum){ 4018 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum())); 4019 } 4020 vz_input->GetValuesPtr(&vz_ptr,&dummy); 4021 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i]; 4022 } 4023 else{ 4024 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0; 4025 } 4026 4027 /*Now Compute vel*/ 4028 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 4029 4030 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 4031 *so the pressure is just the pressure at the z elevation: */ 4032 rho_ice=matpar->GetRhoIce(); 4033 g=matpar->GetG(); 4034 GetParameterListOnVertices(&surface[0],SurfaceEnum); 4035 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]); 4036 4037 /*Now, we have to move the previous Vx and Vy inputs to old 4038 * status, otherwise, we'll wipe them off: */ 4039 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 4040 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 4041 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 4042 4043 /*Add vx and vy as inputs to the tria element: */ 4044 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx)); 4045 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy)); 4046 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel)); 4047 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 4048 4049 /*Free ressources:*/ 4050 xfree((void**)&doflist); 4051 } 4052 /*}}}*/ 4053 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattynStokes {{{1*/ 4054 void Penta::InputUpdateFromSolutionDiagnosticPattynStokes(double* solution){ 4055 4056 const int numdofp=NDOF2*NUMVERTICES; 4057 const int numdofs=NDOF4*NUMVERTICES; 4058 4059 int i,dummy; 4060 double pattyn_values[numdofp]; 4061 double stokes_values[numdofs]; 4062 double vx[NUMVERTICES]; 4063 double vy[NUMVERTICES]; 4064 double vz[NUMVERTICES]; 4065 double vzpattyn[NUMVERTICES]; 4066 double vzstokes[NUMVERTICES]; 4067 double vel[NUMVERTICES]; 4068 double pressure[NUMVERTICES]; 4069 double xyz_list[NUMVERTICES][3]; 4070 double stokesreconditioning; 4071 int* doflistp = NULL; 4072 int* doflists = NULL; 4073 double *vzpattyn_ptr = NULL; 4074 Penta *penta = NULL; 4075 4076 /*OK, we have to add results of this element for pattyn 4077 * and results from the penta at base for macayeal. Now recover results*/ 4078 penta=GetBasalElement(); 4079 4080 /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */ 4081 GetDofList(&doflistp,PattynApproximationEnum,GsetEnum); 4082 GetDofList(&doflists,StokesApproximationEnum,GsetEnum); 4083 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 4084 4085 /*Get node data: */ 4086 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 4087 4088 /*Use the dof list to index into the solution vector: */ 4089 for(i=0;i<numdofp;i++) pattyn_values[i]=solution[doflistp[i]]; 4090 for(i=0;i<numdofs;i++) stokes_values[i]=solution[doflists[i]]; 4091 4092 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4093 for(i=0;i<NUMVERTICES;i++){ 4094 vx[i]=stokes_values[i*NDOF4+0]+pattyn_values[i*NDOF2+0]; 4095 vy[i]=stokes_values[i*NDOF4+1]+pattyn_values[i*NDOF2+1]; 4096 vzstokes[i]=stokes_values[i*NDOF4+2]; 4097 pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning; 4098 } 4099 4100 /*Get Vz*/ 4101 Input* vzpattyn_input=inputs->GetInput(VzPattynEnum); 4102 if (vzpattyn_input){ 4103 if (vzpattyn_input->Enum()!=PentaVertexInputEnum){ 4104 ISSMERROR("Cannot compute Vel as VzPattyn is of type %s",EnumToString(vzpattyn_input->Enum())); 4105 } 4106 vzpattyn_input->GetValuesPtr(&vzpattyn_ptr,&dummy); 4107 for(i=0;i<NUMVERTICES;i++) vzpattyn[i]=vzpattyn_ptr[i]; 4108 } 4109 else{ 4110 ISSMERROR("Cannot update solution as VzPattyn is not present"); 4111 } 4112 4113 /*Now Compute vel*/ 4114 for(i=0;i<NUMVERTICES;i++) { 4115 vz[i]=vzpattyn[i]+vzstokes[i]; 4116 vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 4117 } 4118 4119 /*Now, we have to move the previous Vx and Vy inputs to old 4120 * status, otherwise, we'll wipe them off: */ 4121 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 4122 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 4123 this->inputs->ChangeEnum(VzEnum,VzOldEnum); 4124 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 4125 4126 /*Add vx and vy as inputs to the tria element: */ 4127 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx)); 4128 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy)); 4129 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz)); 4130 this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes)); 4131 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel)); 4132 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 4133 4134 /*Free ressources:*/ 4135 xfree((void**)&doflistp); 4136 xfree((void**)&doflists); 4137 } 4138 /*}}}*/ 4139 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHutter {{{1*/ 4140 void Penta::InputUpdateFromSolutionDiagnosticHutter(double* solution){ 4141 4142 const int numdof=NDOF2*NUMVERTICES; 4143 4144 int i,dummy; 4145 double rho_ice,g; 4146 double values[numdof]; 4147 double vx[NUMVERTICES]; 4148 double vy[NUMVERTICES]; 4149 double vz[NUMVERTICES]; 4150 double vel[NUMVERTICES]; 4151 double pressure[NUMVERTICES]; 4152 double surface[NUMVERTICES]; 4153 double xyz_list[NUMVERTICES][3]; 4154 int* doflist = NULL; 4155 double* vz_ptr = NULL; 4156 4157 /*Get dof list: */ 4158 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 4159 4160 /*Get node data: */ 4161 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 4162 4163 /*Use the dof list to index into the solution vector: */ 4164 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4165 4166 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4167 for(i=0;i<NUMVERTICES;i++){ 4168 vx[i]=values[i*NDOF2+0]; 4169 vy[i]=values[i*NDOF2+1]; 4170 } 4171 4172 /*Get Vz*/ 4173 Input* vz_input=inputs->GetInput(VzEnum); 4174 if (vz_input){ 4175 if (vz_input->Enum()!=PentaVertexInputEnum){ 4176 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum())); 4177 } 4178 vz_input->GetValuesPtr(&vz_ptr,&dummy); 4179 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i]; 4180 } 4181 else{ 4182 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0; 4183 } 4184 4185 /*Now Compute vel*/ 4186 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 4187 4188 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 4189 *so the pressure is just the pressure at the z elevation: */ 4190 rho_ice=matpar->GetRhoIce(); 4191 g=matpar->GetG(); 4192 GetParameterListOnVertices(&surface[0],SurfaceEnum); 4193 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]); 4194 4195 /*Now, we have to move the previous Vx and Vy inputs to old 4196 * status, otherwise, we'll wipe them off: */ 4197 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 4198 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 4199 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 4200 4201 /*Add vx and vy as inputs to the tria element: */ 4202 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx)); 4203 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy)); 4204 this->inputs->AddInput(new TriaVertexInput(VelEnum,vel)); 4205 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 4206 4207 /*Free ressources:*/ 4208 xfree((void**)&doflist); 4209 } 4210 /*}}}*/ 4211 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticVert {{{1*/ 4212 void Penta::InputUpdateFromSolutionDiagnosticVert(double* solution){ 4213 4214 const int numdof=NDOF1*NUMVERTICES; 4215 4216 int i,dummy; 4217 int approximation; 4218 double rho_ice,g; 4219 double values[numdof]; 4220 double vx[NUMVERTICES]; 4221 double vy[NUMVERTICES]; 4222 double vz[NUMVERTICES]; 4223 double vzmacayeal[NUMVERTICES]; 4224 double vzpattyn[NUMVERTICES]; 4225 double vzstokes[NUMVERTICES]; 4226 double vel[NUMVERTICES]; 4227 double pressure[NUMVERTICES]; 4228 double surface[NUMVERTICES]; 4229 double xyz_list[NUMVERTICES][3]; 4230 int* doflist = NULL; 4231 double* vx_ptr = NULL; 4232 double* vy_ptr = NULL; 4233 double* vzstokes_ptr = NULL; 4234 4235 4236 /*Get the approximation and do nothing if the element in Stokes or None*/ 4237 inputs->GetParameterValue(&approximation,ApproximationEnum); 4238 if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){ 4239 return; 4240 } 4241 4242 /*Get dof list and vertices coordinates: */ 4243 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 4244 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 4245 4246 /*Use the dof list to index into the solution vector vz: */ 4247 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4248 for(i=0;i<NUMVERTICES;i++) vz[i]=values[i*NDOF1+0]; 4249 4250 /*Get Vx and Vy*/ 4251 Input* vx_input=inputs->GetInput(VxEnum); 4252 if (vx_input){ 4253 if (vx_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as Vx is of type %s",EnumToString(vx_input->Enum())); 4254 vx_input->GetValuesPtr(&vx_ptr,&dummy); 4255 for(i=0;i<NUMVERTICES;i++) vx[i]=vx_ptr[i]; 4256 } 4257 else for(i=0;i<NUMVERTICES;i++) vx[i]=0.0; 4258 4259 Input* vy_input=inputs->GetInput(VyEnum); 4260 if (vy_input){ 4261 if (vy_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as Vy is of type %s",EnumToString(vy_input->Enum())); 4262 vy_input->GetValuesPtr(&vy_ptr,&dummy); 4263 for(i=0;i<NUMVERTICES;i++) vy[i]=vy_ptr[i]; 4264 } 4265 else for(i=0;i<NUMVERTICES;i++) vy[i]=0.0; 4266 4267 /*Do some modifications if we actually have a PattynStokes or MacAyealStokes element*/ 4268 if(approximation==PattynStokesApproximationEnum){ 4269 Input* vzstokes_input=inputs->GetInput(VzStokesEnum); 4270 if (vzstokes_input){ 4271 if (vzstokes_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as VzStokes is of type %s",EnumToString(vy_input->Enum())); 4272 vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy); 4273 for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i]; 4274 } 4275 else ISSMERROR("Cannot compute Vz as VzStokes in not present in PattynStokes element"); 4276 for(i=0;i<NUMVERTICES;i++){ 4277 vzpattyn[i]=vz[i]; 4278 vz[i]=vzpattyn[i]+vzstokes[i]; 4279 } 4280 } 4281 else if(approximation==MacAyealStokesApproximationEnum){ 4282 Input* vzstokes_input=inputs->GetInput(VzStokesEnum); 4283 if (vzstokes_input){ 4284 if (vzstokes_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as VzStokes is of type %s",EnumToString(vy_input->Enum())); 4285 vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy); 4286 for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i]; 4287 } 4288 else ISSMERROR("Cannot compute Vz as VzStokes in not present in MacAyealStokes element"); 4289 for(i=0;i<NUMVERTICES;i++){ 4290 vzmacayeal[i]=vz[i]; 4291 vz[i]=vzmacayeal[i]+vzstokes[i]; 4292 } 4293 } 4294 4295 /*Now Compute vel*/ 4296 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 4297 4298 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 4299 *so the pressure is just the pressure at the z elevation: except it this is a PattynStokes element */ 4300 if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){ 4301 rho_ice=matpar->GetRhoIce(); 4302 g=matpar->GetG(); 4303 GetParameterListOnVertices(&surface[0],SurfaceEnum); 4304 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]); 4305 } 4306 4307 /*Now, we have to move the previous Vz inputs to old 4308 * status, otherwise, we'll wipe them off and add the new inputs: */ 4309 this->inputs->ChangeEnum(VzEnum,VzOldEnum); 4310 4311 if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){ 4312 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 4313 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 4314 } 4315 else if(approximation==PattynStokesApproximationEnum){ 4316 this->inputs->AddInput(new PentaVertexInput(VzPattynEnum,vzpattyn)); 4317 } 4318 else if(approximation==MacAyealStokesApproximationEnum){ 4319 this->inputs->AddInput(new PentaVertexInput(VzMacAyealEnum,vzpattyn)); 4320 } 4321 4322 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz)); 4323 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel)); 4324 4325 /*Free ressources:*/ 4326 xfree((void**)&doflist); 4327 } 4328 /*}}}*/ 4329 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticStokes {{{1*/ 4330 void Penta::InputUpdateFromSolutionDiagnosticStokes(double* solution){ 4331 4332 const int numdof=NDOF4*NUMVERTICES; 4333 4334 int i; 4335 double values[numdof]; 4336 double vx[NUMVERTICES]; 4337 double vy[NUMVERTICES]; 4338 double vz[NUMVERTICES]; 4339 double vel[NUMVERTICES]; 4340 double pressure[NUMVERTICES]; 4341 double stokesreconditioning; 4342 int* doflist=NULL; 4343 4344 /*Get dof list: */ 4345 GetDofList(&doflist,StokesApproximationEnum,GsetEnum); 4346 4347 /*Use the dof list to index into the solution vector: */ 4348 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4349 4350 /*Ok, we have vx and vy in values, fill in all arrays: */ 4351 for(i=0;i<NUMVERTICES;i++){ 4352 vx[i]=values[i*NDOF4+0]; 4353 vy[i]=values[i*NDOF4+1]; 4354 vz[i]=values[i*NDOF4+2]; 4355 pressure[i]=values[i*NDOF4+3]; 4356 } 4357 4358 /*Recondition pressure and compute vel: */ 4359 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 4360 for(i=0;i<NUMVERTICES;i++) pressure[i]=pressure[i]*stokesreconditioning; 4361 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 4362 4363 /*Now, we have to move the previous inputs to old 4364 * status, otherwise, we'll wipe them off: */ 4365 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 4366 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 4367 this->inputs->ChangeEnum(VzEnum,VzOldEnum); 4368 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 4369 4370 /*Add vx and vy as inputs to the tria element: */ 4371 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx)); 4372 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy)); 4373 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz)); 4374 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel)); 4375 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure)); 4376 4377 /*Free ressources:*/ 4378 xfree((void**)&doflist); 4379 } 4380 /*}}}*/ 4381 /*FUNCTION Penta::InputUpdateFromSolutionAdjointStokes {{{1*/ 4382 void Penta::InputUpdateFromSolutionAdjointStokes(double* solution){ 4383 4384 const int numdof=NDOF4*NUMVERTICES; 4385 4386 int i; 4387 double values[numdof]; 4388 double lambdax[NUMVERTICES]; 4389 double lambday[NUMVERTICES]; 4390 double lambdaz[NUMVERTICES]; 4391 double lambdap[NUMVERTICES]; 4392 int* doflist=NULL; 4393 4394 /*Get dof list: */ 4395 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 4396 4397 /*Use the dof list to index into the solution vector: */ 4398 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4399 4400 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4401 for(i=0;i<NUMVERTICES;i++){ 4402 lambdax[i]=values[i*NDOF4+0]; 4403 lambday[i]=values[i*NDOF4+1]; 4404 lambdaz[i]=values[i*NDOF4+2]; 4405 lambdap[i]=values[i*NDOF4+3]; 4406 } 4407 4408 /*Add vx and vy as inputs to the tria element: */ 4409 this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax)); 4410 this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday)); 4411 this->inputs->AddInput(new PentaVertexInput(AdjointzEnum,lambdaz)); 4412 this->inputs->AddInput(new PentaVertexInput(AdjointpEnum,lambdap)); 4413 4414 /*Free ressources:*/ 4415 xfree((void**)&doflist); 4416 } 4417 /*}}}*/ 4418 /*FUNCTION Penta::InputUpdateFromSolutionAdjointHoriz {{{1*/ 4419 void Penta::InputUpdateFromSolutionAdjointHoriz(double* solution){ 4420 4421 const int numdof=NDOF2*NUMVERTICES; 4422 4423 int i; 4424 double values[numdof]; 4425 double lambdax[NUMVERTICES]; 4426 double lambday[NUMVERTICES]; 4427 int* doflist=NULL; 4428 4429 /*Get dof list: */ 4430 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 4431 4432 /*Use the dof list to index into the solution vector: */ 4433 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4434 4435 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4436 for(i=0;i<NUMVERTICES;i++){ 4437 lambdax[i]=values[i*NDOF2+0]; 4438 lambday[i]=values[i*NDOF2+1]; 4439 } 4440 4441 /*Add vx and vy as inputs to the tria element: */ 4442 this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax)); 4443 this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday)); 4444 4445 /*Free ressources:*/ 4446 xfree((void**)&doflist); 4447 } 4448 /*}}}*/ 4449 /*FUNCTION Penta::InputUpdateFromSolutionThermal {{{1*/ 4450 void Penta::InputUpdateFromSolutionThermal(double* solution){ 4451 4452 const int numdof=NDOF1*NUMVERTICES; 4453 4454 bool converged; 4455 int i; 4456 double values[numdof]; 4457 double B[numdof]; 4458 double B_average; 4459 int* doflist=NULL; 4460 4461 /*Get dof list: */ 4462 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 4463 4464 /*Use the dof list to index into the solution vector: */ 4465 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4466 4467 this->inputs->GetParameterValue(&converged,ConvergedEnum); 4468 if(converged){ 4469 this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,values)); 4470 4471 /*Update Rheology only if convreged (we must make sure that the temperature is below melting point 4472 * otherwise the rheology could be negative*/ 4473 B_average=Paterson((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0); 4474 for(i=0;i<numdof;i++) B[i]=B_average; 4475 this->matice->inputs->AddInput(new PentaVertexInput(RheologyBEnum,B)); 4476 } 4477 else{ 4478 this->inputs->AddInput(new PentaVertexInput(TemporaryTemperatureEnum,values)); 4479 } 4480 4481 /*Free ressources:*/ 4482 xfree((void**)&doflist); 4483 } 4484 /*}}}*/ 4485 /*FUNCTION Penta::InputUpdateFromSolutionOneDof{{{1*/ 4486 void Penta::InputUpdateFromSolutionOneDof(double* solution,int enum_type){ 4487 4488 const int numdof = NDOF1*NUMVERTICES; 4489 4490 double values[numdof]; 4491 int* doflist=NULL; 4492 4493 /*Get dof list: */ 4494 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 4495 4496 /*Use the dof list to index into the solution vector: */ 4497 for(int i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 4498 4499 /*Add input to the element: */ 4500 this->inputs->AddInput(new PentaVertexInput(enum_type,values)); 4501 4502 /*Free ressources:*/ 4503 xfree((void**)&doflist); 4504 } 4505 /*}}}*/ 4506 /*FUNCTION Penta::InputUpdateFromSolutionOneDofCollpased{{{1*/ 4507 void Penta::InputUpdateFromSolutionOneDofCollapsed(double* solution,int enum_type){ 4508 4509 const int numdof = NDOF1*NUMVERTICES; 4510 const int numdof2d = NDOF1*NUMVERTICES2D; 4511 4512 double values[numdof]; 4513 int* doflist = NULL; 4514 Penta *penta = NULL; 4515 4516 /*If not on bed, return*/ 4517 if (!IsOnBed()) return; 4518 4519 /*Get dof list: */ 4520 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 4521 4522 /*Use the dof list to index into the solution vector and extrude it */ 4523 for(int i=0;i<numdof2d;i++){ 4524 values[i] =solution[doflist[i]]; 4525 values[i+numdof2d]=values[i]; 4526 } 4527 4528 /*Start looping over all elements above current element and update all inputs*/ 4529 penta=this; 4530 for(;;){ 4531 /*Add input to the element: */ 4532 penta->inputs->AddInput(new PentaVertexInput(enum_type,values)); 4533 4534 /*Stop if we have reached the surface*/ 4535 if (penta->IsOnSurface()) break; 4536 4537 /* get upper Penta*/ 4538 penta=penta->GetUpperElement(); ISSMASSERT(penta->Id()!=this->id); 4539 } 4540 4541 /*Free ressources:*/ 4542 xfree((void**)&doflist); 4543 } 4544 /*}}}*/ 4545 /*FUNCTION Penta::InputUpdateFromVector(double* vector, int name, int type);{{{1*/ 4546 void Penta::InputUpdateFromVector(double* vector, int name, int type){ 4547 4548 /*Check that name is an element input*/ 4549 if (!IsInput(name)) return; 4550 4551 /*Penta update B in InputUpdateFromSolutionThermal, so don't look for B update here.*/ 4552 4553 switch(type){ 4554 4555 case VertexEnum: 4556 4557 /*New PentaVertexInpu*/ 4558 double values[6]; 4559 4560 /*Get values on the 6 vertices*/ 4561 for (int i=0;i<6;i++){ 4562 values[i]=vector[this->nodes[i]->GetVertexDof()]; 4563 } 4564 4565 /*update input*/ 4566 this->inputs->AddInput(new PentaVertexInput(name,values)); 4567 return; 4568 4569 default: 4570 4571 ISSMERROR("type %i (%s) not implemented yet",type,EnumToString(type)); 4572 } 4573 } 4574 /*}}}*/ 4575 /*FUNCTION Penta::InputUpdateFromVector(int* vector, int name, int type);{{{1*/ 4576 void Penta::InputUpdateFromVector(int* vector, int name, int type){ 4577 ISSMERROR(" not supported yet!"); 4578 } 4579 /*}}}*/ 4580 /*FUNCTION Penta::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/ 4581 void Penta::InputUpdateFromVector(bool* vector, int name, int type){ 4582 ISSMERROR(" not supported yet!"); 4583 } 4584 /*}}}*/ 4585 /*FUNCTION Penta::InputUpdateFromVectorDakota(double* vector, int name, int type);{{{1*/ 4586 void Penta::InputUpdateFromVectorDakota(double* vector, int name, int type){ 4587 ISSMERROR(" not supported yet!"); 4588 } 4589 /*}}}*/ 4590 /*FUNCTION Penta::InputUpdateFromVectorDakota(int* vector, int name, int type);{{{1*/ 4591 void Penta::InputUpdateFromVectorDakota(int* vector, int name, int type){ 4592 ISSMERROR(" not supported yet!"); 4593 } 4594 /*}}}*/ 4595 /*FUNCTION Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type);{{{1*/ 4596 void Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type){ 4597 ISSMERROR(" not supported yet!"); 4598 } 4599 /*}}}*/ 4600 /*FUNCTION Penta::IsOnBed{{{1*/ 4601 bool Penta::IsOnBed(void){ 4602 4603 bool onbed; 4604 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 4605 return onbed; 4606 } 4607 /*}}}*/ 4608 /*FUNCTION Penta::IsInput{{{1*/ 4609 bool Penta::IsInput(int name){ 4610 if ( 4611 name==ThicknessEnum || 4612 name==SurfaceEnum || 4613 name==BedEnum || 4614 name==DtEnum || 4615 name==SurfaceSlopeXEnum || 4616 name==SurfaceSlopeYEnum || 4617 name==MeltingRateEnum || 4618 name==AccumulationRateEnum || 4619 name==GeothermalFluxEnum || 4620 name==SurfaceAreaEnum|| 4621 name==PressureEnum || 4622 name==VxEnum || 4623 name==VyEnum || 4624 name==VzEnum || 4625 name==VxObsEnum || 4626 name==VyObsEnum || 4627 name==VzObsEnum || 4628 name==TemperatureEnum || 4629 name==CmResponseEnum || 4630 name==DragCoefficientEnum || 4631 name==GradientEnum || 4632 name==OldGradientEnum || 4633 name==ConvergedEnum 4634 ) { 4635 return true; 4636 } 4637 else return false; 4638 } 4639 /*}}}*/ 4640 /*FUNCTION Penta::IsOnShelf {{{1*/ 4641 bool Penta::IsOnShelf(){ 4642 4643 bool onshelf; 4644 inputs->GetParameterValue(&onshelf,ElementOnIceShelfEnum); 4645 return onshelf; 4646 } 4647 /*}}}*/ 4648 /*FUNCTION Penta::IsOnSurface{{{1*/ 4649 bool Penta::IsOnSurface(void){ 4650 4651 bool onsurface; 4652 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum); 4653 return onsurface; 4654 } 4655 /*}}}*/ 4656 /*FUNCTION Penta::IsOnWater {{{1*/ 4657 bool Penta::IsOnWater(){ 4658 4659 bool onwater; 4660 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 4661 return onwater; 4662 } 4663 /*}}}*/ 1318 4664 /*FUNCTION Penta::MassFlux {{{1*/ 1319 4665 double Penta::MassFlux( double* segment,bool process_units){ … … 1413 4759 } 1414 4760 /*}}}*/ 4761 /*FUNCTION Penta::MinEdgeLength{{{1*/ 4762 double Penta::MinEdgeLength(double xyz_list[6][3]){ 4763 /*Return the minimum lenght of the nine egdes of the penta*/ 4764 4765 int i,node0,node1; 4766 int edges[9][2]={{0,1},{0,2},{1,2},{3,4},{3,5},{4,5},{0,3},{1,4},{2,5}}; //list of the nine edges 4767 double length; 4768 double minlength=-1; 4769 4770 for(i=0;i<9;i++){ 4771 /*Find the two nodes for this edge*/ 4772 node0=edges[i][0]; 4773 node1=edges[i][1]; 4774 4775 /*Compute the length of this edge and compare it to the minimal length*/ 4776 length=pow(pow(xyz_list[node0][0]-xyz_list[node1][0],2.0)+pow(xyz_list[node0][1]-xyz_list[node1][1],2.0)+pow(xyz_list[node0][2]-xyz_list[node1][2],2.0),0.5); 4777 if(length<minlength || minlength<0) minlength=length; 4778 } 4779 4780 return minlength; 4781 } 4782 /*}}}*/ 1415 4783 /*FUNCTION Penta::MinVel{{{1*/ 1416 4784 void Penta::MinVel(double* pminvel, bool process_units){ … … 1463 4831 /*Assign output pointers:*/ 1464 4832 *pminvz=minvz; 4833 } 4834 /*}}}*/ 4835 /*FUNCTION Penta::MyRank {{{1*/ 4836 int Penta::MyRank(void){ 4837 extern int my_rank; 4838 return my_rank; 4839 } 4840 /*}}}*/ 4841 /*FUNCTION Penta::PatchFill{{{1*/ 4842 void Penta::PatchFill(int* pcount, Patch* patch){ 4843 4844 int i,count; 4845 int vertices_ids[6]; 4846 4847 /*recover pointer: */ 4848 count=*pcount; 4849 4850 /*will be needed later: */ 4851 for(i=0;i<6;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch. 4852 4853 for(i=0;i<this->results->Size();i++){ 4854 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 4855 4856 /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand 4857 *it to the result object, to fill the rest: */ 4858 patch->fillelementinfo(count,this->id,vertices_ids,6); 4859 elementresult->PatchFill(count,patch); 4860 4861 /*increment counter: */ 4862 count++; 4863 } 4864 4865 /*Assign output pointers:*/ 4866 *pcount=count; 4867 }/*}}}*/ 4868 /*FUNCTION Penta::PatchSize{{{1*/ 4869 void Penta::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){ 4870 4871 int i; 4872 int numrows = 0; 4873 int numnodes = 0; 4874 4875 /*Go through all the results objects, and update the counters: */ 4876 for (i=0;i<this->results->Size();i++){ 4877 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 4878 /*first, we have one more result: */ 4879 numrows++; 4880 /*now, how many vertices and how many nodal values for this result? :*/ 4881 numnodes=elementresult->NumberOfNodalValues(); //ask result object. 4882 } 4883 4884 /*Assign output pointers:*/ 4885 *pnumrows=numrows; 4886 *pnumvertices=NUMVERTICES; 4887 *pnumnodes=numnodes; 4888 } 4889 /*}}}*/ 4890 /*FUNCTION Penta::ProcessResultsUnits{{{1*/ 4891 void Penta::ProcessResultsUnits(void){ 4892 4893 int i; 4894 4895 for(i=0;i<this->results->Size();i++){ 4896 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 4897 elementresult->ProcessUnits(this->parameters); 4898 } 4899 } 4900 /*}}}*/ 4901 /*FUNCTION Penta::ReduceMatrixStokes {{{1*/ 4902 void Penta::ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp){ 4903 4904 int i,j; 4905 double Kii[24][24]; 4906 double Kib[24][3]; 4907 double Kbb[3][3]; 4908 double Kbi[3][24]; 4909 double Kbbinv[3][3]; 4910 double Kright[24][24]; 4911 4912 /*Create the four matrices used for reduction */ 4913 for(i=0;i<24;i++){ 4914 for(j=0;j<24;j++){ 4915 Kii[i][j]=*(Ke_temp+27*i+j); 4916 } 4917 for(j=0;j<3;j++){ 4918 Kib[i][j]=*(Ke_temp+27*i+j+24); 4919 } 4920 } 4921 for(i=0;i<3;i++){ 4922 for(j=0;j<24;j++){ 4923 Kbi[i][j]=*(Ke_temp+27*(i+24)+j); 4924 } 4925 for(j=0;j<3;j++){ 4926 Kbb[i][j]=*(Ke_temp+27*(i+24)+j+24); 4927 } 4928 } 4929 4930 /*Inverse the matrix corresponding to bubble part Kbb */ 4931 Matrix3x3Invert(&Kbbinv[0][0], &Kbb[0][0]); 4932 4933 /*Multiply matrices to create the reduce matrix Ke_reduced */ 4934 TripleMultiply(&Kib[0][0],24,3,0, 4935 &Kbbinv[0][0],3,3,0, 4936 &Kbi[0][0],3,24,0, 4937 &Kright[0][0],0); 4938 4939 /*Affect value to the reduced matrix */ 4940 for(i=0;i<24;i++) for(j=0;j<24;j++) *(Ke_reduced+24*i+j)=Kii[i][j]-Kright[i][j]; 4941 } 4942 /*}}}*/ 4943 /*FUNCTION Penta::ReduceVectorStokes {{{1*/ 4944 void Penta::ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp){ 4945 4946 int i,j; 4947 double Pi[24]; 4948 double Pb[3]; 4949 double Kbb[3][3]; 4950 double Kib[24][3]; 4951 double Kbbinv[3][3]; 4952 double Pright[24]; 4953 4954 /*Create the four matrices used for reduction */ 4955 for(i=0;i<24;i++) Pi[i]=*(Pe_temp+i); 4956 for(i=0;i<3;i++) Pb[i]=*(Pe_temp+i+24); 4957 for(j=0;j<3;j++){ 4958 for(i=0;i<24;i++){ 4959 Kib[i][j]=*(Ke_temp+3*i+j); 4960 } 4961 for(i=0;i<3;i++){ 4962 Kbb[i][j]=*(Ke_temp+3*(i+24)+j); 4963 } 4964 } 4965 4966 /*Inverse the matrix corresponding to bubble part Kbb */ 4967 Matrix3x3Invert(&Kbbinv[0][0], &Kbb[0][0]); 4968 4969 /*Multiply matrices to create the reduce matrix Ke_reduced */ 4970 TripleMultiply(&Kib[0][0],24,3,0, 4971 &Kbbinv[0][0],3,3,0, 4972 &Pb[0],3,1,0,&Pright[0],0); 4973 4974 /*Affect value to the reduced matrix */ 4975 for(i=0;i<24;i++) *(Pe_reduced+i)=Pi[i]-Pright[i]; 4976 } 4977 /*}}}*/ 4978 /*FUNCTION Penta::RegularizeInversion {{{1*/ 4979 double Penta::RegularizeInversion(void){ 4980 4981 double J; 4982 Tria* tria=NULL; 4983 4984 /*recover some inputs: */ 4985 int approximation; 4986 inputs->GetParameterValue(&approximation,ApproximationEnum); 4987 4988 /*If on water, return 0: */ 4989 if(IsOnWater())return 0; 4990 4991 /*Bail out if this element if: 4992 * -> Not MacAyeal and not on the surface 4993 * -> MacAyeal (2d model) and not on bed) */ 4994 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){ 4995 return 0; 4996 } 4997 else if (approximation==MacAyealApproximationEnum){ 4998 4999 /*This element should be collapsed into a tria element at its base. Create this tria element, 5000 * and compute RegularizeInversion*/ 5001 5002 /*Depth Average B*/ 5003 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum); 5004 5005 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 5006 J=tria->RegularizeInversion(); 5007 delete tria->matice; delete tria; 5008 5009 /*delete B average*/ 5010 this->matice->inputs->DeleteInput(RheologyBbarEnum); 5011 5012 return J; 5013 } 5014 else{ 5015 5016 /*Depth Average B and put it in inputs*/ 5017 Penta* penta=GetBasalElement(); 5018 penta->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum); 5019 Input* B_input=penta->matice->inputs->GetInput(RheologyBbarEnum); 5020 Input* B_copy=(Input*)B_input->copy(); 5021 this->matice->inputs->AddInput((Input*)B_copy); 5022 5023 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 5024 J=tria->RegularizeInversion(); 5025 delete tria->matice; delete tria; 5026 5027 /*delete B average*/ 5028 this->matice->inputs->DeleteInput(RheologyBbarEnum); 5029 penta->matice->inputs->DeleteInput(RheologyBbarEnum); 5030 5031 return J; 5032 } 5033 } 5034 /*}}}*/ 5035 /*FUNCTION Penta::SetClone {{{1*/ 5036 void Penta::SetClone(int* minranks){ 5037 5038 ISSMERROR("not implemented yet"); 5039 } 5040 /*}}}1*/ 5041 /*FUNCTION Penta::SetCurrentConfiguration {{{1*/ 5042 void Penta::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){ 5043 5044 int analysis_counter; 5045 5046 /*go into parameters and get the analysis_counter: */ 5047 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 5048 5049 /*Get Element type*/ 5050 this->element_type=this->element_type_list[analysis_counter]; 5051 5052 /*Pick up nodes */ 5053 if (this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 5054 else this->nodes=NULL; 5055 } 5056 /*}}}*/ 5057 /*FUNCTION Penta::SpawnTria {{{1*/ 5058 Tria* Penta::SpawnTria(int g0, int g1, int g2){ 5059 5060 int i,analysis_counter; 5061 int indices[3]; 5062 int zero=0; 5063 Tria* tria = NULL; 5064 Inputs* tria_inputs = NULL; 5065 Results* tria_results = NULL; 5066 Parameters* tria_parameters = NULL; 5067 5068 /*go into parameters and get the analysis_counter: */ 5069 this->parameters->FindParam(&analysis_counter,AnalysisCounterEnum); 5070 5071 indices[0]=g0; 5072 indices[1]=g1; 5073 indices[2]=g2; 5074 5075 tria_parameters=this->parameters; 5076 tria_inputs=(Inputs*)this->inputs->SpawnTriaInputs(indices); 5077 tria_results=(Results*)this->results->SpawnTriaResults(indices); 5078 5079 tria=new Tria(); 5080 tria->id=this->id; 5081 tria->inputs=tria_inputs; 5082 tria->results=tria_results; 5083 tria->parameters=tria_parameters; 5084 tria->element_type=P1Enum; //Only P1 CG for now (TO BE CHANGED) 5085 this->SpawnTriaHook(dynamic_cast<TriaHook*>(tria),&indices[0]); 5086 5087 /*Spawn matice*/ 5088 tria->matice=NULL; 5089 tria->matice=(Matice*)this->matice->copy(); 5090 delete tria->matice->inputs; 5091 tria->matice->inputs=(Inputs*)this->matice->inputs->SpawnTriaInputs(indices); 5092 5093 /*recover nodes, matice and matpar: */ 5094 tria->nodes=(Node**)tria->hnodes[analysis_counter]->deliverp(); 5095 tria->matpar=(Matpar*)tria->hmatpar->delivers(); 5096 5097 return tria; 5098 } 5099 /*}}}*/ 5100 /*FUNCTION Penta::SurfaceArea {{{1*/ 5101 double Penta::SurfaceArea(void){ 5102 5103 int approximation; 5104 double S; 5105 Tria* tria=NULL; 5106 5107 /*retrieve inputs :*/ 5108 inputs->GetParameterValue(&approximation,ApproximationEnum); 5109 5110 /*If on water, return 0: */ 5111 if(IsOnWater())return 0; 5112 5113 /*Bail out if this element if: 5114 * -> Non MacAyeal not on the surface 5115 * -> MacAyeal (2d model) and not on bed) */ 5116 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){ 5117 return 0; 5118 } 5119 else if (approximation==MacAyealApproximationEnum){ 5120 5121 /*This element should be collapsed into a tria element at its base. Create this tria element, 5122 * and compute SurfaceArea*/ 5123 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 5124 S=tria->SurfaceArea(); 5125 delete tria->matice; delete tria; 5126 return S; 5127 } 5128 else{ 5129 5130 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 5131 S=tria->SurfaceArea(); 5132 delete tria->matice; delete tria; 5133 return S; 5134 } 5135 } 5136 /*}}}*/ 5137 /*FUNCTION Penta::SurfaceAverageVelMisfit {{{1*/ 5138 double Penta::SurfaceAverageVelMisfit(bool process_units){ 5139 5140 int approximation; 5141 double J; 5142 Tria* tria=NULL; 5143 5144 /*retrieve inputs :*/ 5145 inputs->GetParameterValue(&approximation,ApproximationEnum); 5146 5147 /*If on water, return 0: */ 5148 if(IsOnWater())return 0; 5149 5150 /*Bail out if this element if: 5151 * -> Non MacAyeal and not on the surface 5152 * -> MacAyeal (2d model) and not on bed) */ 5153 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){ 5154 return 0; 5155 } 5156 else if (approximation==MacAyealApproximationEnum){ 5157 5158 /*This element should be collapsed into a tria element at its base. Create this tria element, 5159 * and compute SurfaceAverageVelMisfit*/ 5160 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 5161 J=tria->SurfaceAverageVelMisfit(process_units); 5162 delete tria->matice; delete tria; 5163 return J; 5164 } 5165 else{ 5166 5167 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 5168 J=tria->SurfaceAverageVelMisfit(process_units); 5169 delete tria->matice; delete tria; 5170 return J; 5171 } 5172 } 5173 /*}}}*/ 5174 /*FUNCTION Penta::SurfaceAbsVelMisfit {{{1*/ 5175 double Penta::SurfaceAbsVelMisfit(bool process_units){ 5176 5177 int approximation; 5178 double J; 5179 Tria* tria=NULL; 5180 5181 /*retrieve inputs :*/ 5182 inputs->GetParameterValue(&approximation,ApproximationEnum); 5183 5184 /*If on water, return 0: */ 5185 if(IsOnWater())return 0; 5186 5187 /*Bail out if this element if: 5188 * -> Non MacAyeal and not on the surface 5189 * -> MacAyeal (2d model) and not on bed) */ 5190 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){ 5191 return 0; 5192 } 5193 else if (approximation==MacAyealApproximationEnum){ 5194 5195 /*This element should be collapsed into a tria element at its base. Create this tria element, 5196 * and compute SurfaceAbsVelMisfit*/ 5197 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 5198 J=tria->SurfaceAbsVelMisfit(process_units); 5199 delete tria->matice; delete tria; 5200 return J; 5201 } 5202 else{ 5203 5204 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 5205 J=tria->SurfaceAbsVelMisfit(process_units); 5206 delete tria->matice; delete tria; 5207 return J; 5208 } 5209 } 5210 /*}}}*/ 5211 /*FUNCTION Penta::SurfaceLogVelMisfit {{{1*/ 5212 double Penta::SurfaceLogVelMisfit(bool process_units){ 5213 5214 int approximation; 5215 double J; 5216 Tria* tria=NULL; 5217 5218 /*retrieve inputs :*/ 5219 inputs->GetParameterValue(&approximation,ApproximationEnum); 5220 5221 /*If on water, return 0: */ 5222 if(IsOnWater())return 0; 5223 5224 /*Bail out if this element if: 5225 * -> Non MacAyeal and not on the surface 5226 * -> MacAyeal (2d model) and not on bed) */ 5227 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){ 5228 return 0; 5229 } 5230 else if (approximation==MacAyealApproximationEnum){ 5231 5232 /*This element should be collapsed into a tria element at its base. Create this tria element, 5233 * and compute SurfaceLogVelMisfit*/ 5234 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 5235 J=tria->SurfaceLogVelMisfit(process_units); 5236 delete tria->matice; delete tria; 5237 return J; 5238 } 5239 else{ 5240 5241 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 5242 J=tria->SurfaceLogVelMisfit(process_units); 5243 delete tria->matice; delete tria; 5244 return J; 5245 } 5246 } 5247 /*}}}*/ 5248 /*FUNCTION Penta::SurfaceLogVxVyMisfit {{{1*/ 5249 double Penta::SurfaceLogVxVyMisfit(bool process_units){ 5250 5251 double J; 5252 Tria* tria=NULL; 5253 5254 /*inputs: */ 5255 int approximation; 5256 5257 /*retrieve inputs :*/ 5258 inputs->GetParameterValue(&approximation,ApproximationEnum); 5259 5260 /*If on water, return 0: */ 5261 if(IsOnWater())return 0; 5262 5263 /*Bail out if this element if: 5264 * -> Non MacAyeal and not on the surface 5265 * -> MacAyeal (2d model) and not on bed) */ 5266 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){ 5267 return 0; 5268 } 5269 else if (approximation==MacAyealApproximationEnum){ 5270 5271 /*This element should be collapsed into a tria element at its base. Create this tria element, 5272 * and compute SurfaceLogVxVyMisfit*/ 5273 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 5274 J=tria->SurfaceLogVxVyMisfit(process_units); 5275 delete tria->matice; delete tria; 5276 return J; 5277 } 5278 else{ 5279 5280 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 5281 J=tria->SurfaceLogVxVyMisfit(process_units); 5282 delete tria->matice; delete tria; 5283 return J; 5284 } 5285 } 5286 /*}}}*/ 5287 /*FUNCTION Penta::SurfaceNormal {{{1*/ 5288 void Penta::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){ 5289 5290 int i; 5291 double v13[3],v23[3]; 5292 double normal[3]; 5293 double normal_norm; 5294 5295 for (i=0;i<3;i++){ 5296 v13[i]=xyz_list[0][i]-xyz_list[2][i]; 5297 v23[i]=xyz_list[1][i]-xyz_list[2][i]; 5298 } 5299 5300 normal[0]=v13[1]*v23[2]-v13[2]*v23[1]; 5301 normal[1]=v13[2]*v23[0]-v13[0]*v23[2]; 5302 normal[2]=v13[0]*v23[1]-v13[1]*v23[0]; 5303 5304 normal_norm=sqrt( pow(normal[0],2)+pow(normal[1],2)+pow(normal[2],2) ); 5305 5306 *(surface_normal)=normal[0]/normal_norm; 5307 *(surface_normal+1)=normal[1]/normal_norm; 5308 *(surface_normal+2)=normal[2]/normal_norm; 5309 } 5310 /*}}}*/ 5311 /*FUNCTION Penta::SurfaceRelVelMisfit {{{1*/ 5312 double Penta::SurfaceRelVelMisfit(bool process_units){ 5313 5314 int approximation; 5315 double J; 5316 Tria* tria=NULL; 5317 5318 /*retrieve inputs :*/ 5319 inputs->GetParameterValue(&approximation,ApproximationEnum); 5320 5321 /*If on water, return 0: */ 5322 if(IsOnWater())return 0; 5323 5324 /*Bail out if this element if: 5325 * -> Non MacAyeal and not on the surface 5326 * -> MacAyeal (2d model) and not on bed) */ 5327 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){ 5328 return 0; 5329 } 5330 else if (approximation==MacAyealApproximationEnum){ 5331 5332 /*This element should be collapsed into a tria element at its base. Create this tria element, 5333 * and compute SurfaceRelVelMisfit*/ 5334 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 5335 J=tria->SurfaceRelVelMisfit(process_units); 5336 delete tria->matice; delete tria; 5337 return J; 5338 } 5339 else{ 5340 5341 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 5342 J=tria->SurfaceRelVelMisfit(process_units); 5343 delete tria->matice; delete tria; 5344 return J; 5345 } 1465 5346 } 1466 5347 /*}}}*/ … … 1527 5408 delete tria->matice; delete tria; 1528 5409 return J; 1529 }1530 /*}}}*/1531 /*FUNCTION Penta::SurfaceAbsVelMisfit {{{1*/1532 double Penta::SurfaceAbsVelMisfit(bool process_units){1533 1534 int approximation;1535 double J;1536 Tria* tria=NULL;1537 1538 /*retrieve inputs :*/1539 inputs->GetParameterValue(&approximation,ApproximationEnum);1540 1541 /*If on water, return 0: */1542 if(IsOnWater())return 0;1543 1544 /*Bail out if this element if:1545 * -> Non MacAyeal and not on the surface1546 * -> MacAyeal (2d model) and not on bed) */1547 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){1548 return 0;1549 }1550 else if (approximation==MacAyealApproximationEnum){1551 1552 /*This element should be collapsed into a tria element at its base. Create this tria element,1553 * and compute SurfaceAbsVelMisfit*/1554 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).1555 J=tria->SurfaceAbsVelMisfit(process_units);1556 delete tria->matice; delete tria;1557 return J;1558 }1559 else{1560 1561 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).1562 J=tria->SurfaceAbsVelMisfit(process_units);1563 delete tria->matice; delete tria;1564 return J;1565 }1566 }1567 /*}}}*/1568 /*FUNCTION Penta::SurfaceRelVelMisfit {{{1*/1569 double Penta::SurfaceRelVelMisfit(bool process_units){1570 1571 int approximation;1572 double J;1573 Tria* tria=NULL;1574 1575 /*retrieve inputs :*/1576 inputs->GetParameterValue(&approximation,ApproximationEnum);1577 1578 /*If on water, return 0: */1579 if(IsOnWater())return 0;1580 1581 /*Bail out if this element if:1582 * -> Non MacAyeal and not on the surface1583 * -> MacAyeal (2d model) and not on bed) */1584 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){1585 return 0;1586 }1587 else if (approximation==MacAyealApproximationEnum){1588 1589 /*This element should be collapsed into a tria element at its base. Create this tria element,1590 * and compute SurfaceRelVelMisfit*/1591 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).1592 J=tria->SurfaceRelVelMisfit(process_units);1593 delete tria->matice; delete tria;1594 return J;1595 }1596 else{1597 1598 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).1599 J=tria->SurfaceRelVelMisfit(process_units);1600 delete tria->matice; delete tria;1601 return J;1602 }1603 }1604 /*}}}*/1605 /*FUNCTION Penta::SurfaceLogVelMisfit {{{1*/1606 double Penta::SurfaceLogVelMisfit(bool process_units){1607 1608 int approximation;1609 double J;1610 Tria* tria=NULL;1611 1612 /*retrieve inputs :*/1613 inputs->GetParameterValue(&approximation,ApproximationEnum);1614 1615 /*If on water, return 0: */1616 if(IsOnWater())return 0;1617 1618 /*Bail out if this element if:1619 * -> Non MacAyeal and not on the surface1620 * -> MacAyeal (2d model) and not on bed) */1621 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){1622 return 0;1623 }1624 else if (approximation==MacAyealApproximationEnum){1625 1626 /*This element should be collapsed into a tria element at its base. Create this tria element,1627 * and compute SurfaceLogVelMisfit*/1628 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).1629 J=tria->SurfaceLogVelMisfit(process_units);1630 delete tria->matice; delete tria;1631 return J;1632 }1633 else{1634 1635 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).1636 J=tria->SurfaceLogVelMisfit(process_units);1637 delete tria->matice; delete tria;1638 return J;1639 }1640 }1641 /*}}}*/1642 /*FUNCTION Penta::SurfaceLogVxVyMisfit {{{1*/1643 double Penta::SurfaceLogVxVyMisfit(bool process_units){1644 1645 double J;1646 Tria* tria=NULL;1647 1648 /*inputs: */1649 int approximation;1650 1651 /*retrieve inputs :*/1652 inputs->GetParameterValue(&approximation,ApproximationEnum);1653 1654 /*If on water, return 0: */1655 if(IsOnWater())return 0;1656 1657 /*Bail out if this element if:1658 * -> Non MacAyeal and not on the surface1659 * -> MacAyeal (2d model) and not on bed) */1660 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){1661 return 0;1662 }1663 else if (approximation==MacAyealApproximationEnum){1664 1665 /*This element should be collapsed into a tria element at its base. Create this tria element,1666 * and compute SurfaceLogVxVyMisfit*/1667 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).1668 J=tria->SurfaceLogVxVyMisfit(process_units);1669 delete tria->matice; delete tria;1670 return J;1671 }1672 else{1673 1674 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).1675 J=tria->SurfaceLogVxVyMisfit(process_units);1676 delete tria->matice; delete tria;1677 return J;1678 }1679 }1680 /*}}}*/1681 /*FUNCTION Penta::SurfaceAverageVelMisfit {{{1*/1682 double Penta::SurfaceAverageVelMisfit(bool process_units){1683 1684 int approximation;1685 double J;1686 Tria* tria=NULL;1687 1688 /*retrieve inputs :*/1689 inputs->GetParameterValue(&approximation,ApproximationEnum);1690 1691 /*If on water, return 0: */1692 if(IsOnWater())return 0;1693 1694 /*Bail out if this element if:1695 * -> Non MacAyeal and not on the surface1696 * -> MacAyeal (2d model) and not on bed) */1697 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){1698 return 0;1699 }1700 else if (approximation==MacAyealApproximationEnum){1701 1702 /*This element should be collapsed into a tria element at its base. Create this tria element,1703 * and compute SurfaceAverageVelMisfit*/1704 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).1705 J=tria->SurfaceAverageVelMisfit(process_units);1706 delete tria->matice; delete tria;1707 return J;1708 }1709 else{1710 1711 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).1712 J=tria->SurfaceAverageVelMisfit(process_units);1713 delete tria->matice; delete tria;1714 return J;1715 }1716 }1717 /*}}}*/1718 /*FUNCTION Penta::PatchFill{{{1*/1719 void Penta::PatchFill(int* pcount, Patch* patch){1720 1721 int i,count;1722 int vertices_ids[6];1723 1724 /*recover pointer: */1725 count=*pcount;1726 1727 /*will be needed later: */1728 for(i=0;i<6;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch.1729 1730 for(i=0;i<this->results->Size();i++){1731 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);1732 1733 /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand1734 *it to the result object, to fill the rest: */1735 patch->fillelementinfo(count,this->id,vertices_ids,6);1736 elementresult->PatchFill(count,patch);1737 1738 /*increment counter: */1739 count++;1740 }1741 1742 /*Assign output pointers:*/1743 *pcount=count;1744 }/*}}}*/1745 /*FUNCTION Penta::PatchSize{{{1*/1746 void Penta::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){1747 1748 int i;1749 int numrows = 0;1750 int numnodes = 0;1751 1752 /*Go through all the results objects, and update the counters: */1753 for (i=0;i<this->results->Size();i++){1754 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);1755 /*first, we have one more result: */1756 numrows++;1757 /*now, how many vertices and how many nodal values for this result? :*/1758 numnodes=elementresult->NumberOfNodalValues(); //ask result object.1759 }1760 1761 /*Assign output pointers:*/1762 *pnumrows=numrows;1763 *pnumvertices=NUMVERTICES;1764 *pnumnodes=numnodes;1765 }1766 /*}}}*/1767 /*FUNCTION Penta::ProcessResultsUnits{{{1*/1768 void Penta::ProcessResultsUnits(void){1769 1770 int i;1771 1772 for(i=0;i<this->results->Size();i++){1773 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);1774 elementresult->ProcessUnits(this->parameters);1775 }1776 }1777 /*}}}*/1778 /*FUNCTION Penta::SetCurrentConfiguration {{{1*/1779 void Penta::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){1780 1781 int analysis_counter;1782 1783 /*go into parameters and get the analysis_counter: */1784 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);1785 1786 /*Get Element type*/1787 this->element_type=this->element_type_list[analysis_counter];1788 1789 /*Pick up nodes */1790 if (this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();1791 else this->nodes=NULL;1792 }1793 /*}}}*/1794 /*FUNCTION Penta::SurfaceArea {{{1*/1795 double Penta::SurfaceArea(void){1796 1797 int approximation;1798 double S;1799 Tria* tria=NULL;1800 1801 /*retrieve inputs :*/1802 inputs->GetParameterValue(&approximation,ApproximationEnum);1803 1804 /*If on water, return 0: */1805 if(IsOnWater())return 0;1806 1807 /*Bail out if this element if:1808 * -> Non MacAyeal not on the surface1809 * -> MacAyeal (2d model) and not on bed) */1810 if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){1811 return 0;1812 }1813 else if (approximation==MacAyealApproximationEnum){1814 1815 /*This element should be collapsed into a tria element at its base. Create this tria element,1816 * and compute SurfaceArea*/1817 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).1818 S=tria->SurfaceArea();1819 delete tria->matice; delete tria;1820 return S;1821 }1822 else{1823 1824 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).1825 S=tria->SurfaceArea();1826 delete tria->matice; delete tria;1827 return S;1828 }1829 5410 } 1830 5411 /*}}}*/ … … 1980 5561 } 1981 5562 /*}}}*/ 1982 1983 /*Penta specific routines: */1984 /*FUNCTION Penta::BedNormal {{{1*/1985 void Penta::BedNormal(double* bed_normal, double xyz_list[3][3]){1986 1987 int i;1988 double v13[3],v23[3];1989 double normal[3];1990 double normal_norm;1991 1992 for (i=0;i<3;i++){1993 v13[i]=xyz_list[0][i]-xyz_list[2][i];1994 v23[i]=xyz_list[1][i]-xyz_list[2][i];1995 }1996 1997 normal[0]=v13[1]*v23[2]-v13[2]*v23[1];1998 normal[1]=v13[2]*v23[0]-v13[0]*v23[2];1999 normal[2]=v13[0]*v23[1]-v13[1]*v23[0];2000 normal_norm=sqrt( pow(normal[0],2)+pow(normal[1],2)+pow(normal[2],2) );2001 2002 /*Bed normal is opposite to surface normal*/2003 *(bed_normal)=-normal[0]/normal_norm;2004 *(bed_normal+1)=-normal[1]/normal_norm;2005 *(bed_normal+2)=-normal[2]/normal_norm;2006 }2007 /*}}}*/2008 /*FUNCTION Penta::CreateKMatrixBalancedthickness {{{1*/2009 ElementMatrix* Penta::CreateKMatrixBalancedthickness(void){2010 2011 /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the2012 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build2013 the stiffness matrix. */2014 if (!IsOnBed() || IsOnWater()) return NULL;2015 2016 /*Depth Averaging Vx and Vy*/2017 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);2018 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);2019 2020 /*Spawn Tria element from the base of the Penta: */2021 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2022 ElementMatrix* Ke=tria->CreateKMatrixBalancedthickness();2023 delete tria->matice; delete tria;2024 2025 /*Delete Vx and Vy averaged*/2026 this->inputs->DeleteInput(VxAverageEnum);2027 this->inputs->DeleteInput(VyAverageEnum);2028 2029 /*clean up and return*/2030 return Ke;2031 }2032 /*}}}*/2033 /*FUNCTION Penta::CreateKMatrixBalancedvelocities {{{1*/2034 ElementMatrix* Penta::CreateKMatrixBalancedvelocities(void){2035 2036 /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the2037 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build2038 the stiffness matrix. */2039 if (!IsOnBed() || IsOnWater()) return NULL;2040 2041 /*Depth Averaging Vx and Vy*/2042 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);2043 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);2044 2045 /*Spawn Tria element from the base of the Penta: */2046 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2047 ElementMatrix* Ke=tria->CreateKMatrixBalancedvelocities();2048 delete tria->matice; delete tria;2049 2050 /*Delete Vx and Vy averaged*/2051 this->inputs->DeleteInput(VxAverageEnum);2052 this->inputs->DeleteInput(VyAverageEnum);2053 2054 /*clean up and return*/2055 return Ke;2056 }2057 /*}}}*/2058 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattyn{{{1*/2059 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattyn(void){2060 2061 /*compute all stiffness matrices for this element*/2062 ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealPattynViscous();2063 ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealPattynFriction();2064 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);2065 2066 /*clean-up and return*/2067 delete Ke1;2068 delete Ke2;2069 return Ke;2070 }2071 /*}}}*/2072 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynViscous{{{1*/2073 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynViscous(void){2074 2075 /*Constants*/2076 const int numdofm=NDOF2*NUMVERTICES2D;2077 const int numdofp=NDOF2*NUMVERTICES;2078 const int numdoftotal=2*NDOF2*NUMVERTICES;2079 2080 /*Intermediaries */2081 int i,j,ig;2082 double Jdet;2083 double viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity2084 double epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/2085 double xyz_list[NUMVERTICES][3];2086 double B[3][numdofp];2087 double Bprime[3][numdofm];2088 double D[3][3]={0.0}; // material matrix, simple scalar matrix.2089 double D_scalar;2090 double Ke_gg[numdofp][numdofm]={0.0}; //local element stiffness matrix2091 double Ke_gg_gaussian[numdofp][numdofm]; //stiffness matrix evaluated at the gaussian point.2092 GaussPenta *gauss=NULL;2093 GaussTria *gauss_tria=NULL;2094 2095 /*Find penta on bed as pattyn must be coupled to the dofs on the bed: */2096 Penta* pentabase=GetBasalElement();2097 Tria* tria=pentabase->SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2098 2099 /*Initialize Element matrix and return if necessary*/2100 if(IsOnWater()) return NULL;2101 ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);2102 ElementMatrix* Ke2=new ElementMatrix(this->nodes ,NUMVERTICES,this->parameters,PattynApproximationEnum);2103 ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);2104 delete Ke1; delete Ke2;2105 2106 /* Get node coordinates and dof list: */2107 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2108 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);2109 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2110 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2111 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input);2112 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input);2113 2114 /* Start looping on the number of gaussian points: */2115 gauss=new GaussPenta(5,5);2116 gauss_tria=new GaussTria();2117 for (ig=gauss->begin();ig<gauss->end();ig++){2118 2119 gauss->GaussPoint(ig);2120 gauss->SynchronizeGaussTria(gauss_tria);2121 2122 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);2123 GetBMacAyealPattyn(&B[0][0], &xyz_list[0][0], gauss);2124 tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);2125 2126 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);2127 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);2128 matice->GetViscosity3d(&viscosity, &epsilon[0]);2129 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);2130 2131 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);2132 D_scalar=2*newviscosity*gauss->weight*Jdet;2133 for (i=0;i<3;i++) D[i][i]=D_scalar;2134 2135 TripleMultiply( &B[0][0],3,numdofp,1,2136 &D[0][0],3,3,0,2137 &Bprime[0][0],3,numdofm,0,2138 &Ke_gg_gaussian[0][0],0);2139 2140 for( i=0; i<numdofp; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];2141 }2142 for(i=0;i<numdofp;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];2143 for(i=0;i<numdofm;i++) for(j=0;j<numdofp;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg[j][i];2144 2145 /*Clean-up and return*/2146 delete tria->matice; delete tria;2147 delete gauss;2148 delete gauss_tria;2149 return Ke;2150 }2151 /*}}}*/2152 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynFriction{{{1*/2153 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynFriction(void){2154 2155 /*Initialize Element matrix and return if necessary*/2156 if(IsOnWater() || IsOnShelf() || !IsOnBed()) return NULL;2157 2158 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2159 ElementMatrix* Ke=tria->CreateKMatrixCouplingMacAyealPattynFriction();2160 delete tria->matice; delete tria;2161 2162 return Ke;2163 }2164 /*}}}*/2165 /*FUNCTION Penta::CreateKMatrixCouplingPattynStokes{{{1*/2166 ElementMatrix* Penta::CreateKMatrixCouplingPattynStokes(void){2167 2168 /*compute all stiffness matrices for this element*/2169 ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);2170 ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);2171 ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);2172 delete Ke1;2173 delete Ke2;2174 Ke1=CreateKMatrixDiagnosticPattyn();2175 Ke2=CreateKMatrixDiagnosticStokes();2176 2177 /*Constants*/2178 const int numdofp=NDOF2*NUMVERTICES;2179 const int numdofs=NDOF4*NUMVERTICES;2180 const int numdoftotal=(NDOF2+NDOF4)*NUMVERTICES;2181 int i,j;2182 2183 for(i=0;i<numdofs;i++) for(j=0;j<NUMVERTICES;j++){2184 Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+0]+=Ke2->values[i*numdofs+NDOF4*j+0];2185 Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+1]+=Ke2->values[i*numdofs+NDOF4*j+1];2186 }2187 for(i=0;i<numdofp;i++) for(j=0;j<NUMVERTICES;j++){2188 Ke->values[i*numdoftotal+numdofp+NDOF4*j+0]+=Ke1->values[i*numdofp+NDOF2*j+0];2189 Ke->values[i*numdoftotal+numdofp+NDOF4*j+1]+=Ke1->values[i*numdofp+NDOF2*j+1];2190 }2191 2192 /*clean-up and return*/2193 delete Ke1;2194 delete Ke2;2195 return Ke;2196 }2197 /*}}}*/2198 /*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/2199 ElementMatrix* Penta::CreateKMatrixDiagnosticHoriz(void){2200 2201 int approximation;2202 inputs->GetParameterValue(&approximation,ApproximationEnum);2203 2204 switch(approximation){2205 case MacAyealApproximationEnum:2206 return CreateKMatrixDiagnosticMacAyeal2d();2207 case PattynApproximationEnum:2208 return CreateKMatrixDiagnosticPattyn();2209 case StokesApproximationEnum:2210 return CreateKMatrixDiagnosticStokes();2211 case HutterApproximationEnum:2212 return NULL;2213 case NoneApproximationEnum:2214 return NULL;2215 case MacAyealPattynApproximationEnum:2216 return CreateKMatrixDiagnosticMacAyealPattyn();2217 case PattynStokesApproximationEnum:2218 return CreateKMatrixDiagnosticPattynStokes();2219 default:2220 ISSMERROR("Approximation %s not supported yet",EnumToString(approximation));2221 }2222 }2223 /*}}}*/2224 /*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/2225 ElementMatrix* Penta::CreateKMatrixDiagnosticHutter(void){2226 2227 /*Constants*/2228 const int numdof=NDOF2*NUMVERTICES;2229 2230 /*Intermediaries*/2231 int connectivity[2];2232 int i,i0,i1,j0,j1;2233 double one0,one1;2234 2235 /*Initialize Element matrix and return if necessary*/2236 if(IsOnWater()) return NULL;2237 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);2238 2239 /*Spawn 3 beam elements: */2240 for(i=0;i<3;i++){2241 /*2 dofs of first node*/2242 i0=2*i;2243 i1=2*i+1;2244 /*2 dofs of second node*/2245 j0=2*(i+3);2246 j1=2*(i+3)+1;2247 2248 /*Find connectivity for the two nodes*/2249 connectivity[0]=nodes[i]->GetConnectivity();2250 connectivity[1]=nodes[i+3]->GetConnectivity();2251 one0=1/(double)connectivity[0];2252 one1=1/(double)connectivity[1];2253 2254 /*Create matrix for these two nodes*/2255 if (IsOnBed() && IsOnSurface()){2256 Ke->values[i0*numdof+i0]=one0;2257 Ke->values[i1*numdof+i1]=one0;2258 Ke->values[j0*numdof+i0]=-one1;2259 Ke->values[j0*numdof+j0]=one1;2260 Ke->values[j1*numdof+i1]=-one1;2261 Ke->values[j1*numdof+j1]=one1;2262 }2263 else if (IsOnBed()){2264 Ke->values[i0*numdof+i0]=one0;2265 Ke->values[i1*numdof+i1]=one0;2266 Ke->values[j0*numdof+i0]=-2*one1;2267 Ke->values[j0*numdof+j0]=2*one1;2268 Ke->values[j1*numdof+i1]=-2*one1;2269 Ke->values[j1*numdof+j1]=2*one1;2270 }2271 else if (IsOnSurface()){2272 Ke->values[j0*numdof+i0]=-one1;2273 Ke->values[j0*numdof+j0]=one1;2274 Ke->values[j1*numdof+i1]=-one1;2275 Ke->values[j1*numdof+j1]=one1;2276 }2277 else{ //node is on two horizontal layers and beams include the values only once, so the have to use half of the connectivity2278 Ke->values[j0*numdof+i0]=-2*one1;2279 Ke->values[j0*numdof+j0]=2*one1;2280 Ke->values[j1*numdof+i1]=-2*one1;2281 Ke->values[j1*numdof+j1]=2*one1;2282 }2283 }2284 2285 /*Clean up and return*/2286 return Ke;2287 }2288 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal2d{{{1*/2289 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal2d(void){2290 2291 /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the2292 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build2293 the stiffness matrix. */2294 if (!IsOnBed() || IsOnWater()) return NULL;2295 2296 /*Depth Averaging B*/2297 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum);2298 2299 /*Call Tria function*/2300 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2301 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyeal();2302 delete tria->matice; delete tria;2303 2304 /*Delete B averaged*/2305 this->matice->inputs->DeleteInput(RheologyBbarEnum);2306 2307 /*clean up and return*/2308 return Ke;2309 }2310 /*}}}*/2311 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3d{{{1*/2312 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3d(void){2313 2314 /*compute all stiffness matrices for this element*/2315 ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3dViscous();2316 ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyeal3dFriction();2317 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);2318 2319 /*clean-up and return*/2320 delete Ke1;2321 delete Ke2;2322 return Ke;2323 }2324 /*}}}*/2325 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dViscous{{{1*/2326 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dViscous(void){2327 2328 /*Constants*/2329 const int numdof2d=2*NUMVERTICES2D;2330 2331 /*Intermediaries */2332 int i,j,ig;2333 double Jdet;2334 double viscosity, oldviscosity, newviscosity, viscosity_overshoot;2335 double epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/2336 double xyz_list[NUMVERTICES][3];2337 double B[3][numdof2d];2338 double Bprime[3][numdof2d];2339 double D[3][3]={0.0}; // material matrix, simple scalar matrix.2340 double D_scalar;2341 double Ke_gg_gaussian[numdof2d][numdof2d]; //stiffness matrix evaluated at the gaussian point.2342 Tria* tria=NULL;2343 Penta* pentabase=NULL;2344 GaussPenta *gauss=NULL;2345 GaussTria *gauss_tria=NULL;2346 2347 /*Find penta on bed as this is a macayeal elements: */2348 pentabase=GetBasalElement();2349 tria=pentabase->SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2350 2351 /*Initialize Element matrix and return if necessary*/2352 if(IsOnWater()) return NULL;2353 ElementMatrix* Ke=new ElementMatrix(tria->nodes,NUMVERTICES2D,this->parameters,MacAyealApproximationEnum);2354 2355 /*Retrieve all inputs and parameters*/2356 GetVerticesCoordinates(&xyz_list[0][0], nodes,NUMVERTICES);2357 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);2358 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2359 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2360 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input);2361 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input);2362 2363 /* Start looping on the number of gaussian points: */2364 gauss=new GaussPenta(5,5);2365 gauss_tria=new GaussTria();2366 for (ig=gauss->begin();ig<gauss->end();ig++){2367 2368 gauss->GaussPoint(ig);2369 gauss->SynchronizeGaussTria(gauss_tria);2370 2371 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);2372 tria->GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss_tria);2373 tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);2374 2375 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);2376 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);2377 matice->GetViscosity3d(&viscosity, &epsilon[0]);2378 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);2379 2380 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);2381 D_scalar=2*newviscosity*gauss->weight*Jdet;2382 for (i=0;i<3;i++) D[i][i]=D_scalar;2383 2384 TripleMultiply( &B[0][0],3,numdof2d,1,2385 &D[0][0],3,3,0,2386 &Bprime[0][0],3,numdof2d,0,2387 &Ke_gg_gaussian[0][0],0);2388 2389 for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof2d+j]+=Ke_gg_gaussian[i][j];2390 }2391 2392 /*Clean up and return*/2393 delete tria->matice;2394 delete tria;2395 delete gauss_tria;2396 delete gauss;2397 return Ke;2398 }2399 /*}}}*/2400 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dFriction{{{1*/2401 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dFriction(void){2402 2403 /*Initialize Element matrix and return if necessary*/2404 if(IsOnWater() || IsOnShelf() || !IsOnBed()) return NULL;2405 2406 /*Build a tria element using the 3 grids of the base of the penta. Then use2407 * the tria functionality to build a friction stiffness matrix on these 32408 * grids: */2409 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2410 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyealFriction();2411 delete tria->matice; delete tria;2412 2413 /*clean-up and return*/2414 return Ke;2415 }2416 /*}}}*/2417 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealPattyn{{{1*/2418 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealPattyn(void){2419 2420 /*compute all stiffness matrices for this element*/2421 ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();2422 ElementMatrix* Ke2=CreateKMatrixDiagnosticPattyn();2423 ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealPattyn();2424 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);2425 2426 /*clean-up and return*/2427 delete Ke1;2428 delete Ke2;2429 delete Ke3;2430 return Ke;2431 }2432 /*}}}*/2433 /*FUNCTION Penta::CreateKMatrixDiagnosticPattyn{{{1*/2434 ElementMatrix* Penta::CreateKMatrixDiagnosticPattyn(void){2435 2436 /*compute all stiffness matrices for this element*/2437 ElementMatrix* Ke1=CreateKMatrixDiagnosticPattynViscous();2438 ElementMatrix* Ke2=CreateKMatrixDiagnosticPattynFriction();2439 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);2440 2441 /*clean-up and return*/2442 delete Ke1;2443 delete Ke2;2444 return Ke;2445 }2446 /*}}}*/2447 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynViscous{{{1*/2448 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynViscous(void){2449 2450 /*Constants*/2451 const int numdof=NDOF2*NUMVERTICES;2452 2453 /*Intermediaries */2454 int i,j,ig;2455 int approximation;2456 double xyz_list[NUMVERTICES][3];2457 double Jdet;2458 double viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity2459 double epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/2460 double D_scalar;2461 double D[5][5]={0.0}; // material matrix, simple scalar matrix.2462 double B[5][numdof];2463 double Bprime[5][numdof];2464 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.2465 Tria* tria=NULL;2466 GaussPenta *gauss=NULL;2467 2468 /*Initialize Element matrix and return if necessary*/2469 if(IsOnWater()) return NULL;2470 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);2471 2472 /*Retrieve all inputs and parameters*/2473 inputs->GetParameterValue(&approximation,ApproximationEnum);2474 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2475 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);2476 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2477 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2478 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input);2479 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input);2480 2481 /* Start looping on the number of gaussian points: */2482 gauss=new GaussPenta(5,5);2483 for (ig=gauss->begin();ig<gauss->end();ig++){2484 2485 gauss->GaussPoint(ig);2486 2487 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);2488 GetBPattyn(&B[0][0], &xyz_list[0][0], gauss);2489 GetBprimePattyn(&Bprime[0][0], &xyz_list[0][0], gauss);2490 2491 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);2492 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);2493 matice->GetViscosity3d(&viscosity, &epsilon[0]);2494 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);2495 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);2496 2497 D_scalar=2*newviscosity*gauss->weight*Jdet;2498 for (i=0;i<5;i++) D[i][i]=D_scalar;2499 2500 TripleMultiply( &B[0][0],5,numdof,1,2501 &D[0][0],5,5,0,2502 &Bprime[0][0],5,numdof,0,2503 &Ke_gg_gaussian[0][0],0);2504 2505 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j];2506 }2507 2508 /*Clean up and return*/2509 delete gauss;2510 return Ke;2511 }2512 /*}}}*/2513 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynFriction{{{1*/2514 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynFriction(void){2515 2516 /*Initialize Element matrix and return if necessary*/2517 if(IsOnWater() || IsOnShelf() || !IsOnBed()) return NULL;2518 2519 /*Build a tria element using the 3 grids of the base of the penta. Then use2520 * the tria functionality to build a friction stiffness matrix on these 32521 * grids: */2522 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2523 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticPattynFriction();2524 delete tria->matice; delete tria;2525 2526 /*clean-up and return*/2527 return Ke;2528 }2529 /*}}}*/2530 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynStokes{{{1*/2531 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynStokes(void){2532 2533 /*compute all stiffness matrices for this element*/2534 ElementMatrix* Ke1=CreateKMatrixDiagnosticPattyn();2535 ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();2536 ElementMatrix* Ke3=CreateKMatrixCouplingPattynStokes();2537 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);2538 2539 /*clean-up and return*/2540 delete Ke1;2541 delete Ke2;2542 delete Ke3;2543 return Ke;2544 }2545 /*}}}*/2546 /*FUNCTION Penta::CreateKMatrixDiagnosticStokes{{{1*/2547 ElementMatrix* Penta::CreateKMatrixDiagnosticStokes(void){2548 2549 /*compute all stiffness matrices for this element*/2550 ElementMatrix* Ke1=CreateKMatrixDiagnosticStokesViscous();2551 ElementMatrix* Ke2=CreateKMatrixDiagnosticStokesFriction();2552 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);2553 2554 /*clean-up and return*/2555 delete Ke1;2556 delete Ke2;2557 return Ke;2558 }2559 /*}}}*/2560 /*FUNCTION Penta::CreateKMatrixDiagnosticStokesViscous {{{1*/2561 ElementMatrix* Penta::CreateKMatrixDiagnosticStokesViscous(void){2562 2563 /*Intermediaries */2564 int i,j,ig,approximation;2565 double Jdet,viscosity,stokesreconditioning;2566 double xyz_list[NUMVERTICES][3];2567 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/2568 double B[8][27];2569 double B_prime[8][27];2570 double D_scalar;2571 double D[8][8]={0.0};2572 double Ke_temp[27][27]={0.0}; //for the six nodes and the bubble2573 double Ke_gaussian[27][27];2574 GaussPenta *gauss=NULL;2575 2576 /*If on water or not Stokes, skip stiffness: */2577 inputs->GetParameterValue(&approximation,ApproximationEnum);2578 if(IsOnWater() || (approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum)) return NULL;2579 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);2580 2581 /*Retrieve all inputs and parameters*/2582 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2583 parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);2584 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2585 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2586 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);2587 2588 /* Start looping on the number of gaussian points: */2589 gauss=new GaussPenta(5,5);2590 for (ig=gauss->begin();ig<gauss->end();ig++){2591 2592 gauss->GaussPoint(ig);2593 2594 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);2595 GetBStokes(&B[0][0],&xyz_list[0][0],gauss);2596 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0],gauss);2597 2598 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);2599 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);2600 2601 D_scalar=gauss->weight*Jdet;2602 for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;2603 for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;2604 2605 TripleMultiply( &B[0][0],8,27,1,2606 &D[0][0],8,8,0,2607 &B_prime[0][0],8,27,0,2608 &Ke_gaussian[0][0],0);2609 2610 for(i=0;i<27;i++) for(j=0;j<27;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];2611 }2612 2613 /*Condensation*/2614 ReduceMatrixStokes(Ke->values, &Ke_temp[0][0]);2615 2616 /*Clean up and return*/2617 delete gauss;2618 return Ke;2619 }2620 /*}}}*/2621 /*FUNCTION Penta::CreateKMatrixDiagnosticStokesFriction {{{1*/2622 ElementMatrix* Penta::CreateKMatrixDiagnosticStokesFriction(void){2623 2624 /*Constants*/2625 const int numdof=NUMVERTICES*NDOF4;2626 const int numdof2d=NUMVERTICES2D*NDOF4;2627 2628 /*Intermediaries */2629 int i,j,ig;2630 int analysis_type,approximation;2631 double stokesreconditioning;2632 double viscosity,alpha2_gauss,Jdet2d;2633 double bed_normal[3];2634 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/2635 double xyz_list[NUMVERTICES][3];2636 double xyz_list_tria[NUMVERTICES2D][3];2637 double LStokes[14][numdof2d];2638 double LprimeStokes[14][numdof2d];2639 double DLStokes[14][14]={0.0};2640 double Ke_drag_gaussian[numdof2d][numdof2d];2641 Friction* friction=NULL;2642 GaussPenta *gauss=NULL;2643 2644 /*If on water or not Stokes, skip stiffness: */2645 inputs->GetParameterValue(&approximation,ApproximationEnum);2646 if(IsOnWater() || IsOnShelf() || !IsOnBed() || (approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum)) return NULL;2647 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);2648 2649 /*Retrieve all inputs and parameters*/2650 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2651 parameters->FindParam(&analysis_type,AnalysisTypeEnum);2652 parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);2653 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2654 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2655 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);2656 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];2657 2658 /*build friction object, used later on: */2659 friction=new Friction("3d",inputs,matpar,analysis_type);2660 2661 /* Start looping on the number of gaussian points: */2662 gauss=new GaussPenta(0,1,2,2);2663 for (ig=gauss->begin();ig<gauss->end();ig++){2664 2665 gauss->GaussPoint(ig);2666 2667 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);2668 GetLStokes(&LStokes[0][0], gauss);2669 GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss);2670 2671 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);2672 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);2673 2674 BedNormal(&bed_normal[0],xyz_list_tria);2675 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);2676 2677 DLStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;2678 DLStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;2679 DLStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];2680 DLStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];2681 DLStokes[4][4]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];2682 DLStokes[5][5]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];2683 DLStokes[6][6]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];2684 DLStokes[7][7]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];2685 DLStokes[8][8]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[2];2686 DLStokes[9][9]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0]/2.0;2687 DLStokes[10][10]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1]/2.0;2688 DLStokes[11][11]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];2689 DLStokes[12][12]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];2690 DLStokes[13][13]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[2];2691 2692 TripleMultiply( &LStokes[0][0],14,numdof2d,1,2693 &DLStokes[0][0],14,14,0,2694 &LprimeStokes[0][0],14,numdof2d,0,2695 &Ke_drag_gaussian[0][0],0);2696 2697 for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof+j]+=Ke_drag_gaussian[i][j];2698 }2699 2700 /*Clean up and return*/2701 delete gauss;2702 delete friction;2703 return Ke;2704 }2705 /*}}}*/2706 /*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/2707 ElementMatrix* Penta::CreateKMatrixDiagnosticVert(void){2708 2709 /*compute all stiffness matrices for this element*/2710 ElementMatrix* Ke1=CreateKMatrixDiagnosticVertVolume();2711 ElementMatrix* Ke2=CreateKMatrixDiagnosticVertSurface();2712 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);2713 2714 /*clean-up and return*/2715 delete Ke1;2716 delete Ke2;2717 return Ke;2718 }2719 /*}}}*/2720 /*FUNCTION Penta::CreateKMatrixDiagnosticVertVolume {{{1*/2721 ElementMatrix* Penta::CreateKMatrixDiagnosticVertVolume(void){2722 2723 /*Constants*/2724 const int numdof=NDOF1*NUMVERTICES;2725 2726 /*Intermediaries */2727 int i,j,ig;2728 double Jdet;2729 double xyz_list[NUMVERTICES][3];2730 double B[NDOF1][NUMVERTICES];2731 double Bprime[NDOF1][NUMVERTICES];2732 double DL_scalar;2733 double Ke_gg[numdof][numdof]={0.0};2734 GaussPenta *gauss=NULL;2735 2736 /*Initialize Element matrix and return if necessary*/2737 if(IsOnWater()) return NULL;2738 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);2739 2740 /*Retrieve all inputs and parameters*/2741 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2742 2743 /* Start looping on the number of gaussian points: */2744 gauss=new GaussPenta(2,2);2745 for (ig=gauss->begin();ig<gauss->end();ig++){2746 2747 gauss->GaussPoint(ig);2748 2749 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);2750 GetBVert(&B[0][0], &xyz_list[0][0], gauss);2751 GetBprimeVert(&Bprime[0][0], &xyz_list[0][0], gauss);2752 2753 DL_scalar=gauss->weight*Jdet;2754 2755 TripleMultiply( &B[0][0],1,NUMVERTICES,1,2756 &DL_scalar,1,1,0,2757 &Bprime[0][0],1,NUMVERTICES,0,2758 &Ke_gg[0][0],0);2759 2760 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg[i][j];2761 }2762 2763 /*Clean up and return*/2764 delete gauss;2765 return Ke;2766 }2767 /*}}}*/2768 /*FUNCTION Penta::CreateKMatrixDiagnosticVertSurface {{{1*/2769 ElementMatrix* Penta::CreateKMatrixDiagnosticVertSurface(void){2770 2771 if (!IsOnSurface() || IsOnWater()) return NULL;2772 2773 /*Call Tria function*/2774 Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3,4 and 5 are on the surface2775 ElementMatrix* Ke=tria->CreateKMatrixDiagnosticVertSurface();2776 delete tria->matice; delete tria;2777 2778 /*clean up and return*/2779 return Ke;2780 }2781 /*}}}*/2782 /*FUNCTION Penta::CreateKMatrixMelting {{{1*/2783 ElementMatrix* Penta::CreateKMatrixMelting(void){2784 2785 if (!IsOnBed() || IsOnWater()) return NULL;2786 2787 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2788 ElementMatrix* Ke=tria->CreateKMatrixMelting();2789 2790 delete tria->matice; delete tria;2791 return Ke;2792 }2793 /*}}}*/2794 /*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/2795 ElementMatrix* Penta::CreateKMatrixPrognostic(void){2796 2797 if (!IsOnBed() || IsOnWater()) return NULL;2798 2799 /*Depth Averaging Vx and Vy*/2800 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);2801 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);2802 2803 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2804 ElementMatrix* Ke=tria->CreateKMatrixPrognostic();2805 delete tria->matice; delete tria;2806 2807 /*Delete Vx and Vy averaged*/2808 this->inputs->DeleteInput(VxAverageEnum);2809 this->inputs->DeleteInput(VyAverageEnum);2810 2811 /*clean up and return*/2812 return Ke;2813 }2814 /*}}}*/2815 /*FUNCTION Penta::CreateKMatrixSlope {{{1*/2816 ElementMatrix* Penta::CreateKMatrixSlope(void){2817 2818 if (!IsOnBed() || IsOnWater()) return NULL;2819 2820 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2821 ElementMatrix* Ke=tria->CreateKMatrixSlope();2822 delete tria->matice; delete tria;2823 2824 /*clean up and return*/2825 return Ke;2826 }2827 /*}}}*/2828 /*FUNCTION Penta::CreateKMatrixThermal {{{1*/2829 ElementMatrix* Penta::CreateKMatrixThermal(void){2830 2831 /*compute all stiffness matrices for this element*/2832 ElementMatrix* Ke1=CreateKMatrixThermalVolume();2833 ElementMatrix* Ke2=CreateKMatrixThermalShelf();2834 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);2835 2836 /*clean-up and return*/2837 delete Ke1;2838 delete Ke2;2839 return Ke;2840 }2841 /*}}}*/2842 /*FUNCTION Penta::CreateKMatrixThermalVolume {{{1*/2843 ElementMatrix* Penta::CreateKMatrixThermalVolume(void){2844 2845 /*Constants*/2846 const int numdof=NDOF1*NUMVERTICES;2847 2848 /*Intermediaries */2849 int artdiff;2850 int i,j,ig,found=0;2851 double Jdet,u,v,w,epsvel;2852 double gravity,rho_ice,rho_water;2853 double heatcapacity,thermalconductivity,dt;2854 double tau_parameter,diameter;2855 double xyz_list[NUMVERTICES][3];2856 double B[3][numdof];2857 double Bprime[3][numdof];2858 double B_conduct[3][numdof];2859 double B_advec[3][numdof];2860 double B_artdiff[2][numdof];2861 double Bprime_advec[3][numdof];2862 double L[numdof];2863 double dh1dh6[3][6];2864 double D_scalar_conduct,D_scalar_advec;2865 double D_scalar_trans,D_scalar_artdiff;2866 double D[3][3];2867 double K[2][2]={0.0};2868 double Ke_gaussian_conduct[numdof][numdof];2869 double Ke_gaussian_advec[numdof][numdof];2870 double Ke_gaussian_artdiff[numdof][numdof];2871 double Ke_gaussian_transient[numdof][numdof];2872 Tria* tria=NULL;2873 GaussPenta *gauss=NULL;2874 2875 /*Initialize Element matrix and return if necessary*/2876 if(IsOnWater()) return NULL;2877 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);2878 2879 /*Retrieve all inputs and parameters*/2880 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2881 rho_water=matpar->GetRhoWater();2882 rho_ice=matpar->GetRhoIce();2883 gravity=matpar->GetG();2884 heatcapacity=matpar->GetHeatCapacity();2885 thermalconductivity=matpar->GetThermalConductivity();2886 this->inputs->GetParameterValue(&dt,DtEnum);2887 this->parameters->FindParam(&artdiff,ArtDiffEnum);2888 this->parameters->FindParam(&epsvel,EpsVelEnum);2889 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2890 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2891 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);2892 if (artdiff==2) diameter=MinEdgeLength(xyz_list);2893 2894 /* Start looping on the number of gaussian points: */2895 gauss=new GaussPenta(2,2);2896 for (ig=gauss->begin();ig<gauss->end();ig++){2897 2898 gauss->GaussPoint(ig);2899 2900 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);2901 2902 /*Conduction: */2903 2904 GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss);2905 2906 D_scalar_conduct=gauss->weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity));2907 if(dt) D_scalar_conduct=D_scalar_conduct*dt;2908 2909 D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;2910 D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;2911 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;2912 2913 TripleMultiply(&B_conduct[0][0],3,numdof,1,2914 &D[0][0],3,3,0,2915 &B_conduct[0][0],3,numdof,0,2916 &Ke_gaussian_conduct[0][0],0);2917 2918 /*Advection: */2919 2920 GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss);2921 GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss);2922 2923 vx_input->GetParameterValue(&u, gauss);2924 vy_input->GetParameterValue(&v, gauss);2925 vz_input->GetParameterValue(&w, gauss);2926 2927 D_scalar_advec=gauss->weight*Jdet;2928 if(dt) D_scalar_advec=D_scalar_advec*dt;2929 2930 D[0][0]=D_scalar_advec*u;D[0][1]=0; D[0][2]=0;2931 D[1][0]=0; D[1][1]=D_scalar_advec*v;D[1][2]=0;2932 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_advec*w;2933 2934 TripleMultiply(&B_advec[0][0],3,numdof,1,2935 &D[0][0],3,3,0,2936 &Bprime_advec[0][0],3,numdof,0,2937 &Ke_gaussian_advec[0][0],0);2938 2939 /*Transient: */2940 2941 if(dt){2942 GetNodalFunctionsP1(&L[0], gauss);2943 D_scalar_trans=gauss->weight*Jdet;2944 D_scalar_trans=D_scalar_trans;2945 2946 TripleMultiply(&L[0],numdof,1,0,2947 &D_scalar_trans,1,1,0,2948 &L[0],1,numdof,0,2949 &Ke_gaussian_transient[0][0],0);2950 }2951 else{2952 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gaussian_transient[i][j]=0;2953 }2954 2955 /*Artifficial diffusivity*/2956 2957 if(artdiff==1){2958 /*Build K: */2959 D_scalar_artdiff=gauss->weight*Jdet/(pow(u,2)+pow(v,2)+epsvel);2960 if(dt) D_scalar_artdiff=D_scalar_artdiff*dt;2961 K[0][0]=D_scalar_artdiff*pow(u,2); K[0][1]=D_scalar_artdiff*fabs(u)*fabs(v);2962 K[1][0]=D_scalar_artdiff*fabs(u)*fabs(v);K[1][1]=D_scalar_artdiff*pow(v,2);2963 2964 GetBArtdiff(&B_artdiff[0][0],&xyz_list[0][0],gauss);2965 2966 TripleMultiply(&B_artdiff[0][0],2,numdof,1,2967 &K[0][0],2,2,0,2968 &B_artdiff[0][0],2,numdof,0,2969 &Ke_gaussian_artdiff[0][0],0);2970 }2971 else if(artdiff==2){2972 2973 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],&xyz_list[0][0], gauss);2974 2975 tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);2976 2977 for(i=0;i<numdof;i++){2978 for(j=0;j<numdof;j++){2979 Ke_gaussian_artdiff[i][j]=tau_parameter*D_scalar_advec*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i])*(u*dh1dh6[0][j]+v*dh1dh6[1][j]+w*dh1dh6[2][j]);2980 }2981 }2982 if(dt){2983 for(i=0;i<numdof;i++){2984 for(j=0;j<numdof;j++){2985 Ke_gaussian_artdiff[i][j]+=tau_parameter*D_scalar_trans*L[j]*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i]);2986 }2987 }2988 }2989 }2990 else{2991 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gaussian_artdiff[i][j]=0;2992 }2993 2994 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gaussian_conduct[i][j]+Ke_gaussian_advec[i][j]+Ke_gaussian_transient[i][j]+Ke_gaussian_artdiff[i][j];2995 }2996 2997 /*Clean up and return*/2998 delete gauss;2999 return Ke;3000 }3001 /*}}}*/3002 /*FUNCTION Penta::CreateKMatrixThermalShelf {{{1*/3003 ElementMatrix* Penta::CreateKMatrixThermalShelf(void){3004 3005 if (!IsOnBed() || !IsOnShelf() || IsOnWater()) return NULL;3006 3007 /*Call Tria function*/3008 Tria* tria=(Tria*)SpawnTria(0,1,2);3009 ElementMatrix* Ke=tria->CreateKMatrixThermal();3010 delete tria->matice; delete tria;3011 3012 return Ke;3013 }3014 /*}}}*/3015 /*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/3016 ElementVector* Penta::CreatePVectorAdjointHoriz(void){3017 3018 int approximation;3019 inputs->GetParameterValue(&approximation,ApproximationEnum);3020 3021 switch(approximation){3022 case MacAyealApproximationEnum:3023 return CreatePVectorAdjointMacAyeal();3024 case PattynApproximationEnum:3025 return CreatePVectorAdjointPattyn();3026 case NoneApproximationEnum:3027 return NULL;3028 case StokesApproximationEnum:3029 return CreatePVectorAdjointStokes();3030 default:3031 ISSMERROR("Approximation %s not supported yet",EnumToString(approximation));3032 }3033 }3034 /*}}}*/3035 /*FUNCTION Penta::CreatePVectorAdjointMacAyeal{{{1*/3036 ElementVector* Penta::CreatePVectorAdjointMacAyeal(){3037 3038 if (!IsOnBed() || IsOnWater()) return NULL;3039 3040 /*Call Tria function*/3041 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3042 ElementVector* pe=tria->CreatePVectorAdjointHoriz();3043 delete tria->matice; delete tria;3044 3045 /*clean up and return*/3046 return pe;3047 }3048 /*}}}*/3049 /*FUNCTION Penta::CreatePVectorAdjointPattyn{{{1*/3050 ElementVector* Penta::CreatePVectorAdjointPattyn(void){3051 3052 if (!IsOnSurface() || IsOnWater()) return NULL;3053 3054 /*Call Tria function*/3055 Tria* tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).3056 ElementVector* pe=tria->CreatePVectorAdjointHoriz();3057 delete tria->matice; delete tria;3058 3059 /*clean up and return*/3060 return pe;3061 }3062 /*}}}*/3063 /*FUNCTION Penta::CreatePVectorBalancedthickness {{{1*/3064 ElementVector* Penta::CreatePVectorBalancedthickness(void){3065 3066 if (!IsOnBed() || IsOnWater()) return NULL;3067 3068 /*Depth Averaging Vx and Vy*/3069 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);3070 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);3071 3072 /*Call Tria function*/3073 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3074 ElementVector* pe=tria->CreatePVectorBalancedthickness();3075 delete tria->matice; delete tria;3076 3077 /*Delete Vx and Vy averaged*/3078 this->inputs->DeleteInput(VxAverageEnum);3079 this->inputs->DeleteInput(VyAverageEnum);3080 3081 /*Clean up and return*/3082 return pe;3083 }3084 /*}}}*/3085 /*FUNCTION Penta::CreatePVectorBalancedvelocities {{{1*/3086 ElementVector* Penta::CreatePVectorBalancedvelocities(void){3087 3088 if (!IsOnBed() || IsOnWater()) return NULL;3089 3090 /*Depth Averaging Vx and Vy*/3091 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);3092 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);3093 3094 /*Call Tria function*/3095 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3096 ElementVector* pe=tria->CreatePVectorBalancedvelocities();3097 delete tria->matice; delete tria;3098 3099 /*Delete Vx and Vy averaged*/3100 this->inputs->DeleteInput(VxAverageEnum);3101 this->inputs->DeleteInput(VyAverageEnum);3102 3103 /*Clean up and return*/3104 return pe;3105 }3106 /*}}}*/3107 /*FUNCTION Penta::CreatePVectorCouplingPattynStokes {{{1*/3108 ElementVector* Penta::CreatePVectorCouplingPattynStokes(void){3109 3110 /*compute all load vectors for this element*/3111 ElementVector* pe1=CreatePVectorCouplingPattynStokesViscous();3112 ElementVector* pe2=CreatePVectorCouplingPattynStokesFriction();3113 ElementVector* pe =new ElementVector(pe1,pe2);3114 3115 /*clean-up and return*/3116 delete pe1;3117 delete pe2;3118 return pe;3119 }3120 /*}}}*/3121 /*FUNCTION Penta::CreatePVectorCouplingPattynStokesViscous {{{1*/3122 ElementVector* Penta::CreatePVectorCouplingPattynStokesViscous(void){3123 3124 /*Constants*/3125 const int numdof=NUMVERTICES*NDOF4;3126 3127 /*Intermediaries */3128 int i,j,ig;3129 int approximation;3130 double viscosity,Jdet;3131 double stokesreconditioning;3132 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/3133 double dw[3];3134 double xyz_list[NUMVERTICES][3];3135 double l1l6[6]; //for the six nodes of the penta3136 double dh1dh6[3][6]; //for the six nodes of the penta3137 GaussPenta *gauss=NULL;3138 3139 /*Initialize Element vector and return if necessary*/3140 if(IsOnWater()) return NULL;3141 inputs->GetParameterValue(&approximation,ApproximationEnum);3142 if(approximation!=PattynStokesApproximationEnum) return NULL;3143 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);3144 3145 /*Retrieve all inputs and parameters*/3146 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3147 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);3148 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);3149 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);3150 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);3151 Input* vzpattyn_input=inputs->GetInput(VzPattynEnum); ISSMASSERT(vzpattyn_input);3152 3153 /* Start looping on the number of gaussian points: */3154 gauss=new GaussPenta(5,5);3155 for (ig=gauss->begin();ig<gauss->end();ig++){3156 3157 gauss->GaussPoint(ig);3158 3159 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);3160 GetNodalFunctionsP1(&l1l6[0], gauss);3161 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],&xyz_list[0][0], gauss);3162 3163 vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);3164 3165 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);3166 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);3167 3168 for(i=0;i<NUMVERTICES;i++){3169 pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dh1dh6[2][i];3170 pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dh1dh6[2][i];3171 pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dh1dh6[0][i]+dw[1]*dh1dh6[1][i]+2*dw[2]*dh1dh6[2][i]);3172 pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*l1l6[i];3173 }3174 }3175 3176 /*Clean up and return*/3177 delete gauss;3178 return pe;3179 }3180 /*}}}*/3181 /*FUNCTION Penta::CreatePVectorCouplingPattynStokesFriction{{{1*/3182 ElementVector* Penta::CreatePVectorCouplingPattynStokesFriction(void){3183 3184 /*Constants*/3185 const int numdof=NUMVERTICES*NDOF4;3186 3187 /*Intermediaries*/3188 int i,j,ig;3189 int approximation,analysis_type;3190 double Jdet,Jdet2d;3191 double stokesreconditioning;3192 double bed_normal[3];3193 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/3194 double viscosity, w, alpha2_gauss;3195 double dw[3];3196 double xyz_list_tria[NUMVERTICES2D][3];3197 double xyz_list[NUMVERTICES][3];3198 double l1l6[6]; //for the six nodes of the penta3199 Tria* tria=NULL;3200 Friction* friction=NULL;3201 GaussPenta *gauss=NULL;3202 3203 /*Initialize Element vector and return if necessary*/3204 if(IsOnWater() || !IsOnBed() || IsOnShelf()) return NULL;3205 inputs->GetParameterValue(&approximation,ApproximationEnum);3206 if(approximation!=PattynStokesApproximationEnum) return NULL;3207 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);3208 3209 /*Retrieve all inputs and parameters*/3210 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3211 parameters->FindParam(&analysis_type,AnalysisTypeEnum);3212 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);3213 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);3214 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);3215 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);3216 Input* vzpattyn_input=inputs->GetInput(VzPattynEnum); ISSMASSERT(vzpattyn_input);3217 3218 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];3219 3220 /*build friction object, used later on: */3221 friction=new Friction("3d",inputs,matpar,analysis_type);3222 3223 /* Start looping on the number of gauss 2d (nodes on the bedrock) */3224 gauss=new GaussPenta(0,1,2,2);3225 for(ig=gauss->begin();ig<gauss->end();ig++){3226 3227 gauss->GaussPoint(ig);3228 3229 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);3230 GetNodalFunctionsP1(l1l6, gauss);3231 3232 vzpattyn_input->GetParameterValue(&w, gauss);3233 vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);3234 3235 BedNormal(&bed_normal[0],xyz_list_tria);3236 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);3237 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);3238 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);3239 3240 for(i=0;i<NUMVERTICES2D;i++){3241 pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*l1l6[i];3242 pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*l1l6[i];3243 pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*l1l6[i];3244 }3245 }3246 3247 /*Clean up and return*/3248 delete gauss;3249 return pe;3250 }3251 /*}}}*/3252 /*FUNCTION Penta::CreatePVectorDiagnosticHoriz{{{1*/3253 ElementVector* Penta::CreatePVectorDiagnosticHoriz(void){3254 3255 int approximation;3256 inputs->GetParameterValue(&approximation,ApproximationEnum);3257 3258 switch(approximation){3259 case MacAyealApproximationEnum:3260 return CreatePVectorDiagnosticMacAyeal();3261 case PattynApproximationEnum:3262 return CreatePVectorDiagnosticPattyn();3263 case HutterApproximationEnum:3264 return NULL;3265 case NoneApproximationEnum:3266 return NULL;3267 case StokesApproximationEnum:3268 return CreatePVectorDiagnosticStokes();3269 case MacAyealPattynApproximationEnum:3270 return CreatePVectorDiagnosticMacAyealPattyn();3271 case PattynStokesApproximationEnum:3272 return CreatePVectorDiagnosticPattynStokes();3273 default:3274 ISSMERROR("Approximation %s not supported yet",EnumToString(approximation));3275 }3276 }3277 /*}}}*/3278 /*FUNCTION Penta::CreatePVectorDiagnosticMacAyealPattyn{{{1*/3279 ElementVector* Penta::CreatePVectorDiagnosticMacAyealPattyn(void){3280 3281 /*compute all load vectors for this element*/3282 ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();3283 ElementVector* pe2=CreatePVectorDiagnosticPattyn();3284 ElementVector* pe =new ElementVector(pe1,pe2);3285 3286 /*clean-up and return*/3287 delete pe1;3288 delete pe2;3289 return pe;3290 }3291 /*}}}*/3292 /*FUNCTION Penta::CreatePVectorDiagnosticPattynStokes{{{1*/3293 ElementVector* Penta::CreatePVectorDiagnosticPattynStokes(void){3294 3295 /*compute all load vectors for this element*/3296 ElementVector* pe1=CreatePVectorDiagnosticPattyn();3297 ElementVector* pe2=CreatePVectorDiagnosticStokes();3298 ElementVector* pe3=CreatePVectorCouplingPattynStokes();3299 ElementVector* pe =new ElementVector(pe1,pe2,pe3);3300 3301 /*clean-up and return*/3302 delete pe1;3303 delete pe2;3304 delete pe3;3305 return pe;3306 }3307 /*}}}*/3308 /*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/3309 ElementVector* Penta::CreatePVectorDiagnosticHutter(void){3310 3311 /*Constants*/3312 const int numdofs=NDOF2*NUMVERTICES;3313 3314 /*Intermediaries*/3315 int i,j,k,ig;3316 int node0,node1;3317 int connectivity[2];3318 double Jdet;3319 double xyz_list[NUMVERTICES][3];3320 double xyz_list_segment[2][3];3321 double z_list[NUMVERTICES];3322 double z_segment[2],slope[2];3323 double slope2,constant_part;3324 double rho_ice,gravity,n,B;3325 double ub,vb,z_g,surface,thickness;3326 GaussPenta* gauss=NULL;3327 3328 /*Initialize Element vector and return if necessary*/3329 if(IsOnWater()) return NULL;3330 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3331 3332 /*Retrieve all inputs and parameters*/3333 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3334 rho_ice=matpar->GetRhoIce();3335 gravity=matpar->GetG();3336 n=matice->GetN();3337 B=matice->GetB();3338 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);3339 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input);3340 Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); ISSMASSERT(slopex_input);3341 Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); ISSMASSERT(slopey_input);3342 for(i=0;i<NUMVERTICES;i++)z_list[i]=xyz_list[i][2];3343 3344 /*Loop on the three segments*/3345 for(i=0;i<3;i++){3346 node0=i;3347 node1=i+3;3348 3349 for(j=0;j<3;j++){3350 xyz_list_segment[0][j]=xyz_list[node0][j];3351 xyz_list_segment[1][j]=xyz_list[node1][j];3352 }3353 3354 connectivity[0]=nodes[node0]->GetConnectivity();3355 connectivity[1]=nodes[node1]->GetConnectivity();3356 3357 /*Loop on the Gauss points: */3358 gauss=new GaussPenta(node0,node1,3);3359 for(ig=gauss->begin();ig<gauss->end();ig++){3360 gauss->GaussPoint(ig);3361 3362 slopex_input->GetParameterValue(&slope[0],gauss);3363 slopey_input->GetParameterValue(&slope[1],gauss);3364 surface_input->GetParameterValue(&surface,gauss);3365 thickness_input->GetParameterValue(&thickness,gauss);3366 3367 slope2=pow(slope[0],2)+pow(slope[1],2);3368 constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));3369 3370 PentaRef::GetParameterValue(&z_g,&z_list[0],gauss);3371 GetSegmentJacobianDeterminant(&Jdet,&xyz_list_segment[0][0],gauss);3372 3373 if (IsOnSurface()){3374 for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight/(double)connectivity[1];3375 }3376 else{//connectivity is too large, should take only half on it3377 for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight*2/(double)connectivity[1];3378 }3379 }3380 delete gauss;3381 3382 //Deal with lower surface3383 if (IsOnBed()){3384 constant_part=-1.58*pow((double)10.0,-(double)10.0)*rho_ice*gravity*thickness;3385 ub=constant_part*slope[0];3386 vb=constant_part*slope[1];3387 3388 pe->values[2*node0]+=ub/(double)connectivity[0];3389 pe->values[2*node0+1]+=vb/(double)connectivity[0];3390 }3391 }3392 3393 /*Clean up and return*/3394 return pe;3395 }3396 /*}}}*/3397 /*FUNCTION Penta::CreatePVectorDiagnosticMacAyeal{{{1*/3398 ElementVector* Penta::CreatePVectorDiagnosticMacAyeal(void){3399 3400 if (!IsOnBed() || IsOnWater()) return NULL;3401 3402 /*Call Tria function*/3403 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3404 ElementVector* pe=tria->CreatePVectorDiagnosticMacAyeal();3405 delete tria->matice; delete tria;3406 3407 /*Clean up and return*/3408 return pe;3409 }3410 /*}}}*/3411 /*FUNCTION Penta::CreatePVectorDiagnosticPattyn{{{1*/3412 ElementVector* Penta::CreatePVectorDiagnosticPattyn(void){3413 3414 /*Constants*/3415 const int numdof=NDOF2*NUMVERTICES;3416 3417 /*Intermediaries*/3418 int i,j,ig;3419 double Jdet;3420 double slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also!3421 double driving_stress_baseline,thickness;3422 double xyz_list[NUMVERTICES][3];3423 double l1l6[6];3424 GaussPenta *gauss=NULL;3425 3426 /*Initialize Element vector and return if necessary*/3427 if(IsOnWater()) return NULL;3428 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);3429 3430 /*Retrieve all inputs and parameters*/3431 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3432 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);3433 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input);3434 3435 /* Start looping on the number of gaussian points: */3436 gauss=new GaussPenta(2,3);3437 for (ig=gauss->begin();ig<gauss->end();ig++){3438 3439 gauss->GaussPoint(ig);3440 3441 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);3442 GetNodalFunctionsP1(l1l6, gauss);3443 3444 thickness_input->GetParameterValue(&thickness, gauss);3445 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);3446 3447 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG();3448 3449 for(i=0;i<NUMVERTICES;i++) for(j=0;j<NDOF2;j++) pe->values[i*NDOF2+j]+= -driving_stress_baseline*slope[j]*Jdet*gauss->weight*l1l6[i];3450 }3451 3452 /*Clean up and return*/3453 delete gauss;3454 return pe;3455 }3456 /*}}}*/3457 /*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/3458 ElementVector* Penta::CreatePVectorDiagnosticStokes(void){3459 3460 /*compute all load vectors for this element*/3461 ElementVector* pe1=CreatePVectorDiagnosticStokesViscous();3462 ElementVector* pe2=CreatePVectorDiagnosticStokesShelf();3463 ElementVector* pe =new ElementVector(pe1,pe2);3464 3465 /*clean-up and return*/3466 delete pe1;3467 delete pe2;3468 return pe;3469 }3470 /*}}}*/3471 /*FUNCTION Penta::CreatePVectorDiagnosticStokesViscous {{{1*/3472 ElementVector* Penta::CreatePVectorDiagnosticStokesViscous(void){3473 3474 /*Constants*/3475 const int numdofbubble=NDOF4*NUMVERTICES+NDOF3*1;3476 3477 /*Intermediaries*/3478 int i,j,ig;3479 int approximation;3480 double Jdet,viscosity;3481 double gravity,rho_ice,stokesreconditioning;3482 double xyz_list[NUMVERTICES][3];3483 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/3484 double l1l7[7]; //for the six nodes and the bubble3485 double B[8][numdofbubble];3486 double B_prime[8][numdofbubble];3487 double B_prime_bubble[8][3];3488 double D[8][8]={0.0};3489 double D_scalar;3490 double Pe_gaussian[numdofbubble]={0.0}; //for the six nodes and the bubble3491 double Ke_temp[numdofbubble][3]={0.0}; //for the six nodes and the bubble3492 double Ke_gaussian[numdofbubble][3];3493 GaussPenta *gauss=NULL;3494 3495 /*Initialize Element vector and return if necessary*/3496 if(IsOnWater()) return NULL;3497 inputs->GetParameterValue(&approximation,ApproximationEnum);3498 if(approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;3499 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);3500 3501 /*Retrieve all inputs and parameters*/3502 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);3503 rho_ice=matpar->GetRhoIce();3504 gravity=matpar->GetG();3505 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3506 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);3507 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);3508 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);3509 3510 /* Start looping on the number of gaussian points: */3511 gauss=new GaussPenta(5,5);3512 for (ig=gauss->begin();ig<gauss->end();ig++){3513 3514 gauss->GaussPoint(ig);3515 3516 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);3517 GetBStokes(&B[0][0],&xyz_list[0][0],gauss);3518 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss);3519 GetNodalFunctionsMINI(&l1l7[0], gauss);3520 3521 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);3522 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);3523 3524 for(i=0;i<NUMVERTICES+1;i++){3525 Pe_gaussian[i*NDOF4+2]+=-rho_ice*gravity*Jdet*gauss->weight*l1l7[i];3526 }3527 3528 /*Get bubble part of Bprime */3529 for(i=0;i<8;i++) for(j=0;j<3;j++) B_prime_bubble[i][j]=B_prime[i][j+24];3530 3531 D_scalar=gauss->weight*Jdet;3532 for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;3533 for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;3534 3535 TripleMultiply(&B[0][0],8,numdofbubble,1,3536 &D[0][0],8,8,0,3537 &B_prime_bubble[0][0],8,3,0,3538 &Ke_gaussian[0][0],0);3539 3540 for(i=0;i<numdofbubble;i++) for(j=0;j<NDOF3;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];3541 }3542 3543 /*Condensation*/3544 ReduceVectorStokes(pe->values, &Ke_temp[0][0], &Pe_gaussian[0]);3545 3546 /*Clean up and return*/3547 delete gauss;3548 return pe;3549 }3550 /*}}}*/3551 /*FUNCTION Penta::CreatePVectorDiagnosticStokesShelf{{{1*/3552 ElementVector* Penta::CreatePVectorDiagnosticStokesShelf(void){3553 3554 /*Intermediaries*/3555 int i,j,ig;3556 int approximation;3557 double gravity,rho_water,bed,water_pressure;3558 double xyz_list_tria[NUMVERTICES2D][3];3559 double xyz_list[NUMVERTICES][3];3560 double bed_normal[3];3561 double l1l6[6]; //for the six nodes of the penta3562 double Jdet2d;3563 GaussPenta *gauss=NULL;3564 3565 /*Initialize Element vector and return if necessary*/3566 if(IsOnWater() || !IsOnBed() || !IsOnShelf()) return NULL;3567 inputs->GetParameterValue(&approximation,ApproximationEnum);3568 if(approximation!=StokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;3569 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);3570 3571 /*Retrieve all inputs and parameters*/3572 rho_water=matpar->GetRhoWater();3573 gravity=matpar->GetG();3574 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3575 Input* bed_input=inputs->GetInput(BedEnum); ISSMASSERT(bed_input);3576 3577 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];3578 3579 /* Start looping on the number of gauss 2d (nodes on the bedrock) */3580 gauss=new GaussPenta(0,1,2,2);3581 for(ig=gauss->begin();ig<gauss->end();ig++){3582 3583 gauss->GaussPoint(ig);3584 3585 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);3586 GetNodalFunctionsP1(l1l6, gauss);3587 3588 bed_input->GetParameterValue(&bed, gauss);3589 BedNormal(&bed_normal[0],xyz_list_tria);3590 water_pressure=gravity*rho_water*bed;3591 3592 for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) pe->values[i*NDOF4+j]+=water_pressure*gauss->weight*Jdet2d*l1l6[i]*bed_normal[j];3593 }3594 3595 /*Clean up and return*/3596 delete gauss;3597 return pe;3598 }3599 /*}}}*/3600 /*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/3601 ElementVector* Penta::CreatePVectorAdjointStokes(void){3602 3603 if (!IsOnSurface() || IsOnWater()) return NULL;3604 3605 /*Call Tria function*/3606 Tria* tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).3607 ElementVector* pe=tria->CreatePVectorAdjointStokes();3608 delete tria->matice; delete tria;3609 3610 /*clean up and return*/3611 return pe;3612 }3613 /*}}}*/3614 /*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/3615 ElementVector* Penta::CreatePVectorDiagnosticVert(void){3616 3617 /*compute all load vectors for this element*/3618 ElementVector* pe1=CreatePVectorDiagnosticVertVolume();3619 ElementVector* pe2=CreatePVectorDiagnosticVertBase();3620 ElementVector* pe =new ElementVector(pe1,pe2);3621 3622 /*clean-up and return*/3623 delete pe1;3624 delete pe2;3625 return pe;3626 }3627 /*}}}*/3628 /*FUNCTION Penta::CreatePVectorDiagnosticVertVolume {{{1*/3629 ElementVector* Penta::CreatePVectorDiagnosticVertVolume(void){3630 3631 /*Constants*/3632 const int numdof=NDOF1*NUMVERTICES;3633 3634 /*Intermediaries*/3635 int i,ig;3636 int approximation;3637 double Jdet;3638 double xyz_list[NUMVERTICES][3];3639 double dudx,dvdy,dwdz;3640 double du[3],dv[3],dw[3];3641 double l1l6[6];3642 GaussPenta *gauss=NULL;3643 3644 /*Initialize Element vector and return if necessary*/3645 if(IsOnWater()) return NULL;3646 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3647 3648 /*Retrieve all inputs and parameters*/3649 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3650 inputs->GetParameterValue(&approximation,ApproximationEnum);3651 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);3652 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);3653 Input* vzstokes_input=NULL;3654 if(approximation==PattynStokesApproximationEnum){3655 vzstokes_input=inputs->GetInput(VzStokesEnum); ISSMASSERT(vzstokes_input);3656 }3657 3658 /* Start looping on the number of gaussian points: */3659 gauss=new GaussPenta(2,2);3660 for (ig=gauss->begin();ig<gauss->end();ig++){3661 3662 gauss->GaussPoint(ig);3663 3664 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);3665 GetNodalFunctionsP1(l1l6, gauss);3666 3667 vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss);3668 vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss);3669 if(approximation==PattynStokesApproximationEnum){3670 vzstokes_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);3671 dwdz=dw[2];3672 }3673 else dwdz=0;3674 dudx=du[0];3675 dvdy=dv[1];3676 3677 for (i=0;i<numdof;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*l1l6[i];3678 }3679 3680 /*Clean up and return*/3681 delete gauss;3682 return pe;3683 }3684 /*}}}*/3685 /*FUNCTION Penta::CreatePVectorDiagnosticVertBase {{{1*/3686 ElementVector* Penta::CreatePVectorDiagnosticVertBase(void){3687 3688 if (!IsOnBed() || IsOnWater()) return NULL;3689 3690 /*Call Tria function*/3691 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3692 ElementVector* pe=tria->CreatePVectorDiagnosticBaseVert();3693 delete tria->matice; delete tria;3694 3695 /*Clean up and return*/3696 return pe;3697 }3698 /*}}}*/3699 /*FUNCTION Penta::CreatePVectorMelting {{{1*/3700 ElementVector* Penta::CreatePVectorMelting(void){3701 return NULL;3702 }3703 /*}}}*/3704 /*FUNCTION Penta::CreatePVectorPrognostic {{{1*/3705 ElementVector* Penta::CreatePVectorPrognostic(void){3706 3707 if (!IsOnBed() || IsOnWater()) return NULL;3708 3709 /*Depth Averaging Vx and Vy*/3710 this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);3711 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);3712 3713 /*Call Tria function*/3714 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3715 ElementVector* pe=tria->CreatePVectorPrognostic();3716 delete tria->matice; delete tria;3717 3718 /*Delete Vx and Vy averaged*/3719 this->inputs->DeleteInput(VxAverageEnum);3720 this->inputs->DeleteInput(VyAverageEnum);3721 3722 /*Clean up and return*/3723 return pe;3724 }3725 /*}}}*/3726 /*FUNCTION Penta::CreatePVectorSlope {{{1*/3727 ElementVector* Penta::CreatePVectorSlope(void){3728 3729 if (!IsOnBed() || IsOnWater()) return NULL;3730 3731 /*Call Tria function*/3732 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3733 ElementVector* pe=tria->CreatePVectorSlope();3734 delete tria->matice; delete tria;3735 3736 /*clean up and return*/3737 return pe;3738 }3739 /*}}}*/3740 /*FUNCTION Penta::CreatePVectorThermal {{{1*/3741 ElementVector* Penta::CreatePVectorThermal(void){3742 3743 /*compute all load vectors for this element*/3744 ElementVector* pe1=CreatePVectorThermalVolume();3745 ElementVector* pe2=CreatePVectorThermalSheet();3746 ElementVector* pe3=CreatePVectorThermalShelf();3747 ElementVector* pe =new ElementVector(pe1,pe2,pe3);3748 3749 /*clean-up and return*/3750 delete pe1;3751 delete pe2;3752 delete pe3;3753 return pe;3754 }3755 /*}}}*/3756 /*FUNCTION Penta::CreatePVectorThermalVolume {{{1*/3757 ElementVector* Penta::CreatePVectorThermalVolume(void){3758 3759 /*Constants*/3760 const int numdof=NUMVERTICES*NDOF1;3761 3762 /*Intermediaries*/3763 int i,j,ig,found=0;3764 int friction_type,artdiff;3765 double Jdet,phi,dt;3766 double rho_ice,heatcapacity;3767 double thermalconductivity;3768 double viscosity,temperature;3769 double tau_parameter,diameter;3770 double u,v,w;3771 double scalar_def,scalar_transient;3772 double temperature_list[NUMVERTICES];3773 double xyz_list[NUMVERTICES][3];3774 double L[numdof];3775 double dh1dh6[3][6];3776 double epsilon[6];3777 GaussPenta *gauss=NULL;3778 3779 /*Initialize Element vector and return if necessary*/3780 if(IsOnWater()) return NULL;3781 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3782 3783 /*Retrieve all inputs and parameters*/3784 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3785 rho_ice=matpar->GetRhoIce();3786 heatcapacity=matpar->GetHeatCapacity();3787 thermalconductivity=matpar->GetThermalConductivity();3788 this->inputs->GetParameterValue(&dt,DtEnum);3789 this->parameters->FindParam(&artdiff,ArtDiffEnum);3790 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);3791 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);3792 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);3793 Input* temperature_input=NULL;3794 if (dt) temperature_input=inputs->GetInput(TemperatureEnum); ISSMASSERT(inputs);3795 if (artdiff==2) diameter=MinEdgeLength(xyz_list);3796 3797 /* Start looping on the number of gaussian points: */3798 gauss=new GaussPenta(2,3);3799 for (ig=gauss->begin();ig<gauss->end();ig++){3800 3801 gauss->GaussPoint(ig);3802 3803 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);3804 GetNodalFunctionsP1(&L[0], gauss);3805 3806 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);3807 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);3808 GetPhi(&phi, &epsilon[0], viscosity);3809 3810 scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight;3811 if(dt) scalar_def=scalar_def*dt;3812 3813 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=scalar_def*L[i];3814 3815 /* Build transient now */3816 if(dt){3817 temperature_input->GetParameterValue(&temperature, gauss);3818 scalar_transient=temperature*Jdet*gauss->weight;3819 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=scalar_transient*L[i];3820 }3821 3822 if(artdiff==2){3823 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],&xyz_list[0][0], gauss);3824 3825 vx_input->GetParameterValue(&u, gauss);3826 vy_input->GetParameterValue(&v, gauss);3827 vz_input->GetParameterValue(&w, gauss);3828 3829 tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);3830 3831 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=tau_parameter*scalar_def*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i]);3832 if(dt){3833 for(i=0;i<NUMVERTICES;i++) pe->values[i]+=tau_parameter*scalar_transient*(u*dh1dh6[0][i]+v*dh1dh6[1][i]+w*dh1dh6[2][i]);3834 }3835 }3836 }3837 3838 /*Clean up and return*/3839 delete gauss;3840 return pe;3841 }3842 /*}}}*/3843 /*FUNCTION Penta::CreatePVectorThermalShelf {{{1*/3844 ElementVector* Penta::CreatePVectorThermalShelf(void){3845 3846 /* Ice/ocean heat exchange flux on ice shelf base */3847 if (!IsOnBed() || !IsOnShelf() || IsOnWater()) return NULL;3848 3849 /*Call Tria function*/3850 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3851 ElementVector* pe=tria->CreatePVectorThermalShelf();3852 delete tria->matice; delete tria;3853 3854 /*Clean up and return*/3855 return pe;3856 }3857 /*}}}*/3858 /*FUNCTION Penta::CreatePVectorThermalSheet {{{1*/3859 ElementVector* Penta::CreatePVectorThermalSheet(void){3860 3861 /* Geothermal flux on ice sheet base and basal friction */3862 if (!IsOnBed() || IsOnShelf() || IsOnWater()) return NULL;3863 3864 /*Call Tria function*/3865 Tria* tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3866 ElementVector* pe=tria->CreatePVectorThermalSheet();3867 delete tria->matice; delete tria;3868 3869 /*Clean up and return*/3870 return pe;3871 }3872 /*}}}*/3873 /*FUNCTION Penta::GetDofList {{{1*/3874 void Penta::GetDofList(int** pdoflist,int approximation_enum,int setenum){3875 3876 int i,j,count=0;3877 int numberofdofs=0;3878 int* doflist=NULL;3879 3880 /*First, figure out size of doflist: */3881 for(i=0;i<6;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);3882 3883 /*Allocate: */3884 doflist=(int*)xmalloc(numberofdofs*sizeof(int));3885 3886 /*Populate: */3887 count=0;3888 for(i=0;i<6;i++){3889 nodes[i]->GetDofList(doflist+count,approximation_enum,setenum);3890 count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);3891 }3892 3893 /*Assign output pointers:*/3894 *pdoflist=doflist;3895 }3896 /*}}}*/3897 /*FUNCTION Penta::GetDofList1 {{{1*/3898 void Penta::GetDofList1(int* doflist){3899 3900 int i;3901 for(i=0;i<6;i++) doflist[i]=nodes[i]->GetDofList1();3902 3903 }3904 /*}}}*/3905 /*FUNCTION Penta::GetSidList{{{1*/3906 void Penta::GetSidList(int* sidlist){3907 3908 int i;3909 for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList();3910 3911 }3912 /*}}}*/3913 /*FUNCTION Penta::GetElementType {{{1*/3914 int Penta::GetElementType(){3915 3916 /*return PentaRef field*/3917 return this->element_type;3918 }3919 /*}}}*/3920 /*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/3921 void Penta::GetParameterListOnVertices(double* pvalue,int enumtype){3922 3923 /*Intermediaries*/3924 double value[NUMVERTICES];3925 GaussPenta *gauss = NULL;3926 3927 /*Recover input*/3928 Input* input=inputs->GetInput(enumtype);3929 if (!input) ISSMERROR("Input %s not found in element",EnumToString(enumtype));3930 3931 /*Checks in debugging mode*/3932 ISSMASSERT(pvalue);3933 3934 /* Start looping on the number of vertices: */3935 gauss=new GaussPenta();3936 for (int iv=0;iv<NUMVERTICES;iv++){3937 gauss->GaussVertex(iv);3938 input->GetParameterValue(&pvalue[iv],gauss);3939 }3940 3941 /*clean-up*/3942 delete gauss;3943 }3944 /*}}}*/3945 /*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/3946 void Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){3947 3948 /*Intermediaries*/3949 double value[NUMVERTICES];3950 GaussPenta *gauss = NULL;3951 3952 /*Recover input*/3953 Input* input=inputs->GetInput(enumtype);3954 3955 /*Checks in debugging mode*/3956 ISSMASSERT(pvalue);3957 3958 /* Start looping on the number of vertices: */3959 if (input){3960 gauss=new GaussPenta();3961 for (int iv=0;iv<NUMVERTICES;iv++){3962 gauss->GaussVertex(iv);3963 input->GetParameterValue(&pvalue[iv],gauss);3964 }3965 }3966 else{3967 for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;3968 }3969 3970 /*clean-up*/3971 delete gauss;3972 }3973 /*}}}*/3974 /*FUNCTION Penta::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/3975 void Penta::GetParameterValue(double* pvalue,Node* node,int enumtype){3976 3977 Input* input=inputs->GetInput(enumtype);3978 if(!input) ISSMERROR("No input of type %s found in tria",EnumToString(enumtype));3979 3980 GaussPenta* gauss=new GaussPenta();3981 gauss->GaussVertex(this->GetNodeIndex(node));3982 3983 input->GetParameterValue(pvalue,gauss);3984 delete gauss;3985 }3986 /*}}}*/3987 /*FUNCTION Penta::GetPhi {{{1*/3988 void Penta::GetPhi(double* phi, double* epsilon, double viscosity){3989 /*Compute deformational heating from epsilon and viscosity */3990 3991 double epsilon_matrix[3][3];3992 double epsilon_eff;3993 double epsilon_sqr[3][3];3994 3995 /* Build epsilon matrix */3996 epsilon_matrix[0][0]=*(epsilon+0);3997 epsilon_matrix[1][0]=*(epsilon+3);3998 epsilon_matrix[2][0]=*(epsilon+4);3999 epsilon_matrix[0][1]=*(epsilon+3);4000 epsilon_matrix[1][1]=*(epsilon+1);4001 epsilon_matrix[2][1]=*(epsilon+5);4002 epsilon_matrix[0][2]=*(epsilon+4);4003 epsilon_matrix[1][2]=*(epsilon+5);4004 epsilon_matrix[2][2]=*(epsilon+2);4005 4006 /* Effective value of epsilon_matrix */4007 epsilon_sqr[0][0]=pow(epsilon_matrix[0][0],2);4008 epsilon_sqr[1][0]=pow(epsilon_matrix[1][0],2);4009 epsilon_sqr[2][0]=pow(epsilon_matrix[2][0],2);4010 epsilon_sqr[0][1]=pow(epsilon_matrix[0][1],2);4011 epsilon_sqr[1][1]=pow(epsilon_matrix[1][1],2);4012 epsilon_sqr[2][1]=pow(epsilon_matrix[2][1],2);4013 epsilon_sqr[0][2]=pow(epsilon_matrix[0][2],2);4014 epsilon_sqr[1][2]=pow(epsilon_matrix[1][2],2);4015 epsilon_sqr[2][2]=pow(epsilon_matrix[2][2],2);4016 epsilon_eff=1/pow(2,0.5)*pow((epsilon_sqr[0][0]+epsilon_sqr[0][1]+ epsilon_sqr[0][2]+ epsilon_sqr[1][0]+ epsilon_sqr[1][1]+ epsilon_sqr[1][2]+ epsilon_sqr[2][0]+ epsilon_sqr[2][1]+ epsilon_sqr[2][2]),0.5);4017 4018 /*Phi = Tr(sigma * eps)4019 * = Tr(sigma'* eps)4020 * = 2 * eps_eff * sigma'_eff4021 * = 4 * eps_eff ^2*/4022 *phi=4*pow(epsilon_eff,2.0)*viscosity;4023 }4024 /*}}}*/4025 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/4026 void Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){4027 4028 const int numdof=NDOF2*NUMVERTICES;4029 4030 int i;4031 int approximation;4032 int* doflist=NULL;4033 double vx,vy;4034 double values[numdof];4035 GaussPenta* gauss;4036 4037 /*Get approximation enum and dof list: */4038 inputs->GetParameterValue(&approximation,ApproximationEnum);4039 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);4040 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);4041 4042 /*If the element is a coupling, do nothing: every grid is also on an other elements4043 * (as coupling is between MacAyeal and Pattyn) so the other element will take care of it*/4044 GetDofList(&doflist,approximation,GsetEnum);4045 4046 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4047 /*P1 element only for now*/4048 gauss=new GaussPenta();4049 for(i=0;i<NUMVERTICES;i++){4050 4051 /*Recover vx and vy*/4052 gauss->GaussVertex(i);4053 vx_input->GetParameterValue(&vx,gauss);4054 vy_input->GetParameterValue(&vy,gauss);4055 values[i*NDOF2+0]=vx;4056 values[i*NDOF2+1]=vy;4057 }4058 4059 /*Add value to global vector*/4060 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);4061 4062 /*Free ressources:*/4063 delete gauss;4064 xfree((void**)&doflist);4065 }4066 /*}}}*/4067 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/4068 void Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){4069 4070 const int numdof=NDOF2*NUMVERTICES;4071 4072 int i;4073 int* doflist=NULL;4074 double vx,vy;4075 double values[numdof];4076 GaussPenta* gauss=NULL;4077 4078 /*Get dof list: */4079 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4080 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);4081 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);4082 4083 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4084 /*P1 element only for now*/4085 gauss=new GaussPenta();4086 for(i=0;i<NUMVERTICES;i++){4087 /*Recover vx and vy*/4088 gauss->GaussVertex(i);4089 vx_input->GetParameterValue(&vx,gauss);4090 vy_input->GetParameterValue(&vy,gauss);4091 values[i*NDOF2+0]=vx;4092 values[i*NDOF2+1]=vy;4093 }4094 4095 /*Add value to global vector*/4096 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);4097 4098 /*Free ressources:*/4099 delete gauss;4100 xfree((void**)&doflist);4101 }4102 /*}}}*/4103 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/4104 void Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){4105 4106 const int numdof=NDOF1*NUMVERTICES;4107 4108 int i;4109 int* doflist=NULL;4110 double vz;4111 double values[numdof];4112 GaussPenta* gauss=NULL;4113 4114 /*Get dof list: */4115 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4116 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);4117 4118 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4119 /*P1 element only for now*/4120 gauss=new GaussPenta();4121 for(i=0;i<NUMVERTICES;i++){4122 /*Recover vz */4123 gauss->GaussVertex(i);4124 vz_input->GetParameterValue(&vz,gauss);4125 values[i]=vz;4126 }4127 4128 /*Add value to global vector*/4129 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);4130 4131 /*Free ressources:*/4132 delete gauss;4133 xfree((void**)&doflist);4134 }4135 /*}}}*/4136 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/4137 void Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){4138 4139 const int numdof=NDOF4*NUMVERTICES;4140 4141 int i;4142 int* doflist=NULL;4143 double vx,vy,vz,p;4144 double stokesreconditioning;4145 double values[numdof];4146 GaussPenta *gauss;4147 4148 /*Get dof list: */4149 GetDofList(&doflist,StokesApproximationEnum,GsetEnum);4150 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);4151 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);4152 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);4153 Input* p_input =inputs->GetInput(PressureEnum); ISSMASSERT(p_input);4154 4155 /*Recondition pressure: */4156 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);4157 4158 /*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */4159 /*P1 element only for now*/4160 gauss=new GaussPenta();4161 for(i=0;i<NUMVERTICES;i++){4162 gauss->GaussVertex(i);4163 vx_input->GetParameterValue(&vx,gauss);4164 vy_input->GetParameterValue(&vy,gauss);4165 vz_input->GetParameterValue(&vz,gauss);4166 p_input ->GetParameterValue(&p ,gauss);4167 values[i*NDOF4+0]=vx;4168 values[i*NDOF4+1]=vy;4169 values[i*NDOF4+2]=vz;4170 values[i*NDOF4+3]=p/stokesreconditioning;4171 }4172 4173 /*Add value to global vector*/4174 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);4175 4176 /*Free ressources:*/4177 delete gauss;4178 xfree((void**)&doflist);4179 }4180 /*}}}*/4181 /*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/4182 void Penta::GetSolutionFromInputsThermal(Vec solution){4183 4184 const int numdof=NDOF1*NUMVERTICES;4185 4186 int i;4187 int* doflist=NULL;4188 double values[numdof];4189 double temp;4190 GaussPenta *gauss=NULL;4191 4192 /*Get dof list: */4193 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4194 Input* t_input=inputs->GetInput(TemperatureEnum); ISSMASSERT(t_input);4195 4196 gauss=new GaussPenta();4197 for(i=0;i<NUMVERTICES;i++){4198 /*Recover temperature*/4199 gauss->GaussVertex(i);4200 t_input->GetParameterValue(&temp,gauss);4201 values[i]=temp;4202 }4203 4204 /*Add value to global vector*/4205 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);4206 4207 /*Free ressources:*/4208 delete gauss;4209 xfree((void**)&doflist);4210 }4211 /*}}}*/4212 /*FUNCTION Penta::GetStabilizationParameter {{{1*/4213 double Penta::GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity){4214 /*Compute stabilization parameter*/4215 4216 double normu;4217 double tau_parameter;4218 4219 normu=pow(pow(u,2)+pow(v,2)+pow(w,2),0.5);4220 if(normu*diameter/(3*2*thermalconductivity/(rho_ice*heatcapacity))<1){4221 tau_parameter=pow(diameter,2)/(3*2*2*thermalconductivity/(rho_ice*heatcapacity));4222 }4223 else tau_parameter=diameter/(2*normu);4224 4225 return tau_parameter;4226 }4227 /*}}}*/4228 /*FUNCTION Penta::GetStrainRate3dPattyn{{{1*/4229 void Penta::GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input){4230 /*Compute the 3d Blatter/PattynStrain Rate (5 components):4231 *4232 * epsilon=[exx eyy exy exz eyz]4233 *4234 * with exz=1/2 du/dz4235 * eyz=1/2 dv/dz4236 *4237 * the contribution of vz is neglected4238 */4239 4240 int i;4241 double epsilonvx[5];4242 double epsilonvy[5];4243 4244 /*Check that both inputs have been found*/4245 if (!vx_input || !vy_input){4246 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input);4247 }4248 4249 /*Get strain rate assuming that epsilon has been allocated*/4250 vx_input->GetVxStrainRate3dPattyn(epsilonvx,xyz_list,gauss);4251 vy_input->GetVyStrainRate3dPattyn(epsilonvy,xyz_list,gauss);4252 4253 /*Sum all contributions*/4254 for(i=0;i<5;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];4255 }4256 /*}}}*/4257 /*FUNCTION Penta::GetStrainRate3d{{{1*/4258 void Penta::GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input){4259 /*Compute the 3d Strain Rate (6 components):4260 *4261 * epsilon=[exx eyy ezz exy exz eyz]4262 */4263 4264 int i;4265 double epsilonvx[6];4266 double epsilonvy[6];4267 double epsilonvz[6];4268 4269 /*Check that both inputs have been found*/4270 if (!vx_input || !vy_input || !vz_input){4271 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p, vz: %p\n",vx_input,vy_input,vz_input);4272 }4273 4274 /*Get strain rate assuming that epsilon has been allocated*/4275 vx_input->GetVxStrainRate3d(epsilonvx,xyz_list,gauss);4276 vy_input->GetVyStrainRate3d(epsilonvy,xyz_list,gauss);4277 vz_input->GetVzStrainRate3d(epsilonvz,xyz_list,gauss);4278 4279 /*Sum all contributions*/4280 for(i=0;i<6;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]+epsilonvz[i];4281 }4282 /*}}}*/4283 /*FUNCTION Penta::GetBasalElement{{{1*/4284 Penta* Penta::GetBasalElement(void){4285 4286 /*Output*/4287 Penta* penta=NULL;4288 4289 /*Go through all elements till the bed is reached*/4290 penta=this;4291 for(;;){4292 /*Stop if we have reached the surface, else, take lower penta*/4293 if (penta->IsOnBed()) break;4294 4295 /* get lower Penta*/4296 penta=penta->GetLowerElement();4297 ISSMASSERT(penta->Id()!=this->id);4298 }4299 4300 /*return output*/4301 return penta;4302 }4303 /*}}}*/4304 /*FUNCTION Penta::GetLowerElement{{{1*/4305 Penta* Penta::GetLowerElement(void){4306 4307 Penta* upper_penta=NULL;4308 4309 upper_penta=(Penta*)neighbors[0]; //first one (0) under, second one (1) above4310 4311 return upper_penta;4312 }4313 /*}}}*/4314 /*FUNCTION Penta::GetUpperElement{{{1*/4315 Penta* Penta::GetUpperElement(void){4316 4317 Penta* upper_penta=NULL;4318 4319 upper_penta=(Penta*)neighbors[1]; //first one under, second one above4320 4321 return upper_penta;4322 }4323 /*}}}*/4324 /*FUNCTION Penta::GetZcoord {{{1*/4325 double Penta::GetZcoord(GaussPenta* gauss){4326 4327 int i;4328 double z;4329 double xyz_list[NUMVERTICES][3];4330 double z_list[NUMVERTICES];4331 4332 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4333 for(i=0;i<NUMVERTICES;i++) z_list[i]=xyz_list[i][2];4334 PentaRef::GetParameterValue(&z,z_list,gauss);4335 4336 return z;4337 }4338 /*}}}*/4339 /*FUNCTION Penta::GradjB {{{1*/4340 void Penta::GradjB(Vec gradient){4341 4342 int i;4343 int approximation;4344 Tria* tria =NULL;4345 TriaVertexInput* triavertexinput=NULL;4346 4347 /*If on water, skip: */4348 if(IsOnWater())return;4349 inputs->GetParameterValue(&approximation,ApproximationEnum);4350 4351 if (approximation==MacAyealApproximationEnum){4352 /*Bail out element if MacAyeal (2d) and not on bed*/4353 if (!IsOnBed()) return;4354 4355 /*This element should be collapsed into a tria element at its base. Create this tria element,4356 * and compute gardj*/4357 4358 /*Depth Average B*/4359 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum);4360 4361 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).4362 tria->GradjB(gradient);4363 delete tria->matice; delete tria;4364 4365 /*delete B average*/4366 this->matice->inputs->DeleteInput(RheologyBbarEnum);4367 }4368 else{4369 /*Gradient is computed on bed only (Bbar)*/4370 if (!IsOnBed()) return;4371 4372 /*Depth Average B*/4373 this->InputDepthAverageAtBase(RheologyBEnum,RheologyBbarEnum,MaterialsEnum);4374 4375 /*B is a 2d field, use MacAyeal(2d) gradient even if it is Stokes or Pattyn*/4376 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).4377 tria->GradjB(gradient);4378 delete tria->matice; delete tria;4379 4380 /*delete B average*/4381 this->matice->inputs->DeleteInput(RheologyBbarEnum);4382 }4383 }4384 /*}}}*/4385 /*FUNCTION Penta::GradjDrag {{{1*/4386 void Penta::GradjDrag(Vec gradient){4387 4388 int i,approximation;4389 double temp_gradient[6]={0,0,0,0,0,0};4390 Tria* tria=NULL;4391 TriaVertexInput* triavertexinput=NULL;4392 4393 /*retrieve inputs :*/4394 inputs->GetParameterValue(&approximation,ApproximationEnum);4395 4396 /*If on water, on shelf or not on bed, skip: */4397 if(IsOnWater()|| IsOnShelf() || !IsOnBed())return;4398 4399 if (approximation==MacAyealApproximationEnum || approximation==PattynApproximationEnum){4400 /*MacAyeal or Pattyn*/4401 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4402 tria->GradjDrag(gradient);4403 delete tria->matice; delete tria;4404 }4405 else if (approximation==StokesApproximationEnum){4406 /*Stokes*/4407 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4408 tria->GradjDragStokes(gradient);4409 delete tria->matice; delete tria;4410 }4411 else if (approximation==NoneApproximationEnum){4412 return;4413 }4414 else ISSMERROR("approximation %s not supported yet",EnumToString(approximation));4415 }4416 /*}}}*/4417 /*FUNCTION Penta::InputExtrude {{{1*/4418 void Penta::InputExtrude(int enum_type,int object_type){4419 4420 Penta *penta = NULL;4421 Input *original_input = NULL;4422 4423 /*Are we on the base, not on the surface?:*/4424 if(IsOnBed()){4425 /*OK, we are on bed. we will follow the steps:4426 * 1: find input and extrude it.4427 * 2: follow the upper element until we reach the surface4428 * 3: for each element, we will add a copy of the extruded input*/4429 4430 /*Step1: Extrude the original input: */4431 if (object_type==ElementsEnum)4432 original_input=(Input*)this->inputs->GetInput(enum_type);4433 else if (object_type==MaterialsEnum)4434 original_input=(Input*)matice->inputs->GetInput(enum_type);4435 else4436 ISSMERROR("object of type %s not supported yet",EnumToString(object_type));4437 if(!original_input) ISSMERROR("%s%s"," could not find input with enum:",EnumToString(enum_type));4438 original_input->Extrude();4439 4440 /*Stop if there is only one layer of element*/4441 if (this->IsOnSurface()) return;4442 4443 /*Step 2: this input has been extruded for this element, now follow the upper element*/4444 penta=this;4445 for(;;){4446 4447 /* get upper Penta*/4448 penta=penta->GetUpperElement();4449 ISSMASSERT(penta->Id()!=this->id);4450 4451 /*Add input of the basal element to penta->inputs*/4452 Input* copy=NULL;4453 copy=(Input*)original_input->copy();4454 if (object_type==ElementsEnum)4455 penta->inputs->AddInput((Input*)copy);4456 else if (object_type==MaterialsEnum)4457 penta->matice->inputs->AddInput((Input*)copy);4458 else4459 ISSMERROR("object of type %s not supported yet",EnumToString(object_type));4460 4461 /*Stop if we have reached the surface*/4462 if (penta->IsOnSurface()) break;4463 }4464 }4465 4466 return;4467 }4468 /*}}}*/4469 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHoriz {{{1*/4470 void Penta::InputUpdateFromSolutionDiagnosticHoriz(double* solution){4471 4472 int approximation;4473 4474 /*Recover inputs*/4475 inputs->GetParameterValue(&approximation,ApproximationEnum);4476 4477 /*MacAyeal, everything is done by the element on bed*/4478 if (approximation==MacAyealApproximationEnum){4479 if (!IsOnBed()){4480 /*Do nothing. Element on bed will take care of it*/4481 return;4482 }4483 else{4484 InputUpdateFromSolutionDiagnosticMacAyeal(solution);4485 return;4486 }4487 }4488 else if (approximation==PattynApproximationEnum){4489 InputUpdateFromSolutionDiagnosticPattyn(solution);4490 }4491 else if (approximation==PattynStokesApproximationEnum){4492 InputUpdateFromSolutionDiagnosticPattynStokes(solution);4493 }4494 else if (approximation==MacAyealStokesApproximationEnum){4495 InputUpdateFromSolutionDiagnosticMacAyealStokes(solution);4496 }4497 else if (approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){4498 InputUpdateFromSolutionDiagnosticStokes(solution);4499 }4500 else if (approximation==MacAyealPattynApproximationEnum){4501 InputUpdateFromSolutionDiagnosticMacAyealPattyn(solution);4502 }4503 }4504 /*}}}*/4505 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyeal {{{1*/4506 void Penta::InputUpdateFromSolutionDiagnosticMacAyeal(double* solution){4507 4508 const int numdof=NDOF2*NUMVERTICES;4509 4510 int i,dummy;4511 double rho_ice,g;4512 double values[numdof];4513 double vx[NUMVERTICES];4514 double vy[NUMVERTICES];4515 double vz[NUMVERTICES];4516 double vel[NUMVERTICES];4517 double pressure[NUMVERTICES];4518 double surface[NUMVERTICES];4519 double xyz_list[NUMVERTICES][3];4520 int *doflist = NULL;4521 double *vz_ptr = NULL;4522 Penta *penta = NULL;4523 4524 /*Get dof list: */4525 GetDofList(&doflist,MacAyealApproximationEnum,GsetEnum);4526 4527 /*Use the dof list to index into the solution vector: */4528 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];4529 4530 /*Ok, we have vx and vy in values, fill in vx and vy arrays and extrude */4531 for(i=0;i<3;i++){4532 vx[i] =values[i*NDOF2+0];4533 vy[i] =values[i*NDOF2+1];4534 vx[i+3]=vx[i];4535 vy[i+3]=vy[i];4536 }4537 4538 /*Get parameters fro pressure computation*/4539 rho_ice=matpar->GetRhoIce();4540 g=matpar->GetG();4541 4542 /*Start looping over all elements above current element and update all inputs*/4543 penta=this;4544 for(;;){4545 4546 /*Get node data: */4547 GetVerticesCoordinates(&xyz_list[0][0],penta->nodes,NUMVERTICES);4548 4549 /*Now Compute vel*/4550 Input* vz_input=inputs->GetInput(VzEnum);4551 if (vz_input){4552 if (vz_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum()));4553 vz_input->GetValuesPtr(&vz_ptr,&dummy);4554 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];4555 }4556 else{for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;}4557 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);4558 4559 /*Now compute pressure*/4560 GetParameterListOnVertices(&surface[0],SurfaceEnum);4561 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);4562 4563 /*Now, we have to move the previous Vx and Vy inputs to old4564 * status, otherwise, we'll wipe them off: */4565 penta->inputs->ChangeEnum(VxEnum,VxOldEnum);4566 penta->inputs->ChangeEnum(VyEnum,VyOldEnum);4567 penta->inputs->ChangeEnum(PressureEnum,PressureOldEnum);4568 4569 /*Add vx and vy as inputs to the tria element: */4570 penta->inputs->AddInput(new PentaVertexInput(VxEnum,vx));4571 penta->inputs->AddInput(new PentaVertexInput(VyEnum,vy));4572 penta->inputs->AddInput(new PentaVertexInput(VelEnum,vel));4573 penta->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));4574 4575 /*Stop if we have reached the surface*/4576 if (penta->IsOnSurface()) break;4577 4578 /* get upper Penta*/4579 penta=penta->GetUpperElement(); ISSMASSERT(penta->Id()!=this->id);4580 }4581 4582 /*Free ressources:*/4583 xfree((void**)&doflist);4584 }4585 /*}}}*/4586 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn {{{1*/4587 void Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn(double* solution){4588 4589 const int numdof=NDOF2*NUMVERTICES;4590 const int numdof2d=NDOF2*NUMVERTICES2D;4591 4592 int i,dummy;4593 double rho_ice,g;4594 double macayeal_values[numdof];4595 double pattyn_values[numdof];4596 double vx[NUMVERTICES];4597 double vy[NUMVERTICES];4598 double vz[NUMVERTICES];4599 double vel[NUMVERTICES];4600 double pressure[NUMVERTICES];4601 double surface[NUMVERTICES];4602 double xyz_list[NUMVERTICES][3];4603 int* doflistp = NULL;4604 int* doflistm = NULL;4605 double *vz_ptr = NULL;4606 Penta *penta = NULL;4607 4608 /*OK, we have to add results of this element for pattyn4609 * and results from the penta at base for macayeal. Now recover results*/4610 penta=GetBasalElement();4611 4612 /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */4613 GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);4614 penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);4615 4616 /*Get node data: */4617 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4618 4619 /*Use the dof list to index into the solution vector: */4620 for(i=0;i<numdof2d;i++){4621 pattyn_values[i]=solution[doflistp[i]];4622 macayeal_values[i]=solution[doflistm[i]];4623 }4624 for(i=numdof2d;i<numdof;i++){4625 pattyn_values[i]=solution[doflistp[i]];4626 macayeal_values[i]=macayeal_values[i-numdof2d];4627 }4628 4629 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4630 for(i=0;i<NUMVERTICES;i++){4631 vx[i]=macayeal_values[i*NDOF2+0]+pattyn_values[i*NDOF2+0];4632 vy[i]=macayeal_values[i*NDOF2+1]+pattyn_values[i*NDOF2+1];4633 }4634 4635 /*Get Vz*/4636 Input* vz_input=inputs->GetInput(VzEnum);4637 if (vz_input){4638 if (vz_input->Enum()!=PentaVertexInputEnum){4639 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum()));4640 }4641 vz_input->GetValuesPtr(&vz_ptr,&dummy);4642 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];4643 }4644 else{4645 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;4646 }4647 4648 /*Now Compute vel*/4649 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);4650 4651 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,4652 *so the pressure is just the pressure at the z elevation: */4653 rho_ice=matpar->GetRhoIce();4654 g=matpar->GetG();4655 GetParameterListOnVertices(&surface[0],SurfaceEnum);4656 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);4657 4658 /*Now, we have to move the previous Vx and Vy inputs to old4659 * status, otherwise, we'll wipe them off: */4660 this->inputs->ChangeEnum(VxEnum,VxOldEnum);4661 this->inputs->ChangeEnum(VyEnum,VyOldEnum);4662 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);4663 4664 /*Add vx and vy as inputs to the tria element: */4665 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));4666 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));4667 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));4668 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));4669 4670 /*Free ressources:*/4671 xfree((void**)&doflistp);4672 xfree((void**)&doflistm);4673 }4674 /*}}}*/4675 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes {{{1*/4676 void Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes(double* solution){4677 4678 const int numdofm=NDOF2*NUMVERTICES;4679 const int numdofs=NDOF4*NUMVERTICES;4680 const int numdof2d=NDOF2*NUMVERTICES2D;4681 4682 int i,dummy;4683 double stokesreconditioning;4684 double macayeal_values[numdofm];4685 double stokes_values[numdofs];4686 double vx[NUMVERTICES];4687 double vy[NUMVERTICES];4688 double vz[NUMVERTICES];4689 double vzmacayeal[NUMVERTICES];4690 double vzstokes[NUMVERTICES];4691 double vel[NUMVERTICES];4692 double pressure[NUMVERTICES];4693 double xyz_list[NUMVERTICES][3];4694 int* doflistm = NULL;4695 int* doflists = NULL;4696 double *vzmacayeal_ptr = NULL;4697 Penta *penta = NULL;4698 4699 /*OK, we have to add results of this element for macayeal4700 * and results from the penta at base for macayeal. Now recover results*/4701 penta=GetBasalElement();4702 4703 /*Get dof listof this element (macayeal dofs) and of the penta at base (macayeal dofs): */4704 penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);4705 GetDofList(&doflists,StokesApproximationEnum,GsetEnum);4706 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);4707 4708 /*Get node data: */4709 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4710 4711 /*Use the dof list to index into the solution vector: */4712 for(i=0;i<numdof2d;i++){4713 macayeal_values[i]=solution[doflistm[i]];4714 macayeal_values[i+numdof2d]=solution[doflistm[i]];4715 }4716 for(i=0;i<numdofs;i++){4717 stokes_values[i]=solution[doflists[i]];4718 }4719 4720 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4721 for(i=0;i<NUMVERTICES;i++){4722 vx[i]=stokes_values[i*NDOF4+0]+macayeal_values[i*NDOF2+0];4723 vy[i]=stokes_values[i*NDOF4+1]+macayeal_values[i*NDOF2+1];4724 vzstokes[i]=stokes_values[i*NDOF4+2];4725 pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;4726 }4727 4728 /*Get Vz*/4729 Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);4730 if (vzmacayeal_input){4731 if (vzmacayeal_input->Enum()!=PentaVertexInputEnum){4732 ISSMERROR("Cannot compute Vel as VzMacAyeal is of type %s",EnumToString(vzmacayeal_input->Enum()));4733 }4734 vzmacayeal_input->GetValuesPtr(&vzmacayeal_ptr,&dummy);4735 for(i=0;i<NUMVERTICES;i++) vzmacayeal[i]=vzmacayeal_ptr[i];4736 }4737 else{4738 ISSMERROR("Cannot update solution as VzMacAyeal is not present");4739 }4740 4741 /*Now Compute vel*/4742 for(i=0;i<NUMVERTICES;i++) {4743 vz[i]=vzmacayeal[i]+vzstokes[i];4744 vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);4745 }4746 4747 /*Now, we have to move the previous Vx and Vy inputs to old4748 * status, otherwise, we'll wipe them off: */4749 this->inputs->ChangeEnum(VxEnum,VxOldEnum);4750 this->inputs->ChangeEnum(VyEnum,VyOldEnum);4751 this->inputs->ChangeEnum(VzEnum,VzOldEnum);4752 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);4753 4754 /*Add vx and vy as inputs to the tria element: */4755 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));4756 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));4757 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));4758 this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));4759 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));4760 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));4761 4762 /*Free ressources:*/4763 xfree((void**)&doflistm);4764 xfree((void**)&doflists);4765 }4766 /*}}}*/4767 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattyn {{{1*/4768 void Penta::InputUpdateFromSolutionDiagnosticPattyn(double* solution){4769 4770 const int numdof=NDOF2*NUMVERTICES;4771 4772 int i,dummy;4773 double rho_ice,g;4774 double values[numdof];4775 double vx[NUMVERTICES];4776 double vy[NUMVERTICES];4777 double vz[NUMVERTICES];4778 double vel[NUMVERTICES];4779 double pressure[NUMVERTICES];4780 double surface[NUMVERTICES];4781 double xyz_list[NUMVERTICES][3];4782 int* doflist = NULL;4783 double *vz_ptr = NULL;4784 4785 /*Get dof list: */4786 GetDofList(&doflist,PattynApproximationEnum,GsetEnum);4787 4788 /*Get node data: */4789 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4790 4791 /*Use the dof list to index into the solution vector: */4792 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];4793 4794 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4795 for(i=0;i<NUMVERTICES;i++){4796 vx[i]=values[i*NDOF2+0];4797 vy[i]=values[i*NDOF2+1];4798 }4799 4800 /*Get Vz*/4801 Input* vz_input=inputs->GetInput(VzEnum);4802 if (vz_input){4803 if (vz_input->Enum()!=PentaVertexInputEnum){4804 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum()));4805 }4806 vz_input->GetValuesPtr(&vz_ptr,&dummy);4807 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];4808 }4809 else{4810 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;4811 }4812 4813 /*Now Compute vel*/4814 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);4815 4816 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,4817 *so the pressure is just the pressure at the z elevation: */4818 rho_ice=matpar->GetRhoIce();4819 g=matpar->GetG();4820 GetParameterListOnVertices(&surface[0],SurfaceEnum);4821 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);4822 4823 /*Now, we have to move the previous Vx and Vy inputs to old4824 * status, otherwise, we'll wipe them off: */4825 this->inputs->ChangeEnum(VxEnum,VxOldEnum);4826 this->inputs->ChangeEnum(VyEnum,VyOldEnum);4827 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);4828 4829 /*Add vx and vy as inputs to the tria element: */4830 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));4831 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));4832 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));4833 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));4834 4835 /*Free ressources:*/4836 xfree((void**)&doflist);4837 }4838 /*}}}*/4839 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattynStokes {{{1*/4840 void Penta::InputUpdateFromSolutionDiagnosticPattynStokes(double* solution){4841 4842 const int numdofp=NDOF2*NUMVERTICES;4843 const int numdofs=NDOF4*NUMVERTICES;4844 4845 int i,dummy;4846 double pattyn_values[numdofp];4847 double stokes_values[numdofs];4848 double vx[NUMVERTICES];4849 double vy[NUMVERTICES];4850 double vz[NUMVERTICES];4851 double vzpattyn[NUMVERTICES];4852 double vzstokes[NUMVERTICES];4853 double vel[NUMVERTICES];4854 double pressure[NUMVERTICES];4855 double xyz_list[NUMVERTICES][3];4856 double stokesreconditioning;4857 int* doflistp = NULL;4858 int* doflists = NULL;4859 double *vzpattyn_ptr = NULL;4860 Penta *penta = NULL;4861 4862 /*OK, we have to add results of this element for pattyn4863 * and results from the penta at base for macayeal. Now recover results*/4864 penta=GetBasalElement();4865 4866 /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */4867 GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);4868 GetDofList(&doflists,StokesApproximationEnum,GsetEnum);4869 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);4870 4871 /*Get node data: */4872 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4873 4874 /*Use the dof list to index into the solution vector: */4875 for(i=0;i<numdofp;i++) pattyn_values[i]=solution[doflistp[i]];4876 for(i=0;i<numdofs;i++) stokes_values[i]=solution[doflists[i]];4877 4878 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4879 for(i=0;i<NUMVERTICES;i++){4880 vx[i]=stokes_values[i*NDOF4+0]+pattyn_values[i*NDOF2+0];4881 vy[i]=stokes_values[i*NDOF4+1]+pattyn_values[i*NDOF2+1];4882 vzstokes[i]=stokes_values[i*NDOF4+2];4883 pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;4884 }4885 4886 /*Get Vz*/4887 Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);4888 if (vzpattyn_input){4889 if (vzpattyn_input->Enum()!=PentaVertexInputEnum){4890 ISSMERROR("Cannot compute Vel as VzPattyn is of type %s",EnumToString(vzpattyn_input->Enum()));4891 }4892 vzpattyn_input->GetValuesPtr(&vzpattyn_ptr,&dummy);4893 for(i=0;i<NUMVERTICES;i++) vzpattyn[i]=vzpattyn_ptr[i];4894 }4895 else{4896 ISSMERROR("Cannot update solution as VzPattyn is not present");4897 }4898 4899 /*Now Compute vel*/4900 for(i=0;i<NUMVERTICES;i++) {4901 vz[i]=vzpattyn[i]+vzstokes[i];4902 vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);4903 }4904 4905 /*Now, we have to move the previous Vx and Vy inputs to old4906 * status, otherwise, we'll wipe them off: */4907 this->inputs->ChangeEnum(VxEnum,VxOldEnum);4908 this->inputs->ChangeEnum(VyEnum,VyOldEnum);4909 this->inputs->ChangeEnum(VzEnum,VzOldEnum);4910 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);4911 4912 /*Add vx and vy as inputs to the tria element: */4913 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));4914 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));4915 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));4916 this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));4917 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));4918 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));4919 4920 /*Free ressources:*/4921 xfree((void**)&doflistp);4922 xfree((void**)&doflists);4923 }4924 /*}}}*/4925 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHutter {{{1*/4926 void Penta::InputUpdateFromSolutionDiagnosticHutter(double* solution){4927 4928 const int numdof=NDOF2*NUMVERTICES;4929 4930 int i,dummy;4931 double rho_ice,g;4932 double values[numdof];4933 double vx[NUMVERTICES];4934 double vy[NUMVERTICES];4935 double vz[NUMVERTICES];4936 double vel[NUMVERTICES];4937 double pressure[NUMVERTICES];4938 double surface[NUMVERTICES];4939 double xyz_list[NUMVERTICES][3];4940 int* doflist = NULL;4941 double* vz_ptr = NULL;4942 4943 /*Get dof list: */4944 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4945 4946 /*Get node data: */4947 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4948 4949 /*Use the dof list to index into the solution vector: */4950 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];4951 4952 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4953 for(i=0;i<NUMVERTICES;i++){4954 vx[i]=values[i*NDOF2+0];4955 vy[i]=values[i*NDOF2+1];4956 }4957 4958 /*Get Vz*/4959 Input* vz_input=inputs->GetInput(VzEnum);4960 if (vz_input){4961 if (vz_input->Enum()!=PentaVertexInputEnum){4962 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum()));4963 }4964 vz_input->GetValuesPtr(&vz_ptr,&dummy);4965 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];4966 }4967 else{4968 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;4969 }4970 4971 /*Now Compute vel*/4972 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);4973 4974 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,4975 *so the pressure is just the pressure at the z elevation: */4976 rho_ice=matpar->GetRhoIce();4977 g=matpar->GetG();4978 GetParameterListOnVertices(&surface[0],SurfaceEnum);4979 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);4980 4981 /*Now, we have to move the previous Vx and Vy inputs to old4982 * status, otherwise, we'll wipe them off: */4983 this->inputs->ChangeEnum(VxEnum,VxOldEnum);4984 this->inputs->ChangeEnum(VyEnum,VyOldEnum);4985 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);4986 4987 /*Add vx and vy as inputs to the tria element: */4988 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));4989 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));4990 this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));4991 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));4992 4993 /*Free ressources:*/4994 xfree((void**)&doflist);4995 }4996 /*}}}*/4997 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticVert {{{1*/4998 void Penta::InputUpdateFromSolutionDiagnosticVert(double* solution){4999 5000 const int numdof=NDOF1*NUMVERTICES;5001 5002 int i,dummy;5003 int approximation;5004 double rho_ice,g;5005 double values[numdof];5006 double vx[NUMVERTICES];5007 double vy[NUMVERTICES];5008 double vz[NUMVERTICES];5009 double vzmacayeal[NUMVERTICES];5010 double vzpattyn[NUMVERTICES];5011 double vzstokes[NUMVERTICES];5012 double vel[NUMVERTICES];5013 double pressure[NUMVERTICES];5014 double surface[NUMVERTICES];5015 double xyz_list[NUMVERTICES][3];5016 int* doflist = NULL;5017 double* vx_ptr = NULL;5018 double* vy_ptr = NULL;5019 double* vzstokes_ptr = NULL;5020 5021 5022 /*Get the approximation and do nothing if the element in Stokes or None*/5023 inputs->GetParameterValue(&approximation,ApproximationEnum);5024 if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){5025 return;5026 }5027 5028 /*Get dof list and vertices coordinates: */5029 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5030 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);5031 5032 /*Use the dof list to index into the solution vector vz: */5033 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];5034 for(i=0;i<NUMVERTICES;i++) vz[i]=values[i*NDOF1+0];5035 5036 /*Get Vx and Vy*/5037 Input* vx_input=inputs->GetInput(VxEnum);5038 if (vx_input){5039 if (vx_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as Vx is of type %s",EnumToString(vx_input->Enum()));5040 vx_input->GetValuesPtr(&vx_ptr,&dummy);5041 for(i=0;i<NUMVERTICES;i++) vx[i]=vx_ptr[i];5042 }5043 else for(i=0;i<NUMVERTICES;i++) vx[i]=0.0;5044 5045 Input* vy_input=inputs->GetInput(VyEnum);5046 if (vy_input){5047 if (vy_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as Vy is of type %s",EnumToString(vy_input->Enum()));5048 vy_input->GetValuesPtr(&vy_ptr,&dummy);5049 for(i=0;i<NUMVERTICES;i++) vy[i]=vy_ptr[i];5050 }5051 else for(i=0;i<NUMVERTICES;i++) vy[i]=0.0;5052 5053 /*Do some modifications if we actually have a PattynStokes or MacAyealStokes element*/5054 if(approximation==PattynStokesApproximationEnum){5055 Input* vzstokes_input=inputs->GetInput(VzStokesEnum);5056 if (vzstokes_input){5057 if (vzstokes_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as VzStokes is of type %s",EnumToString(vy_input->Enum()));5058 vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);5059 for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];5060 }5061 else ISSMERROR("Cannot compute Vz as VzStokes in not present in PattynStokes element");5062 for(i=0;i<NUMVERTICES;i++){5063 vzpattyn[i]=vz[i];5064 vz[i]=vzpattyn[i]+vzstokes[i];5065 }5066 }5067 else if(approximation==MacAyealStokesApproximationEnum){5068 Input* vzstokes_input=inputs->GetInput(VzStokesEnum);5069 if (vzstokes_input){5070 if (vzstokes_input->Enum()!=PentaVertexInputEnum) ISSMERROR("Cannot compute Vel as VzStokes is of type %s",EnumToString(vy_input->Enum()));5071 vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);5072 for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];5073 }5074 else ISSMERROR("Cannot compute Vz as VzStokes in not present in MacAyealStokes element");5075 for(i=0;i<NUMVERTICES;i++){5076 vzmacayeal[i]=vz[i];5077 vz[i]=vzmacayeal[i]+vzstokes[i];5078 }5079 }5080 5081 /*Now Compute vel*/5082 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);5083 5084 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,5085 *so the pressure is just the pressure at the z elevation: except it this is a PattynStokes element */5086 if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){5087 rho_ice=matpar->GetRhoIce();5088 g=matpar->GetG();5089 GetParameterListOnVertices(&surface[0],SurfaceEnum);5090 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);5091 }5092 5093 /*Now, we have to move the previous Vz inputs to old5094 * status, otherwise, we'll wipe them off and add the new inputs: */5095 this->inputs->ChangeEnum(VzEnum,VzOldEnum);5096 5097 if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){5098 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);5099 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));5100 }5101 else if(approximation==PattynStokesApproximationEnum){5102 this->inputs->AddInput(new PentaVertexInput(VzPattynEnum,vzpattyn));5103 }5104 else if(approximation==MacAyealStokesApproximationEnum){5105 this->inputs->AddInput(new PentaVertexInput(VzMacAyealEnum,vzpattyn));5106 }5107 5108 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));5109 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));5110 5111 /*Free ressources:*/5112 xfree((void**)&doflist);5113 }5114 /*}}}*/5115 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticStokes {{{1*/5116 void Penta::InputUpdateFromSolutionDiagnosticStokes(double* solution){5117 5118 const int numdof=NDOF4*NUMVERTICES;5119 5120 int i;5121 double values[numdof];5122 double vx[NUMVERTICES];5123 double vy[NUMVERTICES];5124 double vz[NUMVERTICES];5125 double vel[NUMVERTICES];5126 double pressure[NUMVERTICES];5127 double stokesreconditioning;5128 int* doflist=NULL;5129 5130 /*Get dof list: */5131 GetDofList(&doflist,StokesApproximationEnum,GsetEnum);5132 5133 /*Use the dof list to index into the solution vector: */5134 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];5135 5136 /*Ok, we have vx and vy in values, fill in all arrays: */5137 for(i=0;i<NUMVERTICES;i++){5138 vx[i]=values[i*NDOF4+0];5139 vy[i]=values[i*NDOF4+1];5140 vz[i]=values[i*NDOF4+2];5141 pressure[i]=values[i*NDOF4+3];5142 }5143 5144 /*Recondition pressure and compute vel: */5145 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);5146 for(i=0;i<NUMVERTICES;i++) pressure[i]=pressure[i]*stokesreconditioning;5147 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);5148 5149 /*Now, we have to move the previous inputs to old5150 * status, otherwise, we'll wipe them off: */5151 this->inputs->ChangeEnum(VxEnum,VxOldEnum);5152 this->inputs->ChangeEnum(VyEnum,VyOldEnum);5153 this->inputs->ChangeEnum(VzEnum,VzOldEnum);5154 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);5155 5156 /*Add vx and vy as inputs to the tria element: */5157 this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));5158 this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));5159 this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));5160 this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));5161 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));5162 5163 /*Free ressources:*/5164 xfree((void**)&doflist);5165 }5166 /*}}}*/5167 /*FUNCTION Penta::InputUpdateFromSolutionAdjointStokes {{{1*/5168 void Penta::InputUpdateFromSolutionAdjointStokes(double* solution){5169 5170 const int numdof=NDOF4*NUMVERTICES;5171 5172 int i;5173 double values[numdof];5174 double lambdax[NUMVERTICES];5175 double lambday[NUMVERTICES];5176 double lambdaz[NUMVERTICES];5177 double lambdap[NUMVERTICES];5178 int* doflist=NULL;5179 5180 /*Get dof list: */5181 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5182 5183 /*Use the dof list to index into the solution vector: */5184 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];5185 5186 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */5187 for(i=0;i<NUMVERTICES;i++){5188 lambdax[i]=values[i*NDOF4+0];5189 lambday[i]=values[i*NDOF4+1];5190 lambdaz[i]=values[i*NDOF4+2];5191 lambdap[i]=values[i*NDOF4+3];5192 }5193 5194 /*Add vx and vy as inputs to the tria element: */5195 this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));5196 this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));5197 this->inputs->AddInput(new PentaVertexInput(AdjointzEnum,lambdaz));5198 this->inputs->AddInput(new PentaVertexInput(AdjointpEnum,lambdap));5199 5200 /*Free ressources:*/5201 xfree((void**)&doflist);5202 }5203 /*}}}*/5204 /*FUNCTION Penta::InputUpdateFromSolutionAdjointHoriz {{{1*/5205 void Penta::InputUpdateFromSolutionAdjointHoriz(double* solution){5206 5207 const int numdof=NDOF2*NUMVERTICES;5208 5209 int i;5210 double values[numdof];5211 double lambdax[NUMVERTICES];5212 double lambday[NUMVERTICES];5213 int* doflist=NULL;5214 5215 /*Get dof list: */5216 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5217 5218 /*Use the dof list to index into the solution vector: */5219 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];5220 5221 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */5222 for(i=0;i<NUMVERTICES;i++){5223 lambdax[i]=values[i*NDOF2+0];5224 lambday[i]=values[i*NDOF2+1];5225 }5226 5227 /*Add vx and vy as inputs to the tria element: */5228 this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));5229 this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));5230 5231 /*Free ressources:*/5232 xfree((void**)&doflist);5233 }5234 /*}}}*/5235 /*FUNCTION Penta::InputUpdateFromSolutionThermal {{{1*/5236 void Penta::InputUpdateFromSolutionThermal(double* solution){5237 5238 const int numdof=NDOF1*NUMVERTICES;5239 5240 bool converged;5241 int i;5242 double values[numdof];5243 double B[numdof];5244 double B_average;5245 int* doflist=NULL;5246 5247 /*Get dof list: */5248 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5249 5250 /*Use the dof list to index into the solution vector: */5251 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];5252 5253 this->inputs->GetParameterValue(&converged,ConvergedEnum);5254 if(converged){5255 this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,values));5256 5257 /*Update Rheology only if convreged (we must make sure that the temperature is below melting point5258 * otherwise the rheology could be negative*/5259 B_average=Paterson((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0);5260 for(i=0;i<numdof;i++) B[i]=B_average;5261 this->matice->inputs->AddInput(new PentaVertexInput(RheologyBEnum,B));5262 }5263 else{5264 this->inputs->AddInput(new PentaVertexInput(TemporaryTemperatureEnum,values));5265 }5266 5267 /*Free ressources:*/5268 xfree((void**)&doflist);5269 }5270 /*}}}*/5271 /*FUNCTION Penta::InputUpdateFromSolutionOneDof{{{1*/5272 void Penta::InputUpdateFromSolutionOneDof(double* solution,int enum_type){5273 5274 const int numdof = NDOF1*NUMVERTICES;5275 5276 double values[numdof];5277 int* doflist=NULL;5278 5279 /*Get dof list: */5280 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5281 5282 /*Use the dof list to index into the solution vector: */5283 for(int i=0;i<numdof;i++) values[i]=solution[doflist[i]];5284 5285 /*Add input to the element: */5286 this->inputs->AddInput(new PentaVertexInput(enum_type,values));5287 5288 /*Free ressources:*/5289 xfree((void**)&doflist);5290 }5291 /*}}}*/5292 /*FUNCTION Penta::InputUpdateFromSolutionOneDofCollpased{{{1*/5293 void Penta::InputUpdateFromSolutionOneDofCollapsed(double* solution,int enum_type){5294 5295 const int numdof = NDOF1*NUMVERTICES;5296 const int numdof2d = NDOF1*NUMVERTICES2D;5297 5298 double values[numdof];5299 int* doflist = NULL;5300 Penta *penta = NULL;5301 5302 /*If not on bed, return*/5303 if (!IsOnBed()) return;5304 5305 /*Get dof list: */5306 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5307 5308 /*Use the dof list to index into the solution vector and extrude it */5309 for(int i=0;i<numdof2d;i++){5310 values[i] =solution[doflist[i]];5311 values[i+numdof2d]=values[i];5312 }5313 5314 /*Start looping over all elements above current element and update all inputs*/5315 penta=this;5316 for(;;){5317 /*Add input to the element: */5318 penta->inputs->AddInput(new PentaVertexInput(enum_type,values));5319 5320 /*Stop if we have reached the surface*/5321 if (penta->IsOnSurface()) break;5322 5323 /* get upper Penta*/5324 penta=penta->GetUpperElement(); ISSMASSERT(penta->Id()!=this->id);5325 }5326 5327 /*Free ressources:*/5328 xfree((void**)&doflist);5329 }5330 /*}}}*/5331 /*FUNCTION Penta::IsInput{{{1*/5332 bool Penta::IsInput(int name){5333 if (5334 name==ThicknessEnum ||5335 name==SurfaceEnum ||5336 name==BedEnum ||5337 name==DtEnum ||5338 name==SurfaceSlopeXEnum ||5339 name==SurfaceSlopeYEnum ||5340 name==MeltingRateEnum ||5341 name==AccumulationRateEnum ||5342 name==GeothermalFluxEnum ||5343 name==SurfaceAreaEnum||5344 name==PressureEnum ||5345 name==VxEnum ||5346 name==VyEnum ||5347 name==VzEnum ||5348 name==VxObsEnum ||5349 name==VyObsEnum ||5350 name==VzObsEnum ||5351 name==TemperatureEnum ||5352 name==CmResponseEnum ||5353 name==DragCoefficientEnum ||5354 name==GradientEnum ||5355 name==OldGradientEnum ||5356 name==ConvergedEnum5357 ) {5358 return true;5359 }5360 else return false;5361 }5362 /*}}}*/5363 /*FUNCTION Penta::IsOnShelf {{{1*/5364 bool Penta::IsOnShelf(){5365 5366 bool onshelf;5367 inputs->GetParameterValue(&onshelf,ElementOnIceShelfEnum);5368 return onshelf;5369 }5370 /*}}}*/5371 /*FUNCTION Penta::IsOnWater {{{1*/5372 bool Penta::IsOnWater(){5373 5374 bool onwater;5375 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);5376 return onwater;5377 }5378 /*}}}*/5379 /*FUNCTION Penta::IsOnSurface{{{1*/5380 bool Penta::IsOnSurface(void){5381 5382 bool onsurface;5383 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);5384 return onsurface;5385 }5386 /*}}}*/5387 /*FUNCTION Penta::IsOnBed{{{1*/5388 bool Penta::IsOnBed(void){5389 5390 bool onbed;5391 inputs->GetParameterValue(&onbed,ElementOnBedEnum);5392 return onbed;5393 }5394 /*}}}*/5395 /*FUNCTION Penta::MinEdgeLength{{{1*/5396 double Penta::MinEdgeLength(double xyz_list[6][3]){5397 /*Return the minimum lenght of the nine egdes of the penta*/5398 5399 int i,node0,node1;5400 int edges[9][2]={{0,1},{0,2},{1,2},{3,4},{3,5},{4,5},{0,3},{1,4},{2,5}}; //list of the nine edges5401 double length;5402 double minlength=-1;5403 5404 for(i=0;i<9;i++){5405 /*Find the two nodes for this edge*/5406 node0=edges[i][0];5407 node1=edges[i][1];5408 5409 /*Compute the length of this edge and compare it to the minimal length*/5410 length=pow(pow(xyz_list[node0][0]-xyz_list[node1][0],2.0)+pow(xyz_list[node0][1]-xyz_list[node1][1],2.0)+pow(xyz_list[node0][2]-xyz_list[node1][2],2.0),0.5);5411 if(length<minlength || minlength<0) minlength=length;5412 }5413 5414 return minlength;5415 }5416 /*}}}*/5417 /*FUNCTION Penta::ReduceMatrixStokes {{{1*/5418 void Penta::ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp){5419 5420 int i,j;5421 double Kii[24][24];5422 double Kib[24][3];5423 double Kbb[3][3];5424 double Kbi[3][24];5425 double Kbbinv[3][3];5426 double Kright[24][24];5427 5428 /*Create the four matrices used for reduction */5429 for(i=0;i<24;i++){5430 for(j=0;j<24;j++){5431 Kii[i][j]=*(Ke_temp+27*i+j);5432 }5433 for(j=0;j<3;j++){5434 Kib[i][j]=*(Ke_temp+27*i+j+24);5435 }5436 }5437 for(i=0;i<3;i++){5438 for(j=0;j<24;j++){5439 Kbi[i][j]=*(Ke_temp+27*(i+24)+j);5440 }5441 for(j=0;j<3;j++){5442 Kbb[i][j]=*(Ke_temp+27*(i+24)+j+24);5443 }5444 }5445 5446 /*Inverse the matrix corresponding to bubble part Kbb */5447 Matrix3x3Invert(&Kbbinv[0][0], &Kbb[0][0]);5448 5449 /*Multiply matrices to create the reduce matrix Ke_reduced */5450 TripleMultiply(&Kib[0][0],24,3,0,5451 &Kbbinv[0][0],3,3,0,5452 &Kbi[0][0],3,24,0,5453 &Kright[0][0],0);5454 5455 /*Affect value to the reduced matrix */5456 for(i=0;i<24;i++) for(j=0;j<24;j++) *(Ke_reduced+24*i+j)=Kii[i][j]-Kright[i][j];5457 }5458 /*}}}*/5459 /*FUNCTION Penta::ReduceVectorStokes {{{1*/5460 void Penta::ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp){5461 5462 int i,j;5463 double Pi[24];5464 double Pb[3];5465 double Kbb[3][3];5466 double Kib[24][3];5467 double Kbbinv[3][3];5468 double Pright[24];5469 5470 /*Create the four matrices used for reduction */5471 for(i=0;i<24;i++) Pi[i]=*(Pe_temp+i);5472 for(i=0;i<3;i++) Pb[i]=*(Pe_temp+i+24);5473 for(j=0;j<3;j++){5474 for(i=0;i<24;i++){5475 Kib[i][j]=*(Ke_temp+3*i+j);5476 }5477 for(i=0;i<3;i++){5478 Kbb[i][j]=*(Ke_temp+3*(i+24)+j);5479 }5480 }5481 5482 /*Inverse the matrix corresponding to bubble part Kbb */5483 Matrix3x3Invert(&Kbbinv[0][0], &Kbb[0][0]);5484 5485 /*Multiply matrices to create the reduce matrix Ke_reduced */5486 TripleMultiply(&Kib[0][0],24,3,0,5487 &Kbbinv[0][0],3,3,0,5488 &Pb[0],3,1,0,&Pright[0],0);5489 5490 /*Affect value to the reduced matrix */5491 for(i=0;i<24;i++) *(Pe_reduced+i)=Pi[i]-Pright[i];5492 }5493 /*}}}*/5494 /*FUNCTION Penta::SetClone {{{1*/5495 void Penta::SetClone(int* minranks){5496 5497 ISSMERROR("not implemented yet");5498 }5499 /*}}}1*/5500 /*FUNCTION Penta::SpawnTria {{{1*/5501 Tria* Penta::SpawnTria(int g0, int g1, int g2){5502 5503 int i,analysis_counter;5504 int indices[3];5505 int zero=0;5506 Tria* tria = NULL;5507 Inputs* tria_inputs = NULL;5508 Results* tria_results = NULL;5509 Parameters* tria_parameters = NULL;5510 5511 /*go into parameters and get the analysis_counter: */5512 this->parameters->FindParam(&analysis_counter,AnalysisCounterEnum);5513 5514 indices[0]=g0;5515 indices[1]=g1;5516 indices[2]=g2;5517 5518 tria_parameters=this->parameters;5519 tria_inputs=(Inputs*)this->inputs->SpawnTriaInputs(indices);5520 tria_results=(Results*)this->results->SpawnTriaResults(indices);5521 5522 tria=new Tria();5523 tria->id=this->id;5524 tria->inputs=tria_inputs;5525 tria->results=tria_results;5526 tria->parameters=tria_parameters;5527 tria->element_type=P1Enum; //Only P1 CG for now (TO BE CHANGED)5528 this->SpawnTriaHook(dynamic_cast<TriaHook*>(tria),&indices[0]);5529 5530 /*Spawn matice*/5531 tria->matice=NULL;5532 tria->matice=(Matice*)this->matice->copy();5533 delete tria->matice->inputs;5534 tria->matice->inputs=(Inputs*)this->matice->inputs->SpawnTriaInputs(indices);5535 5536 /*recover nodes, matice and matpar: */5537 tria->nodes=(Node**)tria->hnodes[analysis_counter]->deliverp();5538 tria->matpar=(Matpar*)tria->hmatpar->delivers();5539 5540 return tria;5541 }5542 /*}}}*/5543 /*FUNCTION Penta::SurfaceNormal {{{1*/5544 void Penta::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){5545 5546 int i;5547 double v13[3],v23[3];5548 double normal[3];5549 double normal_norm;5550 5551 for (i=0;i<3;i++){5552 v13[i]=xyz_list[0][i]-xyz_list[2][i];5553 v23[i]=xyz_list[1][i]-xyz_list[2][i];5554 }5555 5556 normal[0]=v13[1]*v23[2]-v13[2]*v23[1];5557 normal[1]=v13[2]*v23[0]-v13[0]*v23[2];5558 normal[2]=v13[0]*v23[1]-v13[1]*v23[0];5559 5560 normal_norm=sqrt( pow(normal[0],2)+pow(normal[1],2)+pow(normal[2],2) );5561 5562 *(surface_normal)=normal[0]/normal_norm;5563 *(surface_normal+1)=normal[1]/normal_norm;5564 *(surface_normal+2)=normal[2]/normal_norm;5565 }5566 /*}}}*/ -
issm/trunk/src/c/objects/Elements/Tria.cpp
r6397 r6410 26 26 #define NDOF4 4 27 27 28 /* Tria constructors and destructor*/28 /*Constructors/destructor/copy*/ 29 29 /*FUNCTION Tria::Tria(){{{1*/ 30 30 Tria::Tria(){ … … 67 67 } 68 68 /*}}}*/ 69 70 /*Object virtual functions definitions:*/71 69 /*FUNCTION Tria::copy {{{1*/ 72 70 Object* Tria::copy() { … … 104 102 /*point parameters: */ 105 103 tria->parameters=this->parameters; 106 104 107 105 /*recover objects: */ 108 106 tria->nodes=(Node**)xmalloc(3*sizeof(Node*)); //we cannot rely on an analysis_counter to tell us which analysis_type we are running, so we just copy the nodes. … … 114 112 } 115 113 /*}}}*/ 116 /*FUNCTION Tria::DeepEcho{{{1*/ 117 void Tria::DeepEcho(void){ 118 119 printf("Tria:\n"); 120 printf(" id: %i\n",id); 121 if(nodes){ 122 nodes[0]->DeepEcho(); 123 nodes[1]->DeepEcho(); 124 nodes[2]->DeepEcho(); 125 } 126 else printf("nodes = NULL\n"); 127 128 if (matice) matice->DeepEcho(); 129 else printf("matice = NULL\n"); 130 131 if (matpar) matpar->DeepEcho(); 132 else printf("matpar = NULL\n"); 133 134 printf(" parameters\n"); 135 if (parameters) parameters->DeepEcho(); 136 else printf("parameters = NULL\n"); 137 138 printf(" inputs\n"); 139 if (inputs) inputs->DeepEcho(); 140 else printf("inputs=NULL\n"); 141 142 if (results) results->DeepEcho(); 143 else printf("results=NULL\n"); 144 145 return; 146 } 147 /*}}}*/ 148 /*FUNCTION Tria::Demarshall {{{1*/ 149 void Tria::Demarshall(char** pmarshalled_dataset){ 150 151 char* marshalled_dataset=NULL; 152 int i; 153 int flaghook; 154 155 /*recover marshalled_dataset: */ 156 marshalled_dataset=*pmarshalled_dataset; 157 158 /*this time, no need to get enum type, the pointer directly points to the beginning of the 159 *object data (thanks to DataSet::Demarshall):*/ 160 memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id); 161 memcpy(&numanalyses,marshalled_dataset,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses); 162 163 /*demarshall Ref: */ 164 this->element_type_list=(int*)xmalloc(this->numanalyses*sizeof(int)); 165 for(i=0;i<numanalyses;i++){ memcpy(&element_type_list[i],marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);} 166 167 /*allocate dynamic memory: */ 168 this->hnodes=new Hook*[this->numanalyses]; 169 /*demarshall hooks: */ 170 for(i=0;i<numanalyses;i++){ 171 memcpy(&flaghook,marshalled_dataset,sizeof(flaghook));marshalled_dataset+=sizeof(flaghook); 172 if(flaghook){ // there is a hook so demarshall it 173 hnodes[i]=new Hook(); 174 hnodes[i]->Demarshall(&marshalled_dataset); 175 } 176 else hnodes[i]=NULL; //There is no hook so it is NULL 177 } 178 hmatice=new Hook(); hmatice->Demarshall(&marshalled_dataset); 179 hmatpar=new Hook(); hmatpar->Demarshall(&marshalled_dataset); 180 181 /*pointers are garbabe, until configuration is carried out: */ 182 nodes=NULL; 183 matice=NULL; 184 matpar=NULL; 185 186 /*demarshall inputs: */ 187 inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 188 results=(Results*)DataSetDemarshallRaw(&marshalled_dataset); 189 190 /*parameters: may not exist even yet, so let Configure handle it: */ 191 this->parameters=NULL; 192 193 /*return: */ 194 *pmarshalled_dataset=marshalled_dataset; 195 return; 196 } 197 /*}}}*/ 198 /*FUNCTION Tria::Echo{{{1*/ 199 void Tria::Echo(void){ 200 printf("Tria:\n"); 201 printf(" id: %i\n",id); 202 if(nodes){ 203 nodes[0]->Echo(); 204 nodes[1]->Echo(); 205 nodes[2]->Echo(); 206 } 207 else printf("nodes = NULL\n"); 208 209 if (matice) matice->Echo(); 210 else printf("matice = NULL\n"); 211 212 if (matpar) matpar->Echo(); 213 else printf("matpar = NULL\n"); 214 215 printf(" parameters\n"); 216 if (parameters) parameters->Echo(); 217 else printf("parameters = NULL\n"); 218 219 printf(" inputs\n"); 220 if (inputs) inputs->Echo(); 221 else printf("inputs=NULL\n"); 222 223 if (results) results->Echo(); 224 else printf("results=NULL\n"); 225 } 226 /*}}}*/ 227 /*FUNCTION Tria::Enum {{{1*/ 228 int Tria::Enum(void){ 229 230 return TriaEnum; 231 232 } 233 /*}}}*/ 234 /*FUNCTION Tria::Id {{{1*/ 235 int Tria::Id(){ 236 237 return id; 238 239 } 240 /*}}}*/ 114 115 /*Marshall*/ 241 116 /*FUNCTION Tria::Marshall {{{1*/ 242 117 void Tria::Marshall(char** pmarshalled_dataset){ … … 269 144 } 270 145 271 146 /*Marshall hooks: */ 272 147 for(i=0;i<numanalyses;i++){ 273 148 if(hnodes[i]){ … … 319 194 320 195 return sizeof(id) 321 +hnodes_size 322 +sizeof(numanalyses) 323 +numanalyses*sizeof(int) //element_type_lists 324 +hmatice->MarshallSize() 325 +hmatpar->MarshallSize() 326 +inputs->MarshallSize() 327 +results->MarshallSize() 328 +sizeof(int); //sizeof(int) for enum type 329 } 330 /*}}}*/ 331 /*FUNCTION Tria::MyRank {{{1*/ 332 int Tria::MyRank(void){ 333 extern int my_rank; 334 return my_rank; 335 } 336 /*}}}*/ 337 338 /*Update virtual functions definitions: */ 196 +hnodes_size 197 +sizeof(numanalyses) 198 +numanalyses*sizeof(int) //element_type_lists 199 +hmatice->MarshallSize() 200 +hmatpar->MarshallSize() 201 +inputs->MarshallSize() 202 +results->MarshallSize() 203 +sizeof(int); //sizeof(int) for enum type 204 } 205 /*}}}*/ 206 /*FUNCTION Tria::Demarshall {{{1*/ 207 void Tria::Demarshall(char** pmarshalled_dataset){ 208 209 char* marshalled_dataset=NULL; 210 int i; 211 int flaghook; 212 213 /*recover marshalled_dataset: */ 214 marshalled_dataset=*pmarshalled_dataset; 215 216 /*this time, no need to get enum type, the pointer directly points to the beginning of the 217 *object data (thanks to DataSet::Demarshall):*/ 218 memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id); 219 memcpy(&numanalyses,marshalled_dataset,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses); 220 221 /*demarshall Ref: */ 222 this->element_type_list=(int*)xmalloc(this->numanalyses*sizeof(int)); 223 for(i=0;i<numanalyses;i++){ memcpy(&element_type_list[i],marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);} 224 225 /*allocate dynamic memory: */ 226 this->hnodes=new Hook*[this->numanalyses]; 227 /*demarshall hooks: */ 228 for(i=0;i<numanalyses;i++){ 229 memcpy(&flaghook,marshalled_dataset,sizeof(flaghook));marshalled_dataset+=sizeof(flaghook); 230 if(flaghook){ // there is a hook so demarshall it 231 hnodes[i]=new Hook(); 232 hnodes[i]->Demarshall(&marshalled_dataset); 233 } 234 else hnodes[i]=NULL; //There is no hook so it is NULL 235 } 236 hmatice=new Hook(); hmatice->Demarshall(&marshalled_dataset); 237 hmatpar=new Hook(); hmatpar->Demarshall(&marshalled_dataset); 238 239 /*pointers are garbabe, until configuration is carried out: */ 240 nodes=NULL; 241 matice=NULL; 242 matpar=NULL; 243 244 /*demarshall inputs: */ 245 inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 246 results=(Results*)DataSetDemarshallRaw(&marshalled_dataset); 247 248 /*parameters: may not exist even yet, so let Configure handle it: */ 249 this->parameters=NULL; 250 251 /*return: */ 252 *pmarshalled_dataset=marshalled_dataset; 253 return; 254 } 255 /*}}}*/ 256 257 /*Other*/ 258 /*FUNCTION Tria::AverageOntoPartition {{{1*/ 259 void Tria::AverageOntoPartition(Vec partition_contributions,Vec partition_areas,double* vertex_response,double* qmu_part){ 260 261 bool already=false; 262 int i,j; 263 int partition[NUMVERTICES]; 264 int offsetsid[NUMVERTICES]; 265 int offsetdof[NUMVERTICES]; 266 double area; 267 double mean; 268 double values[3]; 269 270 /*First, get the area: */ 271 area=this->GetArea(); 272 273 /*Figure out the average for this element: */ 274 this->GetSidList(&offsetsid[0]); 275 this->GetDofList1(&offsetdof[0]); 276 mean=0; 277 for(i=0;i<NUMVERTICES;i++){ 278 partition[i]=(int)qmu_part[offsetsid[i]]; 279 mean=mean+1.0/NUMVERTICES*vertex_response[offsetdof[i]]; 280 } 281 282 /*Add contribution: */ 283 for(i=0;i<NUMVERTICES;i++){ 284 already=false; 285 for(j=0;j<i;j++){ 286 if (partition[i]==partition[j]){ 287 already=true; 288 break; 289 } 290 } 291 if(!already){ 292 VecSetValue(partition_contributions,partition[i],mean*area,ADD_VALUES); 293 VecSetValue(partition_areas,partition[i],area,ADD_VALUES); 294 }; 295 } 296 } 297 /*}}}*/ 298 /*FUNCTION Tria::CreateKMatrix {{{1*/ 299 void Tria::CreateKMatrix(Mat Kgg, Mat Kff, Mat Kfs){ 300 301 /*retreive parameters: */ 302 ElementMatrix* Ke=NULL; 303 int analysis_type; 304 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 305 306 /*Checks in debugging mode{{{2*/ 307 ISSMASSERT(this->nodes && this->matice && this->matpar && this->parameters && this->inputs); 308 /*}}}*/ 309 310 /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */ 311 switch(analysis_type){ 312 case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum: 313 Ke=CreateKMatrixDiagnosticMacAyeal(); 314 break; 315 case DiagnosticHutterAnalysisEnum: 316 Ke=CreateKMatrixDiagnosticHutter(); 317 break; 318 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum: 319 Ke=CreateKMatrixSlope(); 320 break; 321 case PrognosticAnalysisEnum: 322 Ke=CreateKMatrixPrognostic(); 323 break; 324 case BalancedthicknessAnalysisEnum: 325 Ke=CreateKMatrixBalancedthickness(); 326 break; 327 case AdjointBalancedthicknessAnalysisEnum: 328 Ke=CreateKMatrixAdjointBalancedthickness(); 329 break; 330 case BalancedvelocitiesAnalysisEnum: 331 Ke=CreateKMatrixBalancedvelocities(); 332 break; 333 default: 334 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumToString(analysis_type)); 335 } 336 337 /*Add to global matrix*/ 338 if(Ke){ 339 Ke->AddToGlobal(Kgg,Kff,Kfs); 340 delete Ke; 341 } 342 } 343 /*}}}*/ 344 /*FUNCTION Tria::CreateKMatrixAdjointBalancedthickness {{{1*/ 345 ElementMatrix* Tria::CreateKMatrixAdjointBalancedthickness(void){ 346 347 ElementMatrix* Ke=NULL; 348 349 /*Get Element Matrix of the forward model*/ 350 switch(GetElementType()){ 351 case P1Enum: 352 Ke=CreateKMatrixBalancedthickness_CG(); 353 break; 354 case P1DGEnum: 355 Ke=CreateKMatrixBalancedthickness_DG(); 356 break; 357 default: 358 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType())); 359 } 360 361 /*Transpose and return Ke*/ 362 Ke->Transpose(); 363 return Ke; 364 } 365 /*}}}*/ 366 /*FUNCTION Tria::CreateKMatrixBalancedthickness {{{1*/ 367 ElementMatrix* Tria::CreateKMatrixBalancedthickness(void){ 368 369 switch(GetElementType()){ 370 case P1Enum: 371 return CreateKMatrixBalancedthickness_CG(); 372 case P1DGEnum: 373 return CreateKMatrixBalancedthickness_DG(); 374 default: 375 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType())); 376 } 377 378 } 379 /*}}}*/ 380 /*FUNCTION Tria::CreateKMatrixBalancedthickness_CG {{{1*/ 381 ElementMatrix* Tria::CreateKMatrixBalancedthickness_CG(void){ 382 383 /*Constants*/ 384 const int numdof=NDOF1*NUMVERTICES; 385 386 /*Intermediaries */ 387 int artdiff; 388 int i,j,ig,dim; 389 double Jdettria ,vx,vy,dvxdx,dvydy; 390 double dvx[2],dvy[2]; 391 double xyz_list[NUMVERTICES][3]; 392 double L[NUMVERTICES]; 393 double B[2][NUMVERTICES]; 394 double Bprime[2][NUMVERTICES]; 395 double K[2][2] = {0.0}; 396 double KDL[2][2] = {0.0}; 397 double DL[2][2] = {0.0}; 398 double DLprime[2][2] = {0.0}; 399 double DL_scalar; 400 double Ke_gg_gaussian[numdof][numdof] = {0.0}; 401 double Ke_gg_thickness1[numdof][numdof] = {0.0}; 402 double Ke_gg_thickness2[numdof][numdof] = {0.0}; 403 GaussTria *gauss = NULL; 404 405 /*Initialize Element matrix and return if necessary*/ 406 if(IsOnWater()) return NULL; 407 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 408 409 /*Retrieve all Inputs and parameters: */ 410 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 411 this->parameters->FindParam(&artdiff,ArtDiffEnum); 412 this->parameters->FindParam(&dim,DimEnum); 413 Input* vxaverage_input=NULL; 414 Input* vyaverage_input=NULL; 415 if(dim==2){ 416 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input); 417 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input); 418 } 419 else{ 420 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input); 421 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input); 422 } 423 424 /*Create Artificial diffusivity once for all if requested*/ 425 if(artdiff){ 426 gauss=new GaussTria(); 427 gauss->GaussCenter(); 428 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 429 delete gauss; 430 431 vxaverage_input->GetParameterAverage(&vx); 432 vyaverage_input->GetParameterAverage(&vy); 433 K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(vx); 434 K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(vy); 435 } 436 437 /*Start looping on the number of gaussian points:*/ 438 gauss=new GaussTria(2); 439 for (ig=gauss->begin();ig<gauss->end();ig++){ 440 441 gauss->GaussPoint(ig); 442 443 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 444 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss); 445 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss); 446 447 vxaverage_input->GetParameterValue(&vx,gauss); 448 vyaverage_input->GetParameterValue(&vy,gauss); 449 vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss); 450 vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss); 451 452 dvxdx=dvx[0]; 453 dvydy=dvy[1]; 454 DL_scalar=gauss->weight*Jdettria; 455 456 DL[0][0]=DL_scalar*dvxdx; 457 DL[1][1]=DL_scalar*dvydy; 458 459 DLprime[0][0]=DL_scalar*vx; 460 DLprime[1][1]=DL_scalar*vy; 461 462 TripleMultiply( &B[0][0],2,numdof,1, 463 &DL[0][0],2,2,0, 464 &B[0][0],2,numdof,0, 465 &Ke_gg_thickness1[0][0],0); 466 467 TripleMultiply( &B[0][0],2,numdof,1, 468 &DLprime[0][0],2,2,0, 469 &Bprime[0][0],2,numdof,0, 470 &Ke_gg_thickness2[0][0],0); 471 472 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness1[i][j]; 473 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness2[i][j]; 474 475 if(artdiff){ 476 KDL[0][0]=DL_scalar*K[0][0]; 477 KDL[1][1]=DL_scalar*K[1][1]; 478 479 TripleMultiply( &Bprime[0][0],2,numdof,1, 480 &KDL[0][0],2,2,0, 481 &Bprime[0][0],2,numdof,0, 482 &Ke_gg_gaussian[0][0],0); 483 484 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j]; 485 } 486 } 487 488 /*Clean up and return*/ 489 delete gauss; 490 return Ke; 491 } 492 /*}}}*/ 493 /*FUNCTION Tria::CreateKMatrixBalancedthickness_DG {{{1*/ 494 ElementMatrix* Tria::CreateKMatrixBalancedthickness_DG(void){ 495 496 /*Constants*/ 497 const int numdof=NDOF1*NUMVERTICES; 498 499 /*Intermediaries*/ 500 int i,j,ig,dim; 501 double vx,vy,Jdettria; 502 double xyz_list[NUMVERTICES][3]; 503 double B[2][NUMVERTICES]; 504 double Bprime[2][NUMVERTICES]; 505 double DL[2][2]={0.0}; 506 double DL_scalar; 507 double Ke_gg[numdof][numdof]={0.0}; 508 GaussTria *gauss=NULL; 509 510 /*Initialize Element matrix and return if necessary*/ 511 if(IsOnWater()) return NULL; 512 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 513 514 /*Retrieve all inputs and parameters*/ 515 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 516 this->parameters->FindParam(&dim,DimEnum); 517 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 518 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 519 520 /*Start looping on the number of gaussian points:*/ 521 gauss=new GaussTria(2); 522 for (ig=gauss->begin();ig<gauss->end();ig++){ 523 524 gauss->GaussPoint(ig); 525 526 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 527 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/ 528 GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss); 529 GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss); 530 531 vx_input->GetParameterValue(&vx,gauss); 532 vy_input->GetParameterValue(&vy,gauss); 533 534 DL_scalar=-gauss->weight*Jdettria; 535 DL[0][0]=DL_scalar*vx; 536 DL[1][1]=DL_scalar*vy; 537 538 TripleMultiply( &B[0][0],2,numdof,1, 539 &DL[0][0],2,2,0, 540 &Bprime[0][0],2,numdof,0, 541 &Ke_gg[0][0],0); 542 543 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg[i][j]; 544 } 545 546 /*Clean up and return*/ 547 delete gauss; 548 return Ke; 549 } 550 /*}}}*/ 551 /*FUNCTION Tria::CreateKMatrixBalancedvelocities {{{1*/ 552 ElementMatrix* Tria::CreateKMatrixBalancedvelocities(void){ 553 554 /*Constants*/ 555 const int numdof=NDOF1*NUMVERTICES; 556 557 /*Intermediaries */ 558 int artdiff; 559 int i,j,ig,dim; 560 double nx,ny,norm,Jdettria; 561 double dvx[2],dvy[2]; 562 double vx,vy,dvxdx,dvydy; 563 double v_gauss[2]={0.0}; 564 double surface_normal[3]; 565 double surface_list[3]; 566 double xyz_list[NUMVERTICES][3]; 567 double B[2][NUMVERTICES]; 568 double Bprime[2][NUMVERTICES]; 569 double K[2][2]={0.0}; 570 double KDL[2][2]={0.0}; 571 double DLprime[2][2]={0.0}; 572 double DL_scalar; 573 double Ke_gg_gaussian[numdof][numdof] = {0.0}; 574 double Ke_gg_velocities[numdof][numdof] = {0.0}; 575 GaussTria *gauss=NULL; 576 577 /*Initialize Element matrix and return if necessary*/ 578 if(IsOnWater()) return NULL; 579 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 580 581 /*Retrieve all inputs and parameters*/ 582 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 583 this->parameters->FindParam(&artdiff,ArtDiffEnum); 584 this->parameters->FindParam(&dim,DimEnum); 585 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input); 586 Input* vxaverage_input=NULL; 587 Input* vyaverage_input=NULL; 588 if(dim==2){ 589 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input); 590 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input); 591 } 592 else{ 593 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input); 594 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input); 595 } 596 597 /*Modify z so that it reflects the surface*/ 598 GetParameterListOnVertices(&surface_list[0],SurfaceEnum); 599 for(i=0;i<NUMVERTICES;i++) xyz_list[i][2]=surface_list[i]; 600 601 /*Get normal vector to the surface*/ 602 vxaverage_input->GetParameterAverage(&nx); 603 vyaverage_input->GetParameterAverage(&ny); 604 if(nx==0 && ny==0){ 605 SurfaceNormal(&surface_normal[0],xyz_list); 606 nx=surface_normal[0]; 607 ny=surface_normal[1]; 608 } 609 if(nx==0 && ny==0){ 610 nx=0; ny=1; 611 } 612 norm=pow( pow(nx,2)+pow(ny,2) , (double).5); 613 nx=nx/norm; ny=ny/norm; 614 615 //Create Artificial diffusivity once for all if requested 616 if(artdiff){ 617 gauss=new GaussTria(); 618 gauss->GaussCenter(); 619 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 620 delete gauss; 621 622 vxaverage_input->GetParameterAverage(&v_gauss[0]); 623 vyaverage_input->GetParameterAverage(&v_gauss[1]); 624 K[0][0]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]); //pow should be zero!! 625 K[1][1]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]); 626 } 627 628 /* Start looping on the number of gaussian points: */ 629 gauss=new GaussTria(2); 630 for (ig=gauss->begin();ig<gauss->end();ig++){ 631 632 gauss->GaussPoint(ig); 633 634 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 635 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss); 636 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss); 637 638 vxaverage_input->GetParameterValue(&vx,gauss); 639 vyaverage_input->GetParameterValue(&vy,gauss); 640 vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss); 641 vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss); 642 643 dvxdx=dvx[0]; 644 dvydy=dvy[1]; 645 DL_scalar=gauss->weight*Jdettria; 646 647 DLprime[0][0]=DL_scalar*nx; 648 DLprime[1][1]=DL_scalar*ny; 649 650 TripleMultiply( &B[0][0],2,numdof,1, 651 &DLprime[0][0],2,2,0, 652 &Bprime[0][0],2,numdof,0, 653 &Ke_gg_velocities[0][0],0); 654 655 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_velocities[i][j]; 656 657 if(artdiff){ 658 KDL[0][0]=DL_scalar*K[0][0]; 659 KDL[1][1]=DL_scalar*K[1][1]; 660 661 TripleMultiply( &Bprime[0][0],2,numdof,1, 662 &KDL[0][0],2,2,0, 663 &Bprime[0][0],2,numdof,0, 664 &Ke_gg_gaussian[0][0],0); 665 666 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j]; 667 } 668 } 669 670 /*Clean up and return*/ 671 delete gauss; 672 return Ke; 673 } 674 /*}}}*/ 675 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyeal {{{1*/ 676 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyeal(void){ 677 678 /*compute all stiffness matrices for this element*/ 679 ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyealViscous(); 680 ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyealFriction(); 681 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2); 682 683 /*clean-up and return*/ 684 delete Ke1; 685 delete Ke2; 686 return Ke; 687 688 } 689 /*}}}*/ 690 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealViscous{{{1*/ 691 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealViscous(void){ 692 693 /*Constants*/ 694 const int numdof=NDOF2*NUMVERTICES; 695 696 /*Intermediaries*/ 697 int i,j,ig; 698 double xyz_list[NUMVERTICES][3]; 699 double viscosity,newviscosity,oldviscosity; 700 double viscosity_overshoot,thickness,Jdet; 701 double epsilon[3],oldepsilon[3]; /* epsilon=[exx,eyy,exy]; */ 702 double B[3][numdof]; 703 double Bprime[3][numdof]; 704 double D[3][3] = {0.0}; 705 double D_scalar; 706 double Ke_g[numdof][numdof]; 707 GaussTria *gauss = NULL; 708 709 /*Initialize Element matrix and return if necessary*/ 710 if(IsOnWater()) return NULL; 711 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum); 712 713 /*Retrieve all inputs and parameters*/ 714 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 715 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 716 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 717 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 718 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input); 719 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input); 720 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum); 721 722 /* Start looping on the number of gaussian points: */ 723 gauss=new GaussTria(2); 724 for (ig=gauss->begin();ig<gauss->end();ig++){ 725 726 gauss->GaussPoint(ig); 727 728 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 729 GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss); 730 GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss); 731 732 this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input); 733 this->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input); 734 matice->GetViscosity2d(&viscosity, &epsilon[0]); 735 matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]); 736 thickness_input->GetParameterValue(&thickness, gauss); 737 738 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity); 739 D_scalar=2*newviscosity*thickness*gauss->weight*Jdet; 740 for (i=0;i<3;i++) D[i][i]=D_scalar; 741 742 TripleMultiply(&B[0][0],3,numdof,1, 743 &D[0][0],3,3,0, 744 &Bprime[0][0],3,numdof,0, 745 &Ke_g[0][0],0); 746 747 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j]; 748 } 749 750 /*Clean up and return*/ 751 delete gauss; 752 return Ke; 753 } 754 /*}}}*/ 755 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealFriction {{{1*/ 756 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealFriction(void){ 757 758 /*Constants*/ 759 const int numdof=NDOF2*NUMVERTICES; 760 761 /*Intermediaries*/ 762 int i,j,ig; 763 int analysis_type,drag_type; 764 double MAXSLOPE = .06; // 6 % 765 double MOUNTAINKEXPONENT = 10; 766 double slope_magnitude,alpha2; 767 double Jdet; 768 double L[2][numdof]; 769 double DL[2][2] = {{ 0,0 },{0,0}}; 770 double Ke_g[numdof][numdof]; 771 double DL_scalar; 772 double slope[2] = {0.0,0.0}; 773 double xyz_list[NUMVERTICES][3]; 774 Friction *friction = NULL; 775 GaussTria *gauss = NULL; 776 777 /*Initialize Element matrix and return if necessary*/ 778 if(IsOnWater() || IsOnShelf()) return NULL; 779 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum); 780 781 /*Retrieve all inputs and parameters*/ 782 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 783 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input); 784 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 785 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 786 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 787 inputs->GetParameterValue(&drag_type,DragTypeEnum); 788 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 789 790 /*build friction object, used later on: */ 791 if (drag_type!=2) ISSMERROR(" non-viscous friction not supported yet!"); 792 friction=new Friction("2d",inputs,matpar,analysis_type); 793 794 /* Start looping on the number of gaussian points: */ 795 gauss=new GaussTria(2); 796 for (ig=gauss->begin();ig<gauss->end();ig++){ 797 798 gauss->GaussPoint(ig); 799 800 // If we have a slope > 6% for this element, it means we are on a mountain. In this particular case, 801 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */ 802 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss); 803 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2)); 804 if(slope_magnitude>MAXSLOPE) alpha2=pow((double)10,MOUNTAINKEXPONENT); 805 else friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum); 806 807 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2); 808 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 809 DL_scalar=alpha2*gauss->weight*Jdet; 810 for (i=0;i<2;i++) DL[i][i]=DL_scalar; 811 812 TripleMultiply( &L[0][0],2,numdof,1, 813 &DL[0][0],2,2,0, 814 &L[0][0],2,numdof,0, 815 &Ke_g[0][0],0); 816 817 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j]; 818 } 819 820 /*Clean up and return*/ 821 delete gauss; 822 delete friction; 823 return Ke; 824 } 825 /*}}}*/ 826 /*FUNCTION Tria::CreateKMatrixCouplingMacAyealPattynFriction {{{1*/ 827 ElementMatrix* Tria::CreateKMatrixCouplingMacAyealPattynFriction(void){ 828 829 /*Constants*/ 830 const int numdof = NDOF2 *NUMVERTICES; 831 const int numdoftotal = NDOF4 *NUMVERTICES; 832 833 /*Intermediaries */ 834 int i,j,ig,analysis_type,drag_type; 835 double Jdet,slope_magnitude,alpha2; 836 double xyz_list[NUMVERTICES][3]; 837 double slope[2]={0.0,0.0}; 838 double MAXSLOPE=.06; // 6 % 839 double MOUNTAINKEXPONENT=10; 840 double L[2][numdof]; 841 double DL[2][2] ={{ 0,0 },{0,0}}; //for basal drag 842 double DL_scalar; 843 double Ke_gg[numdof][numdof] ={0.0}; 844 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag 845 Friction *friction = NULL; 846 GaussTria *gauss=NULL; 847 848 /*Initialize Element matrix and return if necessary*/ 849 if(IsOnWater() || IsOnShelf()) return NULL; 850 ElementMatrix* Ke1=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum); 851 ElementMatrix* Ke2=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum); 852 ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2); 853 delete Ke1; delete Ke2; 854 855 /*retrieve inputs :*/ 856 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 857 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 858 inputs->GetParameterValue(&drag_type,DragTypeEnum); 859 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input); 860 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 861 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 862 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 863 864 /*build friction object, used later on: */ 865 if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!"); 866 friction=new Friction("2d",inputs,matpar,analysis_type); 867 868 /* Start looping on the number of gaussian points: */ 869 gauss=new GaussTria(2); 870 for (ig=gauss->begin();ig<gauss->end();ig++){ 871 872 gauss->GaussPoint(ig); 873 874 /*Friction: */ 875 friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum); 876 877 // If we have a slope > 6% for this element, it means we are on a mountain. In this particular case, 878 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */ 879 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss); 880 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2)); 881 882 if (slope_magnitude>MAXSLOPE){ 883 alpha2=pow((double)10,MOUNTAINKEXPONENT); 884 } 885 886 /* Get Jacobian determinant: */ 887 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 888 889 /*Get L matrix: */ 890 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2); 891 892 893 DL_scalar=alpha2*gauss->weight*Jdet; 894 for (i=0;i<2;i++){ 895 DL[i][i]=DL_scalar; 896 } 897 898 /* Do the triple producte tL*D*L: */ 899 TripleMultiply( &L[0][0],2,numdof,1, 900 &DL[0][0],2,2,0, 901 &L[0][0],2,numdof,0, 902 &Ke_gg_gaussian[0][0],0); 903 904 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j]; 905 } 906 907 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdoftotal+(numdof+j)]+=Ke_gg[i][j]; 908 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[(i+numdof)*numdoftotal+j]+=Ke_gg[i][j]; 909 910 /*Clean up and return*/ 911 delete gauss; 912 delete friction; 913 return Ke; 914 } 915 /*}}}*/ 916 /*FUNCTION Tria::CreateKMatrixDiagnosticPattynFriction {{{1*/ 917 ElementMatrix* Tria::CreateKMatrixDiagnosticPattynFriction(void){ 918 919 /*Constants*/ 920 const int numdof = NDOF2*NUMVERTICES; 921 922 /*Intermediaries */ 923 int i,j,ig; 924 int analysis_type,drag_type; 925 double xyz_list[NUMVERTICES][3]; 926 double slope_magnitude,alpha2,Jdet; 927 double slope[2]={0.0,0.0}; 928 double MAXSLOPE=.06; // 6 % 929 double MOUNTAINKEXPONENT=10; 930 double L[2][numdof]; 931 double DL[2][2]={{ 0,0 },{0,0}}; //for basal drag 932 double DL_scalar; 933 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag 934 Friction *friction = NULL; 935 GaussTria *gauss=NULL; 936 937 /*Initialize Element matrix and return if necessary*/ 938 if(IsOnWater() || IsOnShelf()) return NULL; 939 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum); 940 941 /*Retrieve all inputs and parameters*/ 942 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 943 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 944 inputs->GetParameterValue(&drag_type,DragTypeEnum); 945 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input); 946 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 947 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 948 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 949 950 /*build friction object, used later on: */ 951 if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!"); 952 friction=new Friction("2d",inputs,matpar,analysis_type); 953 954 /* Start looping on the number of gaussian points: */ 955 gauss=new GaussTria(2); 956 for (ig=gauss->begin();ig<gauss->end();ig++){ 957 958 gauss->GaussPoint(ig); 959 960 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 961 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2); 962 963 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss); 964 friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum); // TO UNCOMMENT 965 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2)); 966 967 // If we have a slope > 6% for this element, it means we are on a mountain. In this particular case, 968 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */ 969 if (slope_magnitude>MAXSLOPE){ 970 alpha2=pow((double)10,MOUNTAINKEXPONENT); 971 } 972 973 DL_scalar=alpha2*gauss->weight*Jdet; 974 for (i=0;i<2;i++) DL[i][i]=DL_scalar; 975 976 TripleMultiply( &L[0][0],2,numdof,1, 977 &DL[0][0],2,2,0, 978 &L[0][0],2,numdof,0, 979 &Ke_gg_gaussian[0][0],0); 980 981 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j]; 982 } 983 984 /*Clean up and return*/ 985 delete gauss; 986 delete friction; 987 return Ke; 988 } 989 /*}}}*/ 990 /*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/ 991 ElementMatrix* Tria::CreateKMatrixDiagnosticHutter(void){ 992 993 /*Intermediaries*/ 994 const int numdof=NUMVERTICES*NDOF2; 995 int i,connectivity; 996 997 /*Initialize Element matrix and return if necessary*/ 998 if(IsOnWater()) return NULL; 999 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1000 1001 /*Create Element matrix*/ 1002 for(i=0;i<NUMVERTICES;i++){ 1003 connectivity=nodes[i]->GetConnectivity(); 1004 Ke->values[(2*i)*numdof +(2*i) ]=1/(double)connectivity; 1005 Ke->values[(2*i+1)*numdof+(2*i+1)]=1/(double)connectivity; 1006 } 1007 1008 /*Clean up and return*/ 1009 return Ke; 1010 } 1011 /*}}}*/ 1012 /*FUNCTION Tria::CreateKMatrixDiagnosticVertSurface {{{1*/ 1013 ElementMatrix* Tria::CreateKMatrixDiagnosticVertSurface(void){ 1014 1015 /*Constants*/ 1016 const int numdof=NDOF1*NUMVERTICES; 1017 1018 /*Intermediaries */ 1019 int i,j,ig; 1020 double xyz_list[NUMVERTICES][3]; 1021 double surface_normal[3]; 1022 double Jdet,DL_scalar; 1023 double L[3]; 1024 GaussTria *gauss=NULL; 1025 double Ke_g[numdof][numdof]; //stiffness matrix evaluated at the gaussian point. 1026 1027 /*Initialize Element matrix and return if necessary*/ 1028 if(IsOnWater()) return NULL; 1029 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1030 1031 /*Retrieve all inputs and parameters*/ 1032 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1033 SurfaceNormal(&surface_normal[0],xyz_list); 1034 1035 /* Start looping on the number of gaussian points: */ 1036 gauss=new GaussTria(2); 1037 for (ig=gauss->begin();ig<gauss->end();ig++){ 1038 1039 gauss->GaussPoint(ig); 1040 1041 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss); 1042 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1043 1044 /**********************Do not forget the sign**********************************/ 1045 DL_scalar=- gauss->weight*Jdet*surface_normal[2]; 1046 /******************************************************************************/ 1047 1048 TripleMultiply( L,1,3,1, 1049 &DL_scalar,1,1,0, 1050 L,1,3,0, 1051 &Ke_g[0][0],0); 1052 1053 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j]; 1054 } 1055 1056 /*Clean up and return*/ 1057 delete gauss; 1058 return Ke; 1059 } 1060 /*}}}*/ 1061 /*FUNCTION Tria::CreateKMatrixMelting {{{1*/ 1062 ElementMatrix* Tria::CreateKMatrixMelting(void){ 1063 1064 /*Constants*/ 1065 const int numdof=NUMVERTICES*NDOF1; 1066 1067 /*Intermediaries */ 1068 int i,j,ig; 1069 double heatcapacity,latentheat; 1070 double Jdet,D_scalar; 1071 double xyz_list[NUMVERTICES][3]; 1072 double L[3]; 1073 double Ke_gaussian[numdof][numdof]={0.0}; 1074 GaussTria *gauss=NULL; 1075 1076 /*Initialize Element matrix and return if necessary*/ 1077 if(IsOnWater()) return NULL; 1078 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1079 1080 /*Retrieve all inputs and parameters*/ 1081 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1082 latentheat=matpar->GetLatentHeat(); 1083 heatcapacity=matpar->GetHeatCapacity(); 1084 1085 /* Start looping on the number of gauss (nodes on the bedrock) */ 1086 gauss=new GaussTria(2); 1087 for (ig=gauss->begin();ig<gauss->end();ig++){ 1088 1089 gauss->GaussPoint(ig); 1090 1091 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1092 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss); 1093 1094 D_scalar=latentheat/heatcapacity*gauss->weight*Jdet; 1095 1096 TripleMultiply(&L[0],numdof,1,0, 1097 &D_scalar,1,1,0, 1098 &L[0],1,numdof,0, 1099 &Ke_gaussian[0][0],0); 1100 1101 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gaussian[i][j]; 1102 } 1103 1104 /*Clean up and return*/ 1105 delete gauss; 1106 return Ke; 1107 } 1108 /*}}}*/ 1109 /*FUNCTION Tria::CreateKMatrixPrognostic {{{1*/ 1110 ElementMatrix* Tria::CreateKMatrixPrognostic(void){ 1111 1112 switch(GetElementType()){ 1113 case P1Enum: 1114 return CreateKMatrixPrognostic_CG(); 1115 case P1DGEnum: 1116 return CreateKMatrixPrognostic_DG(); 1117 default: 1118 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType())); 1119 } 1120 1121 } 1122 /*}}}*/ 1123 /*FUNCTION Tria::CreateKMatrixPrognostic_CG {{{1*/ 1124 ElementMatrix* Tria::CreateKMatrixPrognostic_CG(void){ 1125 1126 /*Constants*/ 1127 const int numdof=NDOF1*NUMVERTICES; 1128 1129 /*Intermediaries */ 1130 int artdiff; 1131 int i,j,ig,dim; 1132 double Jdettria,DL_scalar,dt; 1133 double vx,vy,dvxdx,dvydy; 1134 double dvx[2],dvy[2]; 1135 double v_gauss[2]={0.0}; 1136 double xyz_list[NUMVERTICES][3]; 1137 double L[NUMVERTICES]; 1138 double B[2][NUMVERTICES]; 1139 double Bprime[2][NUMVERTICES]; 1140 double K[2][2] ={0.0}; 1141 double KDL[2][2] ={0.0}; 1142 double DL[2][2] ={0.0}; 1143 double DLprime[2][2] ={0.0}; 1144 double Ke_gg_gaussian[numdof][numdof] ={0.0}; 1145 double Ke_gg_thickness1[numdof][numdof]={0.0}; 1146 double Ke_gg_thickness2[numdof][numdof]={0.0}; 1147 GaussTria *gauss=NULL; 1148 1149 /*Initialize Element matrix and return if necessary*/ 1150 if(IsOnWater()) return NULL; 1151 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1152 1153 /*Retrieve all inputs and parameters*/ 1154 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1155 this->inputs->GetParameterValue(&dt,DtEnum); 1156 this->parameters->FindParam(&dim,DimEnum); 1157 this->parameters->FindParam(&artdiff,ArtDiffEnum); 1158 Input* vxaverage_input=NULL; 1159 Input* vyaverage_input=NULL; 1160 if(dim==2){ 1161 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input); 1162 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input); 1163 } 1164 else{ 1165 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input); 1166 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input); 1167 } 1168 1169 //Create Artificial diffusivity once for all if requested 1170 if(artdiff){ 1171 gauss=new GaussTria(); 1172 gauss->GaussCenter(); 1173 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 1174 delete gauss; 1175 1176 vxaverage_input->GetParameterAverage(&v_gauss[0]); 1177 vyaverage_input->GetParameterAverage(&v_gauss[1]); 1178 1179 K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]); 1180 K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]); 1181 } 1182 1183 /* Start looping on the number of gaussian points: */ 1184 gauss=new GaussTria(2); 1185 for (ig=gauss->begin();ig<gauss->end();ig++){ 1186 1187 gauss->GaussPoint(ig); 1188 1189 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 1190 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1191 1192 vxaverage_input->GetParameterValue(&vx,gauss); 1193 vyaverage_input->GetParameterValue(&vy,gauss); 1194 vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss); 1195 vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss); 1196 1197 DL_scalar=gauss->weight*Jdettria; 1198 1199 TripleMultiply( &L[0],1,numdof,1, 1200 &DL_scalar,1,1,0, 1201 &L[0],1,numdof,0, 1202 &Ke_gg_gaussian[0][0],0); 1203 1204 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss); 1205 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss); 1206 1207 dvxdx=dvx[0]; 1208 dvydy=dvy[1]; 1209 DL_scalar=dt*gauss->weight*Jdettria; 1210 1211 DL[0][0]=DL_scalar*dvxdx; 1212 DL[1][1]=DL_scalar*dvydy; 1213 DLprime[0][0]=DL_scalar*vx; 1214 DLprime[1][1]=DL_scalar*vy; 1215 1216 TripleMultiply( &B[0][0],2,numdof,1, 1217 &DL[0][0],2,2,0, 1218 &B[0][0],2,numdof,0, 1219 &Ke_gg_thickness1[0][0],0); 1220 1221 TripleMultiply( &B[0][0],2,numdof,1, 1222 &DLprime[0][0],2,2,0, 1223 &Bprime[0][0],2,numdof,0, 1224 &Ke_gg_thickness2[0][0],0); 1225 1226 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j]; 1227 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness1[i][j]; 1228 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness2[i][j]; 1229 1230 if(artdiff){ 1231 KDL[0][0]=DL_scalar*K[0][0]; 1232 KDL[1][1]=DL_scalar*K[1][1]; 1233 1234 TripleMultiply( &Bprime[0][0],2,numdof,1, 1235 &KDL[0][0],2,2,0, 1236 &Bprime[0][0],2,numdof,0, 1237 &Ke_gg_gaussian[0][0],0); 1238 1239 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j]; 1240 } 1241 } 1242 1243 /*Clean up and return*/ 1244 delete gauss; 1245 return Ke; 1246 } 1247 /*}}}*/ 1248 /*FUNCTION Tria::CreateKMatrixPrognostic_DG {{{1*/ 1249 ElementMatrix* Tria::CreateKMatrixPrognostic_DG(void){ 1250 1251 /*Constants*/ 1252 const int numdof=NDOF1*NUMVERTICES; 1253 1254 /*Intermediaries */ 1255 int i,j,ig,dim; 1256 double xyz_list[NUMVERTICES][3]; 1257 double Jdettria,dt,vx,vy; 1258 double L[NUMVERTICES]; 1259 double B[2][NUMVERTICES]; 1260 double Bprime[2][NUMVERTICES]; 1261 double DL[2][2]={0.0}; 1262 double DLprime[2][2]={0.0}; 1263 double DL_scalar; 1264 double Ke_gg1[numdof][numdof]={0.0}; 1265 double Ke_gg2[numdof][numdof]={0.0}; 1266 GaussTria *gauss=NULL; 1267 1268 /*Initialize Element matrix and return if necessary*/ 1269 if(IsOnWater()) return NULL; 1270 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1271 1272 /*Retrieve all inputs and parameters*/ 1273 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1274 this->inputs->GetParameterValue(&dt,DtEnum); 1275 this->parameters->FindParam(&dim,DimEnum); 1276 Input* vxaverage_input=NULL; 1277 Input* vyaverage_input=NULL; 1278 if(dim==2){ 1279 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input); 1280 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input); 1281 } 1282 else{ 1283 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input); 1284 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input); 1285 } 1286 1287 /* Start looping on the number of gaussian points: */ 1288 gauss=new GaussTria(2); 1289 for (ig=gauss->begin();ig<gauss->end();ig++){ 1290 1291 gauss->GaussPoint(ig); 1292 1293 vxaverage_input->GetParameterValue(&vx,gauss); 1294 vyaverage_input->GetParameterValue(&vy,gauss); 1295 1296 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 1297 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1298 1299 DL_scalar=gauss->weight*Jdettria; 1300 1301 TripleMultiply( &L[0],1,numdof,1, 1302 &DL_scalar,1,1,0, 1303 &L[0],1,numdof,0, 1304 &Ke_gg1[0][0],0); 1305 1306 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/ 1307 GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss); 1308 GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss); 1309 1310 DL_scalar=-dt*gauss->weight*Jdettria; 1311 1312 DLprime[0][0]=DL_scalar*vx; 1313 DLprime[1][1]=DL_scalar*vy; 1314 1315 TripleMultiply( &B[0][0],2,numdof,1, 1316 &DLprime[0][0],2,2,0, 1317 &Bprime[0][0],2,numdof,0, 1318 &Ke_gg2[0][0],0); 1319 1320 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg1[i][j]; 1321 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg2[i][j]; 1322 } 1323 1324 /*Clean up and return*/ 1325 delete gauss; 1326 return Ke; 1327 } 1328 /*}}}*/ 1329 /*FUNCTION Tria::CreateKMatrixSlope {{{1*/ 1330 ElementMatrix* Tria::CreateKMatrixSlope(void){ 1331 1332 /*constants: */ 1333 const int numdof=NDOF1*NUMVERTICES; 1334 1335 /* Intermediaries */ 1336 int i,j,ig; 1337 double DL_scalar,Jdet; 1338 double xyz_list[NUMVERTICES][3]; 1339 double L[1][3]; 1340 double Ke_g[numdof][numdof]; 1341 GaussTria *gauss = NULL; 1342 1343 /*Initialize Element matrix and return if necessary*/ 1344 if(IsOnWater()) return NULL; 1345 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1346 1347 GetVerticesCoordinates(&xyz_list[0][0],nodes,NUMVERTICES); 1348 1349 /* Start looping on the number of gaussian points: */ 1350 gauss=new GaussTria(2); 1351 for (ig=gauss->begin();ig<gauss->end();ig++){ 1352 1353 gauss->GaussPoint(ig); 1354 1355 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1356 DL_scalar=gauss->weight*Jdet; 1357 1358 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF1); 1359 1360 TripleMultiply(&L[0][0],1,3,1, 1361 &DL_scalar,1,1,0, 1362 &L[0][0],1,3,0, 1363 &Ke_g[0][0],0); 1364 1365 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j]; 1366 } 1367 1368 /*Clean up and return*/ 1369 delete gauss; 1370 return Ke; 1371 } 1372 /*}}}*/ 1373 /*FUNCTION Tria::CreateKMatrixThermal {{{1*/ 1374 ElementMatrix* Tria::CreateKMatrixThermal(void){ 1375 1376 /*Constants*/ 1377 const int numdof=NDOF1*NUMVERTICES; 1378 1379 /*Intermediaries */ 1380 int i,j,ig; 1381 double mixed_layer_capacity,thermal_exchange_velocity; 1382 double rho_ice,rho_water,heatcapacity; 1383 double Jdet,dt; 1384 double xyz_list[NUMVERTICES][3]; 1385 double l1l2l3[NUMVERTICES]; 1386 double D_scalar; 1387 double Ke_gaussian[numdof][numdof]={0.0}; 1388 GaussTria *gauss=NULL; 1389 1390 /*Initialize Element matrix and return if necessary*/ 1391 if(IsOnWater() || !IsOnShelf()) return NULL; 1392 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum); 1393 1394 /*Retrieve all inputs and parameters*/ 1395 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1396 this->inputs->GetParameterValue(&dt,DtEnum); 1397 mixed_layer_capacity=matpar->GetMixedLayerCapacity(); 1398 thermal_exchange_velocity=matpar->GetThermalExchangeVelocity(); 1399 rho_water=matpar->GetRhoWater(); 1400 rho_ice=matpar->GetRhoIce(); 1401 heatcapacity=matpar->GetHeatCapacity(); 1402 1403 /* Start looping on the number of gauss (nodes on the bedrock) */ 1404 gauss=new GaussTria(2); 1405 for (ig=gauss->begin();ig<gauss->end();ig++){ 1406 1407 gauss->GaussPoint(ig); 1408 1409 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss); 1410 GetNodalFunctions(&l1l2l3[0], gauss); 1411 1412 D_scalar=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice); 1413 if(dt) D_scalar=dt*D_scalar; 1414 1415 TripleMultiply(&l1l2l3[0],numdof,1,0, 1416 &D_scalar,1,1,0, 1417 &l1l2l3[0],1,numdof,0, 1418 &Ke_gaussian[0][0],0); 1419 1420 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gaussian[i][j]; 1421 } 1422 1423 /*Clean up and return*/ 1424 delete gauss; 1425 return Ke; 1426 } 1427 /*}}}*/ 1428 /*FUNCTION Tria::CreatePVector {{{1*/ 1429 void Tria::CreatePVector(Vec pg, Vec pf){ 1430 1431 /*retrive parameters: */ 1432 ElementVector* pe=NULL; 1433 int analysis_type; 1434 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 1435 1436 /*asserts: {{{*/ 1437 /*if debugging mode, check that all pointers exist*/ 1438 ISSMASSERT(this->nodes && this->matice && this->matpar && this->parameters && this->inputs); 1439 /*}}}*/ 1440 1441 /*Just branch to the correct load generator, according to the type of analysis we are carrying out: */ 1442 switch(analysis_type){ 1443 case DiagnosticHorizAnalysisEnum: 1444 pe=CreatePVectorDiagnosticMacAyeal(); 1445 break; 1446 case AdjointHorizAnalysisEnum: 1447 pe=CreatePVectorAdjointHoriz(); 1448 break; 1449 case DiagnosticHutterAnalysisEnum: 1450 pe=CreatePVectorDiagnosticHutter(); 1451 break; 1452 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum: 1453 pe=CreatePVectorSlope(); 1454 break; 1455 case PrognosticAnalysisEnum: 1456 pe=CreatePVectorPrognostic(); 1457 break; 1458 case BalancedthicknessAnalysisEnum: 1459 pe=CreatePVectorBalancedthickness(); 1460 break; 1461 case AdjointBalancedthicknessAnalysisEnum: 1462 pe=CreatePVectorAdjointBalancedthickness(); 1463 break; 1464 case BalancedvelocitiesAnalysisEnum: 1465 pe=CreatePVectorBalancedvelocities(); 1466 break; 1467 default: 1468 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumToString(analysis_type)); 1469 } 1470 1471 /*Add to global Vector*/ 1472 if(pe){ 1473 pe->AddToGlobal(pg,pf); 1474 delete pe; 1475 } 1476 } 1477 /*}}}*/ 1478 /*FUNCTION Tria::CreatePVectorBalancedthickness{{{1*/ 1479 ElementVector* Tria::CreatePVectorBalancedthickness(void){ 1480 1481 switch(GetElementType()){ 1482 case P1Enum: 1483 return CreatePVectorBalancedthickness_CG(); 1484 break; 1485 case P1DGEnum: 1486 return CreatePVectorBalancedthickness_DG(); 1487 default: 1488 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType())); 1489 } 1490 } 1491 /*}}}*/ 1492 /*FUNCTION Tria::CreatePVectorBalancedthickness_CG{{{1*/ 1493 ElementVector* Tria::CreatePVectorBalancedthickness_CG(void){ 1494 1495 /*Constants*/ 1496 const int numdof=NDOF1*NUMVERTICES; 1497 1498 /*Intermediaries */ 1499 int i,j,ig; 1500 double xyz_list[NUMVERTICES][3]; 1501 double dhdt_g,melting_g,accumulation_g,Jdettria; 1502 double L[NUMVERTICES]; 1503 GaussTria* gauss=NULL; 1504 1505 /*Initialize Element vector and return if necessary*/ 1506 if(IsOnWater()) return NULL; 1507 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 1508 1509 /*Retrieve all inputs and parameters*/ 1510 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1511 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input); 1512 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input); 1513 Input* dhdt_input=inputs->GetInput(DhDtEnum); ISSMASSERT(dhdt_input); 1514 1515 /* Start looping on the number of gaussian points: */ 1516 gauss=new GaussTria(2); 1517 for(ig=gauss->begin();ig<gauss->end();ig++){ 1518 1519 gauss->GaussPoint(ig); 1520 1521 accumulation_input->GetParameterValue(&accumulation_g,gauss); 1522 melting_input->GetParameterValue(&melting_g,gauss); 1523 dhdt_input->GetParameterValue(&dhdt_g,gauss); 1524 1525 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 1526 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1527 1528 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(accumulation_g-melting_g-dhdt_g)*L[i]; 1529 } 1530 1531 /*Clean up and return*/ 1532 delete gauss; 1533 return pe; 1534 } 1535 /*}}}*/ 1536 /*FUNCTION Tria::CreatePVectorBalancedthickness_DG {{{1*/ 1537 ElementVector* Tria::CreatePVectorBalancedthickness_DG(void){ 1538 1539 /*Constants*/ 1540 const int numdof=NDOF1*NUMVERTICES; 1541 1542 /*Intermediaries */ 1543 int i,j,ig; 1544 double xyz_list[NUMVERTICES][3]; 1545 double melting_g,accumulation_g,dhdt_g,Jdettria; 1546 double L[NUMVERTICES]; 1547 GaussTria* gauss=NULL; 1548 1549 /*Initialize Element vector and return if necessary*/ 1550 if(IsOnWater()) return NULL; 1551 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 1552 1553 /*Retrieve all inputs and parameters*/ 1554 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1555 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input); 1556 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input); 1557 Input* dhdt_input=inputs->GetInput(DhDtEnum); ISSMASSERT(dhdt_input); 1558 1559 /* Start looping on the number of gaussian points: */ 1560 gauss=new GaussTria(2); 1561 for(ig=gauss->begin();ig<gauss->end();ig++){ 1562 1563 gauss->GaussPoint(ig); 1564 1565 accumulation_input->GetParameterValue(&accumulation_g,gauss); 1566 melting_input->GetParameterValue(&melting_g,gauss); 1567 dhdt_input->GetParameterValue(&dhdt_g,gauss); 1568 1569 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 1570 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1571 1572 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(accumulation_g-melting_g-dhdt_g)*L[i]; 1573 } 1574 1575 /*Clean up and return*/ 1576 delete gauss; 1577 return pe; 1578 } 1579 /*}}}*/ 1580 /*FUNCTION Tria::CreatePVectorBalancedvelocities {{{1*/ 1581 ElementVector* Tria::CreatePVectorBalancedvelocities(void){ 1582 1583 /*Constants*/ 1584 const int numdof=NDOF1*NUMVERTICES; 1585 1586 /*Intermediaries */ 1587 int i,j,ig; 1588 double xyz_list[NUMVERTICES][3]; 1589 double Jdettria,accumulation_g,melting_g; 1590 double L[NUMVERTICES]; 1591 GaussTria* gauss=NULL; 1592 1593 /*Initialize Element vector and return if necessary*/ 1594 if(IsOnWater()) return NULL; 1595 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 1596 1597 /*Retrieve all inputs and parameters*/ 1598 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1599 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input); 1600 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input); 1601 1602 /* Start looping on the number of gaussian points: */ 1603 gauss=new GaussTria(2); 1604 for(ig=gauss->begin();ig<gauss->end();ig++){ 1605 1606 gauss->GaussPoint(ig); 1607 1608 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 1609 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1610 1611 accumulation_input->GetParameterValue(&accumulation_g,gauss); 1612 melting_input->GetParameterValue(&melting_g,gauss); 1613 1614 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(accumulation_g-melting_g)*L[i]; 1615 } 1616 1617 /*Clean up and return*/ 1618 delete gauss; 1619 return pe; 1620 } 1621 /*}}}*/ 1622 /*FUNCTION Tria::CreatePVectorDiagnosticBaseVert {{{1*/ 1623 ElementVector* Tria::CreatePVectorDiagnosticBaseVert(void){ 1624 1625 /*Constants*/ 1626 const int numdof=NDOF1*NUMVERTICES; 1627 1628 /*Intermediaries */ 1629 int i,j,ig; 1630 int approximation; 1631 double xyz_list[NUMVERTICES][3]; 1632 double Jdet; 1633 double vx,vy,vz,dbdx,dbdy,meltingvalue; 1634 double slope[2]; 1635 double L[NUMVERTICES]; 1636 GaussTria* gauss=NULL; 1637 1638 /*Initialize Element vector and return if necessary*/ 1639 if(IsOnWater()) return NULL; 1640 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 1641 1642 /*Retrieve all inputs and parameters*/ 1643 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1644 inputs->GetParameterValue(&approximation,ApproximationEnum); 1645 Input* bed_input=inputs->GetInput(BedEnum); ISSMASSERT(bed_input); 1646 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input); 1647 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1648 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1649 Input* vzstokes_input=NULL; 1650 if(approximation==PattynStokesApproximationEnum){ 1651 vzstokes_input=inputs->GetInput(VzStokesEnum); ISSMASSERT(vzstokes_input); 1652 } 1653 1654 /* Start looping on the number of gaussian points: */ 1655 gauss=new GaussTria(2); 1656 for(ig=gauss->begin();ig<gauss->end();ig++){ 1657 1658 gauss->GaussPoint(ig); 1659 1660 melting_input->GetParameterValue(&meltingvalue, gauss); 1661 bed_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss); 1662 vx_input->GetParameterValue(&vx, gauss); 1663 vy_input->GetParameterValue(&vy, gauss); 1664 if(approximation==PattynStokesApproximationEnum){ 1665 vzstokes_input->GetParameterValue(&vz, gauss); 1666 } 1667 else vz=0; 1668 1669 dbdx=slope[0]; 1670 dbdy=slope[1]; 1671 1672 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss); 1673 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 1674 1675 for(i=0;i<numdof;i++) pe->values[i]+=-Jdet*gauss->weight*(vx*dbdx+vy*dbdy-vz-meltingvalue)*L[i]; 1676 } 1677 1678 /*Clean up and return*/ 1679 delete gauss; 1680 return pe; 1681 } 1682 /*}}}*/ 1683 /*FUNCTION Tria::CreatePVectorDiagnosticMacAyeal {{{1*/ 1684 ElementVector* Tria::CreatePVectorDiagnosticMacAyeal(){ 1685 1686 /*Constants*/ 1687 const int numdof=NDOF2*NUMVERTICES; 1688 1689 /*Intermediaries */ 1690 int i,j,ig,drag_type; 1691 double plastic_stress,driving_stress_baseline,thickness; 1692 double Jdet; 1693 double xyz_list[NUMVERTICES][3]; 1694 double slope[2]; 1695 double l1l2l3[3]; 1696 double pe_g_gaussian[numdof]; 1697 GaussTria* gauss=NULL; 1698 1699 /*Initialize Element vector and return if necessary*/ 1700 if(IsOnWater()) return NULL; 1701 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum); 1702 1703 /*Retrieve all inputs and parameters*/ 1704 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1705 inputs->GetParameterValue(&drag_type,DragTypeEnum); 1706 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1707 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input); 1708 Input* drag_input=inputs->GetInput(DragCoefficientEnum);ISSMASSERT(drag_input); 1709 1710 /* Start looping on the number of gaussian points: */ 1711 gauss=new GaussTria(2); 1712 for(ig=gauss->begin();ig<gauss->end();ig++){ 1713 1714 gauss->GaussPoint(ig); 1715 1716 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1717 GetNodalFunctions(l1l2l3, gauss); 1718 1719 thickness_input->GetParameterValue(&thickness,gauss); 1720 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss); 1721 1722 /*In case we have plastic basal drag, compute plastic stress at gaussian point from k1, k2 and k3 fields in the 1723 * element itself: */ 1724 if(drag_type==1) drag_input->GetParameterValue(&plastic_stress,gauss); 1725 1726 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness; 1727 1728 /*Build pe_g_gaussian vector: */ 1729 if(drag_type==1){ 1730 for (i=0;i<NUMVERTICES;i++){ 1731 for (j=0;j<NDOF2;j++){ 1732 pe->values[i*NDOF2+j]+=(-driving_stress_baseline*slope[j]-plastic_stress)*Jdet*gauss->weight*l1l2l3[i]; 1733 } 1734 } 1735 } 1736 else { 1737 for (i=0;i<NUMVERTICES;i++){ 1738 for (j=0;j<NDOF2;j++){ 1739 pe->values[i*NDOF2+j]+=-driving_stress_baseline*slope[j]*Jdet*gauss->weight*l1l2l3[i]; 1740 } 1741 } 1742 } 1743 } 1744 1745 /*Clean up and return*/ 1746 delete gauss; 1747 return pe; 1748 } 1749 /*}}}*/ 1750 /*FUNCTION Tria::CreatePVectorAdjointBalancedthickness{{{1*/ 1751 ElementVector* Tria::CreatePVectorAdjointBalancedthickness(void){ 1752 1753 /*Constants*/ 1754 const int numdof=1*NUMVERTICES; 1755 1756 /*Intermediaries */ 1757 int i,ig; 1758 double Jdet; 1759 double thickness,thicknessobs,weight; 1760 double xyz_list[NUMVERTICES][3]; 1761 double l1l2l3[3]; 1762 GaussTria* gauss=NULL; 1763 1764 /*Initialize Element vector and return if necessary*/ 1765 if(IsOnWater()) return NULL; 1766 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 1767 1768 /*Retrieve all inputs and parameters*/ 1769 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1770 Input* thickness_input =inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1771 Input* thicknessobs_input=inputs->GetInput(ThicknessObsEnum);ISSMASSERT(thicknessobs_input); 1772 Input* weights_input =inputs->GetInput(WeightsEnum); ISSMASSERT(weights_input); 1773 1774 /* Start looping on the number of gaussian points: */ 1775 gauss=new GaussTria(2); 1776 for(ig=gauss->begin();ig<gauss->end();ig++){ 1777 1778 gauss->GaussPoint(ig); 1779 1780 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1781 GetNodalFunctions(l1l2l3, gauss); 1782 1783 thickness_input->GetParameterValue(&thickness, gauss); 1784 thicknessobs_input->GetParameterValue(&thicknessobs, gauss); 1785 weights_input->GetParameterValue(&weight, gauss); 1786 1787 for(i=0;i<numdof;i++) pe->values[i]+=(thicknessobs-thickness)*weight*Jdet*gauss->weight*l1l2l3[i]; 1788 } 1789 1790 /*Clean up and return*/ 1791 delete gauss; 1792 return pe; 1793 } 1794 /*}}}*/ 1795 /*FUNCTION Tria::CreatePVectorAdjointHoriz{{{1*/ 1796 ElementVector* Tria::CreatePVectorAdjointHoriz(void){ 1797 1798 /*Constants*/ 1799 const int numdof=NDOF2*NUMVERTICES; 1800 1801 /*Intermediaries */ 1802 int i,ig,response; 1803 double Jdet; 1804 double obs_velocity_mag,velocity_mag; 1805 double dux,duy,meanvel,epsvel; 1806 double scalex=0,scaley=0,scale=0,S=0; 1807 double xyz_list[NUMVERTICES][3]; 1808 double vx_list[NUMVERTICES]; 1809 double vy_list[NUMVERTICES]; 1810 double obs_vx_list[NUMVERTICES]; 1811 double obs_vy_list[NUMVERTICES]; 1812 double dux_list[NUMVERTICES]; 1813 double duy_list[NUMVERTICES]; 1814 double weights_list[NUMVERTICES]; 1815 double l1l2l3[3]; 1816 GaussTria* gauss=NULL; 1817 1818 /*Initialize Element vector and return if necessary*/ 1819 if(IsOnWater()) return NULL; 1820 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 1821 1822 /*Retrieve all inputs and parameters*/ 1823 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1824 this->parameters->FindParam(&meanvel,MeanVelEnum); 1825 this->parameters->FindParam(&epsvel,EpsVelEnum); 1826 GetParameterListOnVertices(&obs_vx_list[0],VxObsEnum); 1827 GetParameterListOnVertices(&obs_vy_list[0],VyObsEnum); 1828 GetParameterListOnVertices(&vx_list[0],VxEnum); 1829 GetParameterListOnVertices(&vy_list[0],VyEnum); 1830 GetParameterListOnVertices(&weights_list[0],WeightsEnum); 1831 inputs->GetParameterValue(&response,CmResponseEnum); 1832 if(response==SurfaceAverageVelMisfitEnum){ 1833 inputs->GetParameterValue(&S,SurfaceAreaEnum); 1834 } 1835 1836 /*Get Du at the 3 nodes (integration of the linearized function) 1837 * Here we integrate linearized functions: 1838 * 1839 * J(E) = int_E sum_{i=1}^3 J_i Phi_i 1840 * 1841 * d J dJ_i 1842 * DU= - --- = sum_{i=1}^3 - --- Phi_i = sum_{i=1}^3 DU_i Phi_i 1843 * d u du_i 1844 * 1845 * where J_i are the misfits at the 3 nodes of the triangle 1846 * Phi_i is the nodal function (P1) with respect to 1847 * the vertex i 1848 */ 1849 if(response==SurfaceAbsVelMisfitEnum){ 1850 /*We are using an absolute misfit: 1851 * 1852 * 1 [ 2 2 ] 1853 * J = --- | (u - u ) + (v - v ) | 1854 * 2 [ obs obs ] 1855 * 1856 * dJ 1857 * DU = - -- = (u - u ) 1858 * du obs 1859 */ 1860 for (i=0;i<NUMVERTICES;i++){ 1861 dux_list[i]=obs_vx_list[i]-vx_list[i]; 1862 duy_list[i]=obs_vy_list[i]-vy_list[i]; 1863 } 1864 } 1865 else if(response==SurfaceRelVelMisfitEnum){ 1866 /*We are using a relative misfit: 1867 * 1868 * 1 [ \bar{v}^2 2 \bar{v}^2 2 ] 1869 * J = --- | ------------- (u - u ) + ------------- (v - v ) | 1870 * 2 [ (u + eps)^2 obs (v + eps)^2 obs ] 1871 * obs obs 1872 * 1873 * dJ \bar{v}^2 1874 * DU = - -- = ------------- (u - u ) 1875 * du (u + eps)^2 obs 1876 * obs 1877 */ 1878 for (i=0;i<NUMVERTICES;i++){ 1879 scalex=pow(meanvel/(obs_vx_list[i]+epsvel),2); 1880 scaley=pow(meanvel/(obs_vy_list[i]+epsvel),2); 1881 if(obs_vx_list[i]==0)scalex=0; 1882 if(obs_vy_list[i]==0)scaley=0; 1883 dux_list[i]=scalex*(obs_vx_list[i]-vx_list[i]); 1884 duy_list[i]=scaley*(obs_vy_list[i]-vy_list[i]); 1885 } 1886 } 1887 else if(response==SurfaceLogVelMisfitEnum){ 1888 /*We are using a logarithmic misfit: 1889 * 1890 * [ vel + eps ] 2 1891 * J = 4 \bar{v}^2 | log ( ----------- ) | 1892 * [ vel + eps ] 1893 * obs 1894 * 1895 * dJ 2 * log(...) 1896 * DU = - -- = - 4 \bar{v}^2 ------------- u 1897 * du vel^2 + eps 1898 * 1899 */ 1900 for (i=0;i<NUMVERTICES;i++){ 1901 velocity_mag=sqrt(pow(vx_list[i],2)+pow(vy_list[i],2))+epsvel; //epsvel to avoid velocity being nil. 1902 obs_velocity_mag=sqrt(pow(obs_vx_list[i],2)+pow(obs_vy_list[i],2))+epsvel; //epsvel to avoid observed velocity being nil. 1903 scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag); 1904 dux_list[i]=scale*vx_list[i]; 1905 duy_list[i]=scale*vy_list[i]; 1906 } 1907 } 1908 else if(response==SurfaceAverageVelMisfitEnum){ 1909 /*We are using an spacially average absolute misfit: 1910 * 1911 * 1 2 2 1912 * J = --- sqrt( (u - u ) + (v - v ) ) 1913 * S obs obs 1914 * 1915 * dJ 1 1 1916 * DU = - -- = - --- ----------- * 2 (u - u ) 1917 * du S 2 sqrt(...) obs 1918 */ 1919 for (i=0;i<NUMVERTICES;i++){ 1920 scale=1.0/(S*sqrt(pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2))+epsvel); 1921 dux_list[i]=scale*(obs_vx_list[i]-vx_list[i]); 1922 duy_list[i]=scale*(obs_vy_list[i]-vy_list[i]); 1923 } 1924 } 1925 else if(response==SurfaceLogVxVyMisfitEnum){ 1926 /*We are using an logarithmic 2 misfit: 1927 * 1928 * 1 [ |u| + eps 2 |v| + eps 2 ] 1929 * J = --- \bar{v}^2 | log ( ----------- ) + log ( ----------- ) | 1930 * 2 [ |u |+ eps |v |+ eps ] 1931 * obs obs 1932 * dJ 1 u 1 1933 * DU = - -- = - \bar{v}^2 log(u...) --------- ---- ~ - \bar{v}^2 log(u...) ------ 1934 * du |u| + eps |u| u + eps 1935 */ 1936 for (i=0;i<NUMVERTICES;i++){ 1937 dux_list[i] = - pow(meanvel,(double)2)*( 1938 log((fabs(vx_list[i])+epsvel)/(fabs(obs_vx_list[i])+epsvel)) * 1/(vx_list[i]+epsvel)); 1939 duy_list[i] = - pow(meanvel,(double)2)*( 1940 log((fabs(vy_list[i])+epsvel)/(fabs(obs_vy_list[i])+epsvel)) * 1/(vy_list[i]+epsvel)); 1941 } 1942 } 1943 else{ 1944 /*Not supported yet! : */ 1945 ISSMERROR("response %s not supported yet",EnumToString(response)); 1946 } 1947 1948 /*Apply weights to DU*/ 1949 for (i=0;i<NUMVERTICES;i++){ 1950 dux_list[i]=weights_list[i]*dux_list[i]; 1951 duy_list[i]=weights_list[i]*duy_list[i]; 1952 } 1953 1954 /* Start looping on the number of gaussian points: */ 1955 gauss=new GaussTria(2); 1956 for(ig=gauss->begin();ig<gauss->end();ig++){ 1957 1958 gauss->GaussPoint(ig); 1959 1960 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1961 GetNodalFunctions(l1l2l3, gauss); 1962 1963 TriaRef::GetParameterValue(&dux, &dux_list[0],gauss); 1964 TriaRef::GetParameterValue(&duy, &duy_list[0],gauss); 1965 1966 for (i=0;i<NUMVERTICES;i++){ 1967 pe->values[i*NDOF2+0]+=dux*Jdet*gauss->weight*l1l2l3[i]; 1968 pe->values[i*NDOF2+1]+=duy*Jdet*gauss->weight*l1l2l3[i]; 1969 } 1970 } 1971 1972 /*Clean up and return*/ 1973 delete gauss; 1974 return pe; 1975 } 1976 /*}}}*/ 1977 /*FUNCTION Tria::CreatePVectorAdjointStokes{{{1*/ 1978 ElementVector* Tria::CreatePVectorAdjointStokes(void){ 1979 1980 /*Intermediaries */ 1981 int i,ig; 1982 int fit=-1; 1983 int response; 1984 double Jdet; 1985 double obs_velocity_mag,velocity_mag; 1986 double dux,duy,meanvel,epsvel; 1987 double scalex=0,scaley=0,scale=0,S=0; 1988 double xyz_list[NUMVERTICES][3]; 1989 double vx_list[NUMVERTICES]; 1990 double vy_list[NUMVERTICES]; 1991 double obs_vx_list[NUMVERTICES]; 1992 double obs_vy_list[NUMVERTICES]; 1993 double dux_list[NUMVERTICES]; 1994 double duy_list[NUMVERTICES]; 1995 double weights_list[NUMVERTICES]; 1996 double l1l2l3[3]; 1997 GaussTria* gauss=NULL; 1998 1999 /*Initialize Element vector and return if necessary*/ 2000 if(IsOnWater()) return NULL; 2001 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum); 2002 2003 /*Retrieve all inputs and parameters*/ 2004 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2005 this->parameters->FindParam(&meanvel,MeanVelEnum); 2006 this->parameters->FindParam(&epsvel,EpsVelEnum); 2007 GetParameterListOnVertices(&obs_vx_list[0],VxObsEnum); 2008 GetParameterListOnVertices(&obs_vy_list[0],VyObsEnum); 2009 GetParameterListOnVertices(&vx_list[0],VxEnum); 2010 GetParameterListOnVertices(&vy_list[0],VyEnum); 2011 GetParameterListOnVertices(&weights_list[0],WeightsEnum); 2012 inputs->GetParameterValue(&response,CmResponseEnum); 2013 if(response==SurfaceAverageVelMisfitEnum){ 2014 inputs->GetParameterValue(&S,SurfaceAreaEnum); 2015 } 2016 2017 /*Get Du at the 3 nodes (integration of the linearized function) 2018 * Here we integrate linearized functions: 2019 * 2020 * J(E) = int_E sum_{i=1}^3 J_i Phi_i 2021 * 2022 * d J dJ_i 2023 * DU= - --- = sum_{i=1}^3 - --- Phi_i = sum_{i=1}^3 DU_i Phi_i 2024 * d u du_i 2025 * 2026 * where J_i are the misfits at the 3 nodes of the triangle 2027 * Phi_i is the nodal function (P1) with respect to 2028 * the vertex i 2029 */ 2030 if(response==SurfaceAbsVelMisfitEnum){ 2031 /*We are using an absolute misfit: 2032 * 2033 * 1 [ 2 2 ] 2034 * J = --- | (u - u ) + (v - v ) | 2035 * 2 [ obs obs ] 2036 * 2037 * dJ 2 2038 * DU = - -- = (u - u ) 2039 * du obs 2040 */ 2041 for (i=0;i<NUMVERTICES;i++){ 2042 dux_list[i]=obs_vx_list[i]-vx_list[i]; 2043 duy_list[i]=obs_vy_list[i]-vy_list[i]; 2044 } 2045 } 2046 else if(response==SurfaceRelVelMisfitEnum){ 2047 /*We are using a relative misfit: 2048 * 2049 * 1 [ \bar{v}^2 2 \bar{v}^2 2 ] 2050 * J = --- | ------------- (u - u ) + ------------- (v - v ) | 2051 * 2 [ (u + eps)^2 obs (v + eps)^2 obs ] 2052 * obs obs 2053 * 2054 * dJ \bar{v}^2 2055 * DU = - -- = ------------- (u - u ) 2056 * du (u + eps)^2 obs 2057 * obs 2058 */ 2059 for (i=0;i<NUMVERTICES;i++){ 2060 scalex=pow(meanvel/(obs_vx_list[i]+epsvel),2); 2061 scaley=pow(meanvel/(obs_vy_list[i]+epsvel),2); 2062 if(obs_vx_list[i]==0)scalex=0; 2063 if(obs_vy_list[i]==0)scaley=0; 2064 dux_list[i]=scalex*(obs_vx_list[i]-vx_list[i]); 2065 duy_list[i]=scaley*(obs_vy_list[i]-vy_list[i]); 2066 } 2067 } 2068 else if(response==SurfaceLogVelMisfitEnum){ 2069 /*We are using a logarithmic misfit: 2070 * 2071 * [ vel + eps ] 2 2072 * J = 4 \bar{v}^2 | log ( ----------- ) | 2073 * [ vel + eps ] 2074 * obs 2075 * 2076 * dJ 2 * log(...) 2077 * DU = - -- = - 4 \bar{v}^2 ------------- u 2078 * du vel^2 + eps 2079 * 2080 */ 2081 for (i=0;i<NUMVERTICES;i++){ 2082 velocity_mag=sqrt(pow(vx_list[i],2)+pow(vy_list[i],2))+epsvel; //epsvel to avoid velocity being nil. 2083 obs_velocity_mag=sqrt(pow(obs_vx_list[i],2)+pow(obs_vy_list[i],2))+epsvel; //epsvel to avoid observed velocity being nil. 2084 scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag); 2085 dux_list[i]=scale*vx_list[i]; 2086 duy_list[i]=scale*vy_list[i]; 2087 } 2088 } 2089 else if(response==SurfaceAverageVelMisfitEnum){ 2090 /*We are using an spacially average absolute misfit: 2091 * 2092 * 1 2 2 2093 * J = --- sqrt( (u - u ) + (v - v ) ) 2094 * S obs obs 2095 * 2096 * dJ 1 1 2097 * DU = - -- = - --- ----------- * 2 (u - u ) 2098 * du S 2 sqrt(...) obs 2099 */ 2100 for (i=0;i<NUMVERTICES;i++){ 2101 scale=1.0/(S*sqrt(pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2))+epsvel); 2102 dux_list[i]=scale*(obs_vx_list[i]-vx_list[i]); 2103 duy_list[i]=scale*(obs_vy_list[i]-vy_list[i]); 2104 } 2105 } 2106 else if(response==SurfaceLogVxVyMisfitEnum){ 2107 /*We are using an logarithmic 2 misfit: 2108 * 2109 * 1 [ |u| + eps 2 |v| + eps 2 ] 2110 * J = --- \bar{v}^2 | log ( ----------- ) + log ( ----------- ) | 2111 * 2 [ |u |+ eps |v |+ eps ] 2112 * obs obs 2113 * dJ 1 u 1 2114 * DU = - -- = - \bar{v}^2 log(u...) --------- ---- ~ - \bar{v}^2 log(u...) ------ 2115 * du |u| + eps |u| u + eps 2116 */ 2117 for (i=0;i<NUMVERTICES;i++){ 2118 dux_list[i] = - pow(meanvel,(double)2)*( 2119 log((fabs(vx_list[i])+epsvel)/(fabs(obs_vx_list[i])+epsvel)) * 1/(vx_list[i]+epsvel)); 2120 duy_list[i] = - pow(meanvel,(double)2)*( 2121 log((fabs(vy_list[i])+epsvel)/(fabs(obs_vy_list[i])+epsvel)) * 1/(vy_list[i]+epsvel)); 2122 } 2123 } 2124 else{ 2125 /*Not supported yet! : */ 2126 ISSMERROR("response %s not supported yet",EnumToString(response)); 2127 } 2128 2129 /*Apply weights to DU*/ 2130 for (i=0;i<NUMVERTICES;i++){ 2131 dux_list[i]=weights_list[i]*dux_list[i]; 2132 duy_list[i]=weights_list[i]*duy_list[i]; 2133 } 2134 2135 /* Start looping on the number of gaussian points: */ 2136 gauss=new GaussTria(2); 2137 for(ig=gauss->begin();ig<gauss->end();ig++){ 2138 2139 gauss->GaussPoint(ig); 2140 2141 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 2142 GetNodalFunctions(l1l2l3, gauss); 2143 2144 TriaRef::GetParameterValue(&dux, &dux_list[0],gauss); 2145 TriaRef::GetParameterValue(&duy, &duy_list[0],gauss); 2146 2147 for (i=0;i<NUMVERTICES;i++){ 2148 pe->values[i*NDOF4+0]+=dux*Jdet*gauss->weight*l1l2l3[i]; 2149 pe->values[i*NDOF4+1]+=duy*Jdet*gauss->weight*l1l2l3[i]; 2150 } 2151 } 2152 2153 /*Clean up and return*/ 2154 delete gauss; 2155 return pe; 2156 } 2157 /*}}}*/ 2158 /*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/ 2159 ElementVector* Tria::CreatePVectorDiagnosticHutter(void){ 2160 2161 /*Intermediaries */ 2162 int i,connectivity; 2163 double constant_part,ub,vb; 2164 double rho_ice,gravity,n,B; 2165 double slope2,thickness; 2166 double slope[2]; 2167 GaussTria* gauss=NULL; 2168 2169 /*Initialize Element vector and return if necessary*/ 2170 if(IsOnWater()) return NULL; 2171 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2172 2173 /*Retrieve all inputs and parameters*/ 2174 rho_ice=matpar->GetRhoIce(); 2175 gravity=matpar->GetG(); 2176 n=matice->GetN(); 2177 B=matice->GetBbar(); 2178 Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); ISSMASSERT(slopex_input); 2179 Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); ISSMASSERT(slopey_input); 2180 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 2181 2182 /*Spawn 3 sing elements: */ 2183 gauss=new GaussTria(); 2184 for(i=0;i<NUMVERTICES;i++){ 2185 2186 gauss->GaussVertex(i); 2187 2188 connectivity=nodes[i]->GetConnectivity(); 2189 2190 thickness_input->GetParameterValue(&thickness,gauss); 2191 slopex_input->GetParameterValue(&slope[0],gauss); 2192 slopey_input->GetParameterValue(&slope[1],gauss); 2193 slope2=pow(slope[0],2)+pow(slope[1],2); 2194 2195 constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2)); 2196 2197 ub=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[0]; 2198 vb=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[1]; 2199 2200 pe->values[2*i] =(ub-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[0])/(double)connectivity; 2201 pe->values[2*i+1]=(vb-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[1])/(double)connectivity; 2202 } 2203 2204 /*Clean up and return*/ 2205 delete gauss; 2206 return pe; 2207 } 2208 /*}}}*/ 2209 /*FUNCTION Tria::CreatePVectorPrognostic{{{1*/ 2210 ElementVector* Tria::CreatePVectorPrognostic(void){ 2211 2212 switch(GetElementType()){ 2213 case P1Enum: 2214 return CreatePVectorPrognostic_CG(); 2215 case P1DGEnum: 2216 return CreatePVectorPrognostic_DG(); 2217 default: 2218 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType())); 2219 } 2220 } 2221 /*}}}*/ 2222 /*FUNCTION Tria::CreatePVectorPrognostic_CG {{{1*/ 2223 ElementVector* Tria::CreatePVectorPrognostic_CG(void){ 2224 2225 /*Constants*/ 2226 const int numdof=NDOF1*NUMVERTICES; 2227 2228 /*Intermediaries */ 2229 int i,j,ig; 2230 double Jdettria,dt; 2231 double accumulation_g,melting_g,thickness_g; 2232 double xyz_list[NUMVERTICES][3]; 2233 double L[NUMVERTICES]; 2234 GaussTria* gauss=NULL; 2235 2236 /*Initialize Element vector and return if necessary*/ 2237 if(IsOnWater()) return NULL; 2238 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2239 2240 /*Retrieve all inputs and parameters*/ 2241 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2242 this->parameters->FindParam(&dt,DtEnum); 2243 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input); 2244 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input); 2245 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 2246 2247 /* Start looping on the number of gaussian points: */ 2248 gauss=new GaussTria(2); 2249 for(ig=gauss->begin();ig<gauss->end();ig++){ 2250 2251 gauss->GaussPoint(ig); 2252 2253 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 2254 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 2255 2256 accumulation_input->GetParameterValue(&accumulation_g,gauss); 2257 melting_input->GetParameterValue(&melting_g,gauss); 2258 thickness_input->GetParameterValue(&thickness_g,gauss); 2259 2260 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i]; 2261 } 2262 2263 /*Clean up and return*/ 2264 delete gauss; 2265 return pe; 2266 } 2267 /*}}}*/ 2268 /*FUNCTION Tria::CreatePVectorPrognostic_DG {{{1*/ 2269 ElementVector* Tria::CreatePVectorPrognostic_DG(void){ 2270 2271 /*Constants*/ 2272 const int numdof=NDOF1*NUMVERTICES; 2273 2274 /*Intermediaries */ 2275 int i,j,ig; 2276 double Jdettria,dt; 2277 double accumulation_g,melting_g,thickness_g; 2278 double xyz_list[NUMVERTICES][3]; 2279 double L[NUMVERTICES]; 2280 GaussTria* gauss=NULL; 2281 2282 /*Initialize Element vector and return if necessary*/ 2283 if(IsOnWater()) return NULL; 2284 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2285 2286 /*Retrieve all inputs and parameters*/ 2287 this->parameters->FindParam(&dt,DtEnum); 2288 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2289 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input); 2290 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input); 2291 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 2292 2293 /* Start looping on the number of gaussian points: */ 2294 gauss=new GaussTria(2); 2295 for(ig=gauss->begin();ig<gauss->end();ig++){ 2296 2297 gauss->GaussPoint(ig); 2298 2299 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss); 2300 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1); 2301 2302 accumulation_input->GetParameterValue(&accumulation_g,gauss); 2303 melting_input->GetParameterValue(&melting_g,gauss); 2304 thickness_input->GetParameterValue(&thickness_g,gauss); 2305 2306 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i]; 2307 } 2308 2309 /*Clean up and return*/ 2310 delete gauss; 2311 return pe; 2312 } 2313 /*}}}*/ 2314 /*FUNCTION Tria::CreatePVectorSlope {{{1*/ 2315 ElementVector* Tria::CreatePVectorSlope(void){ 2316 2317 /*Constants*/ 2318 const int numdof=NDOF1*NUMVERTICES; 2319 2320 /*Intermediaries */ 2321 int i,j,ig; 2322 int analysis_type; 2323 double Jdet; 2324 double xyz_list[NUMVERTICES][3]; 2325 double slope[2]; 2326 double l1l2l3[3]; 2327 GaussTria* gauss=NULL; 2328 2329 /*Initialize Element vector and return if necessary*/ 2330 if(IsOnWater()) return NULL; 2331 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2332 2333 /*Retrieve all inputs and parameters*/ 2334 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 2335 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2336 Input* slope_input=NULL; 2337 if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==SurfaceSlopeYAnalysisEnum)){ 2338 slope_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(slope_input); 2339 } 2340 if ( (analysis_type==BedSlopeXAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){ 2341 slope_input=inputs->GetInput(BedEnum); ISSMASSERT(slope_input); 2342 } 2343 2344 /* Start looping on the number of gaussian points: */ 2345 gauss=new GaussTria(2); 2346 for(ig=gauss->begin();ig<gauss->end();ig++){ 2347 2348 gauss->GaussPoint(ig); 2349 2350 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 2351 GetNodalFunctions(l1l2l3, gauss); 2352 2353 slope_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss); 2354 2355 if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==BedSlopeXAnalysisEnum)){ 2356 for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[0]*l1l2l3[i]; 2357 } 2358 if ( (analysis_type==SurfaceSlopeYAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){ 2359 for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[1]*l1l2l3[i]; 2360 } 2361 } 2362 2363 /*Clean up and return*/ 2364 delete gauss; 2365 return pe; 2366 } 2367 /*}}}*/ 2368 /*FUNCTION Tria::CreatePVectorThermalShelf {{{1*/ 2369 ElementVector* Tria::CreatePVectorThermalShelf(void){ 2370 2371 /*Constants*/ 2372 const int numdof=NUMVERTICES*NDOF1; 2373 2374 /*Intermediaries */ 2375 int i,ig; 2376 double Jdet; 2377 double mixed_layer_capacity,thermal_exchange_velocity; 2378 double rho_ice,rho_water,pressure,dt,scalar_ocean; 2379 double meltingpoint,beta,heatcapacity,t_pmp; 2380 double xyz_list[NUMVERTICES][3]; 2381 double l1l2l3[NUMVERTICES]; 2382 GaussTria* gauss=NULL; 2383 2384 /*Initialize Element vector and return if necessary*/ 2385 if(IsOnWater()) return NULL; 2386 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2387 2388 /*Retrieve all inputs and parameters*/ 2389 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2390 mixed_layer_capacity=matpar->GetMixedLayerCapacity(); 2391 thermal_exchange_velocity=matpar->GetThermalExchangeVelocity(); 2392 rho_water=matpar->GetRhoWater(); 2393 rho_ice=matpar->GetRhoIce(); 2394 heatcapacity=matpar->GetHeatCapacity(); 2395 beta=matpar->GetBeta(); 2396 meltingpoint=matpar->GetMeltingPoint(); 2397 this->parameters->FindParam(&dt,DtEnum); 2398 Input* pressure_input=inputs->GetInput(PressureEnum); ISSMASSERT(pressure_input); 2399 2400 /* Start looping on the number of gauss 2d (nodes on the bedrock) */ 2401 gauss=new GaussTria(2); 2402 for(ig=gauss->begin();ig<gauss->end();ig++){ 2403 2404 gauss->GaussPoint(ig); 2405 2406 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss); 2407 GetNodalFunctions(&l1l2l3[0], gauss); 2408 2409 pressure_input->GetParameterValue(&pressure,gauss); 2410 t_pmp=meltingpoint-beta*pressure; 2411 2412 scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice); 2413 if(dt) scalar_ocean=dt*scalar_ocean; 2414 2415 for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*l1l2l3[i]; 2416 } 2417 2418 /*Clean up and return*/ 2419 delete gauss; 2420 return pe; 2421 } 2422 /*}}}*/ 2423 /*FUNCTION Tria::CreatePVectorThermalSheet {{{1*/ 2424 ElementVector* Tria::CreatePVectorThermalSheet(void){ 2425 2426 /*Constants*/ 2427 const int numdof=NUMVERTICES*NDOF1; 2428 2429 /*Intermediaries */ 2430 int i,ig; 2431 int analysis_type,drag_type; 2432 double xyz_list[NUMVERTICES][3]; 2433 double Jdet,dt; 2434 double rho_ice,heatcapacity,geothermalflux_value; 2435 double basalfriction,alpha2,vx,vy,pressure; 2436 double pressure_list[3]; 2437 double scalar; 2438 double l1l2l3[NUMVERTICES]; 2439 Friction* friction=NULL; 2440 GaussTria* gauss=NULL; 2441 2442 /*Initialize Element vector and return if necessary*/ 2443 if(IsOnWater()) return NULL; 2444 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters); 2445 2446 /*Retrieve all inputs and parameters*/ 2447 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2448 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 2449 rho_ice=matpar->GetRhoIce(); 2450 heatcapacity=matpar->GetHeatCapacity(); 2451 this->inputs->GetParameterValue(&dt,DtEnum); 2452 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2453 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2454 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 2455 Input* geothermalflux_input=inputs->GetInput(GeothermalFluxEnum); ISSMASSERT(geothermalflux_input); 2456 2457 /*Build frictoin element, needed later: */ 2458 inputs->GetParameterValue(&drag_type,DragTypeEnum); 2459 if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!"); 2460 friction=new Friction("3d",inputs,matpar,analysis_type); 2461 2462 /* Start looping on the number of gauss 2d (nodes on the bedrock) */ 2463 gauss=new GaussTria(2); 2464 for(ig=gauss->begin();ig<gauss->end();ig++){ 2465 2466 gauss->GaussPoint(ig); 2467 2468 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss); 2469 GetNodalFunctions(&l1l2l3[0], gauss); 2470 2471 geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss); 2472 friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum); 2473 vx_input->GetParameterValue(&vx,gauss); 2474 vy_input->GetParameterValue(&vy,gauss); 2475 basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0)); 2476 2477 scalar=gauss->weight*Jdet*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice); 2478 if(dt) scalar=dt*scalar; 2479 2480 for(i=0;i<numdof;i++) pe->values[i]+=scalar*l1l2l3[i]; 2481 } 2482 2483 /*Clean up and return*/ 2484 delete gauss; 2485 delete friction; 2486 return pe; 2487 } 2488 /*}}}*/ 2489 /*FUNCTION Tria::ComputeBasalStress {{{1*/ 2490 void Tria::ComputeBasalStress(Vec eps){ 2491 ISSMERROR("Not Implemented yet"); 2492 } 2493 /*}}}*/ 2494 /*FUNCTION Tria::ComputeStrainRate {{{1*/ 2495 void Tria::ComputeStrainRate(Vec eps){ 2496 ISSMERROR("Not Implemented yet"); 2497 } 2498 /*}}}*/ 2499 /*FUNCTION Tria::Configure {{{1*/ 2500 void Tria::Configure(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){ 2501 2502 /*go into parameters and get the analysis_counter: */ 2503 int analysis_counter; 2504 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 2505 2506 /*Get Element type*/ 2507 this->element_type=this->element_type_list[analysis_counter]; 2508 2509 /*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective 2510 * datasets, using internal ids and offsets hidden in hooks: */ 2511 if(this->hnodes[analysis_counter]) this->hnodes[analysis_counter]->configure(nodesin); 2512 this->hmatice->configure(materialsin); 2513 this->hmatpar->configure(materialsin); 2514 2515 /*Now, go pick up the objects inside the hooks: */ 2516 if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 2517 else this->nodes=NULL; 2518 this->matice=(Matice*)this->hmatice->delivers(); 2519 this->matpar=(Matpar*)this->hmatpar->delivers(); 2520 2521 /*point parameters to real dataset: */ 2522 this->parameters=parametersin; 2523 2524 } 2525 /*}}}*/ 2526 /*FUNCTION Tria::ControlInputGetGradient{{{1*/ 2527 void Tria::ControlInputGetGradient(Vec gradient,int enum_type){ 2528 2529 int doflist1[NUMVERTICES]; 2530 Input* input=NULL; 2531 2532 if(enum_type==RheologyBbarEnum){ 2533 input=(Input*)matice->inputs->GetInput(enum_type); 2534 } 2535 else{ 2536 input=inputs->GetInput(enum_type); 2537 } 2538 if (!input) ISSMERROR("Input %s not found",EnumToString(enum_type)); 2539 if (input->Enum()!=ControlInputEnum) ISSMERROR("Input %s is not a ControlInput",EnumToString(enum_type)); 2540 2541 this->GetDofList1(&doflist1[0]); 2542 ((ControlInput*)input)->GetGradient(gradient,&doflist1[0]); 2543 2544 }/*}}}*/ 2545 /*FUNCTION Tria::ControlInputScaleGradient{{{1*/ 2546 void Tria::ControlInputScaleGradient(int enum_type,double scale){ 2547 2548 Input* input=NULL; 2549 2550 if(enum_type==RheologyBbarEnum){ 2551 input=(Input*)matice->inputs->GetInput(enum_type); 2552 } 2553 else{ 2554 input=inputs->GetInput(enum_type); 2555 } 2556 if (!input) ISSMERROR("Input %s not found",EnumToString(enum_type)); 2557 if (input->Enum()!=ControlInputEnum) ISSMERROR("Input %s is not a ControlInput",EnumToString(enum_type)); 2558 2559 ((ControlInput*)input)->ScaleGradient(scale); 2560 }/*}}}*/ 2561 /*FUNCTION Tria::ControlInputSetGradient{{{1*/ 2562 void Tria::ControlInputSetGradient(double* gradient,int enum_type){ 2563 2564 int doflist1[NUMVERTICES]; 2565 double grad_list[NUMVERTICES]; 2566 Input* grad_input=NULL; 2567 Input* input=NULL; 2568 2569 if(enum_type==RheologyBbarEnum){ 2570 input=(Input*)matice->inputs->GetInput(enum_type); 2571 } 2572 else{ 2573 input=inputs->GetInput(enum_type); 2574 } 2575 if (!input) ISSMERROR("Input %s not found",EnumToString(enum_type)); 2576 if (input->Enum()!=ControlInputEnum) ISSMERROR("Input %s is not a ControlInput",EnumToString(enum_type)); 2577 2578 this->GetDofList1(&doflist1[0]); 2579 for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[doflist1[i]]; 2580 grad_input=new TriaVertexInput(GradientEnum,grad_list); 2581 2582 ((ControlInput*)input)->SetGradient(grad_input); 2583 2584 }/*}}}*/ 2585 /*FUNCTION Tria::DeepEcho{{{1*/ 2586 void Tria::DeepEcho(void){ 2587 2588 printf("Tria:\n"); 2589 printf(" id: %i\n",id); 2590 if(nodes){ 2591 nodes[0]->DeepEcho(); 2592 nodes[1]->DeepEcho(); 2593 nodes[2]->DeepEcho(); 2594 } 2595 else printf("nodes = NULL\n"); 2596 2597 if (matice) matice->DeepEcho(); 2598 else printf("matice = NULL\n"); 2599 2600 if (matpar) matpar->DeepEcho(); 2601 else printf("matpar = NULL\n"); 2602 2603 printf(" parameters\n"); 2604 if (parameters) parameters->DeepEcho(); 2605 else printf("parameters = NULL\n"); 2606 2607 printf(" inputs\n"); 2608 if (inputs) inputs->DeepEcho(); 2609 else printf("inputs=NULL\n"); 2610 2611 if (results) results->DeepEcho(); 2612 else printf("results=NULL\n"); 2613 2614 return; 2615 } 2616 /*}}}*/ 2617 /*FUNCTION Tria::DeleteResults {{{1*/ 2618 void Tria::DeleteResults(void){ 2619 2620 /*Delete and reinitialize results*/ 2621 delete this->results; 2622 this->results=new Results(); 2623 2624 } 2625 /*}}}*/ 2626 /*FUNCTION Tria::Echo{{{1*/ 2627 void Tria::Echo(void){ 2628 printf("Tria:\n"); 2629 printf(" id: %i\n",id); 2630 if(nodes){ 2631 nodes[0]->Echo(); 2632 nodes[1]->Echo(); 2633 nodes[2]->Echo(); 2634 } 2635 else printf("nodes = NULL\n"); 2636 2637 if (matice) matice->Echo(); 2638 else printf("matice = NULL\n"); 2639 2640 if (matpar) matpar->Echo(); 2641 else printf("matpar = NULL\n"); 2642 2643 printf(" parameters\n"); 2644 if (parameters) parameters->Echo(); 2645 else printf("parameters = NULL\n"); 2646 2647 printf(" inputs\n"); 2648 if (inputs) inputs->Echo(); 2649 else printf("inputs=NULL\n"); 2650 2651 if (results) results->Echo(); 2652 else printf("results=NULL\n"); 2653 } 2654 /*}}}*/ 2655 /*FUNCTION Tria::Enum {{{1*/ 2656 int Tria::Enum(void){ 2657 2658 return TriaEnum; 2659 2660 } 2661 /*}}}*/ 2662 /*FUNCTION Tria::GetArea {{{1*/ 2663 double Tria::GetArea(void){ 2664 2665 double area=0; 2666 double xyz_list[NUMVERTICES][3]; 2667 double x1,y1,x2,y2,x3,y3; 2668 2669 /*Get xyz list: */ 2670 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2671 x1=xyz_list[0][0]; y1=xyz_list[0][1]; 2672 x2=xyz_list[1][0]; y2=xyz_list[1][1]; 2673 x3=xyz_list[2][0]; y3=xyz_list[2][1]; 2674 2675 return (x2*y3 - y2*x3 + x1*y2 - y1*x2 + x3*y1 - y3*x1)/2; 2676 } 2677 /*}}}*/ 2678 /*FUNCTION Tria::GetDofList {{{1*/ 2679 void Tria::GetDofList(int** pdoflist, int approximation_enum,int setenum){ 2680 2681 int i,j; 2682 int count=0; 2683 int numberofdofs=0; 2684 int* doflist=NULL; 2685 2686 /*First, figure out size of doflist and create it: */ 2687 for(i=0;i<3;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum); 2688 doflist=(int*)xmalloc(numberofdofs*sizeof(int)); 2689 2690 /*Populate: */ 2691 count=0; 2692 for(i=0;i<3;i++){ 2693 nodes[i]->GetDofList(doflist+count,approximation_enum,setenum); 2694 count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum); 2695 } 2696 2697 /*Assign output pointers:*/ 2698 *pdoflist=doflist; 2699 } 2700 /*}}}*/ 2701 /*FUNCTION Tria::GetDofList1 {{{1*/ 2702 void Tria::GetDofList1(int* doflist){ 2703 2704 int i; 2705 for(i=0;i<3;i++) doflist[i]=nodes[i]->GetDofList1(); 2706 2707 } 2708 /*}}}*/ 2709 /*FUNCTION Tria::GetElementType {{{1*/ 2710 int Tria::GetElementType(){ 2711 2712 /*return TriaRef field*/ 2713 return this->element_type; 2714 2715 } 2716 /*}}}*/ 2717 /*FUNCTION Tria::GetNodeIndex {{{1*/ 2718 int Tria::GetNodeIndex(Node* node){ 2719 2720 ISSMASSERT(nodes); 2721 for(int i=0;i<NUMVERTICES;i++){ 2722 if(node==nodes[i]) 2723 return i; 2724 } 2725 ISSMERROR("Node provided not found among element nodes"); 2726 } 2727 /*}}}*/ 2728 /*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/ 2729 void Tria::GetParameterListOnVertices(double* pvalue,int enumtype){ 2730 2731 /*Intermediaries*/ 2732 double value[NUMVERTICES]; 2733 GaussTria *gauss = NULL; 2734 2735 /*Recover input*/ 2736 Input* input=inputs->GetInput(enumtype); 2737 if (!input) ISSMERROR("Input %s not found in element",EnumToString(enumtype)); 2738 2739 /*Checks in debugging mode*/ 2740 ISSMASSERT(pvalue); 2741 2742 /* Start looping on the number of vertices: */ 2743 gauss=new GaussTria(); 2744 for (int iv=0;iv<NUMVERTICES;iv++){ 2745 gauss->GaussVertex(iv); 2746 input->GetParameterValue(&pvalue[iv],gauss); 2747 } 2748 2749 /*clean-up*/ 2750 delete gauss; 2751 } 2752 /*}}}*/ 2753 /*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/ 2754 void Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){ 2755 2756 double value[NUMVERTICES]; 2757 GaussTria *gauss = NULL; 2758 Input *input = inputs->GetInput(enumtype); 2759 2760 /*Checks in debugging mode*/ 2761 ISSMASSERT(pvalue); 2762 2763 /* Start looping on the number of vertices: */ 2764 if (input){ 2765 gauss=new GaussTria(); 2766 for (int iv=0;iv<NUMVERTICES;iv++){ 2767 gauss->GaussVertex(iv); 2768 input->GetParameterValue(&pvalue[iv],gauss); 2769 } 2770 } 2771 else{ 2772 for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue; 2773 } 2774 2775 /*clean-up*/ 2776 delete gauss; 2777 } 2778 /*}}}*/ 2779 /*FUNCTION Tria::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/ 2780 void Tria::GetParameterValue(double* pvalue,Node* node,int enumtype){ 2781 2782 Input* input=inputs->GetInput(enumtype); 2783 if(!input) ISSMERROR("No input of type %s found in tria",EnumToString(enumtype)); 2784 2785 GaussTria* gauss=new GaussTria(); 2786 gauss->GaussVertex(this->GetNodeIndex(node)); 2787 2788 input->GetParameterValue(pvalue,gauss); 2789 delete gauss; 2790 } 2791 /*}}}*/ 2792 /*FUNCTION Tria::GetSidList {{{1*/ 2793 void Tria::GetSidList(int* sidlist){ 2794 2795 int i; 2796 for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList(); 2797 2798 } 2799 /*}}}*/ 2800 /*FUNCTION Tria::GetSolutionFromInputs{{{1*/ 2801 void Tria::GetSolutionFromInputs(Vec solution){ 2802 2803 /*retrive parameters: */ 2804 int analysis_type; 2805 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 2806 2807 /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */ 2808 if (analysis_type==DiagnosticHorizAnalysisEnum) 2809 GetSolutionFromInputsDiagnosticHoriz(solution); 2810 else if (analysis_type==DiagnosticHutterAnalysisEnum) 2811 GetSolutionFromInputsDiagnosticHutter(solution); 2812 else 2813 ISSMERROR("analysis: %s not supported yet",EnumToString(analysis_type)); 2814 2815 } 2816 /*}}}*/ 2817 /*FUNCTION Tria::GetSolutionFromInputsDiagnosticHoriz{{{1*/ 2818 void Tria::GetSolutionFromInputsDiagnosticHoriz(Vec solution){ 2819 2820 const int numdof=NDOF2*NUMVERTICES; 2821 2822 int i; 2823 int* doflist=NULL; 2824 double vx,vy; 2825 double values[numdof]; 2826 GaussTria* gauss=NULL; 2827 2828 /*Get dof list: */ 2829 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 2830 2831 /*Get inputs*/ 2832 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2833 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2834 2835 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 2836 /*P1 element only for now*/ 2837 gauss=new GaussTria(); 2838 for(i=0;i<NUMVERTICES;i++){ 2839 2840 gauss->GaussVertex(i); 2841 2842 /*Recover vx and vy*/ 2843 vx_input->GetParameterValue(&vx,gauss); 2844 vy_input->GetParameterValue(&vy,gauss); 2845 values[i*NDOF2+0]=vx; 2846 values[i*NDOF2+1]=vy; 2847 } 2848 2849 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 2850 2851 /*Free ressources:*/ 2852 delete gauss; 2853 xfree((void**)&doflist); 2854 } 2855 /*}}}*/ 2856 /*FUNCTION Tria::GetSolutionFromInputsDiagnosticHutter{{{1*/ 2857 void Tria::GetSolutionFromInputsDiagnosticHutter(Vec solution){ 2858 2859 const int numdof=NDOF2*NUMVERTICES; 2860 2861 int i,dummy; 2862 int* doflist=NULL; 2863 double vx,vy; 2864 double values[numdof]; 2865 GaussTria* gauss=NULL; 2866 2867 /*Get dof list: */ 2868 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 2869 2870 /*Get inputs*/ 2871 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2872 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2873 2874 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 2875 /*P1 element only for now*/ 2876 gauss=new GaussTria(); 2877 for(i=0;i<NUMVERTICES;i++){ 2878 2879 gauss->GaussVertex(i); 2880 2881 /*Recover vx and vy*/ 2882 vx_input->GetParameterValue(&vx,gauss); 2883 vy_input->GetParameterValue(&vy,gauss); 2884 values[i*NDOF2+0]=vx; 2885 values[i*NDOF2+1]=vy; 2886 } 2887 2888 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 2889 2890 /*Free ressources:*/ 2891 delete gauss; 2892 xfree((void**)&doflist); 2893 } 2894 /*}}}*/ 2895 /*FUNCTION Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){{{1*/ 2896 void Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){ 2897 /*Compute the 2d Strain Rate (3 components): 2898 * epsilon=[exx eyy exy] */ 2899 2900 int i; 2901 double epsilonvx[3]; 2902 double epsilonvy[3]; 2903 2904 /*Check that both inputs have been found*/ 2905 if (!vx_input || !vy_input){ 2906 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input); 2907 } 2908 2909 /*Get strain rate assuming that epsilon has been allocated*/ 2910 vx_input->GetVxStrainRate2d(epsilonvx,xyz_list,gauss); 2911 vy_input->GetVyStrainRate2d(epsilonvy,xyz_list,gauss); 2912 2913 /*Sum all contributions*/ 2914 for(i=0;i<3;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]; 2915 } 2916 /*}}}*/ 2917 /*FUNCTION Tria::GetVectorFromInputs{{{1*/ 2918 void Tria::GetVectorFromInputs(Vec vector,int NameEnum){ 2919 2920 int doflist1[NUMVERTICES]; 2921 2922 /*Find NameEnum input in the inputs dataset, and get it to fill in the vector: */ 2923 for(int i=0;i<this->inputs->Size();i++){ 2924 Input* input=(Input*)this->inputs->GetObjectByOffset(i); 2925 if(input->EnumType()==NameEnum){ 2926 /*We found the enum. Use its values to fill into the vector, using the vertices ids: */ 2927 this->GetDofList1(&doflist1[0]); 2928 input->GetVectorFromInputs(vector,&doflist1[0]); 2929 break; 2930 } 2931 } 2932 } 2933 /*}}}*/ 2934 /*FUNCTION Tria::Gradj {{{1*/ 2935 void Tria::Gradj(Vec gradient,int control_type){ 2936 2937 /*If on water, grad = 0: */ 2938 if(IsOnWater())return; 2939 2940 switch(control_type){ 2941 case DragCoefficientEnum: 2942 GradjDrag(gradient); 2943 break; 2944 case RheologyBbarEnum: 2945 GradjB(gradient); 2946 break; 2947 case DhDtEnum: 2948 GradjDhDt(gradient); 2949 break; 2950 case VxEnum: 2951 GradjVx(gradient); 2952 break; 2953 case VyEnum: 2954 GradjVy(gradient); 2955 break; 2956 default: 2957 ISSMERROR("%s%i","control type not supported yet: ",control_type); 2958 } 2959 } 2960 /*}}}*/ 2961 /*FUNCTION Tria::GradjB{{{1*/ 2962 void Tria::GradjB(Vec gradient){ 2963 2964 /*Intermediaries*/ 2965 int i,ig; 2966 int doflist[NUMVERTICES]; 2967 double vx,vy,lambda,mu,thickness,Jdet; 2968 double cm_noisedmp,viscosity_complement; 2969 double dvx[NDOF2],dvy[NDOF2],dadjx[NDOF2],dadjy[NDOF2],dB[NDOF2]; 2970 double xyz_list[NUMVERTICES][3]; 2971 double basis[3],epsilon[3]; 2972 double dbasis[NDOF2][NUMVERTICES]; 2973 double grad_g[NUMVERTICES]; 2974 double grad[NUMVERTICES]={0.0}; 2975 GaussTria *gauss = NULL; 2976 2977 /*retrieve some parameters: */ 2978 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 2979 2980 /* Get node coordinates and dof list: */ 2981 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2982 GetDofList1(&doflist[0]); 2983 2984 /*Retrieve all inputs*/ 2985 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 2986 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 2987 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 2988 Input* adjointx_input=inputs->GetInput(AdjointxEnum); ISSMASSERT(adjointx_input); 2989 Input* adjointy_input=inputs->GetInput(AdjointyEnum); ISSMASSERT(adjointy_input); 2990 Input* rheologyb_input=matice->inputs->GetInput(RheologyBbarEnum); ISSMASSERT(rheologyb_input); 2991 2992 /* Start looping on the number of gaussian points: */ 2993 gauss=new GaussTria(4); 2994 for (ig=gauss->begin();ig<gauss->end();ig++){ 2995 2996 gauss->GaussPoint(ig); 2997 2998 thickness_input->GetParameterValue(&thickness,gauss); 2999 rheologyb_input->GetParameterDerivativeValue(&dB[0],&xyz_list[0][0],gauss); 3000 vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss); 3001 vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss); 3002 adjointx_input->GetParameterDerivativeValue(&dadjx[0],&xyz_list[0][0],gauss); 3003 adjointy_input->GetParameterDerivativeValue(&dadjy[0],&xyz_list[0][0],gauss); 3004 3005 this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input); 3006 matice->GetViscosityComplement(&viscosity_complement,&epsilon[0]); 3007 3008 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 3009 GetNodalFunctions(basis,gauss); 3010 GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss); 3011 3012 /*standard gradient dJ/dki*/ 3013 for (i=0;i<NUMVERTICES;i++){ 3014 grad_g[i]=-viscosity_complement*thickness*( (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1])*Jdet*gauss->weight*basis[i]; 3015 } 3016 /*Add regularization term*/ 3017 for (i=0;i<NUMVERTICES;i++) grad_g[i]-=cm_noisedmp*Jdet*gauss->weight*(dbasis[0][i]*dB[0]+dbasis[1][i]*dB[1]); 3018 for(i=0;i<NUMVERTICES;i++) grad[i]+=grad_g[i]; 3019 } 3020 3021 VecSetValues(gradient,NUMVERTICES,doflist,(const double*)grad,ADD_VALUES); 3022 3023 /*clean-up*/ 3024 delete gauss; 3025 } 3026 /*}}}*/ 3027 /*FUNCTION Tria::GradjDrag {{{1*/ 3028 void Tria::GradjDrag(Vec gradient){ 3029 3030 int i,ig; 3031 int drag_type,analysis_type; 3032 int doflist1[NUMVERTICES]; 3033 double vx,vy,lambda,mu,alpha_complement,Jdet; 3034 double bed,thickness,Neff,drag,cm_noisedmp; 3035 double xyz_list[NUMVERTICES][3]; 3036 double dh1dh3[NDOF2][NUMVERTICES]; 3037 double dk[NDOF2]; 3038 double grade_g[NUMVERTICES]={0.0}; 3039 double grade_g_gaussian[NUMVERTICES]; 3040 double l1l2l3[3]; 3041 double epsilon[3]; /* epsilon=[exx,eyy,exy];*/ 3042 Friction* friction=NULL; 3043 GaussTria *gauss=NULL; 3044 3045 /*retrive parameters: */ 3046 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 3047 3048 /*retrieve some parameters ands return if iceshelf: */ 3049 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 3050 if(IsOnShelf())return; 3051 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 3052 GetDofList1(&doflist1[0]); 3053 3054 /*Build frictoin element, needed later: */ 3055 inputs->GetParameterValue(&drag_type,DragTypeEnum); 3056 friction=new Friction("2d",inputs,matpar,analysis_type); 3057 3058 /*Retrieve all inputs we will be needing: */ 3059 Input* adjointx_input=inputs->GetInput(AdjointxEnum); ISSMASSERT(adjointx_input); 3060 Input* adjointy_input=inputs->GetInput(AdjointyEnum); ISSMASSERT(adjointy_input); 3061 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 3062 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 3063 Input* dragcoefficient_input=inputs->GetInput(DragCoefficientEnum); ISSMASSERT(dragcoefficient_input); 3064 3065 /* Start looping on the number of gaussian points: */ 3066 gauss=new GaussTria(4); 3067 for (ig=gauss->begin();ig<gauss->end();ig++){ 3068 3069 gauss->GaussPoint(ig); 3070 3071 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 3072 GetNodalFunctions(l1l2l3, gauss); 3073 GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss); 3074 3075 /*Build alpha_complement_list: */ 3076 if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum); 3077 else alpha_complement=0; 3078 3079 dragcoefficient_input->GetParameterValue(&drag, gauss); 3080 adjointx_input->GetParameterValue(&lambda, gauss); 3081 adjointy_input->GetParameterValue(&mu, gauss); 3082 vx_input->GetParameterValue(&vx,gauss); 3083 vy_input->GetParameterValue(&vy,gauss); 3084 dragcoefficient_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss); 3085 3086 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */ 3087 for (i=0;i<NUMVERTICES;i++){ 3088 3089 //standard term dJ/dki 3090 grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss->weight*l1l2l3[i]; 3091 3092 //noise dampening d/dki(1/2*(dk/dx)^2) 3093 grade_g_gaussian[i]+=-cm_noisedmp*Jdet*gauss->weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]); 3094 } 3095 3096 /*Add gradje_g_gaussian vector to gradje_g: */ 3097 for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i]; 3098 } 3099 3100 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES); 3101 3102 /*Clean up and return*/ 3103 delete gauss; 3104 delete friction; 3105 } 3106 /*}}}*/ 3107 /*FUNCTION Tria::GradjDragStokes {{{1*/ 3108 void Tria::GradjDragStokes(Vec gradient){ 3109 3110 int i,ig; 3111 int drag_type,analysis_type; 3112 int doflist1[NUMVERTICES]; 3113 double bed,thickness,Neff; 3114 double lambda,mu,xi,Jdet,vx,vy,vz; 3115 double alpha_complement,drag,cm_noisedmp; 3116 double surface_normal[3],bed_normal[3]; 3117 double xyz_list[NUMVERTICES][3]; 3118 double dh1dh3[NDOF2][NUMVERTICES]; 3119 double dk[NDOF2]; 3120 double l1l2l3[3]; 3121 double epsilon[3]; /* epsilon=[exx,eyy,exy];*/ 3122 double grade_g[NUMVERTICES]={0.0}; 3123 double grade_g_gaussian[NUMVERTICES]; 3124 Friction* friction=NULL; 3125 GaussTria* gauss=NULL; 3126 3127 /*retrive parameters: */ 3128 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 3129 3130 /*retrieve inputs :*/ 3131 inputs->GetParameterValue(&drag_type,DragTypeEnum); 3132 Input* drag_input =inputs->GetInput(DragCoefficientEnum); ISSMASSERT(drag_input); 3133 Input* vx_input =inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 3134 Input* vy_input =inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 3135 Input* vz_input =inputs->GetInput(VzEnum); ISSMASSERT(vz_input); 3136 Input* adjointx_input=inputs->GetInput(AdjointxEnum); ISSMASSERT(adjointx_input); 3137 Input* adjointy_input=inputs->GetInput(AdjointyEnum); ISSMASSERT(adjointy_input); 3138 Input* adjointz_input=inputs->GetInput(AdjointzEnum); ISSMASSERT(adjointz_input); 3139 3140 /*retrieve some parameters: */ 3141 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 3142 3143 /*Get out if shelf*/ 3144 if(IsOnShelf())return; 3145 3146 /* Get node coordinates and dof list: */ 3147 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 3148 GetDofList1(&doflist1[0]); 3149 3150 /*Build frictoin element, needed later: */ 3151 inputs->GetParameterValue(&drag_type,DragTypeEnum); 3152 friction=new Friction("2d",inputs,matpar,analysis_type); 3153 3154 /* Start looping on the number of gaussian points: */ 3155 gauss=new GaussTria(4); 3156 for(ig=gauss->begin();ig<gauss->end();ig++){ 3157 3158 gauss->GaussPoint(ig); 3159 3160 /*Recover alpha_complement and drag: */ 3161 if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum); 3162 else alpha_complement=0; 3163 drag_input->GetParameterValue(&drag,gauss); 3164 3165 /*recover lambda mu and xi: */ 3166 adjointx_input->GetParameterValue(&lambda,gauss); 3167 adjointy_input->GetParameterValue(&mu ,gauss); 3168 adjointz_input->GetParameterValue(&xi ,gauss); 3169 3170 /*recover vx vy and vz: */ 3171 vx_input->GetParameterValue(&vx, gauss); 3172 vy_input->GetParameterValue(&vy, gauss); 3173 vz_input->GetParameterValue(&vz, gauss); 3174 3175 /*Get normal vector to the bed */ 3176 SurfaceNormal(&surface_normal[0],xyz_list); 3177 3178 bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result 3179 bed_normal[1]=-surface_normal[1]; 3180 bed_normal[2]=-surface_normal[2]; 3181 3182 /* Get Jacobian determinant: */ 3183 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss); 3184 3185 /* Get nodal functions value at gaussian point:*/ 3186 GetNodalFunctions(l1l2l3, gauss); 3187 3188 /*Get nodal functions derivatives*/ 3189 GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss); 3190 3191 /*Get k derivative: dk/dx */ 3192 drag_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss); 3193 3194 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */ 3195 for (i=0;i<NUMVERTICES;i++){ 3196 //standard gradient dJ/dki 3197 grade_g_gaussian[i]=( 3198 -lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2])) 3199 -mu *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2])) 3200 -xi *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2])) 3201 )*Jdet*gauss->weight*l1l2l3[i]; 3202 3203 //Add regularization term 3204 grade_g_gaussian[i]+= - cm_noisedmp*Jdet*gauss->weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]); 3205 } 3206 3207 /*Add gradje_g_gaussian vector to gradje_g: */ 3208 for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i]; 3209 } 3210 3211 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES); 3212 3213 delete friction; 3214 delete gauss; 3215 } 3216 /*}}}*/ 3217 /*FUNCTION Tria::GradjDhDt{{{1*/ 3218 void Tria::GradjDhDt(Vec gradient){ 3219 3220 /*Intermediaries*/ 3221 int doflist1[NUMVERTICES]; 3222 double lambda[NUMVERTICES]; 3223 double gradient_g[NUMVERTICES]; 3224 3225 GetDofList1(&doflist1[0]); 3226 3227 /*Compute Gradient*/ 3228 GetParameterListOnVertices(&lambda[0],AdjointEnum); 3229 for(int i=0;i<NUMVERTICES;i++) gradient_g[i]=-lambda[i]; 3230 3231 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)gradient_g,INSERT_VALUES); 3232 } 3233 /*}}}*/ 3234 /*FUNCTION Tria::GradjVx{{{1*/ 3235 void Tria::GradjVx(Vec gradient){ 3236 3237 /*Intermediaries*/ 3238 int i,ig; 3239 int doflist1[NUMVERTICES]; 3240 double thickness,Jdet,cm_noisedmp; 3241 double l1l2l3[3]; 3242 double dbasis[NDOF2][NUMVERTICES]; 3243 double Dlambda[2],dp[2]; 3244 double xyz_list[NUMVERTICES][3]; 3245 double grade_g[NUMVERTICES] = {0.0}; 3246 GaussTria *gauss = NULL; 3247 3248 /* Get node coordinates and dof list: */ 3249 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 3250 GetDofList1(&doflist1[0]); 3251 3252 /*Retrieve all inputs we will be needing: */ 3253 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 3254 Input* adjoint_input=inputs->GetInput(AdjointEnum); ISSMASSERT(adjoint_input); 3255 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 3256 3257 /* Start looping on the number of gaussian points: */ 3258 gauss=new GaussTria(2); 3259 for (ig=gauss->begin();ig<gauss->end();ig++){ 3260 3261 gauss->GaussPoint(ig); 3262 3263 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 3264 GetNodalFunctions(l1l2l3, gauss); 3265 GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss); 3266 3267 adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss); 3268 thickness_input->GetParameterValue(&thickness, gauss); 3269 thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss); 3270 3271 for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*l1l2l3[i]; 3272 3273 //noise dampening d/dki(1/2*(dk/dx)^2) 3274 //for (i=0;i<NUMVERTICES;i++) grade_g[i]-=cm_noisedmp*Jdet*gauss->weight*(dbasis[0][i]*dp[0]+dbasis[1][i]*dp[1]); 3275 } 3276 3277 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES); 3278 3279 /*Clean up and return*/ 3280 delete gauss; 3281 } 3282 /*}}}*/ 3283 /*FUNCTION Tria::GradjVy{{{1*/ 3284 void Tria::GradjVy(Vec gradient){ 3285 3286 /*Intermediaries*/ 3287 int i,ig; 3288 int doflist1[NUMVERTICES]; 3289 double thickness,Jdet,cm_noisedmp; 3290 double l1l2l3[3]; 3291 double dbasis[NDOF2][NUMVERTICES]; 3292 double Dlambda[2],dp[2]; 3293 double xyz_list[NUMVERTICES][3]; 3294 double grade_g[NUMVERTICES] = {0.0}; 3295 GaussTria *gauss = NULL; 3296 3297 /* Get node coordinates and dof list: */ 3298 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 3299 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 3300 GetDofList1(&doflist1[0]); 3301 3302 /*Retrieve all inputs we will be needing: */ 3303 Input* adjoint_input=inputs->GetInput(AdjointEnum); ISSMASSERT(adjoint_input); 3304 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 3305 3306 /* Start looping on the number of gaussian points: */ 3307 gauss=new GaussTria(2); 3308 for (ig=gauss->begin();ig<gauss->end();ig++){ 3309 3310 gauss->GaussPoint(ig); 3311 3312 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 3313 GetNodalFunctions(l1l2l3, gauss); 3314 GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss); 3315 3316 adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss); 3317 thickness_input->GetParameterValue(&thickness, gauss); 3318 thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss); 3319 3320 for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*l1l2l3[i]; 3321 3322 //noise dampening d/dki(1/2*(dk/dx)^2) 3323 //for (i=0;i<NUMVERTICES;i++) grade_g[i]-=cm_noisedmp*Jdet*gauss->weight*(dbasis[0][i]*dp[0]+dbasis[1][i]*dp[1]); 3324 } 3325 3326 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES); 3327 3328 /*Clean up and return*/ 3329 delete gauss; 3330 } 3331 /*}}}*/ 3332 /*FUNCTION Tria::Id {{{1*/ 3333 int Tria::Id(){ 3334 3335 return id; 3336 3337 } 3338 /*}}}*/ 3339 /*FUNCTION Tria::InputArtificialNoise{{{1*/ 3340 void Tria::InputArtificialNoise(int enum_type,double min,double max){ 3341 3342 Input* input=NULL; 3343 3344 /*Make a copy of the original input: */ 3345 input=(Input*)this->inputs->GetInput(enum_type); 3346 if(!input)ISSMERROR(" could not find old input with enum: %s",EnumToString(enum_type)); 3347 3348 /*ArtificialNoise: */ 3349 input->ArtificialNoise(min,max); 3350 } 3351 /*}}}*/ 3352 /*FUNCTION Tria::InputControlUpdate{{{1*/ 3353 void Tria::InputControlUpdate(double scalar,bool save_parameter){ 3354 3355 /*Intermediary*/ 3356 int num_controls; 3357 int* control_type=NULL; 3358 Input* input=NULL; 3359 double *cm_min=NULL; 3360 double *cm_max=NULL; 3361 3362 /*retrieve some parameters: */ 3363 this->parameters->FindParam(&cm_min,NULL,CmMinEnum); 3364 this->parameters->FindParam(&cm_max,NULL,CmMaxEnum); 3365 this->parameters->FindParam(&num_controls,NumControlsEnum); 3366 this->parameters->FindParam(&control_type,NULL,ControlTypeEnum); 3367 3368 for(int i=0;i<num_controls;i++){ 3369 3370 if(control_type[i]==RheologyBbarEnum){ 3371 input=(Input*)matice->inputs->GetInput(control_type[i]); ISSMASSERT(input); 3372 } 3373 else{ 3374 input=(Input*)this->inputs->GetInput(control_type[i]); ISSMASSERT(input); 3375 } 3376 3377 if (input->Enum()!=ControlInputEnum){ 3378 ISSMERROR("input %s is not a ControlInput",EnumToString(control_type[i])); 3379 } 3380 3381 ((ControlInput*)input)->UpdateValue(scalar); 3382 input->Constrain(cm_min[i],cm_max[i]); 3383 if (save_parameter) ((ControlInput*)input)->SaveValue(); 3384 3385 } 3386 3387 /*Clean up and return*/ 3388 xfree((void**)&control_type); 3389 xfree((void**)&cm_min); 3390 xfree((void**)&cm_max); 3391 } 3392 /*}}}*/ 3393 /*FUNCTION Tria::InputConvergence{{{1*/ 3394 bool Tria::InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){ 3395 3396 bool converged=true; 3397 int i; 3398 Input** new_inputs=NULL; 3399 Input** old_inputs=NULL; 3400 3401 new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs 3402 old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs 3403 3404 for(i=0;i<num_enums/2;i++){ 3405 new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]); 3406 old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]); 3407 if(!new_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumToString(enums[2*i+0])); 3408 if(!old_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumToString(enums[2*i+0])); 3409 } 3410 3411 /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/ 3412 for(i=0;i<num_criterionenums;i++){ 3413 IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]); 3414 if(eps[i]>criterionvalues[i]) converged=false; 3415 } 3416 3417 /*clean up and return*/ 3418 xfree((void**)&new_inputs); 3419 xfree((void**)&old_inputs); 3420 return converged; 3421 } 3422 /*}}}*/ 3423 /*FUNCTION Tria::InputDepthAverageAtBase {{{1*/ 3424 void Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type,int object_enum){ 3425 3426 /*New input*/ 3427 Input* oldinput=NULL; 3428 Input* newinput=NULL; 3429 3430 /*copy input of enum_type*/ 3431 if (object_enum==ElementsEnum) 3432 oldinput=(Input*)this->inputs->GetInput(enum_type); 3433 else if (object_enum==MaterialsEnum) 3434 oldinput=(Input*)this->matice->inputs->GetInput(enum_type); 3435 else 3436 ISSMERROR("object %s not supported yet",EnumToString(object_enum)); 3437 if(!oldinput)ISSMERROR("%s%s"," could not find old input with enum: ",EnumToString(enum_type)); 3438 newinput=(Input*)oldinput->copy(); 3439 3440 /*Assign new name (average)*/ 3441 newinput->ChangeEnum(average_enum_type); 3442 3443 /*Add new input to current element*/ 3444 if (object_enum==ElementsEnum) 3445 this->inputs->AddInput((Input*)newinput); 3446 else if (object_enum==MaterialsEnum) 3447 this->matice->inputs->AddInput((Input*)newinput); 3448 else 3449 ISSMERROR("object %s not supported yet",EnumToString(object_enum)); 3450 } 3451 /*}}}*/ 3452 /*FUNCTION Tria::InputDuplicate{{{1*/ 3453 void Tria::InputDuplicate(int original_enum,int new_enum){ 3454 3455 /*Call inputs method*/ 3456 if (IsInput(original_enum)) inputs->DuplicateInput(original_enum,new_enum); 3457 3458 } 3459 /*}}}*/ 3460 /*FUNCTION Tria::InputScale{{{1*/ 3461 void Tria::InputScale(int enum_type,double scale_factor){ 3462 3463 Input* input=NULL; 3464 3465 /*Make a copy of the original input: */ 3466 input=(Input*)this->inputs->GetInput(enum_type); 3467 if(!input)ISSMERROR(" could not find old input with enum: %s",EnumToString(enum_type)); 3468 3469 /*Scale: */ 3470 input->Scale(scale_factor); 3471 } 3472 /*}}}*/ 3473 /*FUNCTION Tria::InputToResult{{{1*/ 3474 void Tria::InputToResult(int enum_type,int step,double time){ 3475 3476 int i; 3477 Input *input = NULL; 3478 3479 /*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */ 3480 if (enum_type==RheologyBbarEnum) input=this->matice->inputs->GetInput(enum_type); 3481 else input=this->inputs->GetInput(enum_type); 3482 if (!input) ISSMERROR("Input %s not found in tria->inputs",EnumToString(enum_type)); 3483 3484 /*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result 3485 * object out of the input, with the additional step and time information: */ 3486 this->results->AddObject((Object*)input->SpawnResult(step,time)); 3487 if(input->Enum()==ControlInputEnum) this->results->AddObject((Object*)((ControlInput*)input)->SpawnGradient(step,time)); 3488 } 3489 /*}}}*/ 339 3490 /*FUNCTION Tria::InputUpdateFromConstant(int value, int name);{{{1*/ 340 3491 void Tria::InputUpdateFromConstant(int constant, int name){ … … 362 3513 /*update input*/ 363 3514 this->inputs->AddInput(new BoolInput(name,constant)); 3515 } 3516 /*}}}*/ 3517 /*FUNCTION Tria::InputUpdateFromIoModel{{{1*/ 3518 void Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){ //i is the element index 3519 3520 /*Intermediaries*/ 3521 int i,j; 3522 int tria_vertex_ids[3]; 3523 double nodeinputs[3]; 3524 3525 /*Checks if debuging*/ 3526 /*{{{2*/ 3527 ISSMASSERT(iomodel->elements); 3528 /*}}}*/ 3529 3530 /*Recover vertices ids needed to initialize inputs*/ 3531 for(i=0;i<3;i++){ 3532 tria_vertex_ids[i]=(int)iomodel->elements[3*index+i]; //ids for vertices are in the elements array from Matlab 3533 } 3534 3535 /*add as many inputs per element as requested:*/ 3536 if (iomodel->thickness) { 3537 for(i=0;i<3;i++)nodeinputs[i]=iomodel->thickness[tria_vertex_ids[i]-1]; 3538 this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,nodeinputs)); 3539 } 3540 if (iomodel->surface) { 3541 for(i=0;i<3;i++)nodeinputs[i]=iomodel->surface[tria_vertex_ids[i]-1]; 3542 this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,nodeinputs)); 3543 } 3544 if (iomodel->bed) { 3545 for(i=0;i<3;i++)nodeinputs[i]=iomodel->bed[tria_vertex_ids[i]-1]; 3546 this->inputs->AddInput(new TriaVertexInput(BedEnum,nodeinputs)); 3547 } 3548 if (iomodel->drag_coefficient) { 3549 for(i=0;i<3;i++)nodeinputs[i]=iomodel->drag_coefficient[tria_vertex_ids[i]-1]; 3550 this->inputs->AddInput(new TriaVertexInput(DragCoefficientEnum,nodeinputs)); 3551 3552 if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index])); 3553 if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index])); 3554 this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type)); 3555 } 3556 if (iomodel->thickness_obs) { 3557 for(i=0;i<3;i++)nodeinputs[i]=iomodel->thickness_obs[tria_vertex_ids[i]-1]; 3558 this->inputs->AddInput(new TriaVertexInput(ThicknessObsEnum,nodeinputs)); 3559 } 3560 if (iomodel->melting_rate) { 3561 for(i=0;i<3;i++)nodeinputs[i]=iomodel->melting_rate[tria_vertex_ids[i]-1]/iomodel->yts; 3562 this->inputs->AddInput(new TriaVertexInput(MeltingRateEnum,nodeinputs)); 3563 } 3564 if (iomodel->accumulation_rate) { 3565 for(i=0;i<3;i++)nodeinputs[i]=iomodel->accumulation_rate[tria_vertex_ids[i]-1]/iomodel->yts; 3566 this->inputs->AddInput(new TriaVertexInput(AccumulationRateEnum,nodeinputs)); 3567 } 3568 if (iomodel->geothermalflux) { 3569 for(i=0;i<3;i++)nodeinputs[i]=iomodel->geothermalflux[tria_vertex_ids[i]-1]; 3570 this->inputs->AddInput(new TriaVertexInput(GeothermalFluxEnum,nodeinputs)); 3571 } 3572 if (iomodel->dhdt){ 3573 for(i=0;i<3;i++)nodeinputs[i]=iomodel->dhdt[tria_vertex_ids[i]-1]/iomodel->yts; 3574 this->inputs->AddInput(new TriaVertexInput(DhDtEnum,nodeinputs)); 3575 } 3576 if (iomodel->pressure){ 3577 for(i=0;i<3;i++)nodeinputs[i]=iomodel->pressure[tria_vertex_ids[i]-1]; 3578 this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs)); 3579 } 3580 if (iomodel->temperature) { 3581 for(i=0;i<3;i++)nodeinputs[i]=iomodel->temperature[tria_vertex_ids[i]-1]; 3582 this->inputs->AddInput(new TriaVertexInput(TemperatureEnum,nodeinputs)); 3583 } 3584 /*vx,vy and vz: */ 3585 if (iomodel->vx) { 3586 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx[tria_vertex_ids[i]-1]/iomodel->yts; 3587 this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs)); 3588 this->inputs->AddInput(new TriaVertexInput(VxOldEnum,nodeinputs)); 3589 if(iomodel->qmu_analysis)this->inputs->AddInput(new TriaVertexInput(QmuVxEnum,nodeinputs)); 3590 } 3591 if (iomodel->vy) { 3592 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy[tria_vertex_ids[i]-1]/iomodel->yts; 3593 this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs)); 3594 this->inputs->AddInput(new TriaVertexInput(VyOldEnum,nodeinputs)); 3595 if(iomodel->qmu_analysis)this->inputs->AddInput(new TriaVertexInput(QmuVyEnum,nodeinputs)); 3596 } 3597 if (iomodel->vz) { 3598 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz[tria_vertex_ids[i]-1]/iomodel->yts; 3599 this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs)); 3600 this->inputs->AddInput(new TriaVertexInput(VzOldEnum,nodeinputs)); 3601 if(iomodel->qmu_analysis)this->inputs->AddInput(new TriaVertexInput(QmuVzEnum,nodeinputs)); 3602 } 3603 if (iomodel->vx_obs) { 3604 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx_obs[tria_vertex_ids[i]-1]/iomodel->yts; 3605 this->inputs->AddInput(new TriaVertexInput(VxObsEnum,nodeinputs)); 3606 } 3607 if (iomodel->vy_obs) { 3608 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy_obs[tria_vertex_ids[i]-1]/iomodel->yts; 3609 this->inputs->AddInput(new TriaVertexInput(VyObsEnum,nodeinputs)); 3610 } 3611 if (iomodel->vz_obs) { 3612 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz_obs[tria_vertex_ids[i]-1]/iomodel->yts; 3613 this->inputs->AddInput(new TriaVertexInput(VzObsEnum,nodeinputs)); 3614 } 3615 if (iomodel->weights) { 3616 for(i=0;i<3;i++)nodeinputs[i]=iomodel->weights[tria_vertex_ids[i]-1]; 3617 this->inputs->AddInput(new TriaVertexInput(WeightsEnum,nodeinputs)); 3618 } 3619 if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index])); 3620 if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index])); 3621 if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index])); 3622 if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index])); 3623 3624 /*time: */ 3625 this->inputs->AddInput(new DoubleInput(DtEnum,iomodel->dt*iomodel->yts)); 3626 3627 /*Control Inputs*/ 3628 if (iomodel->control_analysis && iomodel->control_type){ 3629 for(i=0;i<iomodel->num_control_type;i++){ 3630 switch((int)iomodel->control_type[i]){ 3631 case DhDtEnum: 3632 if (iomodel->dhdt){ 3633 for(j=0;j<3;j++)nodeinputs[j]=iomodel->dhdt[tria_vertex_ids[j]-1]/iomodel->yts; 3634 this->inputs->AddInput(new ControlInput(DhDtEnum,TriaVertexInputEnum,nodeinputs,i+1)); 3635 } 3636 break; 3637 case VxEnum: 3638 if (iomodel->vx){ 3639 for(j=0;j<3;j++)nodeinputs[j]=iomodel->vx[tria_vertex_ids[j]-1]/iomodel->yts; 3640 this->inputs->AddInput(new ControlInput(VxEnum,TriaVertexInputEnum,nodeinputs,i+1)); 3641 } 3642 break; 3643 case VyEnum: 3644 if (iomodel->vy){ 3645 for(j=0;j<3;j++)nodeinputs[j]=iomodel->vy[tria_vertex_ids[j]-1]/iomodel->yts; 3646 this->inputs->AddInput(new ControlInput(VyEnum,TriaVertexInputEnum,nodeinputs,i+1)); 3647 } 3648 break; 3649 case DragCoefficientEnum: 3650 if (iomodel->drag_coefficient){ 3651 for(j=0;j<3;j++)nodeinputs[j]=iomodel->drag_coefficient[tria_vertex_ids[j]-1]; 3652 this->inputs->AddInput(new ControlInput(DragCoefficientEnum,TriaVertexInputEnum,nodeinputs,i+1)); 3653 } 3654 break; 3655 case RheologyBbarEnum: 3656 /*Matice will take care of it*/ break; 3657 default: 3658 ISSMERROR("Control %s not implemented yet",EnumToString((int)iomodel->control_type[i])); 3659 } 3660 } 3661 } 364 3662 } 365 3663 /*}}}*/ … … 411 3709 } 412 3710 /*}}}*/ 3711 /*FUNCTION Tria::InputUpdateFromSolutionAdjointBalancedthickness {{{1*/ 3712 void Tria::InputUpdateFromSolutionAdjointBalancedthickness(double* solution){ 3713 3714 const int numdof=NDOF1*NUMVERTICES; 3715 3716 int i; 3717 int* doflist=NULL; 3718 double values[numdof]; 3719 double lambda[NUMVERTICES]; 3720 3721 /*Get dof list: */ 3722 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 3723 3724 /*Use the dof list to index into the solution vector: */ 3725 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 3726 3727 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 3728 for(i=0;i<numdof;i++) lambda[i]=values[i]; 3729 3730 /*Add vx and vy as inputs to the tria element: */ 3731 this->inputs->AddInput(new TriaVertexInput(AdjointEnum,lambda)); 3732 3733 /*Free ressources:*/ 3734 xfree((void**)&doflist); 3735 } 3736 /*}}}*/ 3737 /*FUNCTION Tria::InputUpdateFromSolutionAdjointHoriz {{{1*/ 3738 void Tria::InputUpdateFromSolutionAdjointHoriz(double* solution){ 3739 3740 const int numdof=NDOF2*NUMVERTICES; 3741 3742 int i; 3743 int* doflist=NULL; 3744 double values[numdof]; 3745 double lambdax[NUMVERTICES]; 3746 double lambday[NUMVERTICES]; 3747 3748 /*Get dof list: */ 3749 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 3750 3751 /*Use the dof list to index into the solution vector: */ 3752 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 3753 3754 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 3755 for(i=0;i<NUMVERTICES;i++){ 3756 lambdax[i]=values[i*NDOF2+0]; 3757 lambday[i]=values[i*NDOF2+1]; 3758 } 3759 3760 /*Add vx and vy as inputs to the tria element: */ 3761 this->inputs->AddInput(new TriaVertexInput(AdjointxEnum,lambdax)); 3762 this->inputs->AddInput(new TriaVertexInput(AdjointyEnum,lambday)); 3763 3764 /*Free ressources:*/ 3765 xfree((void**)&doflist); 3766 } 3767 /*}}}*/ 3768 /*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHoriz {{{1*/ 3769 void Tria::InputUpdateFromSolutionDiagnosticHoriz(double* solution){ 3770 3771 const int numdof=NDOF2*NUMVERTICES; 3772 3773 int i; 3774 int dummy; 3775 int* doflist=NULL; 3776 double rho_ice,g; 3777 double values[numdof]; 3778 double vx[NUMVERTICES]; 3779 double vy[NUMVERTICES]; 3780 double vz[NUMVERTICES]; 3781 double vel[NUMVERTICES]; 3782 double pressure[NUMVERTICES]; 3783 double thickness[NUMVERTICES]; 3784 3785 /*Get dof list: */ 3786 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 3787 3788 /*Use the dof list to index into the solution vector: */ 3789 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 3790 3791 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 3792 for(i=0;i<NUMVERTICES;i++){ 3793 vx[i]=values[i*NDOF2+0]; 3794 vy[i]=values[i*NDOF2+1]; 3795 } 3796 3797 /*Get Vz and compute vel*/ 3798 GetParameterListOnVertices(&vz[0],VzEnum,0); 3799 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 3800 3801 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D, 3802 *so the pressure is just the pressure at the bedrock: */ 3803 rho_ice=matpar->GetRhoIce(); 3804 g=matpar->GetG(); 3805 GetParameterListOnVertices(&thickness[0],ThicknessEnum); 3806 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i]; 3807 3808 /*Now, we have to move the previous Vx and Vy inputs to old 3809 * status, otherwise, we'll wipe them off: */ 3810 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 3811 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 3812 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 3813 3814 /*Add vx and vy as inputs to the tria element: */ 3815 this->inputs->AddInput(new TriaVertexInput(VxEnum,vx)); 3816 this->inputs->AddInput(new TriaVertexInput(VyEnum,vy)); 3817 this->inputs->AddInput(new TriaVertexInput(VelEnum,vel)); 3818 this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure)); 3819 3820 /*Free ressources:*/ 3821 xfree((void**)&doflist); 3822 3823 } 3824 /*}}}*/ 3825 /*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHutter {{{1*/ 3826 void Tria::InputUpdateFromSolutionDiagnosticHutter(double* solution){ 3827 3828 const int numdof=NDOF2*NUMVERTICES; 3829 3830 int i; 3831 int dummy; 3832 int* doflist=NULL; 3833 double rho_ice,g; 3834 double values[numdof]; 3835 double vx[NUMVERTICES]; 3836 double vy[NUMVERTICES]; 3837 double vz[NUMVERTICES]; 3838 double vel[NUMVERTICES]; 3839 double pressure[NUMVERTICES]; 3840 double thickness[NUMVERTICES]; 3841 double* vz_ptr=NULL; 3842 Input* vz_input=NULL; 3843 3844 /*Get dof list: */ 3845 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 3846 3847 /*Use the dof list to index into the solution vector: */ 3848 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 3849 3850 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 3851 for(i=0;i<NUMVERTICES;i++){ 3852 vx[i]=values[i*NDOF2+0]; 3853 vy[i]=values[i*NDOF2+1]; 3854 } 3855 3856 /*Get Vz*/ 3857 vz_input=inputs->GetInput(VzEnum); 3858 if (vz_input){ 3859 if (vz_input->Enum()!=TriaVertexInputEnum){ 3860 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum())); 3861 } 3862 vz_input->GetValuesPtr(&vz_ptr,&dummy); 3863 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i]; 3864 } 3865 else{ 3866 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0; 3867 } 3868 3869 /*Now Compute vel*/ 3870 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5); 3871 3872 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D, 3873 *so the pressure is just the pressure at the bedrock: */ 3874 rho_ice=matpar->GetRhoIce(); 3875 g=matpar->GetG(); 3876 GetParameterListOnVertices(&thickness[0],ThicknessEnum); 3877 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i]; 3878 3879 /*Now, we have to move the previous Vx and Vy inputs to old 3880 * status, otherwise, we'll wipe them off: */ 3881 this->inputs->ChangeEnum(VxEnum,VxOldEnum); 3882 this->inputs->ChangeEnum(VyEnum,VyOldEnum); 3883 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum); 3884 3885 /*Add vx and vy as inputs to the tria element: */ 3886 this->inputs->AddInput(new TriaVertexInput(VxEnum,vx)); 3887 this->inputs->AddInput(new TriaVertexInput(VyEnum,vy)); 3888 this->inputs->AddInput(new TriaVertexInput(VelEnum,vel)); 3889 this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure)); 3890 3891 /*Free ressources:*/ 3892 xfree((void**)&doflist); 3893 } 3894 /*}}}*/ 3895 /*FUNCTION Tria::InputUpdateFromSolutionOneDof{{{1*/ 3896 void Tria::InputUpdateFromSolutionOneDof(double* solution,int enum_type){ 3897 3898 const int numdof = NDOF1*NUMVERTICES; 3899 3900 int* doflist=NULL; 3901 double values[numdof]; 3902 3903 /*Get dof list: */ 3904 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 3905 3906 /*Use the dof list to index into the solution vector: */ 3907 for(int i=0;i<numdof;i++) values[i]=solution[doflist[i]]; 3908 3909 /*Add input to the element: */ 3910 this->inputs->AddInput(new TriaVertexInput(enum_type,values)); 3911 3912 /*Free ressources:*/ 3913 xfree((void**)&doflist); 3914 } 3915 /*}}}*/ 413 3916 /*FUNCTION Tria::InputUpdateFromVector(double* vector, int name, int type);{{{1*/ 414 3917 void Tria::InputUpdateFromVector(double* vector, int name, int type){ … … 535 4038 } 536 4039 /*}}}*/ 537 /*FUNCTION Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){{{1*/ 538 void Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){ //i is the element index 539 540 /*Intermediaries*/ 541 int i,j; 542 int tria_vertex_ids[3]; 543 double nodeinputs[3]; 544 545 /*Checks if debuging*/ 546 /*{{{2*/ 547 ISSMASSERT(iomodel->elements); 548 /*}}}*/ 549 550 /*Recover vertices ids needed to initialize inputs*/ 551 for(i=0;i<3;i++){ 552 tria_vertex_ids[i]=(int)iomodel->elements[3*index+i]; //ids for vertices are in the elements array from Matlab 553 } 554 555 /*add as many inputs per element as requested:*/ 556 if (iomodel->thickness) { 557 for(i=0;i<3;i++)nodeinputs[i]=iomodel->thickness[tria_vertex_ids[i]-1]; 558 this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,nodeinputs)); 559 } 560 if (iomodel->surface) { 561 for(i=0;i<3;i++)nodeinputs[i]=iomodel->surface[tria_vertex_ids[i]-1]; 562 this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,nodeinputs)); 563 } 564 if (iomodel->bed) { 565 for(i=0;i<3;i++)nodeinputs[i]=iomodel->bed[tria_vertex_ids[i]-1]; 566 this->inputs->AddInput(new TriaVertexInput(BedEnum,nodeinputs)); 567 } 568 if (iomodel->drag_coefficient) { 569 for(i=0;i<3;i++)nodeinputs[i]=iomodel->drag_coefficient[tria_vertex_ids[i]-1]; 570 this->inputs->AddInput(new TriaVertexInput(DragCoefficientEnum,nodeinputs)); 571 572 if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index])); 573 if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index])); 574 this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type)); 575 } 576 if (iomodel->thickness_obs) { 577 for(i=0;i<3;i++)nodeinputs[i]=iomodel->thickness_obs[tria_vertex_ids[i]-1]; 578 this->inputs->AddInput(new TriaVertexInput(ThicknessObsEnum,nodeinputs)); 579 } 580 if (iomodel->melting_rate) { 581 for(i=0;i<3;i++)nodeinputs[i]=iomodel->melting_rate[tria_vertex_ids[i]-1]/iomodel->yts; 582 this->inputs->AddInput(new TriaVertexInput(MeltingRateEnum,nodeinputs)); 583 } 584 if (iomodel->accumulation_rate) { 585 for(i=0;i<3;i++)nodeinputs[i]=iomodel->accumulation_rate[tria_vertex_ids[i]-1]/iomodel->yts; 586 this->inputs->AddInput(new TriaVertexInput(AccumulationRateEnum,nodeinputs)); 587 } 588 if (iomodel->geothermalflux) { 589 for(i=0;i<3;i++)nodeinputs[i]=iomodel->geothermalflux[tria_vertex_ids[i]-1]; 590 this->inputs->AddInput(new TriaVertexInput(GeothermalFluxEnum,nodeinputs)); 591 } 592 if (iomodel->dhdt){ 593 for(i=0;i<3;i++)nodeinputs[i]=iomodel->dhdt[tria_vertex_ids[i]-1]/iomodel->yts; 594 this->inputs->AddInput(new TriaVertexInput(DhDtEnum,nodeinputs)); 595 } 596 if (iomodel->pressure){ 597 for(i=0;i<3;i++)nodeinputs[i]=iomodel->pressure[tria_vertex_ids[i]-1]; 598 this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs)); 599 } 600 if (iomodel->temperature) { 601 for(i=0;i<3;i++)nodeinputs[i]=iomodel->temperature[tria_vertex_ids[i]-1]; 602 this->inputs->AddInput(new TriaVertexInput(TemperatureEnum,nodeinputs)); 603 } 604 /*vx,vy and vz: */ 605 if (iomodel->vx) { 606 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx[tria_vertex_ids[i]-1]/iomodel->yts; 607 this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs)); 608 this->inputs->AddInput(new TriaVertexInput(VxOldEnum,nodeinputs)); 609 if(iomodel->qmu_analysis)this->inputs->AddInput(new TriaVertexInput(QmuVxEnum,nodeinputs)); 610 } 611 if (iomodel->vy) { 612 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy[tria_vertex_ids[i]-1]/iomodel->yts; 613 this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs)); 614 this->inputs->AddInput(new TriaVertexInput(VyOldEnum,nodeinputs)); 615 if(iomodel->qmu_analysis)this->inputs->AddInput(new TriaVertexInput(QmuVyEnum,nodeinputs)); 616 } 617 if (iomodel->vz) { 618 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz[tria_vertex_ids[i]-1]/iomodel->yts; 619 this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs)); 620 this->inputs->AddInput(new TriaVertexInput(VzOldEnum,nodeinputs)); 621 if(iomodel->qmu_analysis)this->inputs->AddInput(new TriaVertexInput(QmuVzEnum,nodeinputs)); 622 } 623 if (iomodel->vx_obs) { 624 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx_obs[tria_vertex_ids[i]-1]/iomodel->yts; 625 this->inputs->AddInput(new TriaVertexInput(VxObsEnum,nodeinputs)); 626 } 627 if (iomodel->vy_obs) { 628 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy_obs[tria_vertex_ids[i]-1]/iomodel->yts; 629 this->inputs->AddInput(new TriaVertexInput(VyObsEnum,nodeinputs)); 630 } 631 if (iomodel->vz_obs) { 632 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz_obs[tria_vertex_ids[i]-1]/iomodel->yts; 633 this->inputs->AddInput(new TriaVertexInput(VzObsEnum,nodeinputs)); 634 } 635 if (iomodel->weights) { 636 for(i=0;i<3;i++)nodeinputs[i]=iomodel->weights[tria_vertex_ids[i]-1]; 637 this->inputs->AddInput(new TriaVertexInput(WeightsEnum,nodeinputs)); 638 } 639 if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index])); 640 if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index])); 641 if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index])); 642 if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index])); 643 644 /*time: */ 645 this->inputs->AddInput(new DoubleInput(DtEnum,iomodel->dt*iomodel->yts)); 646 647 /*Control Inputs*/ 648 if (iomodel->control_analysis && iomodel->control_type){ 649 for(i=0;i<iomodel->num_control_type;i++){ 650 switch((int)iomodel->control_type[i]){ 651 case DhDtEnum: 652 if (iomodel->dhdt){ 653 for(j=0;j<3;j++)nodeinputs[j]=iomodel->dhdt[tria_vertex_ids[j]-1]/iomodel->yts; 654 this->inputs->AddInput(new ControlInput(DhDtEnum,TriaVertexInputEnum,nodeinputs,i+1)); 655 } 656 break; 657 case VxEnum: 658 if (iomodel->vx){ 659 for(j=0;j<3;j++)nodeinputs[j]=iomodel->vx[tria_vertex_ids[j]-1]/iomodel->yts; 660 this->inputs->AddInput(new ControlInput(VxEnum,TriaVertexInputEnum,nodeinputs,i+1)); 661 } 662 break; 663 case VyEnum: 664 if (iomodel->vy){ 665 for(j=0;j<3;j++)nodeinputs[j]=iomodel->vy[tria_vertex_ids[j]-1]/iomodel->yts; 666 this->inputs->AddInput(new ControlInput(VyEnum,TriaVertexInputEnum,nodeinputs,i+1)); 667 } 668 break; 669 case DragCoefficientEnum: 670 if (iomodel->drag_coefficient){ 671 for(j=0;j<3;j++)nodeinputs[j]=iomodel->drag_coefficient[tria_vertex_ids[j]-1]; 672 this->inputs->AddInput(new ControlInput(DragCoefficientEnum,TriaVertexInputEnum,nodeinputs,i+1)); 673 } 674 break; 675 case RheologyBbarEnum: 676 /*Matice will take care of it*/ break; 677 default: 678 ISSMERROR("Control %s not implemented yet",EnumToString((int)iomodel->control_type[i])); 679 } 680 } 681 } 682 } 683 /*}}}*/ 684 685 /*Element virtual functions definitions: */ 686 /*FUNCTION Tria::AverageOntoPartition {{{1*/ 687 void Tria::AverageOntoPartition(Vec partition_contributions,Vec partition_areas,double* vertex_response,double* qmu_part){ 688 689 bool already=false; 690 int i,j; 691 int partition[NUMVERTICES]; 692 int offsetsid[NUMVERTICES]; 693 int offsetdof[NUMVERTICES]; 694 double area; 695 double mean; 696 double values[3]; 697 698 /*First, get the area: */ 699 area=this->GetArea(); 700 701 /*Figure out the average for this element: */ 702 this->GetSidList(&offsetsid[0]); 703 this->GetDofList1(&offsetdof[0]); 704 mean=0; 705 for(i=0;i<NUMVERTICES;i++){ 706 partition[i]=(int)qmu_part[offsetsid[i]]; 707 mean=mean+1.0/NUMVERTICES*vertex_response[offsetdof[i]]; 708 } 709 710 /*Add contribution: */ 711 for(i=0;i<NUMVERTICES;i++){ 712 already=false; 713 for(j=0;j<i;j++){ 714 if (partition[i]==partition[j]){ 715 already=true; 716 break; 717 } 718 } 719 if(!already){ 720 VecSetValue(partition_contributions,partition[i],mean*area,ADD_VALUES); 721 VecSetValue(partition_areas,partition[i],area,ADD_VALUES); 722 }; 723 } 724 } 725 /*}}}*/ 726 /*FUNCTION Tria::ComputeBasalStress {{{1*/ 727 void Tria::ComputeBasalStress(Vec eps){ 728 ISSMERROR("Not Implemented yet"); 729 } 730 /*}}}*/ 731 /*FUNCTION Tria::ComputeStrainRate {{{1*/ 732 void Tria::ComputeStrainRate(Vec eps){ 733 ISSMERROR("Not Implemented yet"); 734 } 735 /*}}}*/ 736 /*FUNCTION Tria::SetCurrentConfiguration {{{1*/ 737 void Tria::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){ 4040 /*FUNCTION Tria::IsInput{{{1*/ 4041 bool Tria::IsInput(int name){ 4042 if ( 4043 name==ThicknessEnum || 4044 name==SurfaceEnum || 4045 name==BedEnum || 4046 name==SurfaceSlopeXEnum || 4047 name==SurfaceSlopeYEnum || 4048 name==MeltingRateEnum || 4049 name==DtEnum || 4050 name==AccumulationRateEnum || 4051 name==SurfaceAreaEnum|| 4052 name==VxEnum || 4053 name==VyEnum || 4054 name==VxObsEnum || 4055 name==VyObsEnum || 4056 name==CmResponseEnum || 4057 name==DragCoefficientEnum || 4058 name==GradientEnum || 4059 name==OldGradientEnum 4060 ){ 4061 return true; 4062 } 4063 else return false; 4064 } 4065 /*}}}*/ 4066 /*FUNCTION Tria::IsOnBed {{{1*/ 4067 bool Tria::IsOnBed(){ 738 4068 739 /*go into parameters and get the analysis_counter: */ 740 int analysis_counter; 741 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 742 743 /*Get Element type*/ 744 this->element_type=this->element_type_list[analysis_counter]; 745 746 /*Pick up nodes*/ 747 if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 748 else this->nodes=NULL; 749 750 } 751 /*}}}*/ 752 /*FUNCTION Tria::Configure {{{1*/ 753 void Tria::Configure(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){ 754 755 /*go into parameters and get the analysis_counter: */ 756 int analysis_counter; 757 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 758 759 /*Get Element type*/ 760 this->element_type=this->element_type_list[analysis_counter]; 761 762 /*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective 763 * datasets, using internal ids and offsets hidden in hooks: */ 764 if(this->hnodes[analysis_counter]) this->hnodes[analysis_counter]->configure(nodesin); 765 this->hmatice->configure(materialsin); 766 this->hmatpar->configure(materialsin); 767 768 /*Now, go pick up the objects inside the hooks: */ 769 if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 770 else this->nodes=NULL; 771 this->matice=(Matice*)this->hmatice->delivers(); 772 this->matpar=(Matpar*)this->hmatpar->delivers(); 773 774 /*point parameters to real dataset: */ 775 this->parameters=parametersin; 776 777 } 778 /*}}}*/ 779 /*FUNCTION Tria::ControlInputGetGradient{{{1*/ 780 void Tria::ControlInputGetGradient(Vec gradient,int enum_type){ 781 782 int doflist1[NUMVERTICES]; 783 Input* input=NULL; 784 785 if(enum_type==RheologyBbarEnum){ 786 input=(Input*)matice->inputs->GetInput(enum_type); 787 } 788 else{ 789 input=inputs->GetInput(enum_type); 790 } 791 if (!input) ISSMERROR("Input %s not found",EnumToString(enum_type)); 792 if (input->Enum()!=ControlInputEnum) ISSMERROR("Input %s is not a ControlInput",EnumToString(enum_type)); 793 794 this->GetDofList1(&doflist1[0]); 795 ((ControlInput*)input)->GetGradient(gradient,&doflist1[0]); 796 797 }/*}}}*/ 798 /*FUNCTION Tria::ControlInputScaleGradient{{{1*/ 799 void Tria::ControlInputScaleGradient(int enum_type,double scale){ 800 801 Input* input=NULL; 802 803 if(enum_type==RheologyBbarEnum){ 804 input=(Input*)matice->inputs->GetInput(enum_type); 805 } 806 else{ 807 input=inputs->GetInput(enum_type); 808 } 809 if (!input) ISSMERROR("Input %s not found",EnumToString(enum_type)); 810 if (input->Enum()!=ControlInputEnum) ISSMERROR("Input %s is not a ControlInput",EnumToString(enum_type)); 811 812 ((ControlInput*)input)->ScaleGradient(scale); 813 }/*}}}*/ 814 /*FUNCTION Tria::ControlInputSetGradient{{{1*/ 815 void Tria::ControlInputSetGradient(double* gradient,int enum_type){ 816 817 int doflist1[NUMVERTICES]; 818 double grad_list[NUMVERTICES]; 819 Input* grad_input=NULL; 820 Input* input=NULL; 821 822 if(enum_type==RheologyBbarEnum){ 823 input=(Input*)matice->inputs->GetInput(enum_type); 824 } 825 else{ 826 input=inputs->GetInput(enum_type); 827 } 828 if (!input) ISSMERROR("Input %s not found",EnumToString(enum_type)); 829 if (input->Enum()!=ControlInputEnum) ISSMERROR("Input %s is not a ControlInput",EnumToString(enum_type)); 830 831 this->GetDofList1(&doflist1[0]); 832 for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[doflist1[i]]; 833 grad_input=new TriaVertexInput(GradientEnum,grad_list); 834 835 ((ControlInput*)input)->SetGradient(grad_input); 836 837 }/*}}}*/ 4069 bool onbed; 4070 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 4071 return onbed; 4072 } 4073 /*}}}*/ 4074 /*FUNCTION Tria::IsOnShelf {{{1*/ 4075 bool Tria::IsOnShelf(){ 4076 4077 bool shelf; 4078 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 4079 return shelf; 4080 } 4081 /*}}}*/ 4082 /*FUNCTION Tria::IsOnWater {{{1*/ 4083 bool Tria::IsOnWater(){ 4084 4085 bool water; 4086 inputs->GetParameterValue(&water,ElementOnWaterEnum); 4087 return water; 4088 } 4089 /*}}}*/ 4090 /*FUNCTION Tria::MassFlux {{{1*/ 4091 double Tria::MassFlux( double* segment,bool process_units){ 4092 4093 const int numdofs=2; 4094 4095 int i; 4096 double mass_flux=0; 4097 double xyz_list[NUMVERTICES][3]; 4098 double normal[2]; 4099 double length,rho_ice; 4100 double x1,y1,x2,y2,h1,h2; 4101 double vx1,vx2,vy1,vy2; 4102 GaussTria* gauss_1=NULL; 4103 GaussTria* gauss_2=NULL; 4104 4105 /*Get material parameters :*/ 4106 rho_ice=matpar->GetRhoIce(); 4107 4108 /*First off, check that this segment belongs to this element: */ 4109 if ((int)*(segment+4)!=this->id)ISSMERROR("%s%i%s%i","error message: segment with id ",(int)*(segment+4)," does not belong to element with id:",this->id); 4110 4111 /*Recover segment node locations: */ 4112 x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3); 4113 4114 /*Get xyz list: */ 4115 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 4116 4117 /*get area coordinates of 0 and 1 locations: */ 4118 gauss_1=new GaussTria(); 4119 gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]); 4120 gauss_2=new GaussTria(); 4121 gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]); 4122 4123 normal[0]=cos(atan2(x1-x2,y2-y1)); 4124 normal[1]=sin(atan2(x1-x2,y2-y1)); 4125 4126 length=sqrt(pow(x2-x1,2.0)+pow(y2-y1,2)); 4127 4128 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 4129 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 4130 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 4131 4132 thickness_input->GetParameterValue(&h1, gauss_1); 4133 thickness_input->GetParameterValue(&h2, gauss_2); 4134 vx_input->GetParameterValue(&vx1,gauss_1); 4135 vx_input->GetParameterValue(&vx2,gauss_2); 4136 vy_input->GetParameterValue(&vy1,gauss_1); 4137 vy_input->GetParameterValue(&vy2,gauss_2); 4138 4139 mass_flux= rho_ice*length*( 4140 (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+ 4141 (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1] 4142 ); 4143 4144 /*Process units: */ 4145 mass_flux=UnitConversion(mass_flux,IuToExtEnum,MassFluxEnum,this->parameters); 4146 4147 /*clean up and return:*/ 4148 delete gauss_1; 4149 delete gauss_2; 4150 return mass_flux; 4151 } 4152 /*}}}*/ 4153 /*FUNCTION Tria::MaxAbsVx{{{1*/ 4154 void Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){ 4155 4156 /*Get maximum:*/ 4157 double maxabsvx=this->inputs->MaxAbs(VxEnum); 4158 4159 /*process units if requested: */ 4160 if(process_units) maxabsvx=UnitConversion(maxabsvx,IuToExtEnum,VxEnum,this->parameters); 4161 4162 /*Assign output pointers:*/ 4163 *pmaxabsvx=maxabsvx; 4164 } 4165 /*}}}*/ 4166 /*FUNCTION Tria::MaxAbsVy{{{1*/ 4167 void Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){ 4168 4169 /*Get maximum:*/ 4170 double maxabsvy=this->inputs->MaxAbs(VyEnum); 4171 4172 /*process units if requested: */ 4173 if(process_units) maxabsvy=UnitConversion(maxabsvy,IuToExtEnum,VyEnum,this->parameters); 4174 4175 /*Assign output pointers:*/ 4176 *pmaxabsvy=maxabsvy; 4177 } 4178 /*}}}*/ 4179 /*FUNCTION Tria::MaxAbsVz{{{1*/ 4180 void Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){ 4181 4182 /*Get maximum:*/ 4183 double maxabsvz=this->inputs->MaxAbs(VzEnum); 4184 4185 /*process units if requested: */ 4186 if(process_units) maxabsvz=UnitConversion(maxabsvz,IuToExtEnum,VyEnum,this->parameters); 4187 4188 /*Assign output pointers:*/ 4189 *pmaxabsvz=maxabsvz; 4190 } 4191 /*}}}*/ 4192 /*FUNCTION Tria::MaxVel{{{1*/ 4193 void Tria::MaxVel(double* pmaxvel, bool process_units){ 4194 4195 /*Get maximum:*/ 4196 double maxvel=this->inputs->Max(VelEnum); 4197 4198 /*process units if requested: */ 4199 if(process_units) maxvel=UnitConversion(maxvel,IuToExtEnum,VelEnum,this->parameters); 4200 4201 /*Assign output pointers:*/ 4202 *pmaxvel=maxvel; 4203 } 4204 /*}}}*/ 4205 /*FUNCTION Tria::MaxVx{{{1*/ 4206 void Tria::MaxVx(double* pmaxvx, bool process_units){ 4207 4208 /*Get maximum:*/ 4209 double maxvx=this->inputs->Max(VxEnum); 4210 4211 /*process units if requested: */ 4212 if(process_units) maxvx=UnitConversion(maxvx,IuToExtEnum,VxEnum,this->parameters); 4213 4214 /*Assign output pointers:*/ 4215 *pmaxvx=maxvx; 4216 } 4217 /*}}}*/ 4218 /*FUNCTION Tria::MaxVy{{{1*/ 4219 void Tria::MaxVy(double* pmaxvy, bool process_units){ 4220 4221 /*Get maximum:*/ 4222 double maxvy=this->inputs->Max(VyEnum); 4223 4224 /*process units if requested: */ 4225 if(process_units) maxvy=UnitConversion(maxvy,IuToExtEnum,VyEnum,this->parameters); 4226 4227 /*Assign output pointers:*/ 4228 *pmaxvy=maxvy; 4229 4230 } 4231 /*}}}*/ 4232 /*FUNCTION Tria::MaxVz{{{1*/ 4233 void Tria::MaxVz(double* pmaxvz, bool process_units){ 4234 4235 /*Get maximum:*/ 4236 double maxvz=this->inputs->Max(VzEnum); 4237 4238 /*process units if requested: */ 4239 if(process_units) maxvz=UnitConversion(maxvz,IuToExtEnum,VzEnum,this->parameters); 4240 4241 /*Assign output pointers:*/ 4242 *pmaxvz=maxvz; 4243 } 4244 /*}}}*/ 4245 /*FUNCTION Tria::MinVel{{{1*/ 4246 void Tria::MinVel(double* pminvel, bool process_units){ 4247 4248 /*Get minimum:*/ 4249 double minvel=this->inputs->Min(VelEnum); 4250 4251 /*process units if requested: */ 4252 if(process_units) minvel=UnitConversion(minvel,IuToExtEnum,VelEnum,this->parameters); 4253 4254 /*Assign output pointers:*/ 4255 *pminvel=minvel; 4256 } 4257 /*}}}*/ 4258 /*FUNCTION Tria::MinVx{{{1*/ 4259 void Tria::MinVx(double* pminvx, bool process_units){ 4260 4261 /*Get minimum:*/ 4262 double minvx=this->inputs->Min(VxEnum); 4263 4264 /*process units if requested: */ 4265 if(process_units) minvx=UnitConversion(minvx,IuToExtEnum,VxEnum,this->parameters); 4266 4267 /*Assign output pointers:*/ 4268 *pminvx=minvx; 4269 } 4270 /*}}}*/ 4271 /*FUNCTION Tria::MinVy{{{1*/ 4272 void Tria::MinVy(double* pminvy, bool process_units){ 4273 4274 /*Get minimum:*/ 4275 double minvy=this->inputs->Min(VyEnum); 4276 4277 /*process units if requested: */ 4278 if(process_units) minvy=UnitConversion(minvy,IuToExtEnum,VyEnum,this->parameters); 4279 4280 /*Assign output pointers:*/ 4281 *pminvy=minvy; 4282 } 4283 /*}}}*/ 4284 /*FUNCTION Tria::MinVz{{{1*/ 4285 void Tria::MinVz(double* pminvz, bool process_units){ 4286 4287 /*Get minimum:*/ 4288 double minvz=this->inputs->Min(VzEnum); 4289 4290 /*process units if requested: */ 4291 if(process_units) minvz=UnitConversion(minvz,IuToExtEnum,VzEnum,this->parameters); 4292 4293 /*Assign output pointers:*/ 4294 *pminvz=minvz; 4295 } 4296 /*}}}*/ 4297 /*FUNCTION Tria::MyRank {{{1*/ 4298 int Tria::MyRank(void){ 4299 extern int my_rank; 4300 return my_rank; 4301 } 4302 /*}}}*/ 4303 /*FUNCTION Tria::PatchFill{{{1*/ 4304 void Tria::PatchFill(int* prow, Patch* patch){ 4305 4306 int i,row; 4307 int vertices_ids[3]; 4308 4309 /*recover pointer: */ 4310 row=*prow; 4311 4312 for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch. 4313 4314 for(i=0;i<this->results->Size();i++){ 4315 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 4316 4317 /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand 4318 *it to the result object, to fill the rest: */ 4319 patch->fillelementinfo(row,this->id,vertices_ids,3); 4320 elementresult->PatchFill(row,patch); 4321 4322 /*increment rower: */ 4323 row++; 4324 } 4325 4326 /*Assign output pointers:*/ 4327 *prow=row; 4328 } 4329 /*}}}*/ 4330 /*FUNCTION Tria::PatchSize{{{1*/ 4331 void Tria::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){ 4332 4333 int i; 4334 int numrows = 0; 4335 int numnodes = 0; 4336 4337 /*Go through all the results objects, and update the counters: */ 4338 for (i=0;i<this->results->Size();i++){ 4339 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 4340 /*first, we have one more result: */ 4341 numrows++; 4342 /*now, how many vertices and how many nodal values for this result? :*/ 4343 numnodes=elementresult->NumberOfNodalValues(); //ask result object. 4344 } 4345 4346 /*Assign output pointers:*/ 4347 *pnumrows=numrows; 4348 *pnumvertices=NUMVERTICES; 4349 *pnumnodes=numnodes; 4350 } 4351 /*}}}*/ 4352 /*FUNCTION Tria::ProcessResultsUnits{{{1*/ 4353 void Tria::ProcessResultsUnits(void){ 4354 4355 int i; 4356 4357 for(i=0;i<this->results->Size();i++){ 4358 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 4359 elementresult->ProcessUnits(this->parameters); 4360 } 4361 } 4362 /*}}}*/ 838 4363 /*FUNCTION Tria::RegularizeInversion {{{1*/ 839 4364 double Tria::RegularizeInversion(){ … … 908 4433 } 909 4434 /*}}}*/ 910 /*FUNCTION Tria::CreateKMatrix {{{1*/ 911 void Tria::CreateKMatrix(Mat Kgg, Mat Kff, Mat Kfs){ 912 913 /*retreive parameters: */ 914 ElementMatrix* Ke=NULL; 915 int analysis_type; 916 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 917 918 /*Checks in debugging mode{{{2*/ 919 ISSMASSERT(this->nodes && this->matice && this->matpar && this->parameters && this->inputs); 920 /*}}}*/ 921 922 /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */ 923 switch(analysis_type){ 924 case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum: 925 Ke=CreateKMatrixDiagnosticMacAyeal(); 926 break; 927 case DiagnosticHutterAnalysisEnum: 928 Ke=CreateKMatrixDiagnosticHutter(); 929 break; 930 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum: 931 Ke=CreateKMatrixSlope(); 932 break; 933 case PrognosticAnalysisEnum: 934 Ke=CreateKMatrixPrognostic(); 935 break; 936 case BalancedthicknessAnalysisEnum: 937 Ke=CreateKMatrixBalancedthickness(); 938 break; 939 case AdjointBalancedthicknessAnalysisEnum: 940 Ke=CreateKMatrixAdjointBalancedthickness(); 941 break; 942 case BalancedvelocitiesAnalysisEnum: 943 Ke=CreateKMatrixBalancedvelocities(); 944 break; 945 default: 946 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumToString(analysis_type)); 947 } 948 949 /*Add to global matrix*/ 950 if(Ke){ 951 Ke->AddToGlobal(Kgg,Kff,Kfs); 952 delete Ke; 953 } 954 } 955 /*}}}*/ 956 /*FUNCTION Tria::CreatePVector {{{1*/ 957 void Tria::CreatePVector(Vec pg, Vec pf){ 958 959 /*retrive parameters: */ 960 ElementVector* pe=NULL; 961 int analysis_type; 962 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 963 964 /*asserts: {{{*/ 965 /*if debugging mode, check that all pointers exist*/ 966 ISSMASSERT(this->nodes && this->matice && this->matpar && this->parameters && this->inputs); 967 /*}}}*/ 968 969 /*Just branch to the correct load generator, according to the type of analysis we are carrying out: */ 970 switch(analysis_type){ 971 case DiagnosticHorizAnalysisEnum: 972 pe=CreatePVectorDiagnosticMacAyeal(); 973 break; 974 case AdjointHorizAnalysisEnum: 975 pe=CreatePVectorAdjointHoriz(); 976 break; 977 case DiagnosticHutterAnalysisEnum: 978 pe=CreatePVectorDiagnosticHutter(); 979 break; 980 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum: 981 pe=CreatePVectorSlope(); 982 break; 983 case PrognosticAnalysisEnum: 984 pe=CreatePVectorPrognostic(); 985 break; 986 case BalancedthicknessAnalysisEnum: 987 pe=CreatePVectorBalancedthickness(); 988 break; 989 case AdjointBalancedthicknessAnalysisEnum: 990 pe=CreatePVectorAdjointBalancedthickness(); 991 break; 992 case BalancedvelocitiesAnalysisEnum: 993 pe=CreatePVectorBalancedvelocities(); 994 break; 995 default: 996 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumToString(analysis_type)); 997 } 998 999 /*Add to global Vector*/ 1000 if(pe){ 1001 pe->AddToGlobal(pg,pf); 1002 delete pe; 1003 } 1004 } 1005 /*}}}*/ 1006 /*FUNCTION Tria::DeleteResults {{{1*/ 1007 void Tria::DeleteResults(void){ 1008 1009 /*Delete and reinitialize results*/ 1010 delete this->results; 1011 this->results=new Results(); 1012 1013 } 1014 /*}}}*/ 1015 /*FUNCTION Tria::GetNodeIndex {{{1*/ 1016 int Tria::GetNodeIndex(Node* node){ 1017 1018 ISSMASSERT(nodes); 1019 for(int i=0;i<NUMVERTICES;i++){ 1020 if(node==nodes[i]) 1021 return i; 1022 } 1023 ISSMERROR("Node provided not found among element nodes"); 1024 } 1025 /*}}}*/ 1026 /*FUNCTION Tria::IsOnBed {{{1*/ 1027 bool Tria::IsOnBed(){ 4435 /*FUNCTION Tria::SetClone {{{1*/ 4436 void Tria::SetClone(int* minranks){ 4437 4438 ISSMERROR("not implemented yet"); 4439 } 4440 /*}}}1*/ 4441 /*FUNCTION Tria::SetCurrentConfiguration {{{1*/ 4442 void Tria::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){ 1028 4443 1029 bool onbed; 1030 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 1031 return onbed; 1032 } 1033 /*}}}*/ 1034 /*FUNCTION Tria::IsOnShelf {{{1*/ 1035 bool Tria::IsOnShelf(){ 1036 1037 bool shelf; 1038 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 1039 return shelf; 1040 } 1041 /*}}}*/ 1042 /*FUNCTION Tria::IsOnWater {{{1*/ 1043 bool Tria::IsOnWater(){ 1044 1045 bool water; 1046 inputs->GetParameterValue(&water,ElementOnWaterEnum); 1047 return water; 1048 } 1049 /*}}}*/ 1050 /*FUNCTION Tria::GetSolutionFromInputs{{{1*/ 1051 void Tria::GetSolutionFromInputs(Vec solution){ 1052 1053 /*retrive parameters: */ 1054 int analysis_type; 1055 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 1056 1057 /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */ 1058 if (analysis_type==DiagnosticHorizAnalysisEnum) 1059 GetSolutionFromInputsDiagnosticHoriz(solution); 1060 else if (analysis_type==DiagnosticHutterAnalysisEnum) 1061 GetSolutionFromInputsDiagnosticHutter(solution); 1062 else 1063 ISSMERROR("analysis: %s not supported yet",EnumToString(analysis_type)); 1064 1065 } 1066 /*}}}*/ 1067 /*FUNCTION Tria::GetVectorFromInputs{{{1*/ 1068 void Tria::GetVectorFromInputs(Vec vector,int NameEnum){ 1069 1070 int doflist1[NUMVERTICES]; 1071 1072 /*Find NameEnum input in the inputs dataset, and get it to fill in the vector: */ 1073 for(int i=0;i<this->inputs->Size();i++){ 1074 Input* input=(Input*)this->inputs->GetObjectByOffset(i); 1075 if(input->EnumType()==NameEnum){ 1076 /*We found the enum. Use its values to fill into the vector, using the vertices ids: */ 1077 this->GetDofList1(&doflist1[0]); 1078 input->GetVectorFromInputs(vector,&doflist1[0]); 1079 break; 1080 } 1081 } 1082 } 1083 /*}}}*/ 1084 /*FUNCTION Tria::Gradj {{{1*/ 1085 void Tria::Gradj(Vec gradient,int control_type){ 1086 1087 /*If on water, grad = 0: */ 1088 if(IsOnWater())return; 1089 1090 switch(control_type){ 1091 case DragCoefficientEnum: 1092 GradjDrag(gradient); 1093 break; 1094 case RheologyBbarEnum: 1095 GradjB(gradient); 1096 break; 1097 case DhDtEnum: 1098 GradjDhDt(gradient); 1099 break; 1100 case VxEnum: 1101 GradjVx(gradient); 1102 break; 1103 case VyEnum: 1104 GradjVy(gradient); 1105 break; 1106 default: 1107 ISSMERROR("%s%i","control type not supported yet: ",control_type); 1108 } 1109 } 1110 /*}}}*/ 1111 /*FUNCTION Tria::GradjB{{{1*/ 1112 void Tria::GradjB(Vec gradient){ 1113 1114 /*Intermediaries*/ 1115 int i,ig; 1116 int doflist[NUMVERTICES]; 1117 double vx,vy,lambda,mu,thickness,Jdet; 1118 double cm_noisedmp,viscosity_complement; 1119 double dvx[NDOF2],dvy[NDOF2],dadjx[NDOF2],dadjy[NDOF2],dB[NDOF2]; 1120 double xyz_list[NUMVERTICES][3]; 1121 double basis[3],epsilon[3]; 1122 double dbasis[NDOF2][NUMVERTICES]; 1123 double grad_g[NUMVERTICES]; 1124 double grad[NUMVERTICES]={0.0}; 1125 GaussTria *gauss = NULL; 1126 1127 /*retrieve some parameters: */ 1128 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 1129 1130 /* Get node coordinates and dof list: */ 1131 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1132 GetDofList1(&doflist[0]); 1133 1134 /*Retrieve all inputs*/ 1135 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1136 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1137 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1138 Input* adjointx_input=inputs->GetInput(AdjointxEnum); ISSMASSERT(adjointx_input); 1139 Input* adjointy_input=inputs->GetInput(AdjointyEnum); ISSMASSERT(adjointy_input); 1140 Input* rheologyb_input=matice->inputs->GetInput(RheologyBbarEnum); ISSMASSERT(rheologyb_input); 1141 1142 /* Start looping on the number of gaussian points: */ 1143 gauss=new GaussTria(4); 1144 for (ig=gauss->begin();ig<gauss->end();ig++){ 1145 1146 gauss->GaussPoint(ig); 1147 1148 thickness_input->GetParameterValue(&thickness,gauss); 1149 rheologyb_input->GetParameterDerivativeValue(&dB[0],&xyz_list[0][0],gauss); 1150 vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss); 1151 vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss); 1152 adjointx_input->GetParameterDerivativeValue(&dadjx[0],&xyz_list[0][0],gauss); 1153 adjointy_input->GetParameterDerivativeValue(&dadjy[0],&xyz_list[0][0],gauss); 1154 1155 this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input); 1156 matice->GetViscosityComplement(&viscosity_complement,&epsilon[0]); 1157 1158 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1159 GetNodalFunctions(basis,gauss); 1160 GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss); 1161 1162 /*standard gradient dJ/dki*/ 1163 for (i=0;i<NUMVERTICES;i++){ 1164 grad_g[i]=-viscosity_complement*thickness*( (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1])*Jdet*gauss->weight*basis[i]; 1165 } 1166 /*Add regularization term*/ 1167 for (i=0;i<NUMVERTICES;i++) grad_g[i]-=cm_noisedmp*Jdet*gauss->weight*(dbasis[0][i]*dB[0]+dbasis[1][i]*dB[1]); 1168 for(i=0;i<NUMVERTICES;i++) grad[i]+=grad_g[i]; 1169 } 1170 1171 VecSetValues(gradient,NUMVERTICES,doflist,(const double*)grad,ADD_VALUES); 1172 1173 /*clean-up*/ 1174 delete gauss; 1175 } 1176 /*}}}*/ 1177 /*FUNCTION Tria::GradjDrag {{{1*/ 1178 void Tria::GradjDrag(Vec gradient){ 1179 1180 int i,ig; 1181 int drag_type,analysis_type; 1182 int doflist1[NUMVERTICES]; 1183 double vx,vy,lambda,mu,alpha_complement,Jdet; 1184 double bed,thickness,Neff,drag,cm_noisedmp; 1185 double xyz_list[NUMVERTICES][3]; 1186 double dh1dh3[NDOF2][NUMVERTICES]; 1187 double dk[NDOF2]; 1188 double grade_g[NUMVERTICES]={0.0}; 1189 double grade_g_gaussian[NUMVERTICES]; 1190 double l1l2l3[3]; 1191 double epsilon[3]; /* epsilon=[exx,eyy,exy];*/ 1192 Friction* friction=NULL; 1193 GaussTria *gauss=NULL; 1194 1195 /*retrive parameters: */ 1196 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 1197 1198 /*retrieve some parameters ands return if iceshelf: */ 1199 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 1200 if(IsOnShelf())return; 1201 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1202 GetDofList1(&doflist1[0]); 1203 1204 /*Build frictoin element, needed later: */ 1205 inputs->GetParameterValue(&drag_type,DragTypeEnum); 1206 friction=new Friction("2d",inputs,matpar,analysis_type); 1207 1208 /*Retrieve all inputs we will be needing: */ 1209 Input* adjointx_input=inputs->GetInput(AdjointxEnum); ISSMASSERT(adjointx_input); 1210 Input* adjointy_input=inputs->GetInput(AdjointyEnum); ISSMASSERT(adjointy_input); 1211 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1212 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1213 Input* dragcoefficient_input=inputs->GetInput(DragCoefficientEnum); ISSMASSERT(dragcoefficient_input); 1214 1215 /* Start looping on the number of gaussian points: */ 1216 gauss=new GaussTria(4); 1217 for (ig=gauss->begin();ig<gauss->end();ig++){ 1218 1219 gauss->GaussPoint(ig); 1220 1221 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1222 GetNodalFunctions(l1l2l3, gauss); 1223 GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss); 1224 1225 /*Build alpha_complement_list: */ 1226 if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum); 1227 else alpha_complement=0; 1228 1229 dragcoefficient_input->GetParameterValue(&drag, gauss); 1230 adjointx_input->GetParameterValue(&lambda, gauss); 1231 adjointy_input->GetParameterValue(&mu, gauss); 1232 vx_input->GetParameterValue(&vx,gauss); 1233 vy_input->GetParameterValue(&vy,gauss); 1234 dragcoefficient_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss); 1235 1236 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */ 1237 for (i=0;i<NUMVERTICES;i++){ 1238 1239 //standard term dJ/dki 1240 grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss->weight*l1l2l3[i]; 1241 1242 //noise dampening d/dki(1/2*(dk/dx)^2) 1243 grade_g_gaussian[i]+=-cm_noisedmp*Jdet*gauss->weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]); 1244 } 1245 1246 /*Add gradje_g_gaussian vector to gradje_g: */ 1247 for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i]; 1248 } 1249 1250 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES); 1251 1252 /*Clean up and return*/ 1253 delete gauss; 1254 delete friction; 1255 } 1256 /*}}}*/ 1257 /*FUNCTION Tria::GradjDhDt{{{1*/ 1258 void Tria::GradjDhDt(Vec gradient){ 1259 1260 /*Intermediaries*/ 1261 int doflist1[NUMVERTICES]; 1262 double lambda[NUMVERTICES]; 1263 double gradient_g[NUMVERTICES]; 1264 1265 GetDofList1(&doflist1[0]); 1266 1267 /*Compute Gradient*/ 1268 GetParameterListOnVertices(&lambda[0],AdjointEnum); 1269 for(int i=0;i<NUMVERTICES;i++) gradient_g[i]=-lambda[i]; 1270 1271 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)gradient_g,INSERT_VALUES); 1272 } 1273 /*}}}*/ 1274 /*FUNCTION Tria::GradjVx{{{1*/ 1275 void Tria::GradjVx(Vec gradient){ 1276 1277 /*Intermediaries*/ 1278 int i,ig; 1279 int doflist1[NUMVERTICES]; 1280 double thickness,Jdet,cm_noisedmp; 1281 double l1l2l3[3]; 1282 double dbasis[NDOF2][NUMVERTICES]; 1283 double Dlambda[2],dp[2]; 1284 double xyz_list[NUMVERTICES][3]; 1285 double grade_g[NUMVERTICES] = {0.0}; 1286 GaussTria *gauss = NULL; 1287 1288 /* Get node coordinates and dof list: */ 1289 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1290 GetDofList1(&doflist1[0]); 1291 1292 /*Retrieve all inputs we will be needing: */ 1293 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 1294 Input* adjoint_input=inputs->GetInput(AdjointEnum); ISSMASSERT(adjoint_input); 1295 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1296 1297 /* Start looping on the number of gaussian points: */ 1298 gauss=new GaussTria(2); 1299 for (ig=gauss->begin();ig<gauss->end();ig++){ 1300 1301 gauss->GaussPoint(ig); 1302 1303 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1304 GetNodalFunctions(l1l2l3, gauss); 1305 GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss); 1306 1307 adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss); 1308 thickness_input->GetParameterValue(&thickness, gauss); 1309 thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss); 1310 1311 for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*l1l2l3[i]; 1312 1313 //noise dampening d/dki(1/2*(dk/dx)^2) 1314 //for (i=0;i<NUMVERTICES;i++) grade_g[i]-=cm_noisedmp*Jdet*gauss->weight*(dbasis[0][i]*dp[0]+dbasis[1][i]*dp[1]); 1315 } 1316 1317 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES); 1318 1319 /*Clean up and return*/ 1320 delete gauss; 1321 } 1322 /*}}}*/ 1323 /*FUNCTION Tria::GradjVy{{{1*/ 1324 void Tria::GradjVy(Vec gradient){ 1325 1326 /*Intermediaries*/ 1327 int i,ig; 1328 int doflist1[NUMVERTICES]; 1329 double thickness,Jdet,cm_noisedmp; 1330 double l1l2l3[3]; 1331 double dbasis[NDOF2][NUMVERTICES]; 1332 double Dlambda[2],dp[2]; 1333 double xyz_list[NUMVERTICES][3]; 1334 double grade_g[NUMVERTICES] = {0.0}; 1335 GaussTria *gauss = NULL; 1336 1337 /* Get node coordinates and dof list: */ 1338 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum); 1339 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1340 GetDofList1(&doflist1[0]); 1341 1342 /*Retrieve all inputs we will be needing: */ 1343 Input* adjoint_input=inputs->GetInput(AdjointEnum); ISSMASSERT(adjoint_input); 1344 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1345 1346 /* Start looping on the number of gaussian points: */ 1347 gauss=new GaussTria(2); 1348 for (ig=gauss->begin();ig<gauss->end();ig++){ 1349 1350 gauss->GaussPoint(ig); 1351 1352 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1353 GetNodalFunctions(l1l2l3, gauss); 1354 GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss); 1355 1356 adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss); 1357 thickness_input->GetParameterValue(&thickness, gauss); 1358 thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss); 1359 1360 for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*l1l2l3[i]; 1361 1362 //noise dampening d/dki(1/2*(dk/dx)^2) 1363 //for (i=0;i<NUMVERTICES;i++) grade_g[i]-=cm_noisedmp*Jdet*gauss->weight*(dbasis[0][i]*dp[0]+dbasis[1][i]*dp[1]); 1364 } 1365 1366 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES); 1367 1368 /*Clean up and return*/ 1369 delete gauss; 1370 } 1371 /*}}}*/ 1372 /*FUNCTION Tria::InputControlUpdate{{{1*/ 1373 void Tria::InputControlUpdate(double scalar,bool save_parameter){ 1374 1375 /*Intermediary*/ 1376 int num_controls; 1377 int* control_type=NULL; 1378 Input* input=NULL; 1379 double *cm_min=NULL; 1380 double *cm_max=NULL; 1381 1382 /*retrieve some parameters: */ 1383 this->parameters->FindParam(&cm_min,NULL,CmMinEnum); 1384 this->parameters->FindParam(&cm_max,NULL,CmMaxEnum); 1385 this->parameters->FindParam(&num_controls,NumControlsEnum); 1386 this->parameters->FindParam(&control_type,NULL,ControlTypeEnum); 1387 1388 for(int i=0;i<num_controls;i++){ 1389 1390 if(control_type[i]==RheologyBbarEnum){ 1391 input=(Input*)matice->inputs->GetInput(control_type[i]); ISSMASSERT(input); 1392 } 1393 else{ 1394 input=(Input*)this->inputs->GetInput(control_type[i]); ISSMASSERT(input); 1395 } 1396 1397 if (input->Enum()!=ControlInputEnum){ 1398 ISSMERROR("input %s is not a ControlInput",EnumToString(control_type[i])); 1399 } 1400 1401 ((ControlInput*)input)->UpdateValue(scalar); 1402 input->Constrain(cm_min[i],cm_max[i]); 1403 if (save_parameter) ((ControlInput*)input)->SaveValue(); 1404 1405 } 1406 1407 /*Clean up and return*/ 1408 xfree((void**)&control_type); 1409 xfree((void**)&cm_min); 1410 xfree((void**)&cm_max); 1411 } 1412 /*}}}*/ 1413 /*FUNCTION Tria::InputConvergence{{{1*/ 1414 bool Tria::InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){ 1415 1416 bool converged=true; 1417 int i; 1418 Input** new_inputs=NULL; 1419 Input** old_inputs=NULL; 1420 1421 new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs 1422 old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs 1423 1424 for(i=0;i<num_enums/2;i++){ 1425 new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]); 1426 old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]); 1427 if(!new_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumToString(enums[2*i+0])); 1428 if(!old_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumToString(enums[2*i+0])); 1429 } 1430 1431 /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/ 1432 for(i=0;i<num_criterionenums;i++){ 1433 IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]); 1434 if(eps[i]>criterionvalues[i]) converged=false; 1435 } 1436 1437 /*clean up and return*/ 1438 xfree((void**)&new_inputs); 1439 xfree((void**)&old_inputs); 1440 return converged; 1441 } 1442 /*}}}*/ 1443 /*FUNCTION Tria::InputDepthAverageAtBase {{{1*/ 1444 void Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type,int object_enum){ 1445 1446 /*New input*/ 1447 Input* oldinput=NULL; 1448 Input* newinput=NULL; 1449 1450 /*copy input of enum_type*/ 1451 if (object_enum==ElementsEnum) 1452 oldinput=(Input*)this->inputs->GetInput(enum_type); 1453 else if (object_enum==MaterialsEnum) 1454 oldinput=(Input*)this->matice->inputs->GetInput(enum_type); 1455 else 1456 ISSMERROR("object %s not supported yet",EnumToString(object_enum)); 1457 if(!oldinput)ISSMERROR("%s%s"," could not find old input with enum: ",EnumToString(enum_type)); 1458 newinput=(Input*)oldinput->copy(); 1459 1460 /*Assign new name (average)*/ 1461 newinput->ChangeEnum(average_enum_type); 1462 1463 /*Add new input to current element*/ 1464 if (object_enum==ElementsEnum) 1465 this->inputs->AddInput((Input*)newinput); 1466 else if (object_enum==MaterialsEnum) 1467 this->matice->inputs->AddInput((Input*)newinput); 1468 else 1469 ISSMERROR("object %s not supported yet",EnumToString(object_enum)); 1470 } 1471 /*}}}*/ 1472 /*FUNCTION Tria::InputDuplicate{{{1*/ 1473 void Tria::InputDuplicate(int original_enum,int new_enum){ 1474 1475 /*Call inputs method*/ 1476 if (IsInput(original_enum)) inputs->DuplicateInput(original_enum,new_enum); 1477 1478 } 1479 /*}}}*/ 1480 /*FUNCTION Tria::InputScale{{{1*/ 1481 void Tria::InputScale(int enum_type,double scale_factor){ 1482 1483 Input* input=NULL; 1484 1485 /*Make a copy of the original input: */ 1486 input=(Input*)this->inputs->GetInput(enum_type); 1487 if(!input)ISSMERROR(" could not find old input with enum: %s",EnumToString(enum_type)); 1488 1489 /*Scale: */ 1490 input->Scale(scale_factor); 1491 } 1492 /*}}}*/ 1493 /*FUNCTION Tria::InputArtificialNoise{{{1*/ 1494 void Tria::InputArtificialNoise(int enum_type,double min,double max){ 1495 1496 Input* input=NULL; 1497 1498 /*Make a copy of the original input: */ 1499 input=(Input*)this->inputs->GetInput(enum_type); 1500 if(!input)ISSMERROR(" could not find old input with enum: %s",EnumToString(enum_type)); 1501 1502 /*ArtificialNoise: */ 1503 input->ArtificialNoise(min,max); 1504 } 1505 /*}}}*/ 1506 /*FUNCTION Tria::InputToResult{{{1*/ 1507 void Tria::InputToResult(int enum_type,int step,double time){ 1508 1509 int i; 1510 Input *input = NULL; 1511 1512 /*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */ 1513 if (enum_type==RheologyBbarEnum) input=this->matice->inputs->GetInput(enum_type); 1514 else input=this->inputs->GetInput(enum_type); 1515 if (!input) ISSMERROR("Input %s not found in tria->inputs",EnumToString(enum_type)); 1516 1517 /*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result 1518 * object out of the input, with the additional step and time information: */ 1519 this->results->AddObject((Object*)input->SpawnResult(step,time)); 1520 if(input->Enum()==ControlInputEnum) this->results->AddObject((Object*)((ControlInput*)input)->SpawnGradient(step,time)); 1521 } 1522 /*}}}*/ 1523 /*FUNCTION Tria::MassFlux {{{1*/ 1524 double Tria::MassFlux( double* segment,bool process_units){ 1525 1526 const int numdofs=2; 1527 1528 int i; 1529 double mass_flux=0; 1530 double xyz_list[NUMVERTICES][3]; 1531 double normal[2]; 1532 double length,rho_ice; 1533 double x1,y1,x2,y2,h1,h2; 1534 double vx1,vx2,vy1,vy2; 1535 GaussTria* gauss_1=NULL; 1536 GaussTria* gauss_2=NULL; 1537 1538 /*Get material parameters :*/ 1539 rho_ice=matpar->GetRhoIce(); 1540 1541 /*First off, check that this segment belongs to this element: */ 1542 if ((int)*(segment+4)!=this->id)ISSMERROR("%s%i%s%i","error message: segment with id ",(int)*(segment+4)," does not belong to element with id:",this->id); 1543 1544 /*Recover segment node locations: */ 1545 x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3); 1546 1547 /*Get xyz list: */ 1548 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1549 1550 /*get area coordinates of 0 and 1 locations: */ 1551 gauss_1=new GaussTria(); 1552 gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]); 1553 gauss_2=new GaussTria(); 1554 gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]); 1555 1556 normal[0]=cos(atan2(x1-x2,y2-y1)); 1557 normal[1]=sin(atan2(x1-x2,y2-y1)); 1558 1559 length=sqrt(pow(x2-x1,2.0)+pow(y2-y1,2)); 1560 1561 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1562 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input); 1563 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input); 1564 1565 thickness_input->GetParameterValue(&h1, gauss_1); 1566 thickness_input->GetParameterValue(&h2, gauss_2); 1567 vx_input->GetParameterValue(&vx1,gauss_1); 1568 vx_input->GetParameterValue(&vx2,gauss_2); 1569 vy_input->GetParameterValue(&vy1,gauss_1); 1570 vy_input->GetParameterValue(&vy2,gauss_2); 1571 1572 mass_flux= rho_ice*length*( 1573 (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+ 1574 (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1] 1575 ); 1576 1577 /*Process units: */ 1578 mass_flux=UnitConversion(mass_flux,IuToExtEnum,MassFluxEnum,this->parameters); 1579 1580 /*clean up and return:*/ 1581 delete gauss_1; 1582 delete gauss_2; 1583 return mass_flux; 1584 } 1585 /*}}}*/ 1586 /*FUNCTION Tria::MaxAbsVx{{{1*/ 1587 void Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){ 1588 1589 /*Get maximum:*/ 1590 double maxabsvx=this->inputs->MaxAbs(VxEnum); 1591 1592 /*process units if requested: */ 1593 if(process_units) maxabsvx=UnitConversion(maxabsvx,IuToExtEnum,VxEnum,this->parameters); 1594 1595 /*Assign output pointers:*/ 1596 *pmaxabsvx=maxabsvx; 1597 } 1598 /*}}}*/ 1599 /*FUNCTION Tria::MaxAbsVy{{{1*/ 1600 void Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){ 1601 1602 /*Get maximum:*/ 1603 double maxabsvy=this->inputs->MaxAbs(VyEnum); 1604 1605 /*process units if requested: */ 1606 if(process_units) maxabsvy=UnitConversion(maxabsvy,IuToExtEnum,VyEnum,this->parameters); 1607 1608 /*Assign output pointers:*/ 1609 *pmaxabsvy=maxabsvy; 1610 } 1611 /*}}}*/ 1612 /*FUNCTION Tria::MaxAbsVz{{{1*/ 1613 void Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){ 1614 1615 /*Get maximum:*/ 1616 double maxabsvz=this->inputs->MaxAbs(VzEnum); 1617 1618 /*process units if requested: */ 1619 if(process_units) maxabsvz=UnitConversion(maxabsvz,IuToExtEnum,VyEnum,this->parameters); 1620 1621 /*Assign output pointers:*/ 1622 *pmaxabsvz=maxabsvz; 1623 } 1624 /*}}}*/ 1625 /*FUNCTION Tria::MaxVel{{{1*/ 1626 void Tria::MaxVel(double* pmaxvel, bool process_units){ 1627 1628 /*Get maximum:*/ 1629 double maxvel=this->inputs->Max(VelEnum); 1630 1631 /*process units if requested: */ 1632 if(process_units) maxvel=UnitConversion(maxvel,IuToExtEnum,VelEnum,this->parameters); 1633 1634 /*Assign output pointers:*/ 1635 *pmaxvel=maxvel; 1636 } 1637 /*}}}*/ 1638 /*FUNCTION Tria::MaxVx{{{1*/ 1639 void Tria::MaxVx(double* pmaxvx, bool process_units){ 1640 1641 /*Get maximum:*/ 1642 double maxvx=this->inputs->Max(VxEnum); 1643 1644 /*process units if requested: */ 1645 if(process_units) maxvx=UnitConversion(maxvx,IuToExtEnum,VxEnum,this->parameters); 1646 1647 /*Assign output pointers:*/ 1648 *pmaxvx=maxvx; 1649 } 1650 /*}}}*/ 1651 /*FUNCTION Tria::MaxVy{{{1*/ 1652 void Tria::MaxVy(double* pmaxvy, bool process_units){ 1653 1654 /*Get maximum:*/ 1655 double maxvy=this->inputs->Max(VyEnum); 1656 1657 /*process units if requested: */ 1658 if(process_units) maxvy=UnitConversion(maxvy,IuToExtEnum,VyEnum,this->parameters); 1659 1660 /*Assign output pointers:*/ 1661 *pmaxvy=maxvy; 1662 1663 } 1664 /*}}}*/ 1665 /*FUNCTION Tria::MaxVz{{{1*/ 1666 void Tria::MaxVz(double* pmaxvz, bool process_units){ 1667 1668 /*Get maximum:*/ 1669 double maxvz=this->inputs->Max(VzEnum); 1670 1671 /*process units if requested: */ 1672 if(process_units) maxvz=UnitConversion(maxvz,IuToExtEnum,VzEnum,this->parameters); 1673 1674 /*Assign output pointers:*/ 1675 *pmaxvz=maxvz; 1676 } 1677 /*}}}*/ 1678 /*FUNCTION Tria::MinVel{{{1*/ 1679 void Tria::MinVel(double* pminvel, bool process_units){ 1680 1681 /*Get minimum:*/ 1682 double minvel=this->inputs->Min(VelEnum); 1683 1684 /*process units if requested: */ 1685 if(process_units) minvel=UnitConversion(minvel,IuToExtEnum,VelEnum,this->parameters); 1686 1687 /*Assign output pointers:*/ 1688 *pminvel=minvel; 1689 } 1690 /*}}}*/ 1691 /*FUNCTION Tria::MinVx{{{1*/ 1692 void Tria::MinVx(double* pminvx, bool process_units){ 1693 1694 /*Get minimum:*/ 1695 double minvx=this->inputs->Min(VxEnum); 1696 1697 /*process units if requested: */ 1698 if(process_units) minvx=UnitConversion(minvx,IuToExtEnum,VxEnum,this->parameters); 1699 1700 /*Assign output pointers:*/ 1701 *pminvx=minvx; 1702 } 1703 /*}}}*/ 1704 /*FUNCTION Tria::MinVy{{{1*/ 1705 void Tria::MinVy(double* pminvy, bool process_units){ 1706 1707 /*Get minimum:*/ 1708 double minvy=this->inputs->Min(VyEnum); 1709 1710 /*process units if requested: */ 1711 if(process_units) minvy=UnitConversion(minvy,IuToExtEnum,VyEnum,this->parameters); 1712 1713 /*Assign output pointers:*/ 1714 *pminvy=minvy; 1715 } 1716 /*}}}*/ 1717 /*FUNCTION Tria::MinVz{{{1*/ 1718 void Tria::MinVz(double* pminvz, bool process_units){ 1719 1720 /*Get minimum:*/ 1721 double minvz=this->inputs->Min(VzEnum); 1722 1723 /*process units if requested: */ 1724 if(process_units) minvz=UnitConversion(minvz,IuToExtEnum,VzEnum,this->parameters); 1725 1726 /*Assign output pointers:*/ 1727 *pminvz=minvz; 1728 } 1729 /*}}}*/ 1730 /*FUNCTION Tria::TimeAdapt{{{1*/ 1731 double Tria::TimeAdapt(void){ 1732 1733 /*intermediary: */ 1734 int i; 1735 double C,dt; 1736 double dx,dy; 1737 double maxx,minx; 1738 double maxy,miny; 1739 double maxabsvx,maxabsvy; 1740 double xyz_list[NUMVERTICES][3]; 1741 1742 /*get CFL coefficient:*/ 1743 this->parameters->FindParam(&C,CflCoefficientEnum); 1744 1745 /*Get for Vx and Vy, the max of abs value: */ 1746 this->MaxAbsVx(&maxabsvx,false); 1747 this->MaxAbsVy(&maxabsvy,false); 1748 1749 /* Get node coordinates and dof list: */ 1750 GetVerticesCoordinates(&xyz_list[0][0], this->nodes, NUMVERTICES); 1751 1752 minx=xyz_list[0][0]; 1753 maxx=xyz_list[0][0]; 1754 miny=xyz_list[0][1]; 1755 maxy=xyz_list[0][1]; 1756 1757 for(i=1;i<NUMVERTICES;i++){ 1758 if (xyz_list[i][0]<minx)minx=xyz_list[i][0]; 1759 if (xyz_list[i][0]>maxx)maxx=xyz_list[i][0]; 1760 if (xyz_list[i][1]<miny)miny=xyz_list[i][1]; 1761 if (xyz_list[i][1]>maxy)maxy=xyz_list[i][1]; 1762 } 1763 dx=maxx-minx; 1764 dy=maxy-miny; 1765 1766 /*CFL criterion: */ 1767 dt=C/(maxabsvy/dx+maxabsvy/dy); 1768 1769 return dt; 1770 } 1771 /*}}}*/ 1772 /*FUNCTION Tria::ThicknessAbsMisfit {{{1*/ 1773 double Tria::ThicknessAbsMisfit(bool process_units){ 1774 1775 /* Constants */ 1776 const int numdof=1*NUMVERTICES; 1777 1778 /*Intermediaries*/ 1779 int i,ig; 1780 double thickness,thicknessobs,weight; 1781 double Jdet; 1782 double Jelem = 0; 1783 double xyz_list[NUMVERTICES][3]; 1784 GaussTria *gauss = NULL; 1785 1786 /*If on water, return 0: */ 1787 if(IsOnWater())return 0; 1788 1789 /* Get node coordinates and dof list: */ 1790 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 1791 1792 /*Retrieve all inputs we will be needing: */ 1793 Input* thickness_input =inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 1794 Input* thicknessobs_input=inputs->GetInput(ThicknessObsEnum);ISSMASSERT(thicknessobs_input); 1795 Input* weights_input =inputs->GetInput(WeightsEnum); ISSMASSERT(weights_input); 1796 1797 /* Start looping on the number of gaussian points: */ 1798 gauss=new GaussTria(2); 1799 for (ig=gauss->begin();ig<gauss->end();ig++){ 1800 1801 gauss->GaussPoint(ig); 1802 1803 /* Get Jacobian determinant: */ 1804 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 1805 1806 /*Get parameters at gauss point*/ 1807 thickness_input->GetParameterValue(&thickness,gauss); 1808 thicknessobs_input->GetParameterValue(&thicknessobs,gauss); 1809 weights_input->GetParameterValue(&weight,gauss); 1810 1811 /*compute ThicknessAbsMisfit*/ 1812 Jelem+=0.5*pow(thickness-thicknessobs,2.0)*weight*Jdet*gauss->weight; 1813 } 1814 1815 /* clean up and Return: */ 1816 delete gauss; 1817 return Jelem; 4444 /*go into parameters and get the analysis_counter: */ 4445 int analysis_counter; 4446 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 4447 4448 /*Get Element type*/ 4449 this->element_type=this->element_type_list[analysis_counter]; 4450 4451 /*Pick up nodes*/ 4452 if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 4453 else this->nodes=NULL; 4454 1818 4455 } 1819 4456 /*}}}*/ … … 1896 4533 } 1897 4534 /*}}}*/ 1898 /*FUNCTION Tria::SurfaceRelVelMisfit {{{1*/ 1899 double Tria::SurfaceRelVelMisfit(bool process_units){ 4535 /*FUNCTION Tria::SurfaceArea {{{1*/ 4536 double Tria::SurfaceArea(void){ 4537 4538 int i; 4539 double S; 4540 double normal[3]; 4541 double v13[3],v23[3]; 4542 double xyz_list[NUMVERTICES][3]; 4543 4544 /*If on water, return 0: */ 4545 if(IsOnWater())return 0; 4546 4547 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 4548 4549 for (i=0;i<3;i++){ 4550 v13[i]=xyz_list[0][i]-xyz_list[2][i]; 4551 v23[i]=xyz_list[1][i]-xyz_list[2][i]; 4552 } 4553 4554 normal[0]=v13[1]*v23[2]-v13[2]*v23[1]; 4555 normal[1]=v13[2]*v23[0]-v13[0]*v23[2]; 4556 normal[2]=v13[0]*v23[1]-v13[1]*v23[0]; 4557 4558 S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2)); 4559 4560 /*Return: */ 4561 return S; 4562 } 4563 /*}}}*/ 4564 /*FUNCTION Tria::SurfaceAverageVelMisfit {{{1*/ 4565 double Tria::SurfaceAverageVelMisfit(bool process_units){ 1900 4566 1901 4567 const int numdof=2*NUMVERTICES; 1902 4568 1903 4569 int i,ig; 1904 double Jelem=0; 1905 double scalex=1,scaley=1; 1906 double meanvel, epsvel,misfit,Jdet; 1907 double velocity_mag,obs_velocity_mag; 4570 int fit=-1; 4571 double Jelem=0,S=0; 4572 double scalex=1, scaley=1; 4573 double meanvel, epsvel,Jdet; 4574 double velocity_mag,obs_velocity_mag,misfit; 1908 4575 double xyz_list[NUMVERTICES][3]; 1909 4576 double vx_list[NUMVERTICES]; … … 1923 4590 1924 4591 /* Recover input data: */ 4592 inputs->GetParameterValue(&S,SurfaceAreaEnum); 1925 4593 GetParameterListOnVertices(&obs_vx_list[0],VxObsEnum); 1926 4594 GetParameterListOnVertices(&obs_vy_list[0],VyObsEnum); … … 1933 4601 this->parameters->FindParam(&epsvel,EpsVelEnum); 1934 4602 1935 /* Compute Surface RelVelMisfit at the 3 nodes4603 /* Compute SurfaceAverageVelMisfit at the 3 nodes 1936 4604 * Here we integrate linearized functions: 1937 4605 * … … 1943 4611 */ 1944 4612 1945 /*We are using a relative misfit: 1946 * 1947 * 1 [ \bar{v}^2 2 \bar{v}^2 2 ] 1948 * J = --- | ------------- (u - u ) + ------------- (v - v ) | 1949 * 2 [ (u + eps)^2 obs (v + eps)^2 obs ] 1950 * obs obs 4613 /*We are using a spacially average absolute misfit: 4614 * 4615 * 1 2 2 4616 * J = --- sqrt( (u - u ) + (v - v ) ) 4617 * S obs obs 1951 4618 */ 1952 for (i=0;i<NUMVERTICES;i++){ 1953 scalex=pow(meanvel/(obs_vx_list[i]+epsvel),(double)2); 1954 scaley=pow(meanvel/(obs_vy_list[i]+epsvel),(double)2); 1955 if(obs_vx_list[i]==0)scalex=0; 1956 if(obs_vy_list[i]==0)scaley=0; 1957 misfit_list[i]=0.5*(scalex*pow((vx_list[i]-obs_vx_list[i]),2)+scaley*pow((vy_list[i]-obs_vy_list[i]),2)); 1958 } 4619 for (i=0;i<NUMVERTICES;i++) misfit_square_list[i]=pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2); 1959 4620 1960 4621 /*Process units: */ 1961 if(process_units)UnitConversion(&misfit_list[0],NUMVERTICES,IuToExtEnum,SurfaceRelVelMisfitEnum,this->parameters); 4622 if(process_units)UnitConversion(&misfit_square_list[0],NUMVERTICES,IuToExtEnum,SurfaceAverageVelMisfitEnum,this->parameters); 4623 4624 /*Take the square root, and scale by surface: */ 4625 for (i=0;i<NUMVERTICES;i++)misfit_list[i]=pow(misfit_square_list[i],2)/S; 1962 4626 1963 4627 /*Apply weights to misfits*/ … … 1975 4639 } 1976 4640 1977 /*clean 4641 /*clean-up and Return: */ 1978 4642 delete gauss; 1979 4643 return Jelem; … … 2145 4809 } 2146 4810 /*}}}*/ 2147 /*FUNCTION Tria::SurfaceAverageVelMisfit {{{1*/ 2148 double Tria::SurfaceAverageVelMisfit(bool process_units){ 4811 /*FUNCTION Tria::SurfaceNormal{{{1*/ 4812 void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){ 4813 4814 int i; 4815 double v13[3],v23[3]; 4816 double normal[3]; 4817 double normal_norm; 4818 4819 for (i=0;i<3;i++){ 4820 v13[i]=xyz_list[0][i]-xyz_list[2][i]; 4821 v23[i]=xyz_list[1][i]-xyz_list[2][i]; 4822 } 4823 4824 normal[0]=v13[1]*v23[2]-v13[2]*v23[1]; 4825 normal[1]=v13[2]*v23[0]-v13[0]*v23[2]; 4826 normal[2]=v13[0]*v23[1]-v13[1]*v23[0]; 4827 4828 normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) ); 4829 4830 *(surface_normal)=normal[0]/normal_norm; 4831 *(surface_normal+1)=normal[1]/normal_norm; 4832 *(surface_normal+2)=normal[2]/normal_norm; 4833 } 4834 /*}}}*/ 4835 /*FUNCTION Tria::SurfaceRelVelMisfit {{{1*/ 4836 double Tria::SurfaceRelVelMisfit(bool process_units){ 2149 4837 2150 4838 const int numdof=2*NUMVERTICES; 2151 4839 2152 4840 int i,ig; 2153 int fit=-1; 2154 double Jelem=0,S=0; 2155 double scalex=1, scaley=1; 2156 double meanvel, epsvel,Jdet; 2157 double velocity_mag,obs_velocity_mag,misfit; 4841 double Jelem=0; 4842 double scalex=1,scaley=1; 4843 double meanvel, epsvel,misfit,Jdet; 4844 double velocity_mag,obs_velocity_mag; 2158 4845 double xyz_list[NUMVERTICES][3]; 2159 4846 double vx_list[NUMVERTICES]; … … 2173 4860 2174 4861 /* Recover input data: */ 2175 inputs->GetParameterValue(&S,SurfaceAreaEnum);2176 4862 GetParameterListOnVertices(&obs_vx_list[0],VxObsEnum); 2177 4863 GetParameterListOnVertices(&obs_vy_list[0],VyObsEnum); … … 2184 4870 this->parameters->FindParam(&epsvel,EpsVelEnum); 2185 4871 2186 /* Compute Surface AverageVelMisfit at the 3 nodes4872 /* Compute SurfaceRelVelMisfit at the 3 nodes 2187 4873 * Here we integrate linearized functions: 2188 4874 * … … 2194 4880 */ 2195 4881 2196 /*We are using a spacially average absolute misfit: 2197 * 2198 * 1 2 2 2199 * J = --- sqrt( (u - u ) + (v - v ) ) 2200 * S obs obs 4882 /*We are using a relative misfit: 4883 * 4884 * 1 [ \bar{v}^2 2 \bar{v}^2 2 ] 4885 * J = --- | ------------- (u - u ) + ------------- (v - v ) | 4886 * 2 [ (u + eps)^2 obs (v + eps)^2 obs ] 4887 * obs obs 2201 4888 */ 2202 for (i=0;i<NUMVERTICES;i++) misfit_square_list[i]=pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2); 4889 for (i=0;i<NUMVERTICES;i++){ 4890 scalex=pow(meanvel/(obs_vx_list[i]+epsvel),(double)2); 4891 scaley=pow(meanvel/(obs_vy_list[i]+epsvel),(double)2); 4892 if(obs_vx_list[i]==0)scalex=0; 4893 if(obs_vy_list[i]==0)scaley=0; 4894 misfit_list[i]=0.5*(scalex*pow((vx_list[i]-obs_vx_list[i]),2)+scaley*pow((vy_list[i]-obs_vy_list[i]),2)); 4895 } 2203 4896 2204 4897 /*Process units: */ 2205 if(process_units)UnitConversion(&misfit_square_list[0],NUMVERTICES,IuToExtEnum,SurfaceAverageVelMisfitEnum,this->parameters); 2206 2207 /*Take the square root, and scale by surface: */ 2208 for (i=0;i<NUMVERTICES;i++)misfit_list[i]=pow(misfit_square_list[i],2)/S; 4898 if(process_units)UnitConversion(&misfit_list[0],NUMVERTICES,IuToExtEnum,SurfaceRelVelMisfitEnum,this->parameters); 2209 4899 2210 4900 /*Apply weights to misfits*/ … … 2222 4912 } 2223 4913 2224 /*clean -up and Return: */4914 /*clean up and Return: */ 2225 4915 delete gauss; 2226 4916 return Jelem; 2227 4917 } 2228 4918 /*}}}*/ 2229 /*FUNCTION Tria::PatchFill{{{1*/ 2230 void Tria::PatchFill(int* prow, Patch* patch){ 2231 2232 int i,row; 2233 int vertices_ids[3]; 2234 2235 /*recover pointer: */ 2236 row=*prow; 2237 2238 for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch. 2239 2240 for(i=0;i<this->results->Size();i++){ 2241 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 2242 2243 /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand 2244 *it to the result object, to fill the rest: */ 2245 patch->fillelementinfo(row,this->id,vertices_ids,3); 2246 elementresult->PatchFill(row,patch); 2247 2248 /*increment rower: */ 2249 row++; 2250 } 2251 2252 /*Assign output pointers:*/ 2253 *prow=row; 2254 } 2255 /*}}}*/ 2256 /*FUNCTION Tria::PatchSize{{{1*/ 2257 void Tria::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){ 2258 2259 int i; 2260 int numrows = 0; 2261 int numnodes = 0; 2262 2263 /*Go through all the results objects, and update the counters: */ 2264 for (i=0;i<this->results->Size();i++){ 2265 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 2266 /*first, we have one more result: */ 2267 numrows++; 2268 /*now, how many vertices and how many nodal values for this result? :*/ 2269 numnodes=elementresult->NumberOfNodalValues(); //ask result object. 2270 } 2271 2272 /*Assign output pointers:*/ 2273 *pnumrows=numrows; 2274 *pnumvertices=NUMVERTICES; 2275 *pnumnodes=numnodes; 2276 } 2277 /*}}}*/ 2278 /*FUNCTION Tria::ProcessResultsUnits{{{1*/ 2279 void Tria::ProcessResultsUnits(void){ 2280 2281 int i; 2282 2283 for(i=0;i<this->results->Size();i++){ 2284 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i); 2285 elementresult->ProcessUnits(this->parameters); 2286 } 2287 } 2288 /*}}}*/ 2289 /*FUNCTION Tria::SurfaceArea {{{1*/ 2290 double Tria::SurfaceArea(void){ 2291 2292 int i; 2293 double S; 2294 double normal[3]; 2295 double v13[3],v23[3]; 2296 double xyz_list[NUMVERTICES][3]; 4919 /*FUNCTION Tria::ThicknessAbsMisfit {{{1*/ 4920 double Tria::ThicknessAbsMisfit(bool process_units){ 4921 4922 /* Constants */ 4923 const int numdof=1*NUMVERTICES; 4924 4925 /*Intermediaries*/ 4926 int i,ig; 4927 double thickness,thicknessobs,weight; 4928 double Jdet; 4929 double Jelem = 0; 4930 double xyz_list[NUMVERTICES][3]; 4931 GaussTria *gauss = NULL; 2297 4932 2298 4933 /*If on water, return 0: */ 2299 4934 if(IsOnWater())return 0; 2300 4935 4936 /* Get node coordinates and dof list: */ 2301 4937 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES); 2302 4938 2303 for (i=0;i<3;i++){ 2304 v13[i]=xyz_list[0][i]-xyz_list[2][i]; 2305 v23[i]=xyz_list[1][i]-xyz_list[2][i]; 2306 } 2307 2308 normal[0]=v13[1]*v23[2]-v13[2]*v23[1]; 2309 normal[1]=v13[2]*v23[0]-v13[0]*v23[2]; 2310 normal[2]=v13[0]*v23[1]-v13[1]*v23[0]; 2311 2312 S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2)); 2313 2314 /*Return: */ 2315 return S; 4939 /*Retrieve all inputs we will be needing: */ 4940 Input* thickness_input =inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input); 4941 Input* thicknessobs_input=inputs->GetInput(ThicknessObsEnum);ISSMASSERT(thicknessobs_input); 4942 Input* weights_input =inputs->GetInput(WeightsEnum); ISSMASSERT(weights_input); 4943 4944 /* Start looping on the number of gaussian points: */ 4945 gauss=new GaussTria(2); 4946 for (ig=gauss->begin();ig<gauss->end();ig++){ 4947 4948 gauss->GaussPoint(ig); 4949 4950 /* Get Jacobian determinant: */ 4951 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss); 4952 4953 /*Get parameters at gauss point*/ 4954 thickness_input->GetParameterValue(&thickness,gauss); 4955 thicknessobs_input->GetParameterValue(&thicknessobs,gauss); 4956 weights_input->GetParameterValue(&weight,gauss); 4957 4958 /*compute ThicknessAbsMisfit*/ 4959 Jelem+=0.5*pow(thickness-thicknessobs,2.0)*weight*Jdet*gauss->weight; 4960 } 4961 4962 /* clean up and Return: */ 4963 delete gauss; 4964 return Jelem; 4965 } 4966 /*}}}*/ 4967 /*FUNCTION Tria::TimeAdapt{{{1*/ 4968 double Tria::TimeAdapt(void){ 4969 4970 /*intermediary: */ 4971 int i; 4972 double C,dt; 4973 double dx,dy; 4974 double maxx,minx; 4975 double maxy,miny; 4976 double maxabsvx,maxabsvy; 4977 double xyz_list[NUMVERTICES][3]; 4978 4979 /*get CFL coefficient:*/ 4980 this->parameters->FindParam(&C,CflCoefficientEnum); 4981 4982 /*Get for Vx and Vy, the max of abs value: */ 4983 this->MaxAbsVx(&maxabsvx,false); 4984 this->MaxAbsVy(&maxabsvy,false); 4985 4986 /* Get node coordinates and dof list: */ 4987 GetVerticesCoordinates(&xyz_list[0][0], this->nodes, NUMVERTICES); 4988 4989 minx=xyz_list[0][0]; 4990 maxx=xyz_list[0][0]; 4991 miny=xyz_list[0][1]; 4992 maxy=xyz_list[0][1]; 4993 4994 for(i=1;i<NUMVERTICES;i++){ 4995 if (xyz_list[i][0]<minx)minx=xyz_list[i][0]; 4996 if (xyz_list[i][0]>maxx)maxx=xyz_list[i][0]; 4997 if (xyz_list[i][1]<miny)miny=xyz_list[i][1]; 4998 if (xyz_list[i][1]>maxy)maxy=xyz_list[i][1]; 4999 } 5000 dx=maxx-minx; 5001 dy=maxy-miny; 5002 5003 /*CFL criterion: */ 5004 dt=C/(maxabsvy/dx+maxabsvy/dy); 5005 5006 return dt; 2316 5007 } 2317 5008 /*}}}*/ … … 2447 5138 } 2448 5139 /*}}}*/ 2449 2450 /*Tria specific routines: */2451 /*FUNCTION Tria::CreateKMatrixAdjointBalancedthickness {{{1*/2452 ElementMatrix* Tria::CreateKMatrixAdjointBalancedthickness(void){2453 2454 ElementMatrix* Ke=NULL;2455 2456 /*Get Element Matrix of the forward model*/2457 switch(GetElementType()){2458 case P1Enum:2459 Ke=CreateKMatrixBalancedthickness_CG();2460 break;2461 case P1DGEnum:2462 Ke=CreateKMatrixBalancedthickness_DG();2463 break;2464 default:2465 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType()));2466 }2467 2468 /*Transpose and return Ke*/2469 Ke->Transpose();2470 return Ke;2471 }2472 /*}}}*/2473 /*FUNCTION Tria::CreateKMatrixBalancedthickness {{{1*/2474 ElementMatrix* Tria::CreateKMatrixBalancedthickness(void){2475 2476 switch(GetElementType()){2477 case P1Enum:2478 return CreateKMatrixBalancedthickness_CG();2479 case P1DGEnum:2480 return CreateKMatrixBalancedthickness_DG();2481 default:2482 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType()));2483 }2484 2485 }2486 /*}}}*/2487 /*FUNCTION Tria::CreateKMatrixBalancedthickness_CG {{{1*/2488 ElementMatrix* Tria::CreateKMatrixBalancedthickness_CG(void){2489 2490 /*Constants*/2491 const int numdof=NDOF1*NUMVERTICES;2492 2493 /*Intermediaries */2494 int artdiff;2495 int i,j,ig,dim;2496 double Jdettria ,vx,vy,dvxdx,dvydy;2497 double dvx[2],dvy[2];2498 double xyz_list[NUMVERTICES][3];2499 double L[NUMVERTICES];2500 double B[2][NUMVERTICES];2501 double Bprime[2][NUMVERTICES];2502 double K[2][2] = {0.0};2503 double KDL[2][2] = {0.0};2504 double DL[2][2] = {0.0};2505 double DLprime[2][2] = {0.0};2506 double DL_scalar;2507 double Ke_gg_gaussian[numdof][numdof] = {0.0};2508 double Ke_gg_thickness1[numdof][numdof] = {0.0};2509 double Ke_gg_thickness2[numdof][numdof] = {0.0};2510 GaussTria *gauss = NULL;2511 2512 /*Initialize Element matrix and return if necessary*/2513 if(IsOnWater()) return NULL;2514 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);2515 2516 /*Retrieve all Inputs and parameters: */2517 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2518 this->parameters->FindParam(&artdiff,ArtDiffEnum);2519 this->parameters->FindParam(&dim,DimEnum);2520 Input* vxaverage_input=NULL;2521 Input* vyaverage_input=NULL;2522 if(dim==2){2523 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input);2524 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input);2525 }2526 else{2527 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input);2528 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input);2529 }2530 2531 /*Create Artificial diffusivity once for all if requested*/2532 if(artdiff){2533 gauss=new GaussTria();2534 gauss->GaussCenter();2535 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);2536 delete gauss;2537 2538 vxaverage_input->GetParameterAverage(&vx);2539 vyaverage_input->GetParameterAverage(&vy);2540 K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(vx);2541 K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(vy);2542 }2543 2544 /*Start looping on the number of gaussian points:*/2545 gauss=new GaussTria(2);2546 for (ig=gauss->begin();ig<gauss->end();ig++){2547 2548 gauss->GaussPoint(ig);2549 2550 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);2551 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);2552 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);2553 2554 vxaverage_input->GetParameterValue(&vx,gauss);2555 vyaverage_input->GetParameterValue(&vy,gauss);2556 vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);2557 vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);2558 2559 dvxdx=dvx[0];2560 dvydy=dvy[1];2561 DL_scalar=gauss->weight*Jdettria;2562 2563 DL[0][0]=DL_scalar*dvxdx;2564 DL[1][1]=DL_scalar*dvydy;2565 2566 DLprime[0][0]=DL_scalar*vx;2567 DLprime[1][1]=DL_scalar*vy;2568 2569 TripleMultiply( &B[0][0],2,numdof,1,2570 &DL[0][0],2,2,0,2571 &B[0][0],2,numdof,0,2572 &Ke_gg_thickness1[0][0],0);2573 2574 TripleMultiply( &B[0][0],2,numdof,1,2575 &DLprime[0][0],2,2,0,2576 &Bprime[0][0],2,numdof,0,2577 &Ke_gg_thickness2[0][0],0);2578 2579 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness1[i][j];2580 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness2[i][j];2581 2582 if(artdiff){2583 KDL[0][0]=DL_scalar*K[0][0];2584 KDL[1][1]=DL_scalar*K[1][1];2585 2586 TripleMultiply( &Bprime[0][0],2,numdof,1,2587 &KDL[0][0],2,2,0,2588 &Bprime[0][0],2,numdof,0,2589 &Ke_gg_gaussian[0][0],0);2590 2591 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j];2592 }2593 }2594 2595 /*Clean up and return*/2596 delete gauss;2597 return Ke;2598 }2599 /*}}}*/2600 /*FUNCTION Tria::CreateKMatrixBalancedthickness_DG {{{1*/2601 ElementMatrix* Tria::CreateKMatrixBalancedthickness_DG(void){2602 2603 /*Constants*/2604 const int numdof=NDOF1*NUMVERTICES;2605 2606 /*Intermediaries*/2607 int i,j,ig,dim;2608 double vx,vy,Jdettria;2609 double xyz_list[NUMVERTICES][3];2610 double B[2][NUMVERTICES];2611 double Bprime[2][NUMVERTICES];2612 double DL[2][2]={0.0};2613 double DL_scalar;2614 double Ke_gg[numdof][numdof]={0.0};2615 GaussTria *gauss=NULL;2616 2617 /*Initialize Element matrix and return if necessary*/2618 if(IsOnWater()) return NULL;2619 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);2620 2621 /*Retrieve all inputs and parameters*/2622 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2623 this->parameters->FindParam(&dim,DimEnum);2624 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2625 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2626 2627 /*Start looping on the number of gaussian points:*/2628 gauss=new GaussTria(2);2629 for (ig=gauss->begin();ig<gauss->end();ig++){2630 2631 gauss->GaussPoint(ig);2632 2633 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);2634 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/2635 GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);2636 GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss);2637 2638 vx_input->GetParameterValue(&vx,gauss);2639 vy_input->GetParameterValue(&vy,gauss);2640 2641 DL_scalar=-gauss->weight*Jdettria;2642 DL[0][0]=DL_scalar*vx;2643 DL[1][1]=DL_scalar*vy;2644 2645 TripleMultiply( &B[0][0],2,numdof,1,2646 &DL[0][0],2,2,0,2647 &Bprime[0][0],2,numdof,0,2648 &Ke_gg[0][0],0);2649 2650 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg[i][j];2651 }2652 2653 /*Clean up and return*/2654 delete gauss;2655 return Ke;2656 }2657 /*}}}*/2658 /*FUNCTION Tria::CreateKMatrixBalancedvelocities {{{1*/2659 ElementMatrix* Tria::CreateKMatrixBalancedvelocities(void){2660 2661 /*Constants*/2662 const int numdof=NDOF1*NUMVERTICES;2663 2664 /*Intermediaries */2665 int artdiff;2666 int i,j,ig,dim;2667 double nx,ny,norm,Jdettria;2668 double dvx[2],dvy[2];2669 double vx,vy,dvxdx,dvydy;2670 double v_gauss[2]={0.0};2671 double surface_normal[3];2672 double surface_list[3];2673 double xyz_list[NUMVERTICES][3];2674 double B[2][NUMVERTICES];2675 double Bprime[2][NUMVERTICES];2676 double K[2][2]={0.0};2677 double KDL[2][2]={0.0};2678 double DLprime[2][2]={0.0};2679 double DL_scalar;2680 double Ke_gg_gaussian[numdof][numdof] = {0.0};2681 double Ke_gg_velocities[numdof][numdof] = {0.0};2682 GaussTria *gauss=NULL;2683 2684 /*Initialize Element matrix and return if necessary*/2685 if(IsOnWater()) return NULL;2686 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);2687 2688 /*Retrieve all inputs and parameters*/2689 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2690 this->parameters->FindParam(&artdiff,ArtDiffEnum);2691 this->parameters->FindParam(&dim,DimEnum);2692 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input);2693 Input* vxaverage_input=NULL;2694 Input* vyaverage_input=NULL;2695 if(dim==2){2696 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input);2697 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input);2698 }2699 else{2700 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input);2701 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input);2702 }2703 2704 /*Modify z so that it reflects the surface*/2705 GetParameterListOnVertices(&surface_list[0],SurfaceEnum);2706 for(i=0;i<NUMVERTICES;i++) xyz_list[i][2]=surface_list[i];2707 2708 /*Get normal vector to the surface*/2709 vxaverage_input->GetParameterAverage(&nx);2710 vyaverage_input->GetParameterAverage(&ny);2711 if(nx==0 && ny==0){2712 SurfaceNormal(&surface_normal[0],xyz_list);2713 nx=surface_normal[0];2714 ny=surface_normal[1];2715 }2716 if(nx==0 && ny==0){2717 nx=0; ny=1;2718 }2719 norm=pow( pow(nx,2)+pow(ny,2) , (double).5);2720 nx=nx/norm; ny=ny/norm;2721 2722 //Create Artificial diffusivity once for all if requested2723 if(artdiff){2724 gauss=new GaussTria();2725 gauss->GaussCenter();2726 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);2727 delete gauss;2728 2729 vxaverage_input->GetParameterAverage(&v_gauss[0]);2730 vyaverage_input->GetParameterAverage(&v_gauss[1]);2731 K[0][0]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]); //pow should be zero!!2732 K[1][1]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);2733 }2734 2735 /* Start looping on the number of gaussian points: */2736 gauss=new GaussTria(2);2737 for (ig=gauss->begin();ig<gauss->end();ig++){2738 2739 gauss->GaussPoint(ig);2740 2741 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);2742 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);2743 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);2744 2745 vxaverage_input->GetParameterValue(&vx,gauss);2746 vyaverage_input->GetParameterValue(&vy,gauss);2747 vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);2748 vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);2749 2750 dvxdx=dvx[0];2751 dvydy=dvy[1];2752 DL_scalar=gauss->weight*Jdettria;2753 2754 DLprime[0][0]=DL_scalar*nx;2755 DLprime[1][1]=DL_scalar*ny;2756 2757 TripleMultiply( &B[0][0],2,numdof,1,2758 &DLprime[0][0],2,2,0,2759 &Bprime[0][0],2,numdof,0,2760 &Ke_gg_velocities[0][0],0);2761 2762 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_velocities[i][j];2763 2764 if(artdiff){2765 KDL[0][0]=DL_scalar*K[0][0];2766 KDL[1][1]=DL_scalar*K[1][1];2767 2768 TripleMultiply( &Bprime[0][0],2,numdof,1,2769 &KDL[0][0],2,2,0,2770 &Bprime[0][0],2,numdof,0,2771 &Ke_gg_gaussian[0][0],0);2772 2773 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j];2774 }2775 }2776 2777 /*Clean up and return*/2778 delete gauss;2779 return Ke;2780 }2781 /*}}}*/2782 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyeal {{{1*/2783 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyeal(void){2784 2785 /*compute all stiffness matrices for this element*/2786 ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyealViscous();2787 ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyealFriction();2788 ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);2789 2790 /*clean-up and return*/2791 delete Ke1;2792 delete Ke2;2793 return Ke;2794 2795 }2796 /*}}}*/2797 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealViscous{{{1*/2798 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealViscous(void){2799 2800 /*Constants*/2801 const int numdof=NDOF2*NUMVERTICES;2802 2803 /*Intermediaries*/2804 int i,j,ig;2805 double xyz_list[NUMVERTICES][3];2806 double viscosity,newviscosity,oldviscosity;2807 double viscosity_overshoot,thickness,Jdet;2808 double epsilon[3],oldepsilon[3]; /* epsilon=[exx,eyy,exy]; */2809 double B[3][numdof];2810 double Bprime[3][numdof];2811 double D[3][3] = {0.0};2812 double D_scalar;2813 double Ke_g[numdof][numdof];2814 GaussTria *gauss = NULL;2815 2816 /*Initialize Element matrix and return if necessary*/2817 if(IsOnWater()) return NULL;2818 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);2819 2820 /*Retrieve all inputs and parameters*/2821 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2822 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);2823 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2824 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2825 Input* vxold_input=inputs->GetInput(VxOldEnum); ISSMASSERT(vxold_input);2826 Input* vyold_input=inputs->GetInput(VyOldEnum); ISSMASSERT(vyold_input);2827 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);2828 2829 /* Start looping on the number of gaussian points: */2830 gauss=new GaussTria(2);2831 for (ig=gauss->begin();ig<gauss->end();ig++){2832 2833 gauss->GaussPoint(ig);2834 2835 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);2836 GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss);2837 GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss);2838 2839 this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);2840 this->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);2841 matice->GetViscosity2d(&viscosity, &epsilon[0]);2842 matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);2843 thickness_input->GetParameterValue(&thickness, gauss);2844 2845 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);2846 D_scalar=2*newviscosity*thickness*gauss->weight*Jdet;2847 for (i=0;i<3;i++) D[i][i]=D_scalar;2848 2849 TripleMultiply(&B[0][0],3,numdof,1,2850 &D[0][0],3,3,0,2851 &Bprime[0][0],3,numdof,0,2852 &Ke_g[0][0],0);2853 2854 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j];2855 }2856 2857 /*Clean up and return*/2858 delete gauss;2859 return Ke;2860 }2861 /*}}}*/2862 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealFriction {{{1*/2863 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealFriction(void){2864 2865 /*Constants*/2866 const int numdof=NDOF2*NUMVERTICES;2867 2868 /*Intermediaries*/2869 int i,j,ig;2870 int analysis_type,drag_type;2871 double MAXSLOPE = .06; // 6 %2872 double MOUNTAINKEXPONENT = 10;2873 double slope_magnitude,alpha2;2874 double Jdet;2875 double L[2][numdof];2876 double DL[2][2] = {{ 0,0 },{0,0}};2877 double Ke_g[numdof][numdof];2878 double DL_scalar;2879 double slope[2] = {0.0,0.0};2880 double xyz_list[NUMVERTICES][3];2881 Friction *friction = NULL;2882 GaussTria *gauss = NULL;2883 2884 /*Initialize Element matrix and return if necessary*/2885 if(IsOnWater() || IsOnShelf()) return NULL;2886 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);2887 2888 /*Retrieve all inputs and parameters*/2889 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2890 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input);2891 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2892 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2893 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);2894 inputs->GetParameterValue(&drag_type,DragTypeEnum);2895 parameters->FindParam(&analysis_type,AnalysisTypeEnum);2896 2897 /*build friction object, used later on: */2898 if (drag_type!=2) ISSMERROR(" non-viscous friction not supported yet!");2899 friction=new Friction("2d",inputs,matpar,analysis_type);2900 2901 /* Start looping on the number of gaussian points: */2902 gauss=new GaussTria(2);2903 for (ig=gauss->begin();ig<gauss->end();ig++){2904 2905 gauss->GaussPoint(ig);2906 2907 // If we have a slope > 6% for this element, it means we are on a mountain. In this particular case,2908 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */2909 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);2910 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));2911 if(slope_magnitude>MAXSLOPE) alpha2=pow((double)10,MOUNTAINKEXPONENT);2912 else friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);2913 2914 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2);2915 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);2916 DL_scalar=alpha2*gauss->weight*Jdet;2917 for (i=0;i<2;i++) DL[i][i]=DL_scalar;2918 2919 TripleMultiply( &L[0][0],2,numdof,1,2920 &DL[0][0],2,2,0,2921 &L[0][0],2,numdof,0,2922 &Ke_g[0][0],0);2923 2924 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j];2925 }2926 2927 /*Clean up and return*/2928 delete gauss;2929 delete friction;2930 return Ke;2931 }2932 /*}}}*/2933 /*FUNCTION Tria::CreateKMatrixCouplingMacAyealPattynFriction {{{1*/2934 ElementMatrix* Tria::CreateKMatrixCouplingMacAyealPattynFriction(void){2935 2936 /*Constants*/2937 const int numdof = NDOF2 *NUMVERTICES;2938 const int numdoftotal = NDOF4 *NUMVERTICES;2939 2940 /*Intermediaries */2941 int i,j,ig,analysis_type,drag_type;2942 double Jdet,slope_magnitude,alpha2;2943 double xyz_list[NUMVERTICES][3];2944 double slope[2]={0.0,0.0};2945 double MAXSLOPE=.06; // 6 %2946 double MOUNTAINKEXPONENT=10;2947 double L[2][numdof];2948 double DL[2][2] ={{ 0,0 },{0,0}}; //for basal drag2949 double DL_scalar;2950 double Ke_gg[numdof][numdof] ={0.0};2951 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag2952 Friction *friction = NULL;2953 GaussTria *gauss=NULL;2954 2955 /*Initialize Element matrix and return if necessary*/2956 if(IsOnWater() || IsOnShelf()) return NULL;2957 ElementMatrix* Ke1=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);2958 ElementMatrix* Ke2=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);2959 ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);2960 delete Ke1; delete Ke2;2961 2962 /*retrieve inputs :*/2963 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);2964 parameters->FindParam(&analysis_type,AnalysisTypeEnum);2965 inputs->GetParameterValue(&drag_type,DragTypeEnum);2966 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input);2967 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);2968 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);2969 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);2970 2971 /*build friction object, used later on: */2972 if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");2973 friction=new Friction("2d",inputs,matpar,analysis_type);2974 2975 /* Start looping on the number of gaussian points: */2976 gauss=new GaussTria(2);2977 for (ig=gauss->begin();ig<gauss->end();ig++){2978 2979 gauss->GaussPoint(ig);2980 2981 /*Friction: */2982 friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);2983 2984 // If we have a slope > 6% for this element, it means we are on a mountain. In this particular case,2985 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */2986 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);2987 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));2988 2989 if (slope_magnitude>MAXSLOPE){2990 alpha2=pow((double)10,MOUNTAINKEXPONENT);2991 }2992 2993 /* Get Jacobian determinant: */2994 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);2995 2996 /*Get L matrix: */2997 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2);2998 2999 3000 DL_scalar=alpha2*gauss->weight*Jdet;3001 for (i=0;i<2;i++){3002 DL[i][i]=DL_scalar;3003 }3004 3005 /* Do the triple producte tL*D*L: */3006 TripleMultiply( &L[0][0],2,numdof,1,3007 &DL[0][0],2,2,0,3008 &L[0][0],2,numdof,0,3009 &Ke_gg_gaussian[0][0],0);3010 3011 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];3012 }3013 3014 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdoftotal+(numdof+j)]+=Ke_gg[i][j];3015 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[(i+numdof)*numdoftotal+j]+=Ke_gg[i][j];3016 3017 /*Clean up and return*/3018 delete gauss;3019 delete friction;3020 return Ke;3021 }3022 /*}}}*/3023 /*FUNCTION Tria::CreateKMatrixDiagnosticPattynFriction {{{1*/3024 ElementMatrix* Tria::CreateKMatrixDiagnosticPattynFriction(void){3025 3026 /*Constants*/3027 const int numdof = NDOF2*NUMVERTICES;3028 3029 /*Intermediaries */3030 int i,j,ig;3031 int analysis_type,drag_type;3032 double xyz_list[NUMVERTICES][3];3033 double slope_magnitude,alpha2,Jdet;3034 double slope[2]={0.0,0.0};3035 double MAXSLOPE=.06; // 6 %3036 double MOUNTAINKEXPONENT=10;3037 double L[2][numdof];3038 double DL[2][2]={{ 0,0 },{0,0}}; //for basal drag3039 double DL_scalar;3040 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag3041 Friction *friction = NULL;3042 GaussTria *gauss=NULL;3043 3044 /*Initialize Element matrix and return if necessary*/3045 if(IsOnWater() || IsOnShelf()) return NULL;3046 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);3047 3048 /*Retrieve all inputs and parameters*/3049 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3050 parameters->FindParam(&analysis_type,AnalysisTypeEnum);3051 inputs->GetParameterValue(&drag_type,DragTypeEnum);3052 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input);3053 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);3054 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);3055 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);3056 3057 /*build friction object, used later on: */3058 if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");3059 friction=new Friction("2d",inputs,matpar,analysis_type);3060 3061 /* Start looping on the number of gaussian points: */3062 gauss=new GaussTria(2);3063 for (ig=gauss->begin();ig<gauss->end();ig++){3064 3065 gauss->GaussPoint(ig);3066 3067 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);3068 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2);3069 3070 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);3071 friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum); // TO UNCOMMENT3072 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));3073 3074 // If we have a slope > 6% for this element, it means we are on a mountain. In this particular case,3075 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */3076 if (slope_magnitude>MAXSLOPE){3077 alpha2=pow((double)10,MOUNTAINKEXPONENT);3078 }3079 3080 DL_scalar=alpha2*gauss->weight*Jdet;3081 for (i=0;i<2;i++) DL[i][i]=DL_scalar;3082 3083 TripleMultiply( &L[0][0],2,numdof,1,3084 &DL[0][0],2,2,0,3085 &L[0][0],2,numdof,0,3086 &Ke_gg_gaussian[0][0],0);3087 3088 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j];3089 }3090 3091 /*Clean up and return*/3092 delete gauss;3093 delete friction;3094 return Ke;3095 }3096 /*}}}*/3097 /*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/3098 ElementMatrix* Tria::CreateKMatrixDiagnosticHutter(void){3099 3100 /*Intermediaries*/3101 const int numdof=NUMVERTICES*NDOF2;3102 int i,connectivity;3103 3104 /*Initialize Element matrix and return if necessary*/3105 if(IsOnWater()) return NULL;3106 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);3107 3108 /*Create Element matrix*/3109 for(i=0;i<NUMVERTICES;i++){3110 connectivity=nodes[i]->GetConnectivity();3111 Ke->values[(2*i)*numdof +(2*i) ]=1/(double)connectivity;3112 Ke->values[(2*i+1)*numdof+(2*i+1)]=1/(double)connectivity;3113 }3114 3115 /*Clean up and return*/3116 return Ke;3117 }3118 /*}}}*/3119 /*FUNCTION Tria::CreateKMatrixDiagnosticVertSurface {{{1*/3120 ElementMatrix* Tria::CreateKMatrixDiagnosticVertSurface(void){3121 3122 /*Constants*/3123 const int numdof=NDOF1*NUMVERTICES;3124 3125 /*Intermediaries */3126 int i,j,ig;3127 double xyz_list[NUMVERTICES][3];3128 double surface_normal[3];3129 double Jdet,DL_scalar;3130 double L[3];3131 GaussTria *gauss=NULL;3132 double Ke_g[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.3133 3134 /*Initialize Element matrix and return if necessary*/3135 if(IsOnWater()) return NULL;3136 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);3137 3138 /*Retrieve all inputs and parameters*/3139 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3140 SurfaceNormal(&surface_normal[0],xyz_list);3141 3142 /* Start looping on the number of gaussian points: */3143 gauss=new GaussTria(2);3144 for (ig=gauss->begin();ig<gauss->end();ig++){3145 3146 gauss->GaussPoint(ig);3147 3148 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss);3149 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3150 3151 /**********************Do not forget the sign**********************************/3152 DL_scalar=- gauss->weight*Jdet*surface_normal[2];3153 /******************************************************************************/3154 3155 TripleMultiply( L,1,3,1,3156 &DL_scalar,1,1,0,3157 L,1,3,0,3158 &Ke_g[0][0],0);3159 3160 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j];3161 }3162 3163 /*Clean up and return*/3164 delete gauss;3165 return Ke;3166 }3167 /*}}}*/3168 /*FUNCTION Tria::CreateKMatrixMelting {{{1*/3169 ElementMatrix* Tria::CreateKMatrixMelting(void){3170 3171 /*Constants*/3172 const int numdof=NUMVERTICES*NDOF1;3173 3174 /*Intermediaries */3175 int i,j,ig;3176 double heatcapacity,latentheat;3177 double Jdet,D_scalar;3178 double xyz_list[NUMVERTICES][3];3179 double L[3];3180 double Ke_gaussian[numdof][numdof]={0.0};3181 GaussTria *gauss=NULL;3182 3183 /*Initialize Element matrix and return if necessary*/3184 if(IsOnWater()) return NULL;3185 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);3186 3187 /*Retrieve all inputs and parameters*/3188 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3189 latentheat=matpar->GetLatentHeat();3190 heatcapacity=matpar->GetHeatCapacity();3191 3192 /* Start looping on the number of gauss (nodes on the bedrock) */3193 gauss=new GaussTria(2);3194 for (ig=gauss->begin();ig<gauss->end();ig++){3195 3196 gauss->GaussPoint(ig);3197 3198 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3199 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss);3200 3201 D_scalar=latentheat/heatcapacity*gauss->weight*Jdet;3202 3203 TripleMultiply(&L[0],numdof,1,0,3204 &D_scalar,1,1,0,3205 &L[0],1,numdof,0,3206 &Ke_gaussian[0][0],0);3207 3208 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gaussian[i][j];3209 }3210 3211 /*Clean up and return*/3212 delete gauss;3213 return Ke;3214 }3215 /*}}}*/3216 /*FUNCTION Tria::CreateKMatrixPrognostic {{{1*/3217 ElementMatrix* Tria::CreateKMatrixPrognostic(void){3218 3219 switch(GetElementType()){3220 case P1Enum:3221 return CreateKMatrixPrognostic_CG();3222 case P1DGEnum:3223 return CreateKMatrixPrognostic_DG();3224 default:3225 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType()));3226 }3227 3228 }3229 /*}}}*/3230 /*FUNCTION Tria::CreateKMatrixPrognostic_CG {{{1*/3231 ElementMatrix* Tria::CreateKMatrixPrognostic_CG(void){3232 3233 /*Constants*/3234 const int numdof=NDOF1*NUMVERTICES;3235 3236 /*Intermediaries */3237 int artdiff;3238 int i,j,ig,dim;3239 double Jdettria,DL_scalar,dt;3240 double vx,vy,dvxdx,dvydy;3241 double dvx[2],dvy[2];3242 double v_gauss[2]={0.0};3243 double xyz_list[NUMVERTICES][3];3244 double L[NUMVERTICES];3245 double B[2][NUMVERTICES];3246 double Bprime[2][NUMVERTICES];3247 double K[2][2] ={0.0};3248 double KDL[2][2] ={0.0};3249 double DL[2][2] ={0.0};3250 double DLprime[2][2] ={0.0};3251 double Ke_gg_gaussian[numdof][numdof] ={0.0};3252 double Ke_gg_thickness1[numdof][numdof]={0.0};3253 double Ke_gg_thickness2[numdof][numdof]={0.0};3254 GaussTria *gauss=NULL;3255 3256 /*Initialize Element matrix and return if necessary*/3257 if(IsOnWater()) return NULL;3258 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);3259 3260 /*Retrieve all inputs and parameters*/3261 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3262 this->inputs->GetParameterValue(&dt,DtEnum);3263 this->parameters->FindParam(&dim,DimEnum);3264 this->parameters->FindParam(&artdiff,ArtDiffEnum);3265 Input* vxaverage_input=NULL;3266 Input* vyaverage_input=NULL;3267 if(dim==2){3268 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input);3269 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input);3270 }3271 else{3272 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input);3273 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input);3274 }3275 3276 //Create Artificial diffusivity once for all if requested3277 if(artdiff){3278 gauss=new GaussTria();3279 gauss->GaussCenter();3280 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);3281 delete gauss;3282 3283 vxaverage_input->GetParameterAverage(&v_gauss[0]);3284 vyaverage_input->GetParameterAverage(&v_gauss[1]);3285 3286 K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]);3287 K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);3288 }3289 3290 /* Start looping on the number of gaussian points: */3291 gauss=new GaussTria(2);3292 for (ig=gauss->begin();ig<gauss->end();ig++){3293 3294 gauss->GaussPoint(ig);3295 3296 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);3297 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3298 3299 vxaverage_input->GetParameterValue(&vx,gauss);3300 vyaverage_input->GetParameterValue(&vy,gauss);3301 vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);3302 vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);3303 3304 DL_scalar=gauss->weight*Jdettria;3305 3306 TripleMultiply( &L[0],1,numdof,1,3307 &DL_scalar,1,1,0,3308 &L[0],1,numdof,0,3309 &Ke_gg_gaussian[0][0],0);3310 3311 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);3312 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);3313 3314 dvxdx=dvx[0];3315 dvydy=dvy[1];3316 DL_scalar=dt*gauss->weight*Jdettria;3317 3318 DL[0][0]=DL_scalar*dvxdx;3319 DL[1][1]=DL_scalar*dvydy;3320 DLprime[0][0]=DL_scalar*vx;3321 DLprime[1][1]=DL_scalar*vy;3322 3323 TripleMultiply( &B[0][0],2,numdof,1,3324 &DL[0][0],2,2,0,3325 &B[0][0],2,numdof,0,3326 &Ke_gg_thickness1[0][0],0);3327 3328 TripleMultiply( &B[0][0],2,numdof,1,3329 &DLprime[0][0],2,2,0,3330 &Bprime[0][0],2,numdof,0,3331 &Ke_gg_thickness2[0][0],0);3332 3333 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j];3334 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness1[i][j];3335 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_thickness2[i][j];3336 3337 if(artdiff){3338 KDL[0][0]=DL_scalar*K[0][0];3339 KDL[1][1]=DL_scalar*K[1][1];3340 3341 TripleMultiply( &Bprime[0][0],2,numdof,1,3342 &KDL[0][0],2,2,0,3343 &Bprime[0][0],2,numdof,0,3344 &Ke_gg_gaussian[0][0],0);3345 3346 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg_gaussian[i][j];3347 }3348 }3349 3350 /*Clean up and return*/3351 delete gauss;3352 return Ke;3353 }3354 /*}}}*/3355 /*FUNCTION Tria::CreateKMatrixPrognostic_DG {{{1*/3356 ElementMatrix* Tria::CreateKMatrixPrognostic_DG(void){3357 3358 /*Constants*/3359 const int numdof=NDOF1*NUMVERTICES;3360 3361 /*Intermediaries */3362 int i,j,ig,dim;3363 double xyz_list[NUMVERTICES][3];3364 double Jdettria,dt,vx,vy;3365 double L[NUMVERTICES];3366 double B[2][NUMVERTICES];3367 double Bprime[2][NUMVERTICES];3368 double DL[2][2]={0.0};3369 double DLprime[2][2]={0.0};3370 double DL_scalar;3371 double Ke_gg1[numdof][numdof]={0.0};3372 double Ke_gg2[numdof][numdof]={0.0};3373 GaussTria *gauss=NULL;3374 3375 /*Initialize Element matrix and return if necessary*/3376 if(IsOnWater()) return NULL;3377 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);3378 3379 /*Retrieve all inputs and parameters*/3380 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3381 this->inputs->GetParameterValue(&dt,DtEnum);3382 this->parameters->FindParam(&dim,DimEnum);3383 Input* vxaverage_input=NULL;3384 Input* vyaverage_input=NULL;3385 if(dim==2){3386 vxaverage_input=inputs->GetInput(VxEnum); ISSMASSERT(vxaverage_input);3387 vyaverage_input=inputs->GetInput(VyEnum); ISSMASSERT(vyaverage_input);3388 }3389 else{3390 vxaverage_input=inputs->GetInput(VxAverageEnum); ISSMASSERT(vxaverage_input);3391 vyaverage_input=inputs->GetInput(VyAverageEnum); ISSMASSERT(vyaverage_input);3392 }3393 3394 /* Start looping on the number of gaussian points: */3395 gauss=new GaussTria(2);3396 for (ig=gauss->begin();ig<gauss->end();ig++){3397 3398 gauss->GaussPoint(ig);3399 3400 vxaverage_input->GetParameterValue(&vx,gauss);3401 vyaverage_input->GetParameterValue(&vy,gauss);3402 3403 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);3404 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3405 3406 DL_scalar=gauss->weight*Jdettria;3407 3408 TripleMultiply( &L[0],1,numdof,1,3409 &DL_scalar,1,1,0,3410 &L[0],1,numdof,0,3411 &Ke_gg1[0][0],0);3412 3413 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/3414 GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);3415 GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss);3416 3417 DL_scalar=-dt*gauss->weight*Jdettria;3418 3419 DLprime[0][0]=DL_scalar*vx;3420 DLprime[1][1]=DL_scalar*vy;3421 3422 TripleMultiply( &B[0][0],2,numdof,1,3423 &DLprime[0][0],2,2,0,3424 &Bprime[0][0],2,numdof,0,3425 &Ke_gg2[0][0],0);3426 3427 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg1[i][j];3428 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gg2[i][j];3429 }3430 3431 /*Clean up and return*/3432 delete gauss;3433 return Ke;3434 }3435 /*}}}*/3436 /*FUNCTION Tria::CreateKMatrixSlope {{{1*/3437 ElementMatrix* Tria::CreateKMatrixSlope(void){3438 3439 /*constants: */3440 const int numdof=NDOF1*NUMVERTICES;3441 3442 /* Intermediaries */3443 int i,j,ig;3444 double DL_scalar,Jdet;3445 double xyz_list[NUMVERTICES][3];3446 double L[1][3];3447 double Ke_g[numdof][numdof];3448 GaussTria *gauss = NULL;3449 3450 /*Initialize Element matrix and return if necessary*/3451 if(IsOnWater()) return NULL;3452 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);3453 3454 GetVerticesCoordinates(&xyz_list[0][0],nodes,NUMVERTICES);3455 3456 /* Start looping on the number of gaussian points: */3457 gauss=new GaussTria(2);3458 for (ig=gauss->begin();ig<gauss->end();ig++){3459 3460 gauss->GaussPoint(ig);3461 3462 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);3463 DL_scalar=gauss->weight*Jdet;3464 3465 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF1);3466 3467 TripleMultiply(&L[0][0],1,3,1,3468 &DL_scalar,1,1,0,3469 &L[0][0],1,3,0,3470 &Ke_g[0][0],0);3471 3472 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_g[i][j];3473 }3474 3475 /*Clean up and return*/3476 delete gauss;3477 return Ke;3478 }3479 /*}}}*/3480 /*FUNCTION Tria::CreateKMatrixThermal {{{1*/3481 ElementMatrix* Tria::CreateKMatrixThermal(void){3482 3483 /*Constants*/3484 const int numdof=NDOF1*NUMVERTICES;3485 3486 /*Intermediaries */3487 int i,j,ig;3488 double mixed_layer_capacity,thermal_exchange_velocity;3489 double rho_ice,rho_water,heatcapacity;3490 double Jdet,dt;3491 double xyz_list[NUMVERTICES][3];3492 double l1l2l3[NUMVERTICES];3493 double D_scalar;3494 double Ke_gaussian[numdof][numdof]={0.0};3495 GaussTria *gauss=NULL;3496 3497 /*Initialize Element matrix and return if necessary*/3498 if(IsOnWater() || !IsOnShelf()) return NULL;3499 ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);3500 3501 /*Retrieve all inputs and parameters*/3502 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3503 this->inputs->GetParameterValue(&dt,DtEnum);3504 mixed_layer_capacity=matpar->GetMixedLayerCapacity();3505 thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();3506 rho_water=matpar->GetRhoWater();3507 rho_ice=matpar->GetRhoIce();3508 heatcapacity=matpar->GetHeatCapacity();3509 3510 /* Start looping on the number of gauss (nodes on the bedrock) */3511 gauss=new GaussTria(2);3512 for (ig=gauss->begin();ig<gauss->end();ig++){3513 3514 gauss->GaussPoint(ig);3515 3516 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss);3517 GetNodalFunctions(&l1l2l3[0], gauss);3518 3519 D_scalar=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);3520 if(dt) D_scalar=dt*D_scalar;3521 3522 TripleMultiply(&l1l2l3[0],numdof,1,0,3523 &D_scalar,1,1,0,3524 &l1l2l3[0],1,numdof,0,3525 &Ke_gaussian[0][0],0);3526 3527 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdof+j]+=Ke_gaussian[i][j];3528 }3529 3530 /*Clean up and return*/3531 delete gauss;3532 return Ke;3533 }3534 /*}}}*/3535 /*FUNCTION Tria::CreatePVectorBalancedthickness{{{1*/3536 ElementVector* Tria::CreatePVectorBalancedthickness(void){3537 3538 switch(GetElementType()){3539 case P1Enum:3540 return CreatePVectorBalancedthickness_CG();3541 break;3542 case P1DGEnum:3543 return CreatePVectorBalancedthickness_DG();3544 default:3545 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType()));3546 }3547 }3548 /*}}}*/3549 /*FUNCTION Tria::CreatePVectorBalancedthickness_CG{{{1*/3550 ElementVector* Tria::CreatePVectorBalancedthickness_CG(void){3551 3552 /*Constants*/3553 const int numdof=NDOF1*NUMVERTICES;3554 3555 /*Intermediaries */3556 int i,j,ig;3557 double xyz_list[NUMVERTICES][3];3558 double dhdt_g,melting_g,accumulation_g,Jdettria;3559 double L[NUMVERTICES];3560 GaussTria* gauss=NULL;3561 3562 /*Initialize Element vector and return if necessary*/3563 if(IsOnWater()) return NULL;3564 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3565 3566 /*Retrieve all inputs and parameters*/3567 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3568 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input);3569 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input);3570 Input* dhdt_input=inputs->GetInput(DhDtEnum); ISSMASSERT(dhdt_input);3571 3572 /* Start looping on the number of gaussian points: */3573 gauss=new GaussTria(2);3574 for(ig=gauss->begin();ig<gauss->end();ig++){3575 3576 gauss->GaussPoint(ig);3577 3578 accumulation_input->GetParameterValue(&accumulation_g,gauss);3579 melting_input->GetParameterValue(&melting_g,gauss);3580 dhdt_input->GetParameterValue(&dhdt_g,gauss);3581 3582 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);3583 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3584 3585 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(accumulation_g-melting_g-dhdt_g)*L[i];3586 }3587 3588 /*Clean up and return*/3589 delete gauss;3590 return pe;3591 }3592 /*}}}*/3593 /*FUNCTION Tria::CreatePVectorBalancedthickness_DG {{{1*/3594 ElementVector* Tria::CreatePVectorBalancedthickness_DG(void){3595 3596 /*Constants*/3597 const int numdof=NDOF1*NUMVERTICES;3598 3599 /*Intermediaries */3600 int i,j,ig;3601 double xyz_list[NUMVERTICES][3];3602 double melting_g,accumulation_g,dhdt_g,Jdettria;3603 double L[NUMVERTICES];3604 GaussTria* gauss=NULL;3605 3606 /*Initialize Element vector and return if necessary*/3607 if(IsOnWater()) return NULL;3608 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3609 3610 /*Retrieve all inputs and parameters*/3611 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3612 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input);3613 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input);3614 Input* dhdt_input=inputs->GetInput(DhDtEnum); ISSMASSERT(dhdt_input);3615 3616 /* Start looping on the number of gaussian points: */3617 gauss=new GaussTria(2);3618 for(ig=gauss->begin();ig<gauss->end();ig++){3619 3620 gauss->GaussPoint(ig);3621 3622 accumulation_input->GetParameterValue(&accumulation_g,gauss);3623 melting_input->GetParameterValue(&melting_g,gauss);3624 dhdt_input->GetParameterValue(&dhdt_g,gauss);3625 3626 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);3627 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3628 3629 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(accumulation_g-melting_g-dhdt_g)*L[i];3630 }3631 3632 /*Clean up and return*/3633 delete gauss;3634 return pe;3635 }3636 /*}}}*/3637 /*FUNCTION Tria::CreatePVectorBalancedvelocities {{{1*/3638 ElementVector* Tria::CreatePVectorBalancedvelocities(void){3639 3640 /*Constants*/3641 const int numdof=NDOF1*NUMVERTICES;3642 3643 /*Intermediaries */3644 int i,j,ig;3645 double xyz_list[NUMVERTICES][3];3646 double Jdettria,accumulation_g,melting_g;3647 double L[NUMVERTICES];3648 GaussTria* gauss=NULL;3649 3650 /*Initialize Element vector and return if necessary*/3651 if(IsOnWater()) return NULL;3652 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3653 3654 /*Retrieve all inputs and parameters*/3655 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3656 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input);3657 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input);3658 3659 /* Start looping on the number of gaussian points: */3660 gauss=new GaussTria(2);3661 for(ig=gauss->begin();ig<gauss->end();ig++){3662 3663 gauss->GaussPoint(ig);3664 3665 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);3666 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3667 3668 accumulation_input->GetParameterValue(&accumulation_g,gauss);3669 melting_input->GetParameterValue(&melting_g,gauss);3670 3671 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(accumulation_g-melting_g)*L[i];3672 }3673 3674 /*Clean up and return*/3675 delete gauss;3676 return pe;3677 }3678 /*}}}*/3679 /*FUNCTION Tria::CreatePVectorDiagnosticBaseVert {{{1*/3680 ElementVector* Tria::CreatePVectorDiagnosticBaseVert(void){3681 3682 /*Constants*/3683 const int numdof=NDOF1*NUMVERTICES;3684 3685 /*Intermediaries */3686 int i,j,ig;3687 int approximation;3688 double xyz_list[NUMVERTICES][3];3689 double Jdet;3690 double vx,vy,vz,dbdx,dbdy,meltingvalue;3691 double slope[2];3692 double L[NUMVERTICES];3693 GaussTria* gauss=NULL;3694 3695 /*Initialize Element vector and return if necessary*/3696 if(IsOnWater()) return NULL;3697 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3698 3699 /*Retrieve all inputs and parameters*/3700 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3701 inputs->GetParameterValue(&approximation,ApproximationEnum);3702 Input* bed_input=inputs->GetInput(BedEnum); ISSMASSERT(bed_input);3703 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input);3704 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);3705 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);3706 Input* vzstokes_input=NULL;3707 if(approximation==PattynStokesApproximationEnum){3708 vzstokes_input=inputs->GetInput(VzStokesEnum); ISSMASSERT(vzstokes_input);3709 }3710 3711 /* Start looping on the number of gaussian points: */3712 gauss=new GaussTria(2);3713 for(ig=gauss->begin();ig<gauss->end();ig++){3714 3715 gauss->GaussPoint(ig);3716 3717 melting_input->GetParameterValue(&meltingvalue, gauss);3718 bed_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);3719 vx_input->GetParameterValue(&vx, gauss);3720 vy_input->GetParameterValue(&vy, gauss);3721 if(approximation==PattynStokesApproximationEnum){3722 vzstokes_input->GetParameterValue(&vz, gauss);3723 }3724 else vz=0;3725 3726 dbdx=slope[0];3727 dbdy=slope[1];3728 3729 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss);3730 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);3731 3732 for(i=0;i<numdof;i++) pe->values[i]+=-Jdet*gauss->weight*(vx*dbdx+vy*dbdy-vz-meltingvalue)*L[i];3733 }3734 3735 /*Clean up and return*/3736 delete gauss;3737 return pe;3738 }3739 /*}}}*/3740 /*FUNCTION Tria::CreatePVectorDiagnosticMacAyeal {{{1*/3741 ElementVector* Tria::CreatePVectorDiagnosticMacAyeal(){3742 3743 /*Constants*/3744 const int numdof=NDOF2*NUMVERTICES;3745 3746 /*Intermediaries */3747 int i,j,ig,drag_type;3748 double plastic_stress,driving_stress_baseline,thickness;3749 double Jdet;3750 double xyz_list[NUMVERTICES][3];3751 double slope[2];3752 double l1l2l3[3];3753 double pe_g_gaussian[numdof];3754 GaussTria* gauss=NULL;3755 3756 /*Initialize Element vector and return if necessary*/3757 if(IsOnWater()) return NULL;3758 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);3759 3760 /*Retrieve all inputs and parameters*/3761 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3762 inputs->GetParameterValue(&drag_type,DragTypeEnum);3763 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);3764 Input* surface_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(surface_input);3765 Input* drag_input=inputs->GetInput(DragCoefficientEnum);ISSMASSERT(drag_input);3766 3767 /* Start looping on the number of gaussian points: */3768 gauss=new GaussTria(2);3769 for(ig=gauss->begin();ig<gauss->end();ig++){3770 3771 gauss->GaussPoint(ig);3772 3773 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);3774 GetNodalFunctions(l1l2l3, gauss);3775 3776 thickness_input->GetParameterValue(&thickness,gauss);3777 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);3778 3779 /*In case we have plastic basal drag, compute plastic stress at gaussian point from k1, k2 and k3 fields in the3780 * element itself: */3781 if(drag_type==1) drag_input->GetParameterValue(&plastic_stress,gauss);3782 3783 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;3784 3785 /*Build pe_g_gaussian vector: */3786 if(drag_type==1){3787 for (i=0;i<NUMVERTICES;i++){3788 for (j=0;j<NDOF2;j++){3789 pe->values[i*NDOF2+j]+=(-driving_stress_baseline*slope[j]-plastic_stress)*Jdet*gauss->weight*l1l2l3[i];3790 }3791 }3792 }3793 else {3794 for (i=0;i<NUMVERTICES;i++){3795 for (j=0;j<NDOF2;j++){3796 pe->values[i*NDOF2+j]+=-driving_stress_baseline*slope[j]*Jdet*gauss->weight*l1l2l3[i];3797 }3798 }3799 }3800 }3801 3802 /*Clean up and return*/3803 delete gauss;3804 return pe;3805 }3806 /*}}}*/3807 /*FUNCTION Tria::CreatePVectorAdjointBalancedthickness{{{1*/3808 ElementVector* Tria::CreatePVectorAdjointBalancedthickness(void){3809 3810 /*Constants*/3811 const int numdof=1*NUMVERTICES;3812 3813 /*Intermediaries */3814 int i,ig;3815 double Jdet;3816 double thickness,thicknessobs,weight;3817 double xyz_list[NUMVERTICES][3];3818 double l1l2l3[3];3819 GaussTria* gauss=NULL;3820 3821 /*Initialize Element vector and return if necessary*/3822 if(IsOnWater()) return NULL;3823 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3824 3825 /*Retrieve all inputs and parameters*/3826 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3827 Input* thickness_input =inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);3828 Input* thicknessobs_input=inputs->GetInput(ThicknessObsEnum);ISSMASSERT(thicknessobs_input);3829 Input* weights_input =inputs->GetInput(WeightsEnum); ISSMASSERT(weights_input);3830 3831 /* Start looping on the number of gaussian points: */3832 gauss=new GaussTria(2);3833 for(ig=gauss->begin();ig<gauss->end();ig++){3834 3835 gauss->GaussPoint(ig);3836 3837 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);3838 GetNodalFunctions(l1l2l3, gauss);3839 3840 thickness_input->GetParameterValue(&thickness, gauss);3841 thicknessobs_input->GetParameterValue(&thicknessobs, gauss);3842 weights_input->GetParameterValue(&weight, gauss);3843 3844 for(i=0;i<numdof;i++) pe->values[i]+=(thicknessobs-thickness)*weight*Jdet*gauss->weight*l1l2l3[i];3845 }3846 3847 /*Clean up and return*/3848 delete gauss;3849 return pe;3850 }3851 /*}}}*/3852 /*FUNCTION Tria::CreatePVectorAdjointHoriz{{{1*/3853 ElementVector* Tria::CreatePVectorAdjointHoriz(void){3854 3855 /*Constants*/3856 const int numdof=NDOF2*NUMVERTICES;3857 3858 /*Intermediaries */3859 int i,ig,response;3860 double Jdet;3861 double obs_velocity_mag,velocity_mag;3862 double dux,duy,meanvel,epsvel;3863 double scalex=0,scaley=0,scale=0,S=0;3864 double xyz_list[NUMVERTICES][3];3865 double vx_list[NUMVERTICES];3866 double vy_list[NUMVERTICES];3867 double obs_vx_list[NUMVERTICES];3868 double obs_vy_list[NUMVERTICES];3869 double dux_list[NUMVERTICES];3870 double duy_list[NUMVERTICES];3871 double weights_list[NUMVERTICES];3872 double l1l2l3[3];3873 GaussTria* gauss=NULL;3874 3875 /*Initialize Element vector and return if necessary*/3876 if(IsOnWater()) return NULL;3877 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);3878 3879 /*Retrieve all inputs and parameters*/3880 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);3881 this->parameters->FindParam(&meanvel,MeanVelEnum);3882 this->parameters->FindParam(&epsvel,EpsVelEnum);3883 GetParameterListOnVertices(&obs_vx_list[0],VxObsEnum);3884 GetParameterListOnVertices(&obs_vy_list[0],VyObsEnum);3885 GetParameterListOnVertices(&vx_list[0],VxEnum);3886 GetParameterListOnVertices(&vy_list[0],VyEnum);3887 GetParameterListOnVertices(&weights_list[0],WeightsEnum);3888 inputs->GetParameterValue(&response,CmResponseEnum);3889 if(response==SurfaceAverageVelMisfitEnum){3890 inputs->GetParameterValue(&S,SurfaceAreaEnum);3891 }3892 3893 /*Get Du at the 3 nodes (integration of the linearized function)3894 * Here we integrate linearized functions:3895 *3896 * J(E) = int_E sum_{i=1}^3 J_i Phi_i3897 *3898 * d J dJ_i3899 * DU= - --- = sum_{i=1}^3 - --- Phi_i = sum_{i=1}^3 DU_i Phi_i3900 * d u du_i3901 *3902 * where J_i are the misfits at the 3 nodes of the triangle3903 * Phi_i is the nodal function (P1) with respect to3904 * the vertex i3905 */3906 if(response==SurfaceAbsVelMisfitEnum){3907 /*We are using an absolute misfit:3908 *3909 * 1 [ 2 2 ]3910 * J = --- | (u - u ) + (v - v ) |3911 * 2 [ obs obs ]3912 *3913 * dJ3914 * DU = - -- = (u - u )3915 * du obs3916 */3917 for (i=0;i<NUMVERTICES;i++){3918 dux_list[i]=obs_vx_list[i]-vx_list[i];3919 duy_list[i]=obs_vy_list[i]-vy_list[i];3920 }3921 }3922 else if(response==SurfaceRelVelMisfitEnum){3923 /*We are using a relative misfit:3924 *3925 * 1 [ \bar{v}^2 2 \bar{v}^2 2 ]3926 * J = --- | ------------- (u - u ) + ------------- (v - v ) |3927 * 2 [ (u + eps)^2 obs (v + eps)^2 obs ]3928 * obs obs3929 *3930 * dJ \bar{v}^23931 * DU = - -- = ------------- (u - u )3932 * du (u + eps)^2 obs3933 * obs3934 */3935 for (i=0;i<NUMVERTICES;i++){3936 scalex=pow(meanvel/(obs_vx_list[i]+epsvel),2);3937 scaley=pow(meanvel/(obs_vy_list[i]+epsvel),2);3938 if(obs_vx_list[i]==0)scalex=0;3939 if(obs_vy_list[i]==0)scaley=0;3940 dux_list[i]=scalex*(obs_vx_list[i]-vx_list[i]);3941 duy_list[i]=scaley*(obs_vy_list[i]-vy_list[i]);3942 }3943 }3944 else if(response==SurfaceLogVelMisfitEnum){3945 /*We are using a logarithmic misfit:3946 *3947 * [ vel + eps ] 23948 * J = 4 \bar{v}^2 | log ( ----------- ) |3949 * [ vel + eps ]3950 * obs3951 *3952 * dJ 2 * log(...)3953 * DU = - -- = - 4 \bar{v}^2 ------------- u3954 * du vel^2 + eps3955 *3956 */3957 for (i=0;i<NUMVERTICES;i++){3958 velocity_mag=sqrt(pow(vx_list[i],2)+pow(vy_list[i],2))+epsvel; //epsvel to avoid velocity being nil.3959 obs_velocity_mag=sqrt(pow(obs_vx_list[i],2)+pow(obs_vy_list[i],2))+epsvel; //epsvel to avoid observed velocity being nil.3960 scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);3961 dux_list[i]=scale*vx_list[i];3962 duy_list[i]=scale*vy_list[i];3963 }3964 }3965 else if(response==SurfaceAverageVelMisfitEnum){3966 /*We are using an spacially average absolute misfit:3967 *3968 * 1 2 23969 * J = --- sqrt( (u - u ) + (v - v ) )3970 * S obs obs3971 *3972 * dJ 1 13973 * DU = - -- = - --- ----------- * 2 (u - u )3974 * du S 2 sqrt(...) obs3975 */3976 for (i=0;i<NUMVERTICES;i++){3977 scale=1.0/(S*sqrt(pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2))+epsvel);3978 dux_list[i]=scale*(obs_vx_list[i]-vx_list[i]);3979 duy_list[i]=scale*(obs_vy_list[i]-vy_list[i]);3980 }3981 }3982 else if(response==SurfaceLogVxVyMisfitEnum){3983 /*We are using an logarithmic 2 misfit:3984 *3985 * 1 [ |u| + eps 2 |v| + eps 2 ]3986 * J = --- \bar{v}^2 | log ( ----------- ) + log ( ----------- ) |3987 * 2 [ |u |+ eps |v |+ eps ]3988 * obs obs3989 * dJ 1 u 13990 * DU = - -- = - \bar{v}^2 log(u...) --------- ---- ~ - \bar{v}^2 log(u...) ------3991 * du |u| + eps |u| u + eps3992 */3993 for (i=0;i<NUMVERTICES;i++){3994 dux_list[i] = - pow(meanvel,(double)2)*(3995 log((fabs(vx_list[i])+epsvel)/(fabs(obs_vx_list[i])+epsvel)) * 1/(vx_list[i]+epsvel));3996 duy_list[i] = - pow(meanvel,(double)2)*(3997 log((fabs(vy_list[i])+epsvel)/(fabs(obs_vy_list[i])+epsvel)) * 1/(vy_list[i]+epsvel));3998 }3999 }4000 else{4001 /*Not supported yet! : */4002 ISSMERROR("response %s not supported yet",EnumToString(response));4003 }4004 4005 /*Apply weights to DU*/4006 for (i=0;i<NUMVERTICES;i++){4007 dux_list[i]=weights_list[i]*dux_list[i];4008 duy_list[i]=weights_list[i]*duy_list[i];4009 }4010 4011 /* Start looping on the number of gaussian points: */4012 gauss=new GaussTria(2);4013 for(ig=gauss->begin();ig<gauss->end();ig++){4014 4015 gauss->GaussPoint(ig);4016 4017 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);4018 GetNodalFunctions(l1l2l3, gauss);4019 4020 TriaRef::GetParameterValue(&dux, &dux_list[0],gauss);4021 TriaRef::GetParameterValue(&duy, &duy_list[0],gauss);4022 4023 for (i=0;i<NUMVERTICES;i++){4024 pe->values[i*NDOF2+0]+=dux*Jdet*gauss->weight*l1l2l3[i];4025 pe->values[i*NDOF2+1]+=duy*Jdet*gauss->weight*l1l2l3[i];4026 }4027 }4028 4029 /*Clean up and return*/4030 delete gauss;4031 return pe;4032 }4033 /*}}}*/4034 /*FUNCTION Tria::CreatePVectorAdjointStokes{{{1*/4035 ElementVector* Tria::CreatePVectorAdjointStokes(void){4036 4037 /*Intermediaries */4038 int i,ig;4039 int fit=-1;4040 int response;4041 double Jdet;4042 double obs_velocity_mag,velocity_mag;4043 double dux,duy,meanvel,epsvel;4044 double scalex=0,scaley=0,scale=0,S=0;4045 double xyz_list[NUMVERTICES][3];4046 double vx_list[NUMVERTICES];4047 double vy_list[NUMVERTICES];4048 double obs_vx_list[NUMVERTICES];4049 double obs_vy_list[NUMVERTICES];4050 double dux_list[NUMVERTICES];4051 double duy_list[NUMVERTICES];4052 double weights_list[NUMVERTICES];4053 double l1l2l3[3];4054 GaussTria* gauss=NULL;4055 4056 /*Initialize Element vector and return if necessary*/4057 if(IsOnWater()) return NULL;4058 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);4059 4060 /*Retrieve all inputs and parameters*/4061 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4062 this->parameters->FindParam(&meanvel,MeanVelEnum);4063 this->parameters->FindParam(&epsvel,EpsVelEnum);4064 GetParameterListOnVertices(&obs_vx_list[0],VxObsEnum);4065 GetParameterListOnVertices(&obs_vy_list[0],VyObsEnum);4066 GetParameterListOnVertices(&vx_list[0],VxEnum);4067 GetParameterListOnVertices(&vy_list[0],VyEnum);4068 GetParameterListOnVertices(&weights_list[0],WeightsEnum);4069 inputs->GetParameterValue(&response,CmResponseEnum);4070 if(response==SurfaceAverageVelMisfitEnum){4071 inputs->GetParameterValue(&S,SurfaceAreaEnum);4072 }4073 4074 /*Get Du at the 3 nodes (integration of the linearized function)4075 * Here we integrate linearized functions:4076 *4077 * J(E) = int_E sum_{i=1}^3 J_i Phi_i4078 *4079 * d J dJ_i4080 * DU= - --- = sum_{i=1}^3 - --- Phi_i = sum_{i=1}^3 DU_i Phi_i4081 * d u du_i4082 *4083 * where J_i are the misfits at the 3 nodes of the triangle4084 * Phi_i is the nodal function (P1) with respect to4085 * the vertex i4086 */4087 if(response==SurfaceAbsVelMisfitEnum){4088 /*We are using an absolute misfit:4089 *4090 * 1 [ 2 2 ]4091 * J = --- | (u - u ) + (v - v ) |4092 * 2 [ obs obs ]4093 *4094 * dJ 24095 * DU = - -- = (u - u )4096 * du obs4097 */4098 for (i=0;i<NUMVERTICES;i++){4099 dux_list[i]=obs_vx_list[i]-vx_list[i];4100 duy_list[i]=obs_vy_list[i]-vy_list[i];4101 }4102 }4103 else if(response==SurfaceRelVelMisfitEnum){4104 /*We are using a relative misfit:4105 *4106 * 1 [ \bar{v}^2 2 \bar{v}^2 2 ]4107 * J = --- | ------------- (u - u ) + ------------- (v - v ) |4108 * 2 [ (u + eps)^2 obs (v + eps)^2 obs ]4109 * obs obs4110 *4111 * dJ \bar{v}^24112 * DU = - -- = ------------- (u - u )4113 * du (u + eps)^2 obs4114 * obs4115 */4116 for (i=0;i<NUMVERTICES;i++){4117 scalex=pow(meanvel/(obs_vx_list[i]+epsvel),2);4118 scaley=pow(meanvel/(obs_vy_list[i]+epsvel),2);4119 if(obs_vx_list[i]==0)scalex=0;4120 if(obs_vy_list[i]==0)scaley=0;4121 dux_list[i]=scalex*(obs_vx_list[i]-vx_list[i]);4122 duy_list[i]=scaley*(obs_vy_list[i]-vy_list[i]);4123 }4124 }4125 else if(response==SurfaceLogVelMisfitEnum){4126 /*We are using a logarithmic misfit:4127 *4128 * [ vel + eps ] 24129 * J = 4 \bar{v}^2 | log ( ----------- ) |4130 * [ vel + eps ]4131 * obs4132 *4133 * dJ 2 * log(...)4134 * DU = - -- = - 4 \bar{v}^2 ------------- u4135 * du vel^2 + eps4136 *4137 */4138 for (i=0;i<NUMVERTICES;i++){4139 velocity_mag=sqrt(pow(vx_list[i],2)+pow(vy_list[i],2))+epsvel; //epsvel to avoid velocity being nil.4140 obs_velocity_mag=sqrt(pow(obs_vx_list[i],2)+pow(obs_vy_list[i],2))+epsvel; //epsvel to avoid observed velocity being nil.4141 scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);4142 dux_list[i]=scale*vx_list[i];4143 duy_list[i]=scale*vy_list[i];4144 }4145 }4146 else if(response==SurfaceAverageVelMisfitEnum){4147 /*We are using an spacially average absolute misfit:4148 *4149 * 1 2 24150 * J = --- sqrt( (u - u ) + (v - v ) )4151 * S obs obs4152 *4153 * dJ 1 14154 * DU = - -- = - --- ----------- * 2 (u - u )4155 * du S 2 sqrt(...) obs4156 */4157 for (i=0;i<NUMVERTICES;i++){4158 scale=1.0/(S*sqrt(pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2))+epsvel);4159 dux_list[i]=scale*(obs_vx_list[i]-vx_list[i]);4160 duy_list[i]=scale*(obs_vy_list[i]-vy_list[i]);4161 }4162 }4163 else if(response==SurfaceLogVxVyMisfitEnum){4164 /*We are using an logarithmic 2 misfit:4165 *4166 * 1 [ |u| + eps 2 |v| + eps 2 ]4167 * J = --- \bar{v}^2 | log ( ----------- ) + log ( ----------- ) |4168 * 2 [ |u |+ eps |v |+ eps ]4169 * obs obs4170 * dJ 1 u 14171 * DU = - -- = - \bar{v}^2 log(u...) --------- ---- ~ - \bar{v}^2 log(u...) ------4172 * du |u| + eps |u| u + eps4173 */4174 for (i=0;i<NUMVERTICES;i++){4175 dux_list[i] = - pow(meanvel,(double)2)*(4176 log((fabs(vx_list[i])+epsvel)/(fabs(obs_vx_list[i])+epsvel)) * 1/(vx_list[i]+epsvel));4177 duy_list[i] = - pow(meanvel,(double)2)*(4178 log((fabs(vy_list[i])+epsvel)/(fabs(obs_vy_list[i])+epsvel)) * 1/(vy_list[i]+epsvel));4179 }4180 }4181 else{4182 /*Not supported yet! : */4183 ISSMERROR("response %s not supported yet",EnumToString(response));4184 }4185 4186 /*Apply weights to DU*/4187 for (i=0;i<NUMVERTICES;i++){4188 dux_list[i]=weights_list[i]*dux_list[i];4189 duy_list[i]=weights_list[i]*duy_list[i];4190 }4191 4192 /* Start looping on the number of gaussian points: */4193 gauss=new GaussTria(2);4194 for(ig=gauss->begin();ig<gauss->end();ig++){4195 4196 gauss->GaussPoint(ig);4197 4198 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);4199 GetNodalFunctions(l1l2l3, gauss);4200 4201 TriaRef::GetParameterValue(&dux, &dux_list[0],gauss);4202 TriaRef::GetParameterValue(&duy, &duy_list[0],gauss);4203 4204 for (i=0;i<NUMVERTICES;i++){4205 pe->values[i*NDOF4+0]+=dux*Jdet*gauss->weight*l1l2l3[i];4206 pe->values[i*NDOF4+1]+=duy*Jdet*gauss->weight*l1l2l3[i];4207 }4208 }4209 4210 /*Clean up and return*/4211 delete gauss;4212 return pe;4213 }4214 /*}}}*/4215 /*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/4216 ElementVector* Tria::CreatePVectorDiagnosticHutter(void){4217 4218 /*Intermediaries */4219 int i,connectivity;4220 double constant_part,ub,vb;4221 double rho_ice,gravity,n,B;4222 double slope2,thickness;4223 double slope[2];4224 GaussTria* gauss=NULL;4225 4226 /*Initialize Element vector and return if necessary*/4227 if(IsOnWater()) return NULL;4228 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);4229 4230 /*Retrieve all inputs and parameters*/4231 rho_ice=matpar->GetRhoIce();4232 gravity=matpar->GetG();4233 n=matice->GetN();4234 B=matice->GetBbar();4235 Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); ISSMASSERT(slopex_input);4236 Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); ISSMASSERT(slopey_input);4237 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);4238 4239 /*Spawn 3 sing elements: */4240 gauss=new GaussTria();4241 for(i=0;i<NUMVERTICES;i++){4242 4243 gauss->GaussVertex(i);4244 4245 connectivity=nodes[i]->GetConnectivity();4246 4247 thickness_input->GetParameterValue(&thickness,gauss);4248 slopex_input->GetParameterValue(&slope[0],gauss);4249 slopey_input->GetParameterValue(&slope[1],gauss);4250 slope2=pow(slope[0],2)+pow(slope[1],2);4251 4252 constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));4253 4254 ub=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[0];4255 vb=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[1];4256 4257 pe->values[2*i] =(ub-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[0])/(double)connectivity;4258 pe->values[2*i+1]=(vb-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[1])/(double)connectivity;4259 }4260 4261 /*Clean up and return*/4262 delete gauss;4263 return pe;4264 }4265 /*}}}*/4266 /*FUNCTION Tria::CreatePVectorPrognostic{{{1*/4267 ElementVector* Tria::CreatePVectorPrognostic(void){4268 4269 switch(GetElementType()){4270 case P1Enum:4271 return CreatePVectorPrognostic_CG();4272 case P1DGEnum:4273 return CreatePVectorPrognostic_DG();4274 default:4275 ISSMERROR("Element type %s not supported yet",EnumToString(GetElementType()));4276 }4277 }4278 /*}}}*/4279 /*FUNCTION Tria::CreatePVectorPrognostic_CG {{{1*/4280 ElementVector* Tria::CreatePVectorPrognostic_CG(void){4281 4282 /*Constants*/4283 const int numdof=NDOF1*NUMVERTICES;4284 4285 /*Intermediaries */4286 int i,j,ig;4287 double Jdettria,dt;4288 double accumulation_g,melting_g,thickness_g;4289 double xyz_list[NUMVERTICES][3];4290 double L[NUMVERTICES];4291 GaussTria* gauss=NULL;4292 4293 /*Initialize Element vector and return if necessary*/4294 if(IsOnWater()) return NULL;4295 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);4296 4297 /*Retrieve all inputs and parameters*/4298 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4299 this->parameters->FindParam(&dt,DtEnum);4300 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input);4301 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input);4302 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);4303 4304 /* Start looping on the number of gaussian points: */4305 gauss=new GaussTria(2);4306 for(ig=gauss->begin();ig<gauss->end();ig++){4307 4308 gauss->GaussPoint(ig);4309 4310 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);4311 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);4312 4313 accumulation_input->GetParameterValue(&accumulation_g,gauss);4314 melting_input->GetParameterValue(&melting_g,gauss);4315 thickness_input->GetParameterValue(&thickness_g,gauss);4316 4317 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];4318 }4319 4320 /*Clean up and return*/4321 delete gauss;4322 return pe;4323 }4324 /*}}}*/4325 /*FUNCTION Tria::CreatePVectorPrognostic_DG {{{1*/4326 ElementVector* Tria::CreatePVectorPrognostic_DG(void){4327 4328 /*Constants*/4329 const int numdof=NDOF1*NUMVERTICES;4330 4331 /*Intermediaries */4332 int i,j,ig;4333 double Jdettria,dt;4334 double accumulation_g,melting_g,thickness_g;4335 double xyz_list[NUMVERTICES][3];4336 double L[NUMVERTICES];4337 GaussTria* gauss=NULL;4338 4339 /*Initialize Element vector and return if necessary*/4340 if(IsOnWater()) return NULL;4341 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);4342 4343 /*Retrieve all inputs and parameters*/4344 this->parameters->FindParam(&dt,DtEnum);4345 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4346 Input* accumulation_input=inputs->GetInput(AccumulationRateEnum); ISSMASSERT(accumulation_input);4347 Input* melting_input=inputs->GetInput(MeltingRateEnum); ISSMASSERT(melting_input);4348 Input* thickness_input=inputs->GetInput(ThicknessEnum); ISSMASSERT(thickness_input);4349 4350 /* Start looping on the number of gaussian points: */4351 gauss=new GaussTria(2);4352 for(ig=gauss->begin();ig<gauss->end();ig++){4353 4354 gauss->GaussPoint(ig);4355 4356 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);4357 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);4358 4359 accumulation_input->GetParameterValue(&accumulation_g,gauss);4360 melting_input->GetParameterValue(&melting_g,gauss);4361 thickness_input->GetParameterValue(&thickness_g,gauss);4362 4363 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];4364 }4365 4366 /*Clean up and return*/4367 delete gauss;4368 return pe;4369 }4370 /*}}}*/4371 /*FUNCTION Tria::CreatePVectorSlope {{{1*/4372 ElementVector* Tria::CreatePVectorSlope(void){4373 4374 /*Constants*/4375 const int numdof=NDOF1*NUMVERTICES;4376 4377 /*Intermediaries */4378 int i,j,ig;4379 int analysis_type;4380 double Jdet;4381 double xyz_list[NUMVERTICES][3];4382 double slope[2];4383 double l1l2l3[3];4384 GaussTria* gauss=NULL;4385 4386 /*Initialize Element vector and return if necessary*/4387 if(IsOnWater()) return NULL;4388 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);4389 4390 /*Retrieve all inputs and parameters*/4391 parameters->FindParam(&analysis_type,AnalysisTypeEnum);4392 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4393 Input* slope_input=NULL;4394 if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==SurfaceSlopeYAnalysisEnum)){4395 slope_input=inputs->GetInput(SurfaceEnum); ISSMASSERT(slope_input);4396 }4397 if ( (analysis_type==BedSlopeXAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){4398 slope_input=inputs->GetInput(BedEnum); ISSMASSERT(slope_input);4399 }4400 4401 /* Start looping on the number of gaussian points: */4402 gauss=new GaussTria(2);4403 for(ig=gauss->begin();ig<gauss->end();ig++){4404 4405 gauss->GaussPoint(ig);4406 4407 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);4408 GetNodalFunctions(l1l2l3, gauss);4409 4410 slope_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);4411 4412 if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==BedSlopeXAnalysisEnum)){4413 for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[0]*l1l2l3[i];4414 }4415 if ( (analysis_type==SurfaceSlopeYAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){4416 for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[1]*l1l2l3[i];4417 }4418 }4419 4420 /*Clean up and return*/4421 delete gauss;4422 return pe;4423 }4424 /*}}}*/4425 /*FUNCTION Tria::CreatePVectorThermalShelf {{{1*/4426 ElementVector* Tria::CreatePVectorThermalShelf(void){4427 4428 /*Constants*/4429 const int numdof=NUMVERTICES*NDOF1;4430 4431 /*Intermediaries */4432 int i,ig;4433 double Jdet;4434 double mixed_layer_capacity,thermal_exchange_velocity;4435 double rho_ice,rho_water,pressure,dt,scalar_ocean;4436 double meltingpoint,beta,heatcapacity,t_pmp;4437 double xyz_list[NUMVERTICES][3];4438 double l1l2l3[NUMVERTICES];4439 GaussTria* gauss=NULL;4440 4441 /*Initialize Element vector and return if necessary*/4442 if(IsOnWater()) return NULL;4443 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);4444 4445 /*Retrieve all inputs and parameters*/4446 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4447 mixed_layer_capacity=matpar->GetMixedLayerCapacity();4448 thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();4449 rho_water=matpar->GetRhoWater();4450 rho_ice=matpar->GetRhoIce();4451 heatcapacity=matpar->GetHeatCapacity();4452 beta=matpar->GetBeta();4453 meltingpoint=matpar->GetMeltingPoint();4454 this->parameters->FindParam(&dt,DtEnum);4455 Input* pressure_input=inputs->GetInput(PressureEnum); ISSMASSERT(pressure_input);4456 4457 /* Start looping on the number of gauss 2d (nodes on the bedrock) */4458 gauss=new GaussTria(2);4459 for(ig=gauss->begin();ig<gauss->end();ig++){4460 4461 gauss->GaussPoint(ig);4462 4463 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss);4464 GetNodalFunctions(&l1l2l3[0], gauss);4465 4466 pressure_input->GetParameterValue(&pressure,gauss);4467 t_pmp=meltingpoint-beta*pressure;4468 4469 scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);4470 if(dt) scalar_ocean=dt*scalar_ocean;4471 4472 for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*l1l2l3[i];4473 }4474 4475 /*Clean up and return*/4476 delete gauss;4477 return pe;4478 }4479 /*}}}*/4480 /*FUNCTION Tria::CreatePVectorThermalSheet {{{1*/4481 ElementVector* Tria::CreatePVectorThermalSheet(void){4482 4483 /*Constants*/4484 const int numdof=NUMVERTICES*NDOF1;4485 4486 /*Intermediaries */4487 int i,ig;4488 int analysis_type,drag_type;4489 double xyz_list[NUMVERTICES][3];4490 double Jdet,dt;4491 double rho_ice,heatcapacity,geothermalflux_value;4492 double basalfriction,alpha2,vx,vy,pressure;4493 double pressure_list[3];4494 double scalar;4495 double l1l2l3[NUMVERTICES];4496 Friction* friction=NULL;4497 GaussTria* gauss=NULL;4498 4499 /*Initialize Element vector and return if necessary*/4500 if(IsOnWater()) return NULL;4501 ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);4502 4503 /*Retrieve all inputs and parameters*/4504 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4505 parameters->FindParam(&analysis_type,AnalysisTypeEnum);4506 rho_ice=matpar->GetRhoIce();4507 heatcapacity=matpar->GetHeatCapacity();4508 this->inputs->GetParameterValue(&dt,DtEnum);4509 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);4510 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);4511 Input* vz_input=inputs->GetInput(VzEnum); ISSMASSERT(vz_input);4512 Input* geothermalflux_input=inputs->GetInput(GeothermalFluxEnum); ISSMASSERT(geothermalflux_input);4513 4514 /*Build frictoin element, needed later: */4515 inputs->GetParameterValue(&drag_type,DragTypeEnum);4516 if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");4517 friction=new Friction("3d",inputs,matpar,analysis_type);4518 4519 /* Start looping on the number of gauss 2d (nodes on the bedrock) */4520 gauss=new GaussTria(2);4521 for(ig=gauss->begin();ig<gauss->end();ig++){4522 4523 gauss->GaussPoint(ig);4524 4525 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss);4526 GetNodalFunctions(&l1l2l3[0], gauss);4527 4528 geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);4529 friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);4530 vx_input->GetParameterValue(&vx,gauss);4531 vy_input->GetParameterValue(&vy,gauss);4532 basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));4533 4534 scalar=gauss->weight*Jdet*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);4535 if(dt) scalar=dt*scalar;4536 4537 for(i=0;i<numdof;i++) pe->values[i]+=scalar*l1l2l3[i];4538 }4539 4540 /*Clean up and return*/4541 delete gauss;4542 delete friction;4543 return pe;4544 }4545 /*}}}*/4546 /*FUNCTION Tria::GetArea {{{1*/4547 double Tria::GetArea(void){4548 4549 double area=0;4550 double xyz_list[NUMVERTICES][3];4551 double x1,y1,x2,y2,x3,y3;4552 4553 /*Get xyz list: */4554 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4555 x1=xyz_list[0][0]; y1=xyz_list[0][1];4556 x2=xyz_list[1][0]; y2=xyz_list[1][1];4557 x3=xyz_list[2][0]; y3=xyz_list[2][1];4558 4559 return (x2*y3 - y2*x3 + x1*y2 - y1*x2 + x3*y1 - y3*x1)/2;4560 }4561 /*}}}*/4562 /*FUNCTION Tria::GetElementType {{{1*/4563 int Tria::GetElementType(){4564 4565 /*return TriaRef field*/4566 return this->element_type;4567 4568 }4569 /*}}}*/4570 /*FUNCTION Tria::GetDofList {{{1*/4571 void Tria::GetDofList(int** pdoflist, int approximation_enum,int setenum){4572 4573 int i,j;4574 int count=0;4575 int numberofdofs=0;4576 int* doflist=NULL;4577 4578 /*First, figure out size of doflist and create it: */4579 for(i=0;i<3;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);4580 doflist=(int*)xmalloc(numberofdofs*sizeof(int));4581 4582 /*Populate: */4583 count=0;4584 for(i=0;i<3;i++){4585 nodes[i]->GetDofList(doflist+count,approximation_enum,setenum);4586 count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);4587 }4588 4589 /*Assign output pointers:*/4590 *pdoflist=doflist;4591 }4592 /*}}}*/4593 /*FUNCTION Tria::GetDofList1 {{{1*/4594 void Tria::GetDofList1(int* doflist){4595 4596 int i;4597 for(i=0;i<3;i++) doflist[i]=nodes[i]->GetDofList1();4598 4599 }4600 /*}}}*/4601 /*FUNCTION Tria::GetSidList {{{1*/4602 void Tria::GetSidList(int* sidlist){4603 4604 int i;4605 for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList();4606 4607 }4608 /*}}}*/4609 /*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/4610 void Tria::GetParameterListOnVertices(double* pvalue,int enumtype){4611 4612 /*Intermediaries*/4613 double value[NUMVERTICES];4614 GaussTria *gauss = NULL;4615 4616 /*Recover input*/4617 Input* input=inputs->GetInput(enumtype);4618 if (!input) ISSMERROR("Input %s not found in element",EnumToString(enumtype));4619 4620 /*Checks in debugging mode*/4621 ISSMASSERT(pvalue);4622 4623 /* Start looping on the number of vertices: */4624 gauss=new GaussTria();4625 for (int iv=0;iv<NUMVERTICES;iv++){4626 gauss->GaussVertex(iv);4627 input->GetParameterValue(&pvalue[iv],gauss);4628 }4629 4630 /*clean-up*/4631 delete gauss;4632 }4633 /*}}}*/4634 /*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/4635 void Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){4636 4637 double value[NUMVERTICES];4638 GaussTria *gauss = NULL;4639 Input *input = inputs->GetInput(enumtype);4640 4641 /*Checks in debugging mode*/4642 ISSMASSERT(pvalue);4643 4644 /* Start looping on the number of vertices: */4645 if (input){4646 gauss=new GaussTria();4647 for (int iv=0;iv<NUMVERTICES;iv++){4648 gauss->GaussVertex(iv);4649 input->GetParameterValue(&pvalue[iv],gauss);4650 }4651 }4652 else{4653 for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;4654 }4655 4656 /*clean-up*/4657 delete gauss;4658 }4659 /*}}}*/4660 /*FUNCTION Tria::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/4661 void Tria::GetParameterValue(double* pvalue,Node* node,int enumtype){4662 4663 Input* input=inputs->GetInput(enumtype);4664 if(!input) ISSMERROR("No input of type %s found in tria",EnumToString(enumtype));4665 4666 GaussTria* gauss=new GaussTria();4667 gauss->GaussVertex(this->GetNodeIndex(node));4668 4669 input->GetParameterValue(pvalue,gauss);4670 delete gauss;4671 }4672 /*}}}*/4673 /*FUNCTION Tria::GetSolutionFromInputsDiagnosticHoriz{{{1*/4674 void Tria::GetSolutionFromInputsDiagnosticHoriz(Vec solution){4675 4676 const int numdof=NDOF2*NUMVERTICES;4677 4678 int i;4679 int* doflist=NULL;4680 double vx,vy;4681 double values[numdof];4682 GaussTria* gauss=NULL;4683 4684 /*Get dof list: */4685 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4686 4687 /*Get inputs*/4688 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);4689 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);4690 4691 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4692 /*P1 element only for now*/4693 gauss=new GaussTria();4694 for(i=0;i<NUMVERTICES;i++){4695 4696 gauss->GaussVertex(i);4697 4698 /*Recover vx and vy*/4699 vx_input->GetParameterValue(&vx,gauss);4700 vy_input->GetParameterValue(&vy,gauss);4701 values[i*NDOF2+0]=vx;4702 values[i*NDOF2+1]=vy;4703 }4704 4705 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);4706 4707 /*Free ressources:*/4708 delete gauss;4709 xfree((void**)&doflist);4710 }4711 /*}}}*/4712 /*FUNCTION Tria::GetSolutionFromInputsDiagnosticHutter{{{1*/4713 void Tria::GetSolutionFromInputsDiagnosticHutter(Vec solution){4714 4715 const int numdof=NDOF2*NUMVERTICES;4716 4717 int i,dummy;4718 int* doflist=NULL;4719 double vx,vy;4720 double values[numdof];4721 GaussTria* gauss=NULL;4722 4723 /*Get dof list: */4724 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4725 4726 /*Get inputs*/4727 Input* vx_input=inputs->GetInput(VxEnum); ISSMASSERT(vx_input);4728 Input* vy_input=inputs->GetInput(VyEnum); ISSMASSERT(vy_input);4729 4730 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4731 /*P1 element only for now*/4732 gauss=new GaussTria();4733 for(i=0;i<NUMVERTICES;i++){4734 4735 gauss->GaussVertex(i);4736 4737 /*Recover vx and vy*/4738 vx_input->GetParameterValue(&vx,gauss);4739 vy_input->GetParameterValue(&vy,gauss);4740 values[i*NDOF2+0]=vx;4741 values[i*NDOF2+1]=vy;4742 }4743 4744 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);4745 4746 /*Free ressources:*/4747 delete gauss;4748 xfree((void**)&doflist);4749 }4750 /*}}}*/4751 /*FUNCTION Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){{{1*/4752 void Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){4753 /*Compute the 2d Strain Rate (3 components):4754 * epsilon=[exx eyy exy] */4755 4756 int i;4757 double epsilonvx[3];4758 double epsilonvy[3];4759 4760 /*Check that both inputs have been found*/4761 if (!vx_input || !vy_input){4762 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input);4763 }4764 4765 /*Get strain rate assuming that epsilon has been allocated*/4766 vx_input->GetVxStrainRate2d(epsilonvx,xyz_list,gauss);4767 vy_input->GetVyStrainRate2d(epsilonvy,xyz_list,gauss);4768 4769 /*Sum all contributions*/4770 for(i=0;i<3;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];4771 }4772 /*}}}*/4773 /*FUNCTION Tria::GradjDragStokes {{{1*/4774 void Tria::GradjDragStokes(Vec gradient){4775 4776 int i,ig;4777 int drag_type,analysis_type;4778 int doflist1[NUMVERTICES];4779 double bed,thickness,Neff;4780 double lambda,mu,xi,Jdet,vx,vy,vz;4781 double alpha_complement,drag,cm_noisedmp;4782 double surface_normal[3],bed_normal[3];4783 double xyz_list[NUMVERTICES][3];4784 double dh1dh3[NDOF2][NUMVERTICES];4785 double dk[NDOF2];4786 double l1l2l3[3];4787 double epsilon[3]; /* epsilon=[exx,eyy,exy];*/4788 double grade_g[NUMVERTICES]={0.0};4789 double grade_g_gaussian[NUMVERTICES];4790 Friction* friction=NULL;4791 GaussTria* gauss=NULL;4792 4793 /*retrive parameters: */4794 parameters->FindParam(&analysis_type,AnalysisTypeEnum);4795 4796 /*retrieve inputs :*/4797 inputs->GetParameterValue(&drag_type,DragTypeEnum);4798 Input* drag_input =inputs->GetInput(DragCoefficientEnum); ISSMASSERT(drag_input);4799 Input* vx_input =inputs->GetInput(VxEnum); ISSMASSERT(vx_input);4800 Input* vy_input =inputs->GetInput(VyEnum); ISSMASSERT(vy_input);4801 Input* vz_input =inputs->GetInput(VzEnum); ISSMASSERT(vz_input);4802 Input* adjointx_input=inputs->GetInput(AdjointxEnum); ISSMASSERT(adjointx_input);4803 Input* adjointy_input=inputs->GetInput(AdjointyEnum); ISSMASSERT(adjointy_input);4804 Input* adjointz_input=inputs->GetInput(AdjointzEnum); ISSMASSERT(adjointz_input);4805 4806 /*retrieve some parameters: */4807 this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);4808 4809 /*Get out if shelf*/4810 if(IsOnShelf())return;4811 4812 /* Get node coordinates and dof list: */4813 GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);4814 GetDofList1(&doflist1[0]);4815 4816 /*Build frictoin element, needed later: */4817 inputs->GetParameterValue(&drag_type,DragTypeEnum);4818 friction=new Friction("2d",inputs,matpar,analysis_type);4819 4820 /* Start looping on the number of gaussian points: */4821 gauss=new GaussTria(4);4822 for(ig=gauss->begin();ig<gauss->end();ig++){4823 4824 gauss->GaussPoint(ig);4825 4826 /*Recover alpha_complement and drag: */4827 if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum);4828 else alpha_complement=0;4829 drag_input->GetParameterValue(&drag,gauss);4830 4831 /*recover lambda mu and xi: */4832 adjointx_input->GetParameterValue(&lambda,gauss);4833 adjointy_input->GetParameterValue(&mu ,gauss);4834 adjointz_input->GetParameterValue(&xi ,gauss);4835 4836 /*recover vx vy and vz: */4837 vx_input->GetParameterValue(&vx, gauss);4838 vy_input->GetParameterValue(&vy, gauss);4839 vz_input->GetParameterValue(&vz, gauss);4840 4841 /*Get normal vector to the bed */4842 SurfaceNormal(&surface_normal[0],xyz_list);4843 4844 bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result4845 bed_normal[1]=-surface_normal[1];4846 bed_normal[2]=-surface_normal[2];4847 4848 /* Get Jacobian determinant: */4849 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss);4850 4851 /* Get nodal functions value at gaussian point:*/4852 GetNodalFunctions(l1l2l3, gauss);4853 4854 /*Get nodal functions derivatives*/4855 GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss);4856 4857 /*Get k derivative: dk/dx */4858 drag_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);4859 4860 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */4861 for (i=0;i<NUMVERTICES;i++){4862 //standard gradient dJ/dki4863 grade_g_gaussian[i]=(4864 -lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))4865 -mu *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))4866 -xi *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))4867 )*Jdet*gauss->weight*l1l2l3[i];4868 4869 //Add regularization term4870 grade_g_gaussian[i]+= - cm_noisedmp*Jdet*gauss->weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]);4871 }4872 4873 /*Add gradje_g_gaussian vector to gradje_g: */4874 for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i];4875 }4876 4877 VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);4878 4879 delete friction;4880 delete gauss;4881 }4882 /*}}}*/4883 /*FUNCTION Tria::InputUpdateFromSolutionAdjointBalancedthickness {{{1*/4884 void Tria::InputUpdateFromSolutionAdjointBalancedthickness(double* solution){4885 4886 const int numdof=NDOF1*NUMVERTICES;4887 4888 int i;4889 int* doflist=NULL;4890 double values[numdof];4891 double lambda[NUMVERTICES];4892 4893 /*Get dof list: */4894 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4895 4896 /*Use the dof list to index into the solution vector: */4897 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];4898 4899 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4900 for(i=0;i<numdof;i++) lambda[i]=values[i];4901 4902 /*Add vx and vy as inputs to the tria element: */4903 this->inputs->AddInput(new TriaVertexInput(AdjointEnum,lambda));4904 4905 /*Free ressources:*/4906 xfree((void**)&doflist);4907 }4908 /*}}}*/4909 /*FUNCTION Tria::InputUpdateFromSolutionAdjointHoriz {{{1*/4910 void Tria::InputUpdateFromSolutionAdjointHoriz(double* solution){4911 4912 const int numdof=NDOF2*NUMVERTICES;4913 4914 int i;4915 int* doflist=NULL;4916 double values[numdof];4917 double lambdax[NUMVERTICES];4918 double lambday[NUMVERTICES];4919 4920 /*Get dof list: */4921 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4922 4923 /*Use the dof list to index into the solution vector: */4924 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];4925 4926 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4927 for(i=0;i<NUMVERTICES;i++){4928 lambdax[i]=values[i*NDOF2+0];4929 lambday[i]=values[i*NDOF2+1];4930 }4931 4932 /*Add vx and vy as inputs to the tria element: */4933 this->inputs->AddInput(new TriaVertexInput(AdjointxEnum,lambdax));4934 this->inputs->AddInput(new TriaVertexInput(AdjointyEnum,lambday));4935 4936 /*Free ressources:*/4937 xfree((void**)&doflist);4938 }4939 /*}}}*/4940 /*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHoriz {{{1*/4941 void Tria::InputUpdateFromSolutionDiagnosticHoriz(double* solution){4942 4943 const int numdof=NDOF2*NUMVERTICES;4944 4945 int i;4946 int dummy;4947 int* doflist=NULL;4948 double rho_ice,g;4949 double values[numdof];4950 double vx[NUMVERTICES];4951 double vy[NUMVERTICES];4952 double vz[NUMVERTICES];4953 double vel[NUMVERTICES];4954 double pressure[NUMVERTICES];4955 double thickness[NUMVERTICES];4956 4957 /*Get dof list: */4958 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);4959 4960 /*Use the dof list to index into the solution vector: */4961 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];4962 4963 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */4964 for(i=0;i<NUMVERTICES;i++){4965 vx[i]=values[i*NDOF2+0];4966 vy[i]=values[i*NDOF2+1];4967 }4968 4969 /*Get Vz and compute vel*/4970 GetParameterListOnVertices(&vz[0],VzEnum,0);4971 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);4972 4973 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D,4974 *so the pressure is just the pressure at the bedrock: */4975 rho_ice=matpar->GetRhoIce();4976 g=matpar->GetG();4977 GetParameterListOnVertices(&thickness[0],ThicknessEnum);4978 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];4979 4980 /*Now, we have to move the previous Vx and Vy inputs to old4981 * status, otherwise, we'll wipe them off: */4982 this->inputs->ChangeEnum(VxEnum,VxOldEnum);4983 this->inputs->ChangeEnum(VyEnum,VyOldEnum);4984 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);4985 4986 /*Add vx and vy as inputs to the tria element: */4987 this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));4988 this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));4989 this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));4990 this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));4991 4992 /*Free ressources:*/4993 xfree((void**)&doflist);4994 4995 }4996 /*}}}*/4997 /*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHutter {{{1*/4998 void Tria::InputUpdateFromSolutionDiagnosticHutter(double* solution){4999 5000 const int numdof=NDOF2*NUMVERTICES;5001 5002 int i;5003 int dummy;5004 int* doflist=NULL;5005 double rho_ice,g;5006 double values[numdof];5007 double vx[NUMVERTICES];5008 double vy[NUMVERTICES];5009 double vz[NUMVERTICES];5010 double vel[NUMVERTICES];5011 double pressure[NUMVERTICES];5012 double thickness[NUMVERTICES];5013 double* vz_ptr=NULL;5014 Input* vz_input=NULL;5015 5016 /*Get dof list: */5017 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5018 5019 /*Use the dof list to index into the solution vector: */5020 for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];5021 5022 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */5023 for(i=0;i<NUMVERTICES;i++){5024 vx[i]=values[i*NDOF2+0];5025 vy[i]=values[i*NDOF2+1];5026 }5027 5028 /*Get Vz*/5029 vz_input=inputs->GetInput(VzEnum);5030 if (vz_input){5031 if (vz_input->Enum()!=TriaVertexInputEnum){5032 ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumToString(vz_input->Enum()));5033 }5034 vz_input->GetValuesPtr(&vz_ptr,&dummy);5035 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];5036 }5037 else{5038 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;5039 }5040 5041 /*Now Compute vel*/5042 for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);5043 5044 /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D,5045 *so the pressure is just the pressure at the bedrock: */5046 rho_ice=matpar->GetRhoIce();5047 g=matpar->GetG();5048 GetParameterListOnVertices(&thickness[0],ThicknessEnum);5049 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];5050 5051 /*Now, we have to move the previous Vx and Vy inputs to old5052 * status, otherwise, we'll wipe them off: */5053 this->inputs->ChangeEnum(VxEnum,VxOldEnum);5054 this->inputs->ChangeEnum(VyEnum,VyOldEnum);5055 this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);5056 5057 /*Add vx and vy as inputs to the tria element: */5058 this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));5059 this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));5060 this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));5061 this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));5062 5063 /*Free ressources:*/5064 xfree((void**)&doflist);5065 }5066 /*}}}*/5067 /*FUNCTION Tria::InputUpdateFromSolutionOneDof{{{1*/5068 void Tria::InputUpdateFromSolutionOneDof(double* solution,int enum_type){5069 5070 const int numdof = NDOF1*NUMVERTICES;5071 5072 int* doflist=NULL;5073 double values[numdof];5074 5075 /*Get dof list: */5076 GetDofList(&doflist,NoneApproximationEnum,GsetEnum);5077 5078 /*Use the dof list to index into the solution vector: */5079 for(int i=0;i<numdof;i++) values[i]=solution[doflist[i]];5080 5081 /*Add input to the element: */5082 this->inputs->AddInput(new TriaVertexInput(enum_type,values));5083 5084 /*Free ressources:*/5085 xfree((void**)&doflist);5086 }5087 /*}}}*/5088 /*FUNCTION Tria::IsInput{{{1*/5089 bool Tria::IsInput(int name){5090 if (5091 name==ThicknessEnum ||5092 name==SurfaceEnum ||5093 name==BedEnum ||5094 name==SurfaceSlopeXEnum ||5095 name==SurfaceSlopeYEnum ||5096 name==MeltingRateEnum ||5097 name==DtEnum ||5098 name==AccumulationRateEnum ||5099 name==SurfaceAreaEnum||5100 name==VxEnum ||5101 name==VyEnum ||5102 name==VxObsEnum ||5103 name==VyObsEnum ||5104 name==CmResponseEnum ||5105 name==DragCoefficientEnum ||5106 name==GradientEnum ||5107 name==OldGradientEnum5108 ){5109 return true;5110 }5111 else return false;5112 }5113 /*}}}*/5114 /*FUNCTION Tria::SetClone {{{1*/5115 void Tria::SetClone(int* minranks){5116 5117 ISSMERROR("not implemented yet");5118 }5119 /*}}}1*/5120 /*FUNCTION Tria::SurfaceNormal{{{1*/5121 void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){5122 5123 int i;5124 double v13[3],v23[3];5125 double normal[3];5126 double normal_norm;5127 5128 for (i=0;i<3;i++){5129 v13[i]=xyz_list[0][i]-xyz_list[2][i];5130 v23[i]=xyz_list[1][i]-xyz_list[2][i];5131 }5132 5133 normal[0]=v13[1]*v23[2]-v13[2]*v23[1];5134 normal[1]=v13[2]*v23[0]-v13[0]*v23[2];5135 normal[2]=v13[0]*v23[1]-v13[1]*v23[0];5136 5137 normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );5138 5139 *(surface_normal)=normal[0]/normal_norm;5140 *(surface_normal+1)=normal[1]/normal_norm;5141 *(surface_normal+2)=normal[2]/normal_norm;5142 }5143 /*}}}*/ -
issm/trunk/src/c/objects/Elements/Tria.h
r6238 r6410 166 166 void GetDofList(int** pdoflist,int approximation_enum,int setenum); 167 167 void GetDofList1(int* doflist); 168 void 168 void GetSidList(int* sidlist); 169 169 void GetParameterListOnVertices(double* pvalue,int enumtype); 170 170 void GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
Note:
See TracChangeset
for help on using the changeset viewer.