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 @@
#include <vtkm/Hash.h>
#include <vtkm/worklet/AverageByKey.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/DispatcherReduceByKey.h>
#include <vtkm/worklet/Keys.h>
#include <vtkm/worklet/ScatterCounting.h>
......@@ -26,361 +24,261 @@ namespace worklet
namespace
{
struct ExtractEdges
////
//// BEGIN-EXAMPLE GenerateMeshHashCount.cxx
////
struct CountEdgesWorklet : vtkm::worklet::WorkletVisitCellsWithPoints
{
////
//// BEGIN-EXAMPLE GenerateMeshHashCount.cxx
////
struct CountEdges : vtkm::worklet::WorkletVisitCellsWithPoints
using ControlSignature = void(CellSetIn cellSet, FieldOut numEdges);
using ExecutionSignature = _2(CellShape, PointCount);
using InputDomain = _1;
template<typename CellShapeTag>
VTKM_EXEC_CONT vtkm::IdComponent operator()(
CellShapeTag cellShape,
vtkm::IdComponent numPointsInCell) const
{
using ControlSignature = void(CellSetIn cellSet, FieldOut numEdges);
using ExecutionSignature = _2(CellShape, PointCount);
using InputDomain = _1;
template<typename CellShapeTag>
VTKM_EXEC_CONT vtkm::IdComponent operator()(
CellShapeTag cellShape,
vtkm::IdComponent numPointsInCell) const
{
return vtkm::exec::CellEdgeNumberOfEdges(numPointsInCell, cellShape, *this);
}
};
////
//// END-EXAMPLE GenerateMeshHashCount.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashGenHashes.cxx
////
class EdgeHashes : public vtkm::worklet::WorkletVisitCellsWithPoints
return vtkm::exec::CellEdgeNumberOfEdges(numPointsInCell, cellShape, *this);
}
};
////
//// END-EXAMPLE GenerateMeshHashCount.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashGenHashes.cxx
////
class EdgeHashesWorklet : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
using ControlSignature = void(CellSetIn cellSet, FieldOut hashValues);
using ExecutionSignature = _2(CellShape cellShape,
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
{
public:
using ControlSignature = void(CellSetIn cellSet, FieldOut hashValues);
using ExecutionSignature = _2(CellShape cellShape,
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
vtkm::IdComponent numPointsInCell =
globalPointIndicesForCell.GetNumberOfComponents();
//// PAUSE-EXAMPLE
#ifndef CHECK_COLLISIONS
//// RESUME-EXAMPLE
return vtkm::Hash(vtkm::exec::CellEdgeCanonicalId(numPointsInCell,
localEdgeIndex,
cellShape,
globalPointIndicesForCell,
*this));
//// PAUSE-EXAMPLE
//// RESUME-EXAMPLE
return vtkm::Hash(vtkm::exec::CellEdgeCanonicalId(
numPointsInCell, localEdgeIndex, cellShape, globalPointIndicesForCell, *this));
//// PAUSE-EXAMPLE
#else // ! CHECK_COLLISIONS \
// Intentionally use a bad hash value to cause collisions to check to make \
// sure that collision resolution works.
return vtkm::HashType(
vtkm::exec::CellEdgeCanonicalId(numPointsInCell,
localEdgeIndex,
cellShape,
globalPointIndicesForCell,
*this)[0]);
// Intentionally use a bad hash value to cause collisions to check to make \
// sure that collision resolution works.
return vtkm::HashType(vtkm::exec::CellEdgeCanonicalId(numPointsInCell,
localEdgeIndex,
cellShape,
globalPointIndicesForCell,
*this)[0]);
#endif // !CHECK_COLLISIONS
//// RESUME-EXAMPLE
}
};
////
//// END-EXAMPLE GenerateMeshHashGenHashes.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashResolveCollisions.cxx
////
class EdgeHashCollisions : public vtkm::worklet::WorkletReduceByKey
//// RESUME-EXAMPLE
}
};
////
//// END-EXAMPLE GenerateMeshHashGenHashes.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashResolveCollisions.cxx
////
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:
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();
vtkm::IdComponent numEdgesInHash = localEdgeIndices.GetNumberOfComponents();
// Sanity checks.
VTKM_ASSERT(originCells.GetNumberOfComponents() == numEdgesInHash);
VTKM_ASSERT(originEdges.GetNumberOfComponents() == numEdgesInHash);
// Sanity checks.
VTKM_ASSERT(originCells.GetNumberOfComponents() == numEdgesInHash);
VTKM_ASSERT(originEdges.GetNumberOfComponents() == numEdgesInHash);
// Clear out localEdgeIndices
for (vtkm::IdComponent index = 0; index < numEdgesInHash; ++index)
{
localEdgeIndices[index] = -1;
}
// Clear out localEdgeIndices
for (vtkm::IdComponent index = 0; index < numEdgesInHash; ++index)
{
localEdgeIndices[index] = -1;
}
// Count how many unique edges there are and create an id for each;
vtkm::IdComponent numUniqueEdges = 0;
for (vtkm::IdComponent firstEdgeIndex = 0; firstEdgeIndex < numEdgesInHash;
++firstEdgeIndex)
// Count how many unique edges there are and create an id for each;
vtkm::IdComponent numUniqueEdges = 0;
for (vtkm::IdComponent firstEdgeIndex = 0; firstEdgeIndex < numEdgesInHash;
++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;
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),
vtkm::Id laterCellIndex = originCells[laterEdgeIndex];
vtkm::Id2 otherCanonicalEdgeId = vtkm::exec::CellEdgeCanonicalId(
cellSet.GetNumberOfIndices(laterCellIndex),
originEdges[laterEdgeIndex],
cellSet.GetCellShape(laterCellIndex),
cellSet.GetIndices(laterCellIndex),
*this);
for (vtkm::IdComponent laterEdgeIndex = firstEdgeIndex + 1;
laterEdgeIndex < numEdgesInHash;
++laterEdgeIndex)
if (canonicalEdgeId == otherCanonicalEdgeId)
{
vtkm::Id laterCellIndex = originCells[laterEdgeIndex];
vtkm::Id2 otherCanonicalEdgeId = vtkm::exec::CellEdgeCanonicalId(
cellSet.GetNumberOfIndices(laterCellIndex),
originEdges[laterEdgeIndex],
cellSet.GetCellShape(laterCellIndex),
cellSet.GetIndices(laterCellIndex),
*this);
if (canonicalEdgeId == otherCanonicalEdgeId)
{
localEdgeIndices[laterEdgeIndex] = edgeId;
}
localEdgeIndices[laterEdgeIndex] = edgeId;
}
++numUniqueEdges;
}
++numUniqueEdges;
}
return numUniqueEdges;
}
};
////
//// END-EXAMPLE GenerateMeshHashResolveCollisions.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashGenIndices.cxx
////
class EdgeIndices : public vtkm::worklet::WorkletReduceByKey
return numUniqueEdges;
}
};
////
//// END-EXAMPLE GenerateMeshHashResolveCollisions.cxx
////
////
//// 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:
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
// Find the first edge that matches the index given and return it.
for (vtkm::IdComponent edgeIndex = 0;; ++edgeIndex)
{
// Find the first edge that matches the index given and return it.
for (vtkm::IdComponent edgeIndex = 0;; ++edgeIndex)
if (localEdgeIndices[edgeIndex] == localEdgeIndex)
{
if (localEdgeIndices[edgeIndex] == localEdgeIndex)
{
vtkm::Id cellIndex = originCells[edgeIndex];
vtkm::IdComponent numPointsInCell = cellSet.GetNumberOfIndices(cellIndex);
vtkm::IdComponent edgeInCellIndex = originEdges[edgeIndex];
auto cellShape = cellSet.GetCellShape(cellIndex);
vtkm::Id cellIndex = originCells[edgeIndex];
vtkm::IdComponent numPointsInCell = cellSet.GetNumberOfIndices(cellIndex);
vtkm::IdComponent edgeInCellIndex = originEdges[edgeIndex];
auto cellShape = cellSet.GetCellShape(cellIndex);
vtkm::IdComponent pointInCellIndex0 = vtkm::exec::CellEdgeLocalIndex(
numPointsInCell, 0, edgeInCellIndex, cellShape, *this);
vtkm::IdComponent pointInCellIndex1 = vtkm::exec::CellEdgeLocalIndex(
numPointsInCell, 1, edgeInCellIndex, cellShape, *this);
vtkm::IdComponent pointInCellIndex0 = vtkm::exec::CellEdgeLocalIndex(
numPointsInCell, 0, edgeInCellIndex, cellShape, *this);
vtkm::IdComponent pointInCellIndex1 = vtkm::exec::CellEdgeLocalIndex(
numPointsInCell, 1, edgeInCellIndex, cellShape, *this);
auto globalPointIndicesForCell = cellSet.GetIndices(cellIndex);
connectivityOut[0] = globalPointIndicesForCell[pointInCellIndex0];
connectivityOut[1] = globalPointIndicesForCell[pointInCellIndex1];
auto globalPointIndicesForCell = cellSet.GetIndices(cellIndex);
connectivityOut[0] = globalPointIndicesForCell[pointInCellIndex0];
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
////
////
//// BEGIN-EXAMPLE GenerateMeshHashAverageField.cxx
////
class AverageCellField : public vtkm::worklet::WorkletReduceByKey
};
////
//// END-EXAMPLE GenerateMeshHashGenIndices.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshHashAverageField.cxx
////
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 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;
using FieldType = typename InFieldValuesType::ComponentType;
FieldType averageField = FieldType(0);
vtkm::IdComponent numValues = 0;
for (vtkm::IdComponent reduceIndex = 0;
reduceIndex < inFieldValues.GetNumberOfComponents();
++reduceIndex)
FieldType averageField = FieldType(0);
vtkm::IdComponent numValues = 0;
for (vtkm::IdComponent reduceIndex = 0;
reduceIndex < inFieldValues.GetNumberOfComponents();
++reduceIndex)
{
if (localEdgeIndices[reduceIndex] == localEdgeIndex)
{
if (localEdgeIndices[reduceIndex] == localEdgeIndex)
{
FieldType fieldValue = inFieldValues[reduceIndex];
averageField = averageField + fieldValue;
++numValues;
}
FieldType fieldValue = inFieldValues[reduceIndex];
averageField = averageField + fieldValue;
++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;
VTKM_ASSERT(numValues > 0);
return static_cast<FieldType>(averageField / numValues);
}
////
//// 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
......@@ -414,7 +312,10 @@ public:
const vtkm::filter::PolicyBase<Policy>& policy);
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
......@@ -437,22 +338,71 @@ namespace
//// RESUME-EXAMPLE
////
//// BEGIN-EXAMPLE ExtractEdgesFilterDoExecute.cxx
//// BEGIN-EXAMPLE GenerateMeshHashInvoke.cxx
////
template<typename Policy>
inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(
const vtkm::cont::DataSet& inData,
vtkm::filter::PolicyBase<Policy> policy)
{
const vtkm::cont::DynamicCellSet& inCells = inData.GetCellSet();
vtkm::cont::CellSetSingleType<> outCells =
this->Worklet.Run(vtkm::filter::ApplyPolicyCellSet(inCells, policy));
const vtkm::cont::DynamicCellSet& inCellSet =
vtkm::filter::ApplyPolicyCellSet(inData.GetCellSet(), policy);
// First, count the edges in each cell.
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;
outData.SetCellSet(outCells);
outData.SetCellSet(outCellSet);
for (vtkm::IdComponent coordSystemIndex = 0;
coordSystemIndex < inData.GetNumberOfCoordinateSystems();
......@@ -464,40 +414,48 @@ inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(
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>
inline VTKM_CONT bool ExtractEdges::DoMapField(
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::PolicyBase<Policy>&)
{
vtkm::cont::Field output;
vtkm::cont::Field outputField;
if (fieldMeta.IsPointField())
{
output = fieldMeta.AsField(input); // pass through
outputField = fieldMeta.AsField(inputArray); // pass through
}
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
{
return false;
}
result.AddField(output);
result.AddField(outputField);
return true;
}
////
//// END-EXAMPLE ExtractEdgesFilterDoMapField.cxx
//// END-EXAMPLE GenerateMeshHashMapCellField.cxx
////
//// PAUSE-EXAMPLE
......@@ -602,19 +560,6 @@ void CheckOutput(const vtkm::cont::CellSetSingleType<>& cellSet,
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()
{
std::cout << std::endl << "Trying calling filter." << std::endl;
......@@ -623,9 +568,6 @@ void TryFilter()
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::CellSetSingleType<> outCellSet;
......@@ -640,7 +582,6 @@ void TryFilter()
void DoTest()
{
// TryWorklet();
TryFilter();
}
......
......@@ -7,8 +7,6 @@
#include <vtkm/Hash.h>
#include <vtkm/worklet/AverageByKey.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/DispatcherReduceByKey.h>
#include <vtkm/worklet/Keys.h>
#include <vtkm/worklet/ScatterCounting.h>
......@@ -27,419 +25,287 @@ namespace worklet
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 InputDomain = _1;
using ControlSignature = void(CellSetIn cellSet, FieldOut numFaces);
using ExecutionSignature = _2(CellShape);
using InputDomain = _1;
template<typename CellShapeTag>
VTKM_EXEC_CONT vtkm::IdComponent operator()(CellShapeTag cellShape) const
{
return vtkm::exec::CellFaceNumberOfFaces(cellShape, *this);
}
};
template<typename CellShapeTag>
VTKM_EXEC_CONT vtkm::IdComponent operator()(CellShapeTag cellShape) const
{
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
#ifndef CHECK_COLLISIONS
//// RESUME-EXAMPLE
return vtkm::Hash(vtkm::exec::CellFaceCanonicalId(
localFaceIndex, cellShape, globalPointIndicesForCell, *this));
//// RESUME-EXAMPLE
return vtkm::Hash(vtkm::exec::CellFaceCanonicalId(
localFaceIndex, cellShape, globalPointIndicesForCell, *this));
//// PAUSE-EXAMPLE
#else // ! CHECK_COLLISIONS \
// Intentionally use a bad hash value to cause collisions to check to make \
// sure that collision resolution works.
return vtkm::HashType(vtkm::exec::CellFaceCanonicalId(
localFaceIndex, cellShape, globalPointIndicesForCell, *this)[0]);
return vtkm::HashType(vtkm::exec::CellFaceCanonicalId(
localFaceIndex, cellShape, globalPointIndicesForCell, *this)[0]);
#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:
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();
vtkm::IdComponent numFacesInHash = localFaceIndices.GetNumberOfComponents();
// Sanity checks.
VTKM_ASSERT(originCells.GetNumberOfComponents() == numFacesInHash);
VTKM_ASSERT(originFaces.GetNumberOfComponents() == numFacesInHash);
// Sanity checks.
VTKM_ASSERT(originCells.GetNumberOfComponents() == numFacesInHash);
VTKM_ASSERT(originFaces.GetNumberOfComponents() == numFacesInHash);
// Clear out localFaceIndices
for (vtkm::IdComponent index = 0; index < numFacesInHash; ++index)
{
localFaceIndices[index] = -1;
}
// Clear out localFaceIndices
for (vtkm::IdComponent index = 0; index < numFacesInHash; ++index)
{
localFaceIndices[index] = -1;
}
// Count how many unique faces there are and create an id for each;
vtkm::IdComponent numUniqueFaces = 0;
for (vtkm::IdComponent firstFaceIndex = 0; firstFaceIndex < numFacesInHash;
++firstFaceIndex)
// Count how many unique faces there are and create an id for each;
vtkm::IdComponent numUniqueFaces = 0;
for (vtkm::IdComponent firstFaceIndex = 0; firstFaceIndex < numFacesInHash;
++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;
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),
vtkm::Id laterCellIndex = originCells[laterFaceIndex];
vtkm::Id3 otherCanonicalFaceId =
vtkm::exec::CellFaceCanonicalId(originFaces[laterFaceIndex],
cellSet.GetCellShape(laterCellIndex),
cellSet.GetIndices(laterCellIndex),
*this);
for (vtkm::IdComponent laterFaceIndex = firstFaceIndex + 1;
laterFaceIndex < numFacesInHash;
++laterFaceIndex)
if (canonicalFaceId == otherCanonicalFaceId)
{
vtkm::Id laterCellIndex = originCells[laterFaceIndex];
vtkm::Id3 otherCanonicalFaceId =
vtkm::exec::CellFaceCanonicalId(originFaces[laterFaceIndex],
cellSet.GetCellShape(laterCellIndex),
cellSet.GetIndices(laterCellIndex),
*this);
if (canonicalFaceId == otherCanonicalFaceId)
{
localFaceIndices[laterFaceIndex] = faceId;
}
localFaceIndices[laterFaceIndex] = faceId;
}
++numUniqueFaces;
}
++numUniqueFaces;
}
return numUniqueFaces;
}
};
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeCountPointsInFace.cxx
////
class CountPointsInFace : public vtkm::worklet::WorkletReduceByKey
return numUniqueFaces;
}
};
////
//// 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:
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
// Find the first face that matches the index given.
for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
{
// Find the first face that matches the index given.
for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
if (localFaceIndices[faceIndex] == localFaceIndex)
{
if (localFaceIndices[faceIndex] == localFaceIndex)
{
vtkm::Id cellIndex = originCells[faceIndex];
faceShape = vtkm::exec::CellFaceShape(
originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this);
numPointsInFace = vtkm::exec::CellFaceNumberOfPoints(
originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this);
break;
}
vtkm::Id cellIndex = originCells[faceIndex];
faceShape = vtkm::exec::CellFaceShape(
originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this);
numPointsInFace = vtkm::exec::CellFaceNumberOfPoints(
originFaces[faceIndex], cellSet.GetCellShape(cellIndex), *this);
break;
}
}
};
////
//// END-EXAMPLE GenerateMeshVariableShapeCountPointsInFace.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeGenIndices.cxx
////
class FaceIndices : public vtkm::worklet::WorkletReduceByKey
}
};
////
//// END-EXAMPLE GenerateMeshVariableShapeCountPointsInFace.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeGenIndices.cxx
////
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:
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
// Find the first face that matches the index given and return it.
for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
{
// Find the first face that matches the index given and return it.
for (vtkm::IdComponent faceIndex = 0;; ++faceIndex)
if (localFaceIndices[faceIndex] == localFaceIndex)
{
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 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::IdComponent pointInCellIndex = vtkm::exec::CellFaceLocalIndex(
localPointI, faceInCellIndex, cellShape, *this);
connectivityOut[localPointI] =
globalPointIndicesForCell[pointInCellIndex];
}
break;
vtkm::IdComponent pointInCellIndex = vtkm::exec::CellFaceLocalIndex(
localPointI, faceInCellIndex, cellShape, *this);
connectivityOut[localPointI] = globalPointIndicesForCell[pointInCellIndex];
}
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 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;
using FieldType = typename InFieldValuesType::ComponentType;
FieldType averageField = FieldType(0);
vtkm::IdComponent numValues = 0;
for (vtkm::IdComponent reduceIndex = 0;
reduceIndex < inFieldValues.GetNumberOfComponents();
++reduceIndex)
FieldType averageField = FieldType(0);
vtkm::IdComponent numValues = 0;
for (vtkm::IdComponent reduceIndex = 0;
reduceIndex < inFieldValues.GetNumberOfComponents();
++reduceIndex)
{
if (localFaceIndices[reduceIndex] == localFaceIndex)
{
if (localFaceIndices[reduceIndex] == localFaceIndex)
{
FieldType fieldValue = inFieldValues[reduceIndex];
averageField = averageField + fieldValue;
++numValues;
}
FieldType fieldValue = inFieldValues[reduceIndex];
averageField = averageField + fieldValue;
++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;
VTKM_ASSERT(numValues > 0);
return static_cast<FieldType>(averageField / numValues);
}
////
//// 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
......@@ -471,7 +337,10 @@ public:
const vtkm::filter::PolicyBase<Policy>& policy);
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
......@@ -490,20 +359,105 @@ namespace
{
//// RESUME-EXAMPLE
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeInvoke.cxx
////
template<typename Policy>
inline VTKM_CONT vtkm::cont::DataSet ExtractFaces::DoExecute(
const vtkm::cont::DataSet& inData,
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 =
this->Worklet.Run(vtkm::filter::ApplyPolicyCellSet(inCells, policy));
// Eigth, use a reduce-by-key to extract indices for each unique face.
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;
outData.SetCellSet(outCells);
outData.SetCellSet(outCellSet);
for (vtkm::IdComponent coordSystemIndex = 0;
coordSystemIndex < inData.GetNumberOfCoordinateSystems();
......@@ -514,33 +468,51 @@ inline VTKM_CONT vtkm::cont::DataSet ExtractFaces::DoExecute(
return outData;
}
////
//// END-EXAMPLE GenerateMeshVariableShapeInvoke.cxx
////
////
//// BEGIN-EXAMPLE GenerateMeshVariableShapeMapCellField.cxx
////
template<typename T, typename StorageType, typename Policy>
inline VTKM_CONT bool ExtractFaces::DoMapField(
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::PolicyBase<Policy>&)
{
vtkm::cont::Field output;
vtkm::cont::Field outputField;
if (fieldMeta.IsPointField())
{
output = fieldMeta.AsField(input); // pass through
outputField = fieldMeta.AsField(inputArray); // pass through
}
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
{
return false;
}
result.AddField(output);
result.AddField(outputField);
return true;
}
////
//// END-EXAMPLE GenerateMeshVariableShapeMapCellField.cxx
////
//// PAUSE-EXAMPLE
} // anonymous namespace
......@@ -649,11 +621,13 @@ void CheckOutput(const vtkm::cont::CellSetExplicit<>& cellSet,
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
auto connectivity = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint());
auto offsets = cellSet.GetIndexOffsetArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint());
auto offsetsExtended = cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint());
auto offsetsExclusive = vtkm::cont::make_ArrayHandleView(
offsetsExtended, 0, offsetsExtended.GetNumberOfValues() - 1);
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;
vtkm::cont::printSummary_ArrayHandle(connectivity, std::cout, true);
......@@ -662,7 +636,7 @@ void CheckOutput(const vtkm::cont::CellSetExplicit<>& cellSet,
auto nPointsP = numPointsPerFace.GetPortalConstControl();
auto connectivityP = connectivity.GetPortalConstControl();
auto offsetsP = offsets.GetPortalConstControl();
auto offsetsP = offsetsExclusive.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, 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()
////
//// BEGIN-EXAMPLE ClipWithImplicitFunction.cxx
////
////
//// BEGIN-EXAMPLE ImplicitFunctionHandle.cxx
////
// Parameters needed for implicit function
vtkm::Sphere implicitFunction(vtkm::make_Vec(1, 0, 1), 0.5);
......@@ -100,6 +103,9 @@ void DoClipWithImplicitFunction()
vtkm::filter::ClipWithImplicitFunction clip;
clip.SetImplicitFunction(
vtkm::cont::make_ImplicitFunctionHandle(implicitFunction));
////
//// END-EXAMPLE ImplicitFunctionHandle.cxx
////
// By default, ClipWithImplicitFunction will remove everything inside the sphere.
// Set the invert clip flag to keep the inside of the sphere and remove everything
......
File added
No preview for this file type