Merge topic 'dynamic-neighborhood-size'

82536092c Rename boundary classes
e008aff27 Change neighborhood parameter from layer to radius
7f627380b Fix Marching Cubes regression test
01a9e8541 Change WorkletPointNeighborhood to specify neighborhood at runtime

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robert.maynard@kitware.com>
Merge-request: !1457
This commit is contained in:
Kenneth Moreland 2018-12-04 21:02:35 +00:00 committed by Kitware Robot
commit 1766f213ea
15 changed files with 419 additions and 357 deletions

@ -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>;

188
vtkm/exec/BoundaryState.h Normal file

@ -0,0 +1,188 @@
//============================================================================
// 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

@ -0,0 +1,107 @@
//============================================================================
// 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;

@ -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);

@ -440,14 +440,14 @@ void TestNormals(const vtkm::cont::DataSet& dataset, bool structured)
//Calculated using StructuredPointGradient
const vtkm::Vec<vtkm::FloatDefault, 3> hq_sg[numVerts] = {
{ 0.165519f, 0.687006f, 0.707549f }, { 0.188441f, -0.561729f, 0.805574f },
{ 0.179543f, 0.702158f, 0.689012f }, { 0.271085f, 0.692957f, 0.668074f },
{ 0.00313049f, 0.720109f, 0.693854f }, { 0.549947f, -0.551974f, 0.626804f },
{ -0.447526f, -0.588187f, 0.673614f }, { 0.167553f, -0.779396f, 0.603711f },
{ 0.179543f, 0.702158f, -0.689012f }, { 0.271085f, 0.692957f, -0.668074f },
{ 0.00313049f, 0.720109f, -0.693854f }, { 0.165519f, 0.687006f, -0.707549f },
{ 0.549947f, -0.551974f, -0.626804f }, { -0.447526f, -0.588187f, -0.673614f },
{ 0.167553f, -0.779396f, -0.603711f }, { 0.188441f, -0.561729f, -0.805574f }
{ 0.151008f, 0.626778f, 0.764425f }, { 0.133328f, -0.397444f, 0.907889f },
{ 0.162649f, 0.764163f, 0.624180f }, { 0.385327f, 0.664323f, 0.640467f },
{ -0.133720f, 0.713645f, 0.687626f }, { 0.770536f, -0.421248f, 0.478356f },
{ -0.736036f, -0.445244f, 0.509910f }, { 0.123446f, -0.887088f, 0.444788f },
{ 0.162649f, 0.764163f, -0.624180f }, { 0.385327f, 0.664323f, -0.640467f },
{ -0.133720f, 0.713645f, -0.687626f }, { 0.151008f, 0.626778f, -0.764425f },
{ 0.770536f, -0.421248f, -0.478356f }, { -0.736036f, -0.445244f, -0.509910f },
{ 0.123446f, -0.887088f, -0.444788f }, { 0.133328f, -0.397444f, -0.907889f }
};
//Calculated using normals of the output triangles
@ -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::FieldNeighborhood<decltype(pointPortal)> points(pointPortal, boundary);
vtkm::exec::FieldNeighborhood<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::FieldNeighborhood<decltype(pointPortal)> points(pointPortal, boundary);
vtkm::exec::FieldNeighborhood<decltype(fieldPortal)> field(fieldPortal, boundary);
vtkm::worklet::gradient::StructuredPointGradient<T> gradient;
NormalType grad1;

