diff --git a/vtkm/exec/CellFace.h b/vtkm/exec/CellFace.h index bb515094a..e44b66662 100644 --- a/vtkm/exec/CellFace.h +++ b/vtkm/exec/CellFace.h @@ -245,6 +245,87 @@ static inline VTKM_EXEC vtkm::VecCConst 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 +static inline VTKM_EXEC vtkm::Id3 CellFaceCononicalId( + vtkm::IdComponent faceIndex, + CellShapeTag shape, + const GlobalPointIndicesVecType& globalPointIndicesVec, + const vtkm::exec::FunctorBase& worklet) +{ + vtkm::VecCConst 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 diff --git a/vtkm/exec/testing/UnitTestCellEdgeFace.cxx b/vtkm/exec/testing/UnitTestCellEdgeFace.cxx index 44103ae3e..b0e3432ee 100644 --- a/vtkm/exec/testing/UnitTestCellEdgeFace.cxx +++ b/vtkm/exec/testing/UnitTestCellEdgeFace.cxx @@ -29,6 +29,7 @@ #include #include +#include namespace { @@ -57,6 +58,13 @@ struct TestCellFacesFunctor vtkm::exec::FunctorBase workletProxy; workletProxy.SetErrorMessageBuffer(errorMessage); + std::vector pointIndexProxyBuffer(static_cast(numPoints)); + for (std::size_t index = 0; index < pointIndexProxyBuffer.size(); ++index) + { + pointIndexProxyBuffer[index] = static_cast(1000000 - index); + } + vtkm::VecCConst 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"); diff --git a/vtkm/worklet/ExternalFaces.h b/vtkm/worklet/ExternalFaces.h index 5fc44334a..51c1d9cea 100644 --- a/vtkm/worklet/ExternalFaces.h +++ b/vtkm/worklet/ExternalFaces.h @@ -425,72 +425,7 @@ struct ExternalFaces vtkm::Id inputIndex, vtkm::IdComponent visitIndex) const { - vtkm::VecCConst 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; diff --git a/vtkm/worklet/testing/UnitTestExternalFaces.cxx b/vtkm/worklet/testing/UnitTestExternalFaces.cxx index ee9c1dbc3..917a8eed2 100644 --- a/vtkm/worklet/testing/UnitTestExternalFaces.cxx +++ b/vtkm/worklet/testing/UnitTestExternalFaces.cxx @@ -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>(), inDataSet.GetCoordinateSystem(), outCellSet, MyDeviceAdapter()); + } else + { vtkm::worklet::ExternalFaces().Run( inCellSet.Cast>(), outCellSet, MyDeviceAdapter()); + } vtkm::cont::DataSet outDataSet; for (vtkm::IdComponent i = 0; i < inDataSet.GetNumberOfCoordinateSystems(); ++i)