3.6. Unknown Cell Sets
viskores::cont::DataSet must hold a viskores::cont::CellSet object, but it cannot know its specific type at compile time.
To manage storing viskores::cont::CellSet objects without knowing their types, viskores::cont::DataSet actually holds a reference using viskores::cont::UnknownCellSet.
viskores::cont::UnknownCellSet is a simple polymorphic container that stores a reference to a viskores::cont::CellSet of unknown type.
-
class UnknownCellSet
A CellSet of an unknown type.
UnknownCellSetholds aCellSetobject using runtime polymorphism to manage the dynamic type rather than compile-time templates. This adds a programming convenience that helps avoid a proliferation of templates.To interface between the runtime polymorphism and the templated algorithms in Viskores,
UnknownCellSetcontains a method namedCastAndCallForTypesthat determines the correct type from some known list of types. This mechanism is used internally by Viskores’s worklet invocation mechanism to determine the type when running algorithms.If the
UnknownCellSetis used in a context where the possible cell set types can be whittled down to a finite list, you can specify lists of cell set types using theResetCellSetListmethod. This will convert this object to anUncertainCellSetof the given types. In cases where a finite set of types are needed but there is no subset,VISKORES_DEFAULT_CELL_SET_LISTSubclassed by viskores::cont::UncertainCellSet< CellSetList >
It is possible to create an empty viskores::cont::UnknownCellSet.
You can use the viskores::cont::UnknownCellSet::IsValid() function to query whether an viskores::cont::UnknownCellSet holds a valid viskores::cont::CellSet.
Performing operations on an invalid viskores::cont::UnknownCellSet can lead to unexpected behavior.
3.6.1. Generic Operations
Some cell set operations in Viskores require a specific, concrete class of viskores::cont::CellSet.
But viskores::cont::UnknownCellSet provides several functions that allow you to operate on a cell set without knowing the exact type.
-
inline bool viskores::cont::UnknownCellSet::IsValid() const
Returns whether a cell set is stored in this
UnknownCellSet.If the
UnknownCellSetis constructed without aCellSet, it will not have an underlying type, and therefore the operations will be invalid.
-
inline viskores::cont::CellSet *viskores::cont::UnknownCellSet::GetCellSetBase()
Returns a pointer to the
CellSetbase class.
-
inline const viskores::cont::CellSet *viskores::cont::UnknownCellSet::GetCellSetBase() const
-
UnknownCellSet viskores::cont::UnknownCellSet::NewInstance() const
Create a new cell set of the same type as this cell set.
This method creates a new cell set that is the same type as this one and returns a new
UnknownCellSetfor it. This method is convenient when creating output cell sets that should be the same type as the input cell set.
-
std::string viskores::cont::UnknownCellSet::GetCellSetName() const
Returns the name of the cell set type stored in this class.
Returns an empty string if no cell set is stored.
-
inline viskores::Id viskores::cont::UnknownCellSet::GetNumberOfCells() const
Returns the number of cells in the cell set.
-
inline viskores::Id viskores::cont::UnknownCellSet::GetNumberOfPoints() const
Returns the number of points in the cell set.
-
inline viskores::UInt8 viskores::cont::UnknownCellSet::GetCellShape(viskores::Id id) const
Given the index of a cell, returns the identifier for the cell shape.
-
inline viskores::IdComponent viskores::cont::UnknownCellSet::GetNumberOfPointsInCell(viskores::Id id) const
Given the index of a cell, returns the number of points incident on that cell.
-
inline void viskores::cont::UnknownCellSet::GetCellPointIds(viskores::Id id, viskores::Id *ptids) const
Provides the indices for that the cell is incident to.
- Parameters:
id – The index of a cell
ptids – An array to store the incident point ids. The array should be sized based on
GetNumberOfPointsInCell()
-
inline void viskores::cont::UnknownCellSet::DeepCopyFrom(const CellSet *src)
Copy the connectivity arrays from the provided UnknownCellSet to this one.
-
void viskores::cont::UnknownCellSet::PrintSummary(std::ostream &os) const
Prints to the provided stream a summary of the contents of the cell set.
It is common to provide
std::coutto print the summary to standard output.
-
inline void viskores::cont::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
UnknownCellSet.
3.6.2. Casting to Known Types
There are many operations in Viskores 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 viskores::cont::CellSet concrete subclass.
If you happen to know (or can guess) the type, you can use the viskores::cont::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 viskores::cont::UnknownCellSet::AsCellSet().
You can also call viskores::cont::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.
-
template<typename CellSetType>
inline void viskores::cont::UnknownCellSet::AsCellSet(CellSetType &cellSet) const Get the cell set as a known type.
Returns this cell set cast appropriately and stored in the given
CellSettype. Throws anErrorBadTypeif the stored cell set cannot be stored in the given cell set type. Use theCanConvert()method to determine if the cell set can be returned with the given type.
-
template<typename CellSetType>
inline CellSetType viskores::cont::UnknownCellSet::AsCellSet() const Get the cell set as a known type.
Returns this cell set cast appropriately and stored in the given
CellSettype. Throws anErrorBadTypeif the stored cell set cannot be stored in the given cell set type. Use theCanConvert()method to determine if the cell set can be returned with the given type.
1 viskores::cont::CellSetExplicit<> cellSet;
2 unknownCells.AsCellSet(cellSet);
3
4 // This is an equivalent way to get the cell set.
5 auto cellSet2 = unknownCells.AsCellSet<viskores::cont::CellSetExplicit<>>();
If the viskores::cont::UnknownCellSet cannot store its cell set in the type given to viskores::cont::UnknownCellSet::AsCellSet(), it will throw an exception.
Thus, you should not use viskores::cont::UnknownCellSet::AsCellSet() with types that you are not sure about.
Use the viskores::cont::UnknownCellSet::CanConvert() method to determine if a given viskores::cont::CellSet type will work with viskores::cont::UnknownCellSet::AsCellSet().
-
template<typename CellSetType>
inline bool viskores::cont::UnknownCellSet::CanConvert() const Returns true if this cell set can be retrieved as the given type.
This method will return true if calling
AsCellSet()of the given type will succeed. This result is similar toIsType(), and ifIsType()returns true, then this will return true. However, this method will also return true for other types where automatic conversions are made.
viskores::cont::CellSet can be retrieved from an viskores::cont::UnknownCellSet. 1VISKORES_CONT viskores::Id3 Get3DPointDimensions(
2 const viskores::cont::UnknownCellSet& unknownCellSet)
3{
4 if (unknownCellSet.CanConvert<viskores::cont::CellSetStructured<3>>())
5 {
6 viskores::cont::CellSetStructured<3> cellSet;
7 unknownCellSet.AsCellSet(cellSet);
8 return cellSet.GetPointDimensions();
9 }
10 else if (unknownCellSet.CanConvert<viskores::cont::CellSetStructured<2>>())
11 {
12 viskores::cont::CellSetStructured<2> cellSet;
13 unknownCellSet.AsCellSet(cellSet);
14 viskores::Id2 dims = cellSet.GetPointDimensions();
15 return viskores::Id3{ dims[0], dims[1], 1 };
16 }
17 else
18 {
19 return viskores::Id3{ unknownCellSet.GetNumberOfPoints(), 1, 1 };
20 }
21}
By design, viskores::cont::UnknownCellSet::CanConvert() will return true for types that are not actually stored in the viskores::cont::UnknownCellSet but can be retrieved.
If you need to know specifically what type is stored in the viskores::cont::UnknownCellSet, you can use the viskores::cont::UnknownCellSet::IsType() method instead.
You can also use
viskores::cont::UnknownCellSet::GetCellSetName() for debugging purposes.
-
template<typename CellSetType>
inline bool viskores::cont::UnknownCellSet::IsType() const Returns true if this cell set matches the
CellSetTypetemplate argument.
Common Errors
viskores::cont::UnknownCellSet::CanConvert() is almost always safer to use than viskores::cont::UnknownCellSet::IsType() or its similar methods.
Even though viskores::cont::UnknownCellSet::IsType() reflects the actual cell set type, viskores::cont::UnknownCellSet::CanConvert() better describes how viskores::cont::UnknownCellSet will behave.
3.6.3. Casting to a List of Potential Types
Using viskores::cont::UnknownCellSet::AsCellSet() is fine as long as the correct types are known, but often times they are not.
For this use case viskores::cont::UnknownCellSet has a method named viskores::cont::UnknownCellSet::CastAndCallForTypes() that attempts to cast the cell set to some set of types.
-
template<typename CellSetList, typename Functor, typename ...Args>
void viskores::cont::UnknownCellSet::CastAndCallForTypes(Functor &&functor, Args&&... args) const Call a functor using the underlying cell set type.
CastAndCallForTypesattemts to cast the held cell set to a specific type and then calls the given functor with the cast cell set. You must specify theCellSetList(in aviskores::List) as a template argument.After the functor argument, you may add any number of arguments that will be passed to the functor after the converted cell set.
The viskores::cont::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 viskores::cont::CellSet of the appropriate type.
You also have to specify a template parameter that specifies a viskores::List of cell set types to.
The macro VISKORES_DEFAULT_CELL_SET_LIST is often used when nothing more specific is known.
The macros VISKORES_DEFAULT_CELL_SET_LIST_STRUCTURED and VISKORES_DEFAULT_CELL_SET_LIST_UNSTRUCTURED are also useful when you want to operate on only structured or unstructured cell sets.
-
VISKORES_DEFAULT_CELL_SET_LIST
A list of cell set types to use for unknown cell sets.
This macro resolves to a
viskores::Listfilled with concrete subclasses ofviskores::cont::CellSet. These are the default cell types checked during a cast and call operation on an unknown cell set. Filters that do not have restrictions on the types of cells they operate on should support the cell set types in this list.
-
VISKORES_DEFAULT_CELL_SET_LIST_STRUCTURED
A list of structured cell set types to use for unknown cell sets.
This macro resolves to a
viskores::Listfilled with resolved types of theviskores::cont::CellSetStructuredtemplate. Filters that only operate on structured data or have special cases for structured data can use this list in a cast and call to check for structured types.
-
VISKORES_DEFAULT_CELL_SET_LIST_UNSTRUCTURED
A list of unstructured cell set types to use for unknown cell sets.
This macro resolves to a
viskores::Listfilled with concrete subclasses ofviskores::cont::CellSet. Typically, this list contains the types inVISKORES_DEFAULT_CELL_SET_LISTminus the structured cell sets. Filters that have special cases for structured data can use this list in a cast and call to cover the more general unstructured cases.
1struct Get3DPointDimensionsFunctor
2{
3 template<viskores::IdComponent Dims>
4 VISKORES_CONT void operator()(const viskores::cont::CellSetStructured<Dims>& cellSet,
5 viskores::Id3& outDims) const
6 {
7 viskores::Vec<viskores::Id, Dims> pointDims = cellSet.GetPointDimensions();
8 for (viskores::IdComponent d = 0; d < Dims; ++d)
9 {
10 outDims[d] = pointDims[d];
11 }
12 }
13
14 VISKORES_CONT void operator()(const viskores::cont::CellSet& cellSet,
15 viskores::Id3& outDims) const
16 {
17 outDims[0] = cellSet.GetNumberOfPoints();
18 }
19};
20
21VISKORES_CONT viskores::Id3 Get3DPointDimensions(
22 const viskores::cont::UnknownCellSet& unknownCellSet)
23{
24 viskores::Id3 dims(1);
25 unknownCellSet.CastAndCallForTypes<VISKORES_DEFAULT_CELL_SET_LIST>(
26 Get3DPointDimensionsFunctor{}, dims);
27 return dims;
28}
Did You Know?
The first (required) argument to viskores::cont::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.
Did You Know?
When an viskores::cont::UnknownCellSet is used in place of an viskores::cont::CellSet as an argument to a worklet invocation, it will internally use viskores::cont::UnknownCellSet::CastAndCallForTypes() to attempt to call the worklet with an viskores::cont::CellSet of the correct type.
viskores::cont::UnknownCellSet has a simple subclass named viskores::cont::UncertainCellSet for use when you can narrow the cell set to a finite set of types.
viskores::cont::UncertainCellSet has a template parameter that must be specified: a viskores::List of cell set types.
The viskores::cont::UncertainCellSet::CastAndCall() method behaves the same as viskores::cont::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 viskores::cont::UncertainCellSet itself.
-
template<typename CellSetList>
class UncertainCellSet : public viskores::cont::UnknownCellSet A
CellSetof an uncertain type.UncertainCellSetholds aCellSetobject using runtime polymorphism to manage different types. It behaves like its superclass,UnknownCellSet, except that it also contains a template parameter that provides aviskores::Listof potential cell set types.These potental types come into play when the
CastAndCallmethod is called (or theUncertainCellSetis used in theviskores::cont::CastAndCallfunction). In this case, theCastAndCallwill search forCellSets of types that match this list.Both
UncertainCellSetandUnknownCellSethave a method namedResetCellSetListthat redefines the list of potential cell sets by returning a newUncertainCellSetcontaining the sameCellSetbut with the new cell set type list.Public Functions
-
inline Thisclass NewInstance() const
Create a new cell set of the same type as this.
This method creates a new cell set that is the same type as this one and returns a new
UncertainCellSetfor it.
-
inline Thisclass NewInstance() const
1 using StructuredCellSetList = viskores::List<viskores::cont::CellSetStructured<1>,
2 viskores::cont::CellSetStructured<2>,
3 viskores::cont::CellSetStructured<3>>;
4 viskores::cont::UncertainCellSet<StructuredCellSetList> uncertainCellSet(
5 unknownCellSet);
6 uncertainCellSet.CastAndCall(Get3DPointDimensionsFunctor{}, dims);
Did You Know?
Like with viskores::cont::UnknownCellSet, if an viskores::cont::UncertainCellSet is used in a worklet invocation, it will internally use viskores::cont::UncertainCellSet::CastAndCall().
This provides a convenient way to specify what cell set types the invoker should try.
Both viskores::cont::UnknownCellSet and viskores::cont::UncertainCellSet provide a method named viskores::cont::UnknownCellSet::ResetCellSetList() to redefine the types to try.
It has a template parameter that is the viskores::List of cell sets.
viskores::cont::UnknownCellSet::ResetCellSetList() returns a new viskores::cont::UncertainCellSet with the given types.
This is a convenient way to pass these types to functions.
-
template<typename NewCellSetList>
viskores::cont::UncertainCellSet<NewCellSetList> viskores::cont::UnknownCellSet::ResetCellSetList() const
-
template<typename NewCellSetList>
viskores::cont::UncertainCellSet<NewCellSetList> viskores::cont::UnknownCellSet::ResetCellSetList(NewCellSetList) const Assigns potential cell set types.
Calling this method will return an
UncertainCellSetwith the provided cell set list. The returned object will hold the sameCellSet, butCastAndCall’s on the returned object will be constrained to the given types.
1 using StructuredCellSetList = viskores::List<viskores::cont::CellSetStructured<1>,
2 viskores::cont::CellSetStructured<2>,
3 viskores::cont::CellSetStructured<3>>;
4 viskores::cont::Invoker invoke;
5 invoke(
6 MyWorklet{}, unknownCellSet.ResetCellSetList<StructuredCellSetList>(), outArray);
Common Errors
Because it returns a viskores::cont::UncertainCellSet, you need to include viskores/cont/UncertainCellSet.h if you use viskores::cont::UnknownCellSet::ResetCellSetList().
This is true even if you do not directly use the returned object.