2 #include <libmesh/boundary_info.h> 3 #include <libmesh/distributed_mesh.h> 4 #include <libmesh/elem.h> 5 #include <libmesh/mesh.h> 6 #include <libmesh/mesh_generation.h> 7 #include <libmesh/mesh_modification.h> 8 #include <libmesh/parallel_implementation.h> 9 #include <libmesh/node.h> 10 #include <libmesh/replicated_mesh.h> 11 #include <libmesh/utility.h> 28 CPPUNIT_TEST( testReplicatedMeshStitch );
29 CPPUNIT_TEST( testDistributedMeshStitch );
30 CPPUNIT_TEST( testReplicatedBoundaryInfo );
31 CPPUNIT_TEST( testDistributedBoundaryInfo );
32 CPPUNIT_TEST( testReplicatedMeshStitchElemsets );
33 CPPUNIT_TEST( testRemappingStitch );
34 CPPUNIT_TEST( testAmbiguousRemappingStitch );
35 #ifdef LIBMESH_HAVE_EXODUS_API 36 CPPUNIT_TEST( testNodeElemStitch );
38 #endif // LIBMESH_DIM > 2 40 CPPUNIT_TEST_SUITE_END();
53 const std::string & boundary_name_prefix)
57 for (
auto rit = mesh_boundary_ids.rbegin(); rit != mesh_boundary_ids.rend(); ++rit)
59 const auto old_sideset_name = boundary_info.
sideset_name(*rit);
60 const auto old_nodeset_name = boundary_info.
nodeset_name(*rit);
65 boundary_name_prefix + old_sideset_name;
67 boundary_name_prefix + old_nodeset_name;
72 template <
typename MeshType>
80 MeshTools::Generation::build_cube(mesh0, ps, ps, ps, -1, 0, 0, 1, 0, 1,
HEX8);
81 MeshTools::Generation::build_cube(mesh1, ps, ps, ps, 0, 1, 0, 1, 0, 1,
HEX8);
84 renameAndShift(mesh0, 0,
"zero_");
85 renameAndShift(mesh1, 6,
"one_");
87 mesh0.stitch_meshes(mesh1, 2, 10,
TOLERANCE,
true,
false,
false,
false);
89 CPPUNIT_ASSERT_EQUAL(mesh0.n_elem(),
static_cast<dof_id_type>(16));
90 CPPUNIT_ASSERT_EQUAL(mesh0.n_nodes(),
static_cast<dof_id_type>(45));
96 typename std::decay<decltype(sbi.size())>::type expected_size = 10;
97 CPPUNIT_ASSERT_EQUAL(expected_size, sbi.size());
101 CPPUNIT_ASSERT_EQUAL(expected_size, nbi.size());
105 std::set<std::string> expected_names = {{
"zero_left",
115 std::set<std::string> ss_names;
117 ss_names.insert(pr.second);
118 CPPUNIT_ASSERT(ss_names == expected_names);
120 std::set<std::string> ns_names;
122 ns_names.insert(pr.second);
123 CPPUNIT_ASSERT(ns_names == expected_names);
129 testBoundaryInfo<ReplicatedMesh>();
135 testBoundaryInfo<DistributedMesh>();
139 template <
typename MeshType>
155 std::vector<std::string> names2 {
"bar",
"baz"};
156 mesh2.add_elem_integers(names2);
158 std::vector<std::string> names3 {
"bar",
"foo"};
159 mesh3.add_elem_integers(names3);
162 MeshTools::Generation::build_cube (mesh0, ps, ps, ps, -1, 0, 0, 1, 0, 1,
HEX27);
163 MeshTools::Generation::build_cube (mesh1, ps, ps, ps, 0, 1, 0, 1, 0, 1,
HEX27);
164 MeshTools::Generation::build_cube (mesh2, ps, ps, ps, -1, 0, -1, 0, 0, 1,
HEX27);
165 MeshTools::Generation::build_cube (mesh3, ps, ps, ps, 0, 1, -1, 0, 0, 1,
HEX27);
167 struct trivially_copyable_pair
172 mesh0.add_node_integer(
"baz");
173 unsigned int foo1e_idx = mesh1.add_elem_integer(
"foo");
174 mesh2.template add_elem_datum<trivially_copyable_pair>(
"qux");
175 unsigned int qux2n_idx = mesh2.template add_node_datum<trivially_copyable_pair>(
"qux");
176 mesh3.add_node_integers(names3);
178 for (
const auto & elem : mesh1.element_ptr_range())
179 elem->set_extra_integer(foo1e_idx, 2);
181 for (
const auto & node : mesh2.node_ptr_range())
182 node->template set_extra_datum<trivially_copyable_pair>
186 mesh0.stitch_meshes(mesh1, 2, 4,
TOLERANCE,
true,
false,
false,
false);
187 mesh2.stitch_meshes(mesh3, 2, 4,
TOLERANCE,
true,
false,
false,
false);
188 mesh0.stitch_meshes(mesh2, 1, 3,
TOLERANCE,
true,
false,
false,
false);
190 CPPUNIT_ASSERT_EQUAL(mesh0.n_elem(),
static_cast<dof_id_type>(32));
191 CPPUNIT_ASSERT_EQUAL(mesh0.n_nodes(),
static_cast<dof_id_type>(405));
192 CPPUNIT_ASSERT_EQUAL(mesh0.n_elem_integers(), 5u);
193 CPPUNIT_ASSERT_EQUAL(mesh0.n_node_integers(), 5u);
194 std::vector<std::string> all_names {
"foo",
"bar",
"baz",
"qux"};
195 std::vector<unsigned int> node_name_indices {4, 3, 0, 1};
196 for (
unsigned int i=0; i != 4; ++i)
198 CPPUNIT_ASSERT(mesh0.has_elem_integer(all_names[i]));
199 CPPUNIT_ASSERT_EQUAL(mesh0.get_elem_integer_index(all_names[i]), i);
200 CPPUNIT_ASSERT(mesh0.has_node_integer(all_names[i]));
201 CPPUNIT_ASSERT_EQUAL(mesh0.get_node_integer_index(all_names[i]), node_name_indices[i]);
204 unsigned int foo0e_idx = mesh0.get_elem_integer_index(
"foo");
205 for (
const auto & elem : mesh0.element_ptr_range())
207 CPPUNIT_ASSERT_EQUAL(elem->n_extra_integers(), 5u);
208 const Point c = elem->vertex_average();
209 if (c(0) > 0 && c(1) > 0)
210 CPPUNIT_ASSERT_EQUAL(elem->get_extra_integer(foo0e_idx),
static_cast<dof_id_type>(2));
215 unsigned int qux0n_idx = mesh0.get_node_integer_index(
"qux");
216 for (
const auto & node : mesh0.node_ptr_range())
218 CPPUNIT_ASSERT_EQUAL(node->n_extra_integers(), 5u);
219 trivially_copyable_pair datum =
220 node->template get_extra_datum<trivially_copyable_pair>(qux0n_idx);
221 if ((*node)(0) <= 0 && (*node)(1) < 0)
223 CPPUNIT_ASSERT_EQUAL(datum.first, static_cast<dof_id_type>(3));
224 CPPUNIT_ASSERT_EQUAL(datum.second, static_cast<dof_id_type>(4));
236 testMeshStitch<ReplicatedMesh>();
241 testMeshStitch<DistributedMesh>();
244 template <
typename MeshType>
251 auto mesh0 = std::make_unique<MeshType>(*TestCommWorld);
265 auto mesh1 = mesh0->clone();
276 unsigned int elemset_index =
282 for (
const auto & elem :
mesh.element_ptr_range())
285 elem->set_extra_integer(elemset_index, 1);
287 elem->set_extra_integer(elemset_index, 2);
296 mesh1->change_elemset_code(1, 3);
297 mesh1->change_elemset_code(2, 4);
301 mesh1->change_elemset_id(1, 100);
302 mesh1->change_elemset_id(2, 200);
305 mesh0->stitch_meshes(dynamic_cast<UnstructuredMesh &>(*mesh1),
315 dof_id_type n_elem_prestitch = Utility::pow<3>(ps);
318 CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(2 * n_elem_prestitch), mesh0->n_elem());
322 unsigned int elemset_index = mesh0->get_elem_integer_index(
"elemset_code");
323 CPPUNIT_ASSERT_EQUAL(0u, elemset_index);
328 for (
dof_id_type elemset_code=1; elemset_code<5; ++elemset_code)
330 mesh0->get_elemsets(elemset_code, id_set_to_fill);
333 CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), id_set_to_fill.size());
334 CPPUNIT_ASSERT(id_set_to_fill.count(code_to_type[elemset_code]));
337 bool ps_odd = ps % 2;
339 for (
const auto & elem : mesh0->element_ptr_range())
341 dof_id_type elemset_code = elem->get_extra_integer(elemset_index);
342 bool elem_id_odd = elem->id() % 2;
348 if (elem->id() < n_elem_prestitch)
351 CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(1), elemset_code);
353 CPPUNIT_ASSERT_EQUAL(static_cast<dof_id_type>(2), elemset_code);
363 CPPUNIT_ASSERT_EQUAL(ps_odd ? static_cast<dof_id_type>(4) : static_cast<dof_id_type>(3), elemset_code);
365 CPPUNIT_ASSERT_EQUAL(ps_odd ? static_cast<dof_id_type>(3) : static_cast<dof_id_type>(4), elemset_code);
372 testMeshStitchElemsets<ReplicatedMesh>(2);
373 testMeshStitchElemsets<ReplicatedMesh>(3);
384 MeshTools::Generation::build_cube(mesh0, ps, ps, ps, -1, 0, 0, 1, 0, 1,
HEX8);
385 MeshTools::Generation::build_cube(mesh1, ps, ps, ps, 0, 1, 0, 1, 0, 1,
HEX8);
388 renameAndShift(mesh0, 0,
"zero_");
389 renameAndShift(mesh1, 6,
"one_");
392 for (
const auto & elem : mesh0.element_ptr_range())
393 elem->subdomain_id() = 123;
395 for (
const auto & elem : mesh1.element_ptr_range())
396 elem->subdomain_id() = 456;
399 mesh0.subdomain_name(123) =
"OneTwoThree";
402 mesh0.stitch_meshes(mesh1, 2, 10,
TOLERANCE,
true,
false,
false,
405 CPPUNIT_ASSERT_EQUAL(mesh0.n_elem(),
static_cast<dof_id_type>(16));
406 CPPUNIT_ASSERT_EQUAL(mesh0.n_nodes(),
static_cast<dof_id_type>(45));
409 for (
const auto & elem : mesh0.element_ptr_range())
421 MeshTools::Generation::build_cube(mesh0, ps, ps, ps, -1, 0, 0, 1, 0, 1,
HEX8);
422 MeshTools::Generation::build_cube(mesh1, ps, ps, ps, 0, 1, 0, 1, 0, 1,
HEX8);
425 renameAndShift(mesh0, 0,
"zero_");
426 renameAndShift(mesh1, 6,
"one_");
429 for (
const auto & elem : mesh0.element_ptr_range())
430 elem->subdomain_id() = 123;
432 for (
const auto & elem : mesh1.element_ptr_range())
433 elem->subdomain_id() = 123;
438 #ifdef LIBMESH_ENABLE_EXCEPTIONS 439 bool threw_error =
false;
442 mesh0.stitch_meshes(mesh1, 2, 10,
TOLERANCE,
true,
false,
false,
447 std::regex msg_regex(
"safely stitch with a mesh");
448 CPPUNIT_ASSERT(std::regex_search(e.what(), msg_regex));
452 CPPUNIT_ASSERT(threw_error);
453 #endif // LIBMESH_ENABLE_EXCEPTIONS 456 #ifdef LIBMESH_HAVE_EXODUS_API 462 mesh1.
read(
"meshes/component_1.exo");
464 mesh2.
read(
"meshes/component_2.exo");
477 CPPUNIT_ASSERT_EQUAL(merged_nodes, static_cast<std::size_t>(36));
const std::set< boundary_id_type > & get_side_boundary_ids() const
CPPUNIT_TEST_SUITE_REGISTRATION(MeshStitchTest)
void testAmbiguousRemappingStitch()
std::string & nodeset_name(boundary_id_type id)
void testNodeElemStitch()
libMesh::Parallel::Communicator * TestCommWorld
static constexpr Real TOLERANCE
TestClass subdomain_id_type
Based on the 4-byte comment warning above, this probably doesn't work with exodusII at all...
void testDistributedMeshStitch()
void testMeshStitchElemsets(unsigned int ps)
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
Register an integer datum (of type dof_id_type) to be added to each element in the mesh...
void add_elemset_code(dof_id_type code, MeshBase::elemset_type id_set)
Tabulate a user-defined "code" for elements which belong to the element sets specified in id_set...
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
The libMesh namespace provides an interface to certain functionality in the library.
void renameAndShift(UnstructuredMesh &mesh, const boundary_id_type boundary_id_offset, const std::string &boundary_name_prefix)
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
This is the MeshBase class.
void testReplicatedMeshStitch()
const std::set< boundary_id_type > & get_node_boundary_ids() const
void testRemappingStitch()
const std::map< boundary_id_type, std::string > & get_nodeset_name_map() const
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
The UnstructuredMesh class is derived from the MeshBase class.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
void testReplicatedBoundaryInfo()
std::string & subdomain_name(subdomain_id_type id)
void testDistributedBoundaryInfo()
std::string & sideset_name(boundary_id_type id)
void testReplicatedMeshStitchElemsets()
std::set< elemset_id_type > elemset_type
Typedef for the "set" container used to store elemset ids.
A class to represent the internal "this should never happen" errors, to be thrown by "libmesh_error()...
const std::set< boundary_id_type > & get_global_boundary_ids() const
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) override
Reads the file specified by name.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
A Point defines a location in LIBMESH_DIM dimensional Real space.
std::size_t stitch_meshes(const MeshBase &other_mesh, boundary_id_type this_mesh_boundary, boundary_id_type other_mesh_boundary, Real tol=TOLERANCE, bool clear_stitched_boundary_ids=false, bool verbose=true, bool use_binary_search=true, bool enforce_all_nodes_match_on_boundaries=false, bool merge_boundary_nodes_all_or_nothing=false, bool remap_subdomain_ids=false, bool prepare_after_stitching=true)
Stitch other_mesh to this mesh so that this mesh is the union of the two meshes.
void set_union(T &data, const unsigned int root_id) const