Skip to content

Commit

Permalink
Merge pull request #1172 from LLNL/refactor/gunney/use-conduit-topology
Browse files Browse the repository at this point in the history
Use Blueprint-specified coordset name, instead of assuming one
  • Loading branch information
gunney1 committed Aug 22, 2023
2 parents aa2c78d + 24af0c5 commit 985ce90
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 51 deletions.
8 changes: 8 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ The Axom project release numbers follow [Semantic Versioning](http://semver.org/

## [Unreleased] - Release date yyyy-mm-dd

### Changed
- `MarchingCubes` and `DistributedClosestPoint` classes changed from requiring the Blueprint
coordset name to requiring the Blueprint topology name. The changed interface methods are:
- `DistributedClosestPoint::setObjectMesh`
- `DistributedClosestPoint::computeClosestPoints`
- `MarchingCubes::MarchingCubes`
- `MarchingCubesSingleDomain::MarchingCubesSingleDomain`

## [Version 0.8.1] - Release date 2023-08-16

### Changed
Expand Down
64 changes: 44 additions & 20 deletions src/axom/quest/DistributedClosestPoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ namespace mpi
* \param [in] tag tag for MPI message
* \param [in] comm MPI communicator to use
* \param [in] request object holding state for the sent data
* \note Adapted from conduit's relay::mpi's \a send_using_schema and \a isend to use
* non-blocking \a MPI_Isend instead of blocking \a MPI_Send
* \note Adapted from conduit's relay::mpi's \a send_using_schema and \a isend
* to use non-blocking \a MPI_Isend instead of blocking \a MPI_Send
*/
inline int isend_using_schema(conduit::Node& node,
int dest,
Expand Down Expand Up @@ -424,11 +424,11 @@ class DistributedClosestPointImpl
* Import object mesh points from the object blueprint mesh into internal memory.
*
* \param [in] mdMeshNode The blueprint mesh containing the object points.
* \param [in] valuesPath The path to the mesh points.
* \param [in] topologyName Name of the blueprint topology in \a mdMeshNode.
* \note This function currently supports mesh blueprints with the "point" topology
*/
void importObjectPoints(const conduit::Node& mdMeshNode,
const std::string& valuesPath)
const std::string& topologyName)
{
// TODO: See if some of the copies in this method can be optimized out.

Expand All @@ -438,6 +438,13 @@ class DistributedClosestPointImpl
int ptCount = 0;
for(const conduit::Node& domain : mdMeshNode.children())
{
const std::string coordsetName =
domain
.fetch_existing(
axom::fmt::format("topologies/{}/coordset", topologyName))
.as_string();
const std::string valuesPath =
axom::fmt::format("coordsets/{}/values", coordsetName);
auto& values = domain.fetch_existing(valuesPath);
const int N = internal::extractSize(values);
ptCount += N;
Expand All @@ -451,6 +458,13 @@ class DistributedClosestPointImpl
for(conduit::index_t d = 0; d < mdMeshNode.number_of_children(); ++d)
{
const conduit::Node& domain = mdMeshNode.child(d);
const std::string coordsetName =
domain
.fetch_existing(
axom::fmt::format("topologies/{}/coordset", topologyName))
.as_string();
const std::string valuesPath =
axom::fmt::format("coordsets/{}/values", coordsetName);

auto& values = domain.fetch_existing(valuesPath);

Expand Down Expand Up @@ -663,19 +677,24 @@ class DistributedClosestPointImpl
*/
void node_copy_query_to_xfer(conduit::Node& queryNode,
conduit::Node& xferNode,
const std::string& coordset) const
const std::string& topologyName) const
{
xferNode["homeRank"] = m_rank;
xferNode["is_first"] = 1;

conduit::Node& xferDoms = xferNode["xferDoms"];
for(auto& queryDom : queryNode.children())
{
const std::string coordsetName =
queryDom
.fetch_existing(
axom::fmt::format("topologies/{}/coordset", topologyName))
.as_string();
const std::string& domName = queryDom.name();
conduit::Node& xferDom = xferDoms[domName];
conduit::Node& fields = queryDom.fetch_existing("fields");
conduit::Node& queryCoords =
queryDom.fetch_existing(fmt::format("coordsets/{}", coordset));
queryDom.fetch_existing(fmt::format("coordsets/{}", coordsetName));
conduit::Node& queryCoordsValues = queryCoords.fetch_existing("values");

// clang-format off
Expand Down Expand Up @@ -819,10 +838,10 @@ class DistributedClosestPointImpl
*
* \param queryMesh The root node of a mesh blueprint for the query points
* Can be empty if there are no query points for the calling rank
* \param coordset The coordinate set for the query points
* \param topologyName The topology name identifying the query points
*
* When the query mesh contains query points, it uses the \a coordset coordinate set
* of the provided blueprint mesh and contains the following fields:
* The named topology is used to identify the points in the query mesh.
* On completion, the query mesh contains the following fields:
* - cp_rank: Will hold the rank of the object point containing the closest point
* - cp_domain_index: will hold the index of the object domain containing
* the closest points.
Expand All @@ -844,7 +863,7 @@ class DistributedClosestPointImpl
* using check_send_requests().
*/
void computeClosestPoints(conduit::Node& queryMesh_,
const std::string& coordset) const
const std::string& topologyName) const
{
SLIC_ASSERT_MSG(
isBVHTreeInitialized(),
Expand All @@ -868,7 +887,7 @@ class DistributedClosestPointImpl
{
xferNodes[m_rank] = std::make_shared<conduit::Node>();
conduit::Node& xferNode = *xferNodes[m_rank];
node_copy_query_to_xfer(queryMesh, xferNode, coordset);
node_copy_query_to_xfer(queryMesh, xferNode, topologyName);
xferNode["homeRank"] = m_rank;
}

Expand Down Expand Up @@ -1598,12 +1617,13 @@ class DistributedClosestPoint
* \brief Sets the object mesh for the query
*
* \param [in] meshNode Conduit node for the object mesh
* \param [in] coordset The name of the coordset for the object mesh's coordinates
* \param [in] topologyName The name of the topology for the object mesh
*
* \pre \a meshNode must follow the mesh blueprint convention.
* \pre Dimension of the mesh must be 2D or 3D
*/
void setObjectMesh(const conduit::Node& meshNode, const std::string& coordset)
void setObjectMesh(const conduit::Node& meshNode,
const std::string& topologyName)
{
SLIC_ASSERT(this->isValidBlueprint(meshNode));

Expand All @@ -1620,18 +1640,22 @@ class DistributedClosestPoint
const conduit::Node& mdMeshNode(isMultidomain ? meshNode : *tmpNode);

auto domainCount = conduit::blueprint::mesh::number_of_domains(mdMeshNode);
const std::string valuesPath = fmt::format("coordsets/{}/values", coordset);

// Extract the dimension from the coordinate values group
// use allreduce since some ranks might be empty
{
int localDim = -1;
if(domainCount > 0)
{
const conduit::Node& domain0(mdMeshNode[0]);
SLIC_ASSERT(domain0.has_path(valuesPath));
auto& values = domain0.fetch_existing(valuesPath);
localDim = internal::extractDimension(values);
const conduit::Node& domain0 = mdMeshNode.child(0);
const conduit::Node& topology =
domain0.fetch_existing("topologies/" + topologyName);
const std::string coordsetName =
topology.fetch_existing("coordset").as_string();
const conduit::Node& coordset =
domain0.fetch_existing("coordsets/" + coordsetName);
const conduit::Node& coordsetValues = coordset.fetch_existing("values");
localDim = internal::extractDimension(coordsetValues);
}
int dim = -1;
MPI_Allreduce(&localDim, &dim, 1, MPI_INT, MPI_MAX, m_mpiComm);
Expand All @@ -1643,10 +1667,10 @@ class DistributedClosestPoint
switch(m_dimension)
{
case 2:
m_dcp_2->importObjectPoints(mdMeshNode, valuesPath);
m_dcp_2->importObjectPoints(mdMeshNode, topologyName);
break;
case 3:
m_dcp_3->importObjectPoints(mdMeshNode, valuesPath);
m_dcp_3->importObjectPoints(mdMeshNode, topologyName);
break;
}

Expand Down
36 changes: 21 additions & 15 deletions src/axom/quest/MarchingCubes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ namespace quest
{
MarchingCubes::MarchingCubes(RuntimePolicy runtimePolicy,
const conduit::Node& bpMesh,
const std::string& coordsetName,
const std::string& topologyName,
const std::string& maskField)
: m_runtimePolicy(runtimePolicy)
, m_singles()
, m_coordsetPath("coordsets/" + coordsetName)
, m_topologyName(topologyName)
, m_fcnPath()
, m_maskPath(maskField.empty() ? std::string() : "fields/" + maskField)
{
Expand All @@ -31,8 +31,10 @@ MarchingCubes::MarchingCubes(RuntimePolicy runtimePolicy,
m_singles.reserve(conduit::blueprint::mesh::number_of_domains(bpMesh));
for(auto& dom : bpMesh.children())
{
m_singles.emplace_back(
new MarchingCubesSingleDomain(m_runtimePolicy, dom, coordsetName, maskField));
m_singles.emplace_back(new MarchingCubesSingleDomain(m_runtimePolicy,
dom,
m_topologyName,
maskField));
}
}

Expand Down Expand Up @@ -131,12 +133,12 @@ void MarchingCubes::populateContourMesh(

MarchingCubesSingleDomain::MarchingCubesSingleDomain(RuntimePolicy runtimePolicy,
const conduit::Node& dom,
const std::string& coordsetName,
const std::string& topologyName,
const std::string& maskField)
: m_runtimePolicy(runtimePolicy)
, m_dom(nullptr)
, m_ndim(0)
, m_coordsetPath("coordsets/" + coordsetName)
, m_topologyName(topologyName)
, m_fcnPath()
, m_maskPath(maskField.empty() ? std::string() : "fields/" + maskField)
{
Expand All @@ -153,9 +155,13 @@ void MarchingCubesSingleDomain::setDomain(const conduit::Node& dom)
SLIC_ASSERT_MSG(
!conduit::blueprint::mesh::is_multi_domain(dom),
"MarchingCubesSingleDomain is single-domain only. Try MarchingCubes.");
SLIC_ASSERT(
dom.fetch_existing("topologies/" + m_topologyName + "/type").as_string() ==
"structured");

SLIC_ASSERT(dom.has_path(m_coordsetPath));
SLIC_ASSERT(dom["topologies/mesh/type"].as_string() == "structured");
const std::string coordsetPath = "coordsets/" +
dom.fetch_existing("topologies/" + m_topologyName + "/coordset").as_string();
SLIC_ASSERT(dom.has_path(coordsetPath));

if(!m_maskPath.empty())
{
Expand All @@ -164,14 +170,12 @@ void MarchingCubesSingleDomain::setDomain(const conduit::Node& dom)

m_dom = &dom;

const conduit::Node& dimsNode =
m_dom->fetch_existing("topologies/mesh/elements/dims");

m_ndim = dimsNode.number_of_children();

m_ndim = conduit::blueprint::mesh::coordset::dims(
dom.fetch_existing("coordsets/coords"));
SLIC_ASSERT(m_ndim >= 2 && m_ndim <= 3);

const conduit::Node& coordsValues = dom[m_coordsetPath + "/values"];
const conduit::Node& coordsValues =
dom.fetch_existing(coordsetPath + "/values");
bool isInterleaved = conduit::blueprint::mcarray::is_interleaved(coordsValues);
SLIC_ASSERT_MSG(
!isInterleaved,
Expand All @@ -193,7 +197,9 @@ void MarchingCubesSingleDomain::computeIsocontour(double contourVal)
"You must call setFunctionField before computeIsocontour.");

allocateImpl();
m_impl->initialize(*m_dom, m_coordsetPath, m_fcnPath, m_maskPath);
const std::string coordsetPath = "coordsets/" +
m_dom->fetch_existing("topologies/" + m_topologyName + "/coordset").as_string();
m_impl->initialize(*m_dom, coordsetPath, m_fcnPath, m_maskPath);
m_impl->setContourValue(contourVal);
m_impl->markCrossings();
m_impl->scanCrossings();
Expand Down
16 changes: 8 additions & 8 deletions src/axom/quest/MarchingCubes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class MarchingCubes
* The simplest policy is RuntimePolicy::seq, which specifies
* running sequentially on the CPU.
* \param [in] bpMesh Blueprint multi-domain mesh containing scalar field.
* \param [in] coordsetName Name of blueprint point coordinate set.
* \param [in] topologyName Name of Blueprint topology to use in \a bpMesh.
* \param [in] maskField Cell-based std::int32_t mask field. If provided,
* cells where this field evaluates to false are skipped.
*
Expand All @@ -137,7 +137,7 @@ class MarchingCubes
*/
MarchingCubes(RuntimePolicy runtimePolicy,
const conduit::Node &bpMesh,
const std::string &coordsetName,
const std::string &topologyName,
const std::string &maskField = {});

/*!
Expand Down Expand Up @@ -178,7 +178,7 @@ class MarchingCubes

//! @brief Single-domain implementations.
axom::Array<std::unique_ptr<MarchingCubesSingleDomain>> m_singles;
const std::string m_coordsetPath;
const std::string m_topologyName;
std::string m_fcnPath;
std::string m_maskPath;

Expand Down Expand Up @@ -206,7 +206,7 @@ class MarchingCubesSingleDomain
* The simplest policy is RuntimePolicy::seq, which specifies
* running sequentially on the CPU.
* \param [in] dom Blueprint single-domain mesh containing scalar field.
* \param [in] coordsetName Name of blueprint point coordinate set.
* \param [in] topologyName Name of Blueprint topology to use in \a dom
* \param [in] maskField Cell-based std::int32_t mask field. If provided,
* cells where this field evaluates to false are skipped.
*
Expand All @@ -225,7 +225,7 @@ class MarchingCubesSingleDomain
*/
MarchingCubesSingleDomain(RuntimePolicy runtimePolicy,
const conduit::Node &dom,
const std::string &coordsetName,
const std::string &topologyName,
const std::string &maskfield);

/*!
Expand Down Expand Up @@ -319,8 +319,8 @@ class MarchingCubesSingleDomain
const conduit::Node *m_dom;
int m_ndim;

//!@brief Path to coordinate set in m_dom.
const std::string m_coordsetPath;
//!@brief Name of Blueprint topology in m_dom.
const std::string m_topologyName;

//!@brief Path to nodal scalar function in m_dom.
std::string m_fcnPath;
Expand All @@ -339,7 +339,7 @@ class MarchingCubesSingleDomain
{
//!@brief Prepare internal data for operating on the given domain.
virtual void initialize(const conduit::Node &dom,
const std::string &coordsetPath,
const std::string &topologyName,
const std::string &fcnPath,
const std::string &maskPath) = 0;
//!@brief Set the contour value
Expand Down

0 comments on commit 985ce90

Please sign in to comment.