libMesh
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 
12 using namespace libMesh;
13 
14 class MeshGenerationTest : public CppUnit::TestCase
15 {
21 public:
22  LIBMESH_CPPUNIT_TEST_SUITE( MeshGenerationTest );
23 
24  CPPUNIT_TEST( buildLineEdge2 );
25  CPPUNIT_TEST( buildLineEdge3 );
26  CPPUNIT_TEST( buildLineEdge4 );
27 # ifdef LIBMESH_ENABLE_AMR
28  CPPUNIT_TEST( buildSphereEdge2 );
29  CPPUNIT_TEST( buildSphereEdge3 );
30 // CPPUNIT_TEST( buildSphereEdge4 ); Doesn't work with AMR yet
31 # endif
32 
33 #if LIBMESH_DIM > 1
34  CPPUNIT_TEST( buildSquareTri3 );
35  CPPUNIT_TEST( buildSquareTri6 );
36  CPPUNIT_TEST( buildSquareTri7 );
37  CPPUNIT_TEST( buildSquareQuad4 );
38  CPPUNIT_TEST( buildSquareQuad8 );
39  CPPUNIT_TEST( buildSquareQuad9 );
40 # ifdef LIBMESH_ENABLE_AMR
41  CPPUNIT_TEST( buildSphereTri3 );
42  CPPUNIT_TEST( buildSphereQuad4 );
43 # endif
44 #endif
45 #if LIBMESH_DIM > 2
46  CPPUNIT_TEST( buildCubeTet4 );
47  CPPUNIT_TEST( buildCubeTet10 );
48  CPPUNIT_TEST( buildCubeTet14 );
49  CPPUNIT_TEST( buildCubeHex8 );
50  CPPUNIT_TEST( buildCubeHex20 );
51  CPPUNIT_TEST( buildCubeHex27 );
52  CPPUNIT_TEST( buildCubePrism6 );
53  CPPUNIT_TEST( buildCubePrism15 );
54  CPPUNIT_TEST( buildCubePrism18 );
55  CPPUNIT_TEST( buildCubePrism20 );
56  CPPUNIT_TEST( buildCubePrism21 );
57 
58  // These tests throw an exception from contains_point() calls, and
59  // this simply aborts() when exceptions are not enabled.
60 #ifdef LIBMESH_ENABLE_EXCEPTIONS
61  CPPUNIT_TEST( buildCubePyramid5 );
62  CPPUNIT_TEST( buildCubePyramid13 );
63  CPPUNIT_TEST( buildCubePyramid14 );
64 
65 #ifdef LIBMESH_ENABLE_AMR
66  CPPUNIT_TEST( buildSphereHex27 );
67 #endif
68 #endif
69 
70 # ifdef LIBMESH_ENABLE_AMR
71  CPPUNIT_TEST( buildSphereHex8 );
72 # endif
73 #endif
74 
75  CPPUNIT_TEST_SUITE_END();
76 
77 protected:
78  std::unique_ptr<UnstructuredMesh> new_mesh (bool is_replicated)
79  {
80  if (is_replicated)
81  return std::make_unique<ReplicatedMesh>(*TestCommWorld);
82  return std::make_unique<DistributedMesh>(*TestCommWorld);
83  }
84 
85 public:
86  void setUp() {}
87 
88  void tearDown() {}
89 
90  void testBuildLine(UnstructuredMesh & mesh, unsigned int n, ElemType type)
91  {
92  MeshTools::Generation::build_line (mesh, n, -1.0, 2.0, type);
93  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n));
94  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
95  cast_int<dof_id_type>((Elem::type_to_n_nodes_map[type]-1)*n + 1));
96 
98  CPPUNIT_ASSERT_EQUAL(bbox.min()(0), Real(-1.0));
99  CPPUNIT_ASSERT_EQUAL(bbox.max()(0), Real(2.0));
100 
101  // Do serial assertions *after* all parallel assertions, so we
102  // stay in sync after failure on only some processor(s)
103  for (auto & elem : mesh.element_ptr_range())
104  CPPUNIT_ASSERT(elem->has_affine_map());
105  }
106 
107  void testBuildSquare(UnstructuredMesh & mesh, unsigned int n, ElemType type)
108  {
109  MeshTools::Generation::build_square (mesh, n, n, -2.0, 3.0, -4.0, 5.0, type);
110  if (Elem::type_to_n_sides_map[type] == 4)
111  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n));
112  else
113  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*2));
114 
115  switch (type)
116  {
117  case TRI3: // First-order elements
118  case QUAD4:
119  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
120  cast_int<dof_id_type>((n+1)*(n+1)));
121  break;
122  case TRI6: // Second-order elements
123  case QUAD9:
124  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
125  cast_int<dof_id_type>((2*n+1)*(2*n+1)));
126  break;
127  case QUAD8: // Not-really-second-order element missing center nodes
128  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
129  cast_int<dof_id_type>((2*n+1)*(2*n+1) - n*n));
130  break;
131  case TRI7: // Not-really-second-order element with extra center nodes
132  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
133  cast_int<dof_id_type>((2*n+1)*(2*n+1) + 2*n*n));
134  break;
135  default: // Wait, what did we try to build?
136  CPPUNIT_ASSERT(false);
137  }
138 
139  // Our bounding boxes can be loose on higher order elements, but
140  // we can at least assert that they're not too tight
142  CPPUNIT_ASSERT(bbox.min()(0) <= Real(-2.0));
143  CPPUNIT_ASSERT(bbox.max()(0) >= Real(3.0));
144  CPPUNIT_ASSERT(bbox.min()(1) <= Real(-4.0));
145  CPPUNIT_ASSERT(bbox.max()(1) >= Real(5.0));
146 
147  // Do serial assertions *after* all parallel assertions, so we
148  // stay in sync after failure on only some processor(s)
149  for (auto & elem : mesh.element_ptr_range())
150  CPPUNIT_ASSERT(elem->has_affine_map());
151  }
152 
153  void testBuildCube(UnstructuredMesh & mesh, unsigned int n, ElemType type)
154  {
155  MeshTools::Generation::build_cube (mesh, n, n, n, -2.0, 3.0, -4.0, 5.0, -6.0, 7.0, type);
156  switch (Elem::type_to_n_sides_map[type])
157  {
158  case 4: // tets
159  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n*24));
160  break;
161  case 5: // prisms, pyramids
162  if (type == PRISM6 || type == PRISM15 || type == PRISM18 ||
163  type == PRISM20 || type == PRISM21)
164  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n*2));
165  else
166  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n*6));
167  break;
168  case 6: // hexes
169  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), cast_int<dof_id_type>(n*n*n));
170  break;
171  default:
172  libmesh_error();
173  }
174 
175 
176  switch (Elem::type_to_n_nodes_map[type])
177  {
178  case 4: // First-order tets
179  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
180  cast_int<dof_id_type>((n+1)*(n+1)*(n+1) + n*n*n + 3*(n+1)*n*n));
181  break;
182  case 6: // First-order prisms and hexes use the same nodes
183  case 8:
184  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
185  cast_int<dof_id_type>((n+1)*(n+1)*(n+1)));
186  break;
187  case 10: // Second-order tets
188  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
189  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 14*n*n*n + 4*3*(n+1)*n*n));
190  break;
191  case 18:
192  case 27: // Second-order prisms and hexes use the same nodes
193  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
194  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1)));
195  break;
196  case 20:
197  if (type == HEX20)
198  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
199  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) - n*n*n - 3*(n+1)*n*n));
200  if (type == PRISM20)
201  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
202  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 2*(n+1)*n*n));
203  break;
204  case 21: // Prisms based on full Tri7 cross sections
205  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
206  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 2*(2*n+1)*n*n));
207  break;
208  case 15: // weird partial order prism
209  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
210  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) - n*n*n - 2*(n+1)*n*n));
211  break;
212  case 5: // pyramids
213  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
214  cast_int<dof_id_type>((n+1)*(n+1)*(n+1) + n*n*n));
215  break;
216  case 13:
217  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
218  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 8*n*n*n - 3*(n+1)*n*n));
219  break;
220  case 14: // pyramids, tets
221  if (type == PYRAMID14)
222  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
223  cast_int<dof_id_type>((2*n+1)*(2*n+1)*(2*n+1) + 8*n*n*n));
224  else // TET14
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  36*n*n*n + 4*3*(n+1)*n*n));
228  break;
229  default:
230  libmesh_error();
231  }
232 
233  // Our bounding boxes can be loose on higher order elements, but
234  // we can at least assert that they're not too tight
236  CPPUNIT_ASSERT(bbox.min()(0) <= Real(-2.0));
237  CPPUNIT_ASSERT(bbox.max()(0) >= Real(3.0));
238  CPPUNIT_ASSERT(bbox.min()(1) <= Real(-4.0));
239  CPPUNIT_ASSERT(bbox.max()(1) >= Real(5.0));
240  CPPUNIT_ASSERT(bbox.min()(2) <= Real(-6.0));
241  CPPUNIT_ASSERT(bbox.max()(2) >= Real(7.0));
242 
243  // We don't yet try to do affine map optimizations on pyramids
244  if (type == PYRAMID5 ||
245  type == PYRAMID13 ||
246  type == PYRAMID14)
247  return;
248 
249  // Do serial assertions *after* all parallel assertions, so we
250  // stay in sync after failure on only some processor(s)
251  for (auto & elem : mesh.element_ptr_range())
252  CPPUNIT_ASSERT(elem->has_affine_map());
253  }
254 
255  void testBuildSphere(unsigned int n_ref, ElemType type)
256  {
258  MeshTools::Generation::build_sphere (rmesh, 2.0, n_ref, type);
259 
261  dmesh.allow_renumbering(false);
262  MeshTools::Generation::build_sphere (dmesh, 2.0, n_ref, type);
263  }
264 
265 
266  typedef void (MeshGenerationTest::*Builder)(UnstructuredMesh&, unsigned int, ElemType);
267 
268  void tester(Builder f, unsigned int n, ElemType type)
269  {
270  for (int is_replicated = 0; is_replicated != 2; ++is_replicated)
271  {
272  for (int skip_renumber = 0 ; skip_renumber != 2; ++skip_renumber)
273  {
274  std::unique_ptr<UnstructuredMesh> mesh =
275  new_mesh(is_replicated);
276  mesh->allow_renumbering(!skip_renumber);
277  (this->*f)(*mesh, n, type);
278  }
279  }
280  }
281 
285 
286  void buildSphereEdge2 () { LOG_UNIT_TEST; testBuildSphere(2, EDGE2); }
287  void buildSphereEdge3 () { LOG_UNIT_TEST; testBuildSphere(2, EDGE3); }
288  void buildSphereEdge4 () { LOG_UNIT_TEST; testBuildSphere(2, EDGE4); }
289 
296 
297  void buildSphereTri3 () { LOG_UNIT_TEST; testBuildSphere(2, TRI3); }
298  void buildSphereQuad4 () { LOG_UNIT_TEST; testBuildSphere(2, QUAD4); }
299 
300  void buildCubeTet4 () { LOG_UNIT_TEST; tester(&MeshGenerationTest::testBuildCube, 2, TET4); }
303  void buildCubeHex8 () { LOG_UNIT_TEST; tester(&MeshGenerationTest::testBuildCube, 2, HEX8); }
311 
312  // These tests throw an exception from contains_point() calls, and
313  // this simply aborts() when exceptions are not enabled.
314 #ifdef LIBMESH_ENABLE_EXCEPTIONS
318 #endif
319 
320  void buildSphereHex8 () { LOG_UNIT_TEST; testBuildSphere(2, HEX8); }
321  void buildSphereHex27 () { LOG_UNIT_TEST; testBuildSphere(2, HEX27); }
322 };
323 
324 
ElemType
Defines an enum for geometric element types.
void testBuildLine(UnstructuredMesh &mesh, unsigned int n, ElemType type)
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
void testBuildCube(UnstructuredMesh &mesh, unsigned int n, ElemType type)
void build_sphere(UnstructuredMesh &mesh, const Real rad=1, const unsigned int nr=2, const ElemType type=INVALID_ELEM, const unsigned int n_smooth=2, const bool flat=true)
Meshes a spherical or mapped-spherical domain.
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:685
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:1196
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:171
libMesh::BoundingBox create_bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:559
MeshBase & mesh
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.
The libMesh namespace provides an interface to certain functionality in the library.
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:650
std::unique_ptr< UnstructuredMesh > new_mesh(bool is_replicated)
void testBuildSquare(UnstructuredMesh &mesh, unsigned int n, ElemType type)
The UnstructuredMesh class is derived from the MeshBase class.
const Point & min() const
Definition: bounding_box.h:77
CPPUNIT_TEST_SUITE_REGISTRATION(MeshGenerationTest)
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
void tester(Builder f, unsigned int n, ElemType type)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void tester(const std::set< int > &s, int i)
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.
const Point & max() const
Definition: bounding_box.h:86
virtual dof_id_type n_elem() const =0
void ErrorVector unsigned int
Definition: adjoints_ex3.C:360
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.
virtual dof_id_type n_nodes() const =0
void testBuildSphere(unsigned int n_ref, ElemType type)