libMesh
Loading...
Searching...
No Matches
exodus_test.C
Go to the documentation of this file.
1#include "mesh_elem_test.h"
2
3#ifdef LIBMESH_HAVE_EXODUS_API
4
5#include "libmesh/cell_c0polyhedron.h"
6#include "libmesh/distributed_mesh.h"
7#include "libmesh/enum_to_string.h"
8#include "libmesh/exodusII_io.h"
9#include "libmesh/exodusII_io_helper.h"
10#include "libmesh/face_c0polygon.h"
11#include "libmesh/int_range.h"
12#include "libmesh/mesh_communication.h"
13#include "libmesh/mesh_generation.h"
14#include "libmesh/node.h"
15#include "libmesh/replicated_mesh.h"
16
17#include <memory>
18#include <set>
19#include <string>
20#include <vector>
21
22using namespace libMesh;
23
24template <ElemType elem_type>
25class ExodusTest : public MeshPerElemTest<elem_type>
26{
27public:
29 {
30 LOG_UNIT_TEST;
31
32 Mesh input_mesh(*TestCommWorld);
33
34 ExodusII_IO exii(input_mesh);
35 if (input_mesh.processor_id() == 0)
36 exii.read("meshes/exodus_elements/read_exodus_" +
37 Utility::enum_to_string(elem_type) + ".e");
38
39 MeshCommunication().broadcast(input_mesh);
40 input_mesh.prepare_for_use();
41
42 CPPUNIT_ASSERT(this->meshes_equal_enough(input_mesh, true));
43 }
44
46 {
47 LOG_UNIT_TEST;
48
49 // This is a *buffered* write; we use scope to make sure the
50 // ExodusII_IO object gets destructed (and thus is guaranteed to
51 // finish writing and close the file) before we try to read what
52 // was written.
53 {
54 ExodusII_IO exii(*this->_mesh);
55
56 // We still default to 32-char names for backwards
57 // compatibility, but we're writing a mesh with extra-long names
58 // in it for testing, so we manually enable longer names.
59 exii.set_max_name_length(80);
60
61 exii.write("write_exodus_" +
62 Utility::enum_to_string(elem_type) + ".e");
63 }
64
65 Mesh input_mesh(*TestCommWorld);
66 ExodusII_IO exii_input(input_mesh);
67 if (input_mesh.processor_id() == 0)
68 exii_input.read("write_exodus_" +
69 Utility::enum_to_string(elem_type) + ".e");
70
71 MeshCommunication().broadcast(input_mesh);
72 input_mesh.prepare_for_use();
73
74 CPPUNIT_ASSERT(this->meshes_equal_enough(input_mesh, true));
75 }
76};
77
78#define EXODUSTEST \
79 CPPUNIT_TEST(test_read_gold); \
80 CPPUNIT_TEST(test_write);
81
82#define INSTANTIATE_EXODUSTEST(elemtype) \
83 class ExodusTest_##elemtype : public ExodusTest<elemtype> \
84 { \
85 public: \
86 ExodusTest_##elemtype() : ExodusTest<elemtype>() \
87 { \
88 if (unitlog->summarized_logs_enabled()) \
89 this->libmesh_suite_name = "ExodusTest"; \
90 else \
91 this->libmesh_suite_name = "ExodusTest_" #elemtype; \
92 } \
93 CPPUNIT_TEST_SUITE(ExodusTest_##elemtype); \
94 EXODUSTEST; \
95 CPPUNIT_TEST_SUITE_END(); \
96 }; \
97 \
98 CPPUNIT_TEST_SUITE_REGISTRATION(ExodusTest_##elemtype)
99
103
104#if LIBMESH_DIM > 1
109
116
117class ExodusC0PolygonTest : public CppUnit::TestCase
118{
119public:
121
123
125
127 {
128 const std::vector<Point> points =
129 { {0, 0}, {1, 0}, {1.5, 0.5}, {1, 1}, {0, 1} };
130
131 for (auto p : index_range(points))
132 mesh.add_point(points[p], /*id=*/p);
133
134 std::unique_ptr<Elem> polygon =
135 std::make_unique<C0Polygon>(cast_int<unsigned int>(points.size()));
136 for (auto i : index_range(points))
137 polygon->set_node(i, mesh.node_ptr(i));
138
139 polygon->set_id() = 0;
140 Elem *elem = mesh.add_elem(std::move(polygon));
141 elem->subdomain_id() = 1;
143 }
144
146 {
147 LOG_UNIT_TEST;
148
150 this->build_pentagon(mesh);
151
152 {
153 ExodusII_IO exii(mesh);
154 exii.write("write_exodus_C0POLYGON.e");
155 }
156
157 Mesh input_mesh(*TestCommWorld);
158 ExodusII_IO exii_input(input_mesh);
159 if (input_mesh.processor_id() == 0)
160 exii_input.read("write_exodus_C0POLYGON.e");
161
162 MeshCommunication().broadcast(input_mesh);
163 input_mesh.prepare_for_use();
164
165 CPPUNIT_ASSERT_EQUAL(cast_int<dof_id_type>(1), input_mesh.n_elem());
166
167 const Elem *elem = input_mesh.query_elem_ptr(0);
168 bool found_elem = elem;
169 input_mesh.comm().max(found_elem);
170 CPPUNIT_ASSERT(found_elem);
171
172 if (!elem)
173 return;
174
175 CPPUNIT_ASSERT_EQUAL(C0POLYGON, elem->type());
176 CPPUNIT_ASSERT_EQUAL(5u, elem->n_nodes());
177
178 for (auto i : make_range(5))
179 CPPUNIT_ASSERT_EQUAL(cast_int<dof_id_type>(i), elem->node_id(i));
180 }
181};
182
184#endif // LIBMESH_DIM > 1
185
186#if LIBMESH_DIM > 2
187class ExodusC0PolyhedronTest : public CppUnit::TestCase
188{
189public:
191
200
202
204 const std::string &filename)
205 {
206 {
207 ExodusII_IO exii(mesh);
208 exii.write(filename);
209 }
210
211 TestCommWorld->barrier();
212
213 Mesh header_mesh(*TestCommWorld);
214 ExodusII_IO exii(header_mesh);
215 return exii.read_header(filename);
216 }
217
218 // When run in parallel, check that a DistributedMesh really is
219 // distributed before we write it, so the writer is exercised on a
220 // mesh that has to be gathered to processor 0.
222 {
223 if (mesh.n_processors() > 1 &&
224 dynamic_cast<const DistributedMesh *>(&mesh))
225 CPPUNIT_ASSERT(!mesh.is_serial());
226 }
227
229 const std::vector<Point> &points,
230 const std::vector<std::vector<unsigned int>> &nodes_on_side)
231 {
232 for (auto p : index_range(points))
233 mesh.add_point(points[p], /*id=*/p);
234
235 std::vector<std::shared_ptr<Polygon>> sides(nodes_on_side.size());
236 for (auto s : index_range(nodes_on_side))
237 {
238 const auto &nodes_on_s = nodes_on_side[s];
239 sides[s] = std::make_shared<C0Polygon>(nodes_on_s.size());
240 for (auto i : index_range(nodes_on_s))
241 sides[s]->set_node(i, mesh.node_ptr(nodes_on_s[i]));
242 }
243
244 std::unique_ptr<Node> mid_elem_node;
245 std::unique_ptr<Elem> polyhedron =
246 std::make_unique<C0Polyhedron>(sides, mid_elem_node);
247 if (mid_elem_node)
248 mesh.add_node(std::move(mid_elem_node));
249
250 polyhedron->set_id() = 0;
251 Elem *elem = mesh.add_elem(std::move(polyhedron));
252 elem->subdomain_id() = 1;
255 }
256
258 {
259 LOG_UNIT_TEST;
260
263 -1., 1.,
264 -1., 1.,
265 -1., 1.,
268
269 for (auto &elem : mesh.element_ptr_range())
270 elem->subdomain_id() = 1;
272
273 ExodusHeaderInfo header_info =
274 this->write_and_read_header(mesh, "write_exodus_C0POLYHEDRON.e");
275
276 CPPUNIT_ASSERT_EQUAL(header_info.num_dim, 3);
277 CPPUNIT_ASSERT_EQUAL(header_info.num_elem, 8);
278 CPPUNIT_ASSERT_EQUAL(header_info.num_elem_blk, 1);
279 CPPUNIT_ASSERT_EQUAL(header_info.num_face, 48);
280 CPPUNIT_ASSERT_EQUAL(header_info.num_face_blk, 1);
281 CPPUNIT_ASSERT_EQUAL(header_info.num_node_sets, 0);
282 CPPUNIT_ASSERT_EQUAL(header_info.num_side_sets, 0);
283 }
284
286 {
287 LOG_UNIT_TEST;
288
290 const std::vector<Point> points =
291 { { 0, -2, 0}, {-1, -1, 0}, {-1, 1, 0},
292 { 0, 2, 0}, { 1, 1, 0}, { 1, -1, 0},
293 { 0, -2, 1}, {-1, -1, 1}, {-1, 1, 1},
294 { 0, 2, 1}, { 1, 1, 1}, { 1, -1, 1} };
295
296 const std::vector<std::vector<unsigned int>> nodes_on_side =
297 { {0, 1, 2, 3, 4, 5},
298 {0, 1, 7, 6},
299 {1, 2, 8, 7},
300 {2, 3, 9, 8},
301 {3, 4, 10, 9},
302 {4, 5, 11, 10},
303 {5, 0, 6, 11},
304 {6, 7, 8, 9, 10, 11} };
305
306 this->build_c0polyhedron(mesh, points, nodes_on_side);
307
308 ExodusHeaderInfo header_info =
309 this->write_and_read_header(mesh, "write_exodus_C0POLYHEDRON_HEXPRISM.e");
310
311 CPPUNIT_ASSERT_EQUAL(header_info.num_dim, 3);
312 CPPUNIT_ASSERT_EQUAL(header_info.num_elem, 1);
313 CPPUNIT_ASSERT_EQUAL(header_info.num_elem_blk, 1);
314 CPPUNIT_ASSERT_EQUAL(header_info.num_face, 8);
315 CPPUNIT_ASSERT_EQUAL(header_info.num_face_blk, 1);
316 CPPUNIT_ASSERT_EQUAL(header_info.num_node_sets, 0);
317 CPPUNIT_ASSERT_EQUAL(header_info.num_side_sets, 0);
318 }
319
321 {
322 LOG_UNIT_TEST;
323
325 const std::vector<Point> points =
326 { { 0, -2, 0}, {-1, -1, 0}, {-1, 1, 0},
327 { 0, 2, 0}, { 1, 1, 0}, { 1, -1, 0},
328 { 0, -2, 1}, {-1, -1, 1}, {-1, 1, 1},
329 { 0, 2, 1}, { 1, 1, 1}, { 1, -1, 1} };
330
331 const std::vector<std::vector<unsigned int>> nodes_on_side =
332 { {0, 1, 2, 3, 4, 5},
333 {0, 1, 7, 6},
334 {1, 2, 8, 7},
335 {2, 3, 9, 8},
336 {3, 4, 10, 9},
337 {4, 5, 11, 10},
338 {5, 0, 6, 11},
339 {6, 7, 8, 9, 10, 11} };
340
341 this->build_c0polyhedron(mesh, points, nodes_on_side);
342
343 std::vector<std::vector<dof_id_type>> expected_nodes_on_side;
344 const Elem *output_elem = mesh.query_elem_ptr(0);
345 const bool have_output_elem = output_elem;
346 bool found_output_elem = have_output_elem;
347 mesh.comm().max(found_output_elem);
348 CPPUNIT_ASSERT(found_output_elem);
349
350 if (output_elem)
351 {
352 expected_nodes_on_side.reserve(output_elem->n_sides());
353 for (auto s : output_elem->side_index_range())
354 {
355 expected_nodes_on_side.emplace_back();
356 for (const auto n : output_elem->nodes_on_side(s))
357 expected_nodes_on_side.back().push_back(output_elem->node_id(n));
358 }
359 }
360
361 {
362 ExodusII_IO exii(mesh);
363 exii.write("write_exodus_C0POLYHEDRON_HEXPRISM_READ.e");
364 }
365
366 Mesh input_mesh(*TestCommWorld);
367 ExodusII_IO exii_input(input_mesh);
368 if (input_mesh.processor_id() == 0)
369 exii_input.read("write_exodus_C0POLYHEDRON_HEXPRISM_READ.e");
370
371 MeshCommunication().broadcast(input_mesh);
372 input_mesh.prepare_for_use();
373
374 CPPUNIT_ASSERT_EQUAL(cast_int<dof_id_type>(1), input_mesh.n_elem());
375
376 const Elem *elem = input_mesh.query_elem_ptr(0);
377 bool found_elem = elem;
378 input_mesh.comm().max(found_elem);
379 CPPUNIT_ASSERT(found_elem);
380
381 const bool can_compare = have_output_elem && elem;
382 bool found_comparable_elem = can_compare;
383 input_mesh.comm().max(found_comparable_elem);
384 CPPUNIT_ASSERT(found_comparable_elem);
385
386 if (!can_compare)
387 return;
388
389 CPPUNIT_ASSERT_EQUAL(C0POLYHEDRON, elem->type());
390 CPPUNIT_ASSERT_EQUAL(12u, elem->n_vertices());
391 CPPUNIT_ASSERT_EQUAL(8u, elem->n_sides());
392
393 for (auto s : index_range(expected_nodes_on_side))
394 {
395 const auto side_nodes = elem->nodes_on_side(s);
396 CPPUNIT_ASSERT_EQUAL(expected_nodes_on_side[s].size(), side_nodes.size());
397 for (auto n : index_range(expected_nodes_on_side[s]))
398 CPPUNIT_ASSERT_EQUAL(expected_nodes_on_side[s][n],
399 elem->node_id(side_nodes[n]));
400 }
401 }
402
403 // A mesh with a C0POLYHEDRON and a HEX8 in the *same* subdomain. Exodus
404 // requires a single element type per block, so the writer has to split
405 // this subdomain into two blocks (one NFACED, one HEX8). Before that
406 // fix the whole subdomain was written as a single block of the first
407 // element's type, which errored (or, when the first element was the
408 // HEX8, crashed) instead of writing the polyhedra.
409 template <typename MeshType>
410 void test_write_and_read_mixed_poly_hex_impl(const std::string & filename)
411 {
412 MeshType mesh(*TestCommWorld);
413
414 // A hexagonal-prism polyhedron, nodes 0..11, in subdomain 1.
415 const std::vector<Point> points =
416 { { 0, -2, 0}, {-1, -1, 0}, {-1, 1, 0}, { 0, 2, 0}, { 1, 1, 0}, { 1, -1, 0},
417 { 0, -2, 1}, {-1, -1, 1}, {-1, 1, 1}, { 0, 2, 1}, { 1, 1, 1}, { 1, -1, 1} };
418 for (auto p : index_range(points))
419 mesh.add_point(points[p], p);
420
421 const std::vector<std::vector<unsigned int>> nodes_on_side =
422 { {0, 1, 2, 3, 4, 5}, {0, 1, 7, 6}, {1, 2, 8, 7}, {2, 3, 9, 8},
423 {3, 4, 10, 9}, {4, 5, 11, 10}, {5, 0, 6, 11}, {6, 7, 8, 9, 10, 11} };
424 std::vector<std::shared_ptr<Polygon>> sides(nodes_on_side.size());
425 for (auto s : index_range(nodes_on_side))
426 {
427 sides[s] = std::make_shared<C0Polygon>(nodes_on_side[s].size());
428 for (auto i : index_range(nodes_on_side[s]))
429 sides[s]->set_node(i, mesh.node_ptr(nodes_on_side[s][i]));
430 }
431 std::unique_ptr<Node> mid_elem_node;
432 std::unique_ptr<Elem> polyhedron =
433 std::make_unique<C0Polyhedron>(sides, mid_elem_node);
434 if (mid_elem_node)
435 mesh.add_node(std::move(mid_elem_node));
436 polyhedron->set_id() = 0;
437 polyhedron->subdomain_id() = 1;
438 mesh.add_elem(std::move(polyhedron));
439
440 // A HEX8 in the *same* subdomain, nodes 12..19 (offset in x).
441 const std::vector<Point> hex_points =
442 { {5,0,0}, {6,0,0}, {6,1,0}, {5,1,0}, {5,0,1}, {6,0,1}, {6,1,1}, {5,1,1} };
443 for (auto i : index_range(hex_points))
444 mesh.add_point(hex_points[i], 12 + i);
445 std::unique_ptr<Elem> hex = Elem::build(HEX8);
446 for (unsigned int i = 0; i != 8; ++i)
447 hex->set_node(i, mesh.node_ptr(12 + i));
448 hex->set_id() = 1;
449 hex->subdomain_id() = 1;
450 mesh.add_elem(std::move(hex));
451
455
456 {
457 ExodusII_IO exii(mesh);
458 exii.write(filename);
459 }
460
461 TestCommWorld->barrier();
462
463 MeshType input_mesh(*TestCommWorld);
464 ExodusII_IO exii_input(input_mesh);
465 if (input_mesh.processor_id() == 0)
466 exii_input.read(filename);
467
468 MeshCommunication().broadcast(input_mesh);
469 input_mesh.prepare_for_use();
470
471 CPPUNIT_ASSERT_EQUAL(cast_int<dof_id_type>(2), input_mesh.n_elem());
472
473 // Both element types must survive the round trip, in their own blocks.
474 unsigned int n_poly = 0, n_hex = 0;
475 for (const auto & elem : input_mesh.active_local_element_ptr_range())
476 {
477 if (elem->type() == C0POLYHEDRON)
478 ++n_poly;
479 else if (elem->type() == HEX8)
480 ++n_hex;
481 }
482 input_mesh.comm().sum(n_poly);
483 input_mesh.comm().sum(n_hex);
484 CPPUNIT_ASSERT_EQUAL(1u, n_poly);
485 CPPUNIT_ASSERT_EQUAL(1u, n_hex);
486 }
487
489 {
490 LOG_UNIT_TEST;
491 test_write_and_read_mixed_poly_hex_impl<ReplicatedMesh>("write_exodus_mixed_poly_hex_repl.e");
492 }
493
495 {
496 LOG_UNIT_TEST;
497 test_write_and_read_mixed_poly_hex_impl<DistributedMesh>("write_exodus_mixed_poly_hex_dist.e");
498 }
499
500 // A subdomain that mixes element types (here HEX8 + TET4) must be split
501 // into one Exodus block per type, since Exodus allows a single element
502 // type per block. Only the lower-valued ElemType keeps the subdomain
503 // id; the other type is written to a synthesized block whose name is the
504 // element type prefixed onto the original subdomain name, so it round
505 // trips as an identifiable, separate subdomain. This also checks the
506 // add_sides path, where side blocks are numbered above the synthesized
507 // element blocks and so must not collide with them.
508 template <typename MeshType>
509 void test_write_and_read_mixed_hex_tet_block_names_impl(const std::string & basename,
510 bool run_only_on_proc0 = true)
511 {
512 MeshType mesh(*TestCommWorld);
513
514 // HEX8, nodes 0..7, subdomain 1.
515 const std::vector<Point> hex_points =
516 { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0}, {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} };
517 for (auto i : index_range(hex_points))
518 mesh.add_point(hex_points[i], i);
519 std::unique_ptr<Elem> hex = Elem::build(HEX8);
520 for (unsigned int i = 0; i != 8; ++i)
521 hex->set_node(i, mesh.node_ptr(i));
522 hex->set_id() = 0;
523 hex->subdomain_id() = 1;
524 mesh.add_elem(std::move(hex));
525
526 // TET4 in the *same* subdomain 1, nodes 8..11 (offset in x).
527 const std::vector<Point> tet_points =
528 { {5,0,0}, {6,0,0}, {5,1,0}, {5,0,1} };
529 for (auto i : index_range(tet_points))
530 mesh.add_point(tet_points[i], 8 + i);
531 std::unique_ptr<Elem> tet = Elem::build(TET4);
532 for (unsigned int i = 0; i != 4; ++i)
533 tet->set_node(i, mesh.node_ptr(8 + i));
534 tet->set_id() = 1;
535 tet->subdomain_id() = 1;
536 mesh.add_elem(std::move(tet));
537
538 mesh.set_subdomain_name(1, "solid", /*synchronous=*/true);
539
542
543 // ExodusII_IO only writes on processor 0. A helper created with
544 // run_only_on_proc0=false instead writes on every rank (as Nemesis
545 // and MOOSE do), each to its own file, so build_subdomain_map() has
546 // to reduce the local elements across ranks. That needs the whole
547 // mesh on every rank.
548 libmesh_assert(run_only_on_proc0 || mesh.is_serial());
549 const std::string suffix = run_only_on_proc0 ? ".e" :
550 "." + std::to_string(mesh.n_processors()) + "." +
551 std::to_string(mesh.processor_id()) + ".e";
552
553 auto write_mesh = [&mesh, run_only_on_proc0](const std::string & filename,
554 bool add_sides)
555 {
556 if (run_only_on_proc0)
557 {
558 ExodusII_IO exii(mesh);
559 exii.write_added_sides(add_sides);
560 exii.write(filename);
561 }
562 else
563 {
564 ExodusII_IO_Helper helper(mesh, /*v=*/false, /*run_only_on_proc0=*/false);
565 helper.set_add_sides(add_sides);
566 helper.create(filename);
567 helper.initialize(filename, mesh);
569 helper.write_elements(mesh);
570 helper.close();
571 }
572 };
573
574 write_mesh(basename + suffix, /*add_sides=*/false);
575
576 // The mixed subdomain must also survive an add_sides write: its side
577 // blocks are numbered above the synthesized element block, so the two
578 // id spaces must not collide (guarded in build_subdomain_map()).
579 write_mesh(basename + "_sides" + suffix, /*add_sides=*/true);
580
581 TestCommWorld->barrier();
582
583 // Processor 0's file is read back either way.
584 MeshType input_mesh(*TestCommWorld);
585 ExodusII_IO exii_input(input_mesh);
586 if (input_mesh.processor_id() == 0)
587 exii_input.read(basename + suffix);
588
589 MeshCommunication().broadcast(input_mesh);
590 input_mesh.prepare_for_use();
591
592 CPPUNIT_ASSERT_EQUAL(cast_int<dof_id_type>(2), input_mesh.n_elem());
593
594 // Both element types survive the round trip.
595 unsigned int n_hex = 0, n_tet = 0;
596 for (const auto & elem : input_mesh.active_local_element_ptr_range())
597 {
598 if (elem->type() == HEX8)
599 ++n_hex;
600 else if (elem->type() == TET4)
601 ++n_tet;
602 }
603 input_mesh.comm().sum(n_hex);
604 input_mesh.comm().sum(n_tet);
605 CPPUNIT_ASSERT_EQUAL(1u, n_hex);
606 CPPUNIT_ASSERT_EQUAL(1u, n_tet);
607
608 // The single input subdomain became two: the original "solid" (which
609 // kept the TET4, the lower-valued ElemType) and a synthesized
610 // "HEX8_solid" for the HEX8.
611 std::set<subdomain_id_type> sbd_ids;
612 input_mesh.subdomain_ids(sbd_ids);
613 CPPUNIT_ASSERT_EQUAL(std::size_t(2), sbd_ids.size());
614
615 std::set<std::string> names;
616 for (auto sid : sbd_ids)
617 names.insert(input_mesh.subdomain_name(sid));
618 CPPUNIT_ASSERT_EQUAL(std::size_t(1), names.count("solid"));
619 CPPUNIT_ASSERT_EQUAL(std::size_t(1), names.count("solid_HEX8"));
620 }
621
623 {
624 LOG_UNIT_TEST;
625 test_write_and_read_mixed_hex_tet_block_names_impl<ReplicatedMesh>("write_exodus_mixed_hex_tet_repl");
626 }
627
629 {
630 LOG_UNIT_TEST;
631 test_write_and_read_mixed_hex_tet_block_names_impl<DistributedMesh>("write_exodus_mixed_hex_tet_dist");
632 }
633
635 {
636 LOG_UNIT_TEST;
637 test_write_and_read_mixed_hex_tet_block_names_impl<ReplicatedMesh>
638 ("write_exodus_mixed_hex_tet_all_ranks", /*run_only_on_proc0=*/false);
639 }
640};
641
643
647
651
657
658// These tests use PointLocator, which uses contains_point(), which
659// uses inverse_map(), which doesn't play nicely on Pyramids unless we
660// have exceptions support
661#ifdef LIBMESH_ENABLE_EXCEPTIONS
666#endif
667#endif // LIBMESH_DIM > 2
668
669#endif // LIBMESH_HAVE_EXODUS_API
LIBMESH_CPPUNIT_TEST_SUITE(ExodusC0PolygonTest)
void build_pentagon(Mesh &mesh)
CPPUNIT_TEST(test_write_and_read_pentagon)
void test_write_and_read_pentagon()
void test_write_and_read_mixed_hex_tet_block_names_replicated()
CPPUNIT_TEST(test_write_and_read_hexagonal_prism)
CPPUNIT_TEST(test_write_and_read_mixed_hex_tet_block_names_replicated)
void test_write_and_read_mixed_poly_hex_replicated()
CPPUNIT_TEST(test_write_hexagonal_prism_header)
void test_write_hexagonal_prism_header()
void test_write_and_read_hexagonal_prism()
CPPUNIT_TEST(test_write_and_read_mixed_hex_tet_block_names_distributed)
CPPUNIT_TEST(test_write_and_read_mixed_poly_hex_distributed)
void test_write_and_read_mixed_hex_tet_block_names_impl(const std::string &basename, bool run_only_on_proc0=true)
CPPUNIT_TEST(test_write_and_read_mixed_hex_tet_block_names_all_ranks)
void build_c0polyhedron(Mesh &mesh, const std::vector< Point > &points, const std::vector< std::vector< unsigned int > > &nodes_on_side)
void test_write_and_read_mixed_hex_tet_block_names_all_ranks()
ExodusHeaderInfo write_and_read_header(Mesh &mesh, const std::string &filename)
static void assert_distributed_if_parallel(const MeshBase &mesh)
void test_write_and_read_mixed_poly_hex_impl(const std::string &filename)
CPPUNIT_TEST(test_write_cube_header)
void test_write_and_read_mixed_hex_tet_block_names_distributed()
LIBMESH_CPPUNIT_TEST_SUITE(ExodusC0PolyhedronTest)
void test_write_and_read_mixed_poly_hex_distributed()
CPPUNIT_TEST(test_write_and_read_mixed_poly_hex_replicated)
void test_write()
Definition exodus_test.C:45
void test_read_gold()
Definition exodus_test.C:28
bool meshes_equal_enough(Mesh &other_mesh, bool double_precision)
std::unique_ptr< Mesh > _mesh
Definition elem_test.h:26
void max(const T &r, T &o, Request &req) const
void clear()
Clears the underlying data structures and restores the object to a pristine state with no data stored...
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
virtual dof_id_type n_elem() const override final
virtual const Elem * query_elem_ptr(const dof_id_type i) const override final
dof_id_type & set_id()
Definition dof_object.h:841
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual unsigned int n_vertices() const =0
virtual unsigned int n_nodes() const =0
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:382
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
subdomain_id_type subdomain_id() const
Definition elem.h:2712
virtual ElemType type() const =0
virtual unsigned int n_sides() const =0
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2605
IntRange< unsigned short > side_index_range() const
Definition elem.h:2848
This class is used as both an external data structure for passing around Exodus file header informati...
This is the ExodusII_IO_Helper class.
virtual void write_nodal_coordinates(const MeshBase &mesh, bool use_discontinuous=false)
Writes the nodal coordinates contained in "mesh".
void close() noexcept
Closes the ExodusII mesh file.
virtual void create(std::string filename)
Opens an ExodusII mesh file named filename for writing.
virtual void write_elements(const MeshBase &mesh, bool use_discontinuous=false)
Writes the elements contained in "mesh".
virtual void initialize(std::string title, const MeshBase &mesh, bool use_discontinuous=false)
Initializes the Exodus file.
void set_add_sides(bool add_sides)
Sets whether or not to write extra "side" elements.
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition exodusII_io.h:53
void set_max_name_length(unsigned int max_length)
For backwards compatibility, libMesh currently truncates names in ExodusII output to the old default ...
virtual void write(const std::string &fname) override
This method implements writing a mesh to a specified file.
ExodusHeaderInfo read_header(const std::string &name)
Read only the header information, instead of the entire mesh.
virtual void read(const std::string &name) override
This method implements reading a mesh from a specified file.
void write_added_sides(bool val)
By default, we only write out the elements physically stored in the mesh.
This is the MeshBase class.
Definition mesh_base.h:81
void set_subdomain_name(subdomain_id_type id, const std::string &name, bool synchronous=false)
Sets the name for the provided id.
Definition mesh_base.C:1929
virtual bool is_serial() const
Definition mesh_base.h:357
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
virtual const Node * node_ptr(const dof_id_type i) const =0
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
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
virtual Node * add_node(Node *n)=0
Add Node n to the end of the vertex array.
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
This is the MeshCommunication class.
void broadcast(MeshBase &) const
This method takes a mesh (which is assumed to reside on processor 0) and broadcasts it to all the oth...
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
Communicator * TestCommWorld
CPPUNIT_TEST_SUITE_REGISTRATION(ExodusC0PolygonTest)
INSTANTIATE_EXODUSTEST(EDGE2)
MeshBase & mesh
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.
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
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
libmesh_assert(ctx)
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