Resurrect function to get face indices

Due to recent changes to remove static arrays that are not supported on
some devices, the function to return all the local point indices on a
face was removed. That left no way to get the structure of cell faces
short of pulling an internal data structure.

This change resurrects a function to get point indices for a face. The
interface for this method has necessarily changed, so I also changed the
corresponding function for getting edge indices.
This commit is contained in:
Kenneth Moreland 2018-03-22 22:37:33 -06:00
parent b6b0005996
commit 1fe7869211
5 changed files with 86 additions and 59 deletions

@ -41,7 +41,7 @@ public:
static constexpr vtkm::Int32 MAX_NUM_EDGES = 12; static constexpr vtkm::Int32 MAX_NUM_EDGES = 12;
public: public:
VTKM_EXEC vtkm::Int32 NumEdges(vtkm::Int32 i) const VTKM_EXEC vtkm::Int32 NumEdges(vtkm::Int32 cellShapeId) const
{ {
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 numEdges[vtkm::NUMBER_OF_CELL_SHAPES] = { VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 numEdges[vtkm::NUMBER_OF_CELL_SHAPES] = {
// NumEdges // NumEdges
@ -61,10 +61,12 @@ public:
9, // 13: CELL_SHAPE_WEDGE 9, // 13: CELL_SHAPE_WEDGE
8 // 14: CELL_SHAPE_PYRAMID 8 // 14: CELL_SHAPE_PYRAMID
}; };
return numEdges[i]; return numEdges[cellShapeId];
} }
VTKM_EXEC vtkm::Int32 PointsInEdge(vtkm::Int32 i, vtkm::Int32 j, vtkm::Int32 k) const VTKM_EXEC vtkm::Int32 PointsInEdge(vtkm::Int32 cellShapeId,
vtkm::Int32 edgeIndex,
vtkm::Int32 localPointIndex) const
{ {
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32
pointsInEdge[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_EDGES][2] = { pointsInEdge[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_EDGES][2] = {
@ -117,7 +119,7 @@ public:
// clang-format on // clang-format on
}; };
return pointsInEdge[i][j][k]; return pointsInEdge[cellShapeId][edgeIndex][localPointIndex];
} }
}; };
@ -157,57 +159,63 @@ static inline VTKM_EXEC vtkm::IdComponent CellEdgeNumberOfEdges(
} }
template <typename CellShapeTag> template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 2> CellEdgeLocalIndices( static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex, vtkm::IdComponent edgeIndex,
CellShapeTag shape, CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet) const vtkm::exec::FunctorBase& worklet)
{ {
VTKM_ASSUME(pointIndex >= 0);
VTKM_ASSUME(pointIndex < 2);
VTKM_ASSUME(edgeIndex >= 0); VTKM_ASSUME(edgeIndex >= 0);
VTKM_ASSUME(edgeIndex < detail::CellEdgeTables::MAX_NUM_EDGES); VTKM_ASSUME(edgeIndex < detail::CellEdgeTables::MAX_NUM_EDGES);
if (edgeIndex >= vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, worklet)) if (edgeIndex >= vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, worklet))
{ {
worklet.RaiseError("Invalid edge number."); worklet.RaiseError("Invalid edge number.");
return vtkm::Vec<vtkm::IdComponent, 2>(0); return 0;
} }
detail::CellEdgeTables table; detail::CellEdgeTables table;
return vtkm::make_Vec(table.PointsInEdge(CellShapeTag::Id, edgeIndex, 0), return table.PointsInEdge(CellShapeTag::Id, edgeIndex, pointIndex);
table.PointsInEdge(CellShapeTag::Id, edgeIndex, 1));
} }
static inline VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 2> CellEdgeLocalIndices( static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex, vtkm::IdComponent edgeIndex,
vtkm::CellShapeTagPolygon, vtkm::CellShapeTagPolygon,
const vtkm::exec::FunctorBase&) const vtkm::exec::FunctorBase&)
{ {
VTKM_ASSUME(numPoints >= 3); VTKM_ASSUME(numPoints >= 3);
VTKM_ASSUME(pointIndex >= 0);
VTKM_ASSUME(pointIndex < 2);
VTKM_ASSUME(edgeIndex >= 0); VTKM_ASSUME(edgeIndex >= 0);
VTKM_ASSUME(edgeIndex < numPoints); VTKM_ASSUME(edgeIndex < numPoints);
if (edgeIndex < numPoints - 1) if (edgeIndex + pointIndex < numPoints)
{ {
return vtkm::Vec<vtkm::IdComponent, 2>(edgeIndex, edgeIndex + 1); return edgeIndex + pointIndex;
} }
else else
{ {
return vtkm::Vec<vtkm::IdComponent, 2>(edgeIndex, 0); return 0;
} }
} }
static inline VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 2> CellEdgeLocalIndices( static inline VTKM_EXEC vtkm::IdComponent CellEdgeLocalIndex(vtkm::IdComponent numPoints,
vtkm::IdComponent numPoints, vtkm::IdComponent pointIndex,
vtkm::IdComponent edgeIndex, vtkm::IdComponent edgeIndex,
vtkm::CellShapeTagGeneric shape, vtkm::CellShapeTagGeneric shape,
const vtkm::exec::FunctorBase& worklet) const vtkm::exec::FunctorBase& worklet)
{ {
VTKM_ASSUME(pointIndex >= 0);
VTKM_ASSUME(pointIndex < 2);
VTKM_ASSUME(edgeIndex >= 0); VTKM_ASSUME(edgeIndex >= 0);
VTKM_ASSUME(edgeIndex < detail::CellEdgeTables::MAX_NUM_EDGES); VTKM_ASSUME(edgeIndex < detail::CellEdgeTables::MAX_NUM_EDGES);
if (shape.Id == vtkm::CELL_SHAPE_POLYGON) if (shape.Id == vtkm::CELL_SHAPE_POLYGON)
{ {
return CellEdgeLocalIndices(numPoints, edgeIndex, vtkm::CellShapeTagPolygon(), worklet); return CellEdgeLocalIndex(
numPoints, pointIndex, edgeIndex, vtkm::CellShapeTagPolygon(), worklet);
} }
else else
{ {
@ -215,11 +223,10 @@ static inline VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 2> CellEdgeLocalIndices(
if (edgeIndex >= table.NumEdges(shape.Id)) if (edgeIndex >= table.NumEdges(shape.Id))
{ {
worklet.RaiseError("Invalid edge number."); worklet.RaiseError("Invalid edge number.");
return vtkm::Vec<vtkm::IdComponent, 2>(0); return 0;
} }
return vtkm::make_Vec(table.PointsInEdge(shape.Id, edgeIndex, 0), return table.PointsInEdge(shape.Id, edgeIndex, pointIndex);
table.PointsInEdge(shape.Id, edgeIndex, 1));
} }
} }
@ -237,11 +244,10 @@ static inline VTKM_EXEC vtkm::Id2 CellEdgeCanonicalId(
const GlobalPointIndicesVecType& globalPointIndicesVec, const GlobalPointIndicesVecType& globalPointIndicesVec,
const vtkm::exec::FunctorBase& worklet) const vtkm::exec::FunctorBase& worklet)
{ {
vtkm::Vec<vtkm::IdComponent, 2> localPointIndices = vtkm::Id pointIndex0 =
vtkm::exec::CellEdgeLocalIndices(numPoints, edgeIndex, shape, worklet); globalPointIndicesVec[vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, worklet)];
vtkm::Id pointIndex1 =
vtkm::Id pointIndex0 = globalPointIndicesVec[localPointIndices[0]]; globalPointIndicesVec[vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, worklet)];
vtkm::Id pointIndex1 = globalPointIndicesVec[localPointIndices[1]];
if (pointIndex0 < pointIndex1) if (pointIndex0 < pointIndex1)
{ {
return vtkm::Id2(pointIndex0, pointIndex1); return vtkm::Id2(pointIndex0, pointIndex1);

@ -40,7 +40,7 @@ public:
static constexpr vtkm::Int32 MAX_FACE_SIZE = 4; static constexpr vtkm::Int32 MAX_FACE_SIZE = 4;
static constexpr vtkm::Int32 MAX_NUM_FACES = 6; static constexpr vtkm::Int32 MAX_NUM_FACES = 6;
VTKM_EXEC vtkm::Int32 NumFaces(vtkm::Int32 i) const VTKM_EXEC vtkm::Int32 NumFaces(vtkm::Int32 cellShapeId) const
{ {
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 numFaces[vtkm::NUMBER_OF_CELL_SHAPES] = { VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 numFaces[vtkm::NUMBER_OF_CELL_SHAPES] = {
// NumFaces // NumFaces
@ -60,10 +60,10 @@ public:
5, // 13: CELL_SHAPE_WEDGE 5, // 13: CELL_SHAPE_WEDGE
5 // 14: CELL_SHAPE_PYRAMID 5 // 14: CELL_SHAPE_PYRAMID
}; };
return numFaces[i]; return numFaces[cellShapeId];
} }
VTKM_EXEC vtkm::Int32 NumPointsInFace(vtkm::Int32 i, vtkm::Int32 j) const VTKM_EXEC vtkm::Int32 NumPointsInFace(vtkm::Int32 cellShapeId, vtkm::Int32 faceIndex) const
{ {
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32
numPointsInFace[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_FACES] = { numPointsInFace[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_FACES] = {
@ -84,10 +84,12 @@ public:
{ 3, 3, 4, 4, 4, -1 }, // 13: CELL_SHAPE_WEDGE { 3, 3, 4, 4, 4, -1 }, // 13: CELL_SHAPE_WEDGE
{ 4, 3, 3, 3, 3, -1 } // 14: CELL_SHAPE_PYRAMID { 4, 3, 3, 3, 3, -1 } // 14: CELL_SHAPE_PYRAMID
}; };
return numPointsInFace[i][j]; return numPointsInFace[cellShapeId][faceIndex];
} }
VTKM_EXEC vtkm::Int32 PointsInFace(vtkm::Int32 i, vtkm::Int32 j, vtkm::Int32 k) const VTKM_EXEC vtkm::Int32 PointsInFace(vtkm::Int32 cellShapeId,
vtkm::Int32 faceIndex,
vtkm::Int32 localPointIndex) const
{ {
// clang-format off // clang-format off
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 pointsInFace[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_FACES] VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 pointsInFace[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_FACES]
@ -141,7 +143,7 @@ public:
{ 2, 3, 4, -1 }, { 3, 0, 4, -1 },{ -1, -1, -1, -1 } } { 2, 3, 4, -1 }, { 3, 0, 4, -1 },{ -1, -1, -1, -1 } }
// clang-format on // clang-format on
}; };
return pointsInFace[i][j][k]; return pointsInFace[cellShapeId][faceIndex][localPointIndex];
} }
}; };
@ -191,6 +193,24 @@ static inline VTKM_EXEC vtkm::UInt8 CellFaceShape(vtkm::IdComponent faceIndex,
} }
} }
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::IdComponent CellFaceLocalIndex(vtkm::IdComponent pointIndex,
vtkm::IdComponent faceIndex,
CellShapeTag shape,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::IdComponent numPointsInFace = vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, worklet);
if (numPointsInFace < 1)
{
// An invalid face. We should already have gotten an error from
// CellFaceNumberOfPoints.
return -1;
}
detail::CellFaceTables table;
return table.PointsInFace(shape.Id, faceIndex, pointIndex);
}
/// \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 /// Given information about a cell face and the global point indices for that cell, returns a

