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