4.7. Working with Cells
In the control environment, data is defined in mesh structures that comprise a set of finite cells. (See Section 2.4.2 (Cell Sets) for information on defining cell sets in the control environment.) When worklets that operate on cells are scheduled, these grid structures are broken into their independent cells, and that data is handed to the worklet. Thus, cell-based operations in the execution environment exclusively operate on independent cells.
Unlike some other libraries such as VTK, VTK‑m does not have a cell class that holds all the information pertaining to a cell of a particular type. Instead, VTK‑m provides tags or identifiers defining the cell shape, and companion data like coordinate and field information are held in separate structures. This organization is designed so a worklet may specify exactly what information it needs, and only that information will be loaded.
4.7.2. Parametric and World Coordinates
Each cell type supports a one-to-one mapping between a set of parametric coordinates in the unit cube (or some subset of it) and the points in 3D space that are the locus contained in the cell. Parametric coordinates are useful because certain features of the cell, such as vertex location and center, are at a consistent location in parametric space irrespective of the location and distortion of the cell in world space. Also, many field operations are much easier with parametric coordinates.
The vtkm/exec/ParametricCoordinates.h
header file contains the following functions for working with parametric coordinates.
These functions contain several overloads for using different cell shape tags.
-
template<typename ParametricCoordType>
static inline vtkm::ErrorCode vtkm::exec::ParametricCoordinatesCenter(vtkm::IdComponent numPoints, vtkm::CellShapeTagGeneric shape, vtkm::Vec<ParametricCoordType, 3> &pcoords) Returns the parametric center of the given cell shape with the given number of points.
- Parameters:
numPoints – [in] The number of points in the cell.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.pcoords – [out]
vtkm::Vec
to store the parametric center.
-
template<typename ParametricCoordType>
static inline vtkm::ErrorCode vtkm::exec::ParametricCoordinatesPoint(vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex, vtkm::CellShapeTagGeneric shape, vtkm::Vec<ParametricCoordType, 3> &pcoords) Returns the parametric coordinate of a cell point of the given shape with the given number of points.
- Parameters:
numPoints – [in] The number of points in the cell.
pointIndex – [in] The local index for the point to get the parametric coordinates of. This index is between 0 and n-1 where n is the number of points in the cell.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.pcoords – [out]
vtkm::Vec
to store the parametric center.
-
template<typename WorldCoordVector, typename PCoordType>
static inline vtkm::ErrorCode vtkm::exec::ParametricCoordinatesToWorldCoordinates(const WorldCoordVector &pointWCoords, const vtkm::Vec<PCoordType, 3> &pcoords, vtkm::CellShapeTagGeneric shape, typename WorldCoordVector::ComponentType &result) Converts parametric coordinates (coordinates relative to the cell) to world coordinates (coordinates in the global system).
- Parameters:
pointWCoords – [in] A list of world coordinates for each point in the cell. This usually comes from a
FieldInPoint
argument in avtkm::worklet::WorkletVisitCellsWithPoints
where the coordinate system is passed into that argument.pcoords – [in] The parametric coordinates where you want to get world coordinates for.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out]
vtkm::Vec
to store the interpolated world coordinates.
-
template<typename WorldCoordVector>
static inline vtkm::ErrorCode vtkm::exec::WorldCoordinatesToParametricCoordinates(const WorldCoordVector &pointWCoords, const typename WorldCoordVector::ComponentType &wcoords, vtkm::CellShapeTagGeneric shape, typename WorldCoordVector::ComponentType &result) Converts world coordinates (coordinates in the global system) to parametric coordinates (coordinates relative to the cell).
This function can be slow for cell types with nonlinear interpolation (which is anything that is not a simplex).
- Parameters:
pointWCoords – [in] A list of world coordinates for each point in the cell. This usually comes from a
FieldInPoint
argument in avtkm::worklet::WorkletVisitCellsWithPoints
where the coordinate system is passed into that argument.wcoords – [in] The world coordinates where you want to get parametric coordinates for.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out]
vtkm::Vec
to store the associated parametric coordinates.
4.7.3. Interpolation
The shape of every cell is defined by the connections of some finite set of points. Field values defined on those points can be interpolated to any point within the cell to estimate a continuous field.
The vtkm/exec/CellInterpolate.h
header contains the function vtkm::exec::CellInterpolate()
to do this interpolation.
-
template<typename FieldVecType, typename ParametricCoordType>
vtkm::ErrorCode vtkm::exec::CellInterpolate(const FieldVecType &pointFieldValues, const vtkm::Vec<ParametricCoordType, 3> ¶metricCoords, vtkm::CellShapeTagGeneric shape, typename FieldVecType::ComponentType &result) Interpolate a point field in a cell.
Given the point field values for each node and the parametric coordinates of a point within the cell, interpolates the field to that point.
- Parameters:
pointFieldValues – [in] A list of field values for each point in the cell. This usually comes from a
FieldInPoint
argument in avtkm::worklet::WorkletVisitCellsWithPoints
.parametricCoords – [in] The parametric coordinates where you want to get the interpolated field value for.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out] Value to store the interpolated field.
1struct CellCenters : vtkm::worklet::WorkletVisitCellsWithPoints
2{
3 using ControlSignature = void(CellSetIn,
4 FieldInPoint inputField,
5 FieldOutCell outputField);
6 using ExecutionSignature = void(CellShape, PointCount, _2, _3);
7 using InputDomain = _1;
8
9 template<typename CellShapeTag, typename FieldInVecType, typename FieldOutType>
10 VTKM_EXEC void operator()(CellShapeTag shape,
11 vtkm::IdComponent pointCount,
12 const FieldInVecType& inputField,
13 FieldOutType& outputField) const
14 {
15 vtkm::Vec3f center;
16 vtkm::ErrorCode status =
17 vtkm::exec::ParametricCoordinatesCenter(pointCount, shape, center);
18 if (status != vtkm::ErrorCode::Success)
19 {
20 this->RaiseError(vtkm::ErrorString(status));
21 return;
22 }
23 vtkm::exec::CellInterpolate(inputField, center, shape, outputField);
24 }
25};
4.7.4. Derivatives
Since interpolations provide a continuous field function over a cell, it is reasonable to consider the derivative of this function.
The vtkm/exec/CellDerivative.h
header contains the function vtkm::exec::CellDerivative()
to compute derivatives.
The derivative is returned in a vtkm::Vec
of size 3 corresponding to the partial derivatives in the \(x\), \(y\), and \(z\) directions.
This derivative is equivalent to the gradient of the field.
1struct CellDerivatives : vtkm::worklet::WorkletVisitCellsWithPoints
2{
3 using ControlSignature = void(CellSetIn,
4 FieldInPoint inputField,
5 FieldInPoint pointCoordinates,
6 FieldOutCell outputField);
7 using ExecutionSignature = void(CellShape, PointCount, _2, _3, _4);
8 using InputDomain = _1;
9
10 template<typename CellShapeTag,
11 typename FieldInVecType,
12 typename PointCoordVecType,
13 typename FieldOutType>
14 VTKM_EXEC void operator()(CellShapeTag shape,
15 vtkm::IdComponent pointCount,
16 const FieldInVecType& inputField,
17 const PointCoordVecType& pointCoordinates,
18 FieldOutType& outputField) const
19 {
20 vtkm::Vec3f center;
21 vtkm::ErrorCode status =
22 vtkm::exec::ParametricCoordinatesCenter(pointCount, shape, center);
23 if (status != vtkm::ErrorCode::Success)
24 {
25 this->RaiseError(vtkm::ErrorString(status));
26 return;
27 }
28 vtkm::exec::CellDerivative(inputField, pointCoordinates, center, shape, outputField);
29 }
30};
4.7.5. Edges and Faces
As explained earlier in this chapter, a cell is defined by a collection of points and a shape identifier that describes how the points come together to form the structure of the cell. The cell shapes supported by VTK‑m are documented in Section 4.7.1 (Cell Shape Tags and Ids). It contains Figure 4.2, which shows how the points for each shape form the structure of the cell.
Most cell shapes can be broken into subelements. 2D and 3D cells have pairs of points that form edges at the boundaries of the cell. Likewise, 3D cells have loops of edges that form faces that encase the cell. Figure 4.3 demonstrates the relationship of these constituent elements for some example cell shapes.
The header file vtkm/exec/CellEdge.h
contains a collection of functions to help identify the edges of a cell.
-
static inline vtkm::ErrorCode vtkm::exec::CellEdgeNumberOfEdges(vtkm::IdComponent numPoints, vtkm::CellShapeTagGeneric shape, vtkm::IdComponent &numEdges)
Get the number of edges in a cell.
- Parameters:
numPoints – [in] The number of points in the cell.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.numEdges – [out] A reference to return the number of edges.
-
static inline vtkm::ErrorCode vtkm::exec::CellEdgeLocalIndex(vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex, vtkm::IdComponent edgeIndex, vtkm::CellShapeTagGeneric shape, vtkm::IdComponent &result)
Given the index for an edge of a cell and one of the points on that edge, this function returns the point index for the cell.
To get the point indices relative to the data set, the returned index should be used to reference a
PointIndices
list.- Parameters:
numPoints – [in] The number of points in the cell.
pointIndex – [in] The index of the edge within the cell.
edgeIndex – [in] The index of the point on the edge (either 0 or 1).
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out] Reference to put the index of the point relative to the cell (between 0 and the number of points in the cell).
-
template<typename CellShapeTag, typename GlobalPointIndicesVecType>
static inline vtkm::ErrorCode vtkm::exec::CellEdgeCanonicalId(vtkm::IdComponent numPoints, vtkm::IdComponent edgeIndex, CellShapeTag shape, const GlobalPointIndicesVecType &globalPointIndicesVec, vtkm::Id2 &result) Returns a canonical identifier for a cell edge.
Given information about a cell edge and the global point indices for that cell, returns a vtkm::Id2 that contains values that are unique to that edge. The values for two edges will be the same if and only if the edges contain the same points.
The following example demonstrates a pair of worklets that use the cell edge functions. As is typical for operations of this nature, one worklet counts the number of edges in each cell and another uses this count to generate the data.
Did You Know?
Example 4.70 demonstrates one of many techniques for creating cell sets in a worklet. Chapter~ref{chap:GeneratingCellSets} describes this and many more such techniques.
1 struct EdgesCount : vtkm::worklet::WorkletVisitCellsWithPoints
2 {
3 using ControlSignature = void(CellSetIn, FieldOutCell numEdgesInCell);
4 using ExecutionSignature = void(CellShape, PointCount, _2);
5 using InputDomain = _1;
6
7 template<typename CellShapeTag>
8 VTKM_EXEC void operator()(CellShapeTag cellShape,
9 vtkm::IdComponent numPointsInCell,
10 vtkm::IdComponent& numEdges) const
11 {
12 vtkm::ErrorCode status =
13 vtkm::exec::CellEdgeNumberOfEdges(numPointsInCell, cellShape, numEdges);
14 if (status != vtkm::ErrorCode::Success)
15 {
16 this->RaiseError(vtkm::ErrorString(status));
17 }
18 }
19 };
20
21 struct EdgesExtract : vtkm::worklet::WorkletVisitCellsWithPoints
22 {
23 using ControlSignature = void(CellSetIn, FieldOutCell edgeIndices);
24 using ExecutionSignature = void(CellShape, PointIndices, VisitIndex, _2);
25 using InputDomain = _1;
26
27 using ScatterType = vtkm::worklet::ScatterCounting;
28
29 template<typename CellShapeTag,
30 typename PointIndexVecType,
31 typename EdgeIndexVecType>
32 VTKM_EXEC void operator()(CellShapeTag cellShape,
33 const PointIndexVecType& globalPointIndicesForCell,
34 vtkm::IdComponent edgeIndex,
35 EdgeIndexVecType& edgeIndices) const
36 {
37 vtkm::IdComponent numPointsInCell =
38 globalPointIndicesForCell.GetNumberOfComponents();
39
40 vtkm::ErrorCode error;
41
42 vtkm::IdComponent pointInCellIndex0;
43 error = vtkm::exec::CellEdgeLocalIndex(
44 numPointsInCell, 0, edgeIndex, cellShape, pointInCellIndex0);
45 if (error != vtkm::ErrorCode::Success)
46 {
47 this->RaiseError(vtkm::ErrorString(error));
48 return;
49 }
50
51 vtkm::IdComponent pointInCellIndex1;
52 error = vtkm::exec::CellEdgeLocalIndex(
53 numPointsInCell, 1, edgeIndex, cellShape, pointInCellIndex1);
54 if (error != vtkm::ErrorCode::Success)
55 {
56 this->RaiseError(vtkm::ErrorString(error));
57 return;
58 }
59
60 edgeIndices[0] = globalPointIndicesForCell[pointInCellIndex0];
61 edgeIndices[1] = globalPointIndicesForCell[pointInCellIndex1];
62 }
63 };
The header file vtkm/exec/CellFace.h
contains a collection of functions to help identify the faces of a cell.
-
template<typename CellShapeTag>
static inline vtkm::ErrorCode vtkm::exec::CellFaceNumberOfFaces(CellShapeTag shape, vtkm::IdComponent &result) Get the number of faces in a cell.
- Parameters:
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out] A reference to return the number of faces.
-
template<typename CellShapeTag>
static inline vtkm::ErrorCode vtkm::exec::CellFaceNumberOfPoints(vtkm::IdComponent faceIndex, CellShapeTag shape, vtkm::IdComponent &result) Get the number of points in a face.
Given a local index to the face and a shape of the cell, this method returns the number of points in that particular face.
- Parameters:
faceIndex – [in] The index of the face within the cell.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out] A reference to return the number of points in the selected face.
-
template<typename CellShapeTag>
static inline vtkm::ErrorCode vtkm::exec::CellFaceShape(vtkm::IdComponent faceIndex, CellShapeTag shape, vtkm::UInt8 &result) Get the shape of a face.
Given a local index to the face and a shape of the cell, this method returns the identifier for the shape of that face. Faces are always polygons, so it is valid to just to treat the face as a
CELL_SHAPE_POLYGON
. However, the face will be checked to see if it can be further specialized toCELL_SHAPE_TRIANGLE
orCELL_SHAPE_QUAD
.- Parameters:
faceIndex – [in] The index of the face within the cell.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out] A reference to return the number of points in the selected face.
-
template<typename CellShapeTag>
static inline vtkm::ErrorCode vtkm::exec::CellFaceLocalIndex(vtkm::IdComponent pointIndex, vtkm::IdComponent faceIndex, CellShapeTag shape, vtkm::IdComponent &result) Given the index for a face of a cell and one of the points on that face, this function returns the point index for the cell.
To get the point indices relative to the data set, the returned index should be used to reference a
PointIndices
list.- Parameters:
pointIndex – [in] The index of the edge within the cell.
faceIndex – [in] The index of the point on the face.
shape – [in] A tag of type
CellShapeTag*
to identify the shape of the cell. This method is overloaded for different shape types.result – [out] Reference to put the index of the point relative to the cell (between 0 and the number of points in the cell).
-
template<typename CellShapeTag, typename GlobalPointIndicesVecType>
static inline vtkm::ErrorCode vtkm::exec::CellFaceCanonicalId(vtkm::IdComponent faceIndex, CellShapeTag shape, const GlobalPointIndicesVecType &globalPointIndicesVec, vtkm::Id3 &result) Returns a canonical identifier for a cell face.
Given information about a cell face and the global point indices for that cell, returns a
vtkm::Id3
that contains values that are unique to that face. The values for two faces will be the same if and only if the faces contain the same points.Note that this property is only true if the mesh is conforming. That is, any two neighboring cells that share a face have the same points on that face. This preculdes 2 faces sharing more than a single point or single edge.
The following example demonstrates a triple of worklets that use the cell face functions. As is typical for operations of this nature, the worklets are used in steps to first count entities and then generate new entities. In this case, the first worklet counts the number of faces and the second worklet counts the points in each face. The third worklet generates cells for each face.
1 struct FacesCount : vtkm::worklet::WorkletVisitCellsWithPoints
2 {
3 using ControlSignature = void(CellSetIn, FieldOutCell numFacesInCell);
4 using ExecutionSignature = void(CellShape, _2);
5 using InputDomain = _1;
6
7 template<typename CellShapeTag>
8 VTKM_EXEC void operator()(CellShapeTag cellShape, vtkm::IdComponent& numFaces) const
9 {
10 vtkm::ErrorCode status = vtkm::exec::CellFaceNumberOfFaces(cellShape, numFaces);
11 if (status != vtkm::ErrorCode::Success)
12 {
13 this->RaiseError(vtkm::ErrorString(status));
14 }
15 }
16 };
17
18 struct FacesCountPoints : vtkm::worklet::WorkletVisitCellsWithPoints
19 {
20 using ControlSignature = void(CellSetIn,
21 FieldOutCell numPointsInFace,
22 FieldOutCell faceShape);
23 using ExecutionSignature = void(CellShape, VisitIndex, _2, _3);
24 using InputDomain = _1;
25
26 using ScatterType = vtkm::worklet::ScatterCounting;
27
28 template<typename CellShapeTag>
29 VTKM_EXEC void operator()(CellShapeTag cellShape,
30 vtkm::IdComponent faceIndex,
31 vtkm::IdComponent& numPointsInFace,
32 vtkm::UInt8& faceShape) const
33 {
34 vtkm::exec::CellFaceNumberOfPoints(faceIndex, cellShape, numPointsInFace);
35 switch (numPointsInFace)
36 {
37 case 3:
38 faceShape = vtkm::CELL_SHAPE_TRIANGLE;
39 break;
40 case 4:
41 faceShape = vtkm::CELL_SHAPE_QUAD;
42 break;
43 default:
44 faceShape = vtkm::CELL_SHAPE_POLYGON;
45 break;
46 }
47 }
48 };
49
50 struct FacesExtract : vtkm::worklet::WorkletVisitCellsWithPoints
51 {
52 using ControlSignature = void(CellSetIn, FieldOutCell faceIndices);
53 using ExecutionSignature = void(CellShape, PointIndices, VisitIndex, _2);
54 using InputDomain = _1;
55
56 using ScatterType = vtkm::worklet::ScatterCounting;
57
58 template<typename CellShapeTag,
59 typename PointIndexVecType,
60 typename FaceIndexVecType>
61 VTKM_EXEC void operator()(CellShapeTag cellShape,
62 const PointIndexVecType& globalPointIndicesForCell,
63 vtkm::IdComponent faceIndex,
64 FaceIndexVecType& faceIndices) const
65 {
66 vtkm::IdComponent numPointsInFace = faceIndices.GetNumberOfComponents();
67 for (vtkm::IdComponent pointInFaceIndex = 0; pointInFaceIndex < numPointsInFace;
68 pointInFaceIndex++)
69 {
70 vtkm::IdComponent pointInCellIndex;
71 vtkm::ErrorCode error = vtkm::exec::CellFaceLocalIndex(
72 pointInFaceIndex, faceIndex, cellShape, pointInCellIndex);
73 if (error != vtkm::ErrorCode::Success)
74 {
75 this->RaiseError(vtkm::ErrorString(error));
76 return;
77 }
78 faceIndices[pointInFaceIndex] = globalPointIndicesForCell[pointInCellIndex];
79 }
80 }
81 };