@ -39,12 +39,12 @@
#include <vtkm/cont/arg/TypeCheckTagArray.h>
#include <vtkm/cont/arg/TypeCheckTagCellSetStructured.h>
#include <vtkm/exec/arg/Boundary.h>
#include <vtkm/exec/arg/FetchTagArrayDirectIn.h>
#include <vtkm/exec/arg/FetchTagArrayDirectInOut.h>
#include <vtkm/exec/arg/FetchTagArrayDirectOut.h>
#include <vtkm/exec/arg/FetchTagArrayNeighborhoodIn.h>
#include <vtkm/exec/arg/FetchTagCellSetIn.h>
#include <vtkm/exec/arg/OnBoundary.h>
#include <vtkm/exec/arg/ThreadIndicesPointNeighborhood.h>
#include <vtkm/worklet/ScatterIdentity.h>
@ -87,16 +87,16 @@ public:
template <typename Worklet>
using Dispatcher = vtkm::worklet::DispatcherPointNeighborhood<Worklet>;
/// \brief The \c ExecutionSignature tag to get if you the current iteration is on a boundary.
/// \brief The \c ExecutionSignature tag to query if the current iteration is inside the boundary.
///
/// A \c WorkletPointNeighborhood operates by iterating over all points using
/// a defined neighborhood. This \c ExecutionSignature tag provides different
/// types when you are on or off a boundary, allowing for separate code paths
/// just for handling boundaries.
/// A \c WorkletPointNeighborhood operates by iterating over all points using a defined
/// neighborhood. This \c ExecutionSignature tag provides a \c BoundaryState object that allows
/// you to query whether the neighborhood of the current iteration is completely inside the
/// bounds of the mesh or if it extends beyond the mesh. This is important as when you are on a
/// boundary the neighboordhood will contain empty values for a certain subset of values, and in
/// this case the values returned will depend on the boundary behavior.
///
/// This is important as when you are on a boundary the neighboordhood will
/// contain empty values for a certain subset of values
struct OnBoundary : vtkm::exec::arg::OnBoundary
struct Boundary : vtkm::exec::arg::Boundary
{
};
@ -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,
@ -46,12 +46,12 @@ struct StructuredPointGradient : public vtkm::worklet::WorkletPointNeighborhood3
FieldInNeighborhood<StructuredPointGradientInType<T>>,
GradientOutputs outputFields);
using ExecutionSignature = void(OnBoundary, _2, _3, _4);
using ExecutionSignature = void(Boundary, _2, _3, _4);
using InputDomain = _1;
template <typename PointsIn, typename FieldIn, typename GradientOutType>
VTKM_EXEC void operator()(const vtkm::exec::arg::BoundaryState& boundary,
VTKM_EXEC void operator()(const vtkm::exec::BoundaryState& boundary,
const PointsIn& inputPoints,
const FieldIn& inputField,
GradientOutType& outputGradient) const
@ -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::BoundaryState& boundary,
const vtkm::exec::FieldNeighborhood<
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::FieldNeighborhood<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);
@ -113,7 +112,7 @@ struct StructuredPointGradient : public vtkm::worklet::WorkletPointNeighborhood3
//will be float,3 even when T is a 3 component field
template <typename PointsIn, typename CT>
VTKM_EXEC void Jacobian(const PointsIn& inputPoints,
const vtkm::exec::arg::BoundaryState& boundary,
const vtkm::exec::BoundaryState& boundary,
vtkm::Vec<CT, 3>& m_xi,
vtkm::Vec<CT, 3>& m_eta,
vtkm::Vec<CT, 3>& m_zeta) const
@ -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,86 +36,66 @@
namespace test_pointneighborhood
{
struct MaxNeighborValue : public vtkm::worklet::WorkletPointNeighborhood3x3x3
struct MaxNeighborValue : public vtkm::worklet::WorkletPointNeighborhood
{
using ControlSignature = void(FieldInNeighborhood<Scalar> neighbors,
CellSetIn,
FieldOut<Scalar> maxV);
using ExecutionSignature = void(OnBoundary, _1, _3);
using ExecutionSignature = void(Boundary, _1, _3);
//verify input domain can be something other than first parameter
using InputDomain = _2;
template <typename FieldIn, typename FieldOut>
VTKM_EXEC void operator()(const vtkm::exec::arg::BoundaryState& boundary,
const vtkm::exec::arg::Neighborhood<1, FieldIn>& inputField,
VTKM_EXEC void operator()(const vtkm::exec::BoundaryState& boundary,
const vtkm::exec::FieldNeighborhood<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)