Skip to content

Commit 4a57e67

Browse files
authored
Merge pull request #3491 from jwpeterson/match_lower_order_edges
ExodusII_IO: Allow low-order edge blocks to refer to higher-order Elem edges
2 parents ae5a127 + e82ea35 commit 4a57e67

5 files changed

Lines changed: 75 additions & 2 deletions

File tree

src/mesh/exodusII_io_helper.C

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,30 @@ void ExodusII_IO_Helper::read_edge_blocks(MeshBase & mesh)
14441444
// Creates vector if not already there
14451445
auto & vec = edge_map[edge_key];
14461446
vec.emplace_back(elem->id(), e);
1447+
1448+
// If edge_ptr is a higher-order Elem (EDGE3 or higher) then also add
1449+
// a map entry for the lower-order (EDGE2) element which has matching
1450+
// vertices. This allows us to match lower-order edge blocks to edges
1451+
// of higher-order 3D elems (e.g. HEX20, TET10) and simplifies the
1452+
// definition of edge blocks.
1453+
if (edge_ptr->default_order() != FIRST)
1454+
{
1455+
// Construct a temporary low-order edge so that we can compute its key()
1456+
auto low_order_edge =
1457+
Elem::build(Elem::first_order_equivalent_type(edge_ptr->type()));
1458+
1459+
// Assign node pointers to low-order edge
1460+
for (unsigned int v=0; v<edge_ptr->n_vertices(); ++v)
1461+
low_order_edge->set_node(v) = edge_ptr->node_ptr(v);
1462+
1463+
// Compute the key for the temporary low-order edge we just built
1464+
dof_id_type low_order_edge_key = low_order_edge->key();
1465+
1466+
// Add this key to the map associated with the same (elem,
1467+
// edge) pair as the higher-order edge
1468+
auto & low_order_vec = edge_map[low_order_edge_key];
1469+
low_order_vec.emplace_back(elem->id(), e);
1470+
}
14471471
}
14481472

14491473
// Get reference to the mesh's BoundaryInfo object, as we will be
@@ -1533,9 +1557,12 @@ void ExodusII_IO_Helper::read_edge_blocks(MeshBase & mesh)
15331557
build_edge_ptr(edge_ptr, elem_edge_pair.second);
15341558

