Add guide chapter on working with cells

This commit is contained in:
Kenneth Moreland 2024-03-12 15:06:20 -04:00
parent 35f5abcc17
commit 282aa82957
14 changed files with 709 additions and 21 deletions

@ -118,9 +118,7 @@ Explicit meshes are also known as unstructured grids.
Explicit meshes can contain cells of different shapes.
The shapes that |VTKm| currently supports are listed in :numref:`fig:CreateExplicitMeshesCellShapes`.
Each shape is identified using either a numeric identifier, provided by |VTKm| with identifiers of the form ``vtkm::CELL_SHAPE_*`` or special tag structures of the form ``vtkm::CellSetTag*``.
Cell shapes are discussed in detail in ???.
.. todo:: Add cell shape reference above.
Cell shapes are discussed in detail in :chapref:`working-with-cells:Working with Cells`.
.. figure:: images/CellConnections.png
:width: 100%
@ -128,6 +126,8 @@ Cell shapes are discussed in detail in ???.
Basic Cell Shapes.
.. todo:: Add ``vtkm::CellShapeTagPolyLine`` to this figure.
..
.. |CellConnectionsVertex| image:: images/CellConnectionsVertex.png
.. |CellConnectionsLine| image:: images/CellConnectionsLine.png
@ -280,7 +280,7 @@ A cell set determines the topological structure of the data in a data set.
(2D cells have only points and edges, and 1D cells have only points.)
:numref:`fig:CellTopology` shows the relationship between a cell's shape and these topological elements.
The arrangement of these points, edges, and faces is defined by the *shape* of the cell, which prescribes a specific ordering of each.
The basic cell shapes provided by |VTKm| are discussed in detail in Section~\ref{sec:CellShapeTagsIds} starting on page~\pageref{sec:CellShapeTagsIds}.
The basic cell shapes provided by |VTKm| are discussed in detail in :chapref:`working-with-cells:Working with Cells`.
.. todo:: Add cell shape reference above.

