% -*- latex -*-

\chapter{Unknown Cell Sets}
\label{chap:UnknownCellSet}

\index{unknown cell set|(}
\index{cell set!unknown|(}

\vtkmcont{DataSet} must hold a \vtkmcont{CellSet} object, but it cannot know its specific type at compile time.
To manage storing \textidentifier{CellSet}s without knowing their types, \textidentifier{DataSet} actually holds a reference using \vtkmcont{UnknownCellSet}.
\textidentifier{UnknownCellSet} is a simple polymorphic container that stores a reference to a \vtkmcont{CellSet} of unknown type.

It is possible to create an empty \textidentifier{UnknownCellSet}.
You can use the \classmember*{UnknownCellSet}{IsValid} function to query whether an \textidentifier{UnknownCellSet} holds a valid \textidentifier{CellSet}.
Performing operations on an invalid \textidentifier{UnknownCellSet} can lead to unexpected behavior.

\section{Generic Operations}
\label{sec:UnknownCellSet:GenericOperations}

Some cell set operations in \VTKm require a specific, concrete class of \textidentifier{CellSet}.
But \textidentifier{UnknownCellSet} provides several functions that allow you to operate on a cell set without knowing the exact type.

\begin{description}
\item[\classmember*{UnknownCellSet}{IsValid}]%
  Returns true if the \textidentifier{UnknownCellSet} holds a legitimate \textidentifier{CellSet}.
  Other operations on the \textidentifier{UnknownCellSet} may have undefined behavior if it is not valid.
\item[\classmember*{UnknownCellSet}{GetCellSetBase}]%
  All cell set classes inherit from the \vtkmcont{CellSet} base class.
  This method returns a pointer to the contained cell set object as this base type.
\item[\classmember*{UnknownCellSet}{NewInstance}]%
  Creates a new cell set object of the same type as that stored in the \textidentifier{UnknownCellSet} and returns the new instance in another \textidentifier{UnknownCellSet}.
\item[\classmember*{UnknownCellSet}{GetCellSetName}]%
  Return a \textcode{std::string} containing the specific class name of the contained cell set.
\item[\classmember*{UnknownCellSet}{GetNumberOfCells}]%
  Returns the number of cells in the cell set.
\item[\classmember*{UnknownCellSet}{GetNumberOfPoints}]%
  Returns the number of points in the cell set.
\item[\classmember*{UnknownCellSet}{GetCellShape}]%
  Given the index of a cell, returns the identifier for the cell shape.
\item[\classmember*{UnknownCellSet}{GetNumberOfPointsInCell}]%
  Given the index of a cell, returns the number of points incident on that cell.
\item[\classmember*{UnknownCellSet}{GetCellPointIds}]%
  Given the index of a cell and an array of \vtkm{Id}s, returns the indices for that the cell is incident to.
  The number of indices put in the array is equal to the value returned from \classmember*{UnknownCellSet}{GetNumberOfPointsInCell}, and the array should be at least that long.
\item[\classmember*{UnknownCellSet}{DeepCopyFrom}]%
  Will copy the connectivity arrays from the provided \textidentifier{UnknownCellSet} to this one.
\item[\classmember*{UnknownCellSet}{PrintSummary}]%
  Prints to the provided \textcode{std::ostream} (such as \textcode{std::cout}) a summary of the contents of the cell set.
\item[\classmember*{UnknownCellSet}{ReleaseResourcesExecution}]%
  Removes any data stored on any device associated with the cell set.
  The data for the cell set will still be available, but may need to be loaded back on a device before an operation.
  This method has no effect if called on an invalid \textidentifier{UnknownCellSet}.
\end{description}


\section{Casting to Known Types}
\label{sec:UnknownCellSet:CastToKnownType}

\index{unknown cell set!cast|(}

There are many operations in \VTKm that need to know the specific type of cell set.
To perform one of these types of operation, you need to retrieve the data as a \textidentifier{CellSet} concrete subclass.
If you happen to know (or can guess) the type, you can use the \classmember*{UnknownCellSet}{AsCellSet} method to retrieve the cell set as a specific type.
You can pass in a reference to a cell set object of the desired type to \classmember*{UnknownCellSet}{AsCellSet}.
You can also call \classmember*{UnknownCellSet}{AsCellSet} with no arguments and the cast cell set will be returned, but in this case you must specify the desired type with a template argument.

\vtkmlisting{Retrieving a cell set of a known type from \textidentifier{UnknownCellSet}.}{UnknownCellSetAsCellSet.cxx}

\index{unknown cell set!query type|(}

If the \textidentifier{UnknownCellSet} cannot store its cell set in the type given to \classmember*{UnknownCellSet}{AsCellSet}, it will throw an exception.
Thus, you should not use \classmember*{UnknownCellSet}{AsCellSet} with types that you are not sure about.
Use the \classmember*{UnknownCellSet}{CanConvert} method to determine if a given \textidentifier{CellSet} type will work with \classmember*{UnknownCellSet}{AsCellSet}.

\vtkmlisting{Querying whether a given \textidentifier{CellSet} can be retrieved from an \textidentifier{UnknownCellSet}.}{UnknownCellSetCanConvert.cxx}

\index{unknown cell set!cast|)}

By design, \classmember*{UnknownCellSet}{CanConvert} will return true for types that are not actually stored in the \textidentifier{UnknownCellSet} but can be retrieved.
If you need to know specifically what type is stored in the \textidentifier{UnknownCellSet}, you can use the \classmember*{UnknownCellSet}{IsType} method instead.
\textidentifier{UnknownCellSet} also provides \classmember*{UnknownCellSet}{GetCellSetName} for debugging purposes.

\begin{commonerrors}
  \classmember*{UnknownCellSet}{CanConvert} is almost always safer to use than \classmember*{UnknownCellSet}{IsType} or its similar methods.
  Even though \classmember*{UnknownCellSet}{IsType} reflects the actual cell set type, \classmember*{UnknownCellSet}{CanConvert} better describes how \textidentifier{UnknownCellSet} will behave.
\end{commonerrors}

\index{unknown cell set!query type|)}

\section{Casting to a List of Potential Types}
\label{sec:UnknownCellSet:CastToPotentialTypes}

\index{unknown cell set!cast|(}

Using \classmember*{UnknownCellSet}{AsCellSet} is fine as long as the correct types are known, but often times they are not.
For this use case \textidentifier{UnknownCellSet} has a method named \classmember*{UnknownCellSet}{CastAndCallForTypes} that attempts to cast the cell set to some set of types.

The \classmember*{UnknownCellSet}{CastAndCallForTypes} method accepts a functor to run on the appropriately cast cell set.
The functor must have an overloaded const parentheses operator that accepts a \textidentifier{CellSet} of the appropriate type.
You also have to specify a template parameter that specifies a \vtkm{List} of cell set types to.
The macro \vtkmmacro{VTKM\_DEFAULT\_CELL\_SET\_LIST} is often used when nothing more specific is known.
The macros \vtkmmacro{VTKM\_DEFAULT\_CELL\_SET\_LIST\_STRUCTURED} and \vtkmmacro{VTKM\_DEFAULT\_CELL\_SET\_LIST\_UNSTRUCTURED} are also useful when you want to operate on only structured or unstructured cell sets.

\vtkmlisting[ex:UnknownCellSetCastAndCallForTypes.cxx]{Operating on an \textidentifier{UnknownCellSet} with \textcode{CastAndCallForTypes}.}{UnknownCellSetCastAndCallForTypes.cxx}

\begin{didyouknow}
  The first (required) argument to \classmember*{UnknownCellSet}{CastAndCallForTypes} is the functor to call with the cell set.
  You can supply any number of optional arguments after that.
  Those arguments will be passed directly to the functor.
  This makes it easy to pass state to the functor.
\end{didyouknow}

\begin{didyouknow}
  When an \textidentifier{UnknownCellSet} is used in place of an \textidentifier{CellSet} as an argument to a worklet invocation, it will internally use \classmember*{UnknownCellSet}{CastAndCallForTypes} to attempt to call the worklet with an \textidentifier{CellSet} of the correct type.
\end{didyouknow}

\textidentifier{UnknownCellSet} has a simple subclass named \vtkmcont{UncertainCellSet} for use when you can narrow the cell set to a finite set of types.
\textidentifier{UncertainCellSet} has a template parameter that must be specified: a \vtkm{List} of cell set types.
\textidentifier{UncertainCellSet} has a method named \classmember*{UncertainCellSet}{CastAndCall} that behaves the same as \classmember*{UnknownCellSet}{CastAndCallForTypes} except that you do not have to specify the types to try.
Instead, the types are taken from the template parameters of the \textidentifier{UncertainCellSet} itself.

\vtkmlisting{Using \textidentifier{UncertainCellSet} to cast and call a functor.}{UncertainCellSet.cxx}

\begin{didyouknow}
  Like with \textidentifier{UnknownCellSet}, if an \textidentifier{UncertainCellSet} is used in a worklet invocation, it will internally use \classmember*{UncertainCellSet}{CastAndCall}.
  This provides a convenient way to specify what cell set types the invoker should try.
\end{didyouknow}

Both \textidentifier{UnknownCellSet} and \textidentifier{UncertainCellSet} provide a method named \classmember*{UnknownCellSet}{ResetCellSetList} to redefine the types to try.
\classmember*{UncertainCellSet}{ResetCellSetList} has a template parameter that is the \vtkm{List} of cell sets.
\classmember*{UnknownCellSet}{ResetCellSetList} returns a new \textidentifier{UncertainCellSet} with the given types.
This is a convenient way to pass these types to functions.

\vtkmlisting{Resetting the types of an \textidentifier{UnknownCellSet}.}{UnknownCellSetResetCellSetList.cxx}

\begin{commonerrors}
  Because it returns an \textidentifier{UncertainCellSet}, you need to include \vtkmheader{vtkm/cont}{UncertainCellSet.h} if you use \classmember{UnknownCellSet}{ResetCellSetList}.
  This is true even if you do not directly use the returned object.
\end{commonerrors}

\index{unknown cell set!cast|)}

\index{cell set!unknown|)}
\index{unknown cell set|)}

\index{cell set|)}
