mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add support for boundary augmentation for MPI optimization
This commit is contained in:
parent
2a1e1dcfd9
commit
1d9f6b37cf
@ -138,10 +138,10 @@ public:
|
||||
|
||||
std::string getOption(const std::string& option) const
|
||||
{
|
||||
auto index = this->findOption(option);
|
||||
std::size_t index = static_cast<std::size_t>(this->findOption(option));
|
||||
if (index >= 0)
|
||||
{
|
||||
std::string val = this->mCLOptions[static_cast<std::size_t>(index)];
|
||||
std::string val = this->mCLOptions[index];
|
||||
auto valPos = val.find("=");
|
||||
if (valPos)
|
||||
{
|
||||
@ -201,19 +201,21 @@ int main(int argc, char* argv[])
|
||||
ParseCL parser;
|
||||
parser.parse(argc, argv);
|
||||
std::string filename = parser.getOptions().back();
|
||||
bool computeRegularStructure = true;
|
||||
unsigned int computeRegularStructure = 1; // 1=fully augmented
|
||||
bool useMarchingCubes = false;
|
||||
bool computeBranchDecomposition = true;
|
||||
bool printContourTree = false;
|
||||
if (parser.hasOption("--augmentTree"))
|
||||
computeRegularStructure = std::stoi(parser.getOption("--augmentTree"));
|
||||
computeRegularStructure =
|
||||
static_cast<unsigned int>(std::stoi(parser.getOption("--augmentTree")));
|
||||
if (parser.hasOption("--mc"))
|
||||
useMarchingCubes = true;
|
||||
if (parser.hasOption("--printCT"))
|
||||
printContourTree = true;
|
||||
if (parser.hasOption("--branchDecomp"))
|
||||
computeBranchDecomposition = std::stoi(parser.getOption("--branchDecomp"));
|
||||
if (computeBranchDecomposition && (!computeRegularStructure))
|
||||
// We need the fully augmented tree to compute the branch decomposition
|
||||
if (computeBranchDecomposition && (computeRegularStructure != 1))
|
||||
{
|
||||
std::cout << "Regular structure is required for branch decomposition."
|
||||
" Disabling branch decomposition"
|
||||
@ -318,7 +320,12 @@ int main(int argc, char* argv[])
|
||||
std::cout << "--mc Use marching cubes interpolation for contour tree calculation. "
|
||||
"(Default=False)"
|
||||
<< std::endl;
|
||||
std::cout << "--augmentTree Compute the augmented contour tree. (Default=True)"
|
||||
std::cout << "--augmentTree 1 = compute the fully augmented contour tree (Default)"
|
||||
<< std::endl;
|
||||
std::cout << " 2 = compute the boundary augmented contour tree " << std::endl;
|
||||
std::cout << " 0 = no augmentation. NOTE: When using MPI, local ranks use"
|
||||
<< std::endl;
|
||||
std::cout << " boundary augmentation to support parallel merge of blocks"
|
||||
<< std::endl;
|
||||
std::cout << "--branchDecomp Compute the volume branch decomposition for the contour tree. "
|
||||
"Requires --augmentTree (Default=True)"
|
||||
@ -358,6 +365,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
std::cout << "Settings:" << std::endl;
|
||||
std::cout << " filename=" << filename << std::endl;
|
||||
std::cout << " device=" << device << std::endl;
|
||||
std::cout << " mc=" << useMarchingCubes << std::endl;
|
||||
std::cout << " augmentTree=" << computeRegularStructure << std::endl;
|
||||
std::cout << " branchDecomp=" << computeBranchDecomposition << std::endl;
|
||||
@ -367,7 +375,7 @@ int main(int argc, char* argv[])
|
||||
#ifdef ENABLE_SET_NUM_THREADS
|
||||
std::cout << " numThreads=" << numThreads << std::endl;
|
||||
#endif
|
||||
std::cout << " computeIsovalyes=" << (numLevels > 0) << std::endl;
|
||||
std::cout << " computeIsovalues=" << (numLevels > 0) << std::endl;
|
||||
if (numLevels > 0)
|
||||
{
|
||||
std::cout << " levels=" << numLevels << std::endl;
|
||||
@ -450,7 +458,7 @@ int main(int argc, char* argv[])
|
||||
// Print the mesh metadata
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << " Number of dimensions: " << nDims << std::endl;
|
||||
std::cout << "Number of dimensions: " << nDims << std::endl;
|
||||
std::cout << "Number of mesh vertices: " << nVertices << std::endl;
|
||||
}
|
||||
// Check the the number of dimensiosn is either 2D or 3D
|
||||
@ -543,7 +551,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "Number of ranks too large for data. Use " << lastDimSize / 2
|
||||
std::cout << "Number of ranks to large for data. Use " << lastDimSize / 2
|
||||
<< "or fewer ranks" << std::endl;
|
||||
}
|
||||
MPI_Finalize();
|
||||
@ -555,11 +563,6 @@ int main(int argc, char* argv[])
|
||||
nDims == 2 ? static_cast<vtkm::Id>(dims[0]) : static_cast<vtkm::Id>((dims[0] * dims[1]));
|
||||
vtkm::Id blockNumValues = blockSize * blockSliceSize;
|
||||
|
||||
/*//Print the input values
|
||||
for(auto i = values.begin(); i != values.end(); ++i)
|
||||
std::cout << *i << ' ';
|
||||
std::cout<<std::endl;*/
|
||||
|
||||
vtkm::Id startBlock = blocksPerRank * rank;
|
||||
vtkm::Id endBlock = startBlock + blocksPerRank;
|
||||
for (vtkm::Id blockIndex = startBlock; blockIndex < endBlock; ++blockIndex)
|
||||
@ -578,7 +581,6 @@ int main(int argc, char* argv[])
|
||||
vtkm::Id currBlockSize = (vtkm::Id)((blockEnd - blockStart) / blockSliceSize);
|
||||
|
||||
vtkm::cont::DataSet ds;
|
||||
//std::cout<<"Block index: "<<blockIndex<<" start="<<blockStart<<" end="<<blockEnd<<" (rank="<<rank<<")"<<std::endl;
|
||||
|
||||
// 2D data
|
||||
if (nDims == 2)
|
||||
@ -607,10 +609,6 @@ int main(int argc, char* argv[])
|
||||
vtkm::Vec<ValueType, 3> spacing(1, 1, 1);
|
||||
ds = dsb.Create(vdims, origin, spacing);
|
||||
|
||||
//localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(blockIndex, 0, 0));
|
||||
//localBlockOriginsPortal.Set(localBlockIndex, vtkm::Id3((blockStart / blockSliceSize), 0, 0));
|
||||
//localBlockSizesPortal.Set(localBlockIndex, vtkm::Id3(currBlockSize, dims[1], dims[2]));
|
||||
|
||||
localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(0, 0, blockIndex));
|
||||
localBlockOriginsPortal.Set(localBlockIndex,
|
||||
vtkm::Id3(0, 0, (blockStart / blockSliceSize)));
|
||||
|
@ -80,7 +80,7 @@ class ContourTreePPP2 : public vtkm::filter::FilterCell<ContourTreePPP2>
|
||||
public:
|
||||
using SupportedTypes = vtkm::TypeListTagScalarAll;
|
||||
VTKM_CONT
|
||||
ContourTreePPP2(bool useMarchingCubes = false, bool computeRegularStructure = true);
|
||||
ContourTreePPP2(bool useMarchingCubes = false, unsigned int computeRegularStructure = 1);
|
||||
|
||||
// Define the spatial decomposition of the data in case we run in parallel with a multi-block dataset
|
||||
VTKM_CONT
|
||||
@ -131,8 +131,8 @@ private:
|
||||
vtkm::Id nslices) const;
|
||||
|
||||
bool UseMarchingCubes;
|
||||
// 0=no augmentation, 1=full augmentation
|
||||
bool ComputeRegularStructure;
|
||||
// 0=no augmentation, 1=full augmentation, 2=boundary augmentation
|
||||
unsigned int ComputeRegularStructure;
|
||||
// Store timings about the contour tree computation
|
||||
std::vector<std::pair<std::string, vtkm::Float64>> Timings;
|
||||
|
||||
|
@ -93,9 +93,10 @@ struct ContourTreeBlockData
|
||||
vtkm::Id maxNeighbours;
|
||||
|
||||
// Block metadata
|
||||
vtkm::Id3 blockOrigin; // Origin of the data block
|
||||
vtkm::Id3 blockSize; // Extends of the data block
|
||||
vtkm::Id3 globalSize; // Extends of the global mesh
|
||||
vtkm::Id3 blockOrigin; // Origin of the data block
|
||||
vtkm::Id3 blockSize; // Extends of the data block
|
||||
vtkm::Id3 globalSize; // Extends of the global mesh
|
||||
unsigned int computeRegularStructure; // pass through augmentation setting
|
||||
};
|
||||
|
||||
namespace vtkmdiy
|
||||
@ -117,6 +118,7 @@ struct Serialization<ContourTreeBlockData<FieldType>>
|
||||
vtkmdiy::save(bb, block.blockOrigin);
|
||||
vtkmdiy::save(bb, block.blockSize);
|
||||
vtkmdiy::save(bb, block.globalSize);
|
||||
vtkmdiy::save(bb, block.computeRegularStructure);
|
||||
}
|
||||
|
||||
static void load(vtkmdiy::BinaryBuffer& bb, ContourTreeBlockData<FieldType>& block)
|
||||
@ -131,6 +133,7 @@ struct Serialization<ContourTreeBlockData<FieldType>>
|
||||
vtkmdiy::load(bb, block.blockOrigin);
|
||||
vtkmdiy::load(bb, block.blockSize);
|
||||
vtkmdiy::load(bb, block.globalSize);
|
||||
vtkmdiy::load(bb, block.computeRegularStructure);
|
||||
}
|
||||
};
|
||||
|
||||
@ -253,24 +256,18 @@ public:
|
||||
mLocalSortOrders.clear();
|
||||
}
|
||||
|
||||
inline static void GetGlobalMeshIndex(
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType& globalMeshIndex,
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& sortOrder,
|
||||
vtkm::Id startRow,
|
||||
vtkm::Id startCol,
|
||||
vtkm::Id startSlice,
|
||||
vtkm::Id numRows,
|
||||
vtkm::Id numCols,
|
||||
vtkm::Id totalNumRows,
|
||||
vtkm::Id totalNumCols)
|
||||
inline static vtkm::Bounds getGlobalBounds(const vtkm::cont::PartitionedDataSet& input)
|
||||
{
|
||||
auto transformedIndex =
|
||||
vtkm::cont::ArrayHandleTransform<vtkm::worklet::contourtree_augmented::IdArrayType,
|
||||
vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabler>(
|
||||
sortOrder,
|
||||
vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabler(
|
||||
startRow, startCol, startSlice, numRows, numCols, totalNumRows, totalNumCols));
|
||||
vtkm::cont::Algorithm::Copy(transformedIndex, globalMeshIndex);
|
||||
// Get the spatial bounds of a multi -block data set
|
||||
vtkm::Bounds bounds = vtkm::cont::BoundsGlobalCompute(input);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
inline static vtkm::Bounds getLocalBounds(const vtkm::cont::PartitionedDataSet& input)
|
||||
{
|
||||
// Get the spatial bounds of a multi -block data set
|
||||
vtkm::Bounds bounds = vtkm::cont::BoundsCompute(input);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
inline vtkm::Id getLocalNumberOfBlocks() const
|
||||
@ -288,10 +285,17 @@ public:
|
||||
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
|
||||
vtkm::Id localSize = input.GetNumberOfPartitions();
|
||||
vtkm::Id globalSize = 0;
|
||||
#ifdef VTKM_ENABLE_MPI
|
||||
vtkmdiy::mpi::all_reduce(comm, localSize, globalSize, std::plus<vtkm::Id>{});
|
||||
#else
|
||||
globalSize = localSize;
|
||||
#endif
|
||||
return globalSize;
|
||||
}
|
||||
|
||||
// Used to compute the local contour tree mesh in after DoExecute. I.e., the function is
|
||||
// used in PostExecute to construct the initial set of local ContourTreeMesh blocks for
|
||||
// DIY. Subsequent construction of updated ContourTreeMeshes is handled separately.
|
||||
template <typename T>
|
||||
inline static vtkm::worklet::contourtree_augmented::ContourTreeMesh<T>*
|
||||
computeLocalContourTreeMesh(const vtkm::Id3 localBlockOrigin,
|
||||
@ -299,7 +303,8 @@ public:
|
||||
const vtkm::Id3 globalSize,
|
||||
const vtkm::cont::ArrayHandle<T>& field,
|
||||
const vtkm::worklet::contourtree_augmented::ContourTree& contourTree,
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& sortOrder)
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& sortOrder,
|
||||
unsigned int computeRegularStructure)
|
||||
|
||||
{
|
||||
vtkm::Id startRow = localBlockOrigin[0];
|
||||
@ -309,35 +314,49 @@ public:
|
||||
vtkm::Id numCols = localBlockSize[1];
|
||||
vtkm::Id totalNumRows = globalSize[0];
|
||||
vtkm::Id totalNumCols = globalSize[1];
|
||||
|
||||
// compute the global mesh index
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType localGlobalMeshIndex;
|
||||
MultiBlockContourTreeHelper::GetGlobalMeshIndex(localGlobalMeshIndex,
|
||||
sortOrder,
|
||||
startRow,
|
||||
startCol,
|
||||
startSlice,
|
||||
numRows,
|
||||
numCols,
|
||||
totalNumRows,
|
||||
totalNumCols);
|
||||
|
||||
// Compute the local contour tree mesh
|
||||
auto localContourTreeMesh = new vtkm::worklet::contourtree_augmented::ContourTreeMesh<T>(
|
||||
contourTree.arcs, sortOrder, field, localGlobalMeshIndex);
|
||||
return localContourTreeMesh;
|
||||
}
|
||||
|
||||
template <typename FieldType>
|
||||
inline static vtkm::worklet::contourtree_augmented::ContourTreeMesh<FieldType>*
|
||||
computeMergedContourTreeMesh(
|
||||
const vtkm::worklet::contourtree_augmented::IdArrayType& contourTreeArcs,
|
||||
const vtkm::worklet::contourtree_augmented::ContourTreeMesh<FieldType>& contourTreeMesh)
|
||||
{
|
||||
auto localContourTreeMesh =
|
||||
new vtkm::worklet::contourtree_augmented::ContourTreeMesh<FieldType>(contourTreeArcs,
|
||||
contourTreeMesh);
|
||||
return localContourTreeMesh;
|
||||
// compute the global mesh index and initalize the local contour tree mesh
|
||||
if (computeRegularStructure == 1)
|
||||
{
|
||||
// Compute the global mesh index
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType localGlobalMeshIndex;
|
||||
auto transformedIndex = vtkm::cont::ArrayHandleTransform<
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType,
|
||||
vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabler>(
|
||||
sortOrder,
|
||||
vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabler(
|
||||
startRow, startCol, startSlice, numRows, numCols, totalNumRows, totalNumCols));
|
||||
vtkm::cont::Algorithm::Copy(transformedIndex, localGlobalMeshIndex);
|
||||
// Compute the local contour tree mesh
|
||||
auto localContourTreeMesh = new vtkm::worklet::contourtree_augmented::ContourTreeMesh<T>(
|
||||
contourTree.arcs, sortOrder, field, localGlobalMeshIndex);
|
||||
return localContourTreeMesh;
|
||||
}
|
||||
else if (computeRegularStructure == 2)
|
||||
{
|
||||
// Compute the global mesh index for the partially augmented contour tree. I.e., here we
|
||||
// don't need the global mesh index for all nodes, but only for the augmented nodes from the
|
||||
// tree. We, hence, permute the sortOrder by contourTree.augmentednodes and then compute the
|
||||
// globalMeshIndex by tranforming those indices with our IdRelabler
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType localGlobalMeshIndex;
|
||||
vtkm::cont::ArrayHandlePermutation<vtkm::worklet::contourtree_augmented::IdArrayType,
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
permutedSortOrder(contourTree.augmentnodes, sortOrder);
|
||||
auto transformedIndex = vtkm::cont::make_ArrayHandleTransform(
|
||||
permutedSortOrder,
|
||||
vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabler(
|
||||
startRow, startCol, startSlice, numRows, numCols, totalNumRows, totalNumCols));
|
||||
vtkm::cont::Algorithm::Copy(transformedIndex, localGlobalMeshIndex);
|
||||
// Compute the local contour tree mesh
|
||||
auto localContourTreeMesh = new vtkm::worklet::contourtree_augmented::ContourTreeMesh<T>(
|
||||
contourTree.augmentnodes, contourTree.augmentarcs, sortOrder, field, localGlobalMeshIndex);
|
||||
return localContourTreeMesh;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should not be able to get here
|
||||
throw vtkm::cont::ErrorFilterExecution(
|
||||
"Parallel contour tree requires at least parial boundary augmentation");
|
||||
}
|
||||
}
|
||||
|
||||
SpatialDecomposition mSpatialDecomposition;
|
||||
@ -380,7 +399,6 @@ void merge_block_functor(
|
||||
// Here we do the deque first before the send due to the way the iteration is handled in DIY, i.e., in each iteration
|
||||
// A block needs to first collect the data from its neighours and then send the combined block to its neighbours
|
||||
// for the next iteration.
|
||||
|
||||
// 1. dequeue the block and compute the new contour tree and contour tree mesh for the block if we have the hight GID
|
||||
std::vector<int> incoming;
|
||||
rp.incoming(incoming);
|
||||
@ -409,7 +427,6 @@ void merge_block_functor(
|
||||
contourTreeMeshOut.neighbours = block->neighbours;
|
||||
contourTreeMeshOut.firstNeighbour = block->firstNeighbour;
|
||||
contourTreeMeshOut.maxNeighbours = block->maxNeighbours;
|
||||
|
||||
// Merge the two contour tree meshes
|
||||
vtkm::cont::TryExecute(MergeFunctor{}, contourTreeMeshIn, contourTreeMeshOut);
|
||||
|
||||
@ -455,21 +472,43 @@ void merge_block_functor(
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType currSortOrder;
|
||||
vtkm::worklet::ContourTreePPP2 worklet;
|
||||
vtkm::cont::ArrayHandle<FieldType> currField;
|
||||
|
||||
// Run the contour tree compute. NOTE, the first paramerter is unused here. We need to provide
|
||||
// something for the field to keep the API happy
|
||||
vtkm::Id3 maxIdx(currBlockOrigin[0] + currBlockSize[0] - 1,
|
||||
currBlockOrigin[1] + currBlockSize[1] - 1,
|
||||
currBlockOrigin[2] + currBlockSize[2] - 1);
|
||||
auto meshBoundaryExecObj =
|
||||
contourTreeMeshOut.GetMeshBoundaryExecutionObject(globalSize[0], // totalNRows
|
||||
globalSize[1], // totalNCols
|
||||
currBlockOrigin, // minIdx
|
||||
maxIdx // maxIdx
|
||||
);
|
||||
worklet.Run(
|
||||
contourTreeMeshOut.sortedValues,
|
||||
contourTreeMeshOut.sortedValues, // Unused param. Provide something to keep the API happy
|
||||
contourTreeMeshOut,
|
||||
currTimings,
|
||||
currContourTree,
|
||||
currSortOrder,
|
||||
currNumIterations,
|
||||
1 // TODO eventually replace with boundary augmentation but for now compute the full regular structure
|
||||
);
|
||||
auto newContourTreeMesh =
|
||||
vtkm::filter::detail::MultiBlockContourTreeHelper::computeMergedContourTreeMesh(
|
||||
block->computeRegularStructure,
|
||||
meshBoundaryExecObj);
|
||||
vtkm::worklet::contourtree_augmented::ContourTreeMesh<FieldType>* newContourTreeMesh = 0;
|
||||
if (block->computeRegularStructure == 1)
|
||||
{
|
||||
// If we have the fully augmented contour tree
|
||||
newContourTreeMesh = new vtkm::worklet::contourtree_augmented::ContourTreeMesh<FieldType>(
|
||||
currContourTree.arcs, contourTreeMeshOut);
|
||||
}
|
||||
else if (block->computeRegularStructure == 2)
|
||||
{
|
||||
// If we have the partially augmented (e.g., boundary augmented) contour tree
|
||||
newContourTreeMesh = new vtkm::worklet::contourtree_augmented::ContourTreeMesh<FieldType>(
|
||||
currContourTree.augmentnodes, currContourTree.augmentarcs, contourTreeMeshOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should not be able to get here
|
||||
throw vtkm::cont::ErrorFilterExecution(
|
||||
"Parallel contour tree requires at least parial boundary augmentation");
|
||||
}
|
||||
|
||||
// Copy the data from newContourTreeMesh into block
|
||||
block->nVertices = newContourTreeMesh->nVertices;
|
||||
@ -482,13 +521,11 @@ void merge_block_functor(
|
||||
block->blockOrigin = currBlockOrigin;
|
||||
block->blockSize = currBlockSize;
|
||||
block->globalSize = globalSize;
|
||||
|
||||
// TODO delete newContourTreeMesh
|
||||
// TODO Clean up the pointers from the local data blocks from the previous iteration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send our current block (which is either our original block or the one we just combined from the ones we received) to our next neighbour.
|
||||
// Once a rank has send his block (either in its orignal or merged form) it is done with the reduce
|
||||
for (int cc = 0; cc < rp.out_link().size(); ++cc)
|
||||
@ -506,7 +543,7 @@ void merge_block_functor(
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
ContourTreePPP2::ContourTreePPP2(bool useMarchingCubes, bool computeRegularStructure)
|
||||
ContourTreePPP2::ContourTreePPP2(bool useMarchingCubes, unsigned int computeRegularStructure)
|
||||
: vtkm::filter::FilterCell<ContourTreePPP2>()
|
||||
, UseMarchingCubes(useMarchingCubes)
|
||||
, ComputeRegularStructure(computeRegularStructure)
|
||||
@ -579,9 +616,23 @@ vtkm::cont::DataSet ContourTreePPP2::DoExecute(const vtkm::cont::DataSet& input,
|
||||
const auto& cells = input.GetCellSet();
|
||||
vtkm::filter::ApplyPolicyCellSet(cells, policy)
|
||||
.CastAndCall(GetRowsColsSlices(), nRows, nCols, nSlices);
|
||||
// TODO blockIndex=0 --- This needs to change if we have multiple blocks per MPI rank and DoExecute is called for multiple blocks
|
||||
// TODO blockIndex needs to change if we have multiple blocks per MPI rank and DoExecute is called for multiple blocks
|
||||
std::size_t blockIndex = 0;
|
||||
|
||||
// Determine if and what augmentation we need to do
|
||||
unsigned int compRegularStruct = this->ComputeRegularStructure;
|
||||
// When running in parallel we need to at least augment with the boundary vertices
|
||||
if (compRegularStruct == 0)
|
||||
{
|
||||
if (this->MultiBlockTreeHelper)
|
||||
{
|
||||
if (this->MultiBlockTreeHelper->getGlobalNumberOfBlocks() > 1)
|
||||
{
|
||||
compRegularStruct = 2; // Compute boundary augmentation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the worklet
|
||||
worklet.Run(field,
|
||||
this->Timings,
|
||||
@ -594,7 +645,7 @@ vtkm::cont::DataSet ContourTreePPP2::DoExecute(const vtkm::cont::DataSet& input,
|
||||
nCols,
|
||||
nSlices,
|
||||
this->UseMarchingCubes,
|
||||
this->ComputeRegularStructure);
|
||||
compRegularStruct);
|
||||
|
||||
// Update the total timings
|
||||
vtkm::Float64 totalTimeWorklet = 0;
|
||||
@ -683,6 +734,9 @@ VTKM_CONT void ContourTreePPP2::DoPostExecute(
|
||||
localDataBlocks.resize(static_cast<size_t>(input.GetNumberOfPartitions()));
|
||||
std::vector<vtkmdiy::Link*> localLinks; // dummy links needed to make DIY happy
|
||||
localLinks.resize(static_cast<size_t>(input.GetNumberOfPartitions()));
|
||||
// We need to augment at least with the boundary vertices when running in parallel, even if the user requested at the end only the unaugmented contour tree
|
||||
unsigned int compRegularStruct =
|
||||
(this->ComputeRegularStructure > 0) ? this->ComputeRegularStructure : 2;
|
||||
for (std::size_t bi = 0; bi < static_cast<std::size_t>(input.GetNumberOfPartitions()); bi++)
|
||||
{
|
||||
// create the local contour tree mesh
|
||||
@ -702,7 +756,8 @@ VTKM_CONT void ContourTreePPP2::DoPostExecute(
|
||||
this->MultiBlockTreeHelper->mSpatialDecomposition.mGlobalSize,
|
||||
fieldData,
|
||||
MultiBlockTreeHelper->mLocalContourTrees[bi],
|
||||
MultiBlockTreeHelper->mLocalSortOrders[bi]);
|
||||
MultiBlockTreeHelper->mLocalSortOrders[bi],
|
||||
compRegularStruct);
|
||||
localContourTreeMeshes[bi] = currContourTreeMesh;
|
||||
// create the local data block structure
|
||||
localDataBlocks[bi] = new ContourTreeBlockData<T>();
|
||||
@ -720,8 +775,9 @@ VTKM_CONT void ContourTreePPP2::DoPostExecute(
|
||||
this->MultiBlockTreeHelper->mSpatialDecomposition.mLocalBlockSizes.GetPortalConstControl()
|
||||
.Get(static_cast<vtkm::Id>(bi));
|
||||
localDataBlocks[bi]->globalSize = this->MultiBlockTreeHelper->mSpatialDecomposition.mGlobalSize;
|
||||
// We need to augment at least with the boundary vertices when running in parallel
|
||||
localDataBlocks[bi]->computeRegularStructure = compRegularStruct;
|
||||
}
|
||||
|
||||
// Setup vtkmdiy to do global binary reduction of neighbouring blocks. See also RecuctionOperation struct for example
|
||||
|
||||
// Create the vtkmdiy master
|
||||
@ -784,7 +840,6 @@ VTKM_CONT void ContourTreePPP2::DoPostExecute(
|
||||
2, // raix of k-ary reduction. TODO check this value
|
||||
true // contiguous: true=distance doubling , false=distnace halving TODO check this value
|
||||
);
|
||||
|
||||
// reduction
|
||||
vtkmdiy::reduce(master, assigner, partners, &detail::merge_block_functor<T>);
|
||||
|
||||
@ -808,23 +863,32 @@ VTKM_CONT void ContourTreePPP2::DoPostExecute(
|
||||
contourTreeMeshOut.neighbours = localDataBlocks[0]->neighbours;
|
||||
contourTreeMeshOut.firstNeighbour = localDataBlocks[0]->firstNeighbour;
|
||||
contourTreeMeshOut.maxNeighbours = localDataBlocks[0]->maxNeighbours;
|
||||
//auto fieldPermutted = vtkm::cont::make_ArrayHandlePermutation(contourTreeMeshOut.sortOrder, contourTreeMeshOut.sortedValues);
|
||||
//vtkm::cont::Algorithm::Copy(fieldPermutted, currField);
|
||||
// Construct the mesh boundary exectuion object needed for boundary augmentation
|
||||
vtkm::Id3 minIdx(0, 0, 0);
|
||||
vtkm::Id3 maxIdx = this->MultiBlockTreeHelper->mSpatialDecomposition.mGlobalSize;
|
||||
maxIdx[0] = maxIdx[0] - 1;
|
||||
maxIdx[1] = maxIdx[1] - 1;
|
||||
maxIdx[2] = maxIdx[2] > 0 ? (maxIdx[2] - 1) : 0;
|
||||
auto meshBoundaryExecObj = contourTreeMeshOut.GetMeshBoundaryExecutionObject(
|
||||
this->MultiBlockTreeHelper->mSpatialDecomposition.mGlobalSize[0],
|
||||
this->MultiBlockTreeHelper->mSpatialDecomposition.mGlobalSize[1],
|
||||
minIdx,
|
||||
maxIdx);
|
||||
// Run the worklet to compute the final contour tree
|
||||
worklet.Run(
|
||||
contourTreeMeshOut
|
||||
.sortedValues, // This array is not really used we just need to provide something to keep the API happy currField,
|
||||
contourTreeMeshOut.sortedValues, // Unused param. Provide something to keep API happy
|
||||
contourTreeMeshOut,
|
||||
currTimings,
|
||||
this->ContourTreeData,
|
||||
this->MeshSortOrder,
|
||||
currNumIterations,
|
||||
this
|
||||
->ComputeRegularStructure // true // TODO eventually replace with boundary augmentation but for now compute the full regular structure
|
||||
);
|
||||
this->MeshSortOrder =
|
||||
contourTreeMeshOut.globalMeshIndex; // Set the final mesh sort order we need to use
|
||||
this->NumIterations = currNumIterations; // Remeber the number of iterations for the output
|
||||
this->ComputeRegularStructure,
|
||||
meshBoundaryExecObj);
|
||||
|
||||
// Set the final mesh sort order we need to use
|
||||
this->MeshSortOrder = contourTreeMeshOut.globalMeshIndex;
|
||||
// Remeber the number of iterations for the output
|
||||
this->NumIterations = currNumIterations;
|
||||
|
||||
// Return the sorted values of the contour tree as the result
|
||||
// TODO the result we return for the parallel and serial case are different right now. This should be made consistent. However, only in the parallel case are we useing the result output
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include <vtkm/worklet/contourtree_augmented/Mesh_DEM_Triangulation.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/ContourTreeMesh.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshBoundary.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -87,6 +88,11 @@ class ContourTreePPP2
|
||||
public:
|
||||
/*!
|
||||
* Run the contour tree to merge an existing set of contour trees
|
||||
*
|
||||
* meshBoundary : Is computed by calling mesh.GetMeshBoundaryExecutionObject.
|
||||
* It is technically only needed if computeRegularStructure==2.
|
||||
* computeRegularStructure : 0=Off, 1=full augmentation with all vertices
|
||||
* 2=boundary augmentation using meshBoundary
|
||||
*/
|
||||
template <typename FieldType, typename StorageType>
|
||||
void Run(const vtkm::cont::ArrayHandle<FieldType, StorageType>
|
||||
@ -96,7 +102,8 @@ public:
|
||||
contourtree_augmented::ContourTree& contourTree,
|
||||
contourtree_augmented::IdArrayType sortOrder,
|
||||
vtkm::Id& nIterations,
|
||||
bool computeRegularStructure = true)
|
||||
unsigned int computeRegularStructure,
|
||||
const contourtree_augmented::MeshBoundaryContourTreeMeshExec& meshBoundary)
|
||||
{
|
||||
RunContourTree(
|
||||
fieldArray, // Just a place-holder to fill the required field. Used when calling SortData on the contour tree which is a no-op
|
||||
@ -105,7 +112,8 @@ public:
|
||||
sortOrder,
|
||||
nIterations,
|
||||
mesh,
|
||||
computeRegularStructure);
|
||||
computeRegularStructure,
|
||||
meshBoundary);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -114,6 +122,9 @@ public:
|
||||
* allow one to run the contour tree in a consistent fashion independent
|
||||
* of whether the data is 2D, 3D, or 3D_MC. This function just calls
|
||||
* Run2D, Run3D, or Run3D_MC depending on the type
|
||||
*
|
||||
* computeRegularStructure : 0=Off, 1=full augmentation with all vertices
|
||||
* 2=boundary augmentation using meshBoundary
|
||||
*/
|
||||
template <typename FieldType, typename StorageType>
|
||||
void Run(const vtkm::cont::ArrayHandle<FieldType, StorageType> fieldArray,
|
||||
@ -125,7 +136,7 @@ public:
|
||||
const vtkm::Id nCols,
|
||||
const vtkm::Id nSlices = 1,
|
||||
bool useMarchingCubes = false,
|
||||
bool computeRegularStructure = true)
|
||||
unsigned int computeRegularStructure = 1)
|
||||
{
|
||||
using namespace vtkm::worklet::contourtree_augmented;
|
||||
// 2D Contour Tree
|
||||
@ -134,8 +145,14 @@ public:
|
||||
// Build the mesh and fill in the values
|
||||
Mesh_DEM_Triangulation_2D_Freudenthal<FieldType, StorageType> mesh(nRows, nCols);
|
||||
// Run the contour tree on the mesh
|
||||
RunContourTree(
|
||||
fieldArray, timings, contourTree, sortOrder, nIterations, mesh, computeRegularStructure);
|
||||
RunContourTree(fieldArray,
|
||||
timings,
|
||||
contourTree,
|
||||
sortOrder,
|
||||
nIterations,
|
||||
mesh,
|
||||
computeRegularStructure,
|
||||
mesh.GetMeshBoundaryExecutionObject());
|
||||
return;
|
||||
}
|
||||
// 3D Contour Tree using marching cubes
|
||||
@ -144,8 +161,14 @@ public:
|
||||
// Build the mesh and fill in the values
|
||||
Mesh_DEM_Triangulation_3D_MarchingCubes<FieldType, StorageType> mesh(nRows, nCols, nSlices);
|
||||
// Run the contour tree on the mesh
|
||||
RunContourTree(
|
||||
fieldArray, timings, contourTree, sortOrder, nIterations, mesh, computeRegularStructure);
|
||||
RunContourTree(fieldArray,
|
||||
timings,
|
||||
contourTree,
|
||||
sortOrder,
|
||||
nIterations,
|
||||
mesh,
|
||||
computeRegularStructure,
|
||||
mesh.GetMeshBoundaryExecutionObject());
|
||||
return;
|
||||
}
|
||||
// 3D Contour Tree with Freudenthal
|
||||
@ -154,8 +177,14 @@ public:
|
||||
// Build the mesh and fill in the values
|
||||
Mesh_DEM_Triangulation_3D_Freudenthal<FieldType, StorageType> mesh(nRows, nCols, nSlices);
|
||||
// Run the contour tree on the mesh
|
||||
RunContourTree(
|
||||
fieldArray, timings, contourTree, sortOrder, nIterations, mesh, computeRegularStructure);
|
||||
RunContourTree(fieldArray,
|
||||
timings,
|
||||
contourTree,
|
||||
sortOrder,
|
||||
nIterations,
|
||||
mesh,
|
||||
computeRegularStructure,
|
||||
mesh.GetMeshBoundaryExecutionObject());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -165,16 +194,32 @@ private:
|
||||
/*!
|
||||
* Run the contour tree for the given mesh. This function implements the main steps for
|
||||
* computing the contour tree after the mesh has been constructed using the approbrite
|
||||
* contour tree mesh class
|
||||
* contour tree mesh class.
|
||||
*
|
||||
* meshBoundary : This parameter is generated by calling mesh.GetMeshBoundaryExecutionObject
|
||||
* For regular 2D/3D meshes this required no extra parameters, however, for a
|
||||
* ContourTreeMesh additional information about the block must be given. Rather
|
||||
* than generating the MeshBoundary descriptor here, we therefore, require it
|
||||
* as an input. The MeshBoundary is used to augment the contour tree with the
|
||||
* mesh boundary vertices. It is needed only if we want to augement by the
|
||||
* mesh boundary and computeRegularStructure is False (i.e., if we compute
|
||||
* the full regular strucuture this is not needed because all vertices
|
||||
* (including the boundary) will be addded to the tree anyways.
|
||||
* computeRegularStructure : 0=Off, 1=full augmentation with all vertices
|
||||
* 2=boundary augmentation using meshBoundary
|
||||
*/
|
||||
template <typename FieldType, typename StorageType, typename MeshClass>
|
||||
template <typename FieldType,
|
||||
typename StorageType,
|
||||
typename MeshClass,
|
||||
typename MeshBoundaryClass>
|
||||
void RunContourTree(const vtkm::cont::ArrayHandle<FieldType, StorageType> fieldArray,
|
||||
std::vector<std::pair<std::string, vtkm::Float64>>& timings,
|
||||
contourtree_augmented::ContourTree& contourTree,
|
||||
contourtree_augmented::IdArrayType& sortOrder,
|
||||
vtkm::Id& nIterations,
|
||||
MeshClass& mesh,
|
||||
bool computeRegularStructure)
|
||||
unsigned int computeRegularStructure,
|
||||
const MeshBoundaryClass& meshBoundary)
|
||||
{
|
||||
using namespace vtkm::worklet::contourtree_augmented;
|
||||
// Stage 1: Load the data into the mesh. This is done in the Run() method above and accessible
|
||||
@ -259,12 +304,18 @@ private:
|
||||
timer.Start();
|
||||
|
||||
// 9.2 Then we compute the regular structure
|
||||
if (computeRegularStructure)
|
||||
if (computeRegularStructure == 1) // augment with all vertices
|
||||
{
|
||||
treeMaker.ComputeRegularStructure(extrema);
|
||||
timings.push_back(std::pair<std::string, vtkm::Float64>("Contour Tree Regular Structure",
|
||||
timer.GetElapsedTime()));
|
||||
}
|
||||
else if (computeRegularStructure == 2) // augment by the mesh boundary
|
||||
{
|
||||
treeMaker.ComputeBoundaryRegularStructure(extrema, mesh, meshBoundary);
|
||||
timings.push_back(std::pair<std::string, vtkm::Float64>(
|
||||
"Contour Tree Boundary Regular Structure", timer.GetElapsedTime()));
|
||||
}
|
||||
|
||||
// Collect the output data
|
||||
nIterations = treeMaker.nIterations;
|
||||
|
@ -211,7 +211,9 @@ inline void ContourTree::PrintContent() const
|
||||
printHeader(hypernodes.GetNumberOfValues());
|
||||
printIndices("Hypernodes", hypernodes);
|
||||
printIndices("Hyperarcs", hyperarcs);
|
||||
std::cout << std::endl;
|
||||
printHeader(augmentnodes.GetNumberOfValues());
|
||||
printIndices("Augmentnodes", augmentnodes);
|
||||
printIndices("Augmentarcs", augmentarcs);
|
||||
}
|
||||
|
||||
void ContourTree::DebugPrint(const char* message, const char* fileName, long lineNum)
|
||||
|
@ -90,7 +90,6 @@
|
||||
//VTKM includes
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayGetValues.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleImplicit.h>
|
||||
@ -139,11 +138,14 @@ public:
|
||||
// computes the hyperarcs in the contour tree
|
||||
void ComputeHyperAndSuperStructure();
|
||||
|
||||
// computes the regular arcs in the contour tree
|
||||
// computes the regular arcs in the contour tree. Augment the contour tree with all regular vertices.
|
||||
void ComputeRegularStructure(MeshExtrema& meshExtrema);
|
||||
|
||||
template <class Mesh>
|
||||
void ComputeRegularStructure(MeshExtrema& meshExtrema, const Mesh& mesh);
|
||||
// compute the parital regular arcs by augmenting the contour tree with the relevant vertices on the boundary
|
||||
template <class Mesh, class MeshBoundaryExecObj>
|
||||
void ComputeBoundaryRegularStructure(MeshExtrema& meshExtrema,
|
||||
const Mesh& mesh,
|
||||
const MeshBoundaryExecObj& meshBoundary);
|
||||
|
||||
// routine that augments the join & split tree with each other's supernodes
|
||||
// the augmented trees will be stored in the joinSuperarcs / mergeSuperarcs arrays
|
||||
@ -306,12 +308,17 @@ void ContourTreeMaker::ComputeHyperAndSuperStructure()
|
||||
contourTree.whenTransferred, oneIfHypernodeFunctor);
|
||||
vtkm::cont::Algorithm::ScanExclusive(oneIfHypernodeArrayHandle, newHypernodePosition);
|
||||
|
||||
auto getLastValue = [](const IdArrayType& ah) -> vtkm::Id {
|
||||
return vtkm::cont::ArrayGetValue(ah.GetNumberOfValues() - 1, ah);
|
||||
};
|
||||
|
||||
vtkm::Id nHypernodes = getLastValue(newHypernodePosition) +
|
||||
oneIfHypernodeFunctor(getLastValue(contourTree.whenTransferred));
|
||||
vtkm::Id nHypernodes = 0;
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> temp;
|
||||
temp.Allocate(2);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
newHypernodePosition, newHypernodePosition.GetNumberOfValues() - 1, 1, temp);
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
contourTree.whenTransferred, contourTree.whenTransferred.GetNumberOfValues() - 1, 1, temp, 1);
|
||||
auto portal = temp.GetPortalControl();
|
||||
nHypernodes = portal.Get(0) + oneIfHypernodeFunctor(portal.Get(1));
|
||||
}
|
||||
|
||||
IdArrayType newHypernodes;
|
||||
newHypernodes.Allocate(nHypernodes);
|
||||
@ -434,10 +441,12 @@ void InitIdArrayTypeNoSuchElement(IdArrayType& idArray, vtkm::Id size)
|
||||
vtkm::cont::Algorithm::Copy(noSuchElementArray, idArray);
|
||||
}
|
||||
|
||||
template <class Mesh>
|
||||
void ContourTreeMaker::ComputeRegularStructure(MeshExtrema& meshExtrema, const Mesh& mesh)
|
||||
template <class Mesh, class MeshBoundaryExecObj>
|
||||
void ContourTreeMaker::ComputeBoundaryRegularStructure(
|
||||
MeshExtrema& meshExtrema,
|
||||
const Mesh& mesh,
|
||||
const MeshBoundaryExecObj& meshBoundaryExecObj)
|
||||
{ // ComputeRegularStructure()
|
||||
|
||||
// First step - use the superstructure to set the superparent for all supernodes
|
||||
auto supernodesIndex = vtkm::cont::ArrayHandleIndex(contourTree.supernodes.GetNumberOfValues());
|
||||
IdArrayType superparents;
|
||||
@ -453,11 +462,7 @@ void ContourTreeMaker::ComputeRegularStructure(MeshExtrema& meshExtrema, const M
|
||||
// Second step - for all remaining (regular) nodes, locate the superarc to which they belong
|
||||
contourtree_maker_inc_ns::ComputeRegularStructure_LocateSuperarcsOnBoundary
|
||||
locateSuperarcsOnBoundaryWorklet(contourTree.hypernodes.GetNumberOfValues(),
|
||||
contourTree.supernodes.GetNumberOfValues(),
|
||||
mesh.nRows,
|
||||
mesh.nCols,
|
||||
mesh.nSlices,
|
||||
mesh.nDims);
|
||||
contourTree.supernodes.GetNumberOfValues());
|
||||
this->Invoke(locateSuperarcsOnBoundaryWorklet,
|
||||
superparents, // (input/output)
|
||||
contourTree.whenTransferred, // (input)
|
||||
@ -467,7 +472,7 @@ void ContourTreeMaker::ComputeRegularStructure(MeshExtrema& meshExtrema, const M
|
||||
contourTree.supernodes, // (input)
|
||||
meshExtrema.peaks, // (input)
|
||||
meshExtrema.pits, // (input)
|
||||
mesh.sortOrder); // (input)
|
||||
meshBoundaryExecObj); // (input)
|
||||
|
||||
// We have now set the superparent correctly for each node, and need to sort them to get the correct regular arcs
|
||||
// DAVID "ContourTreeMaker.h" line 338
|
||||
@ -493,7 +498,6 @@ void ContourTreeMaker::ComputeRegularStructure(MeshExtrema& meshExtrema, const M
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
superparents, superparents, tmpsuperparents, ContourTreeNoSuchElementSuperParents());
|
||||
vtkm::cont::Algorithm::Copy(tmpsuperparents, superparents);
|
||||
//superparents.erase(std::remove(superparents.begin(), superparents.end(), NO_SUCH_ELEMENT), superparents.end());
|
||||
|
||||
// Create array for sorting
|
||||
IdArrayType augmentnodes_sorted;
|
||||
@ -505,7 +509,6 @@ void ContourTreeMaker::ComputeRegularStructure(MeshExtrema& meshExtrema, const M
|
||||
vtkm::cont::Algorithm::Sort(
|
||||
augmentnodes_sorted,
|
||||
contourtree_maker_inc_ns::ContourTreeNodeComparator(superparents, contourTree.superarcs));
|
||||
|
||||
// now set the arcs based on the array
|
||||
InitIdArrayTypeNoSuchElement(contourTree.augmentarcs,
|
||||
contourTree.augmentnodes.GetNumberOfValues());
|
||||
@ -518,12 +521,10 @@ void ContourTreeMaker::ComputeRegularStructure(MeshExtrema& meshExtrema, const M
|
||||
contourTree.supernodes, // (input)
|
||||
toCompressed, // (input)
|
||||
contourTree.augmentarcs); // (output)
|
||||
|
||||
DebugPrint("Regular Structure Computed", __FILE__, __LINE__);
|
||||
DebugPrint("Regular Boundary Structure Computed", __FILE__, __LINE__);
|
||||
} // ComputeRegularStructure()
|
||||
|
||||
|
||||
|
||||
// routine that augments the join & split tree with each other's supernodes
|
||||
// the augmented trees will be stored in the joinSuperarcs / mergeSuperarcs arrays
|
||||
// the sort IDs will be stored in the ContourTree's arrays, &c.
|
||||
|
@ -398,6 +398,10 @@ public:
|
||||
|
||||
}; // ComputeRegularStructure_LocateSuperarcs.h
|
||||
|
||||
|
||||
|
||||
// TODO This algorithm looks to be a 3d/2d volume algorithm that is iterating 'points' and concerned about being on the 'boundary'. This would be better suited as WorkletMapPointNeighborhood as it can provide the boundary condition logic for you.
|
||||
|
||||
// Worklet for the second step of template <class Mesh> void ContourTreeMaker::ComputeRegularStructure ---
|
||||
// for all remaining (regular) nodes on the boundary, locate the superarc to which they belong
|
||||
class ComputeRegularStructure_LocateSuperarcsOnBoundary : public vtkm::worklet::WorkletMapField
|
||||
@ -411,7 +415,7 @@ public:
|
||||
WholeArrayIn contourTreeSupernodes, // (input)
|
||||
WholeArrayIn meshExtremaPeaks, // (input)
|
||||
WholeArrayIn meshExtremaPits, // (input)
|
||||
FieldIn meshSortOrderPortal); // (input)
|
||||
ExecObject meshBoundary); // (input)
|
||||
|
||||
typedef void ExecutionSignature(_1, InputIndex, _2, _3, _4, _5, _6, _7, _8, _9);
|
||||
using InputDomain = _1;
|
||||
@ -424,52 +428,13 @@ public:
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
ComputeRegularStructure_LocateSuperarcsOnBoundary(vtkm::Id NumHypernodes,
|
||||
vtkm::Id NumSupernodes,
|
||||
vtkm::Id _nRows,
|
||||
vtkm::Id _nCols,
|
||||
vtkm::Id _nSlices,
|
||||
vtkm::Id _nDims)
|
||||
ComputeRegularStructure_LocateSuperarcsOnBoundary(vtkm::Id NumHypernodes, vtkm::Id NumSupernodes)
|
||||
: numHypernodes(NumHypernodes)
|
||||
, numSupernodes(NumSupernodes)
|
||||
, nRows(_nRows)
|
||||
, nCols(_nCols)
|
||||
, nSlices(_nSlices)
|
||||
, nDims(_nDims)
|
||||
{
|
||||
}
|
||||
|
||||
vtkm::Id vertexRow(const vtkm::Id v) const { return (v % (nRows * nCols)) / nCols; }
|
||||
vtkm::Id vertexColumn(const vtkm::Id v) const { return v % nCols; }
|
||||
vtkm::Id vertexSlice(const vtkm::Id v) const { return v / (nRows * nCols); }
|
||||
|
||||
bool liesOnBoundary(const vtkm::Id meshSortOrderValue) const
|
||||
{
|
||||
if (nDims == 2)
|
||||
return liesOnBoundary2(meshSortOrderValue);
|
||||
else
|
||||
return liesOnBoundary3(meshSortOrderValue);
|
||||
}
|
||||
|
||||
bool liesOnBoundary2(const vtkm::Id meshSortOrderValue) const
|
||||
{
|
||||
const vtkm::Id v = meshSortOrderValue;
|
||||
const vtkm::Id row = vertexRow(v);
|
||||
const vtkm::Id col = vertexColumn(v);
|
||||
return (row == 0) || (col == 0) || (row == nRows - 1) || (col == nCols - 1);
|
||||
}
|
||||
|
||||
bool liesOnBoundary3(const vtkm::Id meshSortOrderValue) const
|
||||
{
|
||||
const vtkm::Id v = meshSortOrderValue;
|
||||
const vtkm::Id row = vertexRow(v);
|
||||
const vtkm::Id col = vertexColumn(v);
|
||||
const vtkm::Id sli = vertexSlice(v);
|
||||
return (row == 0) || (col == 0) || (sli == 0) || (row == nRows - 1) || (col == nCols - 1) ||
|
||||
(sli == nSlices - 1);
|
||||
}
|
||||
|
||||
template <typename InOutFieldPortalType, typename InFieldPortalType>
|
||||
template <typename InOutFieldPortalType, typename InFieldPortalType, typename MeshBoundaryType>
|
||||
VTKM_EXEC void operator()(const InOutFieldPortalType& contourTreeSuperparentsPortal,
|
||||
const vtkm::Id node,
|
||||
const InFieldPortalType& contourTreeWhenTransferredPortal,
|
||||
@ -479,12 +444,11 @@ public:
|
||||
const InFieldPortalType& contourTreeSupernodesPortal,
|
||||
const InFieldPortalType& meshExtremaPeaksPortal,
|
||||
const InFieldPortalType& meshExtremaPitsPortal,
|
||||
const vtkm::Id& meshSortOrderValue) const
|
||||
const MeshBoundaryType& meshBoundary) const
|
||||
{
|
||||
// per node
|
||||
// if the superparent is already set, it's a supernode, so skip it.
|
||||
if (noSuchElement(contourTreeSuperparentsPortal.Get(node)) &&
|
||||
liesOnBoundary(meshSortOrderValue))
|
||||
if (noSuchElement(contourTreeSuperparentsPortal.Get(node)) && meshBoundary.liesOnBoundary(node))
|
||||
{ // regular nodes only
|
||||
// we will need to prune top and bottom until one of them prunes past the node
|
||||
vtkm::Id top = meshExtremaPeaksPortal.Get(node);
|
||||
|
@ -16,6 +16,7 @@ set(headers
|
||||
MeshStructureFreudenthal3D.h
|
||||
MeshStructureMarchingCubes.h
|
||||
MeshStructureContourTreeMesh.h
|
||||
MeshBoundary.h
|
||||
)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include <vtkm/cont/EnvironmentTracker.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/ArrayTransforms.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshBoundary.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshStructureContourTreeMesh.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/contourtreemesh/ArcComparator.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/contourtreemesh/CombinedOtherStartIndexNNeighboursWorklet.h>
|
||||
@ -97,7 +98,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
#include <vtkm/thirdparty/diy/Configure.h>
|
||||
#include <vtkm/thirdparty/diy/diy.h>
|
||||
@ -127,12 +127,19 @@ public:
|
||||
|
||||
ContourTreeMesh() {}
|
||||
|
||||
// Constructors
|
||||
// Constructor
|
||||
ContourTreeMesh(const IdArrayType& arcs,
|
||||
const IdArrayType& inSortOrder,
|
||||
const vtkm::cont::ArrayHandle<FieldType>& values,
|
||||
const IdArrayType& inGlobalMeshIndex);
|
||||
|
||||
// Constructor
|
||||
ContourTreeMesh(const IdArrayType& nodes,
|
||||
const IdArrayType& arcs,
|
||||
const IdArrayType& inSortOrder,
|
||||
const vtkm::cont::ArrayHandle<FieldType>& values,
|
||||
const IdArrayType& inGlobalMeshIndex);
|
||||
|
||||
// Construct a ContourTreeMesh from nodes/arcs and another ContourTreeMesh (instead of a Mesh_DEM_Triangulation)
|
||||
// nodes/arcs: From the contour tree
|
||||
// ContourTreeMesh: the contour tree mesh used to compute the contour tree described by nodes/arcs
|
||||
@ -152,6 +159,8 @@ public:
|
||||
this->nVertices = this->sortedValues.GetNumberOfValues();
|
||||
}
|
||||
|
||||
vtkm::Id GetNumberOfVertices() const { return this->nVertices; }
|
||||
|
||||
// Combine two ContourTreeMeshes
|
||||
template <typename DeviceTag>
|
||||
void mergeWith(ContourTreeMesh<FieldType>& other);
|
||||
@ -193,6 +202,12 @@ public:
|
||||
// Debug print routine
|
||||
void DebugPrint(const char* message, const char* fileName, long lineNum);
|
||||
|
||||
// Get boundary execution object
|
||||
MeshBoundaryContourTreeMeshExec GetMeshBoundaryExecutionObject(vtkm::Id totalNRows,
|
||||
vtkm::Id totalNCols,
|
||||
vtkm::Id3 minIdx,
|
||||
vtkm::Id3 maxIdx) const;
|
||||
|
||||
private:
|
||||
vtkm::cont::Invoker Invoke;
|
||||
|
||||
@ -255,6 +270,7 @@ ContourTreeMesh<FieldType>::ContourTreeMesh(const IdArrayType& arcs,
|
||||
const vtkm::cont::ArrayHandle<FieldType>& values,
|
||||
const IdArrayType& inGlobalMeshIndex)
|
||||
: sortOrder(inSortOrder)
|
||||
, sortedValues()
|
||||
, globalMeshIndex(inGlobalMeshIndex)
|
||||
, neighbours()
|
||||
, firstNeighbour()
|
||||
@ -265,6 +281,39 @@ ContourTreeMesh<FieldType>::ContourTreeMesh(const IdArrayType& arcs,
|
||||
// TODO check if we actually need to make this copy here. we could just store the permutedValues array to save memory
|
||||
vtkm::cont::Algorithm::Copy(permutedValues, this->sortedValues);
|
||||
this->InitialiseNeighboursFromArcs(arcs);
|
||||
#ifdef DEBUG_PRINT
|
||||
// Print the contents fo this for debugging
|
||||
DebugPrint("ContourTreeMesh Initialized", __FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <typename FieldType>
|
||||
ContourTreeMesh<FieldType>::ContourTreeMesh(const IdArrayType& nodes,
|
||||
const IdArrayType& arcs,
|
||||
const IdArrayType& inSortOrder,
|
||||
const vtkm::cont::ArrayHandle<FieldType>& values,
|
||||
const IdArrayType& inGlobalMeshIndex)
|
||||
: globalMeshIndex(inGlobalMeshIndex)
|
||||
, neighbours()
|
||||
, firstNeighbour()
|
||||
{
|
||||
// Initialize the sortedValues array the values permutted by the sortOrder permutted by the nodes, i.e.,
|
||||
// this->sortedValues[v] = values[inSortOrder[nodes[v]]];
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayType, IdArrayType> permutedSortOrder(nodes,
|
||||
inSortOrder);
|
||||
auto permutedValues = vtkm::cont::make_ArrayHandlePermutation(permutedSortOrder, values);
|
||||
vtkm::cont::Algorithm::Copy(permutedValues, this->sortedValues);
|
||||
vtkm::cont::Algorithm::Copy(
|
||||
permutedSortOrder,
|
||||
this
|
||||
->sortOrder); // TODO Check if the sortOrder needs to be set form the input or the permutted sortOrder
|
||||
this->nVertices = this->sortedValues.GetNumberOfValues();
|
||||
this->InitialiseNeighboursFromArcs(arcs);
|
||||
#ifdef DEBUG_PRINT
|
||||
// Print the contents fo this for debugging
|
||||
DebugPrint("ContourTreeMesh Initialized", __FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename FieldType>
|
||||
@ -278,6 +327,10 @@ ContourTreeMesh<FieldType>::ContourTreeMesh(const IdArrayType& arcs,
|
||||
{
|
||||
this->nVertices = this->sortedValues.GetNumberOfValues();
|
||||
this->InitialiseNeighboursFromArcs(arcs);
|
||||
#ifdef DEBUG_PRINT
|
||||
// Print the contents fo this for debugging
|
||||
DebugPrint("ContourTreeMesh Initialized", __FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -285,7 +338,7 @@ template <typename FieldType>
|
||||
ContourTreeMesh<FieldType>::ContourTreeMesh(const IdArrayType& nodes,
|
||||
const IdArrayType& arcs,
|
||||
const ContourTreeMesh<FieldType>& mesh)
|
||||
: sortOrder(mesh.SortOrder)
|
||||
: sortOrder(mesh.sortOrder)
|
||||
, neighbours()
|
||||
, firstNeighbour()
|
||||
{
|
||||
@ -294,12 +347,15 @@ ContourTreeMesh<FieldType>::ContourTreeMesh(const IdArrayType& nodes,
|
||||
nodes, mesh.globalMeshIndex);
|
||||
vtkm::cont::Algorithm::Copy(permutedGlobalMeshIndex, this->globalMeshIndex);
|
||||
// Initialize the sortedValues array with the sortedValues permutted by the nodes
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayType, IdArrayType> permutedSortedValues(
|
||||
nodes, mesh.sortedValues);
|
||||
auto permutedSortedValues = vtkm::cont::make_ArrayHandlePermutation(nodes, mesh.sortedValues);
|
||||
vtkm::cont::Algorithm::Copy(permutedSortedValues, this->sortedValues);
|
||||
// Initialize the neighbours from the arcs
|
||||
this->nVertices = this->sortedValues.GetNumberOfValues();
|
||||
this->InitialiseNeighboursFromArcs(arcs);
|
||||
#ifdef DEBUG_PRINT
|
||||
// Print the contents fo this for debugging
|
||||
DebugPrint("ContourTreeMesh Initialized", __FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -598,7 +654,7 @@ void ContourTreeMesh<FieldType>::mergeWith(ContourTreeMesh<FieldType>& other)
|
||||
std::inplace_merge(
|
||||
neighboursBegin, neighboursBegin + combinedOtherStartIndexPortal.Get(vtx), neighboursEnd);
|
||||
auto it = std::unique(neighboursBegin, neighboursEnd);
|
||||
combinedOtherStartIndexPortal.Set(vtx, static_cast<vtkm::Id>(neighboursEnd - it));
|
||||
combinedOtherStartIndexPortal.Set(vtx, neighboursEnd - it);
|
||||
while (it != neighboursEnd)
|
||||
*(it++) = NO_SUCH_ELEMENT;
|
||||
}
|
||||
@ -725,6 +781,17 @@ void ContourTreeMesh<FieldType>::loadVector(std::istream& is,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FieldType>
|
||||
MeshBoundaryContourTreeMeshExec ContourTreeMesh<FieldType>::GetMeshBoundaryExecutionObject(
|
||||
vtkm::Id totalNRows,
|
||||
vtkm::Id totalNCols,
|
||||
vtkm::Id3 minIdx,
|
||||
vtkm::Id3 maxIdx) const
|
||||
{
|
||||
return MeshBoundaryContourTreeMeshExec(
|
||||
this->globalMeshIndex, totalNRows, totalNCols, minIdx, maxIdx);
|
||||
}
|
||||
|
||||
} // namespace contourtree_augmented
|
||||
} // worklet
|
||||
} // vtkm
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <vtkm/worklet/contourtree_augmented/Mesh_DEM_Triangulation.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshBoundary.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshStructureFreudenthal2D.h>
|
||||
|
||||
#include <vtkm/cont/ExecutionObjectBase.h>
|
||||
@ -84,6 +85,8 @@ public:
|
||||
|
||||
Mesh_DEM_Triangulation_2D_Freudenthal(vtkm::Id nrows, vtkm::Id ncols);
|
||||
|
||||
MeshBoundary2DExec GetMeshBoundaryExecutionObject() const;
|
||||
|
||||
private:
|
||||
bool useGetMax; // Define the behavior ofr the PrepareForExecution function
|
||||
}; // class Mesh_DEM_Triangulation
|
||||
@ -122,6 +125,12 @@ MeshStructureFreudenthal2D<DeviceTag>
|
||||
edgeBoundaryDetectionMasks);
|
||||
}
|
||||
|
||||
template <typename T, typename StorageType>
|
||||
MeshBoundary2DExec
|
||||
Mesh_DEM_Triangulation_2D_Freudenthal<T, StorageType>::GetMeshBoundaryExecutionObject() const
|
||||
{
|
||||
return MeshBoundary2DExec(this->nRows, this->nCols, this->sortOrder);
|
||||
}
|
||||
|
||||
} // namespace contourtree_augmented
|
||||
} // worklet
|
||||
|
@ -61,6 +61,7 @@
|
||||
|
||||
#include <vtkm/cont/ExecutionObjectBase.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Mesh_DEM_Triangulation.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshBoundary.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshStructureFreudenthal3D.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/freudenthal_3D/Types.h>
|
||||
|
||||
@ -89,6 +90,8 @@ public:
|
||||
|
||||
Mesh_DEM_Triangulation_3D_Freudenthal(vtkm::Id nrows, vtkm::Id ncols, vtkm::Id nslices);
|
||||
|
||||
MeshBoundary3DExec GetMeshBoundaryExecutionObject() const;
|
||||
|
||||
private:
|
||||
bool useGetMax; // Define the behavior ofr the PrepareForExecution function
|
||||
}; // class Mesh_DEM_Triangulation
|
||||
@ -138,6 +141,13 @@ MeshStructureFreudenthal3D<DeviceTag>
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename StorageType>
|
||||
MeshBoundary3DExec
|
||||
Mesh_DEM_Triangulation_3D_Freudenthal<T, StorageType>::GetMeshBoundaryExecutionObject() const
|
||||
{
|
||||
return MeshBoundary3DExec(this->nRows, this->nCols, this->nSlices, this->sortOrder);
|
||||
}
|
||||
|
||||
} // namespace contourtree_augmented
|
||||
} // worklet
|
||||
} // vtkm
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include <vtkm/cont/ExecutionObjectBase.h>
|
||||
|
||||
#include <vtkm/worklet/contourtree_augmented/Mesh_DEM_Triangulation.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshBoundary.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/MeshStructureMarchingCubes.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem_meshtypes/marchingcubes_3D/Types.h>
|
||||
|
||||
@ -93,6 +94,8 @@ public:
|
||||
|
||||
Mesh_DEM_Triangulation_3D_MarchingCubes(vtkm::Id nrows, vtkm::Id ncols, vtkm::Id nslices);
|
||||
|
||||
MeshBoundary3DExec GetMeshBoundaryExecutionObject() const;
|
||||
|
||||
private:
|
||||
bool useGetMax; // Define the behavior ofr the PrepareForExecution function
|
||||
}; // class Mesh_DEM_Triangulation
|
||||
@ -167,6 +170,13 @@ MeshStructureMarchingCubes<DeviceTag>
|
||||
inCubeConnectionsEighteen);
|
||||
}
|
||||
|
||||
template <typename T, typename StorageType>
|
||||
MeshBoundary3DExec
|
||||
Mesh_DEM_Triangulation_3D_MarchingCubes<T, StorageType>::GetMeshBoundaryExecutionObject() const
|
||||
{
|
||||
return MeshBoundary3DExec(this->nRows, this->nCols, this->nSlices, this->sortOrder);
|
||||
}
|
||||
|
||||
} // namespace contourtree_augmented
|
||||
} // worklet
|
||||
} // vtkm
|
||||
|
@ -0,0 +1,301 @@
|
||||
//============================================================================
|
||||
// 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)
|
||||
//==============================================================================
|
||||
|
||||
// This header contains a collection of classes used to describe the boundary
|
||||
// of a mesh, for each main mesh type (i.e., 2D, 3D, and ContourTreeMesh).
|
||||
// For each mesh type, there are two classes, the actual boundary desriptor
|
||||
// class and an ExectionObject class with the PrepareForInput function that
|
||||
// VTKm expects to generate the object for the execution environment.
|
||||
|
||||
#ifndef vtkm_worklet_contourtree_augmented_mesh_boundary_h
|
||||
#define vtkm_worklet_contourtree_augmented_mesh_boundary_h
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem/MeshStructure2D.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/mesh_dem/MeshStructure3D.h>
|
||||
|
||||
#include <vtkm/cont/ExecutionObjectBase.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_augmented
|
||||
{
|
||||
|
||||
|
||||
template <typename DeviceTag>
|
||||
class MeshBoundary2D
|
||||
{
|
||||
public:
|
||||
// Sort indicies types
|
||||
using sortOrderPortalType = typename IdArrayType::template ExecutionTypes<DeviceTag>::PortalConst;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundary2D()
|
||||
: MeshStructure(mesh_dem::MeshStructure2D<DeviceTag>(0, 0))
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundary2D(vtkm::Id nrows, vtkm::Id ncols, const IdArrayType& sortOrder)
|
||||
: MeshStructure(mesh_dem::MeshStructure2D<DeviceTag>(nrows, ncols))
|
||||
{
|
||||
sortOrderPortal = sortOrder.PrepareForInput(DeviceTag());
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
bool liesOnBoundary(const vtkm::Id index) const
|
||||
{
|
||||
vtkm::Id meshSortOrderValue = this->sortOrderPortal.Get(index);
|
||||
const vtkm::Id row = MeshStructure.vertexRow(meshSortOrderValue);
|
||||
const vtkm::Id col = MeshStructure.vertexColumn(meshSortOrderValue);
|
||||
|
||||
return (row == 0) || (col == 0) || (row == MeshStructure.nRows - 1) ||
|
||||
(col == MeshStructure.nCols - 1);
|
||||
}
|
||||
|
||||
private:
|
||||
// 2D Mesh size parameters
|
||||
mesh_dem::MeshStructure2D<DeviceTag> MeshStructure;
|
||||
sortOrderPortalType sortOrderPortal;
|
||||
};
|
||||
|
||||
class MeshBoundary2DExec : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundary2DExec(vtkm::Id nrows, vtkm::Id ncols, const IdArrayType& inSortOrder)
|
||||
: nRows(nrows)
|
||||
, nCols(ncols)
|
||||
, sortOrder(inSortOrder)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
template <typename DeviceTag>
|
||||
MeshBoundary2D<DeviceTag> PrepareForExecution(DeviceTag) const
|
||||
{
|
||||
return MeshBoundary2D<DeviceTag>(this->nRows, this->nCols, this->sortOrder);
|
||||
}
|
||||
|
||||
private:
|
||||
// 2D Mesh size parameters
|
||||
vtkm::Id nRows;
|
||||
vtkm::Id nCols;
|
||||
const IdArrayType& sortOrder;
|
||||
};
|
||||
|
||||
|
||||
template <typename DeviceTag>
|
||||
class MeshBoundary3D : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
public:
|
||||
// Sort indicies types
|
||||
using sortOrderPortalType = typename IdArrayType::template ExecutionTypes<DeviceTag>::PortalConst;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundary3D()
|
||||
: MeshStructure(mesh_dem::MeshStructure3D<DeviceTag>(0, 0, 0))
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundary3D(vtkm::Id nrows, vtkm::Id ncols, vtkm::Id nslices, const IdArrayType& sortOrder)
|
||||
: MeshStructure(mesh_dem::MeshStructure3D<DeviceTag>(nrows, ncols, nslices))
|
||||
{
|
||||
sortOrderPortal = sortOrder.PrepareForInput(DeviceTag());
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
bool liesOnBoundary(const vtkm::Id index) const
|
||||
{
|
||||
vtkm::Id meshSortOrderValue = this->sortOrderPortal.Get(index);
|
||||
const vtkm::Id row = MeshStructure.vertexRow(meshSortOrderValue);
|
||||
const vtkm::Id col = MeshStructure.vertexColumn(meshSortOrderValue);
|
||||
const vtkm::Id sli = MeshStructure.vertexSlice(meshSortOrderValue);
|
||||
return (row == 0) || (col == 0) || (sli == 0) || (row == MeshStructure.nRows - 1) ||
|
||||
(col == MeshStructure.nCols - 1) || (sli == MeshStructure.nSlices - 1);
|
||||
}
|
||||
|
||||
protected:
|
||||
// 3D Mesh size parameters
|
||||
mesh_dem::MeshStructure3D<DeviceTag> MeshStructure;
|
||||
sortOrderPortalType sortOrderPortal;
|
||||
};
|
||||
|
||||
|
||||
class MeshBoundary3DExec : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundary3DExec(vtkm::Id nrows,
|
||||
vtkm::Id ncols,
|
||||
vtkm::Id nslices,
|
||||
const IdArrayType& inSortOrder)
|
||||
: nRows(nrows)
|
||||
, nCols(ncols)
|
||||
, nSlices(nslices)
|
||||
, sortOrder(inSortOrder)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
template <typename DeviceTag>
|
||||
MeshBoundary3D<DeviceTag> PrepareForExecution(DeviceTag) const
|
||||
{
|
||||
return MeshBoundary3D<DeviceTag>(this->nRows, this->nCols, this->nSlices, this->sortOrder);
|
||||
}
|
||||
|
||||
protected:
|
||||
// 3D Mesh size parameters
|
||||
vtkm::Id nRows;
|
||||
vtkm::Id nCols;
|
||||
vtkm::Id nSlices;
|
||||
const IdArrayType& sortOrder;
|
||||
};
|
||||
|
||||
|
||||
template <typename DeviceTag>
|
||||
class MeshBoundaryContourTreeMesh
|
||||
{
|
||||
public:
|
||||
using IndicesPortalType = typename IdArrayType::template ExecutionTypes<DeviceTag>::PortalConst;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundaryContourTreeMesh() {}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundaryContourTreeMesh(const IdArrayType& globalMeshIndex,
|
||||
vtkm::Id totalNRows,
|
||||
vtkm::Id totalNCols,
|
||||
vtkm::Id3 minIdx,
|
||||
vtkm::Id3 maxIdx)
|
||||
: TotalNRows(totalNRows)
|
||||
, TotalNCols(totalNCols)
|
||||
, MinIdx(minIdx)
|
||||
, MaxIdx(maxIdx)
|
||||
{
|
||||
assert(TotalNRows > 0 && TotalNCols > 0);
|
||||
this->GlobalMeshIndexPortal = globalMeshIndex.PrepareForInput(DeviceTag());
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
bool liesOnBoundary(const vtkm::Id index) const
|
||||
{
|
||||
vtkm::Id idx = GlobalMeshIndexPortal.Get(index);
|
||||
vtkm::Id3 rcs;
|
||||
rcs[0] = vtkm::Id((idx % (this->TotalNRows * this->TotalNCols)) / this->TotalNCols);
|
||||
rcs[1] = vtkm::Id(idx % this->TotalNCols);
|
||||
rcs[2] = vtkm::Id(idx / (this->TotalNRows * this->TotalNCols));
|
||||
for (int d = 0; d < 3; ++d)
|
||||
{
|
||||
if (this->MinIdx[d] != this->MaxIdx[d] &&
|
||||
(rcs[d] == this->MinIdx[d] || rcs[d] == this->MaxIdx[d]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// mesh block parameters
|
||||
vtkm::Id TotalNRows;
|
||||
vtkm::Id TotalNCols;
|
||||
vtkm::Id3 MinIdx;
|
||||
vtkm::Id3 MaxIdx;
|
||||
IndicesPortalType GlobalMeshIndexPortal;
|
||||
};
|
||||
|
||||
|
||||
class MeshBoundaryContourTreeMeshExec : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT
|
||||
MeshBoundaryContourTreeMeshExec(const IdArrayType& globalMeshIndex,
|
||||
vtkm::Id totalNRows,
|
||||
vtkm::Id totalNCols,
|
||||
vtkm::Id3 minIdx,
|
||||
vtkm::Id3 maxIdx)
|
||||
: GlobalMeshIndex(globalMeshIndex)
|
||||
, TotalNRows(totalNRows)
|
||||
, TotalNCols(totalNCols)
|
||||
, MinIdx(minIdx)
|
||||
, MaxIdx(maxIdx)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
template <typename DeviceTag>
|
||||
MeshBoundaryContourTreeMesh<DeviceTag> PrepareForExecution(DeviceTag) const
|
||||
{
|
||||
return MeshBoundaryContourTreeMesh<DeviceTag>(
|
||||
GlobalMeshIndex, this->TotalNRows, this->TotalNCols, this->MinIdx, this->MaxIdx);
|
||||
}
|
||||
|
||||
private:
|
||||
const IdArrayType& GlobalMeshIndex;
|
||||
vtkm::Id TotalNRows;
|
||||
vtkm::Id TotalNCols;
|
||||
vtkm::Id3 MinIdx;
|
||||
vtkm::Id3 MaxIdx;
|
||||
};
|
||||
|
||||
|
||||
} // namespace contourtree_augmented
|
||||
} // worklet
|
||||
} // vtkm
|
||||
|
||||
#endif
|
@ -98,8 +98,12 @@ public:
|
||||
{
|
||||
return isThis(idx) ? this->thisVectorPortal.Get(maskedIndex(idx))
|
||||
: this->otherVectorPortal.Get(maskedIndex(idx));
|
||||
//std::cout<<"CV: idx="<<idx<<" isThis(idx)="<<isThis(idx)<<" maskedIndex(idx)="<<maskedIndex(idx)<<" thisSize="<<thisVectorPortal.GetNumberOfValues()<<" otherSize="<<otherVectorPortal.GetNumberOfValues()<<" thisVal="<< this->thisVectorPortal.Get(maskedIndex(idx))<<" otherVal="<<this->otherVectorPortal.Get(maskedIndex(idx))<< " result="<<val<<std::endl;
|
||||
//return val;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetNumberOfValues() const
|
||||
{
|
||||
return thisVectorPortal.GetNumberOfValues() + otherVectorPortal.GetNumberOfValues();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -124,6 +128,11 @@ public:
|
||||
return CombinedVector<T, DeviceTag>(this->thisVector, this->otherVector);
|
||||
}
|
||||
|
||||
vtkm::Id GetNumberOfValues() const
|
||||
{
|
||||
return thisVector.GetNumberOfValues() + otherVector.GetNumberOfValues();
|
||||
}
|
||||
|
||||
private:
|
||||
const vtkm::cont::ArrayHandle<T>& thisVector;
|
||||
const vtkm::cont::ArrayHandle<T>& otherVector;
|
||||
|
@ -100,7 +100,7 @@ public:
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType meshSortOrder;
|
||||
vtkm::Id numIterations;
|
||||
const bool useMarchingCubes = false;
|
||||
const bool computeRegularStructure = true;
|
||||
const int computeRegularStructure = 1;
|
||||
|
||||
contourTreeWorklet.Run(field,
|
||||
timings,
|
||||
@ -173,7 +173,7 @@ public:
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType meshSortOrder;
|
||||
vtkm::Id numIterations;
|
||||
const bool useMarchingCubes = false;
|
||||
const bool computeRegularStructure = true;
|
||||
const int computeRegularStructure = 1;
|
||||
|
||||
contourTreeWorklet.Run(field,
|
||||
timings,
|
||||
@ -253,7 +253,7 @@ public:
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType meshSortOrder;
|
||||
vtkm::Id numIterations;
|
||||
const bool useMarchingCubes = true;
|
||||
const bool computeRegularStructure = true;
|
||||
const int computeRegularStructure = 1;
|
||||
|
||||
contourTreeWorklet.Run(field,
|
||||
timings,
|
||||
|
Loading…
Reference in New Issue
Block a user