Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • hankchilds/vtk-m-user-guide
  • chris.turney/vtk-m-user-guide
  • oruebel/vtk-m-user-guide
  • m-kim/vtk-m-user-guide
  • tberger/vtk-m-user-guide
  • ollielo/vtk-m-user-guide
  • dpugmire/vtk-m-user-guide
  • sujin.philip/vtk-m-user-guide
  • nadavi/vtk-m-user-guide
  • mletter1/vtk-m-user-guide
  • kmorel/vtk-m-user-guide
  • jameskress/vtk-m-user-guide
  • vbolea/vtk-m-user-guide
  • NAThompson/vtk-m-user-guide
  • vtk/vtk-m-user-guide
15 results
Show changes
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include <vtkm/Hash.h> #include <vtkm/Hash.h>
#include <vtkm/worklet/AverageByKey.h> #include <vtkm/worklet/AverageByKey.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/DispatcherReduceByKey.h>
#include <vtkm/worklet/Keys.h> #include <vtkm/worklet/Keys.h>
#include <vtkm/worklet/ScatterCounting.h> #include <vtkm/worklet/ScatterCounting.h>
...@@ -26,361 +24,261 @@ namespace worklet ...@@ -26,361 +24,261 @@ namespace worklet
namespace namespace
{ {
struct ExtractEdges ////
//// BEGIN-EXAMPLE GenerateMeshHashCount.cxx
////
struct CountEdgesWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
{ {
//// using ControlSignature = void(CellSetIn cellSet, FieldOut numEdges);
//// BEGIN-EXAMPLE GenerateMeshHashCount.cxx using ExecutionSignature = _2(CellShape, PointCount);
//// using InputDomain = _1;
struct CountEdges : vtkm::worklet::WorkletVisitCellsWithPoints
template<typename CellShapeTag>
VTKM_EXEC_CONT vtkm::IdComponent operator()(
CellShapeTag cellShape,
vtkm::IdComponent numPointsInCell) const
{ {
using ControlSignature = void(CellSetIn cellSet, FieldOut numEdges); return vtkm::exec::CellEdgeNumberOfEdges(numPointsInCell, cellShape, *this);
using ExecutionSignature = _2(CellShape, PointCount); }
using InputDomain = _1; };
////
template<typename CellShapeTag> //// END-EXAMPLE GenerateMeshHashCount.cxx
VTKM_EXEC_CONT vtkm::IdComponent operator()( ////
CellShapeTag cellShape,
vtkm::IdComponent numPointsInCell) const ////
{ //// BEGIN-EXAMPLE GenerateMeshHashGenHashes.cxx
return vtkm::exec::CellEdgeNumberOfEdges(numPointsInCell, cellShape, *this); ////
} class EdgeHashesWorklet : public vtkm::worklet::WorkletVisitCellsWithPoints
}; {
//// public:
//// END-EXAMPLE GenerateMeshHashCount.cxx using ControlSignature = void(CellSetIn cellSet, FieldOut hashValues);
//// using ExecutionSignature = _2(CellShape cellShape,
PointIndices globalPointIndices,
//// VisitIndex localEdgeIndex);
//// BEGIN-EXAMPLE GenerateMeshHashGenHashes.cxx using InputDomain = _1;
////
class EdgeHashes : public vtkm::worklet::WorkletVisitCellsWithPoints using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellShapeTag, typename PointIndexVecType>
VTKM_EXEC vtkm::HashType operator()(
CellShapeTag cellShape,
const PointIndexVecType& globalPointIndicesForCell,
vtkm::IdComponent localEdgeIndex) const
{ {
public: vtkm::IdComponent numPointsInCell =
using ControlSignature = void(CellSetIn cellSet, FieldOut hashValues); globalPointIndicesForCell.GetNumberOfComponents();
using ExecutionSignature = _2(CellShape cellShape, //// PAUSE-EXAMPLE
PointIndices globalPointIndices,
VisitIndex localEdgeIndex);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellShapeTag, typename PointIndexVecType>
VTKM_EXEC vtkm::HashType operator()(
CellShapeTag cellShape,
const PointIndexVecType& globalPointIndicesForCell,
vtkm::IdComponent localEdgeIndex) const
{
vtkm::IdComponent numPointsInCell =
globalPointIndicesForCell.GetNumberOfComponents();
//// PAUSE-EXAMPLE
#ifndef CHECK_COLLISIONS #ifndef CHECK_COLLISIONS
//// RESUME-EXAMPLE //// RESUME-EXAMPLE
return vtkm::Hash(vtkm::exec::CellEdgeCanonicalId(numPointsInCell, return vtkm::Hash(vtkm::exec::CellEdgeCanonicalId(
localEdgeIndex, numPointsInCell, localEdgeIndex, cellShape, globalPointIndicesForCell, *this));
cellShape, //// PAUSE-EXAMPLE
globalPointIndicesForCell,
*this));
//// PAUSE-EXAMPLE
#else // ! CHECK_COLLISIONS \ #else // ! CHECK_COLLISIONS \
// Intentionally use a bad hash value to cause collisions to check to make \ // Intentionally use a bad hash value to cause collisions to check to make \
// sure that collision resolution works. // sure that collision resolution works.
return vtkm::HashType( return vtkm::HashType(vtkm::exec::CellEdgeCanonicalId(numPointsInCell,
vtkm::exec::CellEdgeCanonicalId(numPointsInCell, localEdgeIndex,
localEdgeIndex, cellShape,
cellShape, globalPointIndicesForCell,
globalPointIndicesForCell, *this)[0]);
*this)[0]);
#endif // !CHECK_COLLISIONS #endif // !CHECK_COLLISIONS
//// RESUME-EXAMPLE //// RESUME-EXAMPLE
} }
}; };
//// ////
//// END-EXAMPLE GenerateMeshHashGenHashes.cxx //// END-EXAMPLE GenerateMeshHashGenHashes.cxx
//// ////
//// ////
//// BEGIN-EXAMPLE GenerateMeshHashResolveCollisions.cxx //// BEGIN-EXAMPLE GenerateMeshHashResolveCollisions.cxx
//// ////
class EdgeHashCollisions : public vtkm::worklet::WorkletReduceByKey class EdgeHashCollisionsWorklet : public vtkm::worklet::WorkletReduceByKey
{
public:
using ControlSignature = void(KeysIn keys,
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originEdges,
ValuesOut localEdgeIndices,
ReducedValuesOut numEdges);
using ExecutionSignature = _6(_2 inputCells,
_3 originCells,
_4 originEdges,
_5 localEdgeIndices);
using InputDomain = _1;
template<typename CellSetType,
typename OriginCellsType,
typename OriginEdgesType,
typename localEdgeIndicesType>
VTKM_EXEC vtkm::IdComponent operator()(
const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginEdgesType& originEdges,
localEdgeIndicesType& localEdgeIndices) const
{ {
public: vtkm::IdComponent numEdgesInHash = localEdgeIndices.GetNumberOfComponents();
using ControlSignature = void(KeysIn keys,
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originEdges,
ValuesOut localEdgeIndices,
ReducedValuesOut numEdges);
using ExecutionSignature = _6(_2 inputCells,
_3 originCells,
_4 originEdges,
_5 localEdgeIndices);
using InputDomain = _1;
template<typename CellSetType,
typename OriginCellsType,
typename OriginEdgesType,
typename localEdgeIndicesType>
VTKM_EXEC vtkm::IdComponent operator()(
const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginEdgesType& originEdges,
localEdgeIndicesType& localEdgeIndices) const
{
vtkm::IdComponent numEdgesInHash = localEdgeIndices.GetNumberOfComponents();
// Sanity checks. // Sanity checks.
VTKM_ASSERT(originCells.GetNumberOfComponents() == numEdgesInHash); VTKM_ASSERT(originCells.GetNumberOfComponents() == numEdgesInHash);
VTKM_ASSERT(originEdges.GetNumberOfComponents() == numEdgesInHash); VTKM_ASSERT(originEdges.GetNumberOfComponents() == numEdgesInHash);
// Clear out localEdgeIndices // Clear out localEdgeIndices
for (vtkm::IdComponent index = 0; index < numEdgesInHash; ++index) for (vtkm::IdComponent index = 0; index < numEdgesInHash; ++index)
{ {
localEdgeIndices[index] = -1; localEdgeIndices[index] = -1;
} }
// Count how many unique edges there are and create an id for each; // Count how many unique edges there are and create an id for each;
vtkm::IdComponent numUniqueEdges = 0; vtkm::IdComponent numUniqueEdges = 0;
for (vtkm::IdComponent firstEdgeIndex = 0; firstEdgeIndex < numEdgesInHash; for (vtkm::IdComponent firstEdgeIndex = 0; firstEdgeIndex < numEdgesInHash;
++firstEdgeIndex) ++firstEdgeIndex)
{
if (localEdgeIndices[firstEdgeIndex] == -1)
{ {
if (localEdgeIndices[firstEdgeIndex] == -1) vtkm::IdComponent edgeId = numUniqueEdges;
localEdgeIndices[firstEdgeIndex] = edgeId;
// Find all matching edges.
vtkm::Id firstCellIndex = originCells[firstEdgeIndex];
vtkm::Id2 canonicalEdgeId =
vtkm::exec::CellEdgeCanonicalId(cellSet.GetNumberOfIndices(firstCellIndex),
originEdges[firstEdgeIndex],
cellSet.GetCellShape(firstCellIndex),
cellSet.GetIndices(firstCellIndex),
*this);
for (vtkm::IdComponent laterEdgeIndex = firstEdgeIndex + 1;
laterEdgeIndex < numEdgesInHash;
++laterEdgeIndex)
{ {
vtkm::IdComponent edgeId = numUniqueEdges; vtkm::Id laterCellIndex = originCells[laterEdgeIndex];
localEdgeIndices[firstEdgeIndex] = edgeId; vtkm::Id2 otherCanonicalEdgeId = vtkm::exec::CellEdgeCanonicalId(
// Find all matching edges. cellSet.GetNumberOfIndices(laterCellIndex),
vtkm::Id firstCellIndex = originCells[firstEdgeIndex]; originEdges[laterEdgeIndex],
vtkm::Id2 canonicalEdgeId = vtkm::exec::CellEdgeCanonicalId( cellSet.GetCellShape(laterCellIndex),
cellSet.GetNumberOfIndices(firstCellIndex), cellSet.GetIndices(laterCellIndex),
originEdges[firstEdgeIndex],
cellSet.GetCellShape(firstCellIndex),
cellSet.GetIndices(firstCellIndex),
*this); *this);
for (vtkm::IdComponent laterEdgeIndex = firstEdgeIndex + 1; if (canonicalEdgeId == otherCanonicalEdgeId)
laterEdgeIndex < numEdgesInHash;
++laterEdgeIndex)
{ {
vtkm::Id laterCellIndex = originCells[laterEdgeIndex]; localEdgeIndices[laterEdgeIndex] = edgeId;
vtkm::Id2 otherCanonicalEdgeId = vtkm::exec::CellEdgeCanonicalId(
cellSet.GetNumberOfIndices(laterCellIndex),
originEdges[laterEdgeIndex],
cellSet.GetCellShape(laterCellIndex),
cellSet.GetIndices(laterCellIndex),
*this);
if (canonicalEdgeId == otherCanonicalEdgeId)
{
localEdgeIndices[laterEdgeIndex] = edgeId;
}
} }
++numUniqueEdges;
} }
++numUniqueEdges;
} }
return numUniqueEdges;
} }
};
//// return numUniqueEdges;
//// END-EXAMPLE GenerateMeshHashResolveCollisions.cxx }
//// };
////
//// //// END-EXAMPLE GenerateMeshHashResolveCollisions.cxx
//// BEGIN-EXAMPLE GenerateMeshHashGenIndices.cxx ////
////
class EdgeIndices : public vtkm::worklet::WorkletReduceByKey ////
//// BEGIN-EXAMPLE GenerateMeshHashGenIndices.cxx
////
class EdgeIndicesWorklet : public vtkm::worklet::WorkletReduceByKey
{
public:
using ControlSignature = void(KeysIn keys,
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originEdges,
ValuesIn localEdgeIndices,
ReducedValuesOut connectivityOut);
using ExecutionSignature = void(_2 inputCells,
_3 originCell,
_4 originEdge,
_5 localEdgeIndices,
VisitIndex localEdgeIndex,
_6 connectivityOut);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellSetType,
typename OriginCellsType,
typename OriginEdgesType,
typename LocalEdgeIndicesType>
VTKM_EXEC void operator()(const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginEdgesType& originEdges,
const LocalEdgeIndicesType& localEdgeIndices,
vtkm::IdComponent localEdgeIndex,
vtkm::Id2& connectivityOut) const
{ {
public: // Find the first edge that matches the index given and return it.
using ControlSignature = void(KeysIn keys, for (vtkm::IdComponent edgeIndex = 0;; ++edgeIndex)
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originEdges,
ValuesIn localEdgeIndices,
ReducedValuesOut connectivityOut);
using ExecutionSignature = void(_2 inputCells,
_3 originCell,
_4 originEdge,
_5 localEdgeIndices,
VisitIndex localEdgeIndex,
_6 connectivityOut);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellSetType,
typename OriginCellsType,
typename OriginEdgesType,
typename LocalEdgeIndicesType>
VTKM_EXEC void operator()(const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginEdgesType& originEdges,
const LocalEdgeIndicesType& localEdgeIndices,
vtkm::IdComponent localEdgeIndex,
vtkm::Id2& connectivityOut) const
{ {
// Find the first edge that matches the index given and return it. if (localEdgeIndices[edgeIndex] == localEdgeIndex)
for (vtkm::IdComponent edgeIndex = 0;; ++edgeIndex)
{ {
if (localEdgeIndices[edgeIndex] == localEdgeIndex) vtkm::Id cellIndex = originCells[edgeIndex];
{ vtkm::IdComponent numPointsInCell = cellSet.GetNumberOfIndices(cellIndex);
vtkm::Id cellIndex = originCells[edgeIndex]; vtkm::IdComponent edgeInCellIndex = originEdges[edgeIndex];
vtkm::IdComponent numPointsInCell = cellSet.GetNumberOfIndices(cellIndex); auto cellShape = cellSet.GetCellShape(cellIndex);
vtkm::IdComponent edgeInCellIndex = originEdges[edgeIndex];
auto cellShape = cellSet.GetCellShape(cellIndex);
vtkm::IdComponent pointInCellIndex0 = vtkm::exec::CellEdgeLocalIndex( vtkm::IdComponent pointInCellIndex0 = vtkm::exec::CellEdgeLocalIndex(
numPointsInCell, 0, edgeInCellIndex, cellShape, *this); numPointsInCell, 0, edgeInCellIndex, cellShape, *this);
vtkm::IdComponent pointInCellIndex1 = vtkm::exec::CellEdgeLocalIndex( vtkm::IdComponent pointInCellIndex1 = vtkm::exec::CellEdgeLocalIndex(
numPointsInCell, 1, edgeInCellIndex, cellShape, *this); numPointsInCell, 1, edgeInCellIndex, cellShape, *this);
auto globalPointIndicesForCell = cellSet.GetIndices(cellIndex); auto globalPointIndicesForCell = cellSet.GetIndices(cellIndex);
connectivityOut[0] = globalPointIndicesForCell[pointInCellIndex0]; connectivityOut[0] = globalPointIndicesForCell[pointInCellIndex0];
connectivityOut[1] = globalPointIndicesForCell[pointInCellIndex1]; connectivityOut[1] = globalPointIndicesForCell[pointInCellIndex1];
break; break;
}
} }
} }
};
////
//// END-EXAMPLE GenerateMeshHashGenIndices.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashInvoke.cxx
////
template<typename CellSetType>
VTKM_CONT vtkm::cont::CellSetSingleType<> Run(const CellSetType& inCellSet)
{
VTKM_IS_DYNAMIC_OR_STATIC_CELL_SET(CellSetType);
// First, count the edges in each cell.
vtkm::cont::ArrayHandle<vtkm::IdComponent> edgeCounts;
vtkm::worklet::DispatcherMapTopology<CountEdges> countEdgeDispatcher;
countEdgeDispatcher.Invoke(inCellSet, edgeCounts);
vtkm::worklet::ScatterCounting scatter(edgeCounts);
this->OutputToInputCellMap =
scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputEdgeMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Second, for each edge, extract a hash.
vtkm::cont::ArrayHandle<vtkm::HashType> hashValues;
vtkm::worklet::DispatcherMapTopology<EdgeHashes> EdgeHashesDispatcher(scatter);
EdgeHashesDispatcher.Invoke(inCellSet, hashValues);
// Third, use a Keys object to combine all like hashes.
this->CellToEdgeKeys = vtkm::worklet::Keys<vtkm::HashType>(hashValues);
// Fourth, use a reduce-by-key to collect like hash values, resolve collisions,
// and count the number of unique edges associated with each hash.
vtkm::cont::ArrayHandle<vtkm::IdComponent> numUniqueEdgesInEachHash;
vtkm::worklet::DispatcherReduceByKey<EdgeHashCollisions>
edgeHashCollisionDispatcher;
edgeHashCollisionDispatcher.Invoke(this->CellToEdgeKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputEdgeMap,
this->LocalEdgeIndices,
numUniqueEdgesInEachHash);
// Fifth, use a reduce-by-key to extract indices for each unique edge.
this->HashCollisionScatter.reset(
new vtkm::worklet::ScatterCounting(numUniqueEdgesInEachHash));
vtkm::cont::ArrayHandle<vtkm::Id> connectivityArray;
vtkm::worklet::DispatcherReduceByKey<EdgeIndices> edgeIndicesDispatcher(
*this->HashCollisionScatter);
edgeIndicesDispatcher.Invoke(
this->CellToEdgeKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputEdgeMap,
this->LocalEdgeIndices,
vtkm::cont::make_ArrayHandleGroupVec<2>(connectivityArray));
// Sixth, use the created connectivity array to build a cell set.
vtkm::cont::CellSetSingleType<> outCellSet;
outCellSet.Fill(
inCellSet.GetNumberOfPoints(), vtkm::CELL_SHAPE_LINE, 2, connectivityArray);
return outCellSet;
} }
//// };
//// END-EXAMPLE GenerateMeshHashInvoke.cxx ////
//// //// END-EXAMPLE GenerateMeshHashGenIndices.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashAverageField.cxx ////
//// //// BEGIN-EXAMPLE GenerateMeshHashAverageField.cxx
class AverageCellField : public vtkm::worklet::WorkletReduceByKey ////
class AverageCellEdgesFieldWorklet : public vtkm::worklet::WorkletReduceByKey
{
public:
using ControlSignature = void(KeysIn keys,
ValuesIn inFieldValues,
ValuesIn localEdgeIndices,
ReducedValuesOut averagedField);
using ExecutionSignature = _4(_2 inFieldValues,
_3 localEdgeIndices,
VisitIndex localEdgeIndex);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename InFieldValuesType, typename LocalEdgeIndicesType>
VTKM_EXEC typename InFieldValuesType::ComponentType operator()(
const InFieldValuesType& inFieldValues,
const LocalEdgeIndicesType& localEdgeIndices,
vtkm::IdComponent localEdgeIndex) const
{ {
public: using FieldType = typename InFieldValuesType::ComponentType;
using ControlSignature = void(KeysIn keys,
ValuesIn inFieldValues,
ValuesIn localEdgeIndices,
ReducedValuesOut averagedField);
using ExecutionSignature = _4(_2 inFieldValues,
_3 localEdgeIndices,
VisitIndex localEdgeIndex);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename InFieldValuesType, typename LocalEdgeIndicesType>
VTKM_EXEC typename InFieldValuesType::ComponentType operator()(
const InFieldValuesType& inFieldValues,
const LocalEdgeIndicesType& localEdgeIndices,
vtkm::IdComponent localEdgeIndex) const
{
using FieldType = typename InFieldValuesType::ComponentType;
FieldType averageField = FieldType(0); FieldType averageField = FieldType(0);
vtkm::IdComponent numValues = 0; vtkm::IdComponent numValues = 0;
for (vtkm::IdComponent reduceIndex = 0; for (vtkm::IdComponent reduceIndex = 0;
reduceIndex < inFieldValues.GetNumberOfComponents(); reduceIndex < inFieldValues.GetNumberOfComponents();
++reduceIndex) ++reduceIndex)
{
if (localEdgeIndices[reduceIndex] == localEdgeIndex)
{ {
if (localEdgeIndices[reduceIndex] == localEdgeIndex) FieldType fieldValue = inFieldValues[reduceIndex];
{ averageField = averageField + fieldValue;
FieldType fieldValue = inFieldValues[reduceIndex]; ++numValues;
averageField = averageField + fieldValue;
++numValues;
}
} }
VTKM_ASSERT(numValues > 0);
return static_cast<FieldType>(averageField / numValues);
} }
}; VTKM_ASSERT(numValues > 0);
//// return static_cast<FieldType>(averageField / numValues);
//// END-EXAMPLE GenerateMeshHashAverageField.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashMapCellField.cxx
////
template<typename ValueType, typename Storage>
VTKM_CONT vtkm::cont::ArrayHandle<ValueType> ProcessCellField(
const vtkm::cont::ArrayHandle<ValueType, Storage>& inCellField) const
{
vtkm::cont::ArrayHandle<ValueType> averageField;
vtkm::worklet::DispatcherReduceByKey<AverageCellField> dispatcher(
*this->HashCollisionScatter);
dispatcher.Invoke(this->CellToEdgeKeys,
vtkm::cont::make_ArrayHandlePermutation(
this->OutputToInputCellMap, inCellField),
this->LocalEdgeIndices,
averageField);
return averageField;
} }
////
//// END-EXAMPLE GenerateMeshHashMapCellField.cxx
////
vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
vtkm::worklet::Keys<vtkm::HashType> CellToEdgeKeys;
vtkm::cont::ArrayHandle<vtkm::IdComponent> LocalEdgeIndices;
std::shared_ptr<vtkm::worklet::ScatterCounting> HashCollisionScatter;
}; };
////
//// END-EXAMPLE GenerateMeshHashAverageField.cxx
////
} // anonymous namespace } // anonymous namespace
...@@ -414,7 +312,10 @@ public: ...@@ -414,7 +312,10 @@ public:
const vtkm::filter::PolicyBase<Policy>& policy); const vtkm::filter::PolicyBase<Policy>& policy);
private: private:
vtkm::worklet::ExtractEdges Worklet; vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
vtkm::worklet::Keys<vtkm::HashType> CellToEdgeKeys;
vtkm::cont::ArrayHandle<vtkm::IdComponent> LocalEdgeIndices;
std::shared_ptr<vtkm::worklet::ScatterCounting> HashCollisionScatter;
}; };
//// PAUSE-EXAMPLE //// PAUSE-EXAMPLE
...@@ -437,22 +338,71 @@ namespace ...@@ -437,22 +338,71 @@ namespace
//// RESUME-EXAMPLE //// RESUME-EXAMPLE
//// ////
//// BEGIN-EXAMPLE ExtractEdgesFilterDoExecute.cxx //// BEGIN-EXAMPLE GenerateMeshHashInvoke.cxx
//// ////
template<typename Policy> template<typename Policy>
inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute( inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(
const vtkm::cont::DataSet& inData, const vtkm::cont::DataSet& inData,
vtkm::filter::PolicyBase<Policy> policy) vtkm::filter::PolicyBase<Policy> policy)
{ {
const vtkm::cont::DynamicCellSet& inCellSet =
const vtkm::cont::DynamicCellSet& inCells = inData.GetCellSet(); vtkm::filter::ApplyPolicyCellSet(inData.GetCellSet(), policy);
vtkm::cont::CellSetSingleType<> outCells = // First, count the edges in each cell.
this->Worklet.Run(vtkm::filter::ApplyPolicyCellSet(inCells, policy)); vtkm::cont::ArrayHandle<vtkm::IdComponent> edgeCounts;
this->Invoke(vtkm::worklet::CountEdgesWorklet{}, inCellSet, edgeCounts);
// Second, using these counts build a scatter that repeats a cell's visit
// for each edge in the cell.
vtkm::worklet::ScatterCounting scatter(edgeCounts);
this->OutputToInputCellMap =
scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputEdgeMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Third, for each edge, extract a hash.
vtkm::cont::ArrayHandle<vtkm::HashType> hashValues;
this->Invoke(vtkm::worklet::EdgeHashesWorklet{}, scatter, inCellSet, hashValues);
// Fourth, use a Keys object to combine all like hashes.
this->CellToEdgeKeys = vtkm::worklet::Keys<vtkm::HashType>(hashValues);
// Fifth, use a reduce-by-key to collect like hash values, resolve collisions,
// and count the number of unique edges associated with each hash.
vtkm::cont::ArrayHandle<vtkm::IdComponent> numUniqueEdgesInEachHash;
this->Invoke(vtkm::worklet::EdgeHashCollisionsWorklet{},
this->CellToEdgeKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputEdgeMap,
this->LocalEdgeIndices,
numUniqueEdgesInEachHash);
// Sixth, use a reduce-by-key to extract indices for each unique edge.
// (Note that HashCollisionScatter is an std::shared_ptr because we cannot copy
// ScatterCounting objects.)
this->HashCollisionScatter.reset(
new vtkm::worklet::ScatterCounting(numUniqueEdgesInEachHash));
vtkm::cont::ArrayHandle<vtkm::Id> connectivityArray;
//// LABEL InvokeEdgeIndices
this->Invoke(vtkm::worklet::EdgeIndicesWorklet{},
*this->HashCollisionScatter,
this->CellToEdgeKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputEdgeMap,
this->LocalEdgeIndices,
vtkm::cont::make_ArrayHandleGroupVec<2>(connectivityArray));
// Seventh, use the created connectivity array to build a cell set.
vtkm::cont::CellSetSingleType<> outCellSet;
outCellSet.Fill(
inCellSet.GetNumberOfPoints(), vtkm::CELL_SHAPE_LINE, 2, connectivityArray);
vtkm::cont::DataSet outData; vtkm::cont::DataSet outData;
outData.SetCellSet(outCells); outData.SetCellSet(outCellSet);
for (vtkm::IdComponent coordSystemIndex = 0; for (vtkm::IdComponent coordSystemIndex = 0;
coordSystemIndex < inData.GetNumberOfCoordinateSystems(); coordSystemIndex < inData.GetNumberOfCoordinateSystems();
...@@ -464,40 +414,48 @@ inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute( ...@@ -464,40 +414,48 @@ inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(
return outData; return outData;
} }
//// ////
//// END-EXAMPLE ExtractEdgesFilterDoExecute.cxx //// END-EXAMPLE GenerateMeshHashInvoke.cxx
//// ////
//// ////
//// BEGIN-EXAMPLE ExtractEdgesFilterDoMapField.cxx //// BEGIN-EXAMPLE GenerateMeshHashMapCellField.cxx
//// ////
template<typename T, typename StorageType, typename Policy> template<typename T, typename StorageType, typename Policy>
inline VTKM_CONT bool ExtractEdges::DoMapField( inline VTKM_CONT bool ExtractEdges::DoMapField(
vtkm::cont::DataSet& result, vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input, const vtkm::cont::ArrayHandle<T, StorageType>& inputArray,
const vtkm::filter::FieldMetadata& fieldMeta, const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<Policy>&) const vtkm::filter::PolicyBase<Policy>&)
{ {
vtkm::cont::Field output; vtkm::cont::Field outputField;
if (fieldMeta.IsPointField()) if (fieldMeta.IsPointField())
{ {
output = fieldMeta.AsField(input); // pass through outputField = fieldMeta.AsField(inputArray); // pass through
} }
else if (fieldMeta.IsCellField()) else if (fieldMeta.IsCellField())
{ {
output = fieldMeta.AsField(this->Worklet.ProcessCellField(input)); vtkm::cont::ArrayHandle<T> averageField;
this->Invoke(vtkm::worklet::AverageCellEdgesFieldWorklet{},
*this->HashCollisionScatter,
this->CellToEdgeKeys,
vtkm::cont::make_ArrayHandlePermutation(this->OutputToInputCellMap,
inputArray),
this->LocalEdgeIndices,
averageField);
outputField = fieldMeta.AsField(averageField);
} }
else else
{ {
return false; return false;
} }
result.AddField(output); result.AddField(outputField);
return true; return true;
} }
//// ////
//// END-EXAMPLE ExtractEdgesFilterDoMapField.cxx //// END-EXAMPLE GenerateMeshHashMapCellField.cxx
//// ////
//// PAUSE-EXAMPLE //// PAUSE-EXAMPLE
...@@ -602,19 +560,6 @@ void CheckOutput(const vtkm::cont::CellSetSingleType<>& cellSet, ...@@ -602,19 +560,6 @@ void CheckOutput(const vtkm::cont::CellSetSingleType<>& cellSet,
CheckEdge(connectivityPortal, fieldPortal, vtkm::Id2(9, 10), 130.5f); CheckEdge(connectivityPortal, fieldPortal, vtkm::Id2(9, 10), 130.5f);
} }
// void TryWorklet()
//{
// std::cout << std::endl << "Trying calling worklet." << std::endl;
// vtkm::cont::DataSet inDataSet =
// vtkm::cont::testing::MakeTestDataSet().Make3DExplicitDataSet5();
// vtkm::cont::CellSetExplicit<> inCellSet;
// inDataSet.GetCellSet().CopyTo(inCellSet);
// vtkm::worklet::ExtractEdges worklet;
// vtkm::cont::CellSetSingleType<> outCellSet = worklet.Run(inCellSet);
// CheckOutput(outCellSet);
//}
void TryFilter() void TryFilter()
{ {
std::cout << std::endl << "Trying calling filter." << std::endl; std::cout << std::endl << "Trying calling filter." << std::endl;
...@@ -623,9 +568,6 @@ void TryFilter() ...@@ -623,9 +568,6 @@ void TryFilter()
vtkm::filter::ExtractEdges filter; vtkm::filter::ExtractEdges filter;
// NOTE 2018-03-21: I expect this to fail in the short term. Right now no fields
// are copied from input to output. The default should be changed to copy them
// all.
vtkm::cont::DataSet outDataSet = filter.Execute(inDataSet); vtkm::cont::DataSet outDataSet = filter.Execute(inDataSet);
vtkm::cont::CellSetSingleType<> outCellSet; vtkm::cont::CellSetSingleType<> outCellSet;
...@@ -640,7 +582,6 @@ void TryFilter() ...@@ -640,7 +582,6 @@ void TryFilter()
void DoTest() void DoTest()
{ {
// TryWorklet();
TryFilter(); TryFilter();
} }
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#include <vtkm/Hash.h> #include <vtkm/Hash.h>
#include <vtkm/worklet/AverageByKey.h> #include <vtkm/worklet/AverageByKey.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/DispatcherReduceByKey.h>
#include <vtkm/worklet/Keys.h> #include <vtkm/worklet/Keys.h>
#include <vtkm/worklet/ScatterCounting.h> #include <vtkm/worklet/ScatterCounting.h>
...@@ -27,419 +25,287 @@ namespace worklet ...@@ -27,419 +25,287 @@ namespace worklet
namespace namespace
{ {
struct ExtractFaces struct CountFacesWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
{ {
struct CountFaces : vtkm::worklet::WorkletVisitCellsWithPoints using ControlSignature = void(CellSetIn cellSet, FieldOut numFaces);
{ using ExecutionSignature = _2(CellShape);
using ControlSignature = void(CellSetIn cellSet, FieldOut numFaces); using InputDomain = _1;
using ExecutionSignature = _2(CellShape);
using InputDomain = _1;
template<typename CellShapeTag> template<typename CellShapeTag>
VTKM_EXEC_CONT vtkm::IdComponent operator()(CellShapeTag cellShape) const VTKM_EXEC_CONT vtkm::IdComponent operator()(CellShapeTag cellShape) const
{ {
return vtkm::exec::CellFaceNumberOfFaces(cellShape, *this); return vtkm::exec::CellFaceNumberOfFaces(cellShape, *this);
} }
}; };
class FaceHashes : public vtkm::worklet::WorkletVisitCellsWithPoints class FaceHashesWorklet : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
using ControlSignature = void(CellSetIn cellSet, FieldOut hashValues);
using ExecutionSignature = _2(CellShape cellShape,
PointIndices globalPointIndices,
VisitIndex localFaceIndex);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellShapeTag, typename PointIndexVecType>
VTKM_EXEC vtkm::HashType operator()(
CellShapeTag cellShape,
const PointIndexVecType& globalPointIndicesForCell,
vtkm::IdComponent localFaceIndex) const
{ {
public:
using ControlSignature = void(CellSetIn cellSet, FieldOut hashValues);
using ExecutionSignature = _2(CellShape cellShape,
PointIndices globalPointIndices,
VisitIndex localFaceIndex);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellShapeTag, typename PointIndexVecType>
VTKM_EXEC vtkm::HashType operator()(
CellShapeTag cellShape,
const PointIndexVecType& globalPointIndicesForCell,
vtkm::IdComponent localFaceIndex) const
{
//// PAUSE-EXAMPLE //// PAUSE-EXAMPLE
#ifndef CHECK_COLLISIONS #ifndef CHECK_COLLISIONS
//// RESUME-EXAMPLE //// RESUME-EXAMPLE
return vtkm::Hash(vtkm::exec::CellFaceCanonicalId( return vtkm::Hash(vtkm::exec::CellFaceCanonicalId(
localFaceIndex, cellShape, globalPointIndicesForCell, *this)); localFaceIndex, cellShape, globalPointIndicesForCell, *this));
//// PAUSE-EXAMPLE //// PAUSE-EXAMPLE
#else // ! CHECK_COLLISIONS \ #else // ! CHECK_COLLISIONS \
// Intentionally use a bad hash value to cause collisions to check to make \ // Intentionally use a bad hash value to cause collisions to check to make \
// sure that collision resolution works. // sure that collision resolution works.
return vtkm::HashType(vtkm::exec::CellFaceCanonicalId( return vtkm::HashType(vtkm::exec::CellFaceCanonicalId(
localFaceIndex, cellShape, globalPointIndicesForCell, *this)[0]); localFaceIndex, cellShape, globalPointIndicesForCell, *this)[0]);
#endif // !CHECK_COLLISIONS #endif // !CHECK_COLLISIONS
//// RESUME-EXAMPLE //// RESUME-EXAMPLE
} }
}; };
class FaceHashCollisions : public vtkm::worklet::WorkletReduceByKey class FaceHashCollisionsWorklet : public vtkm::worklet::WorkletReduceByKey
{
public:
using ControlSignature = void(KeysIn keys,
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originFaces,
ValuesOut localFaceIndices,
ReducedValuesOut numFaces);
using ExecutionSignature = _6(_2 inputCells,
_3 originCells,
_4 originFaces,
_5 localFaceIndices);
using InputDomain = _1;
template<typename CellSetType,
typename OriginCellsType,
typename OriginFacesType,
typename localFaceIndicesType>
VTKM_EXEC vtkm::IdComponent operator()(
const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginFacesType& originFaces,
localFaceIndicesType& localFaceIndices) const
{ {
public: vtkm::IdComponent numFacesInHash = localFaceIndices.GetNumberOfComponents();
using ControlSignature = void(KeysIn keys,
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originFaces,
ValuesOut localFaceIndices,
ReducedValuesOut numFaces);
using ExecutionSignature = _6(_2 inputCells,
_3 originCells,
_4 originFaces,
_5 localFaceIndices);
using InputDomain = _1;
template<typename CellSetType,
typename OriginCellsType,
typename OriginFacesType,
typename localFaceIndicesType>
VTKM_EXEC vtkm::IdComponent operator()(
const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginFacesType& originFaces,
localFaceIndicesType& localFaceIndices) const
{
vtkm::IdComponent numFacesInHash = localFaceIndices.GetNumberOfComponents();
// Sanity checks. // Sanity checks.
VTKM_ASSERT(originCells.GetNumberOfComponents() == numFacesInHash); VTKM_ASSERT(originCells.GetNumberOfComponents() == numFacesInHash);
VTKM_ASSERT(originFaces.GetNumberOfComponents() == numFacesInHash); VTKM_ASSERT(originFaces.GetNumberOfComponents() == numFacesInHash);
// Clear out localFaceIndices // Clear out localFaceIndices
for (vtkm::IdComponent index = 0; index < numFacesInHash; ++index) for (vtkm::IdComponent index = 0; index < numFacesInHash; ++index)
{ {
localFaceIndices[index] = -1; localFaceIndices[index] = -1;
} }
// Count how many unique faces there are and create an id for each; // Count how many unique faces there are and create an id for each;
vtkm::IdComponent numUniqueFaces = 0; vtkm::IdComponent numUniqueFaces = 0;
for (vtkm::IdComponent firstFaceIndex = 0; firstFaceIndex < numFacesInHash; for (vtkm::IdComponent firstFaceIndex = 0; firstFaceIndex < numFacesInHash;
++firstFaceIndex) ++firstFaceIndex)
{
if (localFaceIndices[firstFaceIndex] == -1)
{ {
if (localFaceIndices[firstFaceIndex] == -1) vtkm::IdComponent faceId = numUniqueFaces;
localFaceIndices[firstFaceIndex] = faceId;
// Find all matching faces.
vtkm::Id firstCellIndex = originCells[firstFaceIndex];
vtkm::Id3 canonicalFaceId =
vtkm::exec::CellFaceCanonicalId(originFaces[firstFaceIndex],
cellSet.GetCellShape(firstCellIndex),
cellSet.GetIndices(firstCellIndex),
*this);
for (vtkm::IdComponent laterFaceIndex = firstFaceIndex + 1;
laterFaceIndex < numFacesInHash;
++laterFaceIndex)
{ {
vtkm::IdComponent faceId = numUniqueFaces; vtkm::Id laterCellIndex = originCells[laterFaceIndex];
localFaceIndices[firstFaceIndex] = faceId; vtkm::Id3 otherCanonicalFaceId =
// Find all matching faces. vtkm::exec::CellFaceCanonicalId(originFaces[laterFaceIndex],
vtkm::Id firstCellIndex = originCells[firstFaceIndex]; cellSet.GetCellShape(laterCellIndex),
vtkm::Id3 canonicalFaceId = cellSet.GetIndices(laterCellIndex),
vtkm::exec::CellFaceCanonicalId(originFaces[firstFaceIndex],
cellSet.GetCellShape(firstCellIndex),
cellSet.GetIndices(firstCellIndex),
*this); *this);
for (vtkm::IdComponent laterFaceIndex = firstFaceIndex + 1; if (canonicalFaceId == otherCanonicalFaceId)
laterFaceIndex < numFacesInHash;
++laterFaceIndex)
{ {
vtkm::Id laterCellIndex = originCells[laterFaceIndex]; localFaceIndices[laterFaceIndex] = faceId;
vtkm::Id3 otherCanonicalFaceId =
vtkm::exec::CellFaceCanonicalId(originFaces[laterFaceIndex],
cellSet.GetCellShape(laterCellIndex),
cellSet.GetIndices(laterCellIndex),
*this);
if (canonicalFaceId == otherCanonicalFaceId)
{
localFaceIndices[laterFaceIndex] = faceId;
}
} }
++numUniqueFaces;
} }
++numUniqueFaces;
} }
return numUniqueFaces;
} }
};
//// return numUniqueFaces;
//// BEGIN-EXAMPLE GenerateMeshVariableShapeCountPointsInFace.cxx }
//// };
class CountPointsInFace : public vtkm::worklet::WorkletReduceByKey
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeCountPointsInFace.cxx
////
class CountPointsInFaceWorklet : public vtkm::worklet::WorkletReduceByKey
{
public:
using ControlSignature = void(KeysIn keys,
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originFaces,
ValuesIn localFaceIndices,
ReducedValuesOut faceShape,
ReducedValuesOut numPointsInEachFace);
using ExecutionSignature = void(_2 inputCells,
_3 originCell,
_4 originFace,
_5 localFaceIndices,
VisitIndex localFaceIndex,
_6 faceShape,
_7 numPointsInFace);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellSetType,
typename OriginCellsType,
typename OriginFacesType,
typename LocalFaceIndicesType>
VTKM_EXEC void operator()(const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginFacesType& originFaces,
const LocalFaceIndicesType& localFaceIndices,
vtkm::IdComponent localFaceIndex,
vtkm::UInt8& faceShape,
vtkm::IdComponent& numPointsInFace) const
{ {
public: // Find the first face that matches the index given.
using ControlSignature = void(KeysIn keys, for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originFaces,
ValuesIn localFaceIndices,
ReducedValuesOut faceShape,
ReducedValuesOut numPointsInEachFace);
using ExecutionSignature = void(_2 inputCells,
_3 originCell,
_4 originFace,
_5 localFaceIndices,
VisitIndex localFaceIndex,
_6 faceShape,
_7 numPointsInFace);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellSetType,
typename OriginCellsType,
typename OriginFacesType,
typename LocalFaceIndicesType>
VTKM_EXEC void operator()(const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginFacesType& originFaces,
const LocalFaceIndicesType& localFaceIndices,
vtkm::IdComponent localFaceIndex,
vtkm::UInt8& faceShape,
vtkm::IdComponent& numPointsInFace) const
{ {
// Find the first face that matches the index given. if (localFaceIndices[faceIndex] == localFaceIndex)
for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
{ {
if (localFaceIndices[faceIndex] == localFaceIndex) vtkm::Id cellIndex = originCells[faceIndex];
{ faceShape = vtkm::exec::CellFaceShape(
vtkm::Id cellIndex = originCells[faceIndex]; originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this);
faceShape = vtkm::exec::CellFaceShape( numPointsInFace = vtkm::exec::CellFaceNumberOfPoints(
originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this); originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this);
numPointsInFace = vtkm::exec::CellFaceNumberOfPoints( break;
originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this);
break;
}
} }
} }
}; }
//// };
//// END-EXAMPLE GenerateMeshVariableShapeCountPointsInFace.cxx ////
//// //// END-EXAMPLE GenerateMeshVariableShapeCountPointsInFace.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeGenIndices.cxx ////
//// //// BEGIN-EXAMPLE GenerateMeshVariableShapeGenIndices.cxx
class FaceIndices : public vtkm::worklet::WorkletReduceByKey ////
class FaceIndicesWorklet : public vtkm::worklet::WorkletReduceByKey
{
public:
using ControlSignature = void(KeysIn keys,
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originFaces,
ValuesIn localFaceIndices,
ReducedValuesOut connectivityOut);
using ExecutionSignature = void(_2 inputCells,
_3 originCell,
_4 originFace,
_5 localFaceIndices,
VisitIndex localFaceIndex,
_6 connectivityOut);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellSetType,
typename OriginCellsType,
typename OriginFacesType,
typename LocalFaceIndicesType,
typename ConnectivityVecType>
VTKM_EXEC void operator()(const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginFacesType& originFaces,
const LocalFaceIndicesType& localFaceIndices,
vtkm::IdComponent localFaceIndex,
ConnectivityVecType& connectivityOut) const
{ {
public: // Find the first face that matches the index given and return it.
using ControlSignature = void(KeysIn keys, for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
WholeCellSetIn<> inputCells,
ValuesIn originCells,
ValuesIn originFaces,
ValuesIn localFaceIndices,
ReducedValuesOut connectivityOut);
using ExecutionSignature = void(_2 inputCells,
_3 originCell,
_4 originFace,
_5 localFaceIndices,
VisitIndex localFaceIndex,
_6 connectivityOut);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename CellSetType,
typename OriginCellsType,
typename OriginFacesType,
typename LocalFaceIndicesType,
typename ConnectivityVecType>
VTKM_EXEC void operator()(const CellSetType& cellSet,
const OriginCellsType& originCells,
const OriginFacesType& originFaces,
const LocalFaceIndicesType& localFaceIndices,
vtkm::IdComponent localFaceIndex,
ConnectivityVecType& connectivityOut) const
{ {
// Find the first face that matches the index given and return it. if (localFaceIndices[faceIndex] == localFaceIndex)
for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
{ {
if (localFaceIndices[faceIndex] == localFaceIndex) vtkm::Id cellIndex = originCells[faceIndex];
vtkm::IdComponent faceInCellIndex = originFaces[faceIndex];
auto cellShape = cellSet.GetCellShape(cellIndex);
vtkm::IdComponent numPointsInFace = connectivityOut.GetNumberOfComponents();
VTKM_ASSERT(
numPointsInFace ==
vtkm::exec::CellFaceNumberOfPoints(faceInCellIndex, cellShape, *this));
auto globalPointIndicesForCell = cellSet.GetIndices(cellIndex);
for (vtkm::IdComponent localPointI = 0; localPointI < numPointsInFace;
++localPointI)
{ {
vtkm::Id cellIndex = originCells[faceIndex]; vtkm::IdComponent pointInCellIndex = vtkm::exec::CellFaceLocalIndex(
vtkm::IdComponent faceInCellIndex = originFaces[faceIndex]; localPointI, faceInCellIndex, cellShape, *this);
auto cellShape = cellSet.GetCellShape(cellIndex); connectivityOut[localPointI] = globalPointIndicesForCell[pointInCellIndex];
vtkm::IdComponent numPointsInFace =
connectivityOut.GetNumberOfComponents();
VTKM_ASSERT(
numPointsInFace ==
vtkm::exec::CellFaceNumberOfPoints(faceInCellIndex, cellShape, *this));
auto globalPointIndicesForCell = cellSet.GetIndices(cellIndex);
for (vtkm::IdComponent localPointI = 0; localPointI < numPointsInFace;
++localPointI)
{
vtkm::IdComponent pointInCellIndex = vtkm::exec::CellFaceLocalIndex(
localPointI, faceInCellIndex, cellShape, *this);
connectivityOut[localPointI] =
globalPointIndicesForCell[pointInCellIndex];
}
break;
} }
break;
} }
} }
};
////
//// END-EXAMPLE GenerateMeshVariableShapeGenIndices.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeInvoke.cxx
////
template<typename InCellSetType>
VTKM_CONT vtkm::cont::CellSetExplicit<> Run(const InCellSetType& inCellSet)
{
VTKM_IS_DYNAMIC_OR_STATIC_CELL_SET(InCellSetType);
using OutCellSetType = vtkm::cont::CellSetExplicit<>;
// First, count the faces in each cell.
vtkm::cont::ArrayHandle<vtkm::IdComponent> faceCounts;
vtkm::worklet::DispatcherMapTopology<CountFaces> countFaceDispatcher;
countFaceDispatcher.Invoke(inCellSet, faceCounts);
vtkm::worklet::ScatterCounting scatter(faceCounts);
this->OutputToInputCellMap =
scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputFaceMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Second, for each face, extract a hash.
vtkm::cont::ArrayHandle<vtkm::HashType> hashValues;
vtkm::worklet::DispatcherMapTopology<FaceHashes> FaceHashesDispatcher(scatter);
FaceHashesDispatcher.Invoke(inCellSet, hashValues);
// Third, use a Keys object to combine all like hashes.
this->CellToFaceKeys = vtkm::worklet::Keys<vtkm::HashType>(hashValues);
// Fourth, use a reduce-by-key to collect like hash values, resolve collisions,
// and count the number of unique faces associated with each hash.
vtkm::cont::ArrayHandle<vtkm::IdComponent> numUniqueFacesInEachHash;
vtkm::worklet::DispatcherReduceByKey<FaceHashCollisions>
faceHashCollisionDispatcher;
faceHashCollisionDispatcher.Invoke(this->CellToFaceKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputFaceMap,
this->LocalFaceIndices,
numUniqueFacesInEachHash);
// Fifth, use a reduce-by-key to count the number of points in each unique face.
// Also identify the shape of each face.
this->HashCollisionScatter.reset(
new vtkm::worklet::ScatterCounting(numUniqueFacesInEachHash));
OutCellSetType::ShapeArrayType shapeArray;
OutCellSetType::NumIndicesArrayType numPointsInEachFace;
vtkm::worklet::DispatcherReduceByKey<CountPointsInFace> countPointsDispatcher(
*this->HashCollisionScatter);
countPointsDispatcher.Invoke(this->CellToFaceKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputFaceMap,
this->LocalFaceIndices,
shapeArray,
numPointsInEachFace);
// Sixth, convert the numPointsInEachFace array to an offsets array and use that
// to create an ArrayHandleGroupVecVariable.
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeOffsetsArray.cxx
////
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray;
vtkm::Id connectivityArraySize;
vtkm::cont::ConvertNumComponentsToOffsets(
numPointsInEachFace, offsetsArray, connectivityArraySize);
OutCellSetType::ConnectivityArrayType connectivityArray;
connectivityArray.Allocate(connectivityArraySize);
auto connectivityArrayVecs =
vtkm::cont::make_ArrayHandleGroupVecVariable(connectivityArray, offsetsArray);
////
//// END-EXAMPLE GenerateMeshVariableShapeOffsetsArray.cxx
////
// Seventh, use a reduce-by-key to extract indices for each unique face.
vtkm::worklet::DispatcherReduceByKey<FaceIndices> faceIndicesDispatcher(
*this->HashCollisionScatter);
faceIndicesDispatcher.Invoke(this->CellToFaceKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputFaceMap,
this->LocalFaceIndices,
connectivityArrayVecs);
// Eigth, use the created connectivity array and others to build a cell set.
OutCellSetType outCellSet;
outCellSet.Fill(inCellSet.GetNumberOfPoints(),
shapeArray,
numPointsInEachFace,
connectivityArray);
return outCellSet;
} }
//// };
//// END-EXAMPLE GenerateMeshVariableShapeInvoke.cxx ////
//// //// END-EXAMPLE GenerateMeshVariableShapeGenIndices.cxx
////
class AverageCellField : public vtkm::worklet::WorkletReduceByKey class AverageCellFacesFieldWorklet : public vtkm::worklet::WorkletReduceByKey
{
public:
using ControlSignature = void(KeysIn keys,
ValuesIn inFieldValues,
ValuesIn localFaceIndices,
ReducedValuesOut averagedField);
using ExecutionSignature = _4(_2 inFieldValues,
_3 localFaceIndices,
VisitIndex localFaceIndex);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename InFieldValuesType, typename LocalFaceIndicesType>
VTKM_EXEC typename InFieldValuesType::ComponentType operator()(
const InFieldValuesType& inFieldValues,
const LocalFaceIndicesType& localFaceIndices,
vtkm::IdComponent localFaceIndex) const
{ {
public: using FieldType = typename InFieldValuesType::ComponentType;
using ControlSignature = void(KeysIn keys,
ValuesIn inFieldValues,
ValuesIn localFaceIndices,
ReducedValuesOut averagedField);
using ExecutionSignature = _4(_2 inFieldValues,
_3 localFaceIndices,
VisitIndex localFaceIndex);
using InputDomain = _1;
using ScatterType = vtkm::worklet::ScatterCounting;
template<typename InFieldValuesType, typename LocalFaceIndicesType>
VTKM_EXEC typename InFieldValuesType::ComponentType operator()(
const InFieldValuesType& inFieldValues,
const LocalFaceIndicesType& localFaceIndices,
vtkm::IdComponent localFaceIndex) const
{
using FieldType = typename InFieldValuesType::ComponentType;
FieldType averageField = FieldType(0); FieldType averageField = FieldType(0);
vtkm::IdComponent numValues = 0; vtkm::IdComponent numValues = 0;
for (vtkm::IdComponent reduceIndex = 0; for (vtkm::IdComponent reduceIndex = 0;
reduceIndex < inFieldValues.GetNumberOfComponents(); reduceIndex < inFieldValues.GetNumberOfComponents();
++reduceIndex) ++reduceIndex)
{
if (localFaceIndices[reduceIndex] == localFaceIndex)
{ {
if (localFaceIndices[reduceIndex] == localFaceIndex) FieldType fieldValue = inFieldValues[reduceIndex];
{ averageField = averageField + fieldValue;
FieldType fieldValue = inFieldValues[reduceIndex]; ++numValues;
averageField = averageField + fieldValue;
++numValues;
}
} }
VTKM_ASSERT(numValues > 0);
return static_cast<FieldType>(averageField / numValues);
} }
}; VTKM_ASSERT(numValues > 0);
return static_cast<FieldType>(averageField / numValues);
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeMapCellField.cxx
////
template<typename ValueType, typename Storage>
VTKM_CONT vtkm::cont::ArrayHandle<ValueType> ProcessCellField(
const vtkm::cont::ArrayHandle<ValueType, Storage>& inCellField) const
{
vtkm::cont::ArrayHandle<ValueType> averageField;
vtkm::worklet::DispatcherReduceByKey<AverageCellField> dispatcher(
*this->HashCollisionScatter);
dispatcher.Invoke(this->CellToFaceKeys,
vtkm::cont::make_ArrayHandlePermutation(
this->OutputToInputCellMap, inCellField),
this->LocalFaceIndices,
averageField);
return averageField;
} }
////
//// END-EXAMPLE GenerateMeshVariableShapeMapCellField.cxx
////
vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
vtkm::worklet::Keys<vtkm::HashType> CellToFaceKeys;
vtkm::cont::ArrayHandle<vtkm::IdComponent> LocalFaceIndices;
std::shared_ptr<vtkm::worklet::ScatterCounting> HashCollisionScatter;
}; };
} // anonymous namespace } // anonymous namespace
...@@ -471,7 +337,10 @@ public: ...@@ -471,7 +337,10 @@ public:
const vtkm::filter::PolicyBase<Policy>& policy); const vtkm::filter::PolicyBase<Policy>& policy);
private: private:
vtkm::worklet::ExtractFaces Worklet; vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
vtkm::worklet::Keys<vtkm::HashType> CellToFaceKeys;
vtkm::cont::ArrayHandle<vtkm::IdComponent> LocalFaceIndices;
std::shared_ptr<vtkm::worklet::ScatterCounting> HashCollisionScatter;
}; };
//// PAUSE-EXAMPLE //// PAUSE-EXAMPLE
...@@ -490,20 +359,105 @@ namespace ...@@ -490,20 +359,105 @@ namespace
{ {
//// RESUME-EXAMPLE //// RESUME-EXAMPLE
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeInvoke.cxx
////
template<typename Policy> template<typename Policy>
inline VTKM_CONT vtkm::cont::DataSet ExtractFaces::DoExecute( inline VTKM_CONT vtkm::cont::DataSet ExtractFaces::DoExecute(
const vtkm::cont::DataSet& inData, const vtkm::cont::DataSet& inData,
vtkm::filter::PolicyBase<Policy> policy) vtkm::filter::PolicyBase<Policy> policy)
{ {
const vtkm::cont::DynamicCellSet& inCells = inData.GetCellSet(); const vtkm::cont::DynamicCellSet& inCellSet =
vtkm::filter::ApplyPolicyCellSet(inData.GetCellSet(), policy);
// First, count the faces in each cell.
vtkm::cont::ArrayHandle<vtkm::IdComponent> faceCounts;
this->Invoke(vtkm::worklet::CountFacesWorklet{}, inCellSet, faceCounts);
// Second, using these counts build a scatter that repeats a cell's visit
// for each edge in the cell.
vtkm::worklet::ScatterCounting scatter(faceCounts);
this->OutputToInputCellMap =
scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputFaceMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Third, for each face, extract a hash.
vtkm::cont::ArrayHandle<vtkm::HashType> hashValues;
this->Invoke(vtkm::worklet::FaceHashesWorklet{}, scatter, inCellSet, hashValues);
// Fourth, use a Keys object to combine all like hashes.
this->CellToFaceKeys = vtkm::worklet::Keys<vtkm::HashType>(hashValues);
// Fifth, use a reduce-by-key to collect like hash values, resolve collisions,
// and count the number of unique faces associated with each hash.
vtkm::cont::ArrayHandle<vtkm::IdComponent> numUniqueFacesInEachHash;
this->Invoke(vtkm::worklet::FaceHashCollisionsWorklet{},
this->CellToFaceKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputFaceMap,
this->LocalFaceIndices,
numUniqueFacesInEachHash);
// Sixth, use a reduce-by-key to count the number of points in each unique face.
// Also identify the shape of each face.
this->HashCollisionScatter.reset(
new vtkm::worklet::ScatterCounting(numUniqueFacesInEachHash));
vtkm::cont::CellSetExplicit<>::ShapesArrayType shapeArray;
vtkm::cont::ArrayHandle<vtkm::IdComponent> numPointsInEachFace;
this->Invoke(vtkm::worklet::CountPointsInFaceWorklet{},
*this->HashCollisionScatter,
this->CellToFaceKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputFaceMap,
this->LocalFaceIndices,
shapeArray,
numPointsInEachFace);
// Seventh, convert the numPointsInEachFace array to an offsets array and use that
// to create an ArrayHandleGroupVecVariable.
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeOffsetsArray.cxx
////
vtkm::cont::ArrayHandle<vtkm::Id> offsetsExtended;
vtkm::Id connectivityArraySize;
vtkm::cont::ConvertNumIndicesToOffsets(
numPointsInEachFace, offsetsExtended, connectivityArraySize);
auto offsetsExclusive = vtkm::cont::make_ArrayHandleView(
offsetsExtended, 0, offsetsExtended.GetNumberOfValues() - 1);
vtkm::cont::CellSetExplicit<>::ConnectivityArrayType connectivityArray;
connectivityArray.Allocate(connectivityArraySize);
auto connectivityArrayVecs = vtkm::cont::make_ArrayHandleGroupVecVariable(
connectivityArray, offsetsExclusive);
////
//// END-EXAMPLE GenerateMeshVariableShapeOffsetsArray.cxx
////
vtkm::cont::CellSetExplicit<> outCells = // Eigth, use a reduce-by-key to extract indices for each unique face.
this->Worklet.Run(vtkm::filter::ApplyPolicyCellSet(inCells, policy)); this->Invoke(vtkm::worklet::FaceIndicesWorklet{},
*this->HashCollisionScatter,
this->CellToFaceKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputFaceMap,
this->LocalFaceIndices,
connectivityArrayVecs);
// Ninth, use the created connectivity array and others to build a cell set.
vtkm::cont::CellSetExplicit<> outCellSet;
outCellSet.Fill(
inCellSet.GetNumberOfPoints(), shapeArray, connectivityArray, offsetsExtended);
vtkm::cont::DataSet outData; vtkm::cont::DataSet outData;
outData.SetCellSet(outCells); outData.SetCellSet(outCellSet);
for (vtkm::IdComponent coordSystemIndex = 0; for (vtkm::IdComponent coordSystemIndex = 0;
coordSystemIndex < inData.GetNumberOfCoordinateSystems(); coordSystemIndex < inData.GetNumberOfCoordinateSystems();
...@@ -514,33 +468,51 @@ inline VTKM_CONT vtkm::cont::DataSet ExtractFaces::DoExecute( ...@@ -514,33 +468,51 @@ inline VTKM_CONT vtkm::cont::DataSet ExtractFaces::DoExecute(
return outData; return outData;
} }
////
//// END-EXAMPLE GenerateMeshVariableShapeInvoke.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeMapCellField.cxx
////
template<typename T, typename StorageType, typename Policy> template<typename T, typename StorageType, typename Policy>
inline VTKM_CONT bool ExtractFaces::DoMapField( inline VTKM_CONT bool ExtractFaces::DoMapField(
vtkm::cont::DataSet& result, vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input, const vtkm::cont::ArrayHandle<T, StorageType>& inputArray,
const vtkm::filter::FieldMetadata& fieldMeta, const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<Policy>&) const vtkm::filter::PolicyBase<Policy>&)
{ {
vtkm::cont::Field output; vtkm::cont::Field outputField;
if (fieldMeta.IsPointField()) if (fieldMeta.IsPointField())
{ {
output = fieldMeta.AsField(input); // pass through outputField = fieldMeta.AsField(inputArray); // pass through
} }
else if (fieldMeta.IsCellField()) else if (fieldMeta.IsCellField())
{ {
output = fieldMeta.AsField(this->Worklet.ProcessCellField(input)); vtkm::cont::ArrayHandle<T> averageFieldArray;
this->Invoke(vtkm::worklet::AverageCellFacesFieldWorklet{},
*this->HashCollisionScatter,
this->CellToFaceKeys,
vtkm::cont::make_ArrayHandlePermutation(this->OutputToInputCellMap,
inputArray),
this->LocalFaceIndices,
averageFieldArray);
outputField = fieldMeta.AsField(averageFieldArray);
} }
else else
{ {
return false; return false;
} }
result.AddField(output); result.AddField(outputField);
return true; return true;
} }
////
//// END-EXAMPLE GenerateMeshVariableShapeMapCellField.cxx
////
//// PAUSE-EXAMPLE //// PAUSE-EXAMPLE
} // anonymous namespace } // anonymous namespace
...@@ -649,11 +621,13 @@ void CheckOutput(const vtkm::cont::CellSetExplicit<>& cellSet, ...@@ -649,11 +621,13 @@ void CheckOutput(const vtkm::cont::CellSetExplicit<>& cellSet,
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
auto connectivity = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(), auto connectivity = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagPoint());
auto offsets = cellSet.GetIndexOffsetArray(vtkm::TopologyElementTagCell(), auto offsetsExtended = cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagPoint());
auto offsetsExclusive = vtkm::cont::make_ArrayHandleView(
offsetsExtended, 0, offsetsExtended.GetNumberOfValues() - 1);
std::cout << "Offsets:" << std::endl; std::cout << "Offsets:" << std::endl;
vtkm::cont::printSummary_ArrayHandle(offsets, std::cout, true); vtkm::cont::printSummary_ArrayHandle(offsetsExclusive, std::cout, true);
std::cout << "Connectivity:" << std::endl; std::cout << "Connectivity:" << std::endl;
vtkm::cont::printSummary_ArrayHandle(connectivity, std::cout, true); vtkm::cont::printSummary_ArrayHandle(connectivity, std::cout, true);
...@@ -662,7 +636,7 @@ void CheckOutput(const vtkm::cont::CellSetExplicit<>& cellSet, ...@@ -662,7 +636,7 @@ void CheckOutput(const vtkm::cont::CellSetExplicit<>& cellSet,
auto nPointsP = numPointsPerFace.GetPortalConstControl(); auto nPointsP = numPointsPerFace.GetPortalConstControl();
auto connectivityP = connectivity.GetPortalConstControl(); auto connectivityP = connectivity.GetPortalConstControl();
auto offsetsP = offsets.GetPortalConstControl(); auto offsetsP = offsetsExclusive.GetPortalConstControl();
auto fieldP = cellField.GetPortalConstControl(); auto fieldP = cellField.GetPortalConstControl();
CheckFace(nPointsP, connectivityP, offsetsP, fieldP, vtkm::Id3(0, 1, 2), 100.1f); CheckFace(nPointsP, connectivityP, offsetsP, fieldP, vtkm::Id3(0, 1, 2), 100.1f);
CheckFace(nPointsP, connectivityP, offsetsP, fieldP, vtkm::Id3(0, 1, 5), 100.1f); CheckFace(nPointsP, connectivityP, offsetsP, fieldP, vtkm::Id3(0, 1, 5), 100.1f);
......
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/ScatterCounting.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/testing/TestingImplicitFunction.h>
namespace
{
class CutImplicitFunction : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
CutImplicitFunction(const vtkm::ImplicitFunction* function)
: Function(function)
{
}
template<typename VecType>
VTKM_EXEC void operator()(const VecType& point, VecType& ret) const
{
if (this->Function->Value(point) > 0)
{
ret = point;
}
else
{
ret = VecType(0, 0, 0);
}
}
private:
const vtkm::ImplicitFunction* Function;
};
void Run()
{
using vtkm::cont::testing::implicit_function_detail::TestArrayEqual;
constexpr vtkm::Id nVerts = 16;
vtkm::Vec3f_32 data[nVerts] = {
vtkm::Vec3f_32(1, 1, 1), vtkm::Vec3f_32(1, 1, 0), vtkm::Vec3f_32(1, 1, -1),
vtkm::Vec3f_32(1, 1, -2), vtkm::Vec3f_32(1, 2, 1), vtkm::Vec3f_32(1, 2, 0),
vtkm::Vec3f_32(1, 2, -1), vtkm::Vec3f_32(1, 2, -2), vtkm::Vec3f_32(2, 1, 1),
vtkm::Vec3f_32(2, 1, 0), vtkm::Vec3f_32(2, 1, -1), vtkm::Vec3f_32(2, 1, -2),
vtkm::Vec3f_32(2, 2, 1), vtkm::Vec3f_32(2, 2, 0), vtkm::Vec3f_32(2, 2, -1),
vtkm::Vec3f_32(2, 2, -2),
};
////
//// BEGIN-EXAMPLE ImplicitFunctionHandle.cxx
////
auto coordinates =
vtkm::cont::make_CoordinateSystem("coordinates", data, 16, vtkm::CopyFlag::On);
auto handle = vtkm::cont::make_ImplicitFunctionHandle(
vtkm::Sphere({ 2.0f, 2.0f, -2.0f }, 2.0f));
vtkm::cont::ArrayHandle<vtkm::Vec3f> internalPoints;
CutImplicitFunction func(
handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagSerial()));
vtkm::worklet::DispatcherMapField<CutImplicitFunction> dispatcher(func);
dispatcher.Invoke(coordinates, internalPoints);
////
//// END-EXAMPLE ImplicitFunctionHandle.cxx
////
std::array<vtkm::Vec3f, 16> values = { { { 1.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 1.0f, 2.0f, 1.0f },
{ 1.0f, 2.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 2.0f, 1.0f, 1.0f },
{ 2.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 2.0f, 2.0f, 1.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f } } };
VTKM_TEST_ASSERT(TestArrayEqual(internalPoints, values),
"Results don't match internal values.");
}
} // anonymous namespace
int ImplicitFunctions(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
}
...@@ -93,6 +93,9 @@ void DoClipWithImplicitFunction() ...@@ -93,6 +93,9 @@ void DoClipWithImplicitFunction()
//// ////
//// BEGIN-EXAMPLE ClipWithImplicitFunction.cxx //// BEGIN-EXAMPLE ClipWithImplicitFunction.cxx
//// ////
////
//// BEGIN-EXAMPLE ImplicitFunctionHandle.cxx
////
// Parameters needed for implicit function // Parameters needed for implicit function
vtkm::Sphere implicitFunction(vtkm::make_Vec(1, 0, 1), 0.5); vtkm::Sphere implicitFunction(vtkm::make_Vec(1, 0, 1), 0.5);
...@@ -100,6 +103,9 @@ void DoClipWithImplicitFunction() ...@@ -100,6 +103,9 @@ void DoClipWithImplicitFunction()
vtkm::filter::ClipWithImplicitFunction clip; vtkm::filter::ClipWithImplicitFunction clip;
clip.SetImplicitFunction( clip.SetImplicitFunction(
vtkm::cont::make_ImplicitFunctionHandle(implicitFunction)); vtkm::cont::make_ImplicitFunctionHandle(implicitFunction));
////
//// END-EXAMPLE ImplicitFunctionHandle.cxx
////
// By default, ClipWithImplicitFunction will remove everything inside the sphere. // By default, ClipWithImplicitFunction will remove everything inside the sphere.
// Set the invert clip flag to keep the inside of the sphere and remove everything // Set the invert clip flag to keep the inside of the sphere and remove everything
......
File added
No preview for this file type