Added fixes for HierarchicalHyperSweeper for pre-simplification

This commit is contained in:
Oliver Ruebel 2023-12-11 04:35:04 -08:00 committed by Gunther H. Weber
parent 3853dbe8ec
commit 2c0b127f7b
8 changed files with 406 additions and 29 deletions

@ -153,7 +153,7 @@ inline bool NoFlagsSet(vtkm::Id flaggedIndex)
// Helper function: to check that the TRANSFER_TO_SUPERARC flag is set
VTKM_EXEC_CONT
inline bool transferToSuperarc(vtkm::Id flaggedIndex)
inline bool TransferToSuperarc(vtkm::Id flaggedIndex)
{ // transferToSuperarc()
return ((flaggedIndex & TRANSFER_TO_SUPERARC) != 0);
} // transferToSuperarc()

@ -91,7 +91,9 @@
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeIntrinsicVertexCountSubtractLowEndWorklet.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferTargetComperator.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateLHEWorklet.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateLHEWorkletRound2.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateRHEWorklet.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateRHEWorkletRound2.h>
namespace vtkm
@ -530,6 +532,9 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::ComputeSupe
} // scope ComputeSuperarcTransferWeightsWorklet
// 5. Now we need to sort the transfer targets into contiguous segments
// TODO / WARNING 11/07/2023
// We have now got a flag of ATTACHMENT_POINT_TRANSFER whose effect is to separate out transfers to
// the superarc from transfers to the supernode
{
// create view of superSortPermute[firstSupernode, lastSupernode) for sorting
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
@ -578,6 +583,16 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::TransferWei
vtkm::Id firstSupernode,
vtkm::Id lastSupernode)
{ // TransferWeights()
// TODO / WARNING 11/07/2023
// This code was originally written on the assumption that the hierarchical tree had been augmented by the attachment points.
// As a result, it assumed that no attachment points remained.
// It is now being used for partially augmented versions due to pre-simplification, for which the correct treatment is to
// transfer not as dependent weight, but as intrinsic weight. Note that this ONLY applies to attachment points: if the
// subtree attaches at a proper supernode in the ancestor level, it should still be treated as dependent weight. The logic
// behind this is that an attachment point is regular with respect to the superarc along which it inserts. Adding it as
// dependent weight means that it is treated as *OUTSIDE* the superarc in the reverse sweep (or equivalent computation)
// Treating it as dependent weight means that both ends of the superarc end up with the correct value.
// 7. Now perform a segmented prefix sum
vtkm::Id numSupernodesToProcess = lastSupernode - firstSupernode;
// Same as std::partial_sum(valuePrefixSum.begin() + firstSupernode, valuePrefixSum.begin() + lastSupernode, valuePrefixSum.begin() + firstSupernode);
@ -602,6 +617,12 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::TransferWei
// 7a. and 7b.
{
// TODO / WARNING 11/07/2023
// Before dealing with attachment points, we just transferred by segments. We now have
// the possibility of transferring some weight at an attachment point,
// and some not. To avoid write conflicts, we treat this as two passes: one for attachment
// points, one for all others. This means duplicating 7a/7b, sadly.
// 7a. Find the RHE of each group and transfer the prefix sum weight
// Note that we do not compute the transfer weight separately, we add it in place instead
// Instantiate the worklet
@ -634,7 +655,7 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::TransferWei
auto valuePrefixSumPreviousValueView = vtkm::cont::make_ArrayHandleView(
this->ValuePrefixSum, firstSupernode, numSupernodesToProcess - 1);
// 7b. Now find the LHE of each group and subtract out the prior weight
// 7b (non-attachment). Now find the LHE of each group and subtract out the prior weight.
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
TransferWeightsUpdateLHEWorklet transferWeightsUpdateLHEWorklet;
this->Invoke(transferWeightsUpdateLHEWorklet,
@ -643,6 +664,43 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::TransferWei
valuePrefixSumPreviousValueView,
this->DependentValues);
}
// 7a (attachment). Find the RHE of each group and transfer the prefix sum weight
// Note that we do not compute the transfer weight separately, we add it in place instead
{
auto supernodeIndex =
vtkm::cont::make_ArrayHandleCounting(firstSupernode, vtkm::Id{ 1 }, numSupernodesToProcess);
auto valuePrefixSumView = vtkm::cont::make_ArrayHandleView(
this->ValuePrefixSum, firstSupernode, numSupernodesToProcess);
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
TransferWeightsUpdateRHEWorkletRound2 transferWeightsUpdateRHEWorkletRound2(lastSupernode);
// Invoke the worklet
this->Invoke(transferWeightsUpdateRHEWorkletRound2, // worklet
supernodeIndex, // input counting array [firstSupernode, lastSupernode)
this->SortedTransferTarget,
valuePrefixSumView, // input view of valuePrefixSum[firstSupernode, lastSupernode)
this->IntrinsicValues,
this->DependentValues);
}
// 7b (i). Now find the LHE of each group and subtract out the prior weight.
{
auto sortedTransferTargetView = vtkm::cont::make_ArrayHandleView(
this->SortedTransferTarget, firstSupernode + 1, numSupernodesToProcess - 1);
auto sortedTransferTargetShiftedView = vtkm::cont::make_ArrayHandleView(
this->SortedTransferTarget, firstSupernode, numSupernodesToProcess - 1);
auto valuePrefixSumPreviousValueView = vtkm::cont::make_ArrayHandleView(
this->ValuePrefixSum, firstSupernode, numSupernodesToProcess - 1);
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
TransferWeightsUpdateLHEWorkletRound2 transferWeightsUpdateLHEWorkletRound2;
this->Invoke(transferWeightsUpdateLHEWorkletRound2,
sortedTransferTargetView,
sortedTransferTargetShiftedView,
valuePrefixSumPreviousValueView,
this->IntrinsicValues,
this->DependentValues);
}
} // TransferWeights()

