1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2 // other Axom Project Developers. See the top-level LICENSE file for details.
3 //
4 // SPDX-License-Identifier: (BSD-3-Clause)
5 #ifndef MINT_STRUCTURED_MESH_TEST_HELPERS_HPP_
6 #define MINT_STRUCTURED_MESH_TEST_HELPERS_HPP_
7
8 #include "axom/mint/config.hpp" // for compile-time definitions
9
10 #include "axom/mint/mesh/blueprint.hpp" // for blueprint functions
11 #include "axom/mint/mesh/CellTypes.hpp" // for CellTypes enum definition
12 #include "axom/mint/mesh/UniformMesh.hpp" // for UniformMesh
13 #include "axom/mint/mesh/StructuredMesh.hpp" // for StructuredMesh
14
15 #include "axom/slic/interface/slic.hpp" // for slic macros
16
17 #include "gtest/gtest.h" // for gtest macros
18
19 /*!
20 * \file StructuredMesh_helpers.hpp
21 * The functions declared in this header file test the methods of the
22 * StructuredMesh class and are used in mint_mesh_uniform_mesh.cpp,
23 * mint_mesh_rectilinear_mesh.cpp, and mint_mesh_curvilinear_mesh.cpp.
24 */
25
26 namespace axom
27 {
28 namespace mint
29 {
30 namespace internal
31 {
32 constexpr double PI = 3.14;
33
34 namespace
35 {
36 /*!
37 * \brief Compare the values of two arrays.
38 *
39 * \param [in] p1 the first pointer to compare.
40 * \param [in] p2 the second pointer to compare.
41 * \param [in] n the number of elements to compare.
42 */
43 template <typename T>
compare_pointers(const T * p1,const T * p2,IndexType n)44 void compare_pointers(const T* p1, const T* p2, IndexType n)
45 {
46 for(IndexType i = 0; i < n; ++i)
47 {
48 EXPECT_EQ(p1[i], p2[i]);
49 }
50 }
51
52 /*!
53 * \brief Check the indexing methods of a 2D StructuredMesh.
54 *
55 * \param [in] m the mesh to check.
56 */
check_indexing2D(const StructuredMesh * m)57 inline void check_indexing2D(const StructuredMesh* m)
58 {
59 SLIC_ASSERT(m != nullptr);
60 SLIC_ASSERT(m->getDimension() == 2);
61
62 /* Check getNode Linear/Grid Index */
63 IndexType idx = 0;
64 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
65 {
66 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
67 {
68 const IndexType nodeID = m->getNodeLinearIndex(i, j);
69 EXPECT_EQ(nodeID, idx++);
70
71 IndexType ii, jj, kk;
72 m->getNodeGridIndex(nodeID, ii, jj);
73 EXPECT_EQ(i, ii);
74 EXPECT_EQ(j, jj);
75
76 m->getNodeGridIndex(nodeID, ii, jj, kk);
77 EXPECT_EQ(i, ii);
78 EXPECT_EQ(j, jj);
79 EXPECT_EQ(0, kk);
80 }
81 }
82
83 /* Check getCell Linear/Grid Index */
84 idx = 0;
85 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
86 {
87 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
88 {
89 const IndexType cellID = m->getCellLinearIndex(i, j);
90 EXPECT_EQ(cellID, idx++);
91
92 IndexType ii, jj, kk;
93 m->getCellGridIndex(cellID, ii, jj);
94 EXPECT_EQ(i, ii);
95 EXPECT_EQ(j, jj);
96
97 m->getCellGridIndex(cellID, ii, jj, kk);
98 EXPECT_EQ(i, ii);
99 EXPECT_EQ(j, jj);
100 EXPECT_EQ(0, kk);
101 }
102 }
103
104 /* Check the getIFace Linear/Grid Index. */
105 idx = 0;
106 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
107 {
108 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
109 {
110 const IndexType faceID = m->getIFaceLinearIndex(i, j);
111 const IndexType faceID2 = m->getFaceLinearIndex(I_DIRECTION, i, j);
112 EXPECT_EQ(faceID, idx++);
113 EXPECT_EQ(faceID, faceID2);
114
115 IndexType ii, jj, kk;
116 m->getIFaceGridIndex(faceID, ii, jj);
117 EXPECT_EQ(i, ii);
118 EXPECT_EQ(j, jj);
119
120 m->getIFaceGridIndex(faceID, ii, jj, kk);
121 EXPECT_EQ(i, ii);
122 EXPECT_EQ(j, jj);
123 EXPECT_EQ(0, kk);
124 }
125 }
126
127 /* Check the getJFace Linear/Grid Index. */
128 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
129 {
130 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
131 {
132 const IndexType faceID = m->getJFaceLinearIndex(i, j);
133 const IndexType faceID2 = m->getFaceLinearIndex(J_DIRECTION, i, j);
134 EXPECT_EQ(faceID, idx++);
135 EXPECT_EQ(faceID, faceID2);
136
137 IndexType ii, jj, kk;
138 m->getJFaceGridIndex(faceID, ii, jj);
139 EXPECT_EQ(i, ii);
140 EXPECT_EQ(j, jj);
141
142 m->getJFaceGridIndex(faceID, ii, jj, kk);
143 EXPECT_EQ(i, ii);
144 EXPECT_EQ(j, jj);
145 EXPECT_EQ(0, kk);
146 }
147 }
148 }
149
150 /*!
151 * \brief Check the indexing methods of a 3D StructuredMesh.
152 *
153 * \param [in] m the mesh to check.
154 */
check_indexing3D(const StructuredMesh * m)155 inline void check_indexing3D(const StructuredMesh* m)
156 {
157 SLIC_ASSERT(m != nullptr);
158 SLIC_ASSERT(m->getDimension() == 3);
159
160 /* Check getNode Linear/Grid Index */
161 IndexType idx = 0;
162 for(IndexType k = 0; k < m->getNodeResolution(2); ++k)
163 {
164 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
165 {
166 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
167 {
168 const IndexType nodeID = m->getNodeLinearIndex(i, j, k);
169 EXPECT_EQ(nodeID, idx++);
170
171 IndexType ii, jj, kk;
172 m->getNodeGridIndex(nodeID, ii, jj, kk);
173 EXPECT_EQ(i, ii);
174 EXPECT_EQ(j, jj);
175 EXPECT_EQ(k, kk);
176 }
177 }
178 }
179
180 /* Check getCell Linear/Grid Index */
181 idx = 0;
182 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
183 {
184 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
185 {
186 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
187 {
188 const IndexType cellID = m->getCellLinearIndex(i, j, k);
189 EXPECT_EQ(cellID, idx++);
190
191 IndexType ii, jj, kk;
192 m->getCellGridIndex(cellID, ii, jj, kk);
193 EXPECT_EQ(i, ii);
194 EXPECT_EQ(j, jj);
195 EXPECT_EQ(k, kk);
196 }
197 }
198 }
199
200 /* Check the getIFace Linear/Grid Index. */
201 idx = 0;
202 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
203 {
204 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
205 {
206 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
207 {
208 const IndexType faceID = m->getIFaceLinearIndex(i, j, k);
209 const IndexType faceID2 = m->getFaceLinearIndex(I_DIRECTION, i, j, k);
210 EXPECT_EQ(faceID, idx++);
211 EXPECT_EQ(faceID, faceID2);
212
213 IndexType ii, jj, kk;
214 m->getIFaceGridIndex(faceID, ii, jj, kk);
215 EXPECT_EQ(i, ii);
216 EXPECT_EQ(j, jj);
217 EXPECT_EQ(k, kk);
218 }
219 }
220 }
221
222 /* Check the getJFace Linear/Grid Index. */
223 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
224 {
225 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
226 {
227 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
228 {
229 const IndexType faceID = m->getJFaceLinearIndex(i, j, k);
230 const IndexType faceID2 = m->getFaceLinearIndex(J_DIRECTION, i, j, k);
231 EXPECT_EQ(faceID, idx++);
232 EXPECT_EQ(faceID, faceID2);
233
234 IndexType ii, jj, kk;
235 m->getJFaceGridIndex(faceID, ii, jj, kk);
236 EXPECT_EQ(i, ii);
237 EXPECT_EQ(j, jj);
238 EXPECT_EQ(k, kk);
239 }
240 }
241 }
242
243 /* Check the getKFace Linear/Grid Index. */
244 for(IndexType k = 0; k < m->getNodeResolution(2); ++k)
245 {
246 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
247 {
248 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
249 {
250 const IndexType faceID = m->getKFaceLinearIndex(i, j, k);
251 const IndexType faceID2 = m->getFaceLinearIndex(K_DIRECTION, i, j, k);
252 EXPECT_EQ(faceID, idx++);
253 EXPECT_EQ(faceID, faceID2);
254
255 IndexType ii, jj, kk;
256 m->getKFaceGridIndex(faceID, ii, jj, kk);
257 EXPECT_EQ(i, ii);
258 EXPECT_EQ(j, jj);
259 EXPECT_EQ(k, kk);
260 }
261 }
262 }
263 }
264
265 /*!
266 * \brief Check the topology related methods of a 1D StructuredMesh.
267 *
268 * \param [in] m the mesh to check.
269 *
270 * \note Since 1D meshes don't have any faces the only method tested here
271 * is getCellNodeIDs.
272 */
check_topology1D(const StructuredMesh * m)273 inline void check_topology1D(const StructuredMesh* m)
274 {
275 SLIC_ASSERT(m != nullptr);
276 SLIC_ASSERT(m->getDimension() == 1);
277
278 EXPECT_EQ(m->getNumberOfCellNodes(), 2);
279 EXPECT_EQ(m->getNumberOfCellFaces(), 0);
280 EXPECT_EQ(m->getNumberOfFaces(), 0);
281 EXPECT_EQ(m->getNumberOfFaceNodes(), 0);
282
283 IndexType cellNodes[2];
284 const IndexType nCells = m->getNumberOfCells();
285 for(IndexType cellID = 0; cellID < nCells; ++cellID)
286 {
287 m->getCellNodeIDs(cellID, cellNodes);
288 EXPECT_EQ(cellNodes[0], cellID);
289 EXPECT_EQ(cellNodes[1], cellID + 1);
290 }
291 }
292
293 /*!
294 * \brief Check the topology related methods of a 2D StructuredMesh.
295 *
296 * \param [in] m the mesh to check.
297 */
check_topology2D(const StructuredMesh * m)298 inline void check_topology2D(const StructuredMesh* m)
299 {
300 SLIC_ASSERT(m != nullptr);
301 SLIC_ASSERT(m->getDimension() == 2);
302
303 EXPECT_EQ(m->getNumberOfCellNodes(), 4);
304
305 /* Check the cell to node map. */
306 IndexType cellNodes[4], cellNodesIJ[4];
307 const IndexType nodeJp = m->nodeJp();
308 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
309 {
310 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
311 {
312 const IndexType cellID = m->getCellLinearIndex(i, j);
313 m->getCellNodeIDs(cellID, cellNodes);
314 m->getCellNodeIDs(i, j, cellNodesIJ);
315 compare_pointers(cellNodes, cellNodesIJ, 4);
316
317 const IndexType nodeID = m->getNodeLinearIndex(i, j);
318 EXPECT_EQ(cellNodes[0], nodeID);
319 EXPECT_EQ(cellNodes[1], nodeID + 1);
320 EXPECT_EQ(cellNodes[2], nodeID + nodeJp + 1);
321 EXPECT_EQ(cellNodes[3], nodeID + nodeJp);
322 }
323 }
324
325 EXPECT_EQ(m->getNumberOfCellFaces(), 4);
326 EXPECT_EQ(m->getNumberOfFaceNodes(), 2);
327
328 const IndexType nIFaces = m->getNodeResolution(0) * m->getCellResolution(1);
329 const IndexType nJFaces = m->getCellResolution(0) * m->getNodeResolution(1);
330 EXPECT_EQ(nIFaces, m->getTotalNumFaces(0));
331 EXPECT_EQ(nJFaces, m->getTotalNumFaces(1));
332
333 const IndexType nFaces = nIFaces + nJFaces;
334 EXPECT_EQ(m->getNumberOfFaces(), nFaces);
335
336 /* Check the cell to face map */
337 const IndexType cellJp = m->cellJp();
338 IndexType cellFaces[4], cellFacesIJ[4];
339 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
340 {
341 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
342 {
343 const IndexType cellID = m->getCellLinearIndex(i, j);
344 m->getCellFaceIDs(cellID, cellFaces);
345 m->getCellFaceIDs(i, j, cellFacesIJ);
346 compare_pointers(cellFaces, cellFacesIJ, 4);
347
348 EXPECT_EQ(cellFaces[0], cellID + j);
349 EXPECT_EQ(cellFaces[1], cellID + j + 1);
350 EXPECT_EQ(cellFaces[2], cellID + nIFaces);
351 EXPECT_EQ(cellFaces[3], cellID + nIFaces + cellJp);
352 }
353 }
354
355 /* Check the face to node map */
356 IndexType faceNodes[2];
357 IndexType faceNodesDir[2];
358
359 /* I-faces */
360 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
361 {
362 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
363 {
364 const IndexType faceID = m->getIFaceLinearIndex(i, j);
365 m->getFaceNodeIDs(faceID, faceNodes);
366 m->getIFaceNodeIDs(faceID, faceNodesDir);
367 compare_pointers(faceNodes, faceNodesDir, 2);
368
369 EXPECT_EQ(faceNodes[0], m->getNodeLinearIndex(i, j));
370 EXPECT_EQ(faceNodes[1], m->getNodeLinearIndex(i, j + 1));
371 }
372 }
373
374 /* J-faces */
375 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
376 {
377 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
378 {
379 const IndexType faceID = m->getJFaceLinearIndex(i, j);
380 m->getFaceNodeIDs(faceID, faceNodes);
381 m->getJFaceNodeIDs(faceID, faceNodesDir);
382 compare_pointers(faceNodes, faceNodesDir, 2);
383
384 EXPECT_EQ(faceNodes[0], m->getNodeLinearIndex(i, j));
385 EXPECT_EQ(faceNodes[1], m->getNodeLinearIndex(i + 1, j));
386 }
387 }
388
389 /* Check the face to cell map */
390 IndexType cell0, cell1, cell2, cell3;
391
392 /* I-faces */
393 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
394 {
395 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
396 {
397 const IndexType faceID = m->getIFaceLinearIndex(i, j);
398 m->getFaceCellIDs(faceID, cell0, cell1);
399 m->getIFaceCellIDs(faceID, cell2, cell3);
400 EXPECT_EQ(cell0, cell2);
401 EXPECT_EQ(cell1, cell3);
402
403 /* Check the boundaries. */
404 if(i == 0)
405 {
406 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j));
407 EXPECT_EQ(cell1, -1);
408 }
409 else if(i == m->getCellResolution(0))
410 {
411 EXPECT_EQ(cell0, m->getCellLinearIndex(i - 1, j));
412 EXPECT_EQ(cell1, -1);
413 }
414 else
415 {
416 EXPECT_EQ(cell0, m->getCellLinearIndex(i - 1, j));
417 EXPECT_EQ(cell1, m->getCellLinearIndex(i, j));
418 }
419 }
420 }
421
422 /* J-faces */
423 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
424 {
425 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
426 {
427 const IndexType faceID = m->getJFaceLinearIndex(i, j);
428 m->getFaceCellIDs(faceID, cell0, cell1);
429 m->getJFaceCellIDs(faceID, cell2, cell3);
430 EXPECT_EQ(cell0, cell2);
431 EXPECT_EQ(cell1, cell3);
432
433 /* Check the boundaries. */
434 if(j == 0)
435 {
436 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j));
437 EXPECT_EQ(cell1, -1);
438 }
439 else if(j == m->getCellResolution(1))
440 {
441 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j - 1));
442 EXPECT_EQ(cell1, -1);
443 }
444 else
445 {
446 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j - 1));
447 EXPECT_EQ(cell1, m->getCellLinearIndex(i, j));
448 }
449 }
450 }
451 }
452
453 /*!
454 * \brief Check the topology related methods of a 3D StructuredMesh.
455 *
456 * \param [in] m the mesh to check.
457 */
check_topology3D(const StructuredMesh * m)458 inline void check_topology3D(const StructuredMesh* m)
459 {
460 SLIC_ASSERT(m != nullptr);
461 SLIC_ASSERT(m->getDimension() == 3);
462
463 EXPECT_EQ(m->getNumberOfCellNodes(), 8);
464
465 /* Check the cell to node map. */
466 IndexType cellNodes[8], cellNodesIJK[8];
467 const IndexType nodeJp = m->nodeJp();
468 const IndexType nodeKp = m->nodeKp();
469 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
470 {
471 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
472 {
473 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
474 {
475 const IndexType cellID = m->getCellLinearIndex(i, j, k);
476 m->getCellNodeIDs(cellID, cellNodes);
477 m->getCellNodeIDs(i, j, k, cellNodesIJK);
478 compare_pointers(cellNodes, cellNodesIJK, 8);
479
480 const IndexType nodeID = m->getNodeLinearIndex(i, j, k);
481 EXPECT_EQ(cellNodes[0], nodeID);
482 EXPECT_EQ(cellNodes[1], nodeID + 1);
483 EXPECT_EQ(cellNodes[2], nodeID + nodeJp + 1);
484 EXPECT_EQ(cellNodes[3], nodeID + nodeJp);
485 EXPECT_EQ(cellNodes[4], nodeID + nodeKp);
486 EXPECT_EQ(cellNodes[5], nodeID + nodeKp + 1);
487 EXPECT_EQ(cellNodes[6], nodeID + nodeKp + nodeJp + 1);
488 EXPECT_EQ(cellNodes[7], nodeID + nodeKp + nodeJp);
489 }
490 }
491 }
492
493 EXPECT_EQ(m->getNumberOfCellFaces(), 6);
494 EXPECT_EQ(m->getNumberOfFaceNodes(), 4);
495
496 const IndexType nIFaces =
497 m->getNodeResolution(0) * m->getCellResolution(1) * m->getCellResolution(2);
498 const IndexType nJFaces =
499 m->getCellResolution(0) * m->getNodeResolution(1) * m->getCellResolution(2);
500 const IndexType nKFaces =
501 m->getCellResolution(0) * m->getCellResolution(1) * m->getNodeResolution(2);
502 EXPECT_EQ(nIFaces, m->getTotalNumFaces(0));
503 EXPECT_EQ(nJFaces, m->getTotalNumFaces(1));
504 EXPECT_EQ(nKFaces, m->getTotalNumFaces(2));
505
506 const IndexType nFaces = nIFaces + nJFaces + nKFaces;
507 EXPECT_EQ(m->getNumberOfFaces(), nFaces);
508
509 /* Check the cell to face map */
510 IndexType cellFaces[6], cellFacesIJK[6];
511 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
512 {
513 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
514 {
515 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
516 {
517 const IndexType cellID = m->getCellLinearIndex(i, j, k);
518 m->getCellFaceIDs(cellID, cellFaces);
519 m->getCellFaceIDs(i, j, k, cellFacesIJK);
520 compare_pointers(cellFaces, cellFacesIJK, 6);
521
522 EXPECT_EQ(cellFaces[0], m->getIFaceLinearIndex(i, j, k));
523 EXPECT_EQ(cellFaces[1], m->getIFaceLinearIndex(i + 1, j, k));
524 EXPECT_EQ(cellFaces[2], m->getJFaceLinearIndex(i, j, k));
525 EXPECT_EQ(cellFaces[3], m->getJFaceLinearIndex(i, j + 1, k));
526 EXPECT_EQ(cellFaces[4], m->getKFaceLinearIndex(i, j, k));
527 EXPECT_EQ(cellFaces[5], m->getKFaceLinearIndex(i, j, k + 1));
528 }
529 }
530 }
531
532 /* Check the face to node map */
533 IndexType faceNodes[4];
534 IndexType faceNodesDir[4];
535
536 /* I-faces */
537 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
538 {
539 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
540 {
541 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
542 {
543 const IndexType faceID = m->getIFaceLinearIndex(i, j, k);
544 m->getFaceNodeIDs(faceID, faceNodes);
545 m->getIFaceNodeIDs(faceID, faceNodesDir);
546 compare_pointers(faceNodes, faceNodesDir, 4);
547
548 EXPECT_EQ(faceNodes[0], m->getNodeLinearIndex(i, j, k));
549 EXPECT_EQ(faceNodes[1], m->getNodeLinearIndex(i, j, k + 1));
550 EXPECT_EQ(faceNodes[2], m->getNodeLinearIndex(i, j + 1, k + 1));
551 EXPECT_EQ(faceNodes[3], m->getNodeLinearIndex(i, j + 1, k));
552 }
553 }
554 }
555
556 /* J-faces */
557 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
558 {
559 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
560 {
561 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
562 {
563 const IndexType faceID = m->getJFaceLinearIndex(i, j, k);
564 m->getFaceNodeIDs(faceID, faceNodes);
565 m->getJFaceNodeIDs(faceID, faceNodesDir);
566 compare_pointers(faceNodes, faceNodesDir, 4);
567
568 EXPECT_EQ(faceNodes[0], m->getNodeLinearIndex(i, j, k));
569 EXPECT_EQ(faceNodes[1], m->getNodeLinearIndex(i + 1, j, k));
570 EXPECT_EQ(faceNodes[2], m->getNodeLinearIndex(i + 1, j, k + 1));
571 EXPECT_EQ(faceNodes[3], m->getNodeLinearIndex(i, j, k + 1));
572 }
573 }
574 }
575
576 /* K-faces */
577 for(IndexType k = 0; k < m->getNodeResolution(2); ++k)
578 {
579 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
580 {
581 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
582 {
583 const IndexType faceID = m->getKFaceLinearIndex(i, j, k);
584 m->getFaceNodeIDs(faceID, faceNodes);
585 m->getKFaceNodeIDs(faceID, faceNodesDir);
586 compare_pointers(faceNodes, faceNodesDir, 4);
587
588 EXPECT_EQ(faceNodes[0], m->getNodeLinearIndex(i, j, k));
589 EXPECT_EQ(faceNodes[1], m->getNodeLinearIndex(i + 1, j, k));
590 EXPECT_EQ(faceNodes[2], m->getNodeLinearIndex(i + 1, j + 1, k));
591 EXPECT_EQ(faceNodes[3], m->getNodeLinearIndex(i, j + 1, k));
592 }
593 }
594 }
595
596 /* Check the face to cell map */
597 IndexType cell0, cell1, cell2, cell3;
598
599 /* I-faces */
600 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
601 {
602 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
603 {
604 for(IndexType i = 0; i < m->getNodeResolution(0); ++i)
605 {
606 const IndexType faceID = m->getIFaceLinearIndex(i, j, k);
607 m->getFaceCellIDs(faceID, cell0, cell1);
608 m->getIFaceCellIDs(faceID, cell2, cell3);
609 EXPECT_EQ(cell0, cell2);
610 EXPECT_EQ(cell1, cell3);
611
612 /* Check the boundaries. */
613 if(i == 0)
614 {
615 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j, k));
616 EXPECT_EQ(cell1, -1);
617 }
618 else if(i == m->getCellResolution(0))
619 {
620 EXPECT_EQ(cell0, m->getCellLinearIndex(i - 1, j, k));
621 EXPECT_EQ(cell1, -1);
622 }
623 else
624 {
625 EXPECT_EQ(cell0, m->getCellLinearIndex(i - 1, j, k));
626 EXPECT_EQ(cell1, m->getCellLinearIndex(i, j, k));
627 }
628 }
629 }
630 }
631
632 /* J-faces */
633 for(IndexType k = 0; k < m->getCellResolution(2); ++k)
634 {
635 for(IndexType j = 0; j < m->getNodeResolution(1); ++j)
636 {
637 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
638 {
639 const IndexType faceID = m->getJFaceLinearIndex(i, j, k);
640 m->getFaceCellIDs(faceID, cell0, cell1);
641 m->getJFaceCellIDs(faceID, cell2, cell3);
642 EXPECT_EQ(cell0, cell2);
643 EXPECT_EQ(cell1, cell3);
644
645 /* Check the boundaries. */
646 if(j == 0)
647 {
648 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j, k));
649 EXPECT_EQ(cell1, -1);
650 }
651 else if(j == m->getCellResolution(1))
652 {
653 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j - 1, k));
654 EXPECT_EQ(cell1, -1);
655 }
656 else
657 {
658 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j - 1, k));
659 EXPECT_EQ(cell1, m->getCellLinearIndex(i, j, k));
660 }
661 }
662 }
663 }
664
665 /* K-faces */
666 for(IndexType k = 0; k < m->getNodeResolution(2); ++k)
667 {
668 for(IndexType j = 0; j < m->getCellResolution(1); ++j)
669 {
670 for(IndexType i = 0; i < m->getCellResolution(0); ++i)
671 {
672 const IndexType faceID = m->getKFaceLinearIndex(i, j, k);
673 m->getFaceCellIDs(faceID, cell0, cell1);
674 m->getKFaceCellIDs(faceID, cell2, cell3);
675 EXPECT_EQ(cell0, cell2);
676 EXPECT_EQ(cell1, cell3);
677
678 /* Check the boundaries. */
679 if(k == 0)
680 {
681 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j, k));
682 EXPECT_EQ(cell1, -1);
683 }
684 else if(k == m->getCellResolution(2))
685 {
686 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j, k - 1));
687 EXPECT_EQ(cell1, -1);
688 }
689 else
690 {
691 EXPECT_EQ(cell0, m->getCellLinearIndex(i, j, k - 1));
692 EXPECT_EQ(cell1, m->getCellLinearIndex(i, j, k));
693 }
694 }
695 }
696 }
697 }
698
699 /*!
700 * \brief Check the indexing and topology related methods of a StructuredMesh.
701 *
702 * \param [in] m the mesh to check.
703 */
check_topology(const StructuredMesh * m)704 inline void check_topology(const StructuredMesh* m)
705 {
706 SLIC_ASSERT(m != nullptr);
707
708 const int ndims = m->getDimension();
709 IndexType nCells = 1;
710 IndexType nNodes = 1;
711 for(int dim = 0; dim < ndims; ++dim)
712 {
713 EXPECT_EQ(m->getNodeResolution(dim), m->getCellResolution(dim) + 1);
714 nNodes *= m->getNodeResolution(dim);
715 nCells *= m->getCellResolution(dim);
716 }
717
718 EXPECT_EQ(nNodes, m->getNumberOfNodes());
719 EXPECT_EQ(nCells, m->getNumberOfCells());
720
721 if(ndims == 1)
722 {
723 check_topology1D(m);
724 }
725 else if(ndims == 2)
726 {
727 check_indexing2D(m);
728 check_topology2D(m);
729 }
730 else
731 {
732 SLIC_ASSERT(ndims == 3);
733 check_indexing3D(m);
734 check_topology3D(m);
735 }
736 }
737
738 } /* namespace */
739
740 /*!
741 * \brief Create a field with the given parameters and check for errors.
742 *
743 * \param [in/out] m the mesh to check.
744 * \param [in] association the association of the field.
745 * \param [in] name the name of the field.
746 * \param [in] numComponents the number of components (optional).
747 */
check_create_field(StructuredMesh * m,int association,const std::string & name,int numComponents=1)748 inline void check_create_field(StructuredMesh* m,
749 int association,
750 const std::string& name,
751 int numComponents = 1)
752 {
753 EXPECT_TRUE(m != nullptr);
754 EXPECT_FALSE(m->hasField(name, association));
755
756 double* f = m->createField<double>(name, association, numComponents);
757 EXPECT_TRUE(m->hasField(name, association));
758
759 IndexType expected_num_tuples;
760 if(association == NODE_CENTERED)
761 {
762 expected_num_tuples = m->getNumberOfNodes();
763 }
764 else if(association == CELL_CENTERED)
765 {
766 expected_num_tuples = m->getNumberOfCells();
767 }
768 else if(association == FACE_CENTERED)
769 {
770 expected_num_tuples = m->getNumberOfFaces();
771 }
772 else
773 {
774 expected_num_tuples = m->getNumberOfEdges();
775 }
776
777 const Field* field = m->getFieldData(association)->getField(name);
778 EXPECT_TRUE(field != nullptr);
779 EXPECT_EQ(f, Field::getDataPtr<double>(field));
780 EXPECT_EQ(numComponents, field->getNumComponents());
781 EXPECT_EQ(expected_num_tuples, field->getNumTuples());
782
783 for(IndexType i = 0; i < expected_num_tuples * numComponents; ++i)
784 {
785 f[i] = PI * i;
786 }
787 }
788
789 /*!
790 * \brief Check that the field has the proper values.
791 *
792 * \param [in] field the field to check.
793 */
check_field_values(const Field * field)794 inline void check_field_values(const Field* field)
795 {
796 const IndexType num_values = field->getNumTuples() * field->getNumComponents();
797 const double* values = Field::getDataPtr<double>(field);
798 for(IndexType i = 0; i < num_values; ++i)
799 {
800 EXPECT_EQ(values[i], PI * i);
801 }
802 }
803
804 /*!
805 * \brief Create a field on each of the topological objects.
806 *
807 * \param [in] m the StructuredMesh to create the fields on.
808 */
check_create_fields(StructuredMesh * m)809 inline void check_create_fields(StructuredMesh* m)
810 {
811 check_create_field(m, NODE_CENTERED, "n1", 1);
812 check_create_field(m, CELL_CENTERED, "c1", 2);
813 check_create_field(m, FACE_CENTERED, "f1", 3);
814 check_create_field(m, EDGE_CENTERED, "e1", 4);
815 }
816
817 /*!
818 * \brief Check that the fields have the proper values.
819 *
820 * \param [in] m the StructuredMesh to check.
821 * \param [in] isInSidre if the fields should be in sidre.
822 */
check_fields(const StructuredMesh * m,bool isInSidre)823 inline void check_fields(const StructuredMesh* m, bool isInSidre)
824 {
825 EXPECT_TRUE(m->hasField("n1", NODE_CENTERED));
826 EXPECT_TRUE(m->hasField("c1", CELL_CENTERED));
827 EXPECT_TRUE(m->hasField("f1", FACE_CENTERED));
828 EXPECT_TRUE(m->hasField("e1", EDGE_CENTERED));
829
830 /* check node-centered field on m. */
831 const FieldData* fd = m->getFieldData(NODE_CENTERED);
832 const Field* field = fd->getField("n1");
833 EXPECT_EQ(field->getNumTuples(), m->getNumberOfNodes());
834 EXPECT_EQ(field->getNumComponents(), 1);
835 EXPECT_EQ(field->isInSidre(), isInSidre);
836 EXPECT_FALSE(field->isExternal());
837 internal::check_field_values(field);
838
839 /* check cell-centered field on m. */
840 fd = m->getFieldData(CELL_CENTERED);
841 field = fd->getField("c1");
842 EXPECT_EQ(field->getNumTuples(), m->getNumberOfCells());
843 EXPECT_EQ(field->getNumComponents(), 2);
844 EXPECT_EQ(field->isInSidre(), isInSidre);
845 EXPECT_FALSE(field->isExternal());
846 internal::check_field_values(field);
847
848 /* check face-centered field on m. */
849 fd = m->getFieldData(FACE_CENTERED);
850 field = fd->getField("f1");
851 EXPECT_EQ(field->getNumTuples(), m->getNumberOfFaces());
852 EXPECT_EQ(field->getNumComponents(), 3);
853 EXPECT_EQ(field->isInSidre(), isInSidre);
854 EXPECT_FALSE(field->isExternal());
855 internal::check_field_values(field);
856
857 /* check edge-centered field on m. */
858 fd = m->getFieldData(EDGE_CENTERED);
859 field = fd->getField("e1");
860 EXPECT_EQ(field->getNumTuples(), m->getNumberOfEdges());
861 EXPECT_EQ(field->getNumComponents(), 4);
862 EXPECT_EQ(field->isInSidre(), isInSidre);
863 EXPECT_FALSE(field->isExternal());
864 internal::check_field_values(field);
865 }
866
867 /*!
868 * \brief Check that the StructuredMesh was constructed correctly.
869 *
870 * \param [in] m the StructuredMesh to check.
871 * \param [in] mesh_type the expected type of the StructuredMesh.
872 * \param [in] ndims the expected number of dimensions.
873 * \param [in] node_dims the expected nodal dimensions of the mesh.
874 */
check_constructor(const StructuredMesh * m,int mesh_type,int ndims,const IndexType * node_dims)875 inline void check_constructor(const StructuredMesh* m,
876 int mesh_type,
877 int ndims,
878 const IndexType* node_dims)
879 {
880 SLIC_ASSERT(mesh_type == STRUCTURED_CURVILINEAR_MESH ||
881 mesh_type == STRUCTURED_RECTILINEAR_MESH ||
882 mesh_type == STRUCTURED_UNIFORM_MESH);
883
884 EXPECT_TRUE(m != nullptr);
885 EXPECT_EQ(m->getMeshType(), mesh_type);
886 EXPECT_TRUE(ndims >= 1 && ndims <= 3);
887
888 const int mesh_dimension = m->getDimension();
889
890 EXPECT_EQ(mesh_dimension, ndims);
891 EXPECT_EQ(m->getMeshType(), mesh_type);
892 EXPECT_FALSE(m->hasExplicitConnectivity());
893 EXPECT_FALSE(m->hasMixedCellTypes());
894
895 if(mesh_type == STRUCTURED_UNIFORM_MESH)
896 {
897 EXPECT_FALSE(m->hasExplicitCoordinates());
898 }
899 else
900 {
901 EXPECT_TRUE(m->hasExplicitCoordinates());
902 }
903
904 CellType cell_type =
905 (mesh_dimension == 3) ? HEX : (mesh_dimension == 2) ? QUAD : SEGMENT;
906 EXPECT_EQ(m->getCellType(), cell_type);
907 EXPECT_EQ(m->getNumberOfCellNodes(), getCellInfo(cell_type).num_nodes);
908 EXPECT_EQ(m->getNumberOfCellFaces(), getCellInfo(cell_type).num_faces);
909
910 for(int i = 0; i < mesh_dimension; ++i)
911 {
912 EXPECT_EQ(m->getNodeResolution(i), node_dims[i]);
913
914 if(mesh_type != STRUCTURED_UNIFORM_MESH)
915 {
916 EXPECT_TRUE(m->getCoordinateArray(i) != nullptr);
917 }
918 }
919
920 check_topology(m);
921 }
922
923 /*!
924 * \brief Check that the UniformMesh was constructed correctly.
925 *
926 * \param [in] m the UniformMesh to check.
927 * \param [in] ndims the expected number of dimensions.
928 * \param [in] origin the origin of the UniformMesh.
929 * \param [in] spacing the spacing between the nodes.
930 * \param [in] node_dims the expected nodal dimensions of the mesh.
931 */
check_constructor(const UniformMesh * m,int ndims,const double * origin,const double * spacing,const IndexType * node_dims)932 inline void check_constructor(const UniformMesh* m,
933 int ndims,
934 const double* origin,
935 const double* spacing,
936 const IndexType* node_dims)
937 {
938 EXPECT_TRUE(m != nullptr);
939 EXPECT_TRUE(ndims >= 1 && ndims <= 3);
940
941 for(int i = 0; i < ndims; ++i)
942 {
943 EXPECT_DOUBLE_EQ(origin[i], m->getOrigin()[i]);
944 EXPECT_DOUBLE_EQ(spacing[i], m->getSpacing()[i]);
945 }
946
947 check_constructor(m, STRUCTURED_UNIFORM_MESH, ndims, node_dims);
948 }
949
950 /*!
951 * \brief Check that the nodal extent of the StructuredMesh was set correctly.
952 *
953 * \param [in] m the StructuredMesh to check.
954 * \param [in] extent the expected extent of the mesh.
955 */
check_node_extent(const StructuredMesh * m,const int64 * extent)956 inline void check_node_extent(const StructuredMesh* m, const int64* extent)
957 {
958 SLIC_ASSERT(m != nullptr);
959 SLIC_ASSERT(extent != nullptr);
960
961 int64 m_extent[6];
962 m->getExtent(m_extent);
963
964 for(int dim = 0; dim < m->getDimension(); ++dim)
965 {
966 EXPECT_EQ(m_extent[2 * dim], extent[2 * dim]);
967 EXPECT_EQ(m_extent[2 * dim + 1], extent[2 * dim + 1]);
968 }
969
970 for(int dim = m->getDimension(); dim < 3; ++dim)
971 {
972 EXPECT_EQ(m_extent[2 * dim], m_extent[2 * dim + 1]);
973 }
974 }
975
976 } /* namespace internal */
977 } /* namespace mint */
978 } /* namespace axom */
979
980 #endif /* MINT_STRUCTURED_MESH_TEST_HELPERS_HPP_ */
981