Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
- Added a bulk `DataAccessor::set()` method for setting many elements at once.

#### Blueprint
- Added `conduit::blueprint::mesh::rename()` helper that renames sub components of a valid mesh and their dependent references. Example: rename a topology and ensure field topology references are updated.
- Added `conduit::blueprint::mesh::remove()` helper that removes sub components of a valid mesh and their dependencies. Examples: remove a field by name, or remove a topology by name and any dependent entries.
- Added `conduit::blueprint::mesh::matset::get_material_names()`, which returns material names for a material set.
- Added the ability for the Partitioner to handle field `matset_values` for both domain slicing and combination.
Expand Down
184 changes: 184 additions & 0 deletions src/libs/blueprint/conduit_blueprint_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9440,6 +9440,190 @@ void mesh::remove(const conduit::Node &n_options,
}


void mesh::rename(const conduit::Node &n_options,
conduit::Node &n_mesh)
{
// check options, each top level entry should be
// a component type name (coordsets) node that is an object with
// children that encode old vs new name
// current_name: new_name (coords: my_coords_new)

NodeConstIterator itr = n_options.children();
while(itr.has_next())
{
const Node &chld = itr.next();
const std::string chld_name = itr.name();

if(!chld.dtype().is_object())
{
CONDUIT_ERROR(conduit_fmt::format(
"mesh::rename option must contain an object with children that are strings\n Value provided: {}\n",
n_options.to_yaml()));
}
else // we have a an object
{
// check that all object entries are strings
NodeConstIterator chld_itr = chld.children();
while(chld_itr.has_next())
{
if(!chld_itr.next().dtype().is_string())
{
CONDUIT_ERROR(conduit_fmt::format(
"mesh::rename option must contain an object with children that are strings\n Value provided: {}\n",
n_options.to_yaml()));
}
}
}
}

// helper to rename a component
auto rename_component = [&](conduit::Node *dom,
const std::string &comp_type,
const std::string &comp_name_old,
const std::string &comp_name_new)
{
if(dom->has_child(comp_type))
{
Node &comp_node = dom->fetch_existing(comp_type);
if(comp_node.has_child(comp_name_old))
{
comp_node.rename_child(comp_name_old,comp_name_new);
}
}
};

// helper to update references to a component that was renamed
auto rename_dependent_component_refs = [&](conduit::Node *dom,
const std::string &comp_type,
const std::string &ref_type,
const std::string &ref_name_old,
const std::string &ref_name_new)
{
if(dom->has_child(comp_type))
{
NodeIterator itr = dom->fetch_existing(comp_type).children();
while(itr.has_next())
{
conduit::Node &curr = itr.next();
if(curr.has_child(ref_type))
{
const std::string ref_name = curr[ref_type].as_string();
if(ref_name == ref_name_old)
{
curr[ref_type] = ref_name_new;
}
}
}
}
};

// note: this isn't const b/c we will alter the mesh
auto domains = conduit::blueprint::mesh::domains(n_mesh);

// loop over all domains
for(size_t i = 0; i < domains.size(); i++)
{
conduit::Node *dom = domains[i];

if(n_options.has_child("coordsets"))
{
NodeConstIterator itr = n_options["coordsets"].children();
while(itr.has_next())
{
const Node &chld_node = itr.next();
std::string chld_name_old = itr.name();
std::string chld_name_new = chld_node.as_string();
rename_component(dom, "coordsets", chld_name_old, chld_name_new);
rename_dependent_component_refs(dom, "topologies", "coordset", chld_name_old, chld_name_new);
}
}

if(n_options.has_child("topologies"))
{
NodeConstIterator itr = n_options["topologies"].children();
while(itr.has_next())
{
const Node &chld_node = itr.next();
std::string chld_name_old = chld_node.name();
std::string chld_name_new = chld_node.as_string();
rename_component(dom, "topologies", chld_name_old, chld_name_new);
rename_dependent_component_refs(dom, "fields", "topology", chld_name_old, chld_name_new);
rename_dependent_component_refs(dom, "matsets", "topology", chld_name_old, chld_name_new);
rename_dependent_component_refs(dom, "adjsets", "topology", chld_name_old, chld_name_new);
rename_dependent_component_refs(dom, "nestsets", "topology", chld_name_old, chld_name_new);
}
}

if(n_options.has_child("fields"))
{
NodeConstIterator itr = n_options["fields"].children();
while(itr.has_next())
{
const Node &chld_node = itr.next();
std::string chld_name_old = chld_node.name();
std::string chld_name_new = chld_node.as_string();
conduit::Node *dom = domains[i];
rename_component(dom, "fields", chld_name_old, chld_name_new);
}
}

if(n_options.has_child("matsets"))
{
NodeConstIterator itr = n_options["matsets"].children();
while(itr.has_next())
{
const Node &chld_node = itr.next();
std::string chld_name_old = chld_node.name();
std::string chld_name_new = chld_node.as_string();
conduit::Node *dom = domains[i];
rename_component(dom, "matsets", chld_name_old, chld_name_new);
rename_dependent_component_refs(dom, "specsets", "matset", chld_name_old, chld_name_new);
rename_dependent_component_refs(dom, "fields", "matset", chld_name_old, chld_name_new);
}
}

if(n_options.has_child("specsets"))
{
NodeConstIterator itr = n_options["specsets"].children();
while(itr.has_next())
{
const Node &chld_node = itr.next();
std::string chld_name_old = chld_node.name();
std::string chld_name_new = chld_node.as_string();
conduit::Node *dom = domains[i];
rename_component(dom, "specsets", chld_name_old, chld_name_new);
}
}

if(n_options.has_child("adjsets"))
{
NodeConstIterator itr = n_options["adjsets"].children();
while(itr.has_next())
{
const Node &chld_node = itr.next();
std::string chld_name_old = chld_node.name();
std::string chld_name_new = chld_node.as_string();
conduit::Node *dom = domains[i];
rename_component(dom, "adjsets", chld_name_old, chld_name_new);
}
}

if(n_options.has_child("nestsets"))
{
NodeConstIterator itr = n_options["nestsets"].children();
while(itr.has_next())
{
const Node &chld_node = itr.next();
std::string chld_name_old = chld_node.name();
std::string chld_name_new = chld_node.as_string();
conduit::Node *dom = domains[i];
rename_component(dom, "nestsets", chld_name_old, chld_name_new);
}
}
}
}


}
//-----------------------------------------------------------------------------
// -- end conduit::blueprint --
Expand Down
54 changes: 51 additions & 3 deletions src/libs/blueprint/conduit_blueprint_mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,10 +401,13 @@ void CONDUIT_BLUEPRINT_API convert(const conduit::Node &n_mesh,
//-------------------------------------------------------------------------
/*!
* @brief Remove specific components of mesh and their dependent entires.
* For example, remove a topology and all assocated fields
*
* For example, remove a topology and all associated fields
*
* If patterns do not match, remove is a no-op and no errors
* are thrown.
*
* @param n_mesh The node containing the input mesh (coordsets, topos,
* fields, matsets, adjsets)
* fields, matsets, specsets, adjsets, and nestsets)
*
* @param n_options A node containing options. Categories support
* both a single string or a list of strings
Expand All @@ -415,6 +418,7 @@ void CONDUIT_BLUEPRINT_API convert(const conduit::Node &n_mesh,
* topologies: mytopo | [ mytopo1, mytopo2, ... ]
* fields: myfield | [ myfield1, myfield2, ... ]
* matsets: mymatset | [ mymatset1, mymatset2, ... ]
* specsets: myspecset | [ myspecset1, myspecset3, ... ]
* adjsets: myadj | [ myadj1,myadj2, ... ]
* nestsets: mynestset | [ mynestset1, mynestset2, ... ]
*
Expand All @@ -428,6 +432,50 @@ void CONDUIT_BLUEPRINT_API remove(const conduit::Node &n_options,
conduit::Node &n_mesh);



//-------------------------------------------------------------------------
/*!
* @brief Rename specific components of mesh and update their dependent
* entires.
*
* For example, rename topology to `my_topo` and update
* all associated fields.
*
* If components are not found rename is a no-op and
* no errors are thrown.
*
* @param n_mesh The node containing the input mesh (coordsets, topos,
* fields, matsets, specsets, adjsets, and nestsets)
*
* @param n_options A node containing options. Entries
* should be an object with children that encode
* desired old_name: new_name relationship.
*
* @verbatim
* options:
* coordsets:
* coords_old : coords_new
* topologies:
* topo_old : topo_new
* fields:
* field1_old : field1_new
* field2_old : field2_new
* matsets:
* matset_old : matset_new
* specsets:
* specset_old : specset_new
* adjsets:
* adjset_old : adjset_new
* nestsets:
* nestset_old : nestset_new
*
* @endverbatim
Comment on lines +454 to +472
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we ever have multiple things to rename in a given category? Maybe we rename multiple fields?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like we can, so should this docstring be updated to make that clearer?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I should add an example that shows this

  • add example

*/
void CONDUIT_BLUEPRINT_API rename(const conduit::Node &n_options,
conduit::Node &n_mesh);



//-----------------------------------------------------------------------------
// blueprint::mesh::logical_dims protocol interface
//-----------------------------------------------------------------------------
Expand Down
84 changes: 84 additions & 0 deletions src/libs/blueprint/python/conduit_blueprint_mesh_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,86 @@ PyBlueprint_mesh_remove(PyObject *, //self
}


//---------------------------------------------------------------------------//
// conduit::blueprint::mesh::rename
//---------------------------------------------------------------------------//

// doc str
const char *PyBlueprint_mesh_rename_doc_str =
"rename(options, mesh)\n"
"\n"
"Assumes mesh::verify() is True\n"
"\n"
"Renames subcomponents of a blueprint mesh tree\n"
"\n"
"Arguments:\n"
" options: options node (conduit.Node instance)\n"
" mesh: input node (conduit.Node instance)\n"
"\n"
"Example Options:\n"
"topologies:\n"
" topo: mytopo\n"
"\n";

// py func
static PyObject *
PyBlueprint_mesh_rename(PyObject *, //self
PyObject *args,
PyObject *kwargs)
{

PyObject *py_options = NULL;
PyObject *py_mesh = NULL;

static const char *kwlist[] = {"options",
"mesh",
NULL};

if (!PyArg_ParseTupleAndKeywords(args,
kwargs,
"OO",
const_cast<char**>(kwlist),
&py_options,
&py_mesh))
{
return NULL;
}

if(!PyConduit_Node_Check(py_options))
{
PyErr_SetString(PyExc_TypeError,
"'options' argument must be a "
"conduit.Node instance");
return NULL;
}

if(!PyConduit_Node_Check(py_mesh))
{
PyErr_SetString(PyExc_TypeError,
"'mesh' argument must be a "
"conduit.Node instance");
return NULL;
}

try
{
Node &options = *PyConduit_Node_Get_Node_Ptr(py_options);
Node &mesh = *PyConduit_Node_Get_Node_Ptr(py_mesh);

blueprint::mesh::rename(options,mesh);
}
catch(conduit::Error &e)
{
PyErr_SetString(PyExc_IOError,
e.message().c_str());
return NULL;
}


Py_RETURN_NONE;
}



//---------------------------------------------------------------------------//
// conduit::blueprint::mesh::partition
Expand Down Expand Up @@ -663,6 +743,10 @@ static PyMethodDef blueprint_mesh_python_funcs[] =
_PyCFunction_CAST(PyBlueprint_mesh_remove),
METH_VARARGS | METH_KEYWORDS,
PyBlueprint_mesh_remove_doc_str},
{"rename",
_PyCFunction_CAST(PyBlueprint_mesh_rename),
METH_VARARGS | METH_KEYWORDS,
PyBlueprint_mesh_rename_doc_str},
{"partition",
_PyCFunction_CAST(PyBlueprint_mesh_partition),
METH_VARARGS | METH_KEYWORDS,
Expand Down
1 change: 1 addition & 0 deletions src/tests/blueprint/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ set(BLUEPRINT_TESTS t_blueprint_smoke
t_blueprint_mesh_matset_accessor
t_blueprint_mesh_topology_metadata
t_blueprint_mesh_remove
t_blueprint_mesh_rename
t_blueprint_mesh_utils
t_blueprint_table_verify
t_blueprint_table_examples
Expand Down
Loading
Loading