NEMoSys  0.63.0
A modular, extensible resource with robust automated mesh generation, mesh quality analysis, adaptive mesh refinement, and data transfer between arbitrary meshes.
gmshMesh.C
Go to the documentation of this file.
1 /*******************************************************************************
2 * Promesh *
3 * Copyright (C) 2022, IllinoisRocstar LLC. All rights reserved. *
4 * *
5 * Promesh is the property of IllinoisRocstar LLC. *
6 * *
7 * IllinoisRocstar LLC *
8 * Champaign, IL *
9 * www.illinoisrocstar.com *
10 * promesh@illinoisrocstar.com *
11 *******************************************************************************/
12 /*******************************************************************************
13 * This file is part of Promesh *
14 * *
15 * This version of Promesh is free software: you can redistribute it and/or *
16 * modify it under the terms of the GNU Lesser General Public License as *
17 * published by the Free Software Foundation, either version 3 of the License, *
18 * or (at your option) any later version. *
19 * *
20 * Promesh is distributed in the hope that it will be useful, but WITHOUT ANY *
21 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more *
23 * details. *
24 * *
25 * You should have received a copy of the GNU Lesser General Public License *
26 * along with this program. If not, see <https://www.gnu.org/licenses/>. *
27 * *
28 *******************************************************************************/
29 #include <gmsh.h>
30 #include <gmsh/Context.h>
31 #include <gmsh/CreateFile.h>
32 #include <gmsh/MHexahedron.h>
33 #include <gmsh/MLine.h>
34 #include <gmsh/MPoint.h>
35 #include <gmsh/MPrism.h>
36 #include <gmsh/MPyramid.h>
37 #include <gmsh/MQuadrangle.h>
38 #include <gmsh/MTetrahedron.h>
39 #include <gmsh/MTriangle.h>
40 
41 #include "Mesh/gmshMesh.H"
42 
43 #include <vtkIdList.h>
44 #include <vtkUnstructuredGrid.h>
45 
46 class nemosysGModel : public GModel {
47  public:
48  void storeElementsInEntities(std::map<int, std::vector<MElement *>> &map) {
49  GModel::_storeElementsInEntities(map);
50  }
51 
52  void associateEntityWithMeshVertices(bool force = false) {
53  GModel::_associateEntityWithMeshVertices(force);
54  }
55 
56  void storeVerticesInEntities(std::vector<MVertex *> &vertices) {
57  GModel::_storeVerticesInEntities(vertices);
58  }
59 
61  int dim, std::map<int, std::map<int, std::string>> &map) {
62  GModel::_storePhysicalTagsInEntities(dim, map);
63  }
64 };
65 
67  gmsh::initialize();
68  // _gmshGModel = GModel();
69  std::cout << "gmshMesh constructed" << std::endl;
70 }
71 
73  // this constructor tries a brute-force
74  // method. Use with care.
75  gmsh::initialize();
76  // dataSet uses smart pointers so deep
77  // copy is not needed
78  dataSet = mb->getDataSet();
79  numPoints = dataSet->GetNumberOfPoints();
80  numCells = dataSet->GetNumberOfCells();
81  std::cout << "Number of points: " << numPoints << std::endl;
82  std::cout << "Number of cells: " << numCells << std::endl;
83  std::cout << "gmshMesh constructed" << std::endl;
84 }
85 
87  // _gmshGModel.destroy();
88  gmsh::finalize();
89  std::cout << "gmshMesh destroyed" << std::endl;
90 }
91 
92 gmshMesh::gmshMesh(const std::string &fname) {
93  gmsh::initialize();
94  filename = fname;
95  read(filename);
96  std::cout << "gmshMesh constructed" << std::endl;
97 }
98 
99 void gmshMesh::read(const std::string &fname) {
100  // Read the file.
101  GModel _gmshGModel = GModel();
102  _gmshGModel.load(fname);
103 
104  vtkSmartPointer<vtkUnstructuredGrid> dataSet_tmp =
106 
107  // get all entities in the model
108  std::vector<GEntity *> entities;
109  _gmshGModel.getEntities(entities);
110 
111  // Add mesh vertices
112  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
113  // Map from gmsh Index `long int` to vtk Id `vtkIdType`. Necessary since gmsh
114  // indices are not their position in the `mesh_vertices` array.
115  std::map<long int, vtkIdType> gmshIndex2vtkId;
116  for (const auto &entity : entities)
117  for (const auto &mesh_vertex : entity->mesh_vertices) {
118  // Order of inserting into map and inserting into vtkPoints is important.
119  // Be mindful if editing.
120  gmshIndex2vtkId[mesh_vertex->getIndex()] = points->GetNumberOfPoints();
121  // `SPoint3` has implicit conversion into `double *`
122  points->InsertNextPoint(mesh_vertex->point());
123 
124  // std::cout << "Inserted point. From mesh_vertex: "
125  // << mesh_vertex->point().x() << " "
126  // << mesh_vertex->point().y() << " "
127  // << mesh_vertex->point().z() << " "
128  // << " To vtkPoints: "
129  // <<
130  // *(points->GetPoint(gmshIndex2vtkId[mesh_vertex->getIndex()]))
131  // << " "
132  // <<
133  // *(points->GetPoint(gmshIndex2vtkId[mesh_vertex->getIndex()])+1)
134  // << " "
135  // <<
136  // *(points->GetPoint(gmshIndex2vtkId[mesh_vertex->getIndex()])+2)
137  // << " "
138  // << std::endl;
139  }
140  dataSet_tmp->SetPoints(points);
141 
142  // Count mesh elements
143  std::size_t numMeshElements = 0;
144  for (const auto &entity : entities)
145  numMeshElements += entity->getNumMeshElements();
146  dataSet_tmp->Allocate(numMeshElements);
147 
148  // Add mesh elements
149  const char **typeName = nullptr;
150  std::vector<const char **> unsupportedTypesList{};
151  std::size_t numUnsupportedElements = 0;
152  for (const auto &entity : entities) {
153  for (int j = 0; j != entity->getNumMeshElements(); ++j) {
154  // Check if element has an equivalent VTK cell type.
155  if (entity->getMeshElement(j)->getTypeForVTK()) {
156  vtkSmartPointer<vtkIdList> idList = vtkSmartPointer<vtkIdList>::New();
157  // Allocate vertices
158  idList->Allocate(entity->getMeshElement(j)->getNumVertices());
159  // Add vertices to vtkIdList
160  for (std::size_t k = 0;
161  k != entity->getMeshElement(j)->getNumVertices(); ++k)
162  idList->InsertNextId(
163  // entity->getMeshElement(j)->getVertexVTK(k)->getIndex()
164  // - 1);
165  gmshIndex2vtkId
166  [entity->getMeshElement(j)->getVertex(k)->getIndex()]);
167  // Add cell to vtkUnstructuredGrid
168  dataSet_tmp->InsertNextCell(entity->getMeshElement(j)->getTypeForVTK(),
169  idList);
170  } else {
171  ++numUnsupportedElements;
172  MElement::getInfoMSH(entity->getMeshElement(j)->getTypeForMSH(),
173  typeName);
174  unsupportedTypesList.emplace_back(typeName);
175  }
176  }
177  }
178 
179  if (numUnsupportedElements) {
180  std::cerr << "WARNING: " << numUnsupportedElements
181  << " unsupported Gmsh elements detected of the following types:";
182  for (const auto &unsupportedType : unsupportedTypesList) {
183  std::cerr << " \"" << unsupportedType << "\"";
184  }
185  std::cerr << std::endl;
186  }
187 
188  /* TODO:
189  * Add geometry storage as vtkCellData
190  * */
191 
192  dataSet = dataSet_tmp;
193 
194  numPoints = dataSet->GetNumberOfPoints();
195  numCells = dataSet->GetNumberOfCells();
196  std::cout << "Number of points: " << numPoints << std::endl;
197  std::cout << "Number of cells: " << numCells << std::endl;
198 }
199 void gmshMesh::write(const std::string &fname) const {
200  write(fname, 4.1, false);
201 }
202 
203 void gmshMesh::write(const std::string &fname, double mshFileVersion,
204  bool binary) const {
205  nemosysGModel _nemosysGModel = nemosysGModel();
206 
207  // Add mesh vertices
208  std::vector<MVertex *> vertices(numPoints);
209  double xyz[3]; // Reused in mesh element loop.
210 
211  for (nemId_t i = 0; i != numPoints; ++i) {
212  dataSet->GetPoint(i, xyz);
213  vertices[i] = new MVertex(xyz[0], xyz[1], xyz[2]);
214  }
215 
216  // Add mesh elements
217  std::map<int, std::vector<MElement *>> elements[8];
218 
219  for (nemId_t i = 0; i != numCells; ++i) {
220  vtkSmartPointer<vtkIdList> idList = vtkSmartPointer<vtkIdList>::New();
221  // Assign type
222  int type = dataSet->GetCellType(i);
223 
224  dataSet->GetCellPoints(i, idList);
225 
226  std::vector<MVertex *> cell(idList->GetNumberOfIds());
227  for (vtkIdType j = 0; j != idList->GetNumberOfIds(); ++j) {
228  cell[j] = vertices[idList->GetId(j)];
229  }
230 
231  /* vv ------- Taken from Gmsh source: src/Geo/GModelIO_VTK.cpp:278 -------
232  * vv */
233  switch (type) {
234  case 1:
235  elements[0][1].push_back(new MPoint(cell));
236  break;
237  // first order elements
238  case 3:
239  elements[1][1].push_back(new MLine(cell));
240  break;
241  case 5:
242  elements[2][1].push_back(new MTriangle(cell));
243  break;
244  case 9:
245  elements[3][1].push_back(new MQuadrangle(cell));
246  break;
247  case 10:
248  elements[4][1].push_back(new MTetrahedron(cell));
249  break;
250  case 12:
251  elements[5][1].push_back(new MHexahedron(cell));
252  break;
253  case 13:
254  elements[6][1].push_back(new MPrism(cell));
255  break;
256  case 14:
257  elements[7][1].push_back(new MPyramid(cell));
258  break;
259  // second order elements
260  case 21:
261  elements[1][1].push_back(new MLine3(cell));
262  break;
263  case 22:
264  elements[2][1].push_back(new MTriangle6(cell));
265  break;
266  case 23:
267  elements[3][1].push_back(new MQuadrangle8(cell));
268  break;
269  case 28:
270  elements[3][1].push_back(new MQuadrangle9(cell));
271  break;
272  case 24:
273  elements[4][1].push_back(new MTetrahedron10(cell));
274  break;
275  case 25:
276  elements[5][1].push_back(new MHexahedron20(cell));
277  break;
278  case 29:
279  elements[5][1].push_back(new MHexahedron27(cell));
280  break;
281  default:
282  Msg::Error("Unknown type of cell %d", type);
283  break;
284  }
285  /* ^^ ------- Taken from Gmsh source: src/Geo/GModelIO_VTK.cpp:278 -------
286  * ^^ */
287  }
288 
289  for (auto &&element : elements)
290  _nemosysGModel.storeElementsInEntities(element);
291  _nemosysGModel.associateEntityWithMeshVertices();
292  _nemosysGModel.storeVerticesInEntities(vertices);
293 
294  // store the physical tags
295  // for(int i = 0; i < 4; i++)
296  // _nemosysGModel.storePhysicalTagsInEntities(i, physicals[i]);
297  // Renumber the indices to be contiguous.
298  _nemosysGModel.renumberMeshVertices();
299  _nemosysGModel.renumberMeshElements();
300 
301  // Write the file.
302  // _nemosysGModel.save(fname);
303 
304  // GModel *temp = nemosysGModel::current();
305  // _nemosysGModel.setAsCurrent();
306  // CTX::instance()->mesh.
307  // CreateOutputFile(fname, FORMAT_MSH);
308  // nemosysGModel::setCurrent(temp);
309  _nemosysGModel.writeMSH(
310  fname, mshFileVersion, binary //,
311  // saveAll, saveParametric, scalingFactor
312  );
313  std::cout << "gmshMesh saved to " << fname << std::endl;
314 }
315 
316 std::vector<double> gmshMesh::getPoint(nemId_t id) const {
317  return std::vector<double>();
318 }
319 std::vector<std::vector<double>> gmshMesh::getVertCrds() const {
320  return std::vector<std::vector<double>>();
321 }
322 std::map<nemId_t, std::vector<double>> gmshMesh::getCell(nemId_t id) const {
323  return std::map<nemId_t, std::vector<double>>();
324 }
325 std::vector<std::vector<double>> gmshMesh::getCellVec(nemId_t id) const {
326  return std::vector<std::vector<double>>();
327 }
328 void gmshMesh::inspectEdges(const std::string &ofname) const {}
329 vtkSmartPointer<vtkDataSet> gmshMesh::extractSurface() {
330  return vtkSmartPointer<vtkDataSet>();
331 }
332 std::vector<double> gmshMesh::getCellLengths() const {
333  return std::vector<double>();
334 }
335 std::vector<double> gmshMesh::getCellCenter(nemId_t cellID) const {
336  return std::vector<double>();
337 }
338 int gmshMesh::getCellType() const { return 0; }
339 std::vector<nemId_t> gmshMesh::getConnectivities() const {
340  return std::vector<nemId_t>();
341 }
342 
gmshMesh()
Definition: gmshMesh.C:66
std::vector< std::vector< double > > getCellVec(nemId_t id) const override
get vector of coords of cell with id
Definition: gmshMesh.C:325
vtkSmartPointer< vtkDataSet > extractSurface() override
extract the surface mesh
Definition: gmshMesh.C:329
std::vector< double > getCellLengths() const override
get diameter of circumsphere of each cell
Definition: gmshMesh.C:332
int getCellType() const override
get cell type as an integer assumes all elements are the same type
Definition: gmshMesh.C:338
std::vector< std::vector< double > > getVertCrds() const override
get 3 vecs with x,y and z coords
Definition: gmshMesh.C:319
A brief description of meshBase.
Definition: meshBase.H:64
std::size_t nemId_t
Definition: meshBase.H:51
void report() const override
generate a report of the mesh
Definition: gmshMesh.C:343
void read(const std::string &fname)
abstract read method reserved for derived classes
Definition: gmshMesh.C:99
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
void storeVerticesInEntities(std::vector< MVertex *> &vertices)
Definition: gmshMesh.C:56
void storePhysicalTagsInEntities(int dim, std::map< int, std::map< int, std::string >> &map)
Definition: gmshMesh.C:60
void inspectEdges(const std::string &ofname) const override
get edge lengths of dataSet
Definition: gmshMesh.C:328
std::vector< double > getPoint(nemId_t id) const override
get point with id
Definition: gmshMesh.C:316
vtkSmartPointer< vtkDataSet > getDataSet() const
get this meshes&#39; dataSet
Definition: meshBase.H:308
~gmshMesh() override
Definition: gmshMesh.C:86
virtual void write() const
write the mesh to file named after the private var &#39;filename&#39;.
Definition: meshBase.H:598
std::map< nemId_t, std::vector< double > > getCell(nemId_t id) const override
get cell with id
Definition: gmshMesh.C:322
std::vector< nemId_t > getConnectivities() const override
get connectivities.
Definition: gmshMesh.C:339
std::vector< double > getCellCenter(nemId_t cellID) const override
get center of a cell
Definition: gmshMesh.C:335
std::vector< vtkIdType > points
points given by id in .inp file
Definition: inpGeoMesh.C:133
void storeElementsInEntities(std::map< int, std::vector< MElement *>> &map)
Definition: gmshMesh.C:48
virtual void report() const
generate a report of the mesh
Definition: meshBase.H:540
void associateEntityWithMeshVertices(bool force=false)
Definition: gmshMesh.C:52