4.3. Worklet Types

Chapter 3.3 (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. VTK‑m 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 VTK‑m and the superclass that supports it.

  • Field Map A worklet deriving 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 vtkm::worklet::WorkletMapField may actually be applied to any array. Thus, a field map can be used as a basic map operation.

  • Topology Map A worklet deriving 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. 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, vtkm::worklet::WorkletVisitPointsWithCells calls the worklet operation for each point and makes every incident cell available.

  • Point Neighborhood A worklet deriving from 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.

  • 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 Vec-like 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.

4.3.1. Field Map

A worklet deriving 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 vtkm::worklet::WorkletMapField can actually be applied to any array.

class WorkletMapField : public vtkm::worklet::internal::WorkletBase

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.

Subclassed by vtkm::rendering::Triangulator::IndicesSort, vtkm::rendering::Triangulator::InterleaveArrays12, vtkm::rendering::Triangulator::InterleaveArrays2, vtkm::rendering::Triangulator::UniqueTriangles, vtkm::worklet::FieldStatistics< FieldType >::CalculatePowers, vtkm::worklet::FieldStatistics< FieldType >::SubtractConst, vtkm::worklet::KernelSplatterFilterUniformGrid< Kernel, DeviceAdapter >::ComputeLocalNeighborId, vtkm::worklet::KernelSplatterFilterUniformGrid< Kernel, DeviceAdapter >::GetFootprint, vtkm::worklet::KernelSplatterFilterUniformGrid< Kernel, DeviceAdapter >::GetSplatValue, vtkm::worklet::KernelSplatterFilterUniformGrid< Kernel, DeviceAdapter >::UpdateVoxelSplats, vtkm::worklet::KernelSplatterFilterUniformGrid< Kernel, DeviceAdapter >::zero_voxel, vtkm::worklet::Normal, vtkm::worklet::Normalize, vtkm::worklet::TriangleWinding::WorkletWindToCellNormals, vtkm::worklet::streamline::MakeStreamLines< FieldType >

A field map worklet supports the following tags in the parameters of its ControlSignature.

struct FieldIn : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletMapField.h>

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 FieldOut : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletMapField.h>

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 FieldInOut : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletMapField.h>

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 WholeArrayIn : public vtkm::worklet::internal::WorkletBase::WholeArrayIn
#include <WorkletMapField.h>

ControlSignature tag for whole input arrays.

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 WholeArrayOut : public vtkm::worklet::internal::WorkletBase::WholeArrayOut
#include <WorkletMapField.h>

ControlSignature tag for whole output arrays.

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 WholeArrayInOut : public vtkm::worklet::internal::WorkletBase::WholeArrayInOut
#include <WorkletMapField.h>

ControlSignature tag for whole input/output arrays.

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 AtomicArrayInOut : public vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
#include <WorkletMapField.h>

ControlSignature tag for whole input/output arrays.

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.

template<typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn : public vtkm::worklet::internal::WorkletBase::WholeCellSetIn<Cell, Point>
#include <WorkletMapField.h>

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

struct ExecObject : public vtkm::worklet::internal::WorkletBase::ExecObject
#include <WorkletMapField.h>

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.

Furthermore, a field map worklet supports the following tags in the parameters of its ExecutionSignature.

struct _1 : public vtkm::placeholders::Arg<1>
#include <WorkletMapField.h>

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.

struct WorkIndex : public vtkm::exec::arg::WorkIndex
#include <WorkletMapField.h>

The ExecutionSignature tag to use to get the work index.

This tag produces a vtkm::Id that uniquely identifies the invocation instance of the worklet. When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index for this work.

struct VisitIndex : public vtkm::exec::arg::VisitIndex
#include <WorkletMapField.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, there is a scatter operation defined that optionally allows each input to go to multiple output entries. When one input is assigned to multiple outputs, there needs to be a mechanism to uniquely identify which output is which. The visit index is a value between 0 and the number of outputs a particular input goes to. This tag in the ExecutionSignature passes the visit index for this work.

struct InputIndex : public vtkm::exec::arg::InputIndex
#include <WorkletMapField.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the input element that the work thread is currently working on. When a worklet has a scatter associated with it, the input and output indices can be different.

struct OutputIndex : public vtkm::exec::arg::OutputIndex
#include <WorkletMapField.h>

The ExecutionSignature tag to use to get the output index.

This tag produces a vtkm::Id that identifies the index of the output element. (This is generally the same as WorkIndex.)

When a worklet is dispatched, it broken into pieces defined by the output domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the output element that the work thread is currently working on. When a worklet has a scatter associated with it, the output and output indices can be different.

struct ThreadIndices : public vtkm::exec::arg::ThreadIndices
#include <WorkletMapField.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. During this process multiple indices associated with the input and output can be generated. This tag in the ExecutionSignature passes the index for this work.

struct Device : public vtkm::worklet::internal::WorkletBase::Device
#include <WorkletMapField.h>

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.

Field maps most commonly perform basic calculator arithmetic, as demonstrated in the following example.

Example 4.42 Implementation and use of a field map worklet.
 1class ComputeMagnitude : public vtkm::worklet::WorkletMapField
 2{
 3public:
 4  using ControlSignature = void(FieldIn inputVectors, FieldOut outputMagnitudes);
 5  using ExecutionSignature = _2(_1);
 6
 7  using InputDomain = _1;
 8
 9  template<typename T, vtkm::IdComponent Size>
10  VTKM_EXEC T operator()(const vtkm::Vec<T, Size>& inVector) const
11  {
12    return vtkm::Magnitude(inVector);
13  }
14};

Although simple, the vtkm::worklet::WorkletMapField worklet type can be used (and abused) as a general parallel-for/scheduling mechanism. In particular, the 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 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.

Example 4.43 Leveraging field maps and field maps for general processing.
 1namespace vtkm
 2{
 3namespace worklet
 4{
 5
 6struct ReverseArrayCopyWorklet : vtkm::worklet::WorkletMapField
 7{
 8  using ControlSignature = void(FieldIn inputArray, WholeArrayOut outputArray);
 9  using ExecutionSignature = void(_1, _2, WorkIndex);
10  using InputDomain = _1;
11
12  template<typename InputType, typename OutputArrayPortalType>
13  VTKM_EXEC void operator()(const InputType& inputValue,
14                            const OutputArrayPortalType& outputArrayPortal,
15                            vtkm::Id workIndex) const
16  {
17    vtkm::Id outIndex = outputArrayPortal.GetNumberOfValues() - workIndex - 1;
18    if (outIndex >= 0)
19    {
20      outputArrayPortal.Set(outIndex, inputValue);
21    }
22    else
23    {
24      this->RaiseError("Output array not sized correctly.");
25    }
26  }
27};
28
29} // namespace worklet
30} // namespace vtkm

4.3.2. Topology Map

A topology map performs a mapping that it applies a function (the operator in the worklet) on all the elements of a 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.

4.3.2.1. Visit Cells with Points

A worklet deriving vtkm::worklet::WorkletVisitCellsWithPoints performs a mapping operation that applies a function (the operator in the worklet) on all the cells of a 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.

class WorkletVisitCellsWithPoints : public vtkm::worklet::WorkletMapTopology<vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint>

Base class for worklets that map from Points to Cells.

Subclassed by vtkm::cont::internal::RConnTableHelpers::WriteConnectivity, vtkm::cont::internal::RConnTableHelpers::WriteNumIndices, vtkm::rendering::Cylinderizer::CountSegments, vtkm::rendering::Cylinderizer::Cylinderize, vtkm::rendering::Cylinderizer::SegmentedStructured< DIM >, vtkm::rendering::Quadralizer::CountQuads, vtkm::rendering::Quadralizer::Quadralize, vtkm::rendering::Quadralizer::SegmentedStructured< DIM >, vtkm::rendering::Triangulator::CountTriangles, vtkm::rendering::Triangulator::Triangulate, vtkm::rendering::Triangulator::TriangulateStructured< DIM >, vtkm::worklet::CellDeepCopy::CountCellPoints, vtkm::worklet::CellDeepCopy::PassCellStructure, vtkm::worklet::TriangleWinding::WorkletGetCellShapesAndSizes, vtkm::worklet::TriangleWinding::WorkletWindToCellNormalsGeneric

A visit cells with points worklet supports the following tags in the parameters of its ControlSignature.

struct CellSetIn : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::CellSetIn
#include <WorkletMapTopology.h>

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 FieldInCell : public vtkm::worklet::WorkletVisitCellsWithPoints::FieldInVisit
#include <WorkletMapTopology.h>

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 FieldInPoint : public vtkm::worklet::WorkletVisitCellsWithPoints::FieldInIncident
#include <WorkletMapTopology.h>

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 FieldInVisit : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldInVisit
#include <WorkletMapTopology.h>

A control signature tag for input fields from the visited topology.

For WorkletVisitCellsWithPoints, this is the same as FieldInCell.

Subclassed by vtkm::worklet::WorkletVisitCellsWithPoints::FieldInCell

struct FieldInIncident : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldInIncident
#include <WorkletMapTopology.h>

A control signature tag for input fields from the incident topology.

For WorkletVisitCellsWithPoints, this is the same as FieldInPoint.

Subclassed by vtkm::worklet::WorkletVisitCellsWithPoints::FieldInPoint

struct FieldOutCell : public vtkm::worklet::WorkletVisitCellsWithPoints::FieldOut
#include <WorkletMapTopology.h>

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 FieldOut : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldOut
#include <WorkletMapTopology.h>

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.

Subclassed by vtkm::worklet::WorkletVisitCellsWithPoints::FieldOutCell

struct FieldInOutCell : public vtkm::worklet::WorkletVisitCellsWithPoints::FieldInOut
#include <WorkletMapTopology.h>

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 FieldInOut : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldInOut
#include <WorkletMapTopology.h>

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.

Subclassed by vtkm::worklet::WorkletVisitCellsWithPoints::FieldInOutCell

struct WholeArrayIn : public vtkm::worklet::internal::WorkletBase::WholeArrayIn
#include <WorkletMapTopology.h>

ControlSignature tag for whole input arrays.

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 WholeArrayOut : public vtkm::worklet::internal::WorkletBase::WholeArrayOut
#include <WorkletMapTopology.h>

ControlSignature tag for whole output arrays.

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 WholeArrayInOut : public vtkm::worklet::internal::WorkletBase::WholeArrayInOut
#include <WorkletMapTopology.h>

ControlSignature tag for whole input/output arrays.

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 AtomicArrayInOut : public vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
#include <WorkletMapTopology.h>

ControlSignature tag for whole input/output arrays.

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.

template<typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn : public vtkm::worklet::internal::WorkletBase::WholeCellSetIn<Cell, Point>
#include <WorkletMapTopology.h>

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

struct ExecObject : public vtkm::worklet::internal::WorkletBase::ExecObject
#include <WorkletMapTopology.h>

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.

A visit cells with points worklet supports the following tags in the parameters of its ExecutionSignature.

struct _1 : public vtkm::placeholders::Arg<1>
#include <WorkletMapTopology.h>

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.

struct CellShape : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::CellShape
#include <WorkletMapTopology.h>

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 PointCount : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::IncidentElementCount
#include <WorkletMapTopology.h>

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 PointIndices : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::IncidentElementIndices
#include <WorkletMapTopology.h>

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 WorkIndex : public vtkm::exec::arg::WorkIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get the work index.

This tag produces a vtkm::Id that uniquely identifies the invocation instance of the worklet. When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index for this work.

struct VisitIndex : public vtkm::exec::arg::VisitIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, there is a scatter operation defined that optionally allows each input to go to multiple output entries. When one input is assigned to multiple outputs, there needs to be a mechanism to uniquely identify which output is which. The visit index is a value between 0 and the number of outputs a particular input goes to. This tag in the ExecutionSignature passes the visit index for this work.

struct InputIndex : public vtkm::exec::arg::InputIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the input element that the work thread is currently working on. When a worklet has a scatter associated with it, the input and output indices can be different.

struct OutputIndex : public vtkm::exec::arg::OutputIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get the output index.

This tag produces a vtkm::Id that identifies the index of the output element. (This is generally the same as WorkIndex.)

When a worklet is dispatched, it broken into pieces defined by the output domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the output element that the work thread is currently working on. When a worklet has a scatter associated with it, the output and output indices can be different.

struct ThreadIndices : public vtkm::exec::arg::ThreadIndices
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. During this process multiple indices associated with the input and output can be generated. This tag in the ExecutionSignature passes the index for this work.

struct Device : public vtkm::worklet::internal::WorkletBase::Device
#include <WorkletMapTopology.h>

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.

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 4.7 (Working with Cells) 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.

Example 4.44 Implementation and use of a visit cells with points worklet.
 1namespace vtkm
 2{
 3namespace worklet
 4{
 5
 6struct CellCenter : public vtkm::worklet::WorkletVisitCellsWithPoints
 7{
 8public:
 9  using ControlSignature = void(CellSetIn cellSet,
10                                FieldInPoint inputPointField,
11                                FieldOut outputCellField);
12  using ExecutionSignature = void(_1, PointCount, _2, _3);
13
14  using InputDomain = _1;
15
16  template<typename CellShape, typename InputPointFieldType, typename OutputType>
17  VTKM_EXEC void operator()(CellShape shape,
18                            vtkm::IdComponent numPoints,
19                            const InputPointFieldType& inputPointField,
20                            OutputType& centerOut) const
21  {
22    vtkm::Vec3f parametricCenter;
23    vtkm::exec::ParametricCoordinatesCenter(numPoints, shape, parametricCenter);
24    vtkm::exec::CellInterpolate(inputPointField, parametricCenter, shape, centerOut);
25  }
26};
27
28} // namespace worklet
29} // namespace vtkm

4.3.2.2. Visit Points with Cells

A worklet deriving vtkm::worklet::WorkletVisitPointsWithCells performs a mapping operation that applies a function (the operator in the worklet) on all the points of a vtkm::cont::DataSet. While operating on the point, the worklet has access to fields associated both with the point and with all incident cells.

class WorkletVisitPointsWithCells : public vtkm::worklet::WorkletMapTopology<vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell>

Base class for worklets that map from Cells to Points.

A visit points with cells worklet supports the following tags in the parameters of its ControlSignature.

struct CellSetIn : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::CellSetIn
#include <WorkletMapTopology.h>

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 FieldInPoint : public vtkm::worklet::WorkletVisitPointsWithCells::FieldInVisit
#include <WorkletMapTopology.h>

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 FieldInCell : public vtkm::worklet::WorkletVisitPointsWithCells::FieldInIncident
#include <WorkletMapTopology.h>

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 FieldInVisit : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldInVisit
#include <WorkletMapTopology.h>

A control signature tag for input fields from the visited topology.

For WorkletVisitPointsWithCells, this is the same as FieldInPoint.

Subclassed by vtkm::worklet::WorkletVisitPointsWithCells::FieldInPoint

struct FieldInIncident : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldInIncident
#include <WorkletMapTopology.h>

A control signature tag for input fields from the incident topology.

For WorkletVisitPointsWithCells, this is the same as FieldInCell.

Subclassed by vtkm::worklet::WorkletVisitPointsWithCells::FieldInCell

struct FieldOutPoint : public vtkm::worklet::WorkletVisitPointsWithCells::FieldOut
#include <WorkletMapTopology.h>

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 FieldOut : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldOut
#include <WorkletMapTopology.h>

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.

Subclassed by vtkm::worklet::WorkletVisitPointsWithCells::FieldOutPoint

struct FieldInOutPoint : public vtkm::worklet::WorkletVisitPointsWithCells::FieldInOut
#include <WorkletMapTopology.h>

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 FieldInOut : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::FieldInOut
#include <WorkletMapTopology.h>

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.

Subclassed by vtkm::worklet::WorkletVisitPointsWithCells::FieldInOutPoint

struct WholeArrayIn : public vtkm::worklet::internal::WorkletBase::WholeArrayIn
#include <WorkletMapTopology.h>

ControlSignature tag for whole input arrays.

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 WholeArrayOut : public vtkm::worklet::internal::WorkletBase::WholeArrayOut
#include <WorkletMapTopology.h>

ControlSignature tag for whole output arrays.

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 WholeArrayInOut : public vtkm::worklet::internal::WorkletBase::WholeArrayInOut
#include <WorkletMapTopology.h>

ControlSignature tag for whole input/output arrays.

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 AtomicArrayInOut : public vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
#include <WorkletMapTopology.h>

ControlSignature tag for whole input/output arrays.

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.

template<typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn : public vtkm::worklet::internal::WorkletBase::WholeCellSetIn<Cell, Point>
#include <WorkletMapTopology.h>

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

struct ExecObject : public vtkm::worklet::internal::WorkletBase::ExecObject
#include <WorkletMapTopology.h>

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.

A visit points with cells worklet supports the following tags in the parameters of its ExecutionSignature.

struct _1 : public vtkm::placeholders::Arg<1>
#include <WorkletMapTopology.h>

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.

struct CellCount : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::IncidentElementCount
#include <WorkletMapTopology.h>

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 CellIndices : public vtkm::worklet::WorkletMapTopology<VisitTopology, IncidentTopology>::IncidentElementIndices
#include <WorkletMapTopology.h>

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 WorkIndex : public vtkm::exec::arg::WorkIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get the work index.

This tag produces a vtkm::Id that uniquely identifies the invocation instance of the worklet. When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index for this work.

struct VisitIndex : public vtkm::exec::arg::VisitIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, there is a scatter operation defined that optionally allows each input to go to multiple output entries. When one input is assigned to multiple outputs, there needs to be a mechanism to uniquely identify which output is which. The visit index is a value between 0 and the number of outputs a particular input goes to. This tag in the ExecutionSignature passes the visit index for this work.

struct InputIndex : public vtkm::exec::arg::InputIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the input element that the work thread is currently working on. When a worklet has a scatter associated with it, the input and output indices can be different.

struct OutputIndex : public vtkm::exec::arg::OutputIndex
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get the output index.

This tag produces a vtkm::Id that identifies the index of the output element. (This is generally the same as WorkIndex.)

When a worklet is dispatched, it broken into pieces defined by the output domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the output element that the work thread is currently working on. When a worklet has a scatter associated with it, the output and output indices can be different.

struct ThreadIndices : public vtkm::exec::arg::ThreadIndices
#include <WorkletMapTopology.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. During this process multiple indices associated with the input and output can be generated. This tag in the ExecutionSignature passes the index for this work.

struct Device : public vtkm::worklet::internal::WorkletBase::Device
#include <WorkletMapTopology.h>

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.

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.

Example 4.45 Implementation and use of a visit points with cells worklet.
 1class AverageCellField : public vtkm::worklet::WorkletVisitPointsWithCells
 2{
 3public:
 4  using ControlSignature = void(CellSetIn cellSet,
 5                                FieldInCell inputCellField,
 6                                FieldOut outputPointField);
 7  using ExecutionSignature = void(CellCount, _2, _3);
 8
 9  using InputDomain = _1;
10
11  template<typename InputCellFieldType, typename OutputFieldType>
12  VTKM_EXEC void operator()(vtkm::IdComponent numCells,
13                            const InputCellFieldType& inputCellField,
14                            OutputFieldType& fieldAverage) const
15  {
16    fieldAverage = OutputFieldType(0);
17
18    for (vtkm::IdComponent cellIndex = 0; cellIndex < numCells; cellIndex++)
19    {
20      fieldAverage = fieldAverage + inputCellField[cellIndex];
21    }
22
23    fieldAverage = fieldAverage / OutputFieldType(numCells);
24  }
25};
26
27//
28// Later in the associated Filter class...
29//
30
31        vtkm::cont::ArrayHandle<T> outFieldData;
32        this->Invoke(AverageCellField{}, inCellSet, inFieldData, outFieldData);

4.3.3. Neighborhood Mapping

VTK‑m 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.

4.3.3.1. Point Neighborhood

A worklet deriving vtkm::worklet::WorkletPointNeighborhood performs a mapping operation that applies a function (the operator in the worklet) on all the points of a vtkm::cont::DataSet. While operating on the point, the worklet has access to field values on nearby points within a neighborhood.

class WorkletPointNeighborhood : public vtkm::worklet::WorkletNeighborhood

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.

Subclassed by vtkm::worklet::AveragePointNeighborhood

A point neighborhood worklet supports the following tags in the parameters of its ControlSignature.

struct CellSetIn : public vtkm::worklet::WorkletNeighborhood::CellSetIn
#include <WorkletPointNeighborhood.h>

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 FieldIn : public vtkm::worklet::WorkletNeighborhood::FieldIn
#include <WorkletPointNeighborhood.h>

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.

struct FieldInNeighborhood : public vtkm::worklet::WorkletNeighborhood::FieldInNeighborhood
#include <WorkletPointNeighborhood.h>

A control signature tag for neighborhood input values.

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 have local indices ranging from -1 to 1 in each dimension.

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 FieldOut : public vtkm::worklet::WorkletNeighborhood::FieldOut
#include <WorkletPointNeighborhood.h>

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.

struct FieldInOut : public vtkm::worklet::WorkletNeighborhood::FieldInOut
#include <WorkletPointNeighborhood.h>

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.

struct WholeArrayIn : public vtkm::worklet::internal::WorkletBase::WholeArrayIn
#include <WorkletPointNeighborhood.h>

ControlSignature tag for whole input arrays.

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 WholeArrayOut : public vtkm::worklet::internal::WorkletBase::WholeArrayOut
#include <WorkletPointNeighborhood.h>

ControlSignature tag for whole output arrays.

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 WholeArrayInOut : public vtkm::worklet::internal::WorkletBase::WholeArrayInOut
#include <WorkletPointNeighborhood.h>

ControlSignature tag for whole input/output arrays.

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 AtomicArrayInOut : public vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
#include <WorkletPointNeighborhood.h>

ControlSignature tag for whole input/output arrays.

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.

template<typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn : public vtkm::worklet::internal::WorkletBase::WholeCellSetIn<Cell, Point>
#include <WorkletPointNeighborhood.h>

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

struct ExecObject : public vtkm::worklet::internal::WorkletBase::ExecObject
#include <WorkletPointNeighborhood.h>

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.

A point neighborhood worklet supports the following tags in the parameters of its ExecutionSignature.

struct _1 : public vtkm::placeholders::Arg<1>
#include <WorkletPointNeighborhood.h>

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.

struct Boundary : public vtkm::worklet::WorkletNeighborhood::Boundary
#include <WorkletPointNeighborhood.h>

The ExecutionSignature tag to query if the current iteration is inside the boundary.

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.

struct WorkIndex : public vtkm::exec::arg::WorkIndex
#include <WorkletPointNeighborhood.h>

The ExecutionSignature tag to use to get the work index.

This tag produces a vtkm::Id that uniquely identifies the invocation instance of the worklet. When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index for this work.

struct VisitIndex : public vtkm::exec::arg::VisitIndex
#include <WorkletPointNeighborhood.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, there is a scatter operation defined that optionally allows each input to go to multiple output entries. When one input is assigned to multiple outputs, there needs to be a mechanism to uniquely identify which output is which. The visit index is a value between 0 and the number of outputs a particular input goes to. This tag in the ExecutionSignature passes the visit index for this work.

struct InputIndex : public vtkm::exec::arg::InputIndex
#include <WorkletPointNeighborhood.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the input element that the work thread is currently working on. When a worklet has a scatter associated with it, the input and output indices can be different.

struct OutputIndex : public vtkm::exec::arg::OutputIndex
#include <WorkletPointNeighborhood.h>

The ExecutionSignature tag to use to get the output index.

This tag produces a vtkm::Id that identifies the index of the output element. (This is generally the same as WorkIndex.)

When a worklet is dispatched, it broken into pieces defined by the output domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the output element that the work thread is currently working on. When a worklet has a scatter associated with it, the output and output indices can be different.

struct ThreadIndices : public vtkm::exec::arg::ThreadIndices
#include <WorkletPointNeighborhood.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. During this process multiple indices associated with the input and output can be generated. This tag in the ExecutionSignature passes the index for this work.

struct Device : public vtkm::worklet::internal::WorkletBase::Device
#include <WorkletPointNeighborhood.h>

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.

4.3.3.2. Cell Neighborhood

A worklet deriving vtkm::worklet::WorkletCellNeighborhood performs a mapping operation that applies a function (the operator in the worklet) on all the cells of a vtkm::cont::DataSet. While operating on the cell, the worklet has access to field values on nearby cells within a neighborhood.

class WorkletCellNeighborhood : public vtkm::worklet::WorkletNeighborhood

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.

A cell neighborhood worklet supports the following tags in the parameters of its ControlSignature.

struct CellSetIn : public vtkm::worklet::WorkletNeighborhood::CellSetIn
#include <WorkletCellNeighborhood.h>

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 FieldIn : public vtkm::worklet::WorkletNeighborhood::FieldIn
#include <WorkletCellNeighborhood.h>

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.

struct FieldInNeighborhood : public vtkm::worklet::WorkletNeighborhood::FieldInNeighborhood
#include <WorkletCellNeighborhood.h>

A control signature tag for neighborhood input values.

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 have local indices ranging from -1 to 1 in each dimension.

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 FieldOut : public vtkm::worklet::WorkletNeighborhood::FieldOut
#include <WorkletCellNeighborhood.h>

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.

struct FieldInOut : public vtkm::worklet::WorkletNeighborhood::FieldInOut
#include <WorkletCellNeighborhood.h>

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.

struct WholeArrayIn : public vtkm::worklet::internal::WorkletBase::WholeArrayIn
#include <WorkletCellNeighborhood.h>

ControlSignature tag for whole input arrays.

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 WholeArrayOut : public vtkm::worklet::internal::WorkletBase::WholeArrayOut
#include <WorkletCellNeighborhood.h>

ControlSignature tag for whole output arrays.

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 WholeArrayInOut : public vtkm::worklet::internal::WorkletBase::WholeArrayInOut
#include <WorkletCellNeighborhood.h>

ControlSignature tag for whole input/output arrays.

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 AtomicArrayInOut : public vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
#include <WorkletCellNeighborhood.h>

ControlSignature tag for whole input/output arrays.

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.

template<typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn : public vtkm::worklet::internal::WorkletBase::WholeCellSetIn<Cell, Point>
#include <WorkletCellNeighborhood.h>

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

struct ExecObject : public vtkm::worklet::internal::WorkletBase::ExecObject
#include <WorkletCellNeighborhood.h>

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.

A cell neighborhood worklet supports the following tags in the parameters of its ExecutionSignature.

struct _1 : public vtkm::placeholders::Arg<1>
#include <WorkletCellNeighborhood.h>

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.

struct Boundary : public vtkm::worklet::WorkletNeighborhood::Boundary
#include <WorkletCellNeighborhood.h>

The ExecutionSignature tag to query if the current iteration is inside the boundary.

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.

struct WorkIndex : public vtkm::exec::arg::WorkIndex
#include <WorkletCellNeighborhood.h>

The ExecutionSignature tag to use to get the work index.

This tag produces a vtkm::Id that uniquely identifies the invocation instance of the worklet. When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index for this work.

struct VisitIndex : public vtkm::exec::arg::VisitIndex
#include <WorkletCellNeighborhood.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, there is a scatter operation defined that optionally allows each input to go to multiple output entries. When one input is assigned to multiple outputs, there needs to be a mechanism to uniquely identify which output is which. The visit index is a value between 0 and the number of outputs a particular input goes to. This tag in the ExecutionSignature passes the visit index for this work.

struct InputIndex : public vtkm::exec::arg::InputIndex
#include <WorkletCellNeighborhood.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the input element that the work thread is currently working on. When a worklet has a scatter associated with it, the input and output indices can be different.

struct OutputIndex : public vtkm::exec::arg::OutputIndex
#include <WorkletCellNeighborhood.h>

The ExecutionSignature tag to use to get the output index.

This tag produces a vtkm::Id that identifies the index of the output element. (This is generally the same as WorkIndex.)

When a worklet is dispatched, it broken into pieces defined by the output domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the output element that the work thread is currently working on. When a worklet has a scatter associated with it, the output and output indices can be different.

struct ThreadIndices : public vtkm::exec::arg::ThreadIndices
#include <WorkletCellNeighborhood.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. During this process multiple indices associated with the input and output can be generated. This tag in the ExecutionSignature passes the index for this work.

struct Device : public vtkm::worklet::internal::WorkletBase::Device
#include <WorkletCellNeighborhood.h>

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.

4.3.3.3. Neighborhood Information

As stated earlier in this section, what makes a 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 vtkm::exec::FieldNeighborhood object.

The vtkm::exec::FieldNeighborhood class contains a vtkm::exec::FieldNeighborhood::Get() method that retrieves a field value relative to the local neighborhood. vtkm::exec::FieldNeighborhood::Get() takes the \(i\), \(j\), \(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.”

template<typename FieldPortalType>
struct FieldNeighborhood

Retrieves field values from a neighborhood.

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 FieldInNeighborhood tag in an ExecutionSignature. There is little reason to construct this in user code.

Public Functions

inline ValueType Get(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const

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.

inline ValueType GetUnchecked(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const

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.

inline ValueType Get(const vtkm::Id3 &ijk) const

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.

inline ValueType GetUnchecked(const vtkm::Id3 &ijk) const

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.

Public Members

vtkm::exec::BoundaryState const *const Boundary

The vtkm::exec::BoundaryState used to find field values from local indices.

FieldPortalType Portal

The array portal containing field values.

Example 4.46 Retrieve neighborhood field value.
1          sum = sum + inputField.Get(i, j, k);

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 vtkm::exec::BoundaryState object, which is provided when a Boundary tag is listed in the ExecutionSignature.

Generally, 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 \(3\times3\times3\) neighborhood centered around the point. Likewise, a point neighborhood with radius 2 would contain a \(5\times5\times5\) neighborhood centered around the point. vtkm::exec::BoundaryState provides several methods to determine if the neighborhood is contained in the mesh.

struct BoundaryState

Provides a neighborhood’s placement with respect to the mesh’s boundary.

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 Boundary tag in an ExecutionSignature. There is little reason to construct this in user code.

Unnamed Group

inline bool IsRadiusInXBoundary(vtkm::IdComponent radius) const

Returns true if a neighborhood of the given radius is contained within the bounds of the cell set in the X, Y, or Z direction. Returns false if the neighborhood extends outside of the boundary of the data in the X, Y, or Z direction.

The radius defines the size of the neighborhood in terms of how far away it extends from the center. So if there is a radius of 1, the neighborhood extends 1 unit away from the center in each direction and is 3x3x3. If there is a radius of 2, the neighborhood extends 2 units for a size of 5x5x5.

inline bool IsRadiusInYBoundary(vtkm::IdComponent radius) const

Returns true if a neighborhood of the given radius is contained within the bounds of the cell set in the X, Y, or Z direction. Returns false if the neighborhood extends outside of the boundary of the data in the X, Y, or Z direction.

The radius defines the size of the neighborhood in terms of how far away it extends from the center. So if there is a radius of 1, the neighborhood extends 1 unit away from the center in each direction and is 3x3x3. If there is a radius of 2, the neighborhood extends 2 units for a size of 5x5x5.

inline bool IsRadiusInZBoundary(vtkm::IdComponent radius) const

Returns true if a neighborhood of the given radius is contained within the bounds of the cell set in the X, Y, or Z direction. Returns false if the neighborhood extends outside of the boundary of the data in the X, Y, or Z direction.

The radius defines the size of the neighborhood in terms of how far away it extends from the center. So if there is a radius of 1, the neighborhood extends 1 unit away from the center in each direction and is 3x3x3. If there is a radius of 2, the neighborhood extends 2 units for a size of 5x5x5.

Unnamed Group

inline bool IsNeighborInXBoundary(vtkm::IdComponent offset) const

Returns true if the neighbor at the specified offset is contained within the bounds of the cell set in the X, Y, or Z direction. Returns false if the neighbor falls outside of the boundary of the data in the X, Y, or Z direction.

inline bool IsNeighborInYBoundary(vtkm::IdComponent offset) const

Returns true if the neighbor at the specified offset is contained within the bounds of the cell set in the X, Y, or Z direction. Returns false if the neighbor falls outside of the boundary of the data in the X, Y, or Z direction.

inline bool IsNeighborInZBoundary(vtkm::IdComponent offset) const

Returns true if the neighbor at the specified offset is contained within the bounds of the cell set in the X, Y, or Z direction. Returns false if the neighbor falls outside of the boundary of the data in the X, Y, or Z direction.

Public Functions

inline const vtkm::Id3 &GetCenterIndex() const

Returns the center index of the neighborhood.

This is typically the position of the invocation of the worklet given this boundary condition.

inline bool IsRadiusInBoundary(vtkm::IdComponent radius) const

Returns true if a neighborhood of the given radius is contained within the bounds of the cell set.

Returns false if the neighborhood extends outside of the boundary of the data.

The radius defines the size of the neighborhood in terms of how far away it extends from the center. So if there is a radius of 1, the neighborhood extends 1 unit away from the center in each direction and is 3x3x3. If there is a radius of 2, the neighborhood extends 2 units for a size of 5x5x5.

inline bool IsNeighborInBoundary(const vtkm::IdComponent3 &neighbor) const

Returns true if the neighbor at the specified offset vector is contained within the bounds of the cell set.

Returns false if the neighbor falls outside of the boundary of the data.

inline vtkm::IdComponent3 MinNeighborIndices(vtkm::IdComponent radius) const

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.

inline vtkm::IdComponent3 MaxNeighborIndices(vtkm::IdComponent radius) const

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.

inline vtkm::Id3 NeighborIndexToFullIndexClamp(const vtkm::IdComponent3 &neighbor) const

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 index that is past the minimum x range of the data, the index at the minimum x boundary is returned.

inline vtkm::Id3 NeighborIndexToFullIndexClamp(vtkm::IdComponent neighborI, vtkm::IdComponent neighborJ, vtkm::IdComponent neighborK) const

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 index that is past the minimum x range of the data, the index at the minimum x boundary is returned.

inline vtkm::Id3 NeighborIndexToFullIndex(const vtkm::IdComponent3 &neighbor) const

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.

inline vtkm::Id3 NeighborIndexToFullIndex(vtkm::IdComponent neighborI, vtkm::IdComponent neighborJ, vtkm::IdComponent neighborK) const

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.

inline vtkm::IdComponent3 ClampNeighborIndex(const vtkm::IdComponent3 &neighbor) const

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 the minimum x range of the data, the neighbor index of the minimum x boundary is returned.

inline vtkm::IdComponent3 ClampNeighborIndex(vtkm::IdComponent neighborI, vtkm::IdComponent neighborJ, vtkm::IdComponent neighborK) const

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 the minimum x range of the data, the neighbor index of the minimum x boundary is returned.

inline vtkm::Id NeighborIndexToFlatIndexClamp(const vtkm::IdComponent3 &neighbor) const

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 neighbor index that is past the minimum x range of the data, the index at the minimum x boundary is returned.

inline vtkm::Id NeighborIndexToFlatIndexClamp(vtkm::IdComponent neighborI, vtkm::IdComponent neighborJ, vtkm::IdComponent neighborK) const

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 neighbor index that is past the minimum x range of the data, the index at the minimum x boundary is returned.

inline vtkm::Id NeighborIndexToFlatIndex(const vtkm::IdComponent3 &neighbor) const

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.

inline vtkm::Id NeighborIndexToFlatIndex(vtkm::IdComponent neighborI, vtkm::IdComponent neighborJ, vtkm::IdComponent neighborK) const

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.

Public Members

vtkm::Id3 IJK

The 3D index of the visited element.

vtkm::Id3 PointDimensions

The dimensions of the elements in the mesh.

The vtkm::exec::BoundaryState::MinNeighborIndices() and vtkm::exec::BoundaryState::MaxNeighborIndices() are particularly useful for iterating over the valid portion of the neighborhood.

Example 4.47 Iterating over the valid portion of a neighborhood.
 1    auto minIndices = boundary.MinNeighborIndices(this->NumberOfLayers);
 2    auto maxIndices = boundary.MaxNeighborIndices(this->NumberOfLayers);
 3
 4    T sum = 0;
 5    vtkm::IdComponent size = 0;
 6    for (vtkm::IdComponent k = minIndices[2]; k <= maxIndices[2]; ++k)
 7    {
 8      for (vtkm::IdComponent j = minIndices[1]; j <= maxIndices[1]; ++j)
 9      {
10        for (vtkm::IdComponent i = minIndices[0]; i <= maxIndices[0]; ++i)
11        {
12          sum = sum + inputField.Get(i, j, k);
13          ++size;
14        }
15      }
16    }

4.3.3.4. 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.

Example 4.48 Implementation and use of a point neighborhood worklet.
 1class ApplyBoxKernel : public vtkm::worklet::WorkletPointNeighborhood
 2{
 3private:
 4  vtkm::IdComponent NumberOfLayers;
 5
 6public:
 7  using ControlSignature = void(CellSetIn cellSet,
 8                                FieldInNeighborhood inputField,
 9                                FieldOut outputField);
10  using ExecutionSignature = _3(_2, Boundary);
11
12  using InputDomain = _1;
13
14  ApplyBoxKernel(vtkm::IdComponent kernelSize)
15  {
16    VTKM_ASSERT(kernelSize >= 3);
17    VTKM_ASSERT((kernelSize % 2) == 1);
18
19    this->NumberOfLayers = (kernelSize - 1) / 2;
20  }
21
22  template<typename InputFieldPortalType>
23  VTKM_EXEC typename InputFieldPortalType::ValueType operator()(
24    const vtkm::exec::FieldNeighborhood<InputFieldPortalType>& inputField,
25    const vtkm::exec::BoundaryState& boundary) const
26  {
27    using T = typename InputFieldPortalType::ValueType;
28
29    auto minIndices = boundary.MinNeighborIndices(this->NumberOfLayers);
30    auto maxIndices = boundary.MaxNeighborIndices(this->NumberOfLayers);
31
32    T sum = 0;
33    vtkm::IdComponent size = 0;
34    for (vtkm::IdComponent k = minIndices[2]; k <= maxIndices[2]; ++k)
35    {
36      for (vtkm::IdComponent j = minIndices[1]; j <= maxIndices[1]; ++j)
37      {
38        for (vtkm::IdComponent i = minIndices[0]; i <= maxIndices[0]; ++i)
39        {
40          sum = sum + inputField.Get(i, j, k);
41          ++size;
42        }
43      }
44    }
45
46    return static_cast<T>(sum / size);
47  }
48};

4.3.4. Reduce by Key

A worklet deriving 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 Vec-like 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.

_images/ReduceByKeys.png

Figure 4.1 The collection of values for a reduce by key worklet.

Figure 4.1 shows a pictorial representation of how VTK‑m 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 Vec-like containing all values that have the key.

4.3.4.1. WorkletReduceByKey Reference

class WorkletReduceByKey : public vtkm::worklet::internal::WorkletBase

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.

Subclassed by vtkm::worklet::AverageByKey::AverageWorklet

A reduce by key worklet supports the following tags in the parameters of its ControlSignature.

struct KeysIn : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletReduceByKey.h>

A control signature tag for input keys.

A WorkletReduceByKey operates by collecting all identical keys and then executing the worklet on each unique key. This tag specifies a vtkm::worklet::Keys object that defines and manages these keys.

A WorkletReduceByKey should have exactly one KeysIn tag in its ControlSignature, and the InputDomain should point to it.

struct ValuesIn : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletReduceByKey.h>

A control signature tag for input values associated with the keys.

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 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 ValuesInOut : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletReduceByKey.h>

A control signature tag for input/output values associated with the keys.

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 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.

struct ValuesOut : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletReduceByKey.h>

A control signature tag for output values associated with the keys.

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.

struct ReducedValuesOut : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletReduceByKey.h>

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. 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 ReducedValuesIn : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletReduceByKey.h>

A control signature tag for reduced input values.

AWorkletReduceByKey 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 ReducedValuesInOut : public vtkm::cont::arg::ControlSignatureTagBase
#include <WorkletReduceByKey.h>

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 WholeArrayIn : public vtkm::worklet::internal::WorkletBase::WholeArrayIn
#include <WorkletReduceByKey.h>

ControlSignature tag for whole input arrays.

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 WholeArrayOut : public vtkm::worklet::internal::WorkletBase::WholeArrayOut
#include <WorkletReduceByKey.h>

ControlSignature tag for whole output arrays.

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 WholeArrayInOut : public vtkm::worklet::internal::WorkletBase::WholeArrayInOut
#include <WorkletReduceByKey.h>

ControlSignature tag for whole input/output arrays.

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 AtomicArrayInOut : public vtkm::worklet::internal::WorkletBase::AtomicArrayInOut
#include <WorkletReduceByKey.h>

ControlSignature tag for whole input/output arrays.

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.

template<typename VisitTopology = Cell, typename IncidentTopology = Point>
struct WholeCellSetIn : public vtkm::worklet::internal::WorkletBase::WholeCellSetIn<Cell, Point>
#include <WorkletReduceByKey.h>

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

struct ExecObject : public vtkm::worklet::internal::WorkletBase::ExecObject
#include <WorkletReduceByKey.h>

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.

A reduce by key worklet supports the following tags in the parameters of its ExecutionSignature.

struct _1 : public vtkm::placeholders::Arg<1>
#include <WorkletReduceByKey.h>

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.

struct ValueCount : public vtkm::exec::arg::ValueCount
#include <WorkletReduceByKey.h>

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 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 WorkIndex : public vtkm::exec::arg::WorkIndex
#include <WorkletReduceByKey.h>

The ExecutionSignature tag to use to get the work index.

This tag produces a vtkm::Id that uniquely identifies the invocation instance of the worklet. When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index for this work.

struct VisitIndex : public vtkm::exec::arg::VisitIndex
#include <WorkletReduceByKey.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, there is a scatter operation defined that optionally allows each input to go to multiple output entries. When one input is assigned to multiple outputs, there needs to be a mechanism to uniquely identify which output is which. The visit index is a value between 0 and the number of outputs a particular input goes to. This tag in the ExecutionSignature passes the visit index for this work.

struct InputIndex : public vtkm::exec::arg::InputIndex
#include <WorkletReduceByKey.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the input element that the work thread is currently working on. When a worklet has a scatter associated with it, the input and output indices can be different.

struct OutputIndex : public vtkm::exec::arg::OutputIndex
#include <WorkletReduceByKey.h>

The ExecutionSignature tag to use to get the output index.

This tag produces a vtkm::Id that identifies the index of the output element. (This is generally the same as WorkIndex.)

When a worklet is dispatched, it broken into pieces defined by the output domain and scheduled on independent threads. This tag in the ExecutionSignature passes the index of the output element that the work thread is currently working on. When a worklet has a scatter associated with it, the output and output indices can be different.

struct ThreadIndices : public vtkm::exec::arg::ThreadIndices
#include <WorkletReduceByKey.h>

The ExecutionSignature tag to use to get 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.

When a worklet is dispatched, it broken into pieces defined by the input domain and scheduled on independent threads. During this process multiple indices associated with the input and output can be generated. This tag in the ExecutionSignature passes the index for this work.

struct Device : public vtkm::worklet::internal::WorkletBase::Device
#include <WorkletReduceByKey.h>

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.

4.3.4.2. 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 vtkm::cont::ArrayHandle. Rather, this argument has to be given a 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 vtkm::worklet::Keys object can be constructed by simply providing a vtkm::cont::ArrayHandle to use as the keys.

template<typename T>
class Keys : public vtkm::worklet::internal::KeysBase

Manage keys for a vtkm::worklet::WorkletReduceByKey.

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.

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 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.

Public Functions

template<typename KeyStorage>
inline Keys(const vtkm::cont::ArrayHandle<KeyType, KeyStorage> &keys, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())

Construct a Keys class from an array of keys.

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 sorted. This is the equivalent of calling BuildArrays(keys, KeysSortType::Unstable, device).

template<typename KeyArrayType>
void BuildArrays(const KeyArrayType &keys, KeysSortType sort, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())

Build the internal arrays without modifying the input.

This is more efficient for stable sorted arrays, but requires an extra copy of the keys for unstable sorting.

template<typename KeyArrayType>
void BuildArraysInPlace(KeyArrayType &keys, KeysSortType sort, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())

Build the internal arrays and also sort the input keys.

This is more efficient for unstable sorting, but requires an extra copy for stable sorting.

inline KeyArrayHandleType GetUniqueKeys() const

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::Id GetInputRange() const

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::ArrayHandle<vtkm::Id> GetSortedValuesMap() const

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::ArrayHandle<vtkm::Id> GetOffsets() const

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::Id GetNumberOfValues() const

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.

4.3.4.3. 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 histogram in parallel. (VTK‑m 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.

Example 4.49 A helper class to manage histogram bins.
 1class BinScalars
 2{
 3public:
 4  VTKM_EXEC_CONT
 5  BinScalars(const vtkm::Range& range, vtkm::Id numBins)
 6    : Range(range)
 7    , NumBins(numBins)
 8  {
 9  }
10
11  VTKM_EXEC_CONT
12  BinScalars(const vtkm::Range& range, vtkm::Float64 tolerance)
13    : Range(range)
14  {
15    this->NumBins = vtkm::Id(this->Range.Length() / tolerance) + 1;
16  }
17
18  VTKM_EXEC_CONT
19  vtkm::Id GetBin(vtkm::Float64 value) const
20  {
21    vtkm::Float64 ratio = (value - this->Range.Min) / this->Range.Length();
22    vtkm::Id bin = vtkm::Id(ratio * this->NumBins);
23    bin = vtkm::Max(bin, vtkm::Id(0));
24    bin = vtkm::Min(bin, this->NumBins - 1);
25    return bin;
26  }
27
28private:
29  vtkm::Range Range;
30  vtkm::Id NumBins;
31};

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.

Example 4.50 A simple map worklet to identify histogram bins, which will be used as keys.
 1  struct IdentifyBins : vtkm::worklet::WorkletMapField
 2  {
 3    using ControlSignature = void(FieldIn data, FieldOut bins);
 4    using ExecutionSignature = _2(_1);
 5    using InputDomain = _1;
 6
 7    BinScalars Bins;
 8
 9    VTKM_CONT
10    IdentifyBins(const BinScalars& bins)
11      : Bins(bins)
12    {
13    }
14
15    VTKM_EXEC
16    vtkm::Id operator()(vtkm::Float64 value) const { return Bins.GetBin(value); }
17  };

Once you generate an array to be used as keys, you need to make a vtkm::worklet::Keys object. The vtkm::worklet::Keys object is what will be passed to the vtkm::cont::Invoker for the argument associated with the KeysIn ControlSignature tag. This of course happens in the control environment after calling the vtkm::cont::Invoker for our worklet for generating the keys.

Example 4.51 Creating a vtkm::worklet::Keys object.
1    vtkm::cont::ArrayHandle<vtkm::Id> binIds;
2    this->Invoke(IdentifyBins(bins), valuesArray, binIds);
3
4    vtkm::worklet::Keys<vtkm::Id> keys(binIds);

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 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.

Example 4.52 A reduce by key worklet to write histogram bin counts.
 1  struct CountBins : vtkm::worklet::WorkletReduceByKey
 2  {
 3    using ControlSignature = void(KeysIn keys, WholeArrayOut binCounts);
 4    using ExecutionSignature = void(_1, ValueCount, _2);
 5    using InputDomain = _1;
 6
 7    template<typename BinCountsPortalType>
 8    VTKM_EXEC void operator()(vtkm::Id binId,
 9                              vtkm::IdComponent numValuesInBin,
10                              BinCountsPortalType& binCounts) const
11    {
12      binCounts.Set(binId, numValuesInBin);
13    }
14  };

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.

Example 4.53 A worklet that averages all values with a common key.
 1  struct BinAverage : vtkm::worklet::WorkletReduceByKey
 2  {
 3    using ControlSignature = void(KeysIn keys,
 4                                  ValuesIn originalValues,
 5                                  ReducedValuesOut averages);
 6    using ExecutionSignature = _3(_2);
 7    using InputDomain = _1;
 8
 9    template<typename OriginalValuesVecType>
10    VTKM_EXEC typename OriginalValuesVecType::ComponentType operator()(
11      const OriginalValuesVecType& originalValues) const
12    {
13      typename OriginalValuesVecType::ComponentType sum = 0;
14      for (vtkm::IdComponent index = 0; index < originalValues.GetNumberOfComponents();
15           index++)
16      {
17        sum = sum + originalValues[index];
18      }
19      return sum / originalValues.GetNumberOfComponents();
20    }
21  };

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.

Example 4.54 Using a reduce by key worklet to average values falling into the same bin.
 1  struct IdentifyBins : vtkm::worklet::WorkletMapField
 2  {
 3    using ControlSignature = void(FieldIn data, FieldOut bins);
 4    using ExecutionSignature = _2(_1);
 5    using InputDomain = _1;
 6
 7    BinScalars Bins;
 8
 9    VTKM_CONT
10    IdentifyBins(const BinScalars& bins)
11      : Bins(bins)
12    {
13    }
14
15    VTKM_EXEC
16    vtkm::Id operator()(vtkm::Float64 value) const { return Bins.GetBin(value); }
17  };
18
19  struct BinAverage : vtkm::worklet::WorkletReduceByKey
20  {
21    using ControlSignature = void(KeysIn keys,
22                                  ValuesIn originalValues,
23                                  ReducedValuesOut averages);
24    using ExecutionSignature = _3(_2);
25    using InputDomain = _1;
26
27    template<typename OriginalValuesVecType>
28    VTKM_EXEC typename OriginalValuesVecType::ComponentType operator()(
29      const OriginalValuesVecType& originalValues) const
30    {
31      typename OriginalValuesVecType::ComponentType sum = 0;
32      for (vtkm::IdComponent index = 0; index < originalValues.GetNumberOfComponents();
33           index++)
34      {
35        sum = sum + originalValues[index];
36      }
37      return sum / originalValues.GetNumberOfComponents();
38    }
39  };
40
41  //
42  // Later in the associated Filter class...
43  //
44
45    vtkm::Range range = vtkm::cont::ArrayRangeCompute(inField).ReadPortal().Get(0);
46    BinScalars bins(range, numBins);
47
48    vtkm::cont::ArrayHandle<vtkm::Id> binIds;
49    this->Invoke(IdentifyBins(bins), inField, binIds);
50
51    vtkm::worklet::Keys<vtkm::Id> keys(binIds);
52
53    vtkm::cont::ArrayHandle<T> combinedValues;
54
55    this->Invoke(BinAverage{}, keys, inField, combinedValues);