diff --git a/vtkm/worklet/contourtree_distributed/CombineHyperSweepBlockFunctor.h b/vtkm/worklet/contourtree_distributed/CombineHyperSweepBlockFunctor.h new file mode 100644 index 000000000..16ed10332 --- /dev/null +++ b/vtkm/worklet/contourtree_distributed/CombineHyperSweepBlockFunctor.h @@ -0,0 +1,163 @@ +//============================================================================ +// 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_combinehypersweepblockfunctor_h +#define vtk_m_worklet_contourtree_distributed_combinehypersweepblockfunctor_h + +#include +#include +#include + +// clang-format off +VTKM_THIRDPARTY_PRE_INCLUDE +#include +VTKM_THIRDPARTY_POST_INCLUDE +// clang-format on + + +namespace vtkm +{ +namespace worklet +{ +namespace contourtree_distributed +{ + +template +struct CobmineHyperSweepBlockFunctor +{ + void operator()( + vtkm::worklet::contourtree_distributed::HyperSweepBlock* b, + const vtkmdiy::ReduceProxy& rp, // communication proxy + const vtkmdiy::RegularSwapPartners& // partners of the current block (unused) + ) const + { + // Get our rank and DIY id + //const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank(); + const auto selfid = rp.gid(); + + std::vector incoming; + rp.incoming(incoming); + + for (const int ingid : incoming) + { + std::cout << rp.round() << std::endl; + auto roundNo = rp.round() - 1; + // NOTE/IMPORTANT: In each round we should have only one swap partner (despite for-loop here). + // If that assumption does not hold, it will break things. + // NOTE/IMPORTANT: This assumption only holds if the number of blocks is a power of two. + // Otherwise, we may need to process more than one incoming block + if (ingid != selfid) + { + vtkm::Id incomingBlockNo; + rp.dequeue(ingid, incomingBlockNo); + // std::cout << "Combining block " << b->BlockNo << " with " << incomingBlockNo << std::endl; + vtkm::cont::ArrayHandle incomingIntrinsicVolume; + rp.dequeue(ingid, incomingIntrinsicVolume); + vtkm::cont::ArrayHandle incomingDependentVolume; + rp.dequeue(ingid, incomingDependentVolume); + + // TODO/FIXME: Replace with something more efficient + vtkm::Id numSupernodesToProcess = + b->HierarchicalContourTree.FirstSupernodePerIteration[roundNo].ReadPortal().Get(0); + + /* + std::cout << "Block " << b->BlockNo << " Round " << roundNo << ": " << numSupernodesToProcess << " entries to process" << std::endl; + + vtkm::worklet::contourtree_augmented::PrintIndices( + "Intrinsic Volume (B)", b->IntrinsicVolume, -1, std::cout); + vtkm::worklet::contourtree_augmented::PrintIndices( + "Dependent Volume (B)", b->DependentVolume, -1, std::cout); + */ + auto intrinsicVolumeView = + make_ArrayHandleView(b->IntrinsicVolume, 0, numSupernodesToProcess); + auto incomingIntrinsicVolumeView = + make_ArrayHandleView(incomingIntrinsicVolume, 0, numSupernodesToProcess); + vtkm::cont::ArrayHandle tempSum; + vtkm::cont::Algorithm::Transform( + intrinsicVolumeView, incomingIntrinsicVolumeView, tempSum, vtkm::Sum()); + vtkm::cont::Algorithm::Copy(tempSum, intrinsicVolumeView); + + auto dependentVolumeView = + make_ArrayHandleView(b->DependentVolume, 0, numSupernodesToProcess); + auto incomingDependentVolumeView = + make_ArrayHandleView(incomingDependentVolume, 0, numSupernodesToProcess); + vtkm::cont::Algorithm::Transform( + dependentVolumeView, incomingDependentVolumeView, tempSum, vtkm::Sum()); + vtkm::cont::Algorithm::Copy(tempSum, dependentVolumeView); + + /* + vtkm::worklet::contourtree_augmented::PrintIndices( + "Intrinsic Volume (A)", b->IntrinsicVolume, -1, std::cout); + vtkm::worklet::contourtree_augmented::PrintIndices( + "Dependent Volume (A)", b->DependentVolume, -1, std::cout); + */ + } + } + + for (int cc = 0; cc < rp.out_link().size(); ++cc) + { + auto target = rp.out_link().target(cc); + if (target.gid != selfid) + { + rp.enqueue(target, b->BlockNo); + rp.enqueue(target, b->IntrinsicVolume); + rp.enqueue(target, b->DependentVolume); + } + } + } +}; + +} // namespace contourtree_distributed +} // namespace worklet +} // namespace vtkm + +#endif diff --git a/vtkm/worklet/contourtree_distributed/HyperSweepBlock.h b/vtkm/worklet/contourtree_distributed/HyperSweepBlock.h new file mode 100644 index 000000000..d45ebf2da --- /dev/null +++ b/vtkm/worklet/contourtree_distributed/HyperSweepBlock.h @@ -0,0 +1,104 @@ +//============================================================================ +// 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_hypersweepblock_h +#define vtk_m_worklet_contourtree_distributed_hypersweepblock_h + +#include +#include +#include + +namespace vtkm +{ +namespace worklet +{ +namespace contourtree_distributed +{ + +template +struct HyperSweepBlock +{ + HyperSweepBlock( + const vtkm::Id& blockNo, + const vtkm::Id3& origin, + const vtkm::Id3& size, + const vtkm::Id3& globalSize, + const vtkm::worklet::contourtree_distributed::HierarchicalContourTree& + hierarchicalContourTree) + : BlockNo(blockNo) + , Origin(origin) + , Size(size) + , GlobalSize(globalSize) + , HierarchicalContourTree(hierarchicalContourTree) + { + } + + // Mesh information + vtkm::Id BlockNo; + vtkm::Id3 Origin; + vtkm::Id3 Size; + vtkm::Id3 GlobalSize; + + // Hierarchical contour tree for this block + const vtkm::worklet::contourtree_distributed::HierarchicalContourTree& + HierarchicalContourTree; + + // Computed values + vtkm::cont::ArrayHandle IntrinsicVolume; + vtkm::cont::ArrayHandle DependentVolume; +}; + +} // namespace contourtree_distributed +} // namespace worklet +} // namespace vtkm + +#endif diff --git a/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx b/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx index 17f0ac13f..a1f2d875b 100644 --- a/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx +++ b/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx @@ -55,11 +55,12 @@ #include #include #include - #include #include +#include #include #include +#include #include // clang-format off @@ -120,124 +121,6 @@ static inline VTKM_CONT bool test_equal_portal_stl_vector(const PortalType1& por } */ -template -struct HyperSweepBlock -{ - HyperSweepBlock( - const vtkm::Id& blockNo, - const vtkm::Id3& origin, - const vtkm::Id3& size, - const vtkm::Id3& globalSize, - const vtkm::worklet::contourtree_distributed::HierarchicalContourTree& - hierarchicalContourTree) - : BlockNo(blockNo) - , Origin(origin) - , Size(size) - , GlobalSize(globalSize) - , HierarchicalContourTree(hierarchicalContourTree) - { - } - - // Mesh information - vtkm::Id BlockNo; - vtkm::Id3 Origin; - vtkm::Id3 Size; - vtkm::Id3 GlobalSize; - - // Hierarchical contour tree for this block - const vtkm::worklet::contourtree_distributed::HierarchicalContourTree& - HierarchicalContourTree; - - // Computed values - vtkm::cont::ArrayHandle IntrinsicVolume; - vtkm::cont::ArrayHandle DependentVolume; -}; - -template -struct CobmineHyperSweepBlockFunctor -{ - void operator()(HyperSweepBlock* b, - const vtkmdiy::ReduceProxy& rp, // communication proxy - const vtkmdiy::RegularSwapPartners& // partners of the current block (unused) - ) const - { - // Get our rank and DIY id - //const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank(); - const auto selfid = rp.gid(); - - std::vector incoming; - rp.incoming(incoming); - - for (const int ingid : incoming) - { - std::cout << rp.round() << std::endl; - auto roundNo = rp.round() - 1; - // NOTE/IMPORTANT: In each round we should have only one swap partner (despite for-loop here). - // If that assumption does not hold, it will break things. - // NOTE/IMPORTANT: This assumption only holds if the number of blocks is a power of two. - // Otherwise, we may need to process more than one incoming block - if (ingid != selfid) - { - vtkm::Id incomingBlockNo; - rp.dequeue(ingid, incomingBlockNo); - // std::cout << "Combining block " << b->BlockNo << " with " << incomingBlockNo << std::endl; - vtkm::cont::ArrayHandle incomingIntrinsicVolume; - rp.dequeue(ingid, incomingIntrinsicVolume); - vtkm::cont::ArrayHandle incomingDependentVolume; - rp.dequeue(ingid, incomingDependentVolume); - - // TODO/FIXME: Replace with something more efficient - vtkm::Id numSupernodesToProcess = - b->HierarchicalContourTree.FirstSupernodePerIteration[roundNo].ReadPortal().Get(0); - - /* - std::cout << "Block " << b->BlockNo << " Round " << roundNo << ": " << numSupernodesToProcess << " entries to process" << std::endl; - - vtkm::worklet::contourtree_augmented::PrintIndices( - "Intrinsic Volume (B)", b->IntrinsicVolume, -1, std::cout); - vtkm::worklet::contourtree_augmented::PrintIndices( - "Dependent Volume (B)", b->DependentVolume, -1, std::cout); - */ - auto intrinsicVolumeView = - make_ArrayHandleView(b->IntrinsicVolume, 0, numSupernodesToProcess); - auto incomingIntrinsicVolumeView = - make_ArrayHandleView(incomingIntrinsicVolume, 0, numSupernodesToProcess); - vtkm::cont::ArrayHandle tempSum; - vtkm::cont::Algorithm::Transform( - intrinsicVolumeView, incomingIntrinsicVolumeView, tempSum, vtkm::Sum()); - vtkm::cont::Algorithm::Copy(tempSum, intrinsicVolumeView); - - auto dependentVolumeView = - make_ArrayHandleView(b->DependentVolume, 0, numSupernodesToProcess); - auto incomingDependentVolumeView = - make_ArrayHandleView(incomingDependentVolume, 0, numSupernodesToProcess); - vtkm::cont::Algorithm::Transform( - dependentVolumeView, incomingDependentVolumeView, tempSum, vtkm::Sum()); - vtkm::cont::Algorithm::Copy(tempSum, dependentVolumeView); - - /* - vtkm::worklet::contourtree_augmented::PrintIndices( - "Intrinsic Volume (A)", b->IntrinsicVolume, -1, std::cout); - vtkm::worklet::contourtree_augmented::PrintIndices( - "Dependent Volume (A)", b->DependentVolume, -1, std::cout); - */ - } - } - - for (int cc = 0; cc < rp.out_link().size(); ++cc) - { - auto target = rp.out_link().target(cc); - if (target.gid != selfid) - { - rp.enqueue(target, b->BlockNo); - rp.enqueue(target, b->IntrinsicVolume); - rp.enqueue(target, b->DependentVolume); - } - } - } -}; - - void TestHierarchicalHyperSweeper() { using vtkm::cont::testing::Testing; @@ -323,62 +206,66 @@ void TestHierarchicalHyperSweeper() } vtkmdiy::fix_links(master, assigner); - HyperSweepBlock* localHyperSweeperBlocks[numBlocks]; + vtkm::worklet::contourtree_distributed::HyperSweepBlock* + localHyperSweeperBlocks[numBlocks]; for (vtkm::Id blockNo = 0; blockNo < numBlocks; ++blockNo) { - localHyperSweeperBlocks[blockNo] = new HyperSweepBlock( - blockNo, origins[blockNo], sizes[blockNo], globalSize, hct[blockNo]); + localHyperSweeperBlocks[blockNo] = + new vtkm::worklet::contourtree_distributed::HyperSweepBlock( + blockNo, origins[blockNo], sizes[blockNo], globalSize, hct[blockNo]); std::cout << blockNo << " -> " << vtkmdiyLocalBlockGids[blockNo] << std::endl; master.add( vtkmdiyLocalBlockGids[blockNo], localHyperSweeperBlocks[blockNo], new vtkmdiy::Link()); } - master.foreach ([](HyperSweepBlock* b, - const vtkmdiy::Master::ProxyWithLink&) { - // Create HyperSweeper - std::cout << "Block " << b->BlockNo << std::endl; - std::cout << b->HierarchicalContourTree.DebugPrint( - "Before initializing HyperSweeper", __FILE__, __LINE__); - vtkm::worklet::contourtree_distributed::HierarchicalHyperSweeper - hyperSweeper(b->BlockNo, b->HierarchicalContourTree, b->IntrinsicVolume, b->DependentVolume); + master.foreach ( + [](vtkm::worklet::contourtree_distributed::HyperSweepBlock* b, + const vtkmdiy::Master::ProxyWithLink&) { + // Create HyperSweeper + std::cout << "Block " << b->BlockNo << std::endl; + std::cout << b->HierarchicalContourTree.DebugPrint( + "Before initializing HyperSweeper", __FILE__, __LINE__); + vtkm::worklet::contourtree_distributed::HierarchicalHyperSweeper + hyperSweeper( + b->BlockNo, b->HierarchicalContourTree, b->IntrinsicVolume, b->DependentVolume); - std::cout << "Block " << b->BlockNo << std::endl; - std::cout << b->HierarchicalContourTree.DebugPrint( - "After initializing HyperSweeper", __FILE__, __LINE__); - // Create mesh and initialize vertex counts - vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler idRelabeler{ b->Origin, - b->Size, - b->GlobalSize }; + std::cout << "Block " << b->BlockNo << std::endl; + std::cout << b->HierarchicalContourTree.DebugPrint( + "After initializing HyperSweeper", __FILE__, __LINE__); + // Create mesh and initialize vertex counts + vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler idRelabeler{ b->Origin, + b->Size, + b->GlobalSize }; - if (b->GlobalSize[2] <= 1) - { - vtkm::worklet::contourtree_augmented::DataSetMeshTriangulation2DFreudenthal mesh( - vtkm::Id2{ b->Size[0], b->Size[1] }); - hyperSweeper.InitializeIntrinsicVertexCount( - b->HierarchicalContourTree, mesh, idRelabeler, b->IntrinsicVolume); - } - else - { - // TODO/FIXME: For getting owned vertices, it should not make a difference if marching - // cubes or not. Verify. - vtkm::worklet::contourtree_augmented::DataSetMeshTriangulation3DFreudenthal mesh(b->Size); - hyperSweeper.InitializeIntrinsicVertexCount( - b->HierarchicalContourTree, mesh, idRelabeler, b->IntrinsicVolume); - } + if (b->GlobalSize[2] <= 1) + { + vtkm::worklet::contourtree_augmented::DataSetMeshTriangulation2DFreudenthal mesh( + vtkm::Id2{ b->Size[0], b->Size[1] }); + hyperSweeper.InitializeIntrinsicVertexCount( + b->HierarchicalContourTree, mesh, idRelabeler, b->IntrinsicVolume); + } + else + { + // TODO/FIXME: For getting owned vertices, it should not make a difference if marching + // cubes or not. Verify. + vtkm::worklet::contourtree_augmented::DataSetMeshTriangulation3DFreudenthal mesh(b->Size); + hyperSweeper.InitializeIntrinsicVertexCount( + b->HierarchicalContourTree, mesh, idRelabeler, b->IntrinsicVolume); + } - std::cout << "Block " << b->BlockNo << std::endl; - std::cout << b->HierarchicalContourTree.DebugPrint( - "After initializing intrinsic vertex count", __FILE__, __LINE__); - // Initialize dependentVolume by copy from intrinsicVolume - vtkm::cont::Algorithm::Copy(b->IntrinsicVolume, b->DependentVolume); + std::cout << "Block " << b->BlockNo << std::endl; + std::cout << b->HierarchicalContourTree.DebugPrint( + "After initializing intrinsic vertex count", __FILE__, __LINE__); + // Initialize dependentVolume by copy from intrinsicVolume + vtkm::cont::Algorithm::Copy(b->IntrinsicVolume, b->DependentVolume); - // Perform the local hypersweep - hyperSweeper.LocalHyperSweep(); - std::cout << "Block " << b->BlockNo << std::endl; - std::cout << b->HierarchicalContourTree.DebugPrint( - "After local hypersweep", __FILE__, __LINE__); - }); + // Perform the local hypersweep + hyperSweeper.LocalHyperSweep(); + std::cout << "Block " << b->BlockNo << std::endl; + std::cout << b->HierarchicalContourTree.DebugPrint( + "After local hypersweep", __FILE__, __LINE__); + }); // Reduce // partners for merge over regular block grid @@ -387,29 +274,32 @@ void TestHierarchicalHyperSweeper() 2, // radix of k-ary reduction. true // contiguous: true=distance doubling, false=distance halving ); - vtkmdiy::reduce( - master, assigner, partners, CobmineHyperSweepBlockFunctor{}); - - + vtkmdiy::reduce(master, + assigner, + partners, + vtkm::worklet::contourtree_distributed::CobmineHyperSweepBlockFunctor< + ContourTreeDataFieldType>{}); // Print vtkm::Id totalVolume = globalSize[0] * globalSize[1] * globalSize[2]; - master.foreach ([&totalVolume](HyperSweepBlock* b, - const vtkmdiy::Master::ProxyWithLink&) { - std::cout << "Block " << b->BlockNo << std::endl; - std::cout << "=========" << std::endl; - vtkm::worklet::contourtree_augmented::PrintHeader(b->IntrinsicVolume.GetNumberOfValues(), - std::cout); - vtkm::worklet::contourtree_augmented::PrintIndices( - "Intrinsic Volume", b->IntrinsicVolume, -1, std::cout); - vtkm::worklet::contourtree_augmented::PrintIndices( - "Dependent Volume", b->DependentVolume, -1, std::cout); + master.foreach ( + [&totalVolume]( + vtkm::worklet::contourtree_distributed::HyperSweepBlock* b, + const vtkmdiy::Master::ProxyWithLink&) { + std::cout << "Block " << b->BlockNo << std::endl; + std::cout << "=========" << std::endl; + vtkm::worklet::contourtree_augmented::PrintHeader(b->IntrinsicVolume.GetNumberOfValues(), + std::cout); + vtkm::worklet::contourtree_augmented::PrintIndices( + "Intrinsic Volume", b->IntrinsicVolume, -1, std::cout); + vtkm::worklet::contourtree_augmented::PrintIndices( + "Dependent Volume", b->DependentVolume, -1, std::cout); - std::cout << b->HierarchicalContourTree.DebugPrint( - "Called from DumpVolumes", __FILE__, __LINE__); - std::cout << b->HierarchicalContourTree.DumpVolumes( - totalVolume, b->IntrinsicVolume, b->DependentVolume); - }); + std::cout << b->HierarchicalContourTree.DebugPrint( + "Called from DumpVolumes", __FILE__, __LINE__); + std::cout << b->HierarchicalContourTree.DumpVolumes( + totalVolume, b->IntrinsicVolume, b->DependentVolume); + }); // Clean-up for (auto b : localHyperSweeperBlocks)