Compute volume and select top volume branches
This commit is contained in:
parent
3406ba3113
commit
a77e5b3c63
@ -74,6 +74,7 @@
|
|||||||
|
|
||||||
#include <vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h>
|
#include <vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h>
|
||||||
#include <vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
|
#include <vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.h>
|
||||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
|
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
|
||||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
|
||||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/ProcessContourTree.h>
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/ProcessContourTree.h>
|
||||||
@ -213,8 +214,8 @@ int main(int argc, char* argv[])
|
|||||||
if (!augmentHierarchicalTree)
|
if (!augmentHierarchicalTree)
|
||||||
{
|
{
|
||||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||||
"Warning: --computeVolumeBranchDecomposition only "
|
"Warning: --computeVolumeBranchDecomposition requires augmentation. "
|
||||||
"allowed augmentation. Enabling --augmentHierarchicalTree option.");
|
"Enabling --augmentHierarchicalTree option.");
|
||||||
augmentHierarchicalTree = true;
|
augmentHierarchicalTree = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,6 +266,31 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vtkm::Id numBranches = 0;
|
||||||
|
if (parser.hasOption("--numBranches"))
|
||||||
|
{
|
||||||
|
numBranches = std::stoi(parser.getOption("--numBranches"));
|
||||||
|
if (!computeHierarchicalVolumetricBranchDecomposition)
|
||||||
|
{
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||||
|
"Warning: --numBranches requires computing branch decomposition. "
|
||||||
|
"Enabling --computeHierarchicalVolumetricBranchDecomposition option.");
|
||||||
|
computeHierarchicalVolumetricBranchDecomposition = true;
|
||||||
|
}
|
||||||
|
if (!augmentHierarchicalTree)
|
||||||
|
{
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||||
|
"Warning: --numBranches requires augmentation. "
|
||||||
|
"Enabling --augmentHierarchicalTree option.");
|
||||||
|
augmentHierarchicalTree = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType eps = 0.00001f;
|
||||||
|
|
||||||
|
if (parser.hasOption("--eps"))
|
||||||
|
eps = std::stof(parser.getOption("--eps"));
|
||||||
|
|
||||||
#ifdef ENABLE_HDFIO
|
#ifdef ENABLE_HDFIO
|
||||||
std::string dataset_name = "data";
|
std::string dataset_name = "data";
|
||||||
if (parser.hasOption("--dataset"))
|
if (parser.hasOption("--dataset"))
|
||||||
@ -336,7 +362,12 @@ int main(int argc, char* argv[])
|
|||||||
std::cout << "--augmentHierarchicalTree Augment the hierarchical tree." << std::endl;
|
std::cout << "--augmentHierarchicalTree Augment the hierarchical tree." << std::endl;
|
||||||
std::cout << "--computeVolumeBranchDecomposition Compute the volume branch decomposition. "
|
std::cout << "--computeVolumeBranchDecomposition Compute the volume branch decomposition. "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout << " Requries --augmentHierarchicalTree to be set." << std::endl;
|
std::cout << " Requires --augmentHierarchicalTree to be set." << std::endl;
|
||||||
|
std::cout << "--numBranches Number of top volume branches to select." << std::endl;
|
||||||
|
std::cout << " Requires --computeVolumeBranchDecomposition." << std::endl;
|
||||||
|
std::cout
|
||||||
|
<< "--eps=<float> Floating point offset awary from the critical point. (default=0.00001)"
|
||||||
|
<< std::endl;
|
||||||
std::cout << "--preSplitFiles Input data is already pre-split into blocks." << std::endl;
|
std::cout << "--preSplitFiles Input data is already pre-split into blocks." << std::endl;
|
||||||
std::cout << "--saveDot Save DOT files of the distributed contour tree " << std::endl
|
std::cout << "--saveDot Save DOT files of the distributed contour tree " << std::endl
|
||||||
<< " computation (Default=False). " << std::endl;
|
<< " computation (Default=False). " << std::endl;
|
||||||
@ -383,6 +414,8 @@ int main(int argc, char* argv[])
|
|||||||
<< " saveOutputData=" << saveOutputData << std::endl
|
<< " saveOutputData=" << saveOutputData << std::endl
|
||||||
<< " forwardSummary=" << forwardSummary << std::endl
|
<< " forwardSummary=" << forwardSummary << std::endl
|
||||||
<< " nblocks=" << numBlocks << std::endl
|
<< " nblocks=" << numBlocks << std::endl
|
||||||
|
<< " nbranches=" << numBranches << std::endl
|
||||||
|
<< " eps=" << eps << std::endl
|
||||||
#ifdef ENABLE_HDFIO
|
#ifdef ENABLE_HDFIO
|
||||||
<< " dataset=" << dataset_name << " (HDF5 only)" << std::endl
|
<< " dataset=" << dataset_name << " (HDF5 only)" << std::endl
|
||||||
<< " blocksPerDim=" << blocksPerDimIn[0] << "," << blocksPerDimIn[1] << ","
|
<< " blocksPerDim=" << blocksPerDimIn[0] << "," << blocksPerDimIn[1] << ","
|
||||||
@ -642,6 +675,15 @@ int main(int argc, char* argv[])
|
|||||||
vtkm::Float64 branchDecompTime = currTime - prevTime;
|
vtkm::Float64 branchDecompTime = currTime - prevTime;
|
||||||
prevTime = currTime;
|
prevTime = currTime;
|
||||||
|
|
||||||
|
// Compute SelectTopVolumeContours if needed
|
||||||
|
vtkm::cont::PartitionedDataSet tp_result;
|
||||||
|
if (numBranches > 0)
|
||||||
|
{
|
||||||
|
vtkm::filter::scalar_topology::SelectTopVolumeContoursFilter tp_filter;
|
||||||
|
tp_filter.SetSavedBranches(numBranches);
|
||||||
|
tp_result = tp_filter.Execute(bd_result);
|
||||||
|
}
|
||||||
|
|
||||||
// Save output
|
// Save output
|
||||||
if (saveOutputData)
|
if (saveOutputData)
|
||||||
{
|
{
|
||||||
@ -684,6 +726,66 @@ int main(int argc, char* argv[])
|
|||||||
<< lowerEndGRId.Get(branch) << std::endl;
|
<< lowerEndGRId.Get(branch) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (numBranches > 0)
|
||||||
|
{
|
||||||
|
#ifndef DEBUG_PRINT
|
||||||
|
bool print_to_files = (rank == 0);
|
||||||
|
vtkm::Id max_blocks_to_print = 1;
|
||||||
|
#else
|
||||||
|
bool print_to_files = true;
|
||||||
|
vtkm::Id max_blocks_to_print = result.GetNumberOfPartitions();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (vtkm::Id ds_no = 0; print_to_files && ds_no < max_blocks_to_print; ++ds_no)
|
||||||
|
{
|
||||||
|
auto ds = tp_result.GetPartition(ds_no);
|
||||||
|
std::string topVolumeBranchFileName = std::string("TopVolumeBranch_Rank_") +
|
||||||
|
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
|
||||||
|
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
|
||||||
|
std::ofstream topVolumeBranchStream(topVolumeBranchFileName.c_str());
|
||||||
|
auto topVolBranchGRId = ds.GetField("TopVolumeBranchGlobalRegularIds")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||||
|
.ReadPortal();
|
||||||
|
auto topVolBranchVolume = ds.GetField("TopVolumeBranchVolume")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||||
|
.ReadPortal();
|
||||||
|
auto topVolBranchSaddleEpsilon = ds.GetField("TopVolumeBranchSaddleEpsilon")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||||
|
.ReadPortal();
|
||||||
|
auto topVolBranchSaddleIsoValue = ds.GetField("TopVolumeBranchSaddleIsoValue")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<ValueType>>()
|
||||||
|
.ReadPortal();
|
||||||
|
|
||||||
|
vtkm::Id nSelectedBranches = topVolBranchGRId.GetNumberOfValues();
|
||||||
|
for (vtkm::Id branch = 0; branch < nSelectedBranches; ++branch)
|
||||||
|
{
|
||||||
|
topVolumeBranchStream << std::setw(12) << topVolBranchGRId.Get(branch)
|
||||||
|
<< std::setw(14) << topVolBranchVolume.Get(branch)
|
||||||
|
<< std::setw(5) << topVolBranchSaddleEpsilon.Get(branch)
|
||||||
|
<< std::setw(14) << topVolBranchSaddleIsoValue.Get(branch)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string isoValuesFileName = std::string("IsoValues_Rank_") +
|
||||||
|
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
|
||||||
|
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
|
||||||
|
std::ofstream isoValuesStream(isoValuesFileName.c_str());
|
||||||
|
|
||||||
|
for (vtkm::Id branch = 0; branch < nSelectedBranches; ++branch)
|
||||||
|
{
|
||||||
|
isoValuesStream << (topVolBranchSaddleIsoValue.Get(branch) +
|
||||||
|
(eps * topVolBranchSaddleEpsilon.Get(branch)))
|
||||||
|
<< " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
isoValuesStream << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -12,17 +12,21 @@ set(scalar_topology_headers
|
|||||||
ContourTreeUniformAugmented.h
|
ContourTreeUniformAugmented.h
|
||||||
ContourTreeUniformDistributed.h
|
ContourTreeUniformDistributed.h
|
||||||
DistributedBranchDecompositionFilter.h
|
DistributedBranchDecompositionFilter.h
|
||||||
|
SelectTopVolumeContoursFilter.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(scalar_topology_sources
|
set(scalar_topology_sources
|
||||||
internal/BranchDecompositionBlock.cxx
|
internal/BranchDecompositionBlock.cxx
|
||||||
|
internal/SelectTopVolumeContoursBlock.cxx
|
||||||
internal/ComputeBlockIndices.cxx
|
internal/ComputeBlockIndices.cxx
|
||||||
internal/ComputeDistributedBranchDecompositionFunctor.cxx
|
internal/ComputeDistributedBranchDecompositionFunctor.cxx
|
||||||
|
internal/SelectTopVolumeContoursFunctor.cxx
|
||||||
internal/ExchangeBranchEndsFunctor.cxx
|
internal/ExchangeBranchEndsFunctor.cxx
|
||||||
ContourTreeUniform.cxx
|
ContourTreeUniform.cxx
|
||||||
ContourTreeUniformAugmented.cxx
|
ContourTreeUniformAugmented.cxx
|
||||||
ContourTreeUniformDistributed.cxx
|
ContourTreeUniformDistributed.cxx
|
||||||
DistributedBranchDecompositionFilter.cxx
|
DistributedBranchDecompositionFilter.cxx
|
||||||
|
SelectTopVolumeContoursFilter.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
vtkm_library(
|
vtkm_library(
|
||||||
|
@ -832,6 +832,15 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute(
|
|||||||
"from information in CellSetStructured.");
|
"from information in CellSetStructured.");
|
||||||
diyBounds = vtkm::filter::scalar_topology::internal::ComputeBlockIndices(
|
diyBounds = vtkm::filter::scalar_topology::internal::ComputeBlockIndices(
|
||||||
input, diyDivisions, vtkmdiyLocalBlockGids);
|
input, diyDivisions, vtkmdiyLocalBlockGids);
|
||||||
|
|
||||||
|
// Set BlocksPerDimension fromn diyDivisions result as add them
|
||||||
|
// as information to the output data set for use in subsequent
|
||||||
|
// filters
|
||||||
|
this->BlocksPerDimension = vtkm::Id3{ 1, 1, 1 };
|
||||||
|
for (unsigned int d = 0; d < diyDivisions.size(); ++d)
|
||||||
|
{
|
||||||
|
this->BlocksPerDimension[d] = diyDivisions[d];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -331,7 +331,6 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
|||||||
outputDataSets[ds_no] = input.GetPartition(ds_no);
|
outputDataSets[ds_no] = input.GetPartition(ds_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
branch_decomposition_master.foreach (
|
branch_decomposition_master.foreach (
|
||||||
[&](BranchDecompositionBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
[&](BranchDecompositionBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||||
vtkm::cont::Field branchRootField(
|
vtkm::cont::Field branchRootField(
|
||||||
@ -347,6 +346,51 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
|||||||
vtkm::cont::Field::Association::WholeDataSet,
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
b->VolumetricBranchDecomposer.LowerEndGRId);
|
b->VolumetricBranchDecomposer.LowerEndGRId);
|
||||||
outputDataSets[b->LocalBlockNo].AddField(LowerEndGRIdField);
|
outputDataSets[b->LocalBlockNo].AddField(LowerEndGRIdField);
|
||||||
|
|
||||||
|
vtkm::cont::Field UpperEndIntrinsicVolume(
|
||||||
|
"UpperEndIntrinsicVolume",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.UpperEndIntrinsicVolume);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(UpperEndIntrinsicVolume);
|
||||||
|
vtkm::cont::Field UpperEndDependentVolume(
|
||||||
|
"UpperEndDependentVolume",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.UpperEndDependentVolume);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(UpperEndDependentVolume);
|
||||||
|
vtkm::cont::Field LowerEndIntrinsicVolume(
|
||||||
|
"LowerEndIntrinsicVolume",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.LowerEndIntrinsicVolume);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(LowerEndIntrinsicVolume);
|
||||||
|
vtkm::cont::Field LowerEndDependentVolume(
|
||||||
|
"LowerEndDependentVolume",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.LowerEndDependentVolume);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(LowerEndDependentVolume);
|
||||||
|
vtkm::cont::Field LowerEndSuperarcId("LowerEndSuperarcId",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.LowerEndSuperarcId);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(LowerEndSuperarcId);
|
||||||
|
vtkm::cont::Field UpperEndSuperarcId("UpperEndSuperarcId",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.UpperEndSuperarcId);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(UpperEndSuperarcId);
|
||||||
|
vtkm::cont::Field LowerEndValue("LowerEndValue",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.LowerEndValue);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(LowerEndValue);
|
||||||
|
vtkm::cont::Field UpperEndValue("UpperEndValue",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.UpperEndValue);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(UpperEndValue);
|
||||||
|
vtkm::cont::Field BranchRoot("BranchRoot",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.BranchRoot);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(BranchRoot);
|
||||||
|
vtkm::cont::Field BranchRootGRId("BranchRootGRId",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->VolumetricBranchDecomposer.BranchRootGRId);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(BranchRootGRId);
|
||||||
});
|
});
|
||||||
|
|
||||||
timingsStream << " " << std::setw(38) << std::left
|
timingsStream << " " << std::setw(38) << std::left
|
||||||
|
183
vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.cxx
Normal file
183
vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.cxx
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/cont/EnvironmentTracker.h>
|
||||||
|
#include <vtkm/cont/ErrorFilterExecution.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursBlock.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursFunctor.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/ArrayTransforms.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
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKM_CONT vtkm::cont::DataSet SelectTopVolumeContoursFilter::DoExecute(const vtkm::cont::DataSet&)
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorFilterExecution(
|
||||||
|
"SelectTopVolumeContoursFilter expects PartitionedDataSet as input.");
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT vtkm::cont::PartitionedDataSet SelectTopVolumeContoursFilter::DoExecutePartitions(
|
||||||
|
const vtkm::cont::PartitionedDataSet& input)
|
||||||
|
{
|
||||||
|
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
|
||||||
|
int rank = comm.rank();
|
||||||
|
int size = comm.size();
|
||||||
|
|
||||||
|
using SelectTopVolumeContoursBlock =
|
||||||
|
vtkm::filter::scalar_topology::internal::SelectTopVolumeContoursBlock;
|
||||||
|
vtkmdiy::Master branch_top_volume_master(comm,
|
||||||
|
1, // Use 1 thread, VTK-M will do the treading
|
||||||
|
-1, // All blocks in memory
|
||||||
|
0, // No create function
|
||||||
|
SelectTopVolumeContoursBlock::Destroy);
|
||||||
|
|
||||||
|
auto firstDS = input.GetPartition(0);
|
||||||
|
vtkm::Id3 firstPointDimensions, firstGlobalPointDimensions, firstGlobalPointIndexStart;
|
||||||
|
firstDS.GetCellSet().CastAndCallForTypes<VTKM_DEFAULT_CELL_SET_LIST_STRUCTURED>(
|
||||||
|
vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(),
|
||||||
|
firstPointDimensions,
|
||||||
|
firstGlobalPointDimensions,
|
||||||
|
firstGlobalPointIndexStart);
|
||||||
|
int numDims = firstGlobalPointDimensions[2] > 1 ? 3 : 2;
|
||||||
|
auto vtkmBlocksPerDimensionRP = input.GetPartition(0)
|
||||||
|
.GetField("vtkmBlocksPerDimension")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||||
|
.ReadPortal();
|
||||||
|
|
||||||
|
int globalNumberOfBlocks = 1;
|
||||||
|
|
||||||
|
for (vtkm::IdComponent d = 0; d < static_cast<vtkm::IdComponent>(numDims); ++d)
|
||||||
|
{
|
||||||
|
globalNumberOfBlocks *= static_cast<int>(vtkmBlocksPerDimensionRP.Get(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkmdiy::DynamicAssigner assigner(comm, size, globalNumberOfBlocks);
|
||||||
|
for (vtkm::Id localBlockIndex = 0; localBlockIndex < input.GetNumberOfPartitions();
|
||||||
|
++localBlockIndex)
|
||||||
|
{
|
||||||
|
const vtkm::cont::DataSet& ds = input.GetPartition(localBlockIndex);
|
||||||
|
int globalBlockId = static_cast<int>(
|
||||||
|
vtkm::cont::ArrayGetValue(0,
|
||||||
|
ds.GetField("vtkmGlobalBlockId")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()));
|
||||||
|
|
||||||
|
SelectTopVolumeContoursBlock* b =
|
||||||
|
new SelectTopVolumeContoursBlock(localBlockIndex, globalBlockId);
|
||||||
|
|
||||||
|
branch_top_volume_master.add(globalBlockId, b, new vtkmdiy::Link());
|
||||||
|
assigner.set_rank(rank, globalBlockId);
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkmdiy::fix_links(branch_top_volume_master, assigner);
|
||||||
|
|
||||||
|
branch_top_volume_master.foreach (
|
||||||
|
[&](SelectTopVolumeContoursBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||||
|
const auto& globalSize = firstGlobalPointDimensions;
|
||||||
|
vtkm::Id totalVolume = globalSize[0] * globalSize[1] * globalSize[2];
|
||||||
|
const vtkm::cont::DataSet& ds = input.GetPartition(b->LocalBlockNo);
|
||||||
|
|
||||||
|
b->SortBranchByVolume(ds, totalVolume);
|
||||||
|
|
||||||
|
// copy the top volume branches into a smaller array
|
||||||
|
// we skip index 0 because it must be the main branch (which has the highest volume)
|
||||||
|
vtkm::Id nActualSavedBranches =
|
||||||
|
std::min(this->nSavedBranches, b->SortedBranchByVolume.GetNumberOfValues() - 1);
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType topVolumeBranch;
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
b->SortedBranchByVolume, 1, nActualSavedBranches, topVolumeBranch);
|
||||||
|
|
||||||
|
auto branchRootGRId =
|
||||||
|
ds.GetField("BranchRootGRId").GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
|
branchRootGRId, topVolumeBranch, b->TopVolumeBranchRootGRId);
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
|
branchRootGRId, topVolumeBranch, b->TopVolumeBranchRootGRId);
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
|
b->BranchVolume, topVolumeBranch, b->TopVolumeBranchVolume);
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
|
b->BranchSaddleEpsilon, topVolumeBranch, b->TopVolumeBranchSaddleEpsilon);
|
||||||
|
|
||||||
|
auto resolveArray = [&](const auto& inArray) {
|
||||||
|
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||||
|
InArrayHandleType topVolBranchSaddleIsoValue;
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithRawIndex<InArrayHandleType>(
|
||||||
|
inArray, topVolumeBranch, topVolBranchSaddleIsoValue);
|
||||||
|
b->TopVolumeBranchSaddleIsoValue = topVolBranchSaddleIsoValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
b->BranchSaddleIsoValue
|
||||||
|
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(resolveArray);
|
||||||
|
});
|
||||||
|
|
||||||
|
// We apply all-to-all broadcast to collect the top nSavedBranches branches by volume
|
||||||
|
vtkmdiy::all_to_all(
|
||||||
|
branch_top_volume_master,
|
||||||
|
assigner,
|
||||||
|
vtkm::filter::scalar_topology::internal::SelectTopVolumeContoursFunctor(this->nSavedBranches));
|
||||||
|
|
||||||
|
// For each block, we compute the get the extracted isosurface for every selected branch
|
||||||
|
// storing format: key (branch ID) - Value (list of meshes in the isosurface)
|
||||||
|
|
||||||
|
std::vector<vtkm::cont::DataSet> outputDataSets(input.GetNumberOfPartitions());
|
||||||
|
|
||||||
|
branch_top_volume_master.foreach (
|
||||||
|
[&](SelectTopVolumeContoursBlock* b, const vtkmdiy::Master::ProxyWithLink&) {
|
||||||
|
vtkm::cont::Field TopVolBranchGRIdField("TopVolumeBranchGlobalRegularIds",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->TopVolumeBranchRootGRId);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(TopVolBranchGRIdField);
|
||||||
|
vtkm::cont::Field TopVolBranchVolumeField("TopVolumeBranchVolume",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->TopVolumeBranchVolume);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(TopVolBranchVolumeField);
|
||||||
|
vtkm::cont::Field TopVolBranchSaddleEpsilonField("TopVolumeBranchSaddleEpsilon",
|
||||||
|
vtkm::cont::Field::Association::WholeDataSet,
|
||||||
|
b->TopVolumeBranchSaddleEpsilon);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(TopVolBranchSaddleEpsilonField);
|
||||||
|
|
||||||
|
auto resolveArray = [&](const auto& inArray) {
|
||||||
|
vtkm::cont::Field TopVolBranchSaddleIsoValueField(
|
||||||
|
"TopVolumeBranchSaddleIsoValue", vtkm::cont::Field::Association::WholeDataSet, inArray);
|
||||||
|
outputDataSets[b->LocalBlockNo].AddField(TopVolBranchSaddleIsoValueField);
|
||||||
|
};
|
||||||
|
b->TopVolumeBranchSaddleIsoValue
|
||||||
|
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(resolveArray);
|
||||||
|
});
|
||||||
|
|
||||||
|
return vtkm::cont::PartitionedDataSet{ outputDataSets };
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace filter
|
||||||
|
} // namespace vtkm
|
83
vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.h
Normal file
83
vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_scalar_topology_SelectTopVolumeContoursFilter_h
|
||||||
|
#define vtk_m_filter_scalar_topology_SelectTopVolumeContoursFilter_h
|
||||||
|
|
||||||
|
#include <vtkm/filter/Filter.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/vtkm_filter_scalar_topology_export.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
/// \brief Compute branch decompostion from distributed contour tree
|
||||||
|
|
||||||
|
class VTKM_FILTER_SCALAR_TOPOLOGY_EXPORT SelectTopVolumeContoursFilter : public vtkm::filter::Filter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VTKM_CONT SelectTopVolumeContoursFilter() = default;
|
||||||
|
|
||||||
|
VTKM_CONT void SetSavedBranches(const vtkm::Id& numBranches)
|
||||||
|
{
|
||||||
|
this->nSavedBranches = numBranches;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&) override;
|
||||||
|
VTKM_CONT vtkm::cont::PartitionedDataSet DoExecutePartitions(
|
||||||
|
const vtkm::cont::PartitionedDataSet& inData) override;
|
||||||
|
|
||||||
|
vtkm::Id nSavedBranches;
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType BranchVolume;
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType BranchSaddleEpsilon;
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType SortedBranchByVolume;
|
||||||
|
vtkm::cont::UnknownArrayHandle BranchSaddleIsoValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace worklet
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
|
#endif
|
@ -10,8 +10,10 @@
|
|||||||
|
|
||||||
set(headers
|
set(headers
|
||||||
BranchDecompositionBlock.h
|
BranchDecompositionBlock.h
|
||||||
|
SelectTopVolumeContoursBlock.h
|
||||||
ComputeBlockIndices.h
|
ComputeBlockIndices.h
|
||||||
ComputeDistributedBranchDecompositionFunctor.h
|
ComputeDistributedBranchDecompositionFunctor.h
|
||||||
|
SelectTopVolumeContoursFunctor.h
|
||||||
ExchangeBranchEndsFunctor.h
|
ExchangeBranchEndsFunctor.h
|
||||||
)
|
)
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
@ -0,0 +1,229 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/cont/ArrayCopy.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursBlock.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/select_top_volume_contours/ClarifyBranchEndSupernodeTypeWorklet.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/select_top_volume_contours/GetBranchVolumeWorklet.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/select_top_volume_contours/UpdateInfoByBranchDirectionWorklet.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG_PRINT
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
SelectTopVolumeContoursBlock::SelectTopVolumeContoursBlock(vtkm::Id localBlockNo, int globalBlockId)
|
||||||
|
: LocalBlockNo(localBlockNo)
|
||||||
|
, GlobalBlockId(globalBlockId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectTopVolumeContoursBlock::SortBranchByVolume(
|
||||||
|
const vtkm::cont::DataSet& hierarchicalTreeDataSet,
|
||||||
|
const vtkm::Id totalVolume)
|
||||||
|
{
|
||||||
|
/// Pipeline to compute the branch volume
|
||||||
|
/// 1. check both ends of the branch. If both leaves, then main branch, volume = totalVolume
|
||||||
|
/// 2. for other branches, check the direction of the inner superarc
|
||||||
|
/// branch volume = (inner superarc points to the senior-most node) ?
|
||||||
|
/// dependentVolume[innerSuperarc] :
|
||||||
|
/// reverseVolume[innerSuperarc]
|
||||||
|
/// NOTE: reverseVolume = totalVolume - dependentVolume + intrinsicVolume
|
||||||
|
|
||||||
|
// Generally, if ending superarc has intrinsicVol == dependentVol, then it is a leaf node
|
||||||
|
vtkm::cont::ArrayHandle<bool> isLowerLeaf;
|
||||||
|
vtkm::cont::ArrayHandle<bool> isUpperLeaf;
|
||||||
|
|
||||||
|
auto upperEndIntrinsicVolume = hierarchicalTreeDataSet.GetField("UpperEndIntrinsicVolume")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
auto upperEndDependentVolume = hierarchicalTreeDataSet.GetField("UpperEndDependentVolume")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
auto lowerEndIntrinsicVolume = hierarchicalTreeDataSet.GetField("LowerEndIntrinsicVolume")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
auto lowerEndDependentVolume = hierarchicalTreeDataSet.GetField("LowerEndDependentVolume")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
auto lowerEndSuperarcId = hierarchicalTreeDataSet.GetField("LowerEndSuperarcId")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
auto upperEndSuperarcId = hierarchicalTreeDataSet.GetField("UpperEndSuperarcId")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
auto branchRoot = hierarchicalTreeDataSet.GetField("BranchRoot")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||||
|
|
||||||
|
vtkm::cont::Algorithm::Transform(
|
||||||
|
upperEndIntrinsicVolume, upperEndDependentVolume, isUpperLeaf, vtkm::Equal());
|
||||||
|
vtkm::cont::Algorithm::Transform(
|
||||||
|
lowerEndIntrinsicVolume, lowerEndDependentVolume, isLowerLeaf, vtkm::Equal());
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: special cases (one-superarc branches) exist
|
||||||
|
// if the upper end superarc == lower end superarc == branch root superarc
|
||||||
|
// then it's probably not a leaf-leaf branch (Both equality has to be satisfied!)
|
||||||
|
// exception: the entire domain has only one superarc (intrinsic == dependent == total - 1)
|
||||||
|
// then it is a leaf-leaf branch
|
||||||
|
vtkm::cont::Invoker invoke;
|
||||||
|
|
||||||
|
vtkm::worklet::scalar_topology::select_top_volume_contours::ClarifyBranchEndSupernodeTypeWorklet
|
||||||
|
clarifyNodeTypeWorklet(totalVolume);
|
||||||
|
|
||||||
|
invoke(clarifyNodeTypeWorklet,
|
||||||
|
lowerEndSuperarcId,
|
||||||
|
lowerEndIntrinsicVolume,
|
||||||
|
upperEndSuperarcId,
|
||||||
|
upperEndIntrinsicVolume,
|
||||||
|
branchRoot,
|
||||||
|
isLowerLeaf,
|
||||||
|
isUpperLeaf);
|
||||||
|
|
||||||
|
vtkm::cont::UnknownArrayHandle upperEndValue =
|
||||||
|
hierarchicalTreeDataSet.GetField("UpperEndValue").GetData();
|
||||||
|
|
||||||
|
// Based on the direction info of the branch, store epsilon direction and isovalue of the saddle
|
||||||
|
auto resolveArray = [&](const auto& inArray) {
|
||||||
|
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||||
|
using ValueType = typename InArrayHandleType::ValueType;
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<ValueType> branchSaddleIsoValue;
|
||||||
|
branchSaddleIsoValue.Allocate(isLowerLeaf.GetNumberOfValues());
|
||||||
|
this->BranchSaddleEpsilon.Allocate(isLowerLeaf.GetNumberOfValues());
|
||||||
|
|
||||||
|
vtkm::worklet::scalar_topology::select_top_volume_contours::UpdateInfoByBranchDirectionWorklet<
|
||||||
|
ValueType>
|
||||||
|
updateInfoWorklet;
|
||||||
|
auto lowerEndValue = hierarchicalTreeDataSet.GetField("LowerEndValue")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<ValueType>>();
|
||||||
|
|
||||||
|
invoke(updateInfoWorklet,
|
||||||
|
isLowerLeaf,
|
||||||
|
isUpperLeaf,
|
||||||
|
inArray,
|
||||||
|
lowerEndValue,
|
||||||
|
this->BranchSaddleEpsilon,
|
||||||
|
branchSaddleIsoValue);
|
||||||
|
this->BranchSaddleIsoValue = branchSaddleIsoValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
upperEndValue.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(
|
||||||
|
resolveArray);
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType branchVolume;
|
||||||
|
vtkm::worklet::scalar_topology::select_top_volume_contours::GetBranchVolumeWorklet
|
||||||
|
getBranchVolumeWorklet(totalVolume);
|
||||||
|
|
||||||
|
invoke(getBranchVolumeWorklet, // worklet
|
||||||
|
lowerEndSuperarcId, // input
|
||||||
|
lowerEndIntrinsicVolume, // input
|
||||||
|
lowerEndDependentVolume, // input
|
||||||
|
upperEndSuperarcId, // input
|
||||||
|
upperEndIntrinsicVolume, // input
|
||||||
|
upperEndDependentVolume, // input
|
||||||
|
isLowerLeaf,
|
||||||
|
isUpperLeaf,
|
||||||
|
branchVolume); // output
|
||||||
|
|
||||||
|
#ifdef DEBUG_PRINT
|
||||||
|
std::stringstream resultStream;
|
||||||
|
resultStream << "Branch Volume In The Block" << std::endl;
|
||||||
|
const vtkm::Id nVolume = branchVolume.GetNumberOfValues();
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintHeader(nVolume, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"BranchVolume", branchVolume, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices("isLowerLeaf", isLowerLeaf, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices("isUpperLeaf", isUpperLeaf, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"LowerEndIntrinsicVol", lowerEndIntrinsicVolume, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"LowerEndDependentVol", lowerEndDependentVolume, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"UpperEndIntrinsicVol", upperEndIntrinsicVolume, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"UpperEndDependentVol", upperEndDependentVolume, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"LowerEndSuperarc", lowerEndSuperarcId, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"UpperEndSuperarc", upperEndSuperarcId, -1, resultStream);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices("BranchRoot", branchRoot, -1, resultStream);
|
||||||
|
resultStream << std::endl;
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info, resultStream.str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vtkm::cont::Algorithm::Copy(branchVolume, this->BranchVolume);
|
||||||
|
|
||||||
|
const vtkm::Id nBranches = lowerEndSuperarcId.GetNumberOfValues();
|
||||||
|
vtkm::cont::ArrayHandleIndex branchesIdx(nBranches);
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType sortedBranches;
|
||||||
|
vtkm::cont::Algorithm::Copy(branchesIdx, sortedBranches);
|
||||||
|
|
||||||
|
// sort the branch volume
|
||||||
|
vtkm::cont::Algorithm::SortByKey(branchVolume, sortedBranches, vtkm::SortGreater());
|
||||||
|
vtkm::cont::Algorithm::Copy(sortedBranches, this->SortedBranchByVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace filter
|
||||||
|
} // namespace vtkm
|
@ -0,0 +1,98 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_scalar_topology_internal_SelectTopVolumeContoursBlock_h
|
||||||
|
#define vtk_m_filter_scalar_topology_internal_SelectTopVolumeContoursBlock_h
|
||||||
|
|
||||||
|
#include <vtkm/cont/DataSet.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SelectTopVolumeContoursBlock
|
||||||
|
{
|
||||||
|
SelectTopVolumeContoursBlock(vtkm::Id localBlockNo, int globalBlockId);
|
||||||
|
|
||||||
|
void SortBranchByVolume(const vtkm::cont::DataSet& hierarchicalTreeDataSet,
|
||||||
|
const vtkm::Id totalVolume);
|
||||||
|
|
||||||
|
// Block metadata
|
||||||
|
vtkm::Id LocalBlockNo;
|
||||||
|
int GlobalBlockId; // TODO/FIXME: Check whether really needed. Possibly only during debugging
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType BranchVolume;
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType BranchSaddleEpsilon;
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType SortedBranchByVolume;
|
||||||
|
vtkm::cont::UnknownArrayHandle BranchSaddleIsoValue;
|
||||||
|
|
||||||
|
// Output Datasets.
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchRootGRId;
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchVolume;
|
||||||
|
vtkm::cont::UnknownArrayHandle TopVolumeBranchSaddleIsoValue;
|
||||||
|
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchSaddleEpsilon;
|
||||||
|
|
||||||
|
// Destroy function allowing DIY to own blocks and clean them up after use
|
||||||
|
static void Destroy(void* b) { delete static_cast<SelectTopVolumeContoursBlock*>(b); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace filter
|
||||||
|
} // namespace vtkm
|
||||||
|
#endif
|
@ -0,0 +1,384 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/internal/SelectTopVolumeContoursFunctor.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/GetOuterEndWorklet.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/ArrayTransforms.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchVolumeComparator.h>
|
||||||
|
|
||||||
|
#include <vtkm/Types.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG_PRINT
|
||||||
|
#define DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
|
||||||
|
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
void SelectTopVolumeContoursFunctor::operator()(
|
||||||
|
SelectTopVolumeContoursBlock* b,
|
||||||
|
const vtkmdiy::ReduceProxy& rp // communication proxy
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (this->nSavedBranches < 1)
|
||||||
|
return;
|
||||||
|
// Get our rank and DIY id
|
||||||
|
//const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank();
|
||||||
|
const auto selfid = rp.gid();
|
||||||
|
|
||||||
|
// Aliases to reduce verbosity
|
||||||
|
using IdArrayType = vtkm::worklet::contourtree_augmented::IdArrayType;
|
||||||
|
|
||||||
|
vtkm::cont::Invoker invoke;
|
||||||
|
|
||||||
|
if (rp.in_link().size() == 0)
|
||||||
|
{
|
||||||
|
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_HIGH_VOLUME_BRANCH
|
||||||
|
rp.enqueue(target, b->GlobalBlockId);
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||||
|
"Block " << b->GlobalBlockId << " enqueue to Block " << target.gid);
|
||||||
|
#endif
|
||||||
|
auto topVolBranchRootGRIdPortal = b->TopVolumeBranchRootGRId.ReadPortal();
|
||||||
|
auto topVolBranchVolumePortal = b->TopVolumeBranchVolume.ReadPortal();
|
||||||
|
auto topVolBranchSaddleEpsilonPortal = b->TopVolumeBranchSaddleEpsilon.ReadPortal();
|
||||||
|
|
||||||
|
vtkm::Id nBranches = topVolBranchRootGRIdPortal.GetNumberOfValues();
|
||||||
|
|
||||||
|
rp.enqueue(target, nBranches);
|
||||||
|
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||||
|
rp.enqueue(target, topVolBranchRootGRIdPortal.Get(branch));
|
||||||
|
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||||
|
rp.enqueue(target, topVolBranchVolumePortal.Get(branch));
|
||||||
|
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||||
|
rp.enqueue(target, topVolBranchSaddleEpsilonPortal.Get(branch));
|
||||||
|
|
||||||
|
auto resolveArray = [&](const auto& inArray) {
|
||||||
|
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||||
|
using ValueType = typename InArrayHandleType::ValueType;
|
||||||
|
auto topVolBranchSaddleIsoValuePortal = inArray.ReadPortal();
|
||||||
|
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||||
|
rp.enqueue<ValueType>(target, topVolBranchSaddleIsoValuePortal.Get(branch));
|
||||||
|
};
|
||||||
|
b->TopVolumeBranchSaddleIsoValue
|
||||||
|
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(resolveArray);
|
||||||
|
|
||||||
|
// rp.enqueue(target, b->TopVolumeBranchRootGRId);
|
||||||
|
// rp.enqueue(target, b->TopVolumeBranchVolume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rp.in_link().size(); ++i)
|
||||||
|
{
|
||||||
|
int ingid = rp.in_link().target(i).gid;
|
||||||
|
if (ingid == selfid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// copy incoming to the block
|
||||||
|
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
|
||||||
|
int incomingGlobalBlockId;
|
||||||
|
rp.dequeue(ingid, incomingGlobalBlockId);
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||||
|
"Combining local block " << b->GlobalBlockId << " with incoming block "
|
||||||
|
<< incomingGlobalBlockId);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// dequeue the data from other blocks.
|
||||||
|
// nIncomingBranches
|
||||||
|
// array of incoming branch global regular ID
|
||||||
|
// array of incoming branch volume
|
||||||
|
// array of branch epsilon direction
|
||||||
|
// array of branch saddle end value
|
||||||
|
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||||
|
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||||
|
vtkm::Id nIncoming;
|
||||||
|
rp.dequeue(ingid, nIncoming);
|
||||||
|
|
||||||
|
IdArrayType incomingTopVolBranchGRId;
|
||||||
|
incomingTopVolBranchGRId.Allocate(nIncoming);
|
||||||
|
auto incomingTopVolBranchGRIdPortal = incomingTopVolBranchGRId.WritePortal();
|
||||||
|
for (vtkm::Id branch = 0; branch < nIncoming; ++branch)
|
||||||
|
{
|
||||||
|
vtkm::Id incomingTmpBranchGRId;
|
||||||
|
rp.dequeue(ingid, incomingTmpBranchGRId);
|
||||||
|
incomingTopVolBranchGRIdPortal.Set(branch, incomingTmpBranchGRId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||||
|
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||||
|
// rp.dequeue(ingid, incomingTopVolBranchGRId);
|
||||||
|
|
||||||
|
IdArrayType incomingTopVolBranchVolume;
|
||||||
|
incomingTopVolBranchVolume.Allocate(nIncoming);
|
||||||
|
auto incomingTopVolBranchVolumePortal = incomingTopVolBranchVolume.WritePortal();
|
||||||
|
for (vtkm::Id branch = 0; branch < nIncoming; ++branch)
|
||||||
|
{
|
||||||
|
vtkm::Id incomingTmpBranchVolume;
|
||||||
|
rp.dequeue(ingid, incomingTmpBranchVolume);
|
||||||
|
incomingTopVolBranchVolumePortal.Set(branch, incomingTmpBranchVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||||
|
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||||
|
// rp.dequeue(ingid, incomingTopVolBranchVolume);
|
||||||
|
|
||||||
|
IdArrayType incomingTopVolBranchSaddleEpsilon;
|
||||||
|
incomingTopVolBranchSaddleEpsilon.Allocate(nIncoming);
|
||||||
|
auto incomingTopVolBranchSaddleEpsilonPortal =
|
||||||
|
incomingTopVolBranchSaddleEpsilon.WritePortal();
|
||||||
|
for (vtkm::Id branch = 0; branch < nIncoming; ++branch)
|
||||||
|
{
|
||||||
|
vtkm::Id incomingTmpBranchSaddleEpsilon;
|
||||||
|
rp.dequeue(ingid, incomingTmpBranchSaddleEpsilon);
|
||||||
|
incomingTopVolBranchSaddleEpsilonPortal.Set(branch, incomingTmpBranchSaddleEpsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||||
|
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||||
|
// rp.dequeue(ingid, incomingTopVolBranchSaddleEpsilon);
|
||||||
|
|
||||||
|
auto resolveArray = [&](auto& inArray) {
|
||||||
|
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||||
|
using ValueType = typename InArrayHandleType::ValueType;
|
||||||
|
InArrayHandleType incomingTopVolBranchSaddleIsoValue;
|
||||||
|
incomingTopVolBranchSaddleIsoValue.Allocate(nIncoming);
|
||||||
|
auto incomingTopVolBranchSaddleIsoValuePortal =
|
||||||
|
incomingTopVolBranchSaddleIsoValue.WritePortal();
|
||||||
|
for (vtkm::Id branch = 0; branch < nIncoming; ++branch)
|
||||||
|
{
|
||||||
|
ValueType incomingSaddleValue;
|
||||||
|
rp.dequeue<ValueType>(ingid, incomingSaddleValue);
|
||||||
|
incomingTopVolBranchSaddleIsoValuePortal.Set(branch, incomingSaddleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||||
|
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||||
|
// rp.dequeue<InArrayHandleType>(ingid, incomingTopVolBranchSaddleIsoValue);
|
||||||
|
|
||||||
|
vtkm::Id nSelf = b->TopVolumeBranchRootGRId.GetNumberOfValues();
|
||||||
|
|
||||||
|
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||||
|
"nIncoming = " << nIncoming << ", nSelf = " << nSelf);
|
||||||
|
{
|
||||||
|
std::stringstream rs;
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintHeader(nIncoming, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"incomingTopBranchId", incomingTopVolBranchGRId, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"incomingTopBranchVol", incomingTopVolBranchVolume, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||||
|
"incomingSaddleVal", incomingTopVolBranchSaddleIsoValue, -1, rs);
|
||||||
|
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintHeader(nSelf, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"selfTopBranchId", b->TopVolumeBranchRootGRId, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"selfTopBranchVol", b->TopVolumeBranchVolume, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||||
|
"selfTopSaddleVal", inArray, -1, rs);
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// merge incoming branches with self branches
|
||||||
|
IdArrayType mergedTopVolBranchGRId;
|
||||||
|
IdArrayType mergedTopVolBranchVolume;
|
||||||
|
IdArrayType mergedTopVolBranchSaddleEpsilon;
|
||||||
|
InArrayHandleType mergedTopVolBranchSaddleIsoValue;
|
||||||
|
mergedTopVolBranchGRId.Allocate(nIncoming + nSelf);
|
||||||
|
mergedTopVolBranchVolume.Allocate(nIncoming + nSelf);
|
||||||
|
mergedTopVolBranchSaddleEpsilon.Allocate(nIncoming + nSelf);
|
||||||
|
mergedTopVolBranchSaddleIsoValue.Allocate(nIncoming + nSelf);
|
||||||
|
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
incomingTopVolBranchGRId, 0, nIncoming, mergedTopVolBranchGRId, 0);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
incomingTopVolBranchVolume, 0, nIncoming, mergedTopVolBranchVolume, 0);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
incomingTopVolBranchSaddleEpsilon, 0, nIncoming, mergedTopVolBranchSaddleEpsilon, 0);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange<ValueType, ValueType>(
|
||||||
|
incomingTopVolBranchSaddleIsoValue, 0, nIncoming, mergedTopVolBranchSaddleIsoValue, 0);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
b->TopVolumeBranchRootGRId, 0, nSelf, mergedTopVolBranchGRId, nIncoming);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
b->TopVolumeBranchVolume, 0, nSelf, mergedTopVolBranchVolume, nIncoming);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
b->TopVolumeBranchSaddleEpsilon, 0, nSelf, mergedTopVolBranchSaddleEpsilon, nIncoming);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange<ValueType, ValueType>(
|
||||||
|
inArray, 0, nSelf, mergedTopVolBranchSaddleIsoValue, nIncoming);
|
||||||
|
|
||||||
|
// Sort all branches (incoming + self) based on volume
|
||||||
|
// sorting key: (volume, branch global regular ID)
|
||||||
|
// the highest volume comes first, the lowest branch GR ID comes first
|
||||||
|
vtkm::cont::ArrayHandleIndex mergedBranchId(nIncoming + nSelf);
|
||||||
|
IdArrayType sortedBranchId;
|
||||||
|
vtkm::cont::Algorithm::Copy(mergedBranchId, sortedBranchId);
|
||||||
|
vtkm::worklet::scalar_topology::select_top_volume_contours::BranchVolumeComparator
|
||||||
|
branchVolumeComparator(mergedTopVolBranchGRId, mergedTopVolBranchVolume);
|
||||||
|
vtkm::cont::Algorithm::Sort(sortedBranchId, branchVolumeComparator);
|
||||||
|
|
||||||
|
// permute the branch information based on sorting
|
||||||
|
IdArrayType permutedTopVolBranchGRId;
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
|
||||||
|
mergedTopVolBranchGRId, sortedBranchId, permutedTopVolBranchGRId);
|
||||||
|
IdArrayType permutedTopVolBranchVolume;
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
|
||||||
|
mergedTopVolBranchVolume, sortedBranchId, permutedTopVolBranchVolume);
|
||||||
|
IdArrayType permutedTopVolBranchSaddleEpsilon;
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
|
||||||
|
mergedTopVolBranchSaddleEpsilon, sortedBranchId, permutedTopVolBranchSaddleEpsilon);
|
||||||
|
InArrayHandleType permutedTopVolBranchSaddleIsoValue;
|
||||||
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithRawIndex<InArrayHandleType>(
|
||||||
|
mergedTopVolBranchSaddleIsoValue, sortedBranchId, permutedTopVolBranchSaddleIsoValue);
|
||||||
|
|
||||||
|
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
|
||||||
|
{
|
||||||
|
std::stringstream rs;
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintHeader(nIncoming + nSelf, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"permutedTopBranchId", permutedTopVolBranchGRId, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"permutedTopBranchVol", permutedTopVolBranchVolume, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||||
|
"permutedTopSaddleVal", permutedTopVolBranchSaddleIsoValue, -1, rs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// there may be duplicate branches. We remove duplicate branches based on global regular IDs
|
||||||
|
// We can reuse the filter from removing duplicate branches in the process of collecting branches
|
||||||
|
IdArrayType oneIfUniqueBranch;
|
||||||
|
oneIfUniqueBranch.Allocate(nIncoming + nSelf);
|
||||||
|
vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||||
|
OneIfBranchEndWorklet oneIfUniqueWorklet;
|
||||||
|
invoke(oneIfUniqueWorklet, mergedBranchId, permutedTopVolBranchGRId, oneIfUniqueBranch);
|
||||||
|
|
||||||
|
// Remove duplicate
|
||||||
|
IdArrayType mergedUniqueBranchGRId;
|
||||||
|
IdArrayType mergedUniqueBranchVolume;
|
||||||
|
IdArrayType mergedUniqueBranchSaddleEpsilon;
|
||||||
|
InArrayHandleType mergedUniqueBranchSaddleIsoValue;
|
||||||
|
|
||||||
|
vtkm::cont::Algorithm::CopyIf(
|
||||||
|
permutedTopVolBranchGRId, oneIfUniqueBranch, mergedUniqueBranchGRId);
|
||||||
|
vtkm::cont::Algorithm::CopyIf(
|
||||||
|
permutedTopVolBranchVolume, oneIfUniqueBranch, mergedUniqueBranchVolume);
|
||||||
|
vtkm::cont::Algorithm::CopyIf(
|
||||||
|
permutedTopVolBranchSaddleEpsilon, oneIfUniqueBranch, mergedUniqueBranchSaddleEpsilon);
|
||||||
|
vtkm::cont::Algorithm::CopyIf(
|
||||||
|
permutedTopVolBranchSaddleIsoValue, oneIfUniqueBranch, mergedUniqueBranchSaddleIsoValue);
|
||||||
|
|
||||||
|
vtkm::Id nMergedUnique = mergedUniqueBranchGRId.GetNumberOfValues();
|
||||||
|
|
||||||
|
#ifdef DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
|
||||||
|
{
|
||||||
|
std::stringstream rs;
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintHeader(nMergedUnique, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"mergedUniqueBranchId", mergedUniqueBranchGRId, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
|
"mergedUniqueBranchVol", mergedUniqueBranchVolume, -1, rs);
|
||||||
|
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||||
|
"mergedUniqueSaddleVal", mergedUniqueBranchSaddleIsoValue, -1, rs);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// After removing duplicate, if there are more branches than we need
|
||||||
|
// We only save the top nSavedBranches branches
|
||||||
|
if (nMergedUnique > this->nSavedBranches)
|
||||||
|
{
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
mergedUniqueBranchGRId, 0, this->nSavedBranches, b->TopVolumeBranchRootGRId);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
mergedUniqueBranchVolume, 0, this->nSavedBranches, b->TopVolumeBranchVolume);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(mergedUniqueBranchSaddleEpsilon,
|
||||||
|
0,
|
||||||
|
this->nSavedBranches,
|
||||||
|
b->TopVolumeBranchSaddleEpsilon);
|
||||||
|
// InArrayHandleType subRangeUniqueBranchSaddleIsoValue;
|
||||||
|
inArray.Allocate(this->nSavedBranches);
|
||||||
|
vtkm::cont::Algorithm::CopySubRange(
|
||||||
|
mergedUniqueBranchSaddleIsoValue, 0, this->nSavedBranches, inArray);
|
||||||
|
// inArray = subRangeUniqueBranchSaddleIsoValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vtkm::cont::Algorithm::Copy(mergedUniqueBranchGRId, b->TopVolumeBranchRootGRId);
|
||||||
|
vtkm::cont::Algorithm::Copy(mergedUniqueBranchVolume, b->TopVolumeBranchVolume);
|
||||||
|
vtkm::cont::Algorithm::Copy(mergedUniqueBranchSaddleEpsilon,
|
||||||
|
b->TopVolumeBranchSaddleEpsilon);
|
||||||
|
inArray.Allocate(nMergedUnique);
|
||||||
|
vtkm::cont::Algorithm::Copy(mergedUniqueBranchSaddleIsoValue, inArray);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
b->TopVolumeBranchSaddleIsoValue
|
||||||
|
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(resolveArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace filter
|
||||||
|
} // namespace vtkm
|
@ -0,0 +1,93 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_scalar_topology_internal_SelectTopVolumeContoursFunctor_h
|
||||||
|
#define vtk_m_filter_scalar_topology_internal_SelectTopVolumeContoursFunctor_h
|
||||||
|
|
||||||
|
#include <vtkm/filter/scalar_topology/internal/SelectTopVolumeContoursBlock.h>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||||
|
#include <vtkm/thirdparty/diy/diy.h>
|
||||||
|
VTKM_THIRDPARTY_POST_INCLUDE
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SelectTopVolumeContoursFunctor
|
||||||
|
{
|
||||||
|
SelectTopVolumeContoursFunctor(const vtkm::Id& nSB)
|
||||||
|
: nSavedBranches(nSB)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(SelectTopVolumeContoursBlock* b,
|
||||||
|
const vtkmdiy::ReduceProxy& rp // communication proxy
|
||||||
|
) const;
|
||||||
|
|
||||||
|
const vtkm::Id nSavedBranches;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace filter
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
|
#endif
|
@ -63,6 +63,7 @@
|
|||||||
#include <vtkm/filter/MapFieldPermutation.h>
|
#include <vtkm/filter/MapFieldPermutation.h>
|
||||||
#include <vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h>
|
#include <vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h>
|
||||||
#include <vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
|
#include <vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
|
||||||
|
#include <vtkm/filter/scalar_topology/SelectTopVolumeContoursFilter.h>
|
||||||
#include <vtkm/filter/scalar_topology/testing/SuperArcHelper.h>
|
#include <vtkm/filter/scalar_topology/testing/SuperArcHelper.h>
|
||||||
#include <vtkm/filter/scalar_topology/testing/VolumeHelper.h>
|
#include <vtkm/filter/scalar_topology/testing/VolumeHelper.h>
|
||||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
|
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
|
||||||
@ -466,6 +467,14 @@ inline void TestContourTreeUniformDistributedBranchDecomposition8x9(int nBlocks,
|
|||||||
augmentHierarchicalTree,
|
augmentHierarchicalTree,
|
||||||
computeHierarchicalVolumetricBranchDecomposition);
|
computeHierarchicalVolumetricBranchDecomposition);
|
||||||
|
|
||||||
|
using vtkm::filter::scalar_topology::SelectTopVolumeContoursFilter;
|
||||||
|
|
||||||
|
vtkm::Id numBranches = 2;
|
||||||
|
SelectTopVolumeContoursFilter tp_filter;
|
||||||
|
|
||||||
|
tp_filter.SetSavedBranches(numBranches);
|
||||||
|
|
||||||
|
auto tp_result = tp_filter.Execute(result);
|
||||||
|
|
||||||
if (vtkm::cont::EnvironmentTracker::GetCommunicator().rank() == 0)
|
if (vtkm::cont::EnvironmentTracker::GetCommunicator().rank() == 0)
|
||||||
{
|
{
|
||||||
@ -503,27 +512,99 @@ inline void TestContourTreeUniformDistributedBranchDecomposition8x9(int nBlocks,
|
|||||||
std::sort(computed.begin(), computed.end());
|
std::sort(computed.begin(), computed.end());
|
||||||
std::sort(expected.begin(), expected.end());
|
std::sort(expected.begin(), expected.end());
|
||||||
|
|
||||||
if (computed == expected)
|
if (computed != expected)
|
||||||
{
|
{
|
||||||
std::cout << "Branch Decomposition: Results Match!" << std::endl;
|
std::cout << "Branch Decomposition Results:" << std::endl;
|
||||||
return;
|
std::cout << "Computed Contour Tree" << std::endl;
|
||||||
|
for (std::size_t i = 0; i < computed.size(); i++)
|
||||||
|
{
|
||||||
|
std::cout << std::setw(12) << computed[i].low << std::setw(14) << computed[i].high
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Expected Contour Tree" << std::endl;
|
||||||
|
for (std::size_t i = 0; i < expected.size(); i++)
|
||||||
|
{
|
||||||
|
std::cout << std::setw(12) << expected[i].low << std::setw(14) << expected[i].high
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
VTKM_TEST_FAIL("Branch Decomposition Failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Branch Decomposition Results:" << std::endl;
|
std::cout << "Branch Decomposition: Results Match!" << std::endl;
|
||||||
std::cout << "Computed Contour Tree" << std::endl;
|
|
||||||
for (std::size_t i = 0; i < computed.size(); i++)
|
for (vtkm::Id ds_no = 0; ds_no < result.GetNumberOfPartitions(); ++ds_no)
|
||||||
{
|
{
|
||||||
std::cout << std::setw(12) << computed[i].low << std::setw(14) << computed[i].high
|
auto ds = tp_result.GetPartition(ds_no);
|
||||||
<< std::endl;
|
auto topVolBranchGRId = ds.GetField("TopVolumeBranchGlobalRegularIds")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||||
|
.ReadPortal();
|
||||||
|
auto topVolBranchVolume = ds.GetField("TopVolumeBranchVolume")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||||
|
.ReadPortal();
|
||||||
|
auto topVolBranchSaddleEpsilon = ds.GetField("TopVolumeBranchSaddleEpsilon")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||||
|
.ReadPortal();
|
||||||
|
auto topVolBranchSaddleIsoValue = ds.GetField("TopVolumeBranchSaddleIsoValue")
|
||||||
|
.GetData()
|
||||||
|
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Float32>>()
|
||||||
|
.ReadPortal();
|
||||||
|
|
||||||
|
vtkm::Id nSelectedBranches = topVolBranchGRId.GetNumberOfValues();
|
||||||
|
Edge expectedGRIdVolumeAtBranch0(38, 6);
|
||||||
|
Edge expectedEpsilonIsoAtBranch0(1, 50);
|
||||||
|
Edge expectedGRIdVolumeAtBranch1(50, 2);
|
||||||
|
Edge expectedEpsilonIsoAtBranch1(-1, 30);
|
||||||
|
|
||||||
|
for (vtkm::Id branch = 0; branch < nSelectedBranches; ++branch)
|
||||||
|
{
|
||||||
|
bool failed = false;
|
||||||
|
Edge computedGRIdVolume(topVolBranchGRId.Get(branch), topVolBranchVolume.Get(branch));
|
||||||
|
Edge computedEpsilonIso(topVolBranchSaddleEpsilon.Get(branch),
|
||||||
|
(vtkm::Id)topVolBranchSaddleIsoValue.Get(branch));
|
||||||
|
|
||||||
|
switch (branch)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
failed = !(computedGRIdVolume == expectedGRIdVolumeAtBranch0);
|
||||||
|
failed = (failed || !(computedEpsilonIso == expectedEpsilonIsoAtBranch0));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
failed = !(computedGRIdVolume == expectedGRIdVolumeAtBranch1);
|
||||||
|
failed = (failed || !(computedEpsilonIso == expectedEpsilonIsoAtBranch1));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VTKM_TEST_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
std::vector<Edge> expectedGRIdVolume{ expectedGRIdVolumeAtBranch0,
|
||||||
|
expectedGRIdVolumeAtBranch1 };
|
||||||
|
|
||||||
|
std::vector<Edge> expectedEpsilonIso{ expectedEpsilonIsoAtBranch0,
|
||||||
|
expectedEpsilonIsoAtBranch1 };
|
||||||
|
|
||||||
|
std::cout << "Top Branch Volume Results:" << std::endl;
|
||||||
|
std::cout << "Computed Top Branch Volume:branch=" << branch << std::endl;
|
||||||
|
std::cout << computedGRIdVolume.low << std::setw(14) << computedGRIdVolume.high
|
||||||
|
<< std::setw(5) << computedEpsilonIso.low << std::setw(14)
|
||||||
|
<< computedEpsilonIso.high << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Expected Top Branch Volume:branch=" << branch << std::endl;
|
||||||
|
std::cout << expectedGRIdVolume[branch].low << std::setw(14)
|
||||||
|
<< expectedGRIdVolume[branch].high << std::setw(5)
|
||||||
|
<< expectedEpsilonIso[branch].low << std::setw(14)
|
||||||
|
<< expectedEpsilonIso[branch].high << std::endl;
|
||||||
|
VTKM_TEST_FAIL("Top Branch Volume Computation Failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Expected Contour Tree" << std::endl;
|
std::cout << "Top Branch Volume: Results Match!" << std::endl;
|
||||||
for (std::size_t i = 0; i < expected.size(); i++)
|
|
||||||
{
|
|
||||||
std::cout << std::setw(12) << expected[i].low << std::setw(14) << expected[i].high
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
VTKM_TEST_FAIL("Branch Decomposition Failed!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ set(headers
|
|||||||
vtkm_declare_headers(${headers})
|
vtkm_declare_headers(${headers})
|
||||||
|
|
||||||
add_subdirectory(branch_decomposition)
|
add_subdirectory(branch_decomposition)
|
||||||
|
add_subdirectory(select_top_volume_contours)
|
||||||
add_subdirectory(contourtree)
|
add_subdirectory(contourtree)
|
||||||
add_subdirectory(contourtree_augmented)
|
add_subdirectory(contourtree_augmented)
|
||||||
add_subdirectory(contourtree_distributed)
|
add_subdirectory(contourtree_distributed)
|
||||||
|
19
vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h
19
vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h
@ -600,7 +600,7 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
|||||||
{
|
{
|
||||||
IdArrayType superarcGRId;
|
IdArrayType superarcGRId;
|
||||||
vtkm::cont::make_ArrayHandlePermutation(supernodes, globalRegularIds);
|
vtkm::cont::make_ArrayHandlePermutation(supernodes, globalRegularIds);
|
||||||
vtkm::worklet::contourtree_augmented::PermuteArray<vtkm::Id>(
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
globalRegularIds, supernodes, superarcGRId);
|
globalRegularIds, supernodes, superarcGRId);
|
||||||
|
|
||||||
std::stringstream resultStream;
|
std::stringstream resultStream;
|
||||||
@ -615,7 +615,7 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
|||||||
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||||
using ValueType = typename InArrayHandleType::ValueType;
|
using ValueType = typename InArrayHandleType::ValueType;
|
||||||
vtkm::cont::ArrayHandle<ValueType> superarcValue;
|
vtkm::cont::ArrayHandle<ValueType> superarcValue;
|
||||||
vtkm::worklet::contourtree_augmented::PermuteArray<ValueType>(
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithRawIndex<InArrayHandleType>(
|
||||||
inArray, supernodes, superarcValue);
|
inArray, supernodes, superarcValue);
|
||||||
vtkm::worklet::contourtree_augmented::PrintValues(
|
vtkm::worklet::contourtree_augmented::PrintValues(
|
||||||
"Data Values", superarcValue, -1, resultStream);
|
"Data Values", superarcValue, -1, resultStream);
|
||||||
@ -627,7 +627,6 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
|||||||
"Intrinsic Volumes", intrinsicVolumes, -1, resultStream);
|
"Intrinsic Volumes", intrinsicVolumes, -1, resultStream);
|
||||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||||
"Dependent Volumes", dependentVolumes, -1, resultStream);
|
"Dependent Volumes", dependentVolumes, -1, resultStream);
|
||||||
resultStream << std::endl;
|
|
||||||
|
|
||||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, resultStream.str());
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info, resultStream.str());
|
||||||
}
|
}
|
||||||
@ -690,27 +689,27 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
|||||||
// actualOuterNodeValues[i] = dataValues[supernodes[outerNodes[actualSuperarcs[i]]]];
|
// actualOuterNodeValues[i] = dataValues[supernodes[outerNodes[actualSuperarcs[i]]]];
|
||||||
// actualOuterNodeRegularIds[i] = globalRegularIds[supernodes[outerNodes[actualSuperarcs[i]]]];
|
// actualOuterNodeRegularIds[i] = globalRegularIds[supernodes[outerNodes[actualSuperarcs[i]]]];
|
||||||
// }
|
// }
|
||||||
// Solution: PermuteArray helps allocate the space so no need for explicit allocation
|
// Solution: PermuteArrayWithMaskedIndex helps allocate the space so no need for explicit allocation
|
||||||
// PermuteArray also calls MaskedIndex
|
// PermuteArrayWithMaskedIndex also calls MaskedIndex
|
||||||
|
|
||||||
// IdArrayType, size: nActualSuperarcs
|
// IdArrayType, size: nActualSuperarcs
|
||||||
IdArrayType actualBranchRoots;
|
IdArrayType actualBranchRoots;
|
||||||
vtkm::worklet::contourtree_augmented::PermuteArray<vtkm::Id>(
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
branchRoots, actualSuperarcs, actualBranchRoots);
|
branchRoots, actualSuperarcs, actualBranchRoots);
|
||||||
|
|
||||||
// IdArrayType, size: nActualSuperarcs
|
// IdArrayType, size: nActualSuperarcs
|
||||||
IdArrayType actualOuterNodes;
|
IdArrayType actualOuterNodes;
|
||||||
vtkm::worklet::contourtree_augmented::PermuteArray<vtkm::Id>(
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
outerNodes, actualSuperarcs, actualOuterNodes);
|
outerNodes, actualSuperarcs, actualOuterNodes);
|
||||||
|
|
||||||
// IdArrayType, size: nActualSuperarcs
|
// IdArrayType, size: nActualSuperarcs
|
||||||
IdArrayType actualOuterNodeLocalIds;
|
IdArrayType actualOuterNodeLocalIds;
|
||||||
vtkm::worklet::contourtree_augmented::PermuteArray<vtkm::Id>(
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
supernodes, actualOuterNodes, actualOuterNodeLocalIds);
|
supernodes, actualOuterNodes, actualOuterNodeLocalIds);
|
||||||
|
|
||||||
// IdArrayType, size: nActualSuperarcs
|
// IdArrayType, size: nActualSuperarcs
|
||||||
IdArrayType actualOuterNodeRegularIds;
|
IdArrayType actualOuterNodeRegularIds;
|
||||||
vtkm::worklet::contourtree_augmented::PermuteArray<vtkm::Id>(
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
globalRegularIds, actualOuterNodeLocalIds, actualOuterNodeRegularIds);
|
globalRegularIds, actualOuterNodeLocalIds, actualOuterNodeRegularIds);
|
||||||
|
|
||||||
auto resolveArray = [&](const auto& inArray) {
|
auto resolveArray = [&](const auto& inArray) {
|
||||||
@ -744,7 +743,7 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
|||||||
|
|
||||||
// This is the real superarc local ID after permutation
|
// This is the real superarc local ID after permutation
|
||||||
IdArrayType permutedActualSuperarcs;
|
IdArrayType permutedActualSuperarcs;
|
||||||
vtkm::worklet::contourtree_augmented::PermuteArray<vtkm::Id>(
|
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
actualSuperarcs, sortedSuperarcs, permutedActualSuperarcs);
|
actualSuperarcs, sortedSuperarcs, permutedActualSuperarcs);
|
||||||
|
|
||||||
#ifdef DEBUG_HIERARCHICAL_VOLUMETRIC_BRANCH_DECOMPOSER
|
#ifdef DEBUG_HIERARCHICAL_VOLUMETRIC_BRANCH_DECOMPOSER
|
||||||
|
@ -942,13 +942,13 @@ inline void ActiveGraph::DebugPrint(const char* message, const char* fileName, l
|
|||||||
|
|
||||||
// Active Vertex Arrays
|
// Active Vertex Arrays
|
||||||
IdArrayType activeIndices;
|
IdArrayType activeIndices;
|
||||||
PermuteArray<vtkm::Id>(this->GlobalIndex, this->ActiveVertices, activeIndices);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->GlobalIndex, this->ActiveVertices, activeIndices);
|
||||||
IdArrayType activeFirst;
|
IdArrayType activeFirst;
|
||||||
PermuteArray<vtkm::Id>(this->FirstEdge, this->ActiveVertices, activeFirst);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->FirstEdge, this->ActiveVertices, activeFirst);
|
||||||
IdArrayType activeOutdegree;
|
IdArrayType activeOutdegree;
|
||||||
PermuteArray<vtkm::Id>(this->Outdegree, this->ActiveVertices, activeOutdegree);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->Outdegree, this->ActiveVertices, activeOutdegree);
|
||||||
IdArrayType activeHyperarcs;
|
IdArrayType activeHyperarcs;
|
||||||
PermuteArray<vtkm::Id>(this->Hyperarcs, this->ActiveVertices, activeHyperarcs);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->Hyperarcs, this->ActiveVertices, activeHyperarcs);
|
||||||
std::cout << "Active Vertex Arrays - Size: " << this->ActiveVertices.GetNumberOfValues()
|
std::cout << "Active Vertex Arrays - Size: " << this->ActiveVertices.GetNumberOfValues()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
PrintHeader(this->ActiveVertices.GetNumberOfValues());
|
PrintHeader(this->ActiveVertices.GetNumberOfValues());
|
||||||
@ -961,9 +961,9 @@ inline void ActiveGraph::DebugPrint(const char* message, const char* fileName, l
|
|||||||
|
|
||||||
// Full Edge Arrays
|
// Full Edge Arrays
|
||||||
IdArrayType farIndices;
|
IdArrayType farIndices;
|
||||||
PermuteArray<vtkm::Id>(this->GlobalIndex, this->EdgeFar, farIndices);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->GlobalIndex, this->EdgeFar, farIndices);
|
||||||
IdArrayType nearIndices;
|
IdArrayType nearIndices;
|
||||||
PermuteArray<vtkm::Id>(this->GlobalIndex, this->EdgeNear, nearIndices);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->GlobalIndex, this->EdgeNear, nearIndices);
|
||||||
std::cout << "Full Edge Arrays - Size: " << this->EdgeNear.GetNumberOfValues() << std::endl;
|
std::cout << "Full Edge Arrays - Size: " << this->EdgeNear.GetNumberOfValues() << std::endl;
|
||||||
PrintHeader(this->EdgeFar.GetNumberOfValues());
|
PrintHeader(this->EdgeFar.GetNumberOfValues());
|
||||||
PrintIndices("Near", this->EdgeNear);
|
PrintIndices("Near", this->EdgeNear);
|
||||||
@ -974,9 +974,9 @@ inline void ActiveGraph::DebugPrint(const char* message, const char* fileName, l
|
|||||||
|
|
||||||
// Active Edge Arrays
|
// Active Edge Arrays
|
||||||
IdArrayType activeFarIndices;
|
IdArrayType activeFarIndices;
|
||||||
PermuteArray<vtkm::Id>(this->EdgeFar, this->ActiveEdges, activeFarIndices);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->EdgeFar, this->ActiveEdges, activeFarIndices);
|
||||||
IdArrayType activeNearIndices;
|
IdArrayType activeNearIndices;
|
||||||
PermuteArray<vtkm::Id>(this->EdgeNear, this->ActiveEdges, activeNearIndices);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->EdgeNear, this->ActiveEdges, activeNearIndices);
|
||||||
std::cout << "Active Edge Arrays - Size: " << this->ActiveEdges.GetNumberOfValues()
|
std::cout << "Active Edge Arrays - Size: " << this->ActiveEdges.GetNumberOfValues()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
PrintHeader(this->ActiveEdges.GetNumberOfValues());
|
PrintHeader(this->ActiveEdges.GetNumberOfValues());
|
||||||
@ -987,9 +987,9 @@ inline void ActiveGraph::DebugPrint(const char* message, const char* fileName, l
|
|||||||
|
|
||||||
// Edge Sorter Array
|
// Edge Sorter Array
|
||||||
IdArrayType sortedFarIndices;
|
IdArrayType sortedFarIndices;
|
||||||
PermuteArray<vtkm::Id>(this->EdgeFar, this->EdgeSorter, sortedFarIndices);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->EdgeFar, this->EdgeSorter, sortedFarIndices);
|
||||||
IdArrayType sortedNearIndices;
|
IdArrayType sortedNearIndices;
|
||||||
PermuteArray<vtkm::Id>(this->EdgeNear, this->EdgeSorter, sortedNearIndices);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->EdgeNear, this->EdgeSorter, sortedNearIndices);
|
||||||
std::cout << "Edge Sorter - Size: " << this->EdgeSorter.GetNumberOfValues() << std::endl;
|
std::cout << "Edge Sorter - Size: " << this->EdgeSorter.GetNumberOfValues() << std::endl;
|
||||||
PrintHeader(this->EdgeSorter.GetNumberOfValues());
|
PrintHeader(this->EdgeSorter.GetNumberOfValues());
|
||||||
PrintIndices("Edge Sorter", this->EdgeSorter);
|
PrintIndices("Edge Sorter", this->EdgeSorter);
|
||||||
|
@ -75,7 +75,9 @@ namespace contourtree_augmented
|
|||||||
|
|
||||||
// permute routines
|
// permute routines
|
||||||
template <typename ValueType, typename ArrayType>
|
template <typename ValueType, typename ArrayType>
|
||||||
inline void PermuteArray(const ArrayType& input, IdArrayType& permute, ArrayType& output)
|
inline void PermuteArrayWithMaskedIndex(const ArrayType& input,
|
||||||
|
IdArrayType& permute,
|
||||||
|
ArrayType& output)
|
||||||
{ // permuteValues()
|
{ // permuteValues()
|
||||||
using transform_type =
|
using transform_type =
|
||||||
vtkm::cont::ArrayHandleTransform<IdArrayType, MaskedIndexFunctor<ValueType>>;
|
vtkm::cont::ArrayHandleTransform<IdArrayType, MaskedIndexFunctor<ValueType>>;
|
||||||
@ -110,6 +112,38 @@ inline void PermuteArray(const ArrayType& input, IdArrayType& permute, ArrayType
|
|||||||
} // permuteValues()
|
} // permuteValues()
|
||||||
|
|
||||||
|
|
||||||
|
// permute value type arrays
|
||||||
|
template <typename ArrayType>
|
||||||
|
inline void PermuteArrayWithRawIndex(const ArrayType& input,
|
||||||
|
IdArrayType& permute,
|
||||||
|
ArrayType& output)
|
||||||
|
{ // PermuteArrayWithRawIndex()
|
||||||
|
using permute_type = vtkm::cont::ArrayHandlePermutation<IdArrayType, ArrayType>;
|
||||||
|
|
||||||
|
// resize the output, i.e., output.resize(permute.size());
|
||||||
|
vtkm::Id permNumValues = permute.GetNumberOfValues();
|
||||||
|
vtkm::Id outNumValues = output.GetNumberOfValues();
|
||||||
|
if (permNumValues > outNumValues)
|
||||||
|
{
|
||||||
|
output.Allocate(permNumValues);
|
||||||
|
}
|
||||||
|
else if (permNumValues < outNumValues)
|
||||||
|
{
|
||||||
|
output.Allocate(permNumValues, vtkm::CopyFlag::On);
|
||||||
|
} // else the output has already the correct size
|
||||||
|
|
||||||
|
// The following is equivalent to doing the following in serial
|
||||||
|
//
|
||||||
|
// for (vtkm::Id entry = 0; entry < permute.size(); entry++)
|
||||||
|
// output[entry] = input[permute[entry]];
|
||||||
|
//
|
||||||
|
// fancy vtkm array so that we do not actually copy any data here
|
||||||
|
permute_type permutedInput(permute, input);
|
||||||
|
// Finally, copy the permuted values to the output array
|
||||||
|
vtkm::cont::ArrayCopyDevice(permutedInput, output);
|
||||||
|
} // PermuteArrayWithRawIndex()
|
||||||
|
|
||||||
|
|
||||||
// transform functor used in ContourTreeMesh to flag indicies as other when using the CombinedVectorClass
|
// transform functor used in ContourTreeMesh to flag indicies as other when using the CombinedVectorClass
|
||||||
struct MarkOther
|
struct MarkOther
|
||||||
{
|
{
|
||||||
|
@ -268,13 +268,13 @@ inline void ContourTreeMaker::ComputeHyperAndSuperStructure()
|
|||||||
|
|
||||||
// we have to permute a bunch of arrays, so let's have some temporaries to store them
|
// we have to permute a bunch of arrays, so let's have some temporaries to store them
|
||||||
IdArrayType permutedHyperparents;
|
IdArrayType permutedHyperparents;
|
||||||
PermuteArray<vtkm::Id>(
|
PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
this->ContourTreeResult.Hyperparents, this->ContourTreeResult.Hypernodes, permutedHyperparents);
|
this->ContourTreeResult.Hyperparents, this->ContourTreeResult.Hypernodes, permutedHyperparents);
|
||||||
IdArrayType permutedSupernodes;
|
IdArrayType permutedSupernodes;
|
||||||
PermuteArray<vtkm::Id>(
|
PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
this->ContourTreeResult.Supernodes, this->ContourTreeResult.Hypernodes, permutedSupernodes);
|
this->ContourTreeResult.Supernodes, this->ContourTreeResult.Hypernodes, permutedSupernodes);
|
||||||
IdArrayType permutedSuperarcs;
|
IdArrayType permutedSuperarcs;
|
||||||
PermuteArray<vtkm::Id>(
|
PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
this->ContourTreeResult.Superarcs, this->ContourTreeResult.Hypernodes, permutedSuperarcs);
|
this->ContourTreeResult.Superarcs, this->ContourTreeResult.Hypernodes, permutedSuperarcs);
|
||||||
|
|
||||||
// now we establish the reverse index array
|
// now we establish the reverse index array
|
||||||
@ -284,7 +284,7 @@ inline void ContourTreeMaker::ComputeHyperAndSuperStructure()
|
|||||||
// for (vtkm::Id supernode = 0; supernode < this->ContourTreeResult.Supernodes.size(); supernode++)
|
// for (vtkm::Id supernode = 0; supernode < this->ContourTreeResult.Supernodes.size(); supernode++)
|
||||||
// superSortIndex[this->ContourTreeResult.Hypernodes[supernode]] = supernode;
|
// superSortIndex[this->ContourTreeResult.Hypernodes[supernode]] = supernode;
|
||||||
|
|
||||||
//typedef vtkm::cont::ArrayHandlePermutation<IdArrayType, vtkm::cont::ArrayHandleIndex> PermuteArrayHandleIndex;
|
//typedef vtkm::cont::ArrayHandlePermutation<IdArrayType, vtkm::cont::ArrayHandleIndex> PermuteArrayWithMaskedIndexHandleIndex;
|
||||||
vtkm::cont::ArrayHandlePermutation<IdArrayType, IdArrayType> permutedSuperSortIndex(
|
vtkm::cont::ArrayHandlePermutation<IdArrayType, IdArrayType> permutedSuperSortIndex(
|
||||||
this->ContourTreeResult.Hypernodes, // index array
|
this->ContourTreeResult.Hypernodes, // index array
|
||||||
superSortIndex); // value array
|
superSortIndex); // value array
|
||||||
@ -307,7 +307,7 @@ inline void ContourTreeMaker::ComputeHyperAndSuperStructure()
|
|||||||
|
|
||||||
// we will permute the hyperarcs & copy them back with the new supernode target IDs
|
// we will permute the hyperarcs & copy them back with the new supernode target IDs
|
||||||
IdArrayType permutedHyperarcs;
|
IdArrayType permutedHyperarcs;
|
||||||
PermuteArray<vtkm::Id>(
|
PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
this->ContourTreeResult.Hyperarcs, this->ContourTreeResult.Hypernodes, permutedHyperarcs);
|
this->ContourTreeResult.Hyperarcs, this->ContourTreeResult.Hypernodes, permutedHyperarcs);
|
||||||
contourtree_maker_inc_ns::ComputeHyperAndSuperStructure_PermuteArcs permuteHyperarcsWorklet;
|
contourtree_maker_inc_ns::ComputeHyperAndSuperStructure_PermuteArcs permuteHyperarcsWorklet;
|
||||||
this->Invoke(
|
this->Invoke(
|
||||||
@ -315,9 +315,9 @@ inline void ContourTreeMaker::ComputeHyperAndSuperStructure()
|
|||||||
|
|
||||||
// now swizzle the WhenTransferred value
|
// now swizzle the WhenTransferred value
|
||||||
IdArrayType permutedWhenTransferred;
|
IdArrayType permutedWhenTransferred;
|
||||||
PermuteArray<vtkm::Id>(this->ContourTreeResult.WhenTransferred,
|
PermuteArrayWithMaskedIndex<vtkm::Id>(this->ContourTreeResult.WhenTransferred,
|
||||||
this->ContourTreeResult.Hypernodes,
|
this->ContourTreeResult.Hypernodes,
|
||||||
permutedWhenTransferred);
|
permutedWhenTransferred);
|
||||||
vtkm::cont::Algorithm::Copy(permutedWhenTransferred, this->ContourTreeResult.WhenTransferred);
|
vtkm::cont::Algorithm::Copy(permutedWhenTransferred, this->ContourTreeResult.WhenTransferred);
|
||||||
|
|
||||||
// now we compress both the hypernodes & Hyperarcs
|
// now we compress both the hypernodes & Hyperarcs
|
||||||
|
@ -72,7 +72,7 @@ namespace contourtree_augmented
|
|||||||
{
|
{
|
||||||
|
|
||||||
// local constants to allow changing the spacing as needed
|
// local constants to allow changing the spacing as needed
|
||||||
constexpr int PRINT_WIDTH = 12;
|
constexpr int PRINT_WIDTH = 14;
|
||||||
constexpr int PREFIX_WIDTH = 30;
|
constexpr int PREFIX_WIDTH = 30;
|
||||||
|
|
||||||
template <typename T, typename StorageType>
|
template <typename T, typename StorageType>
|
||||||
|
@ -659,11 +659,12 @@ public:
|
|||||||
|
|
||||||
IdArrayType permutedBranches;
|
IdArrayType permutedBranches;
|
||||||
permutedBranches.Allocate(nSupernodes);
|
permutedBranches.Allocate(nSupernodes);
|
||||||
PermuteArray<vtkm::Id>(whichBranch, supernodeSorter, permutedBranches);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(whichBranch, supernodeSorter, permutedBranches);
|
||||||
|
|
||||||
IdArrayType permutedRegularID;
|
IdArrayType permutedRegularID;
|
||||||
permutedRegularID.Allocate(nSupernodes);
|
permutedRegularID.Allocate(nSupernodes);
|
||||||
PermuteArray<vtkm::Id>(contourTree.Supernodes, supernodeSorter, permutedRegularID);
|
PermuteArrayWithMaskedIndex<vtkm::Id>(
|
||||||
|
contourTree.Supernodes, supernodeSorter, permutedRegularID);
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT
|
#ifdef DEBUG_PRINT
|
||||||
std::cout << "VI A. Sorted into Branches" << std::endl;
|
std::cout << "VI A. Sorted into Branches" << std::endl;
|
||||||
|
146
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchVolumeComparator.h
Normal file
146
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchVolumeComparator.h
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_scalar_topology_worklet_branch_decomposition_select_top_volume_contours_BranchVolumeComparator_h
|
||||||
|
#define vtk_m_filter_scalar_topology_worklet_branch_decomposition_select_top_volume_contours_BranchVolumeComparator_h
|
||||||
|
|
||||||
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace worklet
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace select_top_volume_contours
|
||||||
|
{
|
||||||
|
|
||||||
|
using IdArrayType = vtkm::worklet::contourtree_augmented::IdArrayType;
|
||||||
|
|
||||||
|
// Implementation of BranchVolumeComparator
|
||||||
|
class BranchVolumeComparatorImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using IdPortalType = typename IdArrayType::ReadPortalType;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
VTKM_CONT
|
||||||
|
BranchVolumeComparatorImpl(const IdArrayType& branchRoots,
|
||||||
|
const IdArrayType& branchVolume,
|
||||||
|
vtkm::cont::DeviceAdapterId device,
|
||||||
|
vtkm::cont::Token& token)
|
||||||
|
: branchRootsPortal(branchRoots.PrepareForInput(device, token))
|
||||||
|
, branchVolumePortal(branchVolume.PrepareForInput(device, token))
|
||||||
|
{ // constructor
|
||||||
|
} // constructor
|
||||||
|
|
||||||
|
// () operator - gets called to do comparison
|
||||||
|
VTKM_EXEC
|
||||||
|
bool operator()(const vtkm::Id& i, const vtkm::Id& j) const
|
||||||
|
{ // operator()
|
||||||
|
vtkm::Id volumeI = this->branchVolumePortal.Get(i);
|
||||||
|
vtkm::Id volumeJ = this->branchVolumePortal.Get(j);
|
||||||
|
|
||||||
|
// primary sort on branch volume
|
||||||
|
if (volumeI > volumeJ)
|
||||||
|
return true;
|
||||||
|
if (volumeI < volumeJ)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vtkm::Id branchI =
|
||||||
|
vtkm::worklet::contourtree_augmented::MaskedIndex(this->branchRootsPortal.Get(i));
|
||||||
|
vtkm::Id branchJ =
|
||||||
|
vtkm::worklet::contourtree_augmented::MaskedIndex(this->branchRootsPortal.Get(j));
|
||||||
|
|
||||||
|
// secondary sort on branch ID
|
||||||
|
return (branchI < branchJ);
|
||||||
|
} // operator()
|
||||||
|
|
||||||
|
private:
|
||||||
|
IdPortalType branchRootsPortal;
|
||||||
|
IdPortalType branchVolumePortal;
|
||||||
|
|
||||||
|
}; // BranchVolumeComparatorImpl
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Comparator of branch volume. Higher volume comes first
|
||||||
|
/// </summary>
|
||||||
|
class BranchVolumeComparator : public vtkm::cont::ExecutionObjectBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
VTKM_CONT
|
||||||
|
BranchVolumeComparator(const IdArrayType& branchRoots, const IdArrayType& branchVolume)
|
||||||
|
: BranchRoots(branchRoots)
|
||||||
|
, BranchVolume(branchVolume)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT BranchVolumeComparatorImpl PrepareForExecution(vtkm::cont::DeviceAdapterId device,
|
||||||
|
vtkm::cont::Token& token) const
|
||||||
|
{
|
||||||
|
return BranchVolumeComparatorImpl(this->BranchRoots, this->BranchVolume, device, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IdArrayType BranchRoots;
|
||||||
|
IdArrayType BranchVolume;
|
||||||
|
}; // BranchVolumeComparator
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace select_top_volume_contours
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace worklet
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,19 @@
|
|||||||
|
##============================================================================
|
||||||
|
## 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
|
||||||
|
ClarifyBranchEndSupernodeTypeWorklet.h
|
||||||
|
UpdateInfoByBranchDirectionWorklet.h
|
||||||
|
GetBranchVolumeWorklet.h
|
||||||
|
BranchVolumeComparator.h
|
||||||
|
)
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
vtkm_declare_headers(${headers})
|
133
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/ClarifyBranchEndSupernodeTypeWorklet.h
Normal file
133
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/ClarifyBranchEndSupernodeTypeWorklet.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_scalar_topology_worklet_select_top_volume_contours_ClarifyBranchEndSupernodeTypeWorklet_h
|
||||||
|
#define vtk_m_filter_scalar_topology_worklet_select_top_volume_contours_ClarifyBranchEndSupernodeTypeWorklet_h
|
||||||
|
|
||||||
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace worklet
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace select_top_volume_contours
|
||||||
|
{
|
||||||
|
|
||||||
|
// For special branches that only have one superarc
|
||||||
|
// Clarify which end is leaf and which is saddle
|
||||||
|
class ClarifyBranchEndSupernodeTypeWorklet : public vtkm::worklet::WorkletMapField
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ControlSignature = void(
|
||||||
|
FieldIn lowerSuperarcId, // (input) lower end superarc ID
|
||||||
|
FieldIn lowerIntrinsic, // (input) lower end superarc intrisic volume
|
||||||
|
FieldIn upperSuperarcId, // (input) upper end superarc ID
|
||||||
|
FieldIn upperIntrinsic, // (input) upper end superarc intrisic volume
|
||||||
|
FieldIn branchRoot, // (input) branch root superarc ID
|
||||||
|
FieldInOut isLowerLeaf, // (input/output) bool, whether the lower end is a leaf
|
||||||
|
FieldInOut isUpperLeaf // (input/output) bool, whether the upper end is a leaf
|
||||||
|
);
|
||||||
|
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7);
|
||||||
|
using InputDomain = _1;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
ClarifyBranchEndSupernodeTypeWorklet(const vtkm::Id tVol)
|
||||||
|
: totalVolume(tVol)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The functor checks the direction of the branch
|
||||||
|
VTKM_EXEC void operator()(const vtkm::Id& lowerSuperarcId,
|
||||||
|
const vtkm::Id& lowerIntrinsic,
|
||||||
|
const vtkm::Id& upperSuperarcId,
|
||||||
|
const vtkm::Id& upperIntrinsic,
|
||||||
|
const vtkm::Id& branchRoot,
|
||||||
|
bool& isLowerLeaf,
|
||||||
|
bool& isUpperLeaf) const
|
||||||
|
{
|
||||||
|
// do nothing: not a "leaf-leaf" branch
|
||||||
|
if (!isLowerLeaf || !isUpperLeaf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// do nothing: actual leaf-leaf branch
|
||||||
|
if (lowerIntrinsic == totalVolume - 1 && lowerIntrinsic == upperIntrinsic)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// do something: fake leaf-leaf branch
|
||||||
|
// we already exclude the case of only one superarc above
|
||||||
|
vtkm::Id maskedLowerId = vtkm::worklet::contourtree_augmented::MaskedIndex(lowerSuperarcId);
|
||||||
|
vtkm::Id maskedUpperId = vtkm::worklet::contourtree_augmented::MaskedIndex(upperSuperarcId);
|
||||||
|
vtkm::Id maskedRoot = vtkm::worklet::contourtree_augmented::MaskedIndex(branchRoot);
|
||||||
|
|
||||||
|
if (maskedLowerId == maskedRoot && maskedUpperId == maskedRoot)
|
||||||
|
{
|
||||||
|
const bool isAscending = vtkm::worklet::contourtree_augmented::IsAscending(lowerSuperarcId);
|
||||||
|
if (isAscending)
|
||||||
|
isUpperLeaf = false;
|
||||||
|
else
|
||||||
|
isLowerLeaf = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const vtkm::Id totalVolume;
|
||||||
|
}; // ClarifyBranchEndSupernodeTypeWorklet
|
||||||
|
|
||||||
|
} // namespace select_top_volume_contours
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace worklet
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
|
#endif
|
137
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/GetBranchVolumeWorklet.h
Normal file
137
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/GetBranchVolumeWorklet.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_scalar_topology_worklet_select_top_volume_contours_GetBranchVolumeWorklet_h
|
||||||
|
#define vtk_m_filter_scalar_topology_worklet_select_top_volume_contours_GetBranchVolumeWorklet_h
|
||||||
|
|
||||||
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace worklet
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace select_top_volume_contours
|
||||||
|
{
|
||||||
|
|
||||||
|
using IdArrayType = vtkm::worklet::contourtree_augmented::IdArrayType;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// worklet to check the direction of branch
|
||||||
|
/// return true if the branch inner superarc points to the senior-most node
|
||||||
|
/// return false if the branch inner superarc comes from the senior-most node
|
||||||
|
/// trick: if the branch is the main branch, we return true for computation later
|
||||||
|
/// </summary>
|
||||||
|
class GetBranchVolumeWorklet : public vtkm::worklet::WorkletMapField
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ControlSignature = void(
|
||||||
|
FieldIn lowerDirection, // (input) lower end superarc ID with direction information
|
||||||
|
FieldIn lowerIntrinsic, // (input) lower end superarc intrisic volume
|
||||||
|
FieldIn lowerDependent, // (input) lower end superarc dependent volume
|
||||||
|
FieldIn upperDirection, // (input) upper end superarc ID with direction information
|
||||||
|
FieldIn upperIntrinsic, // (input) upper end superarc intrisic volume
|
||||||
|
FieldIn upperDependent, // (input) upper end superarc dependent volume
|
||||||
|
FieldIn isLowerLeaf, // (input) bool, whether the lower end is a leaf
|
||||||
|
FieldIn isUpperLeaf, // (input) bool, whether the upper end is a leaf
|
||||||
|
FieldOut branchVolume // (output) volume of the branch
|
||||||
|
);
|
||||||
|
using ExecutionSignature = _9(_1, _2, _3, _4, _5, _6, _7, _8);
|
||||||
|
using InputDomain = _1;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
GetBranchVolumeWorklet(const vtkm::Id tVol)
|
||||||
|
: totalVolume(tVol)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The functor checks the direction of the branch
|
||||||
|
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& lowerDirection,
|
||||||
|
const vtkm::Id& lowerIntrinsic,
|
||||||
|
const vtkm::Id& lowerDependent,
|
||||||
|
const vtkm::Id& upperDirection,
|
||||||
|
const vtkm::Id& upperIntrinsic,
|
||||||
|
const vtkm::Id& upperDependent,
|
||||||
|
const bool& isLowerLeaf,
|
||||||
|
const bool& isUpperLeaf) const
|
||||||
|
{
|
||||||
|
if (isLowerLeaf && isUpperLeaf)
|
||||||
|
return totalVolume;
|
||||||
|
// if the branch is a minimum-saddle branch
|
||||||
|
// if the upper end superarc direction is pointing up, then dependent; otherwise, reverse
|
||||||
|
if (isLowerLeaf)
|
||||||
|
return contourtree_augmented::IsAscending(upperDirection)
|
||||||
|
? upperDependent
|
||||||
|
: totalVolume - upperDependent + upperIntrinsic;
|
||||||
|
// if the branch is a maximum-saddle branch
|
||||||
|
// if the lower end superarc direction is pointing down, then true; otherwise, false
|
||||||
|
if (isUpperLeaf)
|
||||||
|
return !contourtree_augmented::IsAscending(lowerDirection)
|
||||||
|
? lowerDependent
|
||||||
|
: totalVolume - lowerDependent + lowerIntrinsic;
|
||||||
|
|
||||||
|
// in case of fallout, should never reach
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const vtkm::Id totalVolume;
|
||||||
|
}; // GetBranchVolumeWorklet
|
||||||
|
|
||||||
|
} // namespace select_top_volume_contours
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace worklet
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
|
#endif
|
124
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/UpdateInfoByBranchDirectionWorklet.h
Normal file
124
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/UpdateInfoByBranchDirectionWorklet.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_scalar_topology_worklet_select_top_volume_contours_UpdateInfoByBranchDirectionWorklet_h
|
||||||
|
#define vtk_m_filter_scalar_topology_worklet_select_top_volume_contours_UpdateInfoByBranchDirectionWorklet_h
|
||||||
|
|
||||||
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace worklet
|
||||||
|
{
|
||||||
|
namespace scalar_topology
|
||||||
|
{
|
||||||
|
namespace select_top_volume_contours
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Get the saddle end isovalue
|
||||||
|
/// 2. Get Epsilon direction near the branch saddle end
|
||||||
|
/// If main branch, epsilon is 0.
|
||||||
|
/// Otherwise, -1 if the branch is the lower leaf branch, or 1 if upper leaf branch.
|
||||||
|
/// </summary>
|
||||||
|
template <typename ValueType>
|
||||||
|
class UpdateInfoByBranchDirectionWorklet : public vtkm::worklet::WorkletMapField
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ControlSignature = void(
|
||||||
|
FieldIn isLowerLeaf, // (input) bool, whether the lower end is a leaf
|
||||||
|
FieldIn isUpperLeaf, // (input) bool, whether the upper end is a leaf
|
||||||
|
FieldIn upperEndValue, // (input) value type, the branch upper end value
|
||||||
|
FieldIn lowerEndValue, // (input) value type, the branch lower end value
|
||||||
|
FieldOut saddleEpsilon, // (output) vtkm::Id, epsilon direction around the saddle isovalue
|
||||||
|
FieldOut saddleValue // (output) value type, the saddle isovalue
|
||||||
|
);
|
||||||
|
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6);
|
||||||
|
using InputDomain = _1;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
VTKM_EXEC_CONT
|
||||||
|
UpdateInfoByBranchDirectionWorklet()
|
||||||
|
{ // constructor
|
||||||
|
} // constructor
|
||||||
|
|
||||||
|
/// The functor returns the isovalue and the epsilon direction around the saddle end of the branch
|
||||||
|
VTKM_EXEC void operator()(const bool isLowerLeaf,
|
||||||
|
const bool isUpperLeaf,
|
||||||
|
const ValueType upperEndValue,
|
||||||
|
const ValueType lowerEndValue,
|
||||||
|
vtkm::Id& saddleEpsilon,
|
||||||
|
ValueType& saddleValue) const
|
||||||
|
{
|
||||||
|
// NOTE: for the main branch, the saddle value is undefined,
|
||||||
|
// because both upper and lower ends are leaf nodes.
|
||||||
|
// Let's use upperEndValue here to make the output not random.
|
||||||
|
if (isLowerLeaf && isUpperLeaf)
|
||||||
|
{
|
||||||
|
saddleEpsilon = 0;
|
||||||
|
saddleValue = upperEndValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saddleEpsilon = isLowerLeaf ? -1 : 1;
|
||||||
|
saddleValue = isLowerLeaf ? upperEndValue : lowerEndValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; // EpsilonFromBranchDirection
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace select_top_volume_contours
|
||||||
|
} // namespace scalar_topology
|
||||||
|
} // namespace worklet
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user