Changeset 21802
- Timestamp:
- 07/17/17 21:18:32 (8 years ago)
- Location:
- issm/trunk-jpl/src
- Files:
-
- 3 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/Makefile.am
r21623 r21802 47 47 ./bamg/Mesh.cpp\ 48 48 ./shared/Bamg/BigPrimeNumber.cpp\ 49 ./classes/AmrBamg.cpp\ 49 50 ./modules/Bamgx/Bamgx.cpp\ 50 51 ./modules/BamgConvertMeshx/BamgConvertMeshx.cpp\ -
issm/trunk-jpl/src/c/bamg/BamgOpts.cpp
r18064 r21802 5 5 BamgOpts::BamgOpts(){/*{{{*/ 6 6 7 this->anisomax =0;8 this->cutoff =0;9 this->coeff =0;10 this->errg =0;11 this->gradation =0;12 this->Hessiantype =0;13 this->MaxCornerAngle =0;14 this->maxnbv =0;15 this->maxsubdiv =0;16 this->Metrictype =0;17 this->nbjacobi =0;18 this->nbsmooth =0;19 this->omega =0;20 this->power =0;21 this->random =0;22 this->verbose =0;7 this->anisomax = 0; 8 this->cutoff = 0; 9 this->coeff = 0; 10 this->errg = 0; 11 this->gradation = 0; 12 this->Hessiantype = 0; 13 this->MaxCornerAngle = 0; 14 this->maxnbv = 0; 15 this->maxsubdiv = 0; 16 this->Metrictype = 0; 17 this->nbjacobi = 0; 18 this->nbsmooth = 0; 19 this->omega = 0; 20 this->power = 0; 21 this->random = 0; 22 this->verbose = 0; 23 23 24 this->Crack =0;25 this->geometricalmetric =0;26 this->KeepVertices =0;27 this->splitcorners =0;24 this->Crack = 0; 25 this->geometricalmetric = 0; 26 this->KeepVertices = 0; 27 this->splitcorners = 0; 28 28 29 this->hmin =0;30 this->hmax =0;29 this->hmin = 0; 30 this->hmax = 0; 31 31 this->hminVertices=NULL; this->hminVerticesSize[0]=this->hminVerticesSize[1]=0; 32 32 this->hmaxVertices=NULL; this->hmaxVerticesSize[0]=this->hmaxVerticesSize[1]=0; -
issm/trunk-jpl/src/c/bamg/Mesh.cpp
r21791 r21802 698 698 for (i=0;i<nbsubdomains;i++){ 699 699 bamgmesh->SubDomains[i*4+0]=3; 700 bamgmesh->SubDomains[i*4+1]=reft[GetId(subdomains[i].head)] ;700 bamgmesh->SubDomains[i*4+1]=reft[GetId(subdomains[i].head)]+1;//MATLAB indexing 701 701 bamgmesh->SubDomains[i*4+2]=1; 702 702 bamgmesh->SubDomains[i*4+3]=subdomains[i].ReferenceNumber; … … 3076 3076 IssmDouble area_3 =((bv.r.x -(*tcvj)(1)->r.x)*((*tcvj)(0)->r.y-(*tcvj)(1)->r.y) 3077 3077 - (bv.r.y -(*tcvj)(1)->r.y)*((*tcvj)(0)->r.x-(*tcvj)(1)->r.x)); 3078 if(area_1<0 || area_2<0 || area_3<0){3079 pointsoutside = true;3080 continue;3081 }3078 // if(area_1<0 || area_2<0 || area_3<0){ 3079 // pointsoutside = true; 3080 // continue; 3081 // } 3082 3082 if(!bv.GeomEdgeHook){ 3083 3083 vertices[nbv].r = bv.r; … … 3086 3086 } 3087 3087 } 3088 if(pointsoutside) _printf_("WARNING: One or more points of the initial mesh fall outside of the geometric boundary\n");3088 //if(pointsoutside) _printf_("WARNING: One or more points of the initial mesh fall outside of the geometric boundary\n"); 3089 3089 Bh.CreateSingleVertexToTriangleConnectivity(); 3090 3090 InsertNewPoints(nbvold,NbTSwap,bamgopts->random); -
issm/trunk-jpl/src/c/classes/FemModel.cpp
r21799 r21802 45 45 46 46 /*configuration: */ 47 int solution_type ;47 int solution_type,amrtype,amr_frequency; 48 48 int ierr; 49 49 … … 80 80 this->parameters->AddObject(new GenericParam<ISSM_MPI_Comm>(incomm,FemModelCommEnum)); 81 81 82 #ifdef _HAVE_NEOPZ_ 83 this->InitializeAdaptiveRefinement(); 84 #endif 82 /*AMR stuff*/ 83 this->parameters->FindParam(&amr_frequency,TransientAmrFrequencyEnum); 84 if(amr_frequency){ 85 this->parameters->FindParam(&amrtype,AmrTypeEnum); 86 switch(amrtype){ 87 88 #ifdef _HAVE_NEOPZ_ 89 case AmrNeopzEnum: this->InitializeAdaptiveRefinementNeopz(); break; 90 #endif 91 92 #ifdef _HAVE_BAMG_ 93 case AmrBamgEnum: this->InitializeAdaptiveRefinementBamg(); break; 94 #endif 95 96 default: _error_("not implemented yet"); 97 } 98 } 85 99 86 100 /*Free resources */ … … 140 154 #ifdef _HAVE_NEOPZ_ 141 155 if(amr)delete amr; 156 #endif 157 158 #ifdef _HAVE_BAMG_ 159 if(amrbamg)delete amrbamg; 142 160 #endif 143 161 … … 1502 1520 } 1503 1521 /*}}}*/ 1522 void FemModel::ReMesh(void){/*{{{*/ 1523 1524 /*Intermediaries*/ 1525 IssmDouble *newx = NULL; 1526 IssmDouble *newy = NULL; 1527 IssmDouble *newz = NULL; 1528 int *newelementslist = NULL; 1529 int newnumberofvertices = -1; 1530 int newnumberofelements = -1; 1531 bool* my_elements = NULL; 1532 int* my_vertices = NULL; 1533 int elementswidth = this->GetElementsWidth();//just tria elements in this version 1534 int amrtype; 1535 1536 /*Branch to specific amr depending on requested method*/ 1537 parameters->FindParam(&amrtype,AmrTypeEnum); 1538 switch(amrtype){ 1539 #ifdef _HAVE_NEOPZ_ 1540 case AmrNeopzEnum: this->ReMeshNeopz(&newnumberofvertices,&newnumberofelements,&newx,&newy,&newz,&newelementslist); break; 1541 #endif 1542 1543 #ifdef _HAVE_BAMG_ 1544 case AmrBamgEnum: this->ReMeshBamg(&newnumberofvertices,&newnumberofelements,&newx,&newy,&newz,&newelementslist); break; 1545 #endif 1546 1547 default: _error_("not implemented yet"); 1548 } 1549 1550 /*Partitioning the new mesh. Maybe ElementsAndVerticesPartitioning.cpp could be modified to set this without iomodel.*/ 1551 this->ElementsAndVerticesPartitioning(newnumberofvertices,newnumberofelements,elementswidth,newelementslist,&my_elements,&my_vertices); 1552 1553 if(this->loads->Size()!=0) _error_("not supported yet"); 1554 1555 /*Create vertices*/ 1556 Vertices* new_vertices=new Vertices(); 1557 this->CreateVertices(newnumberofvertices,newnumberofelements,elementswidth,newelementslist,my_vertices,newx,newy,newz,new_vertices); 1558 1559 /*Creating elements*/ 1560 /*Just Tria in this version*/ 1561 Elements* new_elements=new Elements(); 1562 this->CreateElements(newnumberofelements,elementswidth,newelementslist,my_elements,new_elements); 1563 1564 /*Creating materials*/ 1565 Materials* new_materials=new Materials(); 1566 this->CreateMaterials(newnumberofelements,my_elements,new_materials); 1567 1568 /*Creating nodes and constraints*/ 1569 /*Just SSA (2D) and P1 in this version*/ 1570 Nodes* new_nodes=new Nodes(); 1571 Constraints* new_constraints=new Constraints(); 1572 1573 int nodecounter=0; 1574 int constraintcounter=0; 1575 for(int i=0;i<this->nummodels;i++){//create nodes for each analysis in analysis_type_list 1576 1577 int analysis_enum = this->analysis_type_list[i]; 1578 1579 /*As the domain is 2D, it is not necessary to create nodes for this analysis*/ 1580 /*itapopo must verify if domain is not 3D. Only 2D in this version!*/ 1581 if(analysis_enum==StressbalanceVerticalAnalysisEnum) continue; 1582 1583 this->CreateNodes(newnumberofvertices,my_vertices,nodecounter,analysis_enum,new_nodes); 1584 if(analysis_enum==StressbalanceAnalysisEnum) this->CreateConstraints(newnumberofvertices,newnumberofelements,nodecounter,constraintcounter,newx,newy,my_vertices,new_constraints); 1585 this->UpdateElements(newnumberofelements,newelementslist,my_elements,nodecounter,i,new_elements); 1586 1587 if(new_nodes->Size()) nodecounter=new_nodes->MaximumId(); 1588 constraintcounter = new_constraints->NumberOfConstraints(); 1589 /*Make sure nodecounter is at least 0 (if no node exists, maxid will be -1*/ 1590 _assert_(nodecounter>=0); 1591 } 1592 1593 new_elements->Presort(); 1594 new_nodes->Presort(); 1595 new_vertices->Presort(); 1596 this->loads->Presort(); 1597 new_materials->Presort(); 1598 new_constraints->Presort(); 1599 1600 /*reset hooks for elements, loads and nodes: */ 1601 new_elements->ResetHooks(); 1602 this->loads->ResetHooks(); 1603 new_materials->ResetHooks(); 1604 1605 /*do the post-processing of the datasets to get an FemModel that can actually run analyses: */ 1606 int analysis_type; 1607 for(int i=0;i<this->nummodels;i++){ 1608 analysis_type=this->analysis_type_list[i]; 1609 //SetCurrentConfiguration(analysis_type); 1610 1611 this->analysis_counter=i; 1612 /*Now, plug analysis_counter and analysis_type inside the parameters: */ 1613 this->parameters->SetParam(this->analysis_counter,AnalysisCounterEnum); 1614 this->parameters->SetParam(analysis_type,AnalysisTypeEnum); 1615 this->parameters->SetParam(analysis_type,ConfigurationTypeEnum); 1616 1617 /*configure elements, loads and nodes, for this new analysis: */ 1618 new_elements->SetCurrentConfiguration(new_elements,this->loads,new_nodes,new_vertices,new_materials,this->parameters); 1619 this->loads->SetCurrentConfiguration(new_elements,this->loads,new_nodes,new_vertices,new_materials,this->parameters); 1620 1621 /*take care of toolkits options, that depend on this analysis type (present only after model processor)*/ 1622 if(this->parameters->Exist(ToolkitsOptionsStringsEnum)){ 1623 ToolkitsOptionsFromAnalysis(this->parameters,analysis_type); 1624 if(VerboseSolver()) _printf0_(" toolkits Options set for analysis type: " << EnumToStringx(analysis_type) << "\n"); 1625 } 1626 1627 ConfigureObjectsx(new_elements,this->loads,new_nodes,new_vertices,new_materials,this->parameters); 1628 if(i==0){ 1629 VerticesDofx(new_vertices,this->parameters); //only call once, we only have one set of vertices 1630 } 1631 SpcNodesx(new_nodes,new_constraints,this->parameters,analysis_type); 1632 NodesDofx(new_nodes,this->parameters,analysis_type); 1633 } 1634 1635 /*Finally: interpolate all inputs and insert them into the new elements.*/ 1636 this->InterpolateInputs(new_vertices,new_elements); 1637 1638 /*Delete old structure and set new pointers*/ 1639 delete this->vertices; this->vertices = new_vertices; 1640 delete this->elements; this->elements = new_elements; 1641 delete this->nodes; this->nodes = new_nodes; 1642 delete this->constraints; this->constraints = new_constraints; 1643 delete this->materials; this->materials = new_materials; 1644 1645 GetMaskOfIceVerticesLSMx(this); 1646 1647 /*Insert MISMIP+ bed topography*/ 1648 if(false) this->BedrockFromMismipPlus(); 1649 1650 /*Adjust base, thickness and mask grounded ice leve set*/ 1651 if(true) this->AdjustBaseThicknessAndMask(); 1652 1653 /*Reset current configuration: */ 1654 analysis_type=this->analysis_type_list[this->analysis_counter]; 1655 SetCurrentConfiguration(analysis_type); 1656 1657 /*Cleanup*/ 1658 xDelete<IssmDouble>(newx); 1659 xDelete<IssmDouble>(newy); 1660 xDelete<IssmDouble>(newz); 1661 xDelete<int>(newelementslist); 1662 xDelete<int>(my_vertices); 1663 xDelete<bool>(my_elements); 1664 } 1665 /*}}}*/ 1504 1666 void FemModel::RequestedDependentsx(void){/*{{{*/ 1505 1667 … … 2234 2396 } 2235 2397 /*}}}*/ 2236 #ifdef _HAVE_DAKOTA_ 2237 void FemModel::DakotaResponsesx(double* d_responses,char** responses_descriptors,int numresponsedescriptors,int d_numresponses){/*{{{*/ 2238 2239 int i,j; 2240 int my_rank; 2241 2242 /*intermediary: */ 2243 char root[50]; 2244 int index; 2245 int npart; 2246 double femmodel_response; 2247 int flag; 2248 double *vertex_response = NULL; 2249 double *qmu_response = NULL; 2250 double *responses_pointer = NULL; 2251 2252 /*retrieve npart: */ 2253 parameters->FindParam(&npart,QmuNumberofpartitionsEnum); 2254 my_rank=IssmComm::GetRank(); 2255 2256 /*save the d_responses pointer: */ 2257 responses_pointer=d_responses; 2258 2259 //watch out, we have more d_numresponses than numresponsedescriptors, because the responses have been expanded if they were scaled. 2260 //because we don't know the d_responses descriptors (the scaled ones) we can't key off them, so we will key off the responses_descriptors: */ 2261 2262 for(i=0;i<numresponsedescriptors;i++){ 2263 2264 flag=DescriptorIndex(root,&index,responses_descriptors[i]); 2265 2266 if(flag==ScaledEnum){ 2267 2268 /*this response was scaled. pick up the response from the inputs: */ 2269 GetVectorFromInputsx(&vertex_response,this, StringToEnumx(root),VertexPIdEnum); 2270 2271 /*Now, average it onto the partition nodes: */ 2272 AverageOntoPartitionx(&qmu_response,elements,nodes,vertices,loads,materials,parameters,vertex_response); 2273 2274 /*Copy onto our dakota responses: */ 2275 if(my_rank==0){ 2276 /*plug response: */ 2277 for(j=0;j<npart;j++)responses_pointer[j]=qmu_response[j]; 2278 2279 /*increment response_pointer :*/ 2280 responses_pointer+=npart; 2281 } 2282 2283 /*Free ressources:*/ 2284 xDelete<double>(vertex_response); 2285 xDelete<double>(qmu_response); 2286 2287 } 2288 else if (flag==IndexedEnum){ 2289 2290 /*indexed response: plug index into parameters and call response module: */ 2291 parameters->SetParam(index,IndexEnum); 2292 2293 this->Responsex(&femmodel_response,root); 2294 2295 if(my_rank==0){ 2296 /*plug response: */ 2297 responses_pointer[0]=femmodel_response; 2298 2299 /*increment response_pointer :*/ 2300 responses_pointer++; 2301 } 2302 } 2303 else if (flag==NodalEnum){ 2304 _error_("nodal response functions not supported yet!"); 2305 2306 /*increment response_pointer :*/ 2307 responses_pointer++; 2308 } 2309 else if (flag==RegularEnum){ 2310 2311 /*perfectly normal response function: */ 2312 this->Responsex(&femmodel_response,root); 2313 2314 if(my_rank==0){ 2315 /*plug response: */ 2316 responses_pointer[0]=femmodel_response; 2317 2318 /*increment response_pointer :*/ 2319 responses_pointer++; 2320 } 2321 } 2322 else _error_("flag type " << flag << " not supported yet for response analysis"); 2323 } 2324 2325 /*Synthesize echo: {{{*/ 2326 if(my_rank==0){ 2327 _printf_(" responses: " << d_numresponses << ": "); 2328 for(i=0;i<d_numresponses-1;i++)_printf_(d_responses[i] << "|"); 2329 _printf_(d_responses[d_numresponses-1]); 2330 _printf_("\n"); 2331 } 2332 /*}}}*/ 2333 2334 } 2335 /*}}}*/ 2336 #endif 2337 #ifdef _HAVE_GIAIVINS_ 2338 void FemModel::Deflection(Vector<IssmDouble>* wg,Vector<IssmDouble>* dwgdt, IssmDouble* x, IssmDouble* y){ /*{{{*/ 2339 2340 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 2341 for(int i=0;i<elements->Size();i++){ 2342 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2343 element->GiaDeflection(wg,dwgdt, x,y); 2344 } 2345 } 2346 /*}}}*/ 2347 #endif 2348 #ifdef _HAVE_ESA_ 2349 void FemModel::EsaGeodetic2D(Vector<IssmDouble>* pUp, Vector<IssmDouble>* pNorth, Vector<IssmDouble>* pEast, IssmDouble* xx, IssmDouble* yy){/*{{{*/ 2350 2351 int ns,nsmax; 2352 2353 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 2354 ns = elements->Size(); 2355 2356 /*Figure out max of ns: */ 2357 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 2358 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 2359 2360 /*Call the esa geodetic core: */ 2361 for(int i=0;i<nsmax;i++){ 2362 if(i<ns){ 2363 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2364 element->EsaGeodetic2D(pUp,pNorth,pEast,xx,yy); 2365 } 2366 if(i%100==0){ 2367 pUp->Assemble(); 2368 pNorth->Assemble(); 2369 pEast->Assemble(); 2370 } 2371 } 2372 2373 /*One last time: */ 2374 pUp->Assemble(); 2375 pNorth->Assemble(); 2376 pEast->Assemble(); 2377 2378 /*Free ressources:*/ 2379 xDelete<IssmDouble>(xx); 2380 xDelete<IssmDouble>(yy); 2381 } 2382 /*}}}*/ 2383 void FemModel::EsaGeodetic3D(Vector<IssmDouble>* pUp, Vector<IssmDouble>* pNorth, Vector<IssmDouble>* pEast, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius, IssmDouble* xx, IssmDouble* yy, IssmDouble* zz){/*{{{*/ 2384 2385 IssmDouble eartharea=0; 2386 IssmDouble eartharea_cpu=0; 2387 2388 int ns,nsmax; 2389 2390 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 2391 ns = elements->Size(); 2392 2393 /*First, figure out the surface area of Earth: */ 2394 for(int i=0;i<ns;i++){ 2395 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2396 eartharea_cpu += element->GetAreaSpherical(); 2397 } 2398 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2399 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2400 2401 /*Figure out max of ns: */ 2402 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 2403 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 2404 2405 /*Call the esa geodetic core: */ 2406 for(int i=0;i<nsmax;i++){ 2407 if(i<ns){ 2408 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2409 element->EsaGeodetic3D(pUp,pNorth,pEast,latitude,longitude,radius,xx,yy,zz,eartharea); 2410 } 2411 if(i%100==0){ 2412 pUp->Assemble(); 2413 pNorth->Assemble(); 2414 pEast->Assemble(); 2415 } 2416 } 2417 2418 /*One last time: */ 2419 pUp->Assemble(); 2420 pNorth->Assemble(); 2421 pEast->Assemble(); 2422 2423 /*Free ressources:*/ 2424 xDelete<IssmDouble>(latitude); 2425 xDelete<IssmDouble>(longitude); 2426 xDelete<IssmDouble>(radius); 2427 xDelete<IssmDouble>(xx); 2428 xDelete<IssmDouble>(yy); 2429 xDelete<IssmDouble>(zz); 2430 } 2431 /*}}}*/ 2432 #endif 2433 #ifdef _HAVE_SEALEVELRISE_ 2434 void FemModel::SealevelriseEustatic(Vector<IssmDouble>* pSgi, IssmDouble* peustatic, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius) { /*{{{*/ 2435 2436 /*serialized vectors:*/ 2437 IssmDouble eustatic = 0.; 2438 IssmDouble eustatic_cpu = 0.; 2439 IssmDouble eustatic_cpu_e = 0.; 2440 IssmDouble oceanarea = 0.; 2441 IssmDouble oceanarea_cpu = 0.; 2442 IssmDouble eartharea = 0.; 2443 IssmDouble eartharea_cpu = 0.; 2444 int ns,nsmax; 2445 2446 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 2447 ns = elements->Size(); 2448 2449 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 2450 for(int i=0;i<ns;i++){ 2451 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2452 oceanarea_cpu += element->OceanArea(); 2453 eartharea_cpu += element->GetAreaSpherical(); 2454 } 2455 ISSM_MPI_Reduce (&oceanarea_cpu,&oceanarea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2456 ISSM_MPI_Bcast(&oceanarea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2457 _assert_(oceanarea>0.); 2458 2459 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2460 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2461 2462 /*Figure out max of ns: */ 2463 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 2464 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 2465 2466 /*Call the sea level rise core: */ 2467 for(int i=0;i<nsmax;i++){ 2468 if(i<ns){ 2469 2470 if(VerboseConvergence())if(i%100==0)_printf0_("\r" << " convolution progress: " << (double)i/(double)ns*100 << "% "); 2471 2472 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2473 element->SealevelriseEustatic(pSgi,&eustatic_cpu_e,latitude,longitude,radius,oceanarea,eartharea); 2474 eustatic_cpu+=eustatic_cpu_e; 2475 } 2476 if(i%100==0)pSgi->Assemble(); 2477 } 2478 if(VerboseConvergence())_printf0_("\n"); 2479 2480 /*One last time: */ 2481 pSgi->Assemble(); 2482 2483 /*Sum all eustatic components from all cpus:*/ 2484 ISSM_MPI_Reduce (&eustatic_cpu,&eustatic,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2485 ISSM_MPI_Bcast(&eustatic,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2486 _assert_(!xIsNan<IssmDouble>(eustatic)); 2487 2488 /*Assign output pointers:*/ 2489 *peustatic=eustatic; 2490 2491 } 2492 /*}}}*/ 2493 void FemModel::SealevelriseNonEustatic(Vector<IssmDouble>* pSgo, Vector<IssmDouble>* pSg_old, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius, bool verboseconvolution){/*{{{*/ 2494 2495 /*serialized vectors:*/ 2496 IssmDouble* Sg_old=NULL; 2497 2498 IssmDouble eartharea=0; 2499 IssmDouble eartharea_cpu=0; 2500 2501 int ns,nsmax; 2502 2503 /*Serialize vectors from previous iteration:*/ 2504 Sg_old=pSg_old->ToMPISerial(); 2505 2506 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 2507 ns = elements->Size(); 2508 2509 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 2510 for(int i=0;i<ns;i++){ 2511 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2512 eartharea_cpu += element->GetAreaSpherical(); 2513 } 2514 2515 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2516 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2517 2518 /*Figure out max of ns: */ 2519 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 2520 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 2521 2522 /*Call the sea level rise core: */ 2523 for(int i=0;i<nsmax;i++){ 2524 if(i<ns){ 2525 if(verboseconvolution)if(VerboseConvergence())if(i%100==0)_printf_("\r" << " convolution progress: " << (double)i/(double)ns*100 << "% "); 2526 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2527 element->SealevelriseNonEustatic(pSgo,Sg_old,latitude,longitude,radius,eartharea); 2528 } 2529 if(i%100==0)pSgo->Assemble(); 2530 } 2531 if(verboseconvolution)if(VerboseConvergence())_printf_("\n"); 2532 2533 /*Free ressources:*/ 2534 xDelete<IssmDouble>(Sg_old); 2535 } 2536 /*}}}*/ 2537 void FemModel::SealevelriseRotationalFeedback(Vector<IssmDouble>* pSgo_rot, Vector<IssmDouble>* pSg_old, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius){/*{{{*/ 2538 2539 /*serialized vectors:*/ 2540 IssmDouble* Sg_old=NULL; 2541 IssmDouble eartharea=0; 2542 IssmDouble eartharea_cpu=0; 2543 IssmDouble tide_love_h, tide_love_k, fluid_love, moi_e, moi_p, omega, g; 2544 IssmDouble load_love_k2 = -0.30922675; //degree 2 load Love number 2545 IssmDouble m1, m2, m3; 2546 IssmDouble lati, longi, radi, value; 2547 2548 /*Serialize vectors from previous iteration:*/ 2549 Sg_old=pSg_old->ToMPISerial(); 2550 2551 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 2552 for(int i=0;i<elements->Size();i++){ 2553 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2554 eartharea_cpu += element->GetAreaSpherical(); 2555 } 2556 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2557 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2558 2559 IssmDouble moi_list[3]={0,0,0}; 2560 IssmDouble moi_list_cpu[3]={0,0,0}; 2561 for(int i=0;i<elements->Size();i++){ 2562 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2563 element->SealevelriseMomentOfInertia(&moi_list[0],Sg_old,eartharea); 2564 moi_list_cpu[0] += moi_list[0]; 2565 moi_list_cpu[1] += moi_list[1]; 2566 moi_list_cpu[2] += moi_list[2]; 2567 } 2568 ISSM_MPI_Reduce (&moi_list_cpu[0],&moi_list[0],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2569 ISSM_MPI_Bcast(&moi_list[0],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2570 // 2571 ISSM_MPI_Reduce (&moi_list_cpu[1],&moi_list[1],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2572 ISSM_MPI_Bcast(&moi_list[1],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2573 // 2574 ISSM_MPI_Reduce (&moi_list_cpu[2],&moi_list[2],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2575 ISSM_MPI_Bcast(&moi_list[2],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2576 2577 /*pull out some useful parameters: */ 2578 parameters->FindParam(&tide_love_h,SealevelriseTidalLoveHEnum); 2579 parameters->FindParam(&tide_love_k,SealevelriseTidalLoveKEnum); 2580 parameters->FindParam(&fluid_love,SealevelriseFluidLoveEnum); 2581 parameters->FindParam(&moi_e,SealevelriseEquatorialMoiEnum); 2582 parameters->FindParam(&moi_p,SealevelrisePolarMoiEnum); 2583 parameters->FindParam(&omega,SealevelriseAngularVelocityEnum); 2584 2585 /*compute perturbation terms for angular velocity vector: */ 2586 m1 = 1/(1-tide_love_k/fluid_love) * (1+load_love_k2)/(moi_p-moi_e) * moi_list[0]; 2587 m2 = 1/(1-tide_love_k/fluid_love) * (1+load_love_k2)/(moi_p-moi_e) * moi_list[1]; 2588 m3 = -(1+load_love_k2)/moi_p * moi_list[2]; // term associated with fluid number (3-order-of-magnitude smaller) is negelected 2589 2590 /* Green's function (1+k_2-h_2/g): checked against Glenn Milne's thesis Chapter 3 (eqs: 3.3-4, 3.10-11) 2591 * Perturbation terms for angular velocity vector (m1, m2, m3): checked against Mitrovica (2005 Appendix) & Jensen et al (2013 Appendix A3) 2592 * Sea level rotational feedback: checked against GMD eqs 8-9 (only first order terms, i.e., degree 2 order 0 & 1 considered) 2593 * all DONE in Geographic coordinates: theta \in [-90,90], lambda \in [-180 180] 2594 */ 2595 for(int i=0;i<vertices->Size();i++){ 2596 int sid; 2597 //Vertex* vertex=(Vertex*)vertices->GetObjectByOffset(i); 2598 Vertex* vertex=xDynamicCast<Vertex*>(vertices->GetObjectByOffset(i)); 2599 sid=vertex->Sid(); 2600 2601 lati=latitude[sid]/180*PI; longi=longitude[sid]/180*PI; radi=radius[sid]; 2602 2603 /*only first order terms are considered now: */ 2604 value=((1.0+tide_love_k-tide_love_h)/9.81)*pow(omega*radi,2.0)* 2605 (-m3/6.0 + 0.5*m3*cos(2.0*lati) - 0.5*sin(2.*lati)*(m1*cos(longi)+m2*sin(longi))); 2606 2607 pSgo_rot->SetValue(sid,value,INS_VAL); //INS_VAL ensures that you don't add several times 2608 } 2609 2610 /*Assemble mesh velocity*/ 2611 pSgo_rot->Assemble(); 2612 2613 /*Free ressources:*/ 2614 xDelete<IssmDouble>(Sg_old); 2615 2616 } 2617 /*}}}*/ 2618 void FemModel::SealevelriseGeodetic(Vector<IssmDouble>* pUp, Vector<IssmDouble>* pNorth, Vector<IssmDouble>* pEast, Vector<IssmDouble>* pSg, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius, IssmDouble* xx, IssmDouble* yy, IssmDouble* zz){/*{{{*/ 2619 2620 /*serialized vectors:*/ 2621 IssmDouble* Sg=NULL; 2622 2623 IssmDouble eartharea=0; 2624 IssmDouble eartharea_cpu=0; 2625 2626 int ns,nsmax; 2627 2628 /*Serialize vectors from previous iteration:*/ 2629 Sg=pSg->ToMPISerial(); 2630 2631 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 2632 ns = elements->Size(); 2633 2634 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 2635 for(int i=0;i<ns;i++){ 2636 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2637 eartharea_cpu += element->GetAreaSpherical(); 2638 } 2639 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2640 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2641 2642 /*Figure out max of ns: */ 2643 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 2644 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 2645 2646 /*Call the sea level rise core: */ 2647 for(int i=0;i<nsmax;i++){ 2648 if(i<ns){ 2649 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2650 element->SealevelriseGeodetic(pUp,pNorth,pEast,Sg,latitude,longitude,radius,xx,yy,zz,eartharea); 2651 } 2652 if(i%100==0){ 2653 pUp->Assemble(); 2654 pNorth->Assemble(); 2655 pEast->Assemble(); 2656 } 2657 } 2658 2659 /*One last time: */ 2660 pUp->Assemble(); 2661 pNorth->Assemble(); 2662 pEast->Assemble(); 2663 2664 /*Free ressources:*/ 2665 xDelete<IssmDouble>(Sg); 2666 xDelete<IssmDouble>(latitude); 2667 xDelete<IssmDouble>(longitude); 2668 xDelete<IssmDouble>(radius); 2669 xDelete<IssmDouble>(xx); 2670 xDelete<IssmDouble>(yy); 2671 xDelete<IssmDouble>(zz); 2672 } 2673 /*}}}*/ 2674 IssmDouble FemModel::SealevelriseOceanAverage(Vector<IssmDouble>* Sg) { /*{{{*/ 2675 2676 IssmDouble* Sg_serial=NULL; 2677 IssmDouble oceanvalue,oceanvalue_cpu; 2678 IssmDouble oceanarea,oceanarea_cpu; 2679 2680 /*Serialize vectors from previous iteration:*/ 2681 Sg_serial=Sg->ToMPISerial(); 2682 2683 /*Initialize:*/ 2684 oceanvalue_cpu=0; 2685 oceanarea_cpu=0; 2686 2687 /*Go through elements, and add contribution from each element and divide by overall ocean area:*/ 2688 for(int i=0;i<elements->Size();i++){ 2689 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2690 oceanarea_cpu += element->OceanArea(); 2691 oceanvalue_cpu += element->OceanAverage(Sg_serial); 2692 } 2693 ISSM_MPI_Reduce (&oceanarea_cpu,&oceanarea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2694 ISSM_MPI_Bcast(&oceanarea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2695 2696 ISSM_MPI_Reduce (&oceanvalue_cpu,&oceanvalue,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2697 ISSM_MPI_Bcast(&oceanvalue,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 2698 2699 /*Free ressources:*/ 2700 xDelete<IssmDouble>(Sg_serial); 2701 2702 return oceanvalue/oceanarea; 2703 } 2704 /*}}}*/ 2705 #endif 2706 void FemModel::HydrologyEPLupdateDomainx(IssmDouble* pEplcount){ /*{{{*/ 2707 2708 Vector<IssmDouble>* mask = NULL; 2709 Vector<IssmDouble>* recurence = NULL; 2710 Vector<IssmDouble>* active = NULL; 2711 IssmDouble* serial_mask = NULL; 2712 IssmDouble* serial_rec = NULL; 2713 IssmDouble* serial_active = NULL; 2714 IssmDouble* old_active = NULL; 2715 int* eplzigzag_counter = NULL; 2716 int eplflip_lock; 2717 2718 HydrologyDCEfficientAnalysis* effanalysis = new HydrologyDCEfficientAnalysis(); 2719 HydrologyDCInefficientAnalysis* inefanalysis = new HydrologyDCInefficientAnalysis(); 2720 2721 /*Step 1: update mask, the mask might be extended by residual and/or using downstream sediment head*/ 2722 mask=new Vector<IssmDouble>(this->nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 2723 recurence=new Vector<IssmDouble>(this->nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 2724 this->parameters->FindParam(&eplzigzag_counter,NULL,EplZigZagCounterEnum); 2725 this->parameters->FindParam(&eplflip_lock,HydrologydcEplflipLockEnum); 2726 GetVectorFromInputsx(&old_active,this,HydrologydcMaskEplactiveNodeEnum,NodeSIdEnum); 2727 2728 for (int i=0;i<elements->Size();i++){ 2729 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2730 effanalysis->HydrologyEPLGetMask(mask,recurence,eplzigzag_counter,element); 2731 } 2732 /*check for changes and increment zigzag counter, change the mask if necessary*/ 2733 recurence->Assemble(); 2734 serial_rec=recurence->ToMPISerial(); 2735 for (int i=0;i<nodes->Size();i++){ 2736 Node* node=xDynamicCast<Node*>(nodes->GetObjectByOffset(i)); 2737 if(serial_rec[node->Sid()]==1.)eplzigzag_counter[node->Lid()] ++; 2738 if(eplzigzag_counter[node->Lid()]>eplflip_lock & eplflip_lock!=0){ 2739 mask->SetValue(node->Sid(),old_active[node->Sid()],INS_VAL); 2740 } 2741 } 2742 this->parameters->SetParam(eplzigzag_counter,this->nodes->Size(),EplZigZagCounterEnum); 2743 /*Assemble and serialize*/ 2744 mask->Assemble(); 2745 serial_mask=mask->ToMPISerial(); 2746 2747 xDelete<int>(eplzigzag_counter); 2748 xDelete<IssmDouble>(serial_rec); 2749 xDelete<IssmDouble>(old_active); 2750 delete mask; 2751 delete recurence; 2752 2753 /*Update Mask*/ 2754 InputUpdateFromVectorx(this,serial_mask,HydrologydcMaskEplactiveNodeEnum,NodeSIdEnum); 2755 xDelete<IssmDouble>(serial_mask); 2756 inefanalysis->ElementizeEplMask(this); 2757 /*Step 2: update node activity. If one element is connected to mask=1, all nodes are active*/ 2758 active=new Vector<IssmDouble>(nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 2759 for (int i=0;i<elements->Size();i++){ 2760 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2761 effanalysis->HydrologyEPLGetActive(active,element); 2762 } 2763 2764 /*Assemble and serialize*/ 2765 active->Assemble(); 2766 serial_active=active->ToMPISerial(); 2767 delete active; 2768 2769 /*Update node activation accordingly*/ 2770 int counter =0; 2771 for (int i=0;i<nodes->Size();i++){ 2772 Node* node=xDynamicCast<Node*>(nodes->GetObjectByOffset(i)); 2773 if(node->InAnalysis(HydrologyDCEfficientAnalysisEnum)){ 2774 if(serial_active[node->Sid()]==1.){ 2775 node->Activate(); 2776 if(!node->IsClone()) counter++; 2777 } 2778 else{ 2779 node->Deactivate(); 2780 } 2781 } 2782 } 2783 xDelete<IssmDouble>(serial_active); 2784 delete effanalysis; 2785 delete inefanalysis; 2786 int sum_counter; 2787 ISSM_MPI_Reduce(&counter,&sum_counter,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2788 ISSM_MPI_Bcast(&sum_counter,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 2789 counter=sum_counter; 2790 *pEplcount = counter; 2791 if(VerboseSolution()) _printf0_(" Number of active nodes in EPL layer: "<< counter <<"\n"); 2792 2793 /*Update dof indexings*/ 2794 this->UpdateConstraintsx(); 2795 2796 } 2797 /*}}}*/ 2798 void FemModel::UpdateConstraintsL2ProjectionEPLx(IssmDouble* pL2count){ /*{{{*/ 2799 2800 Vector<IssmDouble>* active = NULL; 2801 IssmDouble* serial_active = NULL; 2802 HydrologyDCEfficientAnalysis* effanalysis = new HydrologyDCEfficientAnalysis(); 2803 2804 /*update node activity. If one element is connected to mask=1, all nodes are active*/ 2805 active=new Vector<IssmDouble>(nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 2806 for (int i=0;i<elements->Size();i++){ 2807 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 2808 effanalysis->HydrologyEPLGetActive(active,element); 2809 } 2810 2811 /*Assemble and serialize*/ 2812 active->Assemble(); 2813 serial_active=active->ToMPISerial(); 2814 delete active; 2815 delete effanalysis; 2816 2817 /*Update node activation accordingly*/ 2818 int counter =0; 2819 for (int i=0;i<nodes->Size();i++){ 2820 Node* node=xDynamicCast<Node*>(nodes->GetObjectByOffset(i)); 2821 if(node->InAnalysis(L2ProjectionEPLAnalysisEnum)){ 2822 if(serial_active[node->Sid()]==1.){ 2823 node->Activate(); 2824 if(!node->IsClone()) counter++; 2825 } 2826 else{ 2827 node->Deactivate(); 2828 } 2829 } 2830 } 2831 xDelete<IssmDouble>(serial_active); 2832 int sum_counter; 2833 ISSM_MPI_Reduce(&counter,&sum_counter,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 2834 ISSM_MPI_Bcast(&sum_counter,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 2835 counter=sum_counter; 2836 *pL2count = counter; 2837 if(VerboseSolution()) _printf0_(" Number of active nodes L2 Projection: "<< counter <<"\n"); 2838 } 2839 /*}}}*/ 2840 #ifdef _HAVE_JAVASCRIPT_ 2841 FemModel::FemModel(IssmDouble* buffer, int buffersize, char* toolkits, char* solution, char* modelname,ISSM_MPI_Comm incomm, bool trace){ /*{{{*/ 2842 /*configuration: */ 2843 int solution_type; 2844 int ierr; 2845 2846 /*First things first, store the communicator, and set it as a global variable: */ 2847 IssmComm::SetComm(incomm); 2848 2849 /*Start profiler: */ 2850 this->profiler=new Profiler(); 2851 profiler->Tag(START); 2852 2853 /*From command line arguments, retrieve different filenames needed to create the FemModel: */ 2854 solution_type=StringToEnumx(solution); 2855 2856 /*Create femmodel from input files: */ 2857 profiler->Tag(STARTINIT); 2858 this->InitFromBuffers((char*)buffer,buffersize,toolkits, solution_type,trace,NULL); 2859 profiler->Tag(FINISHINIT); 2860 2861 /*Save communicator in the parameters dataset: */ 2862 this->parameters->AddObject(new GenericParam<ISSM_MPI_Comm>(incomm,FemModelCommEnum)); 2863 2864 } 2865 /*}}}*/ 2866 void FemModel::CleanUpJs(char** poutput, size_t* psize){/*{{{*/ 2867 2868 /*Intermediary*/ 2869 FILE *output_fid; 2870 GenericParam<char**>* outputbufferparam=NULL; 2871 GenericParam<size_t*>* outputbuffersizeparam=NULL; 2872 char** poutputbuffer; 2873 size_t* poutputbuffersize; 2874 2875 2876 /*Before we delete the profiler, report statistics for this run: */ 2877 profiler->Tag(FINISH); //final tagging 2878 _printf0_("\n"); 2879 _printf0_(" "<<setw(40)<<left<<"FemModel initialization elapsed time:"<<profiler->DeltaTime(STARTINIT,FINISHINIT) << "\n"); 2880 _printf0_(" "<<setw(40)<<left<<"Core solution elapsed time:"<<profiler->DeltaTime(STARTCORE,FINISHCORE) << "\n"); 2881 _printf0_("\n"); 2882 _printf0_(" Total elapsed time: " 2883 <<profiler->DeltaTimeModHour(START,FINISH)<<" hrs " 2884 <<profiler->DeltaTimeModMin(START,FINISH)<<" min " 2885 <<profiler->DeltaTimeModSec(START,FINISH)<<" sec" 2886 ); 2887 _printf0_("\n"); 2888 2889 /*Before we close the output file, recover the buffer and size:*/ 2890 outputbufferparam = xDynamicCast<GenericParam<char**>*>(this->parameters->FindParamObject(OutputBufferPointerEnum)); 2891 poutputbuffer=outputbufferparam->GetParameterValue(); 2892 outputbuffersizeparam = xDynamicCast<GenericParam<size_t*>*>(this->parameters->FindParamObject(OutputBufferSizePointerEnum)); 2893 poutputbuffersize=outputbuffersizeparam->GetParameterValue(); 2894 2895 /*Assign output values: */ 2896 *poutput=*poutputbuffer; 2897 *psize=*poutputbuffersize; 2898 } 2899 /*}}}*/ 2900 void FemModel::InitFromBuffers(char* buffer, int buffersize, char* toolkits, int in_solution_type, bool trace, IssmPDouble* X){/*{{{*/ 2901 2902 /*intermediary*/ 2903 FILE *IOMODEL = NULL; 2904 FILE *toolkitsoptionsfid = NULL; 2905 FILE *output_fid = NULL; 2906 int my_rank; 2907 size_t outputsize; 2908 char *outputbuffer; 2909 const char *rootpath = ""; //needed for Dakota runs only, which we won't do here. 2910 2911 /*recover my_rank:*/ 2912 my_rank=IssmComm::GetRank(); 2913 2914 /*Open input file descriptor on cpu 0: */ 2915 if(my_rank==0) IOMODEL = fmemopen((void*)buffer, buffersize, "rb"); 2916 2917 /*Open toolkits file descriptor: */ 2918 toolkitsoptionsfid=fmemopen((void*)toolkits, strlen(toolkits)+1, "r"); 2919 2920 /*Now, go create FemModel:*/ 2921 this->InitFromFids((char*)rootpath,IOMODEL,toolkitsoptionsfid,in_solution_type,trace,X); 2922 2923 /*Close input file and toolkits file descriptors: */ 2924 if(my_rank==0) fclose(IOMODEL); 2925 fclose(toolkitsoptionsfid); 2926 2927 /*Open output file once for all and add output file descriptor to parameters*/ 2928 output_fid=open_memstream(&outputbuffer,&outputsize); 2929 if(output_fid==NULL)_error_("could not initialize output stream"); 2930 this->parameters->SetParam(output_fid,OutputFilePointerEnum); 2931 this->parameters->AddObject(new GenericParam<char**>(&outputbuffer,OutputBufferPointerEnum)); 2932 this->parameters->AddObject(new GenericParam<size_t*>(&outputsize,OutputBufferSizePointerEnum)); 2933 2934 }/*}}}*/ 2935 #endif 2936 2937 #ifdef _HAVE_NEOPZ_ 2938 void FemModel::InitializeAdaptiveRefinement(void){/*{{{*/ 2939 2940 /*Define variables*/ 2941 int my_rank = IssmComm::GetRank(); 2942 this->amr = NULL;//initialize amr as NULL 2943 int numberofvertices = this->vertices->NumberOfVertices(); 2944 int numberofelements = this->elements->NumberOfElements(); 2945 int numberofsegments = 0; //used on matlab 2946 IssmDouble* x = NULL; 2947 IssmDouble* y = NULL; 2948 IssmDouble* z = NULL; 2949 int* elements = NULL; 2950 int elementswidth = this->GetElementsWidth(); //just tria elements in this version. Itapopo: 2951 int levelmax = 0; 2952 IssmDouble regionlevel1 = 0.; 2953 IssmDouble regionlevelmax = 0.; 2954 2955 /*Get vertices coordinates of the coarse mesh (father mesh)*/ 2956 /*elements comes in Matlab indexing*/ 2957 this->GetMesh(this->vertices,this->elements,&x,&y,&z,&elements); 2958 2959 /*Get amr parameters*/ 2960 this->parameters->FindParam(&levelmax,AmrLevelMaxEnum); 2961 this->parameters->FindParam(®ionlevel1,AmrRegionLevel1Enum); 2962 this->parameters->FindParam(®ionlevelmax,AmrRegionLevelMaxEnum); 2963 2964 /*Create initial mesh (coarse mesh) in neopz data structure*/ 2965 /*Just CPU #0 should keep AMR object*/ 2966 this->SetRefPatterns(); 2967 if(my_rank==0){ 2968 bool ismisomip = false; 2969 if(ismisomip){//itapopo 2970 TPZFileStream fstr; 2971 std::stringstream ss; 2972 int frictionlaw; 2973 2974 this->parameters->FindParam(&frictionlaw,FrictionLawEnum); 2975 2976 ss << levelmax; 2977 if(frictionlaw==1){ 2978 ss << "_viscous/amr.txt"; 2979 }else if(frictionlaw==7){ 2980 ss << "_tsai/amr.txt"; 2981 }else{ 2982 _error_("friction law not supported here."); 2983 } 2984 2985 std::string AMRfile = "/home/santos/Misomip2/L" + ss.str(); 2986 fstr.OpenRead(AMRfile.c_str()); 2987 2988 TPZSaveable *sv = TPZSaveable::Restore(fstr,0); 2989 this->amr = dynamic_cast<AdaptiveMeshRefinement*>(sv); 2990 } 2991 else{ 2992 this->amr = new AdaptiveMeshRefinement(); 2993 //this->amr->SetLevelMax(levelmax); //Set max level of refinement 2994 //this->amr->SetRegions(regionlevel1,regionlevelmax); 2995 this->amr->CreateInitialMesh(numberofvertices,numberofelements,numberofsegments,elementswidth,x,y,z,elements,NULL); 2996 } 2997 this->amr->SetLevelMax(levelmax); //Set max level of refinement 2998 this->amr->SetRegions(regionlevel1,regionlevelmax); 2999 } 3000 3001 /*Free the vectors*/ 3002 xDelete<IssmDouble>(x); 3003 xDelete<IssmDouble>(y); 3004 xDelete<IssmDouble>(z); 3005 xDelete<int>(elements); 3006 3007 } 3008 /*}}}*/ 3009 void FemModel::SetRefPatterns(){/*{{{*/ 3010 3011 /*Initialize the global variable of refinement patterns*/ 3012 gRefDBase.InitializeUniformRefPattern(EOned); 3013 gRefDBase.InitializeUniformRefPattern(ETriangle); 3014 3015 //gRefDBase.InitializeRefPatterns(); 3016 /*Insert specifics patterns to ISSM core*/ 3017 std::string filepath = REFPATTERNDIR; 3018 std::string filename1 = filepath + "/2D_Triang_Rib_3.rpt"; 3019 std::string filename2 = filepath + "/2D_Triang_Rib_4.rpt"; 3020 std::string filename3 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_4.rpt"; 3021 std::string filename4 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_4_permuted.rpt"; 3022 std::string filename5 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_5.rpt"; 3023 std::string filename6 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_5_permuted.rpt"; 3024 std::string filename7 = filepath + "/2D_Triang_Rib_5.rpt"; 3025 3026 TPZAutoPointer<TPZRefPattern> refpat1 = new TPZRefPattern(filename1); 3027 TPZAutoPointer<TPZRefPattern> refpat2 = new TPZRefPattern(filename2); 3028 TPZAutoPointer<TPZRefPattern> refpat3 = new TPZRefPattern(filename3); 3029 TPZAutoPointer<TPZRefPattern> refpat4 = new TPZRefPattern(filename4); 3030 TPZAutoPointer<TPZRefPattern> refpat5 = new TPZRefPattern(filename5); 3031 TPZAutoPointer<TPZRefPattern> refpat6 = new TPZRefPattern(filename6); 3032 TPZAutoPointer<TPZRefPattern> refpat7 = new TPZRefPattern(filename7); 3033 3034 if(!gRefDBase.FindRefPattern(refpat1)) gRefDBase.InsertRefPattern(refpat1); 3035 if(!gRefDBase.FindRefPattern(refpat2)) gRefDBase.InsertRefPattern(refpat2); 3036 if(!gRefDBase.FindRefPattern(refpat3)) gRefDBase.InsertRefPattern(refpat3); 3037 if(!gRefDBase.FindRefPattern(refpat4)) gRefDBase.InsertRefPattern(refpat4); 3038 if(!gRefDBase.FindRefPattern(refpat5)) gRefDBase.InsertRefPattern(refpat5); 3039 if(!gRefDBase.FindRefPattern(refpat6)) gRefDBase.InsertRefPattern(refpat6); 3040 if(!gRefDBase.FindRefPattern(refpat7)) gRefDBase.InsertRefPattern(refpat7); 3041 } 3042 /*}}}*/ 3043 void FemModel::ReMesh(void){/*{{{*/ 3044 3045 /*Variables*/ 3046 IssmDouble *newx = NULL; 3047 IssmDouble *newy = NULL; 3048 IssmDouble *newz = NULL; 3049 int *newelementslist = NULL; 3050 int newnumberofvertices = -1; 3051 int newnumberofelements = -1; 3052 bool* my_elements = NULL; 3053 int* my_vertices = NULL; 3054 int elementswidth = this->GetElementsWidth();//just tria elements in this version 3055 3056 /*Execute refinement and get the new mesh*/ 3057 /*newelementslist come in Matlab indexing*/ 3058 this->ExecuteRefinement(newnumberofvertices,newnumberofelements,&newx,&newy,&newz,&newelementslist); 3059 3060 /*Partitioning the new mesh. Maybe ElementsAndVerticesPartitioning.cpp could be modified to set this without iomodel.*/ 3061 this->ElementsAndVerticesPartitioning(newnumberofvertices,newnumberofelements,elementswidth,newelementslist,&my_elements,&my_vertices); 3062 3063 if(this->loads->Size()!=0) _error_("not supported yet"); 3064 3065 /*Create vertices*/ 3066 Vertices* new_vertices=new Vertices(); 3067 this->CreateVertices(newnumberofvertices,newnumberofelements,elementswidth,newelementslist,my_vertices,newx,newy,newz,new_vertices); 3068 3069 /*Creating elements*/ 3070 /*Just Tria in this version*/ 3071 Elements* new_elements=new Elements(); 3072 this->CreateElements(newnumberofelements,elementswidth,newelementslist,my_elements,new_elements); 3073 3074 /*Creating materials*/ 3075 Materials* new_materials=new Materials(); 3076 this->CreateMaterials(newnumberofelements,my_elements,new_materials); 3077 3078 /*Creating nodes and constraints*/ 3079 /*Just SSA (2D) and P1 in this version*/ 3080 Nodes* new_nodes=new Nodes(); 3081 Constraints* new_constraints=new Constraints(); 3082 3083 int nodecounter=0; 3084 int constraintcounter=0; 3085 for(int i=0;i<this->nummodels;i++){//create nodes for each analysis in analysis_type_list 3086 3087 int analysis_enum = this->analysis_type_list[i]; 3088 3089 /*As the domain is 2D, it is not necessary to create nodes for this analysis*/ 3090 /*itapopo must verify if domain is not 3D. Only 2D in this version!*/ 3091 if(analysis_enum==StressbalanceVerticalAnalysisEnum) continue; 3092 3093 this->CreateNodes(newnumberofvertices,my_vertices,nodecounter,analysis_enum,new_nodes); 3094 if(analysis_enum==StressbalanceAnalysisEnum) this->CreateConstraints(newnumberofvertices,newnumberofelements,nodecounter,constraintcounter,newx,newy,my_vertices,new_constraints); 3095 this->UpdateElements(newnumberofelements,newelementslist,my_elements,nodecounter,i,new_elements); 3096 3097 if(new_nodes->Size()) nodecounter=new_nodes->MaximumId(); 3098 constraintcounter = new_constraints->NumberOfConstraints(); 3099 /*Make sure nodecounter is at least 0 (if no node exists, maxid will be -1*/ 3100 _assert_(nodecounter>=0); 3101 } 3102 3103 new_elements->Presort(); 3104 new_nodes->Presort(); 3105 new_vertices->Presort(); 3106 this->loads->Presort(); 3107 new_materials->Presort(); 3108 new_constraints->Presort(); 3109 3110 /*reset hooks for elements, loads and nodes: */ 3111 new_elements->ResetHooks(); 3112 this->loads->ResetHooks(); 3113 new_materials->ResetHooks(); 3114 3115 /*do the post-processing of the datasets to get an FemModel that can actually run analyses: */ 3116 int analysis_type; 3117 for(int i=0;i<this->nummodels;i++){ 3118 analysis_type=this->analysis_type_list[i]; 3119 //SetCurrentConfiguration(analysis_type); 3120 3121 this->analysis_counter=i; 3122 /*Now, plug analysis_counter and analysis_type inside the parameters: */ 3123 this->parameters->SetParam(this->analysis_counter,AnalysisCounterEnum); 3124 this->parameters->SetParam(analysis_type,AnalysisTypeEnum); 3125 this->parameters->SetParam(analysis_type,ConfigurationTypeEnum); 3126 3127 /*configure elements, loads and nodes, for this new analysis: */ 3128 new_elements->SetCurrentConfiguration(new_elements,this->loads,new_nodes,new_vertices,new_materials,this->parameters); 3129 this->loads->SetCurrentConfiguration(new_elements,this->loads,new_nodes,new_vertices,new_materials,this->parameters); 3130 3131 /*take care of toolkits options, that depend on this analysis type (present only after model processor)*/ 3132 if(this->parameters->Exist(ToolkitsOptionsStringsEnum)){ 3133 ToolkitsOptionsFromAnalysis(this->parameters,analysis_type); 3134 if(VerboseSolver()) _printf0_(" toolkits Options set for analysis type: " << EnumToStringx(analysis_type) << "\n"); 3135 } 3136 3137 ConfigureObjectsx(new_elements,this->loads,new_nodes,new_vertices,new_materials,this->parameters); 3138 if(i==0){ 3139 VerticesDofx(new_vertices,this->parameters); //only call once, we only have one set of vertices 3140 } 3141 SpcNodesx(new_nodes,new_constraints,this->parameters,analysis_type); 3142 NodesDofx(new_nodes,this->parameters,analysis_type); 3143 } 3144 3145 /*Finally: interpolate all inputs and insert them into the new elements.*/ 3146 this->InterpolateInputs(new_vertices,new_elements); 3147 3148 /*Delete old structure and set new pointers*/ 3149 delete this->vertices; this->vertices = new_vertices; 3150 delete this->elements; this->elements = new_elements; 3151 delete this->nodes; this->nodes = new_nodes; 3152 delete this->constraints; this->constraints = new_constraints; 3153 delete this->materials; this->materials = new_materials; 3154 3155 GetMaskOfIceVerticesLSMx(this); 3156 3157 /*Insert MISMIP+ bed topography*/ 3158 if(false) this->BedrockFromMismipPlus(); 3159 3160 /*Adjust base, thickness and mask grounded ice leve set*/ 3161 if(true) this->AdjustBaseThicknessAndMask(); 3162 3163 /*Reset current configuration: */ 3164 analysis_type=this->analysis_type_list[this->analysis_counter]; 3165 SetCurrentConfiguration(analysis_type); 3166 3167 /*Cleanup*/ 3168 xDelete<IssmDouble>(newx); 3169 xDelete<IssmDouble>(newy); 3170 xDelete<IssmDouble>(newz); 3171 xDelete<int>(newelementslist); 3172 xDelete<int>(my_vertices); 3173 xDelete<bool>(my_elements); 3174 3175 return; 3176 3177 } 3178 /*}}}*/ 2398 2399 /*AMR*/ 3179 2400 void FemModel::BedrockFromMismipPlus(void){/*{{{*/ 3180 2401 … … 3245 2466 } 3246 2467 3247 if(abs(sl[i])>0) _error_("Sea level value not supported!");2468 if(abs(sl[i])>0) _error_("Sea level value "<<sl[i]<<" not supported!"); 3248 2469 /*update thickness and mask grounded ice level set*/ 3249 2470 h[i] = s[i]-b[i]; … … 3255 2476 element->AddInput(ThicknessEnum,&h[0],P1Enum); 3256 2477 element->AddInput(BaseEnum,&b[0],P1Enum); 3257 3258 2478 } 3259 2479 … … 3265 2485 xDelete<IssmDouble>(r); 3266 2486 xDelete<IssmDouble>(sl); 3267 3268 return;3269 }3270 /*}}}*/3271 void FemModel::WriteMeshInResults(void){/*{{{*/3272 3273 int step = -1;3274 int numberofelements = -1;3275 int numberofvertices = -1;3276 IssmDouble time = -1;3277 IssmDouble* x = NULL;3278 IssmDouble* y = NULL;3279 IssmDouble* z = NULL;3280 int* elementslist = NULL;3281 3282 if(!this->elements || !this->vertices || !this->results || !this->parameters) return;3283 3284 parameters->FindParam(&step,StepEnum);3285 parameters->FindParam(&time,TimeEnum);3286 numberofelements=this->elements->NumberOfElements();3287 numberofvertices=this->vertices->NumberOfVertices();3288 3289 /*Get mesh. Elementslist comes in Matlab indexing*/3290 this->GetMesh(this->vertices,this->elements,&x,&y,&z,&elementslist);3291 3292 /*Write mesh in Results*/3293 this->results->AddResult(new GenericExternalResult<int*>(this->results->Size()+1,MeshElementsEnum,3294 elementslist,numberofelements,this->GetElementsWidth(),step,time));3295 3296 this->results->AddResult(new GenericExternalResult<IssmDouble*>(this->results->Size()+1,MeshXEnum,3297 x,numberofvertices,1,step,time));3298 3299 this->results->AddResult(new GenericExternalResult<IssmDouble*>(this->results->Size()+1,MeshYEnum,3300 y,numberofvertices,1,step,time));3301 3302 //itapopo3303 if(IssmComm::GetRank()==0){3304 TPZFileStream fstr;3305 std::stringstream ss;3306 int frictionlaw,levelmax;3307 this->parameters->FindParam(&frictionlaw,FrictionLawEnum);3308 this->parameters->FindParam(&levelmax,AmrLevelMaxEnum);3309 ss << levelmax;3310 if(frictionlaw==1){3311 ss << "_viscous/amr.txt";3312 }else if(frictionlaw==7){3313 ss << "_tsai/amr.txt";3314 }else{3315 _error_("friction law not supported here.");3316 }3317 std::string AMRfile = "/home/santos/Misomip2/L" + ss.str();3318 fstr.OpenWrite(AMRfile.c_str());3319 int withclassid = 1;3320 this->amr->Write(fstr,withclassid);3321 }3322 //itapopo3323 3324 /*Cleanup*/3325 xDelete<IssmDouble>(x);3326 xDelete<IssmDouble>(y);3327 xDelete<IssmDouble>(z);3328 xDelete<int>(elementslist);3329 3330 return;3331 2487 } 3332 2488 /*}}}*/ … … 3342 2498 } 3343 2499 input_interpolations->Assemble(); 3344 2500 3345 2501 /*Serialize and set output*/ 3346 2502 IssmDouble* input_interpolations_serial = input_interpolations->ToMPISerial(); … … 3374 2530 P1input_interp[numP1inputs] = inputinterp; 3375 2531 } 3376 2532 numP1inputs++; 3377 2533 break; 3378 2534 case P0Enum: … … 3421 2577 xDelete<IssmDouble>(vector); 3422 2578 } 3423 2579 3424 2580 /*Old mesh coordinates*/ 3425 2581 IssmDouble *Xold = NULL; … … 3433 2589 IssmDouble* YC_new = NULL; 3434 2590 int *Indexnew = NULL; 3435 2591 3436 2592 /*Get the old mesh*/ 3437 2593 this->GetMesh(this->vertices,this->elements,&Xold,&Yold,&Zold,&Indexold); … … 3459 2615 P0inputsold,numelementsold,numP0inputs, 3460 2616 XC_new,YC_new,numelementsnew,NULL); 3461 2617 3462 2618 /*Interpolate P1 inputs in the new mesh*/ 3463 2619 InterpFromMeshToMesh2dx(&P1inputsnew,Indexold,Xold,Yold,numverticesold,numelementsold, 3464 2620 P1inputsold,numverticesold,numP1inputs, 3465 2621 Xnew,Ynew,numverticesnew,NULL); 3466 2622 3467 2623 /*Insert P0 inputs into the new elements.*/ 3468 2624 vector=NULL; 3469 2625 for(int i=0;i<numP0inputs;i++){ 3470 2626 3471 2627 /*Get P0 input vector from the interpolated matrix*/ 3472 2628 vector=xNew<IssmDouble>(numelementsnew); … … 3533 2689 xDelete<IssmDouble>(YC_new); 3534 2690 xDelete<int>(Indexnew); 3535 3536 } 3537 /*}}}*/ 3538 void FemModel::ExecuteRefinement(int &numberofvertices,int &numberofelements,IssmDouble** px,IssmDouble** py,IssmDouble** pz,int** pelementslist){/*{{{*/ 3539 3540 /*elements is in Matlab indexing*/ 3541 int my_rank = IssmComm::GetRank(); 3542 int numberofsegments = -1; 3543 IssmDouble* vx = NULL; //itapopo this is not being used 3544 IssmDouble* vy = NULL; //itapopo this is not being used 3545 IssmDouble* x = NULL; 3546 IssmDouble* y = NULL; 3547 IssmDouble* z = NULL; 3548 int* elementslist = NULL; 3549 int* segments = NULL; 3550 IssmDouble* masklevelset = NULL; 3551 IssmDouble* pelementerror = NULL; 3552 const int elementswidth = this->GetElementsWidth();//just 2D mesh, tria elements 3553 3554 /*Solutions which will be used to refine the elements*/ 3555 this->GetGroundediceLevelSet(&masklevelset);//itapopo verificar se já existe um método igual a esse 3556 3557 //Compute the ZZ error estimator per element 3558 this->ZZErrorEstimator(&pelementerror); 3559 3560 _printf0_("P Element error\n"); 3561 for(int i=0;i<this->elements->NumberOfElements();i++) _printf0_(""<<pelementerror[i]<< "\n"); 3562 _printf0_("\n"); 3563 3564 if(my_rank==0){ 3565 int type_process=1; //1: it refines father mesh. See AdaptiveMeshRefinement.h (.cpp) 3566 this->amr->ExecuteRefinement(type_process,vx,vy,masklevelset, 3567 numberofvertices,numberofelements,numberofsegments,&x,&y,&z,&elementslist,&segments); 3568 if(numberofvertices<=0 || numberofelements<=0 /*|| newnumberofsegments<=0*/) _error_("Error in the refinement process."); 3569 } 3570 else{ 3571 x=xNew<IssmDouble>(numberofvertices); 3572 y=xNew<IssmDouble>(numberofvertices); 3573 z=xNew<IssmDouble>(numberofvertices); 3574 elementslist=xNew<int>(numberofelements*this->GetElementsWidth()); 3575 } 3576 3577 /*Send new mesh to others CPU*/ 3578 ISSM_MPI_Bcast(&numberofvertices,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3579 ISSM_MPI_Bcast(&numberofelements,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3580 ISSM_MPI_Bcast(x,numberofvertices,ISSM_MPI_PDOUBLE,0,IssmComm::GetComm()); 3581 ISSM_MPI_Bcast(y,numberofvertices,ISSM_MPI_PDOUBLE,0,IssmComm::GetComm()); 3582 ISSM_MPI_Bcast(z,numberofvertices,ISSM_MPI_PDOUBLE,0,IssmComm::GetComm()); 3583 ISSM_MPI_Bcast(elementslist,numberofelements*this->GetElementsWidth(),ISSM_MPI_INT,0,IssmComm::GetComm()); 3584 3585 /*Assign the pointers*/ 3586 (*pelementslist) = elementslist; //Matlab indexing 3587 (*px) = x; 3588 (*py) = y; 3589 (*pz) = z; 3590 2691 } 2692 /*}}}*/ 2693 void FemModel::WriteMeshInResults(void){/*{{{*/ 2694 2695 int step = -1; 2696 int numberofelements = -1; 2697 int numberofvertices = -1; 2698 IssmDouble time = -1; 2699 IssmDouble* x = NULL; 2700 IssmDouble* y = NULL; 2701 IssmDouble* z = NULL; 2702 int* elementslist = NULL; 2703 2704 if(!this->elements || !this->vertices || !this->results || !this->parameters) return; 2705 2706 parameters->FindParam(&step,StepEnum); 2707 parameters->FindParam(&time,TimeEnum); 2708 numberofelements=this->elements->NumberOfElements(); 2709 numberofvertices=this->vertices->NumberOfVertices(); 2710 2711 /*Get mesh. Elementslist comes in Matlab indexing*/ 2712 this->GetMesh(this->vertices,this->elements,&x,&y,&z,&elementslist); 2713 2714 /*Write mesh in Results*/ 2715 printf("-------------- file: FemModel.cpp line: %i\n",__LINE__); 2716 this->results->AddResult(new GenericExternalResult<int*>(this->results->Size()+1,MeshElementsEnum, 2717 elementslist,numberofelements,this->GetElementsWidth(),step,time)); 2718 2719 this->results->AddResult(new GenericExternalResult<IssmDouble*>(this->results->Size()+1,MeshXEnum, 2720 x,numberofvertices,1,step,time)); 2721 2722 this->results->AddResult(new GenericExternalResult<IssmDouble*>(this->results->Size()+1,MeshYEnum, 2723 y,numberofvertices,1,step,time)); 2724 2725 //itapopo 2726 #ifdef _HAVE_NEOPZ_ 2727 if(IssmComm::GetRank()==0){ 2728 TPZFileStream fstr; 2729 std::stringstream ss; 2730 int frictionlaw,levelmax; 2731 this->parameters->FindParam(&frictionlaw,FrictionLawEnum); 2732 this->parameters->FindParam(&levelmax,AmrLevelMaxEnum); 2733 ss << levelmax; 2734 if(frictionlaw==1){ 2735 ss << "_viscous/amr.txt"; 2736 }else if(frictionlaw==7){ 2737 ss << "_tsai/amr.txt"; 2738 }else{ 2739 _error_("friction law not supported here."); 2740 } 2741 std::string AMRfile = "/home/santos/Misomip2/L" + ss.str(); 2742 fstr.OpenWrite(AMRfile.c_str()); 2743 int withclassid = 1; 2744 this->amr->Write(fstr,withclassid); 2745 } 2746 #endif 2747 //itapopo 2748 3591 2749 /*Cleanup*/ 3592 if(segments) xDelete<int>(segments);3593 xDelete<IssmDouble>( masklevelset);3594 xDelete<IssmDouble>( pelementerror);3595 2750 xDelete<IssmDouble>(x); 2751 xDelete<IssmDouble>(y); 2752 xDelete<IssmDouble>(z); 2753 xDelete<int>(elementslist); 3596 2754 } 3597 2755 /*}}}*/ … … 3635 2793 connectivity=xNewZeroInit<int>(newnumberofvertices); 3636 2794 3637 for 3638 for 2795 for(int i=0;i<newnumberofelements;i++){ 2796 for(int j=0;j<elementswidth;j++){ 3639 2797 int vertexid = newelementslist[elementswidth*i+j]; 3640 2798 _assert_(vertexid>0 && vertexid-1<newnumberofvertices);//Matlab indexing … … 3722 2880 newmatpar->SetMid(newnumberofelements+1); 3723 2881 materials->AddObject(newmatpar);//put it at the end of the materials 3724 3725 2882 } 3726 2883 /*}}}*/ … … 3954 3111 delete vspcvxflag; 3955 3112 delete vspcvyflag; 3956 3957 3113 } 3958 3114 /*}}}*/ … … 4053 3209 xDelete<int>(npart); 4054 3210 xDelete<int>(index); 4055 4056 3211 } 4057 3212 /*}}}*/ … … 4141 3296 xDelete<IssmDouble>(totalweight); 4142 3297 xDelete<int>(elem_vertices); 4143 4144 3298 } 4145 3299 /*}}}*/ … … 4215 3369 xDelete<int>(elem_vertices); 4216 3370 delete velementerror; 3371 } 3372 /*}}}*/ 3373 3374 #ifdef _HAVE_DAKOTA_ 3375 void FemModel::DakotaResponsesx(double* d_responses,char** responses_descriptors,int numresponsedescriptors,int d_numresponses){/*{{{*/ 3376 3377 int i,j; 3378 int my_rank; 3379 3380 /*intermediary: */ 3381 char root[50]; 3382 int index; 3383 int npart; 3384 double femmodel_response; 3385 int flag; 3386 double *vertex_response = NULL; 3387 double *qmu_response = NULL; 3388 double *responses_pointer = NULL; 3389 3390 /*retrieve npart: */ 3391 parameters->FindParam(&npart,QmuNumberofpartitionsEnum); 3392 my_rank=IssmComm::GetRank(); 3393 3394 /*save the d_responses pointer: */ 3395 responses_pointer=d_responses; 3396 3397 //watch out, we have more d_numresponses than numresponsedescriptors, because the responses have been expanded if they were scaled. 3398 //because we don't know the d_responses descriptors (the scaled ones) we can't key off them, so we will key off the responses_descriptors: */ 3399 3400 for(i=0;i<numresponsedescriptors;i++){ 3401 3402 flag=DescriptorIndex(root,&index,responses_descriptors[i]); 3403 3404 if(flag==ScaledEnum){ 3405 3406 /*this response was scaled. pick up the response from the inputs: */ 3407 GetVectorFromInputsx(&vertex_response,this, StringToEnumx(root),VertexPIdEnum); 3408 3409 /*Now, average it onto the partition nodes: */ 3410 AverageOntoPartitionx(&qmu_response,elements,nodes,vertices,loads,materials,parameters,vertex_response); 3411 3412 /*Copy onto our dakota responses: */ 3413 if(my_rank==0){ 3414 /*plug response: */ 3415 for(j=0;j<npart;j++)responses_pointer[j]=qmu_response[j]; 3416 3417 /*increment response_pointer :*/ 3418 responses_pointer+=npart; 3419 } 3420 3421 /*Free ressources:*/ 3422 xDelete<double>(vertex_response); 3423 xDelete<double>(qmu_response); 3424 3425 } 3426 else if (flag==IndexedEnum){ 3427 3428 /*indexed response: plug index into parameters and call response module: */ 3429 parameters->SetParam(index,IndexEnum); 3430 3431 this->Responsex(&femmodel_response,root); 3432 3433 if(my_rank==0){ 3434 /*plug response: */ 3435 responses_pointer[0]=femmodel_response; 3436 3437 /*increment response_pointer :*/ 3438 responses_pointer++; 3439 } 3440 } 3441 else if (flag==NodalEnum){ 3442 _error_("nodal response functions not supported yet!"); 3443 3444 /*increment response_pointer :*/ 3445 responses_pointer++; 3446 } 3447 else if (flag==RegularEnum){ 3448 3449 /*perfectly normal response function: */ 3450 this->Responsex(&femmodel_response,root); 3451 3452 if(my_rank==0){ 3453 /*plug response: */ 3454 responses_pointer[0]=femmodel_response; 3455 3456 /*increment response_pointer :*/ 3457 responses_pointer++; 3458 } 3459 } 3460 else _error_("flag type " << flag << " not supported yet for response analysis"); 3461 } 3462 3463 /*Synthesize echo: {{{*/ 3464 if(my_rank==0){ 3465 _printf_(" responses: " << d_numresponses << ": "); 3466 for(i=0;i<d_numresponses-1;i++)_printf_(d_responses[i] << "|"); 3467 _printf_(d_responses[d_numresponses-1]); 3468 _printf_("\n"); 3469 } 3470 /*}}}*/ 4217 3471 4218 3472 } 4219 3473 /*}}}*/ 4220 3474 #endif 3475 #ifdef _HAVE_GIAIVINS_ 3476 void FemModel::Deflection(Vector<IssmDouble>* wg,Vector<IssmDouble>* dwgdt, IssmDouble* x, IssmDouble* y){ /*{{{*/ 3477 3478 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 3479 for(int i=0;i<elements->Size();i++){ 3480 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3481 element->GiaDeflection(wg,dwgdt, x,y); 3482 } 3483 } 3484 /*}}}*/ 3485 #endif 3486 #ifdef _HAVE_ESA_ 3487 void FemModel::EsaGeodetic2D(Vector<IssmDouble>* pUp, Vector<IssmDouble>* pNorth, Vector<IssmDouble>* pEast, IssmDouble* xx, IssmDouble* yy){/*{{{*/ 3488 3489 int ns,nsmax; 3490 3491 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 3492 ns = elements->Size(); 3493 3494 /*Figure out max of ns: */ 3495 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 3496 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3497 3498 /*Call the esa geodetic core: */ 3499 for(int i=0;i<nsmax;i++){ 3500 if(i<ns){ 3501 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3502 element->EsaGeodetic2D(pUp,pNorth,pEast,xx,yy); 3503 } 3504 if(i%100==0){ 3505 pUp->Assemble(); 3506 pNorth->Assemble(); 3507 pEast->Assemble(); 3508 } 3509 } 3510 3511 /*One last time: */ 3512 pUp->Assemble(); 3513 pNorth->Assemble(); 3514 pEast->Assemble(); 3515 3516 /*Free ressources:*/ 3517 xDelete<IssmDouble>(xx); 3518 xDelete<IssmDouble>(yy); 3519 } 3520 /*}}}*/ 3521 void FemModel::EsaGeodetic3D(Vector<IssmDouble>* pUp, Vector<IssmDouble>* pNorth, Vector<IssmDouble>* pEast, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius, IssmDouble* xx, IssmDouble* yy, IssmDouble* zz){/*{{{*/ 3522 3523 IssmDouble eartharea=0; 3524 IssmDouble eartharea_cpu=0; 3525 3526 int ns,nsmax; 3527 3528 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 3529 ns = elements->Size(); 3530 3531 /*First, figure out the surface area of Earth: */ 3532 for(int i=0;i<ns;i++){ 3533 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3534 eartharea_cpu += element->GetAreaSpherical(); 3535 } 3536 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3537 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3538 3539 /*Figure out max of ns: */ 3540 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 3541 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3542 3543 /*Call the esa geodetic core: */ 3544 for(int i=0;i<nsmax;i++){ 3545 if(i<ns){ 3546 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3547 element->EsaGeodetic3D(pUp,pNorth,pEast,latitude,longitude,radius,xx,yy,zz,eartharea); 3548 } 3549 if(i%100==0){ 3550 pUp->Assemble(); 3551 pNorth->Assemble(); 3552 pEast->Assemble(); 3553 } 3554 } 3555 3556 /*One last time: */ 3557 pUp->Assemble(); 3558 pNorth->Assemble(); 3559 pEast->Assemble(); 3560 3561 /*Free ressources:*/ 3562 xDelete<IssmDouble>(latitude); 3563 xDelete<IssmDouble>(longitude); 3564 xDelete<IssmDouble>(radius); 3565 xDelete<IssmDouble>(xx); 3566 xDelete<IssmDouble>(yy); 3567 xDelete<IssmDouble>(zz); 3568 } 3569 /*}}}*/ 3570 #endif 3571 #ifdef _HAVE_SEALEVELRISE_ 3572 void FemModel::SealevelriseEustatic(Vector<IssmDouble>* pSgi, IssmDouble* peustatic, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius) { /*{{{*/ 3573 3574 /*serialized vectors:*/ 3575 IssmDouble eustatic = 0.; 3576 IssmDouble eustatic_cpu = 0.; 3577 IssmDouble eustatic_cpu_e = 0.; 3578 IssmDouble oceanarea = 0.; 3579 IssmDouble oceanarea_cpu = 0.; 3580 IssmDouble eartharea = 0.; 3581 IssmDouble eartharea_cpu = 0.; 3582 int ns,nsmax; 3583 3584 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 3585 ns = elements->Size(); 3586 3587 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 3588 for(int i=0;i<ns;i++){ 3589 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3590 oceanarea_cpu += element->OceanArea(); 3591 eartharea_cpu += element->GetAreaSpherical(); 3592 } 3593 ISSM_MPI_Reduce (&oceanarea_cpu,&oceanarea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3594 ISSM_MPI_Bcast(&oceanarea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3595 _assert_(oceanarea>0.); 3596 3597 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3598 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3599 3600 /*Figure out max of ns: */ 3601 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 3602 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3603 3604 /*Call the sea level rise core: */ 3605 for(int i=0;i<nsmax;i++){ 3606 if(i<ns){ 3607 3608 if(VerboseConvergence())if(i%100==0)_printf0_("\r" << " convolution progress: " << (double)i/(double)ns*100 << "% "); 3609 3610 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3611 element->SealevelriseEustatic(pSgi,&eustatic_cpu_e,latitude,longitude,radius,oceanarea,eartharea); 3612 eustatic_cpu+=eustatic_cpu_e; 3613 } 3614 if(i%100==0)pSgi->Assemble(); 3615 } 3616 if(VerboseConvergence())_printf0_("\n"); 3617 3618 /*One last time: */ 3619 pSgi->Assemble(); 3620 3621 /*Sum all eustatic components from all cpus:*/ 3622 ISSM_MPI_Reduce (&eustatic_cpu,&eustatic,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3623 ISSM_MPI_Bcast(&eustatic,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3624 _assert_(!xIsNan<IssmDouble>(eustatic)); 3625 3626 /*Assign output pointers:*/ 3627 *peustatic=eustatic; 3628 3629 } 3630 /*}}}*/ 3631 void FemModel::SealevelriseNonEustatic(Vector<IssmDouble>* pSgo, Vector<IssmDouble>* pSg_old, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius, bool verboseconvolution){/*{{{*/ 3632 3633 /*serialized vectors:*/ 3634 IssmDouble* Sg_old=NULL; 3635 3636 IssmDouble eartharea=0; 3637 IssmDouble eartharea_cpu=0; 3638 3639 int ns,nsmax; 3640 3641 /*Serialize vectors from previous iteration:*/ 3642 Sg_old=pSg_old->ToMPISerial(); 3643 3644 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 3645 ns = elements->Size(); 3646 3647 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 3648 for(int i=0;i<ns;i++){ 3649 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3650 eartharea_cpu += element->GetAreaSpherical(); 3651 } 3652 3653 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3654 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3655 3656 /*Figure out max of ns: */ 3657 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 3658 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3659 3660 /*Call the sea level rise core: */ 3661 for(int i=0;i<nsmax;i++){ 3662 if(i<ns){ 3663 if(verboseconvolution)if(VerboseConvergence())if(i%100==0)_printf_("\r" << " convolution progress: " << (double)i/(double)ns*100 << "% "); 3664 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3665 element->SealevelriseNonEustatic(pSgo,Sg_old,latitude,longitude,radius,eartharea); 3666 } 3667 if(i%100==0)pSgo->Assemble(); 3668 } 3669 if(verboseconvolution)if(VerboseConvergence())_printf_("\n"); 3670 3671 /*Free ressources:*/ 3672 xDelete<IssmDouble>(Sg_old); 3673 } 3674 /*}}}*/ 3675 void FemModel::SealevelriseRotationalFeedback(Vector<IssmDouble>* pSgo_rot, Vector<IssmDouble>* pSg_old, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius){/*{{{*/ 3676 3677 /*serialized vectors:*/ 3678 IssmDouble* Sg_old=NULL; 3679 IssmDouble eartharea=0; 3680 IssmDouble eartharea_cpu=0; 3681 IssmDouble tide_love_h, tide_love_k, fluid_love, moi_e, moi_p, omega, g; 3682 IssmDouble load_love_k2 = -0.30922675; //degree 2 load Love number 3683 IssmDouble m1, m2, m3; 3684 IssmDouble lati, longi, radi, value; 3685 3686 /*Serialize vectors from previous iteration:*/ 3687 Sg_old=pSg_old->ToMPISerial(); 3688 3689 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 3690 for(int i=0;i<elements->Size();i++){ 3691 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3692 eartharea_cpu += element->GetAreaSpherical(); 3693 } 3694 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3695 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3696 3697 IssmDouble moi_list[3]={0,0,0}; 3698 IssmDouble moi_list_cpu[3]={0,0,0}; 3699 for(int i=0;i<elements->Size();i++){ 3700 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3701 element->SealevelriseMomentOfInertia(&moi_list[0],Sg_old,eartharea); 3702 moi_list_cpu[0] += moi_list[0]; 3703 moi_list_cpu[1] += moi_list[1]; 3704 moi_list_cpu[2] += moi_list[2]; 3705 } 3706 ISSM_MPI_Reduce (&moi_list_cpu[0],&moi_list[0],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3707 ISSM_MPI_Bcast(&moi_list[0],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3708 // 3709 ISSM_MPI_Reduce (&moi_list_cpu[1],&moi_list[1],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3710 ISSM_MPI_Bcast(&moi_list[1],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3711 // 3712 ISSM_MPI_Reduce (&moi_list_cpu[2],&moi_list[2],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3713 ISSM_MPI_Bcast(&moi_list[2],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3714 3715 /*pull out some useful parameters: */ 3716 parameters->FindParam(&tide_love_h,SealevelriseTidalLoveHEnum); 3717 parameters->FindParam(&tide_love_k,SealevelriseTidalLoveKEnum); 3718 parameters->FindParam(&fluid_love,SealevelriseFluidLoveEnum); 3719 parameters->FindParam(&moi_e,SealevelriseEquatorialMoiEnum); 3720 parameters->FindParam(&moi_p,SealevelrisePolarMoiEnum); 3721 parameters->FindParam(&omega,SealevelriseAngularVelocityEnum); 3722 3723 /*compute perturbation terms for angular velocity vector: */ 3724 m1 = 1/(1-tide_love_k/fluid_love) * (1+load_love_k2)/(moi_p-moi_e) * moi_list[0]; 3725 m2 = 1/(1-tide_love_k/fluid_love) * (1+load_love_k2)/(moi_p-moi_e) * moi_list[1]; 3726 m3 = -(1+load_love_k2)/moi_p * moi_list[2]; // term associated with fluid number (3-order-of-magnitude smaller) is negelected 3727 3728 /* Green's function (1+k_2-h_2/g): checked against Glenn Milne's thesis Chapter 3 (eqs: 3.3-4, 3.10-11) 3729 * Perturbation terms for angular velocity vector (m1, m2, m3): checked against Mitrovica (2005 Appendix) & Jensen et al (2013 Appendix A3) 3730 * Sea level rotational feedback: checked against GMD eqs 8-9 (only first order terms, i.e., degree 2 order 0 & 1 considered) 3731 * all DONE in Geographic coordinates: theta \in [-90,90], lambda \in [-180 180] 3732 */ 3733 for(int i=0;i<vertices->Size();i++){ 3734 int sid; 3735 //Vertex* vertex=(Vertex*)vertices->GetObjectByOffset(i); 3736 Vertex* vertex=xDynamicCast<Vertex*>(vertices->GetObjectByOffset(i)); 3737 sid=vertex->Sid(); 3738 3739 lati=latitude[sid]/180*PI; longi=longitude[sid]/180*PI; radi=radius[sid]; 3740 3741 /*only first order terms are considered now: */ 3742 value=((1.0+tide_love_k-tide_love_h)/9.81)*pow(omega*radi,2.0)* 3743 (-m3/6.0 + 0.5*m3*cos(2.0*lati) - 0.5*sin(2.*lati)*(m1*cos(longi)+m2*sin(longi))); 3744 3745 pSgo_rot->SetValue(sid,value,INS_VAL); //INS_VAL ensures that you don't add several times 3746 } 3747 3748 /*Assemble mesh velocity*/ 3749 pSgo_rot->Assemble(); 3750 3751 /*Free ressources:*/ 3752 xDelete<IssmDouble>(Sg_old); 3753 3754 } 3755 /*}}}*/ 3756 void FemModel::SealevelriseGeodetic(Vector<IssmDouble>* pUp, Vector<IssmDouble>* pNorth, Vector<IssmDouble>* pEast, Vector<IssmDouble>* pSg, IssmDouble* latitude, IssmDouble* longitude, IssmDouble* radius, IssmDouble* xx, IssmDouble* yy, IssmDouble* zz){/*{{{*/ 3757 3758 /*serialized vectors:*/ 3759 IssmDouble* Sg=NULL; 3760 3761 IssmDouble eartharea=0; 3762 IssmDouble eartharea_cpu=0; 3763 3764 int ns,nsmax; 3765 3766 /*Serialize vectors from previous iteration:*/ 3767 Sg=pSg->ToMPISerial(); 3768 3769 /*Go through elements, and add contribution from each element to the deflection vector wg:*/ 3770 ns = elements->Size(); 3771 3772 /*First, figure out the area of the ocean, which is needed to compute the eustatic component: */ 3773 for(int i=0;i<ns;i++){ 3774 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3775 eartharea_cpu += element->GetAreaSpherical(); 3776 } 3777 ISSM_MPI_Reduce (&eartharea_cpu,&eartharea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3778 ISSM_MPI_Bcast(&eartharea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3779 3780 /*Figure out max of ns: */ 3781 ISSM_MPI_Reduce(&ns,&nsmax,1,ISSM_MPI_INT,ISSM_MPI_MAX,0,IssmComm::GetComm()); 3782 ISSM_MPI_Bcast(&nsmax,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3783 3784 /*Call the sea level rise core: */ 3785 for(int i=0;i<nsmax;i++){ 3786 if(i<ns){ 3787 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3788 element->SealevelriseGeodetic(pUp,pNorth,pEast,Sg,latitude,longitude,radius,xx,yy,zz,eartharea); 3789 } 3790 if(i%100==0){ 3791 pUp->Assemble(); 3792 pNorth->Assemble(); 3793 pEast->Assemble(); 3794 } 3795 } 3796 3797 /*One last time: */ 3798 pUp->Assemble(); 3799 pNorth->Assemble(); 3800 pEast->Assemble(); 3801 3802 /*Free ressources:*/ 3803 xDelete<IssmDouble>(Sg); 3804 xDelete<IssmDouble>(latitude); 3805 xDelete<IssmDouble>(longitude); 3806 xDelete<IssmDouble>(radius); 3807 xDelete<IssmDouble>(xx); 3808 xDelete<IssmDouble>(yy); 3809 xDelete<IssmDouble>(zz); 3810 } 3811 /*}}}*/ 3812 IssmDouble FemModel::SealevelriseOceanAverage(Vector<IssmDouble>* Sg) { /*{{{*/ 3813 3814 IssmDouble* Sg_serial=NULL; 3815 IssmDouble oceanvalue,oceanvalue_cpu; 3816 IssmDouble oceanarea,oceanarea_cpu; 3817 3818 /*Serialize vectors from previous iteration:*/ 3819 Sg_serial=Sg->ToMPISerial(); 3820 3821 /*Initialize:*/ 3822 oceanvalue_cpu=0; 3823 oceanarea_cpu=0; 3824 3825 /*Go through elements, and add contribution from each element and divide by overall ocean area:*/ 3826 for(int i=0;i<elements->Size();i++){ 3827 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3828 oceanarea_cpu += element->OceanArea(); 3829 oceanvalue_cpu += element->OceanAverage(Sg_serial); 3830 } 3831 ISSM_MPI_Reduce (&oceanarea_cpu,&oceanarea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3832 ISSM_MPI_Bcast(&oceanarea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3833 3834 ISSM_MPI_Reduce (&oceanvalue_cpu,&oceanvalue,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3835 ISSM_MPI_Bcast(&oceanvalue,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 3836 3837 /*Free ressources:*/ 3838 xDelete<IssmDouble>(Sg_serial); 3839 3840 return oceanvalue/oceanarea; 3841 } 3842 /*}}}*/ 3843 #endif 3844 void FemModel::HydrologyEPLupdateDomainx(IssmDouble* pEplcount){ /*{{{*/ 3845 3846 Vector<IssmDouble>* mask = NULL; 3847 Vector<IssmDouble>* recurence = NULL; 3848 Vector<IssmDouble>* active = NULL; 3849 IssmDouble* serial_mask = NULL; 3850 IssmDouble* serial_rec = NULL; 3851 IssmDouble* serial_active = NULL; 3852 IssmDouble* old_active = NULL; 3853 int* eplzigzag_counter = NULL; 3854 int eplflip_lock; 3855 3856 HydrologyDCEfficientAnalysis* effanalysis = new HydrologyDCEfficientAnalysis(); 3857 HydrologyDCInefficientAnalysis* inefanalysis = new HydrologyDCInefficientAnalysis(); 3858 3859 /*Step 1: update mask, the mask might be extended by residual and/or using downstream sediment head*/ 3860 mask=new Vector<IssmDouble>(this->nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 3861 recurence=new Vector<IssmDouble>(this->nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 3862 this->parameters->FindParam(&eplzigzag_counter,NULL,EplZigZagCounterEnum); 3863 this->parameters->FindParam(&eplflip_lock,HydrologydcEplflipLockEnum); 3864 GetVectorFromInputsx(&old_active,this,HydrologydcMaskEplactiveNodeEnum,NodeSIdEnum); 3865 3866 for (int i=0;i<elements->Size();i++){ 3867 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3868 effanalysis->HydrologyEPLGetMask(mask,recurence,eplzigzag_counter,element); 3869 } 3870 /*check for changes and increment zigzag counter, change the mask if necessary*/ 3871 recurence->Assemble(); 3872 serial_rec=recurence->ToMPISerial(); 3873 for (int i=0;i<nodes->Size();i++){ 3874 Node* node=xDynamicCast<Node*>(nodes->GetObjectByOffset(i)); 3875 if(serial_rec[node->Sid()]==1.)eplzigzag_counter[node->Lid()] ++; 3876 if(eplzigzag_counter[node->Lid()]>eplflip_lock & eplflip_lock!=0){ 3877 mask->SetValue(node->Sid(),old_active[node->Sid()],INS_VAL); 3878 } 3879 } 3880 this->parameters->SetParam(eplzigzag_counter,this->nodes->Size(),EplZigZagCounterEnum); 3881 /*Assemble and serialize*/ 3882 mask->Assemble(); 3883 serial_mask=mask->ToMPISerial(); 3884 3885 xDelete<int>(eplzigzag_counter); 3886 xDelete<IssmDouble>(serial_rec); 3887 xDelete<IssmDouble>(old_active); 3888 delete mask; 3889 delete recurence; 3890 3891 /*Update Mask*/ 3892 InputUpdateFromVectorx(this,serial_mask,HydrologydcMaskEplactiveNodeEnum,NodeSIdEnum); 3893 xDelete<IssmDouble>(serial_mask); 3894 inefanalysis->ElementizeEplMask(this); 3895 /*Step 2: update node activity. If one element is connected to mask=1, all nodes are active*/ 3896 active=new Vector<IssmDouble>(nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 3897 for (int i=0;i<elements->Size();i++){ 3898 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3899 effanalysis->HydrologyEPLGetActive(active,element); 3900 } 3901 3902 /*Assemble and serialize*/ 3903 active->Assemble(); 3904 serial_active=active->ToMPISerial(); 3905 delete active; 3906 3907 /*Update node activation accordingly*/ 3908 int counter =0; 3909 for (int i=0;i<nodes->Size();i++){ 3910 Node* node=xDynamicCast<Node*>(nodes->GetObjectByOffset(i)); 3911 if(node->InAnalysis(HydrologyDCEfficientAnalysisEnum)){ 3912 if(serial_active[node->Sid()]==1.){ 3913 node->Activate(); 3914 if(!node->IsClone()) counter++; 3915 } 3916 else{ 3917 node->Deactivate(); 3918 } 3919 } 3920 } 3921 xDelete<IssmDouble>(serial_active); 3922 delete effanalysis; 3923 delete inefanalysis; 3924 int sum_counter; 3925 ISSM_MPI_Reduce(&counter,&sum_counter,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3926 ISSM_MPI_Bcast(&sum_counter,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3927 counter=sum_counter; 3928 *pEplcount = counter; 3929 if(VerboseSolution()) _printf0_(" Number of active nodes in EPL layer: "<< counter <<"\n"); 3930 3931 /*Update dof indexings*/ 3932 this->UpdateConstraintsx(); 3933 3934 } 3935 /*}}}*/ 3936 void FemModel::UpdateConstraintsL2ProjectionEPLx(IssmDouble* pL2count){ /*{{{*/ 3937 3938 Vector<IssmDouble>* active = NULL; 3939 IssmDouble* serial_active = NULL; 3940 HydrologyDCEfficientAnalysis* effanalysis = new HydrologyDCEfficientAnalysis(); 3941 3942 /*update node activity. If one element is connected to mask=1, all nodes are active*/ 3943 active=new Vector<IssmDouble>(nodes->NumberOfNodes(HydrologyDCEfficientAnalysisEnum)); 3944 for (int i=0;i<elements->Size();i++){ 3945 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i)); 3946 effanalysis->HydrologyEPLGetActive(active,element); 3947 } 3948 3949 /*Assemble and serialize*/ 3950 active->Assemble(); 3951 serial_active=active->ToMPISerial(); 3952 delete active; 3953 delete effanalysis; 3954 3955 /*Update node activation accordingly*/ 3956 int counter =0; 3957 for (int i=0;i<nodes->Size();i++){ 3958 Node* node=xDynamicCast<Node*>(nodes->GetObjectByOffset(i)); 3959 if(node->InAnalysis(L2ProjectionEPLAnalysisEnum)){ 3960 if(serial_active[node->Sid()]==1.){ 3961 node->Activate(); 3962 if(!node->IsClone()) counter++; 3963 } 3964 else{ 3965 node->Deactivate(); 3966 } 3967 } 3968 } 3969 xDelete<IssmDouble>(serial_active); 3970 int sum_counter; 3971 ISSM_MPI_Reduce(&counter,&sum_counter,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,IssmComm::GetComm() ); 3972 ISSM_MPI_Bcast(&sum_counter,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 3973 counter=sum_counter; 3974 *pL2count = counter; 3975 if(VerboseSolution()) _printf0_(" Number of active nodes L2 Projection: "<< counter <<"\n"); 3976 } 3977 /*}}}*/ 3978 #ifdef _HAVE_JAVASCRIPT_ 3979 FemModel::FemModel(IssmDouble* buffer, int buffersize, char* toolkits, char* solution, char* modelname,ISSM_MPI_Comm incomm, bool trace){ /*{{{*/ 3980 /*configuration: */ 3981 int solution_type; 3982 int ierr; 3983 3984 /*First things first, store the communicator, and set it as a global variable: */ 3985 IssmComm::SetComm(incomm); 3986 3987 /*Start profiler: */ 3988 this->profiler=new Profiler(); 3989 profiler->Tag(START); 3990 3991 /*From command line arguments, retrieve different filenames needed to create the FemModel: */ 3992 solution_type=StringToEnumx(solution); 3993 3994 /*Create femmodel from input files: */ 3995 profiler->Tag(STARTINIT); 3996 this->InitFromBuffers((char*)buffer,buffersize,toolkits, solution_type,trace,NULL); 3997 profiler->Tag(FINISHINIT); 3998 3999 /*Save communicator in the parameters dataset: */ 4000 this->parameters->AddObject(new GenericParam<ISSM_MPI_Comm>(incomm,FemModelCommEnum)); 4001 4002 } 4003 /*}}}*/ 4004 void FemModel::CleanUpJs(char** poutput, size_t* psize){/*{{{*/ 4005 4006 /*Intermediary*/ 4007 FILE *output_fid; 4008 GenericParam<char**>* outputbufferparam=NULL; 4009 GenericParam<size_t*>* outputbuffersizeparam=NULL; 4010 char** poutputbuffer; 4011 size_t* poutputbuffersize; 4012 4013 4014 /*Before we delete the profiler, report statistics for this run: */ 4015 profiler->Tag(FINISH); //final tagging 4016 _printf0_("\n"); 4017 _printf0_(" "<<setw(40)<<left<<"FemModel initialization elapsed time:"<<profiler->DeltaTime(STARTINIT,FINISHINIT) << "\n"); 4018 _printf0_(" "<<setw(40)<<left<<"Core solution elapsed time:"<<profiler->DeltaTime(STARTCORE,FINISHCORE) << "\n"); 4019 _printf0_("\n"); 4020 _printf0_(" Total elapsed time: " 4021 <<profiler->DeltaTimeModHour(START,FINISH)<<" hrs " 4022 <<profiler->DeltaTimeModMin(START,FINISH)<<" min " 4023 <<profiler->DeltaTimeModSec(START,FINISH)<<" sec" 4024 ); 4025 _printf0_("\n"); 4026 4027 /*Before we close the output file, recover the buffer and size:*/ 4028 outputbufferparam = xDynamicCast<GenericParam<char**>*>(this->parameters->FindParamObject(OutputBufferPointerEnum)); 4029 poutputbuffer=outputbufferparam->GetParameterValue(); 4030 outputbuffersizeparam = xDynamicCast<GenericParam<size_t*>*>(this->parameters->FindParamObject(OutputBufferSizePointerEnum)); 4031 poutputbuffersize=outputbuffersizeparam->GetParameterValue(); 4032 4033 /*Assign output values: */ 4034 *poutput=*poutputbuffer; 4035 *psize=*poutputbuffersize; 4036 } 4037 /*}}}*/ 4038 void FemModel::InitFromBuffers(char* buffer, int buffersize, char* toolkits, int in_solution_type, bool trace, IssmPDouble* X){/*{{{*/ 4039 4040 /*intermediary*/ 4041 FILE *IOMODEL = NULL; 4042 FILE *toolkitsoptionsfid = NULL; 4043 FILE *output_fid = NULL; 4044 int my_rank; 4045 size_t outputsize; 4046 char *outputbuffer; 4047 const char *rootpath = ""; //needed for Dakota runs only, which we won't do here. 4048 4049 /*recover my_rank:*/ 4050 my_rank=IssmComm::GetRank(); 4051 4052 /*Open input file descriptor on cpu 0: */ 4053 if(my_rank==0) IOMODEL = fmemopen((void*)buffer, buffersize, "rb"); 4054 4055 /*Open toolkits file descriptor: */ 4056 toolkitsoptionsfid=fmemopen((void*)toolkits, strlen(toolkits)+1, "r"); 4057 4058 /*Now, go create FemModel:*/ 4059 this->InitFromFids((char*)rootpath,IOMODEL,toolkitsoptionsfid,in_solution_type,trace,X); 4060 4061 /*Close input file and toolkits file descriptors: */ 4062 if(my_rank==0) fclose(IOMODEL); 4063 fclose(toolkitsoptionsfid); 4064 4065 /*Open output file once for all and add output file descriptor to parameters*/ 4066 output_fid=open_memstream(&outputbuffer,&outputsize); 4067 if(output_fid==NULL)_error_("could not initialize output stream"); 4068 this->parameters->SetParam(output_fid,OutputFilePointerEnum); 4069 this->parameters->AddObject(new GenericParam<char**>(&outputbuffer,OutputBufferPointerEnum)); 4070 this->parameters->AddObject(new GenericParam<size_t*>(&outputsize,OutputBufferSizePointerEnum)); 4071 4072 }/*}}}*/ 4073 #endif 4074 4075 #ifdef _HAVE_BAMG_ 4076 void FemModel::ReMeshBamg(int* pnewnumberofvertices,int* pnewnumberofelements,IssmDouble** pnewx,IssmDouble** pnewy,IssmDouble** pnewz,int** pnewelementslist){/*{{{*/ 4077 4078 /*Output*/ 4079 IssmDouble *newx = NULL; 4080 IssmDouble *newy = NULL; 4081 IssmDouble *newz = NULL; 4082 int *newelementslist = NULL; 4083 int newnumberofvertices = -1; 4084 int newnumberofelements = -1; 4085 4086 /*Get Rank*/ 4087 int my_rank = IssmComm::GetRank(); 4088 4089 if(my_rank==0){ 4090 this->amrbamg->ExecuteRefinementBamg(&newnumberofvertices,&newnumberofelements,&newx,&newy,&newz,&newelementslist); 4091 if(newnumberofvertices<=0 || newnumberofelements<=0) _error_("Error in the refinement process."); 4092 } 4093 else{ 4094 newx=xNew<IssmDouble>(newnumberofvertices); 4095 newy=xNew<IssmDouble>(newnumberofvertices); 4096 newz=xNew<IssmDouble>(newnumberofvertices); 4097 newelementslist=xNew<int>(newnumberofelements*this->GetElementsWidth()); 4098 } 4099 4100 /*Send new mesh to others CPU*/ 4101 ISSM_MPI_Bcast(&newnumberofvertices,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 4102 ISSM_MPI_Bcast(&newnumberofelements,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 4103 ISSM_MPI_Bcast(newx,newnumberofvertices,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 4104 ISSM_MPI_Bcast(newy,newnumberofvertices,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 4105 ISSM_MPI_Bcast(newz,newnumberofvertices,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 4106 ISSM_MPI_Bcast(newelementslist,newnumberofelements*this->GetElementsWidth(),ISSM_MPI_INT,0,IssmComm::GetComm()); 4107 4108 /*Assign output pointers*/ 4109 *pnewnumberofvertices = newnumberofvertices; 4110 *pnewnumberofelements = newnumberofelements; 4111 *pnewx = newx; 4112 *pnewy = newy; 4113 *pnewz = newz; 4114 *pnewelementslist = newelementslist; 4115 } 4116 /*}}}*/ 4117 void FemModel::InitializeAdaptiveRefinementBamg(void){/*{{{*/ 4118 4119 /*Define variables*/ 4120 int numberofvertices = this->vertices->NumberOfVertices(); 4121 int numberofelements = this->elements->NumberOfElements(); 4122 int numberofsegments = 0; //used on matlab 4123 IssmDouble* x = NULL; 4124 IssmDouble* y = NULL; 4125 IssmDouble* z = NULL; 4126 int* elements = NULL; 4127 int elementswidth = this->GetElementsWidth(); //just tria elements in this version. Itapopo: 4128 IssmDouble hmin,hmax,err; 4129 int fieldenum; 4130 4131 /*Get rank*/ 4132 int my_rank = IssmComm::GetRank(); 4133 4134 /*Initialize field as NULL for now*/ 4135 this->amrbamg = NULL; 4136 4137 /*Get vertices coordinates of the coarse mesh (father mesh)*/ 4138 this->GetMesh(this->vertices,this->elements,&x,&y,&z,&elements); 4139 4140 /*Get amr parameters*/ 4141 this->parameters->FindParam(&hmin,AmrHminEnum); 4142 this->parameters->FindParam(&hmax,AmrHmaxEnum); 4143 this->parameters->FindParam(&fieldenum,AmrFieldEnum); 4144 this->parameters->FindParam(&err,AmrErrEnum); 4145 4146 /*Create bamg data structures for bamg (only cpu 0)*/ 4147 if(my_rank==0){ 4148 /*Re-create original mesh and put it in bamg structure*/ 4149 this->amrbamg = new AmrBamg(hmin,hmax); 4150 this->amrbamg->Initialize(elements,x,y,numberofvertices,numberofelements); 4151 } 4152 4153 /*Free the vectors*/ 4154 xDelete<IssmDouble>(x); 4155 xDelete<IssmDouble>(y); 4156 xDelete<IssmDouble>(z); 4157 xDelete<int>(elements); 4158 } 4159 /*}}}*/ 4160 #endif 4161 4162 #ifdef _HAVE_NEOPZ_ 4163 void FemModel::ReMeshNeopz(int* pnumberofvertices,int* pnumberofelements,IssmDouble** px,IssmDouble** py,IssmDouble** pz,int** pelementslist){/*{{{*/ 4164 4165 /*elements is in Matlab indexing*/ 4166 int my_rank = IssmComm::GetRank(); 4167 int numberofsegments = -1; 4168 int numberofvertices,numberofelements; 4169 IssmDouble* vx = NULL; //itapopo this is not being used 4170 IssmDouble* vy = NULL; //itapopo this is not being used 4171 IssmDouble* x = NULL; 4172 IssmDouble* y = NULL; 4173 IssmDouble* z = NULL; 4174 int* elementslist = NULL; 4175 int* segments = NULL; 4176 IssmDouble* masklevelset = NULL; 4177 IssmDouble* pelementerror = NULL; 4178 const int elementswidth = this->GetElementsWidth();//just 2D mesh, tria elements 4179 4180 /*Solutions which will be used to refine the elements*/ 4181 this->GetGroundediceLevelSet(&masklevelset);//itapopo verificar se já existe um método igual a esse 4182 4183 //Compute the ZZ error estimator per element 4184 this->ZZErrorEstimator(&pelementerror); 4185 4186 _printf0_("P Element error\n"); 4187 for(int i=0;i<this->elements->NumberOfElements();i++) _printf0_(""<<pelementerror[i]<< "\n"); 4188 _printf0_("\n"); 4189 4190 if(my_rank==0){ 4191 int type_process=1; //1: it refines father mesh. See AdaptiveMeshRefinement.h (.cpp) 4192 this->amr->ExecuteRefinement(type_process,vx,vy,masklevelset, 4193 numberofvertices,numberofelements,numberofsegments,&x,&y,&z,&elementslist,&segments); 4194 if(numberofvertices<=0 || numberofelements<=0 /*|| newnumberofsegments<=0*/) _error_("Error in the refinement process."); 4195 } 4196 else{ 4197 x=xNew<IssmDouble>(numberofvertices); 4198 y=xNew<IssmDouble>(numberofvertices); 4199 z=xNew<IssmDouble>(numberofvertices); 4200 elementslist=xNew<int>(numberofelements*this->GetElementsWidth()); 4201 } 4202 4203 /*Send new mesh to others CPU*/ 4204 ISSM_MPI_Bcast(&numberofvertices,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 4205 ISSM_MPI_Bcast(&numberofelements,1,ISSM_MPI_INT,0,IssmComm::GetComm()); 4206 ISSM_MPI_Bcast(x,numberofvertices,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 4207 ISSM_MPI_Bcast(y,numberofvertices,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 4208 ISSM_MPI_Bcast(z,numberofvertices,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); 4209 ISSM_MPI_Bcast(elementslist,numberofelements*this->GetElementsWidth(),ISSM_MPI_INT,0,IssmComm::GetComm()); 4210 4211 /*Assign the pointers*/ 4212 (*pelementslist) = elementslist; //Matlab indexing 4213 (*px) = x; 4214 (*py) = y; 4215 (*pz) = z; 4216 *pnumberofelements = numberofelements; 4217 *pnumberofvertices = numberofvertices; 4218 4219 /*Cleanup*/ 4220 if(segments) xDelete<int>(segments); 4221 xDelete<IssmDouble>(masklevelset); 4222 xDelete<IssmDouble>(pelementerror); 4223 4224 } 4225 /*}}}*/ 4226 void FemModel::InitializeAdaptiveRefinementNeopz(void){/*{{{*/ 4227 4228 /*Define variables*/ 4229 int my_rank = IssmComm::GetRank(); 4230 int numberofvertices = this->vertices->NumberOfVertices(); 4231 int numberofelements = this->elements->NumberOfElements(); 4232 int numberofsegments = 0; //used on matlab 4233 IssmDouble* x = NULL; 4234 IssmDouble* y = NULL; 4235 IssmDouble* z = NULL; 4236 int* elements = NULL; 4237 int elementswidth = this->GetElementsWidth(); //just tria elements in this version. Itapopo: 4238 int levelmax = 0; 4239 IssmDouble regionlevel1 = 0.; 4240 IssmDouble regionlevelmax = 0.; 4241 4242 /*Initialize field as NULL for now*/ 4243 this->amr = NULL; 4244 4245 /*Get vertices coordinates of the coarse mesh (father mesh)*/ 4246 /*elements comes in Matlab indexing*/ 4247 this->GetMesh(this->vertices,this->elements,&x,&y,&z,&elements); 4248 4249 /*Get amr parameters*/ 4250 this->parameters->FindParam(&levelmax,AmrLevelMaxEnum); 4251 this->parameters->FindParam(®ionlevel1,AmrRegionLevel1Enum); 4252 this->parameters->FindParam(®ionlevelmax,AmrRegionLevelMaxEnum); 4253 4254 /*Create initial mesh (coarse mesh) in neopz data structure*/ 4255 /*Just CPU #0 should keep AMR object*/ 4256 this->SetRefPatterns(); 4257 if(my_rank==0){ 4258 bool ismisomip = false; 4259 if(ismisomip){//itapopo 4260 TPZFileStream fstr; 4261 std::stringstream ss; 4262 int frictionlaw; 4263 4264 this->parameters->FindParam(&frictionlaw,FrictionLawEnum); 4265 4266 ss << levelmax; 4267 if(frictionlaw==1){ 4268 ss << "_viscous/amr.txt"; 4269 }else if(frictionlaw==7){ 4270 ss << "_tsai/amr.txt"; 4271 }else{ 4272 _error_("friction law not supported here."); 4273 } 4274 4275 std::string AMRfile = "/home/santos/Misomip2/L" + ss.str(); 4276 fstr.OpenRead(AMRfile.c_str()); 4277 4278 TPZSaveable *sv = TPZSaveable::Restore(fstr,0); 4279 this->amr = dynamic_cast<AdaptiveMeshRefinement*>(sv); 4280 } 4281 else{ 4282 this->amr = new AdaptiveMeshRefinement(); 4283 //this->amr->SetLevelMax(levelmax); //Set max level of refinement 4284 //this->amr->SetRegions(regionlevel1,regionlevelmax); 4285 this->amr->CreateInitialMesh(numberofvertices,numberofelements,numberofsegments,elementswidth,x,y,z,elements,NULL); 4286 } 4287 this->amr->SetLevelMax(levelmax); //Set max level of refinement 4288 this->amr->SetRegions(regionlevel1,regionlevelmax); 4289 } 4290 4291 /*Free the vectors*/ 4292 xDelete<IssmDouble>(x); 4293 xDelete<IssmDouble>(y); 4294 xDelete<IssmDouble>(z); 4295 xDelete<int>(elements); 4296 } 4297 /*}}}*/ 4298 void FemModel::SetRefPatterns(){/*{{{*/ 4299 4300 /*Initialize the global variable of refinement patterns*/ 4301 gRefDBase.InitializeUniformRefPattern(EOned); 4302 gRefDBase.InitializeUniformRefPattern(ETriangle); 4303 4304 //gRefDBase.InitializeRefPatterns(); 4305 /*Insert specifics patterns to ISSM core*/ 4306 std::string filepath = REFPATTERNDIR; 4307 std::string filename1 = filepath + "/2D_Triang_Rib_3.rpt"; 4308 std::string filename2 = filepath + "/2D_Triang_Rib_4.rpt"; 4309 std::string filename3 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_4.rpt"; 4310 std::string filename4 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_4_permuted.rpt"; 4311 std::string filename5 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_5.rpt"; 4312 std::string filename6 = filepath + "/2D_Triang_Rib_OnlyTriang_Side_3_5_permuted.rpt"; 4313 std::string filename7 = filepath + "/2D_Triang_Rib_5.rpt"; 4314 4315 TPZAutoPointer<TPZRefPattern> refpat1 = new TPZRefPattern(filename1); 4316 TPZAutoPointer<TPZRefPattern> refpat2 = new TPZRefPattern(filename2); 4317 TPZAutoPointer<TPZRefPattern> refpat3 = new TPZRefPattern(filename3); 4318 TPZAutoPointer<TPZRefPattern> refpat4 = new TPZRefPattern(filename4); 4319 TPZAutoPointer<TPZRefPattern> refpat5 = new TPZRefPattern(filename5); 4320 TPZAutoPointer<TPZRefPattern> refpat6 = new TPZRefPattern(filename6); 4321 TPZAutoPointer<TPZRefPattern> refpat7 = new TPZRefPattern(filename7); 4322 4323 if(!gRefDBase.FindRefPattern(refpat1)) gRefDBase.InsertRefPattern(refpat1); 4324 if(!gRefDBase.FindRefPattern(refpat2)) gRefDBase.InsertRefPattern(refpat2); 4325 if(!gRefDBase.FindRefPattern(refpat3)) gRefDBase.InsertRefPattern(refpat3); 4326 if(!gRefDBase.FindRefPattern(refpat4)) gRefDBase.InsertRefPattern(refpat4); 4327 if(!gRefDBase.FindRefPattern(refpat5)) gRefDBase.InsertRefPattern(refpat5); 4328 if(!gRefDBase.FindRefPattern(refpat6)) gRefDBase.InsertRefPattern(refpat6); 4329 if(!gRefDBase.FindRefPattern(refpat7)) gRefDBase.InsertRefPattern(refpat7); 4330 } 4331 /*}}}*/ 4332 #endif -
issm/trunk-jpl/src/c/classes/FemModel.h
r21762 r21802 22 22 #ifdef _HAVE_NEOPZ_ 23 23 #include "./AdaptiveMeshRefinement.h" 24 #endif 25 #ifdef _HAVE_BAMG_ 26 #include "./AmrBamg.h" 24 27 #endif 25 28 /*}}}*/ … … 47 50 Vertices *vertices; //one set of vertices 48 51 52 //FIXME: do we want only one class and have virtual functions? or keep 2 classes, at least rename AdaptiveMeshRefinement -> AmrNeopz 49 53 #ifdef _HAVE_NEOPZ_ 50 54 AdaptiveMeshRefinement *amr; //adaptive mesh refinement object. It keeps coarse mesh and execute refinement process 55 #endif 56 57 #ifdef _HAVE_BAMG_ 58 AmrBamg *amrbamg; //adaptive mesh refinement object. It keeps coarse mesh and execute refinement process 51 59 #endif 52 60 … … 61 69 FemModel* copy(); 62 70 void Echo(); 71 int GetElementsWidth(){return 3;};//just tria elements in this first version 63 72 void InitFromFiles(char* rootpath, char* inputfilename, char* outputfilename, char* petscfilename, char* lockfilename, char* restartfilename, const int solution_type,bool trace,IssmPDouble* X=NULL); 64 73 void InitFromFids(char* rootpath, FILE* IOMODEL, FILE* toolkitsoptionsfid, int in_solution_type, bool trace, IssmPDouble* X=NULL); 65 74 void Marshall(char** pmarshalled_data, int* pmarshalled_data_size, int marshall_direction); 75 void ReMesh(void); 66 76 void Restart(void); 67 77 void SetCurrentConfiguration(int configuration_type); … … 146 156 #endif 147 157 148 #ifdef _HAVE_NEOPZ_ 149 /*Adaptive mesh refinement methods*/ 150 void InitializeAdaptiveRefinement(void); 151 void ReMesh(void); 158 /*AMR*/ 152 159 void BedrockFromMismipPlus(void); 153 160 void AdjustBaseThicknessAndMask(void); 154 161 void GetMesh(Vertices* femmodel_vertices,Elements* femmodel_elements,IssmDouble** px, IssmDouble** py, IssmDouble** pz, int** pelementslist); 155 int GetElementsWidth(){return 3;};//just tria elements in this first version156 void ExecuteRefinement(int &numberofvertices,int &numberofelements,IssmDouble** px,IssmDouble** py,IssmDouble** pz,int** pelementslist);157 162 void GetGroundediceLevelSet(IssmDouble** pmasklevelset); 158 163 void CreateVertices(int newnumberofvertices,int newnumberofelements,int elementswidth,int* newelementslist,int* my_vertices,IssmDouble* newx,IssmDouble* newy,IssmDouble* newz,Vertices* vertices); … … 168 173 void SmoothedDeviatoricStressTensor(IssmDouble** ptauxx,IssmDouble** ptauyy,IssmDouble** ptauxy); //nodal values, just for SSA-P1: TauXX, TauYY, TauXY 169 174 void ZZErrorEstimator(IssmDouble** pelementerror); 175 176 #ifdef _HAVE_BAMG_ 177 void ReMeshBamg(int* pnewnumberofvertices,int* pnewnumberofelements,IssmDouble** pnewx,IssmDouble** pnewy,IssmDouble** pnewz,int** pnewelementslist); 178 void InitializeAdaptiveRefinementBamg(void); 179 #endif 180 181 #ifdef _HAVE_NEOPZ_ 182 /*Adaptive mesh refinement methods*/ 183 void ReMeshNeopz(int* pnewnumberofvertices,int* pnewnumberofelements,IssmDouble** pnewx,IssmDouble** pnewy,IssmDouble** pnewz,int** pnewelementslist); 184 void InitializeAdaptiveRefinementNeopz(void); 170 185 #endif 171 186 }; 172 173 187 174 188 #endif -
issm/trunk-jpl/src/c/classes/IoModel.cpp
r21775 r21802 605 605 if(strcmp(record_name,"md.materials.type")==0) integer = IoCodeToEnumMaterials(integer); 606 606 if(strcmp(record_name,"md.timestepping.type")==0) integer = IoCodeToEnumTimestepping(integer); 607 if(strcmp(record_name,"md.amr.type")==0) integer = IoCodeToEnumAmr(integer); 607 608 608 609 /*Broadcast to other cpus*/ -
issm/trunk-jpl/src/c/cores/transient_core.cpp
r21787 r21802 111 111 } 112 112 } 113 if(VerboseSolution()) _printf0_(" computing thermal regime\n");114 113 thermal_core(femmodel); 115 114 } … … 182 181 183 182 /*Adaptive mesh refinement*/ 184 #ifdef _HAVE_NEOPZ_185 183 if(amr_frequency){ 186 184 if(save_results) femmodel->WriteMeshInResults(); 187 if(step%amr_frequency==0 && time<finaltime) femmodel->ReMesh();//Do not refine the last step 188 } 189 #endif 185 if(step%amr_frequency==0 && time<finaltime){ 186 if(VerboseSolution()) _printf0_(" refining mesh\n"); 187 femmodel->ReMesh();//Do not refine the last step 188 } 189 //if(save_results){ 190 // printf("-------------- file: transient_core.cpp line: %i\n",__LINE__); 191 // femmodel->WriteMeshInResults(); 192 // OutputResultsx(femmodel); 193 //} 194 } 190 195 } 191 196 -
issm/trunk-jpl/src/c/modules/InterpFromMeshToMesh2dx/InterpFromMeshToMesh2dx.cpp
r21792 r21802 24 24 R2 r; 25 25 I2 I; 26 int i,j ;26 int i,j,k; 27 27 int it; 28 28 int i0,i1,i2; … … 64 64 if(y_data[i]<ymin) ymin=y_data[i]; 65 65 if(y_data[i]>ymax) ymax=y_data[i]; 66 } 67 68 /*Create Single vertex to element connectivity*/ 69 int* connectivity = xNew<int>(nods_data); 70 for(i=0;i<nels_data;i++){ 71 for(j=0;j<3;j++){ 72 k = index_data[i*3+j]-1; 73 _assert_(k>=0 & k<nods_data); 74 connectivity[k]=i; 75 } 66 76 } 67 77 … … 137 147 /*If we fall outside of the convex or outside of the mesh, return NaN*/ 138 148 if(tb.det<0 || reft[it]<0){ 139 for (j=0;j<N_data;j++){ 140 data_interp[i*N_data+j]=NAN; 141 } 149 _assert_(i0>=0 & i0<nods_data); 150 it=connectivity[i0]; //or i1 or i2 151 _assert_(it>=0 && it<nels_data); 152 for(j=0;j<N_data;j++) data_interp[i*N_data+j]=data[N_data*it+j]; 142 153 } 143 154 else{ 155 /*Inside the mesh!*/ 144 156 if(it<0 || it>=nels_data){ 145 157 _error_("Triangle number " << it << " not in [0 " << nels_data 146 158 << "], report bug to developers (interpolation point: " <<x_interp[i]<<" "<<y_interp[i]<<")"); 147 159 } 148 for (j=0;j<N_data;j++){ 149 150 data_interp[i*N_data+j]=data[N_data*it+j]; 151 } 160 for (j=0;j<N_data;j++) data_interp[i*N_data+j]=data[N_data*it+j]; 152 161 } 153 162 } … … 158 167 delete Th; 159 168 xDelete<long>(reft); 169 xDelete<int>(connectivity); 160 170 *pdata_interp=data_interp; 161 171 return 1; -
issm/trunk-jpl/src/c/modules/ModelProcessorx/CreateParameters.cpp
r21787 r21802 21 21 int numoutputs,materialtype,smb_model,basalforcing_model,timestepping_type; 22 22 char** requestedoutputs = NULL; 23 char* fieldname = NULL; 23 24 IssmDouble time; 24 25 … … 60 61 parameters->AddObject(iomodel->CopyConstantObject("md.inversion.type",InversionTypeEnum)); 61 62 parameters->AddObject(iomodel->CopyConstantObject("md.calving.law",CalvingLawEnum)); 62 {/*This is specific to ice...*/63 {/*This is specific to ice...*/ 63 64 parameters->AddObject(iomodel->CopyConstantObject("md.mesh.elementtype",MeshElementtypeEnum)); 64 65 parameters->AddObject(iomodel->CopyConstantObject("md.steadystate.reltol",SteadystateReltolEnum)); … … 81 82 parameters->AddObject(iomodel->CopyConstantObject("md.materials.rheology_law",MaterialsRheologyLawEnum)); 82 83 parameters->AddObject(iomodel->CopyConstantObject("md.gia.cross_section_shape",GiaCrossSectionShapeEnum)); 83 /*amr properties*/84 parameters->AddObject(iomodel->CopyConstantObject("md.amr.level_max",AmrLevelMaxEnum));85 parameters->AddObject(iomodel->CopyConstantObject("md.amr.region_level_1",AmrRegionLevel1Enum));86 parameters->AddObject(iomodel->CopyConstantObject("md.amr.region_level_max",AmrRegionLevelMaxEnum));87 84 88 85 /*For stress balance only*/ … … 95 92 if(iomodel->domaintype==Domain3DEnum) 96 93 parameters->AddObject(iomodel->CopyConstantObject("md.mesh.numberoflayers",MeshNumberoflayersEnum)); 97 } 98 99 94 } 95 96 /*amr properties*/ 97 int amrtype,amr_frequency; 98 iomodel->FindConstant(&amr_frequency,"md.transient.amr_frequency"); 99 if(solution_type==TransientSolutionEnum && amr_frequency){ 100 parameters->AddObject(iomodel->CopyConstantObject("md.amr.type",AmrTypeEnum)); 101 iomodel->FindConstant(&amrtype,"md.amr.type"); 102 switch(amrtype){ 103 #ifdef _HAVE_NEOPZ_ 104 case AmrNeopzEnum: 105 parameters->AddObject(iomodel->CopyConstantObject("md.amr.level_max",AmrLevelMaxEnum)); 106 parameters->AddObject(iomodel->CopyConstantObject("md.amr.region_level_1",AmrRegionLevel1Enum)); 107 parameters->AddObject(iomodel->CopyConstantObject("md.amr.region_level_max",AmrRegionLevelMaxEnum)); 108 break; 109 #endif 110 111 #ifdef _HAVE_BAMG_ 112 case AmrBamgEnum: 113 parameters->AddObject(iomodel->CopyConstantObject("md.amr.hmin",AmrHminEnum)); 114 parameters->AddObject(iomodel->CopyConstantObject("md.amr.hmax",AmrHmaxEnum)); 115 parameters->AddObject(iomodel->CopyConstantObject("md.amr.err",AmrErrEnum)); 116 /*Convert fieldname to enum and put it in params*/ 117 iomodel->FindConstant(&fieldname,"md.amr.fieldname"); 118 parameters->AddObject(new IntParam(AmrFieldEnum,StringToEnumx(fieldname))); 119 xDelete<char>(fieldname); 120 break; 121 #endif 122 123 default: 124 _error_("Adaptive mesh refinement "<<EnumToStringx(amrtype)<<" not implemented yet"); 125 } 126 } 127 100 128 /*Basal forcing parameters*/ 101 129 parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.model",BasalforcingsEnum)); … … 255 283 ParseToolkitsOptionsx(parameters,toolkitsoptionsfid); 256 284 257 285 #ifdef _HAVE_ADOLC_ 258 286 if(VerboseMProcessor()) _printf0_(" starting autodiff parameters \n"); 259 287 CreateParametersAutodiff(parameters,iomodel); -
issm/trunk-jpl/src/c/shared/Enum/EnumDefinitions.h
r21793 r21802 833 833 /*}}}*/ 834 834 /*Adaptive mesh refinement (AMR){{{*/ 835 TransientAmrFrequencyEnum, 836 AmrTypeEnum, 837 AmrNeopzEnum, 835 838 AmrLevelMaxEnum, 836 839 AmrRegionLevel1Enum, 837 840 AmrRegionLevelMaxEnum, 838 TransientAmrFrequencyEnum, 841 AmrBamgEnum, 842 AmrHminEnum, 843 AmrHmaxEnum, 844 AmrFieldEnum, 845 AmrErrEnum, 839 846 /*}}}*/ 840 847 ParametersENDEnum, -
issm/trunk-jpl/src/c/shared/Enum/EnumToStringx.cpp
r21793 r21802 809 809 case EsaRequestedOutputsEnum : return "EsaRequestedOutputs"; 810 810 case EsaNumRequestedOutputsEnum : return "EsaNumRequestedOutputs"; 811 case TransientAmrFrequencyEnum : return "TransientAmrFrequency"; 812 case AmrTypeEnum : return "AmrType"; 813 case AmrNeopzEnum : return "AmrNeopz"; 811 814 case AmrLevelMaxEnum : return "AmrLevelMax"; 812 815 case AmrRegionLevel1Enum : return "AmrRegionLevel1"; 813 816 case AmrRegionLevelMaxEnum : return "AmrRegionLevelMax"; 814 case TransientAmrFrequencyEnum : return "TransientAmrFrequency"; 817 case AmrBamgEnum : return "AmrBamg"; 818 case AmrHminEnum : return "AmrHmin"; 819 case AmrHmaxEnum : return "AmrHmax"; 820 case AmrFieldEnum : return "AmrField"; 821 case AmrErrEnum : return "AmrErr"; 815 822 case ParametersENDEnum : return "ParametersEND"; 816 823 case XYEnum : return "XY"; -
issm/trunk-jpl/src/c/shared/Enum/StringToEnumx.cpp
r21793 r21802 827 827 else if (strcmp(name,"EsaRequestedOutputs")==0) return EsaRequestedOutputsEnum; 828 828 else if (strcmp(name,"EsaNumRequestedOutputs")==0) return EsaNumRequestedOutputsEnum; 829 else if (strcmp(name,"TransientAmrFrequency")==0) return TransientAmrFrequencyEnum; 830 else if (strcmp(name,"AmrType")==0) return AmrTypeEnum; 831 else if (strcmp(name,"AmrNeopz")==0) return AmrNeopzEnum; 829 832 else if (strcmp(name,"AmrLevelMax")==0) return AmrLevelMaxEnum; 830 833 else if (strcmp(name,"AmrRegionLevel1")==0) return AmrRegionLevel1Enum; 831 834 else if (strcmp(name,"AmrRegionLevelMax")==0) return AmrRegionLevelMaxEnum; 832 else if (strcmp(name,"TransientAmrFrequency")==0) return TransientAmrFrequencyEnum; 835 else if (strcmp(name,"AmrBamg")==0) return AmrBamgEnum; 836 else if (strcmp(name,"AmrHmin")==0) return AmrHminEnum; 837 else if (strcmp(name,"AmrHmax")==0) return AmrHmaxEnum; 838 else if (strcmp(name,"AmrField")==0) return AmrFieldEnum; 839 else if (strcmp(name,"AmrErr")==0) return AmrErrEnum; 833 840 else if (strcmp(name,"ParametersEND")==0) return ParametersENDEnum; 834 841 else if (strcmp(name,"XY")==0) return XYEnum; … … 868 875 else if (strcmp(name,"Moulin")==0) return MoulinEnum; 869 876 else if (strcmp(name,"Pengrid")==0) return PengridEnum; 870 else if (strcmp(name,"Penpair")==0) return PenpairEnum; 877 else stage=8; 878 } 879 if(stage==8){ 880 if (strcmp(name,"Penpair")==0) return PenpairEnum; 871 881 else if (strcmp(name,"Profiler")==0) return ProfilerEnum; 872 882 else if (strcmp(name,"MatrixParam")==0) return MatrixParamEnum; … … 875 885 else if (strcmp(name,"NodeSId")==0) return NodeSIdEnum; 876 886 else if (strcmp(name,"ElementSId")==0) return ElementSIdEnum; 877 else stage=8; 878 } 879 if(stage==8){ 880 if (strcmp(name,"VectorParam")==0) return VectorParamEnum; 887 else if (strcmp(name,"VectorParam")==0) return VectorParamEnum; 881 888 else if (strcmp(name,"Riftfront")==0) return RiftfrontEnum; 882 889 else if (strcmp(name,"Segment")==0) return SegmentEnum; … … 991 998 else if (strcmp(name,"TotalGroundedBmb")==0) return TotalGroundedBmbEnum; 992 999 else if (strcmp(name,"TotalSmb")==0) return TotalSmbEnum; 993 else if (strcmp(name,"P0")==0) return P0Enum; 1000 else stage=9; 1001 } 1002 if(stage==9){ 1003 if (strcmp(name,"P0")==0) return P0Enum; 994 1004 else if (strcmp(name,"P0Array")==0) return P0ArrayEnum; 995 1005 else if (strcmp(name,"P1")==0) return P1Enum; … … 998 1008 else if (strcmp(name,"P1bubblecondensed")==0) return P1bubblecondensedEnum; 999 1009 else if (strcmp(name,"P2")==0) return P2Enum; 1000 else stage=9; 1001 } 1002 if(stage==9){ 1003 if (strcmp(name,"P2bubble")==0) return P2bubbleEnum; 1010 else if (strcmp(name,"P2bubble")==0) return P2bubbleEnum; 1004 1011 else if (strcmp(name,"P2bubblecondensed")==0) return P2bubblecondensedEnum; 1005 1012 else if (strcmp(name,"P2xP1")==0) return P2xP1Enum; -
issm/trunk-jpl/src/c/shared/io/Marshalling/IoCodeConversions.cpp
r21787 r21802 128 128 } 129 129 }/*}}}*/ 130 int IoCodeToEnumAmr(int enum_in){/*{{{*/ 131 switch(enum_in){ 132 case 1: return AmrBamgEnum; 133 case 2: return AmrNeopzEnum; 134 default: _error_("Marshalled AMR code \""<<enum_in<<"\" not supported yet"); 135 } 136 }/*}}}*/ 130 137 131 138 int IoCodeToEnumVertexEquation(int enum_in){/*{{{*/ -
issm/trunk-jpl/src/c/shared/io/Marshalling/IoCodeConversions.h
r21773 r21802 10 10 int IoCodeToEnumMaterials(int enum_in); 11 11 int IoCodeToEnumTimestepping(int enum_in); 12 int IoCodeToEnumAmr(int enum_in); 12 13 13 14 int IoCodeToEnumVertexEquation(int enum_in); -
issm/trunk-jpl/src/m/classes/amr.m
r21674 r21802 50 50 function marshall(self,prefix,md,fid) % {{{ 51 51 52 scale = md.constants.yts;52 WriteData(fid,prefix,'name','md.amr.type','data',2,'format','Integer'); 53 53 WriteData(fid,prefix,'object',self,'fieldname','level_max','format','Integer'); 54 54 WriteData(fid,prefix,'object',self,'fieldname','region_level_1','format','Double'); -
issm/trunk-jpl/src/m/classes/trans.js
r21680 r21802 9 9 10 10 //full analysis: Stressbalance, Masstransport and Thermal but no groundingline migration for now 11 this.issmb = 1;12 this.ismasstransport = 1;13 this.isstressbalance = 1;14 this.isthermal = 1;15 this.isgroundingline = 0;16 this.isgia = 0;11 this.issmb = 1; 12 this.ismasstransport = 1; 13 this.isstressbalance = 1; 14 this.isthermal = 1; 15 this.isgroundingline = 0; 16 this.isgia = 0; 17 17 this.isdamageevolution = 0; 18 this.ismovingfront = 0;19 this.ishydrology = 0;20 this.isslr = 0;21 this.iscoupler = 0;22 this.amr_frequency = 1;18 this.ismovingfront = 0; 19 this.ishydrology = 0; 20 this.isslr = 0; 21 this.iscoupler = 0; 22 this.amr_frequency = 0; 23 23 24 24 //default output -
issm/trunk-jpl/src/m/classes/transient.m
r21680 r21802 68 68 self.isoceancoupling = 0; 69 69 self.iscoupler = 0; 70 self.amr_frequency = 1;70 self.amr_frequency = 0; 71 71 72 72 %default output -
issm/trunk-jpl/src/m/classes/transient.py
r21680 r21802 84 84 85 85 #full analysis: Stressbalance, Masstransport and Thermal but no groundingline migration for now 86 self.issmb = True87 self.ismasstransport = True88 self.isstressbalance = True89 self.isthermal = True90 self.isgroundingline = False91 self.isgia = False92 self.isesa = False86 self.issmb = True 87 self.ismasstransport = True 88 self.isstressbalance = True 89 self.isthermal = True 90 self.isgroundingline = False 91 self.isgia = False 92 self.isesa = False 93 93 self.isdamageevolution = False 94 self.ismovingfront = False95 self.ishydrology = False96 self.isslr = False97 self.isoceancoupling = False98 self.iscoupler = False99 self.amr_frequency = 194 self.ismovingfront = False 95 self.ishydrology = False 96 self.isslr = False 97 self.isoceancoupling = False 98 self.iscoupler = False 99 self.amr_frequency = 0 100 100 101 101 #default output
Note:
See TracChangeset
for help on using the changeset viewer.