Fix errors in HierarchicalAugmenter

Fix CreateSuperarcsWorklet. Use standard copy to reduce complexity of CreateSuperarcsWorklet.
Fix compile errors in HierarchicalAugmenter.
Some more clean-up and optimization for HierarchicalAugmenter.CreateSuperarcsWorklet.
This commit is contained in:
Oliver Ruebel 2021-05-24 16:33:35 -07:00 committed by Gunther H. Weber
parent c6ff4a5f09
commit 35a14f3129
2 changed files with 263 additions and 209 deletions

@ -342,14 +342,18 @@ void HierarchicalAugmenter<FieldType>::PrepareOutAttachmentPoints(vtkm::Id round
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
IsAttachementPointNeededPredicate isAttachementPointNeededPredicate(
this->SuperparentRounds, this->WhichRounds, round);
auto tempAttachmentPointsIndex =
vtkm::cont::ArrayHandleIndex(this->GlobalRegularIds.GetNumberOfValues());
vtkm::cont::Algorithm::CopyIf(
// 1. generate a list of all of the attachment points
vtkm::cont::ArrayHandleIndex(this - GlobalRegularIds.GetNumberOfValues()),
// 2. then our stencil identifies all attachment points needed
isAttachementPointNeededPredicate,
// 3. And the CopyIf compress the supernodes array to eliminate the non-attachement points and
// save to this->AttachmentIds
this->AttachmentIds);
// 1. fancy array of all of the attachment points of which parts are copied to this->AttachmentIds
tempAttachmentPointsIndex, // input
// 2. stencil used with the predicate to decide which AttachementIds to keep
tempAttachmentPointsIndex, // stencil
// 3. CopyIf compress the supernodes array to eliminate the non-attachement
// points and save to this->AttachmentIds
this->AttachmentIds,
// 4. the unary predicate uses the stencil to identify all attachment points needed
isAttachementPointNeededPredicate);
}
// 4. resize the out array
@ -369,19 +373,19 @@ void HierarchicalAugmenter<FieldType>::PrepareOutAttachmentPoints(vtkm::Id round
// outDataValues[outAttachmentPoint] = dataValues[attachmentPoint];
vtkm::cont::Algorithm::Copy(
vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->DataValues),
this->outDataValues);
this->OutDataValues);
// outSupernodeIDs[outAttachmentPoint] = supernodeIDs[attachmentPoint];
vtkm::cont::Algorithm::Copy(
vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->SupernodeIds),
this->OutSupernodeIds);
// outSuperparents[outAttachmentPoint] = superparents[attachmentPoint];
vtkm::cont::Algorithm::Copy(
vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->superparents),
this->outSuperparents);
vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->Superparents),
this->OutSuperparents);
// outSuperparentRounds[outAttachmentPoint] = superparentRounds[attachmentPoint];
vtkm::cont::Algorithm::Copy(
vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->SuperparentRounds),
this->outSuperparentRounds);
this->OutSuperparentRounds);
// outWhichRounds[outAttachmentPoint] = whichRounds[attachmentPoint];
vtkm::cont::Algorithm::Copy(
vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->WhichRounds),
@ -405,9 +409,9 @@ void HierarchicalAugmenter<FieldType>::RetrieveInAttachmentPoints(HierarchicalAu
vtkm::Id numTotalAttachments = numAttachmentsCurrently + numIncomingAttachments;
// I. resize the existing arrays
this->GlobalRegularIDs.Allocate(numTotalAttachments);
this->GlobalRegularIds.Allocate(numTotalAttachments);
this->DataValues.Allocate(numTotalAttachments);
this->SupernodeIDs.Allocate(numTotalAttachments);
this->SupernodeIds.Allocate(numTotalAttachments);
this->Superparents.Allocate(numTotalAttachments);
this->SuperparentRounds.Allocate(numTotalAttachments);
this->WhichRounds.Allocate(numTotalAttachments);
@ -417,36 +421,31 @@ void HierarchicalAugmenter<FieldType>::RetrieveInAttachmentPoints(HierarchicalAu
// The following sequence of copy operations implements the following for from the orginal code
// for (vtkm::Id outAttachmentPoint = 0; outAttachmentPoint < partner.outGlobalRegularIDs.size(); outAttachmentPoint++)
// globalRegularIDs[attachmentPoint] = partner.outGlobalRegularIDs[outAttachmentPoint];
vtkm::cont::Algorithm::Copy(partner.OutGlobalRegularIds,
vtkm::cont::make_ArrayHandleView(this->GlobalRegularIds,
numAttachmentsCurrently,
numIncomingAttachments));
auto tempGlobalRegularIdsView = vtkm::cont::make_ArrayHandleView(
this->GlobalRegularIds, numAttachmentsCurrently, numIncomingAttachments);
vtkm::cont::Algorithm::Copy(partner.OutGlobalRegularIds, tempGlobalRegularIdsView);
// dataValues[attachmentPoint] = partner.outDataValues[outAttachmentPoint];
vtkm::cont::Algorithm::Copy(partner.OutDataValues,
vtkm::cont::make_ArrayHandleView(this->DataValues,
numAttachmentsCurrently,
numIncomingAttachments));
auto tempDataValuesView = vtkm::cont::make_ArrayHandleView(
this->DataValues, numAttachmentsCurrently, numIncomingAttachments);
vtkm::cont::Algorithm::Copy(partner.OutDataValues, tempDataValuesView);
// supernodeIDs[attachmentPoint] = NO_SUCH_ELEMENT;
vtkm::cont::Algorithm::Copy(
vtkm::cont::make_ArrayHandleConstant(vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT,
numIncomingAttachments),
vtkm::cont::make_ArrayHandleView(
this->SupernodeIds, numAttachmentsCurrently, numIncomingAttachments));
auto tempNoSuchElementArr = vtkm::cont::make_ArrayHandleConstant(
vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT, numIncomingAttachments);
auto tempSupernodeIdsView = vtkm::cont::make_ArrayHandleView(
this->SupernodeIds, numAttachmentsCurrently, numIncomingAttachments);
vtkm::cont::Algorithm::Copy(tempNoSuchElementArr, tempSupernodeIdsView);
// superparents[attachmentPoint] = partner.outSuperparents[outAttachmentPoint];
vtkm::cont::Algorithm::Copy(partner.outSuperparents,
vtkm::cont::make_ArrayHandleView(this->Superparents,
numAttachmentsCurrently,
numIncomingAttachments));
auto tempSuperparentsView = vtkm::cont::make_ArrayHandleView(
this->Superparents, numAttachmentsCurrently, numIncomingAttachments);
vtkm::cont::Algorithm::Copy(partner.OutSuperparents, tempSuperparentsView);
// superparentRounds[attachmentPoint] = partner.outSuperparentRounds[outAttachmentPoint];
vtkm::cont::Algorithm::Copy(partner.outSuperparentRounds,
vtkm::cont::make_ArrayHandleView(this->SuperparentRounds,
numAttachmentsCurrently,
numIncomingAttachments));
auto tempSuperparentRoundsView = vtkm::cont::make_ArrayHandleView(
this->SuperparentRounds, numAttachmentsCurrently, numIncomingAttachments);
vtkm::cont::Algorithm::Copy(partner.OutSuperparentRounds, tempSuperparentRoundsView);
// whichRounds[attachmentPoint] = partner.outWhichRounds[outAttachmentPoint];
vtkm::cont::Algorithm::Copy(partner.OutWhichRounds,
vtkm::cont::make_ArrayHandleView(this->WhichRounds,
numAttachmentsCurrently,
numIncomingAttachments));
auto tempWhichRoundsView = vtkm::cont::make_ArrayHandleView(
this->WhichRounds, numAttachmentsCurrently, numIncomingAttachments);
vtkm::cont::Algorithm::Copy(partner.OutWhichRounds, tempWhichRoundsView);
}
} // RetrieveInAttachmentPoints()
@ -455,9 +454,9 @@ void HierarchicalAugmenter<FieldType>::RetrieveInAttachmentPoints(HierarchicalAu
template <typename FieldType>
void HierarchicalAugmenter<FieldType>::ReleaseOutArrays()
{ // ReleaseOutArrays()
this->OutGlobalRegularIDs.ReleaseResources();
this->OutGlobalRegularIds.ReleaseResources();
this->OutDataValues.ReleaseResources();
this->OutSupernodeIDs.ReleaseResources();
this->OutSupernodeIds.ReleaseResources();
this->OutSuperparents.ReleaseResources();
this->OutSuperparentRounds.ReleaseResources();
this->OutWhichRounds.ReleaseResources();
@ -1110,52 +1109,136 @@ void HierarchicalAugmenter<FieldType>::ResizeArrays(vtkm::Id roundNumber)
template <typename FieldType>
void HierarchicalAugmenter<FieldType>::CreateSuperarcs(vtkm::Id roundNumber)
{ // CreateSuperarcs()
// retrieve the ID number of the first supernode at this leverl
// retrieve the ID number of the first supernode at this level
vtkm::Id numSupernodesAlready =
vtkm::cont::ArrayGetValue(0, this->AugmentedTree->FirstSupernodePerIteration[roundNumber]);
// e. Connect superarcs for the level & set hyperparents & superchildren count, whichRound, whichIteration, super2hypernode
{
// TODO: The CreateSuperarcsWorklet uses a lot of arrays and lots of WholeArrayTransfers. This could probably be further optimized.
// TODO: FIX invokation of this worklet
throw std::logic_error("Invocation of CreateSuperarcsWorklet currently broken");
/*
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::CreateSuperarcsWorklet
createSuperarcsWorklet(
numSupernodesAlready,
this->BaseTree->NumRounds,
vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations),
roundNumber);
this->Invoke(
createSuperarcsWorklet, // the worklet
this->SupernodeSorter, // input domain (we need access to InputIndex and InputIndex+1)
this->SuperparentSet, // input
this->BaseTree->Superarcs, // input
this->NewSupernodeIds, // input
this->BaseTree->Hyperparents, // input
this->BaseTree->Supernodes, // input
this->BaseTree->RegularNodeGlobalIds, // input
this->GlobalRegularIdSet, // input
this->BaseTree->Super2Hypernode, // input
this->BaseTree->WhichRound, // input
this->BaseTree->WhichIteration, // input
this->DataValueSet, // input
vtkm::cont::make_ArrayHandleView(
this->AugmentedTree->Superarcs,
{ // START scope for e. to delete temporary variables
// Note: The original PPP algorithm performed all operations listed in this block
// in a single parralel for loop. Many of those operations were smart array
// copies. So to simplfy the worklet and to make more effective use of
// VTKm algorithm, a large number of copy operations have been extracted from
// the loop and are performed here via combinations of fancy array handles and
// vtkm::cont::Algorithm::Copy operations.
// Define the new supernode and regular Id. Both are actually the same here since we are
// augmenting the tree here, but for clarity we define them as separate variables.
// At all levels above 0, we used to keep regular vertices in case
// they are attachment points. After augmentation, we don't need to.
// Instead, at all levels above 0, the regular nodes in each round
// are identical to the supernodes. In order to avoid confusion,
// we will copy the Id into a separate variable
vtkm::cont::ArrayHandleCounting<vtkm::Id> newSupernodeId(
numSupernodesAlready, // start
static_cast<vtkm::Id>(1), // step
this->SupernodeSorter.GetNumberOfValues() // number of values
);
auto newRegularId = newSupernodeId;
// define the superparentOldSuperId
auto permutedSuperparentSet =
vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SuperparentSet);
auto superparentOldSuperId = vtkm::cont::make_ArrayHandleTransform(
permutedSuperparentSet, vtkm::worklet::contourtree_augmented::MaskedIndexFunctor<vtkm::Id>());
// set the supernode's regular Id. Set: augmentedTree->supernodes[newSupernodeID] = newRegularID;
auto permutedAugmentedTreeSupernodes =
vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->Supernodes);
vtkm::cont::Algorithm::Copy(newRegularId, permutedAugmentedTreeSupernodes);
// Run the worklet for more complex operations
{ // START block for CreateSuperarcsWorklet
// create the worklet
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::CreateSuperarcsWorklet
createSuperarcsWorklet(
numSupernodesAlready,
this->SupernodeSorter.GetNumberOfValues()), // output
this->AugmentedTree->Hyperparents, // input/output
this->AugmentedTree->FirstSupernodePerIteration[roundNumber], // input/output
this->AugmentedTree->Supernodes, // input/output
this->AugmentedTree->Super2Hypernode, // input/ouput
this->AugmentedTree->WhichRound, // input/ouput
this->AugmentedTree->WhichIteration, // input/ouput
this->AugmentedTree->RegularNodeGlobalIds, //input/ ouput
this->AugmentedTree->DataValues, // input/ouput
this->AugmentedTree->Regular2Supernode, // input/ouput
this->AugmentedTree->Superparents // input/ouput
);*/
}
this->BaseTree->NumRounds,
vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations),
roundNumber,
this->AugmentedTree->Supernodes.GetNumberOfValues());
// create fancy arrays needed to allow use of FieldIn for worklet parameters
auto permutedGlobalRegularIdSet =
vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet);
auto augmentedTreeSuperarcsView =
vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Superarcs,
numSupernodesAlready,
this->SupernodeSorter.GetNumberOfValues());
auto augmentedTreeSuper2HypernodeView =
vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Super2Hypernode,
numSupernodesAlready,
this->SupernodeSorter.GetNumberOfValues());
// invoke the worklet
this->Invoke(createSuperarcsWorklet, // the worklet
this->SupernodeSorter, // input domain
this->SuperparentSet, // input
this->BaseTree->Superarcs, // input
this->NewSupernodeIds, // input
this->BaseTree->Supernodes, // input
this->BaseTree->RegularNodeGlobalIds, // input
permutedGlobalRegularIdSet, // input
this->BaseTree->Super2Hypernode, // input
this->BaseTree->WhichIteration, // input
augmentedTreeSuperarcsView, // output
this->AugmentedTree->FirstSupernodePerIteration[roundNumber], // input/output
augmentedTreeSuper2HypernodeView // output
);
} // END block for CreateSuperarcsWorklet
// setting the hyperparent is straightforward since the hyperstructure is preserved
// we take the superparent (which is guaranteed to be in the baseTree), find it's hyperparent and use that
// Set: augmentedTree->hyperparents[newSupernodeID] = baseTree->hyperparents[superparentOldSuperID];
auto permutedAugmentedTreeHyperparents =
vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->Hyperparents);
auto permutedBaseTreeHyperparents =
vtkm::cont::make_ArrayHandlePermutation(superparentOldSuperId, this->BaseTree->Hyperparents);
vtkm::cont::Algorithm::Copy(permutedBaseTreeHyperparents, permutedAugmentedTreeHyperparents);
// which round and iteration carry over
// Set: augmentedTree->whichRound[newSupernodeID] = baseTree->whichRound[superparentOldSuperID];
auto permutedAugmentedTreeWhichRound =
vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->WhichRound);
auto permutedBaseTreeWhichRound =
vtkm::cont::make_ArrayHandlePermutation(superparentOldSuperId, this->BaseTree->WhichRound);
vtkm::cont::Algorithm::Copy(permutedBaseTreeWhichRound, permutedAugmentedTreeWhichRound);
// Set: augmentedTree->whichIteration[newSupernodeID] = baseTree->whichIteration[superparentOldSuperID];
auto permutedAugmentedTreeWhichIteration =
vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->WhichIteration);
auto permutedBaseTreeWhichIterationPortal = vtkm::cont::make_ArrayHandlePermutation(
superparentOldSuperId, this->BaseTree->WhichIteration);
vtkm::cont::Algorithm::Copy(permutedBaseTreeWhichIterationPortal,
permutedAugmentedTreeWhichIteration);
// now we deal with the regular-sized arrays. In the following supernodeSetIndex is simply supernodeSorterPortal.Get(supernode);
// copy the global regular Id and data value
// Set: augmentedTree->regularNodeGlobalIDs[newRegularID] = globalRegularIDSet[supernodeSetIndex];
auto permutedAugmentedTreeRegularNodeGlobalIds = vtkm::cont::make_ArrayHandlePermutation(
newRegularId, this->AugmentedTree->RegularNodeGlobalIds);
auto permutedGlobalRegularIdSet =
vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet);
vtkm::cont::Algorithm::Copy(permutedGlobalRegularIdSet,
permutedAugmentedTreeRegularNodeGlobalIds);
// SetL augmentedTree->dataValues[newRegularID] = dataValueSet[supernodeSetIndex];
auto permutedAugmentedTreeDataValues =
vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->DataValues);
auto permutedDataValueSet =
vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->DataValueSet);
vtkm::cont::Algorithm::Copy(permutedDataValueSet, permutedAugmentedTreeDataValues);
// the sort order will be dealt with later
// since all of these nodes are supernodes, they will be their own superparent, which means that:
// a. the regular2node can be set immediately
// Set: augmentedTree->regular2supernode[newRegularID] = newSupernodeID;
auto permutedAugmentedTreeRegular2Supernode =
vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->Regular2Supernode);
vtkm::cont::Algorithm::Copy(newSupernodeId, permutedAugmentedTreeRegular2Supernode);
// b. as can the superparent
// Set: augmentedTree->superparents[newRegularID] = newSupernodeID;
auto permutedAugmentedTreeSuperparents =
vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->Superparents);
vtkm::cont::Algorithm::Copy(newSupernodeId, permutedAugmentedTreeSuperparents);
} // END scope for e. to delete temporary variables
// We have one last bit of cleanup to do. If there were attachment points, then the round in which they transfer has been removed
// While it is possible to turn this into a null round, it is better to reduce the iteration count by one and resize the arrays

