Reduce function size called by CastAndCallForTypes in SelectTopVolumeFunctor

This commit is contained in:
Mingzhe Li 2024-07-09 14:12:16 -07:00 committed by Gunther H. Weber
parent 0425cc7996
commit e22051a0bc
4 changed files with 240 additions and 224 deletions

@ -126,10 +126,9 @@ void SelectTopVolumeContoursBlock::SortBranchByVolume(const vtkm::cont::DataSet&
vtkm::cont::Algorithm::Transform(
lowerEndIntrinsicVolume, lowerEndDependentVolume, isLowerLeaf, vtkm::Equal());
// NOTE: special cases (one-superarc branches) exist
// if the upper end superarc == lower end superarc == branch root superarc
// then it's probably not a leaf-leaf branch (Both equality has to be satisfied!)
// then it's probably not a leaf-leaf branch (Both equality have to be satisfied!)
// exception: the entire domain has only one superarc (intrinsic == dependent == total - 1)
// then it is a leaf-leaf branch
vtkm::cont::Invoker invoke;
@ -177,6 +176,7 @@ void SelectTopVolumeContoursBlock::SortBranchByVolume(const vtkm::cont::DataSet&
upperEndValue.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(
resolveArray);
// Compute the branch volume based on the upper/lower end superarc volumes
vtkm::worklet::contourtree_augmented::IdArrayType branchVolume;
vtkm::worklet::scalar_topology::select_top_volume_contours::GetBranchVolumeWorklet
getBranchVolumeWorklet(totalVolume);

@ -235,9 +235,168 @@ void SelectTopVolumeContoursFunctor::operator()(
// Replace with dequeuing ArrayHandles once bug is fixed.
// rp.dequeue(ingid, incomingTopVolBranchLowerEnd);
auto resolveArray = [&](auto& inArray) {
std::stringstream dataSizeStream;
// Log the amount of exchanged data
dataSizeStream << " " << std::setw(38) << std::left << "Incoming top volume branch size"
<< ": " << nIncoming << std::endl;
VTKM_LOG_S(this->TimingsLogLevel,
std::endl
<< " ---------------- Select Top Volume Branches Step ---------------------"
<< std::endl
<< " Rank : " << rank << std::endl
<< " DIY Id : " << selfid << std::endl
<< " Inc Id : " << ingid << std::endl
<< dataSizeStream.str());
vtkm::Id nSelf = b->tData.TopVolumeBranchRootGRId.GetNumberOfValues();
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "nIncoming = " << nIncoming << ", nSelf = " << nSelf);
{
std::stringstream rs;
vtkm::worklet::contourtree_augmented::PrintHeader(nIncoming, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingTopBranchId", incomingTopVolBranchGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingTopBranchVol", incomingTopVolBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"incomingSaddleVal", incomingTopVolBranchSaddleIsoValue, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingUpperEnd", incomingTopVolBranchUpperEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingLowerEnd", incomingTopVolBranchLowerEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintHeader(nSelf, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchId", b->tData.TopVolumeBranchRootGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchVol", b->tData.TopVolumeBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"selfTopSaddleVal", inArray, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchUpperEnd", b->tData.TopVolumeBranchUpperEndGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchLowerEnd", b->tData.TopVolumeBranchLowerEndGRId, -1, rs);
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
}
#endif
// merge incoming branches with self branches
IdArrayType mergedTopVolBranchGRId;
IdArrayType mergedTopVolBranchVolume;
IdArrayType mergedTopVolBranchSaddleEpsilon;
IdArrayType mergedTopVolBranchUpperEnd;
IdArrayType mergedTopVolBranchLowerEnd;
mergedTopVolBranchGRId.Allocate(nIncoming + nSelf);
mergedTopVolBranchVolume.Allocate(nIncoming + nSelf);
mergedTopVolBranchSaddleEpsilon.Allocate(nIncoming + nSelf);
mergedTopVolBranchUpperEnd.Allocate(nIncoming + nSelf);
mergedTopVolBranchLowerEnd.Allocate(nIncoming + nSelf);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchGRId, 0, nIncoming, mergedTopVolBranchGRId, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchVolume, 0, nIncoming, mergedTopVolBranchVolume, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchSaddleEpsilon, 0, nIncoming, mergedTopVolBranchSaddleEpsilon, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchUpperEnd, 0, nIncoming, mergedTopVolBranchUpperEnd, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchLowerEnd, 0, nIncoming, mergedTopVolBranchLowerEnd, 0);
/*vtkm::cont::Algorithm::CopySubRange<ValueType, ValueType>(
incomingTopVolBranchSaddleIsoValue, 0, nIncoming, mergedTopVolBranchSaddleIsoValue, 0);*/
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchRootGRId, 0, nSelf, mergedTopVolBranchGRId, nIncoming);
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchVolume, 0, nSelf, mergedTopVolBranchVolume, nIncoming);
vtkm::cont::Algorithm::CopySubRange(b->tData.TopVolumeBranchSaddleEpsilon,
0,
nSelf,
mergedTopVolBranchSaddleEpsilon,
nIncoming);
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchUpperEndGRId, 0, nSelf, mergedTopVolBranchUpperEnd, nIncoming);
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchLowerEndGRId, 0, nSelf, mergedTopVolBranchLowerEnd, nIncoming);
// Sort all branches (incoming + self) based on volume
// sorting key: (volume, branch global regular ID)
// the highest volume comes first, the lowest branch GR ID comes first
vtkm::cont::ArrayHandleIndex mergedBranchId(nIncoming + nSelf);
IdArrayType sortedBranchId;
vtkm::cont::Algorithm::Copy(mergedBranchId, sortedBranchId);
vtkm::worklet::scalar_topology::select_top_volume_contours::BranchVolumeComparator
branchVolumeComparator(mergedTopVolBranchGRId, mergedTopVolBranchVolume);
vtkm::cont::Algorithm::Sort(sortedBranchId, branchVolumeComparator);
// permute the branch information based on sorting
IdArrayType permutedTopVolBranchGRId;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchGRId, sortedBranchId, permutedTopVolBranchGRId);
IdArrayType permutedTopVolBranchVolume;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchVolume, sortedBranchId, permutedTopVolBranchVolume);
IdArrayType permutedTopVolBranchSaddleEpsilon;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchSaddleEpsilon, sortedBranchId, permutedTopVolBranchSaddleEpsilon);
IdArrayType permutedTopVolBranchUpperEnd;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchUpperEnd, sortedBranchId, permutedTopVolBranchUpperEnd);
IdArrayType permutedTopVolBranchLowerEnd;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchLowerEnd, sortedBranchId, permutedTopVolBranchLowerEnd);
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
{
std::stringstream rs;
vtkm::worklet::contourtree_augmented::PrintHeader(nIncoming + nSelf, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchId", permutedTopVolBranchGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchVol", permutedTopVolBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchUpperEnd", permutedTopVolBranchUpperEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchLowerEnd", permutedTopVolBranchLowerEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"permutedTopSaddleVal", permutedTopVolBranchSaddleIsoValue, -1, rs);
}
#endif
// there may be duplicate branches. We remove duplicate branches based on global regular IDs
// We can reuse the filter from removing duplicate branches in the process of collecting branches
IdArrayType oneIfUniqueBranch;
oneIfUniqueBranch.Allocate(nIncoming + nSelf);
vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
OneIfBranchEndWorklet oneIfUniqueWorklet;
invoke(oneIfUniqueWorklet, mergedBranchId, permutedTopVolBranchGRId, oneIfUniqueBranch);
// Remove duplicate
IdArrayType mergedUniqueBranchGRId;
IdArrayType mergedUniqueBranchVolume;
IdArrayType mergedUniqueBranchSaddleEpsilon;
IdArrayType mergedUniqueBranchUpperEnd;
IdArrayType mergedUniqueBranchLowerEnd;
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchGRId, oneIfUniqueBranch, mergedUniqueBranchGRId);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchVolume, oneIfUniqueBranch, mergedUniqueBranchVolume);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchSaddleEpsilon, oneIfUniqueBranch, mergedUniqueBranchSaddleEpsilon);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchUpperEnd, oneIfUniqueBranch, mergedUniqueBranchUpperEnd);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchLowerEnd, oneIfUniqueBranch, mergedUniqueBranchLowerEnd);
vtkm::Id nMergedUnique = mergedUniqueBranchGRId.GetNumberOfValues();
// We move all processing to the TopVolumeBranchSaddleIsoValue here
// to reduce the size of the function
auto resolveMerging = [&](auto& inArray) {
using InArrayHandleType = std::decay_t<decltype(inArray)>;
using ValueType = typename InArrayHandleType::ValueType;
InArrayHandleType incomingTopVolBranchSaddleIsoValue;
incomingTopVolBranchSaddleIsoValue.Allocate(nIncoming);
auto incomingTopVolBranchSaddleIsoValuePortal =
@ -249,236 +408,91 @@ void SelectTopVolumeContoursFunctor::operator()(
incomingTopVolBranchSaddleIsoValuePortal.Set(branch, incomingSaddleValue);
}
std::stringstream dataSizeStream;
// Log the amount of exchanged data
dataSizeStream << " " << std::setw(38) << std::left << "Incoming top volume branch size"
<< ": " << nIncoming << std::endl;
VTKM_LOG_S(this->TimingsLogLevel,
std::endl
<< " ---------------- Select Top Volume Branches Step ---------------------"
<< std::endl
<< " Rank : " << rank << std::endl
<< " DIY Id : " << selfid << std::endl
<< " Inc Id : " << ingid << std::endl
<< dataSizeStream.str());
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
// Replace with dequeuing ArrayHandles once bug is fixed.
// rp.dequeue<InArrayHandleType>(ingid, incomingTopVolBranchSaddleIsoValue);
vtkm::Id nSelf = b->tData.TopVolumeBranchRootGRId.GetNumberOfValues();
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
"nIncoming = " << nIncoming << ", nSelf = " << nSelf);
{
std::stringstream rs;
vtkm::worklet::contourtree_augmented::PrintHeader(nIncoming, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingTopBranchId", incomingTopVolBranchGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingTopBranchVol", incomingTopVolBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"incomingSaddleVal", incomingTopVolBranchSaddleIsoValue, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingUpperEnd", incomingTopVolBranchUpperEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"incomingLowerEnd", incomingTopVolBranchLowerEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintHeader(nSelf, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchId", b->tData.TopVolumeBranchRootGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchVol", b->tData.TopVolumeBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"selfTopSaddleVal", inArray, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchUpperEnd", b->tData.TopVolumeBranchUpperEndGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"selfTopBranchLowerEnd", b->tData.TopVolumeBranchLowerEndGRId, -1, rs);
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
}
#endif
// merge incoming branches with self branches
IdArrayType mergedTopVolBranchGRId;
IdArrayType mergedTopVolBranchVolume;
IdArrayType mergedTopVolBranchSaddleEpsilon;
IdArrayType mergedTopVolBranchUpperEnd;
IdArrayType mergedTopVolBranchLowerEnd;
InArrayHandleType mergedTopVolBranchSaddleIsoValue;
mergedTopVolBranchGRId.Allocate(nIncoming + nSelf);
mergedTopVolBranchVolume.Allocate(nIncoming + nSelf);
mergedTopVolBranchSaddleEpsilon.Allocate(nIncoming + nSelf);
mergedTopVolBranchUpperEnd.Allocate(nIncoming + nSelf);
mergedTopVolBranchLowerEnd.Allocate(nIncoming + nSelf);
mergedTopVolBranchSaddleIsoValue.Allocate(nIncoming + nSelf);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchGRId, 0, nIncoming, mergedTopVolBranchGRId, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchVolume, 0, nIncoming, mergedTopVolBranchVolume, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchSaddleEpsilon, 0, nIncoming, mergedTopVolBranchSaddleEpsilon, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchUpperEnd, 0, nIncoming, mergedTopVolBranchUpperEnd, 0);
vtkm::cont::Algorithm::CopySubRange(
incomingTopVolBranchLowerEnd, 0, nIncoming, mergedTopVolBranchLowerEnd, 0);
vtkm::cont::Algorithm::CopySubRange<ValueType, ValueType>(
incomingTopVolBranchSaddleIsoValue, 0, nIncoming, mergedTopVolBranchSaddleIsoValue, 0);
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchRootGRId, 0, nSelf, mergedTopVolBranchGRId, nIncoming);
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchVolume, 0, nSelf, mergedTopVolBranchVolume, nIncoming);
vtkm::cont::Algorithm::CopySubRange(b->tData.TopVolumeBranchSaddleEpsilon,
0,
nSelf,
mergedTopVolBranchSaddleEpsilon,
nIncoming);
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchUpperEndGRId, 0, nSelf, mergedTopVolBranchUpperEnd, nIncoming);
vtkm::cont::Algorithm::CopySubRange(
b->tData.TopVolumeBranchLowerEndGRId, 0, nSelf, mergedTopVolBranchLowerEnd, nIncoming);
vtkm::cont::Algorithm::CopySubRange<ValueType, ValueType>(
inArray, 0, nSelf, mergedTopVolBranchSaddleIsoValue, nIncoming);
// Sort all branches (incoming + self) based on volume
// sorting key: (volume, branch global regular ID)
// the highest volume comes first, the lowest branch GR ID comes first
vtkm::cont::ArrayHandleIndex mergedBranchId(nIncoming + nSelf);
IdArrayType sortedBranchId;
vtkm::cont::Algorithm::Copy(mergedBranchId, sortedBranchId);
vtkm::worklet::scalar_topology::select_top_volume_contours::BranchVolumeComparator
branchVolumeComparator(mergedTopVolBranchGRId, mergedTopVolBranchVolume);
vtkm::cont::Algorithm::Sort(sortedBranchId, branchVolumeComparator);
// permute the branch information based on sorting
IdArrayType permutedTopVolBranchGRId;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchGRId, sortedBranchId, permutedTopVolBranchGRId);
IdArrayType permutedTopVolBranchVolume;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchVolume, sortedBranchId, permutedTopVolBranchVolume);
IdArrayType permutedTopVolBranchSaddleEpsilon;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchSaddleEpsilon, sortedBranchId, permutedTopVolBranchSaddleEpsilon);
IdArrayType permutedTopVolBranchUpperEnd;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchUpperEnd, sortedBranchId, permutedTopVolBranchUpperEnd);
IdArrayType permutedTopVolBranchLowerEnd;
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
mergedTopVolBranchLowerEnd, sortedBranchId, permutedTopVolBranchLowerEnd);
InArrayHandleType permutedTopVolBranchSaddleIsoValue;
vtkm::worklet::contourtree_augmented::PermuteArrayWithRawIndex<InArrayHandleType>(
mergedTopVolBranchSaddleIsoValue, sortedBranchId, permutedTopVolBranchSaddleIsoValue);
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
{
std::stringstream rs;
vtkm::worklet::contourtree_augmented::PrintHeader(nIncoming + nSelf, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchId", permutedTopVolBranchGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchVol", permutedTopVolBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchUpperEnd", permutedTopVolBranchUpperEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"permutedTopBranchLowerEnd", permutedTopVolBranchLowerEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"permutedTopSaddleVal", permutedTopVolBranchSaddleIsoValue, -1, rs);
}
#endif
// there may be duplicate branches. We remove duplicate branches based on global regular IDs
// We can reuse the filter from removing duplicate branches in the process of collecting branches
IdArrayType oneIfUniqueBranch;
oneIfUniqueBranch.Allocate(nIncoming + nSelf);
vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
OneIfBranchEndWorklet oneIfUniqueWorklet;
invoke(oneIfUniqueWorklet, mergedBranchId, permutedTopVolBranchGRId, oneIfUniqueBranch);
// Remove duplicate
IdArrayType mergedUniqueBranchGRId;
IdArrayType mergedUniqueBranchVolume;
IdArrayType mergedUniqueBranchSaddleEpsilon;
IdArrayType mergedUniqueBranchUpperEnd;
IdArrayType mergedUniqueBranchLowerEnd;
InArrayHandleType mergedUniqueBranchSaddleIsoValue;
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchGRId, oneIfUniqueBranch, mergedUniqueBranchGRId);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchVolume, oneIfUniqueBranch, mergedUniqueBranchVolume);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchSaddleEpsilon, oneIfUniqueBranch, mergedUniqueBranchSaddleEpsilon);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchUpperEnd, oneIfUniqueBranch, mergedUniqueBranchUpperEnd);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchLowerEnd, oneIfUniqueBranch, mergedUniqueBranchLowerEnd);
vtkm::cont::Algorithm::CopyIf(
permutedTopVolBranchSaddleIsoValue, oneIfUniqueBranch, mergedUniqueBranchSaddleIsoValue);
vtkm::Id nMergedUnique = mergedUniqueBranchGRId.GetNumberOfValues();
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
{
std::stringstream rs;
vtkm::worklet::contourtree_augmented::PrintHeader(nMergedUnique, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchId", mergedUniqueBranchGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchVol", mergedUniqueBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchUpperEnd", mergedUniqueBranchUpperEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchLowerEnd", mergedUniqueBranchLowerEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"mergedUniqueSaddleVal", mergedUniqueBranchSaddleIsoValue, -1, rs);
}
#endif
// After removing duplicate, if there are more branches than we need
// We only save the top nSavedBranches branches
if (nMergedUnique > this->nSavedBranches)
{
vtkm::cont::Algorithm::CopySubRange(
mergedUniqueBranchGRId, 0, this->nSavedBranches, b->tData.TopVolumeBranchRootGRId);
vtkm::cont::Algorithm::CopySubRange(
mergedUniqueBranchVolume, 0, this->nSavedBranches, b->tData.TopVolumeBranchVolume);
vtkm::cont::Algorithm::CopySubRange(mergedUniqueBranchSaddleEpsilon,
0,
this->nSavedBranches,
b->tData.TopVolumeBranchSaddleEpsilon);
vtkm::cont::Algorithm::CopySubRange(mergedUniqueBranchUpperEnd,
0,
this->nSavedBranches,
b->tData.TopVolumeBranchUpperEndGRId);
vtkm::cont::Algorithm::CopySubRange(mergedUniqueBranchLowerEnd,
0,
this->nSavedBranches,
b->tData.TopVolumeBranchLowerEndGRId);
// InArrayHandleType subRangeUniqueBranchSaddleIsoValue;
inArray.Allocate(this->nSavedBranches);
vtkm::cont::Algorithm::CopySubRange(
mergedUniqueBranchSaddleIsoValue, 0, this->nSavedBranches, inArray);
// inArray = subRangeUniqueBranchSaddleIsoValue;
}
else
{
vtkm::cont::Algorithm::Copy(mergedUniqueBranchGRId, b->tData.TopVolumeBranchRootGRId);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchVolume, b->tData.TopVolumeBranchVolume);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchSaddleEpsilon,
b->tData.TopVolumeBranchSaddleEpsilon);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchUpperEnd,
b->tData.TopVolumeBranchUpperEndGRId);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchLowerEnd,
b->tData.TopVolumeBranchLowerEndGRId);
inArray.Allocate(nMergedUnique);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchSaddleIsoValue, inArray);
}
};
b->tData.TopVolumeBranchSaddleIsoValue
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(resolveArray);
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(resolveMerging);
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
{
std::stringstream rs;
vtkm::worklet::contourtree_augmented::PrintHeader(nMergedUnique, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchId", mergedUniqueBranchGRId, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchVol", mergedUniqueBranchVolume, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchUpperEnd", mergedUniqueBranchUpperEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintIndices(
"mergedUniqueBranchLowerEnd", mergedUniqueBranchLowerEnd, -1, rs);
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
"mergedUniqueSaddleVal", mergedUniqueBranchSaddleIsoValue, -1, rs);
}
#endif
// After removing duplicate, if there are more branches than we need
// We only save the top nSavedBranches branches
if (nMergedUnique > this->nSavedBranches)
{
vtkm::cont::Algorithm::CopySubRange(
mergedUniqueBranchGRId, 0, this->nSavedBranches, b->tData.TopVolumeBranchRootGRId);
vtkm::cont::Algorithm::CopySubRange(
mergedUniqueBranchVolume, 0, this->nSavedBranches, b->tData.TopVolumeBranchVolume);
vtkm::cont::Algorithm::CopySubRange(mergedUniqueBranchSaddleEpsilon,
0,
this->nSavedBranches,
b->tData.TopVolumeBranchSaddleEpsilon);
vtkm::cont::Algorithm::CopySubRange(mergedUniqueBranchUpperEnd,
0,
this->nSavedBranches,
b->tData.TopVolumeBranchUpperEndGRId);
vtkm::cont::Algorithm::CopySubRange(mergedUniqueBranchLowerEnd,
0,
this->nSavedBranches,
b->tData.TopVolumeBranchLowerEndGRId);
}
else
{
vtkm::cont::Algorithm::Copy(mergedUniqueBranchGRId, b->tData.TopVolumeBranchRootGRId);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchVolume, b->tData.TopVolumeBranchVolume);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchSaddleEpsilon,
b->tData.TopVolumeBranchSaddleEpsilon);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchUpperEnd,
b->tData.TopVolumeBranchUpperEndGRId);
vtkm::cont::Algorithm::Copy(mergedUniqueBranchLowerEnd,
b->tData.TopVolumeBranchLowerEndGRId);
}
}
}
}

