mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-19 10:35:42 +00:00
Port/implement HierarchicalHyperSweeper
This commit is contained in:
parent
7506068236
commit
a69f83f3a5
@ -74,6 +74,9 @@
|
||||
#include <vtkm/worklet/contourtree_distributed/SpatialDecomposition.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/TreeGrafter.h>
|
||||
|
||||
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalHyperSweeper.h>
|
||||
|
||||
// DIY includes
|
||||
// clang-format off
|
||||
VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
|
@ -15,6 +15,7 @@ set(headers
|
||||
ContourTreeBlockData.h
|
||||
DistributedContourTreeBlockData.h
|
||||
HierarchicalContourTree.h
|
||||
HierarchicalHyperSweeper.h
|
||||
InteriorForest.h
|
||||
MergeBlockFunctor.h
|
||||
MultiBlockContourTreeHelper.h
|
||||
@ -29,3 +30,4 @@ vtkm_declare_headers(${headers})
|
||||
add_subdirectory(boundary_tree_maker)
|
||||
add_subdirectory(tree_grafter)
|
||||
add_subdirectory(hierarchical_contour_tree)
|
||||
add_subdirectory(hierarchical_hyper_sweeper)
|
||||
|
712
vtkm/worklet/contourtree_distributed/HierarchicalHyperSweeper.h
Normal file
712
vtkm/worklet/contourtree_distributed/HierarchicalHyperSweeper.h
Normal file
@ -0,0 +1,712 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
//=======================================================================================
|
||||
//
|
||||
// Parallel Peak Pruning v. 2.0
|
||||
//
|
||||
// Started June 15, 2017
|
||||
//
|
||||
// Copyright Hamish Carr, University of Leeds
|
||||
//
|
||||
// HierarchicalHyperSweeper.h
|
||||
//
|
||||
//=======================================================================================
|
||||
//
|
||||
// COMMENTS:
|
||||
//
|
||||
// This class encapsulates a hypersweep over the hierarchical contour tree. It is a
|
||||
// separate class primarily to keep the post-processing separate from the main tree
|
||||
// construction, but it should also make it easier to generalise to arbitrary computations
|
||||
//
|
||||
// Basically, the way that this operates is:
|
||||
// 1. First, we do a local (standard) hypersweep over the hierarchical tree
|
||||
// 2. We then fan-in one round at a time. In each round,
|
||||
// a. We trade the prefix of the array with our logical partner, then
|
||||
// b. Combine the array prefix with our own
|
||||
//
|
||||
// Tactically, when we do MPI, we can either embed it in this unit, or leave it in the
|
||||
// calling unit. For ease of porting, we will leave all MPI in the calling unit, so
|
||||
// this unit only needs to do the combination.
|
||||
//
|
||||
// Note that we could define an operator to be passed in, and probably want to template it
|
||||
// that way in the future, but for now, we'll do the first version directly with addition
|
||||
//
|
||||
// By assumption, we need a commutative property, since we do not guarantee that we have
|
||||
// strict ordering along superarcs (which would require sharing a supernode sort with our
|
||||
// partner, if not globally)
|
||||
//
|
||||
//=======================================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_h
|
||||
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vtkm/worklet/contourtree_augmented/PrintVectors.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/data_set_mesh/IdRelabeler.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/HierarchicalContourTree.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/PrintGraph.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/ComputeSuperarcDependentWeightsWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/ComputeSuperarcTransferWeightsWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountComputeSuperparentIdsWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountInitalizeCountsWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountSubtractLowEndWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferTargetComperator.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateLHEWorklet.h>
|
||||
#include <vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateRHEWorklet.h>
|
||||
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
|
||||
// the class itself
|
||||
template <typename MeshType, typename FieldType>
|
||||
class HierarchicalHyperSweeper
|
||||
{ // class HierarchicalHyperSweeper
|
||||
public:
|
||||
// the tree that it hypersweeps over
|
||||
const HierarchicalContourTree<FieldType>& HierarchicalTree;
|
||||
|
||||
// the underlying mesh base block type
|
||||
const MeshType& BaseBlock;
|
||||
|
||||
// the Id of the base block (used for debug output)
|
||||
vtkm::Id BlockId;
|
||||
|
||||
// array of values being operated over (same size as supernode set)
|
||||
const vtkm::cont::ArrayHandle<FieldType>& SweepValues;
|
||||
|
||||
// these are working arrays, lifted up here for ease of debug code
|
||||
// Subranges of these arrays will be reused in the rounds / iterations rather than being reallocated
|
||||
// an array for temporary storage of the prefix sums
|
||||
vtkm::cont::ArrayHandle<FieldType> ValuePrefixSum;
|
||||
// two arrays for collecting targets of transfers
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType TransferTarget;
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType SortedTransferTarget;
|
||||
// an array for indirect sorting of sets of superarcs
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType SuperSortPermute;
|
||||
|
||||
/// Constructor
|
||||
/// @param[in] blockId The Id of the base block (used for debug output)
|
||||
/// @param[in] hierarchicalTree the tree that to hypersweeps over
|
||||
/// @param[in] baseBlock the underlying mesh base block type
|
||||
/// @param[in] sweepValues array of values being operated over (same size as supernode set)
|
||||
HierarchicalHyperSweeper<MeshType, FieldType>(
|
||||
vtkm::Id blockId,
|
||||
const HierarchicalContourTree<FieldType>& hierarchicalTree,
|
||||
const MeshType& baseBlock,
|
||||
const vtkm::cont::ArrayHandle<FieldType>& sweepValues);
|
||||
|
||||
/// Our routines to initialize the sweep need to be static (or externa)l if we are going to use the constructor
|
||||
/// to run the actual hypersweep
|
||||
/// @param[in] hierarchicalTree the tree that to hypersweeps over
|
||||
/// @param[in] baseBlock the underlying mesh base block to initialize from
|
||||
/// @param[in] localToGlobalIdRelabeler Id relabeler used to compute global indices from local mesh indices
|
||||
/// @param[out] superarcRegularCounts arrray for the output superarc regular counts
|
||||
static void InitializeRegularVertexCount(
|
||||
const HierarchicalContourTree<FieldType>& hierarchicalTree,
|
||||
const MeshType& baseBlock,
|
||||
const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler,
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType& superarcRegularCounts);
|
||||
|
||||
/// routine to do the local hypersweep using addition / subtraction
|
||||
/// The funtion use the ComputeSuperarcDependentWeights, ComputeSuperarcTransferWeights,
|
||||
/// and TransferWeights functions to carry out the local hyper sweep
|
||||
void LocalHyperSweep();
|
||||
|
||||
/// Debug routine to print contents of the HiearchicalHyperSweep
|
||||
/// @param[in] message Message to print along the debug output
|
||||
/// @param[in] fileName Name of the file the message is printed from. Usually set to __FILE__
|
||||
/// @param[in] lineNum Line number in the file where the message is printed from. Usually set to __LINE__
|
||||
std::string DebugPrint(std::string message, const char* fileName, long lineNum) const;
|
||||
|
||||
/// Routine to save the HierarchicalContourTree of this HierarchicalHyperSweeper to a Dot file
|
||||
/// @param[in] message Message included in the file
|
||||
/// @param[in] outFileName The name of the file to write the
|
||||
void SaveHierarchicalContourTreeDot(std::string message, const char* outFileName) const;
|
||||
|
||||
protected:
|
||||
// Functions used internally be LocalHyperSweep to compute the local hyper sweep
|
||||
|
||||
/// Routine to compute the correct weights dependent on each superarc in a subrange (defined by the round & iteration)
|
||||
void ComputeSuperarcDependentWeights(vtkm::Id round,
|
||||
vtkm::Id iteration,
|
||||
vtkm::Id firstSupernode,
|
||||
vtkm::Id lastSupernode);
|
||||
|
||||
/// routine to compute the weights to transfer to superarcs (defined by the round & iteration)
|
||||
void ComputeSuperarcTransferWeights(vtkm::Id round,
|
||||
vtkm::Id iteration,
|
||||
vtkm::Id firstSupernode,
|
||||
vtkm::Id lastSupernode);
|
||||
|
||||
/// routine to transfer the weights
|
||||
void TransferWeights(vtkm::Id round,
|
||||
vtkm::Id iteration,
|
||||
vtkm::Id firstSupernode,
|
||||
vtkm::Id lastSupernode);
|
||||
|
||||
private:
|
||||
/// Used internally to Invoke worklets
|
||||
vtkm::cont::Invoker Invoke;
|
||||
|
||||
}; // class HierarchicalHyperSweeper
|
||||
|
||||
|
||||
template <typename MeshType, typename FieldType>
|
||||
HierarchicalHyperSweeper<MeshType, FieldType>::HierarchicalHyperSweeper(
|
||||
vtkm::Id blockId,
|
||||
const HierarchicalContourTree<FieldType>& hierarchicalTree,
|
||||
const MeshType& baseBlock,
|
||||
const vtkm::cont::ArrayHandle<FieldType>& sweepValues)
|
||||
: HierarchicalTree(hierarchicalTree)
|
||||
, BaseBlock(baseBlock)
|
||||
, BlockId(blockId)
|
||||
, SweepValues(sweepValues)
|
||||
{ // constructor
|
||||
// Initalize arrays with 0s
|
||||
vtkm::cont::ArrayHandleConstant<vtkm::Id> tempZeroArray(
|
||||
0, this->HierarchicalTree.Supernodes.GetNumberOfValues());
|
||||
vtkm::cont::Algorithm::Copy(tempZeroArray, this->ValuePrefixSum);
|
||||
vtkm::cont::Algorithm::Copy(tempZeroArray, this->TransferTarget);
|
||||
vtkm::cont::Algorithm::Copy(tempZeroArray, this->SortedTransferTarget);
|
||||
// initialise the supersortPermute to the identity
|
||||
vtkm::cont::ArrayHandleIndex tempIndexArray(
|
||||
this->HierarchicalTree.Supernodes.GetNumberOfValues());
|
||||
vtkm::cont::Algorithm::Copy(tempIndexArray, this->SuperSortPermute);
|
||||
} // constructor
|
||||
|
||||
|
||||
// static function used to compute the initial superarc regular counts
|
||||
template <typename MeshType, typename FieldType>
|
||||
void HierarchicalHyperSweeper<MeshType, FieldType>::InitializeRegularVertexCount(
|
||||
const HierarchicalContourTree<FieldType>& hierarchicalTree,
|
||||
const MeshType& baseBlock,
|
||||
const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler,
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType& superarcRegularCounts)
|
||||
{ // InitializeRegularVertexCount()
|
||||
// TODO: Implement this function
|
||||
vtkm::cont::Invoker
|
||||
localInvoke; // Needed because this a static function so we can't use the invoke from the object
|
||||
// I. Call the mesh to get a list of all regular vertices belonging to the block by global Id
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType globalIds;
|
||||
baseBlock.GetOwnedVerticesByGlobalId(localToGlobalIdRelabeler, globalIds);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
{
|
||||
std::stringstream debugStream;
|
||||
debugStream << std::endl << "Owned Regular Vertex List";
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(globalIds.GetNumberOfValues(), debugStream);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices("GlobalId", globalIds, debugStream);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, debugStream.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// II. Look up the global Ids in the hierarchical tree & convert to superparent Ids
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType superparents;
|
||||
{ // scope to make sure temporary variables are deleted
|
||||
auto findRegularByGlobal = hierarchicalTree.GetFindRegularByGlobal();
|
||||
auto computeSuperparentIdsWorklet = vtkm::worklet::contourtree_distributed::
|
||||
hierarchical_hyper_sweeper::InitializeRegularVertexCountComputeSuperparentIdsWorklet();
|
||||
localInvoke(computeSuperparentIdsWorklet, // worklet to run
|
||||
globalIds, // input
|
||||
findRegularByGlobal, // input
|
||||
hierarchicalTree.Regular2Supernode, // input
|
||||
hierarchicalTree.Superparents, // input
|
||||
superparents // output
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
{
|
||||
std::stringstream debugStream;
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices("Superparents", superparents, debugStream);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, debugStream.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// III. Sort the superparent Ids & count the copies of each
|
||||
vtkm::cont::Algorithm ::Sort(superparents);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
{
|
||||
std::stringstream debugStream;
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices("Sorted SP", superparents, debugStream);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, debugStream.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// initialize the counts to zero.
|
||||
vtkm::cont::Algorithm::Copy(
|
||||
vtkm::cont::ArrayHandleConstant<vtkm::Id>(static_cast<vtkm::Id>(0),
|
||||
hierarchicalTree.Supernodes.GetNumberOfValues()),
|
||||
superarcRegularCounts);
|
||||
{ // scope to make sure temporary variables are deleted
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
|
||||
InitializeRegularVertexCountInitalizeCountsWorklet initalizeCountsWorklet;
|
||||
// set the count to the Id one off the high end of each range
|
||||
localInvoke(initalizeCountsWorklet, // worklet
|
||||
superparents, // input domain
|
||||
superarcRegularCounts // output
|
||||
);
|
||||
}
|
||||
|
||||
// now repeat to subtract out the low end
|
||||
{
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
|
||||
InitializeRegularVertexCountSubtractLowEndWorklet subtractLowEndWorklet;
|
||||
localInvoke(subtractLowEndWorklet, // worklet
|
||||
superparents, // input domain
|
||||
superarcRegularCounts // output
|
||||
);
|
||||
}
|
||||
// and that is that
|
||||
#ifdef DEBUG_PRINT
|
||||
{
|
||||
std::stringstream debugStream;
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"SuperarcRegularCounts", superarcRegularCounts, debugStream);
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, debugStream.str());
|
||||
}
|
||||
#endif
|
||||
} // InitializeRegularVertexCount()
|
||||
|
||||
|
||||
// routine to do the local hypersweep using addition / subtraction
|
||||
template <typename MeshType, typename FieldType>
|
||||
void HierarchicalHyperSweeper<MeshType, FieldType>::LocalHyperSweep()
|
||||
{ // LocalHyperSweep()
|
||||
// TODO: Implement this function
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
DebugPrint(std::string("Hypersweep Block ") + std::to_string(blockId) +
|
||||
std::string(" Starting Local HyperSweep"),
|
||||
__FILE__,
|
||||
__LINE__));
|
||||
#endif
|
||||
|
||||
// I. Iterate over all rounds of the hyperstructure
|
||||
for (vtkm::Id round = 0; round <= this->hierarchicalTree.NumRounds; round++)
|
||||
{ // per round
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
DebugPrint(std::string("Hypersweep Block ") + std::to_string(blockId) +
|
||||
std::string(" Round ") + std::to_string(round) +
|
||||
std::string(" Step 0 Starting Round"),
|
||||
__FILE__,
|
||||
__LINE__));
|
||||
#endif
|
||||
// A. Iterate over all iterations of the round
|
||||
for (vtkm::Id iteration = 0; iteration < this->HierarchicalTree.NumIterations[round];
|
||||
iteration++)
|
||||
{ // per iteration
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
DebugPrint(std::string("Hypersweep Block ") + std::to_string(blockId) +
|
||||
std::string(" Round ") + std::to_string(round) +
|
||||
std::string(" Step 1 Iteration ") + std::to_string(iteration) +
|
||||
std::string(" Step A Starting Iteration"),
|
||||
__FILE__,
|
||||
__LINE__));
|
||||
#endif
|
||||
// 1. Establish the range of supernode Ids that we want to process
|
||||
vtkm::Id firstSupernode = this->HierarchicalTree.FirstSupernodePerIteration[round][iteration];
|
||||
vtkm::Id lastSupernode =
|
||||
this->HierarchicalTree.FirstSupernodePerIteration[round][iteration + 1];
|
||||
|
||||
// call the routine that computes the dependent weights for each superarc in that range
|
||||
this->ComputeSuperarcDependentWeights(round, iteration, firstSupernode, lastSupernode);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
DebugPrint(std::string("Hypersweep Block ") + std::to_string(blockId) +
|
||||
std::string(" Round ") + std::to_string(round) +
|
||||
std::string(" Step 1 Iteration ") + std::to_string(iteration) +
|
||||
std::string(" Step B Dependent Weights Computed"),
|
||||
__FILE__,
|
||||
__LINE__));
|
||||
#endif
|
||||
// now call the routine that computes the weights to be transferred and the superarcs to which they transfer
|
||||
this->ComputeSuperarcTransferWeights(round, iteration, firstSupernode, lastSupernode);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
DebugPrint(std::string("Hypersweep Block ") + std::to_string(blockId) +
|
||||
std::string(" Round ") + std::to_string(round) +
|
||||
std::string(" Step 1 Iteration ") + std::to_string(iteration) +
|
||||
std::string(" Step C Transfer Weights Computed"),
|
||||
__FILE__,
|
||||
__LINE__));
|
||||
#endif
|
||||
|
||||
// transfer the weights
|
||||
this->TransferWeights(round, iteration, firstSupernode, lastSupernode);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
DebugPrint(std::string("Hypersweep Block ") + std::to_string(blockId) +
|
||||
std::string(" Round ") + std::to_string(round) +
|
||||
std::string(" Step 1 Iteration ") + std::to_string(iteration) +
|
||||
std::string(" Step D Weights Transferred"),
|
||||
__FILE__,
|
||||
__LINE__));
|
||||
#endif
|
||||
} // per iteration
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
DebugPrint(std::string("Hypersweep Block ") + std::to_string(blockId) +
|
||||
std::string(" Round ") + std::to_string(round) +
|
||||
std::string(" Step 2 Ending Round"),
|
||||
__FILE__,
|
||||
__LINE__));
|
||||
#endif
|
||||
} // per round
|
||||
} // LocalHyperSweep()
|
||||
|
||||
|
||||
// routine to compute the correct weights dependent on each superarc in a subrange (defined by the round & iteration)
|
||||
template <typename MeshType, typename FieldType>
|
||||
void HierarchicalHyperSweeper<MeshType, FieldType>::ComputeSuperarcDependentWeights(
|
||||
vtkm::Id round,
|
||||
vtkm::Id iteration,
|
||||
vtkm::Id firstSupernode,
|
||||
vtkm::Id lastSupernode)
|
||||
{ // ComputeSuperarcDependentWeights()
|
||||
(void)
|
||||
iteration; // avoid compiler warning for unused parmeter. Kept parameter in case we need it for debugging.
|
||||
|
||||
// 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);
|
||||
{
|
||||
vtkm::Id numValuesToCopy = lastSupernode - firstSupernode;
|
||||
// SweepValues[firstSuperNode, lastSupernode)
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType> sweepValuesView(
|
||||
this->SweepValues, // subset SweepValues
|
||||
firstSupernode, // start at firstSupernode
|
||||
numValuesToCopy); // until lastSuperNode (not inclued)
|
||||
// Target array
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
valuePrefixSumView(this->ValuePrefixSum, // subset SweepValues
|
||||
firstSupernode, // start at firstSupernode
|
||||
numValuesToCopy); // until lastSuperNode (not inclued)
|
||||
// Compute the partial sum for SweepValues[firstSuperNode, lastSupernode) and write to ValuePrefixSum[firstSuperNode, lastSupernode)
|
||||
vtkm::cont::Algorithm::ScanInclusive(sweepValuesView, // 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
|
||||
// b. Attachment points (which don't have a corresponding hyperarc)
|
||||
// and they can be mixed in any given iteration
|
||||
|
||||
// Since we have the prefix sum in a separate array, we avoid read/write conflicts
|
||||
|
||||
// 3. Compute the segmented weights from the prefix sum array
|
||||
{
|
||||
// Create views of the subranges of the arrays we need to update
|
||||
vtkm::Id numValuesToProcess = lastSupernode - firstSupernode;
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> supernodeIndex(
|
||||
firstSupernode, static_cast<vtkm::Id>(1), numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
hierarchicalTreeSuperarcsView(
|
||||
this->HierarchicalTree.Superarcs, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
hierarchicalTreeHyperparentsView(
|
||||
this->HierarchicalTree.Hyperparents, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
hierarchicalTreeHypernodesView(
|
||||
this->HierarchicalTree.Hypernodes, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType> sweepValuesView(
|
||||
this->SweepValues, firstSupernode, numValuesToProcess);
|
||||
// create the worklet
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
|
||||
ComputeSuperarcDependentWeightsWorklet<FieldType>
|
||||
computeSuperarcDependentWeightsWorklet(
|
||||
firstSupernode, round, this->HierarchicalTree.NumRounds);
|
||||
// Execute the worklet
|
||||
this->Invoke(
|
||||
computeSuperarcDependentWeightsWorklet, // the worklet
|
||||
supernodeIndex, // input counting index [firstSupernode, lastSupernode)
|
||||
hierarchicalTreeSuperarcsView, // input view of hierarchicalTree.Superarcs[firstSupernode, lastSupernode)
|
||||
hierarchicalTreeHyperparentsView, // input view of hierarchicalTree.Hyperparents[firstSupernode, lastSupernode)
|
||||
this->hierarchicalTree.Hypernodes, // input full hierarchicalTree.Hypernodes array
|
||||
this->ValuePrefixSum, // input full ValuePrefixSum array
|
||||
sweepValuesView // output view of sweepValues[firstSu
|
||||
);
|
||||
}
|
||||
} // ComputeSuperarcDependentWeights()
|
||||
|
||||
|
||||
// routine to compute the weights to transfer to superarcs (defined by the round & iteration)
|
||||
template <typename MeshType, typename FieldType>
|
||||
void HierarchicalHyperSweeper<MeshType, FieldType>::ComputeSuperarcTransferWeights(
|
||||
vtkm::Id round,
|
||||
vtkm::Id iteration,
|
||||
vtkm::Id firstSupernode,
|
||||
vtkm::Id lastSupernode)
|
||||
{ // ComputeSuperarcTransferWeights()
|
||||
(void)
|
||||
iteration; // avoid compiler warning for unused parmeter. Kept parameter in case we need it for debugging.
|
||||
|
||||
// At this stage, we would otherwise transfer weights by hyperarc, but attachment points don't *have* hyperarcs
|
||||
// so we will do a transfer by superarc instead, making sure that we only transfer from the last superarc in each
|
||||
// hyperarc, plus for any attachment point
|
||||
|
||||
// 4. Set the amount each superarc wants to transfer, reusing the valuePrefixSum array for the purpose
|
||||
// and the transfer target
|
||||
{ // scope ComputeSuperarcTransferWeightsWorklet to make sure temp variables are cleared
|
||||
// Create ArrayHandleViews of the subrange of values that we need to update
|
||||
vtkm::Id numValuesToProcess = lastSupernode - firstSupernode;
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> supernodeIndex(
|
||||
firstSupernode, static_cast<vtkm::Id>(1), numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
hierarchicalTreeSupernodesView(
|
||||
this->HierarchicalTree.Supernodes, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
hierarchicalTreeSuperarcsView(
|
||||
this->HierarchicalTree.Superarcs, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
transferTargetView(this->transferTarget, firstSupernode, numValuesToProcess);
|
||||
// instantiate the worklet
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
|
||||
ComputeSuperarcTransferWeightsWorklet computeSuperarcTransferWeightsWorklet(
|
||||
round, this->HierarchicalTree.NumRounds, lastSupernode);
|
||||
// call the worklet
|
||||
this->Invoke(
|
||||
computeSuperarcTransferWeightsWorklet, // worklet
|
||||
supernodeIndex, // input counting array [firstSupernode, lastSupernode)
|
||||
hierarchicalTreeSupernodesView, // input view of hierarchicalTree.supernodes[firstSupernode, lastSupernode)
|
||||
this->HierarchicalTree.Superparents, // input whole array of hierarchicalTree.superparents
|
||||
this->HierarchicalTree.Hyperparents, // input whole array of hierarchicalTree.hyperparents
|
||||
hierarchicalTreeSuperarcsView, // input/output view of hierarchicalTree.superarcs[firstSupernode, lastSupernode)
|
||||
transferTargetView // input view of transferTarget[firstSupernode, lastSupernode)
|
||||
);
|
||||
} // scope ComputeSuperarcTransferWeightsWorklet
|
||||
|
||||
// 5. Now we need to sort the transfer targets into contiguous segments
|
||||
{
|
||||
// create view of superSortPermute[firstSupernode, lastSupernode) for sorting
|
||||
vtkm::Id numValuesToProcess = lastSupernode - firstSupernode;
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
superSortPermuteView(this->SuperSortPermute, firstSupernode, numValuesToProcess);
|
||||
// create comperator for the sort
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::TransferTargetComperator
|
||||
transferTargetComperator(this->transferTarget);
|
||||
// sort the subrange of our array
|
||||
vtkm::cont::Algorithm::Sort(superSortPermuteView, transferTargetComperator);
|
||||
}
|
||||
|
||||
// 6. The [first,last] subrange is now permuted, so we can copy the transfer targets and weights into arrays
|
||||
// The following code block implements the following for loop using fancy array handles and copy
|
||||
// for (vtkm::Id supernode = firstSupernode; supernode < lastSupernode; supernode++)
|
||||
// {
|
||||
// sortedTransferTarget[supernode] = transferTarget[superSortPermute[supernode]];
|
||||
// valuePrefixSum[supernode] = sweepValues[superSortPermute[supernode]];
|
||||
// }
|
||||
{
|
||||
// copy transfer target in the sorted order
|
||||
vtkm::Id numValuesToProcess = lastSupernode - firstSupernode;
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
sortedTransferTargetView(this->SortedTransferTarget, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
superSortPermuteView(this->SuperSortPermute, firstSupernode, numValuesToProcess);
|
||||
auto permutedTransferTarget =
|
||||
vtkm::cont::make_ArrayHandlePermutation(superSortPermuteView, // idArray
|
||||
this->TransferTarget); // valueArray
|
||||
vtkm::cont::Algorithm::Copy(permutedTransferTarget, sortedTransferTargetView);
|
||||
// Note that any values associated with NO_SUCH_ELEMENT will be ignored
|
||||
// copy transfer weight in the sorted order
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
valuePrefixSumView(this->ValuePrefixSum, firstSupernode, numValuesToProcess);
|
||||
auto permutedSweepValues =
|
||||
vtkm::cont::make_ArrayHandlePermutation(superSortPermuteView, // idArray
|
||||
this->SweepValues); // valueArray
|
||||
vtkm::cont::Algorithm::Copy(permutedSweepValues, valuePrefixSumView);
|
||||
}
|
||||
} // ComputeSuperarcTransferWeights()
|
||||
|
||||
|
||||
// routine to transfer the weights
|
||||
template <typename MeshType, typename FieldType>
|
||||
void HierarchicalHyperSweeper<MeshType, FieldType>::TransferWeights(vtkm::Id round,
|
||||
vtkm::Id iteration,
|
||||
vtkm::Id firstSupernode,
|
||||
vtkm::Id lastSupernode)
|
||||
{ // TransferWeights()
|
||||
// avoid compiler warning for unused parmeters. Kept parameters in case we need it for debugging.
|
||||
(void)round;
|
||||
(void)iteration;
|
||||
|
||||
// 7. Now perform a segmented prefix sum
|
||||
// Same as std::partial_sum(valuePrefixSum.begin() + firstSupernode, valuePrefixSum.begin() + lastSupernode, valuePrefixSum.begin() + firstSupernode);
|
||||
{
|
||||
vtkm::Id numValuesToCopy = lastSupernode - firstSupernode;
|
||||
// ValuePrefixSum[firstSuperNode, lastSupernode)
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
valuePrefixSumView(this->ValuePrefixSum, // subset ValuePrefixSum
|
||||
firstSupernode, // start at firstSupernode
|
||||
numValuesToCopy); // until lastSuperNode (not inclued)
|
||||
// TODO: If it is safe to use the same array as input and output for ScanInclusive then this code should be updated to avoid the extra copy
|
||||
// In this case our traget array is the same as our source array. For safety we
|
||||
// store the values of our prefix sum in a temporary arrya and then copy the values
|
||||
// back into our valuePrefixSumView at the end
|
||||
vtkm::cont::ArrayHandle<FieldType> tempScanInclusiveTarget;
|
||||
tempScanInclusiveTarget.Allocate(numValuesToCopy);
|
||||
// Compute the partial sum for SweepValues[firstSuperNode, lastSupernode) and write to ValuePrefixSum[firstSuperNode, lastSupernode)
|
||||
vtkm::cont::Algorithm::ScanInclusive(valuePrefixSumView, // input
|
||||
tempScanInclusiveTarget); // result of partial sum
|
||||
// Now copy the values from our prefix sum back
|
||||
vtkm::cont::Algorithm::Copy(tempScanInclusiveTarget, valuePrefixSumView);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 7a. and 7b.
|
||||
{
|
||||
// Prepare the approbriate array views for our worklet. This is done to allow us to
|
||||
// use FieldIn instead of having to transfer the entire array to the device when we
|
||||
// really only need a subrange
|
||||
vtkm::Id numValuesToProcess = lastSupernode - firstSupernode;
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> supernodeIndex(
|
||||
firstSupernode, static_cast<vtkm::Id>(1), numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
sortedTransferTargetView(this->SortedTransferTarget, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
sortedTransferTargetShiftedView(
|
||||
this->SortedTransferTarget, firstSupernode + 1, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
valuePrefixSumView(this->ValuePrefixSum, firstSupernode, numValuesToProcess);
|
||||
vtkm::cont::ArrayHandleView<vtkm::worklet::contourtree_augmented::IdArrayType>
|
||||
valuePrefixSumShiftedView(this->ValuePrefixSum, firstSupernode - 1, numValuesToProcess);
|
||||
auto sweepValuePermuted =
|
||||
vtkm::cont::make_ArrayHandlePermutation(sortedTransferTargetView, // idArray
|
||||
this->SweepValues); // valueArray
|
||||
|
||||
// 7a. Find the RHE of each group and transfer the prefix sum weight
|
||||
// Note that we do not compute the transfer weight separately, we add it in place instead
|
||||
// Instantiate the worklet
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
|
||||
TransferWeightsUpdateRHEWorklet transferWeightsUpdateRHEWorklet(lastSupernode);
|
||||
// Invoke the worklet
|
||||
this->Invoke(
|
||||
transferWeightsUpdateRHEWorklet, // worklet
|
||||
supernodeIndex, // input counting array [firstSupernode, lastSupernode)
|
||||
sortedTransferTargetView, // input view of sortedTransferTarget[firstSupernode, lastSupernode)
|
||||
sortedTransferTargetShiftedView, // input view of sortedTransferTarget[firstSupernode+1, lastSupernode+1)
|
||||
valuePrefixSumView, // input view of valuePrefixSum[firstSupernode, lastSupernode)
|
||||
sweepValuePermuted // output view of sweepValues permuted by sortedTransferTarget[firstSupernode, lastSupernode). Use FieldInOut since we don't overwrite all values.
|
||||
);
|
||||
|
||||
// 7b. Now find the LHE of each group and subtract out the prior weight
|
||||
vtkm::worklet::contourtree_distributed::hierarchical_hyper_sweeper::
|
||||
TransferWeightsUpdateLHEWorklet transferWeightsUpdateLHEWorklet(firstSupernode);
|
||||
this->Invoke(
|
||||
transferWeightsUpdateLHEWorklet, // worklet
|
||||
supernodeIndex, // input counting array [firstSupernode, lastSupernode)
|
||||
sortedTransferTargetView, // input view of sortedTransferTarget[firstSupernode, lastSupernode)
|
||||
sortedTransferTargetShiftedView, // input view of sortedTransferTarget[firstSupernode+1, lastSupernode+1)
|
||||
valuePrefixSumShiftedView, // input view of valuePrefixSum[firstSupernode-1, lastSupernode-1)
|
||||
sweepValuePermuted // output view of sweepValues permuted by sortedTransferTarget[firstSupernode, lastSupernode). Use FieldInOut since we don't overwrite all values.
|
||||
);
|
||||
}
|
||||
} // TransferWeights()
|
||||
|
||||
|
||||
// debug routine
|
||||
template <typename MeshType, typename FieldType>
|
||||
std::string HierarchicalHyperSweeper<MeshType, FieldType>::DebugPrint(std::string message,
|
||||
const char* fileName,
|
||||
long lineNum) const
|
||||
{ // DebugPrint()
|
||||
std::stringstream resultStream;
|
||||
resultStream << std::endl;
|
||||
resultStream << "----------------------------------------" << std::endl;
|
||||
resultStream << std::setw(30) << std::left << fileName << ":" << std::right << std::setw(4)
|
||||
<< lineNum << std::endl;
|
||||
resultStream << std::left << message << std::endl;
|
||||
resultStream << "Hypersweep Value Array Contains: " << std::endl;
|
||||
resultStream << "----------------------------------------" << std::endl;
|
||||
resultStream << std::endl;
|
||||
|
||||
vtkm::worklet::contourtree_augmented::PrintHeader(this->SweepValues.GetNumberOfValues(),
|
||||
resultStream);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices("Volume", this->SweepValues, -1, resultStream);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"Prefix Sum", this->ValuePrefixSum - 1, resultStream);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"Transfer To", this->TransferTarget - 1, resultStream);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"Sorted Transfer", this->SortedTransferTarget - 1, resultStream);
|
||||
vtkm::worklet::contourtree_augmented::PrintIndices(
|
||||
"Sort Permute", this->SuperSortPermute - 1, resultStream);
|
||||
} // DebugPrint()
|
||||
|
||||
|
||||
// Routine to save the hierarchical tree to file
|
||||
template <typename MeshType, typename FieldType>
|
||||
void HierarchicalHyperSweeper<MeshType, FieldType>::SaveHierarchicalContourTreeDot(
|
||||
std::string message,
|
||||
const char* outFileName) const
|
||||
{ // SaveHierarchicalContourTreeDot()
|
||||
std::string hierarchicalTreeDotString =
|
||||
HierarchicalContourTreeDotGraphPrint<vtkm::worklet::contourtree_augmented::IdArrayType>(
|
||||
message,
|
||||
this->HierarchicalTree,
|
||||
SHOW_SUPER_STRUCTURE | SHOW_HYPER_STRUCTURE | SHOW_ALL_IDS | SHOW_ALL_SUPERIDS |
|
||||
SHOW_ALL_HYPERIDS | SHOW_EXTRA_DATA, //|GV_NODE_NAME_USES_GLOBAL_ID
|
||||
this->BlockId,
|
||||
this->SweepValues);
|
||||
std::ofstream hierarchicalTreeFile(outFileName);
|
||||
hierarchicalTreeFile << hierarchicalTreeDotString;
|
||||
} // SaveHierarchicalContourTreeDot
|
||||
|
||||
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -404,7 +404,10 @@ void TreeGrafter<MeshType, FieldType>::GraftInteriorForests(
|
||||
this->HierarchicalSuperId, // input
|
||||
attachmentCounter // output
|
||||
);
|
||||
vtkm::Id numAttachmentPoints = vtkm::cont::Algorithm::Reduce(attachmentCounter, 0, vtkm::Sum());
|
||||
// Compute the sum of all values in attachmentCounter. vtkm::Add() is the default (so it could be omitted).
|
||||
// We include it here to be more explicit about what Reduce does.
|
||||
vtkm::Id numAttachmentPoints =
|
||||
vtkm::cont::Algorithm::Reduce(attachmentCounter, static_cast<vtkm::Id>(0), vtkm::Add());
|
||||
|
||||
// if there are any at all, we need an extra iteration
|
||||
if (numAttachmentPoints > 0)
|
||||
|
@ -0,0 +1,22 @@
|
||||
##============================================================================
|
||||
## Copyright (c) Kitware, Inc.
|
||||
## All rights reserved.
|
||||
## See LICENSE.txt for details.
|
||||
##
|
||||
## This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
## PURPOSE. See the above copyright notice for more information.
|
||||
##============================================================================
|
||||
|
||||
set(headers
|
||||
InitializeRegularVertexCountComputeSuperparentIds.h
|
||||
InitializeRegularVertexCountInitalizeCountsWorklet.h
|
||||
InitializeRegularVertexCountSubtractLowEndWorklet.h
|
||||
ComputeSuperarcDependentWeightsWorklet.h
|
||||
ComputeSuperarcTransferWeightsWorklet.h
|
||||
TransferTargetComperator.h
|
||||
TransferWeightsUpdateRHEWorklet.h
|
||||
TransferWeightsUpdateLHEWorklet.h
|
||||
)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
205
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/ComputeSuperarcDependentWeightsWorklet.h
Normal file
205
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/ComputeSuperarcDependentWeightsWorklet.h
Normal file
@ -0,0 +1,205 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_compute_superarc_dependent_weights_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_compute_superarc_dependent_weights_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
/// Worklet used in HierarchicalHyperSweeper.ComputeSuperarcDependentWeightsWorklet(...) to
|
||||
/// compute the superarc dependent weights
|
||||
template <typename FieldType>
|
||||
class ComputeSuperarcDependentWeightsWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn supernodeIndex, // counting index [firstSupernode, lastSupernode)
|
||||
FieldIn
|
||||
hierarchicalTreeSuperarcsView, // view of hierarchicalTree.Superarcs[firstSupernode, lastSupernode)
|
||||
FieldIn
|
||||
hierarchicalTreeHyperparentsView, // view of hierarchicalTree.Hyperparents[firstSupernode, lastSupernode)
|
||||
WholeArrayIn hierarchicalTreeHypernodes, // whole hierarchicalTree.Hypernodes array
|
||||
WholeArrayIn valuePrefixSum, // whole valuePrefixSum array
|
||||
FieldInOut sweepValuesView // output view of sweepValues[firstSupernode, lastSupernode)
|
||||
);
|
||||
using ExecutionSignature = void(InputIndex, _1, _2);
|
||||
using InputDomain = _1;
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
ComputeSuperarcDependentWeightsWorklet(const vtkm::Id& firstSupernode,
|
||||
const vtkm::Id& round,
|
||||
const vtkm::Id& hierarchicalTreeNumRounds)
|
||||
: FirstSupernode(firstSupernode)
|
||||
, Round(round)
|
||||
, HierarchicalTreeNumRounds(hierarchicalTreeNumRounds)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename InFieldPortalType, typename InOutFieldPortalType>
|
||||
VTKM_EXEC void operator()(
|
||||
const vtkm::Id& supernode,
|
||||
const vtkm::Id& superarcTo, // same as hierarchicalTree.superarcs[supernode];
|
||||
const vtkm::Id& hyperparent, // same as hierarchicalTree.hyperparents[supernode];
|
||||
const InFieldPortalType& hierarchicalTreeHypernodesPortal,
|
||||
const InFieldPortalType& valuePrefixSumPortal,
|
||||
vtkm::Id& sweepValue) const
|
||||
{
|
||||
// per supernode
|
||||
// if there is no superarc, it is either the root of the tree or an attachment point
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(superarcTo))
|
||||
{ // null superarc
|
||||
// next we test for whether it is the global root
|
||||
if (this->Round == this->HierarchicalTreeNumRounds)
|
||||
{ // global root
|
||||
// this is guaranteed to be the only element in it's iteration
|
||||
// so the prefix sum is good as it stands
|
||||
sweepValue = valuePrefixSumPortal.Get(supernode);
|
||||
} // global root
|
||||
else
|
||||
{ // attachment point
|
||||
// could be the first in the iteration, in which case it is correct
|
||||
if (supernode == this->FirstSupernode)
|
||||
{
|
||||
sweepValue = valuePrefixSumPortal.Get(supernode);
|
||||
}
|
||||
// otherwise, we are guaranteed that it's a length one chain, so subtract predecessor
|
||||
else
|
||||
{
|
||||
sweepValue =
|
||||
valuePrefixSumPortal.Get(supernode) - valuePrefixSumPortal.Get(supernode - 1);
|
||||
}
|
||||
} // attachment point
|
||||
} // null superarc
|
||||
else
|
||||
{ // actual superarc
|
||||
// use the hyperparent to find the hypernode at the beginning of the chain
|
||||
vtkm::Id hyperparentSuperId = hierarchicalTreeHypernodesPortal.Get(hyperparent);
|
||||
|
||||
// now we check to see which value we subtract
|
||||
FieldType baseValue = 0;
|
||||
if (hyperparentSuperId != this->FirstSupernode)
|
||||
{
|
||||
baseValue = valuePrefixSumPortal.Get(hyperparentSuperId - 1);
|
||||
}
|
||||
// for all others, remove the hyperparent's prefix sum to get the "relative" prefix sum
|
||||
sweepValue = valuePrefixSumPortal.Get(supernode) - baseValue;
|
||||
} // actual superarc
|
||||
|
||||
// In serial this worklet implements the following operation
|
||||
/*
|
||||
for (vtkm::Id supernode = firstSupernode; supernode < lastSupernode; supernode++)
|
||||
{ // per supernode
|
||||
// we need to know the superarc first
|
||||
vtkm::Id superarcTo = hierarchicalTree.superarcs[supernode];
|
||||
|
||||
// if there is no superarc, it is either the root of the tree or an attachment point
|
||||
if (noSuchElement(superarcTo))
|
||||
{ // null superarc
|
||||
// next we test for whether it is the global root
|
||||
if (round == hierarchicalTree.nRounds)
|
||||
{ // global root
|
||||
// this is guaranteed to be the only element in it's iteration
|
||||
// so the prefix sum is good as it stands
|
||||
sweepValues[supernode] = valuePrefixSum[supernode];
|
||||
} // global root
|
||||
else
|
||||
{ // attachment point
|
||||
// could be the first in the iteration, in which case it is correct
|
||||
if (supernode == firstSupernode)
|
||||
sweepValues[supernode] = valuePrefixSum[supernode];
|
||||
// otherwise, we are guaranteed that it's a length one chain, so subtract predecessor
|
||||
else
|
||||
sweepValues[supernode] = valuePrefixSum[supernode] - valuePrefixSum[supernode-1];
|
||||
} // attachment point
|
||||
} // null superarc
|
||||
else
|
||||
{ // actual superarc
|
||||
// use the hyperparent to find the hypernode at the beginning of the chain
|
||||
vtkm::Id hyperparent = hierarchicalTree.hyperparents[supernode];
|
||||
vtkm::Id hyperparentSuperId = hierarchicalTree.hypernodes[hyperparent];
|
||||
|
||||
// now we check to see which value we subtract
|
||||
dataType baseValue = 0;
|
||||
if (hyperparentSuperId != firstSupernode)
|
||||
baseValue = valuePrefixSum[hyperparentSuperId - 1];
|
||||
|
||||
// for all others, remove the hyperparent's prefix sum to get the "relative" prefix sum
|
||||
sweepValues[supernode] = valuePrefixSum[supernode] - baseValue;
|
||||
} // actual superarc
|
||||
} // per supernode
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
private:
|
||||
const vtkm::Id FirstSupernode;
|
||||
const vtkm::Id Round;
|
||||
const vtkm::Id HierarchicalTreeNumRounds;
|
||||
|
||||
}; // ComputeSuperarcDependentWeightsWorklet
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
196
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/ComputeSuperarcTransferWeightsWorklet.h
Normal file
196
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/ComputeSuperarcTransferWeightsWorklet.h
Normal file
@ -0,0 +1,196 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_compute_superarc_transfer_weights_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_compute_superarc_transfer_weights_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
/// Worklet used in HierarchicalHyperSweeper.InitializeRegularVertexCount(...) to
|
||||
/// subtract out the low end from the superarc regular counts
|
||||
class ComputeSuperarcTransferWeightsWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn supernodeIndex, // counting array [firstSupernode, lastSupernode)
|
||||
FieldIn
|
||||
hierarchicalTreeSupernodesView, // view of hierarchicalTree.supernodes[firstSupernode, lastSupernode)
|
||||
WholeArrayIn hierarchicalTreeSuperparents, // whole array of hierarchicalTree.superparents
|
||||
WholeArrayIn hierarchicalTreeHyperparents, // whole array of hierarchicalTree.hyperparents
|
||||
FieldInOut
|
||||
hierarchicalTreeSuperarcsView, // view of hierarchicalTree.superarcs[firstSupernode, lastSupernode)
|
||||
FieldOut transferTargetView // view of transferTarget[firstSupernode, lastSupernode)
|
||||
);
|
||||
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6);
|
||||
using InputDomain = _1;
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
ComputeSuperarcTransferWeightsWorklet(const vtkm::Id& round,
|
||||
const vtkm::Id& hierarchicalTreeNumRounds,
|
||||
const vtkm::Id& lastSupernode)
|
||||
: Round(round)
|
||||
, HierarchicalTreeNumRounds(hierarchicalTreeNumRounds)
|
||||
, LastSupernode(lastSupernode)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename InFieldPortalType, typename InOutFieldPortalType>
|
||||
VTKM_EXEC void operator()(
|
||||
const vtkm::Id& supernode,
|
||||
const vtkm::Id& supernodeRegularId, // same as hierarchicalTree.supernodes[supernode];
|
||||
const InFieldPortalType& hierarchicalTreeSuperparentsPortal,
|
||||
const InFieldPortalType& hierarchicalTreeHyperparentsPortal,
|
||||
vtkm::Id& superarcTo, // same as hierarchicalTree.superarcs[supernode];
|
||||
vtkm::Id& transferTarget // same as transferTarget[supernode]
|
||||
) const
|
||||
{
|
||||
// per supernode
|
||||
// if there is no superarc, it is either the root of the tree or an attachment point
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(superarcTo))
|
||||
{ // null superarc
|
||||
// next we test for whether it is the global root
|
||||
if (this->Round == HierarchicalTreeNumRounds)
|
||||
{ // global root
|
||||
// no transfer, so no target
|
||||
transferTarget = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
} // global root
|
||||
else
|
||||
{ // attachment point
|
||||
// set the transfer target
|
||||
transferTarget = hierarchicalTreeSuperparentsPortal.Get(supernodeRegularId);
|
||||
} // attachment point
|
||||
} // null superarc
|
||||
else
|
||||
{ // actual superarc
|
||||
// test for the last in the subrange / last on the hyperarc
|
||||
if ((supernode != this->LastSupernode - 1) &&
|
||||
(hierarchicalTreeHyperparentsPortal.Get(supernode) ==
|
||||
hierarchicalTreeHyperparentsPortal.Get(supernode + 1)))
|
||||
{ // not a superarc we care about
|
||||
transferTarget = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
} // not a superarc we care about
|
||||
else
|
||||
{ // a superarc we care about
|
||||
// strip off the flag bits
|
||||
superarcTo = vtkm::worklet::contourtree_augmented::MaskedIndex(superarcTo);
|
||||
// and set the weight & target
|
||||
transferTarget = superarcTo;
|
||||
} // a superarc we care about
|
||||
} // actual superarc
|
||||
|
||||
// In serial this worklet implements the following operation
|
||||
/*
|
||||
for (vtkm::Id supernode = firstSupernode; supernode < lastSupernode; supernode++)
|
||||
{ // per supernode
|
||||
// we need to know the superarc
|
||||
vtkm::Id superarcTo = hierarchicalTree.superarcs[supernode];
|
||||
vtkm::Id supernodeRegularId = hierarchicalTree.supernodes[supernode];
|
||||
|
||||
// if there is no superarc, it is either the root of the tree or an attachment point
|
||||
if (noSuchElement(superarcTo))
|
||||
{ // null superarc
|
||||
// next we test for whether it is the global root
|
||||
if (round == hierarchicalTree.nRounds)
|
||||
{ // global root
|
||||
// no transfer, so no target
|
||||
transferTarget[supernode] = NO_SUCH_ELEMENT;
|
||||
} // global root
|
||||
else
|
||||
{ // attachment point
|
||||
// set the transfer target
|
||||
transferTarget[supernode] = hierarchicalTree.superparents[supernodeRegularId];
|
||||
} // attachment point
|
||||
} // null superarc
|
||||
else
|
||||
{ // actual superarc
|
||||
// test for the last in the subrange / last on the hyperarc
|
||||
if ((supernode != lastSupernode - 1) && (hierarchicalTree.hyperparents[supernode] == hierarchicalTree.hyperparents[supernode+1]))
|
||||
{ // not a superarc we care about
|
||||
transferTarget[supernode] = NO_SUCH_ELEMENT;
|
||||
} // not a superarc we care about
|
||||
else
|
||||
{ // a superarc we care about
|
||||
// strip off the flag bits
|
||||
superarcTo = maskedIndex(superarcTo);
|
||||
|
||||
// and set the weight & target
|
||||
transferTarget[supernode] = superarcTo;
|
||||
} // a superarc we care about
|
||||
} // actual superarc
|
||||
} // per supernode
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
private:
|
||||
const vtkm::Id Round;
|
||||
const vtkm::Id HierarchicalTreeNumRounds;
|
||||
const vtkm::Id LastSupernode;
|
||||
|
||||
}; // ComputeSuperarcTransferWeightsWorklet
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
160
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountComputeSuperparentIdsWorklet.h
Normal file
160
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountComputeSuperparentIdsWorklet.h
Normal file
@ -0,0 +1,160 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_initialize_regular_vertex_count_compute_superparent_ids_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_initialize_regular_vertex_count_compute_superparent_ids_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
/// Worklet used in HierarchicalHyperSweeper.InitializeRegularVertexCount(...) to
|
||||
/// Look up the global Ids in the hierarchical tree & convert to superparent Ids
|
||||
class InitializeRegularVertexCountComputeSuperparentIdsWorklet
|
||||
: public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
// TODO: We could avoid the need for WholeArrayIn if we did the findRegularByGlobal mapping outside of the worklet first and then use the mapped
|
||||
using ControlSignature = void(FieldIn globalIds, // input
|
||||
ExecObject findRegularByGlobal, // input
|
||||
WholeArrayIn hierarchicalTreeRegular2Supernode, // input
|
||||
WholeArrayIn hierarchicalTreeSuperparents, // input
|
||||
FieldOut superparents // output
|
||||
|
||||
);
|
||||
using ExecutionSignature = void(_1, _2, _3, _4, _5);
|
||||
using InputDomain = _1;
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
InitializeRegularVertexCountComputeSuperparentIdsWorklet() {}
|
||||
|
||||
template <typename ExecObjType, typename InFieldPortalType>
|
||||
VTKM_EXEC vtkm::Id operator()(const vtkm::Id& globalId,
|
||||
const ExecObjType& findRegularByGlobal,
|
||||
const InFieldPortalType& hierarchicalTreeRegular2SupernodePortal,
|
||||
const InFieldPortalType& hierarchicalTreeSuperparentsPortal,
|
||||
vtkm::Id& superparent) const
|
||||
{
|
||||
// per vertex
|
||||
// retrieve the regular Id (should ALWAYS exist)
|
||||
vtkm::Id hierarchicalRegularId = findRegularByGlobal(globalId);
|
||||
// be paranoid
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(hierarchicalRegularId))
|
||||
{
|
||||
superparent = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attachment points cause a minor problem - they are supernodes, but can have a different
|
||||
// superparent than themselves (or the same one). We therefore test explicitly whether we
|
||||
// are a supernode, and use either supernodeId or superparent depending on this test
|
||||
|
||||
// retrieve the super Id
|
||||
vtkm::Id superId = hierarchicalTreeRegular2SupernodePortal.Get(hierarchicalRegularId);
|
||||
|
||||
// if it doesn't have one, use it's superparent
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(superId))
|
||||
{
|
||||
superparent = hierarchicalTreeSuperparentsPortal.Get(hierarchicalRegularId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if it does have a superId, use it
|
||||
superparent = superId;
|
||||
}
|
||||
}
|
||||
// In serial this worklet implements the following operation
|
||||
/*
|
||||
for (vtkm::Id vertex = 0; vertex < globalIds.GetNumberOfValues(); vertex++)
|
||||
{ // per vertex
|
||||
// retrieve the regular Id (should ALWAYS exist)
|
||||
vtkm::Id hierarchicalRegularId = hierarchicalTree.FindRegularByGlobal(globalIds[vertex]);
|
||||
// be paranoid
|
||||
if (noSuchElement(hierarchicalRegularId))
|
||||
superparents[vertex] = NO_SUCH_ELEMENT;
|
||||
else
|
||||
{ // found a regular Id
|
||||
// Attachment points cause a minor problem - they are supernodes, but can have a different
|
||||
// superparent than themselves (or the same one). We therefore test explicitly whether we
|
||||
// are a supernode, and use either supernodeId or superparent depending on this test
|
||||
|
||||
// retrieve the super Id
|
||||
vtkm::Id superId = hierarchicalTree.regular2supernode[hierarchicalRegularId];
|
||||
|
||||
// if it doesn't have one, use it's superparent
|
||||
if (noSuchElement(superId))
|
||||
superparents[vertex] = hierarchicalTree.superparents[hierarchicalRegularId];
|
||||
else
|
||||
// if it does have a superId, use it
|
||||
superparents[vertex] = superId;
|
||||
} // found a regular Id
|
||||
} // per vertex
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
}; // InitializeRegularVertexCountComputeSuperparentIdsWorklet
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
138
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountInitalizeCountsWorklet.h
Normal file
138
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountInitalizeCountsWorklet.h
Normal file
@ -0,0 +1,138 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_initialize_regular_vertex_count_initialize_counts_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_initialize_regular_vertex_count_initialize_counts_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
/// Worklet used in HierarchicalHyperSweeper.InitializeRegularVertexCount(...) to
|
||||
/// set the count to the Id one off the high end of each range
|
||||
class InitializeRegularVertexCountInitalizeCountsWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(WholeArrayIn superparents, WholeArrayInOut superarcRegularCounts);
|
||||
using ExecutionSignature = void(InputIndex, _1, _2);
|
||||
using InputDomain = _1;
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
InitializeRegularVertexCountInitalizeCountsWorklet() {}
|
||||
|
||||
template <typename InFieldPortalType, typename InOutFieldPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& vertex,
|
||||
const InFieldPortalType superparentsPortal,
|
||||
const InOutFieldPortalType superarcRegularCountsPortal) const
|
||||
{
|
||||
// per vertex
|
||||
// retrieve the superparent
|
||||
vtkm::Id superparent = superparentsPortal.Get(vertex);
|
||||
|
||||
// if it's NSE, ignore (should never happen, but . . . )
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(superparent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// if its the last element, always write
|
||||
if (vertex == superparentsPortal.GetNumberOfValues() - 1)
|
||||
{
|
||||
superarcRegularCountsPortal.Set(superparent, vertex + 1);
|
||||
}
|
||||
// otherwise, only write if different from next one
|
||||
else
|
||||
{
|
||||
if (superparentsPortal.Get(vertex + 1) != superparent)
|
||||
{
|
||||
superarcRegularCountsPortal.Set(superparent, vertex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// In serial this worklet implements the following operation
|
||||
/*
|
||||
for (vtkm::Id vertex = 0; vertex < superparents.size(); vertex++)
|
||||
{ // per vertex
|
||||
// retrieve the superparent
|
||||
vtkm::Id superparent = superparents[vertex];
|
||||
|
||||
// if it's NSE, ignore (should never happen, but . . . )
|
||||
if (noSuchElement(superparent))
|
||||
continue;
|
||||
|
||||
// if its the last element, always write
|
||||
if (vertex == superparents.size() - 1)
|
||||
superarcRegularCounts[superparent] = vertex+1;
|
||||
// otherwise, only write if different from next one
|
||||
else
|
||||
if (superparents[vertex+1] != superparent)
|
||||
superarcRegularCounts[superparent] = vertex+1;
|
||||
} // per vertex
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
}; // InitializeRegularVertexCountInitalizeCountsWorklet
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
141
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountSubtractLowEndWorklet.h
Normal file
141
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/InitializeRegularVertexCountSubtractLowEndWorklet.h
Normal file
@ -0,0 +1,141 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_initialize_regular_vertex_count_subtract_low_end_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_initialize_regular_vertex_count_subtract_low_end_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
/// Worklet used in HierarchicalHyperSweeper.InitializeRegularVertexCount(...) to
|
||||
/// subtract out the low end from the superarc regular counts
|
||||
class InitializeRegularVertexCountSubtractLowEndWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(WholeArrayIn superparents, WholeArrayInOut superarcRegularCounts);
|
||||
using ExecutionSignature = void(InputIndex, _1, _2);
|
||||
using InputDomain = _1;
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
InitializeRegularVertexCountSubtractLowEndWorklet() {}
|
||||
|
||||
template <typename InFieldPortalType, typename InOutFieldPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& vertex,
|
||||
const InFieldPortalType superparentsPortal,
|
||||
const InOutFieldPortalType superarcRegularCountsPortal) const
|
||||
{
|
||||
// per vertex
|
||||
// retrieve the superparent
|
||||
vtkm::Id superparent = superparentsPortal.Get(vertex);
|
||||
|
||||
// if it's NSE, ignore (should never happen, but . . . )
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(superparent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if its the first element, always write
|
||||
if (vertex == 0)
|
||||
{
|
||||
superarcRegularCountsPortal.Set(superparent,
|
||||
superarcRegularCountsPortal.Get(superparent) - vertex);
|
||||
}
|
||||
// otherwise, only write if different from previous one
|
||||
else
|
||||
{
|
||||
if (superparentsPortal.Get(vertex - 1) != superparent)
|
||||
{
|
||||
superarcRegularCountsPortal.Set(superparent,
|
||||
superarcRegularCountsPortal.Get(superparent) - vertex);
|
||||
}
|
||||
}
|
||||
|
||||
// In serial this worklet implements the following operation
|
||||
/*
|
||||
for (vtkm::Id vertex = 0; vertex < superparents.GetNumberOfValues(); vertex++)
|
||||
{ // per vertex
|
||||
// retrieve the superparent
|
||||
vtkm::Id superparent = superparents[vertex];
|
||||
|
||||
// if it's NSE, ignore (should never happen, but . . . )
|
||||
if (noSuchElement(superparent))
|
||||
continue;
|
||||
|
||||
// if its the first element, always write
|
||||
if (vertex == 0)
|
||||
superarcRegularCounts[superparent] -= vertex;
|
||||
// otherwise, only write if different from previous one
|
||||
else
|
||||
if (superparents[vertex-1] != superparent)
|
||||
superarcRegularCounts[superparent] -= vertex;
|
||||
} // per vertex
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
}; // InitializeRegularVertexCountSubtractLowEndWorklet
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
120
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferTargetComperator.h
Normal file
120
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferTargetComperator.h
Normal file
@ -0,0 +1,120 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_target_comperator_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_target_comperator_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ExecutionObjectBase.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
|
||||
// comperator function for an indirect sort on the superarc target
|
||||
class TransferTargetComperatorImpl
|
||||
{
|
||||
public:
|
||||
using IdArrayPortalType =
|
||||
typename vtkm::worklet::contourtree_augmented::IdArrayType::ReadPortalType;
|
||||
|
||||
// constructor - takes vectors as parameters
|
||||
VTKM_CONT
|
||||
TransferTargetComperatorImpl(IdArrayPortalType superarcPortal)
|
||||
: SuperarcPortal(superarcPortal)
|
||||
{ // constructor
|
||||
} // constructor
|
||||
|
||||
// () operator - gets called to do comparison
|
||||
VTKM_EXEC
|
||||
bool operator()(const vtkm::Id& left, const vtkm::Id& right) const
|
||||
{ // operator()
|
||||
return this->SuperarcPortal.Get(left) < this->SuperarcPortal.Get(right);
|
||||
} // operator()
|
||||
|
||||
private:
|
||||
IdArrayPortalType SuperarcPortal;
|
||||
}; // TransferTargetComperatorImpl
|
||||
|
||||
|
||||
class TransferTargetComperator : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
public:
|
||||
// constructor - takes vectors as parameters
|
||||
VTKM_CONT
|
||||
TransferTargetComperator(const vtkm::worklet::contourtree_augmented::IdArrayType superarcs)
|
||||
: Superarcs(superarcs)
|
||||
{ // constructor
|
||||
} // constructor
|
||||
|
||||
VTKM_CONT TransferTargetComperatorImpl PrepareForExecution(vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
return TransferTargetComperatorImpl(this->Superarcs.PrepareForInput(device, token));
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::worklet::contourtree_augmented::IdArrayType Superarcs;
|
||||
}; // TransferTargetComperator
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
152
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateLHEWorklet.h
Normal file
152
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateLHEWorklet.h
Normal file
@ -0,0 +1,152 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_lhe_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_lhe_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
/// Worklet used in HierarchicalHyperSweeper.TransferWeights(...) to implement
|
||||
/// step 7b. Now find the LHE of each group and subtract out the prior weight
|
||||
class TransferWeightsUpdateLHEWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn supernodeIndex, // input counting array [firstSupernode, lastSupernode)
|
||||
FieldIn
|
||||
sortedTransferTargetView, // input view of sortedTransferTarget[firstSupernode, lastSupernode)
|
||||
FieldIn
|
||||
sortedTransferTargetShiftedView, // input view of sortedTransferTarget[firstSupernode+1, lastSupernode+1)
|
||||
FieldIn
|
||||
valuePrefixSumShiftedView, // input view of valuePrefixSum[firstSupernode-1, lastSupernode-1)
|
||||
FieldInOut
|
||||
sweepValuePermuted // output view of sweepValues permuted by sortedTransferTarget[firstSupernode, lastSupernode). Use FieldInOut since we don't overwrite all values.
|
||||
);
|
||||
using ExecutionSignature = void(_1, _2, _3, _4, _5);
|
||||
using InputDomain = _1;
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
TransferWeightsUpdateLHEWorklet(const vtkm::Id& firstSupernode)
|
||||
: FirstSupernode(firstSupernode)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_EXEC void operator()(
|
||||
const vtkm::Id& supernode,
|
||||
const vtkm::Id& sortedTransferTargetValue, // same as sortedTransferTarget[supernode]
|
||||
const vtkm::Id& sortedTransferTargetNextValue, // same as sortedTransferTarget[supernode+1]
|
||||
const vtkm::Id& valuePrefixSumPreviousValue, // same as valuePrefixSum[supernode-1]
|
||||
vtkm::Id& sweepValue // same as sweepValues[sortedTransferTarget[supernode]]
|
||||
) const
|
||||
{
|
||||
// per supernode
|
||||
// ignore any that point at NO_SUCH_ELEMENT
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(sortedTransferTargetValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// the LHE at 0 is special - it subtracts zero. In practice, since NO_SUCH_ELEMENT will sort low, this will never
|
||||
// occur, but let's keep the logic strict
|
||||
if (supernode == this->FirstSupernode)
|
||||
{ // LHE 0
|
||||
sweepValue -= 0;
|
||||
} // LHE 0
|
||||
else if (sortedTransferTargetValue != sortedTransferTargetNextValue)
|
||||
{ // LHE not 0
|
||||
sweepValue -= valuePrefixSumPreviousValue;
|
||||
} // LHE not 0
|
||||
|
||||
// In serial this worklet implements the following operation
|
||||
/*
|
||||
for (vtkm::Id supernode = firstSupernode; supernode < lastSupernode; supernode++)
|
||||
{ // per supernode
|
||||
// ignore any that point at NO_SUCH_ELEMENT
|
||||
if (noSuchElement(sortedTransferTarget[supernode]))
|
||||
continue;
|
||||
|
||||
// the LHE at 0 is special - it subtracts zero. In practice, since NO_SUCH_ELEMENT will sort low, this will never
|
||||
// occur, but let's keep the logic strict
|
||||
if (supernode == firstSupernode)
|
||||
{ // LHE 0
|
||||
sweepValues[sortedTransferTarget[supernode]] -= 0;
|
||||
} // LHE 0
|
||||
else if (sortedTransferTarget[supernode] != sortedTransferTarget[supernode-1])
|
||||
{ // LHE not 0
|
||||
sweepValues[sortedTransferTarget[supernode]] -= valuePrefixSum[supernode-1];
|
||||
} // LHE not 0
|
||||
} // per supernode
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
private:
|
||||
const vtkm::Id FirstSupernode;
|
||||
|
||||
}; // TransferWeightsUpdateLHEWorklet
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
142
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateRHEWorklet.h
Normal file
142
vtkm/worklet/contourtree_distributed/hierarchical_hyper_sweeper/TransferWeightsUpdateRHEWorklet.h
Normal file
@ -0,0 +1,142 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
// Copyright (c) 2018, The Regents of the University of California, through
|
||||
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
|
||||
// from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// (1) Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// (2) Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// (3) Neither the name of the University of California, Lawrence Berkeley National
|
||||
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//=============================================================================
|
||||
//
|
||||
// This code is an extension of the algorithm presented in the paper:
|
||||
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
|
||||
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
|
||||
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
|
||||
// (LDAV), October 2016, Baltimore, Maryland.
|
||||
//
|
||||
// The PPP2 algorithm and software were jointly developed by
|
||||
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
|
||||
// Oliver Ruebel (LBNL)
|
||||
//==============================================================================
|
||||
|
||||
#ifndef vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_rhe_worklet_h
|
||||
#define vtk_m_worklet_contourtree_distributed_hierarchical_hyper_sweeper_transfer_weights_update_rhe_worklet_h
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/contourtree_augmented/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
namespace contourtree_distributed
|
||||
{
|
||||
namespace hierarchical_hyper_sweeper
|
||||
{
|
||||
|
||||
/// Worklet used in HierarchicalHyperSweeper.TransferWeights(...) to implement
|
||||
/// step 7a. Find the RHE of each group and transfer the prefix sum weight.
|
||||
/// Note that we do not compute the transfer weight separately, we add it in place instead
|
||||
class TransferWeightsUpdateRHEWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(
|
||||
FieldIn supernodeIndex, // input counting array [firstSupernode, lastSupernode)
|
||||
FieldIn
|
||||
sortedTransferTargetView, // input view of sortedTransferTarget[firstSupernode, lastSupernode)
|
||||
FieldIn
|
||||
sortedTransferTargetShiftedView, // input view of sortedTransferTarget[firstSupernode+1, lastSupernode+1)
|
||||
FieldIn valuePrefixSumView, // input view of valuePrefixSum[firstSupernode, lastSupernode)
|
||||
FieldInOut
|
||||
sweepValuePermuted // output view of sweepValues permuted by sortedTransferTarget[firstSupernode, lastSupernode). Use FieldInOut since we don't overwrite all values.
|
||||
);
|
||||
using ExecutionSignature = void(_1, _2, _3, _4, _5);
|
||||
using InputDomain = _1;
|
||||
|
||||
// Default Constructor
|
||||
VTKM_EXEC_CONT
|
||||
TransferWeightsUpdateRHEWorklet(const vtkm::Id& lastSupernode)
|
||||
: LastSupernode(lastSupernode)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_EXEC void operator()(
|
||||
const vtkm::Id& supernode,
|
||||
const vtkm::Id& sortedTransferTargetValue, // same as sortedTransferTarget[supernode]
|
||||
const vtkm::Id& sortedTransferTargetNextValue, // same as sortedTransferTarget[supernode+1]
|
||||
const vtkm::Id& valuePrefixSum, // same as valuePrefixSum[supernode]
|
||||
vtkm::Id& sweepValue // same as sweepValues[sortedTransferTarget[supernode]]
|
||||
) const
|
||||
{
|
||||
// per supernode
|
||||
// ignore any that point at NO_SUCH_ELEMENT
|
||||
if (vtkm::worklet::contourtree_augmented::NoSuchElement(sortedTransferTargetValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// the RHE of each segment transfers its weight (including all irrelevant prefixes)
|
||||
if ((supernode == this->LastSupernode - 1) ||
|
||||
(sortedTransferTargetValue != sortedTransferTargetNextValue))
|
||||
{ // RHE of segment
|
||||
sweepValue += valuePrefixSum;
|
||||
} // RHE of segment
|
||||
|
||||
// In serial this worklet implements the following operation
|
||||
/*
|
||||
for (vtkm::Id supernode = firstSupernode; supernode < lastSupernode; supernode++)
|
||||
{ // per supernode
|
||||
// ignore any that point at NO_SUCH_ELEMENT
|
||||
if (noSuchElement(sortedTransferTarget[supernode]))
|
||||
continue;
|
||||
|
||||
// the RHE of each segment transfers its weight (including all irrelevant prefixes)
|
||||
if ((supernode == lastSupernode - 1) || (sortedTransferTarget[supernode] != sortedTransferTarget[supernode+1]))
|
||||
{ // RHE of segment
|
||||
sweepValues[sortedTransferTarget[supernode]] += valuePrefixSum[supernode];
|
||||
} // RHE of segment
|
||||
} // per supernode
|
||||
*/
|
||||
} // operator()()
|
||||
|
||||
private:
|
||||
const vtkm::Id LastSupernode;
|
||||
|
||||
}; // TransferWeightsUpdateRHEWorklet
|
||||
|
||||
} // namespace hierarchical_hyper_sweeper
|
||||
} // namespace contourtree_distributed
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user