vtk-m/vtkm/exec/CellFace.h
Kenneth Moreland 3e1339f9a7 Remove deprecated features from VTK-m
With the major revision 2.0 of VTK-m, many items previously marked as
deprecated were removed. If updating to a new version of VTK-m, it is
recommended to first update to VTK-m 1.9, which will include the deprecated
features but provide warnings (with the right compiler) that will point to
the replacement code. Once the deprecations have been fixed, updating to
2.0 should be smoother.
2022-11-17 07:12:31 -06:00

313 lines
11 KiB
C++

//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_exec_CellFace_h
#define vtk_m_exec_CellFace_h
#include <vtkm/CellShape.h>
#include <vtkm/ErrorCode.h>
#include <vtkm/Types.h>
#include <vtkm/exec/FunctorBase.h>
namespace vtkm
{
namespace exec
{
namespace detail
{
class CellFaceTables
{
public:
static constexpr vtkm::Int32 MAX_FACE_SIZE = 4;
static constexpr vtkm::Int32 MAX_NUM_FACES = 6;
VTKM_EXEC vtkm::Int32 NumFaces(vtkm::Int32 cellShapeId) const
{
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 numFaces[vtkm::NUMBER_OF_CELL_SHAPES] = {
// NumFaces
0, // 0: CELL_SHAPE_EMPTY
0, // 1: CELL_SHAPE_VERTEX
0, // 2: Unused
0, // 3: CELL_SHAPE_LINE
0, // 4: CELL_SHAPE_POLY_LINE
0, // 5: CELL_SHAPE_TRIANGLE
0, // 6: Unused
0, // 7: CELL_SHAPE_POLYGON
0, // 8: Unused
0, // 9: CELL_SHAPE_QUAD
4, // 10: CELL_SHAPE_TETRA
0, // 11: Unused
6, // 12: CELL_SHAPE_HEXAHEDRON
5, // 13: CELL_SHAPE_WEDGE
5 // 14: CELL_SHAPE_PYRAMID
};
return numFaces[cellShapeId];
}
VTKM_EXEC vtkm::Int32 NumPointsInFace(vtkm::Int32 cellShapeId, vtkm::Int32 faceIndex) const
{
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32
numPointsInFace[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_FACES] = {
// NumPointsInFace
{ -1, -1, -1, -1, -1, -1 }, // 0: CELL_SHAPE_EMPTY
{ -1, -1, -1, -1, -1, -1 }, // 1: CELL_SHAPE_VERTEX
{ -1, -1, -1, -1, -1, -1 }, // 2: Unused
{ -1, -1, -1, -1, -1, -1 }, // 3: CELL_SHAPE_LINE
{ -1, -1, -1, -1, -1, -1 }, // 4: CELL_SHAPE_POLY_LINE
{ -1, -1, -1, -1, -1, -1 }, // 5: CELL_SHAPE_TRIANGLE
{ -1, -1, -1, -1, -1, -1 }, // 6: Unused
{ -1, -1, -1, -1, -1, -1 }, // 7: CELL_SHAPE_POLYGON
{ -1, -1, -1, -1, -1, -1 }, // 8: Unused
{ -1, -1, -1, -1, -1, -1 }, // 9: CELL_SHAPE_QUAD
{ 3, 3, 3, 3, -1, -1 }, // 10: CELL_SHAPE_TETRA
{ -1, -1, -1, -1, -1, -1 }, // 11: Unused
{ 4, 4, 4, 4, 4, 4 }, // 12: CELL_SHAPE_HEXAHEDRON
{ 3, 3, 4, 4, 4, -1 }, // 13: CELL_SHAPE_WEDGE
{ 4, 3, 3, 3, 3, -1 } // 14: CELL_SHAPE_PYRAMID
};
return numPointsInFace[cellShapeId][faceIndex];
}
VTKM_EXEC vtkm::Int32 PointsInFace(vtkm::Int32 cellShapeId,
vtkm::Int32 faceIndex,
vtkm::Int32 localPointIndex) const
{
// clang-format off
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 pointsInFace[vtkm::NUMBER_OF_CELL_SHAPES][MAX_NUM_FACES]
[MAX_FACE_SIZE] =
{
// PointsInFace
// 0: CELL_SHAPE_EMPTY
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 1: CELL_SHAPE_VERTEX
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 2: Unused
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 3: CELL_SHAPE_LINE
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 4: CELL_SHAPE_POLY_LINE
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 5: CELL_SHAPE_TRIANGLE
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 6: Unused
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 7: CELL_SHAPE_POLYGON
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 8: Unused
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 9: CELL_SHAPE_QUAD
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 10: CELL_SHAPE_TETRA
{ { 0, 1, 3, -1 }, { 1, 2, 3, -1 }, { 2, 0, 3, -1 },
{ 0, 2, 1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 11: Unused
{ { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 },
{ -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
// 12: CELL_SHAPE_HEXAHEDRON
{ { 0, 4, 7, 3 }, { 1, 2, 6, 5 }, { 0, 1, 5, 4 },
{ 3, 7, 6, 2 }, { 0, 3, 2, 1 }, { 4, 5, 6, 7 } },
// 13: CELL_SHAPE_WEDGE
{ { 0, 1, 2, -1 }, { 3, 5, 4, -1 }, { 0, 3, 4, 1 },
{ 1, 4, 5, 2 }, { 2, 5, 3, 0 }, { -1, -1, -1, -1 } },
// 14: CELL_SHAPE_PYRAMID
{ { 0, 3, 2, 1 }, { 0, 1, 4, -1 }, { 1, 2, 4, -1 },
{ 2, 3, 4, -1 }, { 3, 0, 4, -1 },{ -1, -1, -1, -1 } }
// clang-format on
};
return pointsInFace[cellShapeId][faceIndex][localPointIndex];
}
};
} // namespace detail
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfFaces(CellShapeTag shape,
vtkm::IdComponent& result)
{
(void)shape; //C4100 false positive workaround
detail::CellFaceTables table;
result = table.NumFaces(shape.Id);
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceNumberOfPoints(vtkm::IdComponent faceIndex,
CellShapeTag shape,
vtkm::IdComponent& result)
{
if ((faceIndex < 0) || (faceIndex >= detail::CellFaceTables::MAX_NUM_FACES))
{
result = -1;
return vtkm::ErrorCode::InvalidFaceId;
}
vtkm::IdComponent numFaces;
VTKM_RETURN_ON_ERROR(vtkm::exec::CellFaceNumberOfFaces(shape, numFaces));
if (faceIndex >= numFaces)
{
result = -1;
return vtkm::ErrorCode::InvalidFaceId;
}
detail::CellFaceTables table;
result = table.NumPointsInFace(shape.Id, faceIndex);
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceShape(vtkm::IdComponent faceIndex,
CellShapeTag shape,
vtkm::UInt8& result)
{
if ((faceIndex < 0) || (faceIndex >= detail::CellFaceTables::MAX_NUM_FACES))
{
result = vtkm::CELL_SHAPE_EMPTY;
return vtkm::ErrorCode::InvalidFaceId;
}
vtkm::IdComponent numFacePoints;
VTKM_RETURN_ON_ERROR(CellFaceNumberOfPoints(faceIndex, shape, numFacePoints));
switch (numFacePoints)
{
case 3:
result = vtkm::CELL_SHAPE_TRIANGLE;
break;
case 4:
result = vtkm::CELL_SHAPE_QUAD;
break;
default:
result = vtkm::CELL_SHAPE_POLYGON;
break;
}
return vtkm::ErrorCode::Success;
}
template <typename CellShapeTag>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceLocalIndex(vtkm::IdComponent pointIndex,
vtkm::IdComponent faceIndex,
CellShapeTag shape,
vtkm::IdComponent& result)
{
vtkm::IdComponent numPointsInFace;
result = -1;
VTKM_RETURN_ON_ERROR(vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, numPointsInFace));
if (numPointsInFace < 1)
{
// An invalid face. We should already have gotten an error from
// CellFaceNumberOfPoints.
return vtkm::ErrorCode::InvalidFaceId;
}
detail::CellFaceTables table;
result = table.PointsInFace(shape.Id, faceIndex, pointIndex);
return vtkm::ErrorCode::Success;
}
/// \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
/// 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.
///
template <typename CellShapeTag, typename GlobalPointIndicesVecType>
static inline VTKM_EXEC vtkm::ErrorCode CellFaceCanonicalId(
vtkm::IdComponent faceIndex,
CellShapeTag shape,
const GlobalPointIndicesVecType& globalPointIndicesVec,
vtkm::Id3& result)
{
vtkm::IdComponent numPointsInFace;
result = { -1 };
VTKM_RETURN_ON_ERROR(vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, numPointsInFace));
if (numPointsInFace == 0)
{
// An invalid face. We should already have gotten an error from
// CellFaceNumberOfPoints.
return vtkm::ErrorCode::InvalidFaceId;
}
detail::CellFaceTables table;
//Sort the first 3 face points/nodes in ascending order
result = vtkm::Id3(globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 0)],
globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 1)],
globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, 2)]);
vtkm::Id temp;
if (result[0] > result[2])
{
temp = result[0];
result[0] = result[2];
result[2] = temp;
}
if (result[0] > result[1])
{
temp = result[0];
result[0] = result[1];
result[1] = temp;
}
if (result[1] > result[2])
{
temp = result[1];
result[1] = result[2];
result[2] = temp;
}
// Check the rest of the points to see if they are in the lowest 3
for (vtkm::IdComponent pointIndex = 3; pointIndex < numPointsInFace; pointIndex++)
{
vtkm::Id nextPoint = globalPointIndicesVec[table.PointsInFace(shape.Id, faceIndex, pointIndex)];
if (nextPoint < result[2])
{
if (nextPoint < result[1])
{
result[2] = result[1];
if (nextPoint < result[0])
{
result[1] = result[0];
result[0] = nextPoint;
}
else // nextPoint > P0, nextPoint < P1
{
result[1] = nextPoint;
}
}
else // nextPoint > P1, nextPoint < P2
{
result[2] = nextPoint;
}
}
else // nextPoint > P2
{
// Do nothing. nextPoint not in top 3.
}
}
return vtkm::ErrorCode::Success;
}
}
} // namespace vtkm::exec
#endif //vtk_m_exec_CellFace_h