@ -17,6 +17,8 @@ set(headers
TransferTargetComperator.h
TransferWeightsUpdateRHEWorklet.h
TransferWeightsUpdateLHEWorklet.h
TransferWeightsUpdateRHEWorkletRound2.h
TransferWeightsUpdateLHEWorkletRound2.h
)
vtkm_declare_headers(${headers})

@ -116,7 +116,8 @@ public:
else
{ // attachment point
// set the transfer target
transferTarget = hierarchicalTreeSuperparentsPortal.Get(supernodeRegularId);
transferTarget = hierarchicalTreeSuperparentsPortal.Get(supernodeRegularId) |
vtkm::worklet::contourtree_augmented::TRANSFER_TO_SUPERARC;
} // attachment point
} // null superarc
else

@ -74,10 +74,11 @@ public:
FieldIn sortedTransferTargetShiftedView,
FieldIn valuePrefixSumShiftedView,
WholeArrayInOut dependentValuesPortal);
using ExecutionSgnature = void(_1, _2, _3, _4);
using ExecutionSignature = void(InputIndex, _1, _2, _3, _4);
template <typename InOutPortalType>
VTKM_EXEC void operator()(const vtkm::Id& sortedTransferTargetValue,
VTKM_EXEC void operator()(const vtkm::Id& supernode,
const vtkm::Id& sortedTransferTargetValue,
const vtkm::Id& sortedTransferTargetPreviousValue,
const vtkm::Id& valuePrefixSumPreviousValue,
InOutPortalType& dependentValuesPortal) const
@ -88,30 +89,33 @@ public:
{
return;
}
if (sortedTransferTargetValue != sortedTransferTargetPreviousValue)
// we need to separate out the flag for attachment points
bool superarcTransfer =
vtkm::worklet::contourtree_augmented::TransferToSuperarc(sortedTransferTargetValue);
vtkm::Id superarcOrNodeId =
vtkm::worklet::contourtree_augmented::MaskedIndex(sortedTransferTargetValue);
// ignore the transfers for attachment points
if (superarcTransfer)
{
auto originalValue = dependentValuesPortal.Get(sortedTransferTargetValue);
return;
}
// the LHE at 0 is special - it subtracts zero. In practice, since NO_SUCH_ELEMENT will sort low, this will never
// occur, but let's keep the logic strict
auto originalValue = dependentValuesPortal.Get(superarcOrNodeId);
if (supernode ==
0) // i.e., supernode == firstSupernode but we view the arrays when we call the worklet
{ // LHE 0
dependentValuesPortal.Set(superarcOrNodeId, originalValue - 0);
}
else if (sortedTransferTargetValue != sortedTransferTargetPreviousValue)
{ // LHE not 0
dependentValuesPortal.Set(sortedTransferTargetValue,
originalValue - valuePrefixSumPreviousValue);
}
// In serial this worklet implements the following operation
/*
for (vtkm::Id supernode = firstSupernode + 1; supernode < lastSupernode; supernode++)
{ // per supernode
// ignore any that point at NO_SUCH_ELEMENT
if (noSuchElement(sortedTransferTarget[supernode]))
continue;
// the LHE at 0 is special - it subtracts zero. In practice, since NO_SUCH_ELEMENT will sort low, this will never
// occur, but let's keep the logic strict
if (sortedTransferTarget[supernode] != sortedTransferTarget[supernode-1])
{ // LHE not 0
dependentValues[sortedTransferTarget[supernode]] -= valuePrefixSum[supernode-1];
} // LHE not 0
} // per supernode
*/
} // operator()()
}; // TransferWeightsUpdateLHEWorklet

