Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
SimplicialMesh.cpp
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_SimplicialMesh_cpp_
9#define model_SimplicialMesh_cpp_
10
11#include <chrono>
12#include <sstream>
13#include <fstream>
14#include <assert.h>
15#include <utility> // std::pair, std::make_pair
16#include <set>
17#include <map>
18
19#include <Eigen/LU>
20
21//#include <VertexReader.h>
22#include <TerminalColors.h>
23#include <SimplexTraits.h>
24#include <Simplex.h>
25#include <SimplexReader.h>
26//#include <MeshStats.h>
27// defines mode::cout
28#include <MeshRegionBoundary.h>
29#include <SimplexFactory.h>
30//#include <SimplicialMeshFace.h>
31#include <GmshReader.h>
32#include <SimplicialMesh.h>
34#include <PolyhedralMesh.h>
35
36
37namespace model
38{
39
40 template<int dim>
41 void SimplicialMesh<dim>::createMesh(const std::set<int>& periodicFaceIDs)
42 {
44
45 const auto t0= std::chrono::system_clock::now();
46 vol0=0.0;
47 size_t eleConter=0;
48 for (const auto& eIter : this->simplexReader().elements())
49 {
50 insertSimplex(eIter.second.first,eIter.second.second);
51 eleConter++;
52 std::cout<<greenBoldColor<<"\r"<<"Creating mesh "<<eleConter*100/this->simplexReader().elements().size()<<"%"<<magentaColor<<" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-t0)).count()<<" sec]"<<std::flush;
53 }
54 std::cout<<defaultColor<<std::endl;
55
56
57
58 if(simplices().size())
59 {
60 _xMin=this->template simplexFactory<0>().liveSimplices().begin()->second->P0;
61 _xMax=this->template simplexFactory<0>().liveSimplices().begin()->second->P0;
62
63 for (const auto& nIter : this->template simplexFactory<0>().liveSimplices())
64 {
65 for(int d=0;d<dim;++d)
66 {
67 if (nIter.second->P0(d)<_xMin(d))
68 {
69 _xMin(d)=nIter.second->P0(d);
70 }
71 if (nIter.second->P0(d)>_xMax(d))
72 {
73 _xMax(d)=nIter.second->P0(d);
74 }
75 }
76 }
77 _xC=0.5*(_xMax+_xMin);
78 }
79 else
80 {
81 std::cout<<"Mesh is empty."<<std::endl;
82 }
83 std::cout<<" xMin="<< std::setprecision(15)<<std::scientific<<_xMin.transpose()<<std::endl;
84 std::cout<<" xMax="<< std::setprecision(15)<<std::scientific<<_xMax.transpose()<<std::endl;
85 std::cout<<" xCenter="<< std::setprecision(15)<<std::scientific<<_xC.transpose()<<std::endl;
87 // Populate typename SimplicialMesh<dim>::MeshRegionBoundaryContainerType
89
90 size_t bndSimplexCount=0;
91 size_t rgnBndSimplexCount=0;
92 for (const auto& simpl : this->template simplexFactory<dim-1>().liveSimplices())
93 {
94
95 if(simpl.second->isBoundarySimplex())
96 {// count number of bonudary simplices for later check
97 bndSimplexCount++;
98 }
99
100 if(simpl.second->isRegionBoundarySimplex())
101 {
102 const auto regionIDset=simpl.second->regionIDs();
103 std::pair<size_t,size_t> regionIDs(std::make_pair(*regionIDset.begin(),*regionIDset.rbegin()));
104 const auto regionBndIter=regionBoundaries().find(regionIDs);
105 if(regionBndIter!=regionBoundaries().end())
106 {
107 regionBndIter->second.simplices().insert(simpl.second.get());
108 }
109 else
110 {
111 regionBoundaries().try_emplace(regionIDs,regionIDs,*_polyhedralMesh).first->second.simplices().insert(simpl.second.get());
112 }
113 rgnBndSimplexCount++;
115 }
119 _polyhedralMesh->buildTopology();
120 identifyParallelFaces(periodicFaceIDs);
121
122 // Check that all simplices have been accounted for
123 size_t bndFaceSimplexSum=0;
124 for(auto region : this->regions())
125 {// Sum number of external faces for final check
126 std::cout<<magentaColor<<"MeshRegion "<<region.second->regionID<<defaultColor<<std::endl;
127 std::cout<<" simplices: "<<region.second->simplices().size()<<" Simplex<"<<dim<<","<<dim<<">"<<std::endl;
128 for(auto& face : region.second->faces())
130 std::cout<<" face "<<face.second->sID<<": size="<<face.second->size()<<",hullPts="<<face.second->convexHull().size()<<", outNormal "<<face.second->outNormal().transpose()<<std::endl;
131 bndFaceSimplexSum+=face.second->size();
132 }
133 }
135 size_t rgnBndFaceSimplexSum=0;
136 for(const auto& rgnBnd : regionBoundaries())
137 {// Sum number of internal faces for final check
138 std::cout<<magentaColor<<"MeshRegionBoundary ("<<rgnBnd.second.regionBndID.first<<","<<rgnBnd.second.regionBndID.second<<")"<<defaultColor<<std::endl;
139 std::cout<<" simplices: "<<rgnBnd.second.simplices().size()<<" Simplex<"<<dim<<","<<dim-1<<">"<<std::endl;
140 for(auto& face : rgnBnd.second.faces())
141 {
142 std::cout<<" face "<<face.second->sID<<": hullPts="<<face.second->convexHull().size()<<", outNormal "<<face.second->outNormal().transpose()<<std::endl;
143 rgnBndFaceSimplexSum+=face.second->size();
144 bndFaceSimplexSum-=2*face.second->size(); // each region boundary face was added to two regions
145 }
146 }
147
148 if(bndFaceSimplexSum!=bndSimplexCount)
149 {
150 std::cout<<"boundary simplices="<<bndSimplexCount<<std::endl;
151 std::cout<<"simplices in external faces="<<bndFaceSimplexSum<<std::endl;
152 throw std::runtime_error("WRONG NUMBER OF BOUNDAY FACE SIMPLICES");
153 }
155 if(rgnBndFaceSimplexSum!=rgnBndSimplexCount)
157 std::cout<<"region-boundary simplices="<<rgnBndSimplexCount<<std::endl;
158 std::cout<<"simplices in internal faces="<<rgnBndFaceSimplexSum<<std::endl;
159 throw std::runtime_error("WRONG NUMBER OF REGION-BOUNDARY FACE SIMPLICES");
161 }
162
163 template<int dim>
165 /* init */ _xMin(Eigen::Matrix<double,dim,1>::Zero())
166 /* init */,_xMax(Eigen::Matrix<double,dim,1>::Zero())
167 /* init */,_xC(Eigen::Matrix<double,dim,1>::Zero())
168 /* init */,vol0(0.0)
169 {
170 }
171
172 template<int dim>
173 SimplicialMesh<dim>::SimplicialMesh(const std::string& meshFileName,const Eigen::Matrix<double,dim,dim>& A,const Eigen::Matrix<double,dim,1>& x0,const std::set<int>& periodicFaceIDs) :
174 /* init */ _xMin(Eigen::Matrix<double,dim,1>::Zero())
175 /* init */,_xMax(Eigen::Matrix<double,dim,1>::Zero())
176 /* init */,_xC(Eigen::Matrix<double,dim,1>::Zero())
177 /* init */,vol0(0.0)
178 {
179 this->read(meshFileName,A,x0);
180 createMesh(periodicFaceIDs);
181 this->simplexReader().clear();
182 }
183
184 template<int dim>
185 void SimplicialMesh<dim>::readMesh(const std::string& meshFileName,const Eigen::Matrix<double,dim,dim>& A,const Eigen::Matrix<double,dim,1>& x0,const std::set<int>& periodicFaceIDs)
186 {
187 regionBoundaries().clear();
188 _periodicSimplexPairs.clear();
189 simplices().clear();
190 _simplexFactories.clear();
191 _polyhedralMesh = std::make_shared<PolyhedralMesh<dim>>();
192 this->read(meshFileName,A,x0);
193 createMesh(periodicFaceIDs);
194 this->simplexReader().clear();
195 }
196
197 template<int dim>
199 {
200 return *this;
201 }
202
203 template<int dim>
208
209 template<int dim>
211 {
212 if(!_polyhedralMesh)
213 {
214 throw std::runtime_error("Polyhedral topology has not been built");
215 }
216 return *_polyhedralMesh;
217 }
218
219 template<int dim>
221 {
222 for(auto region : this->regions())
223 {
224 region.second->update();
225 }
226 }
227
228 template<int dim>
230 {
231 for(auto& rgnBnd : regionBoundaries())
232 {
233 rgnBnd.second.update();
234 MeshRegionType* const region1(this->region(rgnBnd.second.regionBndID.first));
235 MeshRegionType* const region2(this->region(rgnBnd.second.regionBndID.second));
236 for(const auto& face : rgnBnd.second.faces())
237 {// add each face to the region boundary to the corresponding two regions
238 region1->faces().emplace(face.second->sID,face.second);
239 region2->faces().emplace(face.second->sID,face.second);
240
241 }
242 }
243 }
244
245 template<int dim>
246 void SimplicialMesh<dim>::identifyParallelFaces(const std::set<int>& periodicFaceIDs)
247 {
248 std::vector<Polyhedron<dim,dim-1>*> faces;
249 std::set<int> available;
250 for(const auto& region : this->regions())
251 {
252 for(const auto& face : region.second->faces())
253 {
254 if(face.second->isExternal())
255 {
256 faces.push_back(face.second.get());
257 available.insert(face.second->sID);
258 }
259 }
260 }
261 for(const auto id : periodicFaceIDs)
262 {
263 if(id != -1 && !available.count(id))
264 {
265 throw std::runtime_error("Unknown external periodic face ID " + std::to_string(id));
266 }
267 }
268 const double tolerance = 1.e-8*(xMax()-xMin()).norm()
269 + 64.0*std::numeric_limits<double>::epsilon()*std::max(xMin().norm(),xMax().norm());
271 if(!periodicFaceIDs.empty())
272 {
273 const auto full = discoverPeriodicMeshLattice(faces,tolerance);
274 lattice = selectPeriodicMeshLattice(full,periodicFaceIDs,tolerance);
275 }
276 const auto& selected = lattice.pairs;
277 PeriodicSimplexPairMap<dim> simplexPairs;
278 for(const auto& entry : selected)
279 {
281 VectorDim shift;
282 if(!isPeriodicFacePair<dim>(*entry.first,*entry.second.second,shift,tolerance,&matches) ||
283 (shift-entry.second.first).norm()>tolerance)
284 {
285 throw std::runtime_error("Active periodic face has inconsistent simplex correspondence.");
286 }
287 simplexPairs.insert(matches.begin(),matches.end());
288 }
289 for(const auto& entry : simplexPairs)
290 {
291 const auto reverse=simplexPairs.find(entry.second.partner);
292 if(reverse==simplexPairs.end() || reverse->second.partner!=entry.first ||
293 (entry.second.shift+reverse->second.shift).norm()>tolerance)
294 {
295 throw std::runtime_error("Nonreciprocal periodic simplex correspondence.");
296 }
297 for(size_t i=0;i<dim;++i)
298 {
299 if(reverse->second.vertexPermutation[entry.second.vertexPermutation[i]]!=i)
300 {
301 throw std::runtime_error("Nonreciprocal periodic vertex permutation.");
302 }
303 }
304 }
305 // Commit only after face and simplex validation have both succeeded.
306 _periodicBasis = lattice.basis;
307 _periodicSimplexPairs.swap(simplexPairs);
308 for(auto* face : faces)
309 {
310 const auto found = selected.find(face);
311 face->periodicFacePair = found == selected.end()
312 ? std::make_pair(VectorDim(VectorDim::Zero()), static_cast<const Polyhedron<dim,dim-1>*>(nullptr))
313 : std::make_pair(found->second.first, static_cast<const Polyhedron<dim,dim-1>*>(found->second.second));
314 }
315 }
316
317 template<int dim>
319 {
320 return _periodicBasis;
321 }
322
323 template<int dim>
325 {
330 if (simplices().count(xID))
331 {
332 throw std::runtime_error("Duplicate volume simplex");
333 }
334 const auto simplex=this->template simplexFactory<dim>().getOrCreate(xID,regionID);
335 simplices().emplace(xID,simplex);
336 vol0+=simplex->vol0;
337 }
338
339 template<int dim>
340 std::pair<bool,const Simplex<dim,dim>*> SimplicialMesh<dim>::search(const Eigen::Matrix<double,dim,1>& P) const
341 {
349 return searchWithGuess(P,simplices().begin()->second.get());
350 }
351
352 template<int dim>
353 std::pair<bool,const Simplex<dim,dim>*> SimplicialMesh<dim>::searchWithGuess(const Eigen::Matrix<double,dim,1>& P,
354 const Simplex<dim,dim>* const guess) const
355 {
362
363 std::set<const Simplex<dim,dim>*> searchSet;
364 if(guess)
365 {
366 return searchWithGuess(true,P,guess,searchSet);
367 }
368 else
369 {
370 return searchWithGuess(true,P,simplices().begin()->second.get(),searchSet);
371 }
372 }
373
374 template<int dim>
375 std::pair<bool,const Simplex<dim,dim>*> SimplicialMesh<dim>::searchRegion(const int& regionID,
376 const Eigen::Matrix<double,dim,1>& P) const
377 {
385 return searchRegionWithGuess(P,*this->region(regionID)->simplices().begin());
386 }
387
388 template<int dim>
389 std::pair<bool,const Simplex<dim,dim>*> SimplicialMesh<dim>::searchRegionWithGuess(const Eigen::Matrix<double,dim,1>& P,
390 const Simplex<dim,dim>* const guess) const
391 {
398 std::set<const Simplex<dim,dim>*> searchSet;
399 return searchWithGuess(false,P,guess,searchSet);
400 }
401
402 template<int dim>
403 std::pair<bool,const Simplex<dim,dim>*> SimplicialMesh<dim>::searchWithGuess(const bool& searchAllRegions,
404 const Eigen::Matrix<double,dim,1>& P,
405 const Simplex<dim,dim>* const guess,
406 std::set<const Simplex<dim,dim>*>& searchSet) const
407 {
414
415 searchSet.clear();
416 std::pair<bool,const Simplex<dim,dim>*> lastSearched(false,NULL);
417 guess->convexDelaunaynSearch(searchAllRegions,P,lastSearched,searchSet);
418 checkSearch(searchAllRegions,P,guess,lastSearched);
419
420 if(!lastSearched.first)
421 {// if search was not successful, try to search neighbors of last searched Simplex
422 const std::pair<bool,const Simplex<dim,dim>*> temp(lastSearched);
423 const Eigen::Matrix<double,dim+1,1> bary=temp.second->pos2bary(P);
424 // Do not overwrite a successful result while checking another face.
425 for(int k=0;k<dim+1 && !lastSearched.first;++k)
426 {
427 if(bary(k)<=FLT_EPSILON)
428 {
429 // for(typename Simplex<dim,dim-1>::ParentContainerType::const_iterator pIter=temp.second->child(k).parentBegin();
430 // /* */ pIter!=temp.second->child(k).parentEnd();++pIter)
431 // {
432 // if((*pIter)->region->regionID==temp.second->region->regionID || searchAllRegions)
433 // {
434 // (*pIter)->convexDelaunaynSearch(searchAllRegions,P,lastSearched,searchSet);
435 // if (lastSearched.first)
436 // {
437 // break;
438 // }
439 // }
440 // }
441 for(const auto& pIter : temp.second->child(k).parents())
442 {
443 if(pIter.second->region->regionID==temp.second->region->regionID || searchAllRegions)
444 {
445 pIter.second->convexDelaunaynSearch(searchAllRegions,P,lastSearched,searchSet);
446 if (lastSearched.first)
447 {
448 break;
449 }
450 }
451 }
452 }
453 }
454
455 if(searchAllRegions)
456 {// if search is still unsuccessful, reset lastSearched to temp
457 if(!lastSearched.first && !lastSearched.second->isBoundarySimplex())
458 {
459 lastSearched=temp;
460 }
461 }
462 else
463 {// if search is still unsuccessful, reset lastSearched to temp
464 if(!lastSearched.first && !lastSearched.second->isBoundarySimplex() && !lastSearched.second->isRegionBoundarySimplex())
465 {
466 lastSearched=temp;
467 }
468 }
469 }
470
471 checkSearch(searchAllRegions,P,guess,lastSearched);
472
473 if(searchAllRegions && !lastSearched.first)
474 {
475 // The global grain assembly can be non-convex: a directed walk
476 // may hit an external face before reaching an interior point in
477 // another grain. Search each convex grain before declaring failure.
478 // Keep the original boundary simplex if the point is truly outside.
479 for(const auto& regionEntry : this->regions())
480 {
481 std::set<const Simplex<dim,dim>*> regionSearchSet;
482 const auto regional=searchWithGuess(false,P,
483 *regionEntry.second->simplices().begin(),regionSearchSet);
484 searchSet.insert(regionSearchSet.begin(),regionSearchSet.end());
485 if(regional.first)
486 {
487 return regional;
488 }
489 }
490 }
491 return lastSearched;
492 }
493
494 template<int dim>
495 void SimplicialMesh<dim>::checkSearch(const bool& searchAllRegions,
496 const Eigen::Matrix<double,dim,1>& P,
497 const Simplex<dim,dim>* const guess,
498 const std::pair<bool,const Simplex<dim,dim>*>& lastSearched) const
499 {
500 if(searchAllRegions)
501 {// Check that search was successful, or that it ended on a boundary (point outside)
502 if(!(lastSearched.first || lastSearched.second->isBoundarySimplex()))
503 {
504 std::cout<<"P="<<std::setprecision(15)<<std::scientific<<P.transpose()<<std::endl;
505 std::cout<<"guess="<<guess->xID<<std::endl;
506 std::cout<<"lastSearched="<<lastSearched.second->xID<<std::endl;
507 assert(0 && "SEARCH DID NOT END ON BOUNDARY SIMPLEX");
508 }
509 }
510 else
511 {// Check that search was successful, or that it ended on a boundary or region-boundary
512 if(!(lastSearched.first || lastSearched.second->isBoundarySimplex() || lastSearched.second->isRegionBoundarySimplex()))
513 {
514 std::cout<<"P="<<std::setprecision(15)<<std::scientific<<P.transpose()<<std::endl;
515 std::cout<<"guess="<<guess->xID<<std::endl;
516 std::cout<<"lastSearched="<<lastSearched.second->xID<<std::endl;
517 assert(0 && "SEARCH DID NOT END ON BOUNDARY/REGION-BOUNDARY SIMPLEX");
518 }
519 }
520 }
521
522 template<int dim>
523 std::pair<bool,const Simplex<dim,dim>*> SimplicialMesh<dim>::isStrictlyInsideMesh(const Eigen::Matrix<double,dim,1>& P,
524 const Simplex<dim,dim>* const guess,
525 const double& tol) const
526 {
527 std::pair<bool,const Simplex<dim,dim>*> temp(searchWithGuess(P,guess));
528 if(temp.first)
529 {
530 const Eigen::Matrix<double,dim+1,1> bary(temp.second->pos2bary(P));
531 int kMin;
532 const double baryMin(bary.minCoeff(&kMin));
533 if (std::fabs(baryMin)<tol && guess->child(kMin).isBoundarySimplex()) // on a boundary face
534 {
535 temp.first=false;
536 }
537 }
538 return temp;
539 }
540
541 template<int dim>
542 std::pair<bool,const Simplex<dim,dim>*> SimplicialMesh<dim>::isOnMeshBoundary(const Eigen::Matrix<double,dim,1>& P, const Simplex<dim,dim>* const guess, const double& tol) const
543 {
544 std::pair<bool,const Simplex<dim,dim>*> temp(searchWithGuess(P,guess));
545 if(temp.first)
546 {
547 const Eigen::Matrix<double,dim+1,1> bary(temp.second->pos2bary(P));
548 int kMin;
549 const double baryMin(bary.minCoeff(&kMin));
550 if (!(std::fabs(baryMin)<tol && guess->child(kMin).isBoundarySimplex())) // not on a boundary face
551 {
552 temp.first=false;
553 }
554 }
555 return temp;
556 }
557
558 template<int dim>
559 const Eigen::Matrix<double,dim,1>& SimplicialMesh<dim>::xMin() const
560 {
561 return _xMin;
562 }
563
564 template<int dim>
565 const double& SimplicialMesh<dim>::xMin(const int& k) const
566 {
567 return _xMin(k);
568 }
569
570 template<int dim>
571 const Eigen::Matrix<double,dim,1>& SimplicialMesh<dim>::xMax() const
572 {
573 return _xMax;
574 }
575
576 template<int dim>
577 const double& SimplicialMesh<dim>::xMax(const int& k) const
578 {
579 return _xMax(k);
580 }
581
582 template<int dim>
583 const Eigen::Matrix<double,dim,1>& SimplicialMesh<dim>::xCenter() const
584 {
585 return _xC;
586 }
587
588 template<int dim>
589 const double& SimplicialMesh<dim>::volume() const
590 {
591 return vol0;
592 }
593
594 template<int dim>
599
600 template<int dim>
605
606 template<int dim>
608 {
609 return regionBoundaries().at(std::make_pair(std::min(i,j),std::max(i,j)));
610 }
611
612 template class SimplicialMesh<1>;
613 template class SimplicialMesh<2>;
614 template class SimplicialMesh<3>;
615}
616#endif
bool isBoundarySimplex() const
Eigen::Matrix< double, dim, Eigen::Dynamic > PeriodicBasisType
const Eigen::Matrix< double, _dim, 1 > & xMax() const
std::pair< bool, const Simplex< _dim, _dim > * > searchRegion(const int &regionID, const Eigen::Matrix< double, dim, 1 > &P) const
std::pair< bool, const Simplex< _dim, _dim > * > isOnMeshBoundary(const Eigen::Matrix< double, dim, 1 > &P, const Simplex< dim, dim > *const guess, const double &tol) const
MeshRegionBoundary< dim > MeshRegionBoundaryType
std::pair< bool, const Simplex< _dim, _dim > * > searchWithGuess(const Eigen::Matrix< double, dim, 1 > &P, const Simplex< dim, dim > *const guess) const
Polyhedron< dim, dim > MeshRegionType
const PolyhedralMesh< _dim > & polyhedralMesh() const
const Eigen::Matrix< double, _dim, 1 > & xMin() const
const SimplexMapType & simplices() const
std::map< typename SimplexTraits< dim, dim >::SimplexIDType, std::shared_ptr< Simplex< dim, dim > > > SimplexMapType
const MeshRegionBoundaryType & regionBoundary(const int &i, const int &j) const
std::pair< bool, const Simplex< _dim, _dim > * > isStrictlyInsideMesh(const Eigen::Matrix< double, dim, 1 > &P, const Simplex< dim, dim > *const guess, const double &tol) const
Eigen::Matrix< double, dim, Eigen::Dynamic > periodicBasis() const
const MeshRegionBoundaryContainerType & regionBoundaries() const
const Eigen::Matrix< double, _dim, 1 > & xCenter() const
Polyhedron< _dim, _dim > * region(const size_t &id)
std::pair< bool, const Simplex< _dim, _dim > * > searchRegionWithGuess(const Eigen::Matrix< double, dim, 1 > &P, const Simplex< dim, dim > *const guess) const
void readMesh(const std::string &meshFileName, const Eigen::Matrix< double, dim, dim > &A, const Eigen::Matrix< double, dim, 1 > &x0, const std::set< int > &)
std::pair< bool, const Simplex< _dim, _dim > * > search(const Eigen::Matrix< double, dim, 1 > &P) const
void insertSimplex(const typename SimplexTraits< dim, dim >::SimplexIDType &xIN, const int &regionID)
void checkSearch(const bool &searchAllRegions, const Eigen::Matrix< double, dim, 1 > &P, const Simplex< dim, dim > *const guess, const std::pair< bool, const Simplex< dim, dim > * > &lastSearched) const
std::map< MeshRegionIDType, MeshRegionBoundaryType > MeshRegionBoundaryContainerType
const double & volume() const
function infiniteDisplacement syms Ax Ay Az Bx By Bz qx qy qz u L x y z real A
size_t InstanceCount< Derived >::count
static std::string magentaColor
PeriodicMeshLattice< dim > discoverPeriodicMeshLattice(const std::vector< Polyhedron< dim, dim-1 > * > &faces, double tolerance)
std::map< const Simplex< dim, dim-1 > *, PeriodicSimplexPair< dim > > PeriodicSimplexPairMap
PeriodicMeshLattice< dim > selectPeriodicMeshLattice(const PeriodicMeshLattice< dim > &full, const std::set< int > &seeds, double tolerance)
static std::string greenBoldColor
static std::string defaultColor
bool isPeriodicFacePair(const Polyhedron< dim, dim-1 > &a, const Polyhedron< dim, dim-1 > &b, Eigen::Matrix< double, dim, 1 > &shift, double tolerance, PeriodicSimplexPairMap< dim > *correspondence=nullptr)
Eigen::Matrix< double, 3, 1 > VectorDim
Definition pyMoDELib.cxx:66
const MeshFacesContainerType & faces() const
Definition Polyhedron.h:136
const SimplexIDType xID
Definition SimplexBase.h:31
ChildSimplexType & child(const int &n)
SimplexReaderBase< dim > & simplexReader()
void read(const int &meshID)
static SimplexIDType sortID(const SimplexIDType &vIN)
SimplexID< nVertices > SimplexIDType
std::string read(const fs::path &path)
int end[2]
int j
int elements
REAL t0
int k
int regions
int i
vertex temp