@ -64,148 +64,115 @@ namespace hierarchical_augmenter
class CreateSuperarcsWorklet : public vtkm::worklet::WorkletMapField
{
public:
// VTKm only defines 20 placeholders for the execution signature, but we need a few more here
using _21 = vtkm::placeholders::Arg<21>;
using _22 = vtkm::placeholders::Arg<22>;
using _23 = vtkm::placeholders::Arg<23>;
// TODO: Check if augmentedTreeFirstSupernodePerIteration could be changed to WholeArrayOut or if we need the In to preserve orignal values
// TODO: This worklet could probably be optimized further to reduce the use of WholeArray passing
/// Control signature for the worklet
/// @param[in] supernodeSorter input domain. We need access to InputIndex and InputIndex+1,
/// therefore this is a WholeArrayIn transfer.
/// @param[in] superparentSet WholeArrayIn because we need access to superparentSet[supernodeSorter[InputIndex]]
/// and superparentSet[supernodeSorter[InputIndex+1]].
/// @param[in] baseTreeSuperarcs WholeArrayIn because we need access to baseTreeSuperarcsPortal.Get(superparentOldSuperId)
/// While this could be done with fancy array magic, it would require a sequence of multiple
/// fancy arrays and would likely not be cheaper then computing things in the worklet.
/// @param[in] newSupernodeIds WholeArrayIn because we need to access newSupernodeIdsPortal.Get(oldTargetSuperId)
/// where oldTargetSuperId is the unmasked baseTreeSuperarcsPortal.Get(superparentOldSuperId)
/// @param[in] baseTreeSupernodes WholeArrayIn because we need to access baseTreeSupernodesPortal.Get(superparentOldSuperId);
/// @param[in] baseTreeRegularNodeGlobalIds WholeArrayIn because we need to access
/// baseTreeRegularNodeGlobalIdsPortal.Get(superparentOldSuperId);
/// @param[in] globalRegularIdSet FieldInd. Permute globalRegularIdSet with supernodeSorter in order to allow this to be a FieldIn.
/// @param[in] baseTreeSuper2Hypernode WholeArrayIn because we need to access
/// baseTreeSuper2HypernodePortal.Get(superparentOldSuperId)
/// @param[in] baseTreeWhichIteration WholeArrayIn because we need to access baseTreeWhichIterationPortal.Get(superparentOldSuperId)
/// and baseTreeWhichIterationPortal.Get(superparentOldSuperId+1)
/// @param[in] augmentedTreeSuperarcsView output view of this->AugmentedTree->Superarcs with
/// vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Superarcs,
/// numSupernodesAlready, this->SupernodeSorter.GetNumberOfValues()).
/// By using this view allows us to do this one as a FieldOut and it effectively the
/// same as accessing the array at the newSuppernodeId location.
/// @param[in] augmentedTreeFirstSupernodePerIteration WholeArrayInOut because we need to update multiple locations.
/// In is used to preseve original values. Set to augmentedTree->firstSupernodePerIteration[roundNumber].
/// @param[in] augmentedTreeSuper2hypernode FieldOut. Output view of this->AugmentedTree->Super2Hypernode
/// vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Super2Hypernode,
/// numSupernodesAlready, this->SupernodeSorter.GetNumberOfValues()).
/// By using this view allows us to do this one as a FieldOut and it effectively the
/// same as accessing the array at the newSuppernodeId location.
using ControlSignature = void(
WholeArrayIn supernodeSorter, // input domain (we need access to InputIndex and InputIndex+1)
WholeArrayIn superparentSet, // input
WholeArrayIn baseTreeSuperarcs, // input
WholeArrayIn newSupernodeIds, // input
WholeArrayIn
baseTreeHyperparents, // input TODO: could potentially be a FieldIn with some array shuffle magic
WholeArrayIn
baseTreeSupernodes, // input TODO: could potentially be a FieldIn with some array shuffle magic
WholeArrayIn
baseTreeRegularNodeGlobalIds, // input TODO: could potentially be a FieldIn with some array shuffle magic
WholeArrayIn
globalRegularIdSet, // input TODO: could potentially be a FieldIn with some array shuffle magic
WholeArrayIn baseTreeSuper2Hypernode, // input TODO: FieldIn possible with array shuffle?
WholeArrayIn baseTreeWhichRound, // input TODO: FieldIn possible with array shuffle?
WholeArrayIn baseTreeWhichIteration, // input TODO: FieldIn possible with array shuffle?
WholeArrayIn dataValueSet, // input TODO: FieldIn possible with array shuffle?
FieldOut
augmentedTreeSuperarcsView, // output view of ArrayHandleView(this->AugmentedTree->Superarcs[, this->NumSupernodesAlready, this->SupernodeSorter.GetNumberOfValues())
WholeArrayInOut augmentedTreeHyperparents, // input/output
WholeArrayInOut
augmentedTreeFirstSupernodePerIteration, // input/output augmentedTree->firstSupernodePerIteration[roundNumber]
WholeArrayInOut
augmentedTreeSupernodes, // input/output TODO: Could potentially change to FieldIn/FieldInOut when permutting the array
WholeArrayInOut
augmentedTreeSuper2hypernode, // input/ouput TODO: Is FieldOut possible with array shuffle?
WholeArrayInOut
augmentedTreeWhichRound, // input/ouput TODO: Is FieldOut possible with array shuffle?
WholeArrayInOut
augmentedTreeWhichIteration, // input/ouput TODO: Is FieldOut possible with array shuffle?
WholeArrayInOut
augmentedTreeRegularNodeGlobalIds, // input/ouput TODO: Is FieldOut possible with array shuffle?
WholeArrayInOut
augmentedTreeDataValues, // input/ouput TODO: Is FieldOut possible with array shuffle?
WholeArrayInOut
augmentedTreeRegular2Supernode, // input/ouput TODO: Is FieldOut possible with array shuffle?
WholeArrayInOut
augmentedTreeSuperparents // input/ouput TODO: Is FieldOut possible with array shuffle?
WholeArrayIn supernodeSorter,
WholeArrayIn superparentSet, // input
WholeArrayIn baseTreeSuperarcs, // input
WholeArrayIn newSupernodeIds, // input
WholeArrayIn baseTreeSupernodes, // input
WholeArrayIn baseTreeRegularNodeGlobalIds, // input
FieldIn globalRegularIdSet, // input
WholeArrayIn baseTreeSuper2Hypernode, // input
WholeArrayIn baseTreeWhichIteration, // input
FieldOut augmentedTreeSuperarcsView, // output
WholeArrayInOut augmentedTreeFirstSupernodePerIteration, // input/output
FieldOut augmentedTreeSuper2hypernode // ouput
);
using ExecutionSignature = void(InputIndex,
_1,
_2,
_3,
_4,
_5,
_6,
_7,
_8,
_9,
_10,
_11,
_12,
_13,
_14,
_15,
_16,
_17,
_18,
_19,
_20,
_21,
_22,
_23);
using ExecutionSignature = void(InputIndex, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12);
using InputDomain = _1;
/// Default Constructor
/// @param[in] numSupernodesAlready Set to vtkm::cont::ArrayGetValue(0, this->AugmentedTree->FirstSupernodePerIteration[roundNumber]);
/// @param[in] baseTreeNumRounds Set to this->BaseTree->NumRounds
/// @param[in] augmentedTreeNumIterations Set to vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations);
/// @param[in] roundNumber Set the current round
/// @param[in] numAugmentedTreeSupernodes Set to augmentedTreeSupernodes this->AugmentedTree->Supernodes.GetNumberOfValues();
VTKM_EXEC_CONT
CreateSuperarcsWorklet(
const vtkm::Id& numSupernodesAlready,
const vtkm::Id& baseTreeNumRounds,
const vtkm::Id&
augmentedTreeNumIterations, // set to vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations)
const vtkm::Id& roundNumber)
CreateSuperarcsWorklet(const vtkm::Id& numSupernodesAlready,
const vtkm::Id& baseTreeNumRounds,
const vtkm::Id& augmentedTreeNumIterations,
const vtkm::Id& roundNumber,
const vtkm::Id& numAugmentedTreeSupernodes)
: NumSupernodesAlready(numSupernodesAlready)
, BaseTreeNumRounds(baseTreeNumRounds)
, AugmentedTreeNumIterations(augmentedTreeNumIterations)
, RoundNumber(roundNumber)
, NumAugmentedTreeSupernodes(numAugmentedTreeSupernodes)
{
}
/// operator() of the workelt
template <typename InFieldPortalType,
typename InFieldPortalType2,
typename InOutFieldPortalType,
typename InOutFieldPortalType2>
template <typename InFieldPortalType, typename InOutFieldPortalType>
VTKM_EXEC void operator()(
const vtkm::Id& supernode, // InputIndex of supernodeSorter
const InFieldPortalType& supernodeSorterPortal,
const InFieldPortalType& superparentSetPortal,
const InFieldPortalType& baseTreeSuperarcsPortal,
const InFieldPortalType& newSupernodeIdsPortal,
const InFieldPortalType& baseTreeHyperparentsPortal,
const InFieldPortalType& baseTreeSupernodesPortal,
const InFieldPortalType& baseTreeRegularNodeGlobalIdsPortal,
const InFieldPortalType& globalRegularIdSetPortal,
const InFieldPortalType& baseTreeSuper2hypernodePortal,
const InFieldPortalType& baseTreeWhichRoundPortal,
const vtkm::Id& globalRegularIdSetValue,
const InFieldPortalType& baseTreeSuper2HypernodePortal,
const InFieldPortalType& baseTreeWhichIterationPortal,
const InFieldPortalType2& dataValueSetPortal,
vtkm::Id& augmentedTreeSuperarcsValue, // same as augmentedTree->superarcs[newSupernodeId]
const InOutFieldPortalType& augmentedTreeHyperparentsPortal,
const InOutFieldPortalType&
augmentedTreeFirstSupernodePerIterationPortal, // augmentedTree->firstSupernodePerIteration[roundNumber]
const InOutFieldPortalType& augmentedTreeSupernodesPortal,
const InOutFieldPortalType& augmentedTreeSuper2hypernodePortal,
const InOutFieldPortalType& augmentedTreeWhichRoundPortal,
const InOutFieldPortalType& augmentedTreeWhichIterationPortal,
const InOutFieldPortalType& augmentedTreeRegularNodeGlobalIdsPortal,
const InOutFieldPortalType2& augmentedTreeDataValuesPortal,
const InOutFieldPortalType& augmentedTreeRegular2SupernodePortal,
const InOutFieldPortalType& augmentedTreeSuperparentsPortal) const
vtkm::Id& augmentedTreeSuper2hypernodeValue) const
{
// per supernode in the set
// retrieve the index from the sorting index array
vtkm::Id supernodeSetIndex = supernodeSorterPortal.Get(supernode);
// work out the new supernode Id
// work out the new supernode Id. We have this defined on the outside as a fancy array handle,
// however, using the fancy handle here would not really make a performance differnce and
// computing it here is more readable
vtkm::Id newSupernodeId = this->NumSupernodesAlready + supernode;
// At all levels above 0, we used to keep regular vertices in case
// they are attachment points. After augmentation, we don't need to.
// Instead, at all levels above 0, the regular nodes in each round
// are identical to the supernodes. In order to avoid confusion,
// we will copy the Id into a separate variable
vtkm::Id newRegularId = newSupernodeId;
// NOTE: The newRegularId is no longer needed here since all parts
// that used it in the worklet have been moved outside
// vtkm::Id newRegularId = newSupernodeId;
// setting the supernode's regular Id is now trivial
augmentedTreeSupernodesPortal.Set(newSupernodeId, newRegularId);
// NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs
// // setting the supernode's regular Id is now trivial
// augmentedTreeSupernodesPortal.Set(newSupernodeId, newRegularId);
// retrieve the ascending flag from the superparent
vtkm::Id superparentSetVal = superparentSetPortal.Get(supernodeSetIndex);
// get the ascending flag from the parent
bool superarcAscends = vtkm::worklet::contourtree_augmented::IsAscending(superparentSetVal);
// strip the ascending flag from the superparent
// strip the ascending flag from the superparent.
vtkm::Id superparentOldSuperId =
vtkm::worklet::contourtree_augmented::MaskedIndex(superparentSetVal);
@ -234,8 +201,8 @@ public:
(superarcAscends ? vtkm::worklet::contourtree_augmented::IS_ASCENDING : 0x00);
} // not the tree root
// since there's an extra entry in the firstSupernode array as a sentinel, set it
augmentedTreeFirstSupernodePerIterationPortal.Set(
this->AugmentedTreeNumIterations, augmentedTreeSupernodesPortal.GetNumberOfValues());
augmentedTreeFirstSupernodePerIterationPortal.Set(this->AugmentedTreeNumIterations,
NumAugmentedTreeSupernodes);
} // last in the array
else if (superparentOldSuperId !=
vtkm::worklet::contourtree_augmented::MaskedIndex(
@ -273,47 +240,50 @@ public:
// set the first supernode in the first iteration to the beginning of the round
augmentedTreeFirstSupernodePerIterationPortal.Set(0, this->NumSupernodesAlready);
// setting the hyperparent is straightforward since the hyperstructure is preserved
// we take the superparent (which is guaranteed to be in the baseTree), find it's hyperparent and use that
augmentedTreeHyperparentsPortal.Set(newSupernodeId,
baseTreeHyperparentsPortal.Get(superparentOldSuperId));
// NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs
// // setting the hyperparent is straightforward since the hyperstructure is preserved
// // we take the superparent (which is guaranteed to be in the baseTree), find it's hyperparent and use that
// augmentedTreeHyperparentsPortal.Set(newSupernodeId, baseTreeHyperparentsPortal.Get(superparentOldSuperId));
// NOTE: This part could potentially be made a separate worklet but it does not seem necessary
// similarly, the super2hypernode should carry over, but it's harder to test because of the attachment points which
// do not have valid old supernode Ids. Instead, we check their superparent's regular global Id against them: if it
// matches, then it must be the start of the superarc, in which case it does have an old Id, and we can then use the
// existing hypernode Id
vtkm::Id superparentOldRegularId = baseTreeSupernodesPortal.Get(superparentOldSuperId);
vtkm::Id superparentGlobalId = baseTreeRegularNodeGlobalIdsPortal.Get(superparentOldRegularId);
if (superparentGlobalId == globalRegularIdSetPortal.Get(supernodeSetIndex))
// Here: globalRegularIdSetValue is the same as globalRegularIdSetPortal.Get(supernodeSetIndex)
if (superparentGlobalId == globalRegularIdSetValue)
{
augmentedTreeSuper2hypernodePortal.Set(
newSupernodeId, baseTreeSuper2hypernodePortal.Get(superparentOldSuperId));
// augmentedTreeSuper2hypernodePortal.Set(newSupernodeId, baseTreeSuper2HypernodePortal.Get(superparentOldSuperId));
augmentedTreeSuper2hypernodeValue = baseTreeSuper2HypernodePortal.Get(superparentOldSuperId);
}
else
{
augmentedTreeSuper2hypernodePortal.Set(newSupernodeId,
vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT);
// augmentedTreeSuper2hypernodePortal.Set(newSupernodeId, vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT);
augmentedTreeSuper2hypernodeValue = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
}
// which round and iteration carry over
augmentedTreeWhichRoundPortal.Set(newSupernodeId,
baseTreeWhichRoundPortal.Get(superparentOldSuperId));
augmentedTreeWhichIterationPortal.Set(newSupernodeId,
baseTreeWhichIterationPortal.Get(superparentOldSuperId));
// NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs
// // which round and iteration carry over
// augmentedTreeWhichRoundPortal.Set(newSupernodeId, baseTreeWhichRoundPortal.Get(superparentOldSuperId));
// augmentedTreeWhichIterationPortal.Set(newSupernodeId, baseTreeWhichIterationPortal.Get(superparentOldSuperId));
// now we deal with the regular-sized arrays
// copy the global regular Id and data value
augmentedTreeRegularNodeGlobalIdsPortal.Set(newRegularId,
globalRegularIdSetPortal.Get(supernodeSetIndex));
augmentedTreeDataValuesPortal.Set(newRegularId, dataValueSetPortal.Get(supernodeSetIndex));
// NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs
// // copy the global regular Id and data value
// augmentedTreeRegularNodeGlobalIdsPortal.Set(newRegularId, globalRegularIdSetPortal.Get(supernodeSetIndex));
// augmentedTreeDataValuesPortal.Set(newRegularId, dataValueSetPortal.Get(supernodeSetIndex));
// the sort order will be dealt with later
// since all of these nodes are supernodes, they will be their own superparent, which means that:
// a. the regular2node can be set immediately
augmentedTreeRegular2SupernodePortal.Set(newRegularId, newSupernodeId);
// b. as can the superparent
augmentedTreeSuperparentsPortal.Set(newRegularId, newSupernodeId);
// NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs
// // the sort order will be dealt with later
// // since all of these nodes are supernodes, they will be their own superparent, which means that:
// // a. the regular2node can be set immediately
// augmentedTreeRegular2SupernodePortal.Set(newRegularId, newSupernodeId);
// // b. as can the superparent
// augmentedTreeSuperparentsPortal.Set(newRegularId, newSupernodeId);
// In serial this worklet implements the following operation
/*
@ -434,6 +404,7 @@ private:
const vtkm::Id BaseTreeNumRounds;
const vtkm::Id AugmentedTreeNumIterations;
const vtkm::Id RoundNumber;
const vtkm::Id NumAugmentedTreeSupernodes;
}; // CreateSuperarcsWorklet