From e22051a0bc4e4859c22b5aa2254f3c21897082e7 Mon Sep 17 00:00:00 2001 From: Mingzhe Li Date: Tue, 9 Jul 2024 14:12:16 -0700 Subject: [PATCH] Reduce function size called by CastAndCallForTypes in SelectTopVolumeFunctor --- .../internal/SelectTopVolumeContoursBlock.cxx | 4 +- .../SelectTopVolumeContoursFunctor.cxx | 410 +++++++++--------- .../BranchDecompositionTreeMaker.h | 18 +- .../TopVolumeBranchData.h | 32 +- 4 files changed, 240 insertions(+), 224 deletions(-) diff --git a/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursBlock.cxx b/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursBlock.cxx index dc8a1f3ad..8b2287400 100644 --- a/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursBlock.cxx +++ b/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursBlock.cxx @@ -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( 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); diff --git a/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursFunctor.cxx b/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursFunctor.cxx index c22939c8f..340db9b45 100644 --- a/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursFunctor.cxx +++ b/vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursFunctor.cxx @@ -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( + "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( + "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( + 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( + mergedTopVolBranchGRId, sortedBranchId, permutedTopVolBranchGRId); + IdArrayType permutedTopVolBranchVolume; + vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( + mergedTopVolBranchVolume, sortedBranchId, permutedTopVolBranchVolume); + IdArrayType permutedTopVolBranchSaddleEpsilon; + vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( + mergedTopVolBranchSaddleEpsilon, sortedBranchId, permutedTopVolBranchSaddleEpsilon); + IdArrayType permutedTopVolBranchUpperEnd; + vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( + mergedTopVolBranchUpperEnd, sortedBranchId, permutedTopVolBranchUpperEnd); + IdArrayType permutedTopVolBranchLowerEnd; + vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( + 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( + "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; 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(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( - "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( - "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( 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( 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( - mergedTopVolBranchGRId, sortedBranchId, permutedTopVolBranchGRId); - IdArrayType permutedTopVolBranchVolume; - vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( - mergedTopVolBranchVolume, sortedBranchId, permutedTopVolBranchVolume); - IdArrayType permutedTopVolBranchSaddleEpsilon; - vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( - mergedTopVolBranchSaddleEpsilon, sortedBranchId, permutedTopVolBranchSaddleEpsilon); - IdArrayType permutedTopVolBranchUpperEnd; - vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( - mergedTopVolBranchUpperEnd, sortedBranchId, permutedTopVolBranchUpperEnd); - IdArrayType permutedTopVolBranchLowerEnd; - vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( - mergedTopVolBranchLowerEnd, sortedBranchId, permutedTopVolBranchLowerEnd); InArrayHandleType permutedTopVolBranchSaddleIsoValue; vtkm::worklet::contourtree_augmented::PermuteArrayWithRawIndex( 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( - "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( - "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(resolveArray); + .CastAndCallForTypes(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( + "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); + } } } } diff --git a/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchDecompositionTreeMaker.h b/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchDecompositionTreeMaker.h index 9373ca726..8a2c9017f 100644 --- a/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchDecompositionTreeMaker.h +++ b/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchDecompositionTreeMaker.h @@ -427,14 +427,6 @@ inline void BranchDecompositionTreeMaker::ComputeTopVolumeBranchHierarchy( vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex( tData.BranchRootGRId, extraMaximaParentBranch, extraMaximaParentBranchRootGRId); - //InArrayHandleType extraMaximaBranchIsoValue; - //vtkm::cont::Algorithm::CopyIf( - // tData.TopVolumeBranchSaddleIsoValue.AsArrayHandle(), - // 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( tData.BranchRootGRId, extraMinimaParentBranch, extraMinimaParentBranchRootGRId); - //InArrayHandleType extraMinimaBranchIsoValue; - //vtkm::cont::Algorithm::CopyIf( - // tData.TopVolumeBranchSaddleIsoValue.AsArrayHandle(), - // 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; - using ValueType = typename InArrayHandleType::ValueType; if (extraMaximaParentBranch.GetNumberOfValues()) { diff --git a/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/TopVolumeBranchData.h b/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/TopVolumeBranchData.h index a9b00ad6e..a95240b80 100644 --- a/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/TopVolumeBranchData.h +++ b/vtkm/filter/scalar_topology/worklet/select_top_volume_contours/TopVolumeBranchData.h @@ -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 IsParentBranch; vtkm::cont::UnknownArrayHandle BranchSaddleIsoValue; - // Output Datasets. + // True if it is the parent of a branch in the branch decomposition tree + vtkm::cont::ArrayHandle 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