Add method for getting a cononical face id

The cononical face id is stored in a vtkm::Id3 (independent of the
actual number of points in the face).
This commit is contained in:
Kenneth Moreland 2017-08-17 15:48:47 -06:00
parent eafacc6dc5
commit 8e72dc738a
4 changed files with 100 additions and 66 deletions

@ -245,6 +245,87 @@ static inline VTKM_EXEC vtkm::VecCConst<vtkm::IdComponent> CellFaceLocalIndices(
return vtkm::make_VecC(detail::PointsInFace[shape.Id][faceIndex], numPointsInFace);
}
/// \brief Returns a cononical identifer 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 try if the mesh is conforming. That is, any two
/// neighboring cells that share a face have the same points on that face. This
/// preculdes to faces sharing more than a single point or single edge.
///
template <typename CellShapeTag, typename GlobalPointIndicesVecType>
static inline VTKM_EXEC vtkm::Id3 CellFaceCononicalId(
vtkm::IdComponent faceIndex,
CellShapeTag shape,
const GlobalPointIndicesVecType& globalPointIndicesVec,
const vtkm::exec::FunctorBase& worklet)
{
vtkm::VecCConst<vtkm::IdComponent> localPointIndices =
vtkm::exec::CellFaceLocalIndices(faceIndex, shape, worklet);
VTKM_ASSERT(localPointIndices.GetNumberOfComponents() >= 3);
//Sort the first 3 face points/nodes in ascending order
vtkm::Id3 sorted(globalPointIndicesVec[localPointIndices[0]],
globalPointIndicesVec[localPointIndices[1]],
globalPointIndicesVec[localPointIndices[2]]);
vtkm::Id temp;
if (sorted[0] > sorted[2])
{
temp = sorted[0];
sorted[0] = sorted[2];
sorted[2] = temp;
}
if (sorted[0] > sorted[1])
{
temp = sorted[0];
sorted[0] = sorted[1];
sorted[1] = temp;
}
if (sorted[1] > sorted[2])
{
temp = sorted[1];
sorted[1] = sorted[2];
sorted[2] = temp;
}
// Check the rest of the points to see if they are in the lowest 3
vtkm::IdComponent numPointsInFace = localPointIndices.GetNumberOfComponents();
for (vtkm::IdComponent pointIndex = 3; pointIndex < numPointsInFace; pointIndex++)
{
vtkm::Id nextPoint = globalPointIndicesVec[localPointIndices[pointIndex]];
if (nextPoint < sorted[2])
{
if (nextPoint < sorted[1])
{
sorted[2] = sorted[1];
if (nextPoint < sorted[0])
{
sorted[1] = sorted[0];
sorted[0] = nextPoint;
}
else // nextPoint > P0, nextPoint < P1
{
sorted[1] = nextPoint;
}
}
else // nextPoint > P1, nextPoint < P2
{
sorted[2] = nextPoint;
}
}
else // nextPoint > P2
{
// Do nothing. nextPoint not in top 3.
}
}
return sorted;
}
}
} // namespace vtkm::exec

@ -29,6 +29,7 @@
#include <vtkm/testing/Testing.h>
#include <set>
#include <vector>
namespace
{
@ -57,6 +58,13 @@ struct TestCellFacesFunctor
vtkm::exec::FunctorBase workletProxy;
workletProxy.SetErrorMessageBuffer(errorMessage);
std::vector<vtkm::Id> pointIndexProxyBuffer(static_cast<std::size_t>(numPoints));
for (std::size_t index = 0; index < pointIndexProxyBuffer.size(); ++index)
{
pointIndexProxyBuffer[index] = static_cast<vtkm::Id>(1000000 - index);
}
vtkm::VecCConst<vtkm::Id> pointIndexProxy(&pointIndexProxyBuffer.at(0), numPoints);
vtkm::IdComponent numEdges = vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, workletProxy);
VTKM_TEST_ASSERT(numEdges > 0, "No edges?");
@ -103,6 +111,12 @@ struct TestCellFacesFunctor
VTKM_TEST_ASSERT(edgeSet.find(edge) != edgeSet.end(), "Edge in face not in cell's edges");
edgesFoundInFaces.insert(edge);
}
vtkm::Id3 cononicalFaceId =
vtkm::exec::CellFaceCononicalId(faceIndex, shape, pointIndexProxy, workletProxy);
VTKM_TEST_ASSERT(cononicalFaceId[0] > 0, "Not using global ids?");
VTKM_TEST_ASSERT(cononicalFaceId[0] < cononicalFaceId[1], "Bad order.");
VTKM_TEST_ASSERT(cononicalFaceId[1] < cononicalFaceId[2], "Bad order.");
}
VTKM_TEST_ASSERT(edgesFoundInFaces.size() == edgeSet.size(),
"Faces did not contain all edges in cell");