15351559
// Determine whether this candidate edge is a "real" match,
1536-
// i.e. also has the same orientation.
1560+
// i.e. also has the same orientation. Note that here we
1561+
// only check that the vertices match regardless of how many
1562+
// nodes the edge has, which allows us to match a lower-order
1563+
// edge to a higher-order Elem.
15371564
bool is_match = true;
1538-
for (int n=0; n<num_nodes_per_edge; ++n)
1565+
for (unsigned int n=0; n<edge_ptr->n_vertices(); ++n)
15391566
if (edge_ptr->node_id(n) != edge->node_id(n))
15401567
{
15411568
is_match = false;

tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ data = meshes/1_quad.bxt.gz \
144144
meshes/bad_64bit_elem_integers.e \
145145
meshes/good_32bit_elem_integers.e \
146146
meshes/mesh_assign_test_mesh.xda \
147+
meshes/mesh_with_low_order_edge_blocks.e \
147148
meshes/shark_tooth_tri6.xda.gz \
148149
meshes/tetgen_one_tet10.ele \
149150
meshes/tetgen_one_tet10.node

tests/Makefile.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ am__unit_tests_dbg_SOURCES_DIST = driver.C libmesh_cppunit.h \
264264
meshes/bad_64bit_elem_integers.e \
265265
meshes/good_32bit_elem_integers.e \
266266
meshes/mesh_assign_test_mesh.xda \
267+
meshes/mesh_with_low_order_edge_blocks.e \
267268
meshes/shark_tooth_tri6.xda.gz meshes/tetgen_one_tet10.ele \
268269
meshes/tetgen_one_tet10.node fparser/autodiff.C
269270
am__dirstamp = $(am__leading_dot)dirstamp
@@ -453,6 +454,7 @@ am__unit_tests_devel_SOURCES_DIST = driver.C libmesh_cppunit.h \
453454
meshes/bad_64bit_elem_integers.e \
454455
meshes/good_32bit_elem_integers.e \
455456
meshes/mesh_assign_test_mesh.xda \
457+
meshes/mesh_with_low_order_edge_blocks.e \
456458
meshes/shark_tooth_tri6.xda.gz meshes/tetgen_one_tet10.ele \
457459
meshes/tetgen_one_tet10.node fparser/autodiff.C
458460
@LIBMESH_ENABLE_FPARSER_TRUE@am__objects_4 = fparser/unit_tests_devel-autodiff.$(OBJEXT)
@@ -636,6 +638,7 @@ am__unit_tests_oprof_SOURCES_DIST = driver.C libmesh_cppunit.h \
636638
meshes/bad_64bit_elem_integers.e \
637639
meshes/good_32bit_elem_integers.e \
638640
meshes/mesh_assign_test_mesh.xda \
641+
meshes/mesh_with_low_order_edge_blocks.e \
639642
meshes/shark_tooth_tri6.xda.gz meshes/tetgen_one_tet10.ele \
640643
meshes/tetgen_one_tet10.node fparser/autodiff.C
641644
@LIBMESH_ENABLE_FPARSER_TRUE@am__objects_6 = fparser/unit_tests_oprof-autodiff.$(OBJEXT)
@@ -819,6 +822,7 @@ am__unit_tests_opt_SOURCES_DIST = driver.C libmesh_cppunit.h \
819822
meshes/bad_64bit_elem_integers.e \
820823
meshes/good_32bit_elem_integers.e \
821824
meshes/mesh_assign_test_mesh.xda \
825+
meshes/mesh_with_low_order_edge_blocks.e \
822826
meshes/shark_tooth_tri6.xda.gz meshes/tetgen_one_tet10.ele \
823827
meshes/tetgen_one_tet10.node fparser/autodiff.C
824828
@LIBMESH_ENABLE_FPARSER_TRUE@am__objects_8 = fparser/unit_tests_opt-autodiff.$(OBJEXT)
@@ -1002,6 +1006,7 @@ am__unit_tests_prof_SOURCES_DIST = driver.C libmesh_cppunit.h \
10021006
meshes/bad_64bit_elem_integers.e \
10031007
meshes/good_32bit_elem_integers.e \
10041008
meshes/mesh_assign_test_mesh.xda \
1009+
meshes/mesh_with_low_order_edge_blocks.e \
10051010
meshes/shark_tooth_tri6.xda.gz meshes/tetgen_one_tet10.ele \
10061011
meshes/tetgen_one_tet10.node fparser/autodiff.C
10071012
@LIBMESH_ENABLE_FPARSER_TRUE@am__objects_10 = fparser/unit_tests_prof-autodiff.$(OBJEXT)
@@ -2168,6 +2173,7 @@ data = meshes/1_quad.bxt.gz \
21682173
meshes/bad_64bit_elem_integers.e \
21692174
meshes/good_32bit_elem_integers.e \
21702175
meshes/mesh_assign_test_mesh.xda \
2176+
meshes/mesh_with_low_order_edge_blocks.e \
21712177
meshes/shark_tooth_tri6.xda.gz \
21722178
meshes/tetgen_one_tet10.ele \
21732179
meshes/tetgen_one_tet10.node

tests/mesh/mesh_input.C

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public:
105105
CPPUNIT_TEST( testExodusReadHeader );
106106
#if LIBMESH_DIM > 2
107107
CPPUNIT_TEST( testExodusIGASidesets );
108+
CPPUNIT_TEST( testLowOrderEdgeBlocks );
108109
#endif
109110
#ifndef LIBMESH_USE_COMPLEX_NUMBERS
110111
CPPUNIT_TEST( testExodusCopyElementVectorDistributed );
@@ -230,6 +231,44 @@ public:
230231
}
231232
}
232233

234+
void testLowOrderEdgeBlocks ()
235+
{
236+
LOG_UNIT_TEST;
237+
238+
Mesh mesh(*TestCommWorld);
239+
ExodusII_IO exii(mesh);
240+
241+
if (mesh.processor_id() == 0)
242+
exii.read("meshes/mesh_with_low_order_edge_blocks.e");
243+
244+
MeshCommunication().broadcast(mesh);
245+
mesh.prepare_for_use();
246+
247+
// Check that we see the boundary ids we expect
248+
BoundaryInfo & bi = mesh.get_boundary_info();
249+
250+
// On a ReplicatedMesh, check that the number of edge boundary
251+
// conditions is as expected. The real test is that we can read
252+
// this file in at all. Prior to the changes in #3491, the Exodus
253+
// reader threw an exception while trying to read this mesh.
254+
if (mesh.is_serial())
255+
{
256+
// Mesh has 15 boundary ids total (including edge and side ids).
257+
CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(15), bi.n_boundary_ids());
258+
259+
// We can binary_search() the build_edge_list() which is sorted
260+
// in lexicographical order before it's returned.
261+
auto edge_list = bi.build_edge_list();
262+
263+
// Search for some tuples we expect to be present
264+
CPPUNIT_ASSERT(std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(4, 1, 8007)));
265+
CPPUNIT_ASSERT(std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(10, 6, 8001)));
266+
267+
// And make sure we don't have entries we shouldn't have
268+
CPPUNIT_ASSERT(!std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(1, 8, 8009)));
269+
CPPUNIT_ASSERT(!std::binary_search(edge_list.begin(), edge_list.end(), std::make_tuple(2, 10, 9011)));
270+
}
271+
}
233272

234273
void testExodusIGASidesets ()
235274
{
11.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)