% -*- latex -*-

\chapter{Worklet Input Output Semantics}
\label{sec:WorkletInOutSemantics}

\index{worklet|(}
\index{worklet!creating|(}

The default scheduling of a worklet provides a 1 to 1 mapping from the input domain to the output domain.
For example, a \vtkmworklet{WorkletMapField} gets run once for every item of the input array and produces one item for the output array.
Likewise, \vtkmworklet{WorkletVisitCellsWithPoints} gets run once for every cell in the input topology and produces one associated item for the output field.

However, there are many operations that do not fall well into this 1 to 1 mapping procedure.
The operation might need to pass over elements that produce no value or the operation might need to produce multiple values for a single input element.
Such non 1 to 1 mappings can be achieved by defining a scatter or a mask (or both) on a worklet.
\fix{Document Mask}

\section{Scatter}
\label{sec:WorkletScatter}

\index{scatter|(}
\index{worklet!scatter|(}

A \keyterm{scatter} allows you to specify for each input element how many output elements should be created.
For example, a scatter allows you to create two output elements for every input element.
A scatter could also allow you to drop every other input element from the output.
The following types of scatter are provided by \VTKm.

\begin{description}
\item[\vtkmworklet{ScatterIdentity}]
  Provides a basic 1 to 1 mapping from input to output.
  This is the default scatter used if none is specified.
\item[\vtkmworklet{ScatterUniform}]
  Provides a 1 to many mapping from input to output with the same number of outputs for each input.
  A template parameter provides the number of output values to produce per input.
\item[\vtkmworklet{ScatterCounting}]
  Provides a 1 to any mapping from input to output with different numbers of outputs for each input.
  The constructor takes an \textidentifier{ArrayHandle} that is the same size as the input containing the count of output values to produce for each input.
  Values can be zero, in which case that input will be skipped.
\item[\vtkmworklet{ScatterPermutation}]
  Reorders the indices.
  The constructor takes a permutation \textidentifier{ArrayHandle} that is sized to the number of output values and maps output indices to input indices.
  For example, if index $i$ of the permutation array contains $j$, then the worklet invocation for output $i$ will get the $j^{\mathrm{th}}$ input values.
  The reordering does not have to be 1 to 1.
  Any input not referenced by the permutation array will be dropped, and any input referenced by the permutation array multiple times will be duplicated.
  However, unlike \textidentifier{ScatterCounting} VisitIndex is always 0 even if an input value happens to be duplicated.
\end{description}

\begin{didyouknow}
  Scatters are often used to create multiple outputs for a single input, but they can also be used to remove inputs from the output.
  In particular, if you provide a count of 0 in a \textidentifier{ScatterCounting} count array, no outputs will be created for the associated input.
  To simply mask out some elements from the input, provide \textidentifier{ScatterCounting} with a stencil array of 0's and 1's with a 0 for every element you want to remove and a 1 for every element you want to pass.
  You can also mix 0's with counts larger than 1 to drop some elements and add multiple results for other elements.
  \textidentifier{ScatterPermutation} can similarly be used to remove input values by leaving them out of the permutation.
\end{didyouknow}

To define a scatter procedure, the worklet must provide a type definition named \scattertype.
The \scattertype must be set to one of the aforementioned \textidentifier{Scatter*} classes.
It is common, but optional, to also provide a static method named \textcode{MakeScatter} that generates an appropriate scatter object for the worklet if you cannot use the default constructor for the scatter.
This static method can be used by users of the worklet to set up the scatter for the \textidentifier{Invoker}.

\vtkmlisting{Declaration of a scatter type in a worklet.}{DeclareScatter.cxx}

When using a scatter that produces multiple outputs for a single input, the worklet is invoked multiple times with the same input values.
In such an event the worklet operator needs to distinguish these calls to produce the correct associated output.
This is done by declaring one of the \executionsignature arguments as \index{visit index} \sigtag{VisitIndex}.
This tag will pass a \vtkm{IdComponent} to the worklet that identifies which invocation is being called.

It is also the case that the when a scatter can produce multiple outputs for some input that the index of the input element is not the same as the \sigtag{WorkIndex}.
If the index to the input element is needed, you can use the \index{input index} \sigtag{InputIndex} tag in the \executionsignature.
It is also good practice to use the \index{output index} \sigtag{OutputIndex} tag if the index to the output element is needed.

Most \textidentifier{Scatter} objects have a state, and this state must be passed to the \vtkmcont{Invoker} when invoking the worklet.
In this case, the \textidentifier{Scatter} object should be passed as the second object to the call to the \textidentifier{Invoker} (after the worklet object).

\vtkmlisting{Invoking with a custom scatter.}{ConstructScatterForInvoke.cxx}

\begin{didyouknow}
  A scatter object does not have to be tied to a single worklet/invoker instance.
  In some cases it makes sense to use the same scatter object multiple times for worklets that have the same input to output mapping.
  Although this is not common, it can save time by reusing the set up computations of \textidentifier{ScatterCounting}.
\end{didyouknow}

To demonstrate using scatters with worklets, we provide some contrived but illustrative examples.
The first example is a worklet that takes a pair of input arrays and interleaves them so that the first, third, fifth, and so on entries come from the first array and the second, fourth, sixth, and so on entries come from the second array.
We achieve this by using a \vtkmworklet{ScatterUniform} of size 2 and using the \sigtag{VisitIndex} to determine from which array to pull a value.

\vtkmlisting{Using \textidentifier{ScatterUniform}.}{ScatterUniform.cxx}

The second example takes a collection of point coordinates and clips them by an axis-aligned bounding box.
It does this using a \vtkmworklet{ScatterCounting} with an array containing 0 for all points outside the bounds and 1 for all points inside the bounds.
As is typical with this type of operation, we use another worklet with a default identity scatter to build the count array.

\vtkmlisting{Using \textidentifier{ScatterCounting}.}{ScatterCounting.cxx}

The third example takes an input array and reverses the ordering.
It does this using a \vtkmworklet{ScatterPermutation} with a permutation array generated from a \vtkmcont{ArrayHandleCounting} counting down from the input array size to 0.

\vtkmlisting{Using \textidentifier{ScatterPermutation}.}{ScatterPermutation.cxx}

\begin{didyouknow}
  A \vtkmworklet{ScatterPermutation} can have less memory usage than a \vtkmworklet{ScatterCounting} when zeroing indices.
  By default, a \vtkmworklet{ScatterPermutation} will omit all fields that are not specified in the input permutation, whereas \vtkmworklet{ScatterCounting} requires 0 values.
  If mapping an input to an output that omits fields, consider using a \vtkmworklet{ScatterPermutation} to save memory.
\end{didyouknow}

\begin{commonerrors}
  A permutation array provided to \vtkmworklet{ScatterPermutation} can be filled with arbitrary id values.
  If an input permutation id exceeds the bounds of an input provided to a \textidentifier{worklet}, an out of bounds error will occur in the worklet functor.
  To prevent this kind of error, you should ensure that ids in the \vtkmworklet{ScatterPermutation} do not exceed the bounds of provided inputs.
\end{commonerrors}


\index{worklet!scatter|)}
\index{scatter|)}

\index{worklet!creating|)}
\index{worklet|)}
