proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
cMeshAdaptPUMI.cpp
Go to the documentation of this file.
1#include <gmi.h>
2#include <gmi_mesh.h>
3#include <gmi_null.h>
4#include <ma.h>
5#include <maShape.h>
6#include <apfMDS.h>
7#include <PCU.h>
8#include <apf.h>
9
10#include <iostream>
11#include <fstream>
12#include <stdio.h>
13#include <string.h>
14
15#include "MeshAdaptPUMI.h"
16#include <sam.h>
17#include <samSz.h>
18
19#include <apfShape.h>
20
21
22extern double dt_err;
23#ifdef PROTEUS_USE_SIMMETRIX
24//PROTEUS_USE_SIMMETRIX is a compiler macro that indicates whether Simmetrix libraries are used
25//This is defined in proteus/config/default.py and is contingent on the existence of a SIM_INCLUDE_DIR path
26 #include <gmi_sim.h>
27 #include <SimUtil.h>
28 #include <SimModel.h>
29 #include <MeshSim.h>
30 #include <SimMeshTools.h>
31 #define FACE 2
32 pAManager SModel_attManager(pModel model);
33#endif
34
40//MeshAdaptPUMIDrvr::MeshAdaptPUMIDrvr(double Hmax, double Hmin, double HPhi,int AdaptMesh, int NumIter, int NumAdaptSteps,const char* sfConfig, const char* maType,const char* logType, double targetError, double targetElementCount,int reconstructedFlag,double maxAspectRatio, double gradingFact)
47// pcuObj_ wraps the MPI_COMM_WORLD that proteus's Python layer (mpi4py)
48// already initialized before this driver is constructed -- not pcu::Init(),
49// which performs its own MPI bring-up and would be wrong here.
50 : pcuObj_(MPI_COMM_WORLD)
51{
52 m = 0;
53 PCUObj = pcuObj_.GetCHandle();
54 PCU_Protect();
55
56#ifdef PROTEUS_USE_SIMMETRIX
57 Sim_readLicenseFile(0);
58 SimModel_start();
59 gmi_register_sim();
60#endif
61 nAdapt=0;
62 nTriggers=0;
63 nEstimate=0;
64 global[0] = global[1] = global[2] = global[3] = 0;
65 local[0] = local[1] = local[2] = local[3] = 0;
66 size_iso = 0;
67 size_scale = 0;
68 size_frame = 0;
69 err_reg = 0;
70 vmsErrH1 = 0;
71 errRho_reg = 0;
72 errRel_reg = 0;
73 error_reference = 0;
74 gmi_register_mesh();
75 gmi_register_null();
78 total_error = 0.0;
79 errRho_max = 0.0;
80 rel_err_total = 0.0;
82 modelFileName = NULL;
83 adapt_type_config = "test"; //refers to isotropic or anisotropic, feature effectively turned off for now
84 has_gBC = false;
85 target_element_count = 0;//targetElementCount;
86 domainVolume = 0.0;
87 THRESHOLD = 0.0;
89 maxAspect = 2.0;//maxAspectRatio;
91}
92
97{
98/*
99 freeField(err_reg);
100 freeField(vmsErrH1);
101 freeField(errRho_reg);
102 freeField(errRel_reg);
103 freeField(error_reference);
104 freeField(size_iso);
105 freeField(size_scale);
106 freeField(size_frame);
107*/
108/*
109 if(isReconstructed){
110 free(modelVertexMaterial);
111 free(modelBoundaryMaterial);
112 free(modelRegionMaterial);
113 //m->destroyNative();
114 //gmi_destroy(m->getModel());
115 //apf::destroyMesh(m);
116 }
117*/
118 // pcuObj_'s own destructor (RAII, SCOREC/core >= 3.0.0) tears down PCU
119 // state automatically -- no explicit PCU_Comm_Free() call needed or
120 // available anymore.
121#ifdef PROTEUS_USE_SIMMETRIX
122 SimModel_stop();
123 Sim_unregisterAllKeys();
124#endif
125}
126
127
128static bool ends_with(std::string const& str, std::string const& ext)
129{
130 return str.size() >= ext.size() &&
131 str.compare(str.size() - ext.size(), ext.size(), ext) == 0;
132}
141
142int MeshAdaptPUMIDrvr::loadModelAndMesh(const char* modelFile, const char* meshFile)
143{
144 comm_size = PCU_Comm_Peers(PCUObj);
145 comm_rank = PCU_Comm_Self(PCUObj);
146 if (ends_with(meshFile, ".msh")){
147 m = apf::loadMdsFromGmsh(gmi_load(modelFile), meshFile, &pcuObj_);
148 std::cout<<"Boundary Condition functionality has not been built in for gmsh yet.\n";
149 }
150 else if (ends_with(modelFile,".smd")){
151 m = apf::loadMdsMesh(modelFile, meshFile, &pcuObj_);
152 modelFileName=(char *) malloc(sizeof(char) * strlen(modelFile));
153 strcpy(modelFileName,modelFile);
155 }
156 else{
157 m = apf::loadMdsMesh(modelFile, meshFile, &pcuObj_);
158 }
159
160 m->verify();
161 return 0;
162}
163
164int MeshAdaptPUMIDrvr::loadMeshForAnalytic(const char* meshFile,double* boxDim,double* sphereCenter, double radius)
165{
166 //assume analytic
167 comm_size = PCU_Comm_Peers(PCUObj);
168 comm_rank = PCU_Comm_Self(PCUObj);
169 m = apf::loadMdsMesh(".null", meshFile, &pcuObj_);
170 m->verify();
171
172 //create analytic geometry
173 gmi_model* testModel = createSphereInBox(boxDim,sphereCenter,radius);
174 m->verify();
175
176
177/*
178 apf::writeVtkFiles("afterAnalytic",m);
179 std::cout<<"test Model "<<testModel<<" mesh model "<<m->getModel()<<std::endl;
180 std::abort();
181*/
182 return 0;
183}
184
185
186
195{
196
197#ifdef PROTEUS_USE_SIMMETRIX
198 pGModel model = 0;
199 model=GM_load(modelFileName,NULL,NULL);
200
201 pAManager attmngr = SModel_attManager(model);
202 pACase acase = AMAN_findCaseByType(attmngr, "problem definition");
203 if (acase){
204 if(comm_rank==0)std::cout<<"Found case, setting the model"<<std::endl;
205 AttCase_setModel(acase,model);
206 has_gBC=true;
207 AttCase_associate(acase,NULL);
208
209 pGFace gFace;
210 GFIter gfIter = GM_faceIter(model);
211 pAttribute Att[GM_numFaces(model)];
212 int attMap[GM_numFaces(model)];
213 int nF=0;
214
215 char strAtt[2][25] = {"traction vector","comp3"};
216 int modelEntTag;
217
218 while(gFace = GFIter_next(gfIter))
219 {
220 if(GEN_attrib((pGEntity)gFace,strAtt[0]))
221 {
222 modelEntTag=GEN_tag((pGEntity)gFace);
223 Att[nF]=GEN_attrib((pGEntity)gFace,strAtt[0]);
224 attMap[nF] = modelEntTag;
225 nF++;
226 }
227 }
228 GFIter_delete(gfIter);
229
230 apf::MeshIterator* fIter = m->begin(FACE);
231 apf::MeshEntity* fEnt;
232 apf::Vector3 evalPt;
233 int numqpt=0;
234 const int nsd = 3;
235 const int bcFlag[nsd+1] = {0,1,1,1};
236
237 //assign a label to the BC type tag
238 char label[9],labelflux[4][9],type_flag;
239
240 sprintf(label,"BCtype");
241 BCtag = m->createIntTag(label,4);
242 for(int idx=0;idx<4;idx++)
243 {
244 if(idx == 0) sprintf(&type_flag,"p");
245 else if(idx == 1) sprintf(&type_flag,"u");
246 else if(idx == 2) sprintf(&type_flag,"v");
247 else if(idx == 3) sprintf(&type_flag,"w");
248 if(idx>0) sprintf(labelflux[idx],"%c_flux",type_flag);
249 }
250
251 while(fEnt = m->iterate(fIter))
252 {
253 apf::ModelEntity* me=m->toModel(fEnt);
254 modelEntTag = m->getModelTag(me);
255 apf::ModelEntity* boundary_face = m->findModelEntity(FACE,modelEntTag);
256 if(numqpt==0)
257 {
258 apf::MeshElement* testElem = apf::createMeshElement(m,fEnt);
259 numqpt = apf::countIntPoints(testElem,integration_order);
260 for(int idx=1;idx<nsd+1;idx++)
261 fluxtag[idx]= m->createDoubleTag(labelflux[idx],numqpt);
262 apf::destroyMeshElement(testElem);
263 }
264 if(me==boundary_face)
265 {
266 for(int i=0;i<nF;i++)
267 {
268 if(attMap[i]==modelEntTag)
269 {
270 apf::MeshElement* testElem = apf::createMeshElement(m,fEnt);
271 double data[nsd+1][numqpt];
272 for(int k=0; k<numqpt;k++)
273 {
274 apf::getIntPoint(testElem,integration_order,k,evalPt);
275 apf::Vector3 evalPtGlobal;
276 apf::mapLocalToGlobal(testElem,evalPt,evalPtGlobal);
277 double evalPtSim[nsd];
278 evalPtGlobal.toArray(evalPtSim);
279 for(int j=0;j<nsd;j++)
280 data[j+1][k]=AttributeTensor1_evalDS((pAttributeTensor1)Att[i], j,evalPtSim);
281 }
282 m->setIntTag(fEnt,BCtag,&(bcFlag[0]));
283 for(int idx=1;idx<nsd+1;idx++)
284 {
285 m->setDoubleTag(fEnt,fluxtag[idx],data[idx]); //set the quadrature points
286 }
287 apf::destroyMeshElement(testElem);
288 break;
289 } //end if on model
290 else
291 {
292 int dummy[4] = {0,0,0,0};
293 m->setIntTag(fEnt,BCtag,&(dummy[0]));
294 }
295 }//end loop over attributes
296 if(nF==0)
297 {
298 int dummy[4] = {0,0,0,0};
299 m->setIntTag(fEnt,BCtag,&(dummy[0]));
300 }
301 }
302 }//end while
303 m->end(fIter);
304 AMAN_release( attmngr );
305 } else {
306 if(comm_rank==0)
307 std::cout<<"Case not found, no BCs?\n"<<std::endl;
308 //exit(1);
309 }
310
311 if(comm_rank==0)std::cout<<"Finished reading and storing diffusive flux BCs\n";
312#endif
313 return 0;
314}
315static int countTotal(apf::Mesh* m, int dim, PCU_t PCUObj)
316{
317 int total = apf::countOwned(m, dim);
318 PCU_Add_Ints(PCUObj, &total, 1);
319 return total;
320}
321
322
324
332{
333 int adaptFlag=0;
334 int assertFlag;
335
336 //get current size field
337 apf::Field* currentField;
338
339/*
340 if(!size_iso) //if no previous size field
341 {
342 currentField = samSz::isoSize(m);
343 }
344 else //otherwise use previous size field, remember to reflect this in interfaceAdapt or collapse to a single function
345 {
346 currentField = apf::createFieldOn(m, "currentField", apf::SCALAR);
347 apf::copyData(currentField,size_iso);
348 }
349*/
350 //currentField = apf::createFieldOn(m, "currentField", apf::SCALAR);
351 //apf::copyData(currentField,size_iso);
352 currentField = samSz::isoSize(m);
353
354 //get error-based size field
356 apf::Field* errorField = sizeFieldList.front();
357 sizeFieldList.pop(); //remove this size field from the queue
358
359
360 apf::Field *errorTriggered = apf::createLagrangeField(m, "errorTriggered", apf::SCALAR, 1);
361 //determine if desired mesh is contained in current mesh
362 apf::MeshEntity* ent;
363 apf::MeshIterator* it = m->begin(0);
364 while( (ent = m->iterate(it)) )
365 {
366 double h_current = apf::getScalar(currentField,ent,0);
367 double h_needed = apf::getScalar(errorField,ent,0);
368 if(h_current>h_needed*1.5){
369 adaptFlag+=1;
370 apf::setScalar(errorTriggered,ent,0,h_current/h_needed*1.0);
371 //apf::writeVtkFiles("willErrorAdapt", m);
372 //std::cout<<"What is the ent? "<<localNumber(ent)<<std::endl;
373 //std::exit(1);
374 //break;
375 }
376 else
377 apf::setScalar(errorTriggered,ent,0,-1);
378
379 }//end while
380 m->end(it);
381
382 //modify error field to be the ratio
383 it = m->begin(0);
384 while( (ent = m->iterate(it)) )
385 {
386 double h_current = apf::getScalar(currentField,ent,0);
387 double h_needed = apf::getScalar(errorField,ent,0);
388 apf::setScalar(errorField,ent,0,h_current/h_needed*1.0);
389 }//end while
390 m->end(it);
391
392 assertFlag = adaptFlag;
393 PCU_Add_Ints(PCUObj, &assertFlag,1);
394 //assert(assertFlag ==0 || assertFlag == PCU_Proc_Peers(PCUObj));
395
396 if(assertFlag>0)
397 {
398 double totalNodes = countTotal(m,0,PCUObj);
399 double triggeredPercentage = assertFlag*100.0/totalNodes;
400 char buffer[50];
401 sprintf(buffer,"Need to error adapt %f%%",triggeredPercentage);
402 logEvent(buffer,3);
403
404/*
405 if(nTriggers%10==0)
406 {
407 char namebuffer[50];
408 sprintf(namebuffer,"needErrorAdapt_%i",nTriggers);
409 apf::writeVtkFiles(namebuffer, m);
410 }
411*/
412 nTriggers++;
413 }
414
415 apf::destroyField(currentField);
416 //apf::destroyField(errorField);
417 apf::destroyField(errorTriggered);
418
419 return assertFlag;
420}
421
423{
424 int adaptFlag=0;
425 int assertFlag;
426
428 sizeFieldList.pop(); //remove this size field from the queue
429
430 //if(m->findField("errorTriggered"))
431 // apf::destroyField(m->findField("errorTriggered"));
432 apf::Field* errorTriggered;
433 if(m->findField("errorTriggered"))
434 errorTriggered = m->findField("errorTriggered");
435 else
436 errorTriggered = apf::createField(m,"errorTriggered",apf::SCALAR,apf::getVoronoiShape(m->getDimension(),1));
437
438 apf::Field* error_current = m->findField("VMSH1");
439 apf::Field* error_reference=NULL;
440
441
442 if(m->findField("errorRate"))
443 apf::destroyField(m->findField("errorRate"));
444 apf::Field* errorRateField = apf::createField(m,"errorRate",apf::SCALAR,apf::getVoronoiShape(m->getDimension(),1));
445
446 //need to set the error trigger field to 0
447 apf::MeshEntity* ent;
448 apf::MeshIterator* it;
449
450 if(nTriggers == 0)
451 {
452 it = m->begin(m->getDimension());
453 while( (ent = m->iterate(it) ) )
454 {
455 apf::setScalar(errorTriggered,ent,0,-1.0);
456 apf::setScalar(errorRateField,ent,0,0.0);
457 }
458 m->end(it);
459 logEvent("SET ERROR TRIGGERED!",4);
460 }
461
462
463 //need to have size field here just to define it
464
465 //set the error reference field to be the current error field for next time otherwise, retrieve the error_reference field
466 if(!m->findField("error_reference"))
467 {
468 T_reference = T_current;
469 error_reference = apf::createField(m,"error_reference",apf::SCALAR,apf::getVoronoiShape(nsd,1));
470 apf::copyData(error_reference,error_current);
471 logEvent("SUCCESSFULLY COPIED!",4);
472
473 return 0;
474 }
475 else
476 {
477 error_reference = m->findField("error_reference");
478 }
479
480 double dt_step = dt_err; //global variable imported from VMS
481
482 if(m->findField("sizeRatio"))
483 apf::destroyField(m->findField("sizeRatio"));
484 apf::Field* sizeRatioField = apf::createField(m,"sizeRatio",apf::SCALAR,apf::getVoronoiShape(m->getDimension(),1));
485
486 it = m->begin(m->getDimension());
487
488 while( (ent = m->iterate(it) ) )
489 {
490 double err_local_current = apf::getScalar(error_current,ent,0);
491 double err_local_ref = apf::getScalar(error_reference,ent,0);
492 double errorRate = (err_local_current-err_local_ref)/(T_current-T_reference);
493 apf::setScalar(errorRateField,ent,0,errorRate);
494 double err_predict = errorRate*delta_T_next + err_local_current;
495
496 //double sizeRatio_local = apf::getScalar(m->findField("sizeRatio"),ent,0);
497 //if(errorRate > 0 && (err_predict > target_error) && sizeRatio_local>2.0 && nTriggers>=5)
498 //double sizeRatio_local_predict = pow(err_predict/target_error,2.0/(2*1+2));
499
500 double h_old;
501 double h_new;
502 apf::MeshElement* element = apf::createMeshElement(m, ent);
503
504 if (m->getDimension() == 2)
505 h_old = apf::computeLargestHeightInTri(m,ent);
506 else
507 h_old = apf::computeShortestHeightInTet(m,ent);
508 h_new = h_old * pow((target_error / err_predict),2.0/(2.0*(1.0)+nsd));
509 //clamp h_new and then compare against h_old
510 if(h_new > hmax)
511 h_new = hmax;
512 if(h_new < hmin)
513 h_new = hmin;
514 double sizeRatio_local_predict = h_old/h_new;
515 apf::setScalar(sizeRatioField,ent,0,sizeRatio_local_predict);
516 apf::destroyMeshElement(element);
517
518 //apf::setScalar(sizeRatioField,ent,0,size_ratio_local_predict);
519 if(errorRate > 0 && sizeRatio_local_predict>2.0 && nTriggers>= (0.1*numAdaptSteps))
520 {
521 if(apf::getScalar(errorTriggered,ent,0)==1)
522 {
523 adaptFlag = 1;
524 apf::setScalar(errorTriggered,ent,0,2.0);
525 }
526 else
527 apf::setScalar(errorTriggered,ent,0,1.0);
528 }
529 else
530 apf::setScalar(errorTriggered,ent,0,-1.0);
531 }
532 m->end(it);
533
534 //upper bound on adapt steps
536 {
537 logEvent("Adapting because upper limit was reached.",4);
538 adaptFlag = 1;
539 }
540
541 assertFlag = adaptFlag;
542 PCU_Add_Ints(PCUObj, &assertFlag,1);
543 nTriggers++;
544
545 //if adapt, modify the error field to be predictive
546 //otherwise, store the current error field to be the next reference field
547 if(assertFlag > 0)
548 {
549 logEvent("Need to error based adapt!!!",4);
550/*
551 it = m->begin(m->getDimension());
552 while( (ent = m->iterate(it) ) )
553 {
554 double err_local_current = apf::getScalar(error_current,ent,0);
555 double err_local_ref = apf::getScalar(error_reference,ent,0);
556 //double errorRate = (err_local_current-err_local_ref)/(T_current-T_reference);
557 double errorRate = apf::getScalar(errorRateField,ent,0);
558
559 //double err_predict = errorRate*dt_step*numAdaptSteps + err_local_current;
560 double err_predict = errorRate*dt_step*numAdaptSteps/10.0 + err_local_current;
561 if(err_predict > err_local_current)
562 {
563 apf::setScalar(error_current,ent,0,err_predict);
564 }
565 }
566 m->end(it);
567*/
568 }
569 else
570 {
571 it = m->begin(m->getDimension());
572 while( (ent = m->iterate(it) ) )
573 {
574 double err_local_current = apf::getScalar(error_current,ent,0);
575 //set the reference field for the next step
576 apf::setScalar(error_reference,ent,0,err_local_current);
577 }
578
579 }
580
581 T_reference = T_current;
582
583 return assertFlag;
584}
585
586
587
589//Master function that calls other adapt-trigger functions
590{
591 int adaptFlag = 0;
592 //TODO: need to separate IBM from interface to allow for two-phase with IBM
593 if(hasInterface or hasIBM)
594 {
595 adaptFlag += willInterfaceAdapt();
596 logEvent("will adapt because of interface",4);
597 }
598 if(hasVMS)
599 {
600 adaptFlag += willErrorAdapt_reference();
601 logEvent("will adapt because of error",4);
602 }
603 //TODO: need to do AllReduce here instead of in each function
604 if(adaptFlag > 0)
605 adaptFlag = 1;
606
607 if(adaptFlag == 0)
608 {
609 //allocated in transfer fields... this is not a good way of doing things, but don't know how to pass a numpy array without having to allocate memory just yet
610 free(rho);
611 free(nu);
612 }
613
614 return adaptFlag;
615}
616
617
619//Does banded adapt need to happen for an isotropic mesh?
620//I need to loop over all mesh edges and determine if the edge intersects the blending region.
621//If so, need to check the size values on the edge-adjacent vertices.
622//If either size value is greater than h_interface*1.5, then we know we need to adapt
623{
624 int adaptFlag=0;
625 int assertFlag;
626
627 //get current size field
628 apf::Field* currentField;
629/*
630 if(!size_iso) //if no previous size field
631 {
632 currentField = samSz::isoSize(m);
633 }
634 else //otherwise use previous size field, remember to reflect this in interfaceAdapt or collapse to a single function
635 {
636 currentField = apf::createFieldOn(m, "currentField", apf::SCALAR);
637 apf::copyData(currentField,size_iso);
638 }
639*/
640
641 currentField = samSz::isoSize(m);
642 double edgeRatio = 1.5; //need to be taken from MeshAdapt library
643
644 //get banded size field
645 double L_band = (N_interface_band)*hPhi;
646 calculateSizeField(L_band);
647 apf::Field* interfaceField = sizeFieldList.front();
648 sizeFieldList.pop(); //destroy this size field
649
650
651 //determine if desired mesh is contained in current mesh
652 apf::MeshEntity* ent;
653 apf::MeshIterator* it = m->begin(0);
654 while( (ent = m->iterate(it)) )
655 {
656 double h_current = apf::getScalar(currentField,ent,0);
657 double h_needed = apf::getScalar(interfaceField,ent,0);
658 if(h_current/h_needed > edgeRatio){
659 adaptFlag=1;
660 break;
661 }
662 }//end while
663
664 assertFlag = adaptFlag;
665 PCU_Add_Ints(PCUObj, &assertFlag,1);
666 //assert(assertFlag ==0 || assertFlag == PCU_Proc_Peers(PCUObj));
667
668 apf::destroyField(currentField);
669 apf::destroyField(interfaceField);
670
671 return assertFlag;
672}
673
674
675
676int MeshAdaptPUMIDrvr::adaptPUMIMesh(const char* inputString)
688{
689 if (hasAniso)
691 if(hasERM)
692 {
693 assert(err_reg);
694 removeBCData();
695 double t1 = PCU_Time();
697 double t2 = PCU_Time();
698 if(comm_rank==0 && logging_config == "on"){
699 std::ofstream myfile;
700 myfile.open("error_estimator_timing.txt", std::ios::app );
701 myfile << t2-t1<<std::endl;
702 myfile.close();
703 }
704 }
705 if((hasVMS) && std::string(inputString)==""){
706 assert(vmsErrH1);
708 }
710 {
712 }
713 if(hasInterface || hasIBM)
714 {
715 double L_band = (N_interface_band+1)*hPhi;
716 calculateSizeField(L_band);
717 if(nAdapt>1 && std::string(inputString)=="interface")
719 else if(nAdapt > 2 && std::string(inputString)=="")
721 }
722 if (useProteus)
723 size_iso = m->findField("proteus_size");
724 if (useProteusAniso){
725 size_frame = m->findField("proteus_sizeFrame");
726 size_scale = m->findField("proteus_sizeScale");
727 adapt_type_config = "anisotropic";
728 }
729/*
730 if (hasTest)
731 testIsotropicSizeField();
732*/
733/*
734 if(size_field_config == "uniform"){
735 //special situation where I only care about err_reg
736 freeField(errRho_reg);
737 freeField(errRel_reg);
738 }
739*/
740 isotropicIntersect();
741
742 if(logging_config=="on"){
743 char namebuffer[50];
744 sprintf(namebuffer,"pumi_preadapt_%i",nAdapt);
745 apf::writeVtkFiles(namebuffer, m);
746 //sprintf(namebuffer,"beforeAnisotropicAdapt%i_.smb",nAdapt);
747 //m->writeNative(namebuffer);
748 }
749
750 if(hasERM){
751 //MeshAdapt error will be thrown if region fields are not freed
752 freeField(err_reg);
753 freeField(errRho_reg);
754 freeField(errRel_reg);
755 }
756 if(hasVMS){
757 freeField(vmsErrH1);
758 if(PCU_Comm_Self(PCUObj)==0) std::cout<<"cleared VMS field\n";
759 }
760
761 // These are relics from an attempt to pass BCs from proteus into the error estimator.
762 // They maybe useful in the future.
763 //m->destroyTag(fluxtag[1]); m->destroyTag(fluxtag[2]); m->destroyTag(fluxtag[3]);
766
767 for (int d = 0; d <= m->getDimension(); ++d)
768 freeNumbering(local[d]);
769
770 apf::Field* adaptSize;
771 apf::Field* adaptFrame;
772
774 ma::Input* in;
775 if(size_field_config == "uniform"){
776 in = ma::makeAdvanced(ma::configureUniformRefine(m));
777 in->shouldFixShape=false;
778 }
779 else{
780 assert(size_iso || (size_scale && size_frame));
781 if(adapt_type_config=="anisotropic" || size_field_config== "interface"){
782 //in = ma::configure(m, size_scale, size_frame);
783 adaptSize = apf::createFieldOn(m, "adapt_size", apf::VECTOR);
784 adaptFrame = apf::createFieldOn(m, "adapt_frame", apf::MATRIX);
785 apf::copyData(adaptSize, size_scale);
786 apf::copyData(adaptFrame, size_frame);
787 in = ma::makeAdvanced(ma::configure(m, adaptSize, adaptFrame));
788 }
789 else{
790 adaptSize = apf::createFieldOn(m, "adapt_size", apf::SCALAR);
791 apf::copyData(adaptSize, size_iso);
792 in = ma::makeAdvanced(ma::configure(m, adaptSize));
793 }
794 }
795
796 ma::validateInput(in);
797 in->shouldRunPreZoltan = true;
798 in->shouldRunMidZoltan = true;
799 in->shouldRunPostZoltan = true;
800 in->maximumImbalance = 1.05;
801 in->maximumIterations = numIter;
802 if(size_field_config == "meshQuality")
803 {
804 in->shouldSnap = true;
805 in->shouldTransferParametric=true;
806 }
807 else
808 in->shouldSnap = false;
809 //in->goodQuality = 0.16;//0.027;
810 //double mass_before = getTotalMass();
811
812 double t1 = PCU_Time();
813 //ma::adapt(in);
814 ma::adaptVerbose(in);
815 double t2 = PCU_Time();
816
817 m->verify();
818 //double mass_after = getTotalMass();
819 //PCU_Add_Doubles(PCUObj, &mass_before,1);
820 //PCU_Add_Doubles(PCUObj, &mass_after,1);
821 if(comm_rank==0 && logging_config=="on"){
822/*
823 std::ios::fmtflags saved(std::cout.flags());
824 std::cout<<std::setprecision(15)<<"Mass Before "<<mass_before<<" After "<<mass_after<<" diff "<<mass_after-mass_before<<std::endl;
825 std::cout.flags(saved);
826 std::ofstream myfile;
827 myfile.open("adapt_timing.txt", std::ios::app);
828 myfile << t2-t1<<std::endl;
829 myfile.close();
830 std::ofstream mymass;
831 mymass.open("mass_check.txt", std::ios::app);
832 mymass <<std::setprecision(15)<<mass_before<<","<<mass_after<<","<<mass_after-mass_before<<std::endl;
833 mymass.close();
834*/
835 }
836
837 if(hasERM){
838 if (has_gBC)
840 }
841 if(logging_config=="on"){
842 char namebuffer[50];
843 sprintf(namebuffer,"pumi_postadapt_%i",nAdapt);
844 apf::writeVtkFiles(namebuffer, m);
845 //sprintf(namebuffer,"afterAnisotropicAdapt%i_.smb",nAdapt);
846 //m->writeNative(namebuffer);
847 }
848 //isReconstructed = 0; //this is needed to maintain consistency with the post-adapt conversion back to Proteus
849 apf::destroyField(adaptSize);
850 if(adapt_type_config=="anisotropic")
851 apf::destroyField(adaptFrame);
852 nAdapt++; //counter for number of adapt steps
853
854 if(logging_config=="debugRestart")
855 m->writeNative("DEBUG_restart.smb");
856
857 nTriggers=0;
858 return 0;
859}
860
868{
869 ma::SizeField* isf = new ma::IdentitySizeField(m);
870 apf::MeshIterator* it = m->begin(m->getDimension());
871 apf::MeshEntity* e;
872 double minq = 1;
873 while ((e = m->iterate(it)))
874 minq = std::min(minq, ma::measureElementQuality(m, isf, e));
875 m->end(it);
876 delete isf;
877 return PCU_Min_Double(PCUObj, minq);
878}
879
886{
887 apf::Field* voff = m->findField("vof");
888 assert(voff);
889 apf::MeshEntity* e;
890 apf::MeshIterator* it = m->begin(m->getDimension());
891 double mass = 0.0;
892 while ((e = m->iterate(it))) {
893 apf::MeshElement* elem = apf::createMeshElement(m,e);
894 apf::Element* voff_elem = apf::createElement(voff, elem);
895 int int_order = 4;
896 for(int l = 0; l < apf::countIntPoints(elem, int_order); ++l) {
897 apf::Vector3 qpt;
898 apf::getIntPoint(elem,int_order,l,qpt);
899 double vof_val = apf::getScalar(voff_elem,qpt);
900 double rho_val = getMPvalue(vof_val,rho[0],rho[1]);
901 double weight = apf::getIntWeight(elem,int_order,l);
902 apf::Matrix3x3 J;
903 apf::getJacobian(elem,qpt,J); //evaluate the Jacobian at the quadrature point
904 double Jdet = apf::getJacobianDeterminant(J,m->getDimension());
905 mass += rho_val*weight*Jdet;
906 }
907 apf::destroyElement(voff_elem);
908 apf::destroyMeshElement(elem);
909 }
910 m->end(it);
911 PCU_Add_Doubles(PCUObj, &mass,1);
912 return mass;
913}
914
915
916//Save mesh with solution
917
918void MeshAdaptPUMIDrvr::writeMesh(const char* meshFile)
919{
920 m->writeNative(meshFile);
921 //apf::writeVtkFiles(meshFile,m);
922}
923
924//Clean mesh of all fields and tags
925
927{
928 //destroy all fields...
929
930 for(int i =0;i<m->countFields();i++)
931 {
932 apf::Field* sample = m->getField(i);
933 freeField(sample);
934 }
935 //std::cout<<"find field " <<m->getField(m->countFields())<<" how many fields? "<<m->countFields()<<std::endl;
936 //std::cout<<"is velocity_old here? "<<m->findField("velocity_old")<<std::endl;
937 apf::Field* sample = m->findField("velocity_old");
938 freeField(sample);
939
940 sample = m->findField("vof_old");
941 freeField(sample);
942 sample = m->findField("ls_old");
943 freeField(sample);
944 sample = m->findField("phi");
945 freeField(sample);
946 sample = m->findField("phi_old");
947 freeField(sample);
948 sample = m->findField("phi_old_old");
949 freeField(sample);
950 sample = m->findField("phid_old");
951 freeField(sample);
952 sample = m->findField("phiCorr");
953 freeField(sample);
954 sample = m->findField("phiCorr_old");
955 freeField(sample);
956 sample = m->findField("phiCorr_old_old");
957 freeField(sample);
958 sample = m->findField("p_old");
959 freeField(sample);
960 sample = m->findField("p");
961 freeField(sample);
962 sample = m->findField("p_old_old");
963 freeField(sample);
964
965 sample = m->findField("VMSH1");
966 freeField(sample);
967 sample = m->findField("VMSL2");
968 freeField(sample);
969
970 //destroy all tags
971 apf::DynamicArray<apf::MeshTag*> listTags;
972 m->getTags(listTags);
973 int nTags = listTags.getSize();
974 int numDim = m->getDimension();
975 for(int i=0; i < nTags; i++)
976 {
977 std::string ignoreString ("proteus_number");
978 std::string tagName (m->getTagName(listTags[i]));
979 if(tagName.find(ignoreString) != std::string::npos)
980 {
981 //do nothing
982 }
983 else{
984 for(int j=0;j<(numDim+1);j++)
985 {
986 apf::MeshIterator* it = m->begin(j);
987 apf::MeshEntity* ent;
988 while( (ent = m->iterate(it)) )
989 {
990 if(m->hasTag(ent,listTags[i]))
991 m->removeTag(ent,listTags[i]);
992 }
993 m->end(it);
994 }
995 m->destroyTag(listTags[i]);
996 }
997 }
998}
999
1001{
1002 nAdapt = numberAdapt;
1003 return;
1004}
1005
1006int MeshAdaptPUMIDrvr::setAdaptProperties(std::vector<std::string> sizeInputs,bool in_adapt, double in_hmax,double in_hmin,double in_hphi, int in_numAdaptSteps, double in_targetError, double in_gradingFactor, bool in_logging, int in_numIterations)
1007{
1008 for (std::vector<std::string>::iterator it = sizeInputs.begin() ; it != sizeInputs.end(); ++it)
1009 {
1010 if(*it == "ibm")
1011 hasIBM=1;
1012 if(*it == "interface")
1013 hasInterface=1;
1014 if(*it == "error_vms")
1015 hasVMS=1;
1016 if(*it == "error_erm")
1017 hasERM=1;
1018 }
1019 hmin=in_hmin;
1020 hmax=in_hmax;
1021 hPhi=in_hphi;
1022 numIter=in_numIterations;
1023 adaptMesh = in_adapt;
1024 numAdaptSteps = in_numAdaptSteps;
1025 if(PCU_Comm_Self(PCUObj)==0)
1026 printf("MeshAdapt: Setting hmax=%lf, hmin=%lf, numIters(meshadapt)=%d\n",
1027 hmax, hmin, numIter);
1028 logging_config = in_logging;
1029 target_error = in_targetError;
1030 gradingFactor = in_gradingFactor;
1031
1032 return 0;
1033}
int int_order
double dt_err
Definition VMS.cpp:18
int loadMeshForAnalytic(const char *meshFile, double *boxDim, double *sphereCenter, double radius)
std::string size_field_config
int setAdaptProperties(std::vector< std::string > sizeInputs, bool in_adapt, double in_hmax, double in_hmin, double in_hphi, int in_numAdaptSteps, double in_targetError, double in_gradingFactor, bool in_logging, int in_numIterations)
void removeBCData()
Function used to remove the BC tags that were created during the computeDiffusiveFlux() function.
double getMinimumQuality()
Function used to get the worst element quality in the mesh.
int loadModelAndMesh(const char *modelFile, const char *meshFile)
Load the mesh and model for SCOREC libraries.
int * exteriorGlobaltoLocalElementBoundariesArray
int getERMSizeField(double err_total)
int willErrorAdapt()
Looks at the estimated error and determines if mesh adaptation is necessary.
double getMPvalue(double field_val, double val_0, double val_1)
Function primarily used to get the VOF-weighted average of physical properties at a given point.
int calculateAnisoSizeField()
void predictiveInterfacePropagation()
void writeMesh(const char *meshFile)
std::string logging_config
int calculateSizeField(double L_band)
Definition SizeField.cpp:84
int adaptPUMIMesh(const char *input)
Function used to trigger adaptation.
void set_nAdapt(int numberAdapt)
double getTotalMass()
Function to track total mass of the domain.
gmi_model * createSphereInBox(double *boxDim, double *sphereCenter, double radius)
apf::MeshTag * fluxtag[4]
std::string adapt_type_config
apf::MeshTag * BCtag
int getSimmetrixBC()
Function used to read in diffusive flux BC from Simmetrix Model.