gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GModelCreateTopologyFromMesh.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <stack>
7 #include <set>
8 #include <map>
9 #include <sstream>
10 #include "OS.h"
11 #include "GModel.h"
12 #include "discreteFace.h"
13 #include "discreteEdge.h"
14 #include "discreteVertex.h"
15 #include "MPoint.h"
16 #include "MVertex.h"
17 #include "MLine.h"
18 #include "MEdge.h"
19 #include "MFace.h"
20 #include "MTriangle.h"
21 #include "MQuadrangle.h"
22 #include "MTetrahedron.h"
23 #include "MHexahedron.h"
24 #include "MPrism.h"
25 #include "MPyramid.h"
26 #include "Context.h"
27 
28 // Assumption: The input mesh is potentially (partially) coloured
29 
30 bool topoExists(GModel *gm)
31 {
32  for(auto it = gm->firstEdge(); it != gm->lastEdge(); it++) {
33  GEdge *ge = *it;
34  if(!ge->getBeginVertex() || !ge->getEndVertex()) return false;
35  }
36  for(auto it = gm->firstFace(); it != gm->lastFace(); it++) {
37  GFace *gf = *it;
38  if(gf->edges().empty()) return false;
39  }
40  for(auto it = gm->firstRegion(); it != gm->lastRegion(); it++) {
41  GRegion *gr = *it;
42  if(gr->faces().empty()) return false;
43  }
44  return true;
45 }
46 
47 // FIXME: Two times the same MLine in each connected part if periodic
48 std::vector<GEdge *> ensureSimplyConnectedEdge(GEdge *ge)
49 {
50  std::vector<GEdge *> _all;
51  std::set<MLine *> _lines;
52  std::map<MVertex *, std::pair<MLine *, MLine *> > _conn;
53 
54  _all.push_back(ge);
55 
56  // create vertex to edge connectivity: only two neighbors are considered...
57  for(std::size_t i = 0; i < ge->lines.size(); i++) {
58  _lines.insert(ge->lines[i]);
59  for(int j = 0; j < 2; j++) {
60  auto it = _conn.find(ge->lines[i]->getVertex(j));
61  if(it == _conn.end())
62  _conn[ge->lines[i]->getVertex(j)] =
63  std::make_pair(ge->lines[i], (MLine *)nullptr);
64  else
65  it->second.second = ge->lines[i];
66  }
67  }
68 
69  std::vector<std::vector<MLine *> > _parts;
70  while(!_lines.empty()) {
71  std::stack<MLine *> _stack;
72  _stack.push(*_lines.begin());
73  std::vector<MLine *> _part;
74  while(!_stack.empty()) {
75  MLine *l = _stack.top();
76  _stack.pop();
77  _lines.erase(l);
78  // avoid adding twice the last one
79  if(!_part.size() || _part[_part.size() - 1] != l) { _part.push_back(l); }
80  for(int j = 0; j < 2; j++) {
81  auto it = _conn.find(l->getVertex(j));
82  if(it->second.first == l && it->second.second != nullptr &&
83  _lines.find(it->second.second) != _lines.end()) {
84  _stack.push(it->second.second);
85  }
86  else if(it->second.second == l &&
87  _lines.find(it->second.first) != _lines.end()) {
88  _stack.push(it->second.first);
89  }
90  }
91  }
92  _parts.push_back(_part);
93  }
94 
95  if(_parts.empty()) {
96  Msg::Warning("No connected part found in Curve %d", ge->tag());
97  }
98  else if(_parts.size() > 1) {
99  Msg::Info("Curve %d is not simply connected: splitting it in %d parts",
100  ge->tag(), _parts.size());
101  }
102 
103  for(size_t i = 0; i < _parts.size(); i++) {
104  if(i == 0)
105  ge->lines = _parts[i];
106  else {
107  discreteEdge *newE = new discreteEdge(
108  ge->model(), ge->model()->getMaxElementaryNumber(1) + 1, nullptr,
109  nullptr);
110  ge->model()->add(newE);
111  newE->lines = _parts[i];
112  _all.push_back(newE);
113  }
114  }
115  return _all;
116 }
117 
118 void assignFace(GFace *gf, std::set<MElement *> &_f)
119 {
120  gf->triangles.clear();
121  gf->quadrangles.clear();
122  for(auto it = _f.begin(); it != _f.end(); ++it) {
123  if((*it)->getNumVertices() == 3)
124  gf->triangles.push_back((MTriangle *)*it);
125  else if((*it)->getNumVertices() == 4)
126  gf->quadrangles.push_back((MQuadrangle *)*it);
127  }
128 }
129 
131 {
132  std::map<MEdge, std::pair<MElement *, MElement *>, MEdgeLessThan> _pairs;
133  std::set<MEdge, MEdgeLessThan> _nonManifold;
134 
135  std::set<MElement *> _allFaces;
136 
137  for(std::size_t i = 0; i < gf->getNumMeshElements(); i++) {
138  MElement *e = gf->getMeshElement(i);
139  _allFaces.insert(e);
140  for(int j = 0; j < e->getNumEdges(); j++) {
141  MEdge ed = e->getEdge(j);
142  if(_nonManifold.find(ed) == _nonManifold.end()) {
143  auto it = _pairs.find(ed);
144  if(it == _pairs.end()) {
145  _pairs[ed] = std::make_pair(e, (MElement *)nullptr);
146  }
147  else {
148  if(it->second.second == nullptr) { it->second.second = e; }
149  else {
150  _nonManifold.insert(ed);
151  _pairs.erase(it);
152  }
153  }
154  }
155  }
156  }
157  if(_nonManifold.empty()) return;
158 
159  std::vector<std::set<MElement *> > _sub;
160  while(!_allFaces.empty()) {
161  std::stack<MElement *> _stack;
162  _stack.push(*_allFaces.begin());
163  std::set<MElement *> _f;
164  while(!_stack.empty()) {
165  MElement *e = _stack.top();
166  _allFaces.erase(e);
167  _stack.pop();
168  _f.insert(e);
169  for(int j = 0; j < e->getNumEdges(); j++) {
170  MEdge ed = e->getEdge(j);
171  if(_nonManifold.find(ed) == _nonManifold.end()) {
172  auto it = _pairs.find(ed);
173  if(it->second.second != nullptr) {
174  MElement *other =
175  it->second.second == e ? it->second.first : it->second.second;
176  if(_f.find(other) == _f.end()) _stack.push(other);
177  }
178  }
179  }
180  }
181  _sub.push_back(_f);
182  }
183 
184  Msg::Info("Surface %d is non-manifold: splitting it in %d parts", gf->tag(),
185  _sub.size());
186 
187  for(std::size_t i = 0; i < _sub.size(); i++) {
188  if(i == 0)
189  assignFace(gf, _sub[i]);
190  else {
191  discreteFace *newF = new discreteFace(
192  gf->model(), gf->model()->getMaxElementaryNumber(2) + 1);
193  gf->model()->add(newF);
194  assignFace(newF, _sub[i]);
195  }
196  }
197 }
198 
200 {
201  std::vector<GFace *> f;
202  for(auto it = gm->firstFace(); it != gm->lastFace(); it++) f.push_back(*it);
203  for(std::size_t i = 0; i < f.size(); i++) ensureManifoldFace(f[i]);
204 }
205 
206 typedef std::map<MVertex *, std::set<GEdge *> > MVertexToGEdgesMap;
207 typedef std::map<MVertex *, GVertex *> MVertexToGVertexMap;
208 typedef std::map<GEdge *, std::set<GVertex *> > GEdgeToGVerticesMap;
209 typedef std::map<std::set<GEdge *>, GVertex *> GEdgesToGVertexMap;
210 
211 void createTopologyFromMesh1D(GModel *gm, int &num)
212 {
213  // list all existing GVertex
214 
215  MVertexToGVertexMap mVertexToGVertex;
216 
217  for(auto it = gm->firstVertex(); it != gm->lastVertex(); it++) {
218  GVertex *gv = *it;
219  if(gv->mesh_vertices.size()) {
220  MVertex *mv = gv->mesh_vertices[0];
221  mVertexToGVertex[mv] = gv;
222  Msg::Debug("The model already has point %i, containing node %i",
223  gv->tag(), mv->getNum());
224  }
225  }
226 
227  // create bundles of edges for each MVertex on the GEdge; if GVertex already
228  // present, link it to the GEdge
229 
230  MVertexToGEdgesMap mVertexToGEdges;
231  GEdgeToGVerticesMap gEdgeToGVertices;
232 
233  for(auto it = gm->firstEdge(); it != gm->lastEdge(); it++) {
234  GEdge *ge = *it;
235  for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
236  MLine *e = (*it)->lines[i];
237  for(int j = 0; j < 2; j++) {
238  MVertex *mv = e->getVertex(j);
239  auto gIter = mVertexToGVertex.find(mv);
240  if(gIter != mVertexToGVertex.end())
241  gEdgeToGVertices[ge].insert(gIter->second);
242  else {
243  auto it = mVertexToGEdges.find(mv);
244  if(it != mVertexToGEdges.end() &&
245  it->second.find(ge) != it->second.end()) {
246  // in bulk
247  mVertexToGEdges.erase(it);
248  }
249  else {
250  mVertexToGEdges[mv].insert(ge);
251  }
252  }
253  }
254  }
255  }
256 
257  // now create any missing GVertex
258 
259  for(auto mvIter = mVertexToGEdges.begin(); mvIter != mVertexToGEdges.end();
260  ++mvIter) {
261  MVertex *mv = mvIter->first;
262  std::set<GEdge *> &gEdges = mvIter->second;
263  num++;
264  discreteVertex *dv = new discreteVertex(
265  gm, gm->getMaxElementaryNumber(0) + 1, mv->x(), mv->y(), mv->z());
266  gm->add(dv);
267  mVertexToGVertex[mv] = dv;
268  MPoint *mp = new MPoint(mv);
269  dv->points.push_back(mp);
270  for(auto gEIter = gEdges.begin(); gEIter != gEdges.end(); ++gEIter) {
271  GEdge *ge = *gEIter;
272  gEdgeToGVertices[ge].insert(dv);
273  }
274  }
275 
276  // link all GEdge to GVertex and vice versa (we expect to see two GVertex per
277  // GEdge unless it is periodic!)
278 
279  for(auto gEIter = gEdgeToGVertices.begin(); gEIter != gEdgeToGVertices.end();
280  ++gEIter) {
281  GEdge *ge = gEIter->first;
282  std::set<GVertex *> gVerts = gEIter->second;
283 
284  if(gVerts.size() == 2) {
285  GVertex *gv1 = *(gVerts.begin());
286  GVertex *gv2 = *(gVerts.rbegin());
287 
288  ge->setBeginVertex(gv1);
289  ge->setEndVertex(gv2);
290 
291  gv1->addEdge(ge);
292  gv2->addEdge(ge);
293  }
294  else {
295  std::vector<GEdge *> splits = ensureSimplyConnectedEdge(ge);
296  if(splits.size() == 1) { // periodic case
297  GVertex *gv1 = *(gVerts.begin());
298  ge->setBeginVertex(gv1);
299  ge->setEndVertex(gv1);
300  gv1->addEdge(ge);
301  }
302  else {
303  std::ostringstream gVertexList;
304  for(auto gvIter = gVerts.begin(); gvIter != gVerts.end(); ++gvIter) {
305  gVertexList << " " << (*gvIter)->tag();
306  }
307  Msg::Error(
308  "Found single/multiply ended GEdge %i in model (GVertices:%s)",
309  ge->tag(), gVertexList.str().c_str());
310  }
311  }
312  }
313 
314  // add GVertex for self-intersecting GEdge; we still need to check this is
315  // actually the case...
316 
317  for(auto it = gm->firstEdge(); it != gm->lastEdge(); it++) {
318  if(!(*it)->getBeginVertex() || !(*it)->getEndVertex()) {
319  num++;
320  MVertex *v = (*it)->lines[0]->getVertex(0);
321  discreteVertex *dv = new discreteVertex(
322  gm, gm->getMaxElementaryNumber(0) + 1, v->x(), v->y(), v->z());
323  gm->add(dv);
324  MPoint *mp = new MPoint(v);
325  dv->points.push_back(mp);
326  dv->addEdge(*it);
327  (*it)->setBeginVertex(dv);
328  (*it)->setEndVertex(dv);
329  gEdgeToGVertices[*it].insert(dv);
330  }
331  }
332 }
333 
334 class topoEdge {
335 protected:
338  std::pair<int, int> ids;
339 
340 public:
341  const MElement *getParent() const { return parent; }
342  const int getIndex() const { return edgeIndex; }
343  const int getType() const { return TYPE_LIN; }
344 
345  inline bool operator==(const topoEdge &f) const { return ids == f.ids; }
346  inline bool operator<(const topoEdge &f) const { return ids < f.ids; }
347 
348  topoEdge(MElement *elt, int num)
349  {
350  parent = elt;
351  edgeIndex = num;
352  MEdge edge = elt->getEdge(num);
353 
354  int id0 = edge.getVertex(0)->getNum();
355  int id1 = edge.getVertex(1)->getNum();
356 
357  if(id0 > id1) std::swap(id0, id1);
358 
359  ids.first = id0;
360  ids.second = id1;
361  }
362 };
363 
364 typedef std::map<topoEdge, std::set<GFace *> > TEdgeToGFacesMap;
365 typedef std::map<topoEdge, GEdge *> TEdgeToGEdgeMap;
366 typedef std::map<GFace *, std::set<GEdge *> > GFaceToGEdgesMap;
367 typedef std::map<std::set<GFace *>, GEdge *> GFacesToGEdgeMap;
368 
369 void createTopologyFromMesh2D(GModel *gm, int &num)
370 {
371  // create an inverse dictionnary for existing edges
372 
373  TEdgeToGEdgeMap tEdgeToGEdge;
374 
375  for(auto it = gm->firstEdge(); it != gm->lastEdge(); it++) {
376  GEdge *ge = *it;
377  for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
378  topoEdge te(ge->lines[i], 0);
379  tEdgeToGEdge[te] = ge;
380  }
381  }
382 
383  // create a list of face intersections and elements on that intersection
384 
385  TEdgeToGFacesMap tEdgeToGFaces;
386  GFaceToGEdgesMap gFaceToGEdges;
387 
388  for(auto it = gm->firstFace(); it != gm->lastFace(); it++) {
389  GFace *gf = *it;
390  for(std::size_t i = 0; i < (*it)->getNumMeshElements(); i++) {
391  MElement *e = (*it)->getMeshElement(i);
392  if(e->getDim() == 2) {
393  for(int j = 0; j < e->getNumEdges(); j++) {
394  topoEdge te(e, j);
395  auto eIter = tEdgeToGEdge.find(te);
396  if(eIter != tEdgeToGEdge.end())
397  gFaceToGEdges[gf].insert(eIter->second);
398  else {
399  auto it = tEdgeToGFaces.find(te);
400  if(it != tEdgeToGFaces.end() &&
401  it->second.find(gf) != it->second.end()) {
402  // in bulk
403  tEdgeToGFaces.erase(it);
404  }
405  else {
406  tEdgeToGFaces[te].insert(gf);
407  }
408  }
409  }
410  }
411  }
412  }
413 
414  // create a GEdge for each face boundary, ie. for which edges have been
415  // visited once
416 
417  GFacesToGEdgeMap gFacesToGEdge;
418 
419  for(auto it = tEdgeToGFaces.begin(); it != tEdgeToGFaces.end(); ++it) {
420  std::set<GFace *> &gfaces = it->second;
421  auto gfIter = gFacesToGEdge.find(gfaces);
422  if(gfIter == gFacesToGEdge.end()) {
423  discreteEdge *de = new discreteEdge(gm, gm->getMaxElementaryNumber(1) + 1,
424  nullptr, nullptr);
425  num++;
426  gm->add(de);
427  auto gfIter = gfaces.begin();
428  for(; gfIter != gfaces.end(); ++gfIter) gFaceToGEdges[*gfIter].insert(de);
429  gFacesToGEdge[gfaces] = de;
430  }
431  }
432 
433  // create elements on new geometric edges
434 
435  MElementFactory eltFactory;
436 
437  for(auto it = tEdgeToGFaces.begin(); it != tEdgeToGFaces.end(); ++it) {
438  const topoEdge &te = it->first;
439  std::set<GFace *> &gfaces = it->second;
440 
441  auto gfIter = gFacesToGEdge.find(gfaces);
442 
443  if(gfIter != gFacesToGEdge.end()) {
444  GEdge *ge = gfIter->second;
445 
446  const MElement *parent = te.getParent();
447  int edgeIndex = te.getIndex();
448 
449  std::vector<MVertex *> vtcs;
450  parent->getEdgeVertices(edgeIndex, vtcs);
451 
452  int type = te.getType();
453  int order = parent->getPolynomialOrder();
454  bool serendipity = parent->getIsOnlySerendipity();
455 
456  int tag = ElementType::getType(type, order, serendipity);
457 
458  MLine *edge = dynamic_cast<MLine *>(eltFactory.create(tag, vtcs));
459 
460  ge->lines.push_back(edge);
461  }
462  }
463 
464  std::map<GEdge *, std::vector<GEdge *> > splitEdge;
465  for(auto it = gm->firstEdge(); it != gm->lastEdge(); it++) {
466  std::vector<GEdge *> split = ensureSimplyConnectedEdge(*it);
467  if(split.size() != 1) splitEdge[*it] = split;
468  }
469 
470  // add split edges to face map
471 
472  for(auto gfToge = gFaceToGEdges.begin(); gfToge != gFaceToGEdges.end();
473  ++gfToge) {
474  std::set<GEdge *> &edgeSet = gfToge->second;
475  std::set<GEdge *> newEdgeSet;
476  auto eIter = edgeSet.begin();
477  for(; eIter != edgeSet.end(); ++eIter) {
478  auto pIter = splitEdge.find(*eIter);
479  if(pIter != splitEdge.end()) {
480  std::vector<GEdge *> &edges = pIter->second;
481  newEdgeSet.insert(edges.begin(), edges.end());
482  }
483  }
484  edgeSet.insert(newEdgeSet.begin(), newEdgeSet.end());
485  }
486 
487  // connect GEdges and GFaces
488 
489  for(auto gfToge = gFaceToGEdges.begin(); gfToge != gFaceToGEdges.end();
490  ++gfToge) {
491  GFace *gf = gfToge->first;
492  std::set<GEdge *> &gEdgeSet = gfToge->second;
493 
494  std::vector<GEdge *> gEdges;
495  gEdges.insert(gEdges.begin(), gEdgeSet.begin(), gEdgeSet.end());
496 
497  gf->set(gEdges);
498  auto eIter = gEdgeSet.begin();
499  for(; eIter != gEdgeSet.end(); eIter++) (*eIter)->addFace(gf);
500  }
501 }
502 
503 class topoFace {
504 protected:
507  std::set<int> vtcs;
508 
509 public:
510  const std::set<int> &getVertices() const { return vtcs; }
511 
512  const MElement *getParent() const { return parent; }
513  const int getIndex() const { return faceIndex; }
514  const int getType() const
515  {
516  switch(vtcs.size()) {
517  case 3: return TYPE_TRI; break;
518  case 4: return TYPE_QUA; break;
519  default: return vtcs.size() > 4 ? TYPE_POLYG : -1; break;
520  }
521  }
522 
523  inline bool operator==(const topoFace &f) const { return vtcs == f.vtcs; }
524  inline bool operator<(const topoFace &f) const { return vtcs < f.vtcs; }
525 
526  topoFace(MElement *elt, int num)
527  {
528  parent = elt;
529  faceIndex = num;
530 
531  std::vector<MVertex *> tmp;
532  MFace face = elt->getFace(num);
533 
534  for(std::size_t i = 0; i < face.getNumVertices(); i++) {
535  vtcs.insert(face.getVertex(i)->getNum());
536  }
537  }
538 };
539 
540 typedef std::map<topoFace, GFace *> TFaceToGFaceMap;
541 typedef std::map<topoFace, std::pair<GRegion *, GRegion *> >
543 typedef std::map<GRegion *, std::set<GFace *> > GRegionToGFacesMap;
544 typedef std::set<std::pair<GRegion *, GRegion *> > GRegionPairSet;
545 typedef std::map<std::pair<GRegion *, GRegion *>, GFace *>
547 
548 void createTopologyFromMesh3D(GModel *gm, int &num)
549 {
550  // create an inverse dictionary for existing faces
551 
552  TFaceToGFaceMap tFaceToGFace;
553  for(auto it = gm->firstFace(); it != gm->lastFace(); it++) {
554  for(unsigned i = 0; i < (*it)->triangles.size(); i++) {
555  topoFace tf((*it)->triangles[i], 0);
556  tFaceToGFace.insert(std::make_pair(tf, *it));
557  }
558  for(unsigned i = 0; i < (*it)->quadrangles.size(); i++) {
559  topoFace tf((*it)->quadrangles[i], 0);
560  tFaceToGFace.insert(std::make_pair(tf, *it));
561  }
562  }
563 
564  // create inverse dictionary for all other faces; this is the most time
565  // consuming part!
566 
567  TFaceToGRegionPairMap tFaceToGRegionPair;
568  GRegionToGFacesMap gRegionToGFaces;
569 
570  for(auto it = gm->firstRegion(); it != gm->lastRegion(); it++) {
571  GRegion *gr = *it;
572  for(unsigned i = 0; i < gr->getNumMeshElements(); i++) {
573  MElement *e = gr->getMeshElement(i);
574  for(int j = 0; j < e->getNumFaces(); j++) {
575  topoFace f(e, j);
576  auto ffIter = tFaceToGFace.find(f);
577  if(ffIter != tFaceToGFace.end())
578  gRegionToGFaces[gr].insert(ffIter->second);
579  else {
580  auto frIter = tFaceToGRegionPair.find(f);
581  if(frIter == tFaceToGRegionPair.end()) {
582  tFaceToGRegionPair[f] = std::make_pair((GRegion *)nullptr, *it);
583  }
584  else
585  frIter->second.first = gr;
586  }
587  }
588  }
589  }
590 
591  // create new GFace for each pair of connected GRegion
592 
593  GRegionPairToGFaceMap gRegionPairToGFace;
594 
595  auto it = tFaceToGRegionPair.begin();
596  for(; it != tFaceToGRegionPair.end(); ++it) {
597  GRegion *r1 = it->second.first;
598  GRegion *r2 = it->second.second;
599  if(r1 != r2) {
600  std::pair<GRegion *, GRegion *> gRegionPair;
601  if(r1 && r2)
602  gRegionPair = std::make_pair(std::min(r1, r2), std::max(r1, r2));
603  else // r1 null
604  gRegionPair = std::make_pair(r1, r2);
605  auto iter = gRegionPairToGFace.find(gRegionPair);
606  if(iter == gRegionPairToGFace.end()) {
607  discreteFace *df =
608  new discreteFace(gm, gm->getMaxElementaryNumber(2) + 1);
609  num++;
610  gm->add(df);
611  if(r1) gRegionToGFaces[r1].insert(df);
612  if(r2) gRegionToGFaces[r2].insert(df);
613  gRegionPairToGFace[gRegionPair] = df;
614  }
615  }
616  }
617 
618  // create elements on new geometric faces
619 
620  MElementFactory eltFactory;
621  for(it = tFaceToGRegionPair.begin(); it != tFaceToGRegionPair.end(); ++it) {
622  const topoFace &tf = it->first;
623  std::pair<GRegion *, GRegion *> grPair = it->second;
624 
625  auto grTogfIter = gRegionPairToGFace.find(grPair);
626 
627  if(grTogfIter != gRegionPairToGFace.end()) {
628  GFace *gf = grTogfIter->second;
629 
630  const MElement *parent = tf.getParent();
631  int faceIndex = tf.getIndex();
632 
633  std::vector<MVertex *> vtcs;
634  parent->getFaceVertices(faceIndex, vtcs);
635 
636  int type = tf.getType();
637  int order = parent->getPolynomialOrder();
638  bool serendipity = parent->getIsOnlySerendipity();
639  int tag = ElementType::getType(type, order, serendipity);
640 
641  MElement *face = eltFactory.create(tag, vtcs);
642 
643  if(parent->getType() != TYPE_PYR) {
644  if(type == TYPE_TRI) gf->triangles.push_back((MTriangle *)face);
645  if(type == TYPE_QUA) gf->quadrangles.push_back((MQuadrangle *)face);
646  }
647  }
648  }
649 
650  // now connect GFaces to GRegions and vice versa
651 
652  auto itTo = gRegionToGFaces.begin();
653  for(; itTo != gRegionToGFaces.end(); ++itTo) {
654  GRegion *gr = itTo->first;
655  std::vector<GFace *> faces;
656  faces.insert(faces.begin(), itTo->second.begin(), itTo->second.end());
657  gr->set(faces);
658  for(auto it3 = faces.begin(); it3 != faces.end(); ++it3)
659  (*it3)->addRegion(itTo->first);
660  }
661 }
662 
664 {
665  if(topoExists(this)) {
666  Msg::Info("Topology exists: no need to create one from mesh");
667  return;
668  }
669 
670  const int dim = getDim();
671  double t1 = Cpu(), w1 = TimeOfDay();
672 
673  Msg::Info("Creating topology from mesh...");
674  int numF = 0, numE = 0, numV = 0;
675  if(dim >= 3)
676  createTopologyFromMesh3D(this, numF);
677  else
678  ensureManifoldFaces(this);
679  if(dim >= 2) createTopologyFromMesh2D(this, numE);
680  if(dim >= 1) createTopologyFromMesh1D(this, numV);
681 
683 
685 
686  double t2 = Cpu(), w2 = TimeOfDay();
687  Msg::Info("Done creating topology from mesh (Wall %gs, CPU %gs)", w2 - w1,
688  t2 - t1);
689 }
GVertex::addEdge
void addEdge(GEdge *e)
Definition: GVertex.cpp:37
MElement::getIsOnlySerendipity
virtual bool getIsOnlySerendipity() const
Definition: MElement.h:86
MTriangle.h
TimeOfDay
double TimeOfDay()
Definition: OS.cpp:399
GModel::firstEdge
eiter firstEdge()
Definition: GModel.h:356
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
MEdge
Definition: MEdge.h:14
std::swap
void swap(picojson::value &x, picojson::value &y)
Definition: picojson.h:1136
createTopologyFromMesh3D
void createTopologyFromMesh3D(GModel *gm, int &num)
Definition: GModelCreateTopologyFromMesh.cpp:548
GModel::getMaxElementaryNumber
int getMaxElementaryNumber(int dim)
Definition: GModel.cpp:817
TYPE_LIN
#define TYPE_LIN
Definition: GmshDefines.h:65
MLine::getVertex
virtual MVertex * getVertex(int num)
Definition: MLine.h:45
GFace
Definition: GFace.h:33
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
GEntity::model
GModel * model() const
Definition: GEntity.h:277
MElementFactory
Definition: MElement.h:517
OS.h
MElement::getFaceVertices
virtual void getFaceVertices(const int num, std::vector< MVertex * > &v) const
Definition: MElement.h:225
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
topoFace::vtcs
std::set< int > vtcs
Definition: GModelCreateTopologyFromMesh.cpp:507
TFaceToGRegionPairMap
std::map< topoFace, std::pair< GRegion *, GRegion * > > TFaceToGRegionPairMap
Definition: GModelCreateTopologyFromMesh.cpp:542
discreteEdge
Definition: discreteEdge.h:12
MVertex
Definition: MVertex.h:24
MElement::getDim
virtual int getDim() const =0
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertexToGEdgesMap
std::map< MVertex *, std::set< GEdge * > > MVertexToGEdgesMap
Definition: GModelCreateTopologyFromMesh.cpp:206
MVertex::z
double z() const
Definition: MVertex.h:62
GEdge::setEndVertex
void setEndVertex(GVertex *gv)
Definition: GEdge.h:62
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
MVertex::getNum
std::size_t getNum() const
Definition: MVertex.h:86
GEdgeToGVerticesMap
std::map< GEdge *, std::set< GVertex * > > GEdgeToGVerticesMap
Definition: GModelCreateTopologyFromMesh.cpp:208
GRegion::set
void set(std::vector< GFace * > const &f)
Definition: GRegion.h:67
TYPE_TRI
#define TYPE_TRI
Definition: GmshDefines.h:66
MVertexToGVertexMap
std::map< MVertex *, GVertex * > MVertexToGVertexMap
Definition: GModelCreateTopologyFromMesh.cpp:207
GRegion::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GRegion.cpp:60
MPoint.h
GModel::firstVertex
viter firstVertex()
Definition: GModel.h:357
MElement::getEdgeVertices
virtual void getEdgeVertices(const int num, std::vector< MVertex * > &v) const
Definition: MElement.h:221
topoFace::getVertices
const std::set< int > & getVertices() const
Definition: GModelCreateTopologyFromMesh.cpp:510
topoEdge::getIndex
const int getIndex() const
Definition: GModelCreateTopologyFromMesh.cpp:342
MLine.h
edges
static int edges[6][2]
Definition: meshGRegionLocalMeshMod.cpp:23
w1
const double w1
Definition: GaussQuadratureHex.cpp:18
TEdgeToGEdgeMap
std::map< topoEdge, GEdge * > TEdgeToGEdgeMap
Definition: GModelCreateTopologyFromMesh.cpp:365
MEdgeLessThan
Definition: MEdge.h:122
topoFace::getIndex
const int getIndex() const
Definition: GModelCreateTopologyFromMesh.cpp:513
topoFace::topoFace
topoFace(MElement *elt, int num)
Definition: GModelCreateTopologyFromMesh.cpp:526
topoEdge::operator<
bool operator<(const topoEdge &f) const
Definition: GModelCreateTopologyFromMesh.cpp:346
GFace::quadrangles
std::vector< MQuadrangle * > quadrangles
Definition: GFace.h:429
discreteVertex.h
MLine
Definition: MLine.h:21
GVertex::points
std::vector< MPoint * > points
Definition: GVertex.h:120
topoFace::faceIndex
int faceIndex
Definition: GModelCreateTopologyFromMesh.cpp:506
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
GRegion::faces
virtual std::vector< GFace * > faces() const
Definition: GRegion.h:64
MElement::getEdge
virtual MEdge getEdge(int num) const =0
GModel::lastFace
fiter lastFace()
Definition: GModel.h:359
MFace
Definition: MFace.h:20
discreteVertex
Definition: discreteVertex.h:15
GFaceToGEdgesMap
std::map< GFace *, std::set< GEdge * > > GFaceToGEdgesMap
Definition: GModelCreateTopologyFromMesh.cpp:366
MFace.h
createTopologyFromMesh2D
void createTopologyFromMesh2D(GModel *gm, int &num)
Definition: GModelCreateTopologyFromMesh.cpp:369
MEdge::getVertex
MVertex * getVertex(std::size_t i) const
Definition: MEdge.h:39
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MElement::getType
virtual int getType() const =0
MHexahedron.h
createTopologyFromMesh1D
void createTopologyFromMesh1D(GModel *gm, int &num)
Definition: GModelCreateTopologyFromMesh.cpp:211
GModel::lastVertex
viter lastVertex()
Definition: GModel.h:361
MElement::getNumFaces
virtual int getNumFaces()=0
GVertex
Definition: GVertex.h:23
topoEdge::edgeIndex
int edgeIndex
Definition: GModelCreateTopologyFromMesh.cpp:337
GFacesToGEdgeMap
std::map< std::set< GFace * >, GEdge * > GFacesToGEdgeMap
Definition: GModelCreateTopologyFromMesh.cpp:367
MVertex.h
ElementType::getType
int getType(int parentType, int order, bool serendip=false)
Definition: ElementType.cpp:757
GModel::getDim
int getDim() const
Definition: GModel.cpp:989
ensureSimplyConnectedEdge
std::vector< GEdge * > ensureSimplyConnectedEdge(GEdge *ge)
Definition: GModelCreateTopologyFromMesh.cpp:48
MElement::getFace
virtual MFace getFace(int num) const =0
GModel
Definition: GModel.h:44
topoEdge::getParent
const MElement * getParent() const
Definition: GModelCreateTopologyFromMesh.cpp:341
Cpu
double Cpu()
Definition: OS.cpp:366
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
GModel::createTopologyFromMesh
void createTopologyFromMesh()
Definition: GModelCreateTopologyFromMesh.cpp:663
MFace::getVertex
MVertex * getVertex(std::size_t i) const
Definition: MFace.h:30
MPyramid.h
GModel::firstFace
fiter firstFace()
Definition: GModel.h:355
topoFace::operator<
bool operator<(const topoFace &f) const
Definition: GModelCreateTopologyFromMesh.cpp:524
GModel::add
bool add(GRegion *r)
Definition: GModel.h:394
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
GRegionPairToGFaceMap
std::map< std::pair< GRegion *, GRegion * >, GFace * > GRegionPairToGFaceMap
Definition: GModelCreateTopologyFromMesh.cpp:546
GRegionPairSet
std::set< std::pair< GRegion *, GRegion * > > GRegionPairSet
Definition: GModelCreateTopologyFromMesh.cpp:544
MElement
Definition: MElement.h:30
GEntity::tag
int tag() const
Definition: GEntity.h:280
discreteFace.h
topoEdge::operator==
bool operator==(const topoEdge &f) const
Definition: GModelCreateTopologyFromMesh.cpp:345
topoFace::parent
MElement * parent
Definition: GModelCreateTopologyFromMesh.cpp:505
GRegion
Definition: GRegion.h:28
topoFace::getParent
const MElement * getParent() const
Definition: GModelCreateTopologyFromMesh.cpp:512
GFace::getMeshElement
MElement * getMeshElement(std::size_t index) const
Definition: GFace.cpp:234
topoEdge::getType
const int getType() const
Definition: GModelCreateTopologyFromMesh.cpp:343
MTriangle
Definition: MTriangle.h:26
TYPE_PYR
#define TYPE_PYR
Definition: GmshDefines.h:69
MElementFactory::create
MElement * create(int type, std::vector< MVertex * > &v, std::size_t num=0, int part=0, bool owner=false, int parent=0, MElement *parent_ptr=nullptr, MElement *d1=nullptr, MElement *d2=nullptr)
Definition: MElement.cpp:2556
LegendrePolynomials::df
void df(int n, double u, double *val)
Definition: orthogonalBasis.cpp:103
contextMeshOptions::changed
int changed
Definition: Context.h:82
GModel::firstRegion
riter firstRegion()
Definition: GModel.h:354
topoFace::operator==
bool operator==(const topoFace &f) const
Definition: GModelCreateTopologyFromMesh.cpp:523
TYPE_QUA
#define TYPE_QUA
Definition: GmshDefines.h:67
GModel::lastRegion
riter lastRegion()
Definition: GModel.h:358
TYPE_POLYG
#define TYPE_POLYG
Definition: GmshDefines.h:72
MEdge.h
discreteEdge.h
ENT_ALL
#define ENT_ALL
Definition: GmshDefines.h:235
Context.h
MTetrahedron.h
MQuadrangle.h
topoEdge::ids
std::pair< int, int > ids
Definition: GModelCreateTopologyFromMesh.cpp:338
MPoint
Definition: MPoint.h:16
GEdge
Definition: GEdge.h:26
topoEdge::topoEdge
topoEdge(MElement *elt, int num)
Definition: GModelCreateTopologyFromMesh.cpp:348
GModel::pruneMeshVertexAssociations
void pruneMeshVertexAssociations()
Definition: GModel.cpp:2527
MPrism.h
topoEdge::parent
MElement * parent
Definition: GModelCreateTopologyFromMesh.cpp:336
GEdge::setBeginVertex
void setBeginVertex(GVertex *gv)
Definition: GEdge.h:61
ensureManifoldFace
void ensureManifoldFace(GFace *gf)
Definition: GModelCreateTopologyFromMesh.cpp:130
GModel::lastEdge
eiter lastEdge()
Definition: GModel.h:360
GModel.h
MFace::getNumVertices
std::size_t getNumVertices() const
Definition: MFace.h:29
topoEdge
Definition: GModelCreateTopologyFromMesh.cpp:334
ensureManifoldFaces
void ensureManifoldFaces(GModel *gm)
Definition: GModelCreateTopologyFromMesh.cpp:199
MVertex::y
double y() const
Definition: MVertex.h:61
MElement::getPolynomialOrder
virtual int getPolynomialOrder() const
Definition: MElement.h:78
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
assignFace
void assignFace(GFace *gf, std::set< MElement * > &_f)
Definition: GModelCreateTopologyFromMesh.cpp:118
TEdgeToGFacesMap
std::map< topoEdge, std::set< GFace * > > TEdgeToGFacesMap
Definition: GModelCreateTopologyFromMesh.cpp:364
GFace::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GFace.cpp:181
GEdgesToGVertexMap
std::map< std::set< GEdge * >, GVertex * > GEdgesToGVertexMap
Definition: GModelCreateTopologyFromMesh.cpp:209
TFaceToGFaceMap
std::map< topoFace, GFace * > TFaceToGFaceMap
Definition: GModelCreateTopologyFromMesh.cpp:540
MElement::getNumEdges
virtual int getNumEdges() const =0
GRegionToGFacesMap
std::map< GRegion *, std::set< GFace * > > GRegionToGFacesMap
Definition: GModelCreateTopologyFromMesh.cpp:543
MQuadrangle
Definition: MQuadrangle.h:26
topoFace::getType
const int getType() const
Definition: GModelCreateTopologyFromMesh.cpp:514
topoExists
bool topoExists(GModel *gm)
Definition: GModelCreateTopologyFromMesh.cpp:30
GRegion::getMeshElement
MElement * getMeshElement(std::size_t index) const
Definition: GRegion.cpp:127
GFace::set
void set(const std::vector< GEdge * > &f)
Definition: GFace.h:125
topoFace
Definition: GModelCreateTopologyFromMesh.cpp:503
MVertex::x
double x() const
Definition: MVertex.h:60
discreteFace
Definition: discreteFace.h:18
faces
static int faces[4][3]
Definition: meshGRegionDelaunayInsertion.cpp:165