mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Change WorkletPointNeighborhood to specify neighborhood at runtime
Previously, WorkletPointNeighborhood had a template argument to select the size of the neighborhood. This change removes that template argument. Instead, the vtkm::exec::arg::BoundaryState methods now take in a size parameter when determining when it overlaps the boundary. If in the future we want to add the ability to select the neighborhood size at compile-time (for performance reasons), I suggest adding this template argument to the OnBoundary tag for ExecutionSignature.
This commit is contained in:
parent
bc13764228
commit
01a9e85416
@ -74,7 +74,7 @@ struct GameOfLifePolicy : public vtkm::filter::PolicyBase<GameOfLifePolicy>
|
||||
using DeviceAdapterList = DevicesToTry;
|
||||
};
|
||||
|
||||
struct UpdateLifeState : public vtkm::worklet::WorkletPointNeighborhood3x3x3
|
||||
struct UpdateLifeState : public vtkm::worklet::WorkletPointNeighborhood
|
||||
{
|
||||
using CountingHandle = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
|
||||
|
||||
|
@ -37,12 +37,11 @@ namespace arg
|
||||
/// \c FetchTagArrayNeighborhoodIn is a tag used with the \c Fetch class to retrieve
|
||||
/// values from an neighborhood.
|
||||
///
|
||||
template <int NeighborhoodSize>
|
||||
struct FetchTagArrayNeighborhoodIn
|
||||
{
|
||||
};
|
||||
|
||||
template <int NeighborhoodSize, typename ExecObjectType>
|
||||
template <typename ExecObjectType>
|
||||
struct Neighborhood
|
||||
{
|
||||
VTKM_EXEC
|
||||
@ -57,18 +56,12 @@ struct Neighborhood
|
||||
VTKM_EXEC
|
||||
ValueType Get(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const
|
||||
{
|
||||
VTKM_ASSERT(i <= NeighborhoodSize && i >= -NeighborhoodSize);
|
||||
VTKM_ASSERT(j <= NeighborhoodSize && j >= -NeighborhoodSize);
|
||||
VTKM_ASSERT(k <= NeighborhoodSize && k >= -NeighborhoodSize);
|
||||
return Portal.Get(this->Boundary->NeighborIndexToFlatIndexClamp(i, j, k));
|
||||
}
|
||||
|
||||
VTKM_EXEC
|
||||
ValueType Get(const vtkm::Id3& ijk) const
|
||||
{
|
||||
VTKM_ASSERT(ijk[0] <= NeighborhoodSize && ijk[0] >= -NeighborhoodSize);
|
||||
VTKM_ASSERT(ijk[1] <= NeighborhoodSize && ijk[1] >= -NeighborhoodSize);
|
||||
VTKM_ASSERT(ijk[2] <= NeighborhoodSize && ijk[2] >= -NeighborhoodSize);
|
||||
return Portal.Get(this->Boundary->NeighborIndexToFlatIndexClamp(ijk));
|
||||
}
|
||||
|
||||
@ -79,8 +72,8 @@ struct Neighborhood
|
||||
/// \brief Specialization of Neighborhood for ArrayPortalUniformPointCoordinates
|
||||
/// We can use fast paths inside ArrayPortalUniformPointCoordinates to allow
|
||||
/// for very fast computation of the coordinates reachable by the neighborhood
|
||||
template <int NeighborhoodSize>
|
||||
struct Neighborhood<NeighborhoodSize, vtkm::internal::ArrayPortalUniformPointCoordinates>
|
||||
template <>
|
||||
struct Neighborhood<vtkm::internal::ArrayPortalUniformPointCoordinates>
|
||||
{
|
||||
VTKM_EXEC
|
||||
Neighborhood(const vtkm::internal::ArrayPortalUniformPointCoordinates& portal,
|
||||
@ -108,14 +101,14 @@ struct Neighborhood<NeighborhoodSize, vtkm::internal::ArrayPortalUniformPointCoo
|
||||
vtkm::internal::ArrayPortalUniformPointCoordinates Portal;
|
||||
};
|
||||
|
||||
template <int NeighborhoodSize, typename ExecObjectType>
|
||||
struct Fetch<vtkm::exec::arg::FetchTagArrayNeighborhoodIn<NeighborhoodSize>,
|
||||
template <typename ExecObjectType>
|
||||
struct Fetch<vtkm::exec::arg::FetchTagArrayNeighborhoodIn,
|
||||
vtkm::exec::arg::AspectTagDefault,
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood<NeighborhoodSize>,
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood,
|
||||
ExecObjectType>
|
||||
{
|
||||
using ThreadIndicesType = vtkm::exec::arg::ThreadIndicesPointNeighborhood<NeighborhoodSize>;
|
||||
using ValueType = Neighborhood<NeighborhoodSize, ExecObjectType>;
|
||||
using ThreadIndicesType = vtkm::exec::arg::ThreadIndicesPointNeighborhood;
|
||||
using ValueType = Neighborhood<ExecObjectType>;
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC
|
||||
|
@ -49,13 +49,13 @@ struct OnBoundary : vtkm::exec::arg::ExecutionSignatureTagBase
|
||||
using AspectTag = vtkm::exec::arg::AspectTagOnBoundary;
|
||||
};
|
||||
|
||||
template <typename FetchTag, int NSize, typename ExecObjectType>
|
||||
template <typename FetchTag, typename ExecObjectType>
|
||||
struct Fetch<FetchTag,
|
||||
vtkm::exec::arg::AspectTagOnBoundary,
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood<NSize>,
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood,
|
||||
ExecObjectType>
|
||||
{
|
||||
using ThreadIndicesType = vtkm::exec::arg::ThreadIndicesPointNeighborhood<NSize>;
|
||||
using ThreadIndicesType = vtkm::exec::arg::ThreadIndicesPointNeighborhood;
|
||||
|
||||
using ValueType = vtkm::exec::arg::BoundaryState;
|
||||
|
||||
|
@ -41,91 +41,96 @@ namespace arg
|
||||
struct BoundaryState
|
||||
{
|
||||
VTKM_EXEC
|
||||
BoundaryState(const vtkm::Id3& ijk, const vtkm::Id3& pdims, int neighborhoodSize)
|
||||
BoundaryState(const vtkm::Id3& ijk, const vtkm::Id3& pdims)
|
||||
: IJK(ijk)
|
||||
, PointDimensions(pdims)
|
||||
, NeighborhoodSize(neighborhoodSize)
|
||||
{
|
||||
for (vtkm::IdComponent dim = 0; dim < 3; ++dim)
|
||||
{
|
||||
if (neighborhoodSize < ijk[dim])
|
||||
{
|
||||
this->MinNeighborhood[dim] = -neighborhoodSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->MinNeighborhood[dim] = static_cast<vtkm::IdComponent>(-ijk[dim]);
|
||||
}
|
||||
if (neighborhoodSize < pdims[dim] - ijk[dim] - 1)
|
||||
{
|
||||
this->MaxNeighborhood[dim] = neighborhoodSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->MaxNeighborhood[dim] = static_cast<vtkm::IdComponent>(pdims[dim] - ijk[dim] - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the minimum neighbor index in the X direction (between -neighborhood size and 0)
|
||||
//@{
|
||||
/// Returns true if a neighborhood of the given number of layers is contained within the bounds
|
||||
/// of the cell set in the X, Y, or Z direction. Returns false if the neighborhood extends ouside
|
||||
/// of the boundary of the data in the X, Y, or Z direction.
|
||||
///
|
||||
VTKM_EXEC vtkm::IdComponent MinNeighborX() const { return this->MinNeighborhood[0]; }
|
||||
/// The number of layers defines the size of the neighborhood in terms of how far away it extends
|
||||
/// from the center. So if there is 1 layer, the neighborhood extends 1 unit away from the center
|
||||
/// in each direction and is 3x3x3. If there are 2 layers, the neighborhood extends 2 units for a
|
||||
/// size of 5x5x5.
|
||||
///
|
||||
VTKM_EXEC bool InXBoundary(vtkm::IdComponent numLayers) const
|
||||
{
|
||||
return (((this->IJK[0] - numLayers) >= 0) &&
|
||||
((this->IJK[0] + numLayers) < this->PointDimensions[0]));
|
||||
}
|
||||
VTKM_EXEC bool InYBoundary(vtkm::IdComponent numLayers) const
|
||||
{
|
||||
return (((this->IJK[1] - numLayers) >= 0) &&
|
||||
((this->IJK[1] + numLayers) < this->PointDimensions[1]));
|
||||
}
|
||||
VTKM_EXEC bool InZBoundary(vtkm::IdComponent numLayers) const
|
||||
{
|
||||
return (((this->IJK[2] - numLayers) >= 0) &&
|
||||
((this->IJK[2] + numLayers) < this->PointDimensions[2]));
|
||||
}
|
||||
//@}
|
||||
|
||||
/// Returns the minimum neighbor index in the Z direction (between -neighborhood size and 0)
|
||||
/// Returns true if a neighborhood of the given number of layers is contained within the bounds
|
||||
/// of the cell set. Returns false if the neighborhood extends ouside of the boundary of the
|
||||
/// data.
|
||||
///
|
||||
VTKM_EXEC vtkm::IdComponent MinNeighborY() const { return this->MinNeighborhood[1]; }
|
||||
/// The number of layers defines the size of the neighborhood in terms of how far away it extends
|
||||
/// from the center. So if there is 1 layer, the neighborhood extends 1 unit away from the center
|
||||
/// in each direction and is 3x3x3. If there are 2 layers, the neighborhood extends 2 units for a
|
||||
/// size of 5x5x5.
|
||||
///
|
||||
VTKM_EXEC bool InBoundary(vtkm::IdComponent numLayers) const
|
||||
{
|
||||
return this->InXBoundary(numLayers) && this->InYBoundary(numLayers) &&
|
||||
this->InZBoundary(numLayers);
|
||||
}
|
||||
|
||||
/// Returns the minimum neighbor index in the Z direction (between -neighborhood size and 0)
|
||||
/// Returns the minimum neighborhood indices that are within the bounds of the data.
|
||||
///
|
||||
VTKM_EXEC vtkm::IdComponent MinNeighborZ() const { return this->MinNeighborhood[2]; }
|
||||
VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 3> MinNeighborIndices(vtkm::IdComponent numLayers) const
|
||||
{
|
||||
vtkm::Vec<vtkm::IdComponent, 3> minIndices;
|
||||
|
||||
/// Returns the maximum neighbor index in the X direction (between 0 and neighborhood size)
|
||||
///
|
||||
VTKM_EXEC vtkm::IdComponent MaxNeighborX() const { return this->MaxNeighborhood[0]; }
|
||||
for (vtkm::IdComponent component = 0; component < 3; ++component)
|
||||
{
|
||||
if (this->IJK[component] >= numLayers)
|
||||
{
|
||||
minIndices[component] = -numLayers;
|
||||
}
|
||||
else
|
||||
{
|
||||
minIndices[component] = static_cast<vtkm::IdComponent>(-this->IJK[component]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the maximum neighbor index in the Z direction (between 0 and neighborhood size)
|
||||
///
|
||||
VTKM_EXEC vtkm::IdComponent MaxNeighborY() const { return this->MaxNeighborhood[1]; }
|
||||
return minIndices;
|
||||
}
|
||||
|
||||
/// Returns the maximum neighbor index in the Z direction (between 0 and neighborhood size)
|
||||
/// Returns the minimum neighborhood indices that are within the bounds of the data.
|
||||
///
|
||||
VTKM_EXEC vtkm::IdComponent MaxNeighborZ() const { return this->MaxNeighborhood[2]; }
|
||||
VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 3> MaxNeighborIndices(vtkm::IdComponent numLayers) const
|
||||
{
|
||||
vtkm::Vec<vtkm::IdComponent, 3> maxIndices;
|
||||
|
||||
/// Returns true if the neighborhood extends past the positive X direction.
|
||||
///
|
||||
VTKM_EXEC bool OnXPositive() const { return this->MaxNeighborX() < this->NeighborhoodSize; }
|
||||
for (vtkm::IdComponent component = 0; component < 3; ++component)
|
||||
{
|
||||
if ((this->PointDimensions[component] - this->IJK[component] - 1) >= numLayers)
|
||||
{
|
||||
maxIndices[component] = numLayers;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxIndices[component] = static_cast<vtkm::IdComponent>(this->PointDimensions[component] -
|
||||
this->IJK[component] - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the neighborhood extends past the negative X direction.
|
||||
///
|
||||
VTKM_EXEC bool OnXNegative() const { return -this->MinNeighborX() < this->NeighborhoodSize; }
|
||||
|
||||
/// Returns true if the neighborhood extends past the positive Y direction.
|
||||
///
|
||||
VTKM_EXEC bool OnYPositive() const { return this->MaxNeighborY() < this->NeighborhoodSize; }
|
||||
|
||||
/// Returns true if the neighborhood extends past the negative Y direction.
|
||||
///
|
||||
VTKM_EXEC bool OnYNegative() const { return -this->MinNeighborY() < this->NeighborhoodSize; }
|
||||
|
||||
/// Returns true if the neighborhood extends past the positive Z direction.
|
||||
///
|
||||
VTKM_EXEC bool OnZPositive() const { return this->MaxNeighborZ() < this->NeighborhoodSize; }
|
||||
|
||||
/// Returns true if the neighborhood extends past the negative Z direction.
|
||||
///
|
||||
VTKM_EXEC bool OnZNegative() const { return -this->MinNeighborZ() < this->NeighborhoodSize; }
|
||||
|
||||
/// Returns true if the neighborhood extends past either X boundary.
|
||||
///
|
||||
VTKM_EXEC bool OnX() const { return this->OnXNegative() || this->OnXPositive(); }
|
||||
|
||||
/// Returns true if the neighborhood extends past either Y boundary.
|
||||
///
|
||||
VTKM_EXEC bool OnY() const { return this->OnYNegative() || this->OnYPositive(); }
|
||||
|
||||
/// Returns true if the neighborhood extends past either Z boundary.
|
||||
///
|
||||
VTKM_EXEC bool OnZ() const { return this->OnZNegative() || this->OnZPositive(); }
|
||||
return maxIndices;
|
||||
}
|
||||
|
||||
//todo: This needs to work with BoundaryConstantValue
|
||||
//todo: This needs to work with BoundaryPeroidic
|
||||
@ -140,9 +145,9 @@ struct BoundaryState
|
||||
VTKM_EXEC vtkm::Id3 NeighborIndexToFullIndexClamp(
|
||||
const vtkm::Vec<vtkm::IdComponent, 3>& neighbor) const
|
||||
{
|
||||
vtkm::Vec<vtkm::IdComponent, 3> clampedNeighbor =
|
||||
vtkm::Max(this->MinNeighborhood, vtkm::Min(this->MaxNeighborhood, neighbor));
|
||||
return this->IJK + clampedNeighbor;
|
||||
vtkm::Id3 fullIndex = this->IJK + neighbor;
|
||||
|
||||
return vtkm::Max(vtkm::Id3(0), vtkm::Min(this->PointDimensions - vtkm::Id3(1), fullIndex));
|
||||
}
|
||||
|
||||
VTKM_EXEC vtkm::Id3 NeighborIndexToFullIndexClamp(vtkm::IdComponent neighborI,
|
||||
@ -181,9 +186,6 @@ struct BoundaryState
|
||||
|
||||
vtkm::Id3 IJK;
|
||||
vtkm::Id3 PointDimensions;
|
||||
vtkm::Vec<vtkm::IdComponent, 3> MinNeighborhood;
|
||||
vtkm::Vec<vtkm::IdComponent, 3> MaxNeighborhood;
|
||||
vtkm::IdComponent NeighborhoodSize;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
@ -213,7 +215,6 @@ inline VTKM_EXEC vtkm::Id3 To3D(vtkm::Vec<vtkm::Id, 1> index)
|
||||
/// \brief Container for thread information in a WorkletPointNeighborhood.
|
||||
///
|
||||
///
|
||||
template <int NeighborhoodSize>
|
||||
class ThreadIndicesPointNeighborhood
|
||||
{
|
||||
|
||||
@ -227,7 +228,7 @@ public:
|
||||
vtkm::TopologyElementTagPoint,
|
||||
Dimension>& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: State(outIndex, detail::To3D(connectivity.GetPointDimensions()), NeighborhoodSize)
|
||||
: State(outIndex, detail::To3D(connectivity.GetPointDimensions()))
|
||||
, InputIndex(0)
|
||||
, OutputIndex(0)
|
||||
, VisitIndex(0)
|
||||
@ -252,8 +253,7 @@ public:
|
||||
Dimension>& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: State(detail::To3D(connectivity.FlatToLogicalToIndex(outToIn.Get(outIndex))),
|
||||
detail::To3D(connectivity.GetPointDimensions()),
|
||||
NeighborhoodSize)
|
||||
detail::To3D(connectivity.GetPointDimensions()))
|
||||
, InputIndex(outToIn.Get(outIndex))
|
||||
, OutputIndex(outIndex)
|
||||
, VisitIndex(static_cast<vtkm::IdComponent>(visit.Get(outIndex)))
|
||||
@ -271,8 +271,7 @@ public:
|
||||
Dimension>& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: State(detail::To3D(connectivity.FlatToLogicalToIndex(inIndex)),
|
||||
detail::To3D(connectivity.GetPointDimensions()),
|
||||
NeighborhoodSize)
|
||||
detail::To3D(connectivity.GetPointDimensions()))
|
||||
, InputIndex(inIndex)
|
||||
, OutputIndex(outIndex)
|
||||
, VisitIndex(visitIndex)
|
||||
|
@ -60,23 +60,33 @@ void verify_neighbors(NeighborhoodType neighbors, vtkm::Id index, vtkm::Id3 inde
|
||||
T expected;
|
||||
auto* boundary = neighbors.Boundary;
|
||||
|
||||
//Verify the boundar flags first
|
||||
VTKM_TEST_ASSERT(test_equal(index3d[0] == (POINT_DIMS[0] - 1), boundary->OnXPositive()),
|
||||
"Got invalid X+ boundary");
|
||||
VTKM_TEST_ASSERT(test_equal(index3d[0] == 0, boundary->OnXNegative()), "Got invalid X- boundary");
|
||||
VTKM_TEST_ASSERT(test_equal(index3d[1] == (POINT_DIMS[1] - 1), boundary->OnYPositive()),
|
||||
"Got invalid Y+ boundary");
|
||||
VTKM_TEST_ASSERT(test_equal(index3d[1] == 0, boundary->OnYNegative()), "Got invalid Y- boundary");
|
||||
VTKM_TEST_ASSERT(test_equal(index3d[2] == (POINT_DIMS[2] - 1), boundary->OnZPositive()),
|
||||
"Got invalid Z+ boundary");
|
||||
VTKM_TEST_ASSERT(test_equal(index3d[2] == 0, boundary->OnZNegative()), "Got invalid Z- boundary");
|
||||
//Verify the boundary flags first
|
||||
VTKM_TEST_ASSERT(((index3d[0] != 0) && (index3d[0] != (POINT_DIMS[0] - 1))) ==
|
||||
boundary->InXBoundary(1),
|
||||
"Got invalid X boundary");
|
||||
VTKM_TEST_ASSERT(((index3d[1] != 0) && (index3d[1] != (POINT_DIMS[1] - 1))) ==
|
||||
boundary->InYBoundary(1),
|
||||
"Got invalid Y boundary");
|
||||
VTKM_TEST_ASSERT(((index3d[2] != 0) && (index3d[2] != (POINT_DIMS[2] - 1))) ==
|
||||
boundary->InZBoundary(1),
|
||||
"Got invalid Z boundary");
|
||||
|
||||
VTKM_TEST_ASSERT(((boundary->MinNeighborIndices(1)[0] == -1) &&
|
||||
(boundary->MaxNeighborIndices(1)[0] == 1)) == boundary->InXBoundary(1),
|
||||
"Got invalid min/max X indices");
|
||||
VTKM_TEST_ASSERT(((boundary->MinNeighborIndices(1)[1] == -1) &&
|
||||
(boundary->MaxNeighborIndices(1)[1] == 1)) == boundary->InYBoundary(1),
|
||||
"Got invalid min/max Y indices");
|
||||
VTKM_TEST_ASSERT(((boundary->MinNeighborIndices(1)[2] == -1) &&
|
||||
(boundary->MaxNeighborIndices(1)[2] == 1)) == boundary->InZBoundary(1),
|
||||
"Got invalid min/max Z indices");
|
||||
|
||||
T forwardX = neighbors.Get(1, 0, 0);
|
||||
expected = boundary->OnXPositive() ? TestValue(index, T()) : TestValue(index + 1, T());
|
||||
expected = (index3d[0] == POINT_DIMS[0] - 1) ? TestValue(index, T()) : TestValue(index + 1, T());
|
||||
VTKM_TEST_ASSERT(test_equal(forwardX, expected), "Got invalid value from Load.");
|
||||
|
||||
T backwardsX = neighbors.Get(-1, 0, 0);
|
||||
expected = boundary->OnXNegative() ? TestValue(index, T()) : TestValue(index - 1, T());
|
||||
expected = (index3d[0] == 0) ? TestValue(index, T()) : TestValue(index - 1, T());
|
||||
VTKM_TEST_ASSERT(test_equal(backwardsX, expected), "Got invalid value from Load.");
|
||||
}
|
||||
|
||||
@ -88,9 +98,9 @@ struct FetchArrayNeighborhoodInTests
|
||||
{
|
||||
TestPortal<T> execObject;
|
||||
|
||||
using FetchType = vtkm::exec::arg::Fetch<vtkm::exec::arg::FetchTagArrayNeighborhoodIn<1>,
|
||||
using FetchType = vtkm::exec::arg::Fetch<vtkm::exec::arg::FetchTagArrayNeighborhoodIn,
|
||||
vtkm::exec::arg::AspectTagDefault,
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood<1>,
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood,
|
||||
TestPortal<T>>;
|
||||
|
||||
FetchType fetch;
|
||||
@ -117,7 +127,7 @@ struct FetchArrayNeighborhoodInTests
|
||||
for (vtkm::Id i = 0; i < POINT_DIMS[0]; i++, index++)
|
||||
{
|
||||
index3d[0] = i;
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood<1> indices(
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood indices(
|
||||
index3d, vtkm::internal::NullType(), vtkm::internal::NullType(), connectivity);
|
||||
|
||||
auto neighbors = fetch.Load(indices, execObject);
|
||||
@ -139,7 +149,7 @@ struct FetchArrayNeighborhoodInTests
|
||||
//Verify that 1D scheduling works with neighborhoods
|
||||
for (vtkm::Id index = 0; index < (POINT_DIMS[0] * POINT_DIMS[1] * POINT_DIMS[2]); index++)
|
||||
{
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood<1> indices(
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood indices(
|
||||
index, TestIndexPortal(), TestIndexPortal(), connectivity);
|
||||
|
||||
auto neighbors = fetch.Load(indices, execObject);
|
||||
|
@ -479,7 +479,12 @@ void TestNormals(const vtkm::cont::DataSet& dataset, bool structured)
|
||||
for (vtkm::Id i = 0; i < numVerts; ++i)
|
||||
{
|
||||
VTKM_TEST_ASSERT(test_equal(normals.GetPortalConstControl().Get(i), expected[i], 0.001),
|
||||
"Result does not match expected values");
|
||||
"Result (",
|
||||
normals.GetPortalConstControl().Get(i),
|
||||
") does not match expected value (",
|
||||
expected[i],
|
||||
") vert ",
|
||||
i);
|
||||
}
|
||||
|
||||
// Test the other normals generation method
|
||||
|
@ -599,13 +599,13 @@ public:
|
||||
//Optimization for structured cellsets so we can call StructuredPointGradient
|
||||
//and have way faster gradients
|
||||
vtkm::exec::ConnectivityStructured<Cell, Point, 3> pointGeom(geometry);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood<3> tpn(pointId, pointId, 0, pointGeom, 0);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood tpn(pointId, pointId, 0, pointGeom, 0);
|
||||
|
||||
const auto& boundary = tpn.GetBoundaryState();
|
||||
auto pointPortal = pointCoordinates.GetPortal();
|
||||
auto fieldPortal = inputField.GetPortal();
|
||||
vtkm::exec::arg::Neighborhood<1, decltype(pointPortal)> points(pointPortal, boundary);
|
||||
vtkm::exec::arg::Neighborhood<1, decltype(fieldPortal)> field(fieldPortal, boundary);
|
||||
vtkm::exec::arg::Neighborhood<decltype(pointPortal)> points(pointPortal, boundary);
|
||||
vtkm::exec::arg::Neighborhood<decltype(fieldPortal)> field(fieldPortal, boundary);
|
||||
|
||||
vtkm::worklet::gradient::StructuredPointGradient<T> gradient;
|
||||
gradient(boundary, points, field, normal);
|
||||
@ -683,13 +683,13 @@ public:
|
||||
//Optimization for structured cellsets so we can call StructuredPointGradient
|
||||
//and have way faster gradients
|
||||
vtkm::exec::ConnectivityStructured<Cell, Point, 3> pointGeom(geometry);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood<3> tpn(pointId, pointId, 0, pointGeom, 0);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood tpn(pointId, pointId, 0, pointGeom, 0);
|
||||
|
||||
const auto& boundary = tpn.GetBoundaryState();
|
||||
auto pointPortal = pointCoordinates.GetPortal();
|
||||
auto fieldPortal = inputField.GetPortal();
|
||||
vtkm::exec::arg::Neighborhood<1, decltype(pointPortal)> points(pointPortal, boundary);
|
||||
vtkm::exec::arg::Neighborhood<1, decltype(fieldPortal)> field(fieldPortal, boundary);
|
||||
vtkm::exec::arg::Neighborhood<decltype(pointPortal)> points(pointPortal, boundary);
|
||||
vtkm::exec::arg::Neighborhood<decltype(fieldPortal)> field(fieldPortal, boundary);
|
||||
|
||||
vtkm::worklet::gradient::StructuredPointGradient<T> gradient;
|
||||
NormalType grad1;
|
||||
|
@ -164,12 +164,9 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
template <int Neighborhood_>
|
||||
class WorkletPointNeighborhood : public WorkletPointNeighborhoodBase
|
||||
{
|
||||
public:
|
||||
static constexpr vtkm::IdComponent Neighborhood = Neighborhood_;
|
||||
|
||||
/// \brief A control signature tag for neighborhood input values.
|
||||
///
|
||||
/// A \c WorkletPointNeighborhood operates allowing access to a adjacent point
|
||||
@ -186,7 +183,7 @@ public:
|
||||
{
|
||||
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArray<TypeList>;
|
||||
using TransportTag = vtkm::cont::arg::TransportTagArrayIn;
|
||||
using FetchTag = vtkm::exec::arg::FetchTagArrayNeighborhoodIn<Neighborhood>;
|
||||
using FetchTag = vtkm::exec::arg::FetchTagArrayNeighborhoodIn;
|
||||
};
|
||||
|
||||
/// Point neighborhood worklets use the related thread indices class.
|
||||
@ -197,7 +194,7 @@ public:
|
||||
typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
vtkm::IdComponent Dimension>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesPointNeighborhood<Neighborhood> GetThreadIndices(
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesPointNeighborhood GetThreadIndices(
|
||||
const IndexType& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
@ -206,14 +203,10 @@ public:
|
||||
Dimension>& inputDomain, //this should be explicitly
|
||||
const T& globalThreadIndexOffset = 0) const
|
||||
{
|
||||
return vtkm::exec::arg::ThreadIndicesPointNeighborhood<Neighborhood>(
|
||||
return vtkm::exec::arg::ThreadIndicesPointNeighborhood(
|
||||
threadIndex, outToIn, visit, inputDomain, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
using WorkletPointNeighborhood3x3x3 = WorkletPointNeighborhood<1>;
|
||||
using WorkletPointNeighborhood5x5x5 = WorkletPointNeighborhood<2>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ template <int Dimension>
|
||||
class ImageGraft;
|
||||
|
||||
template <>
|
||||
class ImageGraft<2> : public vtkm::worklet::WorkletPointNeighborhood3x3x3
|
||||
class ImageGraft<2> : public vtkm::worklet::WorkletPointNeighborhood
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(CellSetIn,
|
||||
|
@ -38,7 +38,7 @@ struct StructuredPointGradientInType : vtkm::ListTagBase<T>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct StructuredPointGradient : public vtkm::worklet::WorkletPointNeighborhood3x3x3
|
||||
struct StructuredPointGradient : public vtkm::worklet::WorkletPointNeighborhood
|
||||
{
|
||||
|
||||
using ControlSignature = void(CellSetIn,
|
||||
@ -67,9 +67,9 @@ struct StructuredPointGradient : public vtkm::worklet::WorkletPointNeighborhood3
|
||||
T deta = inputField.Get(0, 1, 0) - inputField.Get(0, -1, 0);
|
||||
T dzeta = inputField.Get(0, 0, 1) - inputField.Get(0, 0, -1);
|
||||
|
||||
dxi = (boundary.OnX() ? dxi : dxi * 0.5f);
|
||||
deta = (boundary.OnY() ? deta : deta * 0.5f);
|
||||
dzeta = (boundary.OnZ() ? dzeta : dzeta * 0.5f);
|
||||
dxi = (boundary.InXBoundary(1) ? dxi * 0.5f : dxi);
|
||||
deta = (boundary.InYBoundary(1) ? deta * 0.5f : deta);
|
||||
dzeta = (boundary.InZBoundary(1) ? dzeta * 0.5f : dzeta);
|
||||
|
||||
outputGradient[0] = static_cast<OT>(xi[0] * dxi + eta[0] * deta + zeta[0] * dzeta);
|
||||
outputGradient[1] = static_cast<OT>(xi[1] * dxi + eta[1] * deta + zeta[1] * dzeta);
|
||||
@ -77,27 +77,26 @@ struct StructuredPointGradient : public vtkm::worklet::WorkletPointNeighborhood3
|
||||
}
|
||||
|
||||
template <typename FieldIn, typename GradientOutType>
|
||||
VTKM_EXEC void operator()(
|
||||
const vtkm::exec::arg::BoundaryState& boundary,
|
||||
const vtkm::exec::arg::Neighborhood<1, vtkm::internal::ArrayPortalUniformPointCoordinates>&
|
||||
inputPoints,
|
||||
const FieldIn& inputField,
|
||||
GradientOutType& outputGradient) const
|
||||
VTKM_EXEC void operator()(const vtkm::exec::arg::BoundaryState& boundary,
|
||||
const vtkm::exec::arg::Neighborhood<
|
||||
vtkm::internal::ArrayPortalUniformPointCoordinates>& inputPoints,
|
||||
const FieldIn& inputField,
|
||||
GradientOutType& outputGradient) const
|
||||
{
|
||||
//When the points and cells are both structured we can achieve even better
|
||||
//performance by not doing the Jacobian, but instead do an image gradient
|
||||
//using central differences
|
||||
using PointsIn =
|
||||
vtkm::exec::arg::Neighborhood<1, vtkm::internal::ArrayPortalUniformPointCoordinates>;
|
||||
vtkm::exec::arg::Neighborhood<vtkm::internal::ArrayPortalUniformPointCoordinates>;
|
||||
using CoordType = typename PointsIn::ValueType;
|
||||
using OT = typename GradientOutType::ComponentType;
|
||||
|
||||
|
||||
CoordType r = inputPoints.Portal.GetSpacing();
|
||||
|
||||
r[0] = (boundary.OnX() ? r[0] : r[0] * 0.5f);
|
||||
r[1] = (boundary.OnY() ? r[1] : r[1] * 0.5f);
|
||||
r[2] = (boundary.OnZ() ? r[2] : r[2] * 0.5f);
|
||||
r[0] = (boundary.InXBoundary(1) ? r[0] * 0.5f : r[0]);
|
||||
r[1] = (boundary.InYBoundary(1) ? r[1] * 0.5f : r[1]);
|
||||
r[2] = (boundary.InZBoundary(1) ? r[2] * 0.5f : r[2]);
|
||||
|
||||
const T dx = inputField.Get(1, 0, 0) - inputField.Get(-1, 0, 0);
|
||||
const T dy = inputField.Get(0, 1, 0) - inputField.Get(0, -1, 0);
|
||||
@ -124,9 +123,9 @@ struct StructuredPointGradient : public vtkm::worklet::WorkletPointNeighborhood3
|
||||
CoordType eta = inputPoints.Get(0, 1, 0) - inputPoints.Get(0, -1, 0);
|
||||
CoordType zeta = inputPoints.Get(0, 0, 1) - inputPoints.Get(0, 0, -1);
|
||||
|
||||
xi = (boundary.OnX() ? xi : xi * 0.5f);
|
||||
eta = (boundary.OnY() ? eta : eta * 0.5f);
|
||||
zeta = (boundary.OnZ() ? zeta : zeta * 0.5f);
|
||||
xi = (boundary.InXBoundary(1) ? xi * 0.5f : xi);
|
||||
eta = (boundary.InYBoundary(1) ? eta * 0.5f : eta);
|
||||
zeta = (boundary.InZBoundary(1) ? zeta * 0.5f : zeta);
|
||||
|
||||
CT aj = xi[0] * eta[1] * zeta[2] + xi[1] * eta[2] * zeta[0] + xi[2] * eta[0] * zeta[1] -
|
||||
xi[2] * eta[1] * zeta[0] - xi[1] * eta[0] * zeta[2] - xi[0] * eta[2] * zeta[1];
|
||||
|
@ -36,7 +36,7 @@
|
||||
namespace test_pointneighborhood
|
||||
{
|
||||
|
||||
struct MaxNeighborValue : public vtkm::worklet::WorkletPointNeighborhood3x3x3
|
||||
struct MaxNeighborValue : public vtkm::worklet::WorkletPointNeighborhood
|
||||
{
|
||||
|
||||
using ControlSignature = void(FieldInNeighborhood<Scalar> neighbors,
|
||||
@ -49,73 +49,53 @@ struct MaxNeighborValue : public vtkm::worklet::WorkletPointNeighborhood3x3x3
|
||||
|
||||
template <typename FieldIn, typename FieldOut>
|
||||
VTKM_EXEC void operator()(const vtkm::exec::arg::BoundaryState& boundary,
|
||||
const vtkm::exec::arg::Neighborhood<1, FieldIn>& inputField,
|
||||
const vtkm::exec::arg::Neighborhood<FieldIn>& inputField,
|
||||
FieldOut& output) const
|
||||
{
|
||||
using ValueType = typename FieldIn::ValueType;
|
||||
|
||||
auto* nboundary = inputField.Boundary;
|
||||
|
||||
if (!(nboundary->OnXPositive() == boundary.OnXPositive()))
|
||||
if (!(nboundary->InXBoundary(1) == boundary.InXBoundary(1)))
|
||||
{
|
||||
this->RaiseError("Got invalid XPos boundary state");
|
||||
}
|
||||
|
||||
if (!(nboundary->OnXNegative() == boundary.OnXNegative()))
|
||||
{
|
||||
this->RaiseError("Got invalid XNeg boundary state");
|
||||
}
|
||||
|
||||
if (!(nboundary->OnYPositive() == boundary.OnYPositive()))
|
||||
if (!(nboundary->InYBoundary(1) == boundary.InYBoundary(1)))
|
||||
{
|
||||
this->RaiseError("Got invalid YPos boundary state");
|
||||
}
|
||||
|
||||
if (!(nboundary->OnYNegative() == boundary.OnYNegative()))
|
||||
{
|
||||
this->RaiseError("Got invalid YNeg boundary state");
|
||||
}
|
||||
|
||||
if (!(nboundary->OnZPositive() == boundary.OnZPositive()))
|
||||
if (!(nboundary->InZBoundary(1) == boundary.InZBoundary(1)))
|
||||
{
|
||||
this->RaiseError("Got invalid ZPos boundary state");
|
||||
}
|
||||
|
||||
if (!(nboundary->OnZNegative() == boundary.OnZNegative()))
|
||||
if (!(nboundary->InBoundary(1) == boundary.InBoundary(1)))
|
||||
{
|
||||
this->RaiseError("Got invalid ZNeg boundary state");
|
||||
this->RaiseError("Got invalid boundary state");
|
||||
}
|
||||
|
||||
|
||||
if (!(nboundary->OnX() == boundary.OnX()))
|
||||
{
|
||||
this->RaiseError("Got invalid X boundary state");
|
||||
}
|
||||
if (!(nboundary->OnY() == boundary.OnY()))
|
||||
{
|
||||
this->RaiseError("Got invalid Y boundary state");
|
||||
}
|
||||
if (!(nboundary->OnZ() == boundary.OnZ()))
|
||||
{
|
||||
this->RaiseError("Got invalid Z boundary state");
|
||||
}
|
||||
|
||||
auto minNeighbors = boundary.MinNeighborIndices(1);
|
||||
auto maxNeighbors = boundary.MaxNeighborIndices(1);
|
||||
|
||||
ValueType maxV = inputField.Get(0, 0, 0); //our value
|
||||
for (vtkm::IdComponent k = 0; k < 3; ++k)
|
||||
for (vtkm::IdComponent k = minNeighbors[2]; k <= maxNeighbors[2]; ++k)
|
||||
{
|
||||
for (vtkm::IdComponent j = 0; j < 3; ++j)
|
||||
for (vtkm::IdComponent j = minNeighbors[1]; j <= maxNeighbors[1]; ++j)
|
||||
{
|
||||
maxV = vtkm::Max(maxV, inputField.Get(-1, j - 1, k - 1));
|
||||
maxV = vtkm::Max(maxV, inputField.Get(0, j - 1, k - 1));
|
||||
maxV = vtkm::Max(maxV, inputField.Get(1, j - 1, k - 1));
|
||||
for (vtkm::IdComponent i = minNeighbors[0]; i <= maxNeighbors[0]; ++i)
|
||||
{
|
||||
maxV = vtkm::Max(maxV, inputField.Get(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
output = static_cast<FieldOut>(maxV);
|
||||
}
|
||||
};
|
||||
|
||||
struct ScatterIdentityNeighbor : public vtkm::worklet::WorkletPointNeighborhood5x5x5
|
||||
struct ScatterIdentityNeighbor : public vtkm::worklet::WorkletPointNeighborhood
|
||||
{
|
||||
using ControlSignature = void(CellSetIn topology, FieldIn<Vec3> pointCoords);
|
||||
using ExecutionSignature =
|
||||
@ -130,7 +110,7 @@ struct ScatterIdentityNeighbor : public vtkm::worklet::WorkletPointNeighborhood5
|
||||
const vtkm::Id& workIndex,
|
||||
const vtkm::Id& inputIndex,
|
||||
const vtkm::Id& outputIndex,
|
||||
const vtkm::exec::arg::ThreadIndicesPointNeighborhood<2>& vtkmNotUsed(threadIndices),
|
||||
const vtkm::exec::arg::ThreadIndicesPointNeighborhood& vtkmNotUsed(threadIndices),
|
||||
const vtkm::Id& visitIndex) const
|
||||
{
|
||||
if (workIndex != inputIndex)
|
||||
@ -151,7 +131,7 @@ struct ScatterIdentityNeighbor : public vtkm::worklet::WorkletPointNeighborhood5
|
||||
using ScatterType = vtkm::worklet::ScatterIdentity;
|
||||
};
|
||||
|
||||
struct ScatterUniformNeighbor : public vtkm::worklet::WorkletPointNeighborhood5x5x5
|
||||
struct ScatterUniformNeighbor : public vtkm::worklet::WorkletPointNeighborhood
|
||||
{
|
||||
using ControlSignature = void(CellSetIn topology, FieldIn<Vec3> pointCoords);
|
||||
using ExecutionSignature =
|
||||
@ -166,7 +146,7 @@ struct ScatterUniformNeighbor : public vtkm::worklet::WorkletPointNeighborhood5x
|
||||
const vtkm::Id& workIndex,
|
||||
const vtkm::Id& inputIndex,
|
||||
const vtkm::Id& outputIndex,
|
||||
const vtkm::exec::arg::ThreadIndicesPointNeighborhood<2>& vtkmNotUsed(threadIndices),
|
||||
const vtkm::exec::arg::ThreadIndicesPointNeighborhood& vtkmNotUsed(threadIndices),
|
||||
const vtkm::Id& visitIndex) const
|
||||
{
|
||||
if ((workIndex / 3) != inputIndex)
|
||||
|
Loading…
Reference in New Issue
Block a user