mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
Merge branch 'distributed-contours' into 'master'
Distributed Isosurface extraction from branch decomposition See merge request vtk/vtk-m!3226
This commit is contained in:
commit
2a199a1617
@ -669,6 +669,7 @@ int main(int argc, char* argv[])
|
||||
if (computeHierarchicalVolumetricBranchDecomposition)
|
||||
{
|
||||
vtkm::filter::scalar_topology::DistributedBranchDecompositionFilter bd_filter;
|
||||
bd_filter.SetTimingsLogLevel(timingsLogLevel);
|
||||
bd_result = bd_filter.Execute(result);
|
||||
}
|
||||
currTime = totalTime.GetElapsedTime();
|
||||
@ -681,8 +682,13 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
vtkm::filter::scalar_topology::SelectTopVolumeContoursFilter tp_filter;
|
||||
tp_filter.SetSavedBranches(numBranches);
|
||||
tp_filter.SetMarchingCubes(useMarchingCubes);
|
||||
tp_filter.SetTimingsLogLevel(timingsLogLevel);
|
||||
tp_result = tp_filter.Execute(bd_result);
|
||||
}
|
||||
currTime = totalTime.GetElapsedTime();
|
||||
vtkm::Float64 topVolBranchTime = currTime - prevTime;
|
||||
prevTime = currTime;
|
||||
|
||||
// Save output
|
||||
if (saveOutputData)
|
||||
@ -740,14 +746,19 @@ int main(int argc, char* argv[])
|
||||
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 topVolBranchUpperEnd = ds.GetField("TopVolumeBranchUpperEnd")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto topVolBranchLowerEnd = ds.GetField("TopVolumeBranchLowerEnd")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto topVolBranchVolume = ds.GetField("TopVolumeBranchVolume")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
@ -761,10 +772,11 @@ int main(int argc, char* argv[])
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<ValueType>>()
|
||||
.ReadPortal();
|
||||
|
||||
vtkm::Id nSelectedBranches = topVolBranchGRId.GetNumberOfValues();
|
||||
vtkm::Id nSelectedBranches = topVolBranchUpperEnd.GetNumberOfValues();
|
||||
for (vtkm::Id branch = 0; branch < nSelectedBranches; ++branch)
|
||||
{
|
||||
topVolumeBranchStream << std::setw(12) << topVolBranchGRId.Get(branch)
|
||||
topVolumeBranchStream << std::setw(12) << topVolBranchUpperEnd.Get(branch)
|
||||
<< std::setw(12) << topVolBranchLowerEnd.Get(branch)
|
||||
<< std::setw(14) << topVolBranchVolume.Get(branch)
|
||||
<< std::setw(5) << topVolBranchSaddleEpsilon.Get(branch)
|
||||
<< std::setw(14) << topVolBranchSaddleIsoValue.Get(branch)
|
||||
@ -785,6 +797,111 @@ int main(int argc, char* argv[])
|
||||
|
||||
isoValuesStream << std::endl;
|
||||
}
|
||||
|
||||
for (vtkm::Id ds_no = 0; ds_no < tp_result.GetNumberOfPartitions(); ++ds_no)
|
||||
{
|
||||
auto bd_ds = bd_result.GetPartition(ds_no);
|
||||
auto ds = tp_result.GetPartition(ds_no);
|
||||
|
||||
std::string branchDecompositionVolumeFileName =
|
||||
std::string("BranchDecompositionVolume_Rank_") +
|
||||
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
|
||||
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
|
||||
std::ofstream bdVolStream(branchDecompositionVolumeFileName.c_str());
|
||||
|
||||
auto upperEndGRId = bd_ds.GetField("UpperEndGlobalRegularIds")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto lowerEndGRId = bd_ds.GetField("LowerEndGlobalRegularIds")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto branchSaddleEpsilon = ds.GetField("BranchSaddleEpsilon")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto branchVolume = ds.GetField("BranchVolume")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
vtkm::Id nBranches = upperEndGRId.GetNumberOfValues();
|
||||
|
||||
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||
{
|
||||
bdVolStream << std::setw(12) << upperEndGRId.Get(branch) << std::setw(12)
|
||||
<< lowerEndGRId.Get(branch) << std::setw(3)
|
||||
<< branchSaddleEpsilon.Get(branch) << std::setw(18)
|
||||
<< branchVolume.Get(branch) << std::endl;
|
||||
}
|
||||
|
||||
std::string isosurfaceFileName = std::string("Isosurface_Rank_") +
|
||||
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
|
||||
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
|
||||
std::ofstream isosurfaceStream(isosurfaceFileName.c_str());
|
||||
|
||||
auto isosurfaceEdgesFrom = ds.GetField("IsosurfaceEdgesFrom")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Vec3f_64>>()
|
||||
.ReadPortal();
|
||||
auto isosurfaceEdgesTo = ds.GetField("IsosurfaceEdgesTo")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Vec3f_64>>()
|
||||
.ReadPortal();
|
||||
auto isosurfaceEdgesLabels = ds.GetField("IsosurfaceEdgesLabels")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto isosurfaceEdgesOrders = ds.GetField("IsosurfaceEdgesOrders")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto isosurfaceEdgesOffset = ds.GetField("IsosurfaceEdgesOffset")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>()
|
||||
.ReadPortal();
|
||||
auto isosurfaceIsoValue = ds.GetField("IsosurfaceIsoValue")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<ValueType>>()
|
||||
.ReadPortal();
|
||||
vtkm::Id nIsosurfaceEdges = isosurfaceEdgesFrom.GetNumberOfValues();
|
||||
vtkm::Id isoSurfaceCount = 0;
|
||||
|
||||
if (nDims == 2)
|
||||
for (vtkm::Id edge = 0; edge < nIsosurfaceEdges; ++edge)
|
||||
{
|
||||
while (isoSurfaceCount < isosurfaceEdgesLabels.GetNumberOfValues() &&
|
||||
edge == isosurfaceEdgesOffset.Get(isoSurfaceCount))
|
||||
{
|
||||
isosurfaceStream << "Isosurface Info:" << std::setw(5)
|
||||
<< isosurfaceEdgesLabels.Get(isoSurfaceCount) << std::setw(10)
|
||||
<< isosurfaceEdgesOrders.Get(isoSurfaceCount) << std::setw(10)
|
||||
<< isosurfaceIsoValue.Get(isoSurfaceCount) << std::endl;
|
||||
isoSurfaceCount++;
|
||||
}
|
||||
isosurfaceStream << std::setw(6) << isosurfaceEdgesFrom.Get(edge) << std::setw(6)
|
||||
<< isosurfaceEdgesTo.Get(edge) << std::endl;
|
||||
}
|
||||
else if (nDims == 3)
|
||||
{
|
||||
VTKM_ASSERT(nIsosurfaceEdges % 3 == 0);
|
||||
for (vtkm::Id edge = 0; edge < nIsosurfaceEdges; edge += 3)
|
||||
{
|
||||
while (isoSurfaceCount < isosurfaceEdgesLabels.GetNumberOfValues() &&
|
||||
edge == isosurfaceEdgesOffset.Get(isoSurfaceCount))
|
||||
{
|
||||
isosurfaceStream << "Isosurface Info:" << std::setw(5)
|
||||
<< isosurfaceEdgesLabels.Get(isoSurfaceCount) << std::setw(10)
|
||||
<< isosurfaceEdgesOrders.Get(isoSurfaceCount) << std::setw(10)
|
||||
<< isosurfaceIsoValue.Get(isoSurfaceCount) << std::endl;
|
||||
isoSurfaceCount++;
|
||||
}
|
||||
isosurfaceStream << std::setw(6) << isosurfaceEdgesFrom.Get(edge) << std::setw(6)
|
||||
<< isosurfaceEdgesTo.Get(edge) << std::setw(6)
|
||||
<< isosurfaceEdgesTo.Get(edge + 1) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -892,6 +1009,8 @@ int main(int argc, char* argv[])
|
||||
<< ": " << postFilterSyncTime << " seconds" << std::endl
|
||||
<< std::setw(42) << std::left << " Branch Decomposition"
|
||||
<< ": " << branchDecompTime << " seconds" << std::endl
|
||||
<< std::setw(42) << std::left << " Top Volume Branch Extraction"
|
||||
<< ": " << topVolBranchTime << " seconds" << std::endl
|
||||
<< std::setw(42) << std::left << " Save Tree Compiler Data"
|
||||
<< ": " << saveOutputDataTime << " seconds" << std::endl
|
||||
<< std::setw(42) << std::left << " Total Time"
|
||||
|
@ -21,6 +21,7 @@ set(scalar_topology_sources
|
||||
internal/ComputeBlockIndices.cxx
|
||||
internal/ComputeDistributedBranchDecompositionFunctor.cxx
|
||||
internal/SelectTopVolumeContoursFunctor.cxx
|
||||
internal/ParentBranchExtremaFunctor.cxx
|
||||
internal/ExchangeBranchEndsFunctor.cxx
|
||||
ContourTreeUniform.cxx
|
||||
ContourTreeUniformAugmented.cxx
|
||||
|
@ -1138,11 +1138,17 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute(
|
||||
// ******** 3. Augment the hierarchical tree if requested ********
|
||||
if (this->AugmentHierarchicalTree)
|
||||
{
|
||||
master.foreach (
|
||||
[](DistributedContourTreeBlockData* blockData, const vtkmdiy::Master::ProxyWithLink&) {
|
||||
blockData->HierarchicalAugmenter.Initialize(
|
||||
blockData->GlobalBlockId, &blockData->HierarchicalTree, &blockData->AugmentedTree);
|
||||
});
|
||||
master.foreach ([globalPointDimensions](DistributedContourTreeBlockData* blockData,
|
||||
const vtkmdiy::Master::ProxyWithLink&) {
|
||||
blockData->HierarchicalAugmenter.Initialize(
|
||||
blockData->GlobalBlockId,
|
||||
&blockData->HierarchicalTree,
|
||||
&blockData->AugmentedTree,
|
||||
blockData->BlockOrigin, // Origin of the data block
|
||||
blockData->BlockSize, // Extends of the data block
|
||||
globalPointDimensions // global point dimensions
|
||||
);
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left << "Initalize Hierarchical Trees"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
|
@ -80,6 +80,7 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Create DIY Master and Assigner (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
|
||||
timer.Start();
|
||||
|
||||
// Compute global ids (gids) for our local blocks
|
||||
@ -116,6 +117,7 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Get DIY Information (Branch Decomposition)"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
|
||||
timer.Start();
|
||||
|
||||
|
||||
@ -237,7 +239,8 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
||||
branch_decomposition_master,
|
||||
assigner,
|
||||
partners,
|
||||
vtkm::filter::scalar_topology::internal::ComputeDistributedBranchDecompositionFunctor{});
|
||||
vtkm::filter::scalar_topology::internal::ComputeDistributedBranchDecompositionFunctor(
|
||||
this->TimingsLogLevel));
|
||||
|
||||
timingsStream << " " << std::setw(60) << std::left
|
||||
<< "Exchanging best up/down supernode and volume"
|
||||
@ -314,12 +317,19 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
||||
b->VolumetricBranchDecomposer.CollectBranches(ds, b->BranchRoots);
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left << "CollectBranchEnds"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
// Now we have collected the branches, we do a global reduction to exchance branch end information
|
||||
// across all compute ranks
|
||||
vtkmdiy::reduce(branch_decomposition_master,
|
||||
assigner,
|
||||
partners,
|
||||
vtkm::filter::scalar_topology::internal::ExchangeBranchEndsFunctor{});
|
||||
auto exchangeBranchEndsFunctor =
|
||||
vtkm::filter::scalar_topology::internal::ExchangeBranchEndsFunctor(this->TimingsLogLevel);
|
||||
vtkmdiy::reduce(branch_decomposition_master, assigner, partners, exchangeBranchEndsFunctor);
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left << "ExchangeBranchEnds"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
timer.Start();
|
||||
|
||||
std::vector<vtkm::cont::DataSet> outputDataSets(input.GetNumberOfPartitions());
|
||||
// Copy input data set to output
|
||||
@ -347,6 +357,15 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
||||
b->VolumetricBranchDecomposer.LowerEndGRId);
|
||||
outputDataSets[b->LocalBlockNo].AddField(LowerEndGRIdField);
|
||||
|
||||
vtkm::cont::Field UpperEndLocalIdField("UpperEndLocalIds",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
b->VolumetricBranchDecomposer.UpperEndLocalId);
|
||||
outputDataSets[b->LocalBlockNo].AddField(UpperEndLocalIdField);
|
||||
vtkm::cont::Field LowerEndLocalIdField("LowerEndLocalIds",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
b->VolumetricBranchDecomposer.LowerEndLocalId);
|
||||
outputDataSets[b->LocalBlockNo].AddField(LowerEndLocalIdField);
|
||||
|
||||
vtkm::cont::Field UpperEndIntrinsicVolume(
|
||||
"UpperEndIntrinsicVolume",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
@ -383,7 +402,7 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
b->VolumetricBranchDecomposer.UpperEndValue);
|
||||
outputDataSets[b->LocalBlockNo].AddField(UpperEndValue);
|
||||
vtkm::cont::Field BranchRoot("BranchRoot",
|
||||
vtkm::cont::Field BranchRoot("BranchRootByBranch",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
b->VolumetricBranchDecomposer.BranchRoot);
|
||||
outputDataSets[b->LocalBlockNo].AddField(BranchRoot);
|
||||
@ -391,13 +410,74 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
b->VolumetricBranchDecomposer.BranchRootGRId);
|
||||
outputDataSets[b->LocalBlockNo].AddField(BranchRootGRId);
|
||||
|
||||
|
||||
/* To select top volume branches,
|
||||
we need to carry over the input fields below to the output*/
|
||||
using vtkm::worklet::contourtree_augmented::IdArrayType;
|
||||
const vtkm::cont::DataSet& ds = input.GetPartition(b->LocalBlockNo);
|
||||
// RegularNodeGlobalIds
|
||||
vtkm::cont::Field RegularNodeGlobalIds("RegularNodeGlobalIds",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("RegularNodeGlobalIds").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(RegularNodeGlobalIds);
|
||||
// DataValues
|
||||
vtkm::cont::Field DataValues("DataValues",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("DataValues").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(DataValues);
|
||||
// Superparents
|
||||
vtkm::cont::Field Superparents("Superparents",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("Superparents").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(Superparents);
|
||||
// Supernodes
|
||||
vtkm::cont::Field Supernodes("Supernodes",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("Supernodes").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(Supernodes);
|
||||
// Superarcs
|
||||
vtkm::cont::Field Superarcs("Superarcs",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("Superarcs").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(Superarcs);
|
||||
// Superchildren
|
||||
vtkm::cont::Field Superchildren("Superchildren",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("Superchildren").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(Superchildren);
|
||||
// WhichRound
|
||||
vtkm::cont::Field WhichRound("WhichRound",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("WhichRound").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(WhichRound);
|
||||
// WhichIteration
|
||||
vtkm::cont::Field WhichIteration("WhichIteration",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("WhichIteration").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(WhichIteration);
|
||||
// Hyperparents
|
||||
vtkm::cont::Field Hyperparents("Hyperparents",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("Hyperparents").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(Hyperparents);
|
||||
// Hypernodes
|
||||
vtkm::cont::Field Hypernodes("Hypernodes",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("Hypernodes").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(Hypernodes);
|
||||
// Hyperarcs
|
||||
vtkm::cont::Field Hyperarcs("Hyperarcs",
|
||||
vtkm::cont::Field::Association::WholeDataSet,
|
||||
ds.GetField("Hyperarcs").GetData());
|
||||
outputDataSets[b->LocalBlockNo].AddField(Hyperarcs);
|
||||
});
|
||||
|
||||
timingsStream << " " << std::setw(38) << std::left
|
||||
<< "Creating Branch Decomposition Output Data"
|
||||
<< ": " << timer.GetElapsedTime() << " seconds" << std::endl;
|
||||
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Perf,
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< "----------- DoExecutePartitions Timings ------------" << std::endl
|
||||
<< timingsStream.str());
|
||||
|
@ -63,11 +63,18 @@ public:
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>&,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>&,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id3>&);
|
||||
VTKM_CONT void SetTimingsLogLevel(vtkm::cont::LogLevel timingsLogLevel)
|
||||
{
|
||||
this->TimingsLogLevel = timingsLogLevel;
|
||||
}
|
||||
|
||||
private:
|
||||
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&) override;
|
||||
VTKM_CONT vtkm::cont::PartitionedDataSet DoExecutePartitions(
|
||||
const vtkm::cont::PartitionedDataSet& inData) override;
|
||||
|
||||
/// Log level to be used for outputting timing information. Default is vtkm::cont::LogLevel::Perf
|
||||
vtkm::cont::LogLevel TimingsLogLevel = vtkm::cont::LogLevel::Perf;
|
||||
};
|
||||
|
||||
} // namespace scalar_topology
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -44,7 +44,6 @@
|
||||
|
||||
#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
|
||||
{
|
||||
@ -52,28 +51,47 @@ namespace filter
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
/// \brief Compute branch decompostion from distributed contour tree
|
||||
|
||||
/// \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 SetTimingsLogLevel(vtkm::cont::LogLevel timingsLogLevel)
|
||||
{
|
||||
this->TimingsLogLevel = timingsLogLevel;
|
||||
}
|
||||
|
||||
VTKM_CONT void SetSavedBranches(const vtkm::Id& numBranches)
|
||||
{
|
||||
this->nSavedBranches = numBranches;
|
||||
}
|
||||
|
||||
VTKM_CONT void SetMarchingCubes(const bool& marchingCubes)
|
||||
{
|
||||
this->isMarchingCubes = marchingCubes;
|
||||
}
|
||||
|
||||
private:
|
||||
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&) override;
|
||||
VTKM_CONT vtkm::cont::PartitionedDataSet DoExecutePartitions(
|
||||
const vtkm::cont::PartitionedDataSet& inData) override;
|
||||
|
||||
bool isMarchingCubes = false;
|
||||
vtkm::Id nSavedBranches;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType BranchVolume;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType BranchSaddleEpsilon;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType SortedBranchByVolume;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> BranchVolume;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> BranchSaddleEpsilon;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> SortedBranchByVolume;
|
||||
vtkm::cont::UnknownArrayHandle BranchSaddleIsoValue;
|
||||
|
||||
// the parent branch for top volume branches
|
||||
// we only care about the parent branch for top volume branches at the moment
|
||||
// as a result, the index stored in this array follows the descending order of branch volumes
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> TopVolBranchParent;
|
||||
|
||||
/// Log level to be used for outputting timing information. Default is vtkm::cont::LogLevel::Perf
|
||||
vtkm::cont::LogLevel TimingsLogLevel = vtkm::cont::LogLevel::Perf;
|
||||
};
|
||||
|
||||
} // namespace scalar_topology
|
||||
|
@ -13,6 +13,7 @@ set(headers
|
||||
SelectTopVolumeContoursBlock.h
|
||||
ComputeBlockIndices.h
|
||||
ComputeDistributedBranchDecompositionFunctor.h
|
||||
ParentBranchExtremaFunctor.h
|
||||
SelectTopVolumeContoursFunctor.h
|
||||
ExchangeBranchEndsFunctor.h
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ void ComputeDistributedBranchDecompositionFunctor::operator()(
|
||||
) const
|
||||
{
|
||||
// Get our rank and DIY id
|
||||
//const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank();
|
||||
const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank();
|
||||
const auto selfid = rp.gid();
|
||||
|
||||
// Aliases to reduce verbosity
|
||||
@ -110,6 +110,20 @@ void ComputeDistributedBranchDecompositionFunctor::operator()(
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> incomingBestDownSupernode;
|
||||
rp.dequeue(ingid, incomingBestDownSupernode);
|
||||
|
||||
std::stringstream dataSizeStream;
|
||||
// Log the amount of exchanged data
|
||||
dataSizeStream << " " << std::setw(38) << std::left << "Incoming data size"
|
||||
<< ": " << incomingBestUpSupernode.GetNumberOfValues() << std::endl;
|
||||
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< " ---------------- Compute Branch Decomposition Step ---------------------"
|
||||
<< std::endl
|
||||
<< " Rank : " << rank << std::endl
|
||||
<< " DIY Id : " << selfid << std::endl
|
||||
<< " Inc Id : " << ingid << std::endl
|
||||
<< dataSizeStream.str());
|
||||
|
||||
vtkm::Id prefixLength = b->FirstSupernodePerIteration.ReadPortal().Get(rp.round() - 1)[0];
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
|
@ -73,10 +73,17 @@ namespace internal
|
||||
|
||||
struct ComputeDistributedBranchDecompositionFunctor
|
||||
{
|
||||
ComputeDistributedBranchDecompositionFunctor(const vtkm::cont::LogLevel& timingsLogLevel)
|
||||
: TimingsLogLevel(timingsLogLevel)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(BranchDecompositionBlock* b,
|
||||
const vtkmdiy::ReduceProxy& rp, // communication proxy
|
||||
const vtkmdiy::RegularSwapPartners& // partners of the current block (unused)
|
||||
) const;
|
||||
|
||||
const vtkm::cont::LogLevel TimingsLogLevel;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/hierarchical_volumetric_branch_decomposer/BranchEndGlobalUpdateWorklet.h>
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#define DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
@ -75,6 +76,7 @@ void ExchangeBranchEndsFunctor::operator()(
|
||||
) const
|
||||
{
|
||||
// Get our rank and DIY id
|
||||
const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank();
|
||||
const auto selfid = rp.gid();
|
||||
|
||||
// Aliases to reduce verbosity
|
||||
@ -93,6 +95,7 @@ void ExchangeBranchEndsFunctor::operator()(
|
||||
// Otherwise, we may need to process more than one incoming block
|
||||
if (ingid != selfid)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
int incomingGlobalBlockId;
|
||||
rp.dequeue(ingid, incomingGlobalBlockId);
|
||||
@ -126,6 +129,20 @@ void ExchangeBranchEndsFunctor::operator()(
|
||||
IdArrayType incomingLowerEndDependentVolume;
|
||||
rp.dequeue(ingid, incomingLowerEndDependentVolume);
|
||||
|
||||
std::stringstream dataSizeStream;
|
||||
// Log the amount of exchanged data
|
||||
dataSizeStream << " " << std::setw(38) << std::left << "Incoming branch size"
|
||||
<< ": " << incomingBranchRootGRId.GetNumberOfValues() << std::endl;
|
||||
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< " ---------------- Exchange Branch Ends Step ---------------------"
|
||||
<< std::endl
|
||||
<< " Rank : " << rank << std::endl
|
||||
<< " DIY Id : " << selfid << std::endl
|
||||
<< " Inc Id : " << ingid << std::endl
|
||||
<< dataSizeStream.str());
|
||||
|
||||
/// Superarc and Branch IDs are given based on the hierarchical level
|
||||
/// Shared branches should lie on the smaller ID side of the branch array consecutively
|
||||
/// We filter out shared branches first
|
||||
@ -307,7 +324,8 @@ void ExchangeBranchEndsFunctor::operator()(
|
||||
{
|
||||
#ifdef DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
rp.enqueue(target, b->GlobalBlockId);
|
||||
#endif
|
||||
#endif // DEBUG_PRINT_COMBINED_BLOCK_IDS
|
||||
|
||||
rp.enqueue(target, branchDecomposer.BranchRootGRId);
|
||||
rp.enqueue(target, branchDecomposer.UpperEndGRId);
|
||||
rp.enqueue(target, branchDecomposer.LowerEndGRId);
|
||||
|
@ -73,11 +73,19 @@ namespace internal
|
||||
|
||||
struct ExchangeBranchEndsFunctor
|
||||
{
|
||||
ExchangeBranchEndsFunctor(vtkm::cont::LogLevel timingsLogLevel = vtkm::cont::LogLevel::Perf)
|
||||
: TimingsLogLevel(timingsLogLevel)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT void operator()(
|
||||
BranchDecompositionBlock* b,
|
||||
const vtkmdiy::ReduceProxy& rp, // communication proxy
|
||||
const vtkmdiy::RegularSwapPartners& // partners of the current block (unused)
|
||||
) const;
|
||||
|
||||
private:
|
||||
vtkm::cont::LogLevel TimingsLogLevel;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -0,0 +1,355 @@
|
||||
//============================================================================
|
||||
// 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/EnvironmentTracker.h>
|
||||
#include <vtkm/filter/scalar_topology/internal/ParentBranchExtremaFunctor.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/ArrayTransforms.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/select_top_volume_contours/GetBranchHierarchyWorklet.h>
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#define DEBUG_PRINT_UPDATE_PARENT_BRANCH_ISOVALUE
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
|
||||
#endif
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
|
||||
void ParentBranchIsoValueFunctor::operator()(SelectTopVolumeContoursBlock* b,
|
||||
const vtkmdiy::ReduceProxy& rp // communication proxy
|
||||
) const
|
||||
{
|
||||
// Get our rank and
|
||||
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_UPDATE_PARENT_BRANCH_ISOVALUE
|
||||
rp.enqueue(target, b->GlobalBlockId);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Block " << b->GlobalBlockId << " enqueue to Block " << target.gid);
|
||||
#endif
|
||||
auto extraMaximaBranchOrderPortal = b->ExtraMaximaBranchOrder.ReadPortal();
|
||||
vtkm::Id nExtraMaxBranches = extraMaximaBranchOrderPortal.GetNumberOfValues();
|
||||
rp.enqueue(target, nExtraMaxBranches);
|
||||
|
||||
auto resolveMaxArray = [&](const auto& inArray) {
|
||||
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||
using ValueType = typename InArrayHandleType::ValueType;
|
||||
// the global order of the branch can be the identity (unique for each branch)
|
||||
|
||||
auto extraMaxBranchIsoValuePortal = inArray.ReadPortal();
|
||||
for (vtkm::Id branch = 0; branch < nExtraMaxBranches; ++branch)
|
||||
rp.enqueue(target, extraMaximaBranchOrderPortal.Get(branch));
|
||||
for (vtkm::Id branch = 0; branch < nExtraMaxBranches; ++branch)
|
||||
rp.enqueue<ValueType>(target, extraMaxBranchIsoValuePortal.Get(branch));
|
||||
};
|
||||
if (b->ExtraMaximaBranchIsoValue.GetNumberOfValues())
|
||||
b->ExtraMaximaBranchIsoValue
|
||||
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(
|
||||
resolveMaxArray);
|
||||
// rp.enqueue(target, b->ExtraMaximaBranchOrder);
|
||||
// rp.enqueue(target, b->ExtraMaximaBranchIsoValue);
|
||||
|
||||
auto extraMinimaBranchOrderPortal = b->ExtraMinimaBranchOrder.ReadPortal();
|
||||
vtkm::Id nExtraMinBranches = extraMinimaBranchOrderPortal.GetNumberOfValues();
|
||||
rp.enqueue(target, nExtraMinBranches);
|
||||
|
||||
auto resolveMinArray = [&](const auto& inArray) {
|
||||
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||
using ValueType = typename InArrayHandleType::ValueType;
|
||||
|
||||
// the global order of the branch can be the identity (unique for each branch)
|
||||
auto extraMinBranchIsoValuePortal = inArray.ReadPortal();
|
||||
for (vtkm::Id branch = 0; branch < nExtraMinBranches; ++branch)
|
||||
rp.enqueue(target, extraMinimaBranchOrderPortal.Get(branch));
|
||||
for (vtkm::Id branch = 0; branch < nExtraMinBranches; ++branch)
|
||||
rp.enqueue<ValueType>(target, extraMinBranchIsoValuePortal.Get(branch));
|
||||
};
|
||||
if (b->ExtraMinimaBranchIsoValue.GetNumberOfValues())
|
||||
b->ExtraMinimaBranchIsoValue
|
||||
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(
|
||||
resolveMinArray);
|
||||
// rp.enqueue(target, b->ExtraMinimaBranchOrder);
|
||||
// rp.enqueue(target, b->ExtraMinimaBranchIsoValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
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_UPDATE_PARENT_BRANCH_ISOVALUE
|
||||
int incomingGlobalBlockId;
|
||||
rp.dequeue(ingid, incomingGlobalBlockId);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Combining local block " << b->GlobalBlockId << " with incoming block "
|
||||
<< incomingGlobalBlockId);
|
||||
#endif
|
||||
vtkm::Id nSelfMaxBranch = b->ExtraMaximaBranchOrder.GetNumberOfValues();
|
||||
vtkm::Id nSelfMinBranch = b->ExtraMinimaBranchOrder.GetNumberOfValues();
|
||||
|
||||
// dequeue the data from other blocks.
|
||||
// nExtraMaximaBranches (incoming)
|
||||
// array of incoming maxima branch order
|
||||
// array of incoming maxima branch isovalue
|
||||
// nExtraMinimaBranches (incoming)
|
||||
// array of incoming minima branch order
|
||||
// array of incoming minima branch isovalue
|
||||
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||
vtkm::Id nIncomingMaxBranch;
|
||||
rp.dequeue(ingid, nIncomingMaxBranch);
|
||||
|
||||
auto resolveMaxArray = [&](auto& inArray) {
|
||||
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||
using ValueType = typename InArrayHandleType::ValueType;
|
||||
|
||||
IdArrayType incomingMaxBranchOrder;
|
||||
incomingMaxBranchOrder.Allocate(nIncomingMaxBranch);
|
||||
auto incomingMaxBranchOrderPortal = incomingMaxBranchOrder.WritePortal();
|
||||
for (vtkm::Id branch = 0; branch < nIncomingMaxBranch; ++branch)
|
||||
{
|
||||
vtkm::Id incomingTmpBranchOrder;
|
||||
rp.dequeue(ingid, incomingTmpBranchOrder);
|
||||
incomingMaxBranchOrderPortal.Set(branch, incomingTmpBranchOrder);
|
||||
}
|
||||
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||
// rp.dequeue(ingid, incomingMaxBranchOrder);
|
||||
|
||||
InArrayHandleType incomingMaxBranchIsoValue;
|
||||
incomingMaxBranchIsoValue.Allocate(nIncomingMaxBranch);
|
||||
auto incomingMaxBranchIsoValuePortal = incomingMaxBranchIsoValue.WritePortal();
|
||||
for (vtkm::Id branch = 0; branch < nIncomingMaxBranch; ++branch)
|
||||
{
|
||||
ValueType incomingBranchValue;
|
||||
rp.dequeue<ValueType>(ingid, incomingBranchValue);
|
||||
incomingMaxBranchIsoValuePortal.Set(branch, incomingBranchValue);
|
||||
}
|
||||
|
||||
// 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, incomingMaxBranchIsoValue);
|
||||
|
||||
#ifdef DEBUG_PRINT_UPDATE_PARENT_BRANCH_ISOVALUE
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(nIncomingMaxBranch, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingMaxBranchOrder", incomingMaxBranchOrder, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"incomingMaxBranchVal", incomingMaxBranchIsoValue, -1, rs);
|
||||
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(nSelfMaxBranch, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"selfMaxBranchOrder", b->ExtraMaximaBranchOrder, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"selfMaxBranchVal", inArray, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
vtkm::cont::Algorithm::SortByKey(incomingMaxBranchOrder, incomingMaxBranchIsoValue);
|
||||
vtkm::worklet::scalar_topology::select_top_volume_contours::UpdateOuterSaddle<true>
|
||||
updateValueOnMaxBranch;
|
||||
invoke(updateValueOnMaxBranch,
|
||||
b->ExtraMaximaBranchOrder,
|
||||
inArray,
|
||||
incomingMaxBranchOrder,
|
||||
incomingMaxBranchIsoValue);
|
||||
|
||||
#ifdef DEBUG_PRINT_UPDATE_PARENT_BRANCH_ISOVALUE
|
||||
{
|
||||
std::stringstream rs;
|
||||
rs << "After update, block " << b->LocalBlockNo << std::endl;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(nSelfMaxBranch, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"selfMaxBranchOrder", b->ExtraMaximaBranchOrder, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"selfMaxBranchVal", inArray, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
if (nSelfMaxBranch > 0 && nIncomingMaxBranch > 0)
|
||||
b->ExtraMaximaBranchIsoValue
|
||||
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(
|
||||
resolveMaxArray);
|
||||
|
||||
/* Apply the same pipeline for branches with minima to extract */
|
||||
vtkm::Id nIncomingMinBranch;
|
||||
rp.dequeue(ingid, nIncomingMinBranch);
|
||||
|
||||
auto resolveMinArray = [&](auto& inArray) {
|
||||
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||
using ValueType = typename InArrayHandleType::ValueType;
|
||||
|
||||
IdArrayType incomingMinBranchOrder;
|
||||
incomingMinBranchOrder.Allocate(nIncomingMinBranch);
|
||||
auto incomingMinBranchOrderPortal = incomingMinBranchOrder.WritePortal();
|
||||
for (vtkm::Id branch = 0; branch < nIncomingMinBranch; ++branch)
|
||||
{
|
||||
vtkm::Id incomingTmpBranchOrder;
|
||||
rp.dequeue(ingid, incomingTmpBranchOrder);
|
||||
incomingMinBranchOrderPortal.Set(branch, incomingTmpBranchOrder);
|
||||
}
|
||||
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||
// rp.dequeue(ingid, incomingMinBranchOrder);
|
||||
|
||||
InArrayHandleType incomingMinBranchIsoValue;
|
||||
incomingMinBranchIsoValue.Allocate(nIncomingMinBranch);
|
||||
auto incomingMinBranchIsoValuePortal = incomingMinBranchIsoValue.WritePortal();
|
||||
for (vtkm::Id branch = 0; branch < nIncomingMinBranch; ++branch)
|
||||
{
|
||||
ValueType incomingBranchValue;
|
||||
rp.dequeue<ValueType>(ingid, incomingBranchValue);
|
||||
incomingMinBranchIsoValuePortal.Set(branch, incomingBranchValue);
|
||||
}
|
||||
|
||||
// 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, incomingMinBranchIsoValue);
|
||||
|
||||
#ifdef DEBUG_PRINT_UPDATE_PARENT_BRANCH_ISOVALUE
|
||||
{
|
||||
std::stringstream rs;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(nIncomingMinBranch, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingMinBranchOrder", incomingMinBranchOrder, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"incomingMinBranchVal", incomingMinBranchIsoValue, -1, rs);
|
||||
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(nSelfMinBranch, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"selfMinBranchOrder", b->ExtraMinimaBranchOrder, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"selfMinBranchVal", inArray, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
vtkm::cont::Algorithm::SortByKey(incomingMinBranchOrder, incomingMinBranchIsoValue);
|
||||
vtkm::worklet::scalar_topology::select_top_volume_contours::UpdateOuterSaddle<false>
|
||||
updateValueOnMinBranch;
|
||||
invoke(updateValueOnMinBranch,
|
||||
b->ExtraMinimaBranchOrder,
|
||||
inArray,
|
||||
incomingMinBranchOrder,
|
||||
incomingMinBranchIsoValue);
|
||||
|
||||
#ifdef DEBUG_PRINT_UPDATE_PARENT_BRANCH_ISOVALUE
|
||||
{
|
||||
std::stringstream rs;
|
||||
rs << "After update, block " << b->LocalBlockNo << std::endl;
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(nSelfMinBranch, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"selfMinBranchOrder", b->ExtraMinimaBranchOrder, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"selfMinBranchVal", inArray, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
if (nSelfMinBranch > 0 && nIncomingMinBranch > 0)
|
||||
b->ExtraMinimaBranchIsoValue
|
||||
.CastAndCallForTypes<vtkm::TypeListScalarAll, vtkm::cont::StorageListBasic>(
|
||||
resolveMinArray);
|
||||
|
||||
// The logging is commented because the size of exchange is limited by K,
|
||||
// the number of top-volume branches, which is usually small
|
||||
std::stringstream dataSizeStream;
|
||||
// Log the amount of exchanged data
|
||||
dataSizeStream << " " << std::setw(38) << std::left << "Incoming branch size"
|
||||
<< ": " << nIncomingMaxBranch + nIncomingMinBranch << std::endl;
|
||||
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< " ---------------- Exchange Parent Branch Step ---------------------"
|
||||
<< std::endl
|
||||
<< " Rank : " << rank << std::endl
|
||||
<< " DIY Id : " << selfid << std::endl
|
||||
<< " Inc Id : " << ingid << std::endl
|
||||
<< dataSizeStream.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // 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_ParentBranchExtremaFunctor_h
|
||||
#define vtk_m_filter_scalar_topology_internal_ParentBranchExtremaFunctor_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 ParentBranchIsoValueFunctor
|
||||
{
|
||||
ParentBranchIsoValueFunctor(const vtkm::cont::LogLevel& timingsLogLevel)
|
||||
: TimingsLogLevel(timingsLogLevel)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(SelectTopVolumeContoursBlock* b,
|
||||
const vtkmdiy::ReduceProxy& rp // communication proxy
|
||||
) const;
|
||||
|
||||
const vtkm::cont::LogLevel TimingsLogLevel;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace scalar_topology
|
||||
} // namespace filter
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -69,6 +69,12 @@ namespace scalar_topology
|
||||
namespace internal
|
||||
{
|
||||
|
||||
struct IsNegativeDebug
|
||||
{
|
||||
VTKM_EXEC_CONT IsNegativeDebug() {}
|
||||
VTKM_EXEC_CONT bool operator()(vtkm::Id x) const { return x < 0; }
|
||||
};
|
||||
|
||||
SelectTopVolumeContoursBlock::SelectTopVolumeContoursBlock(vtkm::Id localBlockNo, int globalBlockId)
|
||||
: LocalBlockNo(localBlockNo)
|
||||
, GlobalBlockId(globalBlockId)
|
||||
@ -103,13 +109,14 @@ void SelectTopVolumeContoursBlock::SortBranchByVolume(
|
||||
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")
|
||||
auto branchRoot = hierarchicalTreeDataSet.GetField("BranchRootByBranch")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
|
||||
|
@ -76,16 +76,58 @@ struct SelectTopVolumeContoursBlock
|
||||
vtkm::Id LocalBlockNo;
|
||||
int GlobalBlockId; // TODO/FIXME: Check whether really needed. Possibly only during debugging
|
||||
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType BranchRootByBranch;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType BranchRootGRId;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType BranchVolume;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType BranchSaddleEpsilon;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType SortedBranchByVolume;
|
||||
vtkm::cont::ArrayHandle<bool> IsParentBranch;
|
||||
vtkm::cont::UnknownArrayHandle BranchSaddleIsoValue;
|
||||
|
||||
// Output Datasets.
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchRoot;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchRootGRId;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchVolume;
|
||||
// the parent branch of top volume branches (if no parent branch, then NO_SUCH_ELEMENT)
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchParent;
|
||||
vtkm::cont::UnknownArrayHandle TopVolumeBranchSaddleIsoValue;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchSaddleEpsilon;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchUpperEndGRId;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolumeBranchLowerEndGRId;
|
||||
|
||||
// Other top-volume branch information
|
||||
|
||||
// whether the top volume branch is known by the block
|
||||
// size: nTopVolBranches
|
||||
// value range: [0, 1]
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolBranchKnownByBlockStencil;
|
||||
// the branch order (among all branches) by branch root global regular ids
|
||||
// size: nTopVolBranches
|
||||
// value range: {NO_SUCH_ELEMENT} U [0, nBranches - 1]
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolBranchGROrder;
|
||||
// the branch information index (known by the block) of the top volume branch
|
||||
// size: nTopVolBranchKnownByBlock
|
||||
// value range: [0, nBranches - 1]
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TopVolBranchInfoActualIndex;
|
||||
|
||||
// information to extract extra isosurface for extrema
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMaximaBranchUpperEnd;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMaximaBranchLowerEnd;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMaximaBranchOrder;
|
||||
vtkm::cont::UnknownArrayHandle ExtraMaximaBranchIsoValue;
|
||||
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMinimaBranchUpperEnd;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMinimaBranchLowerEnd;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType ExtraMinimaBranchOrder;
|
||||
vtkm::cont::UnknownArrayHandle ExtraMinimaBranchIsoValue;
|
||||
|
||||
// Isosurface output
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f_64> IsosurfaceEdgesFrom;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f_64> IsosurfaceEdgesTo;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType IsosurfaceEdgesOffset;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType IsosurfaceEdgesLabels;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType IsosurfaceEdgesOrders;
|
||||
vtkm::cont::UnknownArrayHandle IsosurfaceIsoValue;
|
||||
|
||||
// Destroy function allowing DIY to own blocks and clean them up after use
|
||||
static void Destroy(void* b) { delete static_cast<SelectTopVolumeContoursBlock*>(b); }
|
||||
|
@ -49,7 +49,7 @@
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#include <vtkm/cont/EnvironmentTracker.h>
|
||||
#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>
|
||||
@ -57,6 +57,8 @@
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
#define DEBUG_PRINT_COMBINED_HIGH_VOLUME_BRANCH
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
|
||||
@ -79,7 +81,7 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
if (this->nSavedBranches < 1)
|
||||
return;
|
||||
// Get our rank and DIY id
|
||||
//const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank();
|
||||
const vtkm::Id rank = vtkm::cont::EnvironmentTracker::GetCommunicator().rank();
|
||||
const auto selfid = rp.gid();
|
||||
|
||||
// Aliases to reduce verbosity
|
||||
@ -102,6 +104,8 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
auto topVolBranchRootGRIdPortal = b->TopVolumeBranchRootGRId.ReadPortal();
|
||||
auto topVolBranchVolumePortal = b->TopVolumeBranchVolume.ReadPortal();
|
||||
auto topVolBranchSaddleEpsilonPortal = b->TopVolumeBranchSaddleEpsilon.ReadPortal();
|
||||
auto topVolBranchUpperEndPortal = b->TopVolumeBranchUpperEndGRId.ReadPortal();
|
||||
auto topVolBranchLowerEndPortal = b->TopVolumeBranchLowerEndGRId.ReadPortal();
|
||||
|
||||
vtkm::Id nBranches = topVolBranchRootGRIdPortal.GetNumberOfValues();
|
||||
|
||||
@ -112,6 +116,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
rp.enqueue(target, topVolBranchVolumePortal.Get(branch));
|
||||
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||
rp.enqueue(target, topVolBranchSaddleEpsilonPortal.Get(branch));
|
||||
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||
rp.enqueue(target, topVolBranchUpperEndPortal.Get(branch));
|
||||
for (vtkm::Id branch = 0; branch < nBranches; ++branch)
|
||||
rp.enqueue(target, topVolBranchLowerEndPortal.Get(branch));
|
||||
|
||||
auto resolveArray = [&](const auto& inArray) {
|
||||
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||
@ -199,6 +207,34 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||
// rp.dequeue(ingid, incomingTopVolBranchSaddleEpsilon);
|
||||
|
||||
IdArrayType incomingTopVolBranchUpperEnd;
|
||||
incomingTopVolBranchUpperEnd.Allocate(nIncoming);
|
||||
auto incomingTopVolBranchUpperEndPortal = incomingTopVolBranchUpperEnd.WritePortal();
|
||||
for (vtkm::Id branch = 0; branch < nIncoming; ++branch)
|
||||
{
|
||||
vtkm::Id incomingTmpBranchUpperEnd;
|
||||
rp.dequeue(ingid, incomingTmpBranchUpperEnd);
|
||||
incomingTopVolBranchUpperEndPortal.Set(branch, incomingTmpBranchUpperEnd);
|
||||
}
|
||||
|
||||
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||
// rp.dequeue(ingid, incomingTopVolBranchUpperEnd);
|
||||
|
||||
IdArrayType incomingTopVolBranchLowerEnd;
|
||||
incomingTopVolBranchLowerEnd.Allocate(nIncoming);
|
||||
auto incomingTopVolBranchLowerEndPortal = incomingTopVolBranchLowerEnd.WritePortal();
|
||||
for (vtkm::Id branch = 0; branch < nIncoming; ++branch)
|
||||
{
|
||||
vtkm::Id incomingTmpBranchLowerEnd;
|
||||
rp.dequeue(ingid, incomingTmpBranchLowerEnd);
|
||||
incomingTopVolBranchLowerEndPortal.Set(branch, incomingTmpBranchLowerEnd);
|
||||
}
|
||||
|
||||
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||
// rp.dequeue(ingid, incomingTopVolBranchLowerEnd);
|
||||
|
||||
auto resolveArray = [&](auto& inArray) {
|
||||
using InArrayHandleType = std::decay_t<decltype(inArray)>;
|
||||
using ValueType = typename InArrayHandleType::ValueType;
|
||||
@ -213,6 +249,20 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
incomingTopVolBranchSaddleIsoValuePortal.Set(branch, incomingSaddleValue);
|
||||
}
|
||||
|
||||
std::stringstream dataSizeStream;
|
||||
// Log the amount of exchanged data
|
||||
dataSizeStream << " " << std::setw(38) << std::left << "Incoming top volume branch size"
|
||||
<< ": " << nIncoming << std::endl;
|
||||
|
||||
VTKM_LOG_S(this->TimingsLogLevel,
|
||||
std::endl
|
||||
<< " ---------------- Select Top Volume Branches Step ---------------------"
|
||||
<< std::endl
|
||||
<< " Rank : " << rank << std::endl
|
||||
<< " DIY Id : " << selfid << std::endl
|
||||
<< " Inc Id : " << ingid << std::endl
|
||||
<< dataSizeStream.str());
|
||||
|
||||
// TODO/FIXME: This is a workaround for a bug in DIY/vtk-m.
|
||||
// Replace with dequeuing ArrayHandles once bug is fixed.
|
||||
// rp.dequeue<InArrayHandleType>(ingid, incomingTopVolBranchSaddleIsoValue);
|
||||
@ -231,6 +281,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
"incomingTopBranchVol", incomingTopVolBranchVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"incomingSaddleVal", incomingTopVolBranchSaddleIsoValue, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingUpperEnd", incomingTopVolBranchUpperEnd, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"incomingLowerEnd", incomingTopVolBranchLowerEnd, -1, rs);
|
||||
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(nSelf, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
@ -239,6 +293,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
"selfTopBranchVol", b->TopVolumeBranchVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"selfTopSaddleVal", inArray, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"selfTopBranchUpperEnd", b->TopVolumeBranchUpperEndGRId, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"selfTopBranchLowerEnd", b->TopVolumeBranchLowerEndGRId, -1, rs);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, rs.str());
|
||||
}
|
||||
#endif
|
||||
@ -246,10 +304,14 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
IdArrayType mergedTopVolBranchGRId;
|
||||
IdArrayType mergedTopVolBranchVolume;
|
||||
IdArrayType mergedTopVolBranchSaddleEpsilon;
|
||||
IdArrayType mergedTopVolBranchUpperEnd;
|
||||
IdArrayType mergedTopVolBranchLowerEnd;
|
||||
InArrayHandleType mergedTopVolBranchSaddleIsoValue;
|
||||
mergedTopVolBranchGRId.Allocate(nIncoming + nSelf);
|
||||
mergedTopVolBranchVolume.Allocate(nIncoming + nSelf);
|
||||
mergedTopVolBranchSaddleEpsilon.Allocate(nIncoming + nSelf);
|
||||
mergedTopVolBranchUpperEnd.Allocate(nIncoming + nSelf);
|
||||
mergedTopVolBranchLowerEnd.Allocate(nIncoming + nSelf);
|
||||
mergedTopVolBranchSaddleIsoValue.Allocate(nIncoming + nSelf);
|
||||
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
@ -258,6 +320,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
incomingTopVolBranchVolume, 0, nIncoming, mergedTopVolBranchVolume, 0);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
incomingTopVolBranchSaddleEpsilon, 0, nIncoming, mergedTopVolBranchSaddleEpsilon, 0);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
incomingTopVolBranchUpperEnd, 0, nIncoming, mergedTopVolBranchUpperEnd, 0);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
incomingTopVolBranchLowerEnd, 0, nIncoming, mergedTopVolBranchLowerEnd, 0);
|
||||
vtkm::cont::Algorithm::CopySubRange<ValueType, ValueType>(
|
||||
incomingTopVolBranchSaddleIsoValue, 0, nIncoming, mergedTopVolBranchSaddleIsoValue, 0);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
@ -266,6 +332,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
b->TopVolumeBranchVolume, 0, nSelf, mergedTopVolBranchVolume, nIncoming);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
b->TopVolumeBranchSaddleEpsilon, 0, nSelf, mergedTopVolBranchSaddleEpsilon, nIncoming);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
b->TopVolumeBranchUpperEndGRId, 0, nSelf, mergedTopVolBranchUpperEnd, nIncoming);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
b->TopVolumeBranchLowerEndGRId, 0, nSelf, mergedTopVolBranchLowerEnd, nIncoming);
|
||||
vtkm::cont::Algorithm::CopySubRange<ValueType, ValueType>(
|
||||
inArray, 0, nSelf, mergedTopVolBranchSaddleIsoValue, nIncoming);
|
||||
|
||||
@ -289,6 +359,12 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
IdArrayType permutedTopVolBranchSaddleEpsilon;
|
||||
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
|
||||
mergedTopVolBranchSaddleEpsilon, sortedBranchId, permutedTopVolBranchSaddleEpsilon);
|
||||
IdArrayType permutedTopVolBranchUpperEnd;
|
||||
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
|
||||
mergedTopVolBranchUpperEnd, sortedBranchId, permutedTopVolBranchUpperEnd);
|
||||
IdArrayType permutedTopVolBranchLowerEnd;
|
||||
vtkm::worklet::contourtree_augmented::PermuteArrayWithMaskedIndex<vtkm::Id, IdArrayType>(
|
||||
mergedTopVolBranchLowerEnd, sortedBranchId, permutedTopVolBranchLowerEnd);
|
||||
InArrayHandleType permutedTopVolBranchSaddleIsoValue;
|
||||
vtkm::worklet::contourtree_augmented::PermuteArrayWithRawIndex<InArrayHandleType>(
|
||||
mergedTopVolBranchSaddleIsoValue, sortedBranchId, permutedTopVolBranchSaddleIsoValue);
|
||||
@ -301,6 +377,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
"permutedTopBranchId", permutedTopVolBranchGRId, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"permutedTopBranchVol", permutedTopVolBranchVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"permutedTopBranchUpperEnd", permutedTopVolBranchUpperEnd, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"permutedTopBranchLowerEnd", permutedTopVolBranchLowerEnd, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"permutedTopSaddleVal", permutedTopVolBranchSaddleIsoValue, -1, rs);
|
||||
}
|
||||
@ -318,6 +398,8 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
IdArrayType mergedUniqueBranchGRId;
|
||||
IdArrayType mergedUniqueBranchVolume;
|
||||
IdArrayType mergedUniqueBranchSaddleEpsilon;
|
||||
IdArrayType mergedUniqueBranchUpperEnd;
|
||||
IdArrayType mergedUniqueBranchLowerEnd;
|
||||
InArrayHandleType mergedUniqueBranchSaddleIsoValue;
|
||||
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
@ -326,6 +408,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
permutedTopVolBranchVolume, oneIfUniqueBranch, mergedUniqueBranchVolume);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
permutedTopVolBranchSaddleEpsilon, oneIfUniqueBranch, mergedUniqueBranchSaddleEpsilon);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
permutedTopVolBranchUpperEnd, oneIfUniqueBranch, mergedUniqueBranchUpperEnd);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
permutedTopVolBranchLowerEnd, oneIfUniqueBranch, mergedUniqueBranchLowerEnd);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
permutedTopVolBranchSaddleIsoValue, oneIfUniqueBranch, mergedUniqueBranchSaddleIsoValue);
|
||||
|
||||
@ -339,6 +425,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
"mergedUniqueBranchId", mergedUniqueBranchGRId, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"mergedUniqueBranchVol", mergedUniqueBranchVolume, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"mergedUniqueBranchUpperEnd", mergedUniqueBranchUpperEnd, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"mergedUniqueBranchLowerEnd", mergedUniqueBranchLowerEnd, -1, rs);
|
||||
vtkm::worklet::contourtree_augmented::PrintValues<ValueType>(
|
||||
"mergedUniqueSaddleVal", mergedUniqueBranchSaddleIsoValue, -1, rs);
|
||||
}
|
||||
@ -356,6 +446,10 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
0,
|
||||
this->nSavedBranches,
|
||||
b->TopVolumeBranchSaddleEpsilon);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
mergedUniqueBranchUpperEnd, 0, this->nSavedBranches, b->TopVolumeBranchUpperEndGRId);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
mergedUniqueBranchLowerEnd, 0, this->nSavedBranches, b->TopVolumeBranchLowerEndGRId);
|
||||
// InArrayHandleType subRangeUniqueBranchSaddleIsoValue;
|
||||
inArray.Allocate(this->nSavedBranches);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
@ -368,6 +462,8 @@ void SelectTopVolumeContoursFunctor::operator()(
|
||||
vtkm::cont::Algorithm::Copy(mergedUniqueBranchVolume, b->TopVolumeBranchVolume);
|
||||
vtkm::cont::Algorithm::Copy(mergedUniqueBranchSaddleEpsilon,
|
||||
b->TopVolumeBranchSaddleEpsilon);
|
||||
vtkm::cont::Algorithm::Copy(mergedUniqueBranchUpperEnd, b->TopVolumeBranchUpperEndGRId);
|
||||
vtkm::cont::Algorithm::Copy(mergedUniqueBranchLowerEnd, b->TopVolumeBranchLowerEndGRId);
|
||||
inArray.Allocate(nMergedUnique);
|
||||
vtkm::cont::Algorithm::Copy(mergedUniqueBranchSaddleIsoValue, inArray);
|
||||
}
|
||||
|
@ -73,8 +73,9 @@ namespace internal
|
||||
|
||||
struct SelectTopVolumeContoursFunctor
|
||||
{
|
||||
SelectTopVolumeContoursFunctor(const vtkm::Id& nSB)
|
||||
SelectTopVolumeContoursFunctor(const vtkm::Id& nSB, const vtkm::cont::LogLevel& timingsLogLevel)
|
||||
: nSavedBranches(nSB)
|
||||
, TimingsLogLevel(timingsLogLevel)
|
||||
{
|
||||
}
|
||||
|
||||
@ -83,6 +84,7 @@ struct SelectTopVolumeContoursFunctor
|
||||
) const;
|
||||
|
||||
const vtkm::Id nSavedBranches;
|
||||
const vtkm::cont::LogLevel TimingsLogLevel;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
19
vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h
19
vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h
@ -182,6 +182,11 @@ public:
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType LowerEndIntrinsicVolume;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType UpperEndDependentVolume;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType LowerEndDependentVolume;
|
||||
// This information is only used when extracting isosurfaces
|
||||
// We need the upper and lower end within the block to determine the superarc containing the isovalue
|
||||
// The information should NOT be exchanged between blocks, since it's local id
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType UpperEndLocalId;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType LowerEndLocalId;
|
||||
|
||||
/// routines to compute branch decomposition by volume
|
||||
/// WARNING: we now have two types of hierarchical tree sharing a data structure:
|
||||
@ -507,11 +512,19 @@ inline void HierarchicalVolumetricBranchDecomposer::CollapseBranches(
|
||||
hierarchicalTreeSuperarcs
|
||||
};
|
||||
|
||||
// Get the number of rounds
|
||||
auto numRoundsArray = hierarchicalTreeDataSet.GetField("NumRounds")
|
||||
.GetData()
|
||||
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
vtkm::Id numRounds = vtkm::cont::ArrayGetValue(0, numRoundsArray);
|
||||
|
||||
using vtkm::worklet::scalar_topology::hierarchical_volumetric_branch_decomposer::
|
||||
CollapseBranchesWorklet;
|
||||
this->Invoke(CollapseBranchesWorklet{}, // the worklet
|
||||
CollapseBranchesWorklet collapseBranchesWorklet(numRounds);
|
||||
this->Invoke(collapseBranchesWorklet, // the worklet
|
||||
this->BestUpSupernode, // input
|
||||
this->BestDownSupernode, // input
|
||||
hierarchicalTreeSuperarcs, // input
|
||||
findRegularByGlobal, // input ExecutionObject
|
||||
findSuperArcBetweenNodes, // input ExecutionObject
|
||||
hierarchicalTreeRegular2Supernode, // input
|
||||
@ -770,6 +783,8 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
||||
vtkm::cont::make_ArrayHandlePermutation(sortedSuperarcs, actualBranchRoots);
|
||||
auto permutedRegularIds =
|
||||
vtkm::cont::make_ArrayHandlePermutation(sortedSuperarcs, actualOuterNodeRegularIds);
|
||||
auto permutedLocalIds =
|
||||
vtkm::cont::make_ArrayHandlePermutation(sortedSuperarcs, actualOuterNodeLocalIds);
|
||||
auto permutedDataValues =
|
||||
vtkm::cont::make_ArrayHandlePermutation(sortedSuperarcs, actualOuterNodeValues);
|
||||
auto permutedIntrinsicVolumes =
|
||||
@ -817,6 +832,7 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
||||
{
|
||||
vtkm::cont::Algorithm::CopyIf(permutedBranchRoots, oneIfBranchEnd, this->BranchRoot);
|
||||
vtkm::cont::Algorithm::CopyIf(branchRootGRIds, oneIfBranchEnd, this->BranchRootGRId);
|
||||
vtkm::cont::Algorithm::CopyIf(permutedLocalIds, oneIfBranchEnd, this->LowerEndLocalId);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
actualDirectedSuperarcs, oneIfBranchEnd, this->LowerEndSuperarcId);
|
||||
vtkm::cont::Algorithm::CopyIf(permutedRegularIds, oneIfBranchEnd, this->LowerEndGRId);
|
||||
@ -857,6 +873,7 @@ inline void HierarchicalVolumetricBranchDecomposer::CollectEndsOfBranches(
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
actualDirectedSuperarcs, oneIfBranchEnd, this->UpperEndSuperarcId);
|
||||
vtkm::cont::Algorithm::CopyIf(permutedRegularIds, oneIfBranchEnd, this->UpperEndGRId);
|
||||
vtkm::cont::Algorithm::CopyIf(permutedLocalIds, oneIfBranchEnd, this->UpperEndLocalId);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
permutedIntrinsicVolumes, oneIfBranchEnd, this->UpperEndIntrinsicVolume);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
using ControlSignature = void(
|
||||
FieldIn bestUpSupernode,
|
||||
FieldIn bestDownSupernode,
|
||||
FieldIn superarcs,
|
||||
// Execution objects from the hierarchical tree to use the FindRegularByGlobal function
|
||||
ExecObject findRegularByGlobal,
|
||||
// Execution objects from the hierarchical tree to use the FindSuperArcBetweenNodes, function
|
||||
@ -72,12 +73,15 @@ public:
|
||||
WholeArrayIn hierarchicalTreeRegular2supernode,
|
||||
WholeArrayIn hierarchicalTreeWhichRound,
|
||||
WholeArrayInOut branchRoot);
|
||||
using ExecutionSignature = void(InputIndex, _1, _2, _3, _4, _5, _6, _7);
|
||||
using ExecutionSignature = void(InputIndex, _1, _2, _3, _4, _5, _6, _7, _8);
|
||||
using InputDomain = _1;
|
||||
|
||||
/// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
CollapseBranchesWorklet() {}
|
||||
CollapseBranchesWorklet(vtkm::Id numRounds)
|
||||
: NumRounds(numRounds)
|
||||
{
|
||||
}
|
||||
|
||||
/// operator() of the workelt
|
||||
template <typename ExecObjectType1,
|
||||
@ -88,6 +92,7 @@ public:
|
||||
const vtkm::Id& supernode, // iteration index
|
||||
const vtkm::Id& bestUpSupernodeId, // bestUpSupernode[supernode]
|
||||
const vtkm::Id& bestDownSupernodeId, // bestDownSupernode[supernode]
|
||||
const vtkm::Id& superarcsId, // hierarchicalTree.superarcs[supernode]
|
||||
const ExecObjectType1& findRegularByGlobal, // Execution object to call FindRegularByGlobal
|
||||
const ExecObjectType2&
|
||||
findSuperArcBetweenNodes, // Execution object to call FindSuperArcBetweenNodes
|
||||
@ -104,6 +109,18 @@ public:
|
||||
// If it does exist and is an upwards superarc, then the current supernode must have an ascending arc to it, and we're done
|
||||
// Also do the same for the best down, then for each supernode, point the higher numbered at the lower
|
||||
|
||||
// ADDED 19/07/2023
|
||||
// If there are any attachment points left in the hierarchical tree, there is an extra edge case we need to deal with.
|
||||
// It occurs when a supernode is simultaneously the target of an ascending superarc and a descending one
|
||||
// What we do is to test for this here: if we are an attachment point, we omit connecting the best up and down
|
||||
// ADDED 19/07/2023
|
||||
// test for attachment points
|
||||
if ((hierarchicalTreeWhichRoundPortal.Get(supernode) != this->NumRounds) &&
|
||||
(vtkm::worklet::contourtree_augmented::NoSuchElement(superarcsId)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is no best up, we're at an upper leaf and will not connect up two superarcs anyway, so we can skip the supernode
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(bestUpSupernodeId))
|
||||
{
|
||||
@ -233,6 +250,8 @@ public:
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
private:
|
||||
vtkm::Id NumRounds;
|
||||
|
||||
}; // CollapseBranchesWorklet
|
||||
|
||||
|
@ -111,7 +111,7 @@ public:
|
||||
using ControlSignature = void(
|
||||
FieldIn superarcId, // (input) actual ID of superarc
|
||||
WholeArrayIn branchRoots, // (array input) branch root (superarc) IDs of all superarcs
|
||||
FieldOut branchEndIndicator // (output) 1 if
|
||||
FieldOut branchEndIndicator // (output) 1 if the superarc is the last of a branch in the array
|
||||
);
|
||||
using ExecutionSignature = _3(_1, _2);
|
||||
using InputDomain = _1;
|
||||
|
@ -102,6 +102,7 @@
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/AttachmentSuperparentAndIndexComparator.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/CopyBaseRegularStructureWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/CreateSuperarcsWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/FillEmptyIterationWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/FindSuperparentForNecessaryNodesWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/HierarchicalAugmenterInOutData.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/IsAscendingDecorator.h>
|
||||
@ -127,6 +128,11 @@ template <typename FieldType>
|
||||
class HierarchicalAugmenter
|
||||
{ // class HierarchicalAugmenter
|
||||
public:
|
||||
/// base mesh variable needs to determine whether a vertex is inside or outside of the block
|
||||
vtkm::Id3 MeshBlockOrigin;
|
||||
vtkm::Id3 MeshBlockSize;
|
||||
vtkm::Id3 MeshGlobalSize;
|
||||
|
||||
/// the tree that it hypersweeps over
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>* BaseTree;
|
||||
/// the tree that it is building
|
||||
@ -198,7 +204,10 @@ public:
|
||||
void Initialize(
|
||||
vtkm::Id blockId,
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>* inBaseTree,
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>* inAugmentedTree);
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>* inAugmentedTree,
|
||||
vtkm::Id3 meshBlockOrigin,
|
||||
vtkm::Id3 meshBockSize,
|
||||
vtkm::Id3 meshGlobalSize);
|
||||
|
||||
/// routine to prepare the set of attachment points to transfer
|
||||
void PrepareOutAttachmentPoints(vtkm::Id round);
|
||||
@ -225,7 +234,7 @@ public:
|
||||
void CopyBaseRegularStructure();
|
||||
|
||||
// subroutines for CopySuperstructure
|
||||
/// gets a list of all the old supernodes to transfer at this level (ie except attachment points
|
||||
/// gets a list of all the old supernodes to transfer at this level (i.e., except attachment points
|
||||
void RetrieveOldSupernodes(vtkm::Id roundNumber);
|
||||
/// resizes the arrays for the level
|
||||
void ResizeArrays(vtkm::Id roundNumber);
|
||||
@ -249,12 +258,18 @@ template <typename FieldType>
|
||||
void HierarchicalAugmenter<FieldType>::Initialize(
|
||||
vtkm::Id blockId,
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>* baseTree,
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>* augmentedTree)
|
||||
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<FieldType>* augmentedTree,
|
||||
vtkm::Id3 meshBlockOrigin,
|
||||
vtkm::Id3 meshBockSize,
|
||||
vtkm::Id3 meshGlobalSize)
|
||||
{ // Initialize()
|
||||
// copy the parameters for use
|
||||
this->BlockId = blockId;
|
||||
this->BaseTree = baseTree;
|
||||
this->AugmentedTree = augmentedTree;
|
||||
this->MeshBlockOrigin = meshBlockOrigin;
|
||||
this->MeshBlockSize = meshBockSize;
|
||||
this->MeshGlobalSize = meshGlobalSize;
|
||||
|
||||
// now construct a list of all attachment points on the block
|
||||
// to do this, we construct an index array with all supernode ID's that satisfy:
|
||||
@ -728,12 +743,13 @@ void HierarchicalAugmenter<FieldType>::CopyBaseRegularStructure()
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType tempRegularNodesNeeded;
|
||||
// create the worklet
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
|
||||
FindSuperparentForNecessaryNodesWorklet findSuperparentForNecessaryNodesWorklet;
|
||||
FindSuperparentForNecessaryNodesWorklet findSuperparentForNecessaryNodesWorklet(
|
||||
this->MeshBlockOrigin, this->MeshBlockSize, this->MeshGlobalSize);
|
||||
// Get a FindRegularByGlobal and FindSuperArcForUnknownNode execution object for our worklet
|
||||
auto findRegularByGlobal = this->AugmentedTree->GetFindRegularByGlobal();
|
||||
auto findSuperArcForUnknownNode = this->AugmentedTree->GetFindSuperArcForUnknownNode();
|
||||
|
||||
// excute the worklet
|
||||
// execute the worklet
|
||||
this->Invoke(findSuperparentForNecessaryNodesWorklet, // the worklet to call
|
||||
// inputs
|
||||
this->BaseTree->RegularNodeGlobalIds, // input domain
|
||||
@ -831,6 +847,11 @@ void HierarchicalAugmenter<FieldType>::CopyBaseRegularStructure()
|
||||
);
|
||||
}
|
||||
|
||||
// Reset the number of regular nodes in round 0
|
||||
vtkm::Id regularNodesInRound0 =
|
||||
numTotalRegular - this->AugmentedTree->NumRegularNodesInRound.ReadPortal().Get(1);
|
||||
this->AugmentedTree->NumRegularNodesInRound.WritePortal().Set(0, regularNodesInRound0);
|
||||
|
||||
// Finally, we resort the regular node sort order
|
||||
{
|
||||
vtkm::worklet::contourtree_distributed::PermuteComparator // hierarchical_contour_tree::
|
||||
@ -1218,6 +1239,7 @@ void HierarchicalAugmenter<FieldType>::CreateSuperarcs(vtkm::Id roundNumber)
|
||||
vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Super2Hypernode,
|
||||
numSupernodesAlready,
|
||||
this->SupernodeSorter.GetNumberOfValues());
|
||||
|
||||
// invoke the worklet
|
||||
this->Invoke(createSuperarcsWorklet, // the worklet
|
||||
this->SupernodeSorter, // input domain
|
||||
@ -1297,6 +1319,19 @@ void HierarchicalAugmenter<FieldType>::CreateSuperarcs(vtkm::Id roundNumber)
|
||||
// But there might be *NO* supernodes in the round, so we check first
|
||||
vtkm::Id iterationArraySize =
|
||||
vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations);
|
||||
|
||||
// This was added because in rare cases there are no supernodes transferred in an iteration, for example because there
|
||||
// are no available upper leaves to prune. If this is case, we are guaranteed that there will be available lower leaves
|
||||
// so the next iteration will have a non-zero number. We had a major bug from this, and it's cropped back up in the.
|
||||
// Hierarchical Augmentation, so I'm expanding the comment just in case.
|
||||
// Mingzhe: for any empty iteration, augmentedTree->FirstSupernodePerIteration[round] will be 0
|
||||
// Fill the 0 out (except when it is leading) by its following number as necessary
|
||||
// There should never be two consecutive zeros, so running it in parallel should be safe
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::FillEmptyIterationWorklet
|
||||
fillEmptyIterationWorklet;
|
||||
this->Invoke(fillEmptyIterationWorklet,
|
||||
this->AugmentedTree->FirstSupernodePerIteration[roundNumber]);
|
||||
|
||||
if (iterationArraySize > 0)
|
||||
{ // at least one iteration
|
||||
vtkm::Id lastSupernodeThisLevel = this->AugmentedTree->Supernodes.GetNumberOfValues() - 1;
|
||||
|
@ -110,6 +110,15 @@ public:
|
||||
if (ingid != selfid)
|
||||
{ // Receive and augment
|
||||
rp.dequeue(ingid, blockData->HierarchicalAugmenter.InData);
|
||||
|
||||
vtkm::Id exchangeSize =
|
||||
blockData->HierarchicalAugmenter.InData.Superparents.GetNumberOfValues();
|
||||
exchangeSize =
|
||||
std::max(exchangeSize,
|
||||
blockData->HierarchicalAugmenter.InData.GlobalRegularIds.GetNumberOfValues());
|
||||
timingsStream << " " << std::setw(38) << std::left << "Retrieved Attachment Points"
|
||||
<< ": " << exchangeSize << std::endl;
|
||||
|
||||
blockData->HierarchicalAugmenter.RetrieveInAttachmentPoints();
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,7 @@
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_contour_tree/FindSuperArcForUnknownNode.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_contour_tree/InitalizeSuperchildrenWorklet.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_contour_tree/PermuteComparator.h>
|
||||
#include <vtkm/filter/scalar_topology/worklet/select_top_volume_contours/LocalIsosurfaceExtractWorklet.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -1024,9 +1025,18 @@ void HierarchicalContourTree<FieldType>::AddToVTKMDataSet(vtkm::cont::DataSet& d
|
||||
vtkm::cont::Field superarcsField(
|
||||
"Superarcs", vtkm::cont::Field::Association::WholeDataSet, this->Superarcs);
|
||||
ds.AddField(superarcsField);
|
||||
vtkm::cont::Field superchildrenField(
|
||||
"Superchildren", vtkm::cont::Field::Association::WholeDataSet, this->Superchildren);
|
||||
ds.AddField(superchildrenField);
|
||||
vtkm::cont::Field hyperparentsField(
|
||||
"Hyperparents", vtkm::cont::Field::Association::WholeDataSet, this->Hyperparents);
|
||||
ds.AddField(hyperparentsField);
|
||||
vtkm::cont::Field hypernodesField(
|
||||
"Hypernodes", vtkm::cont::Field::Association::WholeDataSet, this->Hypernodes);
|
||||
ds.AddField(hypernodesField);
|
||||
vtkm::cont::Field hyperarcsField(
|
||||
"Hyperarcs", vtkm::cont::Field::Association::WholeDataSet, this->Hyperarcs);
|
||||
ds.AddField(hyperarcsField);
|
||||
vtkm::cont::Field super2HypernodeField(
|
||||
"Super2Hypernode", vtkm::cont::Field::Association::WholeDataSet, this->Super2Hypernode);
|
||||
ds.AddField(super2HypernodeField);
|
||||
@ -1054,6 +1064,13 @@ void HierarchicalContourTree<FieldType>::AddToVTKMDataSet(vtkm::cont::DataSet& d
|
||||
ds.AddField(firstSupernodePerIterationOffsetsField);
|
||||
// TODO/FIXME: It seems we may only need the counts for the first iteration, so check, which
|
||||
// information we actually need.
|
||||
// Add the number of rounds as an array of length 1
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> tempNumRounds;
|
||||
tempNumRounds.Allocate(1);
|
||||
vtkm::worklet::contourtree_augmented::IdArraySetValue(0, this->NumRounds, tempNumRounds);
|
||||
vtkm::cont::Field numRoundsField(
|
||||
"NumRounds", vtkm::cont::Field::Association::WholeDataSet, tempNumRounds);
|
||||
ds.AddField(numRoundsField);
|
||||
}
|
||||
|
||||
} // namespace contourtree_distributed
|
||||
|
@ -200,7 +200,6 @@ private:
|
||||
|
||||
}; // class HierarchicalHyperSweeper
|
||||
|
||||
|
||||
template <typename SweepValueType, typename ContourTreeFieldType>
|
||||
HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::HierarchicalHyperSweeper(
|
||||
vtkm::Id blockId,
|
||||
@ -360,6 +359,7 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::LocalHyperS
|
||||
// TODO/FIXME: Use portal? Or is there a more efficient way?
|
||||
auto firstSupernodePerIterationPortal =
|
||||
this->HierarchicalTree.FirstSupernodePerIteration[round].ReadPortal();
|
||||
|
||||
vtkm::Id firstSupernode = firstSupernodePerIterationPortal.Get(iteration);
|
||||
vtkm::Id lastSupernode = firstSupernodePerIterationPortal.Get(iteration + 1);
|
||||
|
||||
@ -424,7 +424,6 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::
|
||||
vtkm::Id lastSupernode)
|
||||
{ // ComputeSuperarcDependentWeights()
|
||||
vtkm::Id numSupernodesToProcess = lastSupernode - firstSupernode;
|
||||
|
||||
// 2. Use sorted prefix sum to compute the total weight to contribute to the super/hypertarget
|
||||
// Same as std::partial_sum(sweepValues.begin() + firstSupernode, sweepValues.begin() + lastSupernode, valuePrefixSum.begin() + firstSupernode);
|
||||
{
|
||||
@ -442,7 +441,6 @@ void HierarchicalHyperSweeper<SweepValueType, ContourTreeFieldType>::
|
||||
vtkm::cont::Algorithm::ScanInclusive(dependentValuesView, // input
|
||||
valuePrefixSumView); // result of partial sum
|
||||
}
|
||||
|
||||
// Since the prefix sum is over *all* supernodes in the iteration, we need to break it into segments
|
||||
// There are two cases we have to worry about:
|
||||
// a. Hyperarcs made up of multiple supernodes
|
||||
|
@ -22,6 +22,7 @@ set(headers
|
||||
SetSuperparentSetDecorator.h
|
||||
AttachmentAndSupernodeComparator.h
|
||||
ResizeArraysBuildNewSupernodeIdsWorklet.h
|
||||
FillEmptyIterationWorklet.h
|
||||
CreateSuperarcsWorklet.h
|
||||
HierarchicalAugmenterInOutData.h
|
||||
)
|
||||
|
@ -175,7 +175,6 @@ public:
|
||||
// strip the ascending flag from the superparent.
|
||||
vtkm::Id superparentOldSuperId =
|
||||
vtkm::worklet::contourtree_augmented::MaskedIndex(superparentSetVal);
|
||||
|
||||
// setting the superarc is done the usual way. Our sort routine has ended up
|
||||
// with the supernodes arranged in either ascending or descending order
|
||||
// inwards along the parent superarc (as expressed by the superparent Id).
|
||||
@ -237,8 +236,12 @@ public:
|
||||
(superarcAscends ? vtkm::worklet::contourtree_augmented::IS_ASCENDING : 0x00);
|
||||
} // not last in the segment
|
||||
|
||||
// The following single line sets the first supernode for the iteration for each round
|
||||
// Why does it execute separately for each supernode? This will kill speed with all the write collisions
|
||||
// Commented out so that the location of the error is apparent
|
||||
// It looks like this was set separately in ResizeArrays(), so it's also redundant!!!!
|
||||
// set the first supernode in the first iteration to the beginning of the round
|
||||
augmentedTreeFirstSupernodePerIterationPortal.Set(0, this->NumSupernodesAlready);
|
||||
// augmentedTreeFirstSupernodePerIterationPortal.Set(0, this->NumSupernodesAlready);
|
||||
|
||||
|
||||
// NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs
|
||||
|
95
vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/FillEmptyIterationWorklet.h
Normal file
95
vtkm/filter/scalar_topology/worklet/contourtree_distributed/hierarchical_augmenter/FillEmptyIterationWorklet.h
Normal file
@ -0,0 +1,95 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
//=============================================================================
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_augmenter_fill_empty_iteration_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_augmenter_fill_empty_iteration_worklet_h
|
||||
|
||||
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_augmenter
|
||||
{
|
||||
|
||||
// Worklet for a rare case where an iteration has no supernode
|
||||
// need to update the FirstSupernodePerIteration array to avoid crash
|
||||
class FillEmptyIterationWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
WholeArrayInOut augmentedTreeFirstSupernodePerIteration // input/output
|
||||
);
|
||||
using ExecutionSignature = void(InputIndex, _1);
|
||||
using InputDomain = _1;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
FillEmptyIterationWorklet() {}
|
||||
|
||||
/// operator() of the worklet
|
||||
template <typename InOutFieldPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& inputIndex,
|
||||
InOutFieldPortalType& firstSupernodePerIteration) const
|
||||
{
|
||||
if (inputIndex == 0 || inputIndex == firstSupernodePerIteration.GetNumberOfValues() - 1)
|
||||
return;
|
||||
if (firstSupernodePerIteration.Get(inputIndex) == 0)
|
||||
{
|
||||
vtkm::Id nextSupernode = firstSupernodePerIteration.Get(inputIndex + 1);
|
||||
firstSupernodePerIteration.Set(inputIndex, nextSupernode);
|
||||
}
|
||||
} // operator()()
|
||||
}; // FillEmptyIterationWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -83,7 +83,14 @@ public:
|
||||
|
||||
/// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
FindSuperparentForNecessaryNodesWorklet() {}
|
||||
FindSuperparentForNecessaryNodesWorklet(vtkm::Id3 meshBlockOrigin,
|
||||
vtkm::Id3 meshBlockSize,
|
||||
vtkm::Id3 meshGlobalSize)
|
||||
: MeshBlockOrigin(meshBlockOrigin)
|
||||
, MeshBlockSize(meshBlockSize)
|
||||
, MeshGlobalSize(meshGlobalSize)
|
||||
{
|
||||
}
|
||||
|
||||
/// operator() of the workelt
|
||||
template <typename InFieldPortalType,
|
||||
@ -111,6 +118,17 @@ public:
|
||||
// first check to see if it is already present (newRegularId set on input)
|
||||
vtkm::Id newRegularId = findRegularByGlobal.FindRegularByGlobal(globalRegularId);
|
||||
|
||||
// WARNING: Mingzhe: the code commented out below comes from one of Oliver's fixes
|
||||
// However, the code fails to work with isosurface extraction code.
|
||||
// Many regular vertices are missing from the array with the code below
|
||||
// Explicitly check whether the vertex belongs to the base block. If it doesn't, we ignore it
|
||||
/* if (!this->IsInMesh(globalRegularId))
|
||||
{
|
||||
// Set to NO_SUCH_ELEMENT by default. By doing this in the worklet we an avoid having to
|
||||
// initialize the output arrays first and we can use FieldIn instead of FieldInOut
|
||||
regularSuperparentsValue = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
regularNodesNeededValue = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
} else */
|
||||
// if it fails this test, then it's already in tree
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(newRegularId))
|
||||
{ // not yet in tree
|
||||
@ -200,7 +218,79 @@ public:
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
}; // FindSuperparentForNecessaryNodesWorklet
|
||||
private:
|
||||
// Mesh data
|
||||
vtkm::Id3 MeshBlockOrigin;
|
||||
vtkm::Id3 MeshBlockSize;
|
||||
vtkm::Id3 MeshGlobalSize;
|
||||
|
||||
VTKM_EXEC
|
||||
bool IsInMesh(vtkm::Id globalId) const
|
||||
{ // IsInMesh()
|
||||
if (this->MeshGlobalSize[2] > 1) // 3D
|
||||
{
|
||||
// convert from global ID to global coords
|
||||
vtkm::Id globalSliceSize = this->MeshGlobalSize[0] * this->MeshGlobalSize[1];
|
||||
vtkm::Id globalSlice = globalId / globalSliceSize;
|
||||
vtkm::Id globalRow = globalId / this->MeshGlobalSize[0];
|
||||
vtkm::Id globalCol = globalId % this->MeshGlobalSize[0];
|
||||
|
||||
// test validity
|
||||
if (globalSlice < this->MeshBlockOrigin[2])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalSlice >= this->MeshBlockOrigin[2] + this->MeshBlockSize[2])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalRow < this->MeshBlockOrigin[1])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalRow >= this->MeshBlockOrigin[1] + this->MeshBlockSize[1])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalCol < this->MeshBlockOrigin[0])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalCol >= this->MeshBlockOrigin[0] + this->MeshBlockSize[0])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// it's in the block - return true
|
||||
return true;
|
||||
} // end if 3D
|
||||
else // 2D mesh
|
||||
{
|
||||
// convert from global ID to global coords
|
||||
vtkm::Id globalRow = globalId / this->MeshGlobalSize[0];
|
||||
vtkm::Id globalCol = globalId % this->MeshGlobalSize[0];
|
||||
|
||||
// test validity
|
||||
if (globalRow < this->MeshBlockOrigin[1])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalRow >= this->MeshBlockOrigin[1] + this->MeshBlockSize[1])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalCol < this->MeshBlockOrigin[0])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (globalCol >= this->MeshBlockOrigin[0] + this->MeshBlockSize[0])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// it's in the block - return true
|
||||
return true;
|
||||
}
|
||||
} // IsInMesh()
|
||||
}; // FindSuperparentForNecessaryNodesWorklet
|
||||
|
||||
} // namespace hierarchical_augmenter
|
||||
} // namespace contourtree_distributed
|
||||
|
@ -118,6 +118,16 @@ public:
|
||||
// the hyperparent which we need to search along
|
||||
vtkm::Id hyperparent = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
|
||||
// sanity check: if above / below does not satisfy the condition, return NO_SUCH_ELEMENT
|
||||
FieldType aboveValue = this->DataValues.Get(above);
|
||||
FieldType belowValue = this->DataValues.Get(below);
|
||||
vtkm::Id aboveGlobalId = this->RegularNodeGlobalIds.Get(above);
|
||||
vtkm::Id belowGlobalId = this->RegularNodeGlobalIds.Get(below);
|
||||
if (nodeValue > aboveValue || (nodeValue == aboveValue && nodeGlobalId > aboveGlobalId))
|
||||
return vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
if (nodeValue < belowValue || (nodeValue == belowValue && nodeGlobalId < belowGlobalId))
|
||||
return vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
|
||||
// to find the superarc, we will first have to convert the above / below to a pair of super/hypernodes
|
||||
vtkm::Id aboveSuperparent = this->Superparents.Get(above);
|
||||
vtkm::Id belowSuperparent = this->Superparents.Get(below);
|
||||
|
236
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchParentComparator.h
Normal file
236
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/BranchParentComparator.h
Normal file
@ -0,0 +1,236 @@
|
||||
//============================================================================
|
||||
// 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_BranchParentComparator_h
|
||||
#define vtk_m_filter_scalar_topology_worklet_branch_decomposition_select_top_volume_contours_BranchParentComparator_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 BranchParentComparator
|
||||
template <typename ValueType>
|
||||
class BranchParentComparatorImpl
|
||||
{
|
||||
public:
|
||||
using ValueArrayType = typename vtkm::cont::ArrayHandle<ValueType>;
|
||||
using IdPortalType = typename IdArrayType::ReadPortalType;
|
||||
using ValuePortalType = typename ValueArrayType::ReadPortalType;
|
||||
|
||||
// constructor
|
||||
VTKM_CONT
|
||||
BranchParentComparatorImpl(const IdArrayType& branchParent,
|
||||
const ValueArrayType& saddleIsoValue,
|
||||
const IdArrayType& branchRootGRId,
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token)
|
||||
: branchParentPortal(branchParent.PrepareForInput(device, token))
|
||||
, saddleIsoValuePortal(saddleIsoValue.PrepareForInput(device, token))
|
||||
, branchRootGRIdPortal(branchRootGRId.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 parentI = this->branchParentPortal.Get(i);
|
||||
vtkm::Id parentJ = this->branchParentPortal.Get(j);
|
||||
|
||||
// primary sort on branch parent
|
||||
if (parentI < parentJ)
|
||||
return true;
|
||||
if (parentI > parentJ)
|
||||
return false;
|
||||
|
||||
ValueType valueI = this->saddleIsoValuePortal.Get(i);
|
||||
ValueType valueJ = this->saddleIsoValuePortal.Get(j);
|
||||
|
||||
// secondary sort on branch saddle isovalue
|
||||
if (valueI < valueJ)
|
||||
return true;
|
||||
if (valueI > valueJ)
|
||||
return false;
|
||||
|
||||
vtkm::Id rootI = this->branchRootGRIdPortal.Get(i);
|
||||
vtkm::Id rootJ = this->branchRootGRIdPortal.Get(j);
|
||||
|
||||
return (rootI < rootJ);
|
||||
} // operator()
|
||||
|
||||
private:
|
||||
IdPortalType branchParentPortal;
|
||||
ValuePortalType saddleIsoValuePortal;
|
||||
IdPortalType branchRootGRIdPortal;
|
||||
|
||||
}; // BranchParentComparatorImpl
|
||||
|
||||
/// <summary>
|
||||
/// Comparator of branch parent. Lower parent comes first
|
||||
/// </summary>
|
||||
template <typename ValueType>
|
||||
class BranchParentComparator : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
using ValueArrayType = typename vtkm::cont::ArrayHandle<ValueType>;
|
||||
|
||||
public:
|
||||
// constructor
|
||||
VTKM_CONT
|
||||
BranchParentComparator(const IdArrayType& branchParent,
|
||||
const ValueArrayType& saddleIsoValue,
|
||||
const IdArrayType& branchRootGRId)
|
||||
: BranchParent(branchParent)
|
||||
, SaddleIsoValue(saddleIsoValue)
|
||||
, BranchRootGRId(branchRootGRId)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT BranchParentComparatorImpl<ValueType> PrepareForExecution(
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
return BranchParentComparatorImpl<ValueType>(
|
||||
this->BranchParent, this->SaddleIsoValue, this->BranchRootGRId, device, token);
|
||||
}
|
||||
|
||||
private:
|
||||
IdArrayType BranchParent;
|
||||
ValueArrayType SaddleIsoValue;
|
||||
IdArrayType BranchRootGRId;
|
||||
}; // BranchParentComparator
|
||||
|
||||
|
||||
// Implementation of SuperarcTargetComparator
|
||||
class SuperarcTargetComparatorImpl
|
||||
{
|
||||
public:
|
||||
using IdPortalType = typename IdArrayType::ReadPortalType;
|
||||
|
||||
// constructor
|
||||
VTKM_CONT
|
||||
SuperarcTargetComparatorImpl(const IdArrayType& superarcTarget,
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token)
|
||||
: superarcPortal(superarcTarget.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_ASSERT(i < superarcPortal.GetNumberOfValues() && i >= 0);
|
||||
VTKM_ASSERT(j < superarcPortal.GetNumberOfValues() && j >= 0);
|
||||
vtkm::Id superarcI = this->superarcPortal.Get(i);
|
||||
vtkm::Id superarcJ = this->superarcPortal.Get(j);
|
||||
|
||||
bool isNullI = vtkm::worklet::contourtree_augmented::NoSuchElement(superarcI);
|
||||
bool isNullJ = vtkm::worklet::contourtree_augmented::NoSuchElement(superarcJ);
|
||||
|
||||
// let the NULL superarc always go first
|
||||
if (isNullI)
|
||||
return true;
|
||||
if (isNullJ)
|
||||
return false;
|
||||
|
||||
vtkm::Id targetI = vtkm::worklet::contourtree_augmented::MaskedIndex(superarcI);
|
||||
vtkm::Id targetJ = vtkm::worklet::contourtree_augmented::MaskedIndex(superarcJ);
|
||||
|
||||
// primary sort on the superarc target
|
||||
return (targetI < targetJ);
|
||||
} // operator()
|
||||
|
||||
private:
|
||||
IdPortalType superarcPortal;
|
||||
|
||||
}; // SuperarcTargetComparatorImpl
|
||||
|
||||
/// <summary>
|
||||
/// Comparator of superarc target. The NULL superarc always comes first.
|
||||
/// </summary>
|
||||
class SuperarcTargetComparator : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
|
||||
public:
|
||||
// constructor
|
||||
VTKM_CONT
|
||||
SuperarcTargetComparator(const IdArrayType& superarcTarget)
|
||||
: SuperarcTarget(superarcTarget)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT SuperarcTargetComparatorImpl PrepareForExecution(vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
return SuperarcTargetComparatorImpl(this->SuperarcTarget, device, token);
|
||||
}
|
||||
|
||||
private:
|
||||
IdArrayType SuperarcTarget;
|
||||
}; // SuperarcTargetComparator
|
||||
|
||||
|
||||
} // namespace select_top_volume_contours
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -9,10 +9,15 @@
|
||||
##============================================================================
|
||||
|
||||
set(headers
|
||||
Predicates.h
|
||||
ClarifyBranchEndSupernodeTypeWorklet.h
|
||||
UpdateInfoByBranchDirectionWorklet.h
|
||||
GetBranchHierarchyWorklet.h
|
||||
GetBranchVolumeWorklet.h
|
||||
BranchParentComparator.h
|
||||
BranchVolumeComparator.h
|
||||
MarchingCubesDataTables.h
|
||||
LocalIsosurfaceExtractWorklet.h
|
||||
)
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
401
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/GetBranchHierarchyWorklet.h
Normal file
401
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/GetBranchHierarchyWorklet.h
Normal file
@ -0,0 +1,401 @@
|
||||
//============================================================================
|
||||
// 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_GetBranchHierarchyWorklet_h
|
||||
#define vtk_m_filter_scalar_topology_worklet_select_top_volume_contours_GetBranchHierarchyWorklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace select_top_volume_contours
|
||||
{
|
||||
|
||||
constexpr vtkm::IdComponent MAX_CONNECTIVITY_3D = static_cast<vtkm::IdComponent>(14);
|
||||
using IdArrayType = vtkm::worklet::contourtree_augmented::IdArrayType;
|
||||
|
||||
/// <summary>
|
||||
/// worklet to check whether the saddle end of branch is known by the block
|
||||
/// if true, we return the saddle end supernode id
|
||||
/// if false (or main branch), we return NO_SUCH_ELEMENT
|
||||
/// </summary>
|
||||
class BranchSaddleIsKnownWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn lowerEndGRId, // (input) branch lower end global regular id
|
||||
FieldIn lowerLocalEnd, // (input) branch local lower end
|
||||
FieldIn lowerLocalEndGRId, // (input) branch local lower end global regular id
|
||||
FieldIn upperEndGRId, // (input) branch upper end global regular id
|
||||
FieldIn upperLocalEnd, // (input) branch local upper end
|
||||
FieldIn upperLocalEndGRId, // (input) branch local upper end global regular id
|
||||
FieldIn branchSaddleEps, // (input) branch saddle epsilon
|
||||
FieldOut branchSaddle // (output) the branch saddle (if known by the block)
|
||||
);
|
||||
using ExecutionSignature = _8(_1, _2, _3, _4, _5, _6, _7);
|
||||
using InputDomain = _1;
|
||||
|
||||
/// Constructor
|
||||
VTKM_EXEC_CONT
|
||||
BranchSaddleIsKnownWorklet() {}
|
||||
|
||||
/// The functor checks the direction of the branch
|
||||
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& lowerEndGRId,
|
||||
const vtkm::Id& lowerLocalEnd,
|
||||
const vtkm::Id& lowerLocalEndGRId,
|
||||
const vtkm::Id& upperEndGRId,
|
||||
const vtkm::Id& upperLocalEnd,
|
||||
const vtkm::Id& upperLocalEndGRId,
|
||||
const vtkm::Id& branchSaddleEps) const
|
||||
{
|
||||
// if main branch
|
||||
if (branchSaddleEps == 0)
|
||||
return vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
|
||||
// if the branch is a minimum-saddle branch
|
||||
if (branchSaddleEps > 0)
|
||||
return lowerEndGRId == lowerLocalEndGRId
|
||||
? lowerLocalEnd
|
||||
: vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
|
||||
// if the branch is a maximum-saddle branch
|
||||
if (branchSaddleEps < 0)
|
||||
return upperEndGRId == upperLocalEndGRId
|
||||
? upperLocalEnd
|
||||
: vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
|
||||
// in case of fallout, should never reach
|
||||
return vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
}
|
||||
|
||||
}; // BranchSaddleIsKnownWorklet
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// worklet to compute the parent branch of branches
|
||||
/// </summary>
|
||||
class GetParentBranchWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn branchSaddle, // (input) branch saddle supernode id
|
||||
FieldIn saddleBranchRoot, // (input) the branch root of the superarc starting from the saddle
|
||||
FieldIn saddleGRId, // (input) branch saddle supernode global regular id
|
||||
WholeArrayIn superarcs, // (array input) all superarc targets in ascending order
|
||||
WholeArrayIn branchRoots, // (array input) all branchRoots of superarcs
|
||||
WholeArrayIn branchRootByBranch, // (array input) branch roots of branches in ascending order
|
||||
WholeArrayIn upperEndGRIds, // (array input) upper local end of branches
|
||||
WholeArrayIn lowerEndGRIds, // (array input) lower local end of branches
|
||||
FieldOut parentBranch // (output) the information index of the parent branch
|
||||
);
|
||||
using ExecutionSignature = _9(_1, _2, _3, _4, _5, _6, _7, _8);
|
||||
using InputDomain = _1;
|
||||
|
||||
/// Constructor
|
||||
VTKM_EXEC_CONT
|
||||
GetParentBranchWorklet() {}
|
||||
|
||||
template <typename IdArrayPortalType>
|
||||
VTKM_EXEC vtkm::Id GetSuperarcEndPoint(const vtkm::Id& branchSaddle,
|
||||
const IdArrayPortalType& sortedSuperarcs,
|
||||
const bool isStart) const
|
||||
{
|
||||
VTKM_ASSERT(vtkm::worklet::contourtree_augmented::NoSuchElement(sortedSuperarcs.Get(0)));
|
||||
using vtkm::worklet::contourtree_augmented::MaskedIndex;
|
||||
vtkm::Id nSuperarcs = sortedSuperarcs.GetNumberOfValues();
|
||||
vtkm::Id endpoint = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
vtkm::Id head = 1;
|
||||
vtkm::Id tail = nSuperarcs - 1;
|
||||
while (head <= tail)
|
||||
{
|
||||
vtkm::Id mid = (head + tail) >> 1;
|
||||
vtkm::Id midSuperarc = MaskedIndex(sortedSuperarcs.Get(mid));
|
||||
if (midSuperarc > branchSaddle)
|
||||
tail = mid - 1;
|
||||
else if (midSuperarc < branchSaddle)
|
||||
head = mid + 1;
|
||||
else if (isStart &&
|
||||
(mid == 1 || (mid > 1 && MaskedIndex(sortedSuperarcs.Get(mid - 1)) < branchSaddle)))
|
||||
{
|
||||
endpoint = mid;
|
||||
break;
|
||||
}
|
||||
else if (!isStart &&
|
||||
(mid == nSuperarcs - 1 ||
|
||||
(mid < nSuperarcs - 1 && MaskedIndex(sortedSuperarcs.Get(mid + 1)) > branchSaddle)))
|
||||
{
|
||||
endpoint = mid;
|
||||
break;
|
||||
}
|
||||
else if (isStart)
|
||||
tail = mid - 1;
|
||||
else
|
||||
head = mid + 1;
|
||||
}
|
||||
VTKM_ASSERT(endpoint >= 1);
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
template <typename IdArrayPortalType>
|
||||
VTKM_EXEC vtkm::Id GetBranchRootIdx(const vtkm::Id& branchRoot,
|
||||
const IdArrayPortalType& branchRootByBranch) const
|
||||
{
|
||||
vtkm::Id nBranchRoot = branchRootByBranch.GetNumberOfValues();
|
||||
vtkm::Id head = 0;
|
||||
vtkm::Id tail = nBranchRoot - 1;
|
||||
while (head <= tail)
|
||||
{
|
||||
vtkm::Id mid = (head + tail) >> 1;
|
||||
vtkm::Id midBranchRoot = branchRootByBranch.Get(mid);
|
||||
if (midBranchRoot == branchRoot)
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
else if (midBranchRoot > branchRoot)
|
||||
tail = mid - 1;
|
||||
else
|
||||
head = mid + 1;
|
||||
}
|
||||
// should always find the branch root index
|
||||
// if not, report error
|
||||
VTKM_ASSERT(false && "Cannot find the branch root known by the block!");
|
||||
return vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
}
|
||||
|
||||
template <typename IdArrayPortalType>
|
||||
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& branchSaddle,
|
||||
const vtkm::Id& saddleBranchRoot,
|
||||
const vtkm::Id& saddleGRId,
|
||||
const IdArrayPortalType& sortedSuperarcs,
|
||||
const IdArrayPortalType& permutedBranchRoots,
|
||||
const IdArrayPortalType& branchRootByBranch,
|
||||
const IdArrayPortalType& upperEndGRIds,
|
||||
const IdArrayPortalType& lowerEndGRIds) const
|
||||
{
|
||||
// there are at most MAX_CONNECTIVITY_3D superarcs connected to the branchSaddle
|
||||
vtkm::Id candidateBranchRoot[MAX_CONNECTIVITY_3D];
|
||||
vtkm::Id nCandidate = 1;
|
||||
candidateBranchRoot[0] = saddleBranchRoot;
|
||||
|
||||
const vtkm::Id superarcStartIdx = GetSuperarcEndPoint(branchSaddle, sortedSuperarcs, true);
|
||||
const vtkm::Id superarcEndIdx = GetSuperarcEndPoint(branchSaddle, sortedSuperarcs, false);
|
||||
VTKM_ASSERT(superarcEndIdx >= superarcStartIdx);
|
||||
VTKM_ASSERT(superarcEndIdx - superarcStartIdx + 2 <= MAX_CONNECTIVITY_3D);
|
||||
for (vtkm::Id superarc = superarcStartIdx; superarc <= superarcEndIdx; superarc++)
|
||||
{
|
||||
candidateBranchRoot[nCandidate++] = permutedBranchRoots.Get(superarc);
|
||||
}
|
||||
|
||||
for (vtkm::Id branchRoot = 0; branchRoot < nCandidate; branchRoot++)
|
||||
{
|
||||
// NOTE: we ALWAYS exclude the virtual superarc, which does not belong to any branch
|
||||
if (candidateBranchRoot[branchRoot] == permutedBranchRoots.Get(0))
|
||||
continue;
|
||||
const vtkm::Id branchIdx =
|
||||
GetBranchRootIdx(candidateBranchRoot[branchRoot], branchRootByBranch);
|
||||
if (upperEndGRIds.Get(branchIdx) != saddleGRId && lowerEndGRIds.Get(branchIdx) != saddleGRId)
|
||||
return branchIdx;
|
||||
}
|
||||
|
||||
// Unfortunately, it seems possible that the parent branch cannot be found
|
||||
// in which case NO_SUCH_ELEMENT is returned
|
||||
// VTKM_ASSERT(false && "Cannot find the parent branch!");
|
||||
return vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
}
|
||||
}; // GetParentBranchWorklet
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// worklet to assign values to arrayhandle with given index
|
||||
/// this is different from permutation: we do not want to change the size of valueOut
|
||||
/// we also don't want to touch the default values in valueOut
|
||||
/// index - value is one to one
|
||||
/// </summary>
|
||||
class AssignValueByIndex : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(FieldIn index, // (input) index
|
||||
FieldIn value, // (input) value
|
||||
WholeArrayOut valueOut // (array output) valueOut[index] = value
|
||||
);
|
||||
using ExecutionSignature = void(_1, _2, _3);
|
||||
using InputDomain = _1;
|
||||
|
||||
/// Constructor
|
||||
VTKM_EXEC_CONT
|
||||
AssignValueByIndex() {}
|
||||
|
||||
template <typename ValueType, typename ValueArrayPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& index,
|
||||
const ValueType& value,
|
||||
ValueArrayPortalType& valueOut) const
|
||||
{
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(index))
|
||||
return;
|
||||
valueOut.Set(index, value);
|
||||
}
|
||||
}; // AssignValueByIndex
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// worklet to get the outer saddles of parent branches from branch-decomposition tree
|
||||
/// This is to visualize the isosurface belong to the parent branch
|
||||
/// that is symmetrical to the outer-most child branch
|
||||
/// we collect the first saddle isovalue if branchSaddleEpsilon(parent) < 0
|
||||
/// or the last saddle isovalue if branchSaddleEpsilon(parent) > 0
|
||||
/// or both if branchSaddleEpsilon(parent) == 0
|
||||
/// </summary>
|
||||
class CollectOuterSaddle : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn parentSaddleEpsilon, // parent saddle epsilon
|
||||
WholeArrayIn branchParent, // (array input) parent branch root ID (local)
|
||||
FieldOut IsOuterSaddle // (output) whether the branch is an outer saddle of the parent
|
||||
);
|
||||
using ExecutionSignature = _3(InputIndex, _1, _2);
|
||||
using InputDomain = _1;
|
||||
|
||||
using IdArrayPortalType = typename IdArrayType::ReadPortalType;
|
||||
|
||||
/// Constructor
|
||||
VTKM_EXEC_CONT
|
||||
CollectOuterSaddle() {}
|
||||
|
||||
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& inputIndex,
|
||||
const vtkm::Id& parentSaddleEpsilon,
|
||||
const IdArrayPortalType& branchParent) const
|
||||
{
|
||||
const vtkm::Id selfParent = branchParent.Get(inputIndex);
|
||||
vtkm::Id isOuterSaddle = 0;
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(selfParent))
|
||||
{
|
||||
return isOuterSaddle;
|
||||
}
|
||||
const bool isFirst = (inputIndex == 0) || (branchParent.Get(inputIndex - 1) != selfParent);
|
||||
const bool isLast = (inputIndex == branchParent.GetNumberOfValues() - 1) ||
|
||||
(branchParent.Get(inputIndex + 1) != selfParent);
|
||||
if (isFirst && parentSaddleEpsilon <= 0)
|
||||
{
|
||||
isOuterSaddle |= 1;
|
||||
}
|
||||
if (isLast && parentSaddleEpsilon >= 0)
|
||||
{
|
||||
isOuterSaddle |= 2;
|
||||
}
|
||||
return isOuterSaddle;
|
||||
}
|
||||
}; // CollectOuterSaddle
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// worklet to update the value of outer saddles for parent branches
|
||||
/// </summary>
|
||||
template <bool isMaximum>
|
||||
class UpdateOuterSaddle : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn branchOrder, // (input) the order of the (top-volume) branch by volume
|
||||
FieldInOut branchValue, // (input/output) the isovalue to extract
|
||||
WholeArrayIn incomingOrders, // (array input) (sorted) orders of branches from the other block
|
||||
WholeArrayIn
|
||||
incomingValues // (array input) isovalues to extract on branches from the other block
|
||||
);
|
||||
using ExecutionSignature = void(_1, _2, _3, _4);
|
||||
using InputDomain = _1;
|
||||
|
||||
using IdArrayPortalType = typename IdArrayType::ReadPortalType;
|
||||
|
||||
/// Constructor
|
||||
VTKM_EXEC_CONT
|
||||
UpdateOuterSaddle() {}
|
||||
|
||||
template <typename ValueType, typename ValuePortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& branchOrder,
|
||||
ValueType& branchValue,
|
||||
const IdArrayPortalType& incomingOrders,
|
||||
const ValuePortalType& incomingValues) const
|
||||
{
|
||||
vtkm::Id head = 0;
|
||||
vtkm::Id tail = incomingOrders.GetNumberOfValues() - 1;
|
||||
while (head <= tail)
|
||||
{
|
||||
vtkm::Id mid = (head + tail) >> 1;
|
||||
vtkm::Id midOrder = incomingOrders.Get(mid);
|
||||
if (midOrder == branchOrder)
|
||||
{
|
||||
const ValueType midValue = incomingValues.Get(mid);
|
||||
if (isMaximum && midValue > branchValue)
|
||||
branchValue = midValue;
|
||||
else if (!isMaximum && midValue < branchValue)
|
||||
branchValue = midValue;
|
||||
return;
|
||||
}
|
||||
else if (midOrder > branchOrder)
|
||||
tail = mid - 1;
|
||||
else
|
||||
head = mid + 1;
|
||||
}
|
||||
}
|
||||
}; // UpdateOuterSaddle
|
||||
|
||||
} // namespace select_top_volume_contours
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -108,18 +108,19 @@ public:
|
||||
{
|
||||
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;
|
||||
: totalVolume - upperDependent + upperIntrinsic - 1;
|
||||
// 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;
|
||||
: totalVolume - lowerDependent + lowerIntrinsic - 1;
|
||||
|
||||
// in case of fallout, should never reach
|
||||
return 0;
|
||||
|
751
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/LocalIsosurfaceExtractWorklet.h
Normal file
751
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/LocalIsosurfaceExtractWorklet.h
Normal file
@ -0,0 +1,751 @@
|
||||
//============================================================================
|
||||
// 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_local_isosurface_extract_worklet_h
|
||||
#define vtk_m_filter_scalar_topology_worklet_select_top_volume_contours_local_isosurface_extract_worklet_h
|
||||
|
||||
#include <vtkm/filter/scalar_topology/worklet/select_top_volume_contours/MarchingCubesDataTables.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace select_top_volume_contours
|
||||
{
|
||||
|
||||
constexpr vtkm::IdComponent MAX_MARCHING_CUBE_TRIANGLES = static_cast<vtkm::IdComponent>(5);
|
||||
constexpr vtkm::IdComponent MAX_LINEAR_INTERPOLATION_TRIANGLES = static_cast<vtkm::IdComponent>(12);
|
||||
|
||||
/// Worklet to check whether the global regular id in inside the block
|
||||
/// The global regular Ids in block should be sorted beforehand
|
||||
class IdxIfWithinBlockWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn regularId, // (input) global regular id
|
||||
WholeArrayIn idsInBlock, // (array input) all global regular ids within the local block
|
||||
FieldOut inBlockIndicator, // (output) 1 if the regularId is inside the block
|
||||
FieldOut inBlockIdx // (output) the index of regularId in idsInBlock
|
||||
);
|
||||
using ExecutionSignature = void(_1, _2, _3, _4);
|
||||
using InputDomain = _1;
|
||||
|
||||
/// Constructor
|
||||
VTKM_EXEC_CONT
|
||||
IdxIfWithinBlockWorklet() {}
|
||||
|
||||
/// The functor uses binary search to locate regularId in idsInBlock
|
||||
/// if the search fails, return NO_SUCH_ELEMENT; otherwise, return the location
|
||||
/// idsInBlock should be sorted
|
||||
template <typename InIdPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& regularId,
|
||||
const InIdPortalType& idsInBlock,
|
||||
vtkm::Id& inBlockIndicator,
|
||||
vtkm::Id& inBlockIdx) const
|
||||
{
|
||||
vtkm::Id head = 0;
|
||||
vtkm::Id tail = idsInBlock.GetNumberOfValues() - 1;
|
||||
inBlockIndicator = 0;
|
||||
inBlockIdx = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
|
||||
while (head <= tail)
|
||||
{
|
||||
vtkm::Id mid = (head + tail) >> 1;
|
||||
vtkm::Id midValue = idsInBlock.Get(mid);
|
||||
if (regularId == midValue)
|
||||
{
|
||||
inBlockIdx = mid;
|
||||
inBlockIndicator = 1;
|
||||
return;
|
||||
}
|
||||
else if (regularId > midValue)
|
||||
head = mid + 1;
|
||||
else
|
||||
tail = mid - 1;
|
||||
}
|
||||
}
|
||||
}; // IdxIfWithinBlockWorklet
|
||||
|
||||
|
||||
/// Worklet for debug, upon remove when release
|
||||
class DebugSearchWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature =
|
||||
void(FieldIn regularId, // (input) global regular id
|
||||
WholeArrayIn idsInBlock, // (array input) all global regular ids within the local block
|
||||
FieldOut foundId);
|
||||
using ExecutionSignature = _3(InputIndex, _1, _2);
|
||||
using InputDomain = _1;
|
||||
|
||||
/// Constructor
|
||||
VTKM_EXEC_CONT
|
||||
DebugSearchWorklet(const vtkm::Id& superarcSize)
|
||||
: SuperarcSize(superarcSize)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename InIdPortalType>
|
||||
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& inputIndex,
|
||||
const vtkm::Id& regularId,
|
||||
const InIdPortalType& idsInBlock) const
|
||||
{
|
||||
vtkm::Id head = 0;
|
||||
vtkm::Id tail = idsInBlock.GetNumberOfValues() - 1;
|
||||
|
||||
while (head <= tail)
|
||||
{
|
||||
vtkm::Id mid = (head + tail) >> 1;
|
||||
vtkm::Id midValue = idsInBlock.Get(mid);
|
||||
if (regularId == midValue)
|
||||
{
|
||||
if (inputIndex < SuperarcSize)
|
||||
return inputIndex;
|
||||
break;
|
||||
}
|
||||
else if (regularId > midValue)
|
||||
head = mid + 1;
|
||||
else
|
||||
tail = mid - 1;
|
||||
}
|
||||
return vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
}
|
||||
|
||||
private:
|
||||
const vtkm::Id SuperarcSize;
|
||||
}; // DebugSearchWorklet
|
||||
|
||||
|
||||
/// Worklet for getting the polarity case of a cell compared to the isovalue.
|
||||
/// Only consider 2D and 3D data.
|
||||
/// The output for each cell is an integer ([0, 7] if 2D, or [0, 255] if 3D)
|
||||
/// indicating the polarity at each vertex of the cell compared to the isovalue.
|
||||
template <typename ValueType>
|
||||
class GetCellCasesWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn localIdx, // (input) local point index
|
||||
WholeArrayIn dataValues, // (array input) data values within block
|
||||
WholeArrayIn vertexOffset, // (array input) vertex offset look-up table
|
||||
FieldOut caseCell // (output) the polarity case (in binary) of the cell
|
||||
);
|
||||
using ExecutionSignature = _4(_1, _2, _3);
|
||||
using InputDomain = _1;
|
||||
|
||||
using IdArrayPortalType = typename vtkm::cont::ArrayHandle<vtkm::Id>::ReadPortalType;
|
||||
using ValueArrayPortalType = typename vtkm::cont::ArrayHandle<ValueType>::ReadPortalType;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="ptDimensions">dimension of points in the grid</param>
|
||||
/// <param name="branchSaddleEpsilon">the direction for tiebreaking when comparing values</param>
|
||||
/// <param name="isoValue">isovalue for the isosurface to extract</param>
|
||||
/// <returns></returns>
|
||||
VTKM_EXEC_CONT
|
||||
GetCellCasesWorklet(const vtkm::Id3 ptDimensions,
|
||||
const vtkm::Id branchSaddleEpsilon,
|
||||
const ValueType isoValue)
|
||||
: PointDimensions(ptDimensions)
|
||||
, BranchSaddleEpsilon(branchSaddleEpsilon)
|
||||
, IsoValue(isoValue)
|
||||
{
|
||||
CellDimensions[0] = ptDimensions[0] - 1;
|
||||
CellDimensions[1] = ptDimensions[1] - 1;
|
||||
CellDimensions[2] = ptDimensions[2] - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the polarity case of cells
|
||||
/// </summary>
|
||||
/// <param name="localIndex">the local index of the point in the local grid</param>
|
||||
/// <param name="dataValuesPortal">all data values on the local grid points</param>
|
||||
/// <returns>integer indicating the polarity case of the cell originating at the input point</returns>
|
||||
VTKM_EXEC vtkm::Id operator()(const vtkm::Id localIndex,
|
||||
const ValueArrayPortalType& dataValuesPortal,
|
||||
const IdArrayPortalType& vertexOffset) const
|
||||
{
|
||||
const vtkm::Id nPoints = PointDimensions[0] * PointDimensions[1] * PointDimensions[2];
|
||||
VTKM_ASSERT(dataValuesPortal.GetNumberOfValues() == nPoints);
|
||||
if (CellDimensions[2] <= 0)
|
||||
{
|
||||
// the 2D local coordinate of the input point
|
||||
vtkm::Id2 localPt(localIndex % CellDimensions[0], localIndex / CellDimensions[0]);
|
||||
vtkm::Id caseCell = 0;
|
||||
// iterate over all points of the cell
|
||||
for (vtkm::Id i = 0; i < nVertices2d; i++)
|
||||
{
|
||||
vtkm::Id currPtIdx = i * 2;
|
||||
vtkm::Id currPt = vertexOffset.Get(currPtIdx) + localPt[0] +
|
||||
(vertexOffset.Get(currPtIdx + 1) + localPt[1]) * PointDimensions[0];
|
||||
VTKM_ASSERT(currPt < nPoints);
|
||||
// when point value == IsoValue
|
||||
// the index is 1 only if the branch is lower-end
|
||||
if (dataValuesPortal.Get(currPt) > IsoValue ||
|
||||
(dataValuesPortal.Get(currPt) == IsoValue && BranchSaddleEpsilon < 0))
|
||||
caseCell |= vtkm::Id(1) << i;
|
||||
}
|
||||
return caseCell;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the 3D local coordinate of the input point
|
||||
vtkm::Id3 localPt(localIndex % CellDimensions[0],
|
||||
(localIndex / CellDimensions[0]) % CellDimensions[1],
|
||||
localIndex / (CellDimensions[0] * CellDimensions[1]));
|
||||
vtkm::Id caseCell = 0;
|
||||
// iterate over all points of the cell
|
||||
for (vtkm::Id i = 0; i < nVertices3d; i++)
|
||||
{
|
||||
vtkm::Id currPtIdx = i * 3;
|
||||
vtkm::Id currPt = vertexOffset.Get(currPtIdx) + localPt[0] +
|
||||
(vertexOffset.Get(currPtIdx + 1) + localPt[1]) * PointDimensions[0] +
|
||||
(vertexOffset.Get(currPtIdx + 2) + localPt[2]) *
|
||||
(PointDimensions[0] * PointDimensions[1]);
|
||||
VTKM_ASSERT(currPt < nPoints);
|
||||
// when point value == IsoValue
|
||||
// the index is 1 only if the branch is lower-end
|
||||
if (dataValuesPortal.Get(currPt) > IsoValue ||
|
||||
(dataValuesPortal.Get(currPt) == IsoValue && BranchSaddleEpsilon < 0))
|
||||
caseCell |= vtkm::Id(1) << i;
|
||||
}
|
||||
return caseCell;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::Id3 PointDimensions;
|
||||
vtkm::Id BranchSaddleEpsilon;
|
||||
ValueType IsoValue;
|
||||
vtkm::Id3 CellDimensions;
|
||||
|
||||
}; // GetCellCasesWorklet
|
||||
|
||||
|
||||
/// Worklet for getting the superarc of a branch given an isovalue
|
||||
class GetSuperarcByIsoValueWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature =
|
||||
void(FieldIn upperEndLocalId, // (input) upper end of the branch
|
||||
FieldIn lowerEndLocalId, // (input) lower end of the branch
|
||||
FieldIn isoValue, // (input) isoValue
|
||||
FieldIn branchSaddleEpsilon, // (input) whether the branch is on top or at the bottom
|
||||
FieldOut superarc, // (output) local superarc that intersects the isosurface
|
||||
ExecObject findSuperarcByNode);
|
||||
using ExecutionSignature = _5(_1, _2, _3, _4, _6);
|
||||
using InputDomain = _1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="totNumPoints">total number of points within the local grid</param>
|
||||
/// <hint>We only need a number that is larger than any grid index</hint>
|
||||
VTKM_EXEC_CONT
|
||||
GetSuperarcByIsoValueWorklet(const vtkm::Id totNumPoints)
|
||||
: TotalNumPoints(totNumPoints)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of GetSuperarcByIsoValueWorklet.
|
||||
/// Check vtkm::worklet::contourtree_distributed::FindSuperArcForUnknownNode
|
||||
/// for the execution object description.
|
||||
/// </summary>
|
||||
/// <typeparam name="ValueType">data value type</typeparam>
|
||||
/// <typeparam name="findSuperarcType">execution object type of findSuperarc</typeparam>
|
||||
/// <param name="upperEndLocalId">local id of the upper end vertex of the branch</param>
|
||||
/// <param name="lowerEndLocalId">local id of the lower end vertex of the branch</param>
|
||||
/// <param name="isoValue">isovalue</param>
|
||||
/// <param name="branchSaddleEpsilon">the direction for tiebreaking when comparing values</param>
|
||||
/// <param name="findSuperarc">execution object</param>
|
||||
/// <returns></returns>
|
||||
template <typename ValueType, typename findSuperarcType>
|
||||
VTKM_EXEC vtkm::Id operator()(const vtkm::Id upperEndLocalId,
|
||||
const vtkm::Id lowerEndLocalId,
|
||||
const ValueType isoValue,
|
||||
const vtkm::Id branchSaddleEpsilon,
|
||||
const findSuperarcType& findSuperarc) const
|
||||
{
|
||||
VTKM_ASSERT(branchSaddleEpsilon != 0);
|
||||
if (branchSaddleEpsilon < 0)
|
||||
return findSuperarc.FindSuperArcForUnknownNode(
|
||||
-1, isoValue, upperEndLocalId, lowerEndLocalId);
|
||||
return findSuperarc.FindSuperArcForUnknownNode(
|
||||
TotalNumPoints, isoValue, upperEndLocalId, lowerEndLocalId);
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::Id TotalNumPoints;
|
||||
|
||||
}; // GetSuperarcByIsoValueWorklet
|
||||
|
||||
|
||||
/// Worklet for calculating the edges to be drawn in the cell
|
||||
/// NOTE: this worklet can only work on 2D and 3D data
|
||||
template <typename ValueType>
|
||||
class GetEdgesInCellWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn edgeOffset, // (input) offset of output edge in the output array
|
||||
FieldIn caseCell, // (input) the marching cube case of the cell
|
||||
WholeArrayIn localIds, // (array input) local ids of points
|
||||
WholeArrayIn dataValues, // (array input) data values within block
|
||||
WholeArrayIn vertexOffset, // (array input) vertex offset look-up table
|
||||
WholeArrayIn edgeTable, // (array input) edge-in-cell look-up table
|
||||
WholeArrayIn numBoundTable, // (array input) number of boundaries look-up table
|
||||
WholeArrayIn boundaryTable, // (array input) edge-of-boundary look-up table
|
||||
WholeArrayIn labelEdgeTable, // (array input) label edge (only for 3D) look-up table
|
||||
WholeArrayOut edgesFrom, // (array output) array of start-points of edges on the isosurface
|
||||
WholeArrayOut edgesTo, // (array output) array of end-points of edges on the isosurface
|
||||
WholeArrayOut
|
||||
isValidEdges, // (array output) whether the edge plan to draw belongs to the branch
|
||||
ExecObject
|
||||
findSuperarcForNode // (execution object) detector for the superarc of interpolated nodes
|
||||
);
|
||||
using ExecutionSignature =
|
||||
void(InputIndex, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13);
|
||||
using InputDomain = _1;
|
||||
|
||||
using IdArrayReadPortalType = typename vtkm::cont::ArrayHandle<vtkm::Id>::ReadPortalType;
|
||||
using IdArrayWritePortalType = typename vtkm::cont::ArrayHandle<vtkm::Id>::WritePortalType;
|
||||
using ValueArrayPortalType = typename vtkm::cont::ArrayHandle<ValueType>::ReadPortalType;
|
||||
using EdgePointArrayPortalType =
|
||||
typename vtkm::cont::ArrayHandle<vtkm::Vec3f_64>::WritePortalType;
|
||||
|
||||
/// Constructor
|
||||
/// ptDimensions: dimension of points in the grid
|
||||
/// branchSuperarc: the superarc on the given branch intersecting the isosurface
|
||||
/// isoValue: isovalue for the isosurface to extract
|
||||
VTKM_EXEC_CONT
|
||||
GetEdgesInCellWorklet(const vtkm::Id3 ptDimensions,
|
||||
const vtkm::Id3 globalPointIndexStart,
|
||||
const ValueType isoValue,
|
||||
const vtkm::Id branchSuperarc,
|
||||
const vtkm::Id branchSaddleEpsilon,
|
||||
const vtkm::Id totNumPoints,
|
||||
const bool marchingCubes)
|
||||
: PointDimensions(ptDimensions)
|
||||
, GlobalPointIndexStart(globalPointIndexStart)
|
||||
, IsoValue(isoValue)
|
||||
, BranchSuperarc(branchSuperarc)
|
||||
, BranchSaddleEpsilon(branchSaddleEpsilon)
|
||||
, TotalNumPoints(totNumPoints)
|
||||
, isMarchingCubes(marchingCubes)
|
||||
{
|
||||
CellDimensions[0] = ptDimensions[0] - 1;
|
||||
CellDimensions[1] = ptDimensions[1] - 1;
|
||||
CellDimensions[2] = ptDimensions[2] - 1;
|
||||
}
|
||||
|
||||
// cell index: the point index within the local cell
|
||||
VTKM_EXEC vtkm::Id CellIndexToNodeIndex2D(const vtkm::Id2& localPt,
|
||||
const vtkm::Id cellIndex,
|
||||
const IdArrayReadPortalType& vertOffset) const
|
||||
{
|
||||
return vertOffset.Get(cellIndex * 2) + localPt[0] +
|
||||
(vertOffset.Get(cellIndex * 2 + 1) + localPt[1]) * PointDimensions[0];
|
||||
}
|
||||
|
||||
// cell index: the point index within the local cell
|
||||
VTKM_EXEC vtkm::Vec3f_64 CellIndexToNodeCoord2D(const vtkm::Id2& localPt,
|
||||
const vtkm::Id cellIndex,
|
||||
const IdArrayReadPortalType& vertOffset) const
|
||||
{
|
||||
return vtkm::Vec3f_64(
|
||||
static_cast<vtkm::Float64>(vertOffset.Get(cellIndex * 2) + localPt[0]),
|
||||
static_cast<vtkm::Float64>(vertOffset.Get(cellIndex * 2 + 1) + localPt[1]),
|
||||
static_cast<vtkm::Float64>(0));
|
||||
}
|
||||
|
||||
// cell index: the point index within the local cell
|
||||
VTKM_EXEC vtkm::Id CellIndexToNodeIndex3D(const vtkm::Id3& localPt,
|
||||
const vtkm::Id cellIndex,
|
||||
const IdArrayReadPortalType& vertOffset) const
|
||||
{
|
||||
return vertOffset.Get(cellIndex * 3) + localPt[0] +
|
||||
(vertOffset.Get(cellIndex * 3 + 1) + localPt[1]) * PointDimensions[0] +
|
||||
(vertOffset.Get(cellIndex * 3 + 2) + localPt[2]) * (PointDimensions[0] * PointDimensions[1]);
|
||||
}
|
||||
|
||||
// cell index: the point index within the local cell
|
||||
VTKM_EXEC vtkm::Vec3f_64 CellIndexToNodeCoord3D(const vtkm::Id3& localPt,
|
||||
const vtkm::Id cellIndex,
|
||||
const IdArrayReadPortalType& vertOffset) const
|
||||
{
|
||||
return vtkm::Vec3f_64(
|
||||
static_cast<vtkm::Float64>(vertOffset.Get(cellIndex * 3) + localPt[0]),
|
||||
static_cast<vtkm::Float64>(vertOffset.Get(cellIndex * 3 + 1) + localPt[1]),
|
||||
static_cast<vtkm::Float64>(vertOffset.Get(cellIndex * 3 + 2) + localPt[2]));
|
||||
}
|
||||
|
||||
// Implementation to draw isosurface edges
|
||||
// all hard-coded numbers in this function depends on the dimension of the data
|
||||
// The number of vertices/lines/faces of a cell is fixed for a certain dimension
|
||||
// The number of cases for the marching cube algorithm are also hard-coded
|
||||
// Check MarchingCubesDataTables.h for more details
|
||||
template <typename FindSuperarcExecType>
|
||||
VTKM_EXEC void operator()(
|
||||
const vtkm::Id localIndex, // refers to the index in the grid
|
||||
const vtkm::Id edgeOffset,
|
||||
const vtkm::Id caseCell,
|
||||
const IdArrayReadPortalType& localIdsPortal, // refers to the index in (superarc etc.) arrays
|
||||
const ValueArrayPortalType& dataValuesPortal,
|
||||
const IdArrayReadPortalType& vertexOffset,
|
||||
const IdArrayReadPortalType& edgeTable,
|
||||
const IdArrayReadPortalType& numBoundTable,
|
||||
const IdArrayReadPortalType& boundaryTable,
|
||||
const IdArrayReadPortalType& labelEdgeTable,
|
||||
EdgePointArrayPortalType& edgesFromPortal,
|
||||
EdgePointArrayPortalType& edgesToPortal,
|
||||
IdArrayWritePortalType& isValidEdgesPortal,
|
||||
const FindSuperarcExecType& findSuperarcForNode) const
|
||||
{
|
||||
const vtkm::Id nPoints = PointDimensions[0] * PointDimensions[1] * PointDimensions[2];
|
||||
// 2D
|
||||
if (CellDimensions[2] <= 0)
|
||||
{
|
||||
const vtkm::Id2 localPt(localIndex % CellDimensions[0], localIndex / CellDimensions[0]);
|
||||
|
||||
VTKM_ASSERT(localIdsPortal.GetNumberOfValues() == nPoints);
|
||||
VTKM_ASSERT(dataValuesPortal.GetNumberOfValues() == nPoints);
|
||||
|
||||
const vtkm::Id numEdges = numBoundTable.Get(caseCell);
|
||||
if (numEdges < 1)
|
||||
return;
|
||||
for (vtkm::Id edgeIndex = 0; edgeIndex < numEdges; edgeIndex++)
|
||||
{
|
||||
const vtkm::Id lineForCaseOffset = caseCell * nLineTableElemSize2d; // 8;
|
||||
const vtkm::Id lineOffset = lineForCaseOffset + edgeIndex * 2;
|
||||
// lineFrom and lineTo are two edges where the isosurface edge intersects
|
||||
const vtkm::Id lineFrom = boundaryTable.Get(lineOffset);
|
||||
const vtkm::Id lineTo = boundaryTable.Get(lineOffset + 1);
|
||||
|
||||
// We need to assure that both lineFrom and lineTo belong to the branch
|
||||
// all 0 and 1 in the variables below refer to the two vertices of the line
|
||||
const vtkm::Id lineFromVert0 =
|
||||
CellIndexToNodeIndex2D(localPt, edgeTable.Get(lineFrom * 2), vertexOffset);
|
||||
const vtkm::Id lineFromVert1 =
|
||||
CellIndexToNodeIndex2D(localPt, edgeTable.Get(lineFrom * 2 + 1), vertexOffset);
|
||||
VTKM_ASSERT(lineFromVert0 < nPoints);
|
||||
VTKM_ASSERT(lineFromVert1 < nPoints);
|
||||
const vtkm::Id lineFromVert0LocalId = localIdsPortal.Get(lineFromVert0);
|
||||
const vtkm::Id lineFromVert1LocalId = localIdsPortal.Get(lineFromVert1);
|
||||
const ValueType lineFromVert0Value = dataValuesPortal.Get(lineFromVert0);
|
||||
const ValueType lineFromVert1Value = dataValuesPortal.Get(lineFromVert1);
|
||||
// due to simulation of simplicity
|
||||
// vert0 < vert1 if their values are equal
|
||||
const vtkm::Id lowVertFrom =
|
||||
lineFromVert0Value <= lineFromVert1Value ? lineFromVert0LocalId : lineFromVert1LocalId;
|
||||
const vtkm::Id highVertFrom =
|
||||
lineFromVert0Value > lineFromVert1Value ? lineFromVert0LocalId : lineFromVert1LocalId;
|
||||
|
||||
const vtkm::Id lineToVert0 =
|
||||
CellIndexToNodeIndex2D(localPt, edgeTable.Get(lineTo * 2), vertexOffset);
|
||||
const vtkm::Id lineToVert1 =
|
||||
CellIndexToNodeIndex2D(localPt, edgeTable.Get(lineTo * 2 + 1), vertexOffset);
|
||||
VTKM_ASSERT(lineToVert0 < nPoints);
|
||||
VTKM_ASSERT(lineToVert1 < nPoints);
|
||||
const vtkm::Id lineToVert0LocalId = localIdsPortal.Get(lineToVert0);
|
||||
const vtkm::Id lineToVert1LocalId = localIdsPortal.Get(lineToVert1);
|
||||
const ValueType lineToVert0Value = dataValuesPortal.Get(lineToVert0);
|
||||
const ValueType lineToVert1Value = dataValuesPortal.Get(lineToVert1);
|
||||
// due to simulation of simplicity
|
||||
// vert0 < vert1 if their values are equal
|
||||
const vtkm::Id lowVertTo =
|
||||
lineToVert0Value <= lineToVert1Value ? lineToVert0LocalId : lineToVert1LocalId;
|
||||
const vtkm::Id highVertTo =
|
||||
lineToVert0Value > lineToVert1Value ? lineToVert0LocalId : lineToVert1LocalId;
|
||||
|
||||
vtkm::Id lineFromSuperarc = -1;
|
||||
vtkm::Id lineToSuperarc = -1;
|
||||
|
||||
// We always extract the isosurface above/below the isovalue by 0+
|
||||
VTKM_ASSERT(BranchSaddleEpsilon != 0);
|
||||
// lower end of branch is leaf
|
||||
// the actual isovalue should be IsoValue-eps
|
||||
// eps is 0+ (infinitely small)
|
||||
if (BranchSaddleEpsilon < 0)
|
||||
{
|
||||
lineFromSuperarc =
|
||||
findSuperarcForNode.FindSuperArcForUnknownNode(-1, IsoValue, highVertFrom, lowVertFrom);
|
||||
lineToSuperarc =
|
||||
findSuperarcForNode.FindSuperArcForUnknownNode(-1, IsoValue, highVertTo, lowVertTo);
|
||||
}
|
||||
// upper end of branch is leaf
|
||||
// the actual isovalue should be IsoValue+eps
|
||||
// eps is 0+ (infinitely small)
|
||||
else if (BranchSaddleEpsilon > 0)
|
||||
{
|
||||
lineFromSuperarc = findSuperarcForNode.FindSuperArcForUnknownNode(
|
||||
TotalNumPoints, IsoValue, highVertFrom, lowVertFrom);
|
||||
lineToSuperarc = findSuperarcForNode.FindSuperArcForUnknownNode(
|
||||
TotalNumPoints, IsoValue, highVertTo, lowVertTo);
|
||||
}
|
||||
|
||||
// we only draw the line if both lineFrom and lineTo belongs to the branch of query
|
||||
if (lineFromSuperarc != BranchSuperarc || lineToSuperarc != BranchSuperarc)
|
||||
{
|
||||
isValidEdgesPortal.Set(edgeOffset + edgeIndex, 0);
|
||||
continue;
|
||||
}
|
||||
isValidEdgesPortal.Set(edgeOffset + edgeIndex, 1);
|
||||
|
||||
// Now let's draw the line
|
||||
vtkm::Vec3f_64 lineFromVert0Coord =
|
||||
CellIndexToNodeCoord2D(localPt, edgeTable.Get(lineFrom * 2), vertexOffset);
|
||||
vtkm::Vec3f_64 lineFromVert1Coord =
|
||||
CellIndexToNodeCoord2D(localPt, edgeTable.Get(lineFrom * 2 + 1), vertexOffset);
|
||||
vtkm::Vec3f_64 lineToVert0Coord =
|
||||
CellIndexToNodeCoord2D(localPt, edgeTable.Get(lineTo * 2), vertexOffset);
|
||||
vtkm::Vec3f_64 lineToVert1Coord =
|
||||
CellIndexToNodeCoord2D(localPt, edgeTable.Get(lineTo * 2 + 1), vertexOffset);
|
||||
|
||||
vtkm::Vec3f_64 fromPt(lineFromVert0Coord);
|
||||
vtkm::Vec3f_64 toPt(lineToVert0Coord);
|
||||
|
||||
vtkm::Float64 fromRatio =
|
||||
vtkm::Float64(IsoValue - lineFromVert0Value) / (lineFromVert1Value - lineFromVert0Value);
|
||||
vtkm::Float64 toRatio =
|
||||
vtkm::Float64(IsoValue - lineToVert0Value) / (lineToVert1Value - lineToVert0Value);
|
||||
|
||||
VTKM_ASSERT(fromRatio >= 0.0 && fromRatio <= 1.0);
|
||||
VTKM_ASSERT(toRatio >= 0.0 && toRatio <= 1.0);
|
||||
|
||||
fromPt += (lineFromVert1Coord - lineFromVert0Coord) * fromRatio;
|
||||
toPt += (lineToVert1Coord - lineToVert0Coord) * toRatio;
|
||||
|
||||
edgesFromPortal.Set(edgeOffset + edgeIndex, fromPt + GlobalPointIndexStart);
|
||||
edgesToPortal.Set(edgeOffset + edgeIndex, toPt + GlobalPointIndexStart);
|
||||
}
|
||||
}
|
||||
else // 3D
|
||||
{
|
||||
vtkm::Id3 localPt(localIndex % CellDimensions[0],
|
||||
(localIndex / CellDimensions[0]) % CellDimensions[1],
|
||||
localIndex / (CellDimensions[0] * CellDimensions[1]));
|
||||
|
||||
const vtkm::Id numTriangles = numBoundTable.Get(caseCell);
|
||||
if (numTriangles < 1)
|
||||
return;
|
||||
|
||||
// we check a specific edge to know the superarc of the triangle
|
||||
// the edge label of the triangle is stored in labelEdgeTable in MarchingCubesDataTables.h
|
||||
// there are at most 5 triangles to draw in each 3D cell (for marching cubes)
|
||||
// for linear interpolation, there are at most 12 triangles
|
||||
if (isMarchingCubes)
|
||||
VTKM_ASSERT(numTriangles <= MAX_MARCHING_CUBE_TRIANGLES);
|
||||
else
|
||||
VTKM_ASSERT(numTriangles <= MAX_LINEAR_INTERPOLATION_TRIANGLES);
|
||||
vtkm::Id triangleSuperarc[MAX_LINEAR_INTERPOLATION_TRIANGLES + 1];
|
||||
|
||||
vtkm::Id triangleLabelIdx = 0;
|
||||
const vtkm::Id nLabelEdgeElemSize =
|
||||
isMarchingCubes ? nLabelEdgeTableMC3dElemSize : nLabelEdgeTableLT3dElemSize;
|
||||
vtkm::Id labelPtr = caseCell * nLabelEdgeElemSize;
|
||||
while (labelEdgeTable.Get(labelPtr) != -1)
|
||||
{
|
||||
vtkm::Id labelCount = labelEdgeTable.Get(labelPtr++);
|
||||
vtkm::Id labelEdge = labelEdgeTable.Get(labelPtr++);
|
||||
|
||||
// compute the superarc of the labelEdge belong to the branch
|
||||
const vtkm::Id labelEdgeVert0 =
|
||||
CellIndexToNodeIndex3D(localPt, edgeTable.Get(labelEdge * 2), vertexOffset);
|
||||
const vtkm::Id labelEdgeVert1 =
|
||||
CellIndexToNodeIndex3D(localPt, edgeTable.Get(labelEdge * 2 + 1), vertexOffset);
|
||||
VTKM_ASSERT(labelEdgeVert0 < nPoints);
|
||||
VTKM_ASSERT(labelEdgeVert1 < nPoints);
|
||||
|
||||
const vtkm::Id labelEdgeVert0LocalId = localIdsPortal.Get(labelEdgeVert0);
|
||||
const vtkm::Id labelEdgeVert1LocalId = localIdsPortal.Get(labelEdgeVert1);
|
||||
const ValueType labelEdgeVert0Value = dataValuesPortal.Get(labelEdgeVert0);
|
||||
const ValueType labelEdgeVert1Value = dataValuesPortal.Get(labelEdgeVert1);
|
||||
// due to simulation of simplicity
|
||||
// vert0 < vert1 if their values are equal
|
||||
const vtkm::Id lowVert = labelEdgeVert0Value <= labelEdgeVert1Value ? labelEdgeVert0LocalId
|
||||
: labelEdgeVert1LocalId;
|
||||
const vtkm::Id highVert =
|
||||
labelEdgeVert0Value > labelEdgeVert1Value ? labelEdgeVert0LocalId : labelEdgeVert1LocalId;
|
||||
|
||||
vtkm::Id labelEdgeSuperarc = -1;
|
||||
|
||||
// We always extract the isosurface above/below the isovalue by 0+
|
||||
VTKM_ASSERT(BranchSaddleEpsilon != 0);
|
||||
// lower end of branch is leaf
|
||||
// the actual isovalue should be IsoValue-(0+)
|
||||
if (BranchSaddleEpsilon < 0)
|
||||
{
|
||||
labelEdgeSuperarc =
|
||||
findSuperarcForNode.FindSuperArcForUnknownNode(-1, IsoValue, highVert, lowVert);
|
||||
}
|
||||
// upper end of branch is leaf
|
||||
// the actual isovalue should be IsoValue+(0+)
|
||||
else if (BranchSaddleEpsilon > 0)
|
||||
{
|
||||
labelEdgeSuperarc = findSuperarcForNode.FindSuperArcForUnknownNode(
|
||||
TotalNumPoints, IsoValue, highVert, lowVert);
|
||||
}
|
||||
for (vtkm::Id i = 0; i < labelCount; i++)
|
||||
triangleSuperarc[triangleLabelIdx++] = labelEdgeSuperarc;
|
||||
}
|
||||
|
||||
VTKM_ASSERT(triangleLabelIdx == numTriangles);
|
||||
|
||||
const vtkm::Id nTriTableElemSize =
|
||||
isMarchingCubes ? nTriTableMC3dElemSize : nTriTableLT3dElemSize;
|
||||
for (vtkm::Id triIndex = 0; triIndex < numTriangles; triIndex++)
|
||||
{
|
||||
const vtkm::Id lineFroms[3] = {
|
||||
boundaryTable.Get(caseCell * nTriTableElemSize + triIndex * 3),
|
||||
boundaryTable.Get(caseCell * nTriTableElemSize + triIndex * 3 + 1),
|
||||
boundaryTable.Get(caseCell * nTriTableElemSize + triIndex * 3 + 2)
|
||||
};
|
||||
const vtkm::Id lineTos[3] = {
|
||||
boundaryTable.Get(caseCell * nTriTableElemSize + triIndex * 3 + 1),
|
||||
boundaryTable.Get(caseCell * nTriTableElemSize + triIndex * 3 + 2),
|
||||
boundaryTable.Get(caseCell * nTriTableElemSize + triIndex * 3)
|
||||
};
|
||||
|
||||
const vtkm::Id labelEdgeSuperarc = triangleSuperarc[triIndex];
|
||||
// we only draw the triangle if the triangle lies on the branch of query
|
||||
if (labelEdgeSuperarc != BranchSuperarc)
|
||||
{
|
||||
isValidEdgesPortal.Set(edgeOffset + triIndex * 3, 0);
|
||||
isValidEdgesPortal.Set(edgeOffset + triIndex * 3 + 1, 0);
|
||||
isValidEdgesPortal.Set(edgeOffset + triIndex * 3 + 2, 0);
|
||||
continue;
|
||||
}
|
||||
isValidEdgesPortal.Set(edgeOffset + triIndex * 3, 1);
|
||||
isValidEdgesPortal.Set(edgeOffset + triIndex * 3 + 1, 1);
|
||||
isValidEdgesPortal.Set(edgeOffset + triIndex * 3 + 2, 1);
|
||||
|
||||
for (vtkm::Id edgeIndex = 0; edgeIndex < 3; edgeIndex++)
|
||||
{
|
||||
// lineFrom and lineTo are two edges where the edge of the triangle intersects
|
||||
const vtkm::Id lineFrom = lineFroms[edgeIndex];
|
||||
const vtkm::Id lineTo = lineTos[edgeIndex];
|
||||
|
||||
// Now let's draw the line
|
||||
vtkm::Vec3f_64 lineFromVert0Coord =
|
||||
CellIndexToNodeCoord3D(localPt, edgeTable.Get(lineFrom * 2), vertexOffset);
|
||||
vtkm::Vec3f_64 lineFromVert1Coord =
|
||||
CellIndexToNodeCoord3D(localPt, edgeTable.Get(lineFrom * 2 + 1), vertexOffset);
|
||||
vtkm::Vec3f_64 lineToVert0Coord =
|
||||
CellIndexToNodeCoord3D(localPt, edgeTable.Get(lineTo * 2), vertexOffset);
|
||||
vtkm::Vec3f_64 lineToVert1Coord =
|
||||
CellIndexToNodeCoord3D(localPt, edgeTable.Get(lineTo * 2 + 1), vertexOffset);
|
||||
|
||||
vtkm::Vec3f_64 fromPt(lineFromVert0Coord);
|
||||
vtkm::Vec3f_64 toPt(lineToVert0Coord);
|
||||
|
||||
const vtkm::Id lineFromVert0 =
|
||||
CellIndexToNodeIndex3D(localPt, edgeTable.Get(lineFrom * 2), vertexOffset);
|
||||
const vtkm::Id lineFromVert1 =
|
||||
CellIndexToNodeIndex3D(localPt, edgeTable.Get(lineFrom * 2 + 1), vertexOffset);
|
||||
VTKM_ASSERT(lineFromVert0 < nPoints);
|
||||
VTKM_ASSERT(lineFromVert1 < nPoints);
|
||||
const ValueType lineFromVert0Value = dataValuesPortal.Get(lineFromVert0);
|
||||
const ValueType lineFromVert1Value = dataValuesPortal.Get(lineFromVert1);
|
||||
|
||||
const vtkm::Id lineToVert0 =
|
||||
CellIndexToNodeIndex3D(localPt, edgeTable.Get(lineTo * 2), vertexOffset);
|
||||
const vtkm::Id lineToVert1 =
|
||||
CellIndexToNodeIndex3D(localPt, edgeTable.Get(lineTo * 2 + 1), vertexOffset);
|
||||
VTKM_ASSERT(lineToVert0 < nPoints);
|
||||
VTKM_ASSERT(lineToVert1 < nPoints);
|
||||
const ValueType lineToVert0Value = dataValuesPortal.Get(lineToVert0);
|
||||
const ValueType lineToVert1Value = dataValuesPortal.Get(lineToVert1);
|
||||
|
||||
vtkm::Float64 fromRatio = vtkm::Float64(IsoValue - lineFromVert0Value) /
|
||||
(lineFromVert1Value - lineFromVert0Value);
|
||||
vtkm::Float64 toRatio =
|
||||
vtkm::Float64(IsoValue - lineToVert0Value) / (lineToVert1Value - lineToVert0Value);
|
||||
VTKM_ASSERT(fromRatio >= 0.0 && fromRatio <= 1.0);
|
||||
VTKM_ASSERT(toRatio >= 0.0 && toRatio <= 1.0);
|
||||
|
||||
fromPt += (lineFromVert1Coord - lineFromVert0Coord) * fromRatio;
|
||||
toPt += (lineToVert1Coord - lineToVert0Coord) * toRatio;
|
||||
|
||||
edgesFromPortal.Set(edgeOffset + triIndex * 3 + edgeIndex,
|
||||
fromPt + GlobalPointIndexStart);
|
||||
edgesToPortal.Set(edgeOffset + triIndex * 3 + edgeIndex, toPt + GlobalPointIndexStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::Id3 PointDimensions;
|
||||
vtkm::Id3 GlobalPointIndexStart;
|
||||
ValueType IsoValue;
|
||||
vtkm::Id BranchSuperarc;
|
||||
vtkm::Id BranchSaddleEpsilon;
|
||||
vtkm::Id TotalNumPoints;
|
||||
bool isMarchingCubes;
|
||||
vtkm::Id3 CellDimensions;
|
||||
|
||||
}; // GetEdgesInCellWorklet
|
||||
|
||||
|
||||
} // namespace select_top_volume_contours
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
945
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/MarchingCubesDataTables.h
Normal file
945
vtkm/filter/scalar_topology/worklet/select_top_volume_contours/MarchingCubesDataTables.h
Normal file
@ -0,0 +1,945 @@
|
||||
//============================================================================
|
||||
// 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_marching_cubes_data_tables_h
|
||||
#define vtk_m_filter_scalar_topology_worklet_select_top_volume_contours_marching_cubes_data_tables_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace select_top_volume_contours
|
||||
{
|
||||
|
||||
// Edges include the diagonal of the triangulation of the mesh
|
||||
const vtkm::Id nVertices2d = 4;
|
||||
const vtkm::Id nEdges2d = 5;
|
||||
const vtkm::Id nCases2d = 16;
|
||||
const vtkm::Id nLineTableElemSize2d = 8;
|
||||
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> vertexOffset2d =
|
||||
vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0, 0, 1, 0, 1, 1, 0, 1 });
|
||||
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> edgeTable2d =
|
||||
vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0, 1, 1, 2, 3, 2, 0, 3, 0, 2 });
|
||||
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> numLinesTable2d =
|
||||
vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 0 });
|
||||
|
||||
// size: nCase2d * nLineTableElemSize2d
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> lineTable2d = vtkm::cont::make_ArrayHandle<vtkm::Id>({
|
||||
#define X -1
|
||||
X, X, X, X, X, X, X, X, 3, 4, 4, 0, X, X, X, X, 0, 1, X, X, X, X, X, X, 3, 4, 4, 1, X, X, X, X,
|
||||
2, 4, 4, 1, X, X, X, X, 3, 2, 0, 1, X, X, X, X, 2, 4, 4, 0, X, X, X, X, 3, 2, X, X, X, X, X, X,
|
||||
3, 2, X, X, X, X, X, X, 2, 4, 4, 0, X, X, X, X, 3, 2, 0, 1, X, X, X, X, 2, 4, 4, 1, X, X, X, X,
|
||||
3, 4, 4, 1, X, X, X, X, 0, 1, X, X, X, X, X, X, 3, 4, 4, 0, X, X, X, X, X, X, X, X, X, X, X, X
|
||||
#undef X
|
||||
});
|
||||
|
||||
const vtkm::Id nVertices3d = 8;
|
||||
const vtkm::Id nEdgesMC3d = 12;
|
||||
const vtkm::Id nEdgesLT3d = 19;
|
||||
const vtkm::Id nCasesMC3d = 256;
|
||||
const vtkm::Id nCasesLT3d = 256;
|
||||
|
||||
// size: nVertices3d * nDims (3)
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> vertexOffset3d = vtkm::cont::make_ArrayHandle<vtkm::Id>(
|
||||
{ 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1 });
|
||||
|
||||
// size: nEdgesMC3d * 2 (vertices per edge)
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> edgeTableMC3d = vtkm::cont::make_ArrayHandle<vtkm::Id>(
|
||||
{ 0, 1, 1, 2, 3, 2, 0, 3, 4, 5, 5, 6, 7, 6, 4, 7, 0, 4, 1, 5, 2, 6, 3, 7 });
|
||||
|
||||
// size: nEdgesLT3d * 2
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> edgeTableLT3d = vtkm::cont::make_ArrayHandle<vtkm::Id>(
|
||||
{ 0, 1, 1, 2, 3, 2, 0, 3, 4, 5, 5, 6, 7, 6, 4, 7, 0, 4, 1,
|
||||
5, 2, 6, 3, 7, 0, 2, 4, 6, 0, 5, 3, 6, 0, 7, 1, 6, 0, 6 });
|
||||
|
||||
// size: nCasesMC3d
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> numTrianglesTableMC3d =
|
||||
vtkm::cont::make_ArrayHandle<vtkm::Id>({
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 2, 3, 4, 4, 3, 3, 4, 4, 3, 4, 5, 5, 2,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4,
|
||||
2, 3, 3, 4, 3, 4, 2, 3, 3, 4, 4, 5, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 3, 2, 4, 5, 5, 4, 5, 2, 4, 1,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 4, 3, 4, 4, 5, 3, 2, 4, 3, 4, 3, 5, 2,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, 3, 4, 4, 3, 4, 5, 5, 4, 4, 3, 5, 2, 5, 4, 2, 1,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 2, 3, 3, 2, 3, 4, 4, 5, 4, 5, 5, 2, 4, 3, 5, 4, 3, 2, 4, 1,
|
||||
3, 4, 4, 5, 4, 5, 3, 4, 4, 5, 5, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0,
|
||||
});
|
||||
|
||||
// size: nCasesMC3d
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> numTrianglesTableLT3d =
|
||||
vtkm::cont::make_ArrayHandle<vtkm::Id>(
|
||||
{ 0, 6, 2, 8, 2, 8, 4, 8, 2, 8, 4, 10, 4, 8, 6, 8, 2, 8, 4, 10, 4, 10,
|
||||
6, 10, 4, 10, 6, 12, 6, 10, 8, 10, 2, 8, 4, 8, 4, 10, 6, 8, 4, 10, 6, 10,
|
||||
6, 10, 8, 8, 4, 8, 6, 8, 6, 10, 8, 8, 6, 10, 8, 10, 8, 10, 10, 8, 6, 12,
|
||||
8, 10, 8, 10, 8, 8, 8, 10, 10, 8, 8, 8, 8, 6, 8, 10, 10, 8, 10, 8, 10, 6,
|
||||
10, 8, 12, 6, 10, 6, 10, 4, 8, 10, 8, 8, 10, 8, 8, 6, 10, 8, 10, 6, 10, 6,
|
||||
8, 4, 8, 8, 8, 6, 10, 6, 8, 4, 10, 6, 10, 4, 10, 4, 8, 2, 2, 8, 4, 10,
|
||||
4, 10, 6, 10, 4, 8, 6, 10, 6, 8, 8, 8, 4, 8, 6, 10, 6, 10, 8, 10, 6, 8,
|
||||
8, 10, 8, 8, 10, 8, 4, 10, 6, 10, 6, 12, 8, 10, 6, 10, 8, 10, 8, 10, 10, 8,
|
||||
6, 8, 8, 8, 8, 10, 10, 8, 8, 8, 10, 8, 10, 8, 12, 6, 8, 10, 10, 8, 10, 8,
|
||||
10, 6, 8, 8, 10, 6, 8, 6, 8, 4, 8, 8, 10, 6, 10, 6, 10, 4, 8, 6, 10, 4,
|
||||
8, 4, 8, 2, 10, 8, 10, 6, 12, 6, 10, 4, 10, 6, 10, 4, 10, 4, 8, 2, 8, 6,
|
||||
8, 4, 10, 4, 8, 2, 8, 4, 8, 2, 8, 2, 6, 0 });
|
||||
|
||||
const vtkm::Id nTriTableMC3dElemSize = 16; // (at most 5 triangles, each with 3 vertices)
|
||||
const vtkm::Id nTriTableLT3dElemSize = 37; // (at most 12 triangles, each with 3 vertices)
|
||||
|
||||
|
||||
// size: nCasesMC3d * nTriTableMCElemSize
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> triTableMC3d = vtkm::cont::make_ArrayHandle<vtkm::Id>({
|
||||
#define X -1
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 8, 3, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 0, 1, 9, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
1, 8, 3, 9, 8, 1, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 10, X, X, X, X, X, X, X, X, X, X,
|
||||
9, 2, 10, 0, 2, 9, X, X, X, X, X, X, X, X, X, X, 2, 8, 3, 2, 10, 8, 10, 9,
|
||||
8, X, X, X, X, X, X, X, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
0, 11, 2, 8, 11, 0, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 11, X, X,
|
||||
X, X, X, X, X, X, X, X, 1, 11, 2, 1, 9, 11, 9, 8, 11, X, X, X, X, X, X, X,
|
||||
3, 10, 1, 11, 10, 3, X, X, X, X, X, X, X, X, X, X, 0, 10, 1, 0, 8, 10, 8, 11,
|
||||
10, X, X, X, X, X, X, X, 3, 9, 0, 3, 11, 9, 11, 10, 9, X, X, X, X, X, X, X,
|
||||
9, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, X, X, X, 4, 7, 8, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 4, 3, 0, 7, 3, 4, X, X, X, X, X, X, X, X, X, X,
|
||||
0, 1, 9, 8, 4, 7, X, X, X, X, X, X, X, X, X, X, 4, 1, 9, 4, 7, 1, 7, 3,
|
||||
1, X, X, X, X, X, X, X, 1, 2, 10, 8, 4, 7, X, X, X, X, X, X, X, X, X, X,
|
||||
3, 4, 7, 3, 0, 4, 1, 2, 10, X, X, X, X, X, X, X, 9, 2, 10, 9, 0, 2, 8, 4,
|
||||
7, X, X, X, X, X, X, X, 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, X, X, X, X,
|
||||
8, 4, 7, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, 11, 4, 7, 11, 2, 4, 2, 0,
|
||||
4, X, X, X, X, X, X, X, 9, 0, 1, 8, 4, 7, 2, 3, 11, X, X, X, X, X, X, X,
|
||||
4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, X, X, X, X, 3, 10, 1, 3, 11, 10, 7, 8,
|
||||
4, X, X, X, X, X, X, X, 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, X, X, X, X,
|
||||
4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, X, X, X, X, 4, 7, 11, 4, 11, 9, 9, 11,
|
||||
10, X, X, X, X, X, X, X, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
9, 5, 4, 0, 8, 3, X, X, X, X, X, X, X, X, X, X, 0, 5, 4, 1, 5, 0, X, X,
|
||||
X, X, X, X, X, X, X, X, 8, 5, 4, 8, 3, 5, 3, 1, 5, X, X, X, X, X, X, X,
|
||||
1, 2, 10, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 10, 4, 9,
|
||||
5, X, X, X, X, X, X, X, 5, 2, 10, 5, 4, 2, 4, 0, 2, X, X, X, X, X, X, X,
|
||||
2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, X, X, X, X, 9, 5, 4, 2, 3, 11, X, X,
|
||||
X, X, X, X, X, X, X, X, 0, 11, 2, 0, 8, 11, 4, 9, 5, X, X, X, X, X, X, X,
|
||||
0, 5, 4, 0, 1, 5, 2, 3, 11, X, X, X, X, X, X, X, 2, 1, 5, 2, 5, 8, 2, 8,
|
||||
11, 4, 8, 5, X, X, X, X, 10, 3, 11, 10, 1, 3, 9, 5, 4, X, X, X, X, X, X, X,
|
||||
4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, X, X, X, X, 5, 4, 0, 5, 0, 11, 5, 11,
|
||||
10, 11, 0, 3, X, X, X, X, 5, 4, 8, 5, 8, 10, 10, 8, 11, X, X, X, X, X, X, X,
|
||||
9, 7, 8, 5, 7, 9, X, X, X, X, X, X, X, X, X, X, 9, 3, 0, 9, 5, 3, 5, 7,
|
||||
3, X, X, X, X, X, X, X, 0, 7, 8, 0, 1, 7, 1, 5, 7, X, X, X, X, X, X, X,
|
||||
1, 5, 3, 3, 5, 7, X, X, X, X, X, X, X, X, X, X, 9, 7, 8, 9, 5, 7, 10, 1,
|
||||
2, X, X, X, X, X, X, X, 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, X, X, X, X,
|
||||
8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, X, X, X, X, 2, 10, 5, 2, 5, 3, 3, 5,
|
||||
7, X, X, X, X, X, X, X, 7, 9, 5, 7, 8, 9, 3, 11, 2, X, X, X, X, X, X, X,
|
||||
9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, X, X, X, X, 2, 3, 11, 0, 1, 8, 1, 7,
|
||||
8, 1, 5, 7, X, X, X, X, 11, 2, 1, 11, 1, 7, 7, 1, 5, X, X, X, X, X, X, X,
|
||||
9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, X, X, X, X, 5, 7, 0, 5, 0, 9, 7, 11,
|
||||
0, 1, 0, 10, 11, 10, 0, X, 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, X,
|
||||
11, 10, 5, 7, 11, 5, X, X, X, X, X, X, X, X, X, X, 10, 6, 5, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 0, 8, 3, 5, 10, 6, X, X, X, X, X, X, X, X, X, X,
|
||||
9, 0, 1, 5, 10, 6, X, X, X, X, X, X, X, X, X, X, 1, 8, 3, 1, 9, 8, 5, 10,
|
||||
6, X, X, X, X, X, X, X, 1, 6, 5, 2, 6, 1, X, X, X, X, X, X, X, X, X, X,
|
||||
1, 6, 5, 1, 2, 6, 3, 0, 8, X, X, X, X, X, X, X, 9, 6, 5, 9, 0, 6, 0, 2,
|
||||
6, X, X, X, X, X, X, X, 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, X, X, X, X,
|
||||
2, 3, 11, 10, 6, 5, X, X, X, X, X, X, X, X, X, X, 11, 0, 8, 11, 2, 0, 10, 6,
|
||||
5, X, X, X, X, X, X, X, 0, 1, 9, 2, 3, 11, 5, 10, 6, X, X, X, X, X, X, X,
|
||||
5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, X, X, X, X, 6, 3, 11, 6, 5, 3, 5, 1,
|
||||
3, X, X, X, X, X, X, X, 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, X, X, X, X,
|
||||
3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, X, X, X, X, 6, 5, 9, 6, 9, 11, 11, 9,
|
||||
8, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 8, X, X, X, X, X, X, X, X, X, X,
|
||||
4, 3, 0, 4, 7, 3, 6, 5, 10, X, X, X, X, X, X, X, 1, 9, 0, 5, 10, 6, 8, 4,
|
||||
7, X, X, X, X, X, X, X, 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, X, X, X, X,
|
||||
6, 1, 2, 6, 5, 1, 4, 7, 8, X, X, X, X, X, X, X, 1, 2, 5, 5, 2, 6, 3, 0,
|
||||
4, 3, 4, 7, X, X, X, X, 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, X, X, X, X,
|
||||
7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, X, 3, 11, 2, 7, 8, 4, 10, 6,
|
||||
5, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, X, X, X, X,
|
||||
0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, X, X, X, X, 9, 2, 1, 9, 11, 2, 9, 4,
|
||||
11, 7, 11, 4, 5, 10, 6, X, 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, X, X, X, X,
|
||||
5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, X, 0, 5, 9, 0, 6, 5, 0, 3,
|
||||
6, 11, 6, 3, 8, 4, 7, X, 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, X, X, X, X,
|
||||
10, 4, 9, 6, 4, 10, X, X, X, X, X, X, X, X, X, X, 4, 10, 6, 4, 9, 10, 0, 8,
|
||||
3, X, X, X, X, X, X, X, 10, 0, 1, 10, 6, 0, 6, 4, 0, X, X, X, X, X, X, X,
|
||||
8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, X, X, X, X, 1, 4, 9, 1, 2, 4, 2, 6,
|
||||
4, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, X, X, X, X,
|
||||
0, 2, 4, 4, 2, 6, X, X, X, X, X, X, X, X, X, X, 8, 3, 2, 8, 2, 4, 4, 2,
|
||||
6, X, X, X, X, X, X, X, 10, 4, 9, 10, 6, 4, 11, 2, 3, X, X, X, X, X, X, X,
|
||||
0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, X, X, X, X, 3, 11, 2, 0, 1, 6, 0, 6,
|
||||
4, 6, 1, 10, X, X, X, X, 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, X,
|
||||
9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, X, X, X, X, 8, 11, 1, 8, 1, 0, 11, 6,
|
||||
1, 9, 1, 4, 6, 4, 1, X, 3, 11, 6, 3, 6, 0, 0, 6, 4, X, X, X, X, X, X, X,
|
||||
6, 4, 8, 11, 6, 8, X, X, X, X, X, X, X, X, X, X, 7, 10, 6, 7, 8, 10, 8, 9,
|
||||
10, X, X, X, X, X, X, X, 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, X, X, X, X,
|
||||
10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, X, X, X, X, 10, 6, 7, 10, 7, 1, 1, 7,
|
||||
3, X, X, X, X, X, X, X, 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, X, X, X, X,
|
||||
2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, X, 7, 8, 0, 7, 0, 6, 6, 0,
|
||||
2, X, X, X, X, X, X, X, 7, 3, 2, 6, 7, 2, X, X, X, X, X, X, X, X, X, X,
|
||||
2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, X, X, X, X, 2, 0, 7, 2, 7, 11, 0, 9,
|
||||
7, 6, 7, 10, 9, 10, 7, X, 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, X,
|
||||
11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, X, X, X, X, 8, 9, 6, 8, 6, 7, 9, 1,
|
||||
6, 11, 6, 3, 1, 3, 6, X, 0, 9, 1, 11, 6, 7, X, X, X, X, X, X, X, X, X, X,
|
||||
7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, X, X, X, X, 7, 11, 6, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 7, 6, 11, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
3, 0, 8, 11, 7, 6, X, X, X, X, X, X, X, X, X, X, 0, 1, 9, 11, 7, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, 8, 1, 9, 8, 3, 1, 11, 7, 6, X, X, X, X, X, X, X,
|
||||
10, 1, 2, 6, 11, 7, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 8, 6, 11,
|
||||
7, X, X, X, X, X, X, X, 2, 9, 0, 2, 10, 9, 6, 11, 7, X, X, X, X, X, X, X,
|
||||
6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, X, X, X, X, 7, 2, 3, 6, 2, 7, X, X,
|
||||
X, X, X, X, X, X, X, X, 7, 0, 8, 7, 6, 0, 6, 2, 0, X, X, X, X, X, X, X,
|
||||
2, 7, 6, 2, 3, 7, 0, 1, 9, X, X, X, X, X, X, X, 1, 6, 2, 1, 8, 6, 1, 9,
|
||||
8, 8, 7, 6, X, X, X, X, 10, 7, 6, 10, 1, 7, 1, 3, 7, X, X, X, X, X, X, X,
|
||||
10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, X, X, X, X, 0, 3, 7, 0, 7, 10, 0, 10,
|
||||
9, 6, 10, 7, X, X, X, X, 7, 6, 10, 7, 10, 8, 8, 10, 9, X, X, X, X, X, X, X,
|
||||
6, 8, 4, 11, 8, 6, X, X, X, X, X, X, X, X, X, X, 3, 6, 11, 3, 0, 6, 0, 4,
|
||||
6, X, X, X, X, X, X, X, 8, 6, 11, 8, 4, 6, 9, 0, 1, X, X, X, X, X, X, X,
|
||||
9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, X, X, X, X, 6, 8, 4, 6, 11, 8, 2, 10,
|
||||
1, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, X, X, X, X,
|
||||
4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, X, X, X, X, 10, 9, 3, 10, 3, 2, 9, 4,
|
||||
3, 11, 3, 6, 4, 6, 3, X, 8, 2, 3, 8, 4, 2, 4, 6, 2, X, X, X, X, X, X, X,
|
||||
0, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 4, 2, 4,
|
||||
6, 4, 3, 8, X, X, X, X, 1, 9, 4, 1, 4, 2, 2, 4, 6, X, X, X, X, X, X, X,
|
||||
8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, X, X, X, X, 10, 1, 0, 10, 0, 6, 6, 0,
|
||||
4, X, X, X, X, X, X, X, 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, X,
|
||||
10, 9, 4, 6, 10, 4, X, X, X, X, X, X, X, X, X, X, 4, 9, 5, 7, 6, 11, X, X,
|
||||
X, X, X, X, X, X, X, X, 0, 8, 3, 4, 9, 5, 11, 7, 6, X, X, X, X, X, X, X,
|
||||
5, 0, 1, 5, 4, 0, 7, 6, 11, X, X, X, X, X, X, X, 11, 7, 6, 8, 3, 4, 3, 5,
|
||||
4, 3, 1, 5, X, X, X, X, 9, 5, 4, 10, 1, 2, 7, 6, 11, X, X, X, X, X, X, X,
|
||||
6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, X, X, X, X, 7, 6, 11, 5, 4, 10, 4, 2,
|
||||
10, 4, 0, 2, X, X, X, X, 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, X,
|
||||
7, 2, 3, 7, 6, 2, 5, 4, 9, X, X, X, X, X, X, X, 9, 5, 4, 0, 8, 6, 0, 6,
|
||||
2, 6, 8, 7, X, X, X, X, 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, X, X, X, X,
|
||||
6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, X, 9, 5, 4, 10, 1, 6, 1, 7,
|
||||
6, 1, 3, 7, X, X, X, X, 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, X,
|
||||
4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, X, 7, 6, 10, 7, 10, 8, 5, 4,
|
||||
10, 4, 8, 10, X, X, X, X, 6, 9, 5, 6, 11, 9, 11, 8, 9, X, X, X, X, X, X, X,
|
||||
3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, X, X, X, X, 0, 11, 8, 0, 5, 11, 0, 1,
|
||||
5, 5, 6, 11, X, X, X, X, 6, 11, 3, 6, 3, 5, 5, 3, 1, X, X, X, X, X, X, X,
|
||||
1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, X, X, X, X, 0, 11, 3, 0, 6, 11, 0, 9,
|
||||
6, 5, 6, 9, 1, 2, 10, X, 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, X,
|
||||
6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, X, X, X, X, 5, 8, 9, 5, 2, 8, 5, 6,
|
||||
2, 3, 8, 2, X, X, X, X, 9, 5, 6, 9, 6, 0, 0, 6, 2, X, X, X, X, X, X, X,
|
||||
1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, X, 1, 5, 6, 2, 1, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, X,
|
||||
10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, X, X, X, X, 0, 3, 8, 5, 6, 10, X, X,
|
||||
X, X, X, X, X, X, X, X, 10, 5, 6, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
11, 5, 10, 7, 5, 11, X, X, X, X, X, X, X, X, X, X, 11, 5, 10, 11, 7, 5, 8, 3,
|
||||
0, X, X, X, X, X, X, X, 5, 11, 7, 5, 10, 11, 1, 9, 0, X, X, X, X, X, X, X,
|
||||
10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, X, X, X, X, 11, 1, 2, 11, 7, 1, 7, 5,
|
||||
1, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, X, X, X, X,
|
||||
9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, X, X, X, X, 7, 5, 2, 7, 2, 11, 5, 9,
|
||||
2, 3, 2, 8, 9, 8, 2, X, 2, 5, 10, 2, 3, 5, 3, 7, 5, X, X, X, X, X, X, X,
|
||||
8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, X, X, X, X, 9, 0, 1, 5, 10, 3, 5, 3,
|
||||
7, 3, 10, 2, X, X, X, X, 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, X,
|
||||
1, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, X, X, X, 0, 8, 7, 0, 7, 1, 1, 7,
|
||||
5, X, X, X, X, X, X, X, 9, 0, 3, 9, 3, 5, 5, 3, 7, X, X, X, X, X, X, X,
|
||||
9, 8, 7, 5, 9, 7, X, X, X, X, X, X, X, X, X, X, 5, 8, 4, 5, 10, 8, 10, 11,
|
||||
8, X, X, X, X, X, X, X, 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, X, X, X, X,
|
||||
0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, X, X, X, X, 10, 11, 4, 10, 4, 5, 11, 3,
|
||||
4, 9, 4, 1, 3, 1, 4, X, 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, X, X, X, X,
|
||||
0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, X, 0, 2, 5, 0, 5, 9, 2, 11,
|
||||
5, 4, 5, 8, 11, 8, 5, X, 9, 4, 5, 2, 11, 3, X, X, X, X, X, X, X, X, X, X,
|
||||
2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, X, X, X, X, 5, 10, 2, 5, 2, 4, 4, 2,
|
||||
0, X, X, X, X, X, X, X, 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, X,
|
||||
5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, X, X, X, X, 8, 4, 5, 8, 5, 3, 3, 5,
|
||||
1, X, X, X, X, X, X, X, 0, 4, 5, 1, 0, 5, X, X, X, X, X, X, X, X, X, X,
|
||||
8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, X, X, X, X, 9, 4, 5, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 4, 11, 7, 4, 9, 11, 9, 10, 11, X, X, X, X, X, X, X,
|
||||
0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, X, X, X, X, 1, 10, 11, 1, 11, 4, 1, 4,
|
||||
0, 7, 4, 11, X, X, X, X, 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, X,
|
||||
4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, X, X, X, X, 9, 7, 4, 9, 11, 7, 9, 1,
|
||||
11, 2, 11, 1, 0, 8, 3, X, 11, 7, 4, 11, 4, 2, 2, 4, 0, X, X, X, X, X, X, X,
|
||||
11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, X, X, X, X, 2, 9, 10, 2, 7, 9, 2, 3,
|
||||
7, 7, 4, 9, X, X, X, X, 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, X,
|
||||
3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, X, 1, 10, 2, 8, 7, 4, X, X,
|
||||
X, X, X, X, X, X, X, X, 4, 9, 1, 4, 1, 7, 7, 1, 3, X, X, X, X, X, X, X,
|
||||
4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, X, X, X, X, 4, 0, 3, 7, 4, 3, X, X,
|
||||
X, X, X, X, X, X, X, X, 4, 8, 7, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
9, 10, 8, 10, 11, 8, X, X, X, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 11, 9,
|
||||
10, X, X, X, X, X, X, X, 0, 1, 10, 0, 10, 8, 8, 10, 11, X, X, X, X, X, X, X,
|
||||
3, 1, 10, 11, 3, 10, X, X, X, X, X, X, X, X, X, X, 1, 2, 11, 1, 11, 9, 9, 11,
|
||||
8, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, X, X, X, X,
|
||||
0, 2, 11, 8, 0, 11, X, X, X, X, X, X, X, X, X, X, 3, 2, 11, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 10, 8, 9, X, X, X, X, X, X, X,
|
||||
9, 10, 2, 0, 9, 2, X, X, X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 0, 1,
|
||||
8, 1, 10, 8, X, X, X, X, 1, 10, 2, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
1, 3, 8, 9, 1, 8, X, X, X, X, X, X, X, X, X, X, 0, 9, 1, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 0, 3, 8, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X
|
||||
#undef X
|
||||
});
|
||||
|
||||
// size: nCasesLT3d * nTriTableLT3dElemSize
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> triTableLT3d = vtkm::cont::make_ArrayHandle<vtkm::Id>({
|
||||
#define X -1
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 3, 12, 18, 3, 16,
|
||||
18, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, 0, 1, 17, 0, 9, 17, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17,
|
||||
14, 9, 17, 3, 12, 18, 3, 16, 18, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 1, 10, 12, 2, 10, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0,
|
||||
14, 18, 3, 18, 10, 3, 2, 10, 3, 16, 18, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 12, 2, 10, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18,
|
||||
17, 14, 9, 17, 3, 18, 10, 3, 2, 10, 3, 16, 18, 8, 14, 18, 8, 16, 18, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 3, 2, 15, 3, 11, 15, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18,
|
||||
0, 14, 18, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 8, 14, 18, 8, 16, 18, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 3, 2, 15, 3, 11, 15, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12,
|
||||
18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 8,
|
||||
14, 18, 8, 16, 18, X, X, X, X, X, X, X, 12, 1, 10, 3, 12, 10, 3, 15, 10, 3, 11, 15,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 18, 15, 10, 16, 18, 15, 16, 11, 15, 8, 14, 18, 8, 16,
|
||||
18, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 3,
|
||||
12, 10, 3, 15, 10, 3, 11, 15, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 18, 15, 10, 16, 18, 15, 16, 11, 15, 8, 14, 18,
|
||||
8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 8, 4, 13, 8, 7, 13, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 18, 0, 14, 18, 3, 12, 18, 3, 16, 18, 14, 18, 13, 14, 4, 13, 16,
|
||||
18, 13, 16, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17,
|
||||
8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 3, 12, 18, 3, 16,
|
||||
18, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 12, 1, 10, 12,
|
||||
2, 10, 8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 3, 18, 10, 3, 2, 10,
|
||||
3, 16, 18, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 0, 12,
|
||||
10, 0, 17, 10, 0, 9, 17, 12, 2, 10, 8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 3, 18, 10, 3,
|
||||
2, 10, 3, 16, 18, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X,
|
||||
3, 2, 15, 3, 11, 15, 8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 12, 18, 15, 12, 2,
|
||||
15, 16, 18, 15, 16, 11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X, X, X, X,
|
||||
X, X, 0, 1, 17, 0, 9, 17, 3, 2, 15, 3, 11, 15, 8, 4, 13, 8, 7, 13, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17,
|
||||
14, 9, 17, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13,
|
||||
16, 7, 13, X, 12, 1, 10, 3, 12, 10, 3, 15, 10, 3, 11, 15, 8, 4, 13, 8, 7, 13, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0,
|
||||
14, 18, 18, 15, 10, 16, 18, 15, 16, 11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X,
|
||||
X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 3, 12, 10, 3, 15, 10, 3, 11, 15,
|
||||
8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18,
|
||||
17, 14, 9, 17, 18, 15, 10, 16, 18, 15, 16, 11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7,
|
||||
13, X, X, X, X, X, X, X, 14, 9, 5, 14, 4, 5, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18,
|
||||
0, 18, 5, 0, 9, 5, 3, 12, 18, 3, 16, 18, 8, 18, 5, 8, 4, 5, 8, 16, 18, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 14, 4, 5, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12,
|
||||
18, 17, 12, 1, 17, 18, 17, 5, 3, 12, 18, 3, 16, 18, 8, 18, 5, 8, 4, 5, 8, 16, 18, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 12, 2, 10, 14, 4, 5,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 3, 18, 10, 3, 2, 10, 3, 16, 18, 8, 18,
|
||||
5, 8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0,
|
||||
17, 5, 12, 2, 10, 14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, 18, 17, 10, 18, 17, 5, 3, 18, 10, 3, 2, 10, 3, 16, 18, 8, 18, 5, 8, 4, 5,
|
||||
8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 14, 9, 5, 3, 2, 15, 3, 11,
|
||||
15, 14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16,
|
||||
11, 15, 8, 18, 5, 8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5,
|
||||
0, 17, 5, 3, 2, 15, 3, 11, 15, 14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 12, 18, 15, 12, 2, 15, 16, 18,
|
||||
15, 16, 11, 15, 8, 18, 5, 8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, 12, 1, 10, 14,
|
||||
9, 5, 3, 12, 10, 3, 15, 10, 3, 11, 15, 14, 4, 5, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 18, 15, 10,
|
||||
16, 18, 15, 16, 11, 15, 8, 18, 5, 8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, 0, 12,
|
||||
10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 3, 12, 10, 3, 15, 10, 3, 11, 15, 14, 4, 5, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17, 5, 18, 15, 10, 16, 18, 15, 16,
|
||||
11, 15, 8, 18, 5, 8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
14, 9, 5, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 3, 12,
|
||||
18, 3, 16, 18, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5,
|
||||
3, 12, 18, 3, 16, 18, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 1, 10, 14, 9, 5, 12, 2, 10, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0,
|
||||
18, 5, 0, 9, 5, 3, 18, 10, 3, 2, 10, 3, 16, 18, 18, 13, 5, 16, 18, 13, 16, 7, 13, X,
|
||||
X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 12, 2, 10, 8, 14, 5,
|
||||
8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17,
|
||||
5, 3, 18, 10, 3, 2, 10, 3, 16, 18, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 14, 9, 5, 3, 2, 15, 3, 11, 15, 8, 14, 5, 8, 13, 5, 8,
|
||||
7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18,
|
||||
0, 18, 5, 0, 9, 5, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 18, 13, 5, 16, 18, 13,
|
||||
16, 7, 13, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 3, 2, 15, 3, 11,
|
||||
15, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, 12,
|
||||
18, 17, 12, 1, 17, 18, 17, 5, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 18, 13, 5, 16,
|
||||
18, 13, 16, 7, 13, X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 3, 12, 10, 3, 15, 10,
|
||||
3, 11, 15, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 18, 15, 10, 16, 18, 15, 16, 11, 15, 18, 13,
|
||||
5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0,
|
||||
17, 5, 3, 12, 10, 3, 15, 10, 3, 11, 15, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X,
|
||||
X, X, X, 18, 17, 10, 18, 17, 5, 18, 15, 10, 16, 18, 15, 16, 11, 15, 18, 13, 5, 16, 18, 13,
|
||||
16, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17, 5, 18, 15,
|
||||
10, 18, 15, 6, 18, 13, 5, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 3, 12, 10, 3, 15, 10, 3,
|
||||
16, 6, 3, 15, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, 0, 18, 10, 0, 1, 10,
|
||||
0, 18, 5, 0, 9, 5, 18, 15, 10, 18, 15, 6, 18, 13, 5, 18, 13, 6, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15,
|
||||
6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, 12, 18, 17, 12,
|
||||
1, 17, 18, 17, 5, 12, 18, 15, 12, 2, 15, 18, 15, 6, 18, 13, 5, 18, 13, 6, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 3, 2, 15, 3, 16, 6,
|
||||
3, 15, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, 0, 12,
|
||||
18, 0, 18, 5, 0, 9, 5, 12, 18, 15, 12, 2, 15, 18, 15, 6, 18, 13, 5, 18, 13, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, 14, 9, 5, 3, 2, 15, 3, 16, 6, 3, 15, 6, 8,
|
||||
14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
18, 17, 10, 18, 17, 5, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 18, 13, 5, 18, 13, 6,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17,
|
||||
5, 12, 2, 10, 16, 11, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X,
|
||||
X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3,
|
||||
11, 6, 18, 13, 5, 18, 13, 6, X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 12, 2, 10,
|
||||
16, 11, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 3, 12, 18, 3, 18, 6, 3, 11, 6, 18, 13,
|
||||
5, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0,
|
||||
17, 5, 16, 11, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 3, 12, 18, 3, 18, 6, 3, 11, 6,
|
||||
18, 13, 5, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 14, 9, 5, 16, 11,
|
||||
6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17, 5, 18, 15, 10, 18, 15, 6, 8, 18, 5, 8,
|
||||
4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10,
|
||||
0, 17, 10, 0, 14, 5, 0, 17, 5, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 14, 4, 5,
|
||||
16, 7, 6, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 18, 15,
|
||||
10, 18, 15, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 12,
|
||||
1, 10, 14, 9, 5, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 14, 4, 5, 16, 7, 6, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 12, 18, 15,
|
||||
12, 2, 15, 18, 15, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X,
|
||||
X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 3, 2, 15, 3, 16, 6, 3, 15, 6, 14, 4, 5, 16, 7,
|
||||
6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 12,
|
||||
18, 15, 12, 2, 15, 18, 15, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X,
|
||||
X, X, X, 14, 9, 5, 3, 2, 15, 3, 16, 6, 3, 15, 6, 14, 4, 5, 16, 7, 6, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17, 5, 3, 18,
|
||||
10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X,
|
||||
X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 12, 2, 10, 16, 11, 6, 14,
|
||||
4, 5, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10,
|
||||
0, 18, 5, 0, 9, 5, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 8, 18, 5, 8, 4, 5,
|
||||
8, 18, 6, 8, 7, 6, X, 12, 1, 10, 14, 9, 5, 12, 2, 10, 16, 11, 6, 14, 4, 5, 16, 7,
|
||||
6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12,
|
||||
1, 17, 18, 17, 5, 3, 12, 18, 3, 18, 6, 3, 11, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8,
|
||||
7, 6, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 16, 11, 6, 14, 4, 5,
|
||||
16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12,
|
||||
18, 0, 18, 5, 0, 9, 5, 3, 12, 18, 3, 18, 6, 3, 11, 6, 8, 18, 5, 8, 4, 5, 8, 18,
|
||||
6, 8, 7, 6, X, X, X, X, X, X, X, 14, 9, 5, 16, 11, 6, 14, 4, 5, 16, 7, 6, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
18, 17, 10, 14, 18, 17, 14, 9, 17, 18, 15, 10, 18, 15, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 3, 12,
|
||||
10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X,
|
||||
X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 18, 15, 10, 18, 15, 6, 14, 18, 13, 14, 4, 13, 18,
|
||||
13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 1, 10, 3, 12, 10, 3, 15, 10,
|
||||
3, 16, 6, 3, 15, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 12, 18, 15, 12, 2, 15, 18, 15,
|
||||
6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 3,
|
||||
2, 15, 3, 16, 6, 3, 15, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 12, 18, 15, 12, 2, 15, 18, 15, 6, 14, 18, 13,
|
||||
14, 4, 13, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 3, 2, 15, 3, 16,
|
||||
6, 3, 15, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 3, 18, 10, 3, 2, 10, 3,
|
||||
18, 6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X, X, X, X, X, 0, 12, 10,
|
||||
0, 17, 10, 0, 9, 17, 12, 2, 10, 16, 11, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 3, 18, 10, 3, 2,
|
||||
10, 3, 18, 6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X, X, X, X, X, 12,
|
||||
1, 10, 12, 2, 10, 16, 11, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17,
|
||||
3, 12, 18, 3, 18, 6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X, X, X, X,
|
||||
X, 0, 1, 17, 0, 9, 17, 16, 11, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 3, 12, 18, 3,
|
||||
18, 6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, 16, 11, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18, 17, 14, 9,
|
||||
17, 18, 15, 10, 18, 15, 6, 8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3,
|
||||
15, 6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10,
|
||||
0, 14, 18, 18, 15, 10, 18, 15, 6, 8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, 12, 1, 10, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 16, 7,
|
||||
6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12,
|
||||
1, 17, 14, 18, 17, 14, 9, 17, 12, 18, 15, 12, 2, 15, 18, 15, 6, 8, 14, 18, 8, 18, 6, 8,
|
||||
7, 6, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 3, 2, 15, 3, 16, 6, 3, 15, 6,
|
||||
16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12,
|
||||
18, 0, 14, 18, 12, 18, 15, 12, 2, 15, 18, 15, 6, 8, 14, 18, 8, 18, 6, 8, 7, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, 3, 2, 15, 3, 16, 6, 3, 15, 6, 16, 7, 6, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
18, 17, 10, 14, 18, 17, 14, 9, 17, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 8, 14, 18,
|
||||
8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 12, 2,
|
||||
10, 16, 11, 6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 8,
|
||||
14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 12, 1, 10, 12, 2, 10, 16, 11, 6,
|
||||
16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 3, 12, 18, 3, 18, 6, 3, 11,
|
||||
6, 8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 16,
|
||||
11, 6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 3, 12, 18, 3, 18, 6, 3, 11, 6, 8, 14, 18,
|
||||
8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 16, 11, 6, 16, 7,
|
||||
6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 16, 11, 6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18,
|
||||
0, 14, 18, 3, 12, 18, 3, 18, 6, 3, 11, 6, 8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 16, 11, 6, 16, 7, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12,
|
||||
18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 3, 12, 18, 3, 18, 6, 3, 11, 6, 8, 14, 18, 8,
|
||||
18, 6, 8, 7, 6, X, X, X, X, X, X, X, 12, 1, 10, 12, 2, 10, 16, 11, 6, 16, 7, 6,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 8, 14,
|
||||
18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 12,
|
||||
2, 10, 16, 11, 6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6,
|
||||
8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 3, 2, 15, 3, 16, 6, 3, 15,
|
||||
6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 18, 0, 14, 18, 12, 18, 15, 12, 2, 15, 18, 15, 6, 8, 14, 18, 8,
|
||||
18, 6, 8, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17,
|
||||
3, 2, 15, 3, 16, 6, 3, 15, 6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 12, 18, 15, 12, 2,
|
||||
15, 18, 15, 6, 8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 12, 1, 10, 3,
|
||||
12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 16, 7, 6, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 18, 15, 10, 18, 15, 6,
|
||||
8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12,
|
||||
10, 0, 17, 10, 0, 9, 17, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 16, 7, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 18, 15, 10, 18,
|
||||
15, 6, 8, 14, 18, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
16, 11, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 3, 12, 18, 3, 18,
|
||||
6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, 0, 1, 17, 0, 9, 17, 16, 11, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17,
|
||||
14, 9, 17, 3, 12, 18, 3, 18, 6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X,
|
||||
X, X, X, X, 12, 1, 10, 12, 2, 10, 16, 11, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0,
|
||||
14, 18, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X,
|
||||
X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 12, 2, 10, 16, 11, 6, 8, 4, 13,
|
||||
8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18,
|
||||
17, 14, 9, 17, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 14, 18, 13, 14, 4, 13, 18, 13,
|
||||
6, X, X, X, X, X, X, X, 3, 2, 15, 3, 16, 6, 3, 15, 6, 8, 4, 13, 8, 16, 6, 8,
|
||||
13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18,
|
||||
0, 14, 18, 12, 18, 15, 12, 2, 15, 18, 15, 6, 14, 18, 13, 14, 4, 13, 18, 13, 6, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 3, 2, 15, 3, 16, 6, 3, 15,
|
||||
6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 12,
|
||||
18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 12, 18, 15, 12, 2, 15, 18, 15, 6, 14, 18, 13, 14,
|
||||
4, 13, 18, 13, 6, X, X, X, X, X, X, X, 12, 1, 10, 3, 12, 10, 3, 15, 10, 3, 16, 6,
|
||||
3, 15, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 18, 15, 10, 18, 15, 6, 14, 18, 13, 14, 4, 13, 18, 13,
|
||||
6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 3,
|
||||
12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 8, 4, 13, 8, 16, 6, 8, 13, 6, X, X, X, X,
|
||||
X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 18, 15, 10, 18, 15, 6, 14, 18, 13, 14, 4, 13,
|
||||
18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 14, 9, 5, 16, 11, 6, 14, 4,
|
||||
5, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 3, 12, 18, 3, 18, 6, 3, 11, 6, 8,
|
||||
18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5,
|
||||
0, 17, 5, 16, 11, 6, 14, 4, 5, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 3, 12, 18, 3, 18, 6, 3, 11,
|
||||
6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X, 12, 1, 10, 14,
|
||||
9, 5, 12, 2, 10, 16, 11, 6, 14, 4, 5, 16, 7, 6, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 3, 18, 10,
|
||||
3, 2, 10, 3, 18, 6, 3, 11, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, 0, 12,
|
||||
10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 12, 2, 10, 16, 11, 6, 14, 4, 5, 16, 7, 6, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17, 5, 3, 18, 10, 3, 2, 10, 3,
|
||||
18, 6, 3, 11, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X, X, X,
|
||||
14, 9, 5, 3, 2, 15, 3, 16, 6, 3, 15, 6, 14, 4, 5, 16, 7, 6, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 12, 18,
|
||||
15, 12, 2, 15, 18, 15, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X,
|
||||
X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 3, 2, 15, 3, 16, 6, 3, 15, 6, 14, 4, 5, 16,
|
||||
7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5,
|
||||
12, 18, 15, 12, 2, 15, 18, 15, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X,
|
||||
X, X, X, X, 12, 1, 10, 14, 9, 5, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 14, 4,
|
||||
5, 16, 7, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0,
|
||||
18, 5, 0, 9, 5, 18, 15, 10, 18, 15, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X,
|
||||
X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 3, 12, 10, 3, 15, 10,
|
||||
3, 16, 6, 3, 15, 6, 14, 4, 5, 16, 7, 6, X, X, X, X, X, X, X, 18, 17, 10, 18, 17,
|
||||
5, 18, 15, 10, 18, 15, 6, 8, 18, 5, 8, 4, 5, 8, 18, 6, 8, 7, 6, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 14, 9, 5, 16, 11, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8,
|
||||
13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18,
|
||||
0, 18, 5, 0, 9, 5, 3, 12, 18, 3, 18, 6, 3, 11, 6, 18, 13, 5, 18, 13, 6, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 16, 11, 6, 8, 14,
|
||||
5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 12,
|
||||
18, 17, 12, 1, 17, 18, 17, 5, 3, 12, 18, 3, 18, 6, 3, 11, 6, 18, 13, 5, 18, 13, 6, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 12, 2, 10, 16, 11, 6,
|
||||
8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11,
|
||||
6, 18, 13, 5, 18, 13, 6, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0,
|
||||
17, 5, 12, 2, 10, 16, 11, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X,
|
||||
X, X, X, 18, 17, 10, 18, 17, 5, 3, 18, 10, 3, 2, 10, 3, 18, 6, 3, 11, 6, 18, 13, 5,
|
||||
18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 14, 9, 5, 3, 2, 15, 3, 16,
|
||||
6, 3, 15, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 12, 18, 15, 12, 2, 15, 18, 15, 6, 18,
|
||||
13, 5, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5,
|
||||
0, 17, 5, 3, 2, 15, 3, 16, 6, 3, 15, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8, 13, 6,
|
||||
X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 12, 18, 15, 12, 2, 15, 18, 15,
|
||||
6, 18, 13, 5, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 1, 10, 14,
|
||||
9, 5, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 8, 14, 5, 8, 13, 5, 8, 16, 6, 8,
|
||||
13, 6, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 18, 15, 10,
|
||||
18, 15, 6, 18, 13, 5, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12,
|
||||
10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 3, 12, 10, 3, 15, 10, 3, 16, 6, 3, 15, 6, 8, 14,
|
||||
5, 8, 13, 5, 8, 16, 6, 8, 13, 6, X, 18, 17, 10, 18, 17, 5, 18, 15, 10, 18, 15, 6, 18,
|
||||
13, 5, 18, 13, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
18, 17, 10, 18, 17, 5, 18, 15, 10, 16, 18, 15, 16, 11, 15, 18, 13, 5, 16, 18, 13, 16, 7, 13,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17,
|
||||
5, 3, 12, 10, 3, 15, 10, 3, 11, 15, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X,
|
||||
X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 18, 15, 10, 16, 18, 15, 16, 11, 15, 18,
|
||||
13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 3, 12, 10,
|
||||
3, 15, 10, 3, 11, 15, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11,
|
||||
15, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0,
|
||||
17, 5, 3, 2, 15, 3, 11, 15, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 12, 18, 15, 12, 2, 15, 16, 18, 15,
|
||||
16, 11, 15, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 14, 9, 5, 3, 2,
|
||||
15, 3, 11, 15, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17, 5, 3, 18, 10, 3, 2, 10, 3, 16, 18, 18,
|
||||
13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10,
|
||||
0, 17, 10, 0, 14, 5, 0, 17, 5, 12, 2, 10, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 3, 18,
|
||||
10, 3, 2, 10, 3, 16, 18, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 12,
|
||||
1, 10, 14, 9, 5, 12, 2, 10, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 3, 12, 18,
|
||||
3, 16, 18, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 3,
|
||||
12, 18, 3, 16, 18, 18, 13, 5, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, 14, 9, 5, 8, 14, 5, 8, 13, 5, 8, 7, 13, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 18, 17, 5, 18, 15,
|
||||
10, 16, 18, 15, 16, 11, 15, 8, 18, 5, 8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17, 5, 3, 12, 10, 3, 15, 10, 3,
|
||||
11, 15, 14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10,
|
||||
0, 18, 5, 0, 9, 5, 18, 15, 10, 16, 18, 15, 16, 11, 15, 8, 18, 5, 8, 4, 5, 8, 16, 18,
|
||||
X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 3, 12, 10, 3, 15, 10, 3, 11, 15, 14, 4,
|
||||
5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12,
|
||||
1, 17, 18, 17, 5, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 8, 18, 5, 8, 4, 5, 8,
|
||||
16, 18, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0, 17, 5, 3, 2, 15, 3, 11, 15,
|
||||
14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12,
|
||||
18, 0, 18, 5, 0, 9, 5, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 8, 18, 5, 8, 4,
|
||||
5, 8, 16, 18, X, X, X, X, X, X, X, 14, 9, 5, 3, 2, 15, 3, 11, 15, 14, 4, 5, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
18, 17, 10, 18, 17, 5, 3, 18, 10, 3, 2, 10, 3, 16, 18, 8, 18, 5, 8, 4, 5, 8, 16, 18,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 14, 5, 0, 17,
|
||||
5, 12, 2, 10, 14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, 0, 18, 10, 0, 1, 10, 0, 18, 5, 0, 9, 5, 3, 18, 10, 3, 2, 10, 3, 16, 18, 8,
|
||||
18, 5, 8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, 12, 1, 10, 14, 9, 5, 12, 2, 10,
|
||||
14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 18, 17, 12, 1, 17, 18, 17, 5, 3, 12, 18, 3, 16, 18, 8, 18, 5, 8, 4,
|
||||
5, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 1, 17, 0, 14, 5, 0,
|
||||
17, 5, 14, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, 0, 12, 18, 0, 18, 5, 0, 9, 5, 3, 12, 18, 3, 16, 18, 8, 18, 5,
|
||||
8, 4, 5, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 14, 9, 5, 14, 4,
|
||||
5, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 18, 15, 10, 16, 18, 15, 16,
|
||||
11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 0, 12, 10,
|
||||
0, 17, 10, 0, 9, 17, 3, 12, 10, 3, 15, 10, 3, 11, 15, 8, 4, 13, 8, 7, 13, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 18, 15, 10, 16, 18,
|
||||
15, 16, 11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X, X, X, X, X, X, 12,
|
||||
1, 10, 3, 12, 10, 3, 15, 10, 3, 11, 15, 8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17,
|
||||
12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13,
|
||||
X, 0, 1, 17, 0, 9, 17, 3, 2, 15, 3, 11, 15, 8, 4, 13, 8, 7, 13, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 12, 18, 15, 12,
|
||||
2, 15, 16, 18, 15, 16, 11, 15, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X, X, X,
|
||||
X, X, X, 3, 2, 15, 3, 11, 15, 8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18, 17, 14, 9,
|
||||
17, 3, 18, 10, 3, 2, 10, 3, 16, 18, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X,
|
||||
X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 12, 2, 10, 8, 4, 13, 8, 7, 13, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10,
|
||||
0, 14, 18, 3, 18, 10, 3, 2, 10, 3, 16, 18, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13,
|
||||
X, X, X, X, X, X, X, 12, 1, 10, 12, 2, 10, 8, 4, 13, 8, 7, 13, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12,
|
||||
1, 17, 14, 18, 17, 14, 9, 17, 3, 12, 18, 3, 16, 18, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16,
|
||||
7, 13, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 8, 4, 13, 8, 7, 13, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12,
|
||||
18, 0, 14, 18, 3, 12, 18, 3, 16, 18, 14, 18, 13, 14, 4, 13, 16, 18, 13, 16, 7, 13, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, 8, 4, 13, 8, 7, 13, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
18, 17, 10, 14, 18, 17, 14, 9, 17, 18, 15, 10, 16, 18, 15, 16, 11, 15, 8, 14, 18, 8, 16, 18,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10, 0, 17, 10, 0, 9, 17, 3, 12,
|
||||
10, 3, 15, 10, 3, 11, 15, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 18, 15, 10, 16, 18, 15, 16, 11, 15, 8, 14, 18, 8,
|
||||
16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 12, 1, 10, 3, 12, 10, 3, 15, 10,
|
||||
3, 11, 15, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17, 12, 18, 15, 12, 2, 15, 16, 18,
|
||||
15, 16, 11, 15, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, 0, 1, 17, 0, 9, 17, 3,
|
||||
2, 15, 3, 11, 15, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 12, 18, 15, 12, 2, 15, 16, 18, 15, 16, 11, 15,
|
||||
8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 3, 2, 15, 3, 11,
|
||||
15, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, 18, 17, 10, 14, 18, 17, 14, 9, 17, 3, 18, 10, 3, 2, 10, 3,
|
||||
16, 18, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 10,
|
||||
0, 17, 10, 0, 9, 17, 12, 2, 10, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, 0, 18, 10, 0, 1, 10, 0, 14, 18, 3, 18, 10, 3, 2,
|
||||
10, 3, 16, 18, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, 12,
|
||||
1, 10, 12, 2, 10, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, 12, 18, 17, 12, 1, 17, 14, 18, 17, 14, 9, 17,
|
||||
3, 12, 18, 3, 16, 18, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, 0, 1, 17, 0, 9, 17, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 12, 18, 0, 14, 18, 3, 12, 18, 3,
|
||||
16, 18, 8, 14, 18, 8, 16, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X
|
||||
#undef X
|
||||
});
|
||||
|
||||
const vtkm::Id nLabelEdgeTableMC3dElemSize = 9; // (at most 4 label edges)
|
||||
const vtkm::Id nLabelEdgeTableLT3dElemSize = 13; // (at most 6 tetrahedra)
|
||||
|
||||
// size: nCasesMC3d * nLabelEdgeTableMC3dElemSize
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> labelEdgeTableMC3d =
|
||||
vtkm::cont::make_ArrayHandle<vtkm::Id>({
|
||||
#define X -1
|
||||
X, X, X, X, X, X, X, X, X, 1, 0, X, X, X, X, X, X, X, 1, 0, X, X, X, X, X, X, X, 2, 1, X, X, X,
|
||||
X, X, X, X, 1, 1, X, X, X, X, X, X, X, 1, 0, 1, 1, X, X, X, X, X, 2, 0, X, X, X, X, X, X, X, 3,
|
||||
2, X, X, X, X, X, X, X, 1, 2, X, X, X, X, X, X, X, 2, 0, X, X, X, X, X, X, X, 1, 0, 1, 2, X, X,
|
||||
X, X, X, 3, 1, X, X, X, X, X, X, X, 2, 1, X, X, X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 3, 0,
|
||||
X, X, X, X, X, X, X, 2, 8, X, X, X, X, X, X, X, 1, 4, X, X, X, X, X, X, X, 2, 0, X, X, X, X, X,
|
||||
X, X, 1, 0, 1, 4, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 1, 1, 1, 4, X, X, X, X, X, 2, 0, 1,
|
||||
1, X, X, X, X, X, 2, 0, 1, 4, X, X, X, X, X, 4, 2, X, X, X, X, X, X, X, 1, 4, 1, 2, X, X, X, X,
|
||||
X, 3, 0, X, X, X, X, X, X, X, 1, 0, 1, 4, 1, 2, X, X, X, 4, 1, X, X, X, X, X, X, X, 2, 1, 1, 4,
|
||||
X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 1, 4, 3, 0, X, X, X, X, X, 3, 4, X, X, X, X, X, X, X,
|
||||
1, 4, X, X, X, X, X, X, X, 1, 4, 1, 0, X, X, X, X, X, 2, 0, X, X, X, X, X, X, X, 3, 1, X, X, X,
|
||||
X, X, X, X, 1, 1, 1, 4, X, X, X, X, X, 1, 0, 1, 1, 1, 4, X, X, X, 3, 0, X, X, X, X, X, X, X, 4,
|
||||
2, X, X, X, X, X, X, X, 1, 4, 1, 2, X, X, X, X, X, 2, 0, 1, 4, X, X, X, X, X, 2, 0, 1, 2, X, X,
|
||||
X, X, X, 4, 1, X, X, X, X, X, X, X, 2, 1, 1, 4, X, X, X, X, X, 1, 4, 3, 0, X, X, X, X, X, 4, 0,
|
||||
X, X, X, X, X, X, X, 3, 4, X, X, X, X, X, X, X, 2, 5, X, X, X, X, X, X, X, 3, 0, X, X, X, X, X,
|
||||
X, X, 3, 0, X, X, X, X, X, X, X, 2, 1, X, X, X, X, X, X, X, 2, 5, 1, 1, X, X, X, X, X, 1, 1, 3,
|
||||
0, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 3, 2, X, X, X, X, X, X, X, 2, 5, 1, 2, X, X, X, X,
|
||||
X, 4, 0, X, X, X, X, X, X, X, 1, 2, 3, 0, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 2, 5, 2, 1,
|
||||
X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 2, 5, X, X, X, X, X, X, X,
|
||||
1, 5, X, X, X, X, X, X, X, 1, 0, 1, 5, X, X, X, X, X, 1, 0, 1, 5, X, X, X, X, X, 2, 1, 1, 5, X,
|
||||
X, X, X, X, 2, 1, X, X, X, X, X, X, X, 2, 1, 1, 0, X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 4,
|
||||
2, X, X, X, X, X, X, X, 1, 2, 1, 5, X, X, X, X, X, 2, 0, 1, 5, X, X, X, X, X, 1, 0, 1, 2, 1, 5,
|
||||
X, X, X, 1, 5, 3, 1, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 4, 0,
|
||||
X, X, X, X, X, X, X, 3, 5, X, X, X, X, X, X, X, 1, 5, 1, 4, X, X, X, X, X, 2, 0, 1, 5, X, X, X,
|
||||
X, X, 1, 0, 1, 5, 1, 4, X, X, X, 1, 5, 3, 1, X, X, X, X, X, 2, 1, 1, 4, X, X, X, X, X, 2, 1, 2,
|
||||
0, X, X, X, X, X, 1, 4, 3, 0, X, X, X, X, X, 5, 2, X, X, X, X, X, X, X, 1, 2, 1, 4, 1, 5, X, X,
|
||||
X, 1, 5, 3, 0, X, X, X, X, X, 1, 0, 1, 4, 1, 2, 1, 5, X, 4, 1, 1, 5, X, X, X, X, X, 1, 4, 3, 1,
|
||||
X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 4, 0, 1, 4, X, X, X, X, X, 4, 4, X, X, X, X, X, X, X,
|
||||
2, 4, X, X, X, X, X, X, X, 2, 4, 1, 0, X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 4, 1, X, X, X,
|
||||
X, X, X, X, 3, 1, X, X, X, X, X, X, X, 1, 0, 3, 1, X, X, X, X, X, 2, 0, X, X, X, X, X, X, X, 3,
|
||||
2, X, X, X, X, X, X, X, 2, 4, 1, 2, X, X, X, X, X, 2, 0, 2, 4, X, X, X, X, X, 1, 2, 3, 0, X, X,
|
||||
X, X, X, 5, 1, X, X, X, X, X, X, X, 4, 1, X, X, X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 3, 0,
|
||||
X, X, X, X, X, X, X, 2, 4, X, X, X, X, X, X, X, 3, 6, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X,
|
||||
X, X, 4, 0, X, X, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 4, 1, X, X, X, X, X, X, X, 5, 0, X,
|
||||
X, X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 2, 2, X, X, X, X, X, X, X, 1, 2, 3, 6, X, X, X, X,
|
||||
X, 5, 0, X, X, X, X, X, X, X, 4, 0, 1, 2, X, X, X, X, X, 4, 1, X, X, X, X, X, X, X, 5, 1, X, X,
|
||||
X, X, X, X, X, 1, 0, 1, 6, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 1, 6, X, X, X, X, X, X, X,
|
||||
1, 6, X, X, X, X, X, X, X, 1, 0, 1, 6, X, X, X, X, X, 1, 0, 1, 6, X, X, X, X, X, 2, 1, 1, 6, X,
|
||||
X, X, X, X, 1, 1, 1, 6, X, X, X, X, X, 1, 1, 1, 0, 1, 6, X, X, X, 2, 0, 1, 6, X, X, X, X, X, 1,
|
||||
6, 3, 2, X, X, X, X, X, 2, 2, X, X, X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 2, 2, 1, 0, X, X,
|
||||
X, X, X, 4, 1, X, X, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 4, 0,
|
||||
X, X, X, X, X, X, X, 3, 6, X, X, X, X, X, X, X, 2, 4, X, X, X, X, X, X, X, 3, 0, X, X, X, X, X,
|
||||
X, X, 2, 4, 1, 0, X, X, X, X, X, 4, 1, X, X, X, X, X, X, X, 2, 4, 1, 1, X, X, X, X, X, 1, 1, 3,
|
||||
0, X, X, X, X, X, 2, 4, 2, 0, X, X, X, X, X, 5, 2, X, X, X, X, X, X, X, 3, 2, X, X, X, X, X, X,
|
||||
X, 2, 0, X, X, X, X, X, X, X, 1, 0, 3, 2, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 4, 1, X, X,
|
||||
X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 2, 4, X, X, X, X, X, X, X,
|
||||
1, 4, 1, 6, X, X, X, X, X, 1, 0, 1, 4, 1, 6, X, X, X, 2, 0, 1, 6, X, X, X, X, X, 1, 6, 3, 1, X,
|
||||
X, X, X, X, 1, 4, 1, 1, 1, 6, X, X, X, 1, 6, 1, 1, 1, 0, 1, 4, X, 1, 6, 3, 0, X, X, X, X, X, 4,
|
||||
2, 1, 6, X, X, X, X, X, 2, 2, 1, 4, X, X, X, X, X, 1, 4, 3, 0, X, X, X, X, X, 2, 2, 2, 0, X, X,
|
||||
X, X, X, 5, 1, X, X, X, X, X, X, X, 1, 4, 3, 1, X, X, X, X, X, 4, 0, 1, 4, X, X, X, X, X, 5, 0,
|
||||
X, X, X, X, X, X, X, 4, 4, X, X, X, X, X, X, X, 3, 5, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X,
|
||||
X, X, 4, 0, X, X, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 1, 1, 3, 5, X, X, X, X, X, 4, 0, 1,
|
||||
1, X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 4, 2, X, X, X, X, X, X, X, 4, 2, X, X, X, X, X, X,
|
||||
X, 3, 0, X, X, X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 2, 1, X, X, X, X, X, X, X, 5, 1, X, X,
|
||||
X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 1, 0, 1, 5, X, X, X, X, X, 1, 5, X, X, X, X, X, X, X,
|
||||
2, 5, X, X, X, X, X, X, X, 2, 5, 1, 0, X, X, X, X, X, 2, 5, 1, 0, X, X, X, X, X, 2, 5, 2, 1, X,
|
||||
X, X, X, X, 3, 1, X, X, X, X, X, X, X, 1, 0, 3, 1, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 5,
|
||||
2, X, X, X, X, X, X, X, 3, 2, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 1, 0, 3, 2, X, X,
|
||||
X, X, X, 5, 1, X, X, X, X, X, X, X, 2, 1, X, X, X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 3, 0,
|
||||
X, X, X, X, X, X, X, 2, 5, X, X, X, X, X, X, X, 3, 4, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X,
|
||||
X, X, 1, 0, 3, 4, X, X, X, X, X, 5, 1, X, X, X, X, X, X, X, 4, 1, X, X, X, X, X, X, X, 5, 0, X,
|
||||
X, X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 1, 4, 1, 2, X, X, X, X, X, 4, 2, X, X, X, X, X, X,
|
||||
X, 3, 0, X, X, X, X, X, X, X, 4, 2, 1, 0, X, X, X, X, X, 4, 1, X, X, X, X, X, X, X, 3, 1, X, X,
|
||||
X, X, X, X, X, 2, 0, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 1, 4, X, X, X, X, X, X, X,
|
||||
3, 4, X, X, X, X, X, X, X, 1, 0, 3, 4, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 5, 1, X, X, X,
|
||||
X, X, X, X, 4, 1, X, X, X, X, X, X, X, 4, 1, 1, 0, X, X, X, X, X, 3, 0, X, X, X, X, X, X, X, 4,
|
||||
2, X, X, X, X, X, X, X, 4, 2, X, X, X, X, X, X, X, 5, 0, X, X, X, X, X, X, X, 5, 0, X, X, X, X,
|
||||
X, X, X, 1, 1, 1, 4, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 2, 0,
|
||||
X, X, X, X, X, X, X, 1, 4, X, X, X, X, X, X, X, 2, 8, X, X, X, X, X, X, X, 3, 0, X, X, X, X, X,
|
||||
X, X, 3, 0, X, X, X, X, X, X, X, 2, 1, X, X, X, X, X, X, X, 3, 1, X, X, X, X, X, X, X, 4, 0, X,
|
||||
X, X, X, X, X, X, 2, 0, X, X, X, X, X, X, X, 1, 2, X, X, X, X, X, X, X, 3, 2, X, X, X, X, X, X,
|
||||
X, 2, 0, X, X, X, X, X, X, X, 4, 0, X, X, X, X, X, X, X, 1, 1, X, X, X, X, X, X, X, 2, 1, X, X,
|
||||
X, X, X, X, X, 1, 0, X, X, X, X, X, X, X, 1, 0, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X
|
||||
#undef X
|
||||
});
|
||||
|
||||
// size: nCasesLT3d * nLabelEdgeTableLT3dElemSize
|
||||
// (TODO/FIXME: it can be improved to be shortened a little bit)
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id> labelEdgeTableLT3d =
|
||||
vtkm::cont::make_ArrayHandle<vtkm::Id>({
|
||||
#define X -1
|
||||
X, X, X, X, X, X, X, X, X, X, X, X, X, 6, 18, X, X, X, X, X, X, X, X, X, X, X,
|
||||
2, 0, X, X, X, X, X, X, X, X, X, X, X, 2, 12, 2, 14, 4, 18, X, X, X, X, X, X, X,
|
||||
2, 12, X, X, X, X, X, X, X, X, X, X, X, 2, 0, 1, 18, 2, 3, 3, 18, X, X, X, X, X,
|
||||
3, 0, 1, 12, X, X, X, X, X, X, X, X, X, 1, 18, 2, 14, 2, 3, 3, 18, X, X, X, X, X,
|
||||
2, 3, X, X, X, X, X, X, X, X, X, X, X, 2, 18, 2, 12, 2, 16, 2, 18, X, X, X, X, X,
|
||||
2, 0, 2, 3, X, X, X, X, X, X, X, X, X, 2, 12, 2, 14, 2, 12, 2, 16, 2, 18, X, X, X,
|
||||
1, 12, 3, 3, X, X, X, X, X, X, X, X, X, 2, 0, 2, 18, 2, 16, 2, 18, X, X, X, X, X,
|
||||
3, 0, 3, 3, X, X, X, X, X, X, X, X, X, 1, 18, 2, 14, 1, 18, 2, 16, 2, 18, X, X, X,
|
||||
2, 8, X, X, X, X, X, X, X, X, X, X, X, 4, 18, 2, 14, 2, 16, X, X, X, X, X, X, X,
|
||||
2, 0, 2, 8, X, X, X, X, X, X, X, X, X, 2, 12, 2, 14, 2, 18, 2, 14, 2, 16, X, X, X,
|
||||
2, 12, 2, 8, X, X, X, X, X, X, X, X, X, 2, 0, 1, 18, 2, 3, 1, 18, 2, 14, 2, 16, X,
|
||||
3, 0, 1, 12, 2, 8, X, X, X, X, X, X, X, 1, 18, 2, 14, 2, 3, 1, 18, 2, 14, 2, 16, X,
|
||||
2, 3, 2, 8, X, X, X, X, X, X, X, X, X, 2, 18, 2, 12, 2, 16, 2, 14, 2, 16, X, X, X,
|
||||
2, 0, 2, 3, 2, 8, X, X, X, X, X, X, X, 2, 12, 2, 14, 2, 12, 2, 16, 2, 14, 2, 16, X,
|
||||
1, 12, 3, 3, 2, 8, X, X, X, X, X, X, X, 2, 0, 2, 18, 2, 16, 2, 14, 2, 16, X, X, X,
|
||||
3, 0, 3, 3, 2, 8, X, X, X, X, X, X, X, 1, 18, 2, 14, 1, 18, 2, 16, 2, 14, 2, 16, X,
|
||||
2, 14, X, X, X, X, X, X, X, X, X, X, X, 1, 18, 2, 0, 2, 18, 2, 8, 1, 18, X, X, X,
|
||||
3, 0, 1, 14, X, X, X, X, X, X, X, X, X, 2, 12, 3, 18, 2, 8, 1, 18, X, X, X, X, X,
|
||||
1, 12, 1, 14, 1, 12, 1, 14, X, X, X, X, X, 4, 0, 2, 3, 1, 18, 2, 8, 1, 18, X, X, X,
|
||||
4, 0, 1, 12, 1, 14, X, X, X, X, X, X, X, 2, 18, 2, 3, 1, 18, 2, 8, 1, 18, X, X, X,
|
||||
1, 14, 2, 3, 1, 14, X, X, X, X, X, X, X, 1, 18, 2, 0, 2, 12, 2, 16, 2, 8, 1, 18, X,
|
||||
3, 0, 2, 3, 1, 14, X, X, X, X, X, X, X, 2, 12, 1, 18, 2, 12, 2, 16, 2, 8, 1, 18, X,
|
||||
1, 12, 1, 14, 3, 3, 1, 14, X, X, X, X, X, 4, 0, 1, 18, 2, 16, 2, 8, 1, 18, X, X, X,
|
||||
4, 0, 3, 3, 1, 14, X, X, X, X, X, X, X, 3, 18, 2, 16, 2, 8, 1, 18, X, X, X, X, X,
|
||||
1, 14, 3, 8, X, X, X, X, X, X, X, X, X, 1, 18, 2, 0, 3, 18, 2, 16, X, X, X, X, X,
|
||||
3, 0, 3, 8, X, X, X, X, X, X, X, X, X, 2, 12, 4, 18, 2, 16, X, X, X, X, X, X, X,
|
||||
1, 12, 1, 14, 1, 12, 3, 8, X, X, X, X, X, 4, 0, 2, 3, 2, 18, 2, 16, X, X, X, X, X,
|
||||
4, 0, 1, 12, 3, 8, X, X, X, X, X, X, X, 2, 18, 2, 3, 2, 18, 2, 16, X, X, X, X, X,
|
||||
1, 14, 2, 3, 3, 8, X, X, X, X, X, X, X, 1, 18, 2, 0, 2, 12, 2, 16, 1, 18, 2, 16, X,
|
||||
3, 0, 2, 3, 3, 8, X, X, X, X, X, X, X, 2, 12, 1, 18, 2, 12, 2, 16, 1, 18, 2, 16, X,
|
||||
1, 12, 1, 14, 3, 3, 3, 8, X, X, X, X, X, 4, 0, 1, 18, 2, 16, 1, 18, 2, 16, X, X, X,
|
||||
4, 0, 3, 3, 3, 8, X, X, X, X, X, X, X, 3, 18, 2, 16, 1, 18, 2, 16, X, X, X, X, X,
|
||||
6, 18, X, X, X, X, X, X, X, X, X, X, X, 4, 0, 4, 3, 4, 8, X, X, X, X, X, X, X,
|
||||
4, 0, 4, 18, X, X, X, X, X, X, X, X, X, 1, 12, 1, 14, 4, 3, 4, 8, X, X, X, X, X,
|
||||
2, 12, 1, 18, 2, 12, 3, 18, X, X, X, X, X, 3, 0, 3, 3, 4, 8, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 0, 2, 12, 3, 18, X, X, X, X, X, 1, 14, 3, 3, 4, 8, X, X, X, X, X, X, X,
|
||||
2, 18, 4, 3, 2, 18, X, X, X, X, X, X, X, 4, 0, 1, 12, 1, 16, 4, 8, X, X, X, X, X,
|
||||
4, 0, 4, 3, 2, 18, X, X, X, X, X, X, X, 1, 12, 1, 14, 1, 12, 1, 16, 4, 8, X, X, X,
|
||||
2, 12, 2, 18, 2, 3, 2, 18, X, X, X, X, X, 3, 0, 1, 16, 4, 8, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 0, 1, 18, 2, 3, 2, 18, X, X, X, 1, 14, 1, 16, 4, 8, X, X, X, X, X, X, X,
|
||||
4, 18, 4, 8, X, X, X, X, X, X, X, X, X, 4, 0, 4, 3, 1, 14, 1, 16, X, X, X, X, X,
|
||||
4, 0, 2, 18, 4, 8, X, X, X, X, X, X, X, 1, 12, 1, 14, 4, 3, 1, 14, 1, 16, X, X, X,
|
||||
2, 12, 1, 18, 2, 12, 1, 18, 4, 8, X, X, X, 3, 0, 3, 3, 1, 14, 1, 16, X, X, X, X, X,
|
||||
1, 18, 2, 0, 2, 12, 1, 18, 4, 8, X, X, X, 1, 14, 3, 3, 1, 14, 1, 16, X, X, X, X, X,
|
||||
2, 18, 4, 3, 4, 8, X, X, X, X, X, X, X, 4, 0, 1, 12, 1, 16, 1, 14, 1, 16, X, X, X,
|
||||
4, 0, 4, 3, 4, 8, X, X, X, X, X, X, X, 1, 12, 1, 14, 1, 12, 1, 16, 1, 14, 1, 16, X,
|
||||
2, 12, 2, 18, 2, 3, 4, 8, X, X, X, X, X, 3, 0, 1, 16, 1, 14, 1, 16, X, X, X, X, X,
|
||||
1, 18, 2, 0, 1, 18, 2, 3, 4, 8, X, X, X, 1, 14, 1, 16, 1, 14, 1, 16, X, X, X, X, X,
|
||||
1, 18, 2, 14, 2, 18, 2, 14, 1, 18, X, X, X, 3, 0, 4, 3, 3, 8, X, X, X, X, X, X, X,
|
||||
2, 0, 3, 18, 2, 14, 1, 18, X, X, X, X, X, 1, 12, 4, 3, 3, 8, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 2, 12, 1, 18, 2, 14, 1, 18, X, 2, 0, 3, 3, 3, 8, X, X, X, X, X, X, X,
|
||||
2, 18, 2, 12, 1, 18, 2, 14, 1, 18, X, X, X, 3, 3, 3, 8, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 14, 4, 3, 2, 14, 1, 18, X, X, X, 3, 0, 1, 12, 1, 16, 3, 8, X, X, X, X, X,
|
||||
2, 0, 1, 18, 4, 3, 2, 14, 1, 18, X, X, X, 2, 12, 1, 16, 3, 8, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 1, 18, 2, 3, 2, 14, 1, 18, X, 2, 0, 1, 16, 3, 8, X, X, X, X, X, X, X,
|
||||
3, 18, 2, 3, 2, 14, 1, 18, X, X, X, X, X, 1, 16, 3, 8, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 14, 3, 18, 2, 8, X, X, X, X, X, 3, 0, 4, 3, 1, 16, X, X, X, X, X, X, X,
|
||||
2, 0, 4, 18, 2, 8, X, X, X, X, X, X, X, 1, 12, 4, 3, 1, 16, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 2, 12, 2, 18, 2, 8, X, X, X, 2, 0, 3, 3, 1, 16, X, X, X, X, X, X, X,
|
||||
2, 18, 2, 12, 2, 18, 2, 8, X, X, X, X, X, 3, 3, 1, 16, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 14, 4, 3, 1, 18, 2, 8, X, X, X, 3, 0, 1, 12, 2, 16, X, X, X, X, X, X, X,
|
||||
2, 0, 1, 18, 4, 3, 1, 18, 2, 8, X, X, X, 2, 12, 2, 16, X, X, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 1, 18, 2, 3, 1, 18, 2, 8, X, 2, 0, 2, 16, X, X, X, X, X, X, X, X, X,
|
||||
3, 18, 2, 3, 1, 18, 2, 8, X, X, X, X, X, 2, 16, X, X, X, X, X, X, X, X, X, X, X,
|
||||
2, 16, X, X, X, X, X, X, X, X, X, X, X, 3, 18, 2, 3, 1, 18, 2, 8, X, X, X, X, X,
|
||||
2, 0, 2, 16, X, X, X, X, X, X, X, X, X, 2, 12, 2, 14, 1, 18, 2, 3, 1, 18, 2, 8, X,
|
||||
2, 12, 2, 16, X, X, X, X, X, X, X, X, X, 2, 0, 1, 18, 4, 3, 1, 18, 2, 8, X, X, X,
|
||||
3, 0, 1, 12, 2, 16, X, X, X, X, X, X, X, 1, 18, 2, 14, 4, 3, 1, 18, 2, 8, X, X, X,
|
||||
3, 3, 1, 16, X, X, X, X, X, X, X, X, X, 2, 18, 2, 12, 2, 18, 2, 8, X, X, X, X, X,
|
||||
2, 0, 3, 3, 1, 16, X, X, X, X, X, X, X, 2, 12, 2, 14, 2, 12, 2, 18, 2, 8, X, X, X,
|
||||
1, 12, 4, 3, 1, 16, X, X, X, X, X, X, X, 2, 0, 4, 18, 2, 8, X, X, X, X, X, X, X,
|
||||
3, 0, 4, 3, 1, 16, X, X, X, X, X, X, X, 1, 18, 2, 14, 3, 18, 2, 8, X, X, X, X, X,
|
||||
1, 16, 3, 8, X, X, X, X, X, X, X, X, X, 3, 18, 2, 3, 2, 14, 1, 18, X, X, X, X, X,
|
||||
2, 0, 1, 16, 3, 8, X, X, X, X, X, X, X, 2, 12, 2, 14, 1, 18, 2, 3, 2, 14, 1, 18, X,
|
||||
2, 12, 1, 16, 3, 8, X, X, X, X, X, X, X, 2, 0, 1, 18, 4, 3, 2, 14, 1, 18, X, X, X,
|
||||
3, 0, 1, 12, 1, 16, 3, 8, X, X, X, X, X, 1, 18, 2, 14, 4, 3, 2, 14, 1, 18, X, X, X,
|
||||
3, 3, 3, 8, X, X, X, X, X, X, X, X, X, 2, 18, 2, 12, 1, 18, 2, 14, 1, 18, X, X, X,
|
||||
2, 0, 3, 3, 3, 8, X, X, X, X, X, X, X, 2, 12, 2, 14, 2, 12, 1, 18, 2, 14, 1, 18, X,
|
||||
1, 12, 4, 3, 3, 8, X, X, X, X, X, X, X, 2, 0, 3, 18, 2, 14, 1, 18, X, X, X, X, X,
|
||||
3, 0, 4, 3, 3, 8, X, X, X, X, X, X, X, 1, 18, 2, 14, 2, 18, 2, 14, 1, 18, X, X, X,
|
||||
1, 14, 1, 16, 1, 14, 1, 16, X, X, X, X, X, 1, 18, 2, 0, 1, 18, 2, 3, 4, 8, X, X, X,
|
||||
3, 0, 1, 16, 1, 14, 1, 16, X, X, X, X, X, 2, 12, 2, 18, 2, 3, 4, 8, X, X, X, X, X,
|
||||
1, 12, 1, 14, 1, 12, 1, 16, 1, 14, 1, 16, X, 4, 0, 4, 3, 4, 8, X, X, X, X, X, X, X,
|
||||
4, 0, 1, 12, 1, 16, 1, 14, 1, 16, X, X, X, 2, 18, 4, 3, 4, 8, X, X, X, X, X, X, X,
|
||||
1, 14, 3, 3, 1, 14, 1, 16, X, X, X, X, X, 1, 18, 2, 0, 2, 12, 1, 18, 4, 8, X, X, X,
|
||||
3, 0, 3, 3, 1, 14, 1, 16, X, X, X, X, X, 2, 12, 1, 18, 2, 12, 1, 18, 4, 8, X, X, X,
|
||||
1, 12, 1, 14, 4, 3, 1, 14, 1, 16, X, X, X, 4, 0, 2, 18, 4, 8, X, X, X, X, X, X, X,
|
||||
4, 0, 4, 3, 1, 14, 1, 16, X, X, X, X, X, 4, 18, 4, 8, X, X, X, X, X, X, X, X, X,
|
||||
1, 14, 1, 16, 4, 8, X, X, X, X, X, X, X, 1, 18, 2, 0, 1, 18, 2, 3, 2, 18, X, X, X,
|
||||
3, 0, 1, 16, 4, 8, X, X, X, X, X, X, X, 2, 12, 2, 18, 2, 3, 2, 18, X, X, X, X, X,
|
||||
1, 12, 1, 14, 1, 12, 1, 16, 4, 8, X, X, X, 4, 0, 4, 3, 2, 18, X, X, X, X, X, X, X,
|
||||
4, 0, 1, 12, 1, 16, 4, 8, X, X, X, X, X, 2, 18, 4, 3, 2, 18, X, X, X, X, X, X, X,
|
||||
1, 14, 3, 3, 4, 8, X, X, X, X, X, X, X, 1, 18, 2, 0, 2, 12, 3, 18, X, X, X, X, X,
|
||||
3, 0, 3, 3, 4, 8, X, X, X, X, X, X, X, 2, 12, 1, 18, 2, 12, 3, 18, X, X, X, X, X,
|
||||
1, 12, 1, 14, 4, 3, 4, 8, X, X, X, X, X, 4, 0, 4, 18, X, X, X, X, X, X, X, X, X,
|
||||
4, 0, 4, 3, 4, 8, X, X, X, X, X, X, X, 6, 18, X, X, X, X, X, X, X, X, X, X, X,
|
||||
3, 18, 2, 16, 1, 18, 2, 16, X, X, X, X, X, 4, 0, 3, 3, 3, 8, X, X, X, X, X, X, X,
|
||||
4, 0, 1, 18, 2, 16, 1, 18, 2, 16, X, X, X, 1, 12, 1, 14, 3, 3, 3, 8, X, X, X, X, X,
|
||||
2, 12, 1, 18, 2, 12, 2, 16, 1, 18, 2, 16, X, 3, 0, 2, 3, 3, 8, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 0, 2, 12, 2, 16, 1, 18, 2, 16, X, 1, 14, 2, 3, 3, 8, X, X, X, X, X, X, X,
|
||||
2, 18, 2, 3, 2, 18, 2, 16, X, X, X, X, X, 4, 0, 1, 12, 3, 8, X, X, X, X, X, X, X,
|
||||
4, 0, 2, 3, 2, 18, 2, 16, X, X, X, X, X, 1, 12, 1, 14, 1, 12, 3, 8, X, X, X, X, X,
|
||||
2, 12, 4, 18, 2, 16, X, X, X, X, X, X, X, 3, 0, 3, 8, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 0, 3, 18, 2, 16, X, X, X, X, X, 1, 14, 3, 8, X, X, X, X, X, X, X, X, X,
|
||||
3, 18, 2, 16, 2, 8, 1, 18, X, X, X, X, X, 4, 0, 3, 3, 1, 14, X, X, X, X, X, X, X,
|
||||
4, 0, 1, 18, 2, 16, 2, 8, 1, 18, X, X, X, 1, 12, 1, 14, 3, 3, 1, 14, X, X, X, X, X,
|
||||
2, 12, 1, 18, 2, 12, 2, 16, 2, 8, 1, 18, X, 3, 0, 2, 3, 1, 14, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 0, 2, 12, 2, 16, 2, 8, 1, 18, X, 1, 14, 2, 3, 1, 14, X, X, X, X, X, X, X,
|
||||
2, 18, 2, 3, 1, 18, 2, 8, 1, 18, X, X, X, 4, 0, 1, 12, 1, 14, X, X, X, X, X, X, X,
|
||||
4, 0, 2, 3, 1, 18, 2, 8, 1, 18, X, X, X, 1, 12, 1, 14, 1, 12, 1, 14, X, X, X, X, X,
|
||||
2, 12, 3, 18, 2, 8, 1, 18, X, X, X, X, X, 3, 0, 1, 14, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 0, 2, 18, 2, 8, 1, 18, X, X, X, 2, 14, X, X, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 14, 1, 18, 2, 16, 2, 14, 2, 16, X, 3, 0, 3, 3, 2, 8, X, X, X, X, X, X, X,
|
||||
2, 0, 2, 18, 2, 16, 2, 14, 2, 16, X, X, X, 1, 12, 3, 3, 2, 8, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 2, 12, 2, 16, 2, 14, 2, 16, X, 2, 0, 2, 3, 2, 8, X, X, X, X, X, X, X,
|
||||
2, 18, 2, 12, 2, 16, 2, 14, 2, 16, X, X, X, 2, 3, 2, 8, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 14, 2, 3, 1, 18, 2, 14, 2, 16, X, 3, 0, 1, 12, 2, 8, X, X, X, X, X, X, X,
|
||||
2, 0, 1, 18, 2, 3, 1, 18, 2, 14, 2, 16, X, 2, 12, 2, 8, X, X, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 2, 18, 2, 14, 2, 16, X, X, X, 2, 0, 2, 8, X, X, X, X, X, X, X, X, X,
|
||||
4, 18, 2, 14, 2, 16, X, X, X, X, X, X, X, 2, 8, X, X, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 14, 1, 18, 2, 16, 2, 18, X, X, X, 3, 0, 3, 3, X, X, X, X, X, X, X, X, X,
|
||||
2, 0, 2, 18, 2, 16, 2, 18, X, X, X, X, X, 1, 12, 3, 3, X, X, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 2, 12, 2, 16, 2, 18, X, X, X, 2, 0, 2, 3, X, X, X, X, X, X, X, X, X,
|
||||
2, 18, 2, 12, 2, 16, 2, 18, X, X, X, X, X, 2, 3, X, X, X, X, X, X, X, X, X, X, X,
|
||||
1, 18, 2, 14, 2, 3, 3, 18, X, X, X, X, X, 3, 0, 1, 12, X, X, X, X, X, X, X, X, X,
|
||||
2, 0, 1, 18, 2, 3, 3, 18, X, X, X, X, X, 2, 12, X, X, X, X, X, X, X, X, X, X, X,
|
||||
2, 12, 2, 14, 4, 18, X, X, X, X, X, X, X, 2, 0, X, X, X, X, X, X, X, X, X, X, X,
|
||||
6, 18, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X
|
||||
#undef X
|
||||
});
|
||||
|
||||
} // namespace select_top_volume_contours
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -0,0 +1,103 @@
|
||||
//============================================================================
|
||||
// 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_predicates_h
|
||||
#define vtk_m_filter_scalar_topology_worklet_select_top_volume_contours_predicates_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace scalar_topology
|
||||
{
|
||||
namespace select_top_volume_contours
|
||||
{
|
||||
|
||||
constexpr vtkm::Id BRANCH_SADDLE = static_cast<vtkm::Id>(1); // 1 << 0
|
||||
constexpr vtkm::Id BRANCH_COVER = static_cast<vtkm::Id>(2); // 1 << 1
|
||||
constexpr vtkm::Id MAXIMA_CONTOUR = static_cast<vtkm::Id>(4); // 1 << 2
|
||||
|
||||
struct IsNonNegative
|
||||
{
|
||||
VTKM_EXEC_CONT
|
||||
IsNonNegative() {}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
bool operator()(const vtkm::Id x) const { return x >= 0; }
|
||||
};
|
||||
|
||||
struct IsExtraMinima
|
||||
{
|
||||
VTKM_EXEC_CONT
|
||||
IsExtraMinima() {}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
bool operator()(const vtkm::Id x) const { return (x & vtkm::Id(1)) != 0; }
|
||||
};
|
||||
|
||||
struct IsExtraMaxima
|
||||
{
|
||||
VTKM_EXEC_CONT
|
||||
IsExtraMaxima() {}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
bool operator()(const vtkm::Id x) const { return (x & vtkm::Id(2)) != 0; }
|
||||
};
|
||||
|
||||
} // namespace select_top_volume_contours
|
||||
} // namespace scalar_topology
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user