@ -71,7 +71,8 @@ struct TestCellFacesFunctor
std::set<EdgeType> edgeSet; std::set<EdgeType> edgeSet;
for (vtkm::IdComponent edgeIndex = 0; edgeIndex < numEdges; edgeIndex++) for (vtkm::IdComponent edgeIndex = 0; edgeIndex < numEdges; edgeIndex++)
{ {
EdgeType edge = vtkm::exec::CellEdgeLocalIndices(numPoints, edgeIndex, shape, workletProxy); EdgeType edge(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, workletProxy),
vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, workletProxy));
VTKM_TEST_ASSERT(edge[0] >= 0, "Bad index in edge."); VTKM_TEST_ASSERT(edge[0] >= 0, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[0] < numPoints, "Bad index in edge."); VTKM_TEST_ASSERT(edge[0] < numPoints, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[1] >= 0, "Bad index in edge."); VTKM_TEST_ASSERT(edge[1] >= 0, "Bad index in edge.");
@ -94,7 +95,6 @@ struct TestCellFacesFunctor
std::set<EdgeType> edgesFoundInFaces; std::set<EdgeType> edgesFoundInFaces;
for (vtkm::IdComponent faceIndex = 0; faceIndex < numFaces; faceIndex++) for (vtkm::IdComponent faceIndex = 0; faceIndex < numFaces; faceIndex++)
{ {
vtkm::exec::detail::CellFaceTables table;
const vtkm::IdComponent numPointsInFace = const vtkm::IdComponent numPointsInFace =
vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, workletProxy); vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, workletProxy);
@ -102,20 +102,22 @@ struct TestCellFacesFunctor
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPointsInFace; pointIndex++) for (vtkm::IdComponent pointIndex = 0; pointIndex < numPointsInFace; pointIndex++)
{ {
VTKM_TEST_ASSERT(table.PointsInFace(shape.Id, faceIndex, pointIndex) >= 0, vtkm::IdComponent localFaceIndex =
"Invalid point index for face."); vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, workletProxy);
VTKM_TEST_ASSERT(table.PointsInFace(shape.Id, faceIndex, pointIndex) <= numPoints, VTKM_TEST_ASSERT(localFaceIndex >= 0, "Invalid point index for face.");
"Invalid point index for face."); VTKM_TEST_ASSERT(localFaceIndex < numPoints, "Invalid point index for face.");
EdgeType edge; EdgeType edge;
if (pointIndex < numPointsInFace - 1) if (pointIndex < numPointsInFace - 1)
{ {
edge = EdgeType(table.PointsInFace(shape.Id, faceIndex, pointIndex), edge = EdgeType(
table.PointsInFace(shape.Id, faceIndex, pointIndex + 1)); vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, workletProxy),
vtkm::exec::CellFaceLocalIndex(pointIndex + 1, faceIndex, shape, workletProxy));
} }
else else
{ {
edge = EdgeType(table.PointsInFace(shape.Id, faceIndex, 0), edge =
table.PointsInFace(shape.Id, faceIndex, pointIndex)); EdgeType(vtkm::exec::CellFaceLocalIndex(0, faceIndex, shape, workletProxy),
vtkm::exec::CellFaceLocalIndex(pointIndex, faceIndex, shape, workletProxy));
} }
MakeEdgeCanonical(edge); MakeEdgeCanonical(edge);
VTKM_TEST_ASSERT(edgeSet.find(edge) != edgeSet.end(), "Edge in face not in cell's edges"); VTKM_TEST_ASSERT(edgeSet.find(edge) != edgeSet.end(), "Edge in face not in cell's edges");
@ -158,7 +160,8 @@ struct TestCellFacesFunctor
std::set<EdgeType> edgeSet; std::set<EdgeType> edgeSet;
for (vtkm::IdComponent edgeIndex = 0; edgeIndex < numEdges; edgeIndex++) for (vtkm::IdComponent edgeIndex = 0; edgeIndex < numEdges; edgeIndex++)
{ {
EdgeType edge = vtkm::exec::CellEdgeLocalIndices(numPoints, edgeIndex, shape, workletProxy); EdgeType edge(vtkm::exec::CellEdgeLocalIndex(numPoints, 0, edgeIndex, shape, workletProxy),
vtkm::exec::CellEdgeLocalIndex(numPoints, 1, edgeIndex, shape, workletProxy));
VTKM_TEST_ASSERT(edge[0] >= 0, "Bad index in edge."); VTKM_TEST_ASSERT(edge[0] >= 0, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[0] < numPoints, "Bad index in edge."); VTKM_TEST_ASSERT(edge[0] < numPoints, "Bad index in edge.");
VTKM_TEST_ASSERT(edge[1] >= 0, "Bad index in edge."); VTKM_TEST_ASSERT(edge[1] >= 0, "Bad index in edge.");

@ -199,10 +199,10 @@ struct EdgesExtracter : public vtkm::worklet::WorkletMapPointToCell
} }
else else
{ {
vtkm::Vec<vtkm::IdComponent, 2> localEdgeIndices = vtkm::exec::CellEdgeLocalIndices( p1 = pointIndices[vtkm::exec::CellEdgeLocalIndex(
pointIndices.GetNumberOfComponents(), visitIndex, shape, *this); pointIndices.GetNumberOfComponents(), 0, visitIndex, shape, *this)];
p1 = pointIndices[localEdgeIndices[0]]; p2 = pointIndices[vtkm::exec::CellEdgeLocalIndex(
p2 = pointIndices[localEdgeIndices[1]]; pointIndices.GetNumberOfComponents(), 1, visitIndex, shape, *this)];
} }
// These indices need to be arranged in a definite order, as they will later be sorted to // These indices need to be arranged in a definite order, as they will later be sorted to
// detect duplicates // detect duplicates

