mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Merge topic 'cononical-face-edge-ids'
1d5a4d47 Update ExternalFaces worklet to use hashes fc7b90ac Add hash function b1e6c1e3 Add method for getting a cononical edge id 8e72dc73 Add method for getting a cononical face id Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !900
This commit is contained in:
commit
8312fe54ab
@ -34,6 +34,7 @@ set(headers
|
||||
Bounds.h
|
||||
CellShape.h
|
||||
CellTraits.h
|
||||
Hash.h
|
||||
ListTag.h
|
||||
Math.h
|
||||
Matrix.h
|
||||
|
127
vtkm/Hash.h
Normal file
127
vtkm/Hash.h
Normal file
@ -0,0 +1,127 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2017 Sandia Corporation.
|
||||
// Copyright 2017 UT-Battelle, LLC.
|
||||
// Copyright 2017 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_Hash_h
|
||||
#define vtk_m_Hash_h
|
||||
|
||||
#include <vtkm/TypeTraits.h>
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
using HashType = vtkm::UInt32;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
static const vtkm::HashType FNV1A_OFFSET = 2166136261;
|
||||
static const vtkm::HashType FNV1A_PRIME = 16777619;
|
||||
|
||||
/// \brief Performs an FNV-1a hash on 32-bit integers returning a 32-bit hash
|
||||
///
|
||||
template <typename InVecType>
|
||||
VTKM_EXEC_CONT inline vtkm::HashType HashFNV1a32(const InVecType& inVec)
|
||||
{
|
||||
using Traits = vtkm::VecTraits<InVecType>;
|
||||
const vtkm::IdComponent numComponents = Traits::GetNumberOfComponents(inVec);
|
||||
|
||||
vtkm::HashType hash = FNV1A_OFFSET;
|
||||
for (vtkm::IdComponent index = 0; index < numComponents; index++)
|
||||
{
|
||||
vtkm::HashType dataBits = static_cast<vtkm::HashType>(Traits::GetComponent(inVec, index));
|
||||
hash = (hash * FNV1A_PRIME) ^ dataBits;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// \brief Performs an FNV-1a hash on 64-bit integers returning a 32-bit hash
|
||||
///
|
||||
template <typename InVecType>
|
||||
VTKM_EXEC_CONT inline vtkm::HashType HashFNV1a64(const InVecType& inVec)
|
||||
{
|
||||
using Traits = vtkm::VecTraits<InVecType>;
|
||||
const vtkm::IdComponent numComponents = Traits::GetNumberOfComponents(inVec);
|
||||
|
||||
vtkm::HashType hash = FNV1A_OFFSET;
|
||||
for (vtkm::IdComponent index = 0; index < numComponents; index++)
|
||||
{
|
||||
vtkm::UInt64 allDataBits = static_cast<vtkm::UInt64>(Traits::GetComponent(inVec, index));
|
||||
vtkm::HashType upperDataBits =
|
||||
static_cast<vtkm::HashType>((allDataBits & 0xFFFFFFFF00000000L) >> 32);
|
||||
hash = (hash * FNV1A_PRIME) ^ upperDataBits;
|
||||
vtkm::HashType lowerDataBits = static_cast<vtkm::HashType>(allDataBits & 0x00000000FFFFFFFFL);
|
||||
hash = (hash * FNV1A_PRIME) ^ lowerDataBits;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
// If you get a compile error saying that there is no implementation of the class HashChooser,
|
||||
// then you have tried to make a hash from an invalid type (like a float).
|
||||
template <typename NumericTag, vtkm::Id DataSize>
|
||||
struct HashChooser;
|
||||
|
||||
template <>
|
||||
struct HashChooser<vtkm::TypeTraitsIntegerTag, 4>
|
||||
{
|
||||
template <typename InVecType>
|
||||
VTKM_EXEC_CONT static vtkm::HashType Hash(const InVecType& inVec)
|
||||
{
|
||||
return vtkm::detail::HashFNV1a32(inVec);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct HashChooser<vtkm::TypeTraitsIntegerTag, 8>
|
||||
{
|
||||
template <typename InVecType>
|
||||
VTKM_EXEC_CONT static vtkm::HashType Hash(const InVecType& inVec)
|
||||
{
|
||||
return vtkm::detail::HashFNV1a64(inVec);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Returns a 32-bit hash on a group of integer-type values.
|
||||
///
|
||||
/// The input to the hash is expected to be a vtkm::Vec or a Vec-like object. The values can be
|
||||
/// either 32-bit integers or 64-bit integers (signed or unsigned). Regardless, the resulting hash
|
||||
/// is an unsigned 32-bit integer.
|
||||
///
|
||||
/// The hash is designed to minimize the probability of collisions, but collisions are always
|
||||
/// possible. Thus, when using these hashes there should be a contingency for dealing with
|
||||
/// collisions.
|
||||
///
|
||||
template <typename InVecType>
|
||||
VTKM_EXEC_CONT inline vtkm::HashType Hash(const InVecType& inVec)
|
||||
{
|
||||
using VecTraits = vtkm::VecTraits<InVecType>;
|
||||
using ComponentType = typename VecTraits::ComponentType;
|
||||
using ComponentTraits = vtkm::TypeTraits<ComponentType>;
|
||||
using Chooser = detail::HashChooser<typename ComponentTraits::NumericTag, sizeof(ComponentType)>;
|
||||
return Chooser::Hash(inVec);
|
||||
}
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
#endif //vtk_m_Hash_h
|
@ -354,6 +354,35 @@ static inline VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 2> CellEdgeLocalIndices(
|
||||
detail::PointsInEdge[shape.Id][edgeIndex][1]);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Returns a cononical 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
|
||||
/// the same if and only if the edges contain the same points.
|
||||
///
|
||||
template <typename CellShapeTag, typename GlobalPointIndicesVecType>
|
||||
static inline VTKM_EXEC vtkm::Id2 CellEdgeCononicalId(
|
||||
vtkm::IdComponent numPoints,
|
||||
vtkm::IdComponent edgeIndex,
|
||||
CellShapeTag shape,
|
||||
const GlobalPointIndicesVecType& globalPointIndicesVec,
|
||||
const vtkm::exec::FunctorBase& worklet)
|
||||
{
|
||||
vtkm::Vec<vtkm::IdComponent, 2> localPointIndices =
|
||||
vtkm::exec::CellEdgeLocalIndices(numPoints, edgeIndex, shape, worklet);
|
||||
|
||||
vtkm::Id pointIndex0 = globalPointIndicesVec[localPointIndices[0]];
|
||||
vtkm::Id pointIndex1 = globalPointIndicesVec[localPointIndices[1]];
|
||||
if (pointIndex0 < pointIndex1)
|
||||
{
|
||||
return vtkm::Id2(pointIndex0, pointIndex1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return vtkm::Id2(pointIndex1, pointIndex0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::exec
|
||||
|
||||
|
@ -245,6 +245,86 @@ 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 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::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?");
|
||||
|
||||
@ -73,6 +81,11 @@ struct TestCellFacesFunctor
|
||||
VTKM_TEST_ASSERT(edge[0] < edge[1], "Internal test error: MakeEdgeCononical failed");
|
||||
VTKM_TEST_ASSERT(edgeSet.find(edge) == edgeSet.end(), "Found duplicate edge");
|
||||
edgeSet.insert(edge);
|
||||
|
||||
vtkm::Id2 cononicalEdgeId =
|
||||
vtkm::exec::CellEdgeCononicalId(numPoints, edgeIndex, shape, pointIndexProxy, workletProxy);
|
||||
VTKM_TEST_ASSERT(cononicalEdgeId[0] > 0, "Not using global ids?");
|
||||
VTKM_TEST_ASSERT(cononicalEdgeId[0] < cononicalEdgeId[1], "Bad order.");
|
||||
}
|
||||
|
||||
vtkm::IdComponent numFaces = vtkm::exec::CellFaceNumberOfFaces(shape, workletProxy);
|
||||
@ -103,6 +116,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");
|
||||
@ -121,6 +140,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 == numPoints, "Polygons should have same number of points and edges");
|
||||
|
||||
@ -137,6 +163,11 @@ struct TestCellFacesFunctor
|
||||
VTKM_TEST_ASSERT(edge[0] < edge[1], "Internal test error: MakeEdgeCononical failed");
|
||||
VTKM_TEST_ASSERT(edgeSet.find(edge) == edgeSet.end(), "Found duplicate edge");
|
||||
edgeSet.insert(edge);
|
||||
|
||||
vtkm::Id2 cononicalEdgeId =
|
||||
vtkm::exec::CellEdgeCononicalId(numPoints, edgeIndex, shape, pointIndexProxy, workletProxy);
|
||||
VTKM_TEST_ASSERT(cononicalEdgeId[0] > 0, "Not using global ids?");
|
||||
VTKM_TEST_ASSERT(cononicalEdgeId[0] < cononicalEdgeId[1], "Bad order.");
|
||||
}
|
||||
|
||||
vtkm::IdComponent numFaces = vtkm::exec::CellFaceNumberOfFaces(shape, workletProxy);
|
||||
|
@ -33,6 +33,7 @@ set(unit_tests
|
||||
UnitTestBounds.cxx
|
||||
UnitTestCellShape.cxx
|
||||
UnitTestExceptions.cxx
|
||||
UnitTestHash.cxx
|
||||
UnitTestListTag.cxx
|
||||
UnitTestMath.cxx
|
||||
UnitTestMatrix.cxx
|
||||
|
87
vtkm/testing/UnitTestHash.cxx
Normal file
87
vtkm/testing/UnitTestHash.cxx
Normal file
@ -0,0 +1,87 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2017 Sandia Corporation.
|
||||
// Copyright 2017 UT-Battelle, LLC.
|
||||
// Copyright 2017 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/Hash.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
VTKM_CONT
|
||||
static void CheckUnique(std::vector<vtkm::HashType> hashes)
|
||||
{
|
||||
std::sort(hashes.begin(), hashes.end());
|
||||
|
||||
for (std::size_t index = 1; index < hashes.size(); ++index)
|
||||
{
|
||||
VTKM_TEST_ASSERT(hashes[index - 1] != hashes[index], "Found duplicate hashes.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VecType>
|
||||
VTKM_CONT static void DoHashTest(VecType&&)
|
||||
{
|
||||
std::cout << "Test hash for " << vtkm::testing::TypeName<VecType>::Name() << std::endl;
|
||||
|
||||
const vtkm::Id NUM_HASHES = 100;
|
||||
std::cout << " Make sure the first " << NUM_HASHES << " values are unique." << std::endl;
|
||||
// There is a small probability that two values of these 100 could be the same. If this test
|
||||
// fails we could just be unlucky (and have to use a different set of 100 hashes), but it is
|
||||
// suspicious and you should double check the hashes.
|
||||
std::vector<vtkm::HashType> hashes;
|
||||
hashes.reserve(NUM_HASHES);
|
||||
for (vtkm::Id index = 0; index < NUM_HASHES; ++index)
|
||||
{
|
||||
hashes.push_back(vtkm::Hash(TestValue(index, VecType())));
|
||||
}
|
||||
CheckUnique(hashes);
|
||||
|
||||
std::cout << " Try close values that should have different hashes." << std::endl;
|
||||
hashes.clear();
|
||||
VecType vec = TestValue(5, VecType());
|
||||
hashes.push_back(vtkm::Hash(vec));
|
||||
vec[0] = vec[0] + 1;
|
||||
hashes.push_back(vtkm::Hash(vec));
|
||||
vec[1] = vec[1] - 1;
|
||||
hashes.push_back(vtkm::Hash(vec));
|
||||
CheckUnique(hashes);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
static void TestHash()
|
||||
{
|
||||
DoHashTest(vtkm::Id2());
|
||||
DoHashTest(vtkm::Id3());
|
||||
DoHashTest(vtkm::Vec<vtkm::Id, 10>());
|
||||
DoHashTest(vtkm::Vec<vtkm::IdComponent, 2>());
|
||||
DoHashTest(vtkm::Vec<vtkm::IdComponent, 3>());
|
||||
DoHashTest(vtkm::Vec<vtkm::IdComponent, 10>());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestHash(int, char* [])
|
||||
{
|
||||
return vtkm::testing::Testing::Run(TestHash);
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
#define vtk_m_worklet_ExternalFaces_h
|
||||
|
||||
#include <vtkm/CellShape.h>
|
||||
#include <vtkm/Hash.h>
|
||||
#include <vtkm/Math.h>
|
||||
|
||||
#include <vtkm/exec/CellFace.h>
|
||||
@ -46,8 +47,6 @@
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
#include <vtkm/worklet/WorkletReduceByKey.h>
|
||||
|
||||
// #define __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
@ -55,50 +54,6 @@ namespace worklet
|
||||
|
||||
struct ExternalFaces
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> CellIdMap;
|
||||
bool PassPolyData;
|
||||
|
||||
//Unary predicate operator
|
||||
//Returns True if the argument is equal to 1; False otherwise.
|
||||
struct IsUnity
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x) const
|
||||
{
|
||||
return x == T(1);
|
||||
}
|
||||
};
|
||||
|
||||
//Returns True if the first vector argument is less than the second
|
||||
//vector argument; otherwise, False
|
||||
struct Id3LessThan
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const vtkm::Vec<T, 3>& a, const vtkm::Vec<T, 3>& b) const
|
||||
{
|
||||
bool isLessThan = false;
|
||||
if (a[0] < b[0])
|
||||
{
|
||||
isLessThan = true;
|
||||
}
|
||||
else if (a[0] == b[0])
|
||||
{
|
||||
if (a[1] < b[1])
|
||||
{
|
||||
isLessThan = true;
|
||||
}
|
||||
else if (a[1] == b[1])
|
||||
{
|
||||
if (a[2] < b[2])
|
||||
{
|
||||
isLessThan = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isLessThan;
|
||||
}
|
||||
};
|
||||
|
||||
//Worklet that returns the number of external faces for each structured cell
|
||||
class NumExternalFacesPerStructuredCell : public vtkm::worklet::WorkletMapPointToCell
|
||||
{
|
||||
@ -387,7 +342,7 @@ struct ExternalFaces
|
||||
}
|
||||
};
|
||||
|
||||
//Worklet that identifies a cell face by 3 cononical points
|
||||
//Worklet that identifies a cell face by a hash value. Not necessarily completely unique.
|
||||
class FaceHash : public vtkm::worklet::WorkletMapPointToCell
|
||||
{
|
||||
public:
|
||||
@ -417,7 +372,7 @@ struct ExternalFaces
|
||||
}
|
||||
|
||||
template <typename CellShapeTag, typename CellNodeVecType>
|
||||
VTKM_EXEC void operator()(vtkm::Id3& faceHash,
|
||||
VTKM_EXEC void operator()(vtkm::HashType& faceHash,
|
||||
vtkm::Id& cellIndex,
|
||||
vtkm::IdComponent& faceIndex,
|
||||
CellShapeTag shape,
|
||||
@ -425,72 +380,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::Hash(vtkm::exec::CellFaceCononicalId(visitIndex, shape, cellNodeIds, *this));
|
||||
|
||||
cellIndex = inputIndex;
|
||||
faceIndex = visitIndex;
|
||||
@ -500,31 +390,127 @@ struct ExternalFaces
|
||||
ScatterType Scatter;
|
||||
};
|
||||
|
||||
// Worklet that identifies the number of cells written out per face, which
|
||||
// is 1 for faces that belong to only one cell (external face) or 0 for
|
||||
// faces that belong to more than one cell (internal face).
|
||||
// Worklet that identifies the number of cells written out per face.
|
||||
// Because there can be collisions in the face ids, this instance might
|
||||
// represent multiple faces, which have to be checked. The resulting
|
||||
// number is the total number of external faces.
|
||||
class FaceCounts : public vtkm::worklet::WorkletReduceByKey
|
||||
{
|
||||
public:
|
||||
typedef void ControlSignature(KeysIn keys, ReducedValuesOut<> numOutputCells);
|
||||
typedef _2 ExecutionSignature(ValueCount);
|
||||
typedef void ControlSignature(KeysIn keys,
|
||||
WholeCellSetIn<> inputCells,
|
||||
ValuesIn<> originCells,
|
||||
ValuesIn<> originFaces,
|
||||
ReducedValuesOut<> numOutputCells);
|
||||
typedef _5 ExecutionSignature(_2, _3, _4);
|
||||
using InputDomain = _1;
|
||||
|
||||
VTKM_EXEC
|
||||
vtkm::IdComponent operator()(vtkm::IdComponent numCellsOnFace) const
|
||||
template <typename CellSetType, typename OriginCellsType, typename OriginFacesType>
|
||||
VTKM_EXEC vtkm::IdComponent operator()(const CellSetType& cellSet,
|
||||
const OriginCellsType& originCells,
|
||||
const OriginFacesType& originFaces) const
|
||||
{
|
||||
if (numCellsOnFace == 1)
|
||||
vtkm::IdComponent numCellsOnHash = originCells.GetNumberOfComponents();
|
||||
VTKM_ASSERT(originFaces.GetNumberOfComponents() == numCellsOnHash);
|
||||
|
||||
// Start by assuming all faces are unique, then remove one for each
|
||||
// face we find a duplicate for.
|
||||
vtkm::IdComponent numExternalFaces = numCellsOnHash;
|
||||
|
||||
for (vtkm::IdComponent myIndex = 0;
|
||||
myIndex < numCellsOnHash - 1; // Don't need to check last face
|
||||
myIndex++)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
vtkm::Id3 myFace =
|
||||
vtkm::exec::CellFaceCononicalId(originFaces[myIndex],
|
||||
cellSet.GetCellShape(originCells[myIndex]),
|
||||
cellSet.GetIndices(originCells[myIndex]),
|
||||
*this);
|
||||
for (vtkm::IdComponent otherIndex = myIndex + 1; otherIndex < numCellsOnHash; otherIndex++)
|
||||
{
|
||||
vtkm::Id3 otherFace =
|
||||
vtkm::exec::CellFaceCononicalId(originFaces[otherIndex],
|
||||
cellSet.GetCellShape(originCells[otherIndex]),
|
||||
cellSet.GetIndices(originCells[otherIndex]),
|
||||
*this);
|
||||
if (myFace == otherFace)
|
||||
{
|
||||
// Faces are the same. Must be internal. Remove 2, one for each face. We don't have to
|
||||
// worry about otherFace matching anything else because a proper topology will have at
|
||||
// most 2 cells sharing a face, so there should be no more matches.
|
||||
numExternalFaces -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numExternalFaces;
|
||||
}
|
||||
};
|
||||
|
||||
// Worklet that returns the number of points for each outputted face
|
||||
private:
|
||||
// Resolves duplicate hashes by finding a specified unique face for a given hash.
|
||||
// Given a cell set (from a WholeCellSetIn) and the cell/face id pairs for each face
|
||||
// associated with a given hash, returns the index of the cell/face provided of the
|
||||
// visitIndex-th unique face. Basically, this method searches through all the cell/face
|
||||
// pairs looking for unique sets and returns the one associated with visitIndex.
|
||||
template <typename CellSetType, typename OriginCellsType, typename OriginFacesType>
|
||||
VTKM_EXEC static vtkm::IdComponent FindUniqueFace(const CellSetType& cellSet,
|
||||
const OriginCellsType& originCells,
|
||||
const OriginFacesType& originFaces,
|
||||
vtkm::IdComponent visitIndex,
|
||||
const vtkm::exec::FunctorBase* self)
|
||||
{
|
||||
vtkm::IdComponent numCellsOnHash = originCells.GetNumberOfComponents();
|
||||
VTKM_ASSERT(originFaces.GetNumberOfComponents() == numCellsOnHash);
|
||||
|
||||
// Find the visitIndex-th unique face.
|
||||
vtkm::IdComponent numFound = 0;
|
||||
vtkm::IdComponent myIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
VTKM_ASSERT(myIndex < numCellsOnHash);
|
||||
vtkm::Id3 myFace = vtkm::exec::CellFaceCononicalId(originFaces[myIndex],
|
||||
cellSet.GetCellShape(originCells[myIndex]),
|
||||
cellSet.GetIndices(originCells[myIndex]),
|
||||
*self);
|
||||
bool foundPair = false;
|
||||
for (vtkm::IdComponent otherIndex = myIndex + 1; otherIndex < numCellsOnHash; otherIndex++)
|
||||
{
|
||||
vtkm::Id3 otherFace =
|
||||
vtkm::exec::CellFaceCononicalId(originFaces[otherIndex],
|
||||
cellSet.GetCellShape(originCells[otherIndex]),
|
||||
cellSet.GetIndices(originCells[otherIndex]),
|
||||
*self);
|
||||
if (myFace == otherFace)
|
||||
{
|
||||
// Faces are the same. Must be internal.
|
||||
foundPair = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundPair)
|
||||
{
|
||||
if (numFound == visitIndex)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
numFound++;
|
||||
}
|
||||
}
|
||||
|
||||
myIndex++;
|
||||
}
|
||||
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public:
|
||||
// Worklet that returns the number of points for each outputted face.
|
||||
// Have to manage the case where multiple faces have the same hash.
|
||||
class NumPointsPerFace : public vtkm::worklet::WorkletReduceByKey
|
||||
{
|
||||
public:
|
||||
@ -533,7 +519,7 @@ struct ExternalFaces
|
||||
ValuesIn<> originCells,
|
||||
ValuesIn<> originFaces,
|
||||
ReducedValuesOut<> numPointsInFace);
|
||||
typedef _5 ExecutionSignature(_2, _3, _4);
|
||||
typedef _5 ExecutionSignature(_2, _3, _4, VisitIndex);
|
||||
using InputDomain = _1;
|
||||
|
||||
using ScatterType = vtkm::worklet::ScatterCounting;
|
||||
@ -557,12 +543,14 @@ struct ExternalFaces
|
||||
template <typename CellSetType, typename OriginCellsType, typename OriginFacesType>
|
||||
VTKM_EXEC vtkm::IdComponent operator()(const CellSetType& cellSet,
|
||||
const OriginCellsType& originCells,
|
||||
const OriginFacesType& originFaces) const
|
||||
const OriginFacesType& originFaces,
|
||||
vtkm::IdComponent visitIndex) const
|
||||
{
|
||||
VTKM_ASSERT(originCells.GetNumberOfComponents() == 1);
|
||||
VTKM_ASSERT(originFaces.GetNumberOfComponents() == 1);
|
||||
vtkm::IdComponent myIndex =
|
||||
ExternalFaces::FindUniqueFace(cellSet, originCells, originFaces, visitIndex, this);
|
||||
|
||||
return vtkm::exec::CellFaceNumberOfPoints(
|
||||
originFaces[0], cellSet.GetCellShape(originCells[0]), *this);
|
||||
originFaces[myIndex], cellSet.GetCellShape(originCells[myIndex]), *this);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -580,7 +568,7 @@ struct ExternalFaces
|
||||
ReducedValuesOut<> shapesOut,
|
||||
ReducedValuesOut<> connectivityOut,
|
||||
ReducedValuesOut<> cellIdMapOut);
|
||||
typedef void ExecutionSignature(_2, _3, _4, _5, _6, _7);
|
||||
typedef void ExecutionSignature(_2, _3, _4, VisitIndex, _5, _6, _7);
|
||||
using InputDomain = _1;
|
||||
|
||||
using ScatterType = vtkm::worklet::ScatterCounting;
|
||||
@ -608,23 +596,24 @@ struct ExternalFaces
|
||||
VTKM_EXEC void operator()(const CellSetType& cellSet,
|
||||
const OriginCellsType& originCells,
|
||||
const OriginFacesType& originFaces,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::UInt8& shapeOut,
|
||||
ConnectivityType& connectivityOut,
|
||||
vtkm::Id& cellIdMapOut) const
|
||||
{
|
||||
VTKM_ASSERT(originCells.GetNumberOfComponents() == 1);
|
||||
VTKM_ASSERT(originFaces.GetNumberOfComponents() == 1);
|
||||
vtkm::IdComponent myIndex =
|
||||
ExternalFaces::FindUniqueFace(cellSet, originCells, originFaces, visitIndex, this);
|
||||
|
||||
typename CellSetType::CellShapeTag shapeIn = cellSet.GetCellShape(originCells[0]);
|
||||
shapeOut = vtkm::exec::CellFaceShape(originFaces[0], shapeIn, *this);
|
||||
cellIdMapOut = originCells[0];
|
||||
typename CellSetType::CellShapeTag shapeIn = cellSet.GetCellShape(originCells[myIndex]);
|
||||
shapeOut = vtkm::exec::CellFaceShape(originFaces[myIndex], shapeIn, *this);
|
||||
cellIdMapOut = originCells[myIndex];
|
||||
|
||||
vtkm::VecCConst<vtkm::IdComponent> localFaceIndices =
|
||||
vtkm::exec::CellFaceLocalIndices(originFaces[0], shapeIn, *this);
|
||||
vtkm::exec::CellFaceLocalIndices(originFaces[myIndex], shapeIn, *this);
|
||||
vtkm::IdComponent numFacePoints = localFaceIndices.GetNumberOfComponents();
|
||||
VTKM_ASSERT(numFacePoints == connectivityOut.GetNumberOfComponents());
|
||||
|
||||
typename CellSetType::IndicesType inCellIndices = cellSet.GetIndices(originCells[0]);
|
||||
typename CellSetType::IndicesType inCellIndices = cellSet.GetIndices(originCells[myIndex]);
|
||||
|
||||
for (vtkm::IdComponent facePointIndex = 0; facePointIndex < numFacePoints; facePointIndex++)
|
||||
{
|
||||
@ -755,6 +744,9 @@ public:
|
||||
VTKM_CONT
|
||||
void SetPassPolyData(bool flag) { this->PassPolyData = flag; }
|
||||
|
||||
VTKM_CONT
|
||||
bool GetPassPolyData() const { return this->PassPolyData; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename ValueType, typename StorageType, typename DeviceAdapter>
|
||||
vtkm::cont::ArrayHandle<ValueType> ProcessCellField(
|
||||
@ -852,30 +844,12 @@ public:
|
||||
vtkm::worklet::DispatcherMapTopology<NumExternalFacesPerStructuredCell>
|
||||
numExternalFacesDispatcher((NumExternalFacesPerStructuredCell(MinPoint, MaxPoint)));
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
vtkm::cont::Timer<DeviceAdapter> timer;
|
||||
#endif
|
||||
numExternalFacesDispatcher.Invoke(inCellSet, numExternalFaces, coord.GetData());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "NumExternalFacesPerStructuredCell_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
typedef typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter> DeviceAlgorithms;
|
||||
vtkm::Id numberOfExternalFaces = DeviceAlgorithms::Reduce(numExternalFaces, 0, vtkm::Sum());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "numberOfExternalFaces_Reduce," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
vtkm::worklet::ScatterCounting scatterCellToExternalFace(numExternalFaces, DeviceAdapter());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "numExternalFaces_ScatterCounting," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
// Maps output cells to input cells. Store this for cell field mapping.
|
||||
this->CellIdMap = scatterCellToExternalFace.GetOutputToInputMap();
|
||||
@ -894,9 +868,6 @@ public:
|
||||
buildConnectivityStructuredDispatcher(
|
||||
(BuildConnectivityStructured(MinPoint, MaxPoint, scatterCellToExternalFace)));
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
buildConnectivityStructuredDispatcher.Invoke(
|
||||
inCellSet,
|
||||
inCellSet,
|
||||
@ -904,13 +875,7 @@ public:
|
||||
facePointCount,
|
||||
vtkm::cont::make_ArrayHandleGroupVec<4>(faceConnectivity),
|
||||
coord.GetData());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "BuildConnectivityStructured_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
outCellSet.Fill(inCellSet.GetNumberOfPoints(), faceShapes, facePointCount, faceConnectivity);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "Total External Faces = " << outCellSet.GetNumberOfCells() << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
@ -928,59 +893,34 @@ public:
|
||||
OffsetsStorage>& outCellSet,
|
||||
DeviceAdapter)
|
||||
{
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorage> PointCountArrayType;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage> ShapeArrayType;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage> OffsetsArrayType;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage> ConnectivityArrayType;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Id> CellIdArrayType;
|
||||
using PointCountArrayType = vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorage>;
|
||||
using ShapeArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage>;
|
||||
using OffsetsArrayType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>;
|
||||
using ConnectivityArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage>;
|
||||
|
||||
//Create a worklet to map the number of faces to each cell
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> facesPerCell;
|
||||
vtkm::worklet::DispatcherMapTopology<NumFacesPerCell> numFacesDispatcher;
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
vtkm::cont::Timer<DeviceAdapter> timer;
|
||||
#endif
|
||||
numFacesDispatcher.Invoke(inCellSet, facesPerCell);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "NumFacesPerCell_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
vtkm::worklet::ScatterCounting scatterCellToFace(facesPerCell, DeviceAdapter());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "FaceInputCount_ScatterCounting," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
facesPerCell.ReleaseResources();
|
||||
|
||||
PointCountArrayType polyDataPointCount;
|
||||
ShapeArrayType polyDataShapes;
|
||||
OffsetsArrayType polyDataOffsets;
|
||||
ConnectivityArrayType polyDataConnectivity;
|
||||
CellIdArrayType polyDataCellIdMap;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> polyDataCellIdMap;
|
||||
vtkm::Id polyDataConnectivitySize = 0;
|
||||
if (this->PassPolyData)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> isPolyDataCell;
|
||||
vtkm::worklet::DispatcherMapTopology<IsPolyDataCell> isPolyDataCellDispatcher;
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
isPolyDataCellDispatcher.Invoke(inCellSet, isPolyDataCell);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "IsPolyDataCell_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
vtkm::worklet::ScatterCounting scatterPolyDataCells(isPolyDataCell, DeviceAdapter());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "scatterPolyDataCells_ScatterCounting," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
isPolyDataCell.ReleaseResources();
|
||||
|
||||
@ -989,13 +929,7 @@ public:
|
||||
vtkm::worklet::DispatcherMapTopology<CountPolyDataCellPoints, DeviceAdapter>
|
||||
countPolyDataCellPointsDispatcher((CountPolyDataCellPoints(scatterPolyDataCells)));
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
countPolyDataCellPointsDispatcher.Invoke(inCellSet, polyDataPointCount);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "CountPolyDataCellPoints_Worklet" << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
vtkm::cont::ConvertNumComponentsToOffsets(
|
||||
polyDataPointCount, polyDataOffsets, polyDataConnectivitySize);
|
||||
@ -1005,17 +939,11 @@ public:
|
||||
|
||||
polyDataConnectivity.Allocate(polyDataConnectivitySize);
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
passPolyDataCellsDispatcher.Invoke(
|
||||
inCellSet,
|
||||
polyDataShapes,
|
||||
vtkm::cont::make_ArrayHandleGroupVecVariable(polyDataConnectivity, polyDataOffsets),
|
||||
polyDataCellIdMap);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "PassPolyDataCells_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1041,70 +969,34 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id3> faceHashes;
|
||||
vtkm::cont::ArrayHandle<vtkm::HashType> faceHashes;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> originCells;
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> originFaces;
|
||||
vtkm::worklet::DispatcherMapTopology<FaceHash, DeviceAdapter> faceHashDispatcher(
|
||||
(FaceHash(scatterCellToFace)));
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
faceHashDispatcher.Invoke(inCellSet, faceHashes, originCells, originFaces);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "FaceHash_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
vtkm::worklet::Keys<vtkm::Id3> faceKeys(faceHashes, DeviceAdapter());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "Keys_BuildArrays," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
vtkm::worklet::Keys<vtkm::HashType> faceKeys(faceHashes, DeviceAdapter());
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> faceOutputCount;
|
||||
vtkm::worklet::DispatcherReduceByKey<FaceCounts, DeviceAdapter> faceCountDispatcher;
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
faceCountDispatcher.Invoke(faceKeys, faceOutputCount);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "FaceCount_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
faceCountDispatcher.Invoke(faceKeys, inCellSet, originCells, originFaces, faceOutputCount);
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
vtkm::worklet::ScatterCounting scatterCullInternalFaces(faceOutputCount, DeviceAdapter());
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "FaceOutputCount_ScatterCounting," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
PointCountArrayType facePointCount;
|
||||
vtkm::worklet::DispatcherReduceByKey<NumPointsPerFace, DeviceAdapter> pointsPerFaceDispatcher(
|
||||
scatterCullInternalFaces);
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
pointsPerFaceDispatcher.Invoke(faceKeys, inCellSet, originCells, originFaces, facePointCount);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "PointsPerFaceCount_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
ShapeArrayType faceShapes;
|
||||
|
||||
OffsetsArrayType faceOffsets;
|
||||
vtkm::Id connectivitySize;
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
vtkm::cont::ConvertNumComponentsToOffsets(facePointCount, faceOffsets, connectivitySize);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "FacePointCount_ScanExclusive," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
ConnectivityArrayType faceConnectivity;
|
||||
// Must pre allocate because worklet invocation will not have enough
|
||||
@ -1114,11 +1006,8 @@ public:
|
||||
vtkm::worklet::DispatcherReduceByKey<BuildConnectivity, DeviceAdapter>
|
||||
buildConnectivityDispatcher(scatterCullInternalFaces);
|
||||
|
||||
CellIdArrayType faceToCellIdMap;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> faceToCellIdMap;
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
timer.Reset();
|
||||
#endif
|
||||
buildConnectivityDispatcher.Invoke(
|
||||
faceKeys,
|
||||
inCellSet,
|
||||
@ -1127,9 +1016,6 @@ public:
|
||||
faceShapes,
|
||||
vtkm::cont::make_ArrayHandleGroupVecVariable(faceConnectivity, faceOffsets),
|
||||
faceToCellIdMap);
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "BuildConnectivity_Worklet," << timer.GetElapsedTime() << "\n";
|
||||
#endif
|
||||
|
||||
if (!polyDataConnectivitySize)
|
||||
{
|
||||
@ -1168,9 +1054,10 @@ public:
|
||||
OffsetsArrayType joinedOffsets;
|
||||
DeviceAlgorithm::Copy(offsetsArray, joinedOffsets);
|
||||
|
||||
vtkm::cont::ArrayHandleConcatenate<CellIdArrayType, CellIdArrayType> cellIdMapArray(
|
||||
faceToCellIdMap, polyDataCellIdMap);
|
||||
CellIdArrayType joinedCellIdMap;
|
||||
vtkm::cont::ArrayHandleConcatenate<vtkm::cont::ArrayHandle<vtkm::Id>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id>>
|
||||
cellIdMapArray(faceToCellIdMap, polyDataCellIdMap);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> joinedCellIdMap;
|
||||
DeviceAlgorithm::Copy(cellIdMapArray, joinedCellIdMap);
|
||||
|
||||
outCellSet.Fill(inCellSet.GetNumberOfPoints(),
|
||||
@ -1180,12 +1067,12 @@ public:
|
||||
joinedOffsets);
|
||||
this->CellIdMap = joinedCellIdMap;
|
||||
}
|
||||
|
||||
#ifdef __VTKM_EXTERNAL_FACES_BENCHMARK
|
||||
std::cout << "Total External Faces = " << outCellSet.GetNumberOfCells() << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> CellIdMap;
|
||||
bool PassPolyData;
|
||||
|
||||
}; //struct ExternalFaces
|
||||
}
|
||||
} //namespace vtkm::worklet
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user