libMesh
mesh_input.C
Go to the documentation of this file.
1 #include <libmesh/distributed_mesh.h>
2 #include <libmesh/dof_map.h>
3 #include <libmesh/equation_systems.h>
4 #include <libmesh/linear_implicit_system.h>
5 #include <libmesh/mesh.h>
6 #include <libmesh/mesh_communication.h>
7 #include <libmesh/mesh_generation.h>
8 #include <libmesh/numeric_vector.h>
9 #include <libmesh/replicated_mesh.h>
10 #include <libmesh/enum_norm_type.h>
11 #include <libmesh/enum_to_string.h>
12 
13 #include <libmesh/abaqus_io.h>
14 #include <libmesh/dyna_io.h>
15 #include <libmesh/exodusII_io.h>
16 #include <libmesh/gmsh_io.h>
17 #include <libmesh/nemesis_io.h>
18 #include <libmesh/stl_io.h>
19 #include <libmesh/vtk_io.h>
20 #include <libmesh/tetgen_io.h>
21 
22 #include "test_comm.h"
23 #include "libmesh_cppunit.h"
24 
25 #include <regex>
26 
27 using namespace libMesh;
28 
29 
31  const Parameters&,
32  const std::string&,
33  const std::string&)
34 {
35  const Real & x = p(0);
36  const Real & y = p(1);
37 
38  return 6*x + 60*y;
39 }
40 
41 
43  const Parameters&,
44  const std::string&,
45  const std::string&)
46 {
47  const Real & x = p(0);
48  const Real & y = p(1);
49 
50  return sin(x) + cos(y);
51 }
52 
53 constexpr int added_sides_nxyz[] = {2,2,2};
54 
56  const Parameters & param,
57  const std::string &,
58  const std::string &)
59 {
60  const Real & x = p(0);
61  const Real & y = p(1);
62  const Real & z = p(2);
63 
64  short facedim = param.have_parameter<short>("face") ?
65  param.get<short>("face") : -1;
66 
67  // What face are we on?
68  auto is_on_face = [facedim](Real r, short rdim) {
69  if (facedim == rdim)
70  return true;
71  if (facedim >= 0)
72  return false;
73  const Real numerator = r * added_sides_nxyz[rdim];
74  return (std::abs(numerator - std::round(numerator)) <
76  };
77 
78 
79 
80  // x/y/z components of a div-free flux,
81  // curl([x^2yz, xy^2z, xyz])
82  if (is_on_face(x, 0))
83  {
84  libmesh_assert(!is_on_face(y, 1));
85  libmesh_assert(!is_on_face(z, 2));
86  return (x*z-x*y*y);
87  }
88  if (is_on_face(y, 1))
89  {
90  libmesh_assert(!is_on_face(z, 2));
91  return (x*x*y-y*z);
92  }
93 
94  libmesh_assert(is_on_face(z, 2));
95  return (y*y*z-x*x*z);
96 }
97 
98 
99 class MeshInputTest : public CppUnit::TestCase {
100 public:
101  LIBMESH_CPPUNIT_TEST_SUITE( MeshInputTest );
102 
103 #if LIBMESH_DIM > 1
104 #ifdef LIBMESH_HAVE_VTK
105  CPPUNIT_TEST( testVTKPreserveElemIds );
106  CPPUNIT_TEST( testVTKPreserveSubdomainIds );
107 #endif
108 
109 #ifdef LIBMESH_HAVE_EXODUS_API
110  CPPUNIT_TEST( testExodusCopyNodalSolutionDistributed );
111  CPPUNIT_TEST( testExodusCopyElementSolutionDistributed );
112  CPPUNIT_TEST( testExodusCopyNodalSolutionReplicated );
113  CPPUNIT_TEST( testExodusCopyElementSolutionReplicated );
114  CPPUNIT_TEST( testExodusReadHeader );
115  CPPUNIT_TEST( testExodusSetNodeUniqueIdsFromMaps );
116  CPPUNIT_TEST( testExodusSetElemUniqueIdsFromMaps );
117 #if LIBMESH_DIM > 2
118  CPPUNIT_TEST( testExodusIGASidesets );
119  CPPUNIT_TEST( testLowOrderEdgeBlocks );
120 #endif
121 #ifndef LIBMESH_USE_COMPLEX_NUMBERS
122  CPPUNIT_TEST( testExodusCopyElementVectorDistributed );
123  CPPUNIT_TEST( testExodusCopyElementVectorReplicated );
124 
125  // Eventually this will support complex numbers.
126  CPPUNIT_TEST( testExodusWriteElementDataFromDiscontinuousNodalData );
127 #endif // !LIBMESH_USE_COMPLEX_NUMBERS
128 
129  CPPUNIT_TEST( testExodusWriteAddedSidesEdgeC0 );
130  CPPUNIT_TEST( testExodusDiscWriteAddedSidesEdgeC0 );
131  CPPUNIT_TEST( testExodusWriteAddedSidesMixedEdgeC0 );
132  CPPUNIT_TEST( testExodusDiscWriteAddedSidesMixedEdgeC0 );
133  // CPPUNIT_TEST( testExodusDiscWriteAddedSidesEdgeDisc ); // need is_on_face fixes
134  // CPPUNIT_TEST( testExodusDiscWriteAddedSidesEdgeDisc ); // need is_on_face fixes
135  CPPUNIT_TEST( testExodusWriteAddedSidesTriC0 );
136  CPPUNIT_TEST( testExodusDiscWriteAddedSidesTriC0 );
137  CPPUNIT_TEST( testExodusWriteAddedSidesMixedTriC0 );
138  CPPUNIT_TEST( testExodusDiscWriteAddedSidesMixedTriC0 );
139  // CPPUNIT_TEST( testExodusWriteAddedSidesTriDisc ); // Need aligned faces
140  // CPPUNIT_TEST( testExodusDiscWriteAddedSidesTriDisc ); // Need aligned faces
141  CPPUNIT_TEST( testExodusWriteAddedSidesQuadC0 );
142  CPPUNIT_TEST( testExodusDiscWriteAddedSidesQuadC0 );
143  CPPUNIT_TEST( testExodusWriteAddedSidesMixedQuadC0 );
144  CPPUNIT_TEST( testExodusDiscWriteAddedSidesMixedQuadC0 );
145  // CPPUNIT_TEST( testExodusWriteAddedSidesQuadDisc ); // need is_on_face fixes
146  // CPPUNIT_TEST( testExodusDiscWriteAddedSidesQuadDisc ); // need is_on_face fixes
147  // CPPUNIT_TEST( testExodusWriteAddedSidesTetC0 ); // BROKEN!?! WHY!?!
148  // CPPUNIT_TEST( testExodusDiscWriteAddedSidesTetC0 ); // BROKEN!?! WHY!?!
149  // CPPUNIT_TEST( testExodusWriteAddedSidesTetDisc );
150  // CPPUNIT_TEST( testExodusDiscWriteAddedSidesTetDisc );
151  CPPUNIT_TEST( testExodusWriteAddedSidesHexC0 );
152  CPPUNIT_TEST( testExodusDiscWriteAddedSidesHexC0 );
153  CPPUNIT_TEST( testExodusWriteAddedSidesMixedHexC0 );
154  CPPUNIT_TEST( testExodusDiscWriteAddedSidesMixedHexC0 );
155  CPPUNIT_TEST( testExodusWriteAddedSidesHexDisc );
156  CPPUNIT_TEST( testExodusDiscWriteAddedSidesHexDisc );
157 
158  CPPUNIT_TEST( testExodusFileMappingsPlateWithHole);
159  CPPUNIT_TEST( testExodusFileMappingsTwoBlocks);
160  CPPUNIT_TEST( testExodusFileMappingsTwoElemIGA);
161  CPPUNIT_TEST( testExodusFileMappingsCyl3d);
162 
163  CPPUNIT_TEST( testExodusDiscPlateWithHole);
164  CPPUNIT_TEST( testExodusDiscTwoBlocks);
165  CPPUNIT_TEST( testExodusDiscTwoElemIGA);
166  CPPUNIT_TEST( testExodusDiscCyl3d);
167 #endif // LIBMESH_HAVE_EXODUS_API
168 
169 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
170  CPPUNIT_TEST( testNemesisReadReplicated );
171  CPPUNIT_TEST( testNemesisReadDistributed );
172 
173  CPPUNIT_TEST( testNemesisCopyNodalSolutionDistributed );
174  CPPUNIT_TEST( testNemesisCopyNodalSolutionReplicated );
175  CPPUNIT_TEST( testNemesisCopyElementSolutionDistributed );
176  CPPUNIT_TEST( testNemesisCopyElementSolutionReplicated );
177 
178  CPPUNIT_TEST( testNemesisSingleElementDistributed );
179  CPPUNIT_TEST( testNemesisSingleElementReplicated );
180 #ifndef LIBMESH_USE_COMPLEX_NUMBERS
181  CPPUNIT_TEST( testNemesisCopyElementVectorDistributed );
182  CPPUNIT_TEST( testNemesisCopyElementVectorReplicated );
183 #endif // !LIBMESH_USE_COMPLEX_NUMBERS
184 #endif // defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
185 
186 #ifdef LIBMESH_HAVE_GZSTREAM
187  CPPUNIT_TEST( testAbaqusReadFirst );
188  CPPUNIT_TEST( testAbaqusReadSecond );
189  CPPUNIT_TEST( testDynaReadElem );
190  CPPUNIT_TEST( testDynaNoSplines );
191  CPPUNIT_TEST( testDynaReadPatch );
192  CPPUNIT_TEST( testDynaFileMappingsFEMEx5);
193  CPPUNIT_TEST( testDynaFileMappingsBlockWithHole);
194  CPPUNIT_TEST( testDynaFileMappingsPlateWithHole);
195  CPPUNIT_TEST( testDynaFileMappingsCyl3d);
196 #endif // LIBMESH_HAVE_GZSTREAM
197 #endif // LIBMESH_DIM > 1
198  //
199 #if LIBMESH_DIM > 1
200  CPPUNIT_TEST( testBadGmsh );
201  CPPUNIT_TEST( testGoodGmsh );
202 #endif
203 
204 #if LIBMESH_DIM > 2
205  CPPUNIT_TEST( testGoodSTL );
206  CPPUNIT_TEST( testGoodSTLBinary );
207 
208  CPPUNIT_TEST( testGmshBCIDOverlap );
209 
210 #ifdef LIBMESH_HAVE_TETGEN
211  CPPUNIT_TEST( testTetgenIO );
212 #endif
213 #endif
214 
215  CPPUNIT_TEST_SUITE_END();
216 
217 private:
218 
219 public:
220  void setUp()
221  {}
222 
223  void tearDown()
224  {}
225 
226 #ifdef LIBMESH_HAVE_VTK
228  {
229  LOG_UNIT_TEST;
230 
231  // Come up with some crazy numbering. Make all the new ids higher
232  // than the existing ids so we don't have to worry about conflicts
233  // while renumbering.
234  dof_id_type start_id;
235 
236  // first scope: write file
237  {
239  mesh.allow_renumbering(false);
240  MeshTools::Generation::build_square (mesh, 3, 3, 0., 1., 0., 1.);
241 
242  start_id = mesh.max_elem_id();
243 
244  // Use a separate container that won't invalidate iterators when
245  // we renumber
246  std::set<Elem *> elements {mesh.elements_begin(), mesh.elements_end()};
247  for (Elem * elem : elements)
248  {
249  const Point center = elem->vertex_average();
250  const int xn = int(center(0)*3);
251  const int yn = int(center(1)*3);
252  const dof_id_type new_id = start_id + yn*5 + xn;
253  mesh.renumber_elem(elem->id(), new_id);
254  }
255 
256  // Explicit writer object here to be absolutely sure we get VTK
257  VTKIO vtk(mesh);
258  vtk.write("read_elem_ids_test.pvtu");
259  }
260 
261  // Make sure that the writing is done before the reading starts.
263 
264  // second scope: read file
265  {
267  mesh.allow_renumbering(false);
268 
269  mesh.read("read_elem_ids_test.pvtu");
271 
272  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), dof_id_type(16));
273  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(9));
274 
275  for (const auto & elem : mesh.element_ptr_range())
276  {
277  const Point center = elem->vertex_average();
278  const int xn = int(center(0)*3);
279  const int yn = int(center(1)*3);
280  const dof_id_type expected_id = start_id + yn*5 + xn;
281  CPPUNIT_ASSERT_EQUAL(elem->id(), expected_id);
282  }
283  }
284  }
285 
287  {
288  LOG_UNIT_TEST;
289 
290  // first scope: write file
291  {
293  mesh.allow_renumbering(false);
294  MeshTools::Generation::build_square (mesh, 3, 3, 0., 1., 0., 1.);
295 
296  for (const auto & elem : mesh.element_ptr_range())
297  {
298  const Point center = elem->vertex_average();
299  const int xn = int(center(0)*3);
300  const int yn = int(center(1)*3);
301  const subdomain_id_type new_id = yn*4 + xn;
302  elem->subdomain_id() = new_id;
303  }
304 
305  // Explicit writer object here to be absolutely sure we get VTK
306  VTKIO vtk(mesh);
307  vtk.write("read_sbd_ids_test.pvtu");
308  }
309 
310  // Make sure that the writing is done before the reading starts.
312 
313  // second scope: read file
314  {
316  mesh.allow_renumbering(false);
317 
318  mesh.read("read_sbd_ids_test.pvtu");
320 
321  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), dof_id_type(16));
322  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(9));
323 
324  for (const auto & elem : mesh.element_ptr_range())
325  {
326  const Point center = elem->vertex_average();
327  const int xn = int(center(0)*3);
328  const int yn = int(center(1)*3);
329  const subdomain_id_type expected_id = yn*4 + xn;
330  CPPUNIT_ASSERT_EQUAL(elem->subdomain_id(), expected_id);
331  }
332  }
333  }
334 #endif // LIBMESH_HAVE_VTK
335 
336 
337 #ifdef LIBMESH_HAVE_EXODUS_API
338 
340  bool set_unique_ids,
341  const std::vector<unique_id_type> & expected_unique_ids)
342  {
343  // This test requires that libmesh is compiled with unique_ids enabled
344 #ifdef LIBMESH_ENABLE_UNIQUE_ID
345  {
347  ExodusII_IO exii(mesh);
348 
349  // Set Node/Elem unique ids based on the node/elem_num_map
350  exii.set_unique_ids_from_maps(set_unique_ids);
351 
352  // Read the mesh
353  exii.read("meshes/nontrivial_node_num_map.exo");
354 
355  // Verify the results.
356  for (auto i : index_range(expected_unique_ids))
357  {
358  // Debugging:
359  // libMesh::out << "unique_id for node " << i
360  // << " = " << mesh.node_ptr(i)->unique_id()
361  // << std::endl;
362 
363  CPPUNIT_ASSERT_EQUAL(mesh.node_ptr(i)->unique_id(), expected_unique_ids[i]);
364  }
365  }
366 #else
367  // Prevent compiler warnings about unused variables when
368  // unique_ids are not enabled.
369  libmesh_ignore(set_unique_ids, expected_unique_ids);
370 #endif // LIBMESH_ENABLE_UNIQUE_ID
371  } // end testExodusSetNodeUniqueIdsFromMaps_implementation()
372 
373 
374 
376  {
377  LOG_UNIT_TEST;
378 
379  // node_num_map = 1, 3, 9, 8, 2, 5, 7, 6, 4
380  // The input is a (zero-based) version of the node_num_map as it
381  // exists in the file.
382  this->testExodusSetNodeUniqueIdsFromMaps_implementation(
383  /*set_unique_ids=*/true,
384  /*expected_unique_ids=*/{0, 2, 8, 7, 1, 4, 6, 5, 3});
385 
386  // The input is the (zero-based) _position_ of the (one-based) id
387  // "i" in the node_num_map, as it exists in the file. For example,
388  // zero-based Node id 3 corresponds to one-based Node id 4, which
389  // appears in (zero-based) position 8 in the node_num_map, hence:
390  // 3 -> 8, etc.
391  this->testExodusSetNodeUniqueIdsFromMaps_implementation(
392  /*set_unique_ids=*/false,
393  /*expected_unique_ids=*/{0, 4, 1, 8, 5, 7, 6, 3, 2});
394  }
395 
397  bool set_unique_ids,
398  const std::vector<unique_id_type> & expected_unique_ids)
399  {
400  // This test requires that libmesh is compiled with unique_ids enabled
401 #ifdef LIBMESH_ENABLE_UNIQUE_ID
402  {
404  ExodusII_IO exii(mesh);
405 
406  // Set Node/Elem unique ids based on the node/elem_num_map
407  exii.set_unique_ids_from_maps(set_unique_ids);
408 
409  // Read the mesh
410  exii.read("meshes/nontrivial_elem_num_map.exo");
411 
412  // Verify the results.
413  auto expected_it = expected_unique_ids.begin();
414  for (const auto & elem : mesh.element_ptr_range())
415  {
416  // Debugging:
417  // libMesh::out << "unique_id for Elem " << elem->id()
418  // << " = " << elem->unique_id()
419  // << std::endl;
420 
421  CPPUNIT_ASSERT_EQUAL(elem->unique_id(), *expected_it++);
422  }
423  }
424 #else
425  // Prevent compiler warnings about unused variables when
426  // unique_ids are not enabled.
427  libmesh_ignore(set_unique_ids, expected_unique_ids);
428 #endif // LIBMESH_ENABLE_UNIQUE_ID
429  }
430 
432  {
433  LOG_UNIT_TEST;
434 
435  // The mesh used in this test has a non-trivial elem_num_map with
436  // a non-contiguous numbering that has a "gap" at the beginning
437  // and is also missing "16":
438  // elem_num_map = 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
439  // 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
440  // 45, 46 ;
441  {
442  // When we assign (zero-based) elem_num_map entries as unique_ids, the
443  // unique_ids are just a zero-based version of the entries above.
444  std::vector<unique_id_type> expected_unique_ids = {
445  10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
446  30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45};
447  this->testExodusSetElemUniqueIdsFromMaps_implementation(
448  /*set_unique_ids=*/true, expected_unique_ids);
449  }
450 
451  {
452  // When libmesh assigns unique_ids, all the Nodes (50) are
453  // numbered first, so the first Elem is assigned a unique_id of
454  // 50 and the rest are sequential from there.
455  std::vector<unique_id_type> expected_unique_ids(/*size=*/35);
456  std::iota(expected_unique_ids.begin(), expected_unique_ids.end(), /*start=*/50);
457  this->testExodusSetElemUniqueIdsFromMaps_implementation(
458  /*set_unique_ids=*/false, expected_unique_ids);
459  }
460  }
461 
463  {
464  LOG_UNIT_TEST;
465 
466  // first scope: write file
467  {
469  MeshTools::Generation::build_square (mesh, 3, 3, 0., 1., 0., 1.);
470  ExodusII_IO exii(mesh);
471  mesh.write("read_header_test.e");
472  }
473 
474  // Make sure that the writing is done before the reading starts.
476 
477  // second scope: read header
478  // Note: The header information is read from file on processor 0
479  // and then broadcast to the other procs, so with this test we are
480  // checking both that the header information is read correctly and
481  // that it is correctly communicated to other procs.
482  {
484  ExodusII_IO exii(mesh);
485  ExodusHeaderInfo header_info = exii.read_header("read_header_test.e");
486 
487  // Make sure the header information is as expected.
488  CPPUNIT_ASSERT_EQUAL(std::string(header_info.title.data()), std::string("read_header_test.e"));
489  CPPUNIT_ASSERT_EQUAL(header_info.num_dim, 2);
490  CPPUNIT_ASSERT_EQUAL(header_info.num_elem, 9);
491  CPPUNIT_ASSERT_EQUAL(header_info.num_elem_blk, 1);
492  CPPUNIT_ASSERT_EQUAL(header_info.num_node_sets, 4);
493  CPPUNIT_ASSERT_EQUAL(header_info.num_side_sets, 4);
494  CPPUNIT_ASSERT_EQUAL(header_info.num_edge_blk, 0);
495  CPPUNIT_ASSERT_EQUAL(header_info.num_edge, 0);
496  }
497  }
498 
500  {
501  LOG_UNIT_TEST;
502 
504  ExodusII_IO exii(mesh);
505 
506  if (mesh.processor_id() == 0)
507  exii.read("meshes/mesh_with_low_order_edge_blocks.e");
508 
511 
512  // Check that we see the boundary ids we expect
514 
515  // On a ReplicatedMesh, check that the number of edge boundary
516  // conditions is as expected. The real test is that we can read
517  // this file in at all. Prior to the changes in #3491, the Exodus
518  // reader threw an exception while trying to read this mesh.
519  if (mesh.is_serial())
520  {
521  // Mesh has 26 boundary ids total (including edge and side ids).
522  // ss_prop1 = 200, 201 ;
523  // ed_prop1 = 8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, 8008, 8009, 8010,
524  // 8011, 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009, 9010,
525  // 9011, 9012 ;
526  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(26), bi.n_boundary_ids());
527 
528  // We can binary_search() the build_edge_list() which is sorted
529  // in lexicographical order before it's returned.
530  auto edge_list = bi.build_edge_list();
531 
532  // Search for some tuples we expect to be present
533  CPPUNIT_ASSERT(std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(4, 1, 8007)));
534  CPPUNIT_ASSERT(std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(10, 6, 8001)));
535 
536  // And make sure we don't have entries we shouldn't have
537  CPPUNIT_ASSERT(!std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(1, 8, 8009)));
538  CPPUNIT_ASSERT(!std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(2, 10, 9011)));
539  }
540  }
541 
543  {
544  LOG_UNIT_TEST;
545 
547 
548  // Block here so we trigger exii destructor early; I thought I
549  // might have had a bug in there at one point
550  {
551  ExodusII_IO exii(mesh);
552  // IGA Exodus meshes require ExodusII 8 or higher
553  if (exii.get_exodus_version() < 800)
554  return;
555 
556  if (mesh.processor_id() == 0)
557  exii.read("meshes/Cube_With_Sidesets.e");
558 
559  }
560 
563 
564  // 5^3 spline nodes + 7^3 Rational Bezier nodes
565  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(468));
566  // 5^3 spline elements + 3^3 Rational Bezier elements
567  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(152));
568 
569  // Check that we see the boundary ids we expect
571 
572  // On a ReplicatedMesh, we should see all 6 boundary ids on each processor
573  if (mesh.is_serial())
574  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(6), bi.n_boundary_ids());
575 
576  // On any mesh, we should see each id on *some* processor
577  {
578  const std::set<boundary_id_type> & bc_ids = bi.get_boundary_ids();
579  // CoreForm gave me a file with 1-based numbering! (faints)
580  for (boundary_id_type i = 1 ; i != 7; ++i)
581  {
582  bool has_bcid = bc_ids.count(i);
583  mesh.comm().max(has_bcid);
584  CPPUNIT_ASSERT(has_bcid);
585  }
586  }
587 
588  // Indexed by bcid-1, because we count from 0, like God and
589  // Dijkstra intended!
590  std::vector<int> side_counts(6, 0);
591 
592  // Map from our side numbers to the file's BCIDs
593  const boundary_id_type libmesh_side_to_bcid[] = {1, 4, 6, 3, 5, 2};
594 
595  for (const auto & elem : mesh.active_local_element_ptr_range())
596  {
597  if (elem->type() == NODEELEM)
598  continue;
599 
600  for (unsigned short side=0; side<elem->n_sides(); side++)
601  {
602  if (elem->neighbor_ptr(side))
603  CPPUNIT_ASSERT_EQUAL(bi.n_boundary_ids(elem, side), 0u);
604  else
605  {
606  CPPUNIT_ASSERT_EQUAL(bi.n_boundary_ids(elem, side), 1u);
607  std::vector<boundary_id_type> bids;
608  bi.boundary_ids(elem, side, bids);
609  side_counts[bids[0]-1]++;
610  CPPUNIT_ASSERT_EQUAL(libmesh_side_to_bcid[side], bids[0]);
611  }
612  }
613  }
614 
615  for (auto bc_count : side_counts)
616  {
617  // We should have 3^2 sides with each id
618  mesh.comm().sum(bc_count);
619  CPPUNIT_ASSERT_EQUAL(bc_count, 9);
620  }
621 
622  // Test a write when we're done reading; I was getting weirdness
623  // from NetCDF at this point in a Moose output test.
624  {
625  ExodusII_IO exii(mesh);
626 
627  exii.write("Cube_With_Sidesets_out.e");
628  }
629  }
630 
631 
632  template <typename MeshType, typename IOType>
633  void testCopyNodalSolutionImpl (const std::string & filename)
634  {
635  {
636  MeshType mesh(*TestCommWorld);
637 
638  EquationSystems es(mesh);
639  System &sys = es.add_system<System> ("SimpleSystem");
640  sys.add_variable("n", FIRST, LAGRANGE);
641 
643  3, 3,
644  0., 1., 0., 1.);
645 
646  es.init();
648 
649  IOType meshoutput(mesh);
650 
651  meshoutput.write_equation_systems(filename, es);
652  }
653 
654  {
655  MeshType mesh(*TestCommWorld);
656  mesh.allow_renumbering(false);
657  IOType meshinput(mesh);
658 
659  // Avoid getting Nemesis solution values mixed up
660  if (meshinput.is_parallel_format())
661  {
663  }
664 
665  EquationSystems es(mesh);
666  System &sys = es.add_system<System> ("SimpleSystem");
667  sys.add_variable("testn", FIRST, LAGRANGE);
668 
669  if (mesh.processor_id() == 0 || meshinput.is_parallel_format())
670  meshinput.read(filename);
671  if (!meshinput.is_parallel_format())
674 
675  es.init();
676 
677  // Read the solution e into variable teste.
678  //
679  // With complex numbers, we'll only bother reading the real
680  // part.
681 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
682  meshinput.copy_nodal_solution(sys, "testn", "r_n");
683 #else
684  meshinput.copy_nodal_solution(sys, "testn", "n");
685 #endif
686 
687  // Exodus only handles double precision
688  Real exotol = std::max(TOLERANCE*TOLERANCE, Real(1e-12));
689 
690  for (Real x = 0; x < 1 + TOLERANCE; x += Real(1.L/3.L))
691  for (Real y = 0; y < 1 + TOLERANCE; y += Real(1.L/3.L))
692  {
693  Point p(x,y);
694  LIBMESH_ASSERT_NUMBERS_EQUAL
695  (sys.point_value(0,p), 6*x+60*y, exotol);
696  }
697  }
698  }
699 
700 
702  { LOG_UNIT_TEST; testCopyNodalSolutionImpl<ReplicatedMesh,ExodusII_IO>("repl_with_nodal_soln.e"); }
703 
705  { LOG_UNIT_TEST; testCopyNodalSolutionImpl<DistributedMesh,ExodusII_IO>("dist_with_nodal_soln.e"); }
706 
707 #if defined(LIBMESH_HAVE_NEMESIS_API)
709  { LOG_UNIT_TEST; testCopyNodalSolutionImpl<ReplicatedMesh,Nemesis_IO>("repl_with_nodal_soln.nem"); }
710 
712  { LOG_UNIT_TEST; testCopyNodalSolutionImpl<DistributedMesh,Nemesis_IO>("dist_with_nodal_soln.nem"); }
713 #endif
714 
715 
716  template <typename MeshType, typename IOType>
717  void testCopyElementSolutionImpl (const std::string & filename)
718  {
719  {
720  MeshType mesh(*TestCommWorld);
721 
722  EquationSystems es(mesh);
723  System &sys = es.add_system<System> ("SimpleSystem");
724  sys.add_variable("e", CONSTANT, MONOMIAL);
725 
727  3, 3,
728  0., 1., 0., 1.);
729 
730  es.init();
732 
733  IOType meshinput(mesh);
734 
735  // Don't try to write element data as nodal data
736  std::set<std::string> sys_list;
737  meshinput.write_equation_systems(filename, es, &sys_list);
738 
739  // Just write it as element data
740  meshinput.write_element_data(es);
741  }
742 
743  {
744  MeshType mesh(*TestCommWorld);
745  mesh.allow_renumbering(false);
746  IOType meshinput(mesh);
747 
748  // Avoid getting Nemesis solution values mixed up
749  if (meshinput.is_parallel_format())
750  {
752  }
753 
754  EquationSystems es(mesh);
755  System &sys = es.add_system<System> ("SimpleSystem");
756  sys.add_variable("teste", CONSTANT, MONOMIAL);
757 
758  if (mesh.processor_id() == 0 || meshinput.is_parallel_format())
759  meshinput.read(filename);
760  if (!meshinput.is_parallel_format())
763 
764  es.init();
765 
766  // Read the solution e into variable teste.
767  //
768  // With complex numbers, we'll only bother reading the real
769  // part.
770 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
771  meshinput.copy_elemental_solution(sys, "teste", "r_e");
772 #else
773  meshinput.copy_elemental_solution(sys, "teste", "e");
774 #endif
775 
776  // Exodus only handles double precision
777  Real exotol = std::max(TOLERANCE*TOLERANCE, Real(1e-12));
778 
779  for (Real x = Real(1.L/6.L); x < 1; x += Real(1.L/3.L))
780  for (Real y = Real(1.L/6.L); y < 1; y += Real(1.L/3.L))
781  {
782  Point p(x,y);
783  LIBMESH_ASSERT_NUMBERS_EQUAL
784  (sys.point_value(0,p), 6*x+60*y, exotol);
785  }
786  }
787  }
788 
789 
791  { LOG_UNIT_TEST; testCopyElementSolutionImpl<ReplicatedMesh,ExodusII_IO>("repl_with_elem_soln.e"); }
792 
794  { LOG_UNIT_TEST; testCopyElementSolutionImpl<DistributedMesh,ExodusII_IO>("dist_with_elem_soln.e"); }
795 
796 #if defined(LIBMESH_HAVE_NEMESIS_API)
798  { LOG_UNIT_TEST; testCopyElementSolutionImpl<ReplicatedMesh,Nemesis_IO>("repl_with_elem_soln.nem"); }
799 
801  { LOG_UNIT_TEST; testCopyElementSolutionImpl<DistributedMesh,Nemesis_IO>("dist_with_elem_soln.nem"); }
802 
803 
804  // This tests that a single-element mesh solution makes it through all of the API to write out a
805  // set of Nemesis files. When this executes in parallel, there are ((number of processors) - 1)
806  // subdomains with zero elements and therefore nothing to write, but the API should handle this.
807  template <typename MeshType, typename IOType>
808  void testSingleElementImpl(const std::string & filename)
809  {
810  {
811  // Generate a single 1x1 square element mesh
812  MeshType mesh(*TestCommWorld);
814 
815  EquationSystems es(mesh);
816  auto & sys = es.add_system<System>("SimpleSystem");
817  sys.add_variable("e", CONSTANT, MONOMIAL);
818 
819  // Set an arbitrary solution for the single element DOF
820  es.init();
821  sys.project_solution(six_x_plus_sixty_y, nullptr, es.parameters);
822 
823  // Write the solution to Nemesis file(s) - only proc 0 should have anything to write!
824  Nemesis_IO nem_io(mesh);
825  std::set<std::string> sys_list;
826  nem_io.write_equation_systems(filename, es, &sys_list);
827  nem_io.write_element_data(es);
828  }
829 
830  // If we can read and copy the correct element value back into the mesh, we know the Nemesis
831  // file(s) were written properly.
832  {
833  MeshType mesh(*TestCommWorld);
834  mesh.allow_renumbering(false);
835  EquationSystems es(mesh);
836  auto & sys = es.add_system<System>("SimpleSystem");
837  sys.add_variable("teste", CONSTANT, MONOMIAL);
838 
839  Nemesis_IO nem_io(mesh);
840  if (mesh.processor_id() == 0 || nem_io.is_parallel_format())
841  nem_io.read(filename);
842 
844  es.init();
845 
846 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
847  nem_io.copy_elemental_solution(sys, "teste", "r_e");
848 #else
849  nem_io.copy_elemental_solution(sys, "teste", "e");
850 #endif
851 
852  // The result should be '\frac{6 + 60}{2} = 33' at all points in the element domain
853  CPPUNIT_ASSERT_EQUAL(int(sys.solution->size()), 1);
854  CPPUNIT_ASSERT_EQUAL(libmesh_real(sys.point_value(0, Point(0.5, 0.5))), Real(33));
855  }
856  }
857 
858 
860  { LOG_UNIT_TEST; testSingleElementImpl<ReplicatedMesh,Nemesis_IO>("repl_with_single_elem.nem"); }
861 
863  { LOG_UNIT_TEST; testSingleElementImpl<DistributedMesh,Nemesis_IO>("dist_with_single_elem.nem"); }
864 #endif //defined(LIBMESH_HAVE_NEMESIS_API)
865 
866 
867 #ifndef LIBMESH_USE_COMPLEX_NUMBERS
868  // So this tester runs through pretty much the same process as 'testCopyElementSolutionImpl()'
869  // except for a CONSTANT MONOMIAL_VEC variable. It mainly serves as a test for writing elemental
870  // vector variables to elements in ExodusII files, and is not actually a test for reading and
871  // copying an elemental solution.
872  template <typename MeshType, typename IOType>
873  void testCopyElementVectorImpl(const std::string & filename)
874  {
875  {
876  MeshType mesh(*TestCommWorld);
877 
878  EquationSystems es(mesh);
879  System & sys = es.add_system<System> ("SimpleSystem");
880  auto e_var = sys.add_variable("e", CONSTANT, MONOMIAL_VEC);
881 
883  3, 3,
884  0., 1., 0., 1.);
885 
886  es.init();
887 
888  // Here, we're going to manually set up the solution because the 'project_solution()' and
889  // 'project_vector()' methods don't work so well with CONSTANT MONOMIAL_VEC variables. They
890  // each lead to an error downstream asserting positive-definiteness when Cholesky decomposing.
891  // Interestingly, the error is only invoked for CONSTANT MONOMIAL_VEC, and not, e.g.,
892  // CONSTANT MONOMIAL nor FIRST LAGRANGE_VEC.
893  //
894  // Anyways, the important thing here is that we test the ExodusII and Nemesis writers, how
895  // the solution is set is hardly important, and we're pretty much following the same
896  // philosophy as the 'test2DProjectVectorFE()' unit tester in 'systems_test.C'
897  Parameters params;
898  for (const auto & elem : mesh.active_local_element_ptr_range())
899  {
900  const Point & p = elem->vertex_average();
901 
902  // Set the x-component with the value from 'six_x_plus_sixty_y()' and the y-component
903  // with that from 'sin_x_plus_cos_y()' at the element centroid (vertex average)
904  sys.current_local_solution->set(
905  elem->dof_number(sys.number(), e_var, 0), six_x_plus_sixty_y(p, params, "", ""));
906  sys.current_local_solution->set(
907  elem->dof_number(sys.number(), e_var, 1), sin_x_plus_cos_y(p, params, "", ""));
908  }
909 
910  // After setting values, we need to assemble
911  sys.current_local_solution->close();
912 
913  IOType meshinput(mesh);
914 
915  // Don't try to write element data as nodal data
916  std::set<std::string> sys_list;
917  meshinput.write_equation_systems(filename, es, &sys_list);
918 
919  // Just write it as element data
920  meshinput.write_element_data(es);
921  }
922 
923  {
924  MeshType mesh(*TestCommWorld);
925  mesh.allow_renumbering(false);
926  IOType meshinput(mesh);
927 
928  // Avoid getting Nemesis solution values mixed up
929  if (meshinput.is_parallel_format())
930  {
932  }
933 
934  EquationSystems es(mesh);
935  System & sys = es.add_system<System> ("SimpleSystem");
936 
937  // We have to read the CONSTANT MONOMIAL_VEC var "e" into separate CONSTANT MONOMIAL vars
938  // "e_x" and "e_y" because 'copy_elemental_solution()' currently doesn't support vectors.
939  // Again, this isn't a test for reading/copying an elemental vector solution, only writing.
940  sys.add_variable("teste_x", CONSTANT, MONOMIAL);
941  sys.add_variable("teste_y", CONSTANT, MONOMIAL);
942 
943  if (mesh.processor_id() == 0 || meshinput.is_parallel_format())
944  meshinput.read(filename);
945  if (!meshinput.is_parallel_format())
948 
949  es.init();
950 
951  // Read the solution e_x and e_y into variable teste_x and teste_y, respectively.
952  meshinput.copy_elemental_solution(sys, "teste_x", "e_x");
953  meshinput.copy_elemental_solution(sys, "teste_y", "e_y");
954 
955  // Exodus only handles double precision
956  Real exotol = std::max(TOLERANCE*TOLERANCE, Real(1e-12));
957 
958  for (Real x = Real(1.L/6.L); x < 1; x += Real(1.L/3.L))
959  for (Real y = Real(1.L/6.L); y < 1; y += Real(1.L/3.L))
960  {
961  Point p(x,y);
962  LIBMESH_ASSERT_NUMBERS_EQUAL
963  (sys.point_value(0,p), 6*x+60*y, exotol);
964  LIBMESH_ASSERT_NUMBERS_EQUAL
965  (sys.point_value(1,p), sin(x)+cos(y), exotol);
966  }
967  }
968  }
969 
971  { LOG_UNIT_TEST; testCopyElementVectorImpl<ReplicatedMesh, ExodusII_IO>("repl_with_elem_vec.e"); }
972 
974  { LOG_UNIT_TEST; testCopyElementVectorImpl<DistributedMesh,ExodusII_IO>("dist_with_elem_vec.e"); }
975 
976 #if defined(LIBMESH_HAVE_NEMESIS_API)
978  { LOG_UNIT_TEST; testCopyElementVectorImpl<ReplicatedMesh,Nemesis_IO>("repl_with_elem_vec.nem"); }
979 
981  { LOG_UNIT_TEST; testCopyElementVectorImpl<DistributedMesh,Nemesis_IO>("dist_with_elem_vec.nem"); }
982 #endif
983 
984 
986  {
987  LOG_UNIT_TEST;
988 
989  // first scope: write file
990  {
992 
993  EquationSystems es(mesh);
994  System & sys = es.add_system<System> ("SimpleSystem");
995  sys.add_variable("u", FIRST, L2_LAGRANGE);
996 
998  (mesh, 2, 2, 2, 0., 1., 0., 1., 0., 1., HEX8);
999 
1000  es.init();
1001 
1002  // Set solution u^e_i = i, for the ith vertex of a given element e.
1003  const DofMap & dof_map = sys.get_dof_map();
1004  std::vector<dof_id_type> dof_indices;
1005  for (const auto & elem : mesh.element_ptr_range())
1006  {
1007  dof_map.dof_indices(elem, dof_indices, /*var_id=*/0);
1008  for (unsigned int i=0; i<dof_indices.size(); ++i)
1009  sys.solution->set(dof_indices[i], i);
1010  }
1011  sys.solution->close();
1012 
1013  // Now write to file.
1014  ExodusII_IO exii(mesh);
1015 
1016  // Don't try to write element data as averaged nodal data.
1017  std::set<std::string> sys_list;
1018  exii.write_equation_systems("elemental_from_nodal.e", es, &sys_list);
1019 
1020  // Write one elemental data field per vertex value.
1021  sys_list = {"SimpleSystem"};
1022 
1024  (es, &sys_list, /*var_suffix=*/"_elem_corner_");
1025  } // end first scope
1026 
1027  // second scope: read values back in, verify they are correct.
1028  {
1029  std::vector<std::string> file_var_names =
1030  {"u_elem_corner_0",
1031  "u_elem_corner_1",
1032  "u_elem_corner_2",
1033  "u_elem_corner_3"};
1034  std::vector<Real> expected_values = {0., 1., 2., 3.};
1035 
1036  // copy_elemental_solution currently requires ReplicatedMesh
1038  mesh.allow_renumbering(false);
1039 
1040  EquationSystems es(mesh);
1041  System & sys = es.add_system<System> ("SimpleSystem");
1042  for (auto i : index_range(file_var_names))
1043  sys.add_variable(file_var_names[i], CONSTANT, MONOMIAL);
1044 
1045  ExodusII_IO exii(mesh);
1046 
1047  if (mesh.processor_id() == 0)
1048  exii.read("elemental_from_nodal.e");
1051 
1052  es.init();
1053 
1054  for (auto i : index_range(file_var_names))
1056  (sys, sys.variable_name(i), file_var_names[i]);
1057 
1058  // Check that the values we read back in are as expected.
1059  for (const auto & elem : mesh.active_element_ptr_range())
1060  for (auto i : index_range(file_var_names))
1061  {
1062  Real read_val = sys.point_value(i, elem->vertex_average());
1063  LIBMESH_ASSERT_FP_EQUAL
1064  (expected_values[i], read_val, TOLERANCE*TOLERANCE);
1065  }
1066  } // end second scope
1067  } // end testExodusWriteElementDataFromDiscontinuousNodalData
1068 
1069 #endif // !LIBMESH_USE_COMPLEX_NUMBERS
1070 
1071 
1072  void testExodusWriteAddedSides
1073  (Number (*exact_sol)(const Point &, const Parameters &, const
1074  std::string &, const std::string &),
1075  const ElemType elem_type,
1076  const Order order,
1077  const bool write_discontinuous = false,
1078  const std::vector<FEType> earlier_vars = {},
1079  const std::vector<FEType> later_vars = {})
1080  {
1081  constexpr unsigned int nx = added_sides_nxyz[0],
1082  ny = added_sides_nxyz[1],
1083  nz = added_sides_nxyz[2];
1084 
1085  const unsigned int dim = Elem::type_to_dim_map[elem_type];
1086  const bool is_tensor = (Elem::build(elem_type)->n_sides() == dim * 2);
1087 
1088  // Figure out how many fake and true elements to expect
1089  dof_id_type n_fake_elem = 0;
1090  dof_id_type n_true_elem = 0;
1091 
1092  dof_id_type n_fake_nodes = 0;
1093  dof_id_type n_true_nodes = 0;
1094 
1095  const std::string filename =
1096  "side_discontinuous_"+Utility::enum_to_string<ElemType>(elem_type)+(write_discontinuous?"_disc":"")+".e";
1097 
1098  // first scope: write file
1099  {
1101 
1102  EquationSystems es(mesh);
1103  System & sys = es.add_system<System> ("SimpleSystem");
1104  int varnum = 1;
1105  for (auto vartype : earlier_vars)
1106  sys.add_variable("earlier_"+std::to_string(varnum++), vartype);
1107 
1108  sys.add_variable("u", order, SIDE_HIERARCHIC);
1109 
1110  varnum = 1;
1111  for (auto vartype : later_vars)
1112  sys.add_variable("later_"+std::to_string(varnum++), vartype);
1113 
1114  if (dim == 3)
1116  (mesh, nx, ny, nz, 0., 1., 0., 1., 0., 1., elem_type);
1117  else if (dim == 2)
1119  (mesh, nx, ny, 0., 1., 0., 1., elem_type);
1120  else
1122  (mesh, nx, 0., 1., elem_type);
1123 
1124  n_true_elem = mesh.n_elem();
1125  n_true_nodes = mesh.n_nodes();
1126  CPPUNIT_ASSERT_LESS(n_true_nodes, n_true_elem); // Ne < Nn
1127 
1128  const unsigned int our_ny = dim>1 ? ny : 1;
1129  const unsigned int our_nz = dim>2 ? nz : 1;
1130 
1131  dof_id_type min_n_elem = nx * our_ny * our_nz;
1132  CPPUNIT_ASSERT_LESSEQUAL(n_true_elem, min_n_elem); // "backwards" API...
1133 
1134  for (const auto & elem : mesh.active_local_element_ptr_range())
1135  {
1136  for (auto s : make_range(elem->n_sides()))
1137  if (!elem->neighbor_ptr(s) || elem->neighbor_ptr(s)->id() < elem->id())
1138  {
1139  ++n_fake_elem;
1140  auto side = elem->build_side_ptr(s);
1141  n_fake_nodes += side->n_nodes();
1142  }
1143  }
1144  mesh.comm().sum(n_fake_elem);
1145  mesh.comm().sum(n_fake_nodes);
1146 
1147  const dof_id_type expected_fakes = [elem_type]() {
1148  switch (elem_type)
1149  {
1150  case EDGE3:
1151  return nx+1;
1152  case TRI6:
1153  return 3*nx*ny + nx + ny;
1154  case QUAD8:
1155  case QUAD9:
1156  return 2*nx*ny + nx + ny;
1157  case TET14:
1158  return 48*nx*ny*nz + 4*(nx*ny+nx*nz+ny*nz);
1159  case HEX27:
1160  return 3*nx*ny*nz + nx*ny + nx*nz + ny*nz;
1161  default:
1162  libmesh_error();
1163  }
1164  } (); // Invoke anonymous lambda
1165 
1166  CPPUNIT_ASSERT_EQUAL(n_fake_elem, expected_fakes); // "backwards" API...
1167 
1168  es.init();
1169  sys.project_solution(exact_sol, nullptr,
1170  es.parameters);
1171 
1172  // Set solution u^e_i = i, for the ith vertex of a given element e.
1173 
1174  // Now write to file.
1175  ExodusII_IO exii(mesh);
1176  exii.write_added_sides(true);
1177 
1178  if (write_discontinuous)
1179  exii.write_discontinuous_equation_systems(filename, es);
1180  else
1181  exii.write_equation_systems(filename, es);
1182  } // end first scope
1183 
1184  // second scope: read file, verify extra elements exist
1185  {
1187  mesh.allow_renumbering(false);
1188  ExodusII_IO exii(mesh);
1189 
1190  if (mesh.processor_id() == 0)
1191  exii.read(filename);
1194 
1195  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), n_true_elem + n_fake_elem);
1196  if (write_discontinuous)
1197  {
1198  const dof_id_type nodes_per_elem = Elem::build(elem_type)->n_nodes();
1199  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
1200  n_true_elem*nodes_per_elem + n_fake_nodes);
1201  }
1202  else
1203  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), n_true_nodes + n_fake_nodes);
1204 
1205  EquationSystems es(mesh);
1206  System & sys = es.add_system<System> ("SimpleSystem");
1207  // Read back into a LAGRANGE variable for testing; we still
1208  // can't use Exodus for a proper restart.
1209  sys.add_variable("ul", SECOND);
1210  es.init();
1211 
1212  const DofMap & dof_map = sys.get_dof_map();
1213 
1214 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
1215  exii.copy_nodal_solution(sys, "ul", "r_u");
1216 #else
1217  exii.copy_nodal_solution(sys, "ul", "u");
1218 #endif
1219 
1220  dof_id_type n_side_nodes = 0;
1221  const std::string nullstr;
1222  const std::string facestr = "face";
1223 
1224  // Debugging this in parallel is tricky. Let's make sure that
1225  // if we have a failure on one rank we see it on all the others
1226  // and we can go on to other tests.
1227 #ifdef LIBMESH_ENABLE_EXCEPTIONS
1228  bool threw_exception = false;
1229  try
1230 #endif // LIBMESH_ENABLE_EXCEPTIONS
1231  {
1232  for (const auto & elem : mesh.active_local_element_ptr_range())
1233  {
1234  // Just look at side elements, not interiors
1235  if (elem->dim() == dim)
1236  continue;
1237 
1238  std::vector<dof_id_type> dof_indices;
1239  dof_map.dof_indices(elem, dof_indices, 0);
1240 
1241  // Find what face direction we're looking at, to
1242  // disambiguate when testing against a discontinuous
1243  // function, since we're evaluating on nodes that overlap
1244  // multiple faces
1245  const Point normal = [elem](){
1246  if (elem->dim() == 2)
1247  return Point((elem->point(1) - elem->point(0)).cross
1248  (elem->point(2) - elem->point(0)));
1249  else if (elem->dim() == 1)
1250  return Point
1251  (elem->point(1)(1)-elem->point(0)(1),
1252  elem->point(0)(0)-elem->point(1)(0));
1253  else
1254  return Point(1);
1255  } (); // Invoke anonymous lambda
1256 
1257  short faceval = -1;
1258  if (is_tensor)
1259  {
1260  if (std::abs(normal(0)) > TOLERANCE)
1261  {
1262  faceval = 0;
1263  libmesh_assert_less(std::abs(normal(1)), TOLERANCE);
1264  libmesh_assert_less(std::abs(normal(2)), TOLERANCE);
1265  }
1266  else if (std::abs(normal(1)) > TOLERANCE)
1267  {
1268  faceval = 1;
1269  libmesh_assert_less(std::abs(normal(2)), TOLERANCE);
1270  }
1271  else
1272  {
1273  faceval = 2;
1274  libmesh_assert_greater(std::abs(normal(2)), TOLERANCE);
1275  }
1276  libmesh_assert_greater_equal(faceval, 0);
1277  es.parameters.set<short>(facestr) = faceval;
1278  }
1279 
1280  for (auto i : index_range(dof_indices))
1281  {
1282  const Point node_pt = elem->point(i);
1283  const Real nodal_coef =
1284  libmesh_real((*sys.current_local_solution)(dof_indices[i]));
1285  const Real exact_val =
1286  libmesh_real(exact_sol
1287  (node_pt, es.parameters, nullstr,
1288  nullstr));
1289  LIBMESH_ASSERT_FP_EQUAL
1290  (nodal_coef, exact_val,
1291  std::max(Real(2),nodal_coef+exact_val)*
1292  TOLERANCE*std::sqrt(TOLERANCE));
1293  ++n_side_nodes;
1294  }
1295  }
1296  }
1297 #ifdef LIBMESH_ENABLE_EXCEPTIONS
1298  catch (...)
1299  {
1300  threw_exception = true;
1301  TestCommWorld->max(threw_exception);
1302  throw;
1303  }
1304  if (!threw_exception)
1305  TestCommWorld->max(threw_exception);
1306  CPPUNIT_ASSERT(!threw_exception);
1307 #endif // LIBMESH_ENABLE_EXCEPTIONS
1308 
1309  TestCommWorld->sum(n_side_nodes);
1310  CPPUNIT_ASSERT_EQUAL(n_side_nodes, n_fake_nodes);
1311  } // end second scope
1312  } // end testExodusWriteAddedSides
1313 
1315  {
1316  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, FIRST);
1317  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, SECOND);
1318  }
1319 
1321  {
1322  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, FIRST, true);
1323  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, SECOND, true);
1324  }
1325 
1327  {
1328  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, FIRST, false, {{FIRST, LAGRANGE}});
1329  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, SECOND, false, {}, {{FIRST, LAGRANGE}});
1330  }
1331 
1333  {
1334  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, FIRST, true, {{FIRST, LAGRANGE}});
1335  testExodusWriteAddedSides(six_x_plus_sixty_y, EDGE3, SECOND, true, {}, {{FIRST, LAGRANGE}});
1336  }
1337 
1339  {
1340  testExodusWriteAddedSides(designed_for_side_elems, EDGE3, SECOND);
1341  }
1342 
1344  {
1345  testExodusWriteAddedSides(designed_for_side_elems, EDGE3, SECOND, true);
1346  }
1347 
1349  {
1350  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, FIRST);
1351  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, SECOND);
1352  }
1353 
1355  {
1356  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, FIRST, true);
1357  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, SECOND, true);
1358  }
1359 
1361  {
1362  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, FIRST, false, {{SECOND, HIERARCHIC}});
1363  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, SECOND, false, {}, {{SECOND, SZABAB}});
1364  }
1365 
1367  {
1368  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, FIRST, true, {{SECOND, HIERARCHIC}});
1369  testExodusWriteAddedSides(six_x_plus_sixty_y, TRI6, SECOND, true, {}, {{SECOND, SZABAB}});
1370  }
1371 
1373  {
1374  testExodusWriteAddedSides(designed_for_side_elems, TRI6, SECOND);
1375  }
1376 
1378  {
1379  testExodusWriteAddedSides(designed_for_side_elems, TRI6, SECOND, true);
1380  }
1381 
1383  {
1384  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, FIRST);
1385  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, SECOND);
1386  }
1387 
1389  {
1390  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, FIRST, true);
1391  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, SECOND, true);
1392  }
1393 
1395  {
1396  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, FIRST, false, {{SECOND, LAGRANGE}});
1397  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, SECOND, false, {}, {{FIRST, LAGRANGE}});
1398  }
1399 
1401  {
1402  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, FIRST, true, {{SECOND, LAGRANGE}});
1403  testExodusWriteAddedSides(six_x_plus_sixty_y, QUAD9, SECOND, true, {}, {{FIRST, LAGRANGE}});
1404  }
1405 
1407  {
1408  testExodusWriteAddedSides(designed_for_side_elems, QUAD9, SECOND);
1409  }
1410 
1412  {
1413  testExodusWriteAddedSides(designed_for_side_elems, QUAD9, SECOND, true);
1414  }
1415 
1417  {
1418  testExodusWriteAddedSides(six_x_plus_sixty_y, TET14, FIRST);
1419  testExodusWriteAddedSides(six_x_plus_sixty_y, TET14, SECOND);
1420  }
1421 
1423  {
1424  testExodusWriteAddedSides(six_x_plus_sixty_y, TET14, FIRST, true);
1425  testExodusWriteAddedSides(six_x_plus_sixty_y, TET14, SECOND, true);
1426  }
1427 
1429  {
1430  testExodusWriteAddedSides(designed_for_side_elems, TET14, SECOND);
1431  }
1432 
1434  {
1435  testExodusWriteAddedSides(designed_for_side_elems, TET14, SECOND, true);
1436  }
1437 
1439  {
1440  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, FIRST);
1441  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, SECOND);
1442  }
1443 
1445  {
1446  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, FIRST, true);
1447  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, SECOND, true);
1448  }
1449 
1451  {
1452  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, FIRST, false, {{FIRST, LAGRANGE}});
1453  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, SECOND, false, {}, {{SECOND, HIERARCHIC}});
1454  }
1455 
1457  {
1458  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, FIRST, true, {{FIRST, LAGRANGE}});
1459  testExodusWriteAddedSides(six_x_plus_sixty_y, HEX27, SECOND, true, {}, {{SECOND, HIERARCHIC}});
1460  }
1461 
1463  {
1464  testExodusWriteAddedSides(designed_for_side_elems, HEX27, SECOND);
1465  }
1466 
1468  {
1469  testExodusWriteAddedSides(designed_for_side_elems, HEX27, SECOND, true);
1470  }
1471 
1472 #endif // LIBMESH_HAVE_EXODUS_API
1473 
1474 
1475 #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
1476  template <typename MeshType>
1478  {
1479  // first scope: write file
1480  {
1481  MeshType mesh(*TestCommWorld);
1482  MeshTools::Generation::build_square (mesh, 3, 3, 0., 1., 0., 1.);
1483  mesh.write("test_nemesis_read.nem");
1484  }
1485 
1486  // Make sure that the writing is done before the reading starts.
1488 
1489  // second scope: read file
1490  {
1491  MeshType mesh(*TestCommWorld);
1492  Nemesis_IO nem(mesh);
1493 
1494  nem.read("test_nemesis_read.nem");
1496  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(9));
1497  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(16));
1498  }
1499  }
1500 
1502  { LOG_UNIT_TEST; testNemesisReadImpl<ReplicatedMesh>(); }
1503 
1505  { LOG_UNIT_TEST; testNemesisReadImpl<DistributedMesh>(); }
1506 #endif
1507 
1508 
1510  {
1511  auto locator = mesh.sub_point_locator();
1512 
1513  for (auto & elem : mesh.element_ptr_range())
1514  {
1515  Point master_pt = {}; // center, for tensor product elements
1516 
1517  // But perturb it to try and trigger any mapping weirdness
1518  if (elem->dim() > 0)
1519  master_pt(0) = 0.25;
1520 
1521  if (elem->dim() > 1)
1522  master_pt(1) = -0.25;
1523 
1524  if (elem->dim() > 2)
1525  master_pt(2) = 0.75;
1526 
1527  Point physical_pt = FEMap::map(elem->dim(), elem, master_pt);
1528 
1529  Point inverse_pt = FEMap::inverse_map(elem->dim(), elem,
1530  physical_pt);
1531 
1532  CPPUNIT_ASSERT((inverse_pt-master_pt).norm() < TOLERANCE);
1533 
1534  CPPUNIT_ASSERT(elem->contains_point(physical_pt));
1535 
1536  // We only want to find elements in the same block
1537  std::set<subdomain_id_type> my_subdomain { elem->subdomain_id() };
1538 
1539  // We can *still* have overlapping NodeElem from a slit mesh
1540  // input file; better check them all
1541  std::set<const Elem * > located_elems;
1542  (*locator)(physical_pt, located_elems, &my_subdomain);
1543 
1544  CPPUNIT_ASSERT(located_elems.count(elem));
1545  }
1546  }
1547 
1548 
1549 
1551  {
1552  CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
1554 
1555  unsigned char weight_index = mesh.default_mapping_data();
1556 
1557  bool found_the_quad = false;
1558 
1559  for (auto & elem : mesh.element_ptr_range())
1560  {
1561  if (elem->type() == NODEELEM)
1562  continue;
1563 
1564  CPPUNIT_ASSERT_EQUAL(elem->type(), QUAD9);
1565  found_the_quad = true;
1566 
1567  for (unsigned int n=0; n != 9; ++n)
1568  CPPUNIT_ASSERT_EQUAL
1569  (elem->node_ref(n).get_extra_datum<Real>(weight_index),
1570  Real(0.75));
1571 
1572  CPPUNIT_ASSERT_EQUAL(elem->point(0)(0), Real(0.5));
1573  CPPUNIT_ASSERT_EQUAL(elem->point(0)(1), Real(0.5));
1574  CPPUNIT_ASSERT_EQUAL(elem->point(1)(0), Real(1.5));
1575  CPPUNIT_ASSERT_EQUAL(elem->point(1)(1), Real(0.5));
1576  CPPUNIT_ASSERT_EQUAL(elem->point(2)(0), Real(1.5));
1577  CPPUNIT_ASSERT_EQUAL(elem->point(2)(1), Real(1.5));
1578  CPPUNIT_ASSERT_EQUAL(elem->point(3)(0), Real(0.5));
1579  CPPUNIT_ASSERT_EQUAL(elem->point(3)(1), Real(1.5));
1580  CPPUNIT_ASSERT(elem->has_affine_map());
1581 #if LIBMESH_DIM > 2
1582  for (unsigned int v=0; v != 4; ++v)
1583  CPPUNIT_ASSERT_EQUAL(elem->point(v)(2), Real(0));
1584 #endif
1585  }
1586 
1587  TestCommWorld->max(found_the_quad);
1588  CPPUNIT_ASSERT(found_the_quad);
1589 
1590  testMasterCenters(mesh);
1591  }
1592 
1593 
1594  void testAbaqusRead (const std::string & fname,
1597  {
1599 
1600  AbaqusIO abaqus(mesh);
1601 
1602  if (mesh.processor_id() == 0)
1603  abaqus.read(fname);
1605 
1607 
1608  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), n_elem);
1609  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), n_nodes);
1610  }
1611 
1612 
1614  {
1615  LOG_UNIT_TEST;
1616  testAbaqusRead("meshes/tensile_sample_test1.inp.gz", 728, 1166);
1617  }
1618 
1619 
1621  {
1622  LOG_UNIT_TEST;
1623  testAbaqusRead("meshes/poly_sample_test2.inp.gz", 1280, 1625);
1624  }
1625 
1626 
1628  {
1629  LOG_UNIT_TEST;
1630 
1632 
1633  DynaIO dyna(mesh);
1634 
1635  if (mesh.processor_id() == 0)
1636  dyna.read("meshes/1_quad.bxt.gz");
1638 
1640 
1641  // We have 1 QUAD9 finite element, attached via a trivial map to 9
1642  // spline Node+NodeElem objects
1643  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(10));
1644  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(18));
1645 
1646  helperTestingDynaQuad(mesh);
1647  }
1648 
1649  void testBadGmsh ()
1650  {
1651  LOG_UNIT_TEST;
1652 
1654 
1655  GmshIO gmsh_io(mesh);
1656 
1657 #ifdef LIBMESH_ENABLE_EXCEPTIONS
1658  std::string what = "";
1659  try
1660  {
1661  if (mesh.processor_id() == 0)
1662  gmsh_io.read("meshes/block.msh");
1663  }
1664  catch (libMesh::LogicError & e)
1665  {
1666  what = e.what();
1667  }
1668 
1669  TestCommWorld->broadcast(what);
1670  std::regex msg_regex("outside entity physical bounding box");
1671  CPPUNIT_ASSERT(std::regex_search(what, msg_regex));
1672 #endif
1673  }
1674 
1676  {
1677  LOG_UNIT_TEST;
1678 
1680 
1681  GmshIO gmsh_io(mesh);
1682 
1683  if (mesh.processor_id() == 0)
1684  gmsh_io.read("meshes/circle.msh");
1686 
1687  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(14));
1688  }
1689 
1691  {
1692  LOG_UNIT_TEST;
1693 
1695 
1696  GmshIO gmsh_io(mesh);
1697 
1698  if (mesh.processor_id() == 0)
1699  gmsh_io.read("meshes/bcid_overlap.msh");
1701 
1702  CPPUNIT_ASSERT_EQUAL(mesh.get_boundary_info().get_sideset_name_map().size(),
1703  std::size_t(2));
1704  CPPUNIT_ASSERT_EQUAL(mesh.get_boundary_info().sideset_name(1),
1705  std::string("srfBC4A"));
1706  CPPUNIT_ASSERT_EQUAL(mesh.get_boundary_info().sideset_name(2),
1707  std::string("srfBC4B"));
1708  CPPUNIT_ASSERT_EQUAL(mesh.get_subdomain_name_map().size(),
1709  std::size_t(2));
1710  CPPUNIT_ASSERT_EQUAL(mesh.subdomain_name(1),
1711  std::string("volBC3A"));
1712  CPPUNIT_ASSERT_EQUAL(mesh.subdomain_name(2),
1713  std::string("volBC3B"));
1714  }
1715 
1716  void testGoodSTL ()
1717  {
1718  LOG_UNIT_TEST;
1719 
1721 
1722  STLIO stl_io(mesh);
1723 
1724  if (mesh.processor_id() == 0)
1725  stl_io.read("meshes/Cluster_34.stl");
1727 
1728  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(40));
1729  }
1730 
1732  {
1733  LOG_UNIT_TEST;
1734 
1736 
1737  STLIO stl_io(mesh);
1738 
1739  if (mesh.processor_id() == 0)
1740  stl_io.read("meshes/engraving.stl");
1742 
1743  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(426));
1744  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), dof_id_type(215));
1745  }
1746 
1748  {
1749 #ifdef LIBMESH_HAVE_TETGEN
1750  LOG_UNIT_TEST;
1751 
1753 
1754  TetGenIO tetgen_io(mesh);
1755 
1756  if (mesh.processor_id() == 0)
1757  tetgen_io.read("meshes/tetgen_one_tet10.ele");
1759 
1761 
1762  // Mesh should contain 1 TET10 finite element
1763  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(1));
1764  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(10));
1765 
1766  // Element should have TET10 reference element volume
1767  const Elem * const elem = mesh.query_elem_ptr(0);
1768 
1769  // On a serial mesh we have every element everywhere
1770  if (mesh.is_serial())
1771  CPPUNIT_ASSERT(elem);
1772  else
1773  {
1774  bool have_elem = elem;
1775  mesh.comm().max(have_elem);
1776  CPPUNIT_ASSERT(have_elem);
1777  }
1778 
1779  if (elem)
1780  {
1781  const Real vol = elem->volume();
1782  LIBMESH_ASSERT_FP_EQUAL(vol, 1./6, TOLERANCE*TOLERANCE);
1783  }
1784 #endif
1785  }
1786 
1788  {
1789  LOG_UNIT_TEST;
1790 
1792 
1793  DynaIO dyna(mesh, /* keep_spline_nodes = */ false);
1794 
1795  if (mesh.processor_id() == 0)
1796  dyna.read("meshes/1_quad.bxt.gz");
1798 
1800 
1801  // We have 1 QUAD9 finite element
1802  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(1));
1803  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(9));
1804 
1805  helperTestingDynaQuad(mesh);
1806  }
1807 
1808 
1810  {
1811  LOG_UNIT_TEST;
1812 
1814 
1815  DynaIO dyna(mesh);
1816  if (mesh.processor_id() == 0)
1817  dyna.read("meshes/25_quad.bxt.gz");
1819 
1821 
1822  // We have 5^2 QUAD9 elements, with 11^2 nodes,
1823  // tied to 49 Node/NodeElem spline nodes
1824  CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(25+49));
1825  CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(121+49));
1826 
1827  CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
1829 
1830  unsigned char weight_index = mesh.default_mapping_data();
1831 
1832  for (const auto & elem : mesh.active_element_ptr_range())
1833  {
1834  if (elem->type() == NODEELEM)
1835  continue;
1836  LIBMESH_ASSERT_FP_EQUAL(Real(0.04), elem->volume(), TOLERANCE);
1837 
1838  for (unsigned int n=0; n != 9; ++n)
1839  CPPUNIT_ASSERT_EQUAL
1840  (elem->node_ref(n).get_extra_datum<Real>(weight_index),
1841  Real(1.0));
1842 
1843  unsigned int n_neighbors = 0, n_neighbors_expected = 2;
1844  for (unsigned int side=0; side != 4; ++side)
1845  if (elem->neighbor_ptr(side))
1846  n_neighbors++;
1847  Point c = elem->vertex_average();
1848 
1849  if (c(0) > 0.2 && c(0) < 0.8)
1850  n_neighbors_expected++;
1851  if (c(1) > 0.2 && c(1) < 0.8)
1852  n_neighbors_expected++;
1853 
1854  CPPUNIT_ASSERT_EQUAL(n_neighbors, n_neighbors_expected);
1855  }
1856 
1857  testMasterCenters(mesh);
1858 
1859 #ifdef LIBMESH_HAVE_SOLVER
1860 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1861  // Now test whether we can assign the desired constraint equations
1862  EquationSystems es(mesh);
1863  System & sys = es.add_system<LinearImplicitSystem>("test");
1864  sys.add_variable("u", SECOND); // to match QUAD9
1865  es.init();
1866 
1867  // We should have a constraint on every FE dof
1868  CPPUNIT_ASSERT_EQUAL(sys.get_dof_map().n_constrained_dofs(), static_cast<dof_id_type>(121));
1869 #endif // LIBMESH_ENABLE_CONSTRAINTS
1870 #endif // LIBMESH_HAVE_SOLVER
1871  }
1872 
1873  void testProjectionRegression(MeshBase & mesh, std::array<Real, 4> expected_norms)
1874  {
1875  int order = 0;
1876  for (const auto elem : mesh.element_ptr_range())
1877  order = std::max(order, int(elem->default_order()));
1878  TestCommWorld->max(order);
1879  CPPUNIT_ASSERT (order > 0);
1880 
1881  // Let's test that IGA constraints are preserved (in a relative
1882  // sense) when we clone a mesh.
1883  std::unique_ptr<MeshBase> mesh_clone = mesh.clone();
1884  CPPUNIT_ASSERT(*mesh_clone == mesh);
1885 
1886  EquationSystems es(mesh);
1887  System &sys = es.add_system<System> ("SimpleSystem");
1888  sys.add_variable("n", Order(order), RATIONAL_BERNSTEIN);
1889 
1890  es.init();
1891 
1892  sys.project_solution(sin_x_plus_cos_y, nullptr, es.parameters);
1893 
1894  // Make this easy to tweak in the future
1895  const Real my_tolerance = TOLERANCE;
1896 
1897  // Calculate some norms, skipping the spline points, and compare
1898  // to regression standard values
1899  std::set<unsigned int> skip_dimensions {0};
1900  const Real L2_norm =
1901  sys.calculate_norm(*sys.solution, 0, L2, &skip_dimensions);
1902 // std::cout.precision(16);
1903 // std::cout << "L2_norm = " << L2_norm << std::endl;
1904  LIBMESH_ASSERT_FP_EQUAL(L2_norm, expected_norms[0], my_tolerance);
1905  const Real Linf_norm =
1906  sys.calculate_norm(*sys.solution, 0, L_INF, &skip_dimensions);
1907 // std::cout << "Linf_norm = " << Linf_norm << std::endl;
1908  LIBMESH_ASSERT_FP_EQUAL(Linf_norm, expected_norms[1], my_tolerance);
1909  const Real H1_norm =
1910  sys.calculate_norm(*sys.solution, 0, H1_SEMINORM, &skip_dimensions);
1911 // std::cout << "H1_norm = " << H1_norm << std::endl;
1912  LIBMESH_ASSERT_FP_EQUAL(H1_norm, expected_norms[2], my_tolerance);
1913  const Real W1inf_norm =
1914  sys.calculate_norm(*sys.solution, 0, W1_INF_SEMINORM, &skip_dimensions);
1915 // std::cout << "W1inf_norm = " << W1inf_norm << std::endl;
1916  // W1_inf seems more sensitive to FP error...
1917  LIBMESH_ASSERT_FP_EQUAL(W1inf_norm, expected_norms[3], 10*my_tolerance);
1918  }
1919 
1920  void testDynaFileMappings (const std::string & filename, std::array<Real, 4> expected_norms)
1921  {
1923 
1924  DynaIO dyna(mesh);
1925  if (mesh.processor_id() == 0)
1926  dyna.read(filename);
1928 
1930 
1931  CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
1933 
1934  // Useful when trying out different projection functions
1935  // std::cout << filename << ":" << std::endl;
1936 
1937  testMasterCenters(mesh);
1938 
1939  testProjectionRegression(mesh, expected_norms);
1940  }
1941 
1943  {
1944  LOG_UNIT_TEST;
1945 
1946  testDynaFileMappings("meshes/PressurizedCyl_Patch6_256Elem.bxt.gz",
1947  // Regression values for sin_x_plus_cos_y
1948  {{0.9639857809698268, 1.839870171669186,
1949  0.7089812562241862, 1.306121188539059}});
1950  }
1951 
1953  {
1954  LOG_UNIT_TEST;
1955 
1956  testDynaFileMappings("meshes/BlockWithHole_Patch9.bxt.gz",
1957  // Regression values for sin_x_plus_cos_y
1958  {{3.22612556930183, 1.97405365384733,
1959  2.53376235803176, 1.41374070517223}});
1960  }
1961 
1963  {
1964  LOG_UNIT_TEST;
1965 
1966  testDynaFileMappings("meshes/PlateWithHole_Patch8.bxt.gz",
1967  // Regression values for sin_x_plus_cos_y
1968  {{2.2812154374012, 1.974049990211937,
1969  1.791640772215248, 1.413679237529376}});
1970  }
1971 
1973  {
1974  LOG_UNIT_TEST;
1975 
1976  testDynaFileMappings("meshes/PressurizedCyl3d_Patch1_8Elem.bxt.gz",
1977  // Regression values for sin_x_plus_cos_y
1978  {{0.963612880188165, 1.82329452603503,
1979  0.707998701597943, 1.31399222566683}});
1980  }
1981 
1982  void testExodusFileMappings (const std::string & filename,
1983  std::array<Real, 4> expected_norms,
1984  bool use_disc_bex = false)
1985  {
1987 
1988  ExodusII_IO exii(mesh);
1989  // IGA Exodus meshes require ExodusII 8 or higher
1990  if (exii.get_exodus_version() < 800)
1991  return;
1992 
1993  // This should default to false
1994  if (use_disc_bex)
1995  exii.set_discontinuous_bex(true);
1996 
1997  if (mesh.processor_id() == 0)
1998  exii.read(filename);
2000 
2002 
2003  CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
2005 
2006  testMasterCenters(mesh);
2007 
2008  testProjectionRegression(mesh, expected_norms);
2009 
2010  // Test a write when we're done reading; I was getting weirdness
2011  // from NetCDF at this point in a Moose output test.
2012  {
2013  ExodusII_IO exii(mesh);
2014 
2015  exii.write("exodus_file_mapping_out.e");
2016  }
2017 
2018 #ifdef LIBMESH_HAVE_VTK
2019  {
2020  VTKIO vtkout(mesh);
2021 
2022  vtkout.write("vtk_file_mapping_out.pvtu");
2023  }
2024 #endif
2025  }
2026 
2028  {
2029  LOG_UNIT_TEST;
2030 
2031  testExodusFileMappings("meshes/PlateWithHole_Patch8.e",
2032  // Regression values for sin_x_plus_cos_y
2033  {{2.2812154374012, 1.974049990211937,
2034  1.791640772215248, 1.413679237529376}});
2035  }
2036 
2038  {
2039  LOG_UNIT_TEST;
2040 
2041  testExodusFileMappings("meshes/two_quads_two_blocks.e",
2042  // Regression values for sin_x_plus_cos_y
2043  {{2.03496953073072, 1.97996853164955,
2044  1.18462134113435, 1.03085301158959}});
2045  }
2047  {
2048  LOG_UNIT_TEST;
2049 
2050  testExodusFileMappings("meshes/two_element_iga_in.e",
2051  // Regression values for sin_x_plus_cos_y
2052  {{1.26865962862531, 1.42562070158386,
2053  1.54905363492342, 1.29782906548366}});
2054  }
2055 
2057  {
2058  LOG_UNIT_TEST;
2059 
2060  testExodusFileMappings("meshes/PressurizedCyl3d_Patch1_8Elem.e",
2061  {{0.963612880188165, 1.82329452603503,
2062  0.707998701597943, 1.31399222566683}});
2063  }
2064 
2066  {
2067  LOG_UNIT_TEST;
2068 
2069  testExodusFileMappings("meshes/PlateWithHole_Patch8.e",
2070  // Regression values for sin_x_plus_cos_y
2071  //
2072  // These are *not* the same as for the continuous plate, because
2073  // we do the C^TKCx=C^Tf trick to pull back projections to the
2074  // spline nodes, and the pseudoinverse here minimizes the error in
2075  // a discretization-dependent norm, not in a Sobolev norm. For
2076  // these coarse meshes, our Sobolev norms can end up being ~0.1%
2077  // different.
2078  {{2.28234312456534, 1.97439548757586,
2079  1.79290449809266, 1.41075128955985}},
2080  true);
2081  }
2082 
2084  {
2085  LOG_UNIT_TEST;
2086 
2087  testExodusFileMappings("meshes/two_quads_two_blocks.e",
2088  // Regression values for sin_x_plus_cos_y
2089  {{2.03496953073072, 1.97996853164955,
2090  1.18462134113435, 1.03085301158959}},
2091  true);
2092  }
2094  {
2095  LOG_UNIT_TEST;
2096 
2097  testExodusFileMappings("meshes/two_element_iga_in.e",
2098  // Regression values for sin_x_plus_cos_y
2099  {{1.26877626663365, 1.42553698909339,
2100  1.54810114917177, 1.29792704408979}},
2101  true);
2102  }
2103 
2105  {
2106  LOG_UNIT_TEST;
2107 
2108  testExodusFileMappings("meshes/PressurizedCyl3d_Patch1_8Elem.e",
2109  {{0.963855209590556, 1.8234396424318,
2110  0.708286572453382, 1.31468940958327}},
2111  true);
2112  }
2113 };
2114 
virtual void read(const std::string &name) override
This method implements reading a mesh from a specified file.
Definition: abaqus_io.C:227
T libmesh_real(T a)
CPPUNIT_TEST_SUITE_REGISTRATION(MeshInputTest)
ElemType
Defines an enum for geometric element types.
virtual void read(const std::string &name) override
Reads in a mesh in the Dyna format from the ASCII file given by name.
Definition: dyna_io.C:139
This is the EquationSystems class.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
Reading and writing meshes in the Gmsh format.
Definition: gmsh_io.h:51
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
void testExodusSetNodeUniqueIdsFromMaps_implementation(bool set_unique_ids, const std::vector< unique_id_type > &expected_unique_ids)
Definition: mesh_input.C:339
void testExodusDiscWriteAddedSidesTriDisc()
Definition: mesh_input.C:1377
bool have_parameter(std::string_view) const
Definition: parameters.h:420
virtual void read(const std::string &base_filename) override
Implements reading the mesh from several different files.
Definition: nemesis_io.C:214
void testCopyNodalSolutionImpl(const std::string &filename)
Definition: mesh_input.C:633
void testGoodSTL()
Definition: mesh_input.C:1716
Reading and writing meshes in (a subset of) LS-DYNA format.
Definition: dyna_io.h:52
virtual void read(const std::string &) override
This method implements reading a mesh from a specified file in TetGen format.
Definition: tetgen_io.C:36
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
This class implements reading and writing triangle meshes in the STL format.
Definition: stl_io.h:45
The AbaqusIO class is a preliminary implementation for reading Abaqus mesh files in ASCII format...
Definition: abaqus_io.h:41
void setUp()
Definition: mesh_input.C:220
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false, bool skip_detect_interior_parents=false)=0
Interfaces for reading/writing a mesh to/from a file.
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:74
void testExodusFileMappingsCyl3d()
Definition: mesh_input.C:2056
This class is used as both an external data structure for passing around Exodus file header informati...
void testDynaNoSplines()
Definition: mesh_input.C:1787
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:1345
void testExodusWriteAddedSidesHexC0()
Definition: mesh_input.C:1438
void testExodusDiscWriteAddedSidesTetDisc()
Definition: mesh_input.C:1433
virtual void write_equation_systems(const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
This method implements writing a mesh with data to a specified file where the data is taken from the ...
Definition: mesh_output.C:31
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2201
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).
Definition: mesh_tools.C:1004
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:218
void testExodusDiscWriteAddedSidesHexDisc()
Definition: mesh_input.C:1467
static constexpr Real TOLERANCE
unsigned int dim
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
Definition: fe_map.C:1512
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:50
void testExodusDiscWriteAddedSidesMixedHexC0()
Definition: mesh_input.C:1456
void testExodusCopyNodalSolutionReplicated()
Definition: mesh_input.C:701
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
void testDynaFileMappingsFEMEx5()
Definition: mesh_input.C:1942
void testExodusFileMappingsPlateWithHole()
Definition: mesh_input.C:2027
void testExodusCopyNodalSolutionDistributed()
Definition: mesh_input.C:704
void testExodusCopyElementSolutionReplicated()
Definition: mesh_input.C:790
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
void testNemesisReadImpl()
Definition: mesh_input.C:1477
static const unsigned int type_to_dim_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the geometric dimension of the ele...
Definition: elem.h:628
Number six_x_plus_sixty_y(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: mesh_input.C:30
void testExodusSetElemUniqueIdsFromMaps_implementation(bool set_unique_ids, const std::vector< unique_id_type > &expected_unique_ids)
Definition: mesh_input.C:396
void sum(T &r) const
void testExodusWriteAddedSidesMixedEdgeC0()
Definition: mesh_input.C:1326
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
void barrier() const
virtual void read(const std::string &mesh_file) override
This method implements reading a mesh from a specified file.
Definition: stl_io.C:165
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
virtual void write(const std::string &) override
Output the mesh without solutions to a .pvtu file.
void testExodusFileMappingsTwoElemIGA()
Definition: mesh_input.C:2046
Number point_value(unsigned int var, const Point &p, const bool insist_on_success=true, const NumericVector< Number > *sol=nullptr) const
Definition: system.C:2219
void skip_noncritical_partitioning(bool skip)
If true is passed in then the elements on this mesh will no longer be (re)partitioned, and the nodes on this mesh will only be repartitioned if they are found "orphaned" via coarsening or other removal of the last element responsible for their node/element processor id consistency.
Definition: mesh_base.h:1401
unique_id_type unique_id() const
Definition: dof_object.h:835
const Parallel::Communicator & comm() const
void testLowOrderEdgeBlocks()
Definition: mesh_input.C:499
void testAbaqusReadFirst()
Definition: mesh_input.C:1613
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 tearDown()
Definition: mesh_input.C:223
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
void testNemesisCopyNodalSolutionReplicated()
Definition: mesh_input.C:708
This class implements reading and writing meshes in the TetGen format.
Definition: tetgen_io.h:47
The libMesh namespace provides an interface to certain functionality in the library.
void testAbaqusRead(const std::string &fname, dof_id_type n_elem, dof_id_type n_nodes)
Definition: mesh_input.C:1594
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:170
This class implements reading and writing meshes in the VTK format.
Definition: vtk_io.h:60
void testNemesisCopyElementSolutionDistributed()
Definition: mesh_input.C:800
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
void testNemesisCopyElementVectorReplicated()
Definition: mesh_input.C:977
void testDynaFileMappingsCyl3d()
Definition: mesh_input.C:1972
This is the MeshBase class.
Definition: mesh_base.h:80
std::size_t n_boundary_ids() const
ElemMappingType default_mapping_type() const
Returns the default master space to physical space mapping basis functions to be used on newly added ...
Definition: mesh_base.h:931
void testNemesisReadReplicated()
Definition: mesh_input.C:1501
void testNemesisCopyNodalSolutionDistributed()
Definition: mesh_input.C:711
void testExodusFileMappings(const std::string &filename, std::array< Real, 4 > expected_norms, bool use_disc_bex=false)
Definition: mesh_input.C:1982
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
void testCopyElementSolutionImpl(const std::string &filename)
Definition: mesh_input.C:717
void testNemesisSingleElementReplicated()
Definition: mesh_input.C:859
virtual bool is_serial() const
Definition: mesh_base.h:347
void testExodusCopyElementSolutionDistributed()
Definition: mesh_input.C:793
void libmesh_ignore(const Args &...)
const dof_id_type n_nodes
Definition: tecplot_io.C:67
unsigned int number() const
Definition: system.h:2393
void testExodusDiscWriteAddedSidesTetC0()
Definition: mesh_input.C:1422
const T & get(std::string_view) const
Definition: parameters.h:451
int8_t boundary_id_type
Definition: id_types.h:51
void testAbaqusReadSecond()
Definition: mesh_input.C:1620
void testExodusDiscTwoBlocks()
Definition: mesh_input.C:2083
This is the MeshCommunication class.
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
Definition: mesh_base.h:1896
void testBadGmsh()
Definition: mesh_input.C:1649
The Nemesis_IO class implements reading parallel meshes in the Nemesis file format from Sandia Nation...
Definition: nemesis_io.h:51
unsigned char default_mapping_data() const
Returns any default data value used by the master space to physical space mapping.
Definition: mesh_base.h:949
virtual void write_equation_systems(const std::string &fname, const EquationSystems &es, const std::set< std::string > *system_names=nullptr) override
Writes out the solution for no specific time or timestep.
Definition: exodusII_io.C:2050
bool is_parallel_format() const
Returns true iff this mesh file format and input class are parallelized, so that all processors can r...
Definition: mesh_input.h:87
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:98
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:442
void testDynaFileMappingsPlateWithHole()
Definition: mesh_input.C:1962
void testExodusWriteAddedSidesEdgeC0()
Definition: mesh_input.C:1314
void testExodusWriteAddedSidesMixedQuadC0()
Definition: mesh_input.C:1394
void set_unique_ids_from_maps(bool val)
If true, this flag enforces the following behaviors:
Definition: exodusII_io.C:977
void testExodusDiscPlateWithHole()
Definition: mesh_input.C:2065
void write_element_data(const EquationSystems &es)
Write out element solution in parallel, without localizing the solution vector.
Definition: nemesis_io.C:1466
virtual dof_id_type max_elem_id() const =0
void copy_elemental_solution(System &system, std::string system_var_name, std::string exodus_var_name, unsigned int timestep=1)
If we read in a elemental solution while reading in a mesh, we can attempt to copy that elemental sol...
Definition: exodusII_io.C:1161
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1655
Real calculate_norm(const NumericVector< Number > &v, unsigned int var, FEMNormType norm_type, std::set< unsigned int > *skip_dimensions=nullptr) const
Definition: system.C:1511
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
libmesh_assert(ctx)
std::vector< BCTuple > build_edge_list() const
Create a list of (element_id, edge_id, boundary_id) tuples for all relevant edges.
void testExodusWriteAddedSidesQuadC0()
Definition: mesh_input.C:1382
void testNemesisCopyElementSolutionReplicated()
Definition: mesh_input.C:797
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1344
const std::string & variable_name(const unsigned int i) const
Definition: system.C:2679
std::string & subdomain_name(subdomain_id_type id)
Definition: mesh_base.C:1880
void testGoodSTLBinary()
Definition: mesh_input.C:1731
void project_solution(FunctionBase< Number > *f, FunctionBase< Gradient > *g=nullptr, std::optional< ConstElemRange > active_local_range=std::nullopt, std::optional< std::vector< unsigned int >> variable_numbers=std::nullopt) const
Projects arbitrary functions onto the current solution.
std::vector< char > title
virtual void read(const std::string &name) override
This method implements reading a mesh from a specified file.
Definition: exodusII_io.C:246
void testNemesisSingleElementDistributed()
Definition: mesh_input.C:862
void helperTestingDynaQuad(const MeshBase &mesh)
Definition: mesh_input.C:1550
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
void testSingleElementImpl(const std::string &filename)
Definition: mesh_input.C:808
Number sin_x_plus_cos_y(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: mesh_input.C:42
void testNemesisReadDistributed()
Definition: mesh_input.C:1504
std::string & sideset_name(boundary_id_type id)
virtual void write(const std::string &name) const =0
void testExodusWriteAddedSidesEdgeDisc()
Definition: mesh_input.C:1338
void testDynaFileMappingsBlockWithHole()
Definition: mesh_input.C:1952
void testCopyElementVectorImpl(const std::string &filename)
Definition: mesh_input.C:873
void testExodusWriteAddedSidesTetDisc()
Definition: mesh_input.C:1428
const std::set< boundary_id_type > & get_boundary_ids() const
void testExodusDiscWriteAddedSidesMixedQuadC0()
Definition: mesh_input.C:1400
void testExodusIGASidesets()
Definition: mesh_input.C:542
void testMasterCenters(const MeshBase &mesh)
Definition: mesh_input.C:1509
void testDynaFileMappings(const std::string &filename, std::array< Real, 4 > expected_norms)
Definition: mesh_input.C:1920
void testProjectionRegression(MeshBase &mesh, std::array< Real, 4 > expected_norms)
Definition: mesh_input.C:1873
static int get_exodus_version()
Definition: exodusII_io.C:170
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void testDynaReadElem()
Definition: mesh_input.C:1627
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
void testGmshBCIDOverlap()
Definition: mesh_input.C:1690
dof_id_type n_constrained_dofs() const
virtual void renumber_elem(dof_id_type old_id, dof_id_type new_id)=0
Changes the id of element old_id, both by changing elem(old_id)->id() and by moving elem(old_id) in t...
void max(const T &r, T &o, Request &req) const
auto norm(const T &a)
Definition: tensor_tools.h:74
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
virtual void write(const std::string &fname) override
This method implements writing a mesh to a specified file.
Definition: exodusII_io.C:2197
constexpr int added_sides_nxyz[]
Definition: mesh_input.C:53
void testExodusCopyElementVectorReplicated()
Definition: mesh_input.C:970
static Point map(const unsigned int dim, const Elem *elem, const Point &reference_point)
Definition: fe_map.C:1954
void testExodusDiscWriteAddedSidesTriC0()
Definition: mesh_input.C:1354
void testExodusDiscWriteAddedSidesHexC0()
Definition: mesh_input.C:1444
void broadcast(MeshBase &) const
Finds all the processors that may contain elements that neighbor my elements.
void copy_elemental_solution(System &system, std::string system_var_name, std::string exodus_var_name, unsigned int timestep=1)
If we read in a elemental solution while reading in a mesh, we can attempt to copy that elemental sol...
Definition: nemesis_io.C:1751
void testTetgenIO()
Definition: mesh_input.C:1747
virtual Real volume() const
Definition: elem.C:3462
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:176
void testExodusWriteAddedSidesMixedHexC0()
Definition: mesh_input.C:1450
Parameters parameters
Data structure holding arbitrary parameters.
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1667
ExodusHeaderInfo read_header(const std::string &name)
Read only the header information, instead of the entire mesh.
Definition: exodusII_io.C:926
void testExodusDiscCyl3d()
Definition: mesh_input.C:2104
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 testDynaReadPatch()
Definition: mesh_input.C:1809
void write_element_data_from_discontinuous_nodal_data(const EquationSystems &es, const std::set< std::string > *system_names=nullptr, const std::string &var_suffix="_elem_node_")
Similar to the function above, but instead of only handling (CONSTANT, MONOMIAL) data, writes out a general discontinuous solution field, e.g.
Definition: exodusII_io.C:1463
void testVTKPreserveElemIds()
Definition: mesh_input.C:227
void set_discontinuous_bex(bool disc_bex)
Set to true (false is the default) to generate independent nodes for every Bezier Extraction element ...
Definition: exodusII_io.C:2436
void testExodusSetNodeUniqueIdsFromMaps()
Definition: mesh_input.C:375
virtual void init()
Initialize all the systems.
void testExodusWriteAddedSidesTriC0()
Definition: mesh_input.C:1348
void testExodusReadHeader()
Definition: mesh_input.C:462
void testExodusSetElemUniqueIdsFromMaps()
Definition: mesh_input.C:431
void testExodusDiscWriteAddedSidesEdgeDisc()
Definition: mesh_input.C:1343
void testExodusCopyElementVectorDistributed()
Definition: mesh_input.C:973
void testExodusWriteAddedSidesQuadDisc()
Definition: mesh_input.C:1406
void testExodusWriteAddedSidesMixedTriC0()
Definition: mesh_input.C:1360
virtual void read(const std::string &name) override
Reads in a mesh in the Gmsh *.msh format from the ASCII file given by name.
Definition: gmsh_io.C:149
virtual dof_id_type n_elem() const =0
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
virtual const Node * node_ptr(const dof_id_type i) const =0
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
processor_id_type processor_id() const
void testExodusDiscTwoElemIGA()
Definition: mesh_input.C:2093
const DofMap & get_dof_map() const
Definition: system.h:2417
void testExodusDiscWriteAddedSidesMixedEdgeC0()
Definition: mesh_input.C:1332
void testExodusDiscWriteAddedSidesQuadDisc()
Definition: mesh_input.C:1411
void testExodusWriteElementDataFromDiscontinuousNodalData()
Definition: mesh_input.C:985
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
void testExodusFileMappingsTwoBlocks()
Definition: mesh_input.C:2037
void testNemesisCopyElementVectorDistributed()
Definition: mesh_input.C:980
void testExodusWriteAddedSidesHexDisc()
Definition: mesh_input.C:1462
void ErrorVector unsigned int
Definition: adjoints_ex3.C:360
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:153
void testExodusDiscWriteAddedSidesQuadC0()
Definition: mesh_input.C:1388
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.
void testExodusDiscWriteAddedSidesEdgeC0()
Definition: mesh_input.C:1320
virtual dof_id_type n_nodes() const =0
uint8_t dof_id_type
Definition: id_types.h:67
Number designed_for_side_elems(const Point &p, const Parameters &param, const std::string &, const std::string &)
Definition: mesh_input.C:55
void testExodusDiscWriteAddedSidesMixedTriC0()
Definition: mesh_input.C:1366
void testExodusWriteAddedSidesTetC0()
Definition: mesh_input.C:1416
void testGoodGmsh()
Definition: mesh_input.C:1675
void testExodusWriteAddedSidesTriDisc()
Definition: mesh_input.C:1372
void testVTKPreserveSubdomainIds()
Definition: mesh_input.C:286