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.
foamMesh.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 "Mesh/foamMesh.H"
30 
31 #include <iostream>
32 #include <string>
33 
34 #include <boost/filesystem.hpp>
35 
36 // openfoam headers
37 #include <cellModeller.H>
38 #include <fileName.H>
39 #include <foamVtkVtuAdaptor.H>
40 #include <fvMesh.H>
41 
42 // vtk
43 #include <vtkCellData.h>
44 #include <vtkCellIterator.h>
45 #include <vtkCellTypes.h>
46 #include <vtkDataSetSurfaceFilter.h>
47 #include <vtkExtractEdges.h>
48 #include <vtkGenericCell.h>
49 #include <vtkIdList.h>
50 #include <vtkPointData.h>
51 #include <vtkPoints.h>
52 #include <vtkTriangleFilter.h>
53 #include <vtkUnstructuredGrid.h>
54 
55 #include "AuxiliaryFunctions.H"
56 
57 namespace FOAM {
58 
59 //////////////////////////////////
60 // foamMesh class
61 //////////////////////////////////
62 
63 foamMesh::foamMesh(bool readDB) {
64  // initialize openfoam
65  int argc = 1;
66  char **argv = new char *[2];
67  argv[0] = new char[100];
68  strcpy(argv[0], "NONE");
69  _args = new Foam::argList(argc, argv);
70  Foam::Info << "Create time\n" << Foam::endl;
71  _runTime = new Foam::Time(Foam::Time::controlDictName, *_args);
72  Foam::argList::noParallel();
73 
74  // reading mesh database from current location
75  if (readDB) read("");
76 }
77 
78 foamMesh::foamMesh(std::shared_ptr<meshBase> fullMesh) {
79  _volMB = fullMesh;
81 }
82 
84  if (_args) {
85  delete _args;
86  _args = nullptr;
87  }
88  if (_runTime) {
89  delete _runTime;
90  _runTime = nullptr;
91  }
92  if (_fmesh) {
93  delete _fmesh;
94  _fmesh = nullptr;
95  }
96  std::cout << "foamMesh destroyed" << std::endl;
97 }
98 
99 void foamMesh::read(const std::string &fname) {
100  // openFOAM's mesh information is distributed through
101  // multiple files therefore fname is meaningless
102  // this implementation reads current working directory
103  // and finds mesh data files automatically if they exist
104  // TODO: Error out when information are not existing
105 
106  _fmesh = nullptr;
107 
108  // reading mesh database and converting
109  Foam::word regionName;
110  if (_args->readIfPresent("region", regionName)) {
111  Foam::Info << "Create mesh " << regionName
112  << " for time = " << _runTime->timeName() << Foam::nl
113  << Foam::endl;
114  } else {
115  if (fname == "domain1")
116  regionName = "domain1";
117  else if (fname == "domain0")
118  regionName = "domain0";
119  else if (fname == "domain2")
120  regionName = "domain2";
121  else if (fname == "domain100")
122  regionName = "domain100";
123  else {
124  regionName = Foam::fvMesh::defaultRegion;
125  Foam::Info << "Create mesh for time = " << _runTime->timeName()
126  << Foam::nl << Foam::endl;
127  }
128  }
129 
130  _fmesh = new Foam::fvMesh(Foam::IOobject(
131  regionName, _runTime->timeName(), *_runTime, Foam::IOobject::MUST_READ));
132 
133  genMshDB();
134 }
135 
137  // creating equivalent vtk topology from fvMesh
138  // by default polyhedral cells will be decomposed to
139  // tets and pyramids. Additional points will be added
140  // to underlying fvMesh.
141  std::cout << "Performing topological decomposition.\n";
142  auto objVfoam = Foam::vtk::vtuAdaptor();
143  dataSet = objVfoam.internal(*_fmesh);
144 
145  // Obtaining the mesh data and generating requested output file
146  numPoints = dataSet->GetNumberOfPoints();
147  numCells = dataSet->GetNumberOfCells();
148  std::cout << "Number of points " << numPoints << std::endl;
149  std::cout << "Number of cells " << numCells << std::endl;
150 }
151 
152 // get point with id
153 std::vector<double> foamMesh::getPoint(nemId_t id) const {
154  double coords[3];
155  dataSet->GetPoint(id, coords);
156  std::vector<double> result(coords, coords + 3);
157  return result;
158 }
159 
160 // get 3 vectors with x,y and z coords
161 std::vector<std::vector<double>> foamMesh::getVertCrds() const {
162  std::vector<std::vector<double>> comp_crds(3);
163  for (int i = 0; i < 3; ++i) { comp_crds[i].resize(numPoints); }
164  double coords[3];
165  for (int i = 0; i < numPoints; ++i) {
166  dataSet->GetPoint(i, coords);
167  comp_crds[0][i] = coords[0];
168  comp_crds[1][i] = coords[1];
169  comp_crds[2][i] = coords[2];
170  }
171  return comp_crds;
172 }
173 
174 // get cell with id : returns point indices and respective coordinates
175 std::map<nemId_t, std::vector<double>> foamMesh::getCell(nemId_t id) const {
176  if (id < numCells) {
177  std::map<nemId_t, std::vector<double>> cell;
178  vtkSmartPointer<vtkIdList> point_ids = vtkSmartPointer<vtkIdList>::New();
179  point_ids = dataSet->GetCell(id)->GetPointIds();
180  vtkIdType num_ids = point_ids->GetNumberOfIds();
181  for (vtkIdType i = 0; i < num_ids; ++i) {
182  nemId_t pntId = point_ids->GetId(i);
183  std::vector<double> coord = getPoint(pntId);
184  cell.insert(std::pair<nemId_t, std::vector<double>>(pntId, coord));
185  }
186 
187  return cell;
188  } else {
189  std::cerr << "Cell ID is out of range!" << std::endl;
190  exit(1);
191  }
192 }
193 
194 std::vector<std::vector<double>> foamMesh::getCellVec(nemId_t id) const {
195  if (id < numCells) {
196  std::vector<std::vector<double>> cell;
197  vtkSmartPointer<vtkIdList> point_ids = vtkSmartPointer<vtkIdList>::New();
198  point_ids = dataSet->GetCell(id)->GetPointIds();
199  vtkIdType num_ids = point_ids->GetNumberOfIds();
200  cell.resize(num_ids);
201  for (vtkIdType i = 0; i < num_ids; ++i) {
202  nemId_t pntId = point_ids->GetId(i);
203  cell[i] = getPoint(pntId);
204  }
205  return cell;
206  } else {
207  std::cerr << "Cell ID is out of range!" << std::endl;
208  exit(1);
209  }
210 }
211 
212 void foamMesh::inspectEdges(const std::string &ofname) const {
213  std::ofstream outputStream(ofname);
214  if (!outputStream.good()) {
215  std::cerr << "error opening " << ofname << std::endl;
216  exit(1);
217  }
218 
219  vtkSmartPointer<vtkExtractEdges> extractEdges =
221  extractEdges->SetInputData(dataSet);
222  extractEdges->Update();
223 
224  vtkSmartPointer<vtkGenericCell> genCell =
226  for (int i = 0; i < extractEdges->GetOutput()->GetNumberOfCells(); ++i) {
227  extractEdges->GetOutput()->GetCell(i, genCell);
228  vtkPoints *points = genCell->GetPoints();
229  double p1[3], p2[3];
230  points->GetPoint(0, p1);
231  points->GetPoint(1, p2);
232  double len = std::sqrt(pow(p1[0] - p2[0], 2) + pow(p1[1] - p2[1], 2) +
233  pow(p1[2] - p2[2], 2));
234  outputStream << len << std::endl;
235  }
236 }
237 
238 std::vector<nemId_t> foamMesh::getConnectivities() const {
239  std::vector<nemId_t> connectivities;
240  vtkSmartPointer<vtkCellIterator> it =
241  vtkSmartPointer<vtkCellIterator>::Take(dataSet->NewCellIterator());
242  for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextCell()) {
243  vtkSmartPointer<vtkIdList> pointIds = it->GetPointIds();
244  for (vtkIdType i = 0; i < pointIds->GetNumberOfIds(); ++i) {
245  connectivities.push_back(pointIds->GetId(i));
246  }
247  }
248  return connectivities;
249 }
250 
251 void foamMesh::report() const {
252  if (!dataSet) {
253  std::cout << "dataSet has not been populated!" << std::endl;
254  exit(1);
255  }
256 
257  using CellContainer = std::map<int, int>;
258  // Generate a report
259  std::cout << "Processing the dataset generated from " << filename << std::endl
260  << " dataSet contains a " << dataSet->GetClassName() << " that has "
261  << numCells << " cells"
262  << " and " << numPoints << " points." << std::endl;
263 
264  CellContainer cellMap;
265  for (int i = 0; i < numCells; i++) { cellMap[dataSet->GetCellType(i)]++; }
266 
267  CellContainer::const_iterator it = cellMap.begin();
268  while (it != cellMap.end()) {
269  std::cout << "\tCell type "
270  << vtkCellTypes::GetClassNameFromTypeId(it->first) << " occurs "
271  << it->second << " times." << std::endl;
272  ++it;
273  }
274 
275  // Now check for point data
276  vtkPointData *pd = dataSet->GetPointData();
277  if (pd) {
278  std::cout << " contains point data with " << pd->GetNumberOfArrays()
279  << " arrays." << std::endl;
280  for (int i = 0; i < pd->GetNumberOfArrays(); i++) {
281  std::cout << "\tArray " << i << " is named "
282  << (pd->GetArrayName(i) ? pd->GetArrayName(i) : "NULL");
283  vtkDataArray *da = pd->GetArray(i);
284  std::cout << " with " << da->GetNumberOfTuples() << " values. "
285  << std::endl;
286  }
287  }
288  // Now check for cell data
289  vtkCellData *cd = dataSet->GetCellData();
290  if (cd) {
291  std::cout << " contains cell data with " << cd->GetNumberOfArrays()
292  << " arrays." << std::endl;
293  for (int i = 0; i < cd->GetNumberOfArrays(); i++) {
294  std::cout << "\tArray " << i << " is named "
295  << (cd->GetArrayName(i) ? cd->GetArrayName(i) : "NULL");
296  vtkDataArray *da = cd->GetArray(i);
297  std::cout << " with " << da->GetNumberOfTuples() << " values. "
298  << std::endl;
299  }
300  }
301  // Now check for field data
302  if (dataSet->GetFieldData()) {
303  std::cout << " contains field data with "
304  << dataSet->GetFieldData()->GetNumberOfArrays() << " arrays."
305  << std::endl;
306  for (int i = 0; i < dataSet->GetFieldData()->GetNumberOfArrays(); i++) {
307  std::cout << "\tArray " << i << " is named "
308  << dataSet->GetFieldData()->GetArray(i)->GetName();
309  vtkDataArray *da = dataSet->GetFieldData()->GetArray(i);
310  std::cout << " with " << da->GetNumberOfTuples() << " values. "
311  << std::endl;
312  }
313  }
314 }
315 
316 // get diameter of circumsphere of each cell
317 std::vector<double> foamMesh::getCellLengths() const {
318  std::vector<double> result;
319  result.resize(getNumberOfCells());
320  for (nemId_t i = 0; i < getNumberOfCells(); ++i) {
321  result[i] = std::sqrt(dataSet->GetCell(i)->GetLength2());
322  }
323  return result;
324 }
325 
326 // get center of a cell
327 std::vector<double> foamMesh::getCellCenter(nemId_t cellID) const {
328  std::vector<double> center(3, 0.0);
329  std::vector<std::vector<double>> cell = getCellVec(cellID);
330 
331  using nemAux::operator*; // for vector multiplication.
332  using nemAux::operator+; // for vector addition.
333  for (int i = 0; i < cell.size(); ++i) { center = center + cell[i]; }
334  return (1. / cell.size()) * center;
335 }
336 
337 // returns the cell type
338 int foamMesh::getCellType() const { return dataSet->GetCellType(0); }
339 
340 vtkSmartPointer<vtkDataSet> foamMesh::extractSurface() {
341  // extract surface polygons
342  vtkSmartPointer<vtkDataSetSurfaceFilter> surfFilt =
344  surfFilt->SetInputData(dataSet);
345  surfFilt->Update();
346 
347  // triangulate the surface
348  vtkSmartPointer<vtkTriangleFilter> triFilt =
350  triFilt->SetInputData(surfFilt->GetOutput());
351  triFilt->Update();
352 
353  return triFilt->GetOutput();
354 }
355 
356 // Created foam dictionaries for VTK->FOAM conversion
358  // fvSchemesDict
359 
360  // creating a base system directory
361  const char dir_path[] = "./system";
362  boost::filesystem::path dir(dir_path);
363  try {
364  boost::filesystem::create_directory(dir);
365  } catch (boost::filesystem::filesystem_error &e) {
366  std::cerr << "Problem in creating system directory for the cfMesh"
367  << "\n";
368  std::cerr << e.what() << std::endl;
369  throw;
370  }
371 
372  std::ofstream contDict;
373  contDict.open(std::string(dir_path) + "/fvSchemes");
374  std::string contText =
375  "\
376 /*--------------------------------*- C++ -*----------------------------------*\n\
377 | ========= | |\n\
378 | \\\\ / F ield | NEMoSys: Mesh Conversion interface |\n\
379 | \\\\ / O peration | |\n\
380 | \\\\ / A nd | |\n\
381 | \\\\/ M anipulation | |\n\
382 \\*---------------------------------------------------------------------------*/\n\
383 \n\
384 FoamFile\n\
385 {\n\
386  version 2.0;\n\
387  format ascii;\n\
388  class dictionary;\n\
389  object fvSchemes;\n\
390 }\n\n\
391 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n\n\
392 gradSchemes\n\
393 {\n\
394  default Gauss linear;\n\
395  grad(p) Gauss linear;\n\
396 }\n\
397 \n\
398 divSchemes\n\
399 {\n\
400  default none;\n\
401  div(phi,U) Gauss linear;\n\
402 }\n\
403 \n\
404 laplacianSchemes\n\
405 {\n\
406  default none;\n\
407  laplacian(nu,U) Gauss linear corrected;\n\
408  laplacian((1|A(U)),p) Gauss linear corrected;\n\
409 }\n\
410 // ************************************************************************* //";
411  contDict << contText;
412  contDict.close();
413 
414  // fvSolutionDict
415 
416  std::ofstream contDict2;
417  contDict2.open(std::string(dir_path) + "/fvSolution");
418  std::string contText2 =
419  "\
420 /*--------------------------------*- C++ -*----------------------------------*\n\
421 | ========= | |\n\
422 | \\\\ / F ield | NEMoSys: Mesh Conversion interface |\n\
423 | \\\\ / O peration | |\n\
424 | \\\\ / A nd | |\n\
425 | \\\\/ M anipulation | |\n\
426 \\*---------------------------------------------------------------------------*/\n\
427 \n\
428 FoamFile\n\
429 {\n\
430  version 2.0;\n\
431  format ascii;\n\
432  class dictionary;\n\
433  object fvSolution;\n\
434 }\n\n\
435 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n\n\
436 \n\
437 // ************************************************************************* //";
438  contDict2 << contText2;
439  contDict2.close();
440 
441  // ControlDict
442 
443  std::ofstream contDict3;
444  contDict3.open(std::string(dir_path) + "/controlDict");
445  std::string contText3 =
446  "\
447 /*--------------------------------*- C++ -*----------------------------------*\n\
448 | ========= | |\n\
449 | \\\\ / F ield | NEMoSys: Mesh Conversion interface |\n\
450 | \\\\ / O peration | |\n\
451 | \\\\ / A nd | |\n\
452 | \\\\/ M anipulation | |\n\
453 \\*---------------------------------------------------------------------------*/\n\
454 \n\
455 FoamFile\n\
456 {\n\
457  version 2.0;\n\
458  format ascii;\n\
459  class dictionary;\n\
460  location \"system\";\n\
461  object controlDict;\n\
462 }\n\n\
463 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n\n\
464 deltaT 1;\n\n\
465 startTime 0;\n\n\
466 writeInterval 1;\n\n\
467 // ************************************************************************* //";
468  contDict3 << contText3;
469  contDict3.close();
470 }
471 
472 // write the mesh to file named fname
473 void foamMesh::write(const std::string &fname) const {
474  int argc = 1;
475  char **argv = new char *[2];
476  argv[0] = new char[100];
477  strcpy(argv[0], "NONE");
478  Foam::argList args(argc, argv);
479  Foam::Info << "Create time\n" << Foam::endl;
480  Foam::argList::noParallel();
481 
482  Foam::Time runTime(Foam::Time::controlDictName, Foam::fileName("."),
483  Foam::fileName("."));
484 
485  // Fetches VTK dataset from VTU/VTK files
486  vtkSmartPointer<vtkDataSet> vtkDS = _volMB->getDataSet();
487 
488  int numPoints = vtkDS->GetNumberOfPoints();
489  int numCells = vtkDS->GetNumberOfCells();
490 
491  // Gets all point numbers and coordinates
492  std::vector<std::vector<double>> verticeZZ;
493  verticeZZ.resize(numPoints);
494  for (int ipt = 0; ipt < numPoints; ipt++) {
495  std::vector<double> getPt = std::vector<double>(3);
496  vtkDS->GetPoint(ipt, &getPt[0]);
497  verticeZZ[ipt].resize(3);
498  verticeZZ[ipt][0] = getPt[0];
499  verticeZZ[ipt][1] = getPt[1];
500  verticeZZ[ipt][2] = getPt[2];
501  }
502 
503  // Gets Ids for cells
504  std::vector<std::vector<int>> cellIdZZ;
505  cellIdZZ.resize(numCells);
506 
507  // Foam point data container
508  Foam::pointField pointData(numPoints);
509 
510  // Gets celltypes for all cells in mesh
511  std::vector<int> typeCell;
512  typeCell.resize(numCells);
513 
514  // Foam cell data container
515  Foam::cellShapeList cellShapeData(numCells);
516 
517  for (int i = 0; i < numPoints; i++) {
518  pointData[i] =
519  Foam::vector(verticeZZ[i][0], verticeZZ[i][1], verticeZZ[i][2]);
520  }
521 
522  for (int i = 0; i < numCells; i++) {
523  vtkIdList *ptIds = vtkIdList::New();
524  vtkDS->GetCellPoints(i, ptIds);
525  int numIds = ptIds->GetNumberOfIds();
526  cellIdZZ[i].resize(numIds);
527  for (int j = 0; j < numIds; j++) { cellIdZZ[i][j] = ptIds->GetId(j); }
528 
529  Foam::labelList meshPoints(numIds);
530 
531  for (int k = 0; k < numIds; k++) { meshPoints[k] = cellIdZZ[i][k]; }
532 
533  typeCell[i] = vtkDS->GetCellType(i);
534 
535  if (typeCell[i] == 12) {
536  cellShapeData[i] = Foam::cellShape("hex", meshPoints, true);
537  } else if (typeCell[i] == 14) {
538  cellShapeData[i] = Foam::cellShape("pyr", meshPoints, true);
539  } else if (typeCell[i] == 10) {
540  cellShapeData[i] = Foam::cellShape("tet", meshPoints, true);
541  } else {
542  std::cerr << "Only Hexahedral, Tetrahedral,"
543  << " and Pyramid cells are supported for VTK->FOAM!"
544  << std::endl;
545  throw;
546  }
547  }
548 
549  Foam::polyMesh mesh(Foam::IOobject(Foam::polyMesh::defaultRegion,
550  runTime.constant(), runTime),
551  std::move(pointData), // Vertices
552  cellShapeData, // Cell shape and points
553  Foam::faceListList(), // Boundary faces
554  Foam::wordList(), // Boundary Patch Names
555  Foam::wordList(), // Boundary Patch Type
556  "defaultPatch", // Default Patch Name
557  Foam::polyPatch::typeName, // Default Patch Type
558  Foam::wordList() // Boundary Patch Physical Type
559  );
560  // ****************************************************************** //
561 
562  std::cout << "Writing mesh for time 0" << std::endl;
563 
564  mesh.write();
565 }
566 
567 void foamMesh::readAMR(const Foam::Time &runTime) {
568  _fmesh = new Foam::fvMesh(Foam::IOobject(Foam::fvMesh::defaultRegion,
569  runTime.timeName(), runTime,
570  Foam::IOobject::MUST_READ));
571 
572  genMshDB();
573 }
574 
575 } // namespace FOAM
nemId_t numPoints
number of points in mesh
Definition: meshBase.H:714
void inspectEdges(const std::string &ofname) const override
get edge lengths of dataSet
Definition: foamMesh.C:212
Foam::Time * _runTime
Definition: foamMesh.H:181
Foam::argList * _args
Definition: foamMesh.H:180
vtkSmartPointer< vtkDataSet > dataSet
mesh points, topology and data
Definition: meshBase.H:722
std::map< nemId_t, std::vector< double > > getCell(nemId_t id) const override
get cell with id : returns point indices and respective coordinates
Definition: foamMesh.C:175
std::shared_ptr< meshBase > _volMB
Shared meshBase pointer for foamMesh constructor and some methods.
Definition: foamMesh.H:188
~foamMesh() override
foamMesh standard destructor
Definition: foamMesh.C:83
void read(const std::string &fname) override
general purpose mesh information read method
Definition: foamMesh.C:99
std::size_t nemId_t
Definition: meshBase.H:51
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
void readAMR(const Foam::Time &runTime)
Reads fvMesh for adaptive mesh refinement process.
Definition: foamMesh.C:567
Foam::fvMesh * _fmesh
Definition: foamMesh.H:182
std::vector< double > getPoint(nemId_t id) const override
get point with id
Definition: foamMesh.C:153
nemId_t numCells
number of cells in mesh
Definition: meshBase.H:718
void genMshDB()
Return a polyMesh Object.
Definition: foamMesh.C:136
std::vector< std::vector< double > > getVertCrds() const override
get 3 vecs with x,y and z coords
Definition: foamMesh.C:161
std::vector< std::vector< double > > getCellVec(nemId_t id) const override
get cell points ids and their coordinates
Definition: foamMesh.C:194
virtual void write() const
write the mesh to file named after the private var &#39;filename&#39;.
Definition: meshBase.H:598
std::shared_ptr< meshBase > mesh
int getCellType() const override
get cell type as an integer.
Definition: foamMesh.C:338
std::vector< vtkIdType > points
points given by id in .inp file
Definition: inpGeoMesh.C:133
foamMesh(bool readDB=false)
foamMesh default constructor.
Definition: foamMesh.C:63
std::vector< double > getCellLengths() const override
get diameter of circumsphere of each cell
Definition: foamMesh.C:317
void createFoamDicts()
Created necessary dictionaries for OpenFOAM runtime environment.
Definition: foamMesh.C:357
std::string filename
name of mesh file
Definition: meshBase.H:726
std::vector< double > getCellCenter(nemId_t cellID) const override
get center of a cell
Definition: foamMesh.C:327
vtkSmartPointer< vtkDataSet > extractSurface() override
Extracts foam mesh surface using VTK data set.
Definition: foamMesh.C:340
nemId_t getNumberOfCells() const
return the number of cells
Definition: meshBase.H:550
std::vector< nemId_t > getConnectivities() const override
get vtk cell connectivities in terms of point ids
Definition: foamMesh.C:238
Definition: foamMesh.C:57
void report() const override
generate a report of the mesh
Definition: foamMesh.C:251