Port bugfix for ListNewNodesCopyIdsWorklet.

This commit is contained in:
Oliver Ruebel 2020-11-09 16:53:46 -08:00 committed by Gunther H. Weber
parent e115236168
commit e734c6358c
5 changed files with 53 additions and 33 deletions

@ -166,15 +166,18 @@ public:
/// Routine to return the global IDs for a set of vertices
/// We here return a fancy array handle to convert values on-the-fly without requiring additional memory
/// SortIdArrayType must be an array if Ids. Usually this is a vtkm::worklet::contourtree_augmented::IdArrayType
/// but in some cases it may also be a fancy array to avoid memory allocation
/// @param[in] meshIds Array with mesh Ids to be converted from local to global Ids
/// @param[in] localToGlobalIdRelabeler This parameter is the IdRelabeler
/// used to transform local to global Ids. The relabeler relies on the
/// decomposition of the global mesh which is not know by this block.
inline vtkm::cont::ArrayHandleTransform<IdArrayType, mesh_dem::IdRelabeler>
GetGlobalIdsFromMeshIndices(const IdArrayType& meshIds,
template <typename MeshIdArrayType>
inline vtkm::cont::ArrayHandleTransform<MeshIdArrayType, mesh_dem::IdRelabeler>
GetGlobalIdsFromMeshIndices(const MeshIdArrayType& meshIds,
const mesh_dem::IdRelabeler* localToGlobalIdRelabeler) const
{ // GetGlobalIDsFromMeshIndices()
return vtkm::cont::ArrayHandleTransform<IdArrayType, mesh_dem::IdRelabeler>(
return vtkm::cont::ArrayHandleTransform<MeshIdArrayType, mesh_dem::IdRelabeler>(
meshIds, *localToGlobalIdRelabeler);
} // GetGlobalIDsFromMeshIndices()

@ -241,15 +241,18 @@ public:
/// notice that the sort ID is the same as the mesh ID for the ContourTreeMesh class.
/// To reduce memory usage we here use a fancy array handle rather than copy data
/// as is needed for the DataSetMesh types.
/// MeshIdArrayType must be an array if Ids. Usually this is a vtkm::worklet::contourtree_augmented::IdArrayType
/// but in some cases it may also be a fancy array to avoid memory allocation
/// We here return a fancy array handle to convert values on-the-fly without requiring additional memory
/// @param[in] meshIds Array with mesh Ids to be converted from local to global Ids
/// @param[in] localToGlobalIdRelabeler This parameter is here only for
/// consistency with the DataSetMesh types but is not
/// used here and as such can simply be set to nullptr
inline vtkm::cont::ArrayHandlePermutation<IdArrayType, IdArrayType> GetGlobalIdsFromMeshIndices(
const IdArrayType& meshIds,
const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler =
nullptr) const
template <typename MeshIdArrayType>
inline vtkm::cont::ArrayHandlePermutation<MeshIdArrayType, IdArrayType>
GetGlobalIdsFromMeshIndices(const MeshIdArrayType& meshIds,
const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler*
localToGlobalIdRelabeler = nullptr) const
{ // GetGlobalIDsFromMeshIndices()
(void)localToGlobalIdRelabeler; // avoid compiler warning
return vtkm::cont::make_ArrayHandlePermutation(meshIds, this->GlobalMeshIndex);

@ -1228,7 +1228,9 @@ void BoundaryTreeMaker<MeshType, MeshBoundaryExecObjType>::SetInteriorForest(
// now fill them in
auto meshGlobalIds =
this->Mesh->GetGlobalIdsFromMeshIndices(this->BractVertexSuperset, localToGlobalIdRelabeler);
this->Mesh
->template GetGlobalIdsFromMeshIndices<vtkm::worklet::contourtree_augmented::IdArrayType>(
this->BractVertexSuperset, localToGlobalIdRelabeler);
auto setInteriorForestWorklet =
vtkm::worklet::contourtree_distributed::bract_maker::SetInteriorForestWorklet();
// NOTE: We don't need this->BractVertexSuperset as input since meshGlobalIds is already transformed accordingly

@ -989,11 +989,25 @@ void TreeGrafter<MeshType, FieldType>::ListNewNodes(
this->ContourTree.Nodes.GetNumberOfValues()),
this->HierarchicalTreeId);
// B. Set the ID correctly for every vertex in the BRACT
// We know by assumption that they are all in the hierarchical tree
// Convert the mesh ids from this->InteriorForest-BractMeshIndices to global mesh indices
auto globalIdsForBractMeshIndices = this->Mesh->GetGlobalIdsFromMeshIndices(
this->InteriorForest->BractMeshIndices, localToGlobalIdRelabeler);
// B. Set the ID correctly for every regular node
// They will not all be in the hierarchical tree, so NO_SUCH_ELEMENT will occur, but that is
// what we want in this case. It also means we don't have to set it to NO_SUCH_ELEMENT in section
// A., but paranoia indicates we leave that in
// This section implements:
// for (indexType vertex = 0; vertex < contourTree->nodes.size(); vertex++)
// { // per vertex in the bract
// // now convert to a global index
// indexType globalID = mesh->GetGlobalIDFromMeshIndex(vertex);
//
// // look that one up and store the result (NO_SUCH_ELEMENT is acceptable, but should never occur)
// hierarchicalTreeID[vertex] = hierarchicalTree.FindRegularByGlobal(globalID);
// } // per vertex in the bract
// Convert the mesh ids for the contourtree nodes to global ids. This will also be our
// main field array for the worklet
auto globalIdsForBractMeshIndices =
this->Mesh->template GetGlobalIdsFromMeshIndices<vtkm::cont::ArrayHandleIndex>(
vtkm::cont::ArrayHandleIndex(this->ContourTree.Nodes.GetNumberOfValues()),
localToGlobalIdRelabeler);
// Get a FindRegularByGlobal execution object that we can use as an input for worklets to call the function
auto findRegularByGlobal = hierarchicalTree.GetFindRegularByGlobal();
// look up our gloabl ids (NO_SUCH_ELEMENT is acceptable, but should never occur) and
@ -1002,9 +1016,8 @@ void TreeGrafter<MeshType, FieldType>::ListNewNodes(
auto listNewNodesCopyIdsWorklet =
vtkm::worklet::contourtree_distributed::tree_grafter::ListNewNodesCopyIdsWorklet();
this->Invoke(listNewNodesCopyIdsWorklet,
this->InteriorForest->BractMeshIndices, // input mesh index
globalIdsForBractMeshIndices, // input global indices
findRegularByGlobal, // input object to call FindRegularByGlobal
globalIdsForBractMeshIndices, // input global indices
findRegularByGlobal, // input object to call FindRegularByGlobal
this->HierarchicalTreeId);
// C. Start with the list of all nodes in the non-hierarchical tree
@ -1250,8 +1263,10 @@ void TreeGrafter<MeshType, FieldType>::CopyNewNodes(
totalNNodes,
vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT);
// TODO: The original code created a separate array newNodesGloablId that was set to NO_SUCH_ELEMENT first but we should only need the fancy array here and save the memory
auto newNodesGloablId = this->Mesh->GetGlobalIdsFromMeshIndices(
this->NewNodes, localToGlobalIdRelabeler); // this is a fancy array
auto newNodesGloablId =
this->Mesh
->template GetGlobalIdsFromMeshIndices<vtkm::worklet::contourtree_augmented::IdArrayType>(
this->NewNodes, localToGlobalIdRelabeler); // this is a fancy array
vtkm::cont::Algorithm::CopySubRange(
newNodesGloablId, // array to copy
0, // start index

@ -70,14 +70,13 @@ class ListNewNodesCopyIdsWorklet : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(
FieldIn interiorForestBractMeshIndices, // input mesh ids
FieldIn globalIdsForBractMeshIndices, // input iteration index.
ExecObject findRegularByGlobal, // input to findRegularByGlobal
FieldIn globalIdsForBractMeshIndices, // input iteration index.
ExecObject findRegularByGlobal, // input to findRegularByGlobal
WholeArrayOut
hierarchicalTreeId // output (need WholeArrayOut because globalIdsForBractMeshIndices is 1 smaller and need to avoid false resize
);
using ExecutionSignature = void(_1, _2, _3, _4);
using ExecutionSignature = void(InputIndex, _1, _2, _3);
using InputDomain = _1;
// Default Constructor
@ -85,27 +84,25 @@ public:
ListNewNodesCopyIdsWorklet() {}
template <typename ExecObjectType, typename OutFieldPortalType>
VTKM_EXEC void operator()(const vtkm::Id& meshId,
VTKM_EXEC void operator()(const vtkm::Id& vertex,
const vtkm::Id& globalId,
const ExecObjectType& findRegularByGlobal,
const OutFieldPortalType& hierarchicalTreeIdPortal) const
{ // operator ()
// the lookup to mesh->GetGlobalIDFromMeshIndex is done outside the worklet
// for all mesh ids so all we need to do here is call FindRegularByGlobal
hierarchicalTreeIdPortal.Set(meshId, findRegularByGlobal.FindRegularByGlobal(globalId));
hierarchicalTreeIdPortal.Set(vertex, findRegularByGlobal.FindRegularByGlobal(globalId));
// In serial this worklet implements the following operation
/*
for (indexType bractVertex = 0; bractVertex < residue->bractMeshIndices.size(); bractVertex++)
{ // per vertex in the bract
// retrieve mesh ID
indexType meshID = residue->bractMeshIndices[bractVertex];
for (indexType vertex = 0; vertex < contourTree->nodes.size(); vertex++)
{ // per vertex in the bract
// now convert to a global index
indexType globalID = mesh->GetGlobalIDFromMeshIndex(vertex);
// now convert to a global index
indexType globalID = mesh->GetGlobalIDFromMeshIndex(meshID);
// look that one up and store the result (NO_SUCH_ELEMENT is acceptable, but should never occur)
hierarchicalTreeID[meshID] = hierarchicalTree.FindRegularByGlobal(globalID);
} // per vertex in the bract
// look that one up and store the result (NO_SUCH_ELEMENT is acceptable, but should never occur)
hierarchicalTreeID[vertex] = hierarchicalTree.FindRegularByGlobal(globalID);
} // per vertex in the bract
*/
} // operator ()