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.
MeshQuality.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 <vtkCell.h>
30 #include <vtkCellData.h>
31 #include <vtkCellType.h>
32 #include <vtkFieldData.h>
33 #include "AuxiliaryFunctions.H"
35 
36 #ifdef HAVE_CFMSH
37 // openfoam headers
38 # include <argList.H>
39 # include <fvMesh.H>
40 
41 // cfmesh headers
42 # include <meshOptimizer.H>
43 # include <polyMeshGenModifier.H>
44 #endif
45 
46 MeshQuality::MeshQuality(const meshBase *_mesh) : mesh(_mesh) {
48  qualityFilter->SetInputData(mesh->getDataSet());
49  qualityFilter->SetTriangleQualityMeasureToShape();
50  qualityFilter->SetTetQualityMeasureToShape();
51  qualityFilter->SetQuadQualityMeasureToShape();
52  qualityFilter->SetHexQualityMeasureToShape();
53  qualityFilter->Update();
54 }
55 
57  // mesh->unsetCellDataArray("Quality");
58  // mesh->unsetFieldDataArray("Mesh Triangle Quality");
59  // mesh->unsetFieldDataArray("Mesh Quadrilateral Quality");
60  // mesh->unsetFieldDataArray("Mesh Tetrahedron Quality");
61  // mesh->unsetFieldDataArray("Mesh Hexahedron Quality");
62 }
63 
64 void MeshQuality::checkMesh(std::ostream &outputStream) {
65  outputStream << "------------- Shape Quality Statistics -------------\n\n";
66  outputStream << "Cell Type" << std::setw(16) << "Num Cells" << std::setw(16)
67  << "Minimum" << std::setw(16) << "Maximum" << std::setw(16)
68  << "Average" << std::setw(16) << "Variance" << std::endl;
69 
70  for (int i = 0; i < 4; ++i) {
71  if (i == 0)
72  outputStream << "Tri" << std::setw(16);
73  else if (i == 1)
74  outputStream << "Quad" << std::setw(15);
75  else if (i == 2)
76  outputStream << "Tet" << std::setw(16);
77  else
78  outputStream << "Hex" << std::setw(16);
79 
80  vtkSmartPointer<vtkDoubleArray> qualityField = getStats(i);
81  double *val = qualityField->GetTuple(0);
82 
83  outputStream << std::right << val[4] << std::setw(16) << std::right
84  << val[0] << std::setw(16) << std::right << val[2]
85  << std::setw(16) << std::right << val[1] << std::setw(16)
86  << std::right << val[3] << std::endl;
87  }
88 
89  outputStream << "\n------------- Detailed Statistics ------------------\n"
90  << std::endl;
91 
92  vtkSmartPointer<vtkDoubleArray> qualityArray = vtkDoubleArray::SafeDownCast(
93  qualityFilter->GetOutput()->GetCellData()->GetArray("Quality"));
94 
95  mesh->getDataSet()->GetCellData()->AddArray(qualityArray);
96  std::string qfn = nemAux::trim_fname(mesh->getFileName(), "") + "-qal.vtu";
97  mesh->write(qfn);
98 
99  // writing to file
100  outputStream << "Type" << std::setw(10) << "Quality\n" << std::endl;
101  for (int i = 0; i < mesh->getNumberOfCells(); ++i) {
102  int cellType = mesh->getDataSet()->GetCell(i)->GetCellType();
103  double val = qualityArray->GetValue(i);
104  switch (cellType) {
105  case VTK_TRIANGLE: {
106  outputStream << "TRI\t" << std::right << setw(10) << val << "\n";
107  break;
108  }
109  case VTK_TETRA: {
110  outputStream << "TET\t" << std::right << setw(10) << val << "\n";
111  break;
112  }
113  case VTK_QUAD: {
114  outputStream << "QUAD\t" << std::right << setw(10) << val << "\n";
115  break;
116  }
117  case VTK_HEXAHEDRON: {
118  outputStream << "HEX\t" << std::right << setw(10) << val << "\n";
119  break;
120  }
121  default: {
122  std::cerr
123  << "Invalid cell type. Only tri, quad, tet, and hex supported."
124  << std::endl;
125  exit(1);
126  }
127  }
128  }
129 }
130 
131 void MeshQuality::checkMesh() { checkMesh(std::cout); }
132 
133 void MeshQuality::checkMesh(const std::string &fname) {
134  std::ofstream outputStream(fname);
135  if (!outputStream.good()) {
136  std::cerr << "Error opening file " << fname << std::endl;
137  exit(1);
138  }
139  checkMesh(outputStream);
140 }
141 
142 vtkSmartPointer<vtkDoubleArray> MeshQuality::getStats(int n) {
143  vtkSmartPointer<vtkDoubleArray> qualityField =
145  switch (n) {
146  case 0: {
147  qualityField = vtkDoubleArray::SafeDownCast(
148  qualityFilter->GetOutput()->GetFieldData()->GetArray(
149  "Mesh Triangle Quality"));
150  break;
151  }
152  case 1: {
153  qualityField = vtkDoubleArray::SafeDownCast(
154  qualityFilter->GetOutput()->GetFieldData()->GetArray(
155  "Mesh Quadrilateral Quality"));
156  break;
157  }
158  case 2: {
159  qualityField = vtkDoubleArray::SafeDownCast(
160  qualityFilter->GetOutput()->GetFieldData()->GetArray(
161  "Mesh Tetrahedron Quality"));
162  break;
163  }
164  case 3: {
165  qualityField = vtkDoubleArray::SafeDownCast(
166  qualityFilter->GetOutput()->GetFieldData()->GetArray(
167  "Mesh Hexahedron Quality"));
168  break;
169  }
170  default: {
171  std::cerr << "Invalid cell type. Only tri, quad, tet, and hex supported."
172  << std::endl;
173  exit(1);
174  }
175  }
176  return qualityField;
177 }
178 
180 #ifdef HAVE_CFMSH
181  // initialize openfoam
182  //#include "setRootCase.H"
183  int argc = 1;
184  char **argv = new char *[2];
185  argv[0] = new char[100];
186  strcpy(argv[0], "NONE");
187  Foam::argList args(argc, argv);
188  //#include "createTime.H"
189  Foam::Info << "Create time\n" << Foam::endl;
190  Foam::Time runTime(Foam::Time::controlDictName, args);
191  //- 2d cartesian mesher cannot be run in parallel
192  Foam::argList::noParallel();
193 
194  //- load the mesh from disk
195  Foam::Module::polyMeshGen pmg(runTime);
196  pmg.read();
197 
198  //- construct the smoother
199  Foam::Module::meshOptimizer mOpt(pmg);
200 
201  if (_cfmQPrms->consCellSet.has_value()) {
202  const std::string &constrainedCellSet = _cfmQPrms->consCellSet.value();
203 
204  //- lock cells in constrainedCellSet
205  mOpt.lockCellsInSubset(constrainedCellSet);
206 
207  //- find boundary faces which shall be locked
208  Foam::Module::labelLongList lockedBndFaces, selectedCells;
209 
210  const Foam::label sId = pmg.cellSubsetIndex(constrainedCellSet);
211  pmg.cellsInSubset(sId, selectedCells);
212 
213  Foam::boolList activeCell(pmg.cells().size(), false);
214  forAll (selectedCells, i)
215  activeCell[selectedCells[i]] = true;
216  }
217 
218  //- clear geometry information before volume smoothing
219  pmg.clearAddressingData();
220 
221  //- perform optimisation using the laplace smoother and
222  mOpt.optimizeMeshFV(_cfmQPrms->nLoops, _cfmQPrms->nLoops,
224 
225  //- perform optimisation of worst quality faces
226  mOpt.optimizeMeshFVBestQuality(_cfmQPrms->nLoops, _cfmQPrms->qualThrsh);
227 
228  //- check the mesh again and untangl bad regions if any of them exist
229  mOpt.untangleMeshFV(_cfmQPrms->nLoops, _cfmQPrms->nIterations,
230  _cfmQPrms->nSrfItr);
231  Foam::Info << "Writing mesh" << Foam::endl;
232  pmg.write();
233 
234  delete[] argv;
235  Foam::Info << "Finished mesh quality enhancement task." << Foam::endl;
236 #else
237  std::cerr << "Compile with CFMSH option enabled to use this feature."
238  << std::endl;
239 #endif
240 }
const cfmeshQualityParams * _cfmQPrms
Definition: MeshQuality.H:72
MeshQuality()=default
A brief description of meshBase.
Definition: meshBase.H:64
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
std::string trim_fname(const std::string &name, const std::string &ext)
vtkSmartPointer< vtkDataSet > getDataSet() const
get this meshes&#39; dataSet
Definition: meshBase.H:308
const std::string & getFileName() const
get the current file name
Definition: meshBase.H:680
void checkMesh()
Definition: MeshQuality.C:131
virtual void write() const
write the mesh to file named after the private var &#39;filename&#39;.
Definition: meshBase.H:598
VTKCellType cellType
Definition: inpGeoMesh.C:129
std::shared_ptr< meshBase > mesh
jsoncons::optional< std::string > consCellSet
vtkSmartPointer< vtkDoubleArray > getStats(int n)
Definition: MeshQuality.C:142
vtkSmartPointer< vtkMeshQuality > qualityFilter
Definition: MeshQuality.H:70
nemId_t getNumberOfCells() const
return the number of cells
Definition: meshBase.H:550
const meshBase * mesh
Definition: MeshQuality.H:69
void cfmOptimize()
Definition: MeshQuality.C:179