@ -10,6 +10,7 @@
set(examples
GuideExampleArrayHandle.cxx
GuideExampleCellShapes.cxx
GuideExampleColorTables.cxx
GuideExampleCoreDataTypes.cxx
GuideExampleEnvironmentModifierMacros.cxx
@ -28,6 +29,7 @@ set(examples
set(examples_device
GuideExampleCellEdgesFaces.cxx
GuideExampleCellLocator.cxx
GuideExampleCellOperations.cxx
GuideExampleDataSetCreation.cxx
GuideExampleErrorHandling.cxx
GuideExampleFilterDataSetWithField.cxx

@ -0,0 +1,153 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/exec/CellDerivative.h>
#include <vtkm/exec/CellInterpolate.h>
#include <vtkm/exec/ParametricCoordinates.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
////
//// BEGIN-EXAMPLE CellCenters
////
struct CellCenters : vtkm::worklet::WorkletVisitCellsWithPoints
{
using ControlSignature = void(CellSetIn,
FieldInPoint inputField,
FieldOutCell outputField);
using ExecutionSignature = void(CellShape, PointCount, _2, _3);
using InputDomain = _1;
template<typename CellShapeTag, typename FieldInVecType, typename FieldOutType>
VTKM_EXEC void operator()(CellShapeTag shape,
vtkm::IdComponent pointCount,
const FieldInVecType& inputField,
FieldOutType& outputField) const
{
vtkm::Vec3f center;
vtkm::ErrorCode status =
vtkm::exec::ParametricCoordinatesCenter(pointCount, shape, center);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
return;
}
vtkm::exec::CellInterpolate(inputField, center, shape, outputField);
}
};
////
//// END-EXAMPLE CellCenters
////
void TryCellCenters()
{
std::cout << "Trying CellCenters worklet." << std::endl;
vtkm::cont::DataSet dataSet =
vtkm::cont::testing::MakeTestDataSet().Make3DUniformDataSet0();
using ArrayType = vtkm::cont::ArrayHandle<vtkm::Float32>;
ArrayType centers;
vtkm::worklet::DispatcherMapTopology<CellCenters> dispatcher;
dispatcher.Invoke(dataSet.GetCellSet(),
dataSet.GetField("pointvar").GetData().AsArrayHandle<ArrayType>(),
centers);
vtkm::cont::printSummary_ArrayHandle(centers, std::cout);
std::cout << std::endl;
VTKM_TEST_ASSERT(centers.GetNumberOfValues() ==
dataSet.GetCellSet().GetNumberOfCells(),
"Bad number of cells.");
VTKM_TEST_ASSERT(test_equal(60.1875, centers.ReadPortal().Get(0)), "Bad first value.");
}
////
//// BEGIN-EXAMPLE CellDerivatives
////
struct CellDerivatives : vtkm::worklet::WorkletVisitCellsWithPoints
{
using ControlSignature = void(CellSetIn,
FieldInPoint inputField,
FieldInPoint pointCoordinates,
FieldOutCell outputField);
using ExecutionSignature = void(CellShape, PointCount, _2, _3, _4);
using InputDomain = _1;
template<typename CellShapeTag,
typename FieldInVecType,
typename PointCoordVecType,
typename FieldOutType>
VTKM_EXEC void operator()(CellShapeTag shape,
vtkm::IdComponent pointCount,
const FieldInVecType& inputField,
const PointCoordVecType& pointCoordinates,
FieldOutType& outputField) const
{
vtkm::Vec3f center;
vtkm::ErrorCode status =
vtkm::exec::ParametricCoordinatesCenter(pointCount, shape, center);
if (status != vtkm::ErrorCode::Success)
{
this->RaiseError(vtkm::ErrorString(status));
return;
}
vtkm::exec::CellDerivative(inputField, pointCoordinates, center, shape, outputField);
}
};
////
//// END-EXAMPLE CellDerivatives
////
void TryCellDerivatives()
{
std::cout << "Trying CellDerivatives worklet." << std::endl;
vtkm::cont::DataSet dataSet =
vtkm::cont::testing::MakeTestDataSet().Make3DUniformDataSet0();
using ArrayType = vtkm::cont::ArrayHandle<vtkm::Float32>;
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> derivatives;
vtkm::worklet::DispatcherMapTopology<CellDerivatives> dispatcher;
dispatcher.Invoke(dataSet.GetCellSet(),
dataSet.GetField("pointvar").GetData().AsArrayHandle<ArrayType>(),
dataSet.GetCoordinateSystem().GetData(),
derivatives);
vtkm::cont::printSummary_ArrayHandle(derivatives, std::cout);
std::cout << std::endl;
VTKM_TEST_ASSERT(derivatives.GetNumberOfValues() ==
dataSet.GetCellSet().GetNumberOfCells(),
"Bad number of cells.");
VTKM_TEST_ASSERT(
test_equal(vtkm::make_Vec(10.025, 30.075, 60.125), derivatives.ReadPortal().Get(0)),
"Bad first value.");
}
void Run()
{
TryCellCenters();
TryCellDerivatives();
}
} // anonymous namespace
int GuideExampleCellOperations(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
}

@ -0,0 +1,150 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/CellShape.h>
#include <vtkm/CellTraits.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/testing/Testing.h>
namespace CellShapesExamples
{
////
//// BEGIN-EXAMPLE CellShapeIdToTag
////
void CellFunction(vtkm::CellShapeTagTriangle)
{
std::cout << "In CellFunction for triangles." << std::endl;
}
void DoSomethingWithACell()
{
// Calls CellFunction overloaded with a vtkm::CellShapeTagTriangle.
CellFunction(vtkm::CellShapeIdToTag<vtkm::CELL_SHAPE_TRIANGLE>::Tag());
}
////
//// END-EXAMPLE CellShapeIdToTag
////
////
//// BEGIN-EXAMPLE GenericCellNormal
////
namespace detail
{
template<typename PointCoordinatesVector, typename WorkletType>
VTKM_EXEC_CONT typename PointCoordinatesVector::ComponentType CellNormalImpl(
const PointCoordinatesVector& pointCoordinates,
vtkm::CellTopologicalDimensionsTag<2>,
const WorkletType& worklet)
{
if (pointCoordinates.GetNumberOfComponents() >= 3)
{
return vtkm::TriangleNormal(
pointCoordinates[0], pointCoordinates[1], pointCoordinates[2]);
}
else
{
worklet.RaiseError("Degenerate polygon.");
return typename PointCoordinatesVector::ComponentType();
}
}
template<typename PointCoordinatesVector,
vtkm::IdComponent Dimensions,
typename WorkletType>
VTKM_EXEC_CONT typename PointCoordinatesVector::ComponentType CellNormalImpl(
const PointCoordinatesVector&,
vtkm::CellTopologicalDimensionsTag<Dimensions>,
const WorkletType& worklet)
{
worklet.RaiseError("Only polygons supported for cell normals.");
return typename PointCoordinatesVector::ComponentType();
}
} // namespace detail
template<typename CellShape, typename PointCoordinatesVector, typename WorkletType>
VTKM_EXEC_CONT typename PointCoordinatesVector::ComponentType CellNormal(
CellShape,
const PointCoordinatesVector& pointCoordinates,
const WorkletType& worklet)
{
return detail::CellNormalImpl(
pointCoordinates,
typename vtkm::CellTraits<CellShape>::TopologicalDimensionsTag(),
worklet);
}
template<typename PointCoordinatesVector, typename WorkletType>
VTKM_EXEC_CONT typename PointCoordinatesVector::ComponentType CellNormal(
vtkm::CellShapeTagGeneric shape,
const PointCoordinatesVector& pointCoordinates,
const WorkletType& worklet)
{
switch (shape.Id)
{
vtkmGenericCellShapeMacro(
return CellNormal(CellShapeTag(), pointCoordinates, worklet));
default:
worklet.RaiseError("Unknown cell type.");
return typename PointCoordinatesVector::ComponentType();
}
}
////
//// END-EXAMPLE GenericCellNormal
////
struct FakeWorklet : vtkm::exec::FunctorBase
{
};
void Run()
{
std::cout << "Basic identifier to tag." << std::endl;
DoSomethingWithACell();
std::cout << "Function with dynamic lookup of cell shape." << std::endl;
vtkm::Vec<vtkm::Vec3f, 3> pointCoordinates;
pointCoordinates[0] = vtkm::Vec3f(0.0f, 0.0f, 0.0f);
pointCoordinates[1] = vtkm::Vec3f(1.0f, 0.0f, 0.0f);
pointCoordinates[2] = vtkm::Vec3f(0.0f, 1.0f, 0.0f);
vtkm::Vec3f expectedNormal(0.0f, 0.0f, 1.0f);
char errorBuffer[256];
errorBuffer[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(errorBuffer, 256);
FakeWorklet worklet;
worklet.SetErrorMessageBuffer(errorMessage);
vtkm::Vec3f normal =
CellNormal(vtkm::CellShapeTagTriangle(), pointCoordinates, worklet);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), "Error finding normal.");
VTKM_TEST_ASSERT(test_equal(normal, expectedNormal), "Bad normal.");
normal = CellNormal(
vtkm::CellShapeTagGeneric(vtkm::CELL_SHAPE_TRIANGLE), pointCoordinates, worklet);
VTKM_TEST_ASSERT(!errorMessage.IsErrorRaised(), "Error finding normal.");
VTKM_TEST_ASSERT(test_equal(normal, expectedNormal), "Bad normal.");
CellNormal(vtkm::CellShapeTagLine(), pointCoordinates, worklet);
VTKM_TEST_ASSERT(errorMessage.IsErrorRaised(), "Expected error not raised.");
}
} // namespace CellShapesExamples
int GuideExampleCellShapes(int argc, char* argv[])
{
return vtkm::testing::Testing::Run(CellShapesExamples::Run, argc, argv);
}