@ -0,0 +1,132 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// Copyright (c) 2018, The Regents of the University of California, through
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
// from the U.S. Dept. of Energy). All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// (1) Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// (2) Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// (3) Neither the name of the University of California, Lawrence Berkeley National
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//=============================================================================
//
// This code is an extension of the algorithm presented in the paper:
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
// (LDAV), October 2016, Baltimore, Maryland.
//
// The PPP2 algorithm and software were jointly developed by
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
// Oliver Ruebel (LBNL)
//==============================================================================
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_lhe_worklet_round2_h
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_lhe_worklet_round2_h
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace vtkm
{
namespace worklet
{
namespace contourtree_distributed
{
namespace hierarchical_hyper_sweeper
{
/// Worklet used in HierarchicalHyperSweeper.TransferWeights(...) to implement
/// step 7b. Now find the LHE of each group and subtract out the prior weight
class TransferWeightsUpdateLHEWorkletRound2 : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn sortedTransferTargetPortal,
FieldIn sortedTransferTargetShiftedView,
FieldIn valuePrefixSumShiftedView,
WholeArrayInOut intrinsicValues,
WholeArrayInOut dependentValues);
using ExecutionSignature = void(InputIndex, _1, _2, _3, _4, _5);
template <typename InOutPortalType>
VTKM_EXEC void operator()(const vtkm::Id& supernode,
const vtkm::Id& sortedTransferTargetValue,
const vtkm::Id& sortedTransferTargetPreviousValue,
const vtkm::Id& valuePrefixSumPreviousValue,
InOutPortalType& intrinsicValuesPortal,
InOutPortalType& dependentValuesPortal) const
{
// per supernode
// ignore any that point at NO_SUCH_ELEMENT
if (vtkm::worklet::contourtree_augmented::NoSuchElement(sortedTransferTargetValue))
{
return;
}
// we need to separate out the flag for attachment points
bool superarcTransfer =
vtkm::worklet::contourtree_augmented::TransferToSuperarc(sortedTransferTargetValue);
vtkm::Id superarcOrNodeId =
vtkm::worklet::contourtree_augmented::MaskedIndex(sortedTransferTargetValue);
// ignore the transfers for attachment points
if (superarcTransfer)
{
return;
}
// the LHE at 0 is special - it subtracts zero. In practice, since NO_SUCH_ELEMENT will sort low, this will never
// occur, but let's keep the logic strict
auto originalIntrinsicValue = dependentValuesPortal.Get(superarcOrNodeId);
auto originalDependentValue = dependentValuesPortal.Get(superarcOrNodeId);
if (supernode ==
0) // i.e., supernode == firstSupernode but we view the arrays when we call the worklet
{ // LHE 0
intrinsicValuesPortal.Set(superarcOrNodeId, originalIntrinsicValue - 0);
dependentValuesPortal.Set(superarcOrNodeId, originalDependentValue - 0);
}
else if (sortedTransferTargetValue != sortedTransferTargetPreviousValue)
{ // LHE not 0
intrinsicValuesPortal.Set(sortedTransferTargetValue,
originalIntrinsicValue - valuePrefixSumPreviousValue);
dependentValuesPortal.Set(sortedTransferTargetValue,
originalDependentValue - valuePrefixSumPreviousValue);
}
} // operator()()
}; // TransferWeightsUpdateLHEWorklet
} // namespace hierarchical_hyper_sweeper
} // namespace contourtree_distributed
} // namespace worklet
} // namespace vtkm
#endif

