libMesh
Loading...
Searching...
No Matches
mesh_generation_test.C
Go to the documentation of this file.
1#include <libmesh/libmesh.h>
2#include <libmesh/distributed_mesh.h>
3#include <libmesh/elem.h>
4#include <libmesh/mesh_generation.h>
5#include <libmesh/mesh_tools.h>
6#include <libmesh/replicated_mesh.h>
7
8#include "test_comm.h"
9#include "libmesh_cppunit.h"
10
11
12using namespace libMesh;
13
14class MeshGenerationTest : public CppUnit::TestCase
15{
21public:
23
27# ifdef LIBMESH_ENABLE_AMR
30// CPPUNIT_TEST( buildSphereEdge4 ); Doesn't work with AMR yet
31# endif
32
33#if LIBMESH_DIM > 1
42# ifdef LIBMESH_ENABLE_AMR
45# endif
46#endif
47#if LIBMESH_DIM > 2
60
61 // These tests throw an exception from contains_point() calls, and
62 // this simply aborts() when exceptions are not enabled.
63#ifdef LIBMESH_ENABLE_EXCEPTIONS
67
68#ifdef LIBMESH_ENABLE_AMR
70#endif
71#endif
72
73# ifdef LIBMESH_ENABLE_AMR
75# endif
76#endif
77
79
80protected:
81 std::unique_ptr<UnstructuredMesh> new_mesh (bool is_replicated)
82 {
83 if (is_replicated)
84 return std::make_unique<ReplicatedMesh>(*TestCommWorld);
85 return std::make_unique<DistributedMesh>(*TestCommWorld);
86 }
87
88public:
89 void setUp() {}
90
91 void tearDown() {}
92
93 void testBuildLine(UnstructuredMesh & mesh, unsigned int n, ElemType type)
94 {
95 MeshTools::Generation::build_line (mesh, n, -1.0, 2.0, type);
96 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n));
97 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
98 cast_int<dof_id_type>((Elem::type_to_n_nodes_map[type]-1)*n + 1));
99
101 CPPUNIT_ASSERT_EQUAL(bbox.min()(0), Real(-1.0));
102 CPPUNIT_ASSERT_EQUAL(bbox.max()(0), Real(2.0));
103
104 // Do serial assertions *after* all parallel assertions, so we
105 // stay in sync after failure on only some processor(s)
106 for (auto & elem : mesh.element_ptr_range())
107 CPPUNIT_ASSERT(elem->has_affine_map());
108 }
109
110 void testBuildSquare(UnstructuredMesh & mesh, unsigned int n, ElemType type)
111 {
112 MeshTools::Generation::build_square (mesh, n, n, -2.0, 3.0, -4.0, 5.0, type);
113 if (type == C0POLYGON)
114 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n + 4 + 2 * (n - 1) + ((n - 1) / 2)));
115 else if (Elem::type_to_n_sides_map[type] == 4)
116 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n));
117 else
118 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*2));
119
120 switch (type)
121 {
122 case TRI3: // First-order elements
123 case QUAD4:
124 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
125 cast_int<dof_id_type>((n+1)*(n+1)));
126 break;
127 case TRI6: // Second-order elements
128 case QUAD9:
129 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
130 cast_int<dof_id_type>((2*n+1)*(2*n+1)));
131 break;
132 case QUAD8: // Not-really-second-order element missing center nodes
133 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
134 cast_int<dof_id_type>((2*n+1)*(2*n+1) - n*n));
135 break;
136 case TRI7: // Not-really-second-order element with extra center nodes
137 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
138 cast_int<dof_id_type>((2*n+1)*(2*n+1) + 2*n*n));
139 break;
140 case C0POLYGON:
141 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
142 cast_int<dof_id_type>(4 + 2*n*n + (n - 1) + 2*n + 2 * (n%2)));
143 break;
144 default: // Wait, what did we try to build?
145 CPPUNIT_ASSERT(false);
146 }
147
148 // Our bounding boxes can be loose on higher order elements, but
149 // we can at least assert that they're not too tight
151 CPPUNIT_ASSERT(bbox.min()(0) <= Real(-2.0));
152 CPPUNIT_ASSERT(bbox.max()(0) >= Real(3.0));
153 CPPUNIT_ASSERT(bbox.min()(1) <= Real(-4.0));
154 CPPUNIT_ASSERT(bbox.max()(1) >= Real(5.0));
155
156 if (type == C0POLYGON)
157 {
159 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.min()(0),
160 Real(-2.0),
162 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.max()(0),
163 Real(3.0),
165 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.min()(1),
166 Real(-4.0),
168 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.max()(1),
169 Real(5.0),
171 }
172
173 // Do serial assertions *after* all parallel assertions, so we
174 // stay in sync after failure on only some processor(s)
175 if (type != C0POLYGON)
176 for (auto & elem : mesh.element_ptr_range())
177 CPPUNIT_ASSERT(elem->has_affine_map());
178 }
179
180 void testBuildCube(UnstructuredMesh & mesh, unsigned int n, ElemType type)
181 {
182 MeshTools::Generation::build_cube (mesh, n, n, n, -2.0, 3.0, -4.0, 5.0, -6.0, 7.0, type);
183 if (type == C0POLYHEDRON)
184 {
185 const dof_id_type grid_nodes = cast_int<dof_id_type>((n+1)*(n+1)*(n+1));
186
187 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n));
188 CPPUNIT_ASSERT(mesh.n_nodes() >= grid_nodes);
189 CPPUNIT_ASSERT(mesh.n_nodes() <= grid_nodes + cast_int<dof_id_type>(n*n*n));
190 }
191 else
192 {
193 switch (Elem::type_to_n_sides_map[type])
194 {
195 case 4: // tets
196 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n*24));
197 break;
198 case 5: // prisms, pyramids
199 if (type == PRISM6 || type == PRISM15 || type == PRISM18 ||
200 type == PRISM20 || type == PRISM21)
201 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n*2));
202 else
203 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n*6));
204 break;
205 case 6: // hexes
206 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n));
207 break;
208 default:
209 libmesh_error();
210 }
211
212
213 switch (Elem::type_to_n_nodes_map[type])
214 {
215 case 4: // First-order tets
216 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
217 cast_int<dof_id_type>((n+1)*(n+1)*(n+1) + n*n*n + 3*(n+1)*n*n));
218 break;
219 case 6: // First-order prisms and hexes use the same nodes
220 case 8:
221 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
222 cast_int<dof_id_type>((n+1)*(n+1)*(n+1)));
223 break;
224 case 10: // Second-order tets
225 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
226 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 14*n*n*n + 4*3*(n+1)*n*n));
227 break;
228 case 18:
229 case 27: // Second-order prisms and hexes use the same nodes
230 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
231 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1)));
232 break;
233 case 20:
234 if (type == HEX20)
235 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
236 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) - n*n*n - 3*(n+1)*n*n));
237 if (type == PRISM20)
238 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
239 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 2*(n+1)*n*n));
240 break;
241 case 21: // Prisms based on full Tri7 cross sections
242 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
243 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 2*(2*n+1)*n*n));
244 break;
245 case 15: // weird partial order prism
246 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
247 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) - n*n*n - 2*(n+1)*n*n));
248 break;
249 case 5: // pyramids
250 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
251 cast_int<dof_id_type>((n+1)*(n+1)*(n+1) + n*n*n));
252 break;
253 case 13:
254 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
255 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 8*n*n*n - 3*(n+1)*n*n));
256 break;
257 case 14: // pyramids, tets
258 if (type == PYRAMID14)
259 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
260 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 8*n*n*n));
261 else // TET14
262 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
263 cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 14*n*n*n + 4*3*(n+1)*n*n +
264 36*n*n*n + 4*3*(n+1)*n*n));
265 break;
266 default:
267 libmesh_error();
268 }
269 }
270
271 // Our bounding boxes can be loose on higher order elements, but
272 // we can at least assert that they're not too tight
274 CPPUNIT_ASSERT(bbox.min()(0) <= Real(-2.0));
275 CPPUNIT_ASSERT(bbox.max()(0) >= Real(3.0));
276 CPPUNIT_ASSERT(bbox.min()(1) <= Real(-4.0));
277 CPPUNIT_ASSERT(bbox.max()(1) >= Real(5.0));
278 CPPUNIT_ASSERT(bbox.min()(2) <= Real(-6.0));
279 CPPUNIT_ASSERT(bbox.max()(2) >= Real(7.0));
280
281 if (type == C0POLYHEDRON)
282 {
284 const Real expected_volume = Real(5) * Real(9) * Real(13);
285
286 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.min()(0),
287 Real(-2.0),
289 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.max()(0),
290 Real(3.0),
292 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.min()(1),
293 Real(-4.0),
295 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.max()(1),
296 Real(5.0),
298 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.min()(2),
299 Real(-6.0),
301 LIBMESH_ASSERT_FP_EQUAL(nodal_bbox.max()(2),
302 Real(7.0),
304 LIBMESH_ASSERT_FP_EQUAL(MeshTools::volume(mesh),
305 expected_volume,
307
308 for (auto & elem : mesh.element_ptr_range())
309 {
310 CPPUNIT_ASSERT_EQUAL(elem->type(), C0POLYHEDRON);
311 CPPUNIT_ASSERT_EQUAL(elem->n_sides(), 6u);
312 CPPUNIT_ASSERT(elem->n_sub_elem() > 0);
313 CPPUNIT_ASSERT(elem->volume() > 0);
314 }
315
316 return;
317 }
318
319 // We don't yet try to do affine map optimizations on pyramids
320 if (type == PYRAMID5 ||
321 type == PYRAMID13 ||
322 type == PYRAMID14)
323 return;
324
325 // Do serial assertions *after* all parallel assertions, so we
326 // stay in sync after failure on only some processor(s)
327 for (auto & elem : mesh.element_ptr_range())
328 CPPUNIT_ASSERT(elem->has_affine_map());
329 }
330
331 void testBuildSphere(unsigned int n_ref, ElemType type)
332 {
334 MeshTools::Generation::build_sphere (rmesh, 2.0, n_ref, type);
335
337 dmesh.allow_renumbering(false);
338 MeshTools::Generation::build_sphere (dmesh, 2.0, n_ref, type);
339 }
340
341
343
344 void tester(Builder f, unsigned int n, ElemType type)
345 {
346 for (int is_replicated = 0; is_replicated != 2; ++is_replicated)
347 {
348 for (int skip_renumber = 0 ; skip_renumber != 2; ++skip_renumber)
349 {
350 std::unique_ptr<UnstructuredMesh> mesh =
351 new_mesh(is_replicated);
352 mesh->allow_renumbering(!skip_renumber);
353 (this->*f)(*mesh, n, type);
354 }
355 }
356 }
357
361
362 void buildSphereEdge2 () { LOG_UNIT_TEST; testBuildSphere(2, EDGE2); }
363 void buildSphereEdge3 () { LOG_UNIT_TEST; testBuildSphere(2, EDGE3); }
364 void buildSphereEdge4 () { LOG_UNIT_TEST; testBuildSphere(2, EDGE4); }
365
374
375 void buildSphereTri3 () { LOG_UNIT_TEST; testBuildSphere(2, TRI3); }
376 void buildSphereQuad4 () { LOG_UNIT_TEST; testBuildSphere(2, QUAD4); }
377
391
392 // These tests throw an exception from contains_point() calls, and
393 // this simply aborts() when exceptions are not enabled.
394#ifdef LIBMESH_ENABLE_EXCEPTIONS
398#endif
399
400 void buildSphereHex8 () { LOG_UNIT_TEST; testBuildSphere(2, HEX8); }
401 void buildSphereHex27 () { LOG_UNIT_TEST; testBuildSphere(2, HEX27); }
402};
403
404
void ErrorVector unsigned int
CPPUNIT_TEST(buildSquareQuad9)
CPPUNIT_TEST(buildLineEdge2)
std::unique_ptr< UnstructuredMesh > new_mesh(bool is_replicated)
void testBuildLine(UnstructuredMesh &mesh, unsigned int n, ElemType type)
CPPUNIT_TEST(buildLineEdge3)
LIBMESH_CPPUNIT_TEST_SUITE(MeshGenerationTest)
The goal of this test is to verify proper operation of MeshGeneration functions, as well as to indire...
CPPUNIT_TEST(buildCubePrism6)
CPPUNIT_TEST(buildCubePyramid13)
CPPUNIT_TEST(buildCubeTet4)
CPPUNIT_TEST(buildCubePrism18)
void testBuildSphere(unsigned int n_ref, ElemType type)
CPPUNIT_TEST(buildCubeHex20)
CPPUNIT_TEST(buildCubePrism15)
CPPUNIT_TEST(buildSphereEdge3)
CPPUNIT_TEST(buildCubeC0Polyhedron)
CPPUNIT_TEST(buildSphereEdge2)
CPPUNIT_TEST(buildLineEdge4)
void testBuildCube(UnstructuredMesh &mesh, unsigned int n, ElemType type)
CPPUNIT_TEST(buildCubeHex8)
CPPUNIT_TEST(buildSquareTri6)
CPPUNIT_TEST(buildSphereHex8)
CPPUNIT_TEST(buildSquareC0PolygonEven)
CPPUNIT_TEST(buildSquareTri3)
CPPUNIT_TEST(buildSquareQuad8)
CPPUNIT_TEST(buildCubeHex27)
CPPUNIT_TEST(buildSphereTri3)
CPPUNIT_TEST(buildCubeTet14)
void testBuildSquare(UnstructuredMesh &mesh, unsigned int n, ElemType type)
void tester(Builder f, unsigned int n, ElemType type)
CPPUNIT_TEST(buildCubePrism21)
CPPUNIT_TEST(buildSphereQuad4)
CPPUNIT_TEST(buildCubePyramid5)
CPPUNIT_TEST(buildSquareTri7)
CPPUNIT_TEST(buildCubePyramid14)
CPPUNIT_TEST(buildCubePrism20)
CPPUNIT_TEST(buildCubeTet10)
CPPUNIT_TEST(buildSquareC0PolygonOdd)
CPPUNIT_TEST(buildSphereHex27)
CPPUNIT_TEST(buildSquareQuad4)
void(MeshGenerationTest::* Builder)(UnstructuredMesh &, unsigned int, ElemType)
Defines a Cartesian bounding box by the two corner extremum.
const Point & max() const
const Point & min() const
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
Definition elem.h:643
static const unsigned int type_to_n_sides_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of sides on the element...
Definition elem.h:678
virtual dof_id_type n_elem() const =0
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use.
Definition mesh_base.h:1355
virtual dof_id_type n_nodes() const =0
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
The UnstructuredMesh class is derived from the MeshBase class.
Communicator * TestCommWorld
MeshBase & mesh
CPPUNIT_TEST_SUITE_REGISTRATION(MeshGenerationTest)
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
void build_sphere(UnstructuredMesh &mesh, const Real radius=1, const unsigned int n_refinements=2, const ElemType type=INVALID_ELEM, const unsigned int n_smooth=2, const bool flat=true)
Fills mesh with a mesh discretizing a ball (||x||<= radius) or sphere (||x|| = radius) domain.
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
Real volume(const MeshBase &mesh, unsigned int dim=libMesh::invalid_uint)
Find the total volume of a mesh (interpreting that as area for dim = 2, or total arc length for dim =...
libMesh::BoundingBox create_bounding_box(const MeshBase &mesh)
Definition mesh_tools.C:566
libMesh::BoundingBox create_nodal_bounding_box(const MeshBase &mesh)
Definition mesh_tools.C:591
The libMesh namespace provides an interface to certain functionality in the library.
ElemType
Defines an enum for geometric element types.
static constexpr Real TOLERANCE
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real