diff --git a/src/libs/blueprint/conduit_blueprint_mesh.hpp b/src/libs/blueprint/conduit_blueprint_mesh.hpp index daa81d1ac..e3b07d2f8 100644 --- a/src/libs/blueprint/conduit_blueprint_mesh.hpp +++ b/src/libs/blueprint/conduit_blueprint_mesh.hpp @@ -769,6 +769,17 @@ namespace matset conduit::Node &dest, const float64 epsilon = CONDUIT_EPSILON); + //------------------------------------------------------------------------- + index_t CONDUIT_BLUEPRINT_API count_zones_from_matset(const conduit::Node &matset); + //------------------------------------------------------------------------- + bool CONDUIT_BLUEPRINT_API is_material_in_zone(const conduit::Node &matset, + const std::string &matname, + const index_t zone_id, + const float64 epsilon = CONDUIT_EPSILON); + //----------------------------------------------------------------------------- + std::map CONDUIT_BLUEPRINT_API create_reverse_material_map( + const conduit::Node &src_matset); + //------------------------------------------------------------------------- // blueprint::mesh::matset::index protocol interface //------------------------------------------------------------------------- diff --git a/src/libs/blueprint/conduit_blueprint_mesh_matset_xforms.cpp b/src/libs/blueprint/conduit_blueprint_mesh_matset_xforms.cpp index 22382f160..19c9a3d3d 100644 --- a/src/libs/blueprint/conduit_blueprint_mesh_matset_xforms.cpp +++ b/src/libs/blueprint/conduit_blueprint_mesh_matset_xforms.cpp @@ -527,22 +527,6 @@ copy_matset_independent_parts_of_field(const conduit::Node &src_field, dest_field["matset"] = dest_matset_name; } -//----------------------------------------------------------------------------- -void -create_reverse_matmap(const conduit::Node &src_matset, - std::map &reverse_matmap) -{ - // fill out map - auto matmap_itr = src_matset["material_map"].children(); - while (matmap_itr.has_next()) - { - const Node &matmap_entry = matmap_itr.next(); - const std::string matname = matmap_itr.name(); - - reverse_matmap[matmap_entry.to_int()] = matname; - } -} - //----------------------------------------------------------------------------- // load the element ids into a set to find out how many there are int @@ -564,13 +548,13 @@ determine_num_elems_in_multi_buffer_by_material(const conduit::Node &elem_ids) } return static_cast(elem_ids_set.size()); -}; +} //----------------------------------------------------------------------------- void walk_uni_buffer_by_element_to_multi_buffer_by_element( const conduit::Node &src_matset, - std::map &reverse_matmap, + const std::map &reverse_matmap, float64_accessor &values, // can be either vol fracs or matset vals int64_accessor &material_ids, std::map> &new_vals) @@ -579,7 +563,7 @@ walk_uni_buffer_by_element_to_multi_buffer_by_element( int num_elems = o2m_idx.size(); // initialize sizes - for (auto & mapitem : reverse_matmap) + for (const auto & mapitem : reverse_matmap) { const std::string &matname = mapitem.second; new_vals[matname] = std::vector(num_elems); @@ -594,7 +578,7 @@ walk_uni_buffer_by_element_to_multi_buffer_by_element( float64 val = values[data_index]; int mat_id = material_ids[data_index]; - const std::string &matname = reverse_matmap[mat_id]; + const std::string &matname = reverse_matmap.at(mat_id); new_vals[matname][elem_id] = val; } } @@ -806,8 +790,7 @@ uni_buffer_by_element_to_multi_buffer_by_element_matset(const conduit::Node &src dest_matset["topology"].set(src_matset["topology"]); // map material numbers to material names - std::map reverse_matmap; - create_reverse_matmap(src_matset, reverse_matmap); + const std::map reverse_matmap = create_reverse_material_map(src_matset["material_map"]); // get ptr to vol fracs and mat ids float64_accessor volume_fractions = src_matset["volume_fractions"].value(); @@ -843,8 +826,7 @@ uni_buffer_by_element_to_multi_buffer_by_element_field(const conduit::Node &src_ dest_field); // map material numbers to material names - std::map reverse_matmap; - create_reverse_matmap(src_matset, reverse_matmap); + const std::map reverse_matmap = create_reverse_material_map(src_matset["material_map"]); // get ptr to matset values and mat ids float64_accessor matset_values = src_field["matset_values"].value(); @@ -879,8 +861,7 @@ uni_buffer_by_element_to_multi_buffer_by_material_matset(const conduit::Node &sr dest_matset["topology"].set(src_matset["topology"]); // map material numbers to material names - std::map reverse_matmap; - create_reverse_matmap(src_matset, reverse_matmap); + const std::map reverse_matmap = create_reverse_material_map(src_matset["material_map"]); // get ptr to vol fracs and mat ids float64_accessor volume_fractions = src_matset["volume_fractions"].value(); @@ -900,7 +881,7 @@ uni_buffer_by_element_to_multi_buffer_by_material_matset(const conduit::Node &sr float64 vol_frac = volume_fractions[data_index]; int64 mat_id = material_ids[data_index]; - const std::string &matname = reverse_matmap[mat_id]; + const std::string &matname = reverse_matmap.at(mat_id); new_vol_fracs[matname].push_back(vol_frac); new_elem_ids[matname].push_back(elem_id); @@ -929,8 +910,7 @@ uni_buffer_by_element_to_multi_buffer_by_material_field(const conduit::Node &src dest_field); // map material numbers to material names - std::map reverse_matmap; - create_reverse_matmap(src_matset, reverse_matmap); + const std::map reverse_matmap = create_reverse_material_map(src_matset["material_map"]); // get ptr to matset values and mat ids float64_accessor matset_values = src_field["matset_values"].value(); @@ -948,7 +928,7 @@ uni_buffer_by_element_to_multi_buffer_by_material_field(const conduit::Node &src float64 mset_val = matset_values[data_index]; int64 mat_id = material_ids[data_index]; - const std::string &matname = reverse_matmap[mat_id]; + const std::string &matname = reverse_matmap.at(mat_id); new_mset_vals[matname].push_back(mset_val); } @@ -1304,6 +1284,134 @@ to_silo(const conduit::Node &matset, epsilon); } +//----------------------------------------------------------------------------- +std::map +create_reverse_material_map(const conduit::Node &src_material_map) +{ + std::map reverse_matmap; + // fill out map + auto matmap_itr = src_material_map.children(); + while (matmap_itr.has_next()) + { + const Node &matmap_entry = matmap_itr.next(); + const std::string matname = matmap_itr.name(); + reverse_matmap[matmap_entry.to_int()] = matname; + } + return reverse_matmap; +} +//------------------------------------------------------------------------- +index_t +count_zones_from_matset(const conduit::Node &matset) +{ + // extra seat belt here + if (! matset.dtype().is_object()) + { + CONDUIT_ERROR("blueprint::mesh::matset::count_zones_in_matset" + " passed matset node must be a valid matset tree."); + } + // full + if (is_element_dominant(matset) && is_multi_buffer(matset)) + { + if (matset["volume_fractions"].number_of_children() > 0) + { + return matset["volume_fractions"][0].dtype().number_of_elements(); + } + else + { + return 0; + } + } + // sparse_by_element + else if (is_element_dominant(matset)) + { + return matset["sizes"].dtype().number_of_elements(); + } + // sparse_by_material + else if (is_material_dominant(matset)) + { + return detail::determine_num_elems_in_multi_buffer_by_material(matset["element_ids"]); + } + else + { + CONDUIT_ERROR("Unknown matset type."); + } + + return -1; +} + +//------------------------------------------------------------------------- +bool +is_material_in_zone(const conduit::Node &matset, + const std::string &matname, + const index_t zone_id, + const float64 epsilon) +{ + // extra seat belt here + if (! matset.dtype().is_object()) + { + CONDUIT_ERROR("blueprint::mesh::matset::is_material_in_zone" + " passed matset node must be a valid matset tree."); + } + // full + if (is_element_dominant(matset) && is_multi_buffer(matset)) + { + if (matset["volume_fractions"].has_child(matname)) + { + const float64_accessor vfs = matset["volume_fractions"][matname].value(); + return vfs[zone_id] > epsilon; + } + else + { + // obviously the material is not present in the zone; it is not + // present in the matset + return false; + } + } + // sparse_by_element + else if (is_element_dominant(matset)) + { + const index_t_accessor sizes = matset["sizes"].value(); + const index_t_accessor offsets = matset["offsets"].value(); + const index_t_accessor material_ids = matset["material_ids"].value(); + const index_t size = sizes[zone_id]; + const index_t offset = offsets[zone_id]; + std::map reverse_matmap = mesh::matset::create_reverse_material_map(matset["material_map"]); + // look at materials in this zone + for (index_t idx = 0; idx < size; idx ++) + { + const index_t mat_id = material_ids[idx + offset]; + const std::string &curr_matname = reverse_matmap.at(mat_id); + if (curr_matname == matname) + { + // we found the right material in this zone + return true; + } + } + // not found in this zone + return false; + } + // sparse_by_material + else if (is_material_dominant(matset)) + { + if (matset["element_ids"].has_child(matname)) + { + const index_t_accessor elem_ids = matset["element_ids"][matname].value(); + return elem_ids.count(zone_id) > 0; + } + else + { + // obviously the material is not present in the zone; it is not + // present in the matset + return false; + } + } + else + { + CONDUIT_ERROR("Unknown matset type."); + } + return false; +} + //----------------------------------------------------------------------------- void to_multi_buffer_full(const conduit::Node &src_matset, diff --git a/src/tests/blueprint/t_blueprint_mesh_matset_xforms.cpp b/src/tests/blueprint/t_blueprint_mesh_matset_xforms.cpp index 95f951e76..c05b00c4c 100644 --- a/src/tests/blueprint/t_blueprint_mesh_matset_xforms.cpp +++ b/src/tests/blueprint/t_blueprint_mesh_matset_xforms.cpp @@ -35,6 +35,94 @@ convert_to_material_based(const Node &topo, Node &mset) /// Test Cases /// +//----------------------------------------------------------------------------- +TEST(conduit_blueprint_mesh_matset_xforms, mesh_util_create_reverse_matmap) +{ + Node material_map; + material_map["mat1"] = 5; + material_map["mat2"] = 213423; + material_map["mat3"] = 6; + material_map["mat4"] = 0; + + const std::map reverse_matmap = + blueprint::mesh::matset::create_reverse_material_map(material_map); + EXPECT_EQ("mat4", reverse_matmap.at(0)); + EXPECT_EQ("mat1", reverse_matmap.at(5)); + EXPECT_EQ("mat3", reverse_matmap.at(6)); + EXPECT_EQ("mat2", reverse_matmap.at(213423)); +} + +//----------------------------------------------------------------------------- +TEST(conduit_blueprint_mesh_matset_xforms, mesh_util_count_zones_from_matset) +{ + const int nx = 4, ny = 4; + const double radius = 0.25; + + CONDUIT_INFO("venn full count zones"); + { + Node mesh; + blueprint::mesh::examples::venn("full", nx, ny, radius, mesh); + const Node &mset = mesh["matsets/matset"]; + + EXPECT_EQ(16, blueprint::mesh::matset::count_zones_from_matset(mset)); + } + + CONDUIT_INFO("venn sparse_by_material count zones"); + { + Node mesh; + blueprint::mesh::examples::venn("sparse_by_material", nx, ny, radius, mesh); + const Node &mset = mesh["matsets/matset"]; + + EXPECT_EQ(16, blueprint::mesh::matset::count_zones_from_matset(mset)); + } + + CONDUIT_INFO("venn sparse_by_element count zones"); + { + Node mesh; + blueprint::mesh::examples::venn("sparse_by_element", nx, ny, radius, mesh); + const Node &mset = mesh["matsets/matset"]; + + EXPECT_EQ(16, blueprint::mesh::matset::count_zones_from_matset(mset)); + } +} + +//----------------------------------------------------------------------------- +TEST(conduit_blueprint_mesh_matset_xforms, mesh_util_is_material_in_zone) +{ + const int nx = 2, ny = 2; + const double radius = 0.25; + + CONDUIT_INFO("venn full check mat in zone"); + { + Node mesh; + blueprint::mesh::examples::venn("full", nx, ny, radius, mesh); + const Node &mset = mesh["matsets/matset"]; + + EXPECT_FALSE(blueprint::mesh::matset::is_material_in_zone(mset, "circle_c", 0)); + EXPECT_TRUE(blueprint::mesh::matset::is_material_in_zone(mset, "circle_c", 3)); + } + + CONDUIT_INFO("venn sparse_by_material check mat in zone"); + { + Node mesh; + blueprint::mesh::examples::venn("sparse_by_material", nx, ny, radius, mesh); + const Node &mset = mesh["matsets/matset"]; + + EXPECT_FALSE(blueprint::mesh::matset::is_material_in_zone(mset, "circle_c", 0)); + EXPECT_TRUE(blueprint::mesh::matset::is_material_in_zone(mset, "circle_c", 3)); + } + + CONDUIT_INFO("venn sparse_by_element check mat in zone"); + { + Node mesh; + blueprint::mesh::examples::venn("sparse_by_element", nx, ny, radius, mesh); + const Node &mset = mesh["matsets/matset"]; + + EXPECT_FALSE(blueprint::mesh::matset::is_material_in_zone(mset, "circle_c", 0)); + EXPECT_TRUE(blueprint::mesh::matset::is_material_in_zone(mset, "circle_c", 3)); + } +} + //----------------------------------------------------------------------------- TEST(conduit_blueprint_mesh_matset_xforms, mesh_util_to_silo_basic) {