gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GModel.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 <limits>
7 #include <stdlib.h>
8 #include <sstream>
9 #include <stack>
10 #include "GmshConfig.h"
11 #include "GmshMessage.h"
12 #include "GModel.h"
13 #include "GModelIO_GEO.h"
14 #include "GModelIO_OCC.h"
15 #include "MPoint.h"
16 #include "MLine.h"
17 #include "MTriangle.h"
18 #include "MQuadrangle.h"
19 #include "MTetrahedron.h"
20 #include "MHexahedron.h"
21 #include "MPrism.h"
22 #include "MPyramid.h"
23 #include "MTrihedron.h"
24 #include "MElementCut.h"
25 #include "MElementOctree.h"
26 #include "discreteRegion.h"
27 #include "discreteFace.h"
28 #include "discreteEdge.h"
29 #include "discreteVertex.h"
30 #include "partitionRegion.h"
31 #include "partitionFace.h"
32 #include "partitionEdge.h"
33 #include "partitionVertex.h"
34 #include "gmshSurface.h"
35 #include "SmoothData.h"
36 #include "Context.h"
37 #include "OS.h"
38 #include "StringUtils.h"
39 #include "GEdgeLoop.h"
40 #include "MVertexRTree.h"
41 #include "OpenFile.h"
42 #include "CreateFile.h"
43 #include "Options.h"
44 #include "GModelParametrize.h"
45 
46 #if defined(HAVE_MESH)
47 #include "meshGEdge.h"
48 #include "meshGFace.h"
49 #include "meshGRegion.h"
50 #include "Field.h"
51 #include "Generator.h"
52 #include "meshPartition.h"
53 #include "HighOrder.h"
54 #include "meshMetric.h"
55 #include "meshGRegionMMG.h"
56 #include "meshGFaceBamg.h"
57 #include "meshRefine.h"
58 #endif
59 
60 #if defined(HAVE_POST)
61 #include "PView.h"
62 #include "PViewDataGModel.h"
63 #endif
64 
65 #if defined(HAVE_KBIPACK)
66 #include "Homology.h"
67 #endif
68 
69 std::vector<GModel *> GModel::list;
70 int GModel::_current = -1;
71 
72 GModel::GModel(const std::string &name)
73  : _name(name), _visible(1), _elementOctree(nullptr),
74  _geo_internals(nullptr), _occ_internals(nullptr), _acis_internals(nullptr),
75  _parasolid_internals(nullptr), _fields(nullptr),
76  _currentMeshEntity(nullptr), _numPartitions(0), normals(nullptr),
77  lcCallback(nullptr)
78 {
83 
84  // hide all other models
85  for(std::size_t i = 0; i < list.size(); i++) list[i]->setVisibility(0);
86 
87  // push new one into the list
88  list.push_back(this);
89 
90  // we always create an internal GEO model; other CAD internals are created
91  // on-demand
93 
94 #if defined(HAVE_MESH)
95  _fields = new FieldManager();
96 #endif
97 }
98 
100 {
101  auto it = std::find(list.begin(), list.end(), this);
102  if(it != list.end()) list.erase(it);
103 
104  if(getVisibility()) {
105  // if no other model is visible, make the last one visible
106  bool othervisible = false;
107  for(std::size_t i = 0; i < list.size(); i++) {
108  if(list[i]->getVisibility()) othervisible = true;
109  }
110  if(!othervisible && list.size()) list.back()->setVisibility(1);
111  }
112 
113  destroy();
118 #if defined(HAVE_MESH)
119  delete _fields;
120 #endif
121 }
122 
123 void GModel::setFileName(const std::string &fileName)
124 {
125  _fileName = fileName;
126  _fileNames.insert(fileName);
127 
128  Msg::SetOnelabString("Gmsh/Model name", fileName,
129  Msg::GetNumOnelabClients() > 1, false, true, 0, "file");
130  Msg::SetOnelabString("Gmsh/Model absolute path",
131  SplitFileName(GetAbsolutePath(fileName))[0], false,
132  false, true, 0);
133  Msg::SetWindowTitle(fileName);
134 }
135 
137 {
138  if(list.empty()) {
139  Msg::Debug("No current model available: creating one");
140  new GModel();
141  }
142  if(index >= 0) _current = index;
143  if(_current < 0 || _current >= (int)list.size()) return list.back();
144  return list[_current];
145 }
146 
148 {
149  for(std::size_t i = 0; i < list.size(); i++) {
150  if(list[i] == m) {
151  _current = i;
152  break;
153  }
154  }
155  return _current;
156 }
157 
158 GModel *GModel::findByName(const std::string &name, const std::string &fileName)
159 {
160  // return last mesh with given name
161  for(int i = list.size() - 1; i >= 0; i--)
162  if(list[i]->getName() == name &&
163  (fileName.empty() || !list[i]->hasFileName(fileName)))
164  return list[i];
165  return nullptr;
166 }
167 
168 void GModel::destroy(bool keepName)
169 {
170  Msg::Debug("Destroying model %s", getName().c_str());
171 
172  if(!keepName) {
173  _name.clear();
174  _fileNames.clear();
175  }
176 
181  _currentMeshEntity = nullptr;
182  _lastMeshEntityError.clear();
183  _lastMeshVertexError.clear();
184 
185  for(auto it = firstRegion(); it != lastRegion(); ++it) delete *it;
186  regions.clear();
187  std::set<GRegion *, GEntityPtrLessThan>().swap(regions);
188 
189  for(auto it = firstFace(); it != lastFace(); ++it) delete *it;
190  faces.clear();
191  std::set<GFace *, GEntityPtrLessThan>().swap(faces);
192 
193  for(auto it = firstEdge(); it != lastEdge(); ++it) delete *it;
194  edges.clear();
195  std::set<GEdge *, GEntityPtrLessThan>().swap(edges);
196 
197  for(auto it = firstVertex(); it != lastVertex(); ++it) delete *it;
198  vertices.clear();
199  std::set<GVertex *, GEntityPtrLessThan>().swap(vertices);
200 
202 
204 
205  if(normals) delete normals;
206  normals = nullptr;
207 
208 #if defined(HAVE_MESH)
209  _fields->reset();
210 #endif
212 }
213 
215 {
216  // this is called in GEntity::deleteMesh()
217 #pragma omp critical
218  {
219  _vertexVectorCache.clear();
220  std::vector<MVertex *>().swap(_vertexVectorCache);
221  _vertexMapCache.clear();
222  std::map<int, MVertex *>().swap(_vertexMapCache);
223  _elementVectorCache.clear();
224  std::vector<std::pair<MElement *, int> >().swap(_elementVectorCache);
225  _elementMapCache.clear();
226  std::map<int, std::pair<MElement *, int> >().swap(_elementMapCache);
227  _elementIndexCache.clear();
228  std::map<int, int>().swap(_elementIndexCache);
229  if(_elementOctree) {
230  delete _elementOctree;
231  _elementOctree = nullptr;
232  }
233  }
234 }
235 
237 {
238  for(auto it = firstRegion(); it != lastRegion(); ++it) (*it)->deleteMesh();
239  for(auto it = firstFace(); it != lastFace(); ++it) (*it)->deleteMesh();
240  for(auto it = firstEdge(); it != lastEdge(); ++it) (*it)->deleteMesh();
241  for(auto it = firstVertex(); it != lastVertex(); ++it) (*it)->deleteMesh();
243  _currentMeshEntity = nullptr;
244  _lastMeshEntityError.clear();
245  _lastMeshVertexError.clear();
246 }
247 
248 void GModel::deleteMesh(const std::vector<GEntity *> &entities)
249 {
250  if(entities.empty()) {
251  deleteMesh();
252  return;
253  }
254  for(std::size_t i = 0; i < entities.size(); i++) {
255  GEntity *ge = entities[i];
256  bool ok = true;
257  switch(ge->dim()) {
258  case 0: {
259  std::vector<GEdge *> e = ge->edges();
260  for(auto it = e.begin(); it != e.end(); ++it) {
261  if((*it)->getNumMeshElements()) {
262  ok = false;
263  break;
264  }
265  }
266  } break;
267  case 1: {
268  std::vector<GFace *> f = ge->faces();
269  for(auto it = f.begin(); it != f.end(); ++it) {
270  if((*it)->getNumMeshElements()) {
271  ok = false;
272  break;
273  }
274  }
275  } break;
276  case 2: {
277  std::list<GRegion *> r = ge->regions();
278  for(auto it = r.begin(); it != r.end(); ++it) {
279  if((*it)->getNumMeshElements()) {
280  ok = false;
281  break;
282  }
283  }
284  } break;
285  }
286  if(ok) { ge->deleteMesh(); }
287  else {
288  Msg::Warning("Cannot delete mesh of entity (%d, %d), connected to mesh "
289  "of higher dimensional entity",
290  ge->dim(), ge->tag());
291  }
292  }
294  _currentMeshEntity = nullptr;
295  _lastMeshEntityError.clear();
296  _lastMeshVertexError.clear();
297 }
298 
300 {
301  for(auto it = firstRegion(); it != lastRegion(); ++it)
302  (*it)->deleteVertexArrays();
303  for(auto it = firstFace(); it != lastFace(); ++it)
304  (*it)->deleteVertexArrays();
305  for(auto it = firstEdge(); it != lastEdge(); ++it)
306  (*it)->deleteVertexArrays();
307  for(auto it = firstVertex(); it != lastVertex(); ++it)
308  (*it)->deleteVertexArrays();
309 }
310 
311 bool GModel::empty() const
312 {
313  return vertices.empty() && edges.empty() && faces.empty() && regions.empty();
314 }
315 
317 {
318  GEntity tmp((GModel *)this, n);
319  auto it = regions.find((GRegion *)&tmp);
320  if(it != regions.end())
321  return *it;
322  else
323  return nullptr;
324 }
325 
327 {
328  GEntity tmp((GModel *)this, n);
329  auto it = faces.find((GFace *)&tmp);
330  if(it != faces.end())
331  return *it;
332  else
333  return nullptr;
334 }
335 
337 {
338  GEntity tmp((GModel *)this, n);
339  auto it = edges.find((GEdge *)&tmp);
340  if(it != edges.end())
341  return *it;
342  else
343  return nullptr;
344 }
345 
347 {
348  GEntity tmp((GModel *)this, n);
349  auto it = vertices.find((GVertex *)&tmp);
350  if(it != vertices.end())
351  return *it;
352  else
353  return nullptr;
354 }
355 
356 GEntity *GModel::getEntityByTag(int dim, int n) const
357 {
358  switch(dim) {
359  case 0: return getVertexByTag(n);
360  case 1: return getEdgeByTag(n);
361  case 2: return getFaceByTag(n);
362  case 3: return getRegionByTag(n);
363  }
364  return nullptr;
365 }
366 
367 bool GModel::changeEntityTag(int dim, int tag, int newTag)
368 {
369  if(dim == 0) {
370  GVertex *gv = getVertexByTag(tag);
371  if(gv) {
372  vertices.erase(gv);
373  gv->setTag(newTag);
374  vertices.insert(gv);
375  }
376  else {
377  Msg::Error("Unknown model point %d", tag);
378  return false;
379  }
380  }
381  else if(dim == 1) {
382  GEdge *ge = getEdgeByTag(tag);
383  if(ge) {
384  edges.erase(ge);
385  ge->setTag(newTag);
386  edges.insert(ge);
387  }
388  else {
389  Msg::Error("Unknown model curve %d", tag);
390  return false;
391  }
392  }
393  else if(dim == 2) {
394  GFace *gf = getFaceByTag(tag);
395  if(gf) {
396  faces.erase(gf);
397  gf->setTag(newTag);
398  faces.insert(gf);
399  }
400  else {
401  Msg::Error("Unknown model surface %d", tag);
402  return false;
403  }
404  }
405  else if(dim == 3) {
406  GRegion *gr = getRegionByTag(tag);
407  if(gr) {
408  regions.erase(gr);
409  gr->setTag(newTag);
410  regions.insert(gr);
411  }
412  else {
413  Msg::Error("Unknown model volume %d", tag);
414  return false;
415  }
416  }
417  return true;
418 }
419 
420 std::vector<int> GModel::getTagsForPhysicalName(int dim,
421  const std::string &name)
422 {
423  std::vector<int> tags;
424  std::map<int, std::vector<GEntity *> > physicalGroups;
425  getPhysicalGroups(dim, physicalGroups);
426  std::vector<GEntity *> entities =
427  physicalGroups[getPhysicalNumber(dim, name)];
428  for(auto it = entities.begin(); it != entities.end(); it++) {
429  GEntity *ge = *it;
430  tags.push_back(ge->tag());
431  }
432  return tags;
433 }
434 
436 {
437  auto it = std::find(firstRegion(), lastRegion(), r);
438  if(it != (riter)regions.end()) {
439  regions.erase(it);
440  std::vector<GFace *> f = r->faces();
441  for(auto it = f.begin(); it != f.end(); it++) (*it)->delRegion(r);
442  return true;
443  }
444  else {
445  return false;
446  }
447 }
448 
450 {
451  auto it = std::find(firstFace(), lastFace(), f);
452  if(it != faces.end()) {
453  faces.erase(it);
454  std::vector<GEdge *> const &e = f->edges();
455  for(auto it = e.begin(); it != e.end(); it++) (*it)->delFace(f);
456  return true;
457  }
458  else {
459  return false;
460  }
461 }
462 
464 {
465  auto it = std::find(firstEdge(), lastEdge(), e);
466  if(it != edges.end()) {
467  edges.erase(it);
468  if(e->getBeginVertex()) e->getBeginVertex()->delEdge(e);
469  if(e->getEndVertex()) e->getEndVertex()->delEdge(e);
470  return true;
471  }
472  else {
473  return false;
474  }
475 }
476 
478 {
479  auto it = std::find(firstVertex(), lastVertex(), v);
480  if(it != vertices.end()) {
481  vertices.erase(it);
482  return true;
483  }
484  else {
485  return false;
486  }
487 }
488 
489 void GModel::remove(int dim, int tag, std::vector<GEntity*> &removed,
490  bool recursive)
491 {
492  if(dim == 3) {
493  GRegion *gr = getRegionByTag(tag);
494  if(gr) {
495  if(remove(gr)) removed.push_back(gr);
496  if(recursive) {
497  std::vector<GFace *> f = gr->faces();
498  for(auto it = f.begin(); it != f.end(); it++)
499  remove(2, (*it)->tag(), removed, recursive);
500  }
501  }
502  }
503  else if(dim == 2) {
504  GFace *gf = getFaceByTag(tag);
505  if(gf) {
506  bool skip = false;
507  for(auto it = firstRegion(); it != lastRegion(); it++) {
508  std::vector<GFace *> f = (*it)->faces();
509  if(std::find(f.begin(), f.end(), gf) != f.end()) {
510  skip = true;
511  break;
512  }
513  auto ef = (*it)->embeddedFaces();
514  if(std::find(ef.begin(), ef.end(), gf) != ef.end()) {
515  skip = true;
516  break;
517  }
518  }
519  if(!skip) {
520  if(remove(gf)) removed.push_back(gf);
521  if(recursive) {
522  std::vector<GEdge *> const &e = gf->edges();
523  for(auto it = e.begin(); it != e.end(); it++)
524  remove(1, (*it)->tag(), removed, recursive);
525  }
526  }
527  }
528  }
529  else if(dim == 1) {
530  GEdge *ge = getEdgeByTag(tag);
531  if(ge) {
532  bool skip = false;
533  for(auto it = firstRegion(); it != lastRegion(); it++) {
534  auto ee = (*it)->embeddedEdges();
535  if(std::find(ee.begin(), ee.end(), ge) != ee.end()) {
536  skip = true;
537  break;
538  }
539  }
540  if(!skip) {
541  for(auto it = firstFace(); it != lastFace(); it++) {
542  std::vector<GEdge *> const &e = (*it)->edges();
543  if(std::find(e.begin(), e.end(), ge) != e.end()) {
544  skip = true;
545  break;
546  }
547  auto ee = (*it)->embeddedEdges();
548  if(std::find(ee.begin(), ee.end(), ge) != ee.end()) {
549  skip = true;
550  break;
551  }
552  }
553  }
554  if(!skip) {
555  if(remove(ge)) removed.push_back(ge);
556  if(recursive) {
557  if(ge->getBeginVertex())
558  remove(0, ge->getBeginVertex()->tag(), removed);
559  if(ge->getEndVertex())
560  remove(0, ge->getEndVertex()->tag(), removed);
561  }
562  }
563  }
564  }
565  else if(dim == 0) {
566  GVertex *gv = getVertexByTag(tag);
567  if(gv) {
568  bool skip = false;
569  for(auto it = firstEdge(); it != lastEdge(); it++) {
570  GEdge *ge = *it;
571  if(ge->getBeginVertex() == gv || ge->getEndVertex() == gv) {
572  skip = true;
573  break;
574  }
575  }
576  if(!skip) {
577  for(auto it = firstFace(); it != lastFace(); it++) {
578  auto ev = (*it)->embeddedVertices();
579  if(std::find(ev.begin(), ev.end(), gv) != ev.end()) {
580  skip = true;
581  break;
582  }
583  }
584  }
585  if(!skip) {
586  for(auto it = firstRegion(); it != lastRegion(); it++) {
587  auto ev = (*it)->embeddedVertices();
588  if(std::find(ev.begin(), ev.end(), gv) != ev.end()) {
589  skip = true;
590  break;
591  }
592  }
593  }
594  if(!skip) {
595  if(remove(gv)) removed.push_back(gv);
596  }
597  }
598  }
599 }
600 
601 void GModel::remove(const std::vector<std::pair<int, int> > &dimTags,
602  std::vector<GEntity*> &removed, bool recursive)
603 {
604  for(std::size_t i = 0; i < dimTags.size(); i++)
605  remove(dimTags[i].first, dimTags[i].second, removed, recursive);
606 }
607 
609 {
610  regions.clear();
611  faces.clear();
612  edges.clear();
613  vertices.clear();
614 }
615 
617 {
618  if(!CTX::instance()->geom.snapPoints) return;
619 
620  auto vit = firstVertex();
621 
622  double tol = CTX::instance()->geom.tolerance;
623 
624  while(vit != lastVertex()) {
625  std::vector<GEdge *> const &edges = (*vit)->edges();
626  for(auto it = edges.begin(); it != edges.end(); ++it) {
627  Range<double> parb = (*it)->parBounds(0);
628  double t;
629  if((*it)->getBeginVertex() == *vit) { t = parb.low(); }
630  else if((*it)->getEndVertex() == *vit) {
631  t = parb.high();
632  }
633  else {
634  Msg::Error("Weird point: impossible to snap");
635  break;
636  }
637  GPoint gp = (*it)->point(t);
638  double d = sqrt((gp.x() - (*vit)->x()) * (gp.x() - (*vit)->x()) +
639  (gp.y() - (*vit)->y()) * (gp.y() - (*vit)->y()) +
640  (gp.z() - (*vit)->z()) * (gp.z() - (*vit)->z()));
641  if(d > tol) {
642  (*vit)->setPosition(gp);
643  Msg::Info("Snapping geometry point %d to curve (distance = %g)",
644  (*vit)->tag(), d);
645  }
646  }
647  vit++;
648  }
649 }
650 
651 void GModel::getEntities(std::vector<GEntity *> &entities, int dim) const
652 {
653  entities.clear();
654  switch(dim) {
655  case 0:
656  entities.insert(entities.end(), vertices.begin(), vertices.end());
657  break;
658  case 1: entities.insert(entities.end(), edges.begin(), edges.end()); break;
659  case 2: entities.insert(entities.end(), faces.begin(), faces.end()); break;
660  case 3:
661  entities.insert(entities.end(), regions.begin(), regions.end());
662  break;
663  default:
664  entities.insert(entities.end(), vertices.begin(), vertices.end());
665  entities.insert(entities.end(), edges.begin(), edges.end());
666  entities.insert(entities.end(), faces.begin(), faces.end());
667  entities.insert(entities.end(), regions.begin(), regions.end());
668  break;
669  }
670 }
671 
672 void GModel::getEntitiesInBox(std::vector<GEntity *> &entities,
673  const SBoundingBox3d &box, int dim) const
674 {
675  entities.clear();
676  std::vector<GEntity *> all;
677  getEntities(all, dim);
678  // if we use this often, create an rtree to avoid the linear search
679  for(std::size_t i = 0; i < all.size(); i++) {
680  SBoundingBox3d bbox = all[i]->bounds();
681  if(bbox.min().x() >= box.min().x() && bbox.max().x() <= box.max().x() &&
682  bbox.min().y() >= box.min().y() && bbox.max().y() <= box.max().y() &&
683  bbox.min().z() >= box.min().z() && bbox.max().z() <= box.max().z())
684  entities.push_back(all[i]);
685  }
686 }
687 
689 public:
690  bool operator()(const int &i1, const int &i2) const
691  {
692  if(std::abs(i1) < std::abs(i2)) return true;
693  return false;
694  }
695 };
696 
697 bool GModel::getBoundaryTags(const std::vector<std::pair<int, int> > &inDimTags,
698  std::vector<std::pair<int, int> > &outDimTags,
699  bool combined, bool oriented, bool recursive)
700 {
701  bool ret = true;
702  for(std::size_t i = 0; i < inDimTags.size(); i++) {
703  int dim = inDimTags[i].first;
704  int tag = std::abs(inDimTags[i].second); // abs for backward compatibility
705  bool reverse = (inDimTags[i].second < 0);
706  if(dim == 3) {
707  GRegion *gr = getRegionByTag(tag);
708  if(gr) {
709  if(recursive) {
710  std::vector<GVertex *> const &vert = gr->vertices();
711  for(auto it = vert.begin(); it != vert.end(); it++)
712  outDimTags.push_back(std::make_pair(0, (*it)->tag()));
713  }
714  else {
715  std::vector<GFace *> faces(gr->faces());
716  std::vector<int> const &orientations = gr->faceOrientations();
717  auto ito = orientations.begin();
718  for(auto it = faces.begin(); it != faces.end(); it++) {
719  int t = (*it)->tag();
720  if(oriented && ito != orientations.end()) {
721  t *= *ito;
722  ito++;
723  }
724  outDimTags.push_back(std::make_pair(2, t));
725  }
726  }
727  }
728  else {
729  Msg::Error("Unknown model region with tag %d", tag);
730  ret = false;
731  }
732  }
733  else if(dim == 2) {
734  GFace *gf = getFaceByTag(tag);
735  if(gf) {
736  if(recursive) {
737  std::vector<GVertex *> const &vert = gf->vertices();
738  for(auto it = vert.begin(); it != vert.end(); it++)
739  outDimTags.push_back(std::make_pair(0, (*it)->tag()));
740  }
741  else {
742  std::vector<GEdge *> const &edges = gf->edges();
743  std::vector<int> orientations(gf->edgeOrientations());
744  auto ito = orientations.begin();
745  for(auto it = edges.begin(); it != edges.end(); it++) {
746  int t = (*it)->tag();
747  if(oriented && ito != orientations.end()) {
748  t *= *ito;
749  ito++;
750  }
751  outDimTags.push_back(std::make_pair(1, t));
752  }
753  }
754  }
755  else {
756  Msg::Error("Unknown model face with tag %d", tag);
757  ret = false;
758  }
759  }
760  else if(dim == 1) {
761  GEdge *ge = getEdgeByTag(tag);
762  if(ge) {
763  if(reverse) { // for backward compatibility
764  if(ge->getEndVertex())
765  outDimTags.push_back(
766  std::make_pair(0, ge->getEndVertex()->tag()));
767  if(ge->getBeginVertex())
768  outDimTags.push_back(
769  std::make_pair(0, ge->getBeginVertex()->tag()));
770  }
771  else {
772  if(ge->getBeginVertex())
773  outDimTags.push_back(
774  std::make_pair(0, ge->getBeginVertex()->tag()));
775  if(ge->getEndVertex())
776  outDimTags.push_back(
777  std::make_pair(0, ge->getEndVertex()->tag()));
778  }
779  }
780  else {
781  Msg::Error("Unknown model curve with tag %d", tag);
782  ret = false;
783  }
784  }
785  else if(dim == 0) {
786  GVertex *gv = getVertexByTag(tag);
787  if(gv && recursive) {
788  outDimTags.push_back(std::make_pair(0, gv->tag()));
789  }
790  }
791  }
792 
793  if(combined) {
794  // compute boundary of the combined shapes
795  std::set<int, AbsIntLessThan> c[3];
796  for(std::size_t i = 0; i < outDimTags.size(); i++) {
797  int dim = outDimTags[i].first;
798  int tag = outDimTags[i].second;
799  if(dim >= 0 && dim < 3) {
800  auto it = c[dim].find(tag);
801  if(it == c[dim].end())
802  c[dim].insert(tag);
803  else {
804  c[dim].erase(it);
805  }
806  }
807  }
808  outDimTags.clear();
809  for(int dim = 0; dim < 3; dim++) {
810  for(auto it = c[dim].begin(); it != c[dim].end(); it++)
811  outDimTags.push_back(std::make_pair(dim, *it));
812  }
813  }
814  return ret;
815 }
816 
818 {
819  std::vector<GEntity *> entities;
820  getEntities(entities);
821  int num = 0;
822  for(std::size_t i = 0; i < entities.size(); i++)
823  if(dim < 0 || entities[i]->dim() == dim)
824  num = std::max(num, std::abs(entities[i]->tag()));
825  return num;
826 }
827 
829 {
830  std::vector<GEntity *> entities;
831  getEntities(entities);
832  for(std::size_t i = 0; i < entities.size(); i++)
833  if(entities[i]->physicals.size()) return false;
834  return true;
835 }
836 
838  std::map<int, std::vector<GEntity *> > groups[4]) const
839 {
840  std::vector<GEntity *> entities;
841  getEntities(entities);
842  for(std::size_t i = 0; i < entities.size(); i++) {
843  std::map<int, std::vector<GEntity *> > &group(groups[entities[i]->dim()]);
844  for(std::size_t j = 0; j < entities[i]->physicals.size(); j++) {
845  // physicals can be stored with negative signs when the entity should be
846  // "reversed"
847  int p = std::abs(entities[i]->physicals[j]);
848  group[p].push_back(entities[i]);
849  }
850  }
851  for(int dim = 0; dim < 4; ++dim) {
852  std::map<int, std::vector<GEntity *> > &group(groups[dim]);
853  for(auto it = group.begin(); it != group.end(); ++it) {
854  std::vector<GEntity *> &v = it->second;
855  std::sort(v.begin(), v.end(), GEntityPtrLessThan());
856  std::unique(v.begin(), v.end(), GEntityPtrLessThan());
857  }
858  }
859 }
860 
862  int dim, std::map<int, std::vector<GEntity *> > &groups) const
863 {
864  std::vector<GEntity *> entities;
865  getEntities(entities, dim);
866  for(std::size_t i = 0; i < entities.size(); i++) {
867  for(std::size_t j = 0; j < entities[i]->physicals.size(); j++) {
868  // physicals can be stored with negative signs when the entity should be
869  // "reversed"
870  int p = std::abs(entities[i]->physicals[j]);
871  groups[p].push_back(entities[i]);
872  }
873  }
874  for(auto it = groups.begin(); it != groups.end(); ++it) {
875  std::vector<GEntity *> &v = it->second;
876  std::sort(v.begin(), v.end(), GEntityPtrLessThan());
877  std::unique(v.begin(), v.end(), GEntityPtrLessThan());
878  }
879 }
880 
881 void GModel::addPhysicalGroup(int dim, int tag, const std::vector<int> &tags)
882 {
883  for(auto t : tags) {
884  GEntity *ge = getEntityByTag(dim, std::abs(t));
885  if(ge)
886  ge->physicals.push_back((t > 0) ? tag : -tag);
887  else
888  Msg::Warning("Unknown entity of dimension %d and tag %d in physical "
889  "group %d", dim, t, tag);
890  }
891 }
892 
894 {
895  std::vector<GEntity *> entities;
896  getEntities(entities);
897  for(std::size_t i = 0; i < entities.size(); i++)
898  entities[i]->physicals.clear();
899 }
900 
901 void GModel::removePhysicalGroup(int dim, int tag)
902 {
903  // FIXME: this is very inefficient - needs to be rewriten (and we should
904  // generalize the function by taking a list of dim, tag pairs)
905  std::vector<GEntity *> entities;
906  getEntities(entities, dim);
907  for(std::size_t i = 0; i < entities.size(); i++) {
908  std::vector<int> p;
909  for(std::size_t j = 0; j < entities[i]->physicals.size(); j++)
910  if(std::abs(entities[i]->physicals[j]) != tag)
911  p.push_back(entities[i]->physicals[j]);
912  entities[i]->physicals = p;
913  }
914  _physicalNames.erase(std::make_pair(dim, tag));
915 }
916 
918 {
919  std::vector<GEntity *> entities;
920  getEntities(entities);
921  int num = 0;
922  for(std::size_t i = 0; i < entities.size(); i++)
923  if(dim < 0 || entities[i]->dim() == dim)
924  for(std::size_t j = 0; j < entities[i]->physicals.size(); j++)
925  num = std::max(num, std::abs(entities[i]->physicals[j]));
926  return num;
927 }
928 
929 void GModel::getInnerPhysicalNamesIterators(std::vector<piter> &iterators)
930 {
931  iterators.resize(4, firstPhysicalName());
932 
933  for(auto physIt = firstPhysicalName(); physIt != lastPhysicalName(); ++physIt)
934  iterators[physIt->first.first] = physIt;
935 }
936 
937 int GModel::setPhysicalName(const std::string &name, int dim, int number)
938 {
939  // check if the name is already used
940  int findPhy = getPhysicalNumber(dim, name);
941  if(findPhy != -1) return findPhy;
942 
943  // if no number is given, find the next available one
944  if(!number) number = getMaxPhysicalNumber(dim) + 1;
945  _physicalNames.insert(std::make_pair(std::make_pair(dim, number), name));
946  return number;
947 }
948 
949 GModel::piter GModel::setPhysicalName(piter pos, const std::string &name,
950  int dim, int number)
951 {
952  // if no number is given, find the next available one
953  if(!number) number = getMaxPhysicalNumber(dim) + 1;
954  // Insertion complexity in O(1) if position points to the element that will
955  // FOLLOW the inserted element.
956  if(pos != lastPhysicalName()) ++pos;
957  return _physicalNames.insert(pos, std::make_pair(std::make_pair(dim, number),
958  name));
959 }
960 
961 std::string GModel::getPhysicalName(int dim, int number) const
962 {
963  auto it = _physicalNames.find(std::make_pair(dim, number));
964  if(it != _physicalNames.end()) return it->second;
965  return "";
966 }
967 
968 void GModel::removePhysicalName(const std::string &name)
969 {
970  auto it = _physicalNames.begin();
971  while(it != _physicalNames.end()) {
972  if(it->second == name)
973  // it = _physicalNames.erase(it); // C++11 only
974  _physicalNames.erase(it++);
975  else
976  ++it;
977  }
978 }
979 
980 int GModel::getPhysicalNumber(const int &dim, const std::string &name)
981 {
982  for(auto physIt = firstPhysicalName(); physIt != lastPhysicalName(); ++physIt)
983  if(dim == physIt->first.first && name == physIt->second)
984  return physIt->first.second;
985 
986  return -1;
987 }
988 
989 int GModel::getDim() const
990 {
991  if(getNumRegions() > 0) return 3;
992  if(getNumFaces() > 0) return 2;
993  if(getNumEdges() > 0) return 1;
994  if(getNumVertices() > 0) return 0;
995  return -1;
996 }
997 
999 {
1000  if(getNumMeshElements(3)) return 3;
1001  if(getNumMeshElements(2)) return 2;
1002  if(getNumMeshElements(1)) return 1;
1003  if(getNumMeshElements(0)) return 0;
1004  return -1;
1005 }
1006 
1007 std::string GModel::getElementaryName(int dim, int tag)
1008 {
1009  auto it = _elementaryNames.find(std::make_pair(dim, tag));
1010  if(it != _elementaryNames.end()) return it->second;
1011  return "";
1012 }
1013 
1014 void GModel::removeElementaryName(const std::string &name)
1015 {
1016  auto it = _elementaryNames.begin();
1017  while(it != _elementaryNames.end()) {
1018  if(it->second == name)
1019  // it = _elementaryNames.erase(it); // C++11 only
1020  _elementaryNames.erase(it++);
1021  else
1022  ++it;
1023  }
1024 }
1025 
1027 {
1028  std::vector<GEntity *> entities;
1029  getEntities(entities);
1030 
1031  for(std::size_t i = 0; i < entities.size(); i++) {
1032  entities[i]->setSelection(val);
1033  // reset selection in elements (stored in the visibility flag to
1034  // save space)
1035  if(val == 0) {
1036  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++)
1037  if(entities[i]->getMeshElement(j)->getVisibility() == 2)
1038  entities[i]->getMeshElement(j)->setVisibility(1);
1039  }
1040  }
1041 }
1042 
1043 SBoundingBox3d GModel::bounds(bool aroundVisible)
1044 {
1045  std::vector<GEntity *> entities;
1046  getEntities(entities);
1047  SBoundingBox3d bb;
1048  for(std::size_t i = 0; i < entities.size(); i++) {
1049  if(!aroundVisible || entities[i]->getVisibility()) {
1050  if(entities[i]->getNativeType() == GEntity::OpenCascadeModel) {
1051  bb += entities[i]->bounds();
1052  }
1053  else {
1054  // using the mesh vertices for now
1055  if(entities[i]->dim() == 0)
1056  bb += static_cast<GVertex *>(entities[i])->xyz();
1057  else
1058  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
1059  bb += entities[i]->mesh_vertices[j]->point();
1060  }
1061  }
1062  }
1063  return bb;
1064 }
1065 
1067 {
1068 #if defined(HAVE_MESH)
1069  GenerateMesh(this, dimension);
1070  if(CTX::instance()->mesh.renumber) {
1073  }
1074  // must be done after renumbering:
1075  std::vector<std::pair<int, int> > newPhysicals;
1076  computeHomology(newPhysicals);
1078  return true;
1079 #else
1080  Msg::Error("Mesh module not compiled");
1081  return false;
1082 #endif
1083 }
1084 
1086 {
1087  bool ok = true;
1088  for(auto it = regions.begin(); it != regions.end(); ++it)
1089  for(std::size_t i = 0; i < (*it)->getNumMeshElements(); ++i)
1090  if(!(*it)->getMeshElement(i)->setVolumePositive()) ok = false;
1091  return ok;
1092 }
1093 
1094 static void
1095 addToMap(std::multimap<MFace, MElement *, MFaceLessThan> &faceToElement,
1096  std::map<MElement *, std::vector<std::pair<MElement *, bool> > >
1097  &elToNeighbors,
1098  const MFace &face, MElement *el)
1099 {
1100  auto fit = faceToElement.find(face);
1101  if(fit == faceToElement.end()) {
1102  faceToElement.insert(std::make_pair(face, el));
1103  }
1104  else { // We found the neighbor face outFace
1105  faceToElement.insert(std::make_pair(face, el));
1106  if(faceToElement.count(face) > 2) {
1107  Msg::Error(
1108  "Topological fault: Face sharing two other faces. Element %i. "
1109  "Number of nodes %i. Count of faces: %i Three first nodes %i %i %i",
1110  el->getNum(), face.getNumVertices(), faceToElement.count(face),
1111  face.getVertex(0)->getNum(), face.getVertex(1)->getNum(),
1112  face.getVertex(2)->getNum());
1113  return;
1114  }
1115  MFace outFace = fit->first;
1116  std::vector<std::pair<MElement *, bool> > &neigh = elToNeighbors[el];
1117  for(size_t iN = 0; iN < neigh.size(); iN++)
1118  if(neigh[iN].first == fit->second) // Neigbor is already in the map
1119  return;
1120  int i0 = -1;
1121  while(face.getVertex(0) != outFace.getVertex(++i0))
1122  ;
1123  bool sameOrientation =
1124  face.getVertex(1) == outFace.getVertex((i0 + 1) % face.getNumVertices());
1125  neigh.push_back(std::make_pair(fit->second, !sameOrientation));
1126  elToNeighbors[fit->second].push_back(std::make_pair(el, !sameOrientation));
1127  }
1128 }
1129 
1130 static void
1131 checkConformity(std::multimap<MFace, MElement *, MFaceLessThan> &faceToElement,
1132  std::map<MElement *, std::vector<std::pair<MElement *, bool> > >
1133  &elToNeighbors,
1134  const MFace &face, MElement *el)
1135 {
1136  int connectivity = faceToElement.count(face);
1138  // Each face of a trihedron should exist twice (no face on the boundary)
1139  if(connectivity != 2)
1140  Msg::Error("Non conforming trihedron %i (nb connections for a face %i)",
1141  el->getNum(), faceToElement.count(face));
1142  }
1143  else {
1144  // A face can exist twice (inside) or once (boundary)
1145  if(connectivity != 2) {
1146  for(std::size_t iV = 0; iV < face.getNumVertices(); iV++)
1147  if(face.getVertex(iV)->onWhat()->dim() == 3 || connectivity != 1) {
1148  for(std::size_t jV = 0; jV < face.getNumVertices(); jV++)
1149  Msg::Info("Node %i on entity of dim %i", face.getVertex(jV)->getNum(),
1150  face.getVertex(iV)->onWhat()->dim());
1151  Msg::Error("Non conforming element %i (%i connection(s) for a face "
1152  "located on dim %i (vertex %i))",
1153  el->getNum(), connectivity,
1154  face.getVertex(iV)->onWhat()->dim(),
1155  face.getVertex(iV)->getNum());
1156  }
1157  }
1158  }
1159 }
1160 
1162 {
1163  Msg::Info("Orienting volumes according to topology");
1164  std::map<MElement *, std::vector<std::pair<MElement *, bool> > >
1165  elToNeighbors;
1166  std::multimap<MFace, MElement *, MFaceLessThan> faceToElement;
1167 
1168  MElement *el;
1169  for(auto it = regions.begin(); it != regions.end(); ++it) {
1170  for(std::size_t iEl = 0; iEl < (*it)->getNumMeshElements(); ++iEl) {
1171  el = (*it)->getMeshElement(iEl);
1172  for(int iFace = 0; iFace < el->getNumFaces(); iFace++) {
1173  addToMap(faceToElement, elToNeighbors, el->getFace(iFace), el);
1174  }
1175  }
1176  }
1177  for(auto it = regions.begin(); it != regions.end(); ++it) {
1178  for(std::size_t iEl = 0; iEl < (*it)->getNumMeshElements(); ++iEl) {
1179  el = (*it)->getMeshElement(iEl);
1180  for(int iFace = 0; iFace < el->getNumFaces(); iFace++) {
1181  checkConformity(faceToElement, elToNeighbors, el->getFace(iFace), el);
1182  }
1183  }
1184  }
1185  std::vector<std::pair<MElement *, bool> > queue;
1186  std::set<MElement *> queued;
1187  if((*regions.begin())->tetrahedra.size() == 0) {
1188  Msg::Error(
1189  "setAllVolumePositiveTopology needs at least one tetrahedron to start");
1190  return;
1191  }
1192  el = (*regions.begin())->tetrahedra[0];
1193  queue.push_back(std::make_pair(el, true));
1194  for(size_t i = 0; i < queue.size(); i++) {
1195  el = queue[i].first;
1196  if(!queue[i].second) {
1197  el->reverse();
1198  // Msg::Info("Reverted element %i of type %i", el->getNum(),
1199  // el->getType());
1200  }
1201  const std::vector<std::pair<MElement *, bool> > &neigh = elToNeighbors[el];
1202  for(size_t iN = 0; iN < neigh.size(); iN++)
1203  if(queued.count(neigh[iN].first) == 0) {
1204  queue.push_back(
1205  std::make_pair(neigh[iN].first, neigh[iN].second == queue[i].second));
1206  // if(!(neigh[iN].second == queue[i].second))
1207  // Msg::Info("Queuing element %i (%i) from el %i (%i)",
1208  // neigh[iN].first->getNum(), neigh[iN].second,
1209  // el->getNum(), queue[i].second);
1210  queued.insert(neigh[iN].first);
1211  }
1212  }
1213 }
1214 
1216 {
1217 #if defined(HAVE_MESH)
1218  AdaptMesh(this);
1219  if(CTX::instance()->mesh.renumber) {
1222  }
1224  return 1;
1225 #else
1226  Msg::Error("Mesh module not compiled");
1227  return 0;
1228 #endif
1229 }
1230 
1231 int GModel::adaptMesh(std::vector<int> technique,
1232  std::vector<simpleFunction<double> *> f,
1233  std::vector<std::vector<double> > parameters, int niter,
1234  bool meshAll)
1235 {
1236  // For all algorithms:
1237  //
1238  // parameters[1] = lcmin (default : in global gmsh options
1239  // CTX::instance()->mesh.lcMin)
1240  // parameters[2] = lcmax (default : in global gmsh options
1241  // CTX::instance()->mesh.lcMax) niter is the maximum number of iterations
1242 
1243  // Available algorithms:
1244  //
1245  // 1) Assume that the function is a levelset -> adapt using Coupez
1246  // technique (technique = 1)
1247  // parameters[0] = thickness of the interface (mandatory)
1248  // 2) Assume that the function is a physical quantity -> adapt using the
1249  // Hessian (technique = 2)
1250  // parameters[0] = N, the final number of elements
1251  // 3) A variant of 1) by P. Frey (= Coupez + takes curvature function into
1252  // account)
1253  // parameters[0] = thickness of the interface (mandatory)
1254  // parameters[3] = the required minimum number of elements to
1255  // represent a circle - used for curvature-based metric (default:
1256  // = 15)
1257  // 4) A variant (3), direct implementation in the metric eigendirections,
1258  // assuming a level set (ls):
1259  // - hmin is imposed in the ls gradient,
1260  // - hmax is imposed in the two eigendirections of the ls hessian that
1261  // are
1262  // (almost ?) tangent to the iso-zero plane
1263  // + the latter eigenvalues (1/hmax^2) are modified if necessary to
1264  // capture the iso-zero curvature
1265  // parameters[0] = thickness of the interface in the positive ls
1266  // direction (mandatory) parameters[4] = thickness of the interface in
1267  // the negative ls direction
1268  // (=parameters[0] if not specified)
1269  // parameters[3] = the required minimum number of elements to represent a
1270  // circle
1271  // - used for curvature-based metric (default: = 15)
1272  // 5) Same as 4, except that the transition in band E uses linear
1273  // interpolation
1274  // of h, instead of linear interpolation of metric
1275 
1276 #if defined(HAVE_MESH)
1277  // copy context (in order to allow multiple calls)
1278  CTX _backup = *(CTX::instance());
1279 
1280  if(getNumMeshElements() == 0) mesh(getDim());
1281  int nbElemsOld = getNumMeshElements();
1282  int nbElems;
1283 
1284  FieldManager *fields = getFields();
1285  fields->reset();
1286 
1287  int ITER = 0;
1288  if(meshAll) {
1289  while(1) {
1290  Msg::Info(" - Adapt mesh (all dimensions) iter. = %d", ITER);
1291  fields->reset();
1292  meshMetric *metric = new meshMetric(this);
1293  for(std::size_t imetric = 0; imetric < technique.size(); imetric++) {
1294  metric->addMetric(technique[imetric], f[imetric], parameters[imetric]);
1295  }
1296  fields->setBackgroundField(metric);
1297 
1299  opt_mesh_algo2d(0, GMSH_SET, 7.0); // bamg
1300  opt_mesh_algo3d(0, GMSH_SET, 7.0); // mmg3d
1301  opt_mesh_lc_from_points(0, GMSH_SET, 0.0); // do not mesh lines with lc
1302 
1303  std::for_each(firstRegion(), lastRegion(), deMeshGRegion());
1304  std::for_each(firstFace(), lastFace(), deMeshGFace());
1305  std::for_each(firstEdge(), lastEdge(), deMeshGEdge());
1306 
1307  GenerateMesh(this, getDim());
1308  nbElems = getNumMeshElements();
1309 
1310  char name[256];
1311  sprintf(name, "meshAdapt-%d.msh", ITER);
1312  writeMSH(name);
1313  // metric->exportInfo(name);
1314 
1315  if(ITER++ >= niter) break;
1316  if(ITER > 3 && fabs((double)(nbElems - nbElemsOld)) < 0.01 * nbElemsOld)
1317  break;
1318 
1319  nbElemsOld = nbElems;
1320  }
1321  }
1322  else { // adapt only upper most dimension
1323  while(1) {
1324  Msg::Info(" - Adapt mesh iter. = %d ", ITER);
1325  std::vector<MElement *> elements;
1326 
1327  if(getDim() == 2) {
1328  for(auto fit = firstFace(); fit != lastFace(); ++fit) {
1329  if((*fit)->quadrangles.size()) return -1;
1330  for(unsigned i = 0; i < (*fit)->triangles.size(); i++) {
1331  elements.push_back((*fit)->triangles[i]);
1332  }
1333  }
1334  }
1335  else if(getDim() == 3) {
1336  for(auto rit = firstRegion(); rit != lastRegion(); ++rit) {
1337  if((*rit)->hexahedra.size()) return -1;
1338  for(unsigned i = 0; i < (*rit)->tetrahedra.size(); i++) {
1339  elements.push_back((*rit)->tetrahedra[i]);
1340  }
1341  }
1342  }
1343 
1344  if(elements.size() == 0) return -1;
1345 
1346  fields->reset();
1347  meshMetric *metric = new meshMetric(this);
1348  for(std::size_t imetric = 0; imetric < technique.size(); imetric++) {
1349  metric->addMetric(technique[imetric], f[imetric], parameters[imetric]);
1350  }
1351  fields->setBackgroundField(metric);
1352 
1353  if(getDim() == 2) {
1354  for(auto fit = firstFace(); fit != lastFace(); ++fit) {
1355  if((*fit)->geomType() != GEntity::DiscreteSurface) {
1356  meshGFaceBamg(*fit);
1357  laplaceSmoothing(*fit, CTX::instance()->mesh.nbSmoothing);
1358  }
1359  if(_elementOctree) delete _elementOctree;
1360  _elementOctree = nullptr;
1361  }
1362  }
1363  else if(getDim() == 3) {
1364  for(auto rit = firstRegion(); rit != lastRegion(); ++rit) {
1365  refineMeshMMG(*rit);
1366  if(_elementOctree) delete _elementOctree;
1367  _elementOctree = nullptr;
1368  }
1369  }
1370 
1371  char name[256];
1372  sprintf(name, "meshAdapt-%d.msh", ITER);
1373  writeMSH(name);
1374 
1375  nbElems = getNumMeshElements();
1376  if(++ITER >= niter) break;
1377  if(ITER > 3 && fabs((double)(nbElems - nbElemsOld)) < 0.01 * nbElemsOld)
1378  break;
1379 
1380  nbElemsOld = nbElems;
1381  }
1382  }
1383 
1384  fields->reset();
1385  // copy context (in order to allow multiple calls)
1386  *(CTX::instance()) = _backup;
1387 
1388  if(CTX::instance()->mesh.renumber) {
1391  }
1393 
1394  return 0;
1395 #else
1396  Msg::Error("Mesh module not compiled");
1397  return -1;
1398 #endif
1399 }
1400 
1401 int GModel::refineMesh(int linear, bool splitIntoQuads, bool splitIntoHexas,
1402  bool barycentric)
1403 {
1404 #if defined(HAVE_MESH)
1405  if(!barycentric) { RefineMesh(this, linear, splitIntoQuads, splitIntoHexas); }
1406  else {
1407  BarycentricRefineMesh(this);
1408  }
1409  if(CTX::instance()->mesh.renumber) {
1412  }
1414  return 1;
1415 #else
1416  Msg::Error("Mesh module not compiled");
1417  return 0;
1418 #endif
1419 }
1420 
1422 {
1423 #if defined(HAVE_MESH)
1424  RecombineMesh(this);
1425  if(CTX::instance()->mesh.renumber) {
1428  }
1430  return 1;
1431 #else
1432  Msg::Error("Mesh module not compiled");
1433  return 0;
1434 #endif
1435 }
1436 
1437 int GModel::optimizeMesh(const std::string &how, const bool force, int niter)
1438 {
1439 #if defined(HAVE_MESH)
1440  OptimizeMesh(this, how, force, niter);
1441  FixPeriodicMesh(this);
1442  if(CTX::instance()->mesh.renumber) {
1445  }
1447  return 1;
1448 #else
1449  Msg::Error("Mesh module not compiled");
1450  return 0;
1451 #endif
1452 }
1453 
1454 int GModel::setOrderN(int order, int linear, int incomplete, int onlyVisible)
1455 {
1456 #if defined(HAVE_MESH)
1457  if(order > 1)
1458  SetOrderN(this, order, linear, incomplete, onlyVisible);
1459  else
1460  SetOrder1(this);
1461  FixPeriodicMesh(this);
1462  if(CTX::instance()->mesh.renumber) {
1465  }
1467  return true;
1468 #else
1469  Msg::Error("Mesh module not compiled");
1470  return false;
1471 #endif
1472 }
1473 
1474 int GModel::getMeshStatus(bool countDiscrete)
1475 {
1476  std::size_t numEle3D = 0;
1477  bool toMesh3D = false;
1478  bool onlyVisible = CTX::instance()->mesh.meshOnlyVisible;
1479 
1480  for(auto it = firstRegion(); it != lastRegion(); ++it) {
1481  GRegion *gr = *it;
1482  if(countDiscrete || gr->geomType() != GEntity::DiscreteVolume)
1483  numEle3D += gr->getNumMeshElements();
1484  if(countDiscrete && numEle3D) return 3;
1485  if(gr->geomType() != GEntity::DiscreteVolume &&
1487  toMesh3D = true;
1488  }
1489  if(numEle3D && toMesh3D) return 3;
1490 
1491  std::size_t numEle2D = 0;
1492  bool toMesh2D = false, meshDone2D = true;
1493  for(auto it = firstFace(); it != lastFace(); ++it) {
1494  GFace *gf = *it;
1495  if(countDiscrete || gf->geomType() != GEntity::DiscreteSurface)
1496  numEle2D += gf->getNumMeshElements();
1497  if(countDiscrete && numEle2D) return 2;
1498  if(gf->geomType() != GEntity::DiscreteSurface &&
1500  toMesh2D = true;
1501  if(gf->meshStatistics.status != GEntity::DONE &&
1502  (!onlyVisible || (onlyVisible && gf->getVisibility())))
1503  meshDone2D = false;
1504  }
1505  if(numEle2D && toMesh2D && meshDone2D) return 2;
1506 
1507  std::size_t numEle1D = 0;
1508  bool toMesh1D = false, meshDone1D = true;
1509  for(auto it = firstEdge(); it != lastEdge(); ++it) {
1510  GEdge *ge = *it;
1511  if(countDiscrete || ge->geomType() != GEntity::DiscreteCurve)
1512  numEle1D += ge->getNumMeshElements();
1513  if(countDiscrete && numEle1D) return 1;
1514  if(ge->geomType() != GEntity::DiscreteCurve &&
1516  toMesh1D = true;
1517  if(ge->meshStatistics.status != GEntity::DONE &&
1518  (!onlyVisible || (onlyVisible && ge->getVisibility())))
1519  meshDone1D = false;
1520  }
1521  if(numEle1D && toMesh1D && meshDone1D) return 1;
1522 
1523  for(auto it = firstVertex(); it != lastVertex(); ++it)
1524  if((*it)->mesh_vertices.size()) return 0;
1525 
1526  return -1;
1527 }
1528 
1529 std::size_t GModel::getNumMeshVertices(int dim) const
1530 {
1531  std::vector<GEntity *> entities;
1532  getEntities(entities);
1533  std::size_t n = 0;
1534  for(std::size_t i = 0; i < entities.size(); i++)
1535  if(entities[i]->dim() == dim || dim < 0)
1536  n += entities[i]->getNumMeshVertices();
1537  return n;
1538 }
1539 
1540 std::size_t GModel::getNumMeshElements(int dim) const
1541 {
1542  std::vector<GEntity *> entities;
1543  getEntities(entities);
1544  std::size_t n = 0;
1545  for(std::size_t i = 0; i < entities.size(); i++)
1546  if(entities[i]->dim() == dim || dim < 0)
1547  n += entities[i]->getNumMeshElements();
1548  return n;
1549 }
1550 
1552 {
1553  std::vector<GEntity *> entities;
1554  getEntities(entities);
1555  std::size_t n = 0;
1556  for(std::size_t i = 0; i < entities.size(); i++)
1557  n += entities[i]->getNumMeshParentElements();
1558  return n;
1559 }
1560 
1561 std::size_t GModel::addMEdge(MEdge &edge, std::size_t num)
1562 {
1563  std::pair<MEdge, std::size_t> key(std::move(edge),
1564  num ? num : _mapEdgeNum.size() + 1);
1565  std::pair<hashmapMEdge::iterator, bool> it = _mapEdgeNum.insert(std::move(key));
1566  return it.first->second;
1567 }
1568 
1569 std::size_t GModel::getMEdge(MVertex *v0, MVertex *v1, MEdge &edge)
1570 {
1571  MEdge e(v0, v1);
1572  auto it = _mapEdgeNum.find(e);
1573  if(it != _mapEdgeNum.end()) {
1574  edge = it->first;
1575  return it->second;
1576  }
1577  else {
1578  Msg::Error("Unknown edge %d %d", v0->getNum(), v1->getNum());
1579  return 0;
1580  }
1581 }
1582 
1583 std::size_t GModel::addMFace(MFace &face, std::size_t num)
1584 {
1585  std::pair<MFace, std::size_t> key(std::move(face),
1586  num ? num : _mapFaceNum.size() + 1);
1587  std::pair<hashmapMFace::iterator, bool> it = _mapFaceNum.insert(std::move(key));
1588  return it.first->second;
1589 }
1590 
1591 std::size_t GModel::getMFace(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3,
1592  MFace &face)
1593 {
1594  MFace f(v0, v1, v2, v3);
1595  auto it = _mapFaceNum.find(f);
1596  if(it != _mapFaceNum.end()) {
1597  face = it->first;
1598  return it->second;
1599  }
1600  else {
1601  Msg::Error("Unknown face %d %d %d", v0->getNum(), v1->getNum(), v2->getNum());
1602  return 0;
1603  }
1604 }
1605 
1606 #if defined(HAVE_POST)
1607 static void getDependentViewData(GModel *m, PViewDataGModel::DataType type,
1608  std::vector<stepData<double> *> &data)
1609 {
1610  for(std::size_t i = 0; i < PView::list.size(); i++) {
1611  PViewDataGModel *d =
1612  dynamic_cast<PViewDataGModel *>(PView::list[i]->getData());
1613  if(d && d->getType() == type) {
1614  for(int step = 0; step < d->getNumTimeSteps(); step++) {
1615  if(d->getStepData(step)->getModel() == m)
1616  data.push_back(d->getStepData(step));
1617  }
1618  }
1619  }
1620 }
1621 #endif
1622 
1624 {
1626  setMaxVertexNumber(CTX::instance()->mesh.firstNodeTag - 1);
1627  std::vector<GEntity *> entities;
1628  getEntities(entities);
1629 
1630 #if defined(HAVE_POST)
1631  // check if any nodal post-processing datasets depend on the model; if so,
1632  // keep track of the old node numbering
1633  std::map<MVertex *, int> old;
1634  std::vector<stepData<double> *> data;
1635  getDependentViewData(this, PViewDataGModel::NodeData, data);
1636  if(data.size()) {
1637  for(std::size_t i = 0; i < entities.size(); i++) {
1638  GEntity *ge = entities[i];
1639  for(std::size_t j = 0; j < ge->getNumMeshVertices(); j++) {
1640  MVertex *v = ge->getMeshVertex(j);
1641  old[v] = v->getNum();
1642  }
1643  }
1644  }
1645 #endif
1646 
1647  // check if we will potentially only save a subset of elements: only those
1648  // belonging to physical groups and/or those not being orphans
1649  bool saveOnlyPhysicals = false;
1650  if(!CTX::instance()->mesh.saveAll) {
1651  for(std::size_t i = 0; i < entities.size(); i++) {
1652  if(entities[i]->physicals.size()) {
1653  saveOnlyPhysicals = true;
1654  break;
1655  }
1656  }
1657  }
1658  bool pruneOrphans = CTX::instance()->mesh.saveWithoutOrphans;
1659 
1660  std::size_t n = CTX::instance()->mesh.firstNodeTag - 1;
1661  if(saveOnlyPhysicals || pruneOrphans) {
1662  Msg::Debug("Renumbering for potentially partial mesh save");
1663  // if we potentially only save a subset of elements, make sure to first
1664  // renumber the nodes that belong to those elements (so that we end up
1665  // with a dense node numbering in the output file)
1666  std::size_t nv = CTX::instance()->mesh.firstNodeTag - 1;
1667  for(std::size_t i = 0; i < entities.size(); i++) {
1668  GEntity *ge = entities[i];
1669  nv += ge->getNumMeshVertices();
1670  }
1671  for(std::size_t i = 0; i < entities.size(); i++) {
1672  GEntity *ge = entities[i];
1673  for(std::size_t j = 0; j < ge->getNumMeshVertices(); j++) {
1674  ge->getMeshVertex(j)->forceNum(nv + 1);
1675  }
1676  }
1677  for(std::size_t i = 0; i < entities.size(); i++) {
1678  GEntity *ge = entities[i];
1679  if(!((pruneOrphans && ge->isOrphan()) ||
1680  (saveOnlyPhysicals && ge->physicals.empty()))) {
1681  for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1682  MElement *e = ge->getMeshElement(j);
1683  for(std::size_t k = 0; k < e->getNumVertices(); k++) {
1684  e->getVertex(k)->forceNum(0);
1685  }
1686  }
1687  }
1688  }
1689  for(std::size_t i = 0; i < entities.size(); i++) {
1690  GEntity *ge = entities[i];
1691  for(std::size_t j = 0; j < ge->getNumMeshVertices(); j++) {
1692  MVertex *v = ge->getMeshVertex(j);
1693  if(v->getNum() == 0) v->forceNum(++n);
1694  }
1695  }
1696  for(std::size_t i = 0; i < entities.size(); i++) {
1697  GEntity *ge = entities[i];
1698  for(std::size_t j = 0; j < ge->getNumMeshVertices(); j++) {
1699  MVertex *v = ge->getMeshVertex(j);
1700  if(v->getNum() == nv + 1) v->forceNum(++n);
1701  }
1702  }
1703  }
1704  else {
1705  // full save
1706  for(std::size_t i = 0; i < entities.size(); i++) {
1707  GEntity *ge = entities[i];
1708  for(std::size_t j = 0; j < ge->getNumMeshVertices(); j++) {
1709  ge->getMeshVertex(j)->forceNum(++n);
1710  }
1711  }
1712  }
1713 
1714 #if defined(HAVE_POST)
1715  // renumber any dependent nodal post-processing datasets
1716  if(data.size()) {
1717  int n = data.size();
1718  Msg::Info("Renumbering nodal model data (%d step%s)", n, n > 1 ? "s" : "");
1719  std::map<int, int> remap;
1720  for(std::size_t i = 0; i < entities.size(); i++) {
1721  GEntity *ge = entities[i];
1722  for(std::size_t j = 0; j < ge->getNumMeshVertices(); j++) {
1723  MVertex *v = ge->getMeshVertex(j);
1724  remap[old[v]] = v->getNum();
1725  }
1726  }
1727  for(auto d : data) { d->renumberData(remap); }
1728  }
1729 #endif
1730 }
1731 
1733 {
1735  setMaxElementNumber(CTX::instance()->mesh.firstElementTag - 1);
1736  std::vector<GEntity *> entities;
1737  getEntities(entities);
1738 
1739 #if defined(HAVE_POST)
1740  // check if any element-based post-processing datasets depend on the model; if
1741  // so, keep track of the old element numbering
1742  std::map<MElement *, int> old;
1743  std::vector<stepData<double> *> data[2];
1744  getDependentViewData(this, PViewDataGModel::ElementData, data[0]);
1745  getDependentViewData(this, PViewDataGModel::ElementNodeData, data[1]);
1746  if(data[0].size() || data[1].size()) {
1747  for(std::size_t i = 0; i < entities.size(); i++) {
1748  GEntity *ge = entities[i];
1749  for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1750  MElement *e = ge->getMeshElement(j);
1751  old[e] = e->getNum();
1752  }
1753  }
1754  }
1755 #endif
1756 
1757  // check if we will potentially only save a subset of elements: only those
1758  // belonging to physical groups and/or those not being orphans
1759  bool saveOnlyPhysicals = false;
1760  if(!CTX::instance()->mesh.saveAll) {
1761  for(std::size_t i = 0; i < entities.size(); i++) {
1762  if(entities[i]->physicals.size()) {
1763  saveOnlyPhysicals = true;
1764  break;
1765  }
1766  }
1767  }
1768  bool pruneOrphans = CTX::instance()->mesh.saveWithoutOrphans;
1769 
1770  std::size_t n = CTX::instance()->mesh.firstElementTag - 1;
1771  if(saveOnlyPhysicals || pruneOrphans) {
1772  for(std::size_t i = 0; i < entities.size(); i++) {
1773  GEntity *ge = entities[i];
1774  if(!((pruneOrphans && ge->isOrphan()) ||
1775  (saveOnlyPhysicals && ge->physicals.empty()))) {
1776  for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1777  ge->getMeshElement(j)->forceNum(++n);
1778  }
1779  }
1780  }
1781  for(std::size_t i = 0; i < entities.size(); i++) {
1782  GEntity *ge = entities[i];
1783  if(((pruneOrphans && ge->isOrphan()) ||
1784  (saveOnlyPhysicals && ge->physicals.empty()))) {
1785  for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1786  ge->getMeshElement(j)->forceNum(++n);
1787  }
1788  }
1789  }
1790  }
1791  else {
1792  // full save
1793  for(std::size_t i = 0; i < entities.size(); i++) {
1794  GEntity *ge = entities[i];
1795  for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1796  ge->getMeshElement(j)->forceNum(++n);
1797  }
1798  }
1799  }
1800 
1801 #if defined(HAVE_POST)
1802  // renumber any dependent element post-processing datasets
1803  if(data[0].size() || data[1].size()) {
1804  int n = data[0].size() + data[1].size();
1805  Msg::Info("Renumbering element model data (%d step%s)", n,
1806  n > 1 ? "s" : "");
1807  std::map<int, int> remap;
1808  for(std::size_t i = 0; i < entities.size(); i++) {
1809  GEntity *ge = entities[i];
1810  for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
1811  MElement *e = ge->getMeshElement(j);
1812  remap[old[e]] = e->getNum();
1813  }
1814  }
1815  for(int i = 0; i < 2; i++) {
1816  for(auto d : data[i]) { d->renumberData(remap); }
1817  }
1818  }
1819 #endif
1820 }
1821 
1822 std::size_t GModel::getNumMeshElements(unsigned c[6])
1823 {
1824  c[0] = 0;
1825  c[1] = 0;
1826  c[2] = 0;
1827  c[3] = 0;
1828  c[4] = 0;
1829  c[5] = 0;
1830  for(auto it = firstRegion(); it != lastRegion(); ++it)
1831  (*it)->getNumMeshElements(c);
1832  if(c[0] + c[1] + c[2] + c[3] + c[4] + c[5]) return 3;
1833  for(auto it = firstFace(); it != lastFace(); ++it)
1834  (*it)->getNumMeshElements(c);
1835  if(c[0] + c[1] + c[2]) return 2;
1836  for(auto it = firstEdge(); it != lastEdge(); ++it)
1837  (*it)->getNumMeshElements(c);
1838  if(c[0]) return 1;
1839  return 0;
1840 }
1841 
1843  bool strict)
1844 {
1845  if(!_elementOctree) {
1846 #pragma omp barrier
1847 #pragma omp single
1848  {
1849  Msg::Debug("Rebuilding mesh element octree");
1850  _elementOctree = new MElementOctree(this);
1851  }
1852  }
1853  MElement *e = _elementOctree->find(p.x(), p.y(), p.z(), dim, strict);
1854  if(e) {
1855  double xyz[3] = {p.x(), p.y(), p.z()}, uvw[3];
1856  e->xyz2uvw(xyz, uvw);
1857  param.setPosition(uvw[0], uvw[1], uvw[2]);
1858  }
1859  else {
1860  param.setPosition(0, 0, 0);
1861  }
1862  return e;
1863 }
1864 
1865 std::vector<MElement *> GModel::getMeshElementsByCoord(SPoint3 &p, int dim,
1866  bool strict)
1867 {
1868  if(!_elementOctree) {
1869 #pragma omp barrier
1870 #pragma omp single
1871  {
1872  Msg::Debug("Rebuilding mesh element octree");
1873  _elementOctree = new MElementOctree(this);
1874  }
1875  }
1876  return _elementOctree->findAll(p.x(), p.y(), p.z(), dim, strict);
1877 }
1878 
1879 void GModel::rebuildMeshVertexCache(bool onlyIfNecessary)
1880 {
1881  if(!onlyIfNecessary ||
1882  (_vertexVectorCache.empty() && _vertexMapCache.empty())) {
1883  _vertexVectorCache.clear();
1884  _vertexMapCache.clear();
1885  bool dense = false;
1887  Msg::Debug("We have a dense node numbering in the cache");
1888  dense = true;
1889  }
1890  else if(_maxVertexNum < 10 * getNumMeshVertices()) {
1891  Msg::Debug(
1892  "We have a fairly dense node numbering - still using cache vector");
1893  dense = true;
1894  }
1895  std::vector<GEntity *> entities;
1896  getEntities(entities);
1897  if(dense) {
1898  // numbering starts at 1
1899  _vertexVectorCache.resize(_maxVertexNum + 1, (MVertex *)nullptr);
1900  for(std::size_t i = 0; i < entities.size(); i++)
1901  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
1902  _vertexVectorCache[entities[i]->mesh_vertices[j]->getNum()] =
1903  entities[i]->mesh_vertices[j];
1904  }
1905  else {
1906  for(std::size_t i = 0; i < entities.size(); i++)
1907  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
1908  _vertexMapCache[entities[i]->mesh_vertices[j]->getNum()] =
1909  entities[i]->mesh_vertices[j];
1910  }
1911  }
1912 }
1913 
1914 void GModel::rebuildMeshElementCache(bool onlyIfNecessary)
1915 {
1916  if(!onlyIfNecessary ||
1917  (_elementVectorCache.empty() && _elementMapCache.empty())) {
1918  Msg::Debug("Rebuilding mesh element cache");
1919  _elementVectorCache.clear();
1920  _elementMapCache.clear();
1921  bool dense = false;
1923  Msg::Debug("We have a dense element numbering in the cache");
1924  dense = true;
1925  }
1926  else if(_maxElementNum < 10 * getNumMeshElements()) {
1927  Msg::Debug(
1928  "We have a fairly dense element numbering - still using cache vector");
1929  dense = true;
1930  }
1931  std::vector<GEntity *> entities;
1932  getEntities(entities);
1933  if(dense) {
1934  // numbering starts at 1
1935  _elementVectorCache.resize(_maxElementNum + 1, std::make_pair(nullptr, 0));
1936  for(std::size_t i = 0; i < entities.size(); i++)
1937  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
1938  MElement *e = entities[i]->getMeshElement(j);
1939  _elementVectorCache[e->getNum()] =
1940  std::make_pair(e, entities[i]->tag());
1941  }
1942  }
1943  else {
1944  for(std::size_t i = 0; i < entities.size(); i++)
1945  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
1946  MElement *e = entities[i]->getMeshElement(j);
1947  _elementMapCache[e->getNum()] = std::make_pair(e, entities[i]->tag());
1948  }
1949  }
1950  }
1951 }
1952 
1954 {
1955  if(_vertexVectorCache.empty() && _vertexMapCache.empty()) {
1956 #pragma omp barrier
1957 #pragma omp single
1958  {
1959  Msg::Debug("Rebuilding mesh node cache");
1961  }
1962  }
1963 
1964  if(n < (int)_vertexVectorCache.size())
1965  return _vertexVectorCache[n];
1966  else
1967  return _vertexMapCache[n];
1968 }
1969 
1971 {
1972  if(_vertexVectorCache.empty() && _vertexMapCache.empty()) {
1973  Msg::Debug("Rebuilding mesh node cache");
1975  }
1976  if (_vertexVectorCache.size() > 0) {
1977 #pragma omp critical
1978  if (v->getNum() >= _vertexVectorCache.size()) {
1979  _vertexVectorCache.resize(v->getNum()+1, nullptr);
1980  }
1981  _vertexVectorCache[v->getNum()] = v;
1982  } else {
1983  _vertexMapCache[v->getNum()] = v;
1984  }
1985 }
1986 
1988  std::vector<MVertex *> &v)
1989 {
1990  v.clear();
1991  std::map<int, std::vector<GEntity *> > groups;
1992  getPhysicalGroups(dim, groups);
1993  std::map<int, std::vector<GEntity *> >::const_iterator it = groups.find(num);
1994  if(it == groups.end()) return;
1995  const std::vector<GEntity *> &entities = it->second;
1996  std::set<MVertex *, MVertexPtrLessThan> sv;
1997  for(std::size_t i = 0; i < entities.size(); i++) {
1998  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
1999  MElement *e = entities[i]->getMeshElement(j);
2000  for(std::size_t k = 0; k < e->getNumVertices(); k++)
2001  sv.insert(e->getVertex(k));
2002  }
2003  }
2004  v.insert(v.begin(), sv.begin(), sv.end());
2005 }
2006 
2007 MElement *GModel::getMeshElementByTag(int n, int &entityTag)
2008 {
2009  if(_elementVectorCache.empty() && _elementMapCache.empty()) {
2010 #pragma omp barrier
2011 #pragma omp single
2012  {
2013  Msg::Debug("Rebuilding mesh element cache");
2015  }
2016  }
2017 
2018  std::pair<MElement*, int> ret;
2019  if(n < (int)_elementVectorCache.size())
2020  ret = _elementVectorCache[n];
2021  else
2022  ret = _elementMapCache[n];
2023  entityTag = ret.second;
2024  return ret.first;
2025 }
2026 
2028 {
2029  if(!e) return 0;
2030  if(_elementIndexCache.empty()) return e->getNum();
2031  auto it = _elementIndexCache.find(e->getNum());
2032  if(it != _elementIndexCache.end()) return it->second;
2033  return e->getNum();
2034 }
2035 
2037 {
2038  _elementIndexCache[e->getNum()] = index;
2039 }
2040 
2041 template <class T>
2042 static std::size_t removeInvisible(std::vector<T *> &elements, bool all)
2043 {
2044  std::vector<T *> tmp;
2045  std::size_t n = elements.size();
2046  for(std::size_t i = 0; i < n; i++) {
2047  if(all || !elements[i]->getVisibility())
2048  delete elements[i];
2049  else
2050  tmp.push_back(elements[i]);
2051  }
2052  elements.clear();
2053  elements = tmp;
2054  return n - elements.size();
2055 }
2056 
2058 {
2059  std::size_t n = 0;
2060  for(auto it = firstRegion(); it != lastRegion(); ++it) {
2061  bool all = !(*it)->getVisibility();
2062  n += removeInvisible((*it)->tetrahedra, all);
2063  n += removeInvisible((*it)->hexahedra, all);
2064  n += removeInvisible((*it)->prisms, all);
2065  n += removeInvisible((*it)->pyramids, all);
2066  n += removeInvisible((*it)->trihedra, all);
2067  n += removeInvisible((*it)->polyhedra, all);
2068  (*it)->deleteVertexArrays();
2069  }
2070  for(auto it = firstFace(); it != lastFace(); ++it) {
2071  bool all = !(*it)->getVisibility();
2072  n += removeInvisible((*it)->triangles, all);
2073  n += removeInvisible((*it)->quadrangles, all);
2074  n += removeInvisible((*it)->polygons, all);
2075  (*it)->deleteVertexArrays();
2076  }
2077  for(auto it = firstEdge(); it != lastEdge(); ++it) {
2078  bool all = !(*it)->getVisibility();
2079  n += removeInvisible((*it)->lines, all);
2080  (*it)->deleteVertexArrays();
2081  }
2083  Msg::Info("Removed %lu elements", n);
2084  return n;
2085 }
2086 
2087 template <class T>
2088 static std::size_t reverseInvisible(std::vector<T *> &elements, bool all)
2089 {
2090  std::size_t n = 0;
2091  std::vector<T *> tmp;
2092  for(std::size_t i = 0; i < elements.size(); i++) {
2093  if(all || !elements[i]->getVisibility()) {
2094  elements[i]->reverse();
2095  elements[i]->setVisibility(1);
2096  n++;
2097  }
2098  }
2099  return n;
2100 }
2101 
2103 {
2104  std::size_t n = 0;
2105  for(auto it = firstRegion(); it != lastRegion(); ++it) {
2106  bool all = !(*it)->getVisibility();
2107  n += reverseInvisible((*it)->tetrahedra, all);
2108  n += reverseInvisible((*it)->hexahedra, all);
2109  n += reverseInvisible((*it)->prisms, all);
2110  n += reverseInvisible((*it)->pyramids, all);
2111  n += reverseInvisible((*it)->trihedra, all);
2112  n += reverseInvisible((*it)->polyhedra, all);
2113  (*it)->deleteVertexArrays();
2114  if(all) (*it)->setVisibility(1);
2115  }
2116  for(auto it = firstFace(); it != lastFace(); ++it) {
2117  bool all = !(*it)->getVisibility();
2118  n += reverseInvisible((*it)->triangles, all);
2119  n += reverseInvisible((*it)->quadrangles, all);
2120  n += reverseInvisible((*it)->polygons, all);
2121  (*it)->deleteVertexArrays();
2122  if(all) (*it)->setVisibility(1);
2123  }
2124  for(auto it = firstEdge(); it != lastEdge(); ++it) {
2125  bool all = !(*it)->getVisibility();
2126  n += reverseInvisible((*it)->lines, all);
2127  (*it)->deleteVertexArrays();
2128  if(all) (*it)->setVisibility(1);
2129  }
2131  Msg::Info("Reversed %lu elements", n);
2132  return n;
2133 }
2134 
2135 std::size_t GModel::indexMeshVertices(bool all, int singlePartition,
2136  bool renumber)
2137 {
2138  std::vector<GEntity *> entities;
2139  getEntities(entities);
2140 
2141  // tag all mesh nodes with -1 (negative nodes will not be saved)
2142  for(std::size_t i = 0; i < entities.size(); i++)
2143  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
2144  entities[i]->mesh_vertices[j]->setIndex(-1);
2145 
2146  // tag all mesh nodes belonging to elements that need to be saved with 0, or
2147  // with -2 if they need to be taken into account in the numbering but need not
2148  // to be saved (because we save a single partition and they are not used in
2149  // that partition)
2150  for(std::size_t i = 0; i < entities.size(); i++) {
2151  if(all || entities[i]->physicals.size() ||
2152  (entities[i]->getParentEntity() &&
2153  entities[i]->getParentEntity()->physicals.size())) {
2154  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
2155  MElement *e = entities[i]->getMeshElement(j);
2156  for(std::size_t k = 0; k < e->getNumVertices(); k++) {
2157  if(singlePartition <= 0 || e->getPartition() == singlePartition)
2158  e->getVertex(k)->setIndex(0);
2159  else if(e->getVertex(k)->getIndex() == -1)
2160  e->getVertex(k)->setIndex(-2);
2161  }
2162  }
2163  }
2164  }
2165 
2166  // renumber all the mesh nodes tagged with 0
2167  std::size_t numVertices = 0;
2168  long int index = 0;
2169  for(std::size_t i = 0; i < entities.size(); i++) {
2170  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++) {
2171  MVertex *v = entities[i]->mesh_vertices[j];
2172  if(!v->getIndex()) {
2173  index++;
2174  numVertices++;
2175  if(renumber)
2176  v->setIndex(index);
2177  else
2178  v->setIndex(v->getNum());
2179  }
2180  else if(v->getIndex() == -2) {
2181  index++;
2182  }
2183  }
2184  }
2185 
2186  return numVertices;
2187 }
2188 
2189 void GModel::scaleMesh(double factor)
2190 {
2191  std::vector<GEntity *> entities;
2192  getEntities(entities);
2193  for(std::size_t i = 0; i < entities.size(); i++)
2194  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++) {
2195  MVertex *v = entities[i]->mesh_vertices[j];
2196  v->x() *= factor;
2197  v->y() *= factor;
2198  v->z() *= factor;
2199  }
2200 }
2201 
2203 {
2204 #pragma omp atomic write
2205  _currentMeshEntity = e;
2206 }
2207 
2209  int numPart, std::vector<std::pair<MElement *, int> > elementPartition)
2210 {
2211 #if defined(HAVE_MESH) && (defined(HAVE_METIS))
2212  if(numPart > 0) {
2213  if(_numPartitions > 0) UnpartitionMesh(this);
2214  if(elementPartition.empty())
2215  return PartitionMesh(this, numPart);
2216  else
2217  return PartitionUsingThisSplit(this, elementPartition);
2218  }
2219  return 1;
2220 #else
2221  Msg::Error("Mesh or Metis module not compiled");
2222  return 1;
2223 #endif
2224 }
2225 
2227 {
2228 #if defined(HAVE_MESH)
2229  return UnpartitionMesh(this);
2230 #else
2231  Msg::Error("Mesh module not compiled");
2232  return 1;
2233 #endif
2234 }
2235 
2237 {
2238 #if defined(HAVE_MESH) && (defined(HAVE_METIS))
2239  int ier = ConvertOldPartitioningToNewOne(this);
2240  return ier;
2241 #else
2242  Msg::Error("Mesh or Metis module not compiled");
2243  return 1;
2244 #endif
2245 }
2246 
2247 void GModel::storeChain(int dim,
2248  std::map<int, std::vector<MElement *> > &entityMap,
2249  std::map<int, std::map<int, std::string> > &physicalMap)
2250 {
2251  _storeElementsInEntities(entityMap);
2252  _storePhysicalTagsInEntities(dim, physicalMap);
2253  std::map<int, std::vector<MElement *> >::iterator it;
2254  for(it = entityMap.begin(); it != entityMap.end(); it++) {
2255  if(dim == 0)
2256  _chainVertices.insert(getVertexByTag(it->first));
2257  else if(dim == 1)
2258  _chainEdges.insert(getEdgeByTag(it->first));
2259  else if(dim == 2)
2260  _chainFaces.insert(getFaceByTag(it->first));
2261  else if(dim == 3)
2262  _chainRegions.insert(getRegionByTag(it->first));
2263  }
2264 }
2265 
2266 template <class T>
2267 static void _addElements(std::vector<T *> &dst,
2268  const std::vector<MElement *> &src)
2269 {
2270  for(std::size_t i = 0; i < src.size(); i++) dst.push_back((T *)src[i]);
2271 }
2272 
2274  std::map<int, std::vector<MElement *> > &map)
2275 {
2276  std::map<int, std::vector<MElement *> >::const_iterator it = map.begin();
2277  for(; it != map.end(); ++it) {
2278  if(!it->second.size()) continue;
2279  int type = it->second[0]->getType();
2280  switch(type) {
2281  case TYPE_PNT: {
2282  GVertex *v = getVertexByTag(it->first);
2283  if(!v) {
2284  double x = it->second[0]->getVertex(0)->x();
2285  double y = it->second[0]->getVertex(0)->y();
2286  double z = it->second[0]->getVertex(0)->z();
2287  v = new discreteVertex(this, it->first, x, y, z);
2288  add(v);
2289  }
2290  if(!v->points.empty()) { // CAD points already have one by default
2291  v->points.clear();
2292  v->mesh_vertices.clear();
2293  }
2294  _addElements(v->points, it->second);
2295  } break;
2296  case TYPE_LIN: {
2297  GEdge *e = getEdgeByTag(it->first);
2298  if(!e) {
2299  e = new discreteEdge(this, it->first, nullptr, nullptr);
2300  add(e);
2301  }
2302  _addElements(e->lines, it->second);
2303  } break;
2304  case TYPE_TRI:
2305  case TYPE_QUA:
2306  case TYPE_POLYG: {
2307  GFace *f = getFaceByTag(it->first);
2308  if(!f) {
2309  f = new discreteFace(this, it->first);
2310  add(f);
2311  }
2312  if(type == TYPE_TRI)
2313  _addElements(f->triangles, it->second);
2314  else if(type == TYPE_QUA)
2315  _addElements(f->quadrangles, it->second);
2316  else
2317  _addElements(f->polygons, it->second);
2318  } break;
2319  case TYPE_TET:
2320  case TYPE_HEX:
2321  case TYPE_PYR:
2322  case TYPE_TRIH:
2323  case TYPE_PRI:
2324  case TYPE_POLYH: {
2325  GRegion *r = getRegionByTag(it->first);
2326  if(!r) {
2327  r = new discreteRegion(this, it->first);
2328  add(r);
2329  }
2330  if(type == TYPE_TET)
2331  _addElements(r->tetrahedra, it->second);
2332  else if(type == TYPE_HEX)
2333  _addElements(r->hexahedra, it->second);
2334  else if(type == TYPE_PRI)
2335  _addElements(r->prisms, it->second);
2336  else if(type == TYPE_PYR)
2337  _addElements(r->pyramids, it->second);
2338  else if(type == TYPE_TRIH)
2339  _addElements(r->trihedra, it->second);
2340  else
2341  _addElements(r->polyhedra, it->second);
2342  } break;
2343  }
2344  }
2345 }
2346 
2348  std::map<int, std::vector<MElement *> > &map)
2349 {
2350  std::map<int, std::vector<MElement *> >::const_iterator it;
2351  for(it = map.begin(); it != map.end(); ++it)
2352  for(std::size_t i = 0; i < it->second.size(); ++i)
2353  it->second[i]->updateParent(this);
2354 }
2355 
2356 template <class T>
2358  std::vector<T *> &elements,
2359  bool force = false)
2360 {
2361  for(std::size_t i = 0; i < elements.size(); i++) {
2362  for(std::size_t j = 0; j < elements[i]->getNumVertices(); j++) {
2363  if(force || !elements[i]->getVertex(j)->onWhat() ||
2364  elements[i]->getVertex(j)->onWhat()->dim() > ge->dim())
2365  elements[i]->getVertex(j)->setEntity(ge);
2366  }
2367  }
2368 }
2369 
2371  const std::vector<std::pair<int, int> > &dimTags)
2372 {
2373  std::vector<discreteEdge *> e;
2374  std::vector<discreteFace *> f;
2375  std::vector<discreteRegion *> r;
2376 
2377  if(dimTags.empty()) {
2378  for(auto it = firstEdge(); it != lastEdge(); it++) {
2379  discreteEdge *de = dynamic_cast<discreteEdge *>(*it);
2380  if(de) e.push_back(de);
2381  }
2382  for(auto it = firstFace(); it != lastFace(); it++) {
2383  discreteFace *df = dynamic_cast<discreteFace *>(*it);
2384  if(df) f.push_back(df);
2385  }
2386  for(auto it = firstRegion(); it != lastRegion(); it++) {
2387  discreteRegion *dr = dynamic_cast<discreteRegion *>(*it);
2388  if(dr) r.push_back(dr);
2389  }
2390  }
2391  else {
2392  for(std::size_t i = 0; i < dimTags.size(); i++) {
2393  int dim = dimTags[i].first;
2394  int tag = dimTags[i].second;
2395  if(dim == 1) {
2396  discreteEdge *de = dynamic_cast<discreteEdge *>(getEdgeByTag(tag));
2397  if(de)
2398  e.push_back(de);
2399  else
2400  Msg::Error("No discrete curve with tag %d", tag);
2401  }
2402  else if(dim == 2) {
2403  discreteFace *df = dynamic_cast<discreteFace *>(getFaceByTag(tag));
2404  if(df)
2405  f.push_back(df);
2406  else
2407  Msg::Error("No discrete surface with tag %d", tag);
2408  }
2409  else if(dim == 3) {
2410  discreteRegion *dr =
2411  dynamic_cast<discreteRegion *>(getRegionByTag(tag));
2412  if(dr)
2413  r.push_back(dr);
2414  else
2415  Msg::Error("No discrete volume with tag %d", tag);
2416  }
2417  }
2418  }
2419 
2420  if(e.size()) {
2421  Msg::StatusBar(true, "Creating geometry of discrete curves...");
2422  double t1 = Cpu(), w1 = TimeOfDay();
2423  for(std::size_t i = 0; i < e.size(); i++) {
2424  if(e[i]->createGeometry())
2425  Msg::Error("Could not create geometry of discrete curve %d",
2426  e[i]->tag());
2427  }
2428  double t2 = Cpu(), w2 = TimeOfDay();
2429  Msg::StatusBar(true,
2430  "Done creating geometry of discrete curves "
2431  "(Wall %gs, CPU %gs)",
2432  w2 - w1, t2 - t1);
2433  }
2434 
2435  if(f.size()) {
2436  Msg::StatusBar(true, "Creating geometry of discrete surfaces...");
2437  double t1 = Cpu(), w1 = TimeOfDay();
2438  Msg::StartProgressMeter(f.size());
2439  for(std::size_t i = 0; i < f.size(); i++) {
2440  Msg::ProgressMeter(i, true, "Creating geometry");
2441  if(f[i]->createGeometry())
2442  Msg::Error("Could not create geometry of discrete surface %d",
2443  f[i]->tag());
2444  }
2446  double t2 = Cpu();
2447  double w2 = TimeOfDay();
2448  Msg::StatusBar(true,
2449  "Done creating geometry of discrete surfaces "
2450  "(Wall %gs, CPU %gs)",
2451  w2 - w1, t2 - t1);
2452  }
2453 
2454  if(r.size()) {
2455  Msg::StatusBar(true, "Creating geometry of discrete volumes...");
2456  double t1 = Cpu(), w1 = TimeOfDay();
2457  for(std::size_t i = 0; i < r.size(); i++) {
2458  if(r[i]->createGeometry())
2459  Msg::Error("Could not create geometry of discrete volume %d",
2460  r[i]->tag());
2461  }
2462  double t2 = Cpu(), w2 = TimeOfDay();
2463  Msg::StatusBar(true,
2464  "Done creating geometry of discrete volumes "
2465  "(Wall %gs, CPU %gs)",
2466  w2 - w1, t2 - t1);
2467  }
2468 }
2469 
2471 {
2472  // loop on regions, then on faces, edges and vertices and store the entity
2473  // pointer in the the elements' vertices (this way we associate the entity of
2474  // lowest geometrical degree with each vertex)
2475  for(auto it = firstRegion(); it != lastRegion(); ++it) {
2476  _associateEntityWithElementVertices(*it, (*it)->tetrahedra);
2477  _associateEntityWithElementVertices(*it, (*it)->hexahedra);
2478  _associateEntityWithElementVertices(*it, (*it)->prisms);
2479  _associateEntityWithElementVertices(*it, (*it)->pyramids);
2480  _associateEntityWithElementVertices(*it, (*it)->trihedra);
2481  _associateEntityWithElementVertices(*it, (*it)->polyhedra);
2482  }
2483  for(auto it = firstFace(); it != lastFace(); ++it) {
2484  _associateEntityWithElementVertices(*it, (*it)->triangles);
2485  _associateEntityWithElementVertices(*it, (*it)->quadrangles);
2486  _associateEntityWithElementVertices(*it, (*it)->polygons);
2487  }
2488  for(auto it = firstEdge(); it != lastEdge(); ++it) {
2489  _associateEntityWithElementVertices(*it, (*it)->lines);
2490  }
2491  for(auto it = firstVertex(); it != lastVertex(); ++it) {
2492  _associateEntityWithElementVertices(*it, (*it)->points);
2493  }
2494 }
2495 
2496 void GModel::_storeVerticesInEntities(std::map<int, MVertex *> &vertices)
2497 {
2498  auto it = vertices.begin();
2499  for(; it != vertices.end(); ++it) {
2500  MVertex *v = it->second;
2501  GEntity *ge = v->onWhat();
2502  if(ge)
2503  ge->mesh_vertices.push_back(v);
2504  else {
2505  delete v; // we delete all unused vertices
2506  it->second = 0;
2507  }
2508  }
2509 }
2510 
2511 void GModel::_storeVerticesInEntities(std::vector<MVertex *> &vertices)
2512 {
2513  for(std::size_t i = 0; i < vertices.size(); i++) {
2514  MVertex *v = vertices[i];
2515  if(v) { // the vector is allowed to have null entries
2516  GEntity *ge = v->onWhat();
2517  if(ge)
2518  ge->mesh_vertices.push_back(v);
2519  else {
2520  delete v; // we delete all unused vertices
2521  vertices[i] = nullptr;
2522  }
2523  }
2524  }
2525 }
2526 
2528 {
2529  std::vector<GEntity *> entities;
2530  std::set<MVertex *, MVertexPtrLessThan> vertSet;
2531  getEntities(entities);
2532  for(std::size_t i = 0; i < entities.size(); i++) {
2533  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
2534  MElement *e = entities[i]->getMeshElement(j);
2535  for(std::size_t k = 0; k < e->getNumVertices(); k++) {
2536  MVertex *v = e->getVertex(k);
2537  v->setEntity(nullptr);
2538  vertSet.insert(v);
2539  }
2540  }
2541  entities[i]->mesh_vertices.clear();
2542  }
2543  std::vector<MVertex *> vertices(vertSet.begin(), vertSet.end());
2545  // associate mesh nodes primarily with chain entities
2546  for(auto it = _chainRegions.begin(); it != _chainRegions.end(); ++it) {
2547  _associateEntityWithElementVertices(*it, (*it)->tetrahedra, true);
2548  _associateEntityWithElementVertices(*it, (*it)->hexahedra, true);
2549  _associateEntityWithElementVertices(*it, (*it)->prisms, true);
2550  _associateEntityWithElementVertices(*it, (*it)->pyramids, true);
2551  _associateEntityWithElementVertices(*it, (*it)->trihedra, true);
2552  _associateEntityWithElementVertices(*it, (*it)->polyhedra, true);
2553  }
2554  for(auto it = _chainFaces.begin(); it != _chainFaces.end(); ++it) {
2555  _associateEntityWithElementVertices(*it, (*it)->triangles, true);
2556  _associateEntityWithElementVertices(*it, (*it)->quadrangles, true);
2557  _associateEntityWithElementVertices(*it, (*it)->polygons, true);
2558  }
2559  for(auto it = _chainEdges.begin(); it != _chainEdges.end(); ++it) {
2560  _associateEntityWithElementVertices(*it, (*it)->lines, true);
2561  }
2562  for(auto it = _chainVertices.begin(); it != _chainVertices.end(); ++it) {
2563  _associateEntityWithElementVertices(*it, (*it)->points, true);
2564  }
2566 }
2567 
2569  int dim, std::map<int, std::map<int, std::string> > &map)
2570 {
2571  std::map<int, std::map<int, std::string> >::const_iterator it = map.begin();
2572  for(; it != map.end(); ++it) {
2573  GEntity *ge = nullptr;
2574  switch(dim) {
2575  case 0: ge = getVertexByTag(it->first); break;
2576  case 1: ge = getEdgeByTag(it->first); break;
2577  case 2: ge = getFaceByTag(it->first); break;
2578  case 3: ge = getRegionByTag(it->first); break;
2579  }
2580 
2581  if(ge) {
2582  for(auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
2583  if(std::find(ge->physicals.begin(), ge->physicals.end(), it2->first) ==
2584  ge->physicals.end()) {
2585  ge->physicals.push_back(it2->first);
2586  }
2587  if(it2->second.size() && it2->second != "unnamed")
2588  _physicalNames.insert(
2589  std::make_pair(std::make_pair(dim, it2->first), it2->second));
2590  }
2591  }
2592  }
2593 }
2594 
2596 {
2597  int numEle = getNumMeshElements();
2598  if(!numEle) return;
2599 
2600  Msg::StatusBar(true, "Checking mesh coherence (%d elements)...", numEle);
2601 
2602  SBoundingBox3d bbox = bounds();
2603  double lc = bbox.empty() ? 1. : norm(SVector3(bbox.max(), bbox.min()));
2604  double eps = lc * tolerance;
2605 
2606  std::vector<GEntity *> entities;
2607  getEntities(entities);
2608 
2609  // check for duplicate mesh nodes
2610  {
2611  Msg::Info("Checking for duplicate nodes...");
2612  std::vector<MVertex *> vertices;
2613  for(std::size_t i = 0; i < entities.size(); i++)
2614  vertices.insert(vertices.end(), entities[i]->mesh_vertices.begin(),
2615  entities[i]->mesh_vertices.end());
2616  MVertexRTree pos(eps);
2617  std::set<MVertex *, MVertexPtrLessThan> duplicates;
2618  int num = pos.insert(vertices, true, &duplicates);
2619  if(num) {
2620  Msg::Error("%d duplicate node%s: see `duplicate_node.pos'", num,
2621  num > 1 ? "s" : "");
2622  FILE *fp = Fopen("duplicate_nodes.pos", "w");
2623  if(fp) {
2624  fprintf(fp, "View \"duplicate vertices\"{\n");
2625  for(auto it = duplicates.begin(); it != duplicates.end(); it++) {
2626  MVertex *v = *it;
2627  fprintf(fp, "SP(%.16g,%.16g,%.16g){%lu};\n", v->x(), v->y(), v->z(),
2628  v->getNum());
2629  }
2630  fprintf(fp, "};\n");
2631  fclose(fp);
2632  }
2633  }
2634  }
2635 
2636  // check for duplicate elements and inverted or zero-volume elements
2637  {
2638  Msg::Info("Checking for duplicate elements...");
2639  std::vector<MVertex *> vertices;
2640  for(std::size_t i = 0; i < entities.size(); i++) {
2641  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
2642  MElement *e = entities[i]->getMeshElement(j);
2643  double vol = e->getVolume();
2644  if(vol < 0)
2645  Msg::Warning("Element %d of dimension %d on entity %d has negative "
2646  "volume", e->getNum(), e->getDim(), entities[i]->tag());
2647  else if(vol < eps * eps * eps)
2648  Msg::Warning("Element %d of dimension %d on entity %d has zero volume",
2649  e->getNum(), e->getDim(), entities[i]->tag());
2650  SPoint3 p = e->barycenter();
2651  vertices.push_back(new MVertex(p.x(), p.y(), p.z()));
2652  }
2653  }
2654  MVertexRTree pos(eps);
2655  int num = pos.insert(vertices, true);
2656  for(std::size_t i = 0; i < vertices.size(); i++) delete vertices[i];
2657  if(num) Msg::Error("%d duplicate element%s", num, num > 1 ? "s" : "");
2658  }
2659 
2660  // check for isolated nodes (not belonging to any elements
2661  {
2662  Msg::Info("Checking for isolated nodes...");
2663  std::vector<GEntity *> entities2;
2664  getEntities(entities2, getMeshDim());
2665  std::set<MVertex *, MVertexPtrLessThan> allv;
2666  for(std::size_t i = 0; i < entities2.size(); i++) {
2667  for(std::size_t j = 0; j < entities2[i]->getNumMeshElements(); j++) {
2668  MElement *e = entities2[i]->getMeshElement(j);
2669  for(std::size_t k = 0; k < e->getNumVertices(); k++) {
2670  allv.insert(e->getVertex(k));
2671  }
2672  }
2673  }
2674  int diff = (int)(getNumMeshVertices() - allv.size());
2675  if(diff) {
2676  Msg::Warning("%d node%s not connected to any %dD elements", diff,
2677  (diff > 1) ? "s" : "", getMeshDim());
2678  }
2679  }
2680 
2681  Msg::StatusBar(true, "Done checking mesh coherence");
2682 }
2683 
2685  const std::vector<GEntity*> &ents)
2686 {
2687  Msg::StatusBar(true, "Removing duplicate mesh nodes...");
2688 
2689  SBoundingBox3d bbox = bounds();
2690  double lc = bbox.empty() ? 1. : norm(SVector3(bbox.max(), bbox.min()));
2691  double eps = lc * tolerance;
2692 
2693  // get entities (in order of increasing dimensions so that topological
2694  // classification of vertices remains correct)
2695  std::vector<GEntity*> entities(ents);
2696  if(entities.empty()) getEntities(entities);
2697 
2698  // re-index all vertices (don't use MVertex::getNum(), as we want to be able
2699  // to remove duplicate vertices from "incorrect" meshes, where vertices with
2700  // the same number are duplicated)
2701  int n = 0;
2702  for(std::size_t i = 0; i < entities.size(); i++) {
2703  GEntity *ge = entities[i];
2704  for(std::size_t j = 0; j < ge->mesh_vertices.size(); j++) {
2705  MVertex *v = ge->mesh_vertices[j];
2706  v->setIndex(++n);
2707  }
2708  }
2709 
2710  MVertexRTree pos(eps);
2711  std::map<int, MVertex *> vertices;
2712  std::map<MVertex *, MVertex *> duplicates;
2713  for(std::size_t i = 0; i < entities.size(); i++) {
2714  GEntity *ge = entities[i];
2715  for(std::size_t j = 0; j < ge->mesh_vertices.size(); j++) {
2716  MVertex *v = ge->mesh_vertices[j];
2717  MVertex *v2 = pos.insert(v);
2718  if(v2)
2719  duplicates[v] = v2; // v should be removed
2720  else
2721  vertices[v->getIndex()] = v;
2722  }
2723  }
2724 
2725  int num = (int)duplicates.size();
2726  Msg::Info("Found %d duplicate nodes ", num);
2727 
2728  if(!num) {
2729  Msg::Info("No duplicate nodes found");
2730  return 0;
2731  }
2732 
2733  for(std::size_t i = 0; i < entities.size(); i++) {
2734  GEntity *ge = entities[i];
2735  // clear list of vertices owned by entity
2736  ge->mesh_vertices.clear();
2737  // replace vertices in element
2738  for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) {
2739  MElement *e = ge->getMeshElement(j);
2740  for(std::size_t k = 0; k < e->getNumVertices(); k++) {
2741  auto it = duplicates.find(e->getVertex(k));
2742  if(it != duplicates.end()) e->setVertex(k, it->second);
2743  }
2744  }
2745  // replace vertices in periodic copies
2746  std::map<MVertex *, MVertex *> &corrVtcs = ge->correspondingVertices;
2747  if(corrVtcs.size()) {
2748  std::map<MVertex *, MVertex *>::iterator cIter;
2749  for(cIter = duplicates.begin(); cIter != duplicates.end(); ++cIter) {
2750  MVertex *oldTgt = cIter->first;
2751  MVertex *newTgt = cIter->second;
2752  auto cvIter = corrVtcs.find(oldTgt);
2753  if(cvIter != corrVtcs.end()) {
2754  MVertex *src = cvIter->second;
2755  corrVtcs.erase(cvIter);
2756  corrVtcs[newTgt] = src;
2757  }
2758  }
2759  for(cIter = corrVtcs.begin(); cIter != corrVtcs.end(); ++cIter) {
2760  MVertex *oldSrc = cIter->second;
2761  auto nIter = duplicates.find(oldSrc);
2762  if(nIter != duplicates.end()) {
2763  MVertex *tgt = cIter->first;
2764  MVertex *newSrc = nIter->second;
2765  corrVtcs[tgt] = newSrc;
2766  }
2767  }
2768  }
2769  }
2770 
2774 
2775  // delete duplicates
2776  std::vector<MVertex *> to_delete;
2777  for(auto it = duplicates.begin(); it != duplicates.end(); it++)
2778  to_delete.push_back(it->first);
2779  for(std::size_t i = 0; i < to_delete.size(); i++) delete to_delete[i];
2780 
2781  if(CTX::instance()->mesh.renumber) {
2783  }
2784 
2785  if(num)
2786  Msg::Info("Removed %d duplicate mesh node%s", num, num > 1 ? "s" : "");
2787 
2788  Msg::StatusBar(true, "Done removing duplicate mesh nodes");
2789  return num;
2790 }
2791 
2792 int GModel::removeDuplicateMeshElements(const std::vector<GEntity*> &ents)
2793 {
2794  Msg::StatusBar(true, "Removing duplicate mesh elements...");
2795 
2796  // this removes elements that have the same nodes (in the same entity)
2797  std::vector<GEntity*> entities(ents);
2798  if(entities.empty()) getEntities(entities);
2799  int num = 0;
2800  for(auto &e : entities) {
2801  std::vector<int> types;
2802  e->getElementTypes(types);
2803  for(auto t : types) {
2804  std::set<MElement*, MElementPtrLessThanVertices> uniq;
2805  for(std::size_t i = 0; i < e->getNumMeshElementsByType(t); i++) {
2806  MElement *ele = e->getMeshElementByType(t, i);
2807  uniq.insert(ele);
2808  }
2809  int diff = e->getNumMeshElementsByType(t) - uniq.size();
2810  if(diff > 0) {
2811  num += diff;
2812  Msg::Info("Removed %d duplicate element%s in entity %d of dimension %d",
2813  diff, diff > 1 ? "s" : "", e->tag(), e->dim());
2814  e->removeElements(t);
2815  for(auto ele : uniq) e->addElement(t, ele);
2816  }
2817  }
2818  }
2819 
2820  if(CTX::instance()->mesh.renumber) {
2822  }
2823 
2824  Msg::StatusBar(true, "Done removing duplicate mesh elements");
2825  return num;
2826 }
2827 
2829 {
2830  // Is this still necessary/useful?
2831  // 1) It's quite horrible
2832  // 2) It's only called when reading MSH2 files
2833 
2834  Msg::Debug("Aligning periodic boundaries");
2835 
2836  // realigning edges
2837 
2838  for(auto it = firstEdge(); it != lastEdge(); ++it) {
2839  GEdge *tgt = *it;
2840  GEdge *src = dynamic_cast<GEdge *>(tgt->getMeshMaster());
2841 
2842  if(src != nullptr && src != tgt) {
2843  // compose a search list on master edge
2844 
2845  std::map<MEdge, MLine *, MEdgeLessThan> srcLines;
2846  for(std::size_t i = 0; i < src->getNumMeshElements(); i++) {
2847  MLine *srcLine = dynamic_cast<MLine *>(src->getMeshElement(i));
2848  if(!srcLine) {
2849  Msg::Debug("Master element %d is not a line",
2850  src->getMeshElement(i)->getNum());
2851  return;
2852  }
2853  srcLines[MEdge(srcLine->getVertex(0), srcLine->getVertex(1))] = srcLine;
2854  }
2855 
2856  // run through slave edge elements
2857  // - check whether we find a counterpart (if not, abort)
2858  // - check orientation and reorient if necessary
2859 
2860  for(std::size_t i = 0; i < tgt->getNumMeshElements(); ++i) {
2861  MLine *tgtLine = dynamic_cast<MLine *>(tgt->getMeshElement(i));
2862 
2863  if(!tgtLine) {
2864  Msg::Debug("Slave element %d is not a line",
2865  tgt->getMeshElement(i)->getNum());
2866  return;
2867  }
2868 
2869  MVertex *tgtVtcs[2];
2870  for(int iVtx = 0; iVtx < 2; iVtx++) {
2871  MVertex *tgtVtx = tgtLine->getVertex(iVtx);
2872  GEntity *ge = tgtVtx->onWhat();
2873  std::map<MVertex *, MVertex *> &geV2v = ge->correspondingVertices;
2874  std::map<MVertex *, MVertex *> &v2v = tgt->correspondingVertices;
2875  auto srcIter = v2v.find(tgtVtx);
2876  if(srcIter == v2v.end() || !srcIter->second) {
2877  srcIter = geV2v.find(tgtVtx);
2878  if(srcIter == geV2v.end() || !srcIter->second) {
2879  Msg::Debug(
2880  "Could not find periodic counterpart of node %d on curve %d "
2881  "or on entity %d of dimension %d",
2882  tgtVtx->getNum(), tgt->tag(), ge->tag(), ge->dim());
2883  return;
2884  }
2885  else
2886  tgtVtcs[iVtx] = srcIter->second;
2887  }
2888  else
2889  tgtVtcs[iVtx] = srcIter->second;
2890  }
2891 
2892  MEdge tgtEdge(tgtVtcs[0], tgtVtcs[1]);
2893 
2894  auto sIter = srcLines.find(tgtEdge);
2895 
2896  if(sIter == srcLines.end() || !sIter->second) {
2897  Msg::Debug(
2898  "Could not find periodic counterpart of mesh edge %d-%d on "
2899  "curve %d for mesh edge %d-%d on curve %d",
2900  tgtLine->getVertex(0)->getNum(), tgtLine->getVertex(1)->getNum(),
2901  tgt->tag(), tgtVtcs[0]->getNum(), tgtVtcs[1]->getNum(), src->tag());
2902  return;
2903  }
2904  else {
2905  MLine *srcLine = sIter->second;
2906  MEdge srcEdge(srcLine->getVertex(0), srcLine->getVertex(1));
2907  if(tgtEdge.computeCorrespondence(srcEdge) == -1) tgtLine->reverse();
2908  }
2909  }
2910  }
2911  }
2912 
2913  // run through all model faces
2914 
2915  for(auto it = firstFace(); it != lastFace(); ++it) {
2916  GFace *tgt = *it;
2917  GFace *src = dynamic_cast<GFace *>(tgt->getMeshMaster());
2918  if(src != nullptr && src != tgt) {
2919  std::map<MFace, MElement *, MFaceLessThan> srcElmts;
2920 
2921  for(std::size_t i = 0; i < src->getNumMeshElements(); ++i) {
2922  MElement *srcElmt = src->getMeshElement(i);
2923  int nbVtcs = 0;
2924  if(dynamic_cast<MTriangle *>(srcElmt)) nbVtcs = 3;
2925  if(dynamic_cast<MQuadrangle *>(srcElmt)) nbVtcs = 4;
2926  std::vector<MVertex *> vtcs;
2927  vtcs.reserve(nbVtcs);
2928  for(int iVtx = 0; iVtx < nbVtcs; iVtx++) {
2929  vtcs.push_back(srcElmt->getVertex(iVtx));
2930  }
2931  srcElmts[MFace(vtcs)] = srcElmt;
2932  }
2933 
2934  for(std::size_t i = 0; i < tgt->getNumMeshElements(); ++i) {
2935  MElement *tgtElmt = tgt->getMeshElement(i);
2936  MTriangle *tgtTri = dynamic_cast<MTriangle *>(tgtElmt);
2937  MQuadrangle *tgtQua = dynamic_cast<MQuadrangle *>(tgtElmt);
2938 
2939  int nbVtcs = 0;
2940  if(tgtTri) nbVtcs = 3;
2941  if(tgtQua) nbVtcs = 4;
2942 
2943  std::vector<MVertex *> vtcs;
2944  for(int iVtx = 0; iVtx < nbVtcs; iVtx++) {
2945  MVertex *vtx = tgtElmt->getVertex(iVtx);
2946  GEntity *ge = vtx->onWhat();
2947 
2948  std::map<MVertex *, MVertex *> &geV2v = ge->correspondingVertices;
2949  std::map<MVertex *, MVertex *> &v2v = tgt->correspondingVertices;
2950 
2951  auto vIter = v2v.find(vtx);
2952  if(vIter == v2v.end() || !vIter->second) {
2953  vIter = geV2v.find(vtx);
2954  if(vIter == geV2v.end() || !vIter->second) {
2955  Msg::Debug("Could not find periodic counterpart of node %d in "
2956  "surface %d or in entity %d of dimension %d",
2957  vtx->getNum(), tgt->tag(), ge->tag(), ge->dim());
2958  return;
2959  }
2960  else
2961  vtcs.push_back(vIter->second);
2962  }
2963  else
2964  vtcs.push_back(vIter->second);
2965  }
2966  MFace tgtFace(vtcs);
2967 
2968  auto mIter = srcElmts.find(tgtFace);
2969  if(mIter == srcElmts.end()) {
2970  std::ostringstream faceDef;
2971  for(int iVtx = 0; iVtx < nbVtcs; iVtx++) {
2972  faceDef << vtcs[iVtx]->getNum() << " ";
2973  }
2974  Msg::Debug("Could not find periodic counterpart of mesh face %s in "
2975  "surface %d connected to surface %d",
2976  faceDef.str().c_str(), tgt->tag(), src->tag());
2977  return;
2978  }
2979  else {
2980  const MFace &srcFace = mIter->first;
2981  MElement *srcElmt = mIter->second;
2982  std::vector<MVertex *> srcVtcs;
2983 
2984  if((tgtTri && !dynamic_cast<MTriangle *>(srcElmt)) ||
2985  (tgtQua && !dynamic_cast<MQuadrangle *>(srcElmt))) {
2986  Msg::Error("Invalid source/target elements");
2987  return;
2988  }
2989 
2990  int rotation = 0;
2991  bool swap = false;
2992 
2993  if(!tgtFace.computeCorrespondence(srcFace, rotation, swap)) {
2994  Msg::Debug(
2995  "Could not find correspondence between mesh face %d-%d-%d "
2996  "(slave) and %d-%d-%d (master)",
2997  tgtElmt->getVertex(0)->getNum(), tgtElmt->getVertex(1)->getNum(),
2998  tgtElmt->getVertex(2)->getNum(), srcElmt->getVertex(0)->getNum(),
2999  srcElmt->getVertex(1)->getNum(), srcElmt->getVertex(2)->getNum());
3000  return;
3001  }
3002 
3003  if(tgtTri) tgtTri->reorient(rotation, swap);
3004  if(tgtQua) tgtQua->reorient(rotation, swap);
3005  }
3006  }
3007  }
3008  }
3009  Msg::Debug("Done aligning periodic boundaries");
3010 }
3011 
3013  const MFace &f, std::multimap<MFace, MElement *, MFaceLessThan> &e2f,
3014  std::set<MElement *> &group, std::set<MFace, MFaceLessThan> &touched,
3015  int recur_level)
3016 {
3017  // this is very slow...
3018  std::stack<MFace> _stack;
3019  _stack.push(f);
3020 
3021  while(!_stack.empty()) {
3022  MFace ff = _stack.top();
3023  _stack.pop();
3024  if(touched.find(ff) == touched.end()) {
3025  touched.insert(ff);
3026  for(auto it = e2f.lower_bound(ff); it != e2f.upper_bound(ff); ++it) {
3027  group.insert(it->second);
3028  for(int i = 0; i < it->second->getNumFaces(); ++i) {
3029  _stack.push(it->second->getFace(i));
3030  }
3031  }
3032  }
3033  }
3034 }
3035 
3036 static int connectedVolumes(std::vector<MElement *> &elements,
3037  std::vector<std::vector<MElement *> > &regs)
3038 {
3039  std::multimap<MFace, MElement *, MFaceLessThan> e2f;
3040  for(std::size_t i = 0; i < elements.size(); ++i) {
3041  for(int j = 0; j < elements[i]->getNumFaces(); j++) {
3042  e2f.insert(std::make_pair(elements[i]->getFace(j), elements[i]));
3043  }
3044  }
3045  while(!e2f.empty()) {
3046  std::set<MElement *> group;
3047  std::set<MFace, MFaceLessThan> touched;
3048  connectMElementsByMFace(e2f.begin()->first, e2f, group, touched, 0);
3049  std::vector<MElement *> temp;
3050  temp.insert(temp.begin(), group.begin(), group.end());
3051  regs.push_back(temp);
3052  for(auto it = touched.begin(); it != touched.end(); ++it) e2f.erase(*it);
3053  }
3054  return regs.size();
3055 }
3056 
3058  const MEdge &e, std::multimap<MEdge, MElement *, MEdgeLessThan> &e2e,
3059  std::set<MElement *> &group, std::set<MEdge, MEdgeLessThan> &touched)
3060 {
3061  // this is very slow...
3062  std::stack<MEdge> _stack;
3063  _stack.push(e);
3064 
3065  while(!_stack.empty()) {
3066  MEdge ee = _stack.top();
3067  _stack.pop();
3068  if(touched.find(ee) == touched.end()) {
3069  touched.insert(ee);
3070  for(auto it = e2e.lower_bound(ee); it != e2e.upper_bound(ee); ++it) {
3071  group.insert(it->second);
3072  for(int i = 0; i < it->second->getNumEdges(); ++i) {
3073  _stack.push(it->second->getEdge(i));
3074  }
3075  }
3076  }
3077  }
3078 }
3079 
3080 static int connectedSurfaces(std::vector<MElement *> &elements,
3081  std::vector<std::vector<MElement *> > &faces)
3082 {
3083  std::multimap<MEdge, MElement *, MEdgeLessThan> e2e;
3084  for(std::size_t i = 0; i < elements.size(); ++i) {
3085  for(int j = 0; j < elements[i]->getNumEdges(); j++) {
3086  e2e.insert(std::make_pair(elements[i]->getEdge(j), elements[i]));
3087  }
3088  }
3089  while(!e2e.empty()) {
3090  std::set<MElement *> group;
3091  std::set<MEdge, MEdgeLessThan> touched;
3092  connectMElementsByMEdge(e2e.begin()->first, e2e, group, touched);
3093  std::vector<MElement *> temp;
3094  temp.insert(temp.begin(), group.begin(), group.end());
3095  faces.push_back(temp);
3096  for(auto it = touched.begin(); it != touched.end(); ++it) e2e.erase(*it);
3097  }
3098  return faces.size();
3099 }
3100 
3102 {
3103  Msg::Info("Making discrete regions simply connected...");
3104 
3105  std::vector<discreteRegion *> discRegions;
3106  for(auto it = firstRegion(); it != lastRegion(); it++)
3107  if((*it)->geomType() == GEntity::DiscreteVolume)
3108  discRegions.push_back((discreteRegion *)*it);
3109 
3110  std::set<MVertex *> touched;
3111 
3112  for(auto itR = discRegions.begin(); itR != discRegions.end(); itR++) {
3113  std::vector<MElement *> allElements((*itR)->getNumMeshElements());
3114  for(std::size_t i = 0; i < (*itR)->getNumMeshElements(); i++)
3115  allElements[i] = (*itR)->getMeshElement(i);
3116 
3117  std::vector<std::vector<MElement *> > conRegions;
3118  int nbRegions = connectedVolumes(allElements, conRegions);
3119  if(nbRegions > 1) remove(*itR);
3120 
3121  for(int ire = 0; ire < nbRegions; ire++) {
3122  int numR =
3123  (nbRegions == 1) ? (*itR)->tag() : getMaxElementaryNumber(3) + 1;
3124  discreteRegion *r = new discreteRegion(this, numR);
3125  add(r);
3126  std::vector<MElement *> myElements = conRegions[ire];
3127  std::set<MVertex *> myVertices;
3128  for(std::size_t i = 0; i < myElements.size(); i++) {
3129  MElement *e = myElements[i];
3130  std::vector<MVertex *> verts;
3131  e->getVertices(verts);
3132  for(std::size_t k = 0; k < verts.size(); k++) {
3133  if(verts[k]->onWhat() && verts[k]->onWhat()->dim() == 3) {
3134  if(touched.find(verts[k]) == touched.end()) {
3135  verts[k]->setEntity(r);
3136  myVertices.insert(verts[k]);
3137  touched.insert(verts[k]);
3138  }
3139  }
3140  }
3141  MElementFactory factory;
3142  MElement *e2 = factory.create(e->getTypeForMSH(), verts, e->getNum(),
3143  e->getPartition());
3144  switch(e2->getType()) {
3145  case TYPE_TET: r->tetrahedra.push_back((MTetrahedron *)e2); break;
3146  case TYPE_HEX: r->hexahedra.push_back((MHexahedron *)e2); break;
3147  case TYPE_PRI: r->prisms.push_back((MPrism *)e2); break;
3148  case TYPE_PYR: r->pyramids.push_back((MPyramid *)e2); break;
3149  case TYPE_TRIH: r->trihedra.push_back((MTrihedron *)e2); break;
3150  }
3151  }
3152  r->mesh_vertices.insert(r->mesh_vertices.begin(), myVertices.begin(),
3153  myVertices.end());
3154  }
3155  }
3156 
3157  Msg::Info("Done making discrete regions simply connected");
3158 }
3159 
3161 {
3162  Msg::Info("Making discrete faces simply connected...");
3163 
3164  std::vector<discreteFace *> discFaces;
3165  for(auto it = firstFace(); it != lastFace(); it++)
3166  if((*it)->geomType() == GEntity::DiscreteSurface)
3167  discFaces.push_back((discreteFace *)*it);
3168 
3169  std::set<MVertex *> touched;
3170 
3171  for(auto itF = discFaces.begin(); itF != discFaces.end(); itF++) {
3172  std::vector<MElement *> allElements((*itF)->getNumMeshElements());
3173  for(std::size_t i = 0; i < (*itF)->getNumMeshElements(); i++)
3174  allElements[i] = (*itF)->getMeshElement(i);
3175 
3176  std::vector<std::vector<MElement *> > conFaces;
3177  int nbFaces = connectedSurfaces(allElements, conFaces);
3178  if(nbFaces > 1) remove(*itF);
3179 
3180  for(int ifa = 0; ifa < nbFaces; ifa++) {
3181  int numF = (nbFaces == 1) ? (*itF)->tag() : getMaxElementaryNumber(2) + 1;
3182  discreteFace *f = new discreteFace(this, numF);
3183  add(f);
3184  std::vector<MElement *> myElements = conFaces[ifa];
3185  std::set<MVertex *> myVertices;
3186  for(std::size_t i = 0; i < myElements.size(); i++) {
3187  MElement *e = myElements[i];
3188  std::vector<MVertex *> verts;
3189  e->getVertices(verts);
3190  for(std::size_t k = 0; k < verts.size(); k++) {
3191  if(verts[k]->onWhat() && verts[k]->onWhat()->dim() == 2) {
3192  if(touched.find(verts[k]) == touched.end()) {
3193  verts[k]->setEntity(f);
3194  myVertices.insert(verts[k]);
3195  touched.insert(verts[k]);
3196  }
3197  }
3198  }
3199  MElementFactory factory;
3200  MElement *e2 = factory.create(e->getTypeForMSH(), verts, e->getNum(),
3201  e->getPartition());
3202  if(e2->getType() == TYPE_TRI)
3203  f->triangles.push_back((MTriangle *)e2);
3204  else
3205  f->quadrangles.push_back((MQuadrangle *)e2);
3206  }
3207  f->mesh_vertices.insert(f->mesh_vertices.begin(), myVertices.begin(),
3208  myVertices.end());
3209  }
3210  }
3211 
3212  Msg::Info("Done making discrete faces simply connected");
3213 }
3214 
3215 static void
3216 makeSimplyConnected(std::map<int, std::vector<MElement *> > elements[11])
3217 {
3218  // only for tetras and triangles
3219  Msg::Info("Make simply connected regions and surfaces");
3220  std::vector<int> regs;
3221  for(auto it = elements[4].begin(); it != elements[4].end(); it++)
3222  regs.push_back(it->first);
3223  std::multimap<MFace, MElement *, MFaceLessThan> f2e;
3224  if(regs.size() > 2) {
3225  for(std::size_t i = 0; i < regs.size(); i++) {
3226  for(std::size_t j = 0; j < elements[4][regs[i]].size(); j++) {
3227  MElement *el = elements[4][regs[i]][j];
3228  for(int k = 0; k < el->getNumFaces(); k++)
3229  f2e.insert(std::make_pair(el->getFace(k), el));
3230  }
3231  }
3232  }
3233  for(std::size_t i = 0; i < regs.size(); i++) {
3234  int ri = regs[i];
3235  std::vector<MElement *> allElements;
3236  for(std::size_t j = 0; j < elements[4][ri].size(); j++)
3237  allElements.push_back(elements[4][ri][j]);
3238  std::vector<std::vector<MElement *> > conRegions;
3239  int nbConRegions = connectedVolumes(allElements, conRegions);
3240  Msg::Info("%d connected regions (reg=%d)", nbConRegions, ri);
3241  std::size_t maxNumEl = 1;
3242  for(int j = 0; j < nbConRegions; j++)
3243  if(conRegions[j].size() > maxNumEl) maxNumEl = conRegions[j].size();
3244  for(int j = 0; j < nbConRegions; j++) {
3245  // remove conRegions containing few elements
3246  if(conRegions[j].size() < maxNumEl * 1.e-4) {
3247  // find adjacent region
3248  int r2 = ri;
3249  if(regs.size() == 2)
3250  r2 = (ri + 1) % 2;
3251  else {
3252  for(std::size_t k = 0; k < conRegions[j].size(); k++) {
3253  MElement *el = conRegions[j][k];
3254  for(int l = 0; l < el->getNumFaces(); l++) {
3255  MFace mf = el->getFace(l);
3256  auto itl = f2e.lower_bound(mf);
3257  for(; itl != f2e.upper_bound(mf); itl++) {
3258  if(itl->second != el) break;
3259  }
3260  MElement *el2 = itl->second;
3261  bool sameRegion = false;
3262  for(std::size_t m = 0; m < conRegions[j].size(); m++)
3263  if(conRegions[j][m] == el2) {
3264  sameRegion = true;
3265  break;
3266  }
3267  if(sameRegion) continue;
3268  for(std::size_t m = 0; m < regs.size(); m++) {
3269  int rm = regs[m];
3270  if(rm == ri) continue;
3271  for(std::size_t n = 0; n < elements[4][rm].size(); n++)
3272  if(elements[4][rm][n] == el2) {
3273  r2 = rm;
3274  break;
3275  }
3276  if(r2 != ri) break;
3277  }
3278  if(r2 != ri) break;
3279  }
3280  if(r2 != ri) break;
3281  }
3282  if(r2 == ri)
3283  Msg::Warning("Element not found for simply connected regions");
3284  }
3285 
3286  for(std::size_t k = 0; k < conRegions[j].size(); k++) {
3287  MElement *el = conRegions[j][k];
3288  std::size_t l = 0;
3289  for(; l < elements[4][ri].size(); l++)
3290  if(elements[4][ri][l] == el) break;
3291  elements[4][ri].erase(elements[4][ri].begin() + l);
3292  elements[4][r2].push_back(el);
3293  }
3294  }
3295  }
3296  }
3297 
3298  std::vector<int> faces;
3299  for(auto it = elements[2].begin(); it != elements[2].end(); it++)
3300  faces.push_back(it->first);
3301  std::multimap<MEdge, MElement *, MEdgeLessThan> e2e;
3302  if(faces.size() > 2) {
3303  for(std::size_t i = 0; i < faces.size(); i++) {
3304  for(std::size_t j = 0; j < elements[2][faces[i]].size(); j++) {
3305  MElement *el = elements[2][faces[i]][j];
3306  for(int k = 0; k < el->getNumEdges(); k++)
3307  e2e.insert(std::make_pair(el->getEdge(k), el));
3308  }
3309  }
3310  }
3311  for(std::size_t i = 0; i < faces.size(); i++) {
3312  int fi = faces[i];
3313  std::vector<MElement *> allElements;
3314  for(std::size_t j = 0; j < elements[2][fi].size(); j++)
3315  allElements.push_back(elements[2][fi][j]);
3316  std::vector<std::vector<MElement *> > conSurfaces;
3317  int nbConSurfaces = connectedSurfaces(allElements, conSurfaces);
3318  Msg::Info("%d connected surfaces (reg=%d)", nbConSurfaces, fi);
3319  std::size_t maxNumEl = 1;
3320  for(int j = 0; j < nbConSurfaces; j++)
3321  if(conSurfaces[j].size() > maxNumEl) maxNumEl = conSurfaces[j].size();
3322  for(int j = 0; j < nbConSurfaces; j++) {
3323  // remove conSurfaces containing few elements
3324  if(conSurfaces[j].size() < maxNumEl * 1.e-4) {
3325  // find adjacent surface
3326  int f2 = fi;
3327  if(faces.size() == 2)
3328  f2 = (fi + 1) % 2;
3329  else {
3330  for(std::size_t k = 0; k < conSurfaces[j].size(); k++) {
3331  MElement *el = conSurfaces[j][k];
3332  for(int l = 0; l < el->getNumEdges(); l++) {
3333  MEdge me = el->getEdge(l);
3334  auto itl = e2e.lower_bound(me);
3335  for(; itl != e2e.upper_bound(me); itl++) {
3336  if(itl->second != el) break;
3337  }
3338  MElement *el2 = itl->second;
3339  bool sameSurface = false;
3340  for(std::size_t m = 0; m < conSurfaces[j].size(); m++)
3341  if(conSurfaces[j][m] == el2) {
3342  sameSurface = true;
3343  break;
3344  }
3345  if(sameSurface) continue;
3346  for(std::size_t m = 0; m < faces.size(); m++) {
3347  int fm = faces[m];
3348  if(fm == fi) continue;
3349  for(std::size_t n = 0; n < elements[2][fm].size(); n++)
3350  if(elements[2][fm][n] == el2) {
3351  f2 = fm;
3352  break;
3353  }
3354  if(f2 != fi) break;
3355  }
3356  if(f2 != fi) break;
3357  }
3358  if(f2 != fi) break;
3359  }
3360  if(f2 == fi)
3361  Msg::Warning("Element not found for simply connected surfaces");
3362  }
3363  for(std::size_t k = 0; k < conSurfaces[j].size(); k++) {
3364  MElement *el = conSurfaces[j][k];
3365  std::size_t l = 0;
3366  for(; l < elements[2][fi].size(); l++)
3367  if(elements[2][fi][l] == el) break;
3368  elements[2][fi].erase(elements[2][fi].begin() + l);
3369  elements[2][f2].push_back(el);
3370  }
3371  }
3372  }
3373  }
3374 }
3375 
3376 GModel *GModel::buildCutGModel(gLevelset *ls, bool cutElem, bool saveTri)
3377 {
3378  if(saveTri)
3379  CTX::instance()->mesh.saveTri = 1;
3380  else
3381  CTX::instance()->mesh.saveTri = 0;
3382 
3383  std::map<int, std::vector<MElement *> > elements[11];
3384  std::map<int, std::map<int, std::string> > physicals[4];
3385  std::map<int, MVertex *> vertexMap;
3386 
3387  if(cutElem)
3388  Msg::Info("Cutting mesh...");
3389  else
3390  Msg::Info("Splitting mesh...");
3391  double t1 = Cpu(), w1 = TimeOfDay();
3392 
3393  GModel *cutGM =
3394  buildCutMesh(this, ls, elements, vertexMap, physicals, cutElem);
3395 
3396  if(!cutElem) makeSimplyConnected(elements);
3397 
3398  for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
3399  cutGM->_storeElementsInEntities(elements[i]);
3401  cutGM->_storeVerticesInEntities(vertexMap);
3402 
3403  for(int i = 0; i < 4; i++) {
3404  cutGM->_storePhysicalTagsInEntities(i, physicals[i]);
3405  auto it = physicals[i].begin();
3406  for(; it != physicals[i].end(); it++) {
3407  auto it2 = it->second.begin();
3408  for(; it2 != it->second.end(); it2++)
3409  if(it2->second != "")
3410  cutGM->setPhysicalName(it2->second, i, it2->first);
3411  }
3412  }
3413 
3414  if(cutElem)
3415  Msg::Info("Mesh cutting completed (Wall %gs, CPU %gs)", TimeOfDay() - w1,
3416  Cpu() - t1);
3417  else
3418  Msg::Info("Mesh splitting completed (Wall %gs, CPU %gs)", TimeOfDay() - w1,
3419  Cpu() - t1);
3420 
3421  return cutGM;
3422 }
3423 
3424 void GModel::load(const std::string &fileName)
3425 {
3426  GModel *temp = GModel::current();
3427  GModel::setCurrent(this);
3428  MergeFile(fileName, true);
3429  GModel::setCurrent(temp);
3430 }
3431 
3432 void GModel::save(const std::string &fileName)
3433 {
3434  GModel *temp = GModel::current();
3435  GModel::setCurrent(this);
3436  CreateOutputFile(fileName, FORMAT_AUTO);
3437  GModel::setCurrent(temp);
3438 }
3439 
3440 int GModel::readGEO(const std::string &name)
3441 {
3442  // readGEO is static, because it can create several models
3443  ParseFile(name, true);
3444  // sync OCC first, as GEO_Internals currently contains attributes (physicals)
3445  // that should also be applied to entities from OCC_Internals
3449  return 1;
3450 }
3451 
3452 void GModel::setPhysicalNumToEntitiesInBox(int EntityDimension,
3453  int PhysicalNumber,
3454  const SBoundingBox3d &box)
3455 {
3456  std::vector<GEntity *> entities;
3457  getEntitiesInBox(entities, box, EntityDimension);
3458  for(std::size_t i = 0; i < entities.size(); i++)
3459  entities[i]->addPhysicalEntity(PhysicalNumber);
3460 }
3461 
3462 void GModel::setPhysicalNumToEntitiesInBox(int EntityDimension,
3463  int PhysicalNumber,
3464  std::vector<double> p1,
3465  std::vector<double> p2)
3466 {
3467  if(p1.size() != 3 || p2.size() != 3) return;
3468  SBoundingBox3d box(p1[0], p1[2], p1[2], p2[0], p2[1], p2[3]);
3469  setPhysicalNumToEntitiesInBox(EntityDimension, PhysicalNumber, box);
3470 }
3471 
3472 void GModel::classifySurfaces(double angleThreshold, bool includeBoundary,
3473  bool forReparametrization,
3474  double curveAngleThreshold)
3475 {
3476  classifyFaces(this, angleThreshold, includeBoundary, forReparametrization,
3477  curveAngleThreshold);
3478 }
3479 
3480 void GModel::addHomologyRequest(const std::string &type,
3481  const std::vector<int> &domain,
3482  const std::vector<int> &subdomain,
3483  const std::vector<int> &dim)
3484 {
3485  std::pair<const std::vector<int>, const std::vector<int> > p(domain,
3486  subdomain);
3487  std::pair<const std::string, const std::vector<int> > p2(type, dim);
3488  _homologyRequests.insert(std::make_pair(p, p2));
3489 }
3490 
3492 {
3493  _homologyRequests.clear();
3494 }
3495 
3496 void GModel::computeHomology(std::vector<std::pair<int, int> > &newPhysicals)
3497 {
3498  newPhysicals.clear();
3499 
3500  if(_homologyRequests.empty()) return;
3501 
3502 #if defined(HAVE_KBIPACK)
3503  Msg::StatusBar(true, "Homology and cohomology computation...");
3504  double t1 = Cpu(), w1 = TimeOfDay();
3505 
3506  // find unique domain/subdomain requests
3507  typedef std::pair<const std::vector<int>, const std::vector<int> > dpair;
3508  typedef std::pair<const std::string, const std::vector<int> > tpair;
3509  std::set<dpair> domains;
3510  for(auto it = _homologyRequests.begin(); it != _homologyRequests.end(); it++)
3511  domains.insert(it->first);
3512  Msg::Info("Number of cell complexes to construct: %d", domains.size());
3513 
3514  for(auto it = domains.begin(); it != domains.end(); it++) {
3515  std::pair<std::multimap<dpair, tpair>::iterator,
3516  std::multimap<dpair, tpair>::iterator>
3517  itp = _homologyRequests.equal_range(*it);
3518  bool prepareToRestore = (itp.first != --itp.second);
3519  itp.second++;
3520  std::vector<int> imdomain;
3521  Homology *homology =
3522  new Homology(this, itp.first->first.first, itp.first->first.second,
3523  imdomain, prepareToRestore);
3524 
3525  for(auto itt = itp.first; itt != itp.second; itt++) {
3526  std::string type = itt->second.first;
3527  std::vector<int> dim0 = itt->second.second;
3528  if(dim0.empty())
3529  for(int i = 0; i < getDim(); i++) dim0.push_back(i);
3530  std::vector<int> dim;
3531 
3532  std::stringstream ss;
3533  for(std::size_t i = 0; i < dim0.size(); i++) {
3534  int d = dim0.at(i);
3535  if(d >= 0 && d <= getDim()) {
3536  dim.push_back(d);
3537  ss << "H";
3538  if(type == "Homology") ss << "_";
3539  if(type == "Cohomology") ss << "^";
3540  ss << d;
3541  if(i < dim0.size() - 1 && dim0.at(i + 1) >= 0 &&
3542  dim0.at(i + 1) <= getDim())
3543  ss << ", ";
3544  }
3545  }
3546  std::string dims = ss.str();
3547 
3548  if(type != "Homology" && type != "Cohomology" && type != "Betti") {
3549  Msg::Error("Unknown type of homology computation: %s", type.c_str());
3550  }
3551  else if(dim.empty()) {
3552  Msg::Error("Invalid homology computation dimensions given");
3553  }
3554  else if(type == "Betti") {
3555  homology->findBettiNumbers();
3556  }
3557  else if(type == "Homology" && !homology->isHomologyComputed(dim)) {
3558  homology->findHomologyBasis(dim);
3559  Msg::Info("Homology space basis chains to save: %s", dims.c_str());
3560  for(std::size_t i = 0; i < dim.size(); i++) {
3561  std::vector<int> p = homology->addChainsToModel(dim.at(i));
3562  for(auto t : p) newPhysicals.push_back({dim.at(i), t});
3563  }
3564  }
3565  else if(type == "Cohomology" && !homology->isCohomologyComputed(dim)) {
3566  homology->findCohomologyBasis(dim);
3567  Msg::Info("Cohomology space basis cochains to save: %s", dims.c_str());
3568  for(std::size_t i = 0; i < dim.size(); i++) {
3569  std::vector<int> p = homology->addCochainsToModel(dim.at(i));
3570  for(auto t : p) newPhysicals.push_back({dim.at(i), t});
3571  }
3572  }
3573  }
3575  delete homology;
3576  }
3577  Msg::Info("");
3578 
3579  double t2 = Cpu(), w2 = TimeOfDay();
3580  Msg::StatusBar(true,
3581  "Done homology and cohomology computation "
3582  "(Wall %gs, CPU %gs)",
3583  w2 - w1, t2 - t1);
3584 
3585 #else
3586  Msg::Error("Homology computation requires KBIPACK");
3587 #endif
3588 }
3589 
3591 {
3592 #if defined(HAVE_HXT) && defined(HAVE_P4EST)
3593  FieldManager *fields = getFields();
3594  int myId = fields->newId();
3595  fields->newField(myId, std::string("AutomaticMeshSizeField"));
3596  fields->get(myId)->update();
3597 #else
3598  Msg::Error("Size field computation requires both HXT and P4EST");
3599 #endif
3600 }
3601 
3602 #if !defined(HAVE_ACIS)
3603 
3605 
3607 
3608 int GModel::readACISSAT(const std::string &fn)
3609 {
3610  Msg::Error("Gmsh must be compiled with ACIS support to load '%s'",
3611  fn.c_str());
3612  return 0;
3613 }
3614 
3615 #endif
3616 
3617 #if !defined(HAVE_PARASOLID)
3618 
3620 
3622 
3623 int GModel::readParasolidXMT(const std::string &fn)
3624 {
3625  Msg::Error("Gmsh must be compiled with Parasolid support to read '%s'",
3626  fn.c_str());
3627  return 0;
3628 }
3629 
3630 int GModel::writeParasolidXMT(const std::string &fn)
3631 {
3632  Msg::Error("Gmsh must be compiled with Parasolid support to write '%s'",
3633  fn.c_str());
3634  return 0;
3635 }
3636 
3637 int GModel::readParasolidSTEP(const std::string &fn)
3638 {
3639  Msg::Error("Gmsh must be compiled with Parasolid support to read '%s'",
3640  fn.c_str());
3641  return 0;
3642 }
3643 
3644 int GModel::writeParasolidSTEP(const std::string &fn)
3645 {
3646  Msg::Error("Gmsh must be compiled with Parasolid support to write '%s'",
3647  fn.c_str());
3648  return 0;
3649 }
3650 
3651 #endif
MElement::getNum
virtual std::size_t getNum() const
Definition: MElement.h:68
GModel::normals
smooth_normals * normals
Definition: GModel.h:653
GModel::removeDuplicateMeshElements
int removeDuplicateMeshElements(const std::vector< GEntity * > &entities=std::vector< GEntity * >())
Definition: GModel.cpp:2792
GModel::GModel
GModel(const std::string &name="")
Definition: GModel.cpp:72
GModel::setOrderN
int setOrderN(int order, int linear, int incomplete, int onlyVisible)
Definition: GModel.cpp:1454
GModel::_name
std::string _name
Definition: GModel.h:90
SetOrderN
void SetOrderN(GModel *m, int order, bool linear, bool incomplete, bool onlyVisible)
Definition: HighOrder.cpp:1396
MElement::xyz2uvw
virtual void xyz2uvw(double xyz[3], double uvw[3]) const
Definition: MElement.cpp:1128
MTriangle.h
GModel::setVisibility
void setVisibility(char val)
Definition: GModel.h:341
CreateFile.h
TimeOfDay
double TimeOfDay()
Definition: OS.cpp:399
tags
static std::map< SPoint2, unsigned int > tags
Definition: drawGraph2d.cpp:400
GModel::_lastMeshEntityError
std::vector< GEntity * > _lastMeshEntityError
Definition: GModel.h:134
MTrihedron.h
contextGeometryOptions::tolerance
double tolerance
Definition: Context.h:99
GModel::_fields
FieldManager * _fields
Definition: GModel.h:128
SplitFileName
std::vector< std::string > SplitFileName(const std::string &fileName)
Definition: StringUtils.cpp:93
GModel::readParasolidXMT
int readParasolidXMT(const std::string &name)
Definition: GModel.cpp:3623
GModel::firstEdge
eiter firstEdge()
Definition: GModel.h:356
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
GFace::status
GEntity::MeshGenerationStatus status
Definition: GFace.h:395
Field.h
PViewDataGModel::ElementData
@ ElementData
Definition: PViewDataGModel.h:195
MEdge
Definition: MEdge.h:14
GEdge::getMeshElement
MElement * getMeshElement(std::size_t index) const
Definition: GEdge.cpp:173
GModel::getNumMeshParentElements
std::size_t getNumMeshParentElements() const
Definition: GModel.cpp:1551
FieldManager::reset
void reset()
Definition: Field.cpp:68
CTX
Definition: Context.h:127
contextMeshOptions::renumber
int renumber
Definition: Context.h:48
AdaptMesh
void AdaptMesh(GModel *m)
Definition: Generator.cpp:1303
GMSH_SET
#define GMSH_SET
Definition: Options.h:12
PViewDataGModel
Definition: PViewDataGModel.h:191
GModel::_chainEdges
std::set< GEdge *, GEntityPtrLessThan > _chainEdges
Definition: GModel.h:51
GRegion::method
char method
Definition: GRegion.h:146
GPoint::y
double y() const
Definition: GPoint.h:22
GModel::convertOldPartitioningToNewOne
int convertOldPartitioningToNewOne()
Definition: GModel.cpp:2236
MergeFile
int MergeFile(const std::string &fileName, bool errorIfMissing, bool setBoundingBox, bool importPhysicalsInOnelab, int partitionToRead)
Definition: OpenFile.cpp:298
GFace::edgeOrientations
virtual std::vector< int > const & edgeOrientations() const
Definition: GFace.h:139
GModel::getMaxElementaryNumber
int getMaxElementaryNumber(int dim)
Definition: GModel.cpp:817
MLine::reverse
virtual void reverse()
Definition: MLine.h:85
MElement::forceNum
void forceNum(std::size_t num)
Definition: MElement.cpp:54
GModel::setAllVolumesPositiveTopology
void setAllVolumesPositiveTopology()
Definition: GModel.cpp:1161
contextMeshOptions::firstElementTag
int firstElementTag
Definition: Context.h:57
PViewDataGModel::NodeData
@ NodeData
Definition: PViewDataGModel.h:194
GModel::getNumMeshVertices
std::size_t getNumMeshVertices(int dim=-1) const
Definition: GModel.cpp:1529
GenerateMesh
void GenerateMesh(GModel *m, int ask)
Definition: Generator.cpp:1649
TYPE_LIN
#define TYPE_LIN
Definition: GmshDefines.h:65
MTetrahedron
Definition: MTetrahedron.h:34
MLine::getVertex
virtual MVertex * getVertex(int num)
Definition: MLine.h:45
GEntity::getMeshVertex
MVertex * getMeshVertex(std::size_t index)
Definition: GEntity.h:379
GFace
Definition: GFace.h:33
MElement::getTypeForMSH
virtual int getTypeForMSH() const
Definition: MElement.h:488
GModel::recombineMesh
int recombineMesh()
Definition: GModel.cpp:1421
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GModel::removeDuplicateMeshVertices
int removeDuplicateMeshVertices(double tolerance, const std::vector< GEntity * > &entities=std::vector< GEntity * >())
Definition: GModel.cpp:2684
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
discreteRegion.h
MElementFactory
Definition: MElement.h:517
OS.h
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
checkConformity
static void checkConformity(std::multimap< MFace, MElement *, MFaceLessThan > &faceToElement, std::map< MElement *, std::vector< std::pair< MElement *, bool > > > &elToNeighbors, const MFace &face, MElement *el)
Definition: GModel.cpp:1131
GModel::load
void load(const std::string &fileName)
Definition: GModel.cpp:3424
discreteEdge
Definition: discreteEdge.h:12
GModel::deleteOCCInternals
void deleteOCCInternals()
Definition: GModelIO_OCC.cpp:5880
MVertex
Definition: MVertex.h:24
MElement::getDim
virtual int getDim() const =0
MElementOctree.h
GModel::getName
std::string getName() const
Definition: GModel.h:329
CreateOutputFile
void CreateOutputFile(const std::string &fileName, int format, bool status)
Definition: CreateFile.cpp:290
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
GModel::_fileNames
std::set< std::string > _fileNames
Definition: GModel.h:94
GEntity::OpenCascadeModel
@ OpenCascadeModel
Definition: GEntity.h:82
_associateEntityWithElementVertices
static void _associateEntityWithElementVertices(GEntity *ge, std::vector< T * > &elements, bool force=false)
Definition: GModel.cpp:2357
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
Msg::StatusBar
static void StatusBar(bool log, const char *fmt,...)
Definition: GmshMessage.cpp:686
MVertex::z
double z() const
Definition: MVertex.h:62
GModel::deleteACISInternals
void deleteACISInternals()
Definition: GModel.cpp:3606
buildCutMesh
GModel * buildCutMesh(GModel *gm, gLevelset *ls, std::map< int, std::vector< MElement * > > elements[10], std::map< int, MVertex * > &vertexMap, std::map< int, std::map< int, std::string > > physicals[4], bool cutElem)
Definition: MElementCut.cpp:1462
GModel::_currentMeshEntity
GEntity * _currentMeshEntity
Definition: GModel.h:131
opt_mesh_lc_integration_precision
double opt_mesh_lc_integration_precision(OPT_ARGS_NUM)
Definition: Options.cpp:5126
GFace::method
char method
Definition: GFace.h:348
GEntity::physicals
std::vector< int > physicals
Definition: GEntity.h:65
box
Definition: gl2gif.cpp:311
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
opt_mesh_algo3d
double opt_mesh_algo3d(OPT_ARGS_NUM)
Definition: Options.cpp:6058
MVertex::getNum
std::size_t getNum() const
Definition: MVertex.h:86
GModel::getFaceByTag
GFace * getFaceByTag(int n) const
Definition: GModel.cpp:326
GEntity::deleteMesh
virtual void deleteMesh()
Definition: GEntity.h:190
GModelParametrize.h
TYPE_PNT
#define TYPE_PNT
Definition: GmshDefines.h:64
GFace::meshAttributes
struct GFace::@18 meshAttributes
SBoundingBox3d::min
SPoint3 min() const
Definition: SBoundingBox3d.h:90
Range::high
T high() const
Definition: Range.h:20
GModel::empty
bool empty() const
Definition: GModel.cpp:311
GModel::_storeElementsInEntities
void _storeElementsInEntities(std::map< int, std::vector< MElement * > > &map)
Definition: GModel.cpp:2273
SVector3
Definition: SVector3.h:16
GModel::getMeshVertexByTag
MVertex * getMeshVertexByTag(int n)
Definition: GModel.cpp:1953
TYPE_TRI
#define TYPE_TRI
Definition: GmshDefines.h:66
GModel::getInnerPhysicalNamesIterators
void getInnerPhysicalNamesIterators(std::vector< piter > &iterators)
Definition: GModel.cpp:929
reverseInvisible
static std::size_t reverseInvisible(std::vector< T * > &elements, bool all)
Definition: GModel.cpp:2088
meshGFaceBamg
void meshGFaceBamg(GFace *gf)
Definition: meshGFaceBamg.cpp:242
GEdgeLoop.h
SPoint3::setPosition
void setPosition(double xx, double yy, double zz)
Definition: SPoint3.h:104
PView.h
GModelIO_OCC.h
GModelIO_GEO.h
PartitionUsingThisSplit
int PartitionUsingThisSplit(GModel *model, std::vector< std::pair< MElement *, int > > &elmToPartition)
Definition: meshPartition.cpp:2656
GRegion::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GRegion.cpp:60
meshGEdge.h
contextMeshOptions::meshOnlyVisible
int meshOnlyVisible
Definition: Context.h:36
GEntity::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GEntity.h:211
connectMElementsByMEdge
static void connectMElementsByMEdge(const MEdge &e, std::multimap< MEdge, MElement *, MEdgeLessThan > &e2e, std::set< MElement * > &group, std::set< MEdge, MEdgeLessThan > &touched)
Definition: GModel.cpp:3057
contextMeshOptions::firstNodeTag
int firstNodeTag
Definition: Context.h:57
MPyramid
Definition: MPyramid.h:32
GEntity::setTag
void setTag(int tag)
Definition: GEntity.h:281
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
MPoint.h
GModel::firstVertex
viter firstVertex()
Definition: GModel.h:357
MPrism
Definition: MPrism.h:34
GModel::deleteGEOInternals
void deleteGEOInternals()
Definition: GModelIO_GEO.cpp:1672
GModel::destroyMeshCaches
void destroyMeshCaches()
Definition: GModel.cpp:214
gmshSurface.h
opt_mesh_lc_from_points
double opt_mesh_lc_from_points(OPT_ARGS_NUM)
Definition: Options.cpp:5077
GModel::getEdgeByTag
GEdge * getEdgeByTag(int n) const
Definition: GModel.cpp:336
GModel::createParasolidInternals
void createParasolidInternals()
Definition: GModel.cpp:3619
GModel::getMeshDim
int getMeshDim() const
Definition: GModel.cpp:998
GmshMessage.h
GModel::setMaxVertexNumber
void setMaxVertexNumber(std::size_t num)
Definition: GModel.h:224
MLine.h
GModel::buildCutGModel
GModel * buildCutGModel(gLevelset *ls, bool cutElem=true, bool saveTri=false)
Definition: GModel.cpp:3376
UnpartitionMesh
int UnpartitionMesh(GModel *model)
Definition: meshPartition.cpp:2652
dimension
int dimension
Definition: GModelIO_TOCHNOG.cpp:18
GModel::getNumMeshElements
std::size_t getNumMeshElements(int dim=-1) const
Definition: GModel.cpp:1540
w1
const double w1
Definition: GaussQuadratureHex.cpp:18
GModel::removePhysicalGroups
void removePhysicalGroups()
Definition: GModel.cpp:893
GEntity
Definition: GEntity.h:31
GPoint
Definition: GPoint.h:13
GModel::~GModel
virtual ~GModel()
Definition: GModel.cpp:99
GEntity::getNumMeshVertices
std::size_t getNumMeshVertices()
Definition: GEntity.h:376
GEntityPtrLessThan
Definition: GEntity.h:419
GModel::firstPhysicalName
piter firstPhysicalName()
Definition: GModel.h:458
TYPE_PRI
#define TYPE_PRI
Definition: GmshDefines.h:70
GModel::addMVertexToVertexCache
void addMVertexToVertexCache(MVertex *v)
Definition: GModel.cpp:1970
AbsIntLessThan::operator()
bool operator()(const int &i1, const int &i2) const
Definition: GModel.cpp:690
GEntity::getMeshMaster
GEntity * getMeshMaster() const
Definition: GEntity.h:291
GModel::snapVertices
void snapVertices()
Definition: GModel.cpp:616
MElement::getNumVertices
virtual std::size_t getNumVertices() const =0
meshMetric.h
MElement::setVertex
virtual void setVertex(int num, MVertex *v)
Definition: MElement.h:109
GModel::getMeshElementIndex
int getMeshElementIndex(MElement *e)
Definition: GModel.cpp:2027
gmshSurface::reset
static void reset()
Definition: gmshSurface.h:30
refineMeshMMG
void refineMeshMMG(GRegion *gr)
Definition: meshGRegionMMG.cpp:359
GModel::rebuildMeshVertexCache
void rebuildMeshVertexCache(bool onlyIfNecessary=false)
Definition: GModel.cpp:1879
deMeshGEdge
Definition: meshGEdge.h:18
GModel::createGeometryOfDiscreteEntities
void createGeometryOfDiscreteEntities(const std::vector< std::pair< int, int > > &dimTags=std::vector< std::pair< int, int > >())
Definition: GModel.cpp:2370
GEntity::DiscreteCurve
@ DiscreteCurve
Definition: GEntity.h:104
GModel::_physicalNames
std::map< std::pair< int, int >, std::string > _physicalNames
Definition: GModel.h:150
discreteRegion
Definition: discreteRegion.h:13
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
GModel::_elementIndexCache
std::map< int, int > _elementIndexCache
Definition: GModel.h:105
discreteVertex.h
GModel::makeDiscreteRegionsSimplyConnected
void makeDiscreteRegionsSimplyConnected()
Definition: GModel.cpp:3101
FixPeriodicMesh
void FixPeriodicMesh(GModel *m)
Definition: Generator.cpp:1455
meshGRegionMMG.h
MLine
Definition: MLine.h:21
GVertex::points
std::vector< MPoint * > points
Definition: GVertex.h:120
GModel::_current
static int _current
Definition: GModel.h:139
GRegion::polyhedra
std::vector< MPolyhedron * > polyhedra
Definition: GRegion.h:168
GModel::findByName
static GModel * findByName(const std::string &name, const std::string &fileName="")
Definition: GModel.cpp:158
GModel::_mapFaceNum
hashmapMFace _mapFaceNum
Definition: GModel.h:54
GPoint::z
double z() const
Definition: GPoint.h:23
GFace::vertices
virtual std::vector< GVertex * > vertices() const
Definition: GFace.cpp:390
deMeshGRegion
Definition: meshGRegion.h:48
Msg::SetOnelabString
static void SetOnelabString(const std::string &name, const std::string &val, bool visible=true, bool persistent=false, bool readOnly=false, int changedValue=3, const std::string &kind="")
Definition: GmshMessage.cpp:1021
AbsIntLessThan
Definition: GModel.cpp:688
GModel::getEntitiesInBox
void getEntitiesInBox(std::vector< GEntity * > &entities, const SBoundingBox3d &box, int dim=-1) const
Definition: GModel.cpp:672
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
MElement::getVertex
virtual const MVertex * getVertex(int num) const =0
GRegion::faces
virtual std::vector< GFace * > faces() const
Definition: GRegion.h:64
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
GRegion::hexahedra
std::vector< MHexahedron * > hexahedra
Definition: GRegion.h:164
MElement::getEdge
virtual MEdge getEdge(int num) const =0
GModel::getPhysicalGroups
void getPhysicalGroups(std::map< int, std::vector< GEntity * > > groups[4]) const
Definition: GModel.cpp:837
GModel::lastFace
fiter lastFace()
Definition: GModel.h:359
GModel::addMFace
std::size_t addMFace(MFace &face, std::size_t num=0)
Definition: GModel.cpp:1583
GEntity::regions
virtual std::list< GRegion * > regions() const
Definition: GEntity.h:202
MFace
Definition: MFace.h:20
discreteVertex
Definition: discreteVertex.h:15
GModel::getPhysicalName
std::string getPhysicalName(int dim, int num) const
Definition: GModel.cpp:961
GModel::bounds
SBoundingBox3d bounds(bool aroundVisible=false)
Definition: GModel.cpp:1043
MTrihedron
Definition: MTrihedron.h:31
MVertex::setIndex
void setIndex(long int index)
Definition: MVertex.h:94
Range
Definition: Range.h:10
GModel::scaleMesh
void scaleMesh(double factor)
Definition: GModel.cpp:2189
GModel::createACISInternals
void createACISInternals()
Definition: GModel.cpp:3604
GModel::renumberMeshVertices
void renumberMeshVertices()
Definition: GModel.cpp:1623
GFace::meshStatistics
struct GFace::@19 meshStatistics
simpleFunction< double >
GModel::_elementaryNames
std::map< std::pair< int, int >, std::string > _elementaryNames
Definition: GModel.h:150
GModel::setFileName
void setFileName(const std::string &fileName)
Definition: GModel.cpp:123
GModel::changeEntityTag
bool changeEntityTag(int dim, int tag, int newTag)
Definition: GModel.cpp:367
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MElement::getType
virtual int getType() const =0
connectedVolumes
static int connectedVolumes(std::vector< MElement * > &elements, std::vector< std::vector< MElement * > > &regs)
Definition: GModel.cpp:3036
gLevelset
Definition: gmshLevelset.h:64
MElementCut.h
MHexahedron.h
FieldManager::newId
int newId()
Definition: Field.cpp:98
GModel::lastVertex
viter lastVertex()
Definition: GModel.h:361
HighOrder.h
MElement::getNumFaces
virtual int getNumFaces()=0
GEntity::getNumMeshElements
virtual std::size_t getNumMeshElements() const
Definition: GEntity.h:348
GVertex
Definition: GVertex.h:23
GModel::getMaxPhysicalNumber
int getMaxPhysicalNumber(int dim)
Definition: GModel.cpp:917
MVertexRTree::insert
MVertex * insert(MVertex *v, bool warnIfExists=false, std::set< MVertex *, MVertexPtrLessThan > *duplicates=nullptr)
Definition: MVertexRTree.h:38
meshRefine.h
tolerance
#define tolerance
Definition: curvature.cpp:11
SBoundingBox3d::empty
bool empty()
Definition: SBoundingBox3d.h:36
GModel::refineMesh
int refineMesh(int linear, bool splitIntoQuads=false, bool splitIntoHexas=false, bool barycentric=false)
Definition: GModel.cpp:1401
swap
void swap(double &a, double &b)
Definition: meshTriangulation.cpp:27
Homology.h
meshPartition.h
partitionRegion.h
GRegion::faceOrientations
virtual std::vector< int > faceOrientations() const
Definition: GRegion.h:66
MElement::getVolume
virtual double getVolume()
Definition: MElement.cpp:567
GModel::getDim
int getDim() const
Definition: GModel.cpp:989
GEntity::DiscreteVolume
@ DiscreteVolume
Definition: GEntity.h:120
norm
void norm(const double *vec, double *norm)
Definition: gmshLevelset.cpp:202
connectMElementsByMFace
static void connectMElementsByMFace(const MFace &f, std::multimap< MFace, MElement *, MFaceLessThan > &e2f, std::set< MElement * > &group, std::set< MFace, MFaceLessThan > &touched, int recur_level)
Definition: GModel.cpp:3012
GModel::_fileName
std::string _fileName
Definition: GModel.h:93
FieldManager::get
Field * get(int id)
Definition: Field.cpp:74
GModel::getNumVertices
std::size_t getNumVertices() const
Definition: GModel.h:347
MElement::getFace
virtual MFace getFace(int num) const =0
contextMeshOptions::saveWithoutOrphans
int saveWithoutOrphans
Definition: Context.h:66
GModel::setPhysicalNumToEntitiesInBox
void setPhysicalNumToEntitiesInBox(int EntityDimension, int PhysicalNumber, std::vector< double > p1, std::vector< double > p2)
Definition: GModel.cpp:3462
GModel
Definition: GModel.h:44
GModel::computeSizeField
void computeSizeField()
Definition: GModel.cpp:3590
Msg::StopProgressMeter
static void StopProgressMeter()
Definition: GmshMessage.cpp:318
GModel::rebuildMeshElementCache
void rebuildMeshElementCache(bool onlyIfNecessary=false)
Definition: GModel.cpp:1914
Cpu
double Cpu()
Definition: OS.cpp:366
GModel::classifySurfaces
void classifySurfaces(double angleThreshold, bool includeBoundary, bool forReparametrization, double curveAngleThreshold)
Definition: GModel.cpp:3472
GModel::vertices
std::set< GVertex *, GEntityPtrLessThan > vertices
Definition: GModel.h:146
GRegion::vertices
virtual std::vector< GVertex * > vertices() const
Definition: GRegion.cpp:603
GEntity::DONE
@ DONE
Definition: GEntity.h:130
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
GModel::addHomologyRequest
void addHomologyRequest(const std::string &type, const std::vector< int > &domain, const std::vector< int > &subdomain, const std::vector< int > &dim)
Definition: GModel.cpp:3480
GModel::getMeshVerticesForPhysicalGroup
void getMeshVerticesForPhysicalGroup(int dim, int num, std::vector< MVertex * > &)
Definition: GModel.cpp:1987
GModel::clearHomologyRequests
void clearHomologyRequests()
Definition: GModel.cpp:3491
MFace::getVertex
MVertex * getVertex(std::size_t i) const
Definition: MFace.h:30
Msg::SetWindowTitle
static void SetWindowTitle(const std::string &title)
Definition: GmshMessage.cpp:743
MESH_NONE
#define MESH_NONE
Definition: GmshDefines.h:258
MElement::reverse
virtual void reverse()
Definition: MElement.h:308
MPyramid.h
FieldManager
Definition: Field.h:145
GModel::getBoundaryTags
bool getBoundaryTags(const std::vector< std::pair< int, int > > &inDimTags, std::vector< std::pair< int, int > > &outDimTags, bool combined, bool oriented=true, bool recursive=false)
Definition: GModel.cpp:697
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
MQuadrangle::reorient
virtual void reorient(int rotation, bool swap)
Definition: MQuadrangle.cpp:464
GModel::firstFace
fiter firstFace()
Definition: GModel.h:355
MElementOctree
Definition: MElementOctree.h:15
GModel::removeInvisibleElements
std::size_t removeInvisibleElements()
Definition: GModel.cpp:2057
GEdge::meshAttributes
struct GEdge::@16 meshAttributes
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
GRegion::trihedra
std::vector< MTrihedron * > trihedra
Definition: GRegion.h:167
GModel::_checkPointedMaxVertexNum
std::size_t _checkPointedMaxVertexNum
Definition: GModel.h:57
contextMeshOptions::saveTri
int saveTri
Definition: Context.h:60
MHexahedron
Definition: MHexahedron.h:28
meshMetric
Definition: meshMetric.h:22
GModel::createGEOInternals
void createGEOInternals()
Definition: GModelIO_GEO.cpp:1670
GModel::add
bool add(GRegion *r)
Definition: GModel.h:394
GModel::_elementVectorCache
std::vector< std::pair< MElement *, int > > _elementVectorCache
Definition: GModel.h:103
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
GModel::getElementaryName
std::string getElementaryName(int dim, int tag)
Definition: GModel.cpp:1007
GModel::getNumRegions
std::size_t getNumRegions() const
Definition: GModel.h:344
GModel::destroy
void destroy(bool keepName=false)
Definition: GModel.cpp:168
deMeshGFace
Definition: meshGFace.h:30
GModel::getFields
FieldManager * getFields()
Definition: GModel.h:325
MElement
Definition: MElement.h:30
GModel::getMeshElementByTag
MElement * getMeshElementByTag(int n)
Definition: GModel.h:538
PViewDataGModel.h
GModel::remove
void remove()
Definition: GModel.cpp:608
skip
void skip(const char *skip, const char *until)
GModel::resetOCCInternals
void resetOCCInternals()
Definition: GModelIO_OCC.cpp:5886
GModel::_vertexMapCache
std::map< int, MVertex * > _vertexMapCache
Definition: GModel.h:102
GEntity::tag
int tag() const
Definition: GEntity.h:280
GModel::_checkPointedMaxElementNum
std::size_t _checkPointedMaxElementNum
Definition: GModel.h:57
ConvertOldPartitioningToNewOne
int ConvertOldPartitioningToNewOne(GModel *model)
Definition: meshPartition.cpp:2654
GModel::getNumFaces
std::size_t getNumFaces() const
Definition: GModel.h:345
GModel::list
static std::vector< GModel * > list
Definition: GModel.h:202
GModel::_numPartitions
std::size_t _numPartitions
Definition: GModel.h:153
GModel::deleteMesh
void deleteMesh()
Definition: GModel.cpp:236
GModel::removePhysicalName
void removePhysicalName(const std::string &name)
Definition: GModel.cpp:968
partitionFace.h
discreteFace.h
GModel::reverseInvisibleElements
std::size_t reverseInvisibleElements()
Definition: GModel.cpp:2102
MVertexRTree.h
GModel::_lastMeshVertexError
std::vector< MVertex * > _lastMeshVertexError
Definition: GModel.h:135
GModel::removeElementaryName
void removeElementaryName(const std::string &name)
Definition: GModel.cpp:1014
partitionEdge.h
GModel::_homologyRequests
std::multimap< std::pair< const std::vector< int >, const std::vector< int > >, std::pair< const std::string, const std::vector< int > > > _homologyRequests
Definition: GModel.h:48
connectedSurfaces
static int connectedSurfaces(std::vector< MElement * > &elements, std::vector< std::vector< MElement * > > &faces)
Definition: GModel.cpp:3080
GModel::save
void save(const std::string &fileName)
Definition: GModel.cpp:3432
PViewDataGModel::getNumTimeSteps
int getNumTimeSteps()
Definition: PViewDataGModel.cpp:270
GModel::makeDiscreteFacesSimplyConnected
void makeDiscreteFacesSimplyConnected()
Definition: GModel.cpp:3160
GModel::computeHomology
void computeHomology(std::vector< std::pair< int, int > > &newPhysicals)
Definition: GModel.cpp:3496
_addElements
static void _addElements(std::vector< T * > &dst, const std::vector< MElement * > &src)
Definition: GModel.cpp:2267
GModel::_vertexVectorCache
std::vector< MVertex * > _vertexVectorCache
Definition: GModel.h:101
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
GModel::alignPeriodicBoundaries
void alignPeriodicBoundaries()
Definition: GModel.cpp:2828
MVertex::forceNum
void forceNum(std::size_t num)
Definition: MVertex.cpp:48
PViewDataGModel::getType
int getType(int step, int ent, int ele)
Definition: PViewDataGModel.cpp:700
CTX::geom
contextGeometryOptions geom
Definition: Context.h:311
GRegion
Definition: GRegion.h:28
MElementOctree::find
MElement * find(double x, double y, double z, int dim=-1, bool strict=false) const
Definition: MElementOctree.cpp:205
GModel::getNumEdges
std::size_t getNumEdges() const
Definition: GModel.h:346
GRegion::prisms
std::vector< MPrism * > prisms
Definition: GRegion.h:165
GFace::getMeshElement
MElement * getMeshElement(std::size_t index) const
Definition: GFace.cpp:234
MTriangle
Definition: MTriangle.h:26
GModel::readGEO
static int readGEO(const std::string &name)
Definition: GModel.cpp:3440
GEntity::DiscreteSurface
@ DiscreteSurface
Definition: GEntity.h:117
GModel::piter
std::map< std::pair< int, int >, std::string >::iterator piter
Definition: GModel.h:194
GModel::getMeshElementsByCoord
std::vector< MElement * > getMeshElementsByCoord(SPoint3 &p, int dim=-1, bool strict=true)
Definition: GModel.cpp:1865
TYPE_PYR
#define TYPE_PYR
Definition: GmshDefines.h:69
StringUtils.h
GRegion::pyramids
std::vector< MPyramid * > pyramids
Definition: GRegion.h:166
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
GModel::writeMSH
int writeMSH(const std::string &name, double version=2.2, bool binary=false, bool saveAll=false, bool saveParametric=false, double scalingFactor=1.0, int elementStartNum=0, int saveSinglePartition=0, bool append=false)
Definition: GModelIO_MSH.cpp:76
GModel::readACISSAT
int readACISSAT(const std::string &name)
Definition: GModel.cpp:3608
LegendrePolynomials::df
void df(int n, double u, double *val)
Definition: orthogonalBasis.cpp:103
contextMeshOptions::changed
int changed
Definition: Context.h:82
GetAbsolutePath
std::string GetAbsolutePath(const std::string &fileName)
Definition: OS.cpp:454
GModel::getVisibility
char getVisibility() const
Definition: GModel.h:340
MElement::getVertices
void getVertices(std::vector< MVertex * > &verts)
Definition: MElement.h:103
GModel::writeParasolidXMT
int writeParasolidXMT(const std::string &name)
Definition: GModel.cpp:3630
GModel::firstRegion
riter firstRegion()
Definition: GModel.h:354
GEntity::isOrphan
virtual bool isOrphan()
Definition: GEntity.h:224
GModel::_elementOctree
MElementOctree * _elementOctree
Definition: GModel.h:113
GModel::setCurrent
static int setCurrent(GModel *m)
Definition: GModel.cpp:147
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
Msg::GetNumOnelabClients
static int GetNumOnelabClients()
Definition: GmshMessage.cpp:1277
GEdge::status
GEntity::MeshGenerationStatus status
Definition: GEdge.h:263
PViewDataGModel::ElementNodeData
@ ElementNodeData
Definition: PViewDataGModel.h:196
meshGFace.h
GModel::adaptMesh
int adaptMesh()
Definition: GModel.cpp:1215
GEdge::meshStatistics
struct GEdge::@17 meshStatistics
GModel::_storeParentsInSubElements
void _storeParentsInSubElements(std::map< int, std::vector< MElement * > > &map)
Definition: GModel.cpp:2347
discreteEdge.h
MVertex::getIndex
long int getIndex() const
Definition: MVertex.h:93
ENT_ALL
#define ENT_ALL
Definition: GmshDefines.h:235
Context.h
GEntity::getMeshElement
virtual MElement * getMeshElement(std::size_t index) const
Definition: GEntity.h:363
MTetrahedron.h
GModel::unpartitionMesh
int unpartitionMesh()
Definition: GModel.cpp:2226
laplaceSmoothing
void laplaceSmoothing(GFace *gf, int niter, bool infinity_norm)
Definition: meshGFaceOptimize.cpp:978
z
const double z
Definition: GaussQuadratureQuad.cpp:56
GModel::storeChain
void storeChain(int dim, std::map< int, std::vector< MElement * > > &entityMap, std::map< int, std::map< int, std::string > > &physicalMap)
Definition: GModel.cpp:2247
GModel::lastPhysicalName
piter lastPhysicalName()
Definition: GModel.h:459
addToMap
static void addToMap(std::multimap< MFace, MElement *, MFaceLessThan > &faceToElement, std::map< MElement *, std::vector< std::pair< MElement *, bool > > > &elToNeighbors, const MFace &face, MElement *el)
Definition: GModel.cpp:1095
MQuadrangle.h
GModel::writeParasolidSTEP
int writeParasolidSTEP(const std::string &name)
Definition: GModel.cpp:3644
GRegion::meshAttributes
struct GRegion::@20 meshAttributes
GModel::setMeshElementIndex
void setMeshElementIndex(MElement *e, int index)
Definition: GModel.cpp:2036
GModel::faces
std::set< GFace *, GEntityPtrLessThan > faces
Definition: GModel.h:144
makeSimplyConnected
static void makeSimplyConnected(std::map< int, std::vector< MElement * > > elements[11])
Definition: GModel.cpp:3216
GVertex::delEdge
void delEdge(GEdge *e)
Definition: GVertex.cpp:43
GModel::noPhysicalGroups
bool noPhysicalGroups()
Definition: GModel.cpp:828
Msg::StartProgressMeter
static void StartProgressMeter(int ntotal)
Definition: GmshMessage.cpp:312
GModel::removePhysicalGroup
void removePhysicalGroup(int dim, int num)
Definition: GModel.cpp:901
GEdge
Definition: GEdge.h:26
GModel::optimizeMesh
int optimizeMesh(const std::string &how, bool force=false, int niter=1)
Definition: GModel.cpp:1437
OCC_Internals::synchronize
void synchronize(GModel *model)
Definition: GModelIO_OCC.h:803
PViewDataGModel::DataType
DataType
Definition: PViewDataGModel.h:193
GModel::_maxVertexNum
std::size_t _maxVertexNum
Definition: GModel.h:56
GModel::pruneMeshVertexAssociations
void pruneMeshVertexAssociations()
Definition: GModel.cpp:2527
TYPE_HEX
#define TYPE_HEX
Definition: GmshDefines.h:71
GModel::_chainVertices
std::set< GVertex *, GEntityPtrLessThan > _chainVertices
Definition: GModel.h:52
GModel::riter
std::set< GRegion *, GEntityPtrLessThan >::iterator riter
Definition: GModel.h:183
FORMAT_AUTO
#define FORMAT_AUTO
Definition: GmshDefines.h:18
GModel::_elementMapCache
std::map< int, std::pair< MElement *, int > > _elementMapCache
Definition: GModel.h:104
MPrism.h
MElementOctree::findAll
std::vector< MElement * > findAll(double x, double y, double z, int dim, bool strict=false) const
Definition: MElementOctree.cpp:145
MElement::barycenter
virtual SPoint3 barycenter(bool primary=false) const
Definition: MElement.cpp:520
GModel::_chainFaces
std::set< GFace *, GEntityPtrLessThan > _chainFaces
Definition: GModel.h:50
Field::update
virtual void update()
Definition: Field.h:110
TYPE_TET
#define TYPE_TET
Definition: GmshDefines.h:68
GModel::setPhysicalName
int setPhysicalName(const std::string &name, int dim, int num=0)
Definition: GModel.cpp:937
PartitionMesh
int PartitionMesh(GModel *model, int numPart)
Definition: meshPartition.cpp:2646
GModel::getEntityByTag
GEntity * getEntityByTag(int dim, int n) const
Definition: GModel.cpp:356
GModel::_mapEdgeNum
hashmapMEdge _mapEdgeNum
Definition: GModel.h:53
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
GModel::mesh
int mesh(int dimension)
Definition: GModel.cpp:1066
GModel::getMFace
std::size_t getMFace(MVertex *v0, MVertex *v1, MVertex *v2, MVertex *v3, MFace &face)
Definition: GModel.cpp:1591
GModel::regions
std::set< GRegion *, GEntityPtrLessThan > regions
Definition: GModel.h:143
meshGRegion.h
RecombineMesh
void RecombineMesh(GModel *m)
Definition: Generator.cpp:1318
MEdge::computeCorrespondence
int computeCorrespondence(MEdge &other)
Definition: MEdge.h:44
TYPE_TRIH
#define TYPE_TRIH
Definition: GmshDefines.h:76
Options.h
GModel::renumberMeshElements
void renumberMeshElements()
Definition: GModel.cpp:1732
MVertexRTree
Definition: MVertexRTree.h:16
GModel::lastEdge
eiter lastEdge()
Definition: GModel.h:360
RefineMesh
void RefineMesh(GModel *m, bool linear, bool splitIntoQuads, bool splitIntoHexas)
Definition: meshRefine.cpp:463
GModel::getMEdge
std::size_t getMEdge(MVertex *v0, MVertex *v1, MEdge &edge)
Definition: GModel.cpp:1569
GModel.h
MFace::getNumVertices
std::size_t getNumVertices() const
Definition: MFace.h:29
GEdge::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GEdge.h:201
GModel::getRegionByTag
GRegion * getRegionByTag(int n) const
Definition: GModel.cpp:316
MVertex::y
double y() const
Definition: MVertex.h:61
GModel::_storeVerticesInEntities
void _storeVerticesInEntities(std::map< int, MVertex * > &vertices)
Definition: GModel.cpp:2496
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
GModel::checkMeshCoherence
void checkMeshCoherence(double tolerance)
Definition: GModel.cpp:2595
GModel::readParasolidSTEP
int readParasolidSTEP(const std::string &name)
Definition: GModel.cpp:3637
opt_mesh_algo2d
double opt_mesh_algo2d(OPT_ARGS_NUM)
Definition: Options.cpp:5889
GModel::setMaxElementNumber
void setMaxElementNumber(std::size_t num)
Definition: GModel.h:229
Range::low
T low() const
Definition: Range.h:18
PViewDataGModel::getStepData
stepData< double > * getStepData(int step)
Definition: PViewDataGModel.h:321
MFace::computeCorrespondence
bool computeCorrespondence(const MFace &, int &, bool &) const
Definition: MFace.cpp:212
GFace::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GFace.cpp:181
MElement::getPartition
virtual int getPartition() const
Definition: MElement.h:92
PView::list
static std::vector< PView * > list
Definition: PView.h:112
GEO_Internals::synchronize
void synchronize(GModel *model, bool resetMeshAttributes=true)
Definition: GModelIO_GEO.cpp:1370
classifyFaces
void classifyFaces(GModel *gm, double curveAngleThreshold)
Definition: GModelParametrize.cpp:103
FieldManager::newField
Field * newField(int id, const std::string &type_name)
Definition: Field.cpp:81
MTriangle::reorient
virtual void reorient(int rotation, bool swap)
Definition: MTriangle.cpp:382
SBoundingBox3d::max
SPoint3 max() const
Definition: SBoundingBox3d.h:91
GModel::addPhysicalGroup
void addPhysicalGroup(int dim, int tag, const std::vector< int > &tags)
Definition: GModel.cpp:881
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
Msg::ProgressMeter
static void ProgressMeter(int n, bool log, const char *fmt,...)
Definition: GmshMessage.cpp:783
GModel::getVertexByTag
GVertex * getVertexByTag(int n) const
Definition: GModel.cpp:346
partitionVertex.h
GModel::setSelection
void setSelection(int val)
Definition: GModel.cpp:1026
GModel::getGEOInternals
GEO_Internals * getGEOInternals()
Definition: GModel.h:315
ParseFile
int ParseFile(const std::string &fileName, bool close, bool errorIfMissing)
Definition: OpenFile.cpp:177
MVertex::setEntity
void setEntity(GEntity *ge)
Definition: MVertex.h:83
OptimizeMesh
void OptimizeMesh(GModel *m, const std::string &how, bool force, int niter)
Definition: Generator.cpp:1101
GModel::deleteVertexArrays
void deleteVertexArrays()
Definition: GModel.cpp:299
Generator.h
stepData
Definition: PViewDataGModel.h:13
GModel::deleteParasolidInternals
void deleteParasolidInternals()
Definition: GModel.cpp:3621
GModel::getMeshStatus
int getMeshStatus(bool countDiscrete=true)
Definition: GModel.cpp:1474
GPoint::x
double x() const
Definition: GPoint.h:21
GEntity::getVisibility
virtual char getVisibility()
Definition: GEntity.cpp:35
MElement::getNumEdges
virtual int getNumEdges() const =0
GEntity::correspondingVertices
std::map< MVertex *, MVertex * > correspondingVertices
Definition: GEntity.h:406
GModel::_maxElementNum
std::size_t _maxElementNum
Definition: GModel.h:56
GModel::_associateEntityWithMeshVertices
void _associateEntityWithMeshVertices()
Definition: GModel.cpp:2470
GModel::setAllVolumesPositive
bool setAllVolumesPositive()
Definition: GModel.cpp:1085
GEntity::faces
virtual std::vector< GFace * > faces() const
Definition: GEntity.h:208
GModel::getOCCInternals
OCC_Internals * getOCCInternals()
Definition: GModel.h:314
TYPE_POLYH
#define TYPE_POLYH
Definition: GmshDefines.h:73
GModel::edges
std::set< GEdge *, GEntityPtrLessThan > edges
Definition: GModel.h:145
MQuadrangle
Definition: MQuadrangle.h:26
GModel::addMEdge
std::size_t addMEdge(MEdge &edge, std::size_t num=0)
Definition: GModel.cpp:1561
SBoundingBox3d
Definition: SBoundingBox3d.h:21
ElementType::getParentType
int getParentType(int type)
Definition: ElementType.cpp:10
GModel::_chainRegions
std::set< GRegion *, GEntityPtrLessThan > _chainRegions
Definition: GModel.h:49
GModel::setCurrentMeshEntity
void setCurrentMeshEntity(GEntity *e)
Definition: GModel.cpp:2202
GModel::getTagsForPhysicalName
std::vector< int > getTagsForPhysicalName(int dim, const std::string &name)
Definition: GModel.cpp:420
removeInvisible
static std::size_t removeInvisible(std::vector< T * > &elements, bool all)
Definition: GModel.cpp:2042
GModel::indexMeshVertices
std::size_t indexMeshVertices(bool all, int singlePartition=0, bool renumber=true)
Definition: GModel.cpp:2135
GModel::getPhysicalNumber
int getPhysicalNumber(const int &dim, const std::string &name)
Definition: GModel.cpp:980
OpenFile.h
GEdge::method
char method
Definition: GEdge.h:250
GModel::_storePhysicalTagsInEntities
void _storePhysicalTagsInEntities(int dim, std::map< int, std::map< int, std::string > > &map)
Definition: GModel.cpp:2568
meshGFaceBamg.h
GRegion::tetrahedra
std::vector< MTetrahedron * > tetrahedra
Definition: GRegion.h:163
GModel::current
static GModel * current(int index=-1)
Definition: GModel.cpp:136
meshMetric::addMetric
void addMetric(int technique, simpleFunction< double > *fct, const std::vector< double > &parameters)
Definition: meshMetric.cpp:64
SmoothData.h
MVertex::x
double x() const
Definition: MVertex.h:60
FieldManager::setBackgroundField
void setBackgroundField(Field *BGF)
Definition: Field.cpp:3224
GModel::partitionMesh
int partitionMesh(int num, std::vector< std::pair< MElement *, int > > elementPartition=std::vector< std::pair< MElement *, int > >())
Definition: GModel.cpp:2208
SetOrder1
void SetOrder1(GModel *m, bool onlyVisible, bool skipDiscrete)
Definition: HighOrder.cpp:1233
discreteFace
Definition: discreteFace.h:18
faces
static int faces[4][3]
Definition: meshGRegionDelaunayInsertion.cpp:165
BarycentricRefineMesh
void BarycentricRefineMesh(GModel *m)
Definition: meshRefine.cpp:507
GModel::getMeshElementByCoord
MElement * getMeshElementByCoord(SPoint3 &p, SPoint3 &param, int dim=-1, bool strict=true)
Definition: GModel.cpp:1842