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.
diffMesh.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/diffMesh.H"
30 
31 #include <cmath>
32 
33 /*
34 #include <vtkCell.h>
35 #include <vtkPointData.h>
36 #include <vtkPoints.h>
37 #include <vtkSmartPointer.h>
38 */
39 
40 namespace NEM {
41 namespace MSH {
42 
43 bool is_close(double val1, double val2, double floor, double rel_tol) {
44  if (std::fabs(val1) <= floor && std::fabs(val2) <= floor) {
45  return true;
46  } else {
47  return std::fabs((val1 - val2) / val1) < rel_tol;
48  }
49 }
50 
51 int diffMesh(geoMeshBase *gmb1, geoMeshBase *gmb2, double floor, double relTol,
52  double numCellsTol, double numPointsTol) {
53  // Check if equal number of points and cells.
54  {
55  auto points1 = gmb1->getNumberOfPoints();
56  auto points2 = gmb2->getNumberOfPoints();
57  if (numPointsTol > 0) {
58  if (!is_close(points1, points2, 0, numPointsTol)) {
59  std::cerr << "Meshes don't have similar number of points: " << points1
60  << " vs " << points2 << std::endl;
61  return 1;
62  }
63  } else {
64  if (points1 != points2) {
65  std::cerr << "Meshes don't have same number of points: " << points1
66  << " vs " << points2 << std::endl;
67  return 1;
68  }
69  }
70  }
71  {
72  auto cells1 = gmb1->getNumberOfCells();
73  auto cells2 = gmb2->getNumberOfCells();
74  if (numCellsTol > 0) {
75  if (!is_close(cells1, cells2, 0, numCellsTol)) {
76  std::cerr << "Meshes don't have similar number of cells: " << cells1
77  << " vs " << cells2 << std::endl;
78  return 1;
79  }
80  } else {
81  if (cells1 != cells2) {
82  std::cerr << "Meshes don't have same number of cells: " << cells1
83  << " vs " << cells2 << std::endl;
84  return 1;
85  }
86  }
87  }
88 
89  if (numPointsTol <= 0) {
90  // Check if point coordinates match within tolerance
91  for (int i = 0; i < gmb1->getNumberOfPoints(); ++i) {
92  std::array<double, 3> coord1{};
93  std::array<double, 3> coord2{};
94  gmb1->getPoint(i, &coord1);
95  gmb2->getPoint(i, &coord2);
96  for (int j = 0; j < 3; ++j) {
97  if (!is_close(coord1[j], coord2[j], floor, relTol)) {
98  std::cerr << "Meshes differ in point coordinates" << std::endl;
99  std::cerr << "Index " << i << " Component " << j << std::endl;
100  std::cerr << "Coord 1 " << std::setprecision(15) << coord1[j]
101  << " Coord 2 " << std::setprecision(15) << coord2[j]
102  << std::endl;
103  std::cerr << "Meshes differ in point coordinates" << std::endl;
104  return 1;
105  }
106  }
107  }
108  }
109 
110  if (numCellsTol <= 0) {
111  for (int i = 0; i < gmb1->getNumberOfCells(); ++i) {
112  vtkSmartPointer<vtkPoints> points1 = gmb1->getCell(i)->GetPoints();
113  vtkSmartPointer<vtkPoints> points2 = gmb2->getCell(i)->GetPoints();
114 
115  if (points1->GetNumberOfPoints() != points2->GetNumberOfPoints()) {
116  std::cerr << "Meshes differ in cells" << std::endl;
117  return 1;
118  }
119 
120  for (int j = 0; j < points1->GetNumberOfPoints(); ++j) {
121  std::vector<double> coord1(3);
122  std::vector<double> coord2(3);
123  points1->GetPoint(j, coord1.data());
124  points2->GetPoint(j, coord2.data());
125  for (int k = 0; k < 3; ++k) {
126  if (!is_close(coord1[k], coord2[k], floor, relTol)) {
127  std::cerr << "Meshes differ in cells" << std::endl;
128  return 1;
129  }
130  }
131  }
132  }
133  }
134 
135  int numPointArr1 = gmb1->getNumberOfPointDataArrays();
136  int numPointArr2 = gmb2->getNumberOfPointDataArrays();
137 
138  if (numPointArr1 != numPointArr2) {
139  std::cerr << "Meshes have different numbers of point data" << std::endl;
140  std::cerr << "Mesh 1 has " << numPointArr1 << std::endl;
141  std::cerr << "Mesh 2 has " << numPointArr2 << std::endl;
142  return 1;
143  }
144 
145  for (int i = 0; i < numPointArr1; ++i) {
146  auto arr1 = gmb1->getPointDataArrayCopy(i);
147  auto arr2 = gmb2->getPointDataArrayCopy(arr1->GetName());
148  if (!arr2) {
149  std::cerr << "Mesh 2 does not have a point data array of name "
150  << arr1->GetName() << std::endl;
151  return 1;
152  }
153  /*
154  if (arr1->GetDataType() != arr2->GetDataType()) {
155  std::cerr << "For point data array " << arr1->GetName()
156  << ",\narrays do not have same data type:\n"
157  << arr1->GetDataTypeAsString() << " vs "
158  << arr2->GetDataTypeAsString() << std::endl;
159  return 1;
160  }
161  */
162  if (arr1->GetNumberOfComponents() != arr2->GetNumberOfComponents()) {
163  std::cerr << "For point data array " << arr1->GetName()
164  << ",\narrays do not have same number of components:\n"
165  << arr1->GetNumberOfComponents() << " vs "
166  << arr2->GetNumberOfComponents() << std::endl;
167  return 1;
168  }
169  if (numPointsTol <= 0) {
170  auto da1 = vtkDataArray::FastDownCast(arr1);
171  auto da2 = vtkDataArray::FastDownCast(arr2);
172  if (da1 && da2) {
173  int numComponents = da1->GetNumberOfComponents();
174  for (int j = 0; j < gmb1->getNumberOfPoints(); ++j) {
175  std::vector<double> comps1(numComponents);
176  std::vector<double> comps2(numComponents);
177  da1->GetTuple(j, comps1.data());
178  da2->GetTuple(j, comps2.data());
179  for (int k = 0; k < numComponents; ++k) {
180  if (!is_close(comps1[k], comps2[k], floor, relTol)) {
181  std::cerr << "For point data array " << da1->GetName()
182  << std::endl;
183  std::cerr << "Meshes differ in point data values at point " << j
184  << " component " << k << std::endl;
185  std::cerr << comps1[k] << " " << comps2[k] << std::endl;
186  return 1;
187  }
188  }
189  }
190  }
191  }
192  }
193 
194  int numCellArr1 = gmb1->getNumberOfCellDataArrays();
195  int numCellArr2 = gmb2->getNumberOfCellDataArrays();
196 
197  if (numCellArr1 != numCellArr2) {
198  std::cerr << "Meshes have different numbers of cell data" << std::endl;
199  std::cerr << "Mesh 1 has " << numCellArr1 << std::endl;
200  std::cerr << "Mesh 2 has " << numCellArr2 << std::endl;
201  return 1;
202  }
203 
204  for (int i = 0; i < numCellArr1; ++i) {
205  auto arr1 = gmb1->getCellDataArrayCopy(i);
206  if (arr1->GetName() == gmb1->getGeoEntArrayName()) {
207  continue;
208  }
209  auto arr2 = gmb2->getCellDataArrayCopy(arr1->GetName());
210  if (!arr2) {
211  std::cerr << "Mesh 2 does not have a cell data array of name "
212  << arr1->GetName() << std::endl;
213  return 1;
214  }
215  /*
216  if (arr1->GetDataType() != arr2->GetDataType()) {
217  std::cerr << "For cell data array " << arr1->GetName()
218  << ",\narrays do not have same data type:\n"
219  << arr1->GetDataTypeAsString() << " vs "
220  << arr2->GetDataTypeAsString() << std::endl;
221  return 1;
222  }
223  */
224  if (arr1->GetNumberOfComponents() != arr2->GetNumberOfComponents()) {
225  std::cerr << "For cell data array " << arr1->GetName()
226  << ",\narrays do not have same number of components:\n"
227  << arr1->GetNumberOfComponents() << " vs "
228  << arr2->GetNumberOfComponents() << std::endl;
229  return 1;
230  }
231  if (numCellsTol <= 0) {
232  auto da1 = vtkDataArray::FastDownCast(arr1);
233  auto da2 = vtkDataArray::FastDownCast(arr2);
234  if (da1 && da2) {
235  int numComponents = da1->GetNumberOfComponents();
236  for (int j = 0; j < gmb1->getNumberOfCells(); ++j) {
237  std::vector<double> comps1(numComponents);
238  std::vector<double> comps2(numComponents);
239  da1->GetTuple(j, comps1.data());
240  da2->GetTuple(j, comps2.data());
241  for (int k = 0; k < numComponents; ++k) {
242  if (!is_close(comps1[k], comps2[k], floor, relTol)) {
243  std::cerr << "For cell data array " << da1->GetName()
244  << std::endl;
245  std::cerr << "Meshes differ in cell data values at cell " << j
246  << " component " << k << std::endl;
247  std::cerr << comps1[k] << " " << comps2[k] << std::endl;
248  return 1;
249  }
250  }
251  }
252  }
253  }
254  }
255  std::cout << "Meshes are the same" << std::endl;
256  return 0;
257 }
258 
259 } // namespace MSH
260 } // namespace NEM
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
void getPointDataArrayCopy(const std::string &arrayName, vtkAbstractArray *array, int *arrayIdx=nullptr) const
Get copy of point data array by name.
Definition: geoMeshBase.C:159
nemId_t getNumberOfCells() const
Get the number of cells in mesh.
Definition: geoMeshBase.H:190
int diffMesh(geoMeshBase *gmb1, geoMeshBase *gmb2, double floor, double relTol, double numCellsTol, double numPointsTol)
Compare two geoMeshBase objects.
Definition: diffMesh.C:51
nemId_t getNumberOfPoints() const
Get the number of points in mesh.
Definition: geoMeshBase.H:183
const std::string & getGeoEntArrayName() const
Get the name of the geometric entities array.
Definition: geoMeshBase.H:157
bool is_close(double val1, double val2, double floor, double rel_tol)
Definition: diffMesh.C:43
void getCellDataArrayCopy(const std::string &arrayName, vtkAbstractArray *array, int *arrayIdx=nullptr) const
Get copy of cell data array by name.
Definition: geoMeshBase.C:180
abstract class to specify geometry and mesh data
Definition: geoMeshBase.H:102
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