@ -11,3 +11,4 @@ Advanced Development
extended-filter-impl.rst
worklet-error-handling.rst
math.rst
working-with-cells.rst

@ -0,0 +1,258 @@
==============================
Working with Cells
==============================
.. index:: cell
In the control environment, data is defined in mesh structures that comprise a set of finite cells.
(See :secref:`dataset: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, |VTKm| does not have a cell class that holds all the information pertaining to a cell of a particular type.
Instead, |VTKm| 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.
------------------------------
Cell Shape Tags and Ids
------------------------------
.. index::
double: tag; cell shape
double: tag; shape
Cell shapes can be specified with either a tag (defined with a struct with a name like ``CellShapeTag*``) or an enumerated identifier (defined with a constant number with a name like ``CELL_SHAPE_*``).
These shape tags and identifiers are defined in :file:`vtkm/CellShape.h` and declared in the ``vtkm`` namespace (because they can be used in either the control or the execution environment).
:numref:`fig:CellShapes` gives both the identifier and the tag names.
.. figure:: images/CellConnections.png
:width: 100%
:name: fig:CellShapes
Basic Cell Shapes.
.. doxygenstruct:: vtkm::CellShapeTagVertex
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_VERTEX
.. doxygenstruct:: vtkm::CellShapeTagLine
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_LINE
.. doxygenstruct:: vtkm::CellShapeTagPolyLine
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_POLY_LINE
.. doxygenstruct:: vtkm::CellShapeTagTriangle
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_TRIANGLE
.. doxygenstruct:: vtkm::CellShapeTagPolygon
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_POLYGON
.. doxygenstruct:: vtkm::CellShapeTagQuad
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_QUAD
.. doxygenstruct:: vtkm::CellShapeTagTetra
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_TETRA
.. doxygenstruct:: vtkm::CellShapeTagHexahedron
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_HEXAHEDRON
.. doxygenstruct:: vtkm::CellShapeTagWedge
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_WEDGE
.. doxygenstruct:: vtkm::CellShapeTagPyramid
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_PYRAMID
In addition to the basic cell shapes, there is a special "empty" cell with the identifier :enumerator:`vtkm::CELL_SHAPE_EMPTY` and tag :class:`vtkm::CellShapeTagEmpty`.
This type of cell has no points, edges, or faces and can be thought of as a placeholder for a null or void cell.
.. doxygenstruct:: vtkm::CellShapeTagEmpty
:members:
.. doxygenenumvalue:: vtkm::CELL_SHAPE_EMPTY
There is also a special cell shape "tag" named :class:`vtkm::CellShapeTagGeneric` that is used when the actual cell shape is not known at compile time.
:class:`vtkm::CellShapeTagGeneric` actually has a member variable named :var:`vtkm::CellShapeTagGeneric::Id` that stores the identifier for the cell shape.
There is no equivalent identifier for a generic cell; cell shape identifiers can be placed in a :type:`vtkm::IdComponent` at runtime.
.. doxygenstruct:: vtkm::CellShapeTagGeneric
:members:
When using cell shapes in templated classes and functions, you can use the :c:macro:`VTKM_IS_CELL_SHAPE_TAG` to ensure a type is a valid cell shape tag.
This macro takes one argument and will produce a compile error if the argument is not a cell shape tag type.
.. doxygendefine:: VTKM_IS_CELL_SHAPE_TAG
Converting Between Tags and Identifiers
========================================
Every cell shape tag has a member variable named ``Id`` that contains the identifier for the cell shape.
This provides a convenient mechanism for converting a cell shape tag to an identifier.
Most cell shape tags have their ``Id`` member as a compile-time constant, but :var:`vtkm::CellShapeTagGeneric::Id` is set at run time.
The :file:`vtkm/CellShape.h` header also declares a templated class named :class:`vtkm::CellShapeIdToTag` that converts a cell shape identifier to a cell shape tag.
:class:`vtkm::CellShapeIdToTag` has a single template argument that is the identifier.
Inside the class is a type named :var:`vtkm::CellShapeIdToTag::Tag` that is the type of the correct tag.
.. doxygenstruct:: vtkm::CellShapeIdToTag
:members:
.. load-example:: CellShapeIdToTag
:file: GuideExampleCellShapes.cxx
:caption: Using :class:`vtkm::CellShapeIdToTag`.
However, :class:`vtkm::CellShapeIdToTag` is only viable if the identifier can be resolved at compile time.
In the case where a cell identifier is stored in a variable or an array or the code is using a :class:`vtkm::CellShapeTagGeneric`, the correct cell shape is not known until run time.
In this case, the :c:macro:`vtkmGenericCellShapeMacro` macro can be used to check all possible conditions.
This macro is embedded in a switch statement where the condition is the cell shape identifier.
.. doxygendefine:: vtkmGenericCellShapeMacro
Often this method is used to implement the condition for a :class:`vtkm::CellShapeTagGeneric` in a function overloaded for cell types.
A demonstration of :c:macro:`vtkmGenericCellShapeMacro` is given in :numref:`ex:GenericCellNormal`.
Cell Traits
==============================
.. index:: cell traits
The :file:`vtkm/CellTraits.h` header file contains a traits class named :class:`vtkm::CellTraits` that provides information about a cell.
.. doxygenstruct:: vtkm::CellTraits
:members:
.. doxygenstruct:: vtkm::CellTopologicalDimensionsTag
.. doxygenstruct:: vtkm::CellTraitsTagSizeFixed
.. doxygenstruct:: vtkm::CellTraitsTagSizeVariable
.. load-example:: GenericCellNormal
:file: GuideExampleCellShapes.cxx
:caption: Using :class:`vtkm::CellTraits` to implement a polygon normal estimator.
-----------------------------------
Parametric and World Coordinates
-----------------------------------
.. index::
double: cell; parametric coordinates
double: cell; 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 :file:`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.
.. doxygenfunction:: vtkm::exec::ParametricCoordinatesCenter(vtkm::IdComponent, vtkm::CellShapeTagGeneric, vtkm::Vec<ParametricCoordType, 3>&)
.. doxygenfunction:: vtkm::exec::ParametricCoordinatesPoint(vtkm::IdComponent, vtkm::IdComponent, vtkm::CellShapeTagGeneric, vtkm::Vec<ParametricCoordType, 3>&)
.. doxygenfunction:: vtkm::exec::ParametricCoordinatesToWorldCoordinates(const WorldCoordVector&, const vtkm::Vec<PCoordType, 3>&, vtkm::CellShapeTagGeneric, typename WorldCoordVector::ComponentType&)
.. doxygenfunction:: vtkm::exec::WorldCoordinatesToParametricCoordinates(const WorldCoordVector&, const typename WorldCoordVector::ComponentType&, vtkm::CellShapeTagGeneric, typename WorldCoordVector::ComponentType&)
------------------------------
Interpolation
------------------------------
.. index::
double: cell; 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 :file:`vtkm/exec/CellInterpolate.h` header contains the function :func:`vtkm::exec::CellInterpolate` to do this interpolation.
.. doxygenfunction:: vtkm::exec::CellInterpolate(const FieldVecType&, const vtkm::Vec<ParametricCoordType, 3>&, vtkm::CellShapeTagGeneric, typename FieldVecType::ComponentType&)
.. load-example:: CellCenters
:file: GuideExampleCellOperations.cxx
:caption: Interpolating field values to a cell's center.
------------------------------
Derivatives
------------------------------
.. index::
double: cell; derivative
double: cell; gradient
Since interpolations provide a continuous field function over a cell, it is reasonable to consider the derivative of this function.
The :file:`vtkm/exec/CellDerivative.h` header contains the function :func:`vtkm::exec::CellDerivative` to compute derivatives.
The derivative is returned in a :class:`vtkm::Vec` of size 3 corresponding to the partial derivatives in the :math:`x`, :math:`y`, and :math:`z` directions.
This derivative is equivalent to the gradient of the field.
.. load-example:: CellDerivatives
:file: GuideExampleCellOperations.cxx
:caption: Computing the derivative of the field at cell centers.
------------------------------
Edges and Faces
------------------------------
.. index::
single: point
single: cell; point
double: cell; shape
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 |VTKm| are documented in :secref:`working-with-cells:Cell Shape Tags and Ids`.
It contains :numref:`fig:CellShapes`, which shows how the points for each shape form the structure of the cell.
.. index::
single: edge
single: cell; edge
single: shape; edge
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.
:numref:`fig:CellConstituents` demonstrates the relationship of these constituent elements for some example cell shapes.
.. figure:: images/CellConstituents.png
:width: 50%
:name: fig:CellConstituents
The constituent elements (points, edges, and faces) of cells..
The header file :file:`vtkm/exec/CellEdge.h` contains a collection of functions to help identify the edges of a cell.
.. doxygenfunction:: vtkm::exec::CellEdgeNumberOfEdges(vtkm::IdComponent, vtkm::CellShapeTagGeneric, vtkm::IdComponent&)
.. doxygenfunction:: vtkm::exec::CellEdgeLocalIndex(vtkm::IdComponent, vtkm::IdComponent, vtkm::IdComponent, vtkm::CellShapeTagGeneric, vtkm::IdComponent&)
.. doxygenfunction:: vtkm::exec::CellEdgeCanonicalId
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.
.. didyouknow::
:numref:`ex:CellEdge` demonstrates one of many techniques for creating cell sets in a worklet.
Chapter~\ref{chap:GeneratingCellSets} describes this and many more such techniques.
.. todo:: Fix chap:GeneratingCellSets reference above.
.. load-example:: CellEdge
:file: GuideExampleCellEdgesFaces.cxx
:caption: Using cell edge functions.
.. index::
single: face
single: cell; face
single: shape; face
The header file :file:`vtkm/exec/CellFace.h` contains a collection of functions to help identify the faces of a cell.
.. doxygenfunction:: vtkm::exec::CellFaceNumberOfFaces
.. doxygenfunction:: vtkm::exec::CellFaceNumberOfPoints
.. doxygenfunction:: vtkm::exec::CellFaceShape
.. doxygenfunction:: vtkm::exec::CellFaceLocalIndex
.. doxygenfunction:: vtkm::exec::CellFaceCanonicalId
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.
.. load-example:: CellFace
:file: GuideExampleCellEdgesFaces.cxx
:caption: Using cell face functions.

@ -131,11 +131,9 @@ A visit cells with points worklet supports the following tags in the parameters
:content-only:
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 \ref{chap:WorkingWithCells} for a description on how to work with the cell information provided to the worklet.
See :chapref:`working-with-cells: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.
.. todo:: Fix reference to chapter on working with cells above.
.. load-example:: UseWorkletVisitCellsWithPoints
:file: GuideExampleUseWorkletVisitCellsWithPoints.cxx
:caption: Implementation and use of a visit cells with points worklet.
@ -210,7 +208,7 @@ The following example does a simple averaging, but you can also implement other
This tag represents the cell set that defines the collection of elements the map will operate on.
A \sigtag{CellSetIn} argument expects a \textidentifier{CellSet} subclass or an \textidentifier{UnknownCellSet} in the associated parameter of the \textidentifier{Invoker}.
Each invocation of the worklet gets a cell shape tag.
(Cell shapes and the operations you can do with cells are discussed in Chapter \ref{chap:WorkingWithCells}.)
(Cell shapes and the operations you can do with cells are discussed in :chapref:`working-with-cells:Working with Cells`.)
There must be exactly one \sigtag{CellSetIn} argument, and the worklet's \inputdomain must be set to this argument.
@ -248,7 +246,7 @@ The following example does a simple averaging, but you can also implement other
\item[\sigtag{CellShape}]
This tag produces a shape tag corresponding to the shape of the visited element.
(Cell shapes and the operations you can do with cells are discussed in Chapter \ref{chap:WorkingWithCells}.)
(Cell shapes and the operations you can do with cells are discussed in :chapref:`working-with-cells:Working with Cells`.)
This is the same value that gets provided if you reference the \textsignature{CellSetIn} parameter.
If the ``visit'' element is cells, the \sigtag{CellShape} clearly will match the shape of each cell.

@ -33,20 +33,38 @@ namespace vtkm
enum CellShapeIdEnum
{
// Linear cells
/// Placeholder for empty or invalid cells.
CELL_SHAPE_EMPTY = lcl::ShapeId::EMPTY,
/// Vertex cells of a single point.
CELL_SHAPE_VERTEX = lcl::ShapeId::VERTEX,
//CELL_SHAPE_POLY_VERTEX = 2,
/// A line cell connecting two points.
CELL_SHAPE_LINE = lcl::ShapeId::LINE,
/// A sequence of line segments.
/// A polyline has 2 or more points, and the points are connected in order
/// by line segments forming a piecewise linear curve.
CELL_SHAPE_POLY_LINE = 4,
/// A triangle.
CELL_SHAPE_TRIANGLE = lcl::ShapeId::TRIANGLE,
//CELL_SHAPE_TRIANGLE_STRIP = 6,
/// A general polygon shape.
/// All polygons have points ordered in counterclockwise order around the front side.
/// Some operations may be invalid if the polygon is not a convex shape.
CELL_SHAPE_POLYGON = lcl::ShapeId::POLYGON,
//CELL_SHAPE_PIXEL = 8,
/// A four-sided polygon.
CELL_SHAPE_QUAD = lcl::ShapeId::QUAD,
/// A tetrahedron.
/// A tetrahedron is a 3D polyhedron with 4 points and 4 triangular faces.
CELL_SHAPE_TETRA = lcl::ShapeId::TETRA,
//CELL_SHAPE_VOXEL = 11,
/// A hexahedron.
CELL_SHAPE_HEXAHEDRON = lcl::ShapeId::HEXAHEDRON,
/// A wedge.
/// Wedges are simple prisms that can be formed by extruding a triangle.
/// They have 2 triangular faces and 3 quadrilateral faces.
CELL_SHAPE_WEDGE = lcl::ShapeId::WEDGE,
/// A pyramid with a quadrilateral base and four triangular faces.0
CELL_SHAPE_PYRAMID = lcl::ShapeId::PYRAMID,
NUMBER_OF_CELL_SHAPES
@ -157,6 +175,8 @@ struct CellShapeTagGeneric
{
}
/// An identifier that corresponds to one of the `CELL_SHAPE_*` identifiers.
/// This value is used to detect the proper shape at runtime.
vtkm::UInt8 Id;
};

@ -52,24 +52,24 @@ struct CellTraits
static const vtkm::IdComponent TOPOLOGICAL_DIMENSIONS = 3;
/// This tag is typedef'ed to
/// vtkm::CellTopologicalDimensionsTag<TOPOLOGICAL_DIMENSIONS>. This provides
/// `vtkm::CellTopologicalDimensionsTag<TOPOLOGICAL_DIMENSIONS>`. This provides
/// a convenient way to overload a function based on topological dimensions
/// (which is usually more efficient than conditionals).
///
using TopologicalDimensionsTag = vtkm::CellTopologicalDimensionsTag<TOPOLOGICAL_DIMENSIONS>;
/// \brief A tag specifying whether the number of points is fixed.
/// @brief A tag specifying whether the number of points is fixed.
///
/// If set to \c CellTraitsTagSizeFixed, then \c NUM_POINTS is set. If set to
/// \c CellTraitsTagSizeVariable, then the number of points is not known at
/// If set to `vtkm::CellTraitsTagSizeFixed`, then `NUM_POINTS` is set. If set to
/// `vtkm::CellTraitsTagSizeVariable`, then the number of points is not known at
/// compile time.
///
using IsSizeFixed = vtkm::CellTraitsTagSizeFixed;
/// \brief Number of points in the cell.
/// @brief Number of points in the cell.
///
/// This is only defined for cell shapes of a fixed number of points (i.e.
/// \c IsSizedFixed is set to \c CellTraitsTagSizeFixed.
/// This is only defined for cell shapes of a fixed number of points (i.e.,
/// `IsSizedFixed` is set to `vtkm::CellTraitsTagSizeFixed`).
///
static constexpr vtkm::IdComponent NUM_POINTS = 3;
};

@ -181,6 +181,20 @@ VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& field,
/// coordinate (i.e. the gradient) at that point. The derivative is not always
/// constant in some "linear" cells.
///
/// @param[in] pointFieldValues A list of field values for each point in the cell. This
/// usually comes from a `FieldInPoint` argument in a
/// `vtkm::worklet::WorkletVisitCellsWithPoints`.
/// @param[in] worldCoordinateValues A list of world coordinates for each point in the cell. This
/// usually comes from a `FieldInPoint` argument in a
/// `vtkm::worklet::WorkletVisitCellsWithPoints` where the coordinate system is passed
/// into that argument.
/// @param[in] parametricCoords The parametric coordinates where you want to find the derivative.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result Value to store the derivative/gradient. Because the derivative is taken
/// partially in the x, y, and z directions, the result is a `vtkm::Vec` of size 3 with the
/// component type the same as the field. If the field is itself a vector, you get a `Vec`
/// of `Vec`s.
template <typename FieldVecType, typename WorldCoordType, typename ParametricCoordType>
VTKM_EXEC vtkm::ErrorCode CellDerivative(const FieldVecType& pointFieldValues,
const WorldCoordType& worldCoordinateValues,

@ -154,6 +154,12 @@ static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent
return vtkm::ErrorCode::Success;
}
/// @brief Get the number of edges in a cell.
///
/// @param[in] numPoints The number of points in the cell.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] numEdges A reference to return the number of edges.
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeNumberOfEdges(vtkm::IdComponent numPoints,
vtkm::CellShapeTagGeneric shape,
vtkm::IdComponent& numEdges)
@ -237,6 +243,18 @@ static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent num
return vtkm::ErrorCode::Success;
}
/// 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.
///
/// @param[in] numPoints The number of points in the cell.
/// @param[in] pointIndex The index of the edge within the cell.
/// @param[in] edgeIndex The index of the point on the edge (either 0 or 1).
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result Reference to put the index of the point relative to the cell
/// (between 0 and the number of points in the cell).
static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex,
@ -273,7 +291,7 @@ static inline VTKM_EXEC vtkm::ErrorCode CellEdgeLocalIndex(vtkm::IdComponent num
}
}
/// \brief Returns a canonical identifier for a cell edge
/// @brief 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

@ -138,6 +138,11 @@ public:
} // namespace detail
/// @brief Get the number of faces in a cell.
///
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result A reference to return the number of faces.
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfFaces(CellShapeTag shape,
vtkm::IdComponent& result)
@ -148,6 +153,15 @@ static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfFaces(CellShapeTag shape
return vtkm::ErrorCode::Success;
}
/// @brief 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.
///
/// @param[in] faceIndex The index of the face within the cell.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result A reference to return the number of points in the selected face.
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfPoints(vtkm::IdComponent faceIndex,
CellShapeTag shape,
@ -171,6 +185,18 @@ static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfPoints(vtkm::IdComponent
return vtkm::ErrorCode::Success;
}
/// @brief 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 to `CELL_SHAPE_TRIANGLE` or `CELL_SHAPE_QUAD`.
///
/// @param[in] faceIndex The index of the face within the cell.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result A reference to return the number of points in the selected face.
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceShape(vtkm::IdComponent faceIndex,
CellShapeTag shape,
@ -200,6 +226,17 @@ static inline VTKM_EXEC vtkm::ErrorCode CellFaceShape(vtkm::IdComponent faceInde
return vtkm::ErrorCode::Success;
}
/// 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.
///
/// @param[in] pointIndex The index of the edge within the cell.
/// @param[in] faceIndex The index of the point on the face.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result 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>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceLocalIndex(vtkm::IdComponent pointIndex,
vtkm::IdComponent faceIndex,
@ -221,10 +258,10 @@ static inline VTKM_EXEC vtkm::ErrorCode CellFaceLocalIndex(vtkm::IdComponent poi
return vtkm::ErrorCode::Success;
}
/// \brief Returns a canonical identifier for a cell face
/// @brief 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
/// `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

@ -158,6 +158,14 @@ VTKM_EXEC vtkm::ErrorCode CellInterpolate(const vtkm::VecAxisAlignedPointCoordin
/// Given the point field values for each node and the parametric coordinates
/// of a point within the cell, interpolates the field to that point.
///
/// @param[in] pointFieldValues A list of field values for each point in the cell. This
/// usually comes from a `FieldInPoint` argument in a
/// `vtkm::worklet::WorkletVisitCellsWithPoints`.
/// @param[in] parametricCoords The parametric coordinates where you want to get the interpolated
/// field value for.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result Value to store the interpolated field.
template <typename FieldVecType, typename ParametricCoordType>
VTKM_EXEC vtkm::ErrorCode CellInterpolate(const FieldVecType& pointFieldValues,
const vtkm::Vec<ParametricCoordType, 3>& parametricCoords,

@ -118,6 +118,10 @@ static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
/// Returns the parametric center of the given cell shape with the given number
/// of points.
///
/// @param[in] numPoints The number of points in the cell.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] pcoords `vtkm::Vec` to store the parametric center.
template <typename ParametricCoordType>
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesCenter(
vtkm::IdComponent numPoints,
@ -241,6 +245,12 @@ static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
/// Returns the parametric coordinate of a cell point of the given shape with
/// the given number of points.
///
/// @param[in] numPoints The number of points in the cell.
/// @param[in] pointIndex 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.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] pcoords `vtkm::Vec` to store the parametric center.
template <typename ParametricCoordType>
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesPoint(
vtkm::IdComponent numPoints,
@ -354,8 +364,17 @@ static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
}
//-----------------------------------------------------------------------------
/// Returns the world coordinate corresponding to the given parametric coordinate of a cell.
/// Converts parametric coordinates (coordinates relative to the cell) to world coordinates
/// (coordinates in the global system).
///
/// @param[in] pointWCoords A list of world coordinates for each point in the cell. This
/// usually comes from a `FieldInPoint` argument in a
/// `vtkm::worklet::WorkletVisitCellsWithPoints` where the coordinate system is passed
/// into that argument.
/// @param[in] pcoords The parametric coordinates where you want to get world coordinates for.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result `vtkm::Vec` to store the interpolated world coordinates.
template <typename WorldCoordVector, typename PCoordType>
static inline VTKM_EXEC vtkm::ErrorCode ParametricCoordinatesToWorldCoordinates(
const WorldCoordVector& pointWCoords,
@ -541,8 +560,18 @@ static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
}
//-----------------------------------------------------------------------------
/// Returns the world paramteric corresponding to the given world coordinate for a cell.
/// 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).
///
/// @param[in] pointWCoords A list of world coordinates for each point in the cell. This
/// usually comes from a `FieldInPoint` argument in a
/// `vtkm::worklet::WorkletVisitCellsWithPoints` where the coordinate system is passed
/// into that argument.
/// @param[in] wcoords The world coordinates where you want to get parametric coordinates for.
/// @param[in] shape A tag of type `CellShapeTag*` to identify the shape of the cell.
/// This method is overloaded for different shape types.
/// @param[out] result `vtkm::Vec` to store the associated parametric coordinates.
template <typename WorldCoordVector>
static inline VTKM_EXEC vtkm::ErrorCode WorldCoordinatesToParametricCoordinates(
const WorldCoordVector& pointWCoords,