libMesh
Loading...
Searching...
No Matches
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
27using 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
53constexpr 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
99class MeshInputTest : public CppUnit::TestCase {
100public:
102
103#if LIBMESH_DIM > 1
104#ifdef LIBMESH_HAVE_VTK
107#endif
108
109#ifdef LIBMESH_HAVE_EXODUS_API
117#if LIBMESH_DIM > 2
120#endif
121#ifndef LIBMESH_USE_COMPLEX_NUMBERS
124
125 // Eventually this will support complex numbers.
127#endif // !LIBMESH_USE_COMPLEX_NUMBERS
128
133 // CPPUNIT_TEST( testExodusDiscWriteAddedSidesEdgeDisc ); // need is_on_face fixes
134 // CPPUNIT_TEST( testExodusDiscWriteAddedSidesEdgeDisc ); // need is_on_face fixes
139 // CPPUNIT_TEST( testExodusWriteAddedSidesTriDisc ); // Need aligned faces
140 // CPPUNIT_TEST( testExodusDiscWriteAddedSidesTriDisc ); // Need aligned faces
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 );
157
162
167#endif // LIBMESH_HAVE_EXODUS_API
168
169#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
172
177
180#ifndef LIBMESH_USE_COMPLEX_NUMBERS
183#endif // !LIBMESH_USE_COMPLEX_NUMBERS
184#endif // defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
185
186#ifdef LIBMESH_HAVE_GZSTREAM
196#endif // LIBMESH_HAVE_GZSTREAM
197#endif // LIBMESH_DIM > 1
198 //
199#if LIBMESH_DIM > 1
202#endif
203
204#if LIBMESH_DIM > 2
207
209
210#ifdef LIBMESH_HAVE_TETGEN
212#endif
213#endif
214
216
217private:
218
219public:
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.
262 TestCommWorld->barrier();
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.
311 TestCommWorld->barrier();
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.
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.
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};
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);
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.
475 TestCommWorld->barrier();
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
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
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
723 System &sys = es.add_system<System> ("SimpleSystem");
724 sys.add_variable("e", CONSTANT, MONOMIAL);
725 sys.add_variable("e_no_p", FEType(CONSTANT, MONOMIAL).set_p_refinement(false));
726 sys.add_variable("e_xyz", FEType(CONSTANT, XYZ));
727
729 3, 3,
730 0., 1., 0., 1.);
731
732 es.init();
734
735 IOType meshinput(mesh);
736
737 // Don't try to write element data as nodal data
738 std::set<std::string> sys_list;
739 meshinput.write_equation_systems(filename, es, &sys_list);
740
741 // Just write it as element data
742 meshinput.write_element_data(es);
743 }
744
745 {
746 MeshType mesh(*TestCommWorld);
747 mesh.allow_renumbering(false);
748 IOType meshinput(mesh);
749
750 // Avoid getting Nemesis solution values mixed up
751 if (meshinput.is_parallel_format())
752 {
754 }
755
757 System &sys = es.add_system<System> ("SimpleSystem");
758 sys.add_variable("teste", CONSTANT, MONOMIAL);
759 sys.add_variable("teste_no_p", FEType(CONSTANT, MONOMIAL).set_p_refinement(false));
760 sys.add_variable("teste_xyz", FEType(CONSTANT, XYZ));
761
762 if (mesh.processor_id() == 0 || meshinput.is_parallel_format())
763 meshinput.read(filename);
764 if (!meshinput.is_parallel_format())
767
768 es.init();
769
770 // Read the solution e into variable teste.
771 //
772 // With complex numbers, we'll only bother reading the real
773 // part.
774#ifdef LIBMESH_USE_COMPLEX_NUMBERS
775 meshinput.copy_elemental_solution(sys, "teste", "r_e");
776 meshinput.copy_elemental_solution(sys, "teste_no_p", "r_e_no_p");
777 meshinput.copy_elemental_solution(sys, "teste_xyz", "r_e_xyz");
778#else
779 meshinput.copy_elemental_solution(sys, "teste", "e");
780 meshinput.copy_elemental_solution(sys, "teste_no_p", "e_no_p");
781 meshinput.copy_elemental_solution(sys, "teste_xyz", "e_xyz");
782#endif
783
784 // Exodus only handles double precision
785 Real exotol = std::max(TOLERANCE*TOLERANCE, Real(1e-12));
786
787 for (Real x = Real(1.L/6.L); x < 1; x += Real(1.L/3.L))
788 for (Real y = Real(1.L/6.L); y < 1; y += Real(1.L/3.L))
789 {
790 Point p(x,y);
791 LIBMESH_ASSERT_NUMBERS_EQUAL
792 (sys.point_value(0,p), 6*x+60*y, exotol);
793 LIBMESH_ASSERT_NUMBERS_EQUAL
794 (sys.point_value(1,p), 6*x+60*y, exotol);
795 LIBMESH_ASSERT_NUMBERS_EQUAL
796 (sys.point_value(2,p), 6*x+60*y, exotol);
797 }
798 }
799 }
800
801
803 { LOG_UNIT_TEST; testCopyElementSolutionImpl<ReplicatedMesh,ExodusII_IO>("repl_with_elem_soln.e"); }
804
806 { LOG_UNIT_TEST; testCopyElementSolutionImpl<DistributedMesh,ExodusII_IO>("dist_with_elem_soln.e"); }
807
808#if defined(LIBMESH_HAVE_NEMESIS_API)
810 { LOG_UNIT_TEST; testCopyElementSolutionImpl<ReplicatedMesh,Nemesis_IO>("repl_with_elem_soln.nem"); }
811
813 { LOG_UNIT_TEST; testCopyElementSolutionImpl<DistributedMesh,Nemesis_IO>("dist_with_elem_soln.nem"); }
814
815
816 // This tests that a single-element mesh solution makes it through all of the API to write out a
817 // set of Nemesis files. When this executes in parallel, there are ((number of processors) - 1)
818 // subdomains with zero elements and therefore nothing to write, but the API should handle this.
819 template <typename MeshType, typename IOType>
820 void testSingleElementImpl(const std::string & filename)
821 {
822 {
823 // Generate a single 1x1 square element mesh
824 MeshType mesh(*TestCommWorld);
826
828 auto & sys = es.add_system<System>("SimpleSystem");
829 sys.add_variable("e", CONSTANT, MONOMIAL);
830
831 // Set an arbitrary solution for the single element DOF
832 es.init();
833 sys.project_solution(six_x_plus_sixty_y, nullptr, es.parameters);
834
835 // Write the solution to Nemesis file(s) - only proc 0 should have anything to write!
836 Nemesis_IO nem_io(mesh);
837 std::set<std::string> sys_list;
838 nem_io.write_equation_systems(filename, es, &sys_list);
839 nem_io.write_element_data(es);
840 }
841
842 // If we can read and copy the correct element value back into the mesh, we know the Nemesis
843 // file(s) were written properly.
844 {
845 MeshType mesh(*TestCommWorld);
846 mesh.allow_renumbering(false);
848 auto & sys = es.add_system<System>("SimpleSystem");
849 sys.add_variable("teste", CONSTANT, MONOMIAL);
850
851 Nemesis_IO nem_io(mesh);
852 if (mesh.processor_id() == 0 || nem_io.is_parallel_format())
853 nem_io.read(filename);
854
856 es.init();
857
858#ifdef LIBMESH_USE_COMPLEX_NUMBERS
859 nem_io.copy_elemental_solution(sys, "teste", "r_e");
860#else
861 nem_io.copy_elemental_solution(sys, "teste", "e");
862#endif
863
864 // The result should be '\frac{6 + 60}{2} = 33' at all points in the element domain
865 CPPUNIT_ASSERT_EQUAL(int(sys.solution->size()), 1);
866 CPPUNIT_ASSERT_EQUAL(libmesh_real(sys.point_value(0, Point(0.5, 0.5))), Real(33));
867 }
868 }
869
870
872 { LOG_UNIT_TEST; testSingleElementImpl<ReplicatedMesh,Nemesis_IO>("repl_with_single_elem.nem"); }
873
875 { LOG_UNIT_TEST; testSingleElementImpl<DistributedMesh,Nemesis_IO>("dist_with_single_elem.nem"); }
876#endif //defined(LIBMESH_HAVE_NEMESIS_API)
877
878
879#ifndef LIBMESH_USE_COMPLEX_NUMBERS
880 // So this tester runs through pretty much the same process as 'testCopyElementSolutionImpl()'
881 // except for a CONSTANT MONOMIAL_VEC variable. It mainly serves as a test for writing elemental
882 // vector variables to elements in ExodusII files, and is not actually a test for reading and
883 // copying an elemental solution.
884 template <typename MeshType, typename IOType>
885 void testCopyElementVectorImpl(const std::string & filename)
886 {
887 {
888 MeshType mesh(*TestCommWorld);
889
891 System & sys = es.add_system<System> ("SimpleSystem");
892 auto e_var = sys.add_variable("e", CONSTANT, MONOMIAL_VEC);
893 auto e_no_p_var = sys.add_variable("e_no_p",
895
897 3, 3,
898 0., 1., 0., 1.);
899
900 es.init();
901
902 // Here, we're going to manually set up the solution because the 'project_solution()' and
903 // 'project_vector()' methods don't work so well with CONSTANT MONOMIAL_VEC variables. They
904 // each lead to an error downstream asserting positive-definiteness when Cholesky decomposing.
905 // Interestingly, the error is only invoked for CONSTANT MONOMIAL_VEC, and not, e.g.,
906 // CONSTANT MONOMIAL nor FIRST LAGRANGE_VEC.
907 //
908 // Anyways, the important thing here is that we test the ExodusII and Nemesis writers, how
909 // the solution is set is hardly important, and we're pretty much following the same
910 // philosophy as the 'test2DProjectVectorFE()' unit tester in 'systems_test.C'
911 Parameters params;
912 for (const auto & elem : mesh.active_local_element_ptr_range())
913 {
914 const Point & p = elem->vertex_average();
915
916 // Set the x-component with the value from 'six_x_plus_sixty_y()' and the y-component
917 // with that from 'sin_x_plus_cos_y()' at the element centroid (vertex average)
918 sys.current_local_solution->set(
919 elem->dof_number(sys.number(), e_var, 0), six_x_plus_sixty_y(p, params, "", ""));
920 sys.current_local_solution->set(
921 elem->dof_number(sys.number(), e_var, 1), sin_x_plus_cos_y(p, params, "", ""));
922 sys.current_local_solution->set(
923 elem->dof_number(sys.number(), e_no_p_var, 0), six_x_plus_sixty_y(p, params, "", ""));
924 sys.current_local_solution->set(
925 elem->dof_number(sys.number(), e_no_p_var, 1), sin_x_plus_cos_y(p, params, "", ""));
926 }
927
928 // After setting values, we need to assemble
929 sys.current_local_solution->close();
930
931 IOType meshinput(mesh);
932
933 // Don't try to write element data as nodal data
934 std::set<std::string> sys_list;
935 meshinput.write_equation_systems(filename, es, &sys_list);
936
937 // Just write it as element data
938 meshinput.write_element_data(es);
939 }
940
941 {
942 MeshType mesh(*TestCommWorld);
943 mesh.allow_renumbering(false);
944 IOType meshinput(mesh);
945
946 // Avoid getting Nemesis solution values mixed up
947 if (meshinput.is_parallel_format())
948 {
950 }
951
953 System & sys = es.add_system<System> ("SimpleSystem");
954
955 // We have to read the CONSTANT MONOMIAL_VEC var "e" into separate CONSTANT MONOMIAL vars
956 // "e_x" and "e_y" because 'copy_elemental_solution()' currently doesn't support vectors.
957 // Again, this isn't a test for reading/copying an elemental vector solution, only writing.
958 sys.add_variable("teste_x", FEType(CONSTANT, MONOMIAL).set_p_refinement(false));
959 sys.add_variable("teste_y", FEType(CONSTANT, MONOMIAL).set_p_refinement(false));
960 sys.add_variable("teste_no_p_x", FEType(CONSTANT, MONOMIAL).set_p_refinement(false));
961 sys.add_variable("teste_no_p_y", FEType(CONSTANT, MONOMIAL).set_p_refinement(false));
962
963 if (mesh.processor_id() == 0 || meshinput.is_parallel_format())
964 meshinput.read(filename);
965 if (!meshinput.is_parallel_format())
968
969 es.init();
970
971 // Read the solution e_x and e_y into variable teste_x and teste_y, respectively.
972 meshinput.copy_elemental_solution(sys, "teste_x", "e_x");
973 meshinput.copy_elemental_solution(sys, "teste_y", "e_y");
974 meshinput.copy_elemental_solution(sys, "teste_no_p_x", "e_no_p_x");
975 meshinput.copy_elemental_solution(sys, "teste_no_p_y", "e_no_p_y");
976
977 // Exodus only handles double precision
978 Real exotol = std::max(TOLERANCE*TOLERANCE, Real(1e-12));
979
980 for (Real x = Real(1.L/6.L); x < 1; x += Real(1.L/3.L))
981 for (Real y = Real(1.L/6.L); y < 1; y += Real(1.L/3.L))
982 {
983 Point p(x,y);
984 LIBMESH_ASSERT_NUMBERS_EQUAL
985 (sys.point_value(0,p), 6*x+60*y, exotol);
986 LIBMESH_ASSERT_NUMBERS_EQUAL
987 (sys.point_value(1,p), sin(x)+cos(y), exotol);
988 LIBMESH_ASSERT_NUMBERS_EQUAL
989 (sys.point_value(2,p), 6*x+60*y, exotol);
990 LIBMESH_ASSERT_NUMBERS_EQUAL
991 (sys.point_value(3,p), sin(x)+cos(y), exotol);
992 }
993 }
994 }
995
997 { LOG_UNIT_TEST; testCopyElementVectorImpl<ReplicatedMesh, ExodusII_IO>("repl_with_elem_vec.e"); }
998
1000 { LOG_UNIT_TEST; testCopyElementVectorImpl<DistributedMesh,ExodusII_IO>("dist_with_elem_vec.e"); }
1001
1002#if defined(LIBMESH_HAVE_NEMESIS_API)
1004 { LOG_UNIT_TEST; testCopyElementVectorImpl<ReplicatedMesh,Nemesis_IO>("repl_with_elem_vec.nem"); }
1005
1007 { LOG_UNIT_TEST; testCopyElementVectorImpl<DistributedMesh,Nemesis_IO>("dist_with_elem_vec.nem"); }
1008#endif
1009
1010
1012 {
1013 LOG_UNIT_TEST;
1014
1015 const Real scalar_value = 42.;
1016 const Real xyz_value = 84.;
1017 const std::vector<Real> vector_values = {10., 20., 30.};
1018
1019 // first scope: write file
1020 {
1022
1024 System & sys = es.add_system<System> ("SimpleSystem");
1025 sys.add_variable("u", FIRST, L2_LAGRANGE);
1026 const auto c_var =
1028 const auto xyz_var =
1029 sys.add_variable("xyz", FEType(CONSTANT, XYZ));
1030 const auto vec_var =
1032
1034 (mesh, 2, 2, 2, 0., 1., 0., 1., 0., 1., HEX8);
1035
1036 es.init();
1037
1038 // Set solution u^e_i = i, for the ith vertex of a given element e.
1039 const DofMap & dof_map = sys.get_dof_map();
1040 std::vector<dof_id_type> dof_indices;
1041 for (const auto & elem : mesh.element_ptr_range())
1042 {
1043 dof_map.dof_indices(elem, dof_indices, /*var_id=*/0);
1044 for (unsigned int i=0; i<dof_indices.size(); ++i)
1045 sys.solution->set(dof_indices[i], i);
1046
1047 sys.solution->set(elem->dof_number(sys.number(), c_var, 0), scalar_value);
1048 sys.solution->set(elem->dof_number(sys.number(), xyz_var, 0), xyz_value);
1049 for (auto comp : index_range(vector_values))
1050 sys.solution->set(elem->dof_number(sys.number(),
1051 vec_var,
1052 cast_int<unsigned int>(comp)),
1053 vector_values[comp]);
1054 }
1055 sys.solution->close();
1056
1057 // Now write to file.
1058 ExodusII_IO exii(mesh);
1059
1060 // Don't try to write element data as averaged nodal data.
1061 std::set<std::string> sys_list;
1062 exii.write_equation_systems("elemental_from_nodal.e", es, &sys_list);
1063
1064 // Write one elemental data field per vertex value.
1065 sys_list = {"SimpleSystem"};
1066
1068 (es, &sys_list, /*var_suffix=*/"_elem_corner_");
1069 } // end first scope
1070
1071 // second scope: read values back in, verify they are correct.
1072 {
1073 std::vector<std::string> file_var_names =
1074 {"u_elem_corner_0",
1075 "u_elem_corner_1",
1076 "u_elem_corner_2",
1077 "u_elem_corner_3",
1078 "c",
1079 "xyz",
1080 "vec_x",
1081 "vec_y",
1082 "vec_z"};
1083 std::vector<Real> expected_values =
1084 {0., 1., 2., 3.,
1085 scalar_value, xyz_value, vector_values[0], vector_values[1], vector_values[2]};
1086
1087 // copy_elemental_solution currently requires ReplicatedMesh
1089 mesh.allow_renumbering(false);
1090
1092 System & sys = es.add_system<System> ("SimpleSystem");
1093 for (auto i : index_range(file_var_names))
1094 sys.add_variable(file_var_names[i], FEType(CONSTANT, MONOMIAL).set_p_refinement(false));
1095
1096 ExodusII_IO exii(mesh);
1097
1098 if (mesh.processor_id() == 0)
1099 exii.read("elemental_from_nodal.e");
1102
1103 es.init();
1104
1105 for (auto i : index_range(file_var_names))
1107 (sys, sys.variable_name(i), file_var_names[i]);
1108
1109 // Check that the values we read back in are as expected.
1110 for (const auto & elem : mesh.active_element_ptr_range())
1111 for (auto i : index_range(file_var_names))
1112 {
1113 Real read_val = sys.point_value(i, elem->vertex_average());
1114 LIBMESH_ASSERT_FP_EQUAL
1115 (expected_values[i], read_val, TOLERANCE*TOLERANCE);
1116 }
1117 } // end second scope
1118 } // end testExodusWriteElementDataFromDiscontinuousNodalData
1119
1120#endif // !LIBMESH_USE_COMPLEX_NUMBERS
1121
1122
1124 (Number (*exact_sol)(const Point &, const Parameters &, const
1125 std::string &, const std::string &),
1126 const ElemType elem_type,
1127 const Order order,
1128 const bool write_discontinuous = false,
1129 const std::vector<FEType> earlier_vars = {},
1130 const std::vector<FEType> later_vars = {})
1131 {
1132 constexpr unsigned int nx = added_sides_nxyz[0],
1133 ny = added_sides_nxyz[1],
1134 nz = added_sides_nxyz[2];
1135
1136 const unsigned int dim = Elem::type_to_dim_map[elem_type];
1137 const bool is_tensor = (Elem::build(elem_type)->n_sides() == dim * 2);
1138
1139 // Figure out how many fake and true elements to expect
1140 dof_id_type n_fake_elem = 0;
1141 dof_id_type n_true_elem = 0;
1142
1143 dof_id_type n_fake_nodes = 0;
1144 dof_id_type n_true_nodes = 0;
1145
1146 const std::string filename =
1147 "side_discontinuous_"+Utility::enum_to_string<ElemType>(elem_type)+(write_discontinuous?"_disc":"")+".e";
1148
1149 // first scope: write file
1150 {
1151 Mesh mesh(*TestCommWorld);
1152
1154 System & sys = es.add_system<System> ("SimpleSystem");
1155 int varnum = 1;
1156 for (auto vartype : earlier_vars)
1157 sys.add_variable("earlier_"+std::to_string(varnum++), vartype);
1158
1159 sys.add_variable("u", order, SIDE_HIERARCHIC);
1160
1161 varnum = 1;
1162 for (auto vartype : later_vars)
1163 sys.add_variable("later_"+std::to_string(varnum++), vartype);
1164
1165 if (dim == 3)
1167 (mesh, nx, ny, nz, 0., 1., 0., 1., 0., 1., elem_type);
1168 else if (dim == 2)
1170 (mesh, nx, ny, 0., 1., 0., 1., elem_type);
1171 else
1173 (mesh, nx, 0., 1., elem_type);
1174
1175 n_true_elem = mesh.n_elem();
1176 n_true_nodes = mesh.n_nodes();
1177 CPPUNIT_ASSERT_LESS(n_true_nodes, n_true_elem); // Ne < Nn
1178
1179 const unsigned int our_ny = dim>1 ? ny : 1;
1180 const unsigned int our_nz = dim>2 ? nz : 1;
1181
1182 dof_id_type min_n_elem = nx * our_ny * our_nz;
1183 CPPUNIT_ASSERT_LESSEQUAL(n_true_elem, min_n_elem); // "backwards" API...
1184
1185 for (const auto & elem : mesh.active_local_element_ptr_range())
1186 {
1187 for (auto s : make_range(elem->n_sides()))
1188 if (!elem->neighbor_ptr(s) || elem->neighbor_ptr(s)->id() < elem->id())
1189 {
1190 ++n_fake_elem;
1191 auto side = elem->build_side_ptr(s);
1192 n_fake_nodes += side->n_nodes();
1193 }
1194 }
1195 mesh.comm().sum(n_fake_elem);
1196 mesh.comm().sum(n_fake_nodes);
1197
1198 const dof_id_type expected_fakes = [elem_type]() {
1199 switch (elem_type)
1200 {
1201 case EDGE3:
1202 return nx+1;
1203 case TRI6:
1204 return 3*nx*ny + nx + ny;
1205 case QUAD8:
1206 case QUAD9:
1207 return 2*nx*ny + nx + ny;
1208 case TET14:
1209 return 48*nx*ny*nz + 4*(nx*ny+nx*nz+ny*nz);
1210 case HEX27:
1211 return 3*nx*ny*nz + nx*ny + nx*nz + ny*nz;
1212 default:
1213 libmesh_error();
1214 }
1215 } (); // Invoke anonymous lambda
1216
1217 CPPUNIT_ASSERT_EQUAL(n_fake_elem, expected_fakes); // "backwards" API...
1218
1219 es.init();
1220 sys.project_solution(exact_sol, nullptr,
1221 es.parameters);
1222
1223 // Set solution u^e_i = i, for the ith vertex of a given element e.
1224
1225 // Now write to file.
1226 ExodusII_IO exii(mesh);
1227 exii.write_added_sides(true);
1228
1229 if (write_discontinuous)
1230 exii.write_discontinuous_equation_systems(filename, es);
1231 else
1232 exii.write_equation_systems(filename, es);
1233 } // end first scope
1234
1235 // second scope: read file, verify extra elements exist
1236 {
1237 Mesh mesh(*TestCommWorld);
1238 mesh.allow_renumbering(false);
1239 ExodusII_IO exii(mesh);
1240
1241 if (mesh.processor_id() == 0)
1242 exii.read(filename);
1245
1246 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), n_true_elem + n_fake_elem);
1247 if (write_discontinuous)
1248 {
1249 const dof_id_type nodes_per_elem = Elem::build(elem_type)->n_nodes();
1250 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(),
1251 n_true_elem*nodes_per_elem + n_fake_nodes);
1252 }
1253 else
1254 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), n_true_nodes + n_fake_nodes);
1255
1257 System & sys = es.add_system<System> ("SimpleSystem");
1258 // Read back into a LAGRANGE variable for testing; we still
1259 // can't use Exodus for a proper restart.
1260 sys.add_variable("ul", SECOND);
1261 es.init();
1262
1263 const DofMap & dof_map = sys.get_dof_map();
1264
1265#ifdef LIBMESH_USE_COMPLEX_NUMBERS
1266 exii.copy_nodal_solution(sys, "ul", "r_u");
1267#else
1268 exii.copy_nodal_solution(sys, "ul", "u");
1269#endif
1270
1271 dof_id_type n_side_nodes = 0;
1272 const std::string nullstr;
1273 const std::string facestr = "face";
1274
1275 // Debugging this in parallel is tricky. Let's make sure that
1276 // if we have a failure on one rank we see it on all the others
1277 // and we can go on to other tests.
1278#ifdef LIBMESH_ENABLE_EXCEPTIONS
1279 bool threw_exception = false;
1280 try
1281#endif // LIBMESH_ENABLE_EXCEPTIONS
1282 {
1283 for (const auto & elem : mesh.active_local_element_ptr_range())
1284 {
1285 // Just look at side elements, not interiors
1286 if (elem->dim() == dim)
1287 continue;
1288
1289 std::vector<dof_id_type> dof_indices;
1290 dof_map.dof_indices(elem, dof_indices, 0);
1291
1292 // Find what face direction we're looking at, to
1293 // disambiguate when testing against a discontinuous
1294 // function, since we're evaluating on nodes that overlap
1295 // multiple faces
1296 const Point normal = [elem](){
1297 if (elem->dim() == 2)
1298 return Point((elem->point(1) - elem->point(0)).cross
1299 (elem->point(2) - elem->point(0)));
1300 else if (elem->dim() == 1)
1301 return Point
1302 (elem->point(1)(1)-elem->point(0)(1),
1303 elem->point(0)(0)-elem->point(1)(0));
1304 else
1305 return Point(1);
1306 } (); // Invoke anonymous lambda
1307
1308 short faceval = -1;
1309 if (is_tensor)
1310 {
1311 if (std::abs(normal(0)) > TOLERANCE)
1312 {
1313 faceval = 0;
1314 libmesh_assert_less(std::abs(normal(1)), TOLERANCE);
1315 libmesh_assert_less(std::abs(normal(2)), TOLERANCE);
1316 }
1317 else if (std::abs(normal(1)) > TOLERANCE)
1318 {
1319 faceval = 1;
1320 libmesh_assert_less(std::abs(normal(2)), TOLERANCE);
1321 }
1322 else
1323 {
1324 faceval = 2;
1325 libmesh_assert_greater(std::abs(normal(2)), TOLERANCE);
1326 }
1327 libmesh_assert_greater_equal(faceval, 0);
1328 es.parameters.set<short>(facestr) = faceval;
1329 }
1330
1331 for (auto i : index_range(dof_indices))
1332 {
1333 const Point node_pt = elem->point(i);
1334 const Real nodal_coef =
1335 libmesh_real((*sys.current_local_solution)(dof_indices[i]));
1336 const Real exact_val =
1337 libmesh_real(exact_sol
1338 (node_pt, es.parameters, nullstr,
1339 nullstr));
1340 LIBMESH_ASSERT_FP_EQUAL
1341 (nodal_coef, exact_val,
1342 std::max(Real(2),nodal_coef+exact_val)*
1343 TOLERANCE*std::sqrt(TOLERANCE));
1344 ++n_side_nodes;
1345 }
1346 }
1347 }
1348#ifdef LIBMESH_ENABLE_EXCEPTIONS
1349 catch (...)
1350 {
1351 threw_exception = true;
1352 TestCommWorld->max(threw_exception);
1353 throw;
1354 }
1355 if (!threw_exception)
1356 TestCommWorld->max(threw_exception);
1357 CPPUNIT_ASSERT(!threw_exception);
1358#endif // LIBMESH_ENABLE_EXCEPTIONS
1359
1360 TestCommWorld->sum(n_side_nodes);
1361 CPPUNIT_ASSERT_EQUAL(n_side_nodes, n_fake_nodes);
1362 } // end second scope
1363 } // end testExodusWriteAddedSides
1364
1370
1376
1382
1388
1393
1398
1404
1410
1416
1422
1427
1432
1438
1444
1450
1456
1461
1466
1472
1478
1483
1488
1494
1500
1506
1512
1517
1522
1523#endif // LIBMESH_HAVE_EXODUS_API
1524
1525
1526#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
1527 template <typename MeshType>
1529 {
1530 // first scope: write file
1531 {
1532 MeshType mesh(*TestCommWorld);
1533 MeshTools::Generation::build_square (mesh, 3, 3, 0., 1., 0., 1.);
1534 mesh.write("test_nemesis_read.nem");
1535 }
1536
1537 // Make sure that the writing is done before the reading starts.
1538 TestCommWorld->barrier();
1539
1540 // second scope: read file
1541 {
1542 MeshType mesh(*TestCommWorld);
1543 Nemesis_IO nem(mesh);
1544
1545 nem.read("test_nemesis_read.nem");
1547 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(9));
1548 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(16));
1549 }
1550 }
1551
1553 { LOG_UNIT_TEST; testNemesisReadImpl<ReplicatedMesh>(); }
1554
1556 { LOG_UNIT_TEST; testNemesisReadImpl<DistributedMesh>(); }
1557#endif
1558
1559
1561 {
1562 auto locator = mesh.sub_point_locator();
1563
1564 for (auto & elem : mesh.element_ptr_range())
1565 {
1566 Point master_pt = {}; // center, for tensor product elements
1567
1568 // But perturb it to try and trigger any mapping weirdness
1569 if (elem->dim() > 0)
1570 master_pt(0) = 0.25;
1571
1572 if (elem->dim() > 1)
1573 master_pt(1) = -0.25;
1574
1575 if (elem->dim() > 2)
1576 master_pt(2) = 0.75;
1577
1578 Point physical_pt = FEMap::map(elem->dim(), elem, master_pt);
1579
1580 Point inverse_pt = FEMap::inverse_map(elem->dim(), elem,
1581 physical_pt);
1582
1583 CPPUNIT_ASSERT((inverse_pt-master_pt).norm() < TOLERANCE);
1584
1585 CPPUNIT_ASSERT(elem->contains_point(physical_pt));
1586
1587 // We only want to find elements in the same block
1588 std::set<subdomain_id_type> my_subdomain { elem->subdomain_id() };
1589
1590 // We can *still* have overlapping NodeElem from a slit mesh
1591 // input file; better check them all
1592 std::set<const Elem * > located_elems;
1593 (*locator)(physical_pt, located_elems, &my_subdomain);
1594
1595 CPPUNIT_ASSERT(located_elems.count(elem));
1596 }
1597 }
1598
1599
1600
1602 {
1603 CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
1605
1606 unsigned char weight_index = mesh.default_mapping_data();
1607
1608 bool found_the_quad = false;
1609
1610 for (auto & elem : mesh.element_ptr_range())
1611 {
1612 if (elem->type() == NODEELEM)
1613 continue;
1614
1615 CPPUNIT_ASSERT_EQUAL(elem->type(), QUAD9);
1616 found_the_quad = true;
1617
1618 for (unsigned int n=0; n != 9; ++n)
1619 CPPUNIT_ASSERT_EQUAL
1620 (elem->node_ref(n).get_extra_datum<Real>(weight_index),
1621 Real(0.75));
1622
1623 CPPUNIT_ASSERT_EQUAL(elem->point(0)(0), Real(0.5));
1624 CPPUNIT_ASSERT_EQUAL(elem->point(0)(1), Real(0.5));
1625 CPPUNIT_ASSERT_EQUAL(elem->point(1)(0), Real(1.5));
1626 CPPUNIT_ASSERT_EQUAL(elem->point(1)(1), Real(0.5));
1627 CPPUNIT_ASSERT_EQUAL(elem->point(2)(0), Real(1.5));
1628 CPPUNIT_ASSERT_EQUAL(elem->point(2)(1), Real(1.5));
1629 CPPUNIT_ASSERT_EQUAL(elem->point(3)(0), Real(0.5));
1630 CPPUNIT_ASSERT_EQUAL(elem->point(3)(1), Real(1.5));
1631 CPPUNIT_ASSERT(elem->has_affine_map());
1632#if LIBMESH_DIM > 2
1633 for (unsigned int v=0; v != 4; ++v)
1634 CPPUNIT_ASSERT_EQUAL(elem->point(v)(2), Real(0));
1635#endif
1636 }
1637
1638 TestCommWorld->max(found_the_quad);
1639 CPPUNIT_ASSERT(found_the_quad);
1640
1642 }
1643
1644
1645 void testAbaqusRead (const std::string & fname,
1646 dof_id_type n_elem,
1648 {
1650
1651 AbaqusIO abaqus(mesh);
1652
1653 if (mesh.processor_id() == 0)
1654 abaqus.read(fname);
1656
1658
1659 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), n_elem);
1660 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), n_nodes);
1661 }
1662
1663
1665 {
1666 LOG_UNIT_TEST;
1667 testAbaqusRead("meshes/tensile_sample_test1.inp.gz", 728, 1166);
1668 }
1669
1670
1672 {
1673 LOG_UNIT_TEST;
1674 testAbaqusRead("meshes/poly_sample_test2.inp.gz", 1280, 1625);
1675 }
1676
1677
1679 {
1680 LOG_UNIT_TEST;
1681
1683
1684 DynaIO dyna(mesh);
1685
1686 if (mesh.processor_id() == 0)
1687 dyna.read("meshes/1_quad.bxt.gz");
1689
1691
1692 // We have 1 QUAD9 finite element, attached via a trivial map to 9
1693 // spline Node+NodeElem objects
1694 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(10));
1695 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(18));
1696
1698 }
1699
1701 {
1702 LOG_UNIT_TEST;
1703
1705
1706 GmshIO gmsh_io(mesh);
1707
1708#ifdef LIBMESH_ENABLE_EXCEPTIONS
1709 std::string what = "";
1710 try
1711 {
1712 if (mesh.processor_id() == 0)
1713 gmsh_io.read("meshes/block.msh");
1714 }
1715 catch (libMesh::LogicError & e)
1716 {
1717 what = e.what();
1718 }
1719
1720 TestCommWorld->broadcast(what);
1721 std::regex msg_regex("outside entity physical bounding box");
1722 CPPUNIT_ASSERT(std::regex_search(what, msg_regex));
1723#endif
1724 }
1725
1727 {
1728 LOG_UNIT_TEST;
1729
1731
1732 GmshIO gmsh_io(mesh);
1733
1734 if (mesh.processor_id() == 0)
1735 gmsh_io.read("meshes/circle.msh");
1737
1738 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(14));
1739 }
1740
1742 {
1743 LOG_UNIT_TEST;
1744
1746
1747 GmshIO gmsh_io(mesh);
1748
1749 if (mesh.processor_id() == 0)
1750 gmsh_io.read("meshes/bcid_overlap.msh");
1752
1753 CPPUNIT_ASSERT_EQUAL(mesh.get_boundary_info().get_sideset_name_map().size(),
1754 std::size_t(2));
1755 CPPUNIT_ASSERT_EQUAL(mesh.get_boundary_info().sideset_name(1),
1756 std::string("srfBC4A"));
1757 CPPUNIT_ASSERT_EQUAL(mesh.get_boundary_info().sideset_name(2),
1758 std::string("srfBC4B"));
1759 CPPUNIT_ASSERT_EQUAL(mesh.get_subdomain_name_map().size(),
1760 std::size_t(2));
1761 CPPUNIT_ASSERT_EQUAL(mesh.subdomain_name(1),
1762 std::string("volBC3A"));
1763 CPPUNIT_ASSERT_EQUAL(mesh.subdomain_name(2),
1764 std::string("volBC3B"));
1765 }
1766
1768 {
1769 LOG_UNIT_TEST;
1770
1772
1773 STLIO stl_io(mesh);
1774
1775 if (mesh.processor_id() == 0)
1776 stl_io.read("meshes/Cluster_34.stl");
1778
1779 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(40));
1780 }
1781
1783 {
1784 LOG_UNIT_TEST;
1785
1787
1788 STLIO stl_io(mesh);
1789
1790 if (mesh.processor_id() == 0)
1791 stl_io.read("meshes/engraving.stl");
1793
1794 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(426));
1795 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), dof_id_type(215));
1796 }
1797
1799 {
1800#ifdef LIBMESH_HAVE_TETGEN
1801 LOG_UNIT_TEST;
1802
1804
1805 TetGenIO tetgen_io(mesh);
1806
1807 if (mesh.processor_id() == 0)
1808 tetgen_io.read("meshes/tetgen_one_tet10.ele");
1810
1812
1813 // Mesh should contain 1 TET10 finite element
1814 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(1));
1815 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(10));
1816
1817 // Element should have TET10 reference element volume
1818 const Elem * const elem = mesh.query_elem_ptr(0);
1819
1820 // On a serial mesh we have every element everywhere
1821 if (mesh.is_serial())
1822 CPPUNIT_ASSERT(elem);
1823 else
1824 {
1825 bool have_elem = elem;
1826 mesh.comm().max(have_elem);
1827 CPPUNIT_ASSERT(have_elem);
1828 }
1829
1830 if (elem)
1831 {
1832 const Real vol = elem->volume();
1833 LIBMESH_ASSERT_FP_EQUAL(vol, 1./6, TOLERANCE*TOLERANCE);
1834 }
1835#endif
1836 }
1837
1839 {
1840 LOG_UNIT_TEST;
1841
1843
1844 DynaIO dyna(mesh, /* keep_spline_nodes = */ false);
1845
1846 if (mesh.processor_id() == 0)
1847 dyna.read("meshes/1_quad.bxt.gz");
1849
1851
1852 // We have 1 QUAD9 finite element
1853 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(1));
1854 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(9));
1855
1857 }
1858
1859
1861 {
1862 LOG_UNIT_TEST;
1863
1865
1866 DynaIO dyna(mesh);
1867 if (mesh.processor_id() == 0)
1868 dyna.read("meshes/25_quad.bxt.gz");
1870
1872
1873 // We have 5^2 QUAD9 elements, with 11^2 nodes,
1874 // tied to 49 Node/NodeElem spline nodes
1875 CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), static_cast<dof_id_type>(25+49));
1876 CPPUNIT_ASSERT_EQUAL(mesh.n_nodes(), static_cast<dof_id_type>(121+49));
1877
1878 CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
1880
1881 unsigned char weight_index = mesh.default_mapping_data();
1882
1883 for (const auto & elem : mesh.active_element_ptr_range())
1884 {
1885 if (elem->type() == NODEELEM)
1886 continue;
1887 LIBMESH_ASSERT_FP_EQUAL(Real(0.04), elem->volume(), TOLERANCE);
1888
1889 for (unsigned int n=0; n != 9; ++n)
1890 CPPUNIT_ASSERT_EQUAL
1891 (elem->node_ref(n).get_extra_datum<Real>(weight_index),
1892 Real(1.0));
1893
1894 unsigned int n_neighbors = 0, n_neighbors_expected = 2;
1895 for (unsigned int side=0; side != 4; ++side)
1896 if (elem->neighbor_ptr(side))
1897 n_neighbors++;
1898 Point c = elem->vertex_average();
1899
1900 if (c(0) > 0.2 && c(0) < 0.8)
1901 n_neighbors_expected++;
1902 if (c(1) > 0.2 && c(1) < 0.8)
1903 n_neighbors_expected++;
1904
1905 CPPUNIT_ASSERT_EQUAL(n_neighbors, n_neighbors_expected);
1906 }
1907
1909
1910#ifdef LIBMESH_HAVE_SOLVER
1911#ifdef LIBMESH_ENABLE_CONSTRAINTS
1912 // Now test whether we can assign the desired constraint equations
1914 System & sys = es.add_system<LinearImplicitSystem>("test");
1915 sys.add_variable("u", SECOND); // to match QUAD9
1916 es.init();
1917
1918 // We should have a constraint on every FE dof
1919 CPPUNIT_ASSERT_EQUAL(sys.get_dof_map().n_constrained_dofs(), static_cast<dof_id_type>(121));
1920#endif // LIBMESH_ENABLE_CONSTRAINTS
1921#endif // LIBMESH_HAVE_SOLVER
1922 }
1923
1924 void testProjectionRegression(MeshBase & mesh, std::array<Real, 4> expected_norms)
1925 {
1926 int order = 0;
1927 for (const auto elem : mesh.element_ptr_range())
1928 order = std::max(order, int(elem->default_order()));
1929 TestCommWorld->max(order);
1930 CPPUNIT_ASSERT (order > 0);
1931
1932 // Let's test that IGA constraints are preserved (in a relative
1933 // sense) when we clone a mesh.
1934 std::unique_ptr<MeshBase> mesh_clone = mesh.clone();
1935 CPPUNIT_ASSERT(*mesh_clone == mesh);
1936
1938 System &sys = es.add_system<System> ("SimpleSystem");
1939 sys.add_variable("n", Order(order), RATIONAL_BERNSTEIN);
1940
1941 es.init();
1942
1944
1945 // Make this easy to tweak in the future
1946 const Real my_tolerance = TOLERANCE;
1947
1948 // Calculate some norms, skipping the spline points, and compare
1949 // to regression standard values
1950 std::set<unsigned int> skip_dimensions {0};
1951 const Real L2_norm =
1952 sys.calculate_norm(*sys.solution, 0, L2, &skip_dimensions);
1953// std::cout.precision(16);
1954// std::cout << "L2_norm = " << L2_norm << std::endl;
1955 LIBMESH_ASSERT_FP_EQUAL(L2_norm, expected_norms[0], my_tolerance);
1956 const Real Linf_norm =
1957 sys.calculate_norm(*sys.solution, 0, L_INF, &skip_dimensions);
1958// std::cout << "Linf_norm = " << Linf_norm << std::endl;
1959 LIBMESH_ASSERT_FP_EQUAL(Linf_norm, expected_norms[1], my_tolerance);
1960 const Real H1_norm =
1961 sys.calculate_norm(*sys.solution, 0, H1_SEMINORM, &skip_dimensions);
1962// std::cout << "H1_norm = " << H1_norm << std::endl;
1963 LIBMESH_ASSERT_FP_EQUAL(H1_norm, expected_norms[2], my_tolerance);
1964 const Real W1inf_norm =
1965 sys.calculate_norm(*sys.solution, 0, W1_INF_SEMINORM, &skip_dimensions);
1966// std::cout << "W1inf_norm = " << W1inf_norm << std::endl;
1967 // W1_inf seems more sensitive to FP error...
1968 LIBMESH_ASSERT_FP_EQUAL(W1inf_norm, expected_norms[3], 10*my_tolerance);
1969 }
1970
1971 void testDynaFileMappings (const std::string & filename, std::array<Real, 4> expected_norms)
1972 {
1974
1975 DynaIO dyna(mesh);
1976 if (mesh.processor_id() == 0)
1977 dyna.read(filename);
1979
1981
1982 CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
1984
1985 // Useful when trying out different projection functions
1986 // std::cout << filename << ":" << std::endl;
1987
1989
1990 testProjectionRegression(mesh, expected_norms);
1991 }
1992
1994 {
1995 LOG_UNIT_TEST;
1996
1997 testDynaFileMappings("meshes/PressurizedCyl_Patch6_256Elem.bxt.gz",
1998 // Regression values for sin_x_plus_cos_y
1999 {{0.9639857809698268, 1.839870171669186,
2000 0.7089812562241862, 1.306121188539059}});
2001 }
2002
2004 {
2005 LOG_UNIT_TEST;
2006
2007 testDynaFileMappings("meshes/BlockWithHole_Patch9.bxt.gz",
2008 // Regression values for sin_x_plus_cos_y
2009 {{3.22612556930183, 1.97405365384733,
2010 2.53376235803176, 1.41374070517223}});
2011 }
2012
2014 {
2015 LOG_UNIT_TEST;
2016
2017 testDynaFileMappings("meshes/PlateWithHole_Patch8.bxt.gz",
2018 // Regression values for sin_x_plus_cos_y
2019 {{2.2812154374012, 1.974049990211937,
2020 1.791640772215248, 1.413679237529376}});
2021 }
2022
2024 {
2025 LOG_UNIT_TEST;
2026
2027 testDynaFileMappings("meshes/PressurizedCyl3d_Patch1_8Elem.bxt.gz",
2028 // Regression values for sin_x_plus_cos_y
2029 {{0.963612880188165, 1.82329452603503,
2030 0.707998701597943, 1.31399222566683}});
2031 }
2032
2033 void testExodusFileMappings (const std::string & filename,
2034 std::array<Real, 4> expected_norms,
2035 bool use_disc_bex = false)
2036 {
2038
2039 ExodusII_IO exii(mesh);
2040 // IGA Exodus meshes require ExodusII 8 or higher
2041 if (exii.get_exodus_version() < 800)
2042 return;
2043
2044 // This should default to false
2045 if (use_disc_bex)
2046 exii.set_discontinuous_bex(true);
2047
2048 if (mesh.processor_id() == 0)
2049 exii.read(filename);
2051
2053
2054 CPPUNIT_ASSERT_EQUAL(mesh.default_mapping_type(),
2056
2058
2059 testProjectionRegression(mesh, expected_norms);
2060
2061 // Test a write when we're done reading; I was getting weirdness
2062 // from NetCDF at this point in a Moose output test.
2063 {
2064 ExodusII_IO exii(mesh);
2065
2066 exii.write("exodus_file_mapping_out.e");
2067 }
2068
2069#ifdef LIBMESH_HAVE_VTK
2070 {
2071 VTKIO vtkout(mesh);
2072
2073 vtkout.write("vtk_file_mapping_out.pvtu");
2074 }
2075#endif
2076 }
2077
2079 {
2080 LOG_UNIT_TEST;
2081
2082 testExodusFileMappings("meshes/PlateWithHole_Patch8.e",
2083 // Regression values for sin_x_plus_cos_y
2084 {{2.2812154374012, 1.974049990211937,
2085 1.791640772215248, 1.413679237529376}});
2086 }
2087
2089 {
2090 LOG_UNIT_TEST;
2091
2092 testExodusFileMappings("meshes/two_quads_two_blocks.e",
2093 // Regression values for sin_x_plus_cos_y
2094 {{2.03496953073072, 1.97996853164955,
2095 1.18462134113435, 1.03085301158959}});
2096 }
2098 {
2099 LOG_UNIT_TEST;
2100
2101 testExodusFileMappings("meshes/two_element_iga_in.e",
2102 // Regression values for sin_x_plus_cos_y
2103 {{1.26865962862531, 1.42562070158386,
2104 1.54905363492342, 1.29782906548366}});
2105 }
2106
2108 {
2109 LOG_UNIT_TEST;
2110
2111 testExodusFileMappings("meshes/PressurizedCyl3d_Patch1_8Elem.e",
2112 {{0.963612880188165, 1.82329452603503,
2113 0.707998701597943, 1.31399222566683}});
2114 }
2115
2117 {
2118 LOG_UNIT_TEST;
2119
2120 testExodusFileMappings("meshes/PlateWithHole_Patch8.e",
2121 // Regression values for sin_x_plus_cos_y
2122 //
2123 // These are *not* the same as for the continuous plate, because
2124 // we do the C^TKCx=C^Tf trick to pull back projections to the
2125 // spline nodes, and the pseudoinverse here minimizes the error in
2126 // a discretization-dependent norm, not in a Sobolev norm. For
2127 // these coarse meshes, our Sobolev norms can end up being ~0.1%
2128 // different.
2129 {{2.28234312456534, 1.97439548757586,
2130 1.79290449809266, 1.41075128955985}},
2131 true);
2132 }
2133
2135 {
2136 LOG_UNIT_TEST;
2137
2138 testExodusFileMappings("meshes/two_quads_two_blocks.e",
2139 // Regression values for sin_x_plus_cos_y
2140 {{2.03496953073072, 1.97996853164955,
2141 1.18462134113435, 1.03085301158959}},
2142 true);
2143 }
2145 {
2146 LOG_UNIT_TEST;
2147
2148 testExodusFileMappings("meshes/two_element_iga_in.e",
2149 // Regression values for sin_x_plus_cos_y
2150 {{1.26877626663365, 1.42553698909339,
2151 1.54810114917177, 1.29792704408979}},
2152 true);
2153 }
2154
2156 {
2157 LOG_UNIT_TEST;
2158
2159 testExodusFileMappings("meshes/PressurizedCyl3d_Patch1_8Elem.e",
2160 {{0.963855209590556, 1.8234396424318,
2161 0.708286572453382, 1.31468940958327}},
2162 true);
2163 }
2164};
2165
unsigned int dim
void ErrorVector unsigned int
void testAbaqusReadSecond()
void testExodusSetNodeUniqueIdsFromMaps()
Definition mesh_input.C:375
void testDynaNoSplines()
CPPUNIT_TEST(testDynaFileMappingsBlockWithHole)
CPPUNIT_TEST(testExodusFileMappingsTwoBlocks)
void testExodusDiscWriteAddedSidesHexC0()
void testGmshBCIDOverlap()
CPPUNIT_TEST(testNemesisReadDistributed)
CPPUNIT_TEST(testNemesisCopyNodalSolutionReplicated)
void testBadGmsh()
void testExodusDiscWriteAddedSidesTriDisc()
void testExodusWriteElementDataFromDiscontinuousNodalData()
void testNemesisCopyElementVectorReplicated()
void testVTKPreserveSubdomainIds()
Definition mesh_input.C:286
void testExodusWriteAddedSidesTetC0()
void testExodusWriteAddedSidesQuadC0()
void testExodusIGASidesets()
Definition mesh_input.C:542
void testExodusWriteAddedSidesEdgeDisc()
void testExodusFileMappingsPlateWithHole()
CPPUNIT_TEST(testExodusFileMappingsCyl3d)
void testAbaqusReadFirst()
void testExodusDiscWriteAddedSidesTetDisc()
CPPUNIT_TEST(testExodusDiscWriteAddedSidesTriC0)
void testExodusCopyElementVectorReplicated()
Definition mesh_input.C:996
void testExodusDiscWriteAddedSidesMixedEdgeC0()
CPPUNIT_TEST(testGmshBCIDOverlap)
CPPUNIT_TEST(testExodusDiscCyl3d)
void testNemesisCopyNodalSolutionReplicated()
Definition mesh_input.C:708
CPPUNIT_TEST(testNemesisSingleElementReplicated)
CPPUNIT_TEST(testNemesisCopyElementSolutionDistributed)
void testExodusWriteAddedSides(Number(*exact_sol)(const Point &, const Parameters &, const std::string &, const std::string &), const ElemType elem_type, const Order order, const bool write_discontinuous=false, const std::vector< FEType > earlier_vars={}, const std::vector< FEType > later_vars={})
void testSingleElementImpl(const std::string &filename)
Definition mesh_input.C:820
CPPUNIT_TEST(testAbaqusReadFirst)
void testGoodSTL()
void testExodusDiscWriteAddedSidesEdgeC0()
void testExodusDiscTwoElemIGA()
CPPUNIT_TEST(testExodusDiscWriteAddedSidesHexC0)
CPPUNIT_TEST(testExodusWriteAddedSidesMixedEdgeC0)
CPPUNIT_TEST(testExodusSetElemUniqueIdsFromMaps)
void testDynaFileMappingsBlockWithHole()
void testGoodGmsh()
void testNemesisSingleElementReplicated()
Definition mesh_input.C:871
void testExodusCopyElementSolutionReplicated()
Definition mesh_input.C:802
void testNemesisReadImpl()
void testDynaReadPatch()
CPPUNIT_TEST(testExodusWriteAddedSidesTriC0)
CPPUNIT_TEST(testExodusDiscTwoBlocks)
CPPUNIT_TEST(testGoodGmsh)
void testNemesisSingleElementDistributed()
Definition mesh_input.C:874
void testExodusCopyElementSolutionDistributed()
Definition mesh_input.C:805
void testCopyNodalSolutionImpl(const std::string &filename)
Definition mesh_input.C:633
void testExodusCopyNodalSolutionDistributed()
Definition mesh_input.C:704
void testExodusReadHeader()
Definition mesh_input.C:462
void testExodusWriteAddedSidesMixedEdgeC0()
CPPUNIT_TEST(testNemesisSingleElementDistributed)
CPPUNIT_TEST(testExodusCopyElementVectorDistributed)
void testExodusSetElemUniqueIdsFromMaps()
Definition mesh_input.C:431
void testExodusFileMappingsCyl3d()
CPPUNIT_TEST(testGoodSTL)
void testNemesisCopyElementSolutionDistributed()
Definition mesh_input.C:812
void testExodusDiscTwoBlocks()
void testExodusDiscWriteAddedSidesQuadC0()
void helperTestingDynaQuad(const MeshBase &mesh)
void testExodusDiscWriteAddedSidesMixedTriC0()
CPPUNIT_TEST(testDynaFileMappingsCyl3d)
void testCopyElementSolutionImpl(const std::string &filename)
Definition mesh_input.C:717
void testExodusDiscWriteAddedSidesMixedHexC0()
CPPUNIT_TEST(testExodusDiscTwoElemIGA)
void testExodusDiscWriteAddedSidesMixedQuadC0()
void testDynaFileMappingsCyl3d()
void testExodusFileMappings(const std::string &filename, std::array< Real, 4 > expected_norms, bool use_disc_bex=false)
void testExodusWriteAddedSidesQuadDisc()
void testExodusWriteAddedSidesMixedTriC0()
void testExodusWriteAddedSidesTetDisc()
CPPUNIT_TEST(testLowOrderEdgeBlocks)
void testNemesisReadDistributed()
CPPUNIT_TEST(testNemesisCopyNodalSolutionDistributed)
void testExodusDiscWriteAddedSidesQuadDisc()
CPPUNIT_TEST(testNemesisCopyElementSolutionReplicated)
void testVTKPreserveElemIds()
Definition mesh_input.C:227
CPPUNIT_TEST(testExodusFileMappingsPlateWithHole)
CPPUNIT_TEST(testExodusWriteAddedSidesHexC0)
void testExodusWriteAddedSidesMixedHexC0()
CPPUNIT_TEST(testDynaReadPatch)
void testLowOrderEdgeBlocks()
Definition mesh_input.C:499
void testDynaFileMappingsFEMEx5()
void testExodusDiscWriteAddedSidesTetC0()
void testCopyElementVectorImpl(const std::string &filename)
Definition mesh_input.C:885
CPPUNIT_TEST(testExodusWriteAddedSidesMixedTriC0)
void testMasterCenters(const MeshBase &mesh)
void testNemesisCopyElementSolutionReplicated()
Definition mesh_input.C:809
void testExodusSetNodeUniqueIdsFromMaps_implementation(bool set_unique_ids, const std::vector< unique_id_type > &expected_unique_ids)
Definition mesh_input.C:339
void testDynaFileMappingsPlateWithHole()
CPPUNIT_TEST(testExodusDiscWriteAddedSidesMixedHexC0)
CPPUNIT_TEST(testExodusWriteAddedSidesMixedHexC0)
void testExodusCopyElementVectorDistributed()
Definition mesh_input.C:999
CPPUNIT_TEST(testExodusCopyElementVectorReplicated)
CPPUNIT_TEST(testExodusCopyElementSolutionReplicated)
void testAbaqusRead(const std::string &fname, dof_id_type n_elem, dof_id_type n_nodes)
CPPUNIT_TEST(testAbaqusReadSecond)
CPPUNIT_TEST(testExodusWriteAddedSidesQuadC0)
CPPUNIT_TEST(testExodusIGASidesets)
CPPUNIT_TEST(testExodusDiscWriteAddedSidesMixedQuadC0)
CPPUNIT_TEST(testExodusWriteAddedSidesMixedQuadC0)
void testNemesisReadReplicated()
void testExodusWriteAddedSidesHexC0()
void testExodusFileMappingsTwoBlocks()
void testTetgenIO()
CPPUNIT_TEST(testDynaFileMappingsFEMEx5)
void testExodusWriteAddedSidesMixedQuadC0()
CPPUNIT_TEST(testExodusFileMappingsTwoElemIGA)
CPPUNIT_TEST(testExodusCopyElementSolutionDistributed)
void testExodusWriteAddedSidesTriDisc()
void testNemesisCopyNodalSolutionDistributed()
Definition mesh_input.C:711
void testGoodSTLBinary()
void testExodusDiscPlateWithHole()
CPPUNIT_TEST(testExodusDiscWriteAddedSidesQuadC0)
CPPUNIT_TEST(testExodusSetNodeUniqueIdsFromMaps)
void testExodusWriteAddedSidesHexDisc()
CPPUNIT_TEST(testExodusCopyNodalSolutionReplicated)
CPPUNIT_TEST(testGoodSTLBinary)
CPPUNIT_TEST(testExodusWriteAddedSidesEdgeC0)
CPPUNIT_TEST(testTetgenIO)
CPPUNIT_TEST(testExodusReadHeader)
void testExodusSetElemUniqueIdsFromMaps_implementation(bool set_unique_ids, const std::vector< unique_id_type > &expected_unique_ids)
Definition mesh_input.C:396
CPPUNIT_TEST(testNemesisCopyElementVectorDistributed)
void testNemesisCopyElementVectorDistributed()
CPPUNIT_TEST(testExodusDiscWriteAddedSidesEdgeC0)
void testExodusDiscWriteAddedSidesTriC0()
void testExodusCopyNodalSolutionReplicated()
Definition mesh_input.C:701
void testExodusFileMappingsTwoElemIGA()
CPPUNIT_TEST(testNemesisCopyElementVectorReplicated)
CPPUNIT_TEST(testBadGmsh)
void testExodusWriteAddedSidesEdgeC0()
void testExodusDiscWriteAddedSidesHexDisc()
void testDynaFileMappings(const std::string &filename, std::array< Real, 4 > expected_norms)
CPPUNIT_TEST(testExodusCopyNodalSolutionDistributed)
void testExodusDiscWriteAddedSidesEdgeDisc()
CPPUNIT_TEST(testDynaReadElem)
CPPUNIT_TEST(testExodusDiscPlateWithHole)
void testExodusDiscCyl3d()
void testProjectionRegression(MeshBase &mesh, std::array< Real, 4 > expected_norms)
LIBMESH_CPPUNIT_TEST_SUITE(MeshInputTest)
CPPUNIT_TEST(testExodusDiscWriteAddedSidesMixedTriC0)
CPPUNIT_TEST(testVTKPreserveSubdomainIds)
CPPUNIT_TEST(testDynaNoSplines)
void testExodusWriteAddedSidesTriC0()
CPPUNIT_TEST(testExodusDiscWriteAddedSidesHexDisc)
CPPUNIT_TEST(testExodusWriteAddedSidesHexDisc)
CPPUNIT_TEST(testDynaFileMappingsPlateWithHole)
CPPUNIT_TEST(testExodusWriteElementDataFromDiscontinuousNodalData)
void testDynaReadElem()
void tearDown()
Definition mesh_input.C:223
CPPUNIT_TEST(testNemesisReadReplicated)
CPPUNIT_TEST(testVTKPreserveElemIds)
CPPUNIT_TEST(testExodusDiscWriteAddedSidesMixedEdgeC0)
void max(const T &r, T &o, Request &req) const
The AbaqusIO class is a preliminary implementation for reading Abaqus mesh files in ASCII format.
Definition abaqus_io.h:42
virtual void read(const std::string &name) override
This method implements reading a mesh from a specified file.
Definition abaqus_io.C:227
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
std::size_t n_boundary_ids() const
std::string & sideset_name(boundary_id_type id)
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.
const std::set< boundary_id_type > & get_boundary_ids() const
std::vector< BCTuple > build_edge_list() const
Create a list of (element_id, edge_id, boundary_id) tuples for all relevant edges.
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
dof_id_type n_constrained_dofs() const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition dof_map.C:2201
unique_id_type unique_id() const
Definition dof_object.h:835
Reading and writing meshes in (a subset of) LS-DYNA format.
Definition dyna_io.h:53
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 base class from which all geometric element types are derived.
Definition elem.h:96
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
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
virtual Real volume() const
Definition elem.C:3462
This is the EquationSystems class.
Parameters parameters
Data structure holding arbitrary parameters.
virtual void init()
Initialize all the systems.
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.
This class is used as both an external data structure for passing around Exodus file header informati...
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition exodusII_io.h:53
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 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.
static int get_exodus_version()
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,...
void set_unique_ids_from_maps(bool val)
If true, this flag enforces the following behaviors:
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...
virtual void read(const std::string &name) override
This method implements reading a mesh from a specified file.
void set_discontinuous_bex(bool disc_bex)
Set to true (false is the default) to generate independent nodes for every Bezier Extraction element ...
static Point map(const unsigned int dim, const Elem *elem, const Point &reference_point)
Definition fe_map.C:1954
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
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition fe_type.h:197
FEType set_p_refinement(bool p) &
"Fluent API" for constructing a non-default p_refinement, for easier compatibility between non-InfFE ...
Definition fe_type.h:298
Reading and writing meshes in the Gmsh format.
Definition gmsh_io.h:53
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
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
This is the MeshBase class.
Definition mesh_base.h:81
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
virtual dof_id_type n_elem() const =0
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 allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use.
Definition mesh_base.h:1355
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
Definition mesh_base.h:1926
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 void write(const std::string &name) const =0
virtual std::unique_ptr< MeshBase > clone() const =0
Virtual "copy constructor".
virtual dof_id_type n_nodes() const =0
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:941
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.
virtual dof_id_type max_elem_id() const =0
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
std::string & subdomain_name(subdomain_id_type id)
Definition mesh_base.C:1887
unsigned char default_mapping_data() const
Returns any default data value used by the master space to physical space mapping.
Definition mesh_base.h:959
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition mesh_base.C:1833
void skip_noncritical_partitioning(bool skip)
If true is passed in then the elements on this mesh will no longer be (re)partitioned,...
Definition mesh_base.h:1411
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...
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
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
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
The Nemesis_IO class implements reading parallel meshes in the Nemesis file format from Sandia Nation...
Definition nemesis_io.h:54
void write_element_data(const EquationSystems &es)
Write out element solution in parallel, without localizing the solution vector.
virtual void read(const std::string &base_filename) override
Implements reading the mesh from several different files.
Definition nemesis_io.C:215
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...
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition parameters.h:75
bool have_parameter(std::string_view) const
Definition parameters.h:420
const T & get(std::string_view) const
Definition parameters.h:451
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
This class implements reading and writing triangle meshes in the STL format.
Definition stl_io.h:47
virtual void read(const std::string &mesh_file) override
This method implements reading a mesh from a specified file.
Definition stl_io.C:165
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition system.h:100
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::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
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
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
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
const std::string & variable_name(const unsigned int i) const
Definition system.C:2679
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
const DofMap & get_dof_map() const
Definition system.h:2417
unsigned int number() const
Definition system.h:2393
This class implements reading and writing meshes in the TetGen format.
Definition tetgen_io.h:49
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
This class implements reading and writing meshes in the VTK format.
Definition vtk_io.h:62
virtual void write(const std::string &) override
Output the mesh without solutions to a .pvtu file.
Communicator * TestCommWorld
MeshBase & mesh
Number six_x_plus_sixty_y(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition mesh_input.C:30
CPPUNIT_TEST_SUITE_REGISTRATION(MeshInputTest)
constexpr int added_sides_nxyz[]
Definition mesh_input.C:53
Number sin_x_plus_cos_y(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition mesh_input.C:42
Number designed_for_side_elems(const Point &p, const Parameters &param, const std::string &, const std::string &)
Definition mesh_input.C:55
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
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
ElemType
Defines an enum for geometric element types.
int8_t boundary_id_type
Definition id_types.h:51
void libmesh_ignore(const Args &...)
@ RATIONAL_BERNSTEIN_MAP
T libmesh_real(T a)
libmesh_assert(ctx)
static constexpr Real TOLERANCE
uint8_t dof_id_type
Definition id_types.h:67
@ RATIONAL_BERNSTEIN
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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
const dof_id_type n_nodes
Definition tecplot_io.C:67