diff --git a/src/wmtk/multimesh/MultiMeshManager.cpp b/src/wmtk/multimesh/MultiMeshManager.cpp index 5b824734a8..fb628a573b 100644 --- a/src/wmtk/multimesh/MultiMeshManager.cpp +++ b/src/wmtk/multimesh/MultiMeshManager.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -605,32 +606,86 @@ std::vector MultiMeshManager::map_to_child_tuples( return {}; } const auto map_handle = child_data.map_handle; + auto map_accessor = my_mesh.create_const_accessor(map_handle); // we will overwrite these tuples inline with the mapped ones while running down the map // functionalities - std::vector tuples = simplex::cofaces_single_dimension_tuples( - my_mesh, - my_simplex, - child_mesh.top_simplex_type()); + std::vector tuples_original; + // original version + { + tuples_original = simplex::cofaces_single_dimension_tuples( + my_mesh, + my_simplex, + child_mesh.top_simplex_type()); - /* - get all tuples of child mesh top simplex type that contain my_simplex - */ + /* + get all tuples of child mesh top simplex type that contain my_simplex + */ - auto map_accessor = my_mesh.create_const_accessor(map_handle); - for (Tuple& tuple : tuples) { - tuple = map_tuple_between_meshes(my_mesh, child_mesh, map_accessor, tuple); - } - tuples.erase( - std::remove_if( - tuples.begin(), - tuples.end(), - [](const Tuple& t) -> bool { return t.is_null(); }), - tuples.end()); - tuples = - wmtk::simplex::utils::make_unique_tuples(child_mesh, tuples, my_simplex.primitive_type()); + for (Tuple& tuple : tuples_original) { + tuple = map_tuple_between_meshes(my_mesh, child_mesh, map_accessor, tuple); + } + tuples_original.erase( + std::remove_if( + tuples_original.begin(), + tuples_original.end(), + [](const Tuple& t) -> bool { return t.is_null(); }), + tuples_original.end()); + tuples_original = wmtk::simplex::utils::make_unique_tuples( + child_mesh, + tuples_original, + my_simplex.primitive_type()); + } + std::vector tuples_new_wout_sorting; + std::vector tuples_new_with_sorting; + { + simplex::SimplexCollection sc(my_mesh); + for (const Tuple& tuple : simplex::cofaces_single_dimension_iterable( + my_mesh, + my_simplex, + child_mesh.top_simplex_type())) { + sc.add(child_mesh.top_simplex_type(), tuple); + } - return tuples; + // unsorted + { + std::vector child_tuples_wout; + child_tuples_wout.reserve(sc.size()); + for (const simplex::Simplex& s : sc.simplex_vector()) { + const Tuple tuple = + map_tuple_between_meshes(my_mesh, child_mesh, map_accessor, s.tuple()); + if (!tuple.is_null()) { + child_tuples_wout.emplace_back(tuple); + } + } + tuples_new_wout_sorting = wmtk::simplex::utils::make_unique_tuples( + child_mesh, + child_tuples_wout, + my_simplex.primitive_type()); + } + sc.sort(); + + // sorted + { + std::vector child_tuples; + child_tuples.reserve(sc.size()); + for (const simplex::Simplex& s : sc.simplex_vector()) { + const Tuple tuple = + map_tuple_between_meshes(my_mesh, child_mesh, map_accessor, s.tuple()); + if (!tuple.is_null()) { + child_tuples.emplace_back(tuple); + } + } + tuples_new_with_sorting = wmtk::simplex::utils::make_unique_tuples( + child_mesh, + child_tuples, + my_simplex.primitive_type()); + } + } + + // return tuples_original; + return tuples_new_with_sorting; + // return tuples_new_wout_sorting; } std::vector MultiMeshManager::map_to_child_tuples( diff --git a/tests/multimesh/test_multi_mesh.cpp b/tests/multimesh/test_multi_mesh.cpp index 203cc7864e..b3cd24152f 100644 --- a/tests/multimesh/test_multi_mesh.cpp +++ b/tests/multimesh/test_multi_mesh.cpp @@ -851,7 +851,7 @@ TEST_CASE("test_split_multi_mesh_1D_2D", "[multimesh][1D][2D]") // Do another edge_split { Tuple edge = parent.edge_tuple_with_vs_and_t(1, 2, 3); -#if defined(WMTK_ENABLE_HASH_UPDATE) +#if defined(WMTK_ENABLE_HASH_UPDATE) REQUIRE(parent.is_valid_with_hash(edge)); #else REQUIRE(parent.is_valid(edge)); @@ -991,12 +991,12 @@ TEST_CASE("test_split_multi_mesh", "[multimesh][2D]") std::vector children = parent.map_to_child(child0, edge_simplex); REQUIRE(children.size() == 1); const Simplex& cs = children[0]; -#if defined(WMTK_ENABLE_HASH_UPDATE) +#if defined(WMTK_ENABLE_HASH_UPDATE) REQUIRE(child0.is_valid_with_hash(cs.tuple())); #else REQUIRE(child0.is_valid(cs.tuple())); #endif - REQUIRE(wmtk::simplex::utils::SimplexComparisons::equal(child0,cs ,edge_f0_simplex)); + REQUIRE(wmtk::simplex::utils::SimplexComparisons::equal(child0, cs, edge_f0_simplex)); } // CHILD1: @@ -1011,12 +1011,12 @@ TEST_CASE("test_split_multi_mesh", "[multimesh][2D]") std::vector children = parent.map_to_child(child1, edge_simplex); REQUIRE(children.size() == 1); const Simplex& cs = children[0]; -#if defined(WMTK_ENABLE_HASH_UPDATE) +#if defined(WMTK_ENABLE_HASH_UPDATE) REQUIRE(child1.is_valid_with_hash(cs.tuple())); #else REQUIRE(child1.is_valid(cs.tuple())); #endif - REQUIRE(wmtk::simplex::utils::SimplexComparisons::equal(child1,cs ,edge_simplex)); + REQUIRE(wmtk::simplex::utils::SimplexComparisons::equal(child1, cs, edge_simplex)); } // CHILD2: @@ -1044,14 +1044,14 @@ TEST_CASE("test_split_multi_mesh", "[multimesh][2D]") std::cout << std::string(DEBUG_Tuple(edge_f0_simplex.tuple())) << " " << std::string(DEBUG_Tuple(edge_simplex.tuple())) << std::endl; -#if defined(WMTK_ENABLE_HASH_UPDATE) +#if defined(WMTK_ENABLE_HASH_UPDATE) REQUIRE(child2.is_valid_with_hash(cs0.tuple())); REQUIRE(child2.is_valid_with_hash(cs1.tuple())); #else REQUIRE(child2.is_valid(cs0.tuple())); REQUIRE(child2.is_valid(cs1.tuple())); #endif - REQUIRE(wmtk::simplex::utils::SimplexComparisons::equal(child2,cs0 ,edge_f0_simplex)); + REQUIRE(wmtk::simplex::utils::SimplexComparisons::equal(child2, cs0, edge_f0_simplex)); REQUIRE(cs1.tuple() == edge_simplex.tuple()); REQUIRE(cs1.primitive_type() == edge_simplex.primitive_type()); } @@ -1126,6 +1126,80 @@ TEST_CASE("test_split_multi_mesh", "[multimesh][2D]") p_mul_manager.check_map_valid(parent); } +TEST_CASE("test_split_multi_mesh_fail", "[multimesh][2D]") +{ + DEBUG_TriMesh parent = two_neighbors(); + std::shared_ptr child1_ptr = std::make_shared(one_ear()); + + auto& child1 = *child1_ptr; + + parent.reserve_more_attributes({10, 10, 10}); + child1.reserve_more_attributes({10, 10, 10}); + + auto child1_map = multimesh::same_simplex_dimension_surjection(parent, child1, {0, 1}); + + + parent.register_child_mesh(child1_ptr, child1_map); + + // test id computation + REQUIRE(parent.absolute_multi_mesh_id().empty()); + REQUIRE(child1.absolute_multi_mesh_id() == std::vector{0}); + + const auto& p_mul_manager = parent.multi_mesh_manager(); + p_mul_manager.check_map_valid(parent); + + { + // PARENT: + // 3-- --- 0 ---- 4 + // | X \ | + // | f1 X \ f2 | + // | X f0 \ | + // | X \ | + // 1 --------- 2 + // vertex = 1 + // face = f1 + // (XXXX indicates the edge) + // + Tuple edge = parent.edge_tuple_with_vs_and_t(1, 0, 1); + simplex::Simplex edge_simplex = simplex::Simplex(parent, PrimitiveType::Edge, edge); + + // CHILD1: + // 3------ 0 + // | X \ . + // | f1 X \ . + // | X f0 \ . + // | X \ . + // 1 --------- 2 + // + { + std::vector children = parent.map_to_child(child1, edge_simplex); + REQUIRE(children.size() == 1); + const Simplex& cs = children[0]; + REQUIRE(child1.is_valid(cs.tuple())); + REQUIRE(wmtk::simplex::utils::SimplexComparisons::equal(child1, cs, edge_simplex)); + } + + operations::EdgeSplit split(parent); + REQUIRE(!split(Simplex::edge(parent, edge)).empty()); + } + + REQUIRE(parent.is_connectivity_valid()); + REQUIRE(child1.is_connectivity_valid()); + + CHECK(parent.fv_from_fid(2) == Vector3l(0, 2, 4)); + CHECK(parent.fv_from_fid(3) == Vector3l(3, 1, 5)); + CHECK(parent.fv_from_fid(4) == Vector3l(3, 5, 0)); + CHECK(parent.fv_from_fid(5) == Vector3l(5, 1, 2)); + CHECK(parent.fv_from_fid(6) == Vector3l(0, 5, 2)); + + CHECK(child1.fv_from_fid(2) == Vector3l(3, 1, 4)); + CHECK(child1.fv_from_fid(3) == Vector3l(3, 4, 0)); + CHECK(child1.fv_from_fid(4) == Vector3l(4, 1, 2)); + CHECK(child1.fv_from_fid(5) == Vector3l(0, 4, 2)); + + p_mul_manager.check_map_valid(parent); +} + TEST_CASE("test_collapse_multi_mesh", "[multimesh][2D]") { DEBUG_TriMesh parent = two_neighbors();