@ -427,14 +427,6 @@ inline void BranchDecompositionTreeMaker::ComputeTopVolumeBranchHierarchy(
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
tData.BranchRootGRId, extraMaximaParentBranch, extraMaximaParentBranchRootGRId);
//InArrayHandleType extraMaximaBranchIsoValue;
//vtkm::cont::Algorithm::CopyIf(
// tData.TopVolumeBranchSaddleIsoValue.AsArrayHandle<InArrayHandleType>(),
// IsOuterSaddle,
// extraMaximaBranchIsoValue,
// vtkm::worklet::scalar_topology::select_top_volume_contours::IsExtraMaxima());
//tData.ExtraMaximaBranchIsoValue = extraMaximaBranchIsoValue;
// a worklet to binary search a number in a sorted array and return the index
vtkm::worklet::scalar_topology::select_top_volume_contours::IdxIfWithinBlockWorklet
getParentBranchOrder;
@ -461,14 +453,6 @@ inline void BranchDecompositionTreeMaker::ComputeTopVolumeBranchHierarchy(
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
tData.BranchRootGRId, extraMinimaParentBranch, extraMinimaParentBranchRootGRId);
//InArrayHandleType extraMinimaBranchIsoValue;
//vtkm::cont::Algorithm::CopyIf(
// tData.TopVolumeBranchSaddleIsoValue.AsArrayHandle<InArrayHandleType>(),
// IsOuterSaddle,
// extraMinimaBranchIsoValue,
// vtkm::worklet::scalar_topology::select_top_volume_contours::IsExtraMinima());
//tData.ExtraMinimaBranchIsoValue = extraMinimaBranchIsoValue;
vtkm::worklet::scalar_topology::select_top_volume_contours::IdxIfWithinBlockWorklet
getParentBranchOrder;
IdArrayType permutedExtraMinimaBranchOrder;
@ -485,9 +469,9 @@ inline void BranchDecompositionTreeMaker::ComputeTopVolumeBranchHierarchy(
branchGRIdByVolumeIdx, permutedExtraMinimaBranchOrder, tData.ExtraMinimaBranchOrder);
}
// Update saddle isovalues for extra contours
auto resolveExtraContourSaddleValue = [&](const auto& inArray) {
using InArrayHandleType = std::decay_t<decltype(inArray)>;
using ValueType = typename InArrayHandleType::ValueType;
if (extraMaximaParentBranch.GetNumberOfValues())
{

@ -75,19 +75,24 @@ namespace scalar_topology
/// Data to store all information about top branches by volume
struct TopVolumeBranchData
{ // struct TopVolumeBranchData
// Data from DHCT. Size: nBranches
vtkm::worklet::contourtree_augmented::IdArrayType BranchRootByBranch;
vtkm::worklet::contourtree_augmented::IdArrayType BranchRootGRId;
vtkm::worklet::contourtree_augmented::IdArrayType BranchVolume;
vtkm::worklet::contourtree_augmented::IdArrayType BranchSaddleEpsilon;
vtkm::worklet::contourtree_augmented::IdArrayType SortedBranchByVolume;
vtkm::cont::ArrayHandle<bool> IsParentBranch;
vtkm::cont::UnknownArrayHandle BranchSaddleIsoValue;
// Output Datasets.
// True if it is the parent of a branch in the branch decomposition tree
vtkm::cont::ArrayHandle<bool> IsParentBranch;
// Output Datasets. Information of top branches by volume.
// Size: nTopVolBranches
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchRoot;
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchRootGRId;
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchVolume;
// the parent branch of top volume branches (if no parent branch, then NO_SUCH_ELEMENT)
// the parent branch of top branches (if no parent branch, then NO_SUCH_ELEMENT)
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchParent;
vtkm::cont::UnknownArrayHandle TopVolumeBranchSaddleIsoValue;
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchSaddleEpsilon;
@ -96,27 +101,40 @@ struct TopVolumeBranchData
// Other top-volume branch information
// whether the top volume branch is known by the block
// Whether the top volume branch is known by the block.
// size: nTopVolBranches
// value range: [0, 1]
vtkm::worklet::contourtree_augmented::IdArrayType TopVolBranchKnownByBlockStencil;
// the branch order (among all branches) by branch root global regular ids
// Branch order (among all branches) by branch root global regular ids.
// size: nTopVolBranches
// value range: {NO_SUCH_ELEMENT} U [0, nBranches - 1]
vtkm::worklet::contourtree_augmented::IdArrayType TopVolBranchGROrder;
// the branch information index (known by the block) of the top volume branch
// Branch information index (among all branches) of the top volume branch.
// Top-volume branches outside the block are excluded.
// size: nTopVolBranchKnownByBlock
// value range: [0, nBranches - 1]
vtkm::worklet::contourtree_augmented::IdArrayType TopVolBranchInfoActualIndex;
// information to extract extra isosurface for extrema
// Information to extract extra contours
// For each top-volume branch, we extract a contour on the branch near the saddle,
// and an extra contour on the parent branch near the same saddle
// The extra contour is dependent on the saddle of top-volume branches
// For top-volume branches with a maximum as the end,
// the isovalue of the extra contour will be higher than the saddle end of the top-volume branch
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMaximaBranchUpperEnd;
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMaximaBranchLowerEnd;
// We copy the branch order of the top-volume branch
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMaximaBranchOrder;
vtkm::cont::UnknownArrayHandle ExtraMaximaBranchIsoValue;
// For top-volume branches with a minimum as the end,
// the isovalue of the extra contour will be lower than the saddle end of the top-volume branch
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMinimaBranchUpperEnd;
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMinimaBranchLowerEnd;
// We copy the branch order of the top-volume branch
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMinimaBranchOrder;
vtkm::cont::UnknownArrayHandle ExtraMinimaBranchIsoValue;
}; // class TopVolumeBranchData