@ -315,11 +315,10 @@ struct ExternalFaces
shapeOut = vtkm::CELL_SHAPE_QUAD; shapeOut = vtkm::CELL_SHAPE_QUAD;
numFacePointsOut = 4; numFacePointsOut = 4;
vtkm::exec::detail::CellFaceTables table;
for (vtkm::IdComponent facePointIndex = 0; facePointIndex < numFacePoints; facePointIndex++) for (vtkm::IdComponent facePointIndex = 0; facePointIndex < numFacePoints; facePointIndex++)
{ {
faceConnectivity[facePointIndex] = faceConnectivity[facePointIndex] =
inCellIndices[table.PointsInFace(shape.Id, faceIndex, facePointIndex)]; inCellIndices[vtkm::exec::CellFaceLocalIndex(facePointIndex, faceIndex, shape, *this)];
} }
} }
@ -619,11 +618,10 @@ public:
typename CellSetType::IndicesType inCellIndices = cellSet.GetIndices(originCells[myIndex]); typename CellSetType::IndicesType inCellIndices = cellSet.GetIndices(originCells[myIndex]);
vtkm::exec::detail::CellFaceTables table;
for (vtkm::IdComponent facePointIndex = 0; facePointIndex < numFacePoints; facePointIndex++) for (vtkm::IdComponent facePointIndex = 0; facePointIndex < numFacePoints; facePointIndex++)
{ {
connectivityOut[facePointIndex] = connectivityOut[facePointIndex] =
inCellIndices[table.PointsInFace(shapeIn.Id, myFace, facePointIndex)]; inCellIndices[vtkm::exec::CellFaceLocalIndex(facePointIndex, myFace, shapeIn, *this)];
} }
} }