mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
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:
commit
1766f213ea
@ -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
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
|
||||
|
107
vtkm/exec/FieldNeighborhood.h
Normal file
107
vtkm/exec/FieldNeighborhood.h
Normal file
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user