mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Move computing branch decomposition to a separate filter
This commit is contained in:
parent
4fe495be8d
commit
f871f51cb8
@ -72,11 +72,12 @@
|
||||
#include <vtkm/io/BOVDataSetReader.h>
|
||||
|
||||
#include <vtkm/filter/ContourTreeUniformDistributed.h>
|
||||
#include <vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/PrintVectors.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/ProcessContourTree.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalContourTree.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalVolumetricBranchDecomposer.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/TreeCompiler.h>
|
||||
|
||||
// clang-format off
|
||||
@ -862,19 +863,17 @@ int main(int argc, char* argv[])
|
||||
prevTime = currTime;
|
||||
|
||||
// Convert the mesh of values into contour tree, pairs of vertex ids
|
||||
vtkm::filter::ContourTreeUniformDistributed filter(
|
||||
blocksPerDim,
|
||||
globalSize,
|
||||
localBlockIndices,
|
||||
localBlockOrigins,
|
||||
localBlockSizes,
|
||||
useBoundaryExtremaOnly,
|
||||
useMarchingCubes,
|
||||
augmentHierarchicalTree,
|
||||
computeHierarchicalVolumetricBranchDecomposition,
|
||||
saveDotFiles,
|
||||
timingsLogLevel,
|
||||
treeLogLevel);
|
||||
vtkm::filter::ContourTreeUniformDistributed filter(blocksPerDim,
|
||||
globalSize,
|
||||
localBlockIndices,
|
||||
localBlockOrigins,
|
||||
localBlockSizes,
|
||||
useBoundaryExtremaOnly,
|
||||
useMarchingCubes,
|
||||
augmentHierarchicalTree,
|
||||
saveDotFiles,
|
||||
timingsLogLevel,
|
||||
treeLogLevel);
|
||||
filter.SetActiveField("values");
|
||||
|
||||
// Execute the contour tree analysis
|
||||
@ -896,17 +895,20 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
if (computeHierarchicalVolumetricBranchDecomposition)
|
||||
{
|
||||
vtkm::filter::scalar_topology::DistributedBranchDecompositionFilter bd_filter(
|
||||
blocksPerDim, globalSize, localBlockIndices, localBlockOrigins, localBlockSizes);
|
||||
auto bd_result = bd_filter.Execute(result);
|
||||
|
||||
for (vtkm::Id ds_no = 0; ds_no < result.GetNumberOfPartitions(); ++ds_no)
|
||||
{
|
||||
auto ds = result.GetPartition(ds_no);
|
||||
auto ds = bd_result.GetPartition(ds_no);
|
||||
std::string branchDecompositionFileName = std::string("BranchDecomposition_Rank_") +
|
||||
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
|
||||
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
|
||||
|
||||
std::ofstream treeStream(branchDecompositionFileName.c_str());
|
||||
treeStream
|
||||
<< vtkm::worklet::contourtree_distributed::HierarchicalVolumetricBranchDecomposer<
|
||||
ValueType>::PrintBranches(ds);
|
||||
treeStream << vtkm::worklet::scalar_topology::HierarchicalVolumetricBranchDecomposer::
|
||||
PrintBranches(ds);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -199,6 +199,7 @@ add_subdirectory(geometry_refinement)
|
||||
add_subdirectory(mesh_info)
|
||||
add_subdirectory(multi_block)
|
||||
add_subdirectory(resampling)
|
||||
add_subdirectory(scalar_topology)
|
||||
add_subdirectory(vector_analysis)
|
||||
add_subdirectory(zfp)
|
||||
|
||||
|
@ -119,7 +119,6 @@ public:
|
||||
bool useBoundaryExtremaOnly = true,
|
||||
bool useMarchingCubes = false,
|
||||
bool augmentHierarchicalTree = false,
|
||||
bool computeHierarchicalVolumetricBranchDecomposition = false,
|
||||
bool saveDotFiles = false,
|
||||
vtkm::cont::LogLevel timingsLogLevel = vtkm::cont::LogLevel::Perf,
|
||||
vtkm::cont::LogLevel treeLogLevel = vtkm::cont::LogLevel::Info);
|
||||
@ -173,14 +172,6 @@ public:
|
||||
std::stringstream& timingsStream,
|
||||
std::vector<vtkm::cont::DataSet>& hierarchicalTreeOutputDataSet);
|
||||
|
||||
template <typename FieldType>
|
||||
VTKM_CONT void ComputeBranchDecomposition(vtkmdiy::Master& inputContourTreeMaster,
|
||||
vtkmdiy::DynamicAssigner& assigner,
|
||||
vtkmdiy::RegularSwapPartners& partners,
|
||||
const FieldType&, // dummy parameter to get the type
|
||||
std::stringstream& timingsStream,
|
||||
std::vector<vtkm::cont::DataSet>& outputDataSet);
|
||||
|
||||
///
|
||||
/// Internal helper function that implements the actual functionality of PostExecute
|
||||
///
|
||||
@ -205,9 +196,6 @@ private:
|
||||
/// Augment hierarchical tree
|
||||
bool AugmentHierarchicalTree;
|
||||
|
||||
/// Compute the hierarchical volumetric branch decomposition
|
||||
bool ComputeHierarchicalVolumetricBranchDecomposition;
|
||||
|
||||
/// Save dot files for all tree computations
|
||||
bool SaveDotFiles;
|
||||
|
||||
|
@ -66,15 +66,12 @@
|
||||
// distributed contour tree includes
|
||||
#include <vtkm/worklet/contourtree_distributed/BoundaryTree.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/BoundaryTreeMaker.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/BranchDecompositionBlock.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/CombineHyperSweepBlockFunctor.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/ComputeDistributedBranchDecompositionFunctor.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/ComputeDistributedContourTreeFunctor.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/DistributedContourTreeBlockData.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalAugmenter.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalAugmenterFunctor.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalHyperSweeper.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalVolumetricBranchDecomposer.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HyperSweepBlock.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/InteriorForest.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/PrintGraph.h>
|
||||
@ -211,7 +208,6 @@ ContourTreeUniformDistributed::ContourTreeUniformDistributed(
|
||||
bool useBoundaryExtremaOnly,
|
||||
bool useMarchingCubes,
|
||||
bool augmentHierarchicalTree,
|
||||
bool computeHierarchicalVolumetricBranchDecomposition,
|
||||
bool saveDotFiles,
|
||||
vtkm::cont::LogLevel timingsLogLevel,
|
||||
vtkm::cont::LogLevel treeLogLevel)
|
||||
@ -219,8 +215,6 @@ ContourTreeUniformDistributed::ContourTreeUniformDistributed(
|
||||
, UseBoundaryExtremaOnly(useBoundaryExtremaOnly)
|
||||
, UseMarchingCubes(useMarchingCubes)
|
||||
, AugmentHierarchicalTree(augmentHierarchicalTree)
|
||||
, ComputeHierarchicalVolumetricBranchDecomposition(
|
||||
computeHierarchicalVolumetricBranchDecomposition)
|
||||
, SaveDotFiles(saveDotFiles)
|
||||
, TimingsLogLevel(timingsLogLevel)
|
||||
, TreeLogLevel(treeLogLevel)
|
||||
@ -235,13 +229,6 @@ ContourTreeUniformDistributed::ContourTreeUniformDistributed(
|
||||
, LocalInteriorForests(static_cast<std::size_t>(localBlockSizes.GetNumberOfValues()))
|
||||
{
|
||||
this->SetOutputFieldName("resultData");
|
||||
if (this->ComputeHierarchicalVolumetricBranchDecomposition && !this->AugmentHierarchicalTree)
|
||||
{
|
||||
this->AugmentHierarchicalTree = true;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Error,
|
||||
"Volumetric branch decmomposition requires augmentation. "
|
||||
<< "Enabling the AugmentHierarchicalTree option.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -842,144 +829,6 @@ inline VTKM_CONT void ContourTreeUniformDistributed::ComputeVolumeMetric(
|
||||
});
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename FieldType>
|
||||
inline VTKM_CONT void ContourTreeUniformDistributed::ComputeBranchDecomposition(
|
||||
vtkmdiy::Master& inputContourTreeMaster,
|
||||
vtkmdiy::DynamicAssigner& assigner,
|
||||
vtkmdiy::RegularSwapPartners& partners,
|
||||
const FieldType&, // dummy parameter to get the type
|
||||
std::stringstream& timingsStream,
|
||||
std::vector<vtkm::cont::DataSet>& outputDataSet)
|
||||
{
|
||||
vtkm::cont::Timer timer;
|
||||
timer.Start();
|
||||
|
||||
using BranchDecompositionBlock =
|
||||
vtkm::worklet::contourtree_distributed::BranchDecompositionBlock<FieldType>;
|
||||
|
||||
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
|
||||
vtkmdiy::Master branch_decomposition_master(comm,
|
||||
1, // Use 1 thread, VTK-M will do the treading
|
||||
-1, // All blocks in memory
|
||||
0, // No create function
|
||||
BranchDecompositionBlock::Destroy);
|
||||
|
||||
// Log the time to create the DIY master for the hyper sweep
|
||||
timingsStream << " " << std::setw(38) << std::left
|
||||
<< "Create DIY Master (Branch Decomposition):" << timer.GetElapsedTime()
|
||||
<< " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Copy data from hierarchical hypersweep to initialize branch decomposition computation
|
||||
using DistributedContourTreeBlockData =
|
||||
vtkm::worklet::contourtree_distributed::DistributedContourTreeBlockData<FieldType>;
|
||||
inputContourTreeMaster.foreach (
|
||||
[&](DistributedContourTreeBlockData* currInBlock, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
BranchDecompositionBlock* newBlock = new BranchDecompositionBlock(
|
||||
currInBlock->LocalBlockNo, currInBlock->GlobalBlockId, currInBlock->AugmentedTree);
|
||||
// NOTE: Use dummy link to make DIY happy. The dummy link is never used, since all
|
||||
// communication is via RegularDecomposer, which sets up its own links. No need
|
||||
// to keep the pointer, as DIY will "own" it and delete it when no longer needed.
|
||||
// NOTE: Since we passed a "Destroy" function to DIY master, it will own the local data
|
||||
// blocks and delete them when done.
|
||||
branch_decomposition_master.add(currInBlock->GlobalBlockId, newBlock, new vtkmdiy::Link());
|
||||
});
|
||||
|
||||
// Log time to copy the data to the HyperSweepBlock data objects
|
||||
timingsStream << " " << std::setw(38) << std::left << "Initialize Branch Decomposition Data"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
vtkmdiy::fix_links(branch_decomposition_master, assigner);
|
||||
|
||||
// Record time to fix the links
|
||||
timingsStream << " " << std::setw(38) << std::left << "Fix DIY Links (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
branch_decomposition_master.foreach (
|
||||
[&](BranchDecompositionBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
// Get intrinsic and dependent volume from data set
|
||||
vtkm::cont::DataSet ds = outputDataSet[b->LocalBlockNo];
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> intrinsicVolume =
|
||||
ds.GetField("IntrinsicVolume").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> dependentVolume =
|
||||
ds.GetField("DependentVolume").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
// Get global size and compute total volume from it
|
||||
const auto& globalSize = this->MultiBlockSpatialDecomposition.GlobalSize;
|
||||
vtkm::Id totalVolume = globalSize[0] * globalSize[1] * globalSize[2];
|
||||
|
||||
// Compute local best up and down paths by volume
|
||||
b->HierarchicalVolumetricBranchDecomposer.LocalBestUpDownByVolume(
|
||||
&b->HierarchicalContourTree, intrinsicVolume, dependentVolume, totalVolume);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(this->TreeLogLevel, "Before reduction");
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(
|
||||
b->HierarchicalVolumetricBranchDecomposer.BestUpSupernode.GetNumberOfValues(), rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpSupernode", b->HierarchicalVolumetricBranchDecomposer.BestUpSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownSupernode", b->HierarchicalVolumetricBranchDecomposer.BestDownSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpVolume", b->HierarchicalVolumetricBranchDecomposer.BestUpVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownVolume", b->HierarchicalVolumetricBranchDecomposer.BestDownVolume, -1, rs);
|
||||
VTKM_LOG_S(this->TreeLogLevel, rs.str());
|
||||
}
|
||||
#endif
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left << "LocalBestUpDownByVolume"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Reduce
|
||||
// partners for merge over regular block grid
|
||||
vtkmdiy::reduce(
|
||||
branch_decomposition_master,
|
||||
assigner,
|
||||
partners,
|
||||
vtkm::worklet::contourtree_distributed::ComputeDistributedBranchDecompositionFunctor<
|
||||
FieldType>{});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left
|
||||
<< "Exchanging best up/down supernode and volume"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
branch_decomposition_master.foreach (
|
||||
[&](BranchDecompositionBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
b->HierarchicalVolumetricBranchDecomposer.CollapseBranches(&b->HierarchicalContourTree,
|
||||
b->BranchRoots);
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left << "CollapseBranches"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
branch_decomposition_master.foreach ([&](BranchDecompositionBlock* b,
|
||||
const vtkmdiy::Master::ProxyWithLink&) {
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(this->TreeLogLevel,
|
||||
b->HierarchicalVolumetricBranchDecomposer.PrintBranches(&b->HierarchicalContourTree,
|
||||
b->BranchRoots));
|
||||
#endif
|
||||
vtkm::cont::Field branchRootField(
|
||||
"BranchRoots", vtkm::cont::Field::Association::WholeMesh, b->BranchRoots);
|
||||
outputDataSet[b->LocalBlockNo].AddField(branchRootField);
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left
|
||||
<< "Creating Branch Decomposition Output Data"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename FieldType, typename StorageType, typename DerivedPolicy>
|
||||
VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute(
|
||||
@ -1350,77 +1199,61 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute(
|
||||
|
||||
// ******** 5. Create output data set ********
|
||||
std::vector<vtkm::cont::DataSet> hierarchicalTreeOutputDataSet(master.size());
|
||||
master.foreach (
|
||||
[&](DistributedContourTreeBlockData* blockData, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
std::stringstream createOutdataTimingsStream;
|
||||
vtkm::cont::Timer iterationTimer;
|
||||
iterationTimer.Start();
|
||||
master.foreach ([&](DistributedContourTreeBlockData* blockData,
|
||||
const vtkmdiy::Master::ProxyWithLink&) {
|
||||
std::stringstream createOutdataTimingsStream;
|
||||
vtkm::cont::Timer iterationTimer;
|
||||
iterationTimer.Start();
|
||||
|
||||
// Use the augmented tree if available or otherwise use the unaugmented hierarchical tree from the current block
|
||||
auto blockHierarchcialTree = this->AugmentHierarchicalTree
|
||||
? (*blockData->HierarchicalAugmenter.AugmentedTree)
|
||||
: blockData->HierarchicalTree;
|
||||
// Use the augmented tree if available or otherwise use the unaugmented hierarchical tree from the current block
|
||||
const auto& blockHierarchcialTree = this->AugmentHierarchicalTree
|
||||
? (*blockData->HierarchicalAugmenter.AugmentedTree)
|
||||
: blockData->HierarchicalTree;
|
||||
|
||||
// Create data set from output
|
||||
vtkm::cont::Field dataValuesField(
|
||||
"DataValues", vtkm::cont::Field::Association::WholeMesh, blockHierarchcialTree.DataValues);
|
||||
hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].AddField(dataValuesField);
|
||||
vtkm::cont::Field regularNodeGlobalIdsField("RegularNodeGlobalIds",
|
||||
vtkm::cont::Field::Association::WholeMesh,
|
||||
blockHierarchcialTree.RegularNodeGlobalIds);
|
||||
hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].AddField(regularNodeGlobalIdsField);
|
||||
vtkm::cont::Field superarcsField(
|
||||
"Superarcs", vtkm::cont::Field::Association::WholeMesh, blockHierarchcialTree.Superarcs);
|
||||
hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].AddField(superarcsField);
|
||||
vtkm::cont::Field supernodesField(
|
||||
"Supernodes", vtkm::cont::Field::Association::WholeMesh, blockHierarchcialTree.Supernodes);
|
||||
hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].AddField(supernodesField);
|
||||
vtkm::cont::Field superparentsField("Superparents",
|
||||
vtkm::cont::Field::Association::WholeMesh,
|
||||
blockHierarchcialTree.Superparents);
|
||||
hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].AddField(superparentsField);
|
||||
// Add the information to the output data set
|
||||
blockHierarchcialTree.AddToVTKMDataSet(hierarchicalTreeOutputDataSet[blockData->LocalBlockNo]);
|
||||
|
||||
// Copy cell set from input data set. This is mainly to ensure that the output data set
|
||||
// has a defined cell set. Without one, serialization for DIY does not work properly.
|
||||
// Having the extents of the input data set may also help in other use cases.
|
||||
hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].SetCellSet(
|
||||
input.GetPartition(blockData->LocalBlockNo).GetCellSet());
|
||||
// Copy cell set from input data set. This is mainly to ensure that the output data set
|
||||
// has a defined cell set. Without one, serialization for DIY does not work properly.
|
||||
// Having the extents of the input data set may also help in other use cases.
|
||||
hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].SetCellSet(
|
||||
input.GetPartition(blockData->LocalBlockNo).GetCellSet());
|
||||
|
||||
// Log the time for each of the iterations of the fan out loop
|
||||
createOutdataTimingsStream << " Create Output Dataset (block=" << blockData->LocalBlockNo
|
||||
// Log the time for each of the iterations of the fan out loop
|
||||
createOutdataTimingsStream << " Create Output Dataset (block=" << blockData->LocalBlockNo
|
||||
<< ") : " << iterationTimer.GetElapsedTime() << " seconds"
|
||||
<< std::endl;
|
||||
iterationTimer.Start();
|
||||
|
||||
// save the corresponding .gv file
|
||||
if (this->SaveDotFiles)
|
||||
{
|
||||
auto nRounds = blockData->ContourTrees.size() - 1;
|
||||
vtkm::filter::contourtree_distributed_detail::SaveHierarchicalTreeDot(
|
||||
blockData, rank, nRounds);
|
||||
|
||||
createOutdataTimingsStream << " Save Dot (block=" << blockData->LocalBlockNo
|
||||
<< ") : " << iterationTimer.GetElapsedTime() << " seconds"
|
||||
<< std::endl;
|
||||
iterationTimer.Start();
|
||||
} // if(this->SaveDotFiles)
|
||||
|
||||
// save the corresponding .gv file
|
||||
if (this->SaveDotFiles)
|
||||
{
|
||||
auto nRounds = blockData->ContourTrees.size() - 1;
|
||||
vtkm::filter::contourtree_distributed_detail::SaveHierarchicalTreeDot(
|
||||
blockData, rank, nRounds);
|
||||
// Log the timing stats we collected
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< " ------------ Create Output Data (block=" << blockData->LocalBlockNo
|
||||
<< ") ------------" << std::endl
|
||||
<< createOutdataTimingsStream.str());
|
||||
|
||||
createOutdataTimingsStream << " Save Dot (block=" << blockData->LocalBlockNo
|
||||
<< ") : " << iterationTimer.GetElapsedTime() << " seconds"
|
||||
<< std::endl;
|
||||
iterationTimer.Start();
|
||||
} // if(this->SaveDotFiles)
|
||||
|
||||
// Log the timing stats we collected
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< " ------------ Create Output Data (block=" << blockData->LocalBlockNo
|
||||
<< ") ------------" << std::endl
|
||||
<< createOutdataTimingsStream.str());
|
||||
|
||||
// Log the stats from the hierarchical contour tree
|
||||
VTKM_LOG_S(this->TreeLogLevel,
|
||||
std::endl
|
||||
<< " ------------ Hierarchical Tree Construction Stats ------------"
|
||||
<< std::endl
|
||||
<< std::setw(42) << std::left << " LocalBlockNo"
|
||||
<< ": " << blockData->LocalBlockNo << std::endl
|
||||
<< blockData->HierarchicalTree.PrintTreeStats() << std::endl);
|
||||
}); // master.foreach
|
||||
// Log the stats from the hierarchical contour tree
|
||||
VTKM_LOG_S(this->TreeLogLevel,
|
||||
std::endl
|
||||
<< " ------------ Hierarchical Tree Construction Stats ------------"
|
||||
<< std::endl
|
||||
<< std::setw(42) << std::left << " LocalBlockNo"
|
||||
<< ": " << blockData->LocalBlockNo << std::endl
|
||||
<< blockData->HierarchicalTree.PrintTreeStats() << std::endl);
|
||||
}); // master.foreach
|
||||
|
||||
// 3.1 Log total augmentation time
|
||||
timingsStream << " " << std::setw(38) << std::left << "Create Output Data"
|
||||
@ -1433,12 +1266,6 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute(
|
||||
master, assigner, partners, FieldType{}, timingsStream, hierarchicalTreeOutputDataSet);
|
||||
}
|
||||
|
||||
if (this->ComputeHierarchicalVolumetricBranchDecomposition)
|
||||
{
|
||||
this->ComputeBranchDecomposition(
|
||||
master, assigner, partners, FieldType{}, timingsStream, hierarchicalTreeOutputDataSet);
|
||||
}
|
||||
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< " ------------ DoPostExecute Timings ------------" << std::endl
|
||||
|
99
vtkm/filter/scalar_topology/BranchDecompositionBlock.cxx
Normal file
99
vtkm/filter/scalar_topology/BranchDecompositionBlock.cxx
Normal file
@ -0,0 +1,99 @@
|
||||
//============================================================================
|
||||
// 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)
|
||||
//==============================================================================
|
||||
|
||||
#include <vtkm/filter/scalar_topology/BranchDecompositionBlock.h>
|
||||
|
||||
// Contour tree includes, not ye moved to new filter design
|
||||
#include <vtkm/worklet/contourtree/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
|
||||
vtkm::cont::ArrayHandleGroupVecVariable<vtkm::cont::ArrayHandle<vtkm::Id>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id>>
|
||||
BranchDecompositionBlock::CreateFirstsupernodePerIterationArrayHandle(
|
||||
const vtkm::cont::DataSet& hierarchicalContourTreeDataSet)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> FirstSupernodePerIterationComponents;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> FirstSupernodePerIterationOffsets;
|
||||
|
||||
vtkm::cont::ArrayCopyShallowIfPossible(
|
||||
hierarchicalContourTreeDataSet.GetField("FirstSupernodePerIterationComponents").GetData(),
|
||||
FirstSupernodePerIterationComponents);
|
||||
vtkm::cont::ArrayCopyShallowIfPossible(
|
||||
hierarchicalContourTreeDataSet.GetField("FirstSupernodePerIterationOffsets").GetData(),
|
||||
FirstSupernodePerIterationOffsets);
|
||||
return vtkm::cont::make_ArrayHandleGroupVecVariable(FirstSupernodePerIterationComponents,
|
||||
FirstSupernodePerIterationOffsets);
|
||||
}
|
||||
|
||||
BranchDecompositionBlock::BranchDecompositionBlock(
|
||||
vtkm::Id localBlockNo,
|
||||
int globalBlockId,
|
||||
const vtkm::cont::DataSet& hierarchicalTreeDataSet)
|
||||
: LocalBlockNo(localBlockNo)
|
||||
, GlobalBlockId(globalBlockId)
|
||||
, FirstSupernodePerIteration(CreateFirstsupernodePerIterationArrayHandle(hierarchicalTreeDataSet))
|
||||
{
|
||||
vtkm::Id nSupernodes =
|
||||
hierarchicalTreeDataSet.GetField("Supernodes").GetData().GetNumberOfValues();
|
||||
this->BranchRoots.AllocateAndFill(nSupernodes,
|
||||
vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT);
|
||||
}
|
||||
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
@ -53,55 +53,45 @@
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_branchdecompositionblock_h
|
||||
#define vtk_m_worklet_contourtree_distributed_branchdecompositionblock_h
|
||||
|
||||
#include <vtkm/worklet/contourtree/Types.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalContourTree.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalVolumetricBranchDecomposer.h>
|
||||
// Contour tree includes
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
|
||||
template <typename ContourTreeDataFieldType>
|
||||
struct BranchDecompositionBlock
|
||||
{
|
||||
BranchDecompositionBlock(
|
||||
vtkm::Id localBlockNo,
|
||||
int globalBlockId,
|
||||
const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<ContourTreeDataFieldType>&
|
||||
hierarchicalContourTree)
|
||||
: LocalBlockNo(localBlockNo)
|
||||
, GlobalBlockId(globalBlockId)
|
||||
, HierarchicalContourTree(hierarchicalContourTree)
|
||||
{
|
||||
// Import/alias for readability
|
||||
using vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
const vtkm::Id nSupernodes = HierarchicalContourTree.Supernodes.GetNumberOfValues();
|
||||
//VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Allocating " << nSupernodes << " valies in BranchRoots");
|
||||
BranchRoots.AllocateAndFill(nSupernodes, NO_SUCH_ELEMENT);
|
||||
}
|
||||
static vtkm::cont::ArrayHandleGroupVecVariable<vtkm::cont::ArrayHandle<vtkm::Id>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id>>
|
||||
CreateFirstsupernodePerIterationArrayHandle(
|
||||
const vtkm::cont::DataSet& hierarchicalContourTreeDataSet);
|
||||
|
||||
// Block metadata TODO/FIXME: Check whether really needed
|
||||
BranchDecompositionBlock(vtkm::Id localBlockNo,
|
||||
int globalBlockId,
|
||||
const vtkm::cont::DataSet& hierarchicalTreeDataSet);
|
||||
|
||||
// Block metadata
|
||||
vtkm::Id LocalBlockNo;
|
||||
int GlobalBlockId;
|
||||
int GlobalBlockId; // TODO/FIXME: Check whether really needed. Possibly only during debugging
|
||||
|
||||
const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<ContourTreeDataFieldType>&
|
||||
HierarchicalContourTree;
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalVolumetricBranchDecomposer<
|
||||
ContourTreeDataFieldType>
|
||||
HierarchicalVolumetricBranchDecomposer;
|
||||
// Data from hierarchical tree needed during reduction
|
||||
vtkm::cont::ArrayHandleGroupVecVariable<vtkm::cont::ArrayHandle<vtkm::Id>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id>>
|
||||
FirstSupernodePerIteration;
|
||||
|
||||
// Decomposer used during reduction and output data set
|
||||
HierarchicalVolumetricBranchDecomposer VolumetricBranchDecomposer;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> BranchRoots;
|
||||
|
||||
// Destroy function allowing DIY to own blocks and clean them up after use
|
||||
static void Destroy(void* b)
|
||||
{
|
||||
delete static_cast<BranchDecompositionBlock<ContourTreeDataFieldType>*>(b);
|
||||
}
|
||||
static void Destroy(void* b) { delete static_cast<BranchDecompositionBlock*>(b); }
|
||||
};
|
||||
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
#endif
|
49
vtkm/filter/scalar_topology/CMakeLists.txt
Normal file
49
vtkm/filter/scalar_topology/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
||||
##============================================================================
|
||||
## 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.
|
||||
##============================================================================
|
||||
set(scalar_topology_headers
|
||||
BranchDecompositionBlock.h
|
||||
ComputeDistributedBranchDecompositionFunctor.h
|
||||
DistributedBranchDecompositionFilter.h
|
||||
)
|
||||
|
||||
set(scalar_topology_sources
|
||||
BranchDecompositionBlock.cxx
|
||||
ComputeDistributedBranchDecompositionFunctor.cxx
|
||||
DistributedBranchDecompositionFilter.cxx
|
||||
)
|
||||
|
||||
# TODO/FIXME: Is the following line needed
|
||||
# set_source_files_properties(DistributedBranchDecompositionFilter.cxx PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
|
||||
vtkm_library(
|
||||
NAME vtkm_filter_scalar_topology
|
||||
HEADERS ${scalar_topology_headers}
|
||||
DEVICE_SOURCES ${scalar_topology_sources}
|
||||
USE_VTKM_JOB_POOL
|
||||
)
|
||||
|
||||
# TODO/FIXME: Are the following lines needed
|
||||
# set_property(TARGET
|
||||
# vtkm_filter_scalar_topology
|
||||
# PROPERTY UNITY_BUILD_MODE GROUP
|
||||
# )
|
||||
|
||||
target_link_libraries(vtkm_filter_scalar_topology PUBLIC vtkm_worklet vtkm_filter_core)
|
||||
if (VTKm_ENABLE_MPI)
|
||||
target_link_libraries(vtkm_filter_scalar_topology PUBLIC MPI::MPI_CXX)
|
||||
endif ()
|
||||
target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_scalar_topology)
|
||||
|
||||
add_subdirectory(worklet)
|
||||
|
||||
#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
|
||||
if (VTKm_ENABLE_TESTING)
|
||||
add_subdirectory(testing)
|
||||
endif ()
|
@ -0,0 +1,220 @@
|
||||
//============================================================================
|
||||
// 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)
|
||||
//==============================================================================
|
||||
|
||||
#include <vtkm/filter/scalar_topology/ComputeDistributedBranchDecompositionFunctor.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/FindBestSupernodeWorklet.h>
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#define DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
#endif
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
|
||||
void ComputeDistributedBranchDecompositionFunctor::operator()(
|
||||
vtkm::worklet::scalar_topology::BranchDecompositionBlock* 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();
|
||||
|
||||
// Aliases to reduce verbosity
|
||||
auto& branchDecomposer = b->VolumetricBranchDecomposer;
|
||||
|
||||
std::vector<int> incoming;
|
||||
rp.incoming(incoming);
|
||||
for (const int ingid : incoming)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
int incomingGlobalBlockId;
|
||||
rp.dequeue(ingid, incomingGlobalBlockId);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Combining local block " << b->GlobalBlockId << " with incomoing block "
|
||||
<< incomingGlobalBlockId);
|
||||
#endif
|
||||
|
||||
// Receive data from swap partner
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestUpVolume;
|
||||
rp.dequeue(ingid, incomingBestUpVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestUpSupernode;
|
||||
rp.dequeue(ingid, incomingBestUpSupernode);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestDownVolume;
|
||||
rp.dequeue(ingid, incomingBestDownVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestDownSupernode;
|
||||
rp.dequeue(ingid, incomingBestDownSupernode);
|
||||
|
||||
vtkm::Id prefixLength = b->FirstSupernodePerIteration.ReadPortal().Get(rp.round() - 1)[0];
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Prefix length is " << prefixLength);
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(
|
||||
incomingBestUpSupernode.GetNumberOfValues(), rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestUpSupernode", incomingBestUpSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestDownSupernode", incomingBestDownSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestUpVolume", incomingBestUpVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestDownVolume", incomingBestDownVolume, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
// NOTE: We are processing input data from the previous round, hence, get
|
||||
// first supernide per ieteration from previous round
|
||||
|
||||
// Create 'views' to restrict worklet to relevant portion of arrays
|
||||
auto bestUpVolumeView = make_ArrayHandleView(branchDecomposer.BestUpVolume, 0, prefixLength);
|
||||
auto bestUpSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestUpSupernode, 0, prefixLength);
|
||||
auto bestDownVolumeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownVolume, 0, prefixLength);
|
||||
auto bestDownSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownSupernode, 0, prefixLength);
|
||||
|
||||
// Check if swap partner knows a better up /down and update
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
FindBestSupernodeWorklet<true>{},
|
||||
incomingBestUpVolume,
|
||||
incomingBestUpSupernode,
|
||||
bestUpVolumeView,
|
||||
bestUpSupernodeView);
|
||||
|
||||
invoke(vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
FindBestSupernodeWorklet<false>{},
|
||||
incomingBestDownVolume,
|
||||
incomingBestDownSupernode,
|
||||
bestDownVolumeView,
|
||||
bestDownSupernodeView);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "After round " << rp.round() - 1);
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(
|
||||
branchDecomposer.BestUpSupernode.GetNumberOfValues(), rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpSupernode", branchDecomposer.BestUpSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownSupernode", branchDecomposer.BestDownSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpVolume", branchDecomposer.BestUpVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownVolume", branchDecomposer.BestDownVolume, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for (int cc = 0; cc < rp.out_link().size(); ++cc)
|
||||
{
|
||||
auto target = rp.out_link().target(cc);
|
||||
if (target.gid != selfid)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
rp.enqueue(target, b->GlobalBlockId);
|
||||
#endif
|
||||
// Determine which portion of up/down volume/supernode to send
|
||||
vtkm::Id prefixLength = b->FirstSupernodePerIteration.ReadPortal().Get(rp.round())[0];
|
||||
|
||||
// Create 'views' to restrict sending to relevant portion of arrays
|
||||
auto bestUpVolumeView = make_ArrayHandleView(branchDecomposer.BestUpVolume, 0, prefixLength);
|
||||
auto bestUpSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestUpSupernode, 0, prefixLength);
|
||||
auto bestDownVolumeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownVolume, 0, prefixLength);
|
||||
auto bestDownSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownSupernode, 0, prefixLength);
|
||||
|
||||
// TODO/FIXME: Check if it is possible to send a portion of the arrays
|
||||
// without copy. enqueue does not accept ArrayHandleView as input as it
|
||||
// is not trivially copyable
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestUpVolume;
|
||||
vtkm::cont::Algorithm::Copy(bestUpVolumeView, sendBestUpVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestUpSupernode;
|
||||
vtkm::cont::Algorithm::Copy(bestUpSupernodeView, sendBestUpSupernode);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestDownVolume;
|
||||
vtkm::cont::Algorithm::Copy(bestDownVolumeView, sendBestDownVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestDownSupernode;
|
||||
vtkm::cont::Algorithm::Copy(bestDownSupernodeView, sendBestDownSupernode);
|
||||
|
||||
rp.enqueue(target, sendBestUpVolume);
|
||||
rp.enqueue(target, sendBestUpSupernode);
|
||||
rp.enqueue(target, sendBestDownVolume);
|
||||
rp.enqueue(target, sendBestDownSupernode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
@ -0,0 +1,84 @@
|
||||
//============================================================================
|
||||
// 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__h
|
||||
#define vtk_m_worklet_contourtree_distributed__h
|
||||
|
||||
#include <vtkm/filter/scalar_topology/BranchDecompositionBlock.h>
|
||||
|
||||
// clang-format off
|
||||
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
#include <vtkm/thirdparty/diy/diy.h>
|
||||
VTKM_THIRDPARTY_POST_INCLUDE
|
||||
// clang-format on
|
||||
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
|
||||
struct ComputeDistributedBranchDecompositionFunctor
|
||||
{
|
||||
void operator()(vtkm::worklet::scalar_topology::BranchDecompositionBlock* b,
|
||||
const vtkmdiy::ReduceProxy& rp, // communication proxy
|
||||
const vtkmdiy::RegularSwapPartners& // partners of the current block (unused)
|
||||
) const;
|
||||
};
|
||||
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -0,0 +1,281 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/filter/scalar_topology/BranchDecompositionBlock.h>
|
||||
#include <vtkm/filter/scalar_topology/ComputeDistributedBranchDecompositionFunctor.h>
|
||||
#include <vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
|
||||
|
||||
// vtkm includes
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
||||
// DIY includes
|
||||
// clang-format off
|
||||
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
#include <vtkm/thirdparty/diy/Configure.h>
|
||||
#include <vtkm/thirdparty/diy/diy.h>
|
||||
VTKM_THIRDPARTY_POST_INCLUDE
|
||||
// clang-format on
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
|
||||
// Constructor to record information about spatial decomposition
|
||||
// TODO/FIXME: Add this information to PartitionedDataSet, so that we do
|
||||
// not need to pass it sperately (or check if it can already be derived from
|
||||
// information stored in PartitionedDataSet)
|
||||
VTKM_CONT DistributedBranchDecompositionFilter::DistributedBranchDecompositionFilter(
|
||||
vtkm::Id3 blocksPerDim,
|
||||
vtkm::Id3 globalSize,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>& localBlockIndices,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>& localBlockOrigins,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>& localBlockSizes)
|
||||
: MultiBlockSpatialDecomposition(blocksPerDim,
|
||||
globalSize,
|
||||
localBlockIndices,
|
||||
localBlockOrigins,
|
||||
localBlockSizes)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT vtkm::cont::DataSet DistributedBranchDecompositionFilter::DoExecute(
|
||||
const vtkm::cont::DataSet& input)
|
||||
{
|
||||
// TODO/FIXME: Is there a better way to do this?
|
||||
return input; // Dummy function, not used
|
||||
}
|
||||
|
||||
|
||||
VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::DoExecutePartitions(
|
||||
const vtkm::cont::PartitionedDataSet& input)
|
||||
{
|
||||
vtkm::cont::Timer timer;
|
||||
timer.Start();
|
||||
std::stringstream timingsStream;
|
||||
|
||||
// Set up DIY master
|
||||
// TODO/FIXME: A lot of the code to set up DIY is the same for this filter and
|
||||
// ContourTreeUniformDistributed. Consolidate? (Which is difficult to do as
|
||||
// multiple variables are set up with some subtle differences)
|
||||
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
|
||||
int rank = comm.rank();
|
||||
int size = comm.size();
|
||||
|
||||
using BranchDecompositionBlock = vtkm::worklet::scalar_topology::BranchDecompositionBlock;
|
||||
vtkmdiy::Master branch_decomposition_master(comm,
|
||||
1, // Use 1 thread, VTK-M will do the treading
|
||||
-1, // All blocks in memory
|
||||
0, // No create function
|
||||
BranchDecompositionBlock::Destroy);
|
||||
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Create DIY Master (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Compute global ids (gids) for our local blocks
|
||||
using RegularDecomposer = vtkmdiy::RegularDecomposer<vtkmdiy::DiscreteBounds>;
|
||||
int globalNumberOfBlocks =
|
||||
static_cast<int>(this->MultiBlockSpatialDecomposition.GetGlobalNumberOfBlocks());
|
||||
int numDims = static_cast<int>(this->MultiBlockSpatialDecomposition.NumberOfDimensions());
|
||||
|
||||
// ... compute division vector for global domain
|
||||
RegularDecomposer::DivisionsVector diyDivisions(numDims);
|
||||
for (vtkm::IdComponent d = 0; d < static_cast<vtkm::IdComponent>(numDims); ++d)
|
||||
{
|
||||
diyDivisions[d] = static_cast<int>(this->MultiBlockSpatialDecomposition.BlocksPerDimension[d]);
|
||||
}
|
||||
|
||||
// ... compute coordinates of local blocks
|
||||
std::vector<int> vtkmdiyLocalBlockGids(static_cast<size_t>(input.GetNumberOfPartitions()));
|
||||
|
||||
auto localBlockIndicesPortal =
|
||||
this->MultiBlockSpatialDecomposition.LocalBlockIndices.ReadPortal();
|
||||
for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++)
|
||||
{
|
||||
RegularDecomposer::DivisionsVector diyCoords(static_cast<size_t>(numDims));
|
||||
auto currentCoords = localBlockIndicesPortal.Get(bi);
|
||||
for (vtkm::IdComponent d = 0; d < numDims; ++d)
|
||||
{
|
||||
diyCoords[d] = static_cast<int>(currentCoords[d]);
|
||||
}
|
||||
vtkmdiyLocalBlockGids[static_cast<size_t>(bi)] =
|
||||
RegularDecomposer::coords_to_gid(diyCoords, diyDivisions);
|
||||
}
|
||||
|
||||
// Record time to compute the local block ids
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Compute Block Ids and Local Links (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Initialize branch decomposition computation from data in PartitionedDataSet blocks
|
||||
for (vtkm::Id localBlockIndex = 0; localBlockIndex < input.GetNumberOfPartitions();
|
||||
++localBlockIndex)
|
||||
{
|
||||
int globalBlockId = vtkmdiyLocalBlockGids[localBlockIndex];
|
||||
const vtkm::cont::DataSet& ds = input.GetPartition(localBlockIndex);
|
||||
BranchDecompositionBlock* newBlock =
|
||||
new BranchDecompositionBlock(localBlockIndex, globalBlockId, ds);
|
||||
// NOTE: Use dummy link to make DIY happy. The dummy link is never used, since all
|
||||
// communication is via RegularDecomposer, which sets up its own links. No need
|
||||
// to keep the pointer, as DIY will "own" it and delete it when no longer needed.
|
||||
// NOTE: Since we passed a "Destroy" function to DIY master, it will own the local data
|
||||
// blocks and delete them when done.
|
||||
branch_decomposition_master.add(globalBlockId, newBlock, new vtkmdiy::Link());
|
||||
}
|
||||
|
||||
// Log time to copy the data to the HyperSweepBlock data objects
|
||||
timingsStream << " " << std::setw(60) << std::left << "Initialize Branch Decomposition Data"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Set up DIY for binary reduction
|
||||
RegularDecomposer::BoolVector shareFace(3, true);
|
||||
RegularDecomposer::BoolVector wrap(3, false);
|
||||
RegularDecomposer::CoordinateVector ghosts(3, 1);
|
||||
RegularDecomposer decomposer(numDims,
|
||||
this->MultiBlockSpatialDecomposition.GetVTKmDIYBounds(),
|
||||
static_cast<int>(globalNumberOfBlocks),
|
||||
shareFace,
|
||||
wrap,
|
||||
ghosts,
|
||||
diyDivisions);
|
||||
|
||||
// Define which blocks live on which rank so that vtkmdiy can manage them
|
||||
vtkmdiy::DynamicAssigner assigner(comm, size, globalNumberOfBlocks);
|
||||
|
||||
for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++)
|
||||
{
|
||||
assigner.set_rank(rank, vtkmdiyLocalBlockGids[static_cast<size_t>(bi)]);
|
||||
}
|
||||
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Create DIY Decomposer and Assigner (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Fix the vtkmdiy links.
|
||||
vtkmdiy::fix_links(branch_decomposition_master, assigner);
|
||||
|
||||
timingsStream << " " << std::setw(60) << std::left << "Fix DIY Links (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// partners for merge over regular block grid
|
||||
vtkmdiy::RegularSwapPartners partners(
|
||||
decomposer, // domain decomposition
|
||||
2, // radix of k-ary reduction.
|
||||
true // contiguous: true=distance doubling, false=distance halving
|
||||
);
|
||||
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Create DIY Swap Partners (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Compute the initial volumes
|
||||
branch_decomposition_master.foreach (
|
||||
[&](BranchDecompositionBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
// Get intrinsic and dependent volume from data set
|
||||
const vtkm::cont::DataSet& ds = input.GetPartition(b->LocalBlockNo);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> intrinsicVolume =
|
||||
ds.GetField("IntrinsicVolume").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> dependentVolume =
|
||||
ds.GetField("DependentVolume").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
// Get global size and compute total volume from it
|
||||
const auto& globalSize = this->MultiBlockSpatialDecomposition.GlobalSize;
|
||||
vtkm::Id totalVolume = globalSize[0] * globalSize[1] * globalSize[2];
|
||||
|
||||
// Compute local best up and down paths by volume
|
||||
b->VolumetricBranchDecomposer.LocalBestUpDownByVolume(
|
||||
ds, intrinsicVolume, dependentVolume, totalVolume);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Before reduction");
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(
|
||||
b->HierarchicalVolumetricBranchDecomposer.BestUpSupernode.GetNumberOfValues(), rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpSupernode", b->HierarchicalVolumetricBranchDecomposer.BestUpSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownSupernode", b->HierarchicalVolumetricBranchDecomposer.BestDownSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpVolume", b->HierarchicalVolumetricBranchDecomposer.BestUpVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownVolume", b->HierarchicalVolumetricBranchDecomposer.BestDownVolume, -1, rs);
|
||||
VTKM_LOG_S(this->TreeLogLevel, rs.str());
|
||||
}
|
||||
#endif
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(60) << std::left << "LocalBestUpDownByVolume"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Reduce
|
||||
// partners for merge over regular block grid
|
||||
vtkmdiy::reduce(branch_decomposition_master,
|
||||
assigner,
|
||||
partners,
|
||||
vtkm::worklet::scalar_topology::ComputeDistributedBranchDecompositionFunctor{});
|
||||
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Exchanging best up/down supernode and volume"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
branch_decomposition_master.foreach (
|
||||
[&](BranchDecompositionBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
const vtkm::cont::DataSet& ds = input.GetPartition(b->LocalBlockNo);
|
||||
b->VolumetricBranchDecomposer.CollapseBranches(ds, b->BranchRoots);
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left << "CollapseBranches"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
std::vector<vtkm::cont::DataSet> outputDataSets(input.GetNumberOfPartitions());
|
||||
// Copy input data set to output
|
||||
// TODO/FIXME: Should we really do this? Or just output branchRoots
|
||||
// and let the application deal with two ParitionedDataSet objects
|
||||
// if it also needs access to the other contour tree data
|
||||
for (vtkm::Id ds_no = 0; ds_no < input.GetNumberOfPartitions(); ++ds_no)
|
||||
{
|
||||
outputDataSets[ds_no] = input.GetPartition(ds_no);
|
||||
}
|
||||
|
||||
branch_decomposition_master.foreach (
|
||||
[&](BranchDecompositionBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
vtkm::cont::Field branchRootField(
|
||||
"BranchRoots", vtkm::cont::Field::Association::WholeMesh, b->BranchRoots);
|
||||
outputDataSets[b->LocalBlockNo].AddField(branchRootField);
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left
|
||||
<< "Creating Branch Decomposition Output Data"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Perf,
|
||||
std::endl
|
||||
<< "----------- DoExecutePartitions Timings ------------" << std::endl
|
||||
<< timingsStream.str());
|
||||
|
||||
return vtkm::cont::PartitionedDataSet{ outputDataSets };
|
||||
}
|
||||
|
||||
} // namespace scalar_topology
|
||||
} // namespace filter
|
||||
} // namespace vtkm
|
@ -0,0 +1,82 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef vtk_m_filter_contour_tree_DistributedBranchDecompositionFilter_h
|
||||
#define vtk_m_filter_contour_tree_DistributedBranchDecompositionFilter_h
|
||||
|
||||
#include <vtkm/filter/NewFilterField.h>
|
||||
#include <vtkm/filter/scalar_topology/vtkm_filter_scalar_topology_export.h>
|
||||
|
||||
#include <vtkm/worklet/contourtree_distributed/SpatialDecomposition.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
/// \brief Compute branch decompostion from distributed contour tree
|
||||
|
||||
class VTKM_FILTER_SCALAR_TOPOLOGY_EXPORT DistributedBranchDecompositionFilter
|
||||
: public vtkm::filter::NewFilter
|
||||
{
|
||||
public:
|
||||
VTKM_CONT DistributedBranchDecompositionFilter(
|
||||
vtkm::Id3 blocksPerDim,
|
||||
vtkm::Id3 globalSize,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>& localBlockIndices,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>& localBlockOrigins,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>& localBlockSizes);
|
||||
|
||||
private:
|
||||
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
|
||||
VTKM_CONT vtkm::cont::PartitionedDataSet DoExecutePartitions(
|
||||
const vtkm::cont::PartitionedDataSet& inData) override;
|
||||
|
||||
/// Information about the spatial decomposition
|
||||
vtkm::worklet::contourtree_distributed::SpatialDecomposition MultiBlockSpatialDecomposition;
|
||||
};
|
||||
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
11
vtkm/filter/scalar_topology/testing/CMakeLists.txt
Normal file
11
vtkm/filter/scalar_topology/testing/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
##=============================================================================
|
||||
##
|
||||
## 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.
|
||||
##
|
||||
##=============================================================================
|
11
vtkm/filter/scalar_topology/worklet/CMakeLists.txt
Normal file
11
vtkm/filter/scalar_topology/worklet/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
##============================================================================
|
||||
## 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.
|
||||
##============================================================================
|
||||
|
||||
add_subdirectory(branch_decomposition)
|
@ -0,0 +1,17 @@
|
||||
##============================================================================
|
||||
## 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.
|
||||
##============================================================================
|
||||
|
||||
set(headers
|
||||
HierarchicalVolumetricBranchDecomposer.h
|
||||
)
|
||||
#-----------------------------------------------------------------------------
|
||||
add_subdirectory(hierarchical_volumetric_branch_decomposer)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
@ -116,24 +116,27 @@
|
||||
//=======================================================================================
|
||||
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_h
|
||||
#ifndef vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_h
|
||||
#define vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_h
|
||||
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
// Contour tree includes, not yet moved into new filter structure
|
||||
#include <vtkm/worklet/contourtree_augmented/NotNoSuchElementPredicate.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/PrintVectors.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/PrintGraph.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_contour_tree/FindRegularByGlobal.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_contour_tree/FindSuperArcBetweenNodes.h>
|
||||
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalContourTree.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_volumetric_branch_decomposer/CollapseBranchesPointerDoublingWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_volumetric_branch_decomposer/CollapseBranchesWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_volumetric_branch_decomposer/LocalBestUpDownByVolumeBestUpDownEdgeWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_volumetric_branch_decomposer/LocalBestUpDownByVolumeInitSuperarcListWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_volumetric_branch_decomposer/LocalBestUpDownByVolumeWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_volumetric_branch_decomposer/SuperArcVolumetricComparatorIndirectGlobalIdComparator.h>
|
||||
// Worklets
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/CollapseBranchesPointerDoublingWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/CollapseBranchesWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/LocalBestUpDownByVolumeBestUpDownEdgeWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/LocalBestUpDownByVolumeInitSuperarcListWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/LocalBestUpDownByVolumeWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/SuperArcVolumetricComparatorIndirectGlobalIdComparator.h>
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#define DEBUG_HIERARCHICAL_VOLUMETRIC_BRANCH_DECOMPOSER
|
||||
@ -143,11 +146,10 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
|
||||
/// Facture class for augmenting the hierarchical contour tree to enable computations of measures, e.g., volumne
|
||||
template <typename FieldType>
|
||||
class HierarchicalVolumetricBranchDecomposer
|
||||
{ // class HierarchicalVolumetricBranchDecomposer
|
||||
public:
|
||||
@ -162,11 +164,6 @@ public:
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType UpVolume;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType DownVolume;
|
||||
|
||||
/// Because we want to use array allocation in main, we need a default constructor
|
||||
/// Unfortunately, that means we have problems with references, and the workaround is to have
|
||||
/// the references passed to the individual functions
|
||||
HierarchicalVolumetricBranchDecomposer<FieldType>(){};
|
||||
|
||||
/// routines to compute branch decomposition by volume
|
||||
/// WARNING: we now have two types of hierarchical tree sharing a data structure:
|
||||
/// I. hierarchical tree without augmentation
|
||||
@ -194,23 +191,22 @@ public:
|
||||
/// routine that determines the best upwards/downwards edges at each vertex
|
||||
/// Unlike the local version, the best might only be stored on another rank
|
||||
/// so we will compute the locally best up or down, then swap until all ranks choose the same best
|
||||
|
||||
void LocalBestUpDownByVolume(
|
||||
const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>*
|
||||
hierarchicalTree,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& intrinsicValues,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& dependentValues,
|
||||
vtkm::Id totalVolume);
|
||||
void LocalBestUpDownByVolume(const vtkm::cont::DataSet& hierarchicalTreeDataSet,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& intrinsicValues,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& dependentValues,
|
||||
vtkm::Id totalVolume);
|
||||
|
||||
/// routine to compute the local set of superarcs that root at a given one
|
||||
void CollapseBranches(const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<
|
||||
FieldType>* hierarchicalTree,
|
||||
void CollapseBranches(const vtkm::cont::DataSet& hierarchicalTreeDataSet,
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType& branchRoot);
|
||||
|
||||
// routine to print branches
|
||||
std::string PrintBranches(const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<
|
||||
FieldType>* hierarchicalTree,
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& branchRoot);
|
||||
/// routines to print branches
|
||||
template <typename IdArrayHandleType, typename DataValueArrayHandleType>
|
||||
static std::string PrintBranches(const IdArrayHandleType& hierarchicalTreeSuperarcsAH,
|
||||
const IdArrayHandleType& hierarchicalTreeSupernodesAH,
|
||||
const IdArrayHandleType& hierarchicalTreeRegularNodeGlobalIdsAH,
|
||||
const DataValueArrayHandleType& hierarchicalTreeDataValuesAH,
|
||||
const IdArrayHandleType& branchRootAH);
|
||||
static std::string PrintBranches(const vtkm::cont::DataSet& ds);
|
||||
|
||||
/// debug routine
|
||||
@ -223,31 +219,39 @@ private:
|
||||
}; // class HierarchicalVolumetricBranchDecomposer
|
||||
|
||||
|
||||
template <typename FieldType>
|
||||
void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>*
|
||||
hierarchicalTree,
|
||||
inline void HierarchicalVolumetricBranchDecomposer::LocalBestUpDownByVolume(
|
||||
const vtkm::cont::DataSet& hierarchicalTreeDataSet,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& intrinsicValues,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& dependentValues,
|
||||
vtkm::Id totalVolume)
|
||||
{
|
||||
// Get required arrays for hierarchical tree form data set
|
||||
auto hierarchicalTreeSupernodes = hierarchicalTreeDataSet.GetField("Supernodes")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeSuperarcs = hierarchicalTreeDataSet.GetField("Superarcs")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeRegularNodeGlobalIds =
|
||||
hierarchicalTreeDataSet.GetField("RegularNodeGlobalIds")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
// LocalBestUpDownByVolume
|
||||
// STAGE I: Allocate memory for our arrays
|
||||
vtkm::Id nSupernodes = hierarchicalTree->Supernodes.GetNumberOfValues();
|
||||
vtkm::Id nSupernodes = hierarchicalTreeSupernodes.GetNumberOfValues();
|
||||
// WARNING: This differs from the non-hierarchical version by using the full size *WITH* virtual superarcs
|
||||
vtkm::Id nSuperarcs = hierarchicalTree->Superarcs.GetNumberOfValues();
|
||||
vtkm::Id nSuperarcs = hierarchicalTreeSuperarcs.GetNumberOfValues();
|
||||
|
||||
// set up a list of superarcs as Edges for reference in our comparator
|
||||
vtkm::worklet::contourtree_augmented::EdgePairArray superarcList;
|
||||
superarcList.Allocate(nSuperarcs);
|
||||
VTKM_ASSERT(hierarchicalTree->Superarcs.GetNumberOfValues() == superarcList.GetNumberOfValues());
|
||||
this->Invoke(vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
this->Invoke(vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
LocalBestUpDownByVolumeInitSuperarcListWorklet{}, // the worklet
|
||||
hierarchicalTree->Superarcs, // input
|
||||
hierarchicalTreeSuperarcs, // input
|
||||
superarcList // output
|
||||
);
|
||||
|
||||
|
||||
#ifdef DEBUG_HIERARCHICAL_VOLUMETRIC_BRANCH_DECOMPOSER
|
||||
{
|
||||
std::stringstream resultStream;
|
||||
@ -265,7 +269,7 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
// and fill it up with index values [0, 1, 2 ... nSuperarcs-1] while simultaneously stream compacting the
|
||||
// values by keeping only those indices where the hierarchicalTree->Superarcs is not NoSuchElement.
|
||||
vtkm::cont::Algorithm::CopyIf(vtkm::cont::ArrayHandleIndex(nSuperarcs), //input
|
||||
hierarchicalTree->Superarcs, // stencil
|
||||
hierarchicalTreeSuperarcs, // stencil
|
||||
actualSuperarcs, // output target array
|
||||
vtkm::worklet::contourtree_augmented::NotNoSuchElementPredicate{});
|
||||
// NOTE: The behavior here is slightly different from the original implementation, as the original code
|
||||
@ -307,12 +311,12 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
// given that we have already suppressed the non-virtual superarcs
|
||||
// however, in this case, we need to use the actualSuperarcs array instead of the main array
|
||||
{
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
LocalBestUpDownByVolumeBestUpDownEdgeWorklet bestUpDownEdgeWorklet(totalVolume);
|
||||
// permut input and output arrays here so we can use FieldIn and FieldOut to
|
||||
// avoid the use of WholeArray access in the worklet
|
||||
auto permutedHierarchicalTreeSuperarcs = vtkm::cont::make_ArrayHandlePermutation(
|
||||
actualSuperarcs, hierarchicalTree->Superarcs); // input
|
||||
auto permutedHierarchicalTreeSuperarcs =
|
||||
vtkm::cont::make_ArrayHandlePermutation(actualSuperarcs, hierarchicalTreeSuperarcs); // input
|
||||
auto permutedDependetValues =
|
||||
vtkm::cont::make_ArrayHandlePermutation(actualSuperarcs, dependentValues); // input
|
||||
auto permutedIntrinsicValues =
|
||||
@ -348,10 +352,10 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
// NB: We reuse the actual superarcs list here - this works because we have indexed the volumes on the underlying superarc ID
|
||||
// NB 2: Notice that we only sort the "actual" ones - this is to avoid unnecessary resize() calls in vtkm later on
|
||||
{
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
SuperArcVolumetricComparatorIndirectGlobalIdComparator
|
||||
SuperArcVolumetricComparatorIndirectGlobalIdComparator(
|
||||
this->UpVolume, superarcList, hierarchicalTree->RegularNodeGlobalIds, false);
|
||||
this->UpVolume, superarcList, hierarchicalTreeRegularNodeGlobalIds, false);
|
||||
vtkm::cont::Algorithm::Sort(actualSuperarcs,
|
||||
SuperArcVolumetricComparatorIndirectGlobalIdComparator);
|
||||
}
|
||||
@ -373,15 +377,15 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
{
|
||||
auto permutedUpVolume =
|
||||
vtkm::cont::make_ArrayHandlePermutation(actualSuperarcs, this->UpVolume);
|
||||
this->Invoke(vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
this->Invoke(vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
LocalBestUpDownByVolumeWorklet<true>{ nActualSuperarcs },
|
||||
actualSuperarcs, // input
|
||||
superarcList, // input
|
||||
permutedUpVolume, // input
|
||||
hierarchicalTree->RegularNodeGlobalIds, // input
|
||||
hierarchicalTree->Supernodes, // input
|
||||
this->BestDownSupernode, // output
|
||||
this->BestDownVolume // output
|
||||
actualSuperarcs, // input
|
||||
superarcList, // input
|
||||
permutedUpVolume, // input
|
||||
hierarchicalTreeRegularNodeGlobalIds, // input
|
||||
hierarchicalTreeSupernodes, // input
|
||||
this->BestDownSupernode, // output
|
||||
this->BestDownVolume // output
|
||||
);
|
||||
}
|
||||
#ifdef DEBUG_HIERARCHICAL_VOLUMETRIC_BRANCH_DECOMPOSER
|
||||
@ -391,10 +395,10 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
|
||||
// II B 3. Repeat for lower vertex
|
||||
{
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
SuperArcVolumetricComparatorIndirectGlobalIdComparator
|
||||
SuperArcVolumetricComparatorIndirectGlobalIdComparator(
|
||||
this->DownVolume, superarcList, hierarchicalTree->RegularNodeGlobalIds, true);
|
||||
this->DownVolume, superarcList, hierarchicalTreeRegularNodeGlobalIds, true);
|
||||
vtkm::cont::Algorithm::Sort(actualSuperarcs,
|
||||
SuperArcVolumetricComparatorIndirectGlobalIdComparator);
|
||||
}
|
||||
@ -417,15 +421,15 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
{
|
||||
auto permutedDownVolume =
|
||||
vtkm::cont::make_ArrayHandlePermutation(actualSuperarcs, this->DownVolume);
|
||||
this->Invoke(vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
this->Invoke(vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
LocalBestUpDownByVolumeWorklet<false>{ nActualSuperarcs },
|
||||
actualSuperarcs, // input
|
||||
superarcList, // input
|
||||
permutedDownVolume, // input
|
||||
hierarchicalTree->RegularNodeGlobalIds, // input
|
||||
hierarchicalTree->Supernodes, // input
|
||||
this->BestUpSupernode, // output
|
||||
this->BestUpVolume // output
|
||||
actualSuperarcs, // input
|
||||
superarcList, // input
|
||||
permutedDownVolume, // input
|
||||
hierarchicalTreeRegularNodeGlobalIds, // input
|
||||
hierarchicalTreeSupernodes, // input
|
||||
this->BestUpSupernode, // output
|
||||
this->BestUpVolume // output
|
||||
);
|
||||
}
|
||||
|
||||
@ -435,32 +439,57 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::LocalBestUpDownByVolume(
|
||||
#endif
|
||||
} // LocalBestUpDownByVolume
|
||||
|
||||
template <typename FieldType>
|
||||
void HierarchicalVolumetricBranchDecomposer<FieldType>::CollapseBranches(
|
||||
const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>*
|
||||
hierarchicalTree,
|
||||
|
||||
inline void HierarchicalVolumetricBranchDecomposer::CollapseBranches(
|
||||
const vtkm::cont::DataSet& hierarchicalTreeDataSet,
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType& branchRoot)
|
||||
{ // CollapseBranches
|
||||
// Get required arrays for hierarchical tree form data set
|
||||
auto hierarchicalTreeSupernodes = hierarchicalTreeDataSet.GetField("Supernodes")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeSuperarcs = hierarchicalTreeDataSet.GetField("Superarcs")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeRegularNodeGlobalIds =
|
||||
hierarchicalTreeDataSet.GetField("RegularNodeGlobalIds")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeRegularNodeSortOrder =
|
||||
hierarchicalTreeDataSet.GetField("RegularNodeSortOrder")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeRegular2Supernode = hierarchicalTreeDataSet.GetField("Regular2Supernode")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeWhichRound = hierarchicalTreeDataSet.GetField("WhichRound")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
// initialise the superarcs to be their own branch roots
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Initializing branch root with " << branchRoot.GetNumberOfValues() << " values.");
|
||||
vtkm::cont::Algorithm::Copy(vtkm::cont::ArrayHandleIndex(branchRoot.GetNumberOfValues()),
|
||||
branchRoot);
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(branchRoot.GetNumberOfValues()), branchRoot);
|
||||
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Convert to superarc ID.");
|
||||
// For each supernode, convert the best up into a superarc ID
|
||||
{
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
CollapseBranchesWorklet collapseBranchesWorklet;
|
||||
auto findRegularByGlobal = hierarchicalTree->GetFindRegularByGlobal();
|
||||
auto findSuperArcBetweenNodes = hierarchicalTree->GetFindSuperArcBetweenNodes();
|
||||
this->Invoke(collapseBranchesWorklet, // the worklet
|
||||
this->BestUpSupernode, // input
|
||||
this->BestDownSupernode, // input
|
||||
findRegularByGlobal, // input ExecutionObject
|
||||
findSuperArcBetweenNodes, // input ExecutionObject
|
||||
hierarchicalTree->Regular2Supernode, // input
|
||||
hierarchicalTree->WhichRound, // input
|
||||
vtkm::worklet::contourtree_distributed::FindRegularByGlobal findRegularByGlobal{
|
||||
hierarchicalTreeRegularNodeSortOrder, hierarchicalTreeRegularNodeGlobalIds
|
||||
};
|
||||
vtkm::worklet::contourtree_distributed::FindSuperArcBetweenNodes findSuperArcBetweenNodes{
|
||||
hierarchicalTreeSuperarcs
|
||||
};
|
||||
|
||||
using vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
CollapseBranchesWorklet;
|
||||
this->Invoke(CollapseBranchesWorklet{}, // the worklet
|
||||
this->BestUpSupernode, // input
|
||||
this->BestDownSupernode, // input
|
||||
findRegularByGlobal, // input ExecutionObject
|
||||
findSuperArcBetweenNodes, // input ExecutionObject
|
||||
hierarchicalTreeRegular2Supernode, // input
|
||||
hierarchicalTreeWhichRound, // input
|
||||
branchRoot);
|
||||
}
|
||||
|
||||
@ -477,112 +506,43 @@ void HierarchicalVolumetricBranchDecomposer<FieldType>::CollapseBranches(
|
||||
for (vtkm::Id iteration = 0; iteration < nLogSteps; iteration++)
|
||||
{ // per iteration
|
||||
// loop through the vertices, updating
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
CollapseBranchesPointerDoublingWorklet collapseBranchesPointerDoublingWorklet;
|
||||
this->Invoke(collapseBranchesPointerDoublingWorklet, branchRoot);
|
||||
using vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
CollapseBranchesPointerDoublingWorklet;
|
||||
this->Invoke(CollapseBranchesPointerDoublingWorklet{}, branchRoot);
|
||||
} // per iteration
|
||||
|
||||
} // CollapseBranches
|
||||
|
||||
|
||||
// routine to print branches
|
||||
template <typename FieldType>
|
||||
std::string HierarchicalVolumetricBranchDecomposer<FieldType>::PrintBranches(
|
||||
const vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>*
|
||||
hierarchicalTree,
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& branchRoot)
|
||||
{ // PrintBranches
|
||||
// we want to dump out the branches as viewed by this rank.
|
||||
// most of the processing will be external, so we keep this simple.
|
||||
// For each end of the superarc, we print out value & global ID prefixed by global ID of the branch root
|
||||
// The external processing will then sort them to construct segments (as usual) in the array
|
||||
// then a post-process can find the first and last in each segment & print out the branch
|
||||
// In order for the sort to work lexicographically, we need to print out in the following order:
|
||||
// I Branch Root Global ID
|
||||
// II Supernode Value
|
||||
// III Supernode Global ID
|
||||
std::stringstream resultStream;
|
||||
// loop through the individual superarcs
|
||||
auto hierarchicalTreeSuperarcsPortal = hierarchicalTree->Superarcs.ReadPortal();
|
||||
auto hierarchicalTreeSupernodesPortal = hierarchicalTree->Supernodes.ReadPortal();
|
||||
auto hierarchicalTreeRegularNodeGlobalIdsPortal =
|
||||
hierarchicalTree->RegularNodeGlobalIds.ReadPortal();
|
||||
auto hierarchicalTreeDataValuesPortal = hierarchicalTree->DataValues.ReadPortal();
|
||||
auto branchRootPortal = branchRoot.ReadPortal();
|
||||
// PrintBranches
|
||||
// we want to dump out the branches as viewed by this rank.
|
||||
// most of the processing will be external, so we keep this simple.
|
||||
// For each end of the superarc, we print out value & global ID prefixed by global ID of the branch root
|
||||
// The external processing will then sort them to construct segments (as usual) in the array
|
||||
// then a post-process can find the first and last in each segment & print out the branch
|
||||
// In order for the sort to work lexicographically, we need to print out in the following order:
|
||||
// I Branch Root Global ID
|
||||
// II Supernode Value
|
||||
// III Supernode Global ID
|
||||
|
||||
for (vtkm::Id superarc = 0; superarc < hierarchicalTree->Superarcs.GetNumberOfValues();
|
||||
superarc++)
|
||||
{ // per superarc
|
||||
// explicit test for root superarc / attachment points
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(
|
||||
hierarchicalTreeSuperarcsPortal.Get(superarc)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// now retrieve the branch root's global ID
|
||||
vtkm::Id branchRootSuperId = branchRootPortal.Get(superarc);
|
||||
vtkm::Id branchRootRegularId = hierarchicalTreeSupernodesPortal.Get(branchRootSuperId);
|
||||
vtkm::Id branchRootGlobalId =
|
||||
hierarchicalTreeRegularNodeGlobalIdsPortal.Get(branchRootRegularId);
|
||||
|
||||
// now retrieve the global ID & value for each end & output them
|
||||
vtkm::Id superFromRegularId = hierarchicalTreeSupernodesPortal.Get(superarc);
|
||||
vtkm::Id superFromGlobalId = hierarchicalTreeRegularNodeGlobalIdsPortal.Get(superFromRegularId);
|
||||
FieldType superFromValue = hierarchicalTreeDataValuesPortal.Get(superFromRegularId);
|
||||
resultStream << branchRootGlobalId << "\t" << superFromValue << "\t" << superFromGlobalId
|
||||
<< std::endl;
|
||||
|
||||
// now retrieve the global ID & value for each end & output them
|
||||
vtkm::Id superToRegularId = vtkm::worklet::contourtree_augmented::MaskedIndex(
|
||||
hierarchicalTreeSuperarcsPortal.Get(superarc));
|
||||
vtkm::Id superToGlobalId = hierarchicalTreeRegularNodeGlobalIdsPortal.Get(superToRegularId);
|
||||
FieldType superToValue = hierarchicalTreeDataValuesPortal.Get(superToRegularId);
|
||||
resultStream << branchRootGlobalId << "\t" << superToValue << "\t" << superToGlobalId
|
||||
<< std::endl;
|
||||
} // per superarc
|
||||
return resultStream.str();
|
||||
} // PrintBranches
|
||||
|
||||
// routine to print branches
|
||||
template <typename FieldType>
|
||||
std::string HierarchicalVolumetricBranchDecomposer<FieldType>::PrintBranches(
|
||||
const vtkm::cont::DataSet& ds)
|
||||
{ // PrintBranches
|
||||
// we want to dump out the branches as viewed by this rank.
|
||||
// most of the processing will be external, so we keep this simple.
|
||||
// For each end of the superarc, we print out value & global ID prefixed by global ID of the branch root
|
||||
// The external processing will then sort them to construct segments (as usual) in the array
|
||||
// then a post-process can find the first and last in each segment & print out the branch
|
||||
// In order for the sort to work lexicographically, we need to print out in the following order:
|
||||
// I Branch Root Global ID
|
||||
// II Supernode Value
|
||||
// III Supernode Global ID
|
||||
std::stringstream resultStream;
|
||||
// loop through the individual superarcs
|
||||
|
||||
|
||||
auto hierarchicalTreeSuperarcsAH =
|
||||
ds.GetField("Superarcs").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
// Note the following is a template to be called via cast-and-call
|
||||
template <typename IdArrayHandleType, typename DataValueArrayHandleType>
|
||||
std::string HierarchicalVolumetricBranchDecomposer::PrintBranches(
|
||||
const IdArrayHandleType& hierarchicalTreeSuperarcsAH,
|
||||
const IdArrayHandleType& hierarchicalTreeSupernodesAH,
|
||||
const IdArrayHandleType& hierarchicalTreeRegularNodeGlobalIdsAH,
|
||||
const DataValueArrayHandleType& hierarchicalTreeDataValuesAH,
|
||||
const IdArrayHandleType& branchRootAH)
|
||||
{
|
||||
auto hierarchicalTreeSuperarcsPortal = hierarchicalTreeSuperarcsAH.ReadPortal();
|
||||
vtkm::Id nSuperarcs = hierarchicalTreeSuperarcsAH.GetNumberOfValues();
|
||||
auto hierarchicalTreeSupernodesPortal = ds.GetField("Supernodes")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto hierarchicalTreeSupernodesPortal = hierarchicalTreeSupernodesAH.ReadPortal();
|
||||
auto hierarchicalTreeRegularNodeGlobalIdsPortal =
|
||||
ds.GetField("RegularNodeGlobalIds")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto hierarchicalTreeDataValuesPortal = ds.GetField("DataValues")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<FieldType>>()
|
||||
.ReadPortal();
|
||||
auto branchRootPortal = ds.GetField("BranchRoots")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
hierarchicalTreeRegularNodeGlobalIdsAH.ReadPortal();
|
||||
auto hierarchicalTreeDataValuesPortal = hierarchicalTreeDataValuesAH.ReadPortal();
|
||||
auto branchRootPortal = branchRootAH.ReadPortal();
|
||||
|
||||
std::stringstream resultStream;
|
||||
// loop through the individual superarcs
|
||||
|
||||
for (vtkm::Id superarc = 0; superarc < nSuperarcs; superarc++)
|
||||
{ // per superarc
|
||||
@ -602,7 +562,7 @@ std::string HierarchicalVolumetricBranchDecomposer<FieldType>::PrintBranches(
|
||||
// now retrieve the global ID & value for each end & output them
|
||||
vtkm::Id superFromRegularId = hierarchicalTreeSupernodesPortal.Get(superarc);
|
||||
vtkm::Id superFromGlobalId = hierarchicalTreeRegularNodeGlobalIdsPortal.Get(superFromRegularId);
|
||||
FieldType superFromValue = hierarchicalTreeDataValuesPortal.Get(superFromRegularId);
|
||||
vtkm::Float64 superFromValue = hierarchicalTreeDataValuesPortal.Get(superFromRegularId);
|
||||
resultStream << branchRootGlobalId << "\t" << superFromValue << "\t" << superFromGlobalId
|
||||
<< std::endl;
|
||||
|
||||
@ -610,18 +570,51 @@ std::string HierarchicalVolumetricBranchDecomposer<FieldType>::PrintBranches(
|
||||
vtkm::Id superToRegularId = vtkm::worklet::contourtree_augmented::MaskedIndex(
|
||||
hierarchicalTreeSuperarcsPortal.Get(superarc));
|
||||
vtkm::Id superToGlobalId = hierarchicalTreeRegularNodeGlobalIdsPortal.Get(superToRegularId);
|
||||
FieldType superToValue = hierarchicalTreeDataValuesPortal.Get(superToRegularId);
|
||||
vtkm::Float64 superToValue = hierarchicalTreeDataValuesPortal.Get(superToRegularId);
|
||||
resultStream << branchRootGlobalId << "\t" << superToValue << "\t" << superToGlobalId
|
||||
<< std::endl;
|
||||
} // per superarc
|
||||
|
||||
return resultStream.str();
|
||||
} // PrintBranches
|
||||
|
||||
inline std::string HierarchicalVolumetricBranchDecomposer::PrintBranches(
|
||||
const vtkm::cont::DataSet& ds)
|
||||
{
|
||||
auto hierarchicalTreeSuperarcsAH =
|
||||
ds.GetField("Superarcs").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto hierarchicalTreeSupernodesAH =
|
||||
ds.GetField("Supernodes").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
auto hierarchicalTreeRegularNodeGlobalIdsAH =
|
||||
ds.GetField("RegularNodeGlobalIds")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
auto hierarchicalTreeDataValuesData = ds.GetField("DataValues").GetData();
|
||||
|
||||
auto branchRootAH =
|
||||
ds.GetField("BranchRoots").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
std::string result;
|
||||
|
||||
hierarchicalTreeDataValuesData.CastAndCallForTypes<TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(
|
||||
[&](const auto& hierarchicalTreeDataValuesAH) {
|
||||
result = PrintBranches(hierarchicalTreeSuperarcsAH,
|
||||
hierarchicalTreeSupernodesAH,
|
||||
hierarchicalTreeRegularNodeGlobalIdsAH,
|
||||
hierarchicalTreeDataValuesAH,
|
||||
branchRootAH);
|
||||
});
|
||||
|
||||
return result;
|
||||
} // PrintBranches
|
||||
|
||||
|
||||
// debug routine
|
||||
template <typename FieldType>
|
||||
std::string HierarchicalVolumetricBranchDecomposer<FieldType>::DebugPrint(std::string message,
|
||||
const char* fileName,
|
||||
long lineNum)
|
||||
inline std::string HierarchicalVolumetricBranchDecomposer::DebugPrint(std::string message,
|
||||
const char* fileName,
|
||||
long lineNum)
|
||||
{ // DebugPrint()
|
||||
std::stringstream resultStream;
|
||||
resultStream << "----------------------------------------" << std::endl;
|
||||
@ -650,7 +643,7 @@ std::string HierarchicalVolumetricBranchDecomposer<FieldType>::DebugPrint(std::s
|
||||
return resultStream.str();
|
||||
} // DebugPrint()
|
||||
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
@ -53,7 +53,7 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace hierarchical_volumetric_branch_decomposer
|
||||
{
|
||||
@ -86,7 +86,7 @@ public:
|
||||
|
||||
}; // CollapseBranchesPointerDoublingWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace hierarchical_volumetric_branch_decomposer
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
@ -43,8 +43,8 @@
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_collapse_branches_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_collapse_branches_worklet_h
|
||||
#ifndef vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_collapse_branches_worklet_h
|
||||
#define vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_collapse_branches_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
@ -53,7 +53,7 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace hierarchical_volumetric_branch_decomposer
|
||||
{
|
||||
@ -236,8 +236,8 @@ public:
|
||||
|
||||
}; // CollapseBranchesWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace hierarchical_volumetric_branch_decomposer
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
@ -43,8 +43,8 @@
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_combine_branch_decomposers_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_combine_branch_decomposers_worklet_h
|
||||
#ifndef vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_combine_branch_decomposers_worklet_h
|
||||
#define vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_combine_branch_decomposers_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
@ -52,7 +52,7 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace hierarchical_volumetric_branch_decomposer
|
||||
{
|
||||
@ -89,8 +89,8 @@ public:
|
||||
} // operator()()
|
||||
}; // FindBestSupernodeWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace hierarchical_volumetric_branch_decomposer
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
@ -43,8 +43,8 @@
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_best_up_down_edge_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_best_up_down_edge_worklet_h
|
||||
#ifndef vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_best_up_down_edge_worklet_h
|
||||
#define vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_best_up_down_edge_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
@ -53,7 +53,7 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace hierarchical_volumetric_branch_decomposer
|
||||
{
|
||||
@ -146,8 +146,8 @@ private:
|
||||
|
||||
}; // LocalBestUpDownByVolumeBestUpDownEdgeWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace hierarchical_volumetric_branch_decomposer
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
@ -43,8 +43,8 @@
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_init_superarc_list_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_init_superarc_list_worklet_h
|
||||
#ifndef vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_init_superarc_list_worklet_h
|
||||
#define vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_localbestupdownbyvolume_init_superarc_list_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
@ -53,7 +53,7 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace hierarchical_volumetric_branch_decomposer
|
||||
{
|
||||
@ -96,8 +96,8 @@ public:
|
||||
|
||||
}; // LocalBestUpDownByVolumeInitSuperarcListWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace hierarchical_volumetric_branch_decomposer
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
@ -43,8 +43,8 @@
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_local_best_updown_by_volume_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_local_best_updown_by_volume_worklet_h
|
||||
#ifndef vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_local_best_updown_by_volume_worklet_h
|
||||
#define vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_local_best_updown_by_volume_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
@ -53,7 +53,7 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace hierarchical_volumetric_branch_decomposer
|
||||
{
|
||||
@ -221,8 +221,8 @@ private:
|
||||
|
||||
}; // LocalBestUpDownByVolumeWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace hierarchical_volumetric_branch_decomposer
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
@ -60,8 +60,8 @@
|
||||
//=======================================================================================
|
||||
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_superarc_volumetric_comparator_indirect_globalid_comparator_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_volumetric_branch_decomposer_superarc_volumetric_comparator_indirect_globalid_comparator_h
|
||||
#ifndef vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_superarc_volumetric_comparator_indirect_globalid_comparator_h
|
||||
#define vtk_m_worklet_scalar_topology_hierarchical_volumetric_branch_decomposer_superarc_volumetric_comparator_indirect_globalid_comparator_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ExecutionObjectBase.h>
|
||||
@ -71,7 +71,7 @@ namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace hierarchical_volumetric_branch_decomposer
|
||||
{
|
||||
@ -240,7 +240,7 @@ private:
|
||||
}; // SuperArcVolumetricComparatorIndirectGlobalIdComparator
|
||||
|
||||
} // namespace hierarchical_volumetric_branch_decomposer
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
@ -293,7 +293,6 @@ inline vtkm::cont::PartitionedDataSet RunContourTreeDUniformDistributed(
|
||||
!useMarchingCubes,
|
||||
useMarchingCubes,
|
||||
false, // no augmentationa
|
||||
false, // no branch decmompostion
|
||||
false, // no save dot
|
||||
vtkm::cont::LogLevel::UserVerboseLast,
|
||||
vtkm::cont::LogLevel::UserVerboseLast);
|
||||
|
@ -53,6 +53,7 @@
|
||||
#ifndef vtk_m_worklet_contourtree_augmented_not_no_such_element_predicate_h
|
||||
#define vtk_m_worklet_contourtree_augmented_not_no_such_element_predicate_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
|
@ -125,7 +125,7 @@ public:
|
||||
|
||||
|
||||
// prints the contents of the BRACT for comparison with sweep and merge
|
||||
std::string BoundaryTree::Print()
|
||||
inline std::string BoundaryTree::Print()
|
||||
{ // Print
|
||||
// Use string steam to record text so the user can print it however they like
|
||||
std::stringstream resultStream;
|
||||
@ -270,7 +270,7 @@ std::string BoundaryTree::PrintGlobalDot(
|
||||
} //PrintGlobalDot
|
||||
|
||||
// debug routine
|
||||
void BoundaryTree::PrintContent(std::ostream& outStream) const
|
||||
inline void BoundaryTree::PrintContent(std::ostream& outStream) const
|
||||
{
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(this->VertexIndex.GetNumberOfValues(),
|
||||
outStream);
|
||||
|
@ -11,15 +11,12 @@
|
||||
set(headers
|
||||
BoundaryTree.h
|
||||
BoundaryTreeMaker.h
|
||||
BranchDecompositionBlock.h
|
||||
CombineHyperSweepBlockFunctor.h
|
||||
ComputeDistributedBranchDecompositionFunctor.h
|
||||
ComputeDistributedContourTreeFunctor.h
|
||||
ContourTreeBlockData.h
|
||||
DistributedContourTreeBlockData.h
|
||||
HierarchicalAugmenter.h
|
||||
HierarchicalAugmenterFunctor.h
|
||||
HierarchicalVolumetricBranchDecomposer.h
|
||||
HierarchicalContourTree.h
|
||||
HierarchicalHyperSweeper.h
|
||||
HyperSweepBlock.h
|
||||
@ -39,4 +36,3 @@ add_subdirectory(tree_grafter)
|
||||
add_subdirectory(hierarchical_contour_tree)
|
||||
add_subdirectory(hierarchical_hyper_sweeper)
|
||||
add_subdirectory(hierarchical_augmenter)
|
||||
add_subdirectory(hierarchical_volumetric_branch_decomposer)
|
||||
|
@ -1,238 +0,0 @@
|
||||
//============================================================================
|
||||
// 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__h
|
||||
#define vtk_m_worklet_contourtree_distributed__h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/BranchDecompositionBlock.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_volumetric_branch_decomposer/FindBestSupernodeWorklet.h>
|
||||
|
||||
// clang-format off
|
||||
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
#include <vtkm/thirdparty/diy/diy.h>
|
||||
VTKM_THIRDPARTY_POST_INCLUDE
|
||||
// clang-format on
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#define DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
#endif
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
|
||||
template <typename ContourTreeDataFieldType>
|
||||
struct ComputeDistributedBranchDecompositionFunctor
|
||||
{
|
||||
void operator()(
|
||||
vtkm::worklet::contourtree_distributed::BranchDecompositionBlock<ContourTreeDataFieldType>* 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();
|
||||
|
||||
// Aliases to reduce verbosity
|
||||
auto& branchDecomposer = b->HierarchicalVolumetricBranchDecomposer;
|
||||
|
||||
std::vector<int> incoming;
|
||||
rp.incoming(incoming);
|
||||
for (const int ingid : incoming)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
int incomingGlobalBlockId;
|
||||
rp.dequeue(ingid, incomingGlobalBlockId);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Combining local block " << b->GlobalBlockId << " with incomoing block "
|
||||
<< incomingGlobalBlockId);
|
||||
#endif
|
||||
|
||||
// Receive data from swap partner
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestUpVolume;
|
||||
rp.dequeue(ingid, incomingBestUpVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestUpSupernode;
|
||||
rp.dequeue(ingid, incomingBestUpSupernode);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestDownVolume;
|
||||
rp.dequeue(ingid, incomingBestDownVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestDownSupernode;
|
||||
rp.dequeue(ingid, incomingBestDownSupernode);
|
||||
|
||||
vtkm::Id prefixLength = vtkm::cont::ArrayGetValue(
|
||||
0, b->HierarchicalContourTree.FirstSupernodePerIteration[rp.round() - 1]);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Prefix length is " << prefixLength);
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(
|
||||
incomingBestUpSupernode.GetNumberOfValues(), rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestUpSupernode", incomingBestUpSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestDownSupernode", incomingBestDownSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestUpVolume", incomingBestUpVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingBestDownVolume", incomingBestDownVolume, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
// NOTE: We are processing input data from the previous round, hence, get
|
||||
// first supernide per ieteration from previous round
|
||||
|
||||
// Create 'views' to restrict worklet to relevant portion of arrays
|
||||
auto bestUpVolumeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestUpVolume, 0, prefixLength);
|
||||
auto bestUpSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestUpSupernode, 0, prefixLength);
|
||||
auto bestDownVolumeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownVolume, 0, prefixLength);
|
||||
auto bestDownSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownSupernode, 0, prefixLength);
|
||||
|
||||
// Check if swap partner knows a better up /down and update
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
FindBestSupernodeWorklet<true>{},
|
||||
incomingBestUpVolume,
|
||||
incomingBestUpSupernode,
|
||||
bestUpVolumeView,
|
||||
bestUpSupernodeView);
|
||||
|
||||
invoke(vtkm::worklet::contourtree_distributed::hierarchical_volumetric_branch_decomposer::
|
||||
FindBestSupernodeWorklet<false>{},
|
||||
incomingBestDownVolume,
|
||||
incomingBestDownSupernode,
|
||||
bestDownVolumeView,
|
||||
bestDownSupernodeView);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "After round " << rp.round() - 1);
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(
|
||||
branchDecomposer.BestUpSupernode.GetNumberOfValues(), rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpSupernode", branchDecomposer.BestUpSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownSupernode", branchDecomposer.BestDownSupernode, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestUpVolume", branchDecomposer.BestUpVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"BestDownVolume", branchDecomposer.BestDownVolume, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for (int cc = 0; cc < rp.out_link().size(); ++cc)
|
||||
{
|
||||
auto target = rp.out_link().target(cc);
|
||||
if (target.gid != selfid)
|
||||
{
|
||||
#ifdef DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
rp.enqueue(target, b->GlobalBlockId);
|
||||
#endif
|
||||
// Determine which portion of up/down volume/supernode to send
|
||||
vtkm::Id prefixLength = vtkm::cont::ArrayGetValue(
|
||||
0, b->HierarchicalContourTree.FirstSupernodePerIteration[rp.round()]);
|
||||
|
||||
// Create 'views' to restrict sending to relevant portion of arrays
|
||||
auto bestUpVolumeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestUpVolume, 0, prefixLength);
|
||||
auto bestUpSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestUpSupernode, 0, prefixLength);
|
||||
auto bestDownVolumeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownVolume, 0, prefixLength);
|
||||
auto bestDownSupernodeView =
|
||||
make_ArrayHandleView(branchDecomposer.BestDownSupernode, 0, prefixLength);
|
||||
|
||||
// TODO/FIXME: Check if it is possible to send a portion of the arrays
|
||||
// without copy. enqueue does not accept ArrayHandleView as input as it
|
||||
// is not trivially copyable
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestUpVolume;
|
||||
vtkm::cont::Algorithm::Copy(bestUpVolumeView, sendBestUpVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestUpSupernode;
|
||||
vtkm::cont::Algorithm::Copy(bestUpSupernodeView, sendBestUpSupernode);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestDownVolume;
|
||||
vtkm::cont::Algorithm::Copy(bestDownVolumeView, sendBestDownVolume);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sendBestDownSupernode;
|
||||
vtkm::cont::Algorithm::Copy(bestDownSupernodeView, sendBestDownSupernode);
|
||||
|
||||
rp.enqueue(target, sendBestUpVolume);
|
||||
rp.enqueue(target, sendBestUpSupernode);
|
||||
rp.enqueue(target, sendBestDownVolume);
|
||||
rp.enqueue(target, sendBestDownSupernode);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -71,6 +71,8 @@
|
||||
#define VOLUME_PRINT_WIDTH 8
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/ContourTree.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h>
|
||||
@ -162,6 +164,8 @@ public:
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType NumIterations;
|
||||
|
||||
/// vectors tracking the segments used in each iteration of the hypersweep
|
||||
// TODO/FIXME: Consider using ArrayHandleGroupVecVariable instead of an STL vector
|
||||
// of ArrayHandles. (Though that may be a bit tricky with dynamic resizing.)
|
||||
std::vector<vtkm::worklet::contourtree_augmented::IdArrayType> FirstSupernodePerIteration;
|
||||
std::vector<vtkm::worklet::contourtree_augmented::IdArrayType> FirstHypernodePerIteration;
|
||||
|
||||
@ -242,6 +246,20 @@ public:
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& intrinsicVolume,
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& dependentVolume);
|
||||
|
||||
// Helper function to convert an STL vector of VTK-m arrays into components and
|
||||
// group arrays (for packing into a vtkm::cont::DataSet and using with an
|
||||
// ArrayHandleGroupVecVariable for access)
|
||||
// TODO/FIXME: Ultimately, we should get rid of the STL arrays and use an
|
||||
// ArrayHandleGroupVecVariable in this class.
|
||||
VTKM_CONT
|
||||
static void ConvertSTLVecOfHandlesToVTKMComponentsAndOffsetsArray(
|
||||
const std::vector<vtkm::worklet::contourtree_augmented::IdArrayType>& inputVec,
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType& outputComponents,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id>& outputOffsets);
|
||||
|
||||
VTKM_CONT
|
||||
void AddToVTKMDataSet(vtkm::cont::DataSet& ds) const;
|
||||
|
||||
private:
|
||||
/// Used internally to Invoke worklets
|
||||
vtkm::cont::Invoker Invoke;
|
||||
@ -946,9 +964,111 @@ std::string HierarchicalContourTree<FieldType>::DumpVolumes(
|
||||
return outStream.str();
|
||||
} // DumpVolumes()
|
||||
|
||||
template <typename FieldType>
|
||||
void HierarchicalContourTree<FieldType>::ConvertSTLVecOfHandlesToVTKMComponentsAndOffsetsArray(
|
||||
const std::vector<vtkm::worklet::contourtree_augmented::IdArrayType>& inputVec,
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType& outputComponents,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id>& outputOffsets)
|
||||
{
|
||||
// Compute num components vector
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> numComponents;
|
||||
numComponents.Allocate(inputVec.size());
|
||||
auto numComponentsWritePortal = numComponents.WritePortal();
|
||||
|
||||
for (vtkm::Id i = 0; i < static_cast<vtkm::Id>(inputVec.size()); ++i)
|
||||
{
|
||||
numComponentsWritePortal.Set(i, inputVec[i].GetNumberOfValues());
|
||||
}
|
||||
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"ConvertSTLVecOfHandlesToVTKMComponentsAndOffsetsArray: Converting to offsets");
|
||||
// Convert to offsets and store in output array
|
||||
vtkm::Id componentsArraySize;
|
||||
vtkm::cont::ConvertNumComponentsToOffsets(numComponents, outputOffsets, componentsArraySize);
|
||||
|
||||
// Copy data to components array
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"ConvertSTLVecOfHandlesToVTKMComponentsAndOffsetsArray: Copying");
|
||||
auto outputOffsetsReadPortal = outputOffsets.ReadPortal();
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Allocating to " << componentsArraySize);
|
||||
outputComponents.Allocate(componentsArraySize);
|
||||
auto numComponentsReadPortal = numComponents.ReadPortal();
|
||||
for (vtkm::Id i = 0; i < static_cast<vtkm::Id>(inputVec.size()); ++i)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Creating view from " << outputOffsetsReadPortal.Get(i) << " size "
|
||||
<< numComponentsReadPortal.Get(i));
|
||||
auto outputView = vtkm::cont::make_ArrayHandleView(
|
||||
outputComponents, outputOffsetsReadPortal.Get(i), numComponentsReadPortal.Get(i));
|
||||
vtkm::cont::ArrayCopy(inputVec[i], outputView);
|
||||
}
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"ConvertSTLVecOfHandlesToVTKMComponentsAndOffsetsArray: Exit");
|
||||
}
|
||||
|
||||
template <typename FieldType>
|
||||
void HierarchicalContourTree<FieldType>::AddToVTKMDataSet(vtkm::cont::DataSet& ds) const
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "AddToVTKMDataSet");
|
||||
// Create data set from output
|
||||
vtkm::cont::Field regularNodeGlobalIdsField(
|
||||
"RegularNodeGlobalIds", vtkm::cont::Field::Association::WholeMesh, this->RegularNodeGlobalIds);
|
||||
ds.AddField(regularNodeGlobalIdsField);
|
||||
vtkm::cont::Field dataValuesField(
|
||||
"DataValues", vtkm::cont::Field::Association::WholeMesh, this->DataValues);
|
||||
ds.AddField(dataValuesField);
|
||||
vtkm::cont::Field regularNodeSortOrderField(
|
||||
"RegularNodeSortOrder", vtkm::cont::Field::Association::WholeMesh, this->RegularNodeSortOrder);
|
||||
ds.AddField(regularNodeSortOrderField);
|
||||
vtkm::cont::Field regular2SupernodeField(
|
||||
"Regular2Supernode", vtkm::cont::Field::Association::WholeMesh, this->Regular2Supernode);
|
||||
ds.AddField(regular2SupernodeField);
|
||||
vtkm::cont::Field superparentsField(
|
||||
"Superparents", vtkm::cont::Field::Association::WholeMesh, this->Superparents);
|
||||
ds.AddField(superparentsField);
|
||||
vtkm::cont::Field supernodesField(
|
||||
"Supernodes", vtkm::cont::Field::Association::WholeMesh, this->Supernodes);
|
||||
ds.AddField(supernodesField);
|
||||
vtkm::cont::Field superarcsField(
|
||||
"Superarcs", vtkm::cont::Field::Association::WholeMesh, this->Superarcs);
|
||||
ds.AddField(superarcsField);
|
||||
vtkm::cont::Field hyperparentsField(
|
||||
"Hyperparents", vtkm::cont::Field::Association::WholeMesh, this->Hyperparents);
|
||||
ds.AddField(hyperparentsField);
|
||||
vtkm::cont::Field super2HypernodeField(
|
||||
"Super2Hypernode", vtkm::cont::Field::Association::WholeMesh, this->Super2Hypernode);
|
||||
ds.AddField(super2HypernodeField);
|
||||
vtkm::cont::Field whichRoundField(
|
||||
"WhichRound", vtkm::cont::Field::Association::WholeMesh, this->WhichRound);
|
||||
ds.AddField(whichRoundField);
|
||||
vtkm::cont::Field whichIterationField(
|
||||
"WhichIteration", vtkm::cont::Field::Association::WholeMesh, this->WhichIteration);
|
||||
ds.AddField(whichIterationField);
|
||||
// TODO/FIXME: See what other fields we need to add
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Calling ConvertSTLVecOfHandlesToVTKMComponentsAndOffsetsArray");
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType firstSupernodePerIterationComponents;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> firstSupernodePerIterationOffsets;
|
||||
ConvertSTLVecOfHandlesToVTKMComponentsAndOffsetsArray(FirstSupernodePerIteration,
|
||||
firstSupernodePerIterationComponents,
|
||||
firstSupernodePerIterationOffsets);
|
||||
vtkm::cont::Field firstSupernodePerIterationComponentsField(
|
||||
"FirstSupernodePerIterationComponents",
|
||||
vtkm::cont::Field::Association::WholeMesh,
|
||||
firstSupernodePerIterationComponents);
|
||||
ds.AddField(firstSupernodePerIterationComponentsField);
|
||||
vtkm::cont::Field firstSupernodePerIterationOffsetsField(
|
||||
"FirstSupernodePerIterationOffsets",
|
||||
vtkm::cont::Field::Association::WholeMesh,
|
||||
firstSupernodePerIterationOffsets);
|
||||
ds.AddField(firstSupernodePerIterationOffsetsField);
|
||||
// TODO/FIXME: It seems we may only need the counts for the first iteration, so check, which
|
||||
// information we actually need.
|
||||
}
|
||||
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user