Commit 1766f213 authored by Kenneth Moreland's avatar Kenneth Moreland Committed by Kitware Robot

Merge topic 'dynamic-neighborhood-size'

82536092 Rename boundary classes
e008aff2 Change neighborhood parameter from layer to radius
7f627380 Fix Marching Cubes regression test
01a9e854 Change WorkletPointNeighborhood to specify neighborhood at runtime
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard's avatarRobert Maynard <robert.maynard@kitware.com>
Merge-request: !1457
parents 4169ff7d 82536092
......@@ -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>;
......
//============================================================================
// 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 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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_exec_BoundaryState_h
#define vtk_m_exec_BoundaryState_h
#include <vtkm/Math.h>
namespace vtkm
{
namespace exec
{
/// \brief Provides a neighborhood's placement with respect to the mesh's boundary.
///
/// \c BoundaryState provides functionality for \c WorkletPointNeighborhood algorithms and Fetch's
/// to determine if they are operating on a point near the boundary. It allows you to query about
/// overlaps of the neighborhood and the mesh boundary. It also helps convert local neighborhood
/// ids to the corresponding location in the mesh.
///
/// This class is typically constructed using the \c Boundary tag in an \c ExecutionSignature.
/// There is little reason to construct this in user code.
///
struct BoundaryState
{
VTKM_EXEC
BoundaryState(const vtkm::Id3& ijk, const vtkm::Id3& pdims)
: IJK(ijk)
, PointDimensions(pdims)
{
}
//@{
/// Returns true if a neighborhood of the given radius 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.
///
/// The radius defines the size of the neighborhood in terms of how far away it extends from the
/// center. So if there is a radius of 1, the neighborhood extends 1 unit away from the center in
/// each direction and is 3x3x3. If there is a radius of 2, the neighborhood extends 2 units for
/// a size of 5x5x5.
///
VTKM_EXEC bool InXBoundary(vtkm::IdComponent radius) const
{
return (((this->IJK[0] - radius) >= 0) && ((this->IJK[0] + radius) < this->PointDimensions[0]));
}
VTKM_EXEC bool InYBoundary(vtkm::IdComponent radius) const
{
return (((this->IJK[1] - radius) >= 0) && ((this->IJK[1] + radius) < this->PointDimensions[1]));
}
VTKM_EXEC bool InZBoundary(vtkm::IdComponent radius) const
{
return (((this->IJK[2] - radius) >= 0) && ((this->IJK[2] + radius) < this->PointDimensions[2]));
}
//@}
/// Returns true if a neighborhood of the given radius is contained within the bounds
/// of the cell set. Returns false if the neighborhood extends ouside of the boundary of the
/// data.
///
/// The radius defines the size of the neighborhood in terms of how far away it extends from the
/// center. So if there is a radius of 1, the neighborhood extends 1 unit away from the center in
/// each direction and is 3x3x3. If there is a radius of 2, the neighborhood extends 2 units for
/// a size of 5x5x5.
///
VTKM_EXEC bool InBoundary(vtkm::IdComponent radius) const
{
return this->InXBoundary(radius) && this->InYBoundary(radius) && this->InZBoundary(radius);
}
/// Returns the minimum neighborhood indices that are within the bounds of the data.
///
VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 3> MinNeighborIndices(vtkm::IdComponent radius) const
{
vtkm::Vec<vtkm::IdComponent, 3> minIndices;
for (vtkm::IdComponent component = 0; component < 3; ++component)
{
if (this->IJK[component] >= radius)
{
minIndices[component] = -radius;
}
else
{
minIndices[component] = static_cast<vtkm::IdComponent>(-this->IJK[component]);
}
}
return minIndices;
}
/// Returns the minimum neighborhood indices that are within the bounds of the data.
///
VTKM_EXEC vtkm::Vec<vtkm::IdComponent, 3> MaxNeighborIndices(vtkm::IdComponent radius) const
{
vtkm::Vec<vtkm::IdComponent, 3> maxIndices;
for (vtkm::IdComponent component = 0; component < 3; ++component)
{
if ((this->PointDimensions[component] - this->IJK[component] - 1) >= radius)
{
maxIndices[component] = radius;
}
else
{
maxIndices[component] = static_cast<vtkm::IdComponent>(this->PointDimensions[component] -
this->IJK[component] - 1);
}
}
return maxIndices;
}
//todo: This needs to work with BoundaryConstantValue
//todo: This needs to work with BoundaryPeroidic
//@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the ijk of the equivalent point in the full data set. If the given value is out
/// of range, the value is clamped to the nearest boundary. For example, if given a neighbor
/// index that is past the minimum x range of the data, the index at the minimum x boundary is
/// returned.
///
VTKM_EXEC vtkm::Id3 NeighborIndexToFullIndexClamp(
const vtkm::Vec<vtkm::IdComponent, 3>& neighbor) const
{
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,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFullIndexClamp(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
//@}
//todo: This needs to work with BoundaryConstantValue
//todo: This needs to work with BoundaryPeroidic
//@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the flat index of the equivalent point in the full data set. If the given value
/// is out of range, the value is clamped to the nearest boundary. For example, if given a
/// neighbor index that is past the minimum x range of the data, the index at the minimum x
/// boundary is returned.
///
VTKM_EXEC vtkm::Id NeighborIndexToFlatIndexClamp(
const vtkm::Vec<vtkm::IdComponent, 3>& neighbor) const
{
vtkm::Id3 full = this->NeighborIndexToFullIndexClamp(neighbor);
return (full[2] * this->PointDimensions[1] + full[1]) * this->PointDimensions[0] + full[0];
}
VTKM_EXEC vtkm::Id NeighborIndexToFlatIndexClamp(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFlatIndexClamp(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
//@}
vtkm::Id3 IJK;
vtkm::Id3 PointDimensions;
};
}
} // namespace vtkm::exec
#endif //vtk_m_exec_BoundaryState_h
......@@ -20,6 +20,7 @@
set(headers
BoundingIntervalHierarchyExec.h
BoundaryState.h
AtomicArrayExecutionObject.h
CellDerivative.h
CellEdge.h
......@@ -33,6 +34,7 @@ set(headers
ConnectivityPermuted.h
ConnectivityStructured.h
ExecutionWholeArray.h
FieldNeighborhood.h
FunctorBase.h
Jacobian.h
ParametricCoordinates.h
......
//============================================================================
// 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 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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_exec_FieldNeighborhood_h
#define vtk_m_exec_FieldNeighborhood_h
#include <vtkm/exec/BoundaryState.h>
#include <vtkm/internal/ArrayPortalUniformPointCoordinates.h>
namespace vtkm
{
namespace exec
{
/// \brief Retrieves field values from a neighborhood.
///
/// \c FieldNeighborhood manages the retrieval of field values within the neighborhood of a
/// \c WorkletPointNeighborhood worklet. The \c Get methods take ijk indices relative to the
/// neighborhood (with 0, 0, 0 being the element visted) and return the field value at that part of
/// the neighborhood. If the requested neighborhood is outside the boundary, a different value will
/// be returned determined by the boundary behavior. A \c BoundaryState object can be used to
/// determine if the neighborhood extends beyond the boundary of the mesh.
///
/// This class is typically constructued using the \c FieldInNeighborhood tag in an
/// \c ExecutionSignature. There is little reason to construct this in user code.
///
/// \c FieldNeighborhood is templated on the array portal from which field values are retrieved.
///
template <typename FieldPortalType>
struct FieldNeighborhood
{
VTKM_EXEC
FieldNeighborhood(const FieldPortalType& portal, const vtkm::exec::BoundaryState& boundary)
: Boundary(&boundary)
, Portal(portal)
{
}
using ValueType = typename FieldPortalType::ValueType;
VTKM_EXEC
ValueType Get(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const
{
return Portal.Get(this->Boundary->NeighborIndexToFlatIndexClamp(i, j, k));
}
VTKM_EXEC
ValueType Get(const vtkm::Id3& ijk) const
{
return Portal.Get(this->Boundary->NeighborIndexToFlatIndexClamp(ijk));
}
vtkm::exec::BoundaryState const* const Boundary;
FieldPortalType Portal;
};
/// \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 <>
struct FieldNeighborhood<vtkm::internal::ArrayPortalUniformPointCoordinates>
{
VTKM_EXEC
FieldNeighborhood(const vtkm::internal::ArrayPortalUniformPointCoordinates& portal,
const vtkm::exec::BoundaryState& boundary)
: Boundary(&boundary)
, Portal(portal)
{
}
using ValueType = vtkm::internal::ArrayPortalUniformPointCoordinates::ValueType;
VTKM_EXEC
ValueType Get(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const
{
return Portal.Get(this->Boundary->NeighborIndexToFullIndexClamp(i, j, k));
}
VTKM_EXEC
ValueType Get(const vtkm::Vec<vtkm::IdComponent, 3>& ijk) const
{
return Portal.Get(this->Boundary->NeighborIndexToFullIndexClamp(ijk));
}
vtkm::exec::BoundaryState const* const Boundary;
vtkm::internal::ArrayPortalUniformPointCoordinates Portal;
};
}
} // namespace vtkm::exec
#endif //vtk_m_exec_FieldNeighborhood_h
......@@ -33,31 +33,31 @@ namespace arg
/// \brief Aspect tag to use for getting if a point is a boundary point.
///
/// The \c AspectTagOnBoundary aspect tag causes the \c Fetch class to obtain
/// The \c AspectTagBoundary aspect tag causes the \c Fetch class to obtain
/// if the point is on a boundary.
///
struct AspectTagOnBoundary
struct AspectTagBoundary
{
};
/// \brief The \c ExecutionSignature tag to get if executing on a boundary element
///
struct OnBoundary : vtkm::exec::arg::ExecutionSignatureTagBase
struct Boundary : vtkm::exec::arg::ExecutionSignatureTagBase
{
static constexpr vtkm::IdComponent INDEX = 1;
using AspectTag = vtkm::exec::arg::AspectTagOnBoundary;
using AspectTag = vtkm::exec::arg::AspectTagBoundary;
};
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::AspectTagBoundary,
vtkm::exec::arg::ThreadIndicesPointNeighborhood,
ExecObjectType>
{
using ThreadIndicesType = vtkm::exec::arg::ThreadIndicesPointNeighborhood<NSize>;
using ThreadIndicesType = vtkm::exec::arg::ThreadIndicesPointNeighborhood;
using ValueType = vtkm::exec::arg::BoundaryState;
using ValueType = vtkm::exec::BoundaryState;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
......
......@@ -21,6 +21,7 @@
set(headers
AspectTagDefault.h
BasicArg.h
Boundary.h
CellShape.h
ExecutionSignatureTagBase.h
Fetch.h
......@@ -36,7 +37,6 @@ set(headers
FromCount.h
FromIndices.h
InputIndex.h
OnBoundary.h
OutputIndex.h
ThreadIndices.h
ThreadIndicesBasic.h
......
......@@ -20,10 +20,10 @@
#ifndef vtk_m_exec_arg_FetchTagArrayNeighborhoodIn_h
#define vtk_m_exec_arg_FetchTagArrayNeighborhoodIn_h
#include <vtkm/exec/FieldNeighborhood.h>
#include <vtkm/exec/arg/AspectTagDefault.h>
#include <vtkm/exec/arg/Fetch.h>
#include <vtkm/exec/arg/ThreadIndicesPointNeighborhood.h>
#include <vtkm/internal/ArrayPortalUniformPointCoordinates.h>
namespace vtkm
{
......@@ -37,85 +37,18 @@ 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>
struct Neighborhood
{
VTKM_EXEC
Neighborhood(const ExecObjectType& portal, const vtkm::exec::arg::BoundaryState& boundary)
: Boundary(&boundary)
, Portal(portal)
{
}
using ValueType = typename ExecObjectType::ValueType;
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));
}
vtkm::exec::arg::BoundaryState const* const Boundary;
ExecObjectType Portal;
};
/// \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>
{
VTKM_EXEC
Neighborhood(const vtkm::internal::ArrayPortalUniformPointCoordinates& portal,
const vtkm::exec::arg::BoundaryState& boundary)
: Boundary(&boundary)
, Portal(portal)
{
}
using ValueType = vtkm::internal::ArrayPortalUniformPointCoordinates::ValueType;
VTKM_EXEC
ValueType Get(vtkm::IdComponent i, vtkm::IdComponent j, vtkm::IdComponent k) const
{
return Portal.Get(this->Boundary->NeighborIndexToFullIndexClamp(i, j, k));
}
VTKM_EXEC
ValueType Get(const vtkm::Vec<vtkm::IdComponent, 3>& ijk) const
{
return Portal.Get(this->Boundary->NeighborIndexToFullIndexClamp(ijk));
}
vtkm::exec::arg::BoundaryState const* const Boundary;
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 = vtkm::exec::FieldNeighborhood<ExecObjectType>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
......
......@@ -20,6 +20,7 @@
#ifndef vtk_m_exec_arg_ThreadIndicesPointNeighborhood_h
#define vtk_m_exec_arg_ThreadIndicesPointNeighborhood_h
#include <vtkm/exec/BoundaryState.h>
#include <vtkm/exec/ConnectivityStructured.h>
#include <vtkm/exec/arg/ThreadIndicesBasic.h>
#include <vtkm/exec/arg/ThreadIndicesTopologyMap.h> //for Deflate and Inflate
......@@ -33,159 +34,6 @@ namespace exec
namespace arg
{
/// \brief Provides information if the current point is a boundary point
/// Provides functionality for WorkletPointNeighborhood algorithms
/// and Fetch's to determine if they are operating on a boundary point
//Todo we need to have this class handle different BoundaryTypes
struct BoundaryState
{
VTKM_EXEC
BoundaryState(const vtkm::Id3& ijk, const vtkm::Id3& pdims, int neighborhoodSize)
: 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)
///
VTKM_EXEC vtkm::IdComponent MinNeighborX() const { return this->MinNeighborhood[0]; }
/// Returns the minimum neighbor index in the Z direction (between -neighborhood size and 0)
///
VTKM_EXEC vtkm::IdComponent MinNeighborY() const { return this->MinNeighborhood[1]; }
/// Returns the minimum neighbor index in the Z direction (between -neighborhood size and 0)
///
VTKM_EXEC vtkm::IdComponent MinNeighborZ() const { return this->MinNeighborhood[2]; }
/// Returns the maximum neighbor index in the X direction (between 0 and neighborhood size)
///
VTKM_EXEC vtkm::IdComponent MaxNeighborX() const { return this->MaxNeighborhood[0]; }
/// Returns the maximum neighbor index in the Z direction (between 0 and neighborhood size)
///
VTKM_EXEC vtkm::IdComponent MaxNeighborY() const { return this->MaxNeighborhood[1]; }
/// Returns the maximum neighbor index in the Z direction (between 0 and neighborhood size)
///
VTKM_EXEC vtkm::IdComponent MaxNeighborZ() const { return this->MaxNeighborhood[2]; }
/// Returns true if the neighborhood extends past the positive X direction.
///
VTKM_EXEC bool OnXPositive() const { return this->MaxNeighborX() < this->NeighborhoodSize; }
/// 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(); }
//todo: This needs to work with BoundaryConstantValue
//todo: This needs to work with BoundaryPeroidic
//@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the ijk of the equivalent point in the full data set. If the given value is out
/// of range, the value is clamped to the nearest boundary. For example, if given a neighbor
/// index that is past the minimum x range of the data, the index at the minimum x boundary is
/// returned.
///
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_EXEC vtkm::Id3 NeighborIndexToFullIndexClamp(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFullIndexClamp(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
//@}
//todo: This needs to work with BoundaryConstantValue
//todo: This needs to work with BoundaryPeroidic
//@{
/// Takes a local neighborhood index (in the ranges of -neighborhood size to neighborhood size)
/// and returns the flat index of the equivalent point in the full data set. If the given value
/// is out of range, the value is clamped to the nearest boundary. For example, if given a
/// neighbor index that is past the minimum x range of the data, the index at the minimum x
/// boundary is returned.
///
VTKM_EXEC vtkm::Id NeighborIndexToFlatIndexClamp(
const vtkm::Vec<vtkm::IdComponent, 3>& neighbor) const
{
vtkm::Id3 full = this->NeighborIndexToFullIndexClamp(neighbor);
return (full[2] * this->PointDimensions[1] + full[1]) * this->PointDimensions[0] + full[0];
}
VTKM_EXEC vtkm::Id NeighborIndexToFlatIndexClamp(vtkm::IdComponent neighborI,
vtkm::IdComponent neighborJ,
vtkm::IdComponent neighborK) const
{
return this->NeighborIndexToFlatIndexClamp(vtkm::make_Vec(neighborI, neighborJ, neighborK));
}
//@}
vtkm::Id3 IJK;
vtkm::Id3 PointDimensions;
vtkm::Vec<vtkm::IdComponent, 3> MinNeighborhood;
vtkm::Vec<vtkm::IdComponent, 3> MaxNeighborhood;
vtkm::IdComponent NeighborhoodSize;
};
namespace detail
{
/// Given a \c Vec of (semi) arbitrary size, inflate it to a vtkm::Id3 by padding with zeros.
......@@ -213,7 +61,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 +74,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 +99,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 +117,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)
......@@ -281,7 +126,7 @@ public:
}
VTKM_EXEC
const BoundaryState& GetBoundaryState() const { return this->State; }
const vtkm::exec::BoundaryState& GetBoundaryState() const { return this->State; }
VTKM_EXEC
vtkm::Id GetInputIndex() const { return this->InputIndex; }
......@@ -302,7 +147,7 @@ public:
vtkm::Id GetGlobalIndex() const { return (this->GlobalThreadIndexOffset + this->OutputIndex); }
private:
BoundaryState State;
vtkm::exec::BoundaryState State;
vtkm::Id InputIndex;
vtkm::Id OutputIndex;
vtkm::IdComponent VisitIndex;
......