Add reference documentation for Worklet types

This commit is contained in:
Kenneth Moreland 2024-01-12 14:58:07 -05:00
parent 4807417358
commit 3b1bfa0cdd
23 changed files with 2719 additions and 182 deletions

@ -149,8 +149,22 @@ EXCLUDE_PATTERNS = */benchmarking/*
EXCLUDE_PATTERNS += */examples/*
EXCLUDE_PATTERNS += */testing/*
EXCLUDE_PATTERNS += */thirdparty/*
EXCLUDE_PATTERNS += @VTKm_SOURCE_DIR@/vtkm/filter/*/worklet/*
EXCLUDE_PATTERNS += @VTKm_SOURCE_DIR@/vtkm/rendering/raytracing/*
EXCLUDE_PATTERNS += UnitTest*
# Before filters existed in VTK-m, users were expected to interact directly
# with worklets, and several algorithms were written in this way. There are
# some complex algorithms that never made the jump to filters, but we never
# threw them out in hopes they become useful. At some point, we should
# probably delete or remove them, but for now just hide them to keep the
# documentation from getting messy.
EXCLUDE_PATTERNS += @VTKm_SOURCE_DIR@/vtkm/worklet/colorconversion/*
EXCLUDE_PATTERNS += @VTKm_SOURCE_DIR@/vtkm/worklet/cosmotools/*
EXCLUDE_PATTERNS += @VTKm_SOURCE_DIR@/vtkm/worklet/spatialstructure/*
EXCLUDE_PATTERNS += @VTKm_SOURCE_DIR@/vtkm/worklet/splatkernels/*
EXCLUDE_PATTERNS += @VTKm_SOURCE_DIR@/vtkm/worklet/wavelets/*
EXCLUDE_SYMBOLS = thrust
EXCLUDE_SYMBOLS += benchmarking
EXCLUDE_SYMBOLS += detail

@ -29,6 +29,11 @@ set(examples_device
GuideExampleDataSetCreation.cxx
GuideExampleErrorHandling.cxx
GuideExampleSimpleAlgorithm.cxx
GuideExampleUseWorkletMapField.cxx
GuideExampleUseWorkletPointNeighborhood.cxx
GuideExampleUseWorkletReduceByKey.cxx
GuideExampleUseWorkletVisitCellsWithPoints.cxx
GuideExampleUseWorkletVisitPointsWithCells.cxx
)
set(extra_libs)

@ -0,0 +1,226 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/UnknownArrayHandle.h>
#include <vtkm/VecTraits.h>
#include <vtkm/VectorAnalysis.h>
namespace
{
////
//// BEGIN-EXAMPLE UseWorkletMapField
////
class ComputeMagnitude : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn inputVectors, FieldOut outputMagnitudes);
using ExecutionSignature = _2(_1);
using InputDomain = _1;
template<typename T, vtkm::IdComponent Size>
VTKM_EXEC T operator()(const vtkm::Vec<T, Size>& inVector) const
{
return vtkm::Magnitude(inVector);
}
};
////
//// END-EXAMPLE UseWorkletMapField
////
} // anonymous namespace
#include <vtkm/filter/FilterField.h>
#define VTKM_FILTER_VECTOR_CALCULUS_EXPORT
////
//// BEGIN-EXAMPLE UseFilterField
////
namespace vtkm
{
namespace filter
{
namespace vector_calculus
{
//// LABEL Export
class VTKM_FILTER_VECTOR_CALCULUS_EXPORT FieldMagnitude
: public vtkm::filter::FilterField
{
public:
VTKM_CONT FieldMagnitude();
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet) override;
};
} // namespace vector_calculus
} // namespace filter
} // namespace vtkm
////
//// END-EXAMPLE UseFilterField
////
////
//// BEGIN-EXAMPLE FilterFieldImpl
////
namespace vtkm
{
namespace filter
{
namespace vector_calculus
{
VTKM_CONT
FieldMagnitude::FieldMagnitude()
{
this->SetOutputFieldName("");
}
VTKM_CONT vtkm::cont::DataSet FieldMagnitude::DoExecute(
const vtkm::cont::DataSet& inDataSet)
{
vtkm::cont::Field inField = this->GetFieldFromDataSet(inDataSet);
vtkm::cont::UnknownArrayHandle outField;
// Use a C++ lambda expression to provide a callback for CastAndCall. The lambda
// will capture references to local variables like outFieldArray (using `[&]`)
// that it can read and write.
auto resolveType = [&](const auto& inFieldArray) {
using InArrayHandleType = std::decay_t<decltype(inFieldArray)>;
using ComponentType =
typename vtkm::VecTraits<typename InArrayHandleType::ValueType>::ComponentType;
vtkm::cont::ArrayHandle<ComponentType> outFieldArray;
this->Invoke(ComputeMagnitude{}, inFieldArray, outFieldArray);
outField = outFieldArray;
};
//// LABEL CastAndCall
this->CastAndCallVecField<3>(inField, resolveType);
std::string outFieldName = this->GetOutputFieldName();
if (outFieldName == "")
{
outFieldName = inField.GetName() + "_magnitude";
}
return this->CreateResultField(
inDataSet, outFieldName, inField.GetAssociation(), outField);
}
} // namespace vector_calculus
} // namespace filter
} // namespace vtkm
////
//// END-EXAMPLE FilterFieldImpl
////
////
//// BEGIN-EXAMPLE RandomArrayAccess
////
namespace vtkm
{
namespace worklet
{
struct ReverseArrayCopyWorklet : vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn inputArray, WholeArrayOut outputArray);
using ExecutionSignature = void(_1, _2, WorkIndex);
using InputDomain = _1;
template<typename InputType, typename OutputArrayPortalType>
VTKM_EXEC void operator()(const InputType& inputValue,
const OutputArrayPortalType& outputArrayPortal,
vtkm::Id workIndex) const
{
vtkm::Id outIndex = outputArrayPortal.GetNumberOfValues() - workIndex - 1;
if (outIndex >= 0)
{
outputArrayPortal.Set(outIndex, inputValue);
}
else
{
this->RaiseError("Output array not sized correctly.");
}
}
};
} // namespace worklet
} // namespace vtkm
////
//// END-EXAMPLE RandomArrayAccess
////
#include <vtkm/cont/testing/Testing.h>
namespace
{
void Test()
{
static const vtkm::Id ARRAY_SIZE = 10;
vtkm::cont::ArrayHandle<vtkm::Vec3f> inputArray;
inputArray.Allocate(ARRAY_SIZE);
SetPortal(inputArray.WritePortal());
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outputArray;
vtkm::cont::DataSet inputDataSet;
vtkm::cont::CellSetStructured<1> cellSet;
cellSet.SetPointDimensions(ARRAY_SIZE);
inputDataSet.SetCellSet(cellSet);
inputDataSet.AddPointField("test_values", inputArray);
vtkm::filter::vector_calculus::FieldMagnitude fieldMagFilter;
fieldMagFilter.SetActiveField("test_values");
vtkm::cont::DataSet magResult = fieldMagFilter.Execute(inputDataSet);
magResult.GetField("test_values_magnitude").GetData().AsArrayHandle(outputArray);
VTKM_TEST_ASSERT(outputArray.GetNumberOfValues() == ARRAY_SIZE,
"Bad output array size.");
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
vtkm::Vec3f testValue = TestValue(index, vtkm::Vec3f());
vtkm::Float64 expectedValue = sqrt(vtkm::Dot(testValue, testValue));
vtkm::Float64 gotValue = outputArray.ReadPortal().Get(index);
VTKM_TEST_ASSERT(test_equal(expectedValue, gotValue), "Got bad value.");
}
vtkm::cont::ArrayHandle<vtkm::Vec3f> outputArray2;
outputArray2.Allocate(ARRAY_SIZE);
vtkm::cont::Invoker invoker;
invoker(vtkm::worklet::ReverseArrayCopyWorklet{}, inputArray, outputArray2);
VTKM_TEST_ASSERT(outputArray2.GetNumberOfValues() == ARRAY_SIZE,
"Bad output array size.");
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
vtkm::Vec3f expectedValue = TestValue(ARRAY_SIZE - index - 1, vtkm::Vec3f());
vtkm::Vec3f gotValue = outputArray2.ReadPortal().Get(index);
VTKM_TEST_ASSERT(test_equal(expectedValue, gotValue), "Got bad value.");
}
}
} // anonymous namespace
int GuideExampleUseWorkletMapField(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,218 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/worklet/WorkletPointNeighborhood.h>
#include <vtkm/exec/BoundaryState.h>
#include <vtkm/exec/FieldNeighborhood.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DefaultTypes.h>
#include <vtkm/cont/UncertainCellSet.h>
namespace boxfilter
{
////
//// BEGIN-EXAMPLE UseWorkletPointNeighborhood
////
class ApplyBoxKernel : public vtkm::worklet::WorkletPointNeighborhood
{
private:
vtkm::IdComponent NumberOfLayers;
public:
using ControlSignature = void(CellSetIn cellSet,
FieldInNeighborhood inputField,
FieldOut outputField);
using ExecutionSignature = _3(_2, Boundary);
using InputDomain = _1;
ApplyBoxKernel(vtkm::IdComponent kernelSize)
{
VTKM_ASSERT(kernelSize >= 3);
VTKM_ASSERT((kernelSize % 2) == 1);
this->NumberOfLayers = (kernelSize - 1) / 2;
}
template<typename InputFieldPortalType>
VTKM_EXEC typename InputFieldPortalType::ValueType operator()(
const vtkm::exec::FieldNeighborhood<InputFieldPortalType>& inputField,
const vtkm::exec::BoundaryState& boundary) const
{
using T = typename InputFieldPortalType::ValueType;
////
//// BEGIN-EXAMPLE GetNeighborhoodBoundary
////
auto minIndices = boundary.MinNeighborIndices(this->NumberOfLayers);
auto maxIndices = boundary.MaxNeighborIndices(this->NumberOfLayers);
T sum = 0;
vtkm::IdComponent size = 0;
for (vtkm::IdComponent k = minIndices[2]; k <= maxIndices[2]; ++k)
{
for (vtkm::IdComponent j = minIndices[1]; j <= maxIndices[1]; ++j)
{
for (vtkm::IdComponent i = minIndices[0]; i <= maxIndices[0]; ++i)
{
////
//// BEGIN-EXAMPLE GetNeighborhoodFieldValue
////
sum = sum + inputField.Get(i, j, k);
////
//// END-EXAMPLE GetNeighborhoodFieldValue
////
++size;
}
}
}
////
//// END-EXAMPLE GetNeighborhoodBoundary
////
return static_cast<T>(sum / size);
}
};
////
//// END-EXAMPLE UseWorkletPointNeighborhood
////
} // namespace boxfilter
#include <vtkm/filter/FilterField.h>
namespace vtkm
{
namespace filter
{
namespace convolution
{
class BoxFilter : public vtkm::filter::FilterField
{
public:
VTKM_CONT BoxFilter() = default;
VTKM_CONT void SetKernelSize(vtkm::IdComponent size) { this->KernelSize = size; }
VTKM_CONT vtkm::IdComponent GetKernelSize() const { return this->KernelSize; }
protected:
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet) override;
private:
vtkm::IdComponent KernelSize = 3;
};
} // namespace convolution
} // namespace filter
} // namespace vtkm
namespace vtkm
{
namespace filter
{
namespace convolution
{
VTKM_CONT cont::DataSet BoxFilter::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
vtkm::cont::Field inField = this->GetFieldFromDataSet(inDataSet);
if (!inField.IsPointField())
{
throw vtkm::cont::ErrorBadType("Box Filter operates on point data.");
}
vtkm::cont::UncertainCellSet<VTKM_DEFAULT_CELL_SET_LIST_STRUCTURED> cellSet =
inDataSet.GetCellSet();
vtkm::cont::UnknownArrayHandle outFieldArray;
auto resolve_field = [&](auto inArray) {
using T = typename std::decay_t<decltype(inArray)>::ValueType;
vtkm::cont::ArrayHandle<T> outArray;
this->Invoke(
boxfilter::ApplyBoxKernel{ this->KernelSize }, cellSet, inArray, outArray);
outFieldArray = outArray;
};
this->CastAndCallScalarField(inField, resolve_field);
std::string outFieldName = this->GetOutputFieldName();
if (outFieldName == "")
{
outFieldName = inField.GetName() + "_blurred";
}
return this->CreateResultField(
inDataSet, outFieldName, inField.GetAssociation(), outFieldArray);
}
} // namespace convolution
} // namespace filter
} // namespace vtkm
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void CheckBoxFilter(const vtkm::cont::DataSet& dataSet)
{
std::cout << "Check box filter." << std::endl;
static const vtkm::Id NUM_POINTS = 18;
static const vtkm::Float32 expected[NUM_POINTS] = {
60.1875f, 65.2f, 70.2125f, 60.1875f, 65.2f, 70.2125f,
90.2667f, 95.2778f, 100.292f, 90.2667f, 95.2778f, 100.292f,
120.337f, 125.35f, 130.363f, 120.337f, 125.35f, 130.363f
};
vtkm::cont::ArrayHandle<vtkm::Float32> outputArray;
dataSet.GetPointField("pointvar_average").GetData().AsArrayHandle(outputArray);
vtkm::cont::printSummary_ArrayHandle(outputArray, std::cout, true);
VTKM_TEST_ASSERT(outputArray.GetNumberOfValues() == NUM_POINTS);
auto portal = outputArray.ReadPortal();
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
{
vtkm::Float32 computed = portal.Get(index);
VTKM_TEST_ASSERT(
test_equal(expected[index], computed), "Unexpected value at index ", index);
}
}
void Test()
{
vtkm::cont::testing::MakeTestDataSet makeTestDataSet;
std::cout << "Making test data set." << std::endl;
vtkm::cont::DataSet dataSet = makeTestDataSet.Make3DUniformDataSet0();
std::cout << "Running box filter." << std::endl;
vtkm::filter::convolution::BoxFilter boxFilter;
boxFilter.SetKernelSize(3);
boxFilter.SetActiveField("pointvar");
boxFilter.SetOutputFieldName("pointvar_average");
vtkm::cont::DataSet results = boxFilter.Execute(dataSet);
CheckBoxFilter(results);
}
} // anonymous namespace
int GuideExampleUseWorkletPointNeighborhood(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,276 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/Algorithm.h>
#include <vtkm/worklet/Keys.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletReduceByKey.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayRangeCompute.h>
#include <vtkm/Math.h>
#include <vtkm/Range.h>
#include <vtkm/cont/testing/Testing.h>
namespace vtkm
{
namespace worklet
{
////
//// BEGIN-EXAMPLE BinScalars
////
class BinScalars
{
public:
VTKM_EXEC_CONT
BinScalars(const vtkm::Range& range, vtkm::Id numBins)
: Range(range)
, NumBins(numBins)
{
}
VTKM_EXEC_CONT
BinScalars(const vtkm::Range& range, vtkm::Float64 tolerance)
: Range(range)
{
this->NumBins = vtkm::Id(this->Range.Length() / tolerance) + 1;
}
VTKM_EXEC_CONT
vtkm::Id GetBin(vtkm::Float64 value) const
{
vtkm::Float64 ratio = (value - this->Range.Min) / this->Range.Length();
vtkm::Id bin = vtkm::Id(ratio * this->NumBins);
bin = vtkm::Max(bin, vtkm::Id(0));
bin = vtkm::Min(bin, this->NumBins - 1);
return bin;
}
private:
vtkm::Range Range;
vtkm::Id NumBins;
};
////
//// END-EXAMPLE BinScalars
////
struct CreateHistogram
{
vtkm::cont::Invoker Invoke;
////
//// BEGIN-EXAMPLE IdentifyBins
////
struct IdentifyBins : vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn data, FieldOut bins);
using ExecutionSignature = _2(_1);
using InputDomain = _1;
BinScalars Bins;
VTKM_CONT
IdentifyBins(const BinScalars& bins)
: Bins(bins)
{
}
VTKM_EXEC
vtkm::Id operator()(vtkm::Float64 value) const { return Bins.GetBin(value); }
};
////
//// END-EXAMPLE IdentifyBins
////
////
//// BEGIN-EXAMPLE CountBins
////
struct CountBins : vtkm::worklet::WorkletReduceByKey
{
using ControlSignature = void(KeysIn keys, WholeArrayOut binCounts);
using ExecutionSignature = void(_1, ValueCount, _2);
using InputDomain = _1;
template<typename BinCountsPortalType>
VTKM_EXEC void operator()(vtkm::Id binId,
vtkm::IdComponent numValuesInBin,
BinCountsPortalType& binCounts) const
{
binCounts.Set(binId, numValuesInBin);
}
};
////
//// END-EXAMPLE CountBins
////
template<typename InArrayHandleType>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> Run(const InArrayHandleType& valuesArray,
vtkm::Id numBins)
{
VTKM_IS_ARRAY_HANDLE(InArrayHandleType);
vtkm::Range range = vtkm::cont::ArrayRangeCompute(valuesArray).ReadPortal().Get(0);
BinScalars bins(range, numBins);
////
//// BEGIN-EXAMPLE CreateKeysObject
////
vtkm::cont::ArrayHandle<vtkm::Id> binIds;
this->Invoke(IdentifyBins(bins), valuesArray, binIds);
////
//// BEGIN-EXAMPLE InvokeCountBins
////
vtkm::worklet::Keys<vtkm::Id> keys(binIds);
////
//// END-EXAMPLE CreateKeysObject
////
vtkm::cont::ArrayHandle<vtkm::Id> histogram;
vtkm::cont::Algorithm::Copy(vtkm::cont::make_ArrayHandleConstant(0, numBins),
histogram);
this->Invoke(CountBins{}, keys, histogram);
////
//// END-EXAMPLE InvokeCountBins
////
return histogram;
}
};
struct CombineSimilarValues
{
////
//// BEGIN-EXAMPLE CombineSimilarValues
////
struct IdentifyBins : vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn data, FieldOut bins);
using ExecutionSignature = _2(_1);
using InputDomain = _1;
BinScalars Bins;
VTKM_CONT
IdentifyBins(const BinScalars& bins)
: Bins(bins)
{
}
VTKM_EXEC
vtkm::Id operator()(vtkm::Float64 value) const { return Bins.GetBin(value); }
};
////
//// BEGIN-EXAMPLE AverageBins
////
struct BinAverage : vtkm::worklet::WorkletReduceByKey
{
using ControlSignature = void(KeysIn keys,
ValuesIn originalValues,
ReducedValuesOut averages);
using ExecutionSignature = _3(_2);
using InputDomain = _1;
template<typename OriginalValuesVecType>
VTKM_EXEC typename OriginalValuesVecType::ComponentType operator()(
const OriginalValuesVecType& originalValues) const
{
typename OriginalValuesVecType::ComponentType sum = 0;
for (vtkm::IdComponent index = 0; index < originalValues.GetNumberOfComponents();
index++)
{
sum = sum + originalValues[index];
}
return sum / originalValues.GetNumberOfComponents();
}
};
////
//// END-EXAMPLE AverageBins
////
//
// Later in the associated Filter class...
//
//// PAUSE-EXAMPLE
vtkm::cont::Invoker Invoke;
vtkm::Id NumBins;
template<typename InArrayHandleType>
VTKM_CONT vtkm::cont::ArrayHandle<typename InArrayHandleType::ValueType> Run(
const InArrayHandleType& inField,
vtkm::Id numBins)
{
VTKM_IS_ARRAY_HANDLE(InArrayHandleType);
using T = typename InArrayHandleType::ValueType;
this->NumBins = numBins;
//// RESUME-EXAMPLE
vtkm::Range range = vtkm::cont::ArrayRangeCompute(inField).ReadPortal().Get(0);
BinScalars bins(range, numBins);
vtkm::cont::ArrayHandle<vtkm::Id> binIds;
this->Invoke(IdentifyBins(bins), inField, binIds);
vtkm::worklet::Keys<vtkm::Id> keys(binIds);
vtkm::cont::ArrayHandle<T> combinedValues;
this->Invoke(BinAverage{}, keys, inField, combinedValues);
////
//// END-EXAMPLE CombineSimilarValues
////
return combinedValues;
}
};
} // namespace worklet
} // namespace vtkm
void DoWorkletReduceByKeyTest()
{
vtkm::Float64 valueBuffer[52] = {
3.568802153, 2.569206462, 3.369894868, 3.05340034, 3.189916551, 3.021942381,
2.146410817, 3.369740333, 4.034567259, 4.338713076, 3.120994598, 2.448715191,
2.296382644, 2.26980974, 3.610078207, 1.590680158, 3.820785828, 3.291345926,
2.888019663, 3.653905802, 2.670358133, 2.937653941, 4.442601425, 2.041263284,
1.877340015, 3.791255574, 2.064493023, 3.850323345, 5.093379708, 2.303811786,
3.473126279, 3.284056471, 2.892983179, 2.044613478, 2.892095399, 2.317791183,
2.885776085, 3.048176117, 2.973250571, 2.034521666, 2.524893933, 2.558984374,
3.928186666, 3.735811764, 3.527816797, 3.293986156, 2.418477242, 3.63490149,
4.500478394, 3.762309474, 0.0, 6.0
};
vtkm::cont::ArrayHandle<vtkm::Float64> valuesArray =
vtkm::cont::make_ArrayHandle(valueBuffer, 52, vtkm::CopyFlag::On);
vtkm::cont::ArrayHandle<vtkm::Id> histogram =
vtkm::worklet::CreateHistogram().Run(valuesArray, 10);
std::cout << "Histogram: " << std::endl;
vtkm::cont::printSummary_ArrayHandle(histogram, std::cout, true);
vtkm::cont::ArrayHandle<vtkm::Float64> combinedArray =
vtkm::worklet::CombineSimilarValues().Run(valuesArray, 60);
std::cout << "Combined values: " << std::endl;
vtkm::cont::printSummary_ArrayHandle(combinedArray, std::cout, true);
}
int GuideExampleUseWorkletReduceByKey(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoWorkletReduceByKeyTest, argc, argv);
}

@ -0,0 +1,202 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/exec/CellInterpolate.h>
#include <vtkm/exec/ParametricCoordinates.h>
////
//// BEGIN-EXAMPLE UseWorkletVisitCellsWithPoints
////
namespace vtkm
{
namespace worklet
{
struct CellCenter : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
using ControlSignature = void(CellSetIn cellSet,
FieldInPoint inputPointField,
FieldOut outputCellField);
using ExecutionSignature = void(_1, PointCount, _2, _3);
using InputDomain = _1;
template<typename CellShape, typename InputPointFieldType, typename OutputType>
VTKM_EXEC void operator()(CellShape shape,
vtkm::IdComponent numPoints,
const InputPointFieldType& inputPointField,
OutputType& centerOut) const
{
vtkm::Vec3f parametricCenter;
vtkm::exec::ParametricCoordinatesCenter(numPoints, shape, parametricCenter);
vtkm::exec::CellInterpolate(inputPointField, parametricCenter, shape, centerOut);
}
};
} // namespace worklet
} // namespace vtkm
////
//// END-EXAMPLE UseWorkletVisitCellsWithPoints
////
#include <vtkm/filter/FilterField.h>
#define VTKM_FILTER_FIELD_CONVERSION_EXPORT
////
//// BEGIN-EXAMPLE UseFilterFieldWithCells
////
namespace vtkm
{
namespace filter
{
namespace field_conversion
{
class VTKM_FILTER_FIELD_CONVERSION_EXPORT CellCenters : public vtkm::filter::FilterField
{
public:
VTKM_CONT CellCenters();
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet) override;
};
} // namespace field_conversion
} // namespace filter
} // namespace vtkm
////
//// END-EXAMPLE UseFilterFieldWithCells
////
////
//// BEGIN-EXAMPLE FilterFieldWithCellsImpl
////
namespace vtkm
{
namespace filter
{
namespace field_conversion
{
VTKM_CONT
CellCenters::CellCenters()
{
this->SetOutputFieldName("");
}
VTKM_CONT cont::DataSet CellCenters::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
vtkm::cont::Field inField = this->GetFieldFromDataSet(inDataSet);
if (!inField.IsPointField())
{
throw vtkm::cont::ErrorBadType("Cell Centers filter operates on point data.");
}
vtkm::cont::UnknownArrayHandle outUnknownArray;
auto resolveType = [&](const auto& inArray) {
using InArrayHandleType = std::decay_t<decltype(inArray)>;
using ValueType = typename InArrayHandleType::ValueType;
vtkm::cont::ArrayHandle<ValueType> outArray;
this->Invoke(vtkm::worklet::CellCenter{}, inDataSet.GetCellSet(), inArray, outArray);
outUnknownArray = outArray;
};
vtkm::cont::UnknownArrayHandle inUnknownArray = inField.GetData();
//// LABEL CastAndCall
inUnknownArray.CastAndCallForTypesWithFloatFallback<VTKM_DEFAULT_TYPE_LIST,
VTKM_DEFAULT_STORAGE_LIST>(
resolveType);
std::string outFieldName = this->GetOutputFieldName();
if (outFieldName == "")
{
outFieldName = inField.GetName() + "_center";
}
return this->CreateResultFieldCell(inDataSet, outFieldName, outUnknownArray);
}
} // namespace field_conversion
} // namespace filter
} // namespace vtkm
////
//// END-EXAMPLE FilterFieldWithCellsImpl
////
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void CheckCellCenters(const vtkm::cont::DataSet& dataSet)
{
std::cout << "Checking cell centers." << std::endl;
vtkm::cont::CellSetStructured<3> cellSet;
dataSet.GetCellSet().AsCellSet(cellSet);
vtkm::cont::ArrayHandle<vtkm::Vec3f> cellCentersArray;
dataSet.GetCellField("cell_center").GetData().AsArrayHandle(cellCentersArray);
VTKM_TEST_ASSERT(cellSet.GetNumberOfCells() == cellCentersArray.GetNumberOfValues(),
"Cell centers array has wrong number of values.");
vtkm::Id3 cellDimensions = cellSet.GetCellDimensions() - vtkm::Id3(1);
vtkm::cont::ArrayHandle<vtkm::Vec3f>::ReadPortalType cellCentersPortal =
cellCentersArray.ReadPortal();
vtkm::Id cellIndex = 0;
for (vtkm::Id kIndex = 0; kIndex < cellDimensions[2]; kIndex++)
{
for (vtkm::Id jIndex = 0; jIndex < cellDimensions[1]; jIndex++)
{
for (vtkm::Id iIndex = 0; iIndex < cellDimensions[0]; iIndex++)
{
vtkm::Vec3f center = cellCentersPortal.Get(cellIndex);
VTKM_TEST_ASSERT(test_equal(center[0], iIndex + 0.5), "Bad X coord.");
VTKM_TEST_ASSERT(test_equal(center[1], jIndex + 0.5), "Bad Y coord.");
VTKM_TEST_ASSERT(test_equal(center[2], kIndex + 0.5), "Bad Z coord.");
cellIndex++;
}
}
}
}
void Test()
{
vtkm::cont::testing::MakeTestDataSet makeTestDataSet;
std::cout << "Making test data set." << std::endl;
vtkm::cont::DataSet dataSet = makeTestDataSet.Make3DUniformDataSet0();
std::cout << "Finding cell centers with filter." << std::endl;
vtkm::filter::field_conversion::CellCenters cellCentersFilter;
cellCentersFilter.SetUseCoordinateSystemAsField(true);
cellCentersFilter.SetOutputFieldName("cell_center");
vtkm::cont::DataSet results = cellCentersFilter.Execute(dataSet);
CheckCellCenters(results);
}
} // anonymous namespace
int GuideExampleUseWorkletVisitCellsWithPoints(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,159 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Field.h>
////
//// BEGIN-EXAMPLE UseWorkletVisitPointsWithCells
////
class AverageCellField : public vtkm::worklet::WorkletVisitPointsWithCells
{
public:
using ControlSignature = void(CellSetIn cellSet,
FieldInCell inputCellField,
FieldOut outputPointField);
using ExecutionSignature = void(CellCount, _2, _3);
using InputDomain = _1;
template<typename InputCellFieldType, typename OutputFieldType>
VTKM_EXEC void operator()(vtkm::IdComponent numCells,
const InputCellFieldType& inputCellField,
OutputFieldType& fieldAverage) const
{
fieldAverage = OutputFieldType(0);
for (vtkm::IdComponent cellIndex = 0; cellIndex < numCells; cellIndex++)
{
fieldAverage = fieldAverage + inputCellField[cellIndex];
}
//// PAUSE-EXAMPLE
// The following line can create a warning when converting numCells to a
// float. However, casting it is tricky since OutputFieldType could be
// a vector, and that would unnecessarily complicate this example. Instead,
// just suppress the warning.
#ifdef VTKM_MSVC
#pragma warning(push)
#pragma warning(disable : 4244)
#endif
//// RESUME-EXAMPLE
fieldAverage = fieldAverage / OutputFieldType(numCells);
//// PAUSE-EXAMPLE
#ifdef VTKM_MSVC
#pragma warning(pop)
#endif
//// RESUME-EXAMPLE
}
};
//
// Later in the associated Filter class...
//
//// PAUSE-EXAMPLE
struct DemoAverageCellField
{
vtkm::cont::Invoker Invoke;
vtkm::cont::DataSet Run(const vtkm::cont::DataSet& inData)
{
vtkm::cont::DataSet outData;
// Copy parts of structure that should be passed through.
outData.SetCellSet(inData.GetCellSet());
for (vtkm::Id coordSysIndex = 0;
coordSysIndex < inData.GetNumberOfCoordinateSystems();
coordSysIndex++)
{
outData.AddCoordinateSystem(inData.GetCoordinateSystem(coordSysIndex));
}
// Copy all fields, converting cell fields to point fields.
for (vtkm::Id fieldIndex = 0; fieldIndex < inData.GetNumberOfFields(); fieldIndex++)
{
vtkm::cont::Field inField = inData.GetField(fieldIndex);
if (inField.GetAssociation() == vtkm::cont::Field::Association::Cells)
{
using T = vtkm::Float32;
vtkm::cont::ArrayHandle<T> inFieldData;
inField.GetData().AsArrayHandle(inFieldData);
vtkm::cont::UnknownCellSet inCellSet = inData.GetCellSet();
//// RESUME-EXAMPLE
vtkm::cont::ArrayHandle<T> outFieldData;
this->Invoke(AverageCellField{}, inCellSet, inFieldData, outFieldData);
////
//// END-EXAMPLE UseWorkletVisitPointsWithCells
////
outData.AddCellField(inField.GetName(), outFieldData);
}
else
{
outData.AddField(inField);
}
}
return outData;
}
};
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void Test()
{
vtkm::cont::testing::MakeTestDataSet makeTestDataSet;
std::cout << "Making test data set." << std::endl;
vtkm::cont::DataSet inDataSet = makeTestDataSet.Make3DUniformDataSet0();
std::cout << "Average cell data." << std::endl;
vtkm::cont::DataSet resultDataSet = DemoAverageCellField().Run(inDataSet);
std::cout << "Checking cell data converted to points." << std::endl;
vtkm::cont::Field convertedField = resultDataSet.GetField("cellvar");
VTKM_TEST_ASSERT(convertedField.GetAssociation() ==
vtkm::cont::Field::Association::Cells,
"Result field has wrong association.");
const vtkm::Id numPoints = 18;
vtkm::Float64 expectedData[numPoints] = { 100.1, 100.15, 100.2, 100.1, 100.15, 100.2,
100.2, 100.25, 100.3, 100.2, 100.25, 100.3,
100.3, 100.35, 100.4, 100.3, 100.35, 100.4 };
vtkm::cont::ArrayHandle<vtkm::Float32> outData;
convertedField.GetData().AsArrayHandle(outData);
vtkm::cont::ArrayHandle<vtkm::Float32>::ReadPortalType outPortal =
outData.ReadPortal();
vtkm::cont::printSummary_ArrayHandle(outData, std::cout);
std::cout << std::endl;
VTKM_TEST_ASSERT(outPortal.GetNumberOfValues() == numPoints,
"Result array wrong size.");
for (vtkm::Id pointId = 0; pointId < numPoints; pointId++)
{
VTKM_TEST_ASSERT(test_equal(outPortal.Get(pointId), expectedData[pointId]),
"Got wrong result.");
}
}
} // anonymous namespace
int GuideExampleUseWorkletVisitPointsWithCells(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f4f78e5ac429118348bb521a51715d514ce94a61a3e59a8b6f668565b98f0d53
size 834405

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e2d619c70a2884786bd2c2a9d7f5fa7844fe14e75c17268ca3538872910872d2
size 70118

@ -7,3 +7,4 @@ Advanced Development
advanced-types.rst
logging.rst
worklet-types.rst

@ -60,11 +60,10 @@ The function prototype matches what data are provided when the worklet is invoke
The return type of the function prototype is always ``void``.
The parameters of the function prototype are *tags* that identify the type of data that is expected to be passed to invoke.
``ControlSignature`` tags are defined by the worklet type and the various tags are documented more fully in Chapter \ref{chap:WorkletTypeReference}.
``ControlSignature`` tags are defined by the worklet type and the various
tags are documented more fully in :chapref:`worklet-types:Worklet Types`.
In the case of :numref:`ex:ControlSignature`, the two tags ``FieldIn`` and ``FieldOut`` represent input and output data, respectively.
.. todo:: Fix worklet type reference above.
.. index::
single: control signature
single: signature; control

@ -0,0 +1,490 @@
==============================
Worklet Types
==============================
.. index::
single: worklet
single: worklet; creating
:chapref:`simple-worklets:Simple Worklets` introduces worklets and provides a simple example of creating a worklet to run an algorithm on a many core device.
Different operations in visualization can have different data access patterns, perform different execution flow, and require different provisions.
|VTKm| manages these different accesses, execution, and provisions by grouping visualization algorithms into common classes of operation and supporting each class with its own worklet type.
Each worklet type has a generic superclass that worklets of that particular type must inherit.
This makes the type of the worklet easy to identify.
The following list describes each worklet type provided by |VTKm| and the superclass that supports it.
.. index::
double: worklet; field map
* **Field Map**
A worklet deriving :class:`vtkm::worklet::WorkletMapField` performs a basic mapping operation that applies a function (the operator in the worklet) on all the field values at a single point or cell and creates a new field value at that same location.
Although the intention is to operate on some variable over a mesh, a :class:`vtkm::worklet::WorkletMapField` may actually be applied to any array.
Thus, a field map can be used as a basic :index:`map` operation.
.. index::
double: worklet; topology map
double: worklet; visit cells
double: worklet; visit points
* **Topology Map**
A worklet deriving :class:`vtkm::worklet::WorkletMapTopology` or one of its child classes performs a mapping operation that applies a function (the operator in the worklet) on all elements of a particular type (such as points or cells) and creates a new field for those elements.
The basic operation is similar to a field map except that in addition to access fields being mapped on, the worklet operation also has access to incident fields.
There are multiple convenience classes available for the most common types of topology mapping.
:class:`vtkm::worklet::WorkletVisitCellsWithPoints` calls the worklet operation for each cell and makes every incident point available.
This type of map also has access to cell structures and can interpolate point fields.
Likewise, :class:`vtkm::worklet::WorkletVisitPointsWithCells` calls the worklet operation for each point and makes every incident cell available.
.. index::
double: worklet; point neighborhood
* **Point Neighborhood**
A worklet deriving from :class:`vtkm::worklet::WorkletPointNeighborhood` performs a mapping operation that applies a function (the operator in the worklet) on all points of a structured mesh.
The basic operation is similar to a field map except that in addition to having access to the point being operated on, you can get the field values of nearby points within a neighborhood of a given size.
Point neighborhood worklets can only applied to structured cell sets.
.. index::
double: worklet; reduce by key
* **Reduce by Key**
A worklet deriving :class:vtkm::worklet::WorkletReduceByKey` operates on an array of keys and one or more associated arrays of values.
When a reduce by key worklet is invoked, all identical keys are collected and the worklet is called once for each unique key.
Each worklet invocation is given a |Veclike| containing all values associated with the unique key.
Reduce by key worklets are very useful for combining like items such as shared topology elements or coincident points.
The remainder of this chapter provides details on how to create worklets of each type.
.. todo:: Add link to new worklet types chapter when available (see below).
------------------------------
Field Map
------------------------------
.. index::
double: worklet; field map
single: map field
A worklet deriving :class:`vtkm::worklet::WorkletMapField` performs a basic mapping operation that applies a function (the operator in the worklet) on all the field values at a single point or cell and creates a new field value at that same location.
Although the intention is to operate on some variable over the mesh, a :class:`vtkm::worklet::WorkletMapField` can actually be applied to any array.
.. doxygenclass:: vtkm::worklet::WorkletMapField
A field map worklet supports the following tags in the parameters of its ``ControlSignature``.
.. doxygengroup:: WorkletMapFieldControlSigTags
:content-only:
Furthermore, a field map worklet supports the following tags in the parameters of its ``ExecutionSignature``.
.. doxygengroup:: WorkletMapFieldExecutionSigTags
:content-only:
Field maps most commonly perform basic calculator arithmetic, as demonstrated in the following example.
.. load-example:: UseWorkletMapField
:file: GuideExampleUseWorkletMapField.cxx
:caption: Implementation and use of a field map worklet.
Although simple, the :class:`vtkm::worklet::WorkletMapField` worklet type can be used (and abused) as a general parallel-for/scheduling mechanism.
In particular, the :class:`WorkIndex` execution signature tag can be used to get a unique index, the ``WholeArray*`` tags can be used to get random access to arrays, and the :class:`ExecObject` control signature tag can be used to pass execution objects directly to the worklet.
Whole arrays and execution objects are talked about in more detail in Chapters \ref{chap:Globals} and \ref{chap:ExecutionObjects}, respectively, in more detail, but here is a simple example that uses the random access of :class`WholeArrayOut` to make a worklet that copies an array in reverse order.
.. todo:: Fix references to globals and execution object chapters above.
.. load-example:: RandomArrayAccess
:file: GuideExampleUseWorkletMapField.cxx
:caption: Leveraging field maps and field maps for general processing.
------------------------------
Topology Map
------------------------------
A topology map performs a mapping that it applies a function (the operator in the worklet) on all the elements of a :class:`vtkm::cont::DataSet` of a particular type (i.e. point, edge, face, or cell).
While operating on the element, the worklet has access to data from all incident elements of another type.
There are several versions of topology maps that differ in what type of element being mapped from and what type of element being mapped to.
The subsequent sections describe these different variations of the topology maps.
Visit Cells with Points
==============================
.. index::
double: worklet; visit cells
A worklet deriving :class:`vtkm::worklet::WorkletVisitCellsWithPoints` performs a mapping operation that applies a function (the operator in the worklet) on all the cells of a :class:`vtkm::cont::DataSet`.
While operating on the cell, the worklet has access to fields associated both with the cell and with all incident points.
Additionally, the worklet can get information about the structure of the cell and can perform operations like interpolation on it.
.. doxygenclass:: vtkm::worklet::WorkletVisitCellsWithPoints
A visit cells with points worklet supports the following tags in the parameters of its ``ControlSignature``.
.. doxygengroup:: WorkletVisitCellsWithPointsControlSigTags
:content-only:
A visit cells with points worklet supports the following tags in the parameters of its ``ExecutionSignature``.
.. doxygengroup:: WorkletVisitCellsWithPointsExecutionSigTags
:content-only:
Point to cell field maps are a powerful construct that allow you to interpolate point fields throughout the space of the data set.
See Chapter \ref{chap:WorkingWithCells} for a description on how to work with the cell information provided to the worklet.
The following example provides a simple demonstration that finds the geometric center of each cell by interpolating the point coordinates to the cell centers.
.. todo:: Fix reference to chapter on working with cells above.
.. load-example:: UseWorkletVisitCellsWithPoints
:file: GuideExampleUseWorkletVisitCellsWithPoints.cxx
:caption: Implementation and use of a visit cells with points worklet.
Visit Points with Cells
==============================
.. index::
double: worklet; visit points
A worklet deriving :class:`vtkm::worklet::WorkletVisitPointsWithCells` performs a mapping operation that applies a function (the operator in the worklet) on all the points of a :class:`vtkm::cont::DataSet`.
While operating on the point, the worklet has access to fields associated both with the point and with all incident cells.
.. doxygenclass:: vtkm::worklet::WorkletVisitPointsWithCells
A visit points with cells worklet supports the following tags in the parameters of its ``ControlSignature``.
.. doxygengroup:: WorkletVisitPointsWithCellsControlSigTags
:content-only:
A visit points with cells worklet supports the following tags in the parameters of its ``ExecutionSignature``.
.. doxygengroup:: WorkletVisitPointsWithCellsExecutionSigTags
:content-only:
Cell to point field maps are typically used for converting fields associated with cells to points so that they can be interpolated.
The following example does a simple averaging, but you can also implement other strategies such as a volume weighted average.
.. load-example:: UseWorkletVisitPointsWithCells
:file: GuideExampleUseWorkletVisitPointsWithCells.cxx
:caption: Implementation and use of a visit points with cells worklet.
..
\subsection{General Topology Maps}
\label{sec:WorkletMapTopology}
\index{worklet types!topology map|(}
\index{topology map worklet|(}
\index{map topology|(}
A worklet deriving :class:`vtkm::worklet::WorkletMapTopology` performs a mapping operation that applies a function (the operator in the worklet) on all the elements of a specified type from a :class:`vtkm::cont::DataSet`.
While operating on each element, the worklet has access to fields associated both with that element and with all incident elements of a different specified type.
The :class:`vtkm::worklet::WorkletMapTopology` class is a template with two template parameters.
The first template parameter specifies the ``visit'' topology element, and the second parameter specifies the ``incident'' topology element.
The worklet is scheduled such that each instance is associated with a particular ``visit'' topology element and has access to ``incident'' topology elements.
\index{topology element tag|(}
\index{tag!topology element|(}
These visit and incident topology elements are specified with topology element tags, which are defined in the \vtkmheader{vtkm}{TopologyElementTag.h} header file.
The available topology element tags are \vtkm{TopologyElementTagCell}, \vtkm{TopologyElementTagPoint}, \vtkm{TopologyElementTagEdge}, and \vtkm{TopologyElementTagFace}, which represent the cell, point, edge, and face elements, respectively.
\index{topology element tag|)}
\index{tag!topology element|)}
:class:`vtkm::worklet::WorkletMapTopology` is a generic form of a topology map, and it can perform identically to the aforementioned forms of topology map with the correct template parameters.
For example,
\begin{quote}
:class:`vtkm::worklet::WorkletMapTopology`\tparams{%
\vtkm{TopologyElementTagCell}, %
\vtkm{TopologyElementTagPoint}}
\end{quote}
is equivalent to the :class:`vtkm::worklet::WorkletVisitCellsWithPoints` class except the signature tags have different names.
The names used in the specific topology map superclasses (such as :class:`vtkm::worklet::WorkletVisitCellsWithPoints`) tend to be easier to read and are thus preferable.
However, the generic :class:`vtkm::worklet::WorkletMapTopology` is available for topology combinations without a specific superclass or to support more general mappings in a worklet.
The general topology map worklet supports the following tags in the parameters of its ``ControlSignature``, which are equivalent to tags in the other topology maps but with different (more general) names.
\begin{description}
\item[\sigtag{CellSetIn}]
This tag represents the cell set that defines the collection of elements the map will operate on.
A \sigtag{CellSetIn} argument expects a \textidentifier{CellSet} subclass or an \textidentifier{UnknownCellSet} in the associated parameter of the \textidentifier{Invoker}.
Each invocation of the worklet gets a cell shape tag.
(Cell shapes and the operations you can do with cells are discussed in Chapter \ref{chap:WorkingWithCells}.)
There must be exactly one \sigtag{CellSetIn} argument, and the worklet's \inputdomain must be set to this argument.
\item[\sigtag{FieldInVisit}]
This tag represents an input field that is associated with the ``visit'' element.
A \sigtag{FieldInVisit} argument expects an \textidentifier{ArrayHandle} or an \textidentifier{UnknownArrayHandle} in the associated parameter of the \textidentifier{Invoker}.
The size of the array must be exactly the number of cells.
Each invocation of the worklet gets a single value out of this array.
\item[\sigtag{FieldInIncident}]
This tag represents an input field that is associated with the ``incident'' elements.
A \sigtag{FieldInIncident} argument expects an \textidentifier{ArrayHandle} or an \textidentifier{UnknownArrayHandle} in the associated parameter of the \textidentifier{Invoker}.
The size of the array must be exactly the number of ``incident'' elements.
Each invocation of the worklet gets a |Veclike| object containing the field values for all the ``incident'' elements incident with the ``visit'' element being visited.
If the field is a vector field, then the provided object is a \textidentifier{Vec} of \textidentifier{Vec}s.
\item[\sigtag{FieldOut}]
This tag represents an output field, which is necessarily associated with ``visit'' elements.
A \sigtag{FieldOut} argument expects an \textidentifier{ArrayHandle} or an \textidentifier{UnknownArrayHandle} in the associated parameter of the \textidentifier{Invoker}.
The array is resized before scheduling begins, and each invocation of the worklet sets a single value in the array.
\item[\sigtag{FieldInOut}]
This tag represents field that is both an input and an output, which is necessarily associated with ``visit'' elements.
A \sigtag{FieldInOut} argument expects an \textidentifier{ArrayHandle} or an \textidentifier{UnknownArrayHandle} in the associated parameter of the \textidentifier{Invoker}.
Each invocation of the worklet gets a single value out of this array, which is replaced by the resulting value after the worklet completes.
\commoncontrolsignaturetags
\end{description}
A general topology map worklet supports the following tags in the parameters of its ``ExecutionSignature``.
\begin{description}
\numericexecutionsignaturetags
\item[\sigtag{CellShape}]
This tag produces a shape tag corresponding to the shape of the visited element.
(Cell shapes and the operations you can do with cells are discussed in Chapter \ref{chap:WorkingWithCells}.)
This is the same value that gets provided if you reference the \textsignature{CellSetIn} parameter.
If the ``visit'' element is cells, the \sigtag{CellShape} clearly will match the shape of each cell.
Other elements will have shapes to match their structures.
Points have vertex shapes, edges have line shapes, and faces have some type of polygonal shape.
\item[\sigtag{IncidentElementCount}]
This tag produces a \vtkm{IdComponent} equal to the number of elements incident on the element being visited.
The Vecs provided from a \textsignature{FieldInIncident} parameter will be the same size as \sigtag{IncidentElementCount}.
\item[\sigtag{IncidentElementIndices}]
This tag produces a |Veclike| object of \vtkm{Id}s giving the indices for all incident elements.
The order of the entries is consistent with the values of all other \textsignature{FieldInIncident} arguments for the same worklet invocation.
\commonexecutionsignaturetags
\end{description}
\index{map topology|)}
\index{topology map worklet|)}
\index{worklet types!topology map|)}
------------------------------
Neighborhood Mapping
------------------------------
.. index::
double: worklet; neighborhood
|VTKm| provides a pair of worklets that allow easy access to data within a neighborhood of nearby elements.
This simplifies operations like smoothing a field by blending each value with that of its neighbors.
This can only be done on data sets with `vtkm::cont::CellSetStructured` cell sets where extended adjacencies are easy to find.
There are two flavors of the worklet: a point neighborhood worklet and a cell neighborhood worklet.
Point Neighborhood
==============================
.. index::
double: worklet; point neighborhood
A worklet deriving :class:`vtkm::worklet::WorkletPointNeighborhood` performs a mapping operation that applies a function (the operator in the worklet) on all the points of a :class:`vtkm::cont::DataSet`.
While operating on the point, the worklet has access to field values on nearby points within a neighborhood.
.. doxygenclass:: vtkm::worklet::WorkletPointNeighborhood
A point neighborhood worklet supports the following tags in the parameters of its ``ControlSignature``.
.. doxygengroup:: WorkletPointNeighborhoodControlSigTags
:content-only:
A point neighborhood worklet supports the following tags in the parameters of its ``ExecutionSignature``.
.. doxygengroup:: WorkletPointNeighborhoodExecutionSigTags
:content-only:
Cell Neighborhood
==============================
.. index::
double: worklet; cell neighborhood
A worklet deriving :class:`vtkm::worklet::WorkletCellNeighborhood` performs a mapping operation that applies a function (the operator in the worklet) on all the cells of a :class:`vtkm::cont::DataSet`.
While operating on the cell, the worklet has access to field values on nearby cells within a neighborhood.
.. doxygenclass:: vtkm::worklet::WorkletCellNeighborhood
A cell neighborhood worklet supports the following tags in the parameters of its ``ControlSignature``.
.. doxygengroup:: WorkletCellNeighborhoodControlSigTags
:content-only:
A cell neighborhood worklet supports the following tags in the parameters of its ``ExecutionSignature``.
.. doxygengroup:: WorkletCellNeighborhoodExecutionSigTags
:content-only:
Neighborhood Information
==============================
As stated earlier in this section, what makes a :class:`vtkm::worklet::WorkletPointNeighborhood` worklet special is its ability to get field information in a neighborhood surrounding a point rather than just the point itself.
This is done using the special ``FieldInNeighborhood`` in the ``ControlSignature``.
When you use this tag, rather than getting the single field value for the point, you get a :class:`vtkm::exec::FieldNeighborhood` object.
The :class:`vtkm::exec::FieldNeighborhood` class contains a :func:`vtkm::exec::FieldNeighborhood::Get` method that retrieves a field value relative to the local neighborhood.
:func:`vtkm::exec::FieldNeighborhood::Get` takes the :math:`i`, :math:`j`, :math:`k` index of the point with respect to the local point.
So, calling ``Get(0,0,0)`` retrieves at the point being visited.
Likewise, ``Get(-1,0,0)`` gets the value to the "left" of the point visited and ``Get(1,0,0)`` gets the value to the "right."
.. doxygenstruct:: vtkm::exec::FieldNeighborhood
:members:
.. load-example:: GetNeighborhoodFieldValue
:file: GuideExampleUseWorkletPointNeighborhood.cxx
:caption: Retrieve neighborhood field value.
When performing operations on a neighborhood within the mesh, it is often important to know whether the expected neighborhood is contained completely within the mesh or whether the neighborhood extends beyond the borders of the mesh.
This can be queried using a :class:`vtkm::exec::BoundaryState` object, which is provided when a ``Boundary`` tag is listed in the ``ExecutionSignature``.
Generally, :class:`vtkm::exec::BoundaryState` allows you to specify the size of the neighborhood at runtime.
The neighborhood size is specified by a radius.
The radius specifies the number of items in each direction the neighborhood extends.
So, for example, a point neighborhood with radius 1 would contain a :math:`3\times3\times3` neighborhood centered around the point.
Likewise, a point neighborhood with radius 2 would contain a :math:`5\times5\times5` neighborhood centered around the point.
:class:`vtkm::exec::BoundaryState` provides several methods to determine if the neighborhood is contained in the mesh.
.. doxygenstruct:: vtkm::exec::BoundaryState
:members:
The :func:`vtkm::exec::BoundaryState::MinNeighborIndices` and :func:`vtkm::exec::BoundaryState::MaxNeighborIndices` are particularly useful for iterating over the valid portion of the neighborhood.
.. load-example:: GetNeighborhoodBoundary
:file: GuideExampleUseWorkletPointNeighborhood.cxx
:caption: Iterating over the valid portion of a neighborhood.
Convolving Small Kernels
==============================
A common use case for point neighborhood worklets is to convolve a small kernel with a structured mesh.
A very simple example of this is averaging out the values the values within some distance to the central point.
This has the effect of smoothing out the field (although smoothing filters with better properties exist).
The following example shows a worklet that applies this simple "box" averaging.
.. load-example:: UseWorkletPointNeighborhood
:file: GuideExampleUseWorkletPointNeighborhood.cxx
:caption: Implementation and use of a point neighborhood worklet.
------------------------------
Reduce by Key
------------------------------
.. index::
double: worklet; reduce by key
A worklet deriving :class:`vtkm::worklet::WorkletReduceByKey` operates on an array of keys and one or more associated arrays of values.
When a reduce by key worklet is invoked, all identical keys are collected and the worklet is called once for each unique key.
Each worklet invocation is given a |Veclike| containing all values associated with the unique key.
Reduce by key worklets are very useful for combining like items such as shared topology elements or coincident points.
.. figure:: images/ReduceByKeys.png
:width: 4in
:name: fig:ReduceByKey
The collection of values for a reduce by key worklet.
:numref:`fig:ReduceByKey` shows a pictorial representation of how |VTKm| collects data for a reduce by key worklet.
All calls to a reduce by key worklet has exactly one array of keys.
The key array in this example has 4 unique keys: 0, 1, 2, 4.
These 4 unique keys will result in 4 calls to the worklet function.
This example also has 2 arrays of values associated with the keys.
(A reduce by keys worklet can have any number of values arrays.)
When the worklet is invoked, all these common keys will be collected with their associated values.
The parenthesis operator of the worklet will be called once per each unique key.
The worklet call will be given a |Veclike| containing all values that have the key.
``WorkletReduceByKey`` Reference
===================================
.. doxygenclass:: vtkm::worklet::WorkletReduceByKey
A reduce by key worklet supports the following tags in the parameters of its ``ControlSignature``.
.. doxygengroup:: WorkletReduceByKeyControlSigTags
:content-only:
A reduce by key worklet supports the following tags in the parameters of its ``ExecutionSignature``.
.. doxygengroup:: WorkletReduceByKeyExecutionSigTags
:content-only:
Key Objects
==============================
As specified in its documentation, the ``InputDomain`` of a ``WorkletReducedByKey`` has to be a ``KeysIn`` argument.
Unlike simple mapping worklets, the control environment object passed as the ``KeysIn`` cannot be a simple :class:`vtkm::cont::ArrayHandle`.
Rather, this argument has to be given a :class:`vtkm::worklet::Keys` object.
This object manages an array of keys by reorganizing (i.e. sorting) the keys and finding duplicated keys that should be merged.
A :class:`vtkm::worklet::Keys` object can be constructed by simply providing a :class:`vtkm::cont::ArrayHandle` to use as the keys.
.. doxygenclass:: vtkm::worklet::Keys
:members:
Reduce by Key Examples
==============================
As stated earlier, the reduce by key worklet is useful for collecting like values.
To demonstrate the reduce by key worklet, we will create a simple mechanism to generate a :index:`histogram` in parallel.
(|VTKm| comes with its own histogram implementation, but we create our own version here for a simple example.)
The way we can use the reduce by key worklet to compute a histogram is to first identify which bin of the histogram each value is in, and then use the bin identifiers as the keys to collect the information.
To help with this example, we will first create a helper class named ``BinScalars`` that helps us manage the bins.
.. load-example:: BinScalars
:file: GuideExampleUseWorkletReduceByKey.cxx
:caption: A helper class to manage histogram bins.
Using this helper class, we can easily create a simple map worklet that takes values, identifies a bin, and writes that result out to an array that can be used as keys.
.. load-example:: IdentifyBins
:file: GuideExampleUseWorkletReduceByKey.cxx
:caption: A simple map worklet to identify histogram bins, which will be used as keys.
Once you generate an array to be used as keys, you need to make a :class:`vtkm::worklet::Keys` object.
The :class:`vtkm::worklet::Keys` object is what will be passed to the :class:`vtkm::cont::Invoker` for the argument associated with the ``KeysIn`` ``ControlSignature`` tag.
This of course happens in the control environment after calling the :class:`vtkm::cont::Invoker` for our worklet for generating the keys.
.. load-example:: CreateKeysObject
:file: GuideExampleUseWorkletReduceByKey.cxx
:caption: Creating a :class:`vtkm::worklet::Keys` object.
Now that we have our keys, we are finally ready for our reduce by key worklet.
A histogram is simply a count of the number of elements in a bin.
In this case, we do not really need any values for the keys.
We just need the size of the bin, which can be identified with the internally calculated ``ValueCount``.
A complication we run into with this histogram filter is that it is possible for a bin to be empty.
If a bin is empty, there will be no key associated with that bin, and the :class:`vtkm::cont::Invoker` will not call the worklet for that bin/key.
To manage this case, we have to initialize an array with 0's and then fill in the non-zero entities with our reduce by key worklet.
We can find the appropriate entry into the array by using the key, which is actually the bin identifier, which doubles as an index into the histogram.
The following example gives the implementation for the reduce by key worklet that fills in positive values of the histogram.
.. load-example:: CountBins
:file: GuideExampleUseWorkletReduceByKey.cxx
:caption: A reduce by key worklet to write histogram bin counts.
The previous example demonstrates the basic usage of the reduce by key worklet to count common keys.
A more common use case is to collect values associated with those keys, do an operation on those values, and provide a "reduced" value for each unique key.
The following example demonstrates such an operation by providing a worklet that finds the average of all values in a particular bin rather than counting them.
.. load-example:: AverageBins
:file: GuideExampleUseWorkletReduceByKey.cxx
:caption: A worklet that averages all values with a common key.
To complete the code required to average all values that fall into the same bin, the following example shows the full code required to invoke such a worklet.
Note that this example repeats much of the previous examples, but shows it in a more complete context.
.. load-example:: CombineSimilarValues
:file: GuideExampleUseWorkletReduceByKey.cxx
:caption: Using a reduce by key worklet to average values falling into the same bin.

@ -18,14 +18,14 @@ namespace vtkm
namespace exec
{
/// \brief Provides a neighborhood's placement with respect to the mesh's boundary.
/// @brief Provides a neighborhood's placement with respect to the mesh's boundary.
///
/// \c BoundaryState provides functionality for \c WorkletPointNeighborhood algorithms and Fetch's
/// `BoundaryState` provides functionality for `vtkm::worklet::WorkletPointNeighborhood` algorithms
/// to determine if they are operating on a point near the boundary. It allows you to query about
/// overlaps of the neighborhood and the mesh boundary. It also helps convert local neighborhood
/// ids to the corresponding location in the mesh.
///
/// This class is typically constructed using the \c Boundary tag in an \c ExecutionSignature.
/// This class is typically constructed using the `Boundary` tag in an `ExecutionSignature`.
/// There is little reason to construct this in user code.
///
struct BoundaryState
@ -114,8 +114,16 @@ struct BoundaryState
this->IsNeighborInZBoundary(neighbor[2]);
}
/// Returns the minimum neighborhood indices that are within the bounds of the data.
/// @brief Returns the minimum neighborhood indices that are within the bounds of the data.
///
/// Given a radius for the neighborhood, returns a `vtkm::IdComponent3` for the "lower left"
/// (minimum) index. If the visited point is in the middle of the mesh, the returned triplet
/// is the negative radius for all components. But if the visited point is near the mesh
/// boundary, then the minimum index will be clipped.
///
/// For example, if the visited point is at [5,5,5] and `MinNeighborIndices(2)` is called,
/// then [-2,-2,-2] is returned. However, if the visited point is at [0,1,2] and
/// `MinNeighborIndices(2)` is called, then [0,-1,-2] is returned.
VTKM_EXEC vtkm::IdComponent3 MinNeighborIndices(vtkm::IdComponent radius) const
{
VTKM_ASSERT(radius >= 0);
@ -136,8 +144,17 @@ struct BoundaryState
return minIndices;
}
/// Returns the minimum neighborhood indices that are within the bounds of the data.
/// @brief Returns the minimum neighborhood indices that are within the bounds of the data.
///
/// Given a radius for the neighborhood, returns a `vtkm::IdComponent3` for the "upper right"
/// (maximum) index. If the visited point is in the middle of the mesh, the returned triplet
/// is the positive radius for all components. But if the visited point is near the mesh
/// boundary, then the maximum index will be clipped.
///
/// For example, if the visited point is at [5,5,5] in a 10 by 10 by 10 mesh and
/// `MaxNeighborIndices(2)` is called, then [2,2,2] is returned. However, if the visited point
/// is at [7, 8, 9] in the same mesh and `MaxNeighborIndices(2)` is called, then [2, 1, 0]
/// is returned.
VTKM_EXEC vtkm::IdComponent3 MaxNeighborIndices(vtkm::IdComponent radius) const
{
VTKM_ASSERT(radius >= 0);
@ -159,7 +176,6 @@ struct BoundaryState
return maxIndices;
}
///@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the ijk of the equivalent point in the full data set. If the given value is out
/// of range, the value is clamped to the nearest boundary. For example, if given a neighbor
@ -173,15 +189,14 @@ struct BoundaryState
return vtkm::Max(vtkm::Id3(0), vtkm::Min(this->PointDimensions - vtkm::Id3(1), fullIndex));
}
/// @copydoc NeighborIndexToFullIndexClamp
VTKM_EXEC vtkm::Id3 NeighborIndexToFullIndexClamp(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFullIndexClamp(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
///@}
///@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the ijk of the equivalent point in the full data set. If the given value is out
/// of range, the returned value is undefined.
@ -191,15 +206,14 @@ struct BoundaryState
return this->IJK + neighbor;
}
/// @copydoc NeighborIndexToFullIndex
VTKM_EXEC vtkm::Id3 NeighborIndexToFullIndex(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFullIndex(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
///@}
///@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to
/// neighborhood size), clamps it to the dataset bounds, and returns a new
/// neighborhood index. For example, if given a neighbor index that is past
@ -214,15 +228,14 @@ struct BoundaryState
return vtkm::IdComponent3{ clampedFullIndex - this->IJK };
}
/// @copydoc ClampNeighborIndex
VTKM_EXEC vtkm::IdComponent3 ClampNeighborIndex(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->ClampNeighborIndex(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
///@}
///@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the flat index of the equivalent point in the full data set. If the given value
/// is out of range, the value is clamped to the nearest boundary. For example, if given a
@ -236,15 +249,14 @@ struct BoundaryState
return (full[2] * this->PointDimensions[1] + full[1]) * this->PointDimensions[0] + full[0];
}
/// @copydoc NeighborIndexToFlatIndexClamp
VTKM_EXEC vtkm::Id NeighborIndexToFlatIndexClamp(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFlatIndexClamp(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
///@}
///@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the flat index of the equivalent point in the full data set. If the given value
/// is out of range, the result is undefined.
@ -255,14 +267,18 @@ struct BoundaryState
return (full[2] * this->PointDimensions[1] + full[1]) * this->PointDimensions[0] + full[0];
}
/// @copydoc NeighborIndexToFlatIndex
VTKM_EXEC vtkm::Id NeighborIndexToFlatIndex(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFlatIndex(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
///@}
/// The 3D index of the visited element.
vtkm::Id3 IJK;
/// The dimensions of the elements in the mesh.
vtkm::Id3 PointDimensions;
};
}

@ -18,19 +18,17 @@ namespace vtkm
namespace exec
{
/// \brief Retrieves field values from a neighborhood.
/// @brief Retrieves field values from a neighborhood.
///
/// \c FieldNeighborhood manages the retrieval of field values within the neighborhood of a
/// \c WorkletPointNeighborhood worklet. The \c Get methods take ijk indices relative to the
/// neighborhood (with 0, 0, 0 being the element visted) and return the field value at that part of
/// the neighborhood. If the requested neighborhood is outside the boundary, a different value will
/// be returned determined by the boundary behavior. A \c BoundaryState object can be used to
/// determine if the neighborhood extends beyond the boundary of the mesh.
/// `FieldNeighborhood` manages the retrieval of field values within the neighborhood of a
/// `vtkm::worklet::WorkletPointNeighborhood` worklet. The `Get` methods take ijk indices
/// relative to the neighborhood (with 0, 0, 0 being the element visted) and return the
/// field value at that part of the neighborhood. If the requested neighborhood is outside
/// the boundary, the value at the nearest boundary will be returned. A `vtkm::exec::BoundaryState`
/// object can be used to determine if the neighborhood extends beyond the boundary of the mesh.
///
/// This class is typically constructed using the \c FieldInNeighborhood tag in an
/// \c ExecutionSignature. There is little reason to construct this in user code.
///
/// \c FieldNeighborhood is templated on the array portal from which field values are retrieved.
/// This class is typically constructed using the `FieldInNeighborhood` tag in an
/// `ExecutionSignature`. There is little reason to construct this in user code.
///
template <typename FieldPortalType>
struct FieldNeighborhood
@ -44,31 +42,59 @@ struct FieldNeighborhood
using ValueType = typename FieldPortalType::ValueType;
/// @brief Retrieve a field value relative to the visited element.
///
/// The index is given as three dimensional i, j, k indices. These indices are relative
/// to the currently visited element. So, calling `Get(0, 0, 0)` retrieves the field
/// value at the visited element. Calling `Get(-1, 0, 0)` retrieves the value to the
/// "left" and `Get(1, 0, 0)` retrieves the value to the "right."
///
/// If the relative index points outside the bounds of the mesh, `Get` will return the
/// value closest to the boundary (i.e. clamping behvior). For example, if the visited
/// element is at the leftmost index of the mesh, `Get(-1, 0, 0)` will refer to a value
/// outside the bounds of the mesh. In this case, `Get` will return the value at the
/// visited index, which is the closest element at that boundary.
///
/// When referring to values in a mesh of less than 3 dimensions (such as a 2D structured),
/// simply use 0 for the unused dimensions.
VTKM_EXEC
ValueType Get(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const
{
return Portal.Get(this->Boundary->NeighborIndexToFlatIndexClamp(i, j, k));
}
/// @brief Retrieve a field value relative to the visited element without bounds checking.
///
/// `GetUnchecked` behaves the same as `Get` except that no bounds checking is done
/// before retrieving the field value. If the relative index is out of bounds of the
/// mesh, the results are undefined.
///
/// `GetUnchecked` is useful in circumstances where the bounds have already be checked.
/// This prevents wasting time repeating checks.
VTKM_EXEC
ValueType GetUnchecked(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const
{
return Portal.Get(this->Boundary->NeighborIndexToFlatIndex(i, j, k));
}
/// @copydoc Get
VTKM_EXEC
ValueType Get(const vtkm::Id3& ijk) const
{
return Portal.Get(this->Boundary->NeighborIndexToFlatIndexClamp(ijk));
}
/// @copydoc GetUnchecked
VTKM_EXEC
ValueType GetUnchecked(const vtkm::Id3& ijk) const
{
return Portal.Get(this->Boundary->NeighborIndexToFlatIndex(ijk));
}
/// The `vtkm::exec::BoundaryState` used to find field values from local indices.
vtkm::exec::BoundaryState const* const Boundary;
/// The array portal containing field values.
FieldPortalType Portal;
};

@ -52,12 +52,27 @@ public:
KeysBase& operator=(const KeysBase&) = default;
~KeysBase() = default;
/// @brief Returns the input range of a keys object when used as an input domain.
///
/// This will be equal to the number of unique keys.
VTKM_CONT
vtkm::Id GetInputRange() const { return this->Offsets.GetNumberOfValues() - 1; }
/// @brief Returns the array that maps each input value to an array of sorted keys.
///
/// This array is used internally as the indices to a `vtkm::cont::ArrayHandlePermutation`
/// to order input values with the grouped keys so that they can then be grouped. This is
/// an internal array that is seldom of use to code outside the
/// `vtkm::worklet::WorkletReduceByKey` implementation.
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Id> GetSortedValuesMap() const { return this->SortedValuesMap; }
/// @brief Returns an offsets array to group keys.
///
/// Given an array of sorted keys (or more frequently values permuted to the sorting of
/// the keys), this array of indices can be used as offsets for a
/// `vtkm::cont::ArrayHandleGroupVecVariable`. This is an internal array that is seldom of
/// use to code outside the `vtkm::worklet::WorkletReduceByKey` implementation.
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Id> GetOffsets() const { return this->Offsets; }
@ -65,6 +80,9 @@ public:
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::IdComponent> GetCounts() const;
/// @brief Returns the number of input keys and values used to build this structure.
///
/// This is also the size of input arrays to a `vtkm::worklet::WorkletReduceByKey`.
VTKM_CONT
vtkm::Id GetNumberOfValues() const { return this->SortedValuesMap.GetNumberOfValues(); }
@ -110,22 +128,21 @@ enum class KeysSortType
Stable = 1
};
/// \brief Manage keys for a \c WorkletReduceByKey.
/// \brief Manage keys for a `vtkm::worklet::WorkletReduceByKey`.
///
/// The \c WorkletReduceByKey worklet (and its associated \c
/// DispatcherReduceByKey) take an array of keys for its input domain, find all
/// identical keys, and runs a worklet that produces a single value for every
/// key given all matching values. This class is used as the associated input
/// for the keys input domain.
/// The `vtkm::worklet::WorkletReduceByKey` worklet takes an array of keys for
/// its input domain, finds all identical keys, and runs a worklet that produces
/// a single value for every key given all matching values. This class is used
/// as the associated input for the keys input domain.
///
/// \c Keys is templated on the key array handle type and accepts an instance
/// `Keys` is templated on the key array handle type and accepts an instance
/// of this array handle as its constructor. It builds the internal structures
/// needed to use the keys.
///
/// The same \c Keys structure can be used for multiple different \c Invoke of
/// different dispatchers. When used in this way, the processing done in the \c
/// Keys structure is reused for all the \c Invoke. This is more efficient than
/// creating a different \c Keys structure for each \c Invoke.
/// The same `Keys` structure can be used for multiple different invokes of
/// different or the same worklets. When used in this way, the processing done in the
/// `Keys` structure is reused for all the invokes. This is more efficient than
/// creating a different `Keys` structure for each invoke.
///
template <typename T>
class VTKM_ALWAYS_EXPORT Keys : public internal::KeysBase
@ -137,9 +154,9 @@ public:
VTKM_CONT
Keys();
/// \b Construct a Keys class from an array of keys.
/// Construct a `Keys` class from an array of keys.
///
/// Given an array of keys, construct a \c Keys class that will manage
/// Given an array of keys, construct a `Keys` class that will manage
/// using these keys to perform reduce-by-key operations.
///
/// The input keys object is not modified and the result is not stable
@ -171,9 +188,27 @@ public:
KeysSortType sort,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny());
/// Returns an array of unique keys. The order of keys in this array describes
/// the order that result values will be placed in a `vtkm::worklet::WorkletReduceByKey`.
VTKM_CONT
KeyArrayHandleType GetUniqueKeys() const { return this->UniqueKeys; }
#ifdef VTKM_DOXYGEN_ONLY
// Document the superclass' methods as methods in this class.
/// @copydoc vtkm::worklet::internal::KeysBase::GetInputRange
vtkm::Id GetInputRange() const;
/// @copydoc vtkm::worklet::internal::KeysBase::GetSortedValuesMap
vtkm::cont::ArrayHandle<vtkm::Id> GetSortedValuesMap() const;
/// @copydoc vtkm::worklet::internal::KeysBase::GetOffsets
vtkm::cont::ArrayHandle<vtkm::Id> GetOffsets() const;
/// @copydoc vtkm::worklet::internal::KeysBase::GetNumberOfValues
vtkm::Id GetNumberOfValues() const;
#endif
using ExecLookup = vtkm::exec::internal::ReduceByKeyLookup<
typename KeyArrayHandleType::ReadPortalType,
typename vtkm::cont::ArrayHandle<vtkm::Id>::ReadPortalType,

@ -28,12 +28,130 @@ namespace worklet
template <typename WorkletType>
class DispatcherCellNeighborhood;
/// @brief Base class for worklets that map over the cells in a structured grid with neighborhood information.
///
/// The domain of a `WorkletCellNeighborhood` is a `vtkm::cont::CellSetStructured`. It visits
/// all the cells in the mesh and provides access to the cell field values of the visited cell
/// and the field values of the nearby connected neighborhood of a prescribed size.
class WorkletCellNeighborhood : public WorkletNeighborhood
{
public:
template <typename Worklet>
using Dispatcher = vtkm::worklet::DispatcherCellNeighborhood<Worklet>;
/// @defgroup WorkletCellNeighborhoodControlSigTags `ControlSignature` tags
/// Tags that can be used in the `ControlSignature` of a `WorkletPointNeighborhood`.
/// @{
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::worklet::WorkletNeighborhood::CellSetIn
struct CellSetIn : vtkm::worklet::WorkletNeighborhood::CellSetIn
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldIn
struct FieldIn : vtkm::worklet::WorkletNeighborhood::FieldIn
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldInNeighborhood
struct FieldInNeighborhood : vtkm::worklet::WorkletNeighborhood::FieldInNeighborhood
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldOut
struct FieldOut : vtkm::worklet::WorkletNeighborhood::FieldOut
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldInOut
struct FieldInOut : vtkm::worklet::WorkletNeighborhood::FieldInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayIn
struct WholeArrayIn : vtkm::worklet::internal::WorkletBase::WholeArrayIn
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayOut
struct WholeArrayOut : vtkm::worklet::internal::WorkletBase::WholeArrayOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayInOut
struct WholeArrayInOut : vtkm::worklet::internal::WorkletBase::WholeArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
struct AtomicArrayInOut : vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeCellSetIn
template <typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn
: vtkm::worklet::internal::WorkletBase::WholeCellSetIn<VisitTopology, IncidentTopology>
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ExecObject
struct ExecObject : vtkm::worklet::internal::WorkletBase::ExecObject
{
};
#endif // VTKM_DOXYGEN_ONLY
/// @}
/// @defgroup WorkletCellNeighborhoodExecutionSigTags `ExecutionSignature` tags
/// Tags that can be used in the `ExecutionSignature` of a `WorkletPointNeighborhood`.
/// @{
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::placeholders::Arg
struct _1 : vtkm::worklet::internal::WorkletBase::_1
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::Boundary
struct Boundary : vtkm::worklet::WorkletNeighborhood::Boundary
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WorkIndex
struct WorkIndex : vtkm::worklet::internal::WorkletBase::WorkIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::VisitIndex
struct VisitIndex : vtkm::worklet::internal::WorkletBase::VisitIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::InputIndex
struct InputIndex : vtkm::worklet::internal::WorkletBase::InputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::OutputIndex
struct OutputIndex : vtkm::worklet::internal::WorkletBase::OutputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ThreadIndices
struct ThreadIndices : vtkm::worklet::internal::WorkletBase::ThreadIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::Device
struct Device : vtkm::worklet::internal::WorkletBase::Device
{
};
#endif // VTKM_DOXYGEN_ONLY
/// @}
/// Point neighborhood worklets use the related thread indices class.
///
VTKM_SUPPRESS_EXEC_WARNINGS

@ -31,8 +31,9 @@ namespace vtkm
namespace worklet
{
/// Base class for worklets that do a simple mapping of field arrays. All
/// inputs and outputs are on the same domain. That is, all the arrays are the
/// @brief Base class for worklets that do a simple mapping of field arrays.
///
/// All inputs and outputs are on the same domain. That is, all the arrays are the
/// same size.
///
class WorkletMapField : public vtkm::worklet::internal::WorkletBase
@ -41,11 +42,21 @@ public:
template <typename Worklet>
using Dispatcher = vtkm::worklet::DispatcherMapField<Worklet>;
/// @defgroup WorkletMapFieldControlSigTags `ControlSignature` tags
/// Tags that can be used in the `ControlSignature` of a `WorkletMapField`.
/// @{
/// \brief A control signature tag for input fields.
/// @brief A control signature tag for input fields.
///
/// A `FieldIn` argument expects a `vtkm::cont::ArrayHandle` in the associated
/// parameter of the invoke. Each invocation of the worklet gets a single value
/// out of this array.
///
/// This tag means that the field is read only.
///
/// The worklet's `InputDomain` can be set to a `FieldIn` argument. In this case,
/// the input domain will be the size of the array.
///
struct FieldIn : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayIn;
@ -53,10 +64,19 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
};
/// \brief A control signature tag for output fields.
/// @brief A control signature tag for output fields.
///
/// A `FieldOut` argument expects a `vtkm::cont::ArrayHandle` in the associated
/// parameter of the invoke. The array is resized before scheduling begins, and
/// each invocation of the worklet sets a single value in the array.
///
/// This tag means that the field is write only.
///
/// Although uncommon, it is possible to set the worklet's `InputDomain` to a
/// `FieldOut` argument. If this is the case, then the `vtkm::cont::ArrayHandle`
/// passed as the argument must be allocated before being passed to the invoke,
/// and the input domain will be the size of the array.
///
struct FieldOut : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayOut;
@ -64,17 +84,109 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectOut;
};
/// \brief A control signature tag for input-output (in-place) fields.
/// @brief A control signature tag for input-output (in-place) fields.
///
/// A `FieldInOut` argument expects a `vtkm::cont::ArrayHandle` in the
/// associated parameter of the invoke. Each invocation of the worklet gets a
/// single value out of this array, which is replaced by the resulting value
/// after the worklet completes.
///
/// This tag means that the field is read and write.
///
/// The worklet's `InputDomain` can be set to a `FieldInOut` argument. In
/// this case, the input domain will be the size of the array.
///
struct FieldInOut : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayInOut;
using TransportTag = vtkm::cont::arg::TransportTagArrayInOut;
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectInOut;
};
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayIn
struct WholeArrayIn : vtkm::worklet::internal::WorkletBase::WholeArrayIn
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayOut
struct WholeArrayOut : vtkm::worklet::internal::WorkletBase::WholeArrayOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayInOut
struct WholeArrayInOut : vtkm::worklet::internal::WorkletBase::WholeArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
struct AtomicArrayInOut : vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeCellSetIn
template <typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn
: vtkm::worklet::internal::WorkletBase::WholeCellSetIn<VisitTopology, IncidentTopology>
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ExecObject
struct ExecObject : vtkm::worklet::internal::WorkletBase::ExecObject
{
};
#endif
/// @}
/// @defgroup WorkletMapFieldExecutionSigTags `ExecutionSignature` tags
/// Tags that can be used in the `ExecutionSignature` of a `WorkletMapField`.
/// @{
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::placeholders::Arg
struct _1 : vtkm::worklet::internal::WorkletBase::_1
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WorkIndex
struct WorkIndex : vtkm::worklet::internal::WorkletBase::WorkIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::VisitIndex
struct VisitIndex : vtkm::worklet::internal::WorkletBase::VisitIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::InputIndex
struct InputIndex : vtkm::worklet::internal::WorkletBase::InputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::OutputIndex
struct OutputIndex : vtkm::worklet::internal::WorkletBase::OutputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ThreadIndices
struct ThreadIndices : vtkm::worklet::internal::WorkletBase::ThreadIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::Device
struct Device : vtkm::worklet::internal::WorkletBase::Device
{
};
#endif
/// @}
};
}
} // namespace vtkm::worklet

@ -96,9 +96,6 @@ public:
/// \brief A control signature tag for output fields.
///
/// This tag takes a template argument that is a type list tag that limits
/// the possible value types in the array.
///
struct FieldOut : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayOut;
@ -116,8 +113,12 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectInOut;
};
/// \brief A control signature tag for input connectivity.
/// @brief A control signature tag for input connectivity.
///
/// The associated parameter of the invoke should be a subclass of `vtkm::cont::CellSet`.
///
/// There should be exactly one `CellSetIn` argument in the `ControlSignature`,
/// and the `InputDomain` must point to it.
struct CellSetIn : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagCellSet;
@ -256,6 +257,7 @@ class WorkletVisitCellsWithPoints
: public WorkletMapTopology<vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint>
{
public:
#ifndef VTKM_DOXYGEN_ONLY
using FieldInPoint = FieldInIncident;
using FieldInCell = FieldInVisit;
@ -267,6 +269,188 @@ public:
using PointCount = IncidentElementCount;
using PointIndices = IncidentElementIndices;
#else // VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @defgroup WorkletVisitCellsWithPointsControlSigTags `ControlSignature` tags
/// Tags that can be used in the `ControlSignature` of a `WorkletVisitCellsWithPoints`.
/// @{
/// @copydoc vtkm::worklet::WorkletMapTopology::CellSetIn
struct CellSetIn
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::CellSetIn
{
};
/// @brief A control signature tag for input fields on the cells of the topology.
///
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle` that has
/// the same number of values as the cells of the provided `CellSet`.
/// The worklet gets a single value that is the field at that cell.
struct FieldInCell : FieldInVisit
{
};
/// @brief A control signature tag for input fields on the points of the topology.
///
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle` that has
/// the same number of values as the points of the provided `CellSet`.
/// The worklet gets a Vec-like object containing the field values on all incident points.
struct FieldInPoint : FieldInIncident
{
};
/// @brief A control signature tag for input fields from the visited topology.
///
/// For `WorkletVisitCellsWithPoints`, this is the same as `FieldInCell`.
struct FieldInVisit
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldInVisit
{
};
/// @brief A control signature tag for input fields from the incident topology.
///
/// For `WorkletVisitCellsWithPoints`, this is the same as `FieldInPoint`.
struct FieldInIncident
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldInIncident
{
};
/// @brief A control signature tag for output fields.
///
/// A `WorkletVisitCellsWithPoints` always has the output on the cells of the topology.
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle`, and it will
/// be resized to the number of cells in the provided `CellSet`.
struct FieldOutCell : FieldOut
{
};
/// @copydoc FieldOutCell
struct FieldOut
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldOut
{
};
/// @brief A control signature tag for input-output (in-place) fields.
///
/// A `WorkletVisitCellsWithPoints` always has the output on the cells of the topology.
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle`, and it must
/// have the same number of values as the number of cells of the topology.
struct FieldInOutCell : FieldInOut
{
};
/// @copydoc FieldInOutCell
struct FieldInOut
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayIn
struct WholeArrayIn : vtkm::worklet::internal::WorkletBase::WholeArrayIn
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayOut
struct WholeArrayOut : vtkm::worklet::internal::WorkletBase::WholeArrayOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayInOut
struct WholeArrayInOut : vtkm::worklet::internal::WorkletBase::WholeArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
struct AtomicArrayInOut : vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeCellSetIn
template <typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn
: vtkm::worklet::internal::WorkletBase::WholeCellSetIn<VisitTopology, IncidentTopology>
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ExecObject
struct ExecObject : vtkm::worklet::internal::WorkletBase::ExecObject
{
};
/// @}
/// @defgroup WorkletVisitCellsWithPointsExecutionSigTags `ExecutionSignature` tags
/// Tags that can be used in the `ExecutionSignature` of a `WorkletVisitCellsWithPoints`.
/// @{
/// @copydoc vtkm::placeholders::Arg
struct _1 : vtkm::worklet::internal::WorkletBase::_1
{
};
/// @brief An execution signature tag to get the shape of the visited cell.
///
/// This tag causes a `vtkm::UInt8` to be passed to the worklet containing containing an
/// id for the shape of the cell being visited.
struct CellShape
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::CellShape
{
};
/// @brief An execution signature tag to get the number of incident points.
///
/// Each cell in a `vtkm::cont::CellSet` can be incident on a number of points. This
/// tag causes a `vtkm::IdComponent` to be passed to the worklet containing the number
/// of incident points.
struct PointCount
: vtkm::worklet::WorkletMapTopology<VisitTopologyType,
IncidentTopologyType>::IncidentElementCount
{
};
/// @brief An execution signature tag to get the indices of the incident points.
///
/// The indices will be provided in a Vec-like object containing `vtkm::Id` indices for the
/// cells in the data set.
struct PointIndices
: vtkm::worklet::WorkletMapTopology<VisitTopologyType,
IncidentTopologyType>::IncidentElementIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WorkIndex
struct WorkIndex : vtkm::worklet::internal::WorkletBase::WorkIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::VisitIndex
struct VisitIndex : vtkm::worklet::internal::WorkletBase::VisitIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::InputIndex
struct InputIndex : vtkm::worklet::internal::WorkletBase::InputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::OutputIndex
struct OutputIndex : vtkm::worklet::internal::WorkletBase::OutputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ThreadIndices
struct ThreadIndices : vtkm::worklet::internal::WorkletBase::ThreadIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::Device
struct Device : vtkm::worklet::internal::WorkletBase::Device
{
};
/// @}
#endif // VTKM_DOXYGEN_ONLY
};
/// Base class for worklets that map from Cells to Points.
@ -275,6 +459,7 @@ class WorkletVisitPointsWithCells
: public WorkletMapTopology<vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell>
{
public:
#ifndef VTKM_DOXYGEN_ONLY
using FieldInCell = FieldInIncident;
using FieldInPoint = FieldInVisit;
@ -286,6 +471,179 @@ public:
using CellCount = IncidentElementCount;
using CellIndices = IncidentElementIndices;
#else // VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @defgroup WorkletVisitPointsWithCellsControlSigTags `ControlSignature` tags
/// Tags that can be used in the `ControlSignature` of a `WorkletVisitPointsWithCells`.
/// @{
/// @copydoc vtkm::worklet::WorkletMapTopology::CellSetIn
struct CellSetIn
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::CellSetIn
{
};
/// @brief A control signature tag for input fields on the points of the topology.
///
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle` that has
/// the same number of values as the points of the provided `CellSet`.
/// The worklet gets a single value that is the field at that point.
struct FieldInPoint : FieldInVisit
{
};
/// @brief A control signature tag for input fields on the cells of the topology.
///
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle` that has
/// the same number of values as the cells of the provided `CellSet`.
/// The worklet gets a Vec-like object containing the field values on all incident cells.
struct FieldInCell : FieldInIncident
{
};
/// @brief A control signature tag for input fields from the visited topology.
///
/// For `WorkletVisitPointsWithCells`, this is the same as `FieldInPoint`.
struct FieldInVisit
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldInVisit
{
};
/// @brief A control signature tag for input fields from the incident topology.
///
/// For `WorkletVisitPointsWithCells`, this is the same as `FieldInCell`.
struct FieldInIncident
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldInIncident
{
};
/// @brief A control signature tag for output fields.
///
/// A `WorkletVisitPointsWithCells` always has the output on the points of the topology.
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle`, and it will
/// be resized to the number of points in the provided `CellSet`.
struct FieldOutPoint : FieldOut
{
};
/// @copydoc FieldOutPoint
struct FieldOut
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldOut
{
};
/// @brief A control signature tag for input-output (in-place) fields.
///
/// A `WorkletVisitPointsWithCells` always has the output on the points of the topology.
/// The associated parameter of the invoke should be a `vtkm::cont::ArrayHandle`, and it must
/// have the same number of values as the number of points of the topology.
struct FieldInOutPoint : FieldInOut
{
};
/// @copydoc FieldInOutPoint
struct FieldInOut
: vtkm::worklet::WorkletMapTopology<VisitTopologyType, IncidentTopologyType>::FieldInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayIn
struct WholeArrayIn : vtkm::worklet::internal::WorkletBase::WholeArrayIn
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayOut
struct WholeArrayOut : vtkm::worklet::internal::WorkletBase::WholeArrayOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayInOut
struct WholeArrayInOut : vtkm::worklet::internal::WorkletBase::WholeArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
struct AtomicArrayInOut : vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeCellSetIn
template <typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn
: vtkm::worklet::internal::WorkletBase::WholeCellSetIn<VisitTopology, IncidentTopology>
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ExecObject
struct ExecObject : vtkm::worklet::internal::WorkletBase::ExecObject
{
};
/// @}
/// @defgroup WorkletVisitPointsWithCellsExecutionSigTags `ExecutionSignature` tags
/// Tags that can be used in the `ExecutionSignature` of a `WorkletVisitPointsWithCells`.
/// @{
/// @copydoc vtkm::placeholders::Arg
struct _1 : vtkm::worklet::internal::WorkletBase::_1
{
};
/// @brief An execution signature tag to get the number of incident cells.
///
/// Each point in a `vtkm::cont::CellSet` can be incident on a number of cells. This
/// tag causes a `vtkm::IdComponent` to be passed to the worklet containing the number
/// of incident cells.
struct CellCount
: vtkm::worklet::WorkletMapTopology<VisitTopologyType,
IncidentTopologyType>::IncidentElementCount
{
};
/// @brief An execution signature tag to get the indices of the incident cells.
///
/// The indices will be provided in a Vec-like object containing `vtkm::Id` indices for the
/// points in the data set.
struct CellIndices
: vtkm::worklet::WorkletMapTopology<VisitTopologyType,
IncidentTopologyType>::IncidentElementIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WorkIndex
struct WorkIndex : vtkm::worklet::internal::WorkletBase::WorkIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::VisitIndex
struct VisitIndex : vtkm::worklet::internal::WorkletBase::VisitIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::InputIndex
struct InputIndex : vtkm::worklet::internal::WorkletBase::InputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::OutputIndex
struct OutputIndex : vtkm::worklet::internal::WorkletBase::OutputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ThreadIndices
struct ThreadIndices : vtkm::worklet::internal::WorkletBase::ThreadIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::Device
struct Device : vtkm::worklet::internal::WorkletBase::Device
{
};
/// @}
#endif // VTKM_DOXYGEN_ONLY
};
}

@ -42,11 +42,11 @@ namespace worklet
class WorkletNeighborhood : public vtkm::worklet::internal::WorkletBase
{
public:
/// \brief The \c ExecutionSignature tag to query if the current iteration is inside the boundary.
/// @brief The `ExecutionSignature` tag to query if the current iteration is inside the boundary.
///
/// A \c WorkletPointNeighborhood operates by iterating over all points using a defined
/// neighborhood. This \c ExecutionSignature tag provides a \c BoundaryState object that allows
/// you to query whether the neighborhood of the current iteration is completely inside the
/// This `ExecutionSignature` tag provides a `vtkm::exec::BoundaryState` object that provides
/// information about where the local neighborhood is in relationship to the full mesh. It allows
/// you to query whether the neighborhood of the current worklet call is completely inside the
/// bounds of the mesh or if it extends beyond the mesh. This is important as when you are on a
/// boundary the neighboordhood will contain empty values for a certain subset of values, and in
/// this case the values returned will depend on the boundary behavior.
@ -72,10 +72,13 @@ public:
VTKM_CONT BoundaryType GetBoundaryCondition() const { return BoundaryType(); }
VTKM_DEPRECATED_SUPPRESS_END
/// \brief A control signature tag for input point fields.
/// @brief A control signature tag for input fields.
///
/// This tag takes a template argument that is a type list tag that limits
/// the possible value types in the array.
/// A `FieldIn` argument expects a `vtkm::cont::ArrayHandle` in the associated
/// parameter of the invoke. Each invocation of the worklet gets a single value
/// out of this array.
///
/// This tag means that the field is read only.
///
struct FieldIn : vtkm::cont::arg::ControlSignatureTagBase
{
@ -84,10 +87,13 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
};
/// \brief A control signature tag for output point fields.
/// @brief A control signature tag for output fields.
///
/// This tag takes a template argument that is a type list tag that limits
/// the possible value types in the array.
/// A `FieldOut` argument expects a `vtkm::cont::ArrayHandle` in the associated
/// parameter of the invoke. The array is resized before scheduling begins, and
/// each invocation of the worklet sets a single value in the array.
///
/// This tag means that the field is write only.
///
struct FieldOut : vtkm::cont::arg::ControlSignatureTagBase
{
@ -96,10 +102,14 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectOut;
};
/// \brief A control signature tag for input-output (in-place) point fields.
/// @brief A control signature tag for input-output (in-place) fields.
///
/// This tag takes a template argument that is a type list tag that limits
/// the possible value types in the array.
/// A `FieldInOut` argument expects a `vtkm::cont::ArrayHandle` in the
/// associated parameter of the invoke. Each invocation of the worklet gets a
/// single value out of this array, which is replaced by the resulting value
/// after the worklet completes.
///
/// This tag means that the field is read and write.
///
struct FieldInOut : vtkm::cont::arg::ControlSignatureTagBase
{
@ -108,8 +118,14 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectInOut;
};
/// \brief A control signature tag for input connectivity.
/// @brief A control signature tag for input connectivity.
///
/// This tag represents the cell set that defines the collection of points the
/// map will operate on. A `CellSetIn` argument expects a `vtkm::cont::CellSetStructured`
/// object in the associated parameter of the invoke.
///
/// There must be exactly one `CellSetIn` argument, and the worklet's `InputDomain` must
/// be set to this argument.
struct CellSetIn : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagCellSetStructured;
@ -118,16 +134,24 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagCellSetIn;
};
/// \brief A control signature tag for neighborhood input values.
/// @brief A control signature tag for neighborhood input values.
///
/// A \c WorkletPointNeighborhood operates allowing access to a adjacent point
/// A neighborhood worklet operates by allowing access to a adjacent element
/// values in a NxNxN patch called a neighborhood.
/// No matter the size of the neighborhood it is symmetric across its center
/// in each axis, and the current point value will be at the center
/// For example a 3x3x3 neighborhood would
/// For example a 3x3x3 neighborhood would have local indices ranging from -1 to 1
/// in each dimension.
///
/// This tag specifies an \c ArrayHandle object that holds the values. It is
/// an input array with entries for each point.
/// This tag specifies a `vtkm::cont::ArrayHandle` object that holds the values. It is
/// an input array with entries for each element.
///
/// What differentiates `FieldInNeighborhood` from `FieldIn` is that `FieldInNeighborhood`
/// allows the worklet function to access the field value at the element it is visiting and
/// the field values in the neighborhood around it. Thus, instead of getting a single value
/// out of the array, each invocation of the worklet gets a `vtkm::exec::FieldNeighborhood`
/// object. These objects allow retrieval of field values using indices relative to the
/// visited element.
///
struct FieldInNeighborhood : vtkm::cont::arg::ControlSignatureTagBase
{

@ -24,12 +24,130 @@ namespace vtkm
namespace worklet
{
/// @brief Base class for worklets that map over the points in a structured grid with neighborhood information.
///
/// The domain of a `WorkletPointNeighborhood` is a `vtkm::cont::CellSetStructured`. It visits
/// all the points in the mesh and provides access to the point field values of the visited point
/// and the field values of the nearby connected neighborhood of a prescribed size.
class WorkletPointNeighborhood : public WorkletNeighborhood
{
public:
template <typename Worklet>
using Dispatcher = vtkm::worklet::DispatcherPointNeighborhood<Worklet>;
/// @defgroup WorkletPointNeighborhoodControlSigTags `ControlSignature` tags
/// Tags that can be used in the `ControlSignature` of a `WorkletPointNeighborhood`.
/// @{
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::worklet::WorkletNeighborhood::CellSetIn
struct CellSetIn : vtkm::worklet::WorkletNeighborhood::CellSetIn
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldIn
struct FieldIn : vtkm::worklet::WorkletNeighborhood::FieldIn
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldInNeighborhood
struct FieldInNeighborhood : vtkm::worklet::WorkletNeighborhood::FieldInNeighborhood
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldOut
struct FieldOut : vtkm::worklet::WorkletNeighborhood::FieldOut
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::FieldInOut
struct FieldInOut : vtkm::worklet::WorkletNeighborhood::FieldInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayIn
struct WholeArrayIn : vtkm::worklet::internal::WorkletBase::WholeArrayIn
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayOut
struct WholeArrayOut : vtkm::worklet::internal::WorkletBase::WholeArrayOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayInOut
struct WholeArrayInOut : vtkm::worklet::internal::WorkletBase::WholeArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
struct AtomicArrayInOut : vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeCellSetIn
template <typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn
: vtkm::worklet::internal::WorkletBase::WholeCellSetIn<VisitTopology, IncidentTopology>
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ExecObject
struct ExecObject : vtkm::worklet::internal::WorkletBase::ExecObject
{
};
#endif // VTKM_DOXYGEN_ONLY
/// @}
/// @defgroup WorkletPointNeighborhoodExecutionSigTags `ExecutionSignature` tags
/// Tags that can be used in the `ExecutionSignature` of a `WorkletPointNeighborhood`.
/// @{
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::placeholders::Arg
struct _1 : vtkm::worklet::internal::WorkletBase::_1
{
};
/// @copydoc vtkm::worklet::WorkletNeighborhood::Boundary
struct Boundary : vtkm::worklet::WorkletNeighborhood::Boundary
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WorkIndex
struct WorkIndex : vtkm::worklet::internal::WorkletBase::WorkIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::VisitIndex
struct VisitIndex : vtkm::worklet::internal::WorkletBase::VisitIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::InputIndex
struct InputIndex : vtkm::worklet::internal::WorkletBase::InputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::OutputIndex
struct OutputIndex : vtkm::worklet::internal::WorkletBase::OutputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ThreadIndices
struct ThreadIndices : vtkm::worklet::internal::WorkletBase::ThreadIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::Device
struct Device : vtkm::worklet::internal::WorkletBase::Device
{
};
#endif // VTKM_DOXYGEN_ONLY
/// @}
/// Point neighborhood worklets use the related thread indices class.
///
VTKM_SUPPRESS_EXEC_WARNINGS

@ -39,19 +39,36 @@ namespace vtkm
namespace worklet
{
/// @brief Base class for worklets that group elements by keys.
///
/// The `InputDomain` of this worklet is a `vtkm::worklet::Keys` object,
/// which holds an array of keys. All entries of this array with the same
/// key are collected together, and the operator of the worklet is called
/// once for each unique key.
///
/// Input arrays are (typically) the same size as the number of keys. When
/// these objects are passed to the operator of the worklet, all values of
/// the associated key are placed in a Vec-like object. Output arrays get
/// sized by the number of unique keys, and each call to the operator produces
/// one result for each output.
class WorkletReduceByKey : public vtkm::worklet::internal::WorkletBase
{
public:
template <typename Worklet>
using Dispatcher = vtkm::worklet::DispatcherReduceByKey<Worklet>;
/// \brief A control signature tag for input keys.
/// @defgroup WorkletReduceByKeyControlSigTags `ControlSignature` tags
/// Tags that can be used in the `ControlSignature` of a `WorkletMapField`.
/// @{
/// @brief A control signature tag for input keys.
///
/// A \c WorkletReduceByKey operates by collecting all identical keys and
/// A `WorkletReduceByKey` operates by collecting all identical keys and
/// then executing the worklet on each unique key. This tag specifies a
/// \c Keys object that defines and manages these keys.
/// `vtkm::worklet::Keys` object that defines and manages these keys.
///
/// A \c WorkletReduceByKey should have exactly one \c KeysIn tag in its \c
/// ControlSignature, and the \c InputDomain should point to it.
/// A `WorkletReduceByKey` should have exactly one `KeysIn` tag in its
/// `ControlSignature`, and the `InputDomain` should point to it.
///
struct KeysIn : vtkm::cont::arg::ControlSignatureTagBase
{
@ -60,12 +77,13 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagKeysIn;
};
/// \brief A control signature tag for input values.
/// @brief A control signature tag for input values associated with the keys.
///
/// A \c WorkletReduceByKey operates by collecting all values associated with
/// A `WorkletReduceByKey` operates by collecting all values associated with
/// identical keys and then giving the worklet a Vec-like object containing
/// all values with a matching key. This tag specifies an \c ArrayHandle
/// object that holds the values.
/// all values with a matching key. This tag specifies an `vtkm::cont::ArrayHandle`
/// object that holds the values. The number of values in this array must be equal
/// to the size of the array used with the `KeysIn` argument.
///
struct ValuesIn : vtkm::cont::arg::ControlSignatureTagBase
{
@ -74,12 +92,13 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
};
/// \brief A control signature tag for input/output values.
/// @brief A control signature tag for input/output values associated with the keys.
///
/// A \c WorkletReduceByKey operates by collecting all values associated with
/// A `WorkletReduceByKey` operates by collecting all values associated with
/// identical keys and then giving the worklet a Vec-like object containing
/// all values with a matching key. This tag specifies an \c ArrayHandle
/// object that holds the values.
/// all values with a matching key. This tag specifies an `vtkm::cont::ArrayHandle`
/// object that holds the values. The number of values in this array must be equal
/// to the size of the array used with the `KeysIn` argument.
///
/// This tag might not work with scatter operations.
///
@ -90,12 +109,14 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
};
/// \brief A control signature tag for output values.
/// \brief A control signature tag for output values associated with the keys.
///
/// A \c WorkletReduceByKey operates by collecting all values associated with
/// identical keys and then giving the worklet a Vec-like object containing
/// all values with a matching key. This tag specifies an \c ArrayHandle
/// object that holds the values.
/// This tag behaves the same as `ValuesInOut` except that the array is resized
/// appropriately and no input values are passed to the worklet. As with
/// `ValuesInOut`, values the worklet writes to its |Veclike| object get placed
/// in the location of the original arrays.
///
/// Use of `ValuesOut` is rare.
///
/// This tag might not work with scatter operations.
///
@ -106,46 +127,14 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
};
/// \brief A control signature tag for reduced output values.
/// @brief A control signature tag for reduced output values.
///
/// A \c WorkletReduceByKey operates by collecting all identical keys and
/// A `WorkletReduceByKey` operates by collecting all identical keys and
/// calling one instance of the worklet for those identical keys. The worklet
/// then produces a "reduced" value per key.
///
/// This tag specifies an \c ArrayHandle object that holds the values. It is
/// an input array with entries for each reduced value. This could be useful
/// to access values from a previous run of WorkletReduceByKey.
///
struct ReducedValuesIn : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayIn;
using TransportTag = vtkm::cont::arg::TransportTagArrayIn;
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
};
/// \brief A control signature tag for reduced output values.
///
/// A \c WorkletReduceByKey operates by collecting all identical keys and
/// calling one instance of the worklet for those identical keys. The worklet
/// then produces a "reduced" value per key.
///
/// This tag specifies an \c ArrayHandle object that holds the values. It is
/// an input/output array with entries for each reduced value. This could be
/// useful to access values from a previous run of WorkletReduceByKey.
///
struct ReducedValuesInOut : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayInOut;
using TransportTag = vtkm::cont::arg::TransportTagArrayInOut;
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectInOut;
};
/// \brief A control signature tag for reduced output values.
///
/// A \c WorkletReduceByKey operates by collecting all identical keys and
/// calling one instance of the worklet for those identical keys. The worklet
/// then produces a "reduced" value per key. This tag specifies an \c
/// ArrayHandle object that holds the values.
/// then produces a "reduced" value per key. This tag specifies a
/// `vtkm::cont::ArrayHandle` object that holds the values. The array is resized
/// to be the number of unique keys, and each call of the operator sets
/// a single value in the array
///
struct ReducedValuesOut : vtkm::cont::arg::ControlSignatureTagBase
{
@ -154,17 +143,149 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectOut;
};
/// \brief The \c ExecutionSignature tag to get the number of values.
/// @brief A control signature tag for reduced input values.
///
/// A \c WorkletReduceByKey operates by collecting all values associated with
/// A`WorkletReduceByKey` operates by collecting all identical keys and
/// calling one instance of the worklet for those identical keys. The worklet
/// then produces a "reduced" value per key.
///
/// This tag specifies a `vtkm::cont::ArrayHandle` object that holds the values.
/// It is an input array with entries for each reduced value. The number of values
/// in the array must equal the number of _unique_ keys.
///
/// A `ReducedValuesIn` argument is usually used to pass reduced values from one
/// invoke of a reduce by key worklet to another invoke of a reduced by key worklet
/// such as in an algorithm that requires iterative steps.
///
struct ReducedValuesIn : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayIn;
using TransportTag = vtkm::cont::arg::TransportTagArrayIn;
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
};
/// @brief A control signature tag for reduced output values.
///
/// A `WorkletReduceByKey` operates by collecting all identical keys and
/// calling one instance of the worklet for those identical keys. The worklet
/// then produces a "reduced" value per key.
///
/// This tag specifies a `vtkm::cont::ArrayHandle` object that holds the values.
/// It is an input/output array with entries for each reduced value. The number
/// of values in the array must equal the number of _unique_ keys.
///
/// This tag behaves the same as `ReducedValuesIn` except that the worklet may
/// write values back into the array. Make sure that the associated parameter to
/// the worklet operator is a reference so that the changed value gets written
/// back to the array.
///
struct ReducedValuesInOut : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArrayInOut;
using TransportTag = vtkm::cont::arg::TransportTagArrayInOut;
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectInOut;
};
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayIn
struct WholeArrayIn : vtkm::worklet::internal::WorkletBase::WholeArrayIn
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayOut
struct WholeArrayOut : vtkm::worklet::internal::WorkletBase::WholeArrayOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeArrayInOut
struct WholeArrayInOut : vtkm::worklet::internal::WorkletBase::WholeArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
struct AtomicArrayInOut : vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::WholeCellSetIn
template <typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn
: vtkm::worklet::internal::WorkletBase::WholeCellSetIn<VisitTopology, IncidentTopology>
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ExecObject
struct ExecObject : vtkm::worklet::internal::WorkletBase::ExecObject
{
};
#endif
/// @}
/// @defgroup WorkletReduceByKeyExecutionSigTags `ExecutionSignature` tags
/// Tags that can be used in the `ExecutionSignature` of a `WorkletMapField`.
/// @{
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::placeholders::Arg
struct _1 : vtkm::worklet::internal::WorkletBase::_1
{
};
#endif
/// @brief The `ExecutionSignature` tag to get the number of values.
///
/// A `WorkletReduceByKey` operates by collecting all values associated with
/// identical keys and then giving the worklet a Vec-like object containing all
/// values with a matching key. This \c ExecutionSignature tag provides the
/// number of values associated with the key and given in the Vec-like objects.
/// values with a matching key. This tag produces a `vtkm::IdComponent` that is
/// equal to the number of times the key associated with this call to the worklet
/// occurs in the input. This is the same size as the Vec-like objects provided
/// by `ValuesIn` arguments.
///
struct ValueCount : vtkm::exec::arg::ValueCount
{
};
#ifdef VTKM_DOXYGEN_ONLY
// These redeclarations of superclass features are for documentation purposes only.
/// @copydoc vtkm::worklet::internal::WorkletBase::WorkIndex
struct WorkIndex : vtkm::worklet::internal::WorkletBase::WorkIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::VisitIndex
struct VisitIndex : vtkm::worklet::internal::WorkletBase::VisitIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::InputIndex
struct InputIndex : vtkm::worklet::internal::WorkletBase::InputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::OutputIndex
struct OutputIndex : vtkm::worklet::internal::WorkletBase::OutputIndex
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::ThreadIndices
struct ThreadIndices : vtkm::worklet::internal::WorkletBase::ThreadIndices
{
};
/// @copydoc vtkm::worklet::internal::WorkletBase::Device
struct Device : vtkm::worklet::internal::WorkletBase::Device
{
};
#endif
/// @}
/// Reduce by key worklets use the related thread indices class.
///
VTKM_SUPPRESS_EXEC_WARNINGS

@ -22,6 +22,11 @@ namespace placeholders
{
//============================================================================
/// @brief Argument placeholders for an `ExecutionSignature`.
///
/// All worklet superclasses declare numeric tags in the form of
/// `_1`, `_2`, `_3` etc. that are used in the `ExecutionSignature`
/// to refer to the corresponding parameter in the `ControlSignature`.
template <int ControlSignatureIndex>
struct Arg : vtkm::exec::arg::BasicArg<ControlSignatureIndex>
{

@ -79,28 +79,45 @@ public:
using _19 = vtkm::placeholders::Arg<19>;
using _20 = vtkm::placeholders::Arg<20>;
/// \c ExecutionSignature tag for getting the work index.
/// @brief `ExecutionSignature` tag for getting the work index.
///
/// This tag produces a `vtkm::Id` that uniquely identifies the invocation
/// instance of the worklet.
///
using WorkIndex = vtkm::exec::arg::WorkIndex;
/// \c ExecutionSignature tag for getting the input index.
/// @brief `ExecutionSignature` tag for getting the input index.
///
/// This tag produces a `vtkm::Id` that identifies the index of the input
/// element, which can differ from the `WorkIndex` in a worklet with a scatter.
using InputIndex = vtkm::exec::arg::InputIndex;
/// \c ExecutionSignature tag for getting the output index.
/// @brief `ExecutionSignature` tag for getting the output index.
///
/// This tag produces a `vtkm::Id` that identifies the index of the output element.
/// (This is generally the same as `WorkIndex`.)
using OutputIndex = vtkm::exec::arg::OutputIndex;
/// \c ExecutionSignature tag for getting the thread indices.
/// @brief `ExecutionSignature` tag for getting the thread indices.
///
/// This tag produces an internal object that manages indices and other metadata
/// of the current thread. Thread indices objects vary by worklet type, but most
/// users can get the information they need through other signature tags.
using ThreadIndices = vtkm::exec::arg::ThreadIndices;
/// \c ExecutionSignature tag for getting the visit index.
/// @brief `ExecutionSignature` tag for getting the visit index.
///
/// This tag produces a `vtkm::IdComponent` that uniquely identifies when multiple
/// worklet invocations operate on the same input item, which can happen when
/// defining a worklet with scatter.
///
using VisitIndex = vtkm::exec::arg::VisitIndex;
/// \c ExecutionSignature tag for getting the device adapter tag.
/// @brief `ExecutionSignature` tag for getting the device adapter tag.
///
/// This tag passes a device adapter tag object. This allows the worklet function
/// to template on or overload itself based on the type of device that it is
/// being executed on.
struct Device : vtkm::exec::arg::ExecutionSignatureTagBase
{
// INDEX 0 (which is an invalid parameter index) is reserved to mean the device adapter tag.
@ -108,7 +125,15 @@ public:
using AspectTag = vtkm::exec::arg::AspectTagDefault;
};
/// \c ControlSignature tag for execution object inputs.
/// @brief `ControlSignature` tag for execution object inputs.
///
/// This tag represents an execution object that is passed directly from the
/// control environment to the worklet. A `ExecObject` argument expects a subclass
/// of `vtkm::exec::ExecutionObjectBase`. Subclasses of `vtkm::exec::ExecutionObjectBase`
/// behave like a factory for objects that work on particular devices. They
/// do this by implementing a `PrepareForExecution()` method that takes a device
/// adapter tag and returns an object that works on that device. That device-specific
/// object is passed directly to the worklet.
struct ExecObject : vtkm::cont::arg::ControlSignatureTagBase
{
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagExecObject;
@ -130,15 +155,11 @@ public:
/// everything in the output domain.
using MaskType = vtkm::worklet::MaskNone;
/// \c ControlSignature tag for whole input arrays.
/// @brief `ControlSignature` tag for whole input arrays.
///
/// The \c WholeArrayIn control signature tag specifies an \c ArrayHandle
/// passed to the \c Invoke operation of the dispatcher. This is converted
/// to an \c ArrayPortal object and passed to the appropriate worklet
/// operator argument with one of the default args.
///
/// The template operator specifies all the potential value types of the
/// array. The default value type is all types.
/// The `WholeArrayIn` control signature tag specifies a `vtkm::cont::ArrayHandle`
/// passed to the invoke of the worklet. An array portal capable of reading
/// from any place in the array is given to the worklet.
///
struct WholeArrayIn : vtkm::cont::arg::ControlSignatureTagBase
{
@ -147,16 +168,12 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagExecObject;
};
/// \c ControlSignature tag for whole output arrays.
/// @brief `ControlSignature` tag for whole output arrays.
///
/// The \c WholeArrayOut control signature tag specifies an \c ArrayHandle
/// passed to the \c Invoke operation of the dispatcher. This is converted to
/// an \c ArrayPortal object and passed to the appropriate worklet operator
/// argument with one of the default args. Care should be taken to not write
/// a value in one instance that will be overridden by another entry.
///
/// The template operator specifies all the potential value types of the
/// array. The default value type is all types.
/// The `WholeArrayOut` control signature tag specifies an `vtkm::cont::ArrayHandle`
/// passed to the invoke of the worklet. An array portal capable of writing
/// to any place in the array is given to the worklet. Developers should take
/// care when using writable whole arrays as introducing race conditions is possible.
///
struct WholeArrayOut : vtkm::cont::arg::ControlSignatureTagBase
{
@ -165,17 +182,13 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagExecObject;
};
/// \c ControlSignature tag for whole input/output arrays.
/// @brief `ControlSignature` tag for whole input/output arrays.
///
/// The \c WholeArrayOut control signature tag specifies an \c ArrayHandle
/// passed to the \c Invoke operation of the dispatcher. This is converted to
/// an \c ArrayPortal object and passed to the appropriate worklet operator
/// argument with one of the default args. Care should be taken to not write
/// a value in one instance that will be read by or overridden by another
/// entry.
///
/// The template operator specifies all the potential value types of the
/// array. The default value type is all types.
/// The `WholeArrayOut` control signature tag specifies a `vtkm::cont::ArrayHandle`
/// passed to the invoke of the worklet. An array portal capable of reading
/// from or writing to any place in the array is given to the worklet. Developers
/// should take care when using writable whole arrays as introducing race
/// conditions is possible.
///
struct WholeArrayInOut : vtkm::cont::arg::ControlSignatureTagBase
{
@ -184,17 +197,13 @@ public:
using FetchTag = vtkm::exec::arg::FetchTagExecObject;
};
/// \c ControlSignature tag for whole input/output arrays.
/// @brief `ControlSignature` tag for whole input/output arrays.
///
/// The \c AtomicArrayInOut control signature tag specifies an \c ArrayHandle
/// passed to the \c Invoke operation of the dispatcher. This is converted to
/// a \c vtkm::exec::AtomicArray object and passed to the appropriate worklet
/// operator argument with one of the default args. The provided atomic
/// operations can be used to resolve concurrency hazards, but have the
/// potential to slow the program quite a bit.
///
/// The template operator specifies all the potential value types of the
/// array. The default value type is all types.
/// The `AtomicArrayInOut` control signature tag specifies `vtkm::cont::ArrayHandle`
/// passed to the invoke of the worklet. A `vtkm::exec::AtomicArray` object capable
/// of performing atomic operations to the entries in the array is given to the
/// worklet. Atomic arrays can help avoid race conditions but can slow down the
/// running of a parallel algorithm.
///
struct AtomicArrayInOut : vtkm::cont::arg::ControlSignatureTagBase
{
@ -233,18 +242,17 @@ public:
};
/// @}
/// \c ControlSignature tag for whole input topology.
///
/// The \c WholeCellSetIn control signature tag specifies an \c CellSet
/// passed to the \c Invoke operation of the dispatcher. This is converted to
/// a \c vtkm::exec::Connectivity* object and passed to the appropriate worklet
/// operator argument with one of the default args. This can be used to
/// global lookup for arbitrary topology information
using Point = vtkm::TopologyElementTagPoint;
using Cell = vtkm::TopologyElementTagCell;
using Edge = vtkm::TopologyElementTagEdge;
using Face = vtkm::TopologyElementTagFace;
/// @brief `ControlSignature` tag for whole input topology.
///
/// The `WholeCellSetIn` control signature tag specifies a `vtkm::cont::CellSet`
/// passed to the invoke of the worklet. A connectivity object capable of finding
/// elements of one type that are incident on elements of a different type. This
/// can be used to global lookup for arbitrary topology information
template <typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn : vtkm::cont::arg::ControlSignatureTagBase
{