@ -100,8 +100,18 @@ public:
if ((supernode == this->LastSupernode - 1) ||
(transferTarget != sortedTransferTargetPortal.Get(supernode + 1)))
{ // RHE of segment
auto originalValue = dependentValuesPortal.Get(transferTarget);
dependentValuesPortal.Set(transferTarget, originalValue + valuePrefixSum);
// we need to separate out the flag for attachment points
bool superarcTransfer =
vtkm::worklet::contourtree_augmented::TransferToSuperarc(transferTarget);
vtkm::Id superarcOrNodeId =
vtkm::worklet::contourtree_augmented::MaskedIndex(transferTarget);
// we ignore attachment points
if (superarcTransfer)
{
return;
}
auto originalValue = dependentValuesPortal.Get(superarcOrNodeId);
dependentValuesPortal.Set(superarcOrNodeId, originalValue + valuePrefixSum);
} // RHE of segment
}
@ -113,10 +123,19 @@ public:
if (noSuchElement(sortedTransferTarget[supernode]))
continue;
// the RHE of each segment transfers its weight (including all irrelevant prefixes)
if ((supernode == lastSupernode - 1) || (sortedTransferTarget[supernode] != sortedTransferTarget[supernode+1]))
{ // RHE of segment
dependentValues[sortedTransferTarget[supernode]] += valuePrefixSum[supernode];
// TODO / WARNING 11/07/2023
// we need to separate out the flag for attachment points
bool superarcTransfer = transferToSuperarc(sortedTransferTarget[supernode]);
indexType superarcOrNodeID = maskedIndex(sortedTransferTarget[supernode]);
// we ignore attachment points
if (superarcTransfer)
continue;
// transfer as dependent weight
dependentValues[superarcOrNodeID] += valuePrefixSum[supernode];
} // RHE of segment
} // per supernode
*/

