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.
geoMeshBase.H
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 #ifndef NEMOSYS_GEOMESHBASE_H_
30 #define NEMOSYS_GEOMESHBASE_H_
31 
32 #include "nemosys_export.h"
33 
34 #include <array>
35 #include <cstdint>
36 #include <memory>
37 #include <ostream>
38 #include <string>
39 
40 #include <vtkAbstractArray.h>
41 #include <vtkCellData.h>
42 #include <vtkCellType.h>
43 #include <vtkDataObject.h>
44 #include <vtkFieldData.h>
45 #include <vtkGenericCell.h>
46 #include <vtkIdList.h>
47 #include <vtkPointData.h>
48 #include <vtkPolyData.h>
49 #include <vtkSmartPointer.h>
50 #include <vtkStringArray.h>
51 #include <vtkUnstructuredGrid.h>
52 
53 namespace NEM {
54 namespace MSH {
55 
56 using nemId_t = std::int64_t;
57 
58 /**
59  * @class GmshInterface
60  * @brief management class for Gmsh interface
61  *
62  * Gmsh uses global (and static members) variables that are initialized and
63  * finalized by Gmsh API commands. This class manages geoMeshBase usage of Gmsh
64  * to guarantee finalization only when no geoMeshBase instances are left.
65  */
66 class NEMOSYS_EXPORT GmshInterface {
67  public:
68  ~GmshInterface();
69 
70  /**@{*/
71  GmshInterface(const GmshInterface &) = delete;
72  GmshInterface &operator=(const GmshInterface &) = delete;
73  GmshInterface(GmshInterface &&) = delete;
74  GmshInterface &operator=(GmshInterface &&) = delete;
75  /**@}*/
76 
77  public:
78  /**
79  * Initialize Gmsh. Will only call gmsh::initialize() on first call to method.
80  */
81  static void Initialize();
82  /**
83  * Finalize Gmsh. Will only call gmsh::finalize() if count is zero.
84  */
85  static void Finalize();
86 
87  private:
88  GmshInterface();
89 
90  private:
91  static std::shared_ptr<GmshInterface> instance;
92  static int count;
93 };
94 
95 /**
96  * @class geoMeshBase
97  * @brief abstract class to specify geometry and mesh data
98  *
99  * geoMeshBase is an abstract class that specifies an interface for geometry
100  * and mesh objects.
101  */
102 class NEMOSYS_EXPORT geoMeshBase : public vtkDataObject {
103  vtkAbstractTypeMacro(geoMeshBase, vtkDataObject)
104 
105  public:
106  /**
107  * Query for conversion from vtk to gmsh
108  * @param vtkType
109  * @return type given by @c GMSH_MSH_TYPES enum
110  */
111  static int getGmshTypeFromVTKType(int vtkType);
112 
113  public:
114  geoMeshBase();
115  ~geoMeshBase() override;
116  // Copy and move constructors/assignment operators deleted in vtkDataObject
117 
118  public:
119  /**
120  * Write mesh to file
121  * @param fileName file name
122  */
123  virtual void write(const std::string &fileName) = 0;
124  /**
125  * Print a report about the mesh
126  * @param out stream
127  */
128  virtual void report(std::ostream &out) const = 0;
129  friend std::ostream &operator<<(std::ostream &os, const geoMeshBase &base) {
130  base.report(os);
131  return os;
132  }
133  /**
134  * Take the GeoMesh of another @c geoMeshBase. Note that @p otherGeoMesh will
135  * be left with an empty mesh.
136  * @param otherGeoMesh other geoMeshBase object; mesh will be left empty
137  */
138  virtual void takeGeoMesh(geoMeshBase *otherGeoMesh);
139  /**
140  * Construct the geometry from the mesh alone. Sets geometry, link, and side
141  * set. Does not alter the mesh.
142  */
143  virtual void reconstructGeo();
144 
145  /**
146  * Merge mesh data from a new geoMesh to an existing geoMesh. Deletes the data
147  * from the new geoMesh pointer
148  * @param otherGeoMesh A new geoMesh data to merge
149  */
150  virtual void mergeGeoMesh(geoMeshBase *otherGeoMesh);
151 
152  public:
153  /**
154  * Get the name of the geometric entities array
155  * @return name of geometric entities array
156  */
157  const std::string &getGeoEntArrayName() const { return _geoMesh.link; }
158  /**
159  * Set the name of the geometric entities array
160  * @param geoEntArrayName name of geometric entities array
161  */
162  void setGeoEntArrayName(const std::string &geoEntArrayName) {
163  auto a = _geoMesh.mesh->GetCellData()->GetArray(_geoMesh.link.c_str());
164  if (a) a->SetName(geoEntArrayName.c_str());
165  _geoMesh.link = geoEntArrayName;
166  }
167  /**
168  * Get the angle threshold used for surface classification
169  * @return angle threshold (in radians)
170  */
171  double getAngleThreshold() const { return _angleThreshold; }
172  /**
173  * Set the angle threshold used for surface classification
174  * @param angleThreshold (in radians)
175  */
176  void setAngleThreshold(double angleThreshold) {
177  _angleThreshold = angleThreshold;
178  }
179  /**
180  * Get the number of points in mesh
181  * @return number of points in mesh
182  */
184  return _geoMesh.mesh->GetNumberOfPoints();
185  }
186  /**
187  * Get the number of cells in mesh
188  * @return number of cells in mesh
189  */
190  nemId_t getNumberOfCells() const { return _geoMesh.mesh->GetNumberOfCells(); }
191  /**
192  * Get the coordinate of a point
193  * @param id point id
194  * @param x array of coordinates as (x,y,z)
195  */
196  void getPoint(nemId_t id, std::array<double, 3> *x) const {
197  _geoMesh.mesh->GetPoint(id, x->data());
198  }
199  /**
200  * Get the coordinate of a point
201  * @param id point id
202  * @return array of coordinates as (x,y,z)
203  */
204  std::array<double, 3> getPoint(nemId_t id) const {
205  std::array<double, 3> x{};
206  getPoint(id, &x);
207  return x;
208  }
209  /**
210  * Get cell.
211  * @param cellId cell id
212  * @param cell cell
213  */
214  void getCell(nemId_t cellId, vtkGenericCell *cell) const {
215  _geoMesh.mesh->GetCell(cellId, cell);
216  }
217  /**
218  * Get cell.
219  * @param cellId cell id
220  * @return cell
221  */
222  vtkCell *getCell(nemId_t cellId) const {
223  return _geoMesh.mesh->GetCell(cellId);
224  }
225  /**
226  * Get cell bounds
227  * @param cellId cell id
228  * @param bounds array of bounds as (x_min,x_max, y_min,y_max, z_min,z_max)
229  */
230  void getCellBounds(nemId_t cellId, std::array<double, 6> *bounds) const {
231  _geoMesh.mesh->GetCellBounds(cellId, bounds->data());
232  }
233  /**
234  * Get cell bounds
235  * @param cellId cell id
236  * @return array of bounds as (x_min,x_max, y_min,y_max, z_min,z_max)
237  */
238  std::array<double, 6> getCellBounds(nemId_t cellId) const {
239  std::array<double, 6> bounds{};
240  getCellBounds(cellId, &bounds);
241  return bounds;
242  }
243  /**
244  * Get VTK cell type
245  * @param cellId cell id
246  * @return VTK cell type (see vtk documentation for specifics)
247  */
248  VTKCellType getCellType(nemId_t cellId) const {
249  return static_cast<VTKCellType>(_geoMesh.mesh->GetCellType(cellId));
250  }
251  /**
252  * Get list of point ids defining specified cell
253  * @param cellId cell id
254  * @param ptIds list of point ids
255  */
256  void getCellPoints(nemId_t cellId, vtkIdList *ptIds) const {
257  _geoMesh.mesh->GetCellPoints(cellId, ptIds);
258  }
259  /**
260  * Get list of cell ids using specified point
261  * @param ptId point id
262  * @param cellIds list of cell ids
263  */
264  void getPointCells(nemId_t ptId, vtkIdList *cellIds) const {
265  _geoMesh.mesh->GetPointCells(ptId, cellIds);
266  }
267  /**
268  * Get list of cells sharing points @p ptIds excluding @p cellId.
269  * @param cellId id of cell to exclude
270  * @param ptIds point id
271  * @param cellIds list of cell ids
272  */
273  void getCellNeighbors(nemId_t cellId, vtkIdList *ptIds,
274  vtkIdList *cellIds) const {
275  _geoMesh.mesh->GetCellNeighbors(cellId, ptIds, cellIds);
276  }
277  /**
278  * Get number of arrays in the point data.
279  * @return number of arrays in the point data
280  */
282  return _geoMesh.mesh->GetPointData()->GetNumberOfArrays();
283  }
284  /**
285  * Get copy of point data array by name. Optionally, get array index.
286  * @param arrayName array name
287  * @param array point data array
288  * @param arrayIdx array index
289  */
290  void getPointDataArrayCopy(const std::string &arrayName,
291  vtkAbstractArray *array,
292  int *arrayIdx = nullptr) const;
293  /**
294  * Create and return a copy of point data array by name. Optionally, get array
295  * index.
296  * @param arrayName array name
297  * @param arrayIdx array index
298  * @return pointer to copy of array
299  */
300  vtkSmartPointer<vtkAbstractArray> getPointDataArrayCopy(
301  const std::string &arrayName, int *arrayIdx = nullptr) const;
302  /**
303  * Get copy of point data array by index.
304  * @param arrayIdx array index
305  * @param array point data array
306  */
307  void getPointDataArrayCopy(int arrayIdx, vtkAbstractArray *array) const;
308  /**
309  * Create and return a copy of point data array by index.
310  * @param arrayIdx array index
311  * @return pointer to copy of array
312  */
313  vtkSmartPointer<vtkAbstractArray> getPointDataArrayCopy(int arrayIdx) const;
314  /**
315  * Get number of arrays in the cell data.
316  * @return number of arrays in the cell data
317  */
319  return _geoMesh.mesh->GetCellData()->GetNumberOfArrays();
320  }
321  /**
322  * Get copy of cell data array by name. Optionally, get array index.
323  * @param arrayName array name
324  * @param array cell data array
325  * @param arrayIdx array index
326  */
327  void getCellDataArrayCopy(const std::string &arrayName,
328  vtkAbstractArray *array,
329  int *arrayIdx = nullptr) const;
330  /**
331  * Create and return a copy of cell data array by name. Optionally, get array
332  * index.
333  * @param arrayName array name
334  * @param arrayIdx array index
335  * @return pointer to copy of array
336  */
337  vtkSmartPointer<vtkAbstractArray> getCellDataArrayCopy(
338  const std::string &arrayName, int *arrayIdx = nullptr) const;
339  /**
340  * Get copy of cell data array by index.
341  * @param arrayIdx array index
342  * @param array cell data array
343  */
344  void getCellDataArrayCopy(int arrayIdx, vtkAbstractArray *array) const;
345  /**
346  * Create and return a copy of cell data array by index.
347  * @param arrayIdx array index
348  * @return pointer to copy of array
349  */
350  vtkSmartPointer<vtkAbstractArray> getCellDataArrayCopy(int arrayIdx) const;
351  /**
352  * Get number of arrays in the field data.
353  * @return number of arrays in the field data
354  */
356  return _geoMesh.mesh->GetFieldData()->GetNumberOfArrays();
357  }
358  /**
359  * Get copy of field data array by name. Optionally, get array index.
360  * @param arrayName array name
361  * @param array field data array
362  * @param arrayIdx array index
363  */
364  void getFieldDataArrayCopy(const std::string &arrayName,
365  vtkAbstractArray *array,
366  int *arrayIdx = nullptr) const;
367  /**
368  * Create and return a copy of field data array by name. Optionally, get array
369  * index.
370  * @param arrayName array name
371  * @param arrayIdx array index
372  * @return pointer to copy of array
373  */
374  vtkSmartPointer<vtkAbstractArray> getFieldDataArrayCopy(
375  const std::string &arrayName, int *arrayIdx = nullptr) const;
376  /**
377  * Get copy of field data array by index.
378  * @param arrayIdx array index
379  * @param array field data array
380  */
381  void getFieldDataArrayCopy(int arrayIdx, vtkAbstractArray *array) const;
382  /**
383  * Create and return a copy of field data array by index.
384  * @param arrayIdx array index
385  * @return pointer to copy of array
386  */
387  vtkSmartPointer<vtkAbstractArray> getFieldDataArrayCopy(int arrayIdx) const;
388 
389  protected:
390  struct NEMOSYS_EXPORT SideSet {
391  SideSet(vtkPolyData *sideSet, vtkIntArray *geoEnt,
392  vtkIdTypeArray *origCell = nullptr, vtkIntArray *cellFace = nullptr,
393  vtkStringArray *setNames = nullptr);
394  SideSet() = default;
395  explicit SideSet(vtkPolyData *sides);
396  /**
397  * @brief Cells represent edges/faces of some GeoMesh.
398  */
399  vtkSmartPointer<vtkPolyData> sides{nullptr};
400 
401  vtkSmartPointer<vtkIntArray> getGeoEntArr() const;
402  void setGeoEntArr(vtkIntArray *arr);
403  vtkSmartPointer<vtkIdTypeArray> getOrigCellArr() const;
404  void setOrigCellArr(vtkIdTypeArray *arr);
405  vtkSmartPointer<vtkIntArray> getCellFaceArr() const;
406  void setCellFaceArr(vtkIntArray *arr);
407  vtkSmartPointer<vtkStringArray> getSideSetNames() const;
408  void setSideSetNamesArr(vtkStringArray *arr);
409 
410  private:
411  static constexpr auto GEO_ENT_NAME = "GeoEnt";
412  // Set to match dataSetRegionSurfaceFilter
413  static constexpr auto ORIG_CELL_NAME = "OrigCellIds";
414  static constexpr auto CELL_FACE_NAME = "CellFaceIds";
415  static constexpr auto NAME_ARR_NAME = "Side Set Names";
416  };
417 
418  struct NEMOSYS_EXPORT GeoMesh {
419  vtkSmartPointer<vtkUnstructuredGrid> mesh;
420  // name of gmsh model with geo
421  std::string geo;
422  // name of cell data array in mesh (and sideSet if sideSet not null) storing
423  // physical group (matching geo) for each cell
424  std::string link;
425  // boundaries of regions, represented by lower dimensional cells
427 
428  /**
429  * @brief For each edge/polygon in sideSet, find the corresponding mesh
430  * element in mesh.
431  * @details Does nothing if "OrigCellIds"/"CellFaceIds" arrays already
432  * present. Sets the sideSet's "OrigCellIds"/"CellFaceIds" arrays.
433  * Orientation of side only checked if multiple candidate original cells.
434  * Both "OrigCellIds" and "CellFaceIds" are set to -1 for any cells in the
435  * sideSet that can't be matched.
436  */
437  void findSide2OrigCell();
438  /**
439  * @brief Get dimension of mesh.
440  * @details All cells in mesh assumed to have same dimension.
441  * @return dimension of mesh
442  */
443  int getDimension() const;
444  };
445 
446  static constexpr auto GEO_ENT_DEFAULT_NAME = "GeoEnt";
447 
448  protected:
449  /**
450  * Construct geoMeshBase from a GeoMesh struct
451  * @param inGeoMesh a mesh, geo, link, and sideSet
452  */
453  explicit geoMeshBase(GeoMesh inGeoMesh);
454 
455  protected:
456  // virtual void update();
457 
458  // void addPoints();
459 
460  /**
461  * Set point data
462  * @param array array pointer
463  * @return array index
464  */
465  int setPointDataArray(vtkAbstractArray *array) {
466  return _geoMesh.mesh->GetPointData()->AddArray(array);
467  }
468  /**
469  * Set cell data
470  * @param array array pointer
471  * @return array index
472  */
473  int setCellDataArray(vtkAbstractArray *array) {
474  return _geoMesh.mesh->GetCellData()->AddArray(array);
475  }
476  /**
477  * Set field data
478  * @param array array pointer
479  * @return array index
480  */
481  int setFieldDataArray(vtkAbstractArray *array) {
482  return _geoMesh.mesh->GetFieldData()->AddArray(array);
483  }
484 
485  /**
486  * Remove point data array by index
487  * @param arrayIdx array index
488  */
489  void unsetPointDataArray(int arrayIdx) {
490  _geoMesh.mesh->GetPointData()->RemoveArray(arrayIdx);
491  }
492  /**
493  * Remove point data array by name
494  * @param arrayName array name
495  */
496  void unsetPointDataArray(const std::string &arrayName) {
497  _geoMesh.mesh->GetPointData()->RemoveArray(arrayName.c_str());
498  }
499  /**
500  * Remove cell data array by index
501  * @param arrayIdx array index
502  */
503  void unsetCellDataArray(int arrayIdx) {
504  _geoMesh.mesh->GetCellData()->RemoveArray(arrayIdx);
505  }
506  /**
507  * Remove cell data array by name
508  * @param arrayName array name
509  */
510  void unsetCellDataArray(const std::string &arrayName) {
511  _geoMesh.mesh->GetCellData()->RemoveArray(arrayName.c_str());
512  }
513  /**
514  * Remove field data array by index
515  * @param arrayIdx array index
516  */
517  void unsetFieldDataArray(int arrayIdx) {
518  _geoMesh.mesh->GetFieldData()->RemoveArray(arrayIdx);
519  }
520  /**
521  * Remove field data array by name
522  * @param arrayName array name
523  */
524  void unsetFieldDataArray(const std::string &arrayName) {
525  _geoMesh.mesh->GetFieldData()->RemoveArray(arrayName.c_str());
526  }
527 
528  protected:
529  /**
530  * Get the underlying geometry object.
531  * @note This is not a copy; Gmsh does not support cloning a model.
532  */
533  const GeoMesh &getGeoMesh() const { return _geoMesh; }
534  /**
535  * Set the underlying geometry object.
536  * @param geoMesh a mesh and geometry
537  */
538  void setGeoMesh(const geoMeshBase::GeoMesh &geoMesh) {
539  assert(geoMesh.mesh->GetNumberOfCells() == 0 ||
540  geoMesh.mesh->GetNumberOfPoints() == 0 ||
541  geoMesh.sideSet.sides == nullptr ||
542  geoMesh.sideSet.sides->GetPoints() == geoMesh.mesh->GetPoints());
543  _geoMesh = geoMesh;
544  }
545 
546  private:
547  virtual void resetNative() = 0;
548 
549  private:
551 
552  /// Dihedral angle threshold (in radians) to classify surfaces (Default: 30
553  /// degrees)
555 };
556 
557 } // namespace MSH
558 } // namespace NEM
559 
560 #endif // NEMOSYS_GEOMESHBASE_H_
VTKCellType getCellType(nemId_t cellId) const
Get VTK cell type.
Definition: geoMeshBase.H:248
virtual void report(std::ostream &out) const =0
Print a report about the mesh.
Definition: geoMeshBase.C:97
int getNumberOfCellDataArrays() const
Get number of arrays in the cell data.
Definition: geoMeshBase.H:318
void getPoint(nemId_t id, std::array< double, 3 > *x) const
Get the coordinate of a point.
Definition: geoMeshBase.H:196
int setPointDataArray(vtkAbstractArray *array)
Set point data.
Definition: geoMeshBase.H:465
void unsetFieldDataArray(int arrayIdx)
Remove field data array by index.
Definition: geoMeshBase.H:517
vtkSmartPointer< vtkUnstructuredGrid > mesh
Definition: geoMeshBase.H:419
void getCellNeighbors(nemId_t cellId, vtkIdList *ptIds, vtkIdList *cellIds) const
Get list of cells sharing points ptIds excluding cellId.
Definition: geoMeshBase.H:273
void unsetPointDataArray(const std::string &arrayName)
Remove point data array by name.
Definition: geoMeshBase.H:496
void unsetCellDataArray(const std::string &arrayName)
Remove cell data array by name.
Definition: geoMeshBase.H:510
nemId_t getNumberOfCells() const
Get the number of cells in mesh.
Definition: geoMeshBase.H:190
void setGeoMesh(const geoMeshBase::GeoMesh &geoMesh)
Set the underlying geometry object.
Definition: geoMeshBase.H:538
void getCellPoints(nemId_t cellId, vtkIdList *ptIds) const
Get list of point ids defining specified cell.
Definition: geoMeshBase.H:256
void unsetCellDataArray(int arrayIdx)
Remove cell data array by index.
Definition: geoMeshBase.H:503
vtkCell * getCell(nemId_t cellId) const
Get cell.
Definition: geoMeshBase.H:222
friend std::ostream & operator<<(std::ostream &os, const geoMeshBase &base)
Definition: geoMeshBase.H:129
std::array< double, 3 > getPoint(nemId_t id) const
Get the coordinate of a point.
Definition: geoMeshBase.H:204
double getAngleThreshold() const
Get the angle threshold used for surface classification.
Definition: geoMeshBase.H:171
std::array< double, 6 > getCellBounds(nemId_t cellId) const
Get cell bounds.
Definition: geoMeshBase.H:238
void getPointCells(nemId_t ptId, vtkIdList *cellIds) const
Get list of cell ids using specified point.
Definition: geoMeshBase.H:264
void unsetFieldDataArray(const std::string &arrayName)
Remove field data array by name.
Definition: geoMeshBase.H:524
vtkSmartPointer< vtkPolyData > sides
Cells represent edges/faces of some GeoMesh.
Definition: geoMeshBase.H:399
std::array< int, 2 > sides
nemId_t getNumberOfPoints() const
Get the number of points in mesh.
Definition: geoMeshBase.H:183
void setAngleThreshold(double angleThreshold)
Set the angle threshold used for surface classification.
Definition: geoMeshBase.H:176
const std::string & getGeoEntArrayName() const
Get the name of the geometric entities array.
Definition: geoMeshBase.H:157
management class for Gmsh interface
Definition: geoMeshBase.H:66
double _angleThreshold
Dihedral angle threshold (in radians) to classify surfaces (Default: 30 degrees)
Definition: geoMeshBase.H:554
int setCellDataArray(vtkAbstractArray *array)
Set cell data.
Definition: geoMeshBase.H:473
void setGeoEntArrayName(const std::string &geoEntArrayName)
Set the name of the geometric entities array.
Definition: geoMeshBase.H:162
void unsetPointDataArray(int arrayIdx)
Remove point data array by index.
Definition: geoMeshBase.H:489
std::int64_t nemId_t
Definition: geoMeshBase.H:56
static std::shared_ptr< GmshInterface > instance
Definition: geoMeshBase.H:91
int getNumberOfFieldDataArrays() const
Get number of arrays in the field data.
Definition: geoMeshBase.H:355
void getCellBounds(nemId_t cellId, std::array< double, 6 > *bounds) const
Get cell bounds.
Definition: geoMeshBase.H:230
abstract class to specify geometry and mesh data
Definition: geoMeshBase.H:102
int setFieldDataArray(vtkAbstractArray *array)
Set field data.
Definition: geoMeshBase.H:481
void getCell(nemId_t cellId, vtkGenericCell *cell) const
Get cell.
Definition: geoMeshBase.H:214
int getNumberOfPointDataArrays() const
Get number of arrays in the point data.
Definition: geoMeshBase.H:281
const GeoMesh & getGeoMesh() const
Get the underlying geometry object.
Definition: geoMeshBase.H:533