Skip to content

Commit

Permalink
Merge pull request #1226 from LLNL/bugfix/whitlock/unstructured_point…
Browse files Browse the repository at this point in the history
…s_change

Unscramble face adjsets in to_topo() used in adjset validation program.
  • Loading branch information
BradWhitlock committed Jan 8, 2024
2 parents f6ed51d + 77d2ac3 commit 5a5b11d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s
#### Blueprint
- The `conduit::blueprint::mpi::mesh::partition_map_back()` function was enhanced so it accepts a "field_prefix" value in its options. The prefix is used when looking for the `global_vertex_ids` field, which could have been created with a prefix by the same option in the `conduit::blueprint::mpi::mesh::generate_partition_field()` function.
- The `conduit::blueprint::mesh::utils::ShapeType` class was enhanced so it can take topologies other than unstructured.
- The `conduit::blueprint::mesh::utils::topology::unstructured::points()` function was changed so it takes an optional argument that can turn off point uniqueness and sorting so the method can return points for an element as they appear in the connectivity, for non-polyhedral shapes.

### Fixed

Expand Down
99 changes: 65 additions & 34 deletions src/libs/blueprint/conduit_blueprint_mesh_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2515,7 +2515,8 @@ topology::unstructured::generate_offsets(const Node &topo,
//-----------------------------------------------------------------------------
std::vector<index_t>
topology::unstructured::points(const Node &n,
const index_t ei)
const index_t ei,
bool unique)
{
// NOTE(JRC): This is a workaround to ensure offsets are generated up-front
// if they don't exist and aren't regenerated for each subcall that needs them.
Expand All @@ -2525,45 +2526,30 @@ topology::unstructured::points(const Node &n,

const ShapeType topo_shape(ntemp);

std::set<index_t> pidxs;
if(!topo_shape.is_poly())
{
index_t_accessor poff_vals = ntemp["elements/offsets"].value();
const index_t eoff = poff_vals[ei];

index_t_accessor pidxs_vals = ntemp["elements/connectivity"].value();
for(index_t pi = 0; pi < topo_shape.indices; pi++)
{
pidxs.insert(pidxs_vals[eoff + pi]);
}
}
else // if(topo_shape.is_poly())
std::vector<index_t> retval;
if(topo_shape.is_polyhedral())
{
// For polyhedra, the points returned will be unique.
Node enode;
std::set<index_t> eidxs;
if(topo_shape.is_polygonal())
{
enode.set_external(ntemp["elements"]);
eidxs.insert(ei);
}
else // if(topo_shape.is_polyhedral())
{
enode.set_external(ntemp["subelements"]);
enode.set_external(ntemp["subelements"]);

index_t_accessor eidxs_vals = ntemp["elements/connectivity"].value();
o2mrelation::O2MIterator eiter(ntemp["elements"]);
eiter.to(ei, o2mrelation::ONE);
eiter.to_front(o2mrelation::MANY);
while(eiter.has_next(o2mrelation::MANY))
{
eiter.next(o2mrelation::MANY);
const index_t tmp = eidxs_vals[eiter.index(o2mrelation::DATA)];
eidxs.insert(tmp);
}
// Gather the face ids for the element.
index_t_accessor eidxs_vals = ntemp["elements/connectivity"].value();
o2mrelation::O2MIterator eiter(ntemp["elements"]);
eiter.to(ei, o2mrelation::ONE);
eiter.to_front(o2mrelation::MANY);
while(eiter.has_next(o2mrelation::MANY))
{
eiter.next(o2mrelation::MANY);
const index_t tmp = eidxs_vals[eiter.index(o2mrelation::DATA)];
eidxs.insert(tmp);
}

// Iterate over the faces and make unique set of point ids.
index_t_accessor pidxs_vals = enode["connectivity"].value();
o2mrelation::O2MIterator piter(enode);
std::set<index_t> pidxs;
for(const index_t eidx : eidxs)
{
piter.to(eidx, o2mrelation::ONE);
Expand All @@ -2575,9 +2561,52 @@ topology::unstructured::points(const Node &n,
pidxs.insert(tmp);
}
}

// Return point ids.
retval = std::vector<index_t>(pidxs.begin(), pidxs.end());
}
else
{
const index_t_accessor poff_vals = ntemp["elements/offsets"].value();
const index_t eoff = poff_vals[ei];

// Determine the number of points for the shape.
index_t npts;
if(topo_shape.is_polygonal())
{
const index_t_accessor psize_vals = ntemp["elements/sizes"].value();
npts = psize_vals[ei];
}
else
{
npts = topo_shape.indices;
}

// Get the points for the shape.
index_t_accessor pidxs_vals = ntemp["elements/connectivity"].value();
if(unique)
{
std::set<index_t> pidxs;
for(index_t pi = 0; pi < npts; pi++)
{
const auto pid = pidxs_vals[eoff + pi];
pidxs.insert(pid);
}
// Return point ids.
retval = std::vector<index_t>(pidxs.begin(), pidxs.end());
}
else
{
retval.reserve(npts);
for(index_t pi = 0; pi < npts; pi++)
{
const auto pid = pidxs_vals[eoff + pi];
retval.push_back(pid);
}
}
}

return std::vector<index_t>(pidxs.begin(), pidxs.end());
return retval;
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -3264,7 +3293,9 @@ foreach_adjset_mesh_pair_impl(conduit::Node &mesh, const std::string &adjsetName
for(index_t i = 0; i < values.number_of_elements(); i++)
{
index_t ei = values[i];
const auto ptids = conduit::blueprint::mesh::utils::topology::unstructured::points(topo, ei);
// Get the element points in their original order.
const bool unique = false;
const auto ptids = conduit::blueprint::mesh::utils::topology::unstructured::points(topo, ei, unique);
B.add(&ptids[0], ptids.size());

minSides = (i == 0) ? ptids.size() : std::min(minSides, ptids.size());
Expand Down
20 changes: 19 additions & 1 deletion src/libs/blueprint/conduit_blueprint_mesh_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,26 @@ namespace topology
void CONDUIT_BLUEPRINT_API generate_offsets_inline(Node &topo);

//-------------------------------------------------------------------------
/**
@brief This function returns the points for a specified element index from
the given topology. For non-polyhedral element types, the \a unique
parameter indicates whether the function will return a unique+sorted
vector of point ids. The order can therefore differ from the point
order in the connectivity. When \a unique is false, the original
cell connectivity is preserved. For polyhedral types, the points
are always unique and sorted according to point id.
@param topo The input topology.
@param ei The element index.
@param unique Whether points should be unique+sorted. The default is true
to continue earlier behavior.
@return A vector of point ids for the given element.
*/
std::vector<index_t> CONDUIT_BLUEPRINT_API points(const Node &topo,
const index_t i);
const index_t ei,
bool unique = true);

//-------------------------------------------------------------------------
/**
* @brief Rewrite the topology's connectivity in terms of the supplied
Expand Down

0 comments on commit 5a5b11d

Please sign in to comment.