@ -0,0 +1,161 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// Copyright (c) 2018, The Regents of the University of California, through
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
// from the U.S. Dept. of Energy). All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// (1) Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// (2) Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// (3) Neither the name of the University of California, Lawrence Berkeley National
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//=============================================================================
//
// This code is an extension of the algorithm presented in the paper:
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
// (LDAV), October 2016, Baltimore, Maryland.
//
// The PPP2 algorithm and software were jointly developed by
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
// Oliver Ruebel (LBNL)
//==============================================================================
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_rhe_worklet_round2_h
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_rhe_worklet_round2_h
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace vtkm
{
namespace worklet
{
namespace contourtree_distributed
{
namespace hierarchical_hyper_sweeper
{
/// Worklet used in HierarchicalHyperSweeper.TransferWeights(...) to implement
/// step 7a. Find the RHE of each group and transfer the prefix sum weight.
/// Note that we do not compute the transfer weight separately, we add it in place instead
class TransferWeightsUpdateRHEWorkletRound2 : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature =
void(FieldIn supernodeIndex, // input counting array [firstSupernode, lastSupernode)
WholeArrayIn sortedTransferTarget,
FieldIn valuePrefixSumView, // input view of valuePrefixSum[firstSupernode, lastSupernode)
WholeArrayInOut intrinsicValuesPortal,
WholeArrayInOut dependentValuesPortal);
using ExecutionSignature = void(_1, _2, _3, _4, _5);
// Default Constructor
VTKM_EXEC_CONT
TransferWeightsUpdateRHEWorkletRound2(const vtkm::Id& lastSupernode)
: LastSupernode(lastSupernode)
{
}
template <typename InPortalType, typename OutPortalType>
VTKM_EXEC void operator()(const vtkm::Id& supernode,
const InPortalType& sortedTransferTargetPortal,
const vtkm::Id& valuePrefixSum, // same as valuePrefixSum[supernode]
OutPortalType& intrinsicValuesPortal,
OutPortalType& dependentValuesPortal) const
{
// per supernode
// ignore any that point at NO_SUCH_ELEMENT
vtkm::Id transferTarget = sortedTransferTargetPortal.Get(supernode);
if (!vtkm::worklet::contourtree_augmented::NoSuchElement(transferTarget))
{
// the RHE of each segment transfers its weight (including all irrelevant prefixes)
if ((supernode == this->LastSupernode - 1) ||
(transferTarget != sortedTransferTargetPortal.Get(supernode + 1)))
{ // RHE of segment
// we need to separate out the flag for attachment points
bool superarcTransfer =
vtkm::worklet::contourtree_augmented::TransferToSuperarc(transferTarget);
vtkm::Id superarcOrNodeId =
vtkm::worklet::contourtree_augmented::MaskedIndex(transferTarget);
// we ignore attachment points
if (superarcTransfer)
{
return;
}
// we modify both intrinsic and dependent values
// we modify both intrinsic and dependent values
auto originalIntrinsicValue = intrinsicValuesPortal.Get(superarcOrNodeId);
intrinsicValuesPortal.Set(superarcOrNodeId, originalIntrinsicValue + valuePrefixSum);
auto originalDependentValue = dependentValuesPortal.Get(superarcOrNodeId);
dependentValuesPortal.Set(superarcOrNodeId, originalDependentValue + valuePrefixSum);
} // RHE of segment
}
// In serial this worklet implements the following operation
/*
for (indexType supernode = firstSupernode; supernode < lastSupernode; supernode++)
{ // per supernode
// ignore any that point at NO_SUCH_ELEMENT
if (noSuchElement(sortedTransferTarget[supernode]))
continue;
// the RHE of each segment transfers its weight (including all irrelevant prefixes)
if ((supernode == lastSupernode - 1) || (sortedTransferTarget[supernode] != sortedTransferTarget[supernode+1]))
{ // RHE of segment
// we need to separate out the flag for attachment points
bool superarcTransfer = transferToSuperarc(sortedTransferTarget[supernode]);
indexType superarcOrNodeID = maskedIndex(sortedTransferTarget[supernode]);
// ignore the transfers for non-attachment points
if (!superarcTransfer)
continue;
// we modify both intrinsic and dependent values
intrinsicValues[superarcOrNodeID] += valuePrefixSum[supernode];
dependentValues[superarcOrNodeID] += valuePrefixSum[supernode];
} // RHE of segment
} // per supernode
*/
} // operator()()
private:
const vtkm::Id LastSupernode;
}; // TransferWeightsUpdateRHEWorklet
} // namespace hierarchical_hyper_sweeper
} // namespace contourtree_distributed
} // namespace worklet
} // namespace vtkm
#endif