diff --git a/src/libs/blueprint/conduit_blueprint_mesh_utils.cpp b/src/libs/blueprint/conduit_blueprint_mesh_utils.cpp index e581fe02d..8c5991fc1 100644 --- a/src/libs/blueprint/conduit_blueprint_mesh_utils.cpp +++ b/src/libs/blueprint/conduit_blueprint_mesh_utils.cpp @@ -2834,7 +2834,27 @@ bool adjset::is_canonical(const Node &adjset) for(conduit::index_t i = 0; i < groups.number_of_children() && retval; i++) { auto pos = groups[i].name().find(conduit::blueprint::mesh::adjset::group_prefix()); - retval &= (pos == 0); + + bool canonical = (pos == 0); + if(canonical) + { + std::vector tokens; + conduit::utils::split_string(groups[i].name(), '_', tokens); + canonical = tokens.size() >= 3; + if(canonical) + { + std::vector doms; + doms.reserve(tokens.size() - 1); + // Start at 1 to skip the groups prefix. + for(size_t j = 1; j < tokens.size(); j++) + doms.push_back(atoi(tokens[j].c_str())); + // Start at 1 because we'll compare pairs. Make sure domains are sorted. + for(size_t j = 1; j < doms.size(); j++) + canonical &= doms[j - 1] < doms[j]; + } + } + + retval &= canonical; } return retval; } diff --git a/src/tests/blueprint/t_blueprint_mesh_utils.cpp b/src/tests/blueprint/t_blueprint_mesh_utils.cpp index d38e40f46..f2a77b225 100644 --- a/src/tests/blueprint/t_blueprint_mesh_utils.cpp +++ b/src/tests/blueprint/t_blueprint_mesh_utils.cpp @@ -617,3 +617,54 @@ TEST(conduit_blueprint_mesh_utils, topology_search_2d_nohit) EXPECT_EQ(resCA.size(), 4); EXPECT_EQ(resCA, answersCA); }; + +//----------------------------------------------------------------------------- +TEST(conduit_blueprint_mesh_utils, is_canonical) +{ + const char *adjsets = R"( +adjsets: + correct: + topology: mesh + association: vertex + groups: + group_0_1: + neighbors: 1 + values: [0,1,2] + wrong_prefix: + topology: mesh + association: vertex + groups: + prefix_0_1: + neighbors: 1 + values: [0,1,2] + out_of_order: + topology: mesh + association: vertex + groups: + group_1_0: + neighbors: 1 + values: [0,1,2] + multi: + topology: mesh + association: vertex + groups: + group_0_1_2: + neighbors: [1,2] + values: [0,1,2] + multi_out_of_order: + topology: mesh + association: vertex + groups: + group_0_2_1: + neighbors: [1,2] + values: [0,1,2] +)"; + + conduit::Node n; + n.parse(adjsets); + EXPECT_TRUE( conduit::blueprint::mesh::utils::adjset::is_canonical(n["adjsets/correct"])); + EXPECT_FALSE(conduit::blueprint::mesh::utils::adjset::is_canonical(n["adjsets/wrong_prefix"])); + EXPECT_FALSE(conduit::blueprint::mesh::utils::adjset::is_canonical(n["adjsets/out_of_order"])); + EXPECT_TRUE( conduit::blueprint::mesh::utils::adjset::is_canonical(n["adjsets/multi"])); + EXPECT_FALSE(conduit::blueprint::mesh::utils::adjset::is_canonical(n["adjsets/multi_out_of_order"])); +}