@ -425,72 +425,7 @@ struct ExternalFaces
vtkm::Id inputIndex,
vtkm::IdComponent visitIndex) const
{
vtkm::VecCConst<vtkm::IdComponent> localFaceIndices =
vtkm::exec::CellFaceLocalIndices(visitIndex, shape, *this);
VTKM_ASSERT(localFaceIndices.GetNumberOfComponents() >= 3);
//Assign cell points/nodes to this face
vtkm::Id faceP1 = cellNodeIds[localFaceIndices[0]];
vtkm::Id faceP2 = cellNodeIds[localFaceIndices[1]];
vtkm::Id faceP3 = cellNodeIds[localFaceIndices[2]];
//Sort the first 3 face points/nodes in ascending order
vtkm::Id sorted[3] = { faceP1, faceP2, faceP3 };
vtkm::Id temp;
if (sorted[0] > sorted[2])
{
temp = sorted[0];
sorted[0] = sorted[2];
sorted[2] = temp;
}
if (sorted[0] > sorted[1])
{
temp = sorted[0];
sorted[0] = sorted[1];
sorted[1] = temp;
}
if (sorted[1] > sorted[2])
{
temp = sorted[1];
sorted[1] = sorted[2];
sorted[2] = temp;
}
// Check the rest of the points to see if they are in the lowest 3
vtkm::IdComponent numPointsInFace = localFaceIndices.GetNumberOfComponents();
for (vtkm::IdComponent pointIndex = 3; pointIndex < numPointsInFace; pointIndex++)
{
vtkm::Id nextPoint = cellNodeIds[localFaceIndices[pointIndex]];
if (nextPoint < sorted[2])
{
if (nextPoint < sorted[1])
{
sorted[2] = sorted[1];
if (nextPoint < sorted[0])
{
sorted[1] = sorted[0];
sorted[0] = nextPoint;
}
else // nextPoint > P0, nextPoint < P1
{
sorted[1] = nextPoint;
}
}
else // nextPoint > P1, nextPoint < P2
{
sorted[2] = nextPoint;
}
}
else // nextPoint > P2
{
// Do nothing. nextPoint not in top 3.
}
}
faceHash[0] = sorted[0];
faceHash[1] = sorted[1];
faceHash[2] = sorted[2];
faceHash = vtkm::exec::CellFaceCononicalId(visitIndex, shape, cellNodeIds, *this);
cellIndex = inputIndex;
faceIndex = visitIndex;

@ -50,13 +50,17 @@ vtkm::cont::DataSet RunExternalFaces(vtkm::cont::DataSet& inDataSet)
//Run the External Faces worklet
if (inCellSet.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
vtkm::worklet::ExternalFaces().Run(inCellSet.Cast<vtkm::cont::CellSetStructured<3>>(),
inDataSet.GetCoordinateSystem(),
outCellSet,
MyDeviceAdapter());
}
else
{
vtkm::worklet::ExternalFaces().Run(
inCellSet.Cast<vtkm::cont::CellSetExplicit<>>(), outCellSet, MyDeviceAdapter());
}
vtkm::cont::DataSet outDataSet;
for (vtkm::IdComponent i = 0; i < inDataSet.GetNumberOfCoordinateSystems(); ++i)