From 0144e6d2b886a98308e78fd001e4254d2d92ba78 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Fri, 3 May 2024 11:15:06 -0500 Subject: [PATCH 1/5] Relax assertion for 1D elements with manifold neighbors --- src/mesh/unstructured_mesh.C | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/mesh/unstructured_mesh.C b/src/mesh/unstructured_mesh.C index d98c7f99d4b..f315cb953bb 100644 --- a/src/mesh/unstructured_mesh.C +++ b/src/mesh/unstructured_mesh.C @@ -1047,11 +1047,26 @@ void UnstructuredMesh::find_neighbors (const bool reset_remote_elements, // Let's make sure that "had children made remote" // situation is actually the case libmesh_assert(neigh->has_children()); + + // This assert is overzealous in the case where + // N 1D elements (N>2, even) meet in a common + // node, but an odd number are flagged for + // refinement. In that case, our parent may have + // a coarse level neighbor on this side while we + // do not, because there was no element for us to + // pair up with. Libmesh currently assumes one + // neighbor per side, and "A neighbor-of B" implies + // "B neighbor-of A" so we can't currently handle + // this case correctly. If we are in that case, + // we therefore accept that the neighbor information + // is incomplete/wrong rather than asserting for + // an unrelated reason. bool neigh_has_remote_children = false; for (auto & child : neigh->child_ref_range()) if (&child == remote_elem) neigh_has_remote_children = true; - libmesh_assert(neigh_has_remote_children); + libmesh_assert(neigh_has_remote_children || + neigh->dim() == 1); // And let's double-check that we don't have // a remote_elem neighboring an active local element From efdaf9219aacb89093f5563092a3e4be83b73684 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Fri, 3 May 2024 11:40:27 -0500 Subject: [PATCH 2/5] Also allow remote_elems to neighbor active local 1D elements --- src/mesh/unstructured_mesh.C | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/mesh/unstructured_mesh.C b/src/mesh/unstructured_mesh.C index f315cb953bb..9d3d5e30a16 100644 --- a/src/mesh/unstructured_mesh.C +++ b/src/mesh/unstructured_mesh.C @@ -1068,11 +1068,13 @@ void UnstructuredMesh::find_neighbors (const bool reset_remote_elements, libmesh_assert(neigh_has_remote_children || neigh->dim() == 1); - // And let's double-check that we don't have - // a remote_elem neighboring an active local element + // And let's double-check that we don't have a + // remote_elem neighboring an active local element + // unless this is a 1D Elem, for the reasons + // discussed above. if (current_elem->active()) - libmesh_assert_not_equal_to (current_elem->processor_id(), - this->processor_id()); + libmesh_assert (current_elem->dim() == 1 || + current_elem->processor_id() != this->processor_id()); #endif // DEBUG neigh = const_cast(remote_elem); } From c2f1e31f0918f87c195b8f0dc8875b3e3050aa4b Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 6 May 2024 08:59:34 -0500 Subject: [PATCH 3/5] Add unit test of refining odd number of 1D elements meeting at a Node --- tests/Makefile.am | 3 +- tests/mesh/nodal_neighbors.C | 28 ++++++++++++++++++ .../meshes/find_neighbors_junction_1D_only.e | Bin 0 -> 38765 bytes 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/meshes/find_neighbors_junction_1D_only.e diff --git a/tests/Makefile.am b/tests/Makefile.am index 2b331612810..4d6bb428ca0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -160,7 +160,8 @@ data = matrices/geom_1_extraction_op.m \ meshes/mesh_with_low_order_edge_blocks.e \ meshes/shark_tooth_tri6.xda.gz \ meshes/tetgen_one_tet10.ele \ - meshes/tetgen_one_tet10.node + meshes/tetgen_one_tet10.node \ + meshes/find_neighbors_junction_1D_only.e unit_tests_data = $(data) diff --git a/tests/mesh/nodal_neighbors.C b/tests/mesh/nodal_neighbors.C index f2b8d08f862..0c7c41d3574 100644 --- a/tests/mesh/nodal_neighbors.C +++ b/tests/mesh/nodal_neighbors.C @@ -4,6 +4,7 @@ #include #include #include +#include #include "test_comm.h" #include "libmesh_cppunit.h" @@ -37,6 +38,7 @@ public: CPPUNIT_TEST( testEdge3 ); CPPUNIT_TEST( testEdge4 ); CPPUNIT_TEST( testOrientation ); + CPPUNIT_TEST( testMultiNeighborRefinement ); CPPUNIT_TEST_SUITE_END(); @@ -242,6 +244,32 @@ public: // } } } + + void testMultiNeighborRefinement() + { + LOG_UNIT_TEST; + + // The input mesh has a Node where 6 1D elements all meet. Then, + // we flag three of those elements for refinement, refine the + // Mesh, and finally test that we can call MeshBase::prepare_for_use(). + // Prior to the changes relaxing some assertions on 1D elements in + // #3853 (https://github.com/libMesh/libmesh/pull/3853) this test + // failed with a segfault. + ReplicatedMesh mesh(*TestCommWorld); + mesh.read("meshes/find_neighbors_junction_1D_only.e"); + + // Mark elements in subdomain 4 for refinement now: + for (const auto & elem : mesh.element_ptr_range()) + if (elem->subdomain_id() == 4) + elem->set_refinement_flag(Elem::REFINE); + + // Do the refinement + MeshRefinement mesh_refinement(mesh); + mesh_refinement.refine_elements(); + + // Trigger a new find_neighbors() call + mesh.prepare_for_use(); + } }; diff --git a/tests/meshes/find_neighbors_junction_1D_only.e b/tests/meshes/find_neighbors_junction_1D_only.e new file mode 100644 index 0000000000000000000000000000000000000000..5db8ae85b3e52a48dc1c7b600b07b7c044919770 GIT binary patch literal 38765 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 F{|En0Vc`G( literal 0 HcmV?d00001 From 606fc472bf438cb63f617637522df4dd29eab38e Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 6 May 2024 09:04:00 -0500 Subject: [PATCH 4/5] Run ./bootstrap --- tests/Makefile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Makefile.in b/tests/Makefile.in index e6fd5e009f6..683c9c7c1a3 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -2242,7 +2242,8 @@ data = matrices/geom_1_extraction_op.m \ meshes/mesh_with_low_order_edge_blocks.e \ meshes/shark_tooth_tri6.xda.gz \ meshes/tetgen_one_tet10.ele \ - meshes/tetgen_one_tet10.node + meshes/tetgen_one_tet10.node \ + meshes/find_neighbors_junction_1D_only.e unit_tests_data = $(data) @LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@unit_tests_dbg_SOURCES = $(unit_tests_sources) From 7faf98460dec3860b1152ccdd38dafbb0bbb463a Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 6 May 2024 10:40:40 -0500 Subject: [PATCH 5/5] Convert unit test exo file from netCDF-4 to 64-bit offset To do the conversion, first ncdump the file to text: ncdump foo.e > foo.txt Then ncgen with the -k '64-bit offset' option: ncgen foo.txt -k '64-bit offset' -o foo.e If not already in your PATH, the ncgen utility can be found in your libMesh build directory: $LIBMESH_BUILD/contrib/netcdf/v4/ncgen/ncgen --- .../meshes/find_neighbors_junction_1D_only.e | Bin 38765 -> 11232 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/meshes/find_neighbors_junction_1D_only.e b/tests/meshes/find_neighbors_junction_1D_only.e index 5db8ae85b3e52a48dc1c7b600b07b7c044919770..8970e2623f9629baabaf079f9a55f623371173ff 100644 GIT binary patch literal 11232 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 F{|En0Vc`G(