Switch from faux to true virtuals

This commit is contained in:
Sujin Philip 2017-10-23 09:38:33 -04:00
parent 280ea84990
commit 8c242cef91
43 changed files with 1533 additions and 1615 deletions

@ -35,6 +35,7 @@ set(headers
CellShape.h
CellTraits.h
Hash.h
ImplicitFunction.h
ListTag.h
Math.h
Matrix.h
@ -55,6 +56,7 @@ set(headers
VectorAnalysis.h
VecTraits.h
VecVariable.h
VirtualObjectBase.h
UnaryPredicates.h
)

643
vtkm/ImplicitFunction.h Normal file

@ -0,0 +1,643 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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_ImplicitFunction_h
#define vtk_m_ImplicitFunction_h
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/VirtualObjectBase.h>
namespace vtkm
{
//============================================================================
class VTKM_ALWAYS_EXPORT ImplicitFunction : public vtkm::VirtualObjectBase
{
public:
using Scalar = vtkm::FloatDefault;
using Vector = vtkm::Vec<Scalar, 3>;
VTKM_EXEC_CONT virtual Scalar Value(const Vector& point) const = 0;
VTKM_EXEC_CONT virtual Vector Gradient(const Vector& point) const = 0;
VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const
{
return this->Value(Vector(x, y, z));
}
VTKM_EXEC_CONT Vector Gradient(Scalar x, Scalar y, Scalar z) const
{
return this->Gradient(Vector(x, y, z));
}
};
//============================================================================
/// A helpful functor that calls the (virtual) value method of a given ImplicitFunction. Can be
/// passed to things that expect a functor instead of an ImplictFunction class (like an array
/// transform).
///
class VTKM_ALWAYS_EXPORT ImplicitFunctionValue
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
using Vector = vtkm::ImplicitFunction::Vector;
VTKM_EXEC_CONT ImplicitFunctionValue()
: Function(nullptr)
{
}
VTKM_EXEC_CONT ImplicitFunctionValue(const ImplicitFunction* function)
: Function(function)
{
}
VTKM_EXEC_CONT Scalar operator()(const Vector& point) const
{
return this->Function->Value(point);
}
private:
const vtkm::ImplicitFunction* Function;
};
/// A helpful functor that calls the (virtual) gradient method of a given ImplicitFunction. Can be
/// passed to things that expect a functor instead of an ImplictFunction class (like an array
/// transform).
///
class VTKM_ALWAYS_EXPORT ImplicitFunctionGradient
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
using Vector = vtkm::ImplicitFunction::Vector;
VTKM_EXEC_CONT ImplicitFunctionGradient()
: Function(nullptr)
{
}
VTKM_EXEC_CONT ImplicitFunctionGradient(const ImplicitFunction* function)
: Function(function)
{
}
VTKM_EXEC_CONT Vector operator()(const Vector& point) const
{
return this->Function->Gradient(point);
}
private:
const vtkm::ImplicitFunction* Function;
};
//============================================================================
/// \brief Implicit function for a box
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunction
{
public:
VTKM_EXEC_CONT Box()
: MinPoint(Vector(Scalar(0)))
, MaxPoint(Vector(Scalar(0)))
{
}
VTKM_EXEC_CONT Box(const Vector& minPoint, const Vector& maxPoint)
: MinPoint(minPoint)
, MaxPoint(maxPoint)
{
}
VTKM_EXEC_CONT Box(Scalar xmin, Scalar xmax, Scalar ymin, Scalar ymax, Scalar zmin, Scalar zmax)
: MinPoint(xmin, ymin, zmin)
, MaxPoint(xmax, ymax, zmax)
{
}
VTKM_CONT void SetMinPoint(const Vector& point)
{
this->MinPoint = point;
this->Modified();
}
VTKM_CONT void SetMaxPoint(const Vector& point)
{
this->MaxPoint = point;
this->Modified();
}
VTKM_EXEC_CONT const Vector& GetMinPoint() const { return this->MinPoint; }
VTKM_EXEC_CONT const Vector& GetMaxPoint() const { return this->MaxPoint; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
Scalar minDistance = vtkm::NegativeInfinity32();
Scalar diff, t, dist;
Scalar distance = Scalar(0.0);
vtkm::IdComponent inside = 1;
for (vtkm::IdComponent d = 0; d < 3; d++)
{
diff = this->MaxPoint[d] - this->MinPoint[d];
if (diff != Scalar(0.0))
{
t = (point[d] - this->MinPoint[d]) / diff;
// Outside before the box
if (t < Scalar(0.0))
{
inside = 0;
dist = this->MinPoint[d] - point[d];
}
// Outside after the box
else if (t > Scalar(1.0))
{
inside = 0;
dist = point[d] - this->MaxPoint[d];
}
else
{
// Inside the box in lower half
if (t <= Scalar(0.5))
{
dist = MinPoint[d] - point[d];
}
// Inside the box in upper half
else
{
dist = point[d] - MaxPoint[d];
}
if (dist > minDistance)
{
minDistance = dist;
}
}
}
else
{
dist = vtkm::Abs(point[d] - MinPoint[d]);
if (dist > Scalar(0.0))
{
inside = 0;
}
}
if (dist > Scalar(0.0))
{
distance += dist * dist;
}
}
distance = vtkm::Sqrt(distance);
if (inside)
{
return minDistance;
}
else
{
return distance;
}
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const override
{
vtkm::IdComponent minAxis = 0;
Scalar dist = 0.0;
Scalar minDist = vtkm::Infinity32();
vtkm::Vec<vtkm::IdComponent, 3> location;
Vector normal(Scalar(0));
Vector inside(Scalar(0));
Vector outside(Scalar(0));
Vector center((this->MaxPoint + this->MinPoint) * Scalar(0.5));
// Compute the location of the point with respect to the box
// Point will lie in one of 27 separate regions around or within the box
// Gradient vector is computed differently in each of the regions.
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (point[d] < this->MinPoint[d])
{
// Outside the box low end
location[d] = 0;
outside[d] = -1.0;
}
else if (point[d] > this->MaxPoint[d])
{
// Outside the box high end
location[d] = 2;
outside[d] = 1.0;
}
else
{
location[d] = 1;
if (point[d] <= center[d])
{
// Inside the box low end
dist = point[d] - this->MinPoint[d];
inside[d] = -1.0;
}
else
{
// Inside the box high end
dist = this->MaxPoint[d] - point[d];
inside[d] = 1.0;
}
if (dist < minDist) // dist is negative
{
minDist = dist;
minAxis = d;
}
}
}
vtkm::Id indx = location[0] + 3 * location[1] + 9 * location[2];
switch (indx)
{
// verts - gradient points away from center point
case 0:
case 2:
case 6:
case 8:
case 18:
case 20:
case 24:
case 26:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = point[d] - center[d];
}
vtkm::Normalize(normal);
break;
// edges - gradient points out from axis of cube
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 15:
case 17:
case 19:
case 21:
case 23:
case 25:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (outside[d] != 0.0)
{
normal[d] = point[d] - center[d];
}
else
{
normal[d] = 0.0;
}
}
vtkm::Normalize(normal);
break;
// faces - gradient points perpendicular to face
case 4:
case 10:
case 12:
case 14:
case 16:
case 22:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = outside[d];
}
break;
// interior - gradient is perpendicular to closest face
case 13:
normal[0] = normal[1] = normal[2] = 0.0;
normal[minAxis] = inside[minAxis];
break;
default:
VTKM_ASSERT(false);
break;
}
return normal;
}
private:
Vector MinPoint;
Vector MaxPoint;
};
//============================================================================
/// \brief Implicit function for a cylinder
class VTKM_ALWAYS_EXPORT Cylinder : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Cylinder()
: Center(Scalar(0))
, Axis(Scalar(1), Scalar(0), Scalar(0))
, Radius(Scalar(0.2))
{
}
VTKM_EXEC_CONT Cylinder(const Vector& axis, Scalar radius)
: Center(Scalar(0))
, Axis(axis)
, Radius(radius)
{
}
VTKM_EXEC_CONT Cylinder(const Vector& center, const Vector& axis, Scalar radius)
: Center(center)
, Axis(axis)
, Radius(radius)
{
}
VTKM_CONT void SetCenter(const Vector& center)
{
this->Center = center;
this->Modified();
}
VTKM_CONT void SetAxis(const Vector& axis)
{
this->Axis = axis;
this->Modified();
}
VTKM_CONT void SetRadius(Scalar radius)
{
this->Radius = radius;
this->Modified();
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
Vector x2c = point - this->Center;
FloatDefault proj = vtkm::dot(this->Axis, x2c);
return vtkm::dot(x2c, x2c) - (proj * proj) - (this->Radius * this->Radius);
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const override
{
Vector x2c = point - this->Center;
FloatDefault t = this->Axis[0] * x2c[0] + this->Axis[1] * x2c[1] + this->Axis[2] * x2c[2];
vtkm::Vec<FloatDefault, 3> closestPoint = this->Center + (this->Axis * t);
return (point - closestPoint) * FloatDefault(2);
}
private:
Vector Center;
Vector Axis;
Scalar Radius;
};
//============================================================================
/// \brief Implicit function for a frustum
class VTKM_ALWAYS_EXPORT Frustum : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Frustum() = default;
VTKM_EXEC_CONT Frustum(const Vector points[6], const Vector normals[6])
{
this->SetPlanes(points, normals);
}
VTKM_EXEC_CONT explicit Frustum(const Vector points[8]) { this->CreateFromPoints(points); }
VTKM_EXEC void SetPlanes(const Vector points[6], const Vector normals[6])
{
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
this->Points[index] = points[index];
}
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
this->Normals[index] = normals[index];
}
this->Modified();
}
VTKM_EXEC void SetPlane(int idx, const Vector& point, const Vector& normal)
{
VTKM_ASSERT((idx >= 0) && (idx < 6));
this->Points[idx] = point;
this->Normals[idx] = normal;
this->Modified();
}
VTKM_EXEC_CONT void GetPlanes(Vector points[6], Vector normals[6]) const
{
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
points[index] = this->Points[index];
}
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
normals[index] = this->Normals[index];
}
}
VTKM_EXEC_CONT const Vector* GetPoints() const { return this->Points; }
VTKM_EXEC_CONT const Vector* GetNormals() const { return this->Normals; }
// The points should be specified in the order of hex-cell vertices
VTKM_EXEC_CONT void CreateFromPoints(const Vector points[8])
{
// XXX(clang-format-3.9): 3.8 is silly. 3.9 makes it look like this.
// clang-format off
int planes[6][3] = {
{ 3, 2, 0 }, { 4, 5, 7 }, { 0, 1, 4 }, { 1, 2, 5 }, { 2, 3, 6 }, { 3, 0, 7 }
};
// clang-format on
for (int i = 0; i < 6; ++i)
{
const Vector& v0 = points[planes[i][0]];
const Vector& v1 = points[planes[i][1]];
const Vector& v2 = points[planes[i][2]];
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::Cross(v2 - v0, v1 - v0));
}
this->Modified();
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
const Vector& p = this->Points[index];
const Vector& n = this->Normals[index];
const Scalar val = vtkm::dot(point - p, n);
maxVal = vtkm::Max(maxVal, val);
}
return maxVal;
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const override
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
vtkm::Id maxValIdx = 0;
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
const Vector& p = this->Points[index];
const Vector& n = this->Normals[index];
Scalar val = vtkm::dot(point - p, n);
if (val > maxVal)
{
maxVal = val;
maxValIdx = index;
}
}
return this->Normals[maxValIdx];
}
private:
Vector Points[6];
Vector Normals[6];
};
//============================================================================
/// \brief Implicit function for a plane
class VTKM_ALWAYS_EXPORT Plane : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Plane()
: Origin(Scalar(0))
, Normal(Scalar(0), Scalar(0), Scalar(1))
{
}
VTKM_EXEC_CONT explicit Plane(const Vector& normal)
: Origin(Scalar(0))
, Normal(normal)
{
}
VTKM_EXEC_CONT Plane(const Vector& origin, const Vector& normal)
: Origin(origin)
, Normal(normal)
{
}
VTKM_CONT void SetOrigin(const Vector& origin)
{
this->Origin = origin;
this->Modified();
}
VTKM_CONT void SetNormal(const Vector& normal)
{
this->Normal = normal;
this->Modified();
}
VTKM_EXEC_CONT const Vector& GetOrigin() const { return this->Origin; }
VTKM_EXEC_CONT const Vector& GetNormal() const { return this->Normal; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
return vtkm::dot(point - this->Origin, this->Normal);
}
VTKM_EXEC_CONT Vector Gradient(const Vector&) const override { return this->Normal; }
private:
Vector Origin;
Vector Normal;
};
//============================================================================
/// \brief Implicit function for a sphere
class VTKM_ALWAYS_EXPORT Sphere : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Sphere()
: Radius(Scalar(0.2))
, Center(Scalar(0))
{
}
VTKM_EXEC_CONT explicit Sphere(Scalar radius)
: Radius(radius)
, Center(Scalar(0))
{
}
VTKM_EXEC_CONT Sphere(Vector center, Scalar radius)
: Radius(radius)
, Center(center)
{
}
VTKM_CONT void SetRadius(Scalar radius)
{
this->Radius = radius;
this->Modified();
}
VTKM_CONT void SetCenter(const Vector& center)
{
this->Center = center;
this->Modified();
}
VTKM_EXEC_CONT Scalar GetRadius() const { return this->Radius; }
VTKM_EXEC_CONT const Vector& GetCenter() const { return this->Center; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
return vtkm::MagnitudeSquared(point - this->Center) - (this->Radius * this->Radius);
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const override
{
return Scalar(2) * (point - this->Center);
}
private:
Scalar Radius;
Vector Center;
};
} // namespace vtkm
#ifdef VTKM_CUDA
// Cuda seems to have a bug where it expects the template class VirtualObjectTransfer
// to be instantiated in a consitent order among all the translation units of an
// executable. Failing to do so results in random crashes and incorrect results.
// We workaroud this issue by explicitly instantiating VirtualObjectTransfer for
// all the implicit functions here.
#include <vtkm/cont/cuda/internal/VirtualObjectTransferCuda.h>
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Box);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Cylinder);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Frustum);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Plane);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Sphere);
#endif
#endif //vtk_m_ImplicitFunction_h

82
vtkm/VirtualObjectBase.h Normal file

@ -0,0 +1,82 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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_VirtualObjectBase_h
#define vtk_m_VirtualObjectBase_h
#include <vtkm/Types.h>
namespace vtkm
{
/// \brief Base class for virtual objects that work in the execution environment
///
/// Any class built in VTK-m that has virtual methods and is intended to work in both the control
/// and execution environment should inherit from \c VirtualObjectBase. Hierarchies under \c
/// VirtualObjectBase can be used in conjunction with \c VirtualObjectHandle to transfer from the
/// control environment (where they are set up) to the execution environment (where they are used).
///
/// In addition to inheriting from \c VirtualObjectBase, virtual objects have to satisfy 2 other
/// conditions to work correctly. First, they have to be a plain old data type that can be copied
/// with \c memcpy (with the exception of the virtual table, which \c VirtualObjectHandle will take
/// care of). Second, if the object changes its state in the control environment, it should call
/// \c Modified on itself so the \c VirtualObjectHandle will know it update the object in the
/// execution environment.
///
class VTKM_ALWAYS_EXPORT VirtualObjectBase
{
public:
VTKM_EXEC_CONT virtual ~VirtualObjectBase() = default;
VTKM_EXEC_CONT void Modified() { this->ModifiedCount++; }
VTKM_EXEC_CONT vtkm::Id GetModifiedCount() const { return this->ModifiedCount; }
protected:
VTKM_EXEC_CONT VirtualObjectBase()
: ModifiedCount(0)
{
}
VTKM_EXEC_CONT VirtualObjectBase(const VirtualObjectBase&) = default;
VTKM_EXEC_CONT VirtualObjectBase(VirtualObjectBase&& other)
: ModifiedCount(other.ModifiedCount)
{
}
VTKM_EXEC_CONT VirtualObjectBase& operator=(const VirtualObjectBase&)
{
this->Modified();
return *this;
}
VTKM_EXEC_CONT VirtualObjectBase& operator=(VirtualObjectBase&&)
{
this->Modified();
return *this;
}
private:
vtkm::Id ModifiedCount;
};
} // namespace vtkm
#endif //vtk_m_VirtualObjectBase_h

@ -24,7 +24,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/worklet/DispatcherMapField.h>
@ -264,7 +264,7 @@ public:
typedef void ControlSignature(FieldIn<Vec3>, FieldOut<Scalar>);
typedef void ExecutionSignature(_1, _2);
EvaluateImplicitFunction(const ImplicitFunction& function)
EvaluateImplicitFunction(const ImplicitFunction* function)
: Function(function)
{
}
@ -272,11 +272,11 @@ public:
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function.Value(point);
val = this->Function->Value(point);
}
private:
ImplicitFunction Function;
const ImplicitFunction* Function;
};
template <typename T1, typename T2>
@ -286,7 +286,7 @@ public:
typedef void ControlSignature(FieldIn<Vec3>, FieldOut<Scalar>);
typedef void ExecutionSignature(_1, _2);
Evaluate2ImplicitFunctions(const T1& f1, const T2& f2)
Evaluate2ImplicitFunctions(const T1* f1, const T2* f2)
: Function1(f1)
, Function2(f2)
{
@ -295,12 +295,12 @@ public:
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function1.Value(point) + this->Function2.Value(point);
val = this->Function1->Value(point) + this->Function2->Value(point);
}
private:
T1 Function1;
T2 Function2;
const T1* Function1;
const T2* Function2;
};
struct ValueTypes : vtkm::ListTagBase<vtkm::Float32, vtkm::Float64>
@ -680,7 +680,7 @@ private:
{
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> Points;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Result;
vtkm::cont::Sphere Sphere1, Sphere2;
vtkm::Sphere Sphere1, Sphere2;
};
static ImplicitFunctionBenchData MakeImplicitFunctionBenchData()
@ -703,8 +703,8 @@ private:
portal.Set(i, vtkm::make_Vec(distx(rangen), disty(rangen), distz(rangen)));
}
data.Sphere1 = vtkm::cont::Sphere({ 0.22f, 0.33f, 0.44f }, 0.55f);
data.Sphere2 = vtkm::cont::Sphere({ 0.22f, 0.33f, 0.11f }, 0.77f);
data.Sphere1 = vtkm::Sphere({ 0.22f, 0.33f, 0.44f }, 0.55f);
data.Sphere2 = vtkm::Sphere({ 0.22f, 0.33f, 0.11f }, 0.77f);
return data;
}
@ -720,10 +720,13 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::cont::Sphere>;
using EvalWorklet = EvaluateImplicitFunction<vtkm::Sphere>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1);
auto handle = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
auto function =
static_cast<const vtkm::Sphere*>(handle.PrepareForExecution(DeviceAdapterTag()));
EvalWorklet eval(function);
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -734,8 +737,8 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function (vtkm::cont::Sphere) on "
<< Internal.Points.GetNumberOfValues() << " points";
description << "Implicit Function (vtkm::Sphere) on " << Internal.Points.GetNumberOfValues()
<< " points";
return description.str();
}
@ -743,9 +746,9 @@ private:
};
template <typename Value>
struct BenchDynamicImplicitFunction
struct BenchVirtualImplicitFunction
{
BenchDynamicImplicitFunction()
BenchVirtualImplicitFunction()
: Internal(MakeImplicitFunctionBenchData())
{
}
@ -753,10 +756,11 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::exec::ImplicitFunction>;
using EvalWorklet = EvaluateImplicitFunction<vtkm::ImplicitFunction>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1.PrepareForExecution(DeviceAdapterTag()));
auto sphere = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
EvalWorklet eval(sphere.PrepareForExecution(DeviceAdapterTag()));
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -767,7 +771,7 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function (DynamicImplicitFunction) on "
description << "Implicit Function (VirtualImplicitFunction) on "
<< Internal.Points.GetNumberOfValues() << " points";
return description.str();
}
@ -786,10 +790,14 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::cont::Sphere, vtkm::cont::Sphere>;
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::Sphere, vtkm::Sphere>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1, Internal.Sphere2);
auto h1 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
auto h2 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere2);
auto f1 = static_cast<const vtkm::Sphere*>(h1.PrepareForExecution(DeviceAdapterTag()));
auto f2 = static_cast<const vtkm::Sphere*>(h2.PrepareForExecution(DeviceAdapterTag()));
EvalWorklet eval(f1, f2);
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -800,8 +808,8 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function 2x(vtkm::cont::Sphere) on "
<< Internal.Points.GetNumberOfValues() << " points";
description << "Implicit Function 2x(vtkm::Sphere) on " << Internal.Points.GetNumberOfValues()
<< " points";
return description.str();
}
@ -809,9 +817,9 @@ private:
};
template <typename Value>
struct Bench2DynamicImplicitFunctions
struct Bench2VirtualImplicitFunctions
{
Bench2DynamicImplicitFunctions()
Bench2VirtualImplicitFunctions()
: Internal(MakeImplicitFunctionBenchData())
{
}
@ -820,11 +828,13 @@ private:
vtkm::Float64 operator()()
{
using EvalWorklet =
Evaluate2ImplicitFunctions<vtkm::exec::ImplicitFunction, vtkm::exec::ImplicitFunction>;
Evaluate2ImplicitFunctions<vtkm::ImplicitFunction, vtkm::ImplicitFunction>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1.PrepareForExecution(DeviceAdapterTag()),
Internal.Sphere2.PrepareForExecution(DeviceAdapterTag()));
auto s1 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
auto s2 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere2);
EvalWorklet eval(s1.PrepareForExecution(DeviceAdapterTag()),
s2.PrepareForExecution(DeviceAdapterTag()));
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -835,7 +845,7 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function 2x(DynamicImplicitFunction) on "
description << "Implicit Function 2x(VirtualImplicitFunction) on "
<< Internal.Points.GetNumberOfValues() << " points";
return description.str();
}
@ -844,9 +854,9 @@ private:
};
VTKM_MAKE_BENCHMARK(ImplicitFunction, BenchImplicitFunction);
VTKM_MAKE_BENCHMARK(ImplicitFunctionDynamic, BenchDynamicImplicitFunction);
VTKM_MAKE_BENCHMARK(ImplicitFunctionVirtual, BenchVirtualImplicitFunction);
VTKM_MAKE_BENCHMARK(ImplicitFunction2, Bench2ImplicitFunctions);
VTKM_MAKE_BENCHMARK(ImplicitFunctionDynamic2, Bench2DynamicImplicitFunctions);
VTKM_MAKE_BENCHMARK(ImplicitFunctionVirtual2, Bench2VirtualImplicitFunctions);
public:
static VTKM_CONT int Run(int benchmarks)
@ -887,9 +897,9 @@ public:
std::cout << "\nBenchmarking Implicit Function\n";
VTKM_RUN_BENCHMARK(ImplicitFunction, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionDynamic, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionVirtual, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunction2, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionDynamic2, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionVirtual2, FloatDefaultType());
}
return 0;

@ -69,7 +69,7 @@ set(headers
ErrorExecution.h
ErrorInternal.h
Field.h
ImplicitFunction.h
ImplicitFunctionHandle.h
MultiBlock.h
PointLocatorUniformGrid.h
RuntimeDeviceInformation.h
@ -80,14 +80,13 @@ set(headers
StorageListTag.h
Timer.h
TryExecute.h
VirtualObjectCache.h
VirtualObjectHandle.h
)
set(header_impls
ArrayHandle.hxx
CellSetExplicit.hxx
CellSetStructured.hxx
ImplicitFunction.hxx
StorageBasic.hxx
)
@ -99,7 +98,6 @@ set(sources
CoordinateSystem.cxx
DynamicArrayHandle.cxx
Field.cxx
ImplicitFunction.cxx
internal/SimplePolymorphicContainer.cxx
MultiBlock.cxx
internal/ArrayManagerExecutionShareWithControl.cxx

@ -40,6 +40,47 @@ struct DeviceAdapterListTagCommon : vtkm::ListTagBase<vtkm::cont::DeviceAdapterT
vtkm::cont::DeviceAdapterTagSerial>
{
};
namespace detail
{
template <typename FunctorType>
class ExecuteIfValidDeviceTag
{
private:
template <typename DeviceAdapter>
using EnableIfValid = std::enable_if<vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
template <typename DeviceAdapter>
using EnableIfInvalid = std::enable_if<!vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
public:
explicit ExecuteIfValidDeviceTag(const FunctorType& functor)
: Functor(functor)
{
}
template <typename DeviceAdapter>
typename EnableIfValid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
this->Functor(DeviceAdapter());
}
template <typename DeviceAdapter>
typename EnableIfInvalid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
}
private:
FunctorType Functor;
};
} // detail
template <typename DeviceList, typename Functor>
VTKM_CONT void ForEachValidDevice(DeviceList devices, const Functor& functor)
{
vtkm::ListForEach(detail::ExecuteIfValidDeviceTag<Functor>(functor), devices);
}
}
} // namespace vtkm::cont

@ -1,29 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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.
//============================================================================
#include <vtkm/cont/ImplicitFunction.h>
namespace vtkm
{
namespace cont
{
ImplicitFunction::~ImplicitFunction() = default;
}
} // vtkm::cont

@ -1,286 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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_cont_ImplicitFunction_h
#define vtk_m_cont_ImplicitFunction_h
#include <vtkm/internal/Configure.h>
#include <vtkm/cont/VirtualObjectCache.h>
#include <vtkm/exec/ImplicitFunction.h>
#include <memory>
namespace vtkm
{
namespace cont
{
class VTKM_CONT_EXPORT ImplicitFunction
{
public:
virtual ~ImplicitFunction();
template <typename DeviceAdapter>
vtkm::exec::ImplicitFunction PrepareForExecution(DeviceAdapter device) const
{
if (!this->Cache->GetValid())
{
this->SetDefaultDevices();
}
return this->Cache->GetVirtualObject(device);
}
void Modified() { this->Cache->SetRefreshFlag(true); }
protected:
using CacheType = vtkm::cont::VirtualObjectCache<vtkm::exec::ImplicitFunction>;
ImplicitFunction()
: Cache(new CacheType)
{
}
ImplicitFunction(ImplicitFunction&& other)
: Cache(std::move(other.Cache))
{
}
ImplicitFunction& operator=(ImplicitFunction&& other)
{
if (this != &other)
{
this->Cache = std::move(other.Cache);
}
return *this;
}
virtual void SetDefaultDevices() const = 0;
std::unique_ptr<CacheType> Cache;
};
template <typename Derived>
class VTKM_ALWAYS_EXPORT ImplicitFunctionImpl : public ImplicitFunction
{
public:
template <typename DeviceAdapterList>
void ResetDevices(DeviceAdapterList devices)
{
this->Cache->Bind(static_cast<const Derived*>(this), devices);
}
protected:
ImplicitFunctionImpl() = default;
ImplicitFunctionImpl(const ImplicitFunctionImpl&)
: ImplicitFunction()
{
}
// Cannot default due to a bug in VS2013
ImplicitFunctionImpl(ImplicitFunctionImpl&& other)
: ImplicitFunction(std::move(other))
{
}
ImplicitFunctionImpl& operator=(const ImplicitFunctionImpl&) { return *this; }
// Cannot default due to a bug in VS2013
ImplicitFunctionImpl& operator=(ImplicitFunctionImpl&& other)
{
ImplicitFunction::operator=(std::move(other));
return *this;
}
void SetDefaultDevices() const override { this->Cache->Bind(static_cast<const Derived*>(this)); }
};
//============================================================================
// ImplicitFunctions:
//============================================================================
/// \brief Implicit function for a box
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunctionImpl<Box>
{
public:
Box();
Box(vtkm::Vec<FloatDefault, 3> minPoint, vtkm::Vec<FloatDefault, 3> maxPoint);
Box(FloatDefault xmin,
FloatDefault xmax,
FloatDefault ymin,
FloatDefault ymax,
FloatDefault zmin,
FloatDefault zmax);
void SetMinPoint(const vtkm::Vec<FloatDefault, 3>& point);
void SetMaxPoint(const vtkm::Vec<FloatDefault, 3>& point);
const vtkm::Vec<FloatDefault, 3>& GetMinPoint() const;
const vtkm::Vec<FloatDefault, 3>& GetMaxPoint() const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault x, FloatDefault y, FloatDefault z) const;
private:
vtkm::Vec<FloatDefault, 3> MinPoint;
vtkm::Vec<FloatDefault, 3> MaxPoint;
};
//============================================================================
/// \brief Implicit function for a cylinder
class VTKM_ALWAYS_EXPORT Cylinder : public ImplicitFunctionImpl<Cylinder>
{
public:
Cylinder();
Cylinder(const vtkm::Vec<FloatDefault, 3>& axis, FloatDefault radius);
Cylinder(const vtkm::Vec<FloatDefault, 3>& center,
const vtkm::Vec<FloatDefault, 3>& axis,
FloatDefault radius);
void SetCenter(const vtkm::Vec<FloatDefault, 3>& center);
void SetAxis(const vtkm::Vec<FloatDefault, 3>& axis);
void SetRadius(FloatDefault radius);
const vtkm::Vec<FloatDefault, 3>& GetCenter() const;
const vtkm::Vec<FloatDefault, 3>& GetAxis() const;
FloatDefault GetRadius() const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault x, FloatDefault y, FloatDefault z) const;
private:
vtkm::Vec<FloatDefault, 3> Center;
vtkm::Vec<FloatDefault, 3> Axis;
FloatDefault Radius;
};
//============================================================================
/// \brief Implicit function for a frustum
class VTKM_ALWAYS_EXPORT Frustum : public ImplicitFunctionImpl<Frustum>
{
public:
Frustum();
Frustum(const vtkm::Vec<FloatDefault, 3> points[6], const vtkm::Vec<FloatDefault, 3> normals[6]);
explicit Frustum(const vtkm::Vec<FloatDefault, 3> points[8]);
void SetPlanes(const vtkm::Vec<FloatDefault, 3> points[6],
const vtkm::Vec<FloatDefault, 3> normals[6]);
void SetPlane(int idx, vtkm::Vec<FloatDefault, 3>& point, vtkm::Vec<FloatDefault, 3>& normal);
void GetPlanes(vtkm::Vec<FloatDefault, 3> points[6], vtkm::Vec<FloatDefault, 3> normals[6]) const;
const vtkm::Vec<FloatDefault, 3>* GetPoints() const;
const vtkm::Vec<FloatDefault, 3>* GetNormals() const;
// The points should be specified in the order of hex-cell vertices
void CreateFromPoints(const vtkm::Vec<FloatDefault, 3> points[8]);
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault, FloatDefault, FloatDefault) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>&) const;
private:
vtkm::Vec<FloatDefault, 3> Points[6];
vtkm::Vec<FloatDefault, 3> Normals[6];
};
//============================================================================
/// \brief Implicit function for a plane
class VTKM_ALWAYS_EXPORT Plane : public ImplicitFunctionImpl<Plane>
{
public:
Plane();
explicit Plane(const vtkm::Vec<FloatDefault, 3>& normal);
Plane(const vtkm::Vec<FloatDefault, 3>& origin, const vtkm::Vec<FloatDefault, 3>& normal);
void SetOrigin(const vtkm::Vec<FloatDefault, 3>& origin);
void SetNormal(const vtkm::Vec<FloatDefault, 3>& normal);
const vtkm::Vec<FloatDefault, 3>& GetOrigin() const;
const vtkm::Vec<FloatDefault, 3>& GetNormal() const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault, FloatDefault, FloatDefault) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>&) const;
private:
vtkm::Vec<FloatDefault, 3> Origin;
vtkm::Vec<FloatDefault, 3> Normal;
};
//============================================================================
/// \brief Implicit function for a sphere
class VTKM_ALWAYS_EXPORT Sphere : public ImplicitFunctionImpl<Sphere>
{
public:
Sphere();
explicit Sphere(FloatDefault radius);
Sphere(vtkm::Vec<FloatDefault, 3> center, FloatDefault radius);
void SetRadius(FloatDefault radius);
void SetCenter(const vtkm::Vec<FloatDefault, 3>& center);
FloatDefault GetRadius() const;
const vtkm::Vec<FloatDefault, 3>& GetCenter() const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>& x) const;
private:
FloatDefault Radius;
vtkm::Vec<FloatDefault, 3> Center;
};
}
} // vtkm::cont
#include <vtkm/cont/ImplicitFunction.hxx>
#endif // vtk_m_cont_ImplicitFunction_h

@ -1,640 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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.
//============================================================================
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <algorithm>
#include <limits>
namespace vtkm
{
namespace cont
{
//============================================================================
inline Box::Box()
: MinPoint(vtkm::Vec<FloatDefault, 3>(FloatDefault(0)))
, MaxPoint(vtkm::Vec<FloatDefault, 3>(FloatDefault(1)))
{
}
inline Box::Box(vtkm::Vec<FloatDefault, 3> minPoint, vtkm::Vec<FloatDefault, 3> maxPoint)
: MinPoint(minPoint)
, MaxPoint(maxPoint)
{
}
inline Box::Box(FloatDefault xmin,
FloatDefault xmax,
FloatDefault ymin,
FloatDefault ymax,
FloatDefault zmin,
FloatDefault zmax)
{
MinPoint[0] = xmin;
MaxPoint[0] = xmax;
MinPoint[1] = ymin;
MaxPoint[1] = ymax;
MinPoint[2] = zmin;
MaxPoint[2] = zmax;
}
inline void Box::SetMinPoint(const vtkm::Vec<FloatDefault, 3>& point)
{
this->MinPoint = point;
this->Modified();
}
inline void Box::SetMaxPoint(const vtkm::Vec<FloatDefault, 3>& point)
{
this->MaxPoint = point;
this->Modified();
}
inline const vtkm::Vec<FloatDefault, 3>& Box::GetMinPoint() const
{
return this->MinPoint;
}
inline const vtkm::Vec<FloatDefault, 3>& Box::GetMaxPoint() const
{
return this->MaxPoint;
}
VTKM_EXEC_CONT
inline FloatDefault Box::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return this->Value(vtkm::Vec<vtkm::FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Box::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
return this->Gradient(vtkm::Vec<FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline FloatDefault Box::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
FloatDefault minDistance = vtkm::NegativeInfinity32();
FloatDefault diff, t, dist;
FloatDefault distance = FloatDefault(0.0);
vtkm::IdComponent inside = 1;
for (vtkm::IdComponent d = 0; d < 3; d++)
{
diff = this->MaxPoint[d] - this->MinPoint[d];
if (diff != FloatDefault(0.0))
{
t = (x[d] - this->MinPoint[d]) / diff;
// Outside before the box
if (t < FloatDefault(0.0))
{
inside = 0;
dist = this->MinPoint[d] - x[d];
}
// Outside after the box
else if (t > FloatDefault(1.0))
{
inside = 0;
dist = x[d] - this->MaxPoint[d];
}
else
{
// Inside the box in lower half
if (t <= FloatDefault(0.5))
{
dist = MinPoint[d] - x[d];
}
// Inside the box in upper half
else
{
dist = x[d] - MaxPoint[d];
}
if (dist > minDistance)
{
minDistance = dist;
}
}
}
else
{
dist = vtkm::Abs(x[d] - MinPoint[d]);
if (dist > FloatDefault(0.0))
{
inside = 0;
}
}
if (dist > FloatDefault(0.0))
{
distance += dist * dist;
}
}
distance = vtkm::Sqrt(distance);
if (inside)
{
return minDistance;
}
else
{
return distance;
}
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Box::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
vtkm::IdComponent minAxis = 0;
FloatDefault dist = 0.0;
FloatDefault minDist = vtkm::Infinity32();
vtkm::Vec<vtkm::IdComponent, 3> location;
vtkm::Vec<FloatDefault, 3> normal(FloatDefault(0));
vtkm::Vec<FloatDefault, 3> inside(FloatDefault(0));
vtkm::Vec<FloatDefault, 3> outside(FloatDefault(0));
vtkm::Vec<FloatDefault, 3> center((this->MaxPoint + this->MinPoint) * FloatDefault(0.5));
// Compute the location of the point with respect to the box
// Point will lie in one of 27 separate regions around or within the box
// Gradient vector is computed differently in each of the regions.
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (x[d] < this->MinPoint[d])
{
// Outside the box low end
location[d] = 0;
outside[d] = -1.0;
}
else if (x[d] > this->MaxPoint[d])
{
// Outside the box high end
location[d] = 2;
outside[d] = 1.0;
}
else
{
location[d] = 1;
if (x[d] <= center[d])
{
// Inside the box low end
dist = x[d] - this->MinPoint[d];
inside[d] = -1.0;
}
else
{
// Inside the box high end
dist = this->MaxPoint[d] - x[d];
inside[d] = 1.0;
}
if (dist < minDist) // dist is negative
{
minDist = dist;
minAxis = d;
}
}
}
vtkm::Id indx = location[0] + 3 * location[1] + 9 * location[2];
switch (indx)
{
// verts - gradient points away from center point
case 0:
case 2:
case 6:
case 8:
case 18:
case 20:
case 24:
case 26:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = x[d] - center[d];
}
vtkm::Normalize(normal);
break;
// edges - gradient points out from axis of cube
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 15:
case 17:
case 19:
case 21:
case 23:
case 25:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (outside[d] != 0.0)
{
normal[d] = x[d] - center[d];
}
else
{
normal[d] = 0.0;
}
}
vtkm::Normalize(normal);
break;
// faces - gradient points perpendicular to face
case 4:
case 10:
case 12:
case 14:
case 16:
case 22:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = outside[d];
}
break;
// interior - gradient is perpendicular to closest face
case 13:
normal[0] = normal[1] = normal[2] = 0.0;
normal[minAxis] = inside[minAxis];
break;
default:
VTKM_ASSERT(false);
break;
}
return normal;
}
//============================================================================
inline Cylinder::Cylinder()
: Center(FloatDefault(0))
, Axis(vtkm::make_Vec(FloatDefault(1), FloatDefault(0), FloatDefault(0)))
, Radius(FloatDefault(0.2))
{
}
inline Cylinder::Cylinder(const vtkm::Vec<FloatDefault, 3>& axis, FloatDefault radius)
: Center(FloatDefault(0))
, Axis(vtkm::Normal(axis))
, Radius(radius)
{
}
inline Cylinder::Cylinder(const vtkm::Vec<FloatDefault, 3>& center,
const vtkm::Vec<FloatDefault, 3>& axis,
FloatDefault radius)
: Center(center)
, Axis(vtkm::Normal(axis))
, Radius(radius)
{
}
inline void Cylinder::SetCenter(const vtkm::Vec<FloatDefault, 3>& center)
{
this->Center = center;
this->Modified();
}
inline void Cylinder::SetAxis(const vtkm::Vec<FloatDefault, 3>& axis)
{
this->Axis = vtkm::Normal(axis);
this->Modified();
}
inline void Cylinder::SetRadius(FloatDefault radius)
{
this->Radius = radius;
this->Modified();
}
inline const vtkm::Vec<FloatDefault, 3>& Cylinder::GetCenter() const
{
return this->Center;
}
inline const vtkm::Vec<FloatDefault, 3>& Cylinder::GetAxis() const
{
return this->Axis;
}
inline FloatDefault Cylinder::GetRadius() const
{
return this->Radius;
}
VTKM_EXEC_CONT
inline FloatDefault Cylinder::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
vtkm::Vec<FloatDefault, 3> x2c = x - this->Center;
FloatDefault proj = vtkm::dot(this->Axis, x2c);
return vtkm::dot(x2c, x2c) - (proj * proj) - (this->Radius * this->Radius);
}
VTKM_EXEC_CONT
inline FloatDefault Cylinder::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return this->Value(vtkm::Vec<vtkm::FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Cylinder::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
vtkm::Vec<FloatDefault, 3> x2c = x - this->Center;
FloatDefault t = this->Axis[0] * x2c[0] + this->Axis[1] * x2c[1] + this->Axis[2] * x2c[2];
vtkm::Vec<FloatDefault, 3> closestPoint = this->Center + (this->Axis * t);
return (x - closestPoint) * FloatDefault(2);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Cylinder::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
return this->Gradient(vtkm::Vec<FloatDefault, 3>(x, y, z));
}
//============================================================================
inline Frustum::Frustum()
{
std::fill(this->Points, this->Points + 6, vtkm::Vec<FloatDefault, 3>{});
std::fill(this->Normals, this->Normals + 6, vtkm::Vec<FloatDefault, 3>{});
}
inline Frustum::Frustum(const vtkm::Vec<FloatDefault, 3> points[6],
const vtkm::Vec<FloatDefault, 3> normals[6])
{
std::copy(points, points + 6, this->Points);
std::copy(normals, normals + 6, this->Normals);
}
inline Frustum::Frustum(const vtkm::Vec<FloatDefault, 3> points[8])
{
this->CreateFromPoints(points);
}
inline void Frustum::SetPlanes(const vtkm::Vec<FloatDefault, 3> points[6],
const vtkm::Vec<FloatDefault, 3> normals[6])
{
std::copy(points, points + 6, this->Points);
std::copy(normals, normals + 6, this->Normals);
this->Modified();
}
inline void Frustum::GetPlanes(vtkm::Vec<FloatDefault, 3> points[6],
vtkm::Vec<FloatDefault, 3> normals[6]) const
{
std::copy(this->Points, this->Points + 6, points);
std::copy(this->Normals, this->Normals + 6, normals);
}
inline const vtkm::Vec<FloatDefault, 3>* Frustum::GetPoints() const
{
return this->Points;
}
inline const vtkm::Vec<FloatDefault, 3>* Frustum::GetNormals() const
{
return this->Normals;
}
inline void Frustum::SetPlane(int idx,
vtkm::Vec<FloatDefault, 3>& point,
vtkm::Vec<FloatDefault, 3>& normal)
{
if (idx < 0 || idx >= 6)
{
std::string msg = "Plane idx ";
msg += std::to_string(idx) + " is out of range [0, 5]";
throw vtkm::cont::ErrorBadValue(msg);
}
this->Points[idx] = point;
this->Normals[idx] = normal;
this->Modified();
}
inline void Frustum::CreateFromPoints(const vtkm::Vec<FloatDefault, 3> points[8])
{
// XXX(clang-format-3.9): 3.8 is silly. 3.9 makes it look like this.
// clang-format off
int planes[6][3] = {
{ 3, 2, 0 }, { 4, 5, 7 }, { 0, 1, 4 }, { 1, 2, 5 }, { 2, 3, 6 }, { 3, 0, 7 }
};
// clang-format on
for (int i = 0; i < 6; ++i)
{
auto& v0 = points[planes[i][0]];
auto& v1 = points[planes[i][1]];
auto& v2 = points[planes[i][2]];
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::Cross(v2 - v0, v1 - v0));
this->Modified();
}
}
VTKM_EXEC_CONT
inline FloatDefault Frustum::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
FloatDefault maxVal = -std::numeric_limits<FloatDefault>::max();
for (int i = 0; i < 6; ++i)
{
auto& p = this->Points[i];
auto& n = this->Normals[i];
FloatDefault val = ((x - p[0]) * n[0]) + ((y - p[1]) * n[1]) + ((z - p[2]) * n[2]);
maxVal = vtkm::Max(maxVal, val);
}
return maxVal;
}
VTKM_EXEC_CONT
inline FloatDefault Frustum::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Value(x[0], x[1], x[2]);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Frustum::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
FloatDefault maxVal = -std::numeric_limits<FloatDefault>::max();
int maxValIdx = 0;
for (int i = 0; i < 6; ++i)
{
auto& p = this->Points[i];
auto& n = this->Normals[i];
FloatDefault val = ((x - p[0]) * n[0]) + ((y - p[1]) * n[1]) + ((z - p[2]) * n[2]);
if (val > maxVal)
{
maxVal = val;
maxValIdx = i;
}
}
return this->Normals[maxValIdx];
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Frustum::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Gradient(x[0], x[1], x[2]);
}
//============================================================================
inline Plane::Plane()
: Origin(FloatDefault(0))
, Normal(FloatDefault(0), FloatDefault(0), FloatDefault(1))
{
}
inline Plane::Plane(const vtkm::Vec<FloatDefault, 3>& normal)
: Origin(FloatDefault(0))
, Normal(normal)
{
}
inline Plane::Plane(const vtkm::Vec<FloatDefault, 3>& origin,
const vtkm::Vec<FloatDefault, 3>& normal)
: Origin(origin)
, Normal(normal)
{
}
inline void Plane::SetOrigin(const vtkm::Vec<FloatDefault, 3>& origin)
{
this->Origin = origin;
this->Modified();
}
inline void Plane::SetNormal(const vtkm::Vec<FloatDefault, 3>& normal)
{
this->Normal = normal;
this->Modified();
}
inline const vtkm::Vec<FloatDefault, 3>& Plane::GetOrigin() const
{
return this->Origin;
}
inline const vtkm::Vec<FloatDefault, 3>& Plane::GetNormal() const
{
return this->Normal;
}
VTKM_EXEC_CONT
inline FloatDefault Plane::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return ((x - this->Origin[0]) * this->Normal[0]) + ((y - this->Origin[1]) * this->Normal[1]) +
((z - this->Origin[2]) * this->Normal[2]);
}
VTKM_EXEC_CONT
inline FloatDefault Plane::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Value(x[0], x[1], x[2]);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Plane::Gradient(FloatDefault, FloatDefault, FloatDefault) const
{
return this->Normal;
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Plane::Gradient(const vtkm::Vec<FloatDefault, 3>&) const
{
return this->Normal;
}
//============================================================================
inline Sphere::Sphere()
: Radius(FloatDefault(0.2))
, Center(FloatDefault(0))
{
}
inline Sphere::Sphere(FloatDefault radius)
: Radius(radius)
, Center(FloatDefault(0))
{
}
inline Sphere::Sphere(vtkm::Vec<FloatDefault, 3> center, FloatDefault radius)
: Radius(radius)
, Center(center)
{
}
inline void Sphere::SetRadius(FloatDefault radius)
{
this->Radius = radius;
this->Modified();
}
inline void Sphere::SetCenter(const vtkm::Vec<FloatDefault, 3>& center)
{
this->Center = center;
this->Modified();
}
inline FloatDefault Sphere::GetRadius() const
{
return this->Radius;
}
inline const vtkm::Vec<FloatDefault, 3>& Sphere::GetCenter() const
{
return this->Center;
}
VTKM_EXEC_CONT
inline FloatDefault Sphere::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return ((x - this->Center[0]) * (x - this->Center[0]) +
(y - this->Center[1]) * (y - this->Center[1]) +
(z - this->Center[2]) * (z - this->Center[2])) -
(this->Radius * this->Radius);
}
VTKM_EXEC_CONT
inline FloatDefault Sphere::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Value(x[0], x[1], x[2]);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Sphere::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
return this->Gradient(vtkm::Vec<FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Sphere::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
return FloatDefault(2) * (x - this->Center);
}
}
} // vtkm::cont

@ -0,0 +1,78 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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_cont_ImplicitFunctionHandle_h
#define vtk_m_cont_ImplicitFunctionHandle_h
#include <vtkm/ImplicitFunction.h>
#include <vtkm/cont/VirtualObjectHandle.h>
namespace vtkm
{
namespace cont
{
class VTKM_ALWAYS_EXPORT ImplicitFunctionHandle
: public vtkm::cont::VirtualObjectHandle<vtkm::ImplicitFunction>
{
private:
using Superclass = vtkm::cont::VirtualObjectHandle<vtkm::ImplicitFunction>;
public:
ImplicitFunctionHandle() = default;
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
explicit ImplicitFunctionHandle(ImplicitFunctionType* function,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Superclass(function, acquireOwnership, devices)
{
}
};
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
VTKM_CONT ImplicitFunctionHandle
make_ImplicitFunctionHandle(ImplicitFunctionType&& func,
DeviceAdapterList devices = DeviceAdapterList())
{
using IFType = typename std::remove_reference<ImplicitFunctionType>::type;
return ImplicitFunctionHandle(
new IFType(std::forward<ImplicitFunctionType>(func)), true, devices);
}
template <typename ImplicitFunctionType, typename... Args>
VTKM_CONT ImplicitFunctionHandle make_ImplicitFunctionHandle(Args&&... args)
{
return ImplicitFunctionHandle(new ImplicitFunctionType(std::forward<Args>(args)...),
true,
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
}
template <typename ImplicitFunctionType, typename DeviceAdapterList, typename... Args>
VTKM_CONT ImplicitFunctionHandle make_ImplicitFunctionHandle(Args&&... args)
{
return ImplicitFunctionHandle(
new ImplicitFunctionType(std::forward<Args>(args)...), true, DeviceAdapterList());
}
}
} // vtkm::cont
#endif // vtk_m_cont_ImplicitFunctionHandle_h

@ -1,310 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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_cont_VirtualObjectCache_h
#define vtk_m_cont_VirtualObjectCache_h
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <array>
#include <type_traits>
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
namespace vtkm
{
namespace cont
{
/// \brief Implements VTK-m's execution side <em> Virtual Methods </em>
/// functionality.
///
/// The template parameter \c VirtualObject is the class that acts as the
/// interface. Following is a method for implementing such classes:
/// 1. Create a <tt>const void*</tt> member variable that will hold a
/// reference to the target class.
/// 2. For each virtual-like method:
/// a. Create a typedef for a function with the same signature,
/// except for an extra <tt>const void*</tt> argument.
/// b. Create a function pointer member variable with the type of the
/// associated typedef from 2a.
/// c. Create an implementation of the method, that calls the associated
/// function pointer with the void pointer to the target class as one of
/// the arguments.
/// 3. Create the following template function:
/// \code{.cpp}
/// template<typename TargetClass>
/// VTKM_EXEC void Bind(const TargetClass *deviceTarget);
/// \endcode
/// This function should set the void pointer from 1 to \c deviceTarget,
/// and assign the function pointers from 2b to functions that cast their
/// first argument to <tt>const TargetClass*</tt> and call the corresponding
/// member function on it.
///
/// Both \c VirtualObject and target class objects should be bitwise copyable.
///
/// \sa vtkm::exec::ImplicitFunction, vtkm::cont::ImplicitFunction
///
template <typename VirtualObject>
class VirtualObjectCache
{
public:
VirtualObjectCache()
: Target(nullptr)
, CurrentDevice(VTKM_DEVICE_ADAPTER_UNDEFINED)
, DeviceState(nullptr)
, RefreshFlag(false)
{
}
~VirtualObjectCache() { this->Reset(); }
VirtualObjectCache(const VirtualObjectCache& other)
: Target(other.Target)
, Transfers(other.Transfers)
, CurrentDevice(VTKM_DEVICE_ADAPTER_UNDEFINED)
, DeviceState(nullptr)
, RefreshFlag(false)
{
}
VirtualObjectCache& operator=(const VirtualObjectCache& other)
{
if (this != &other)
{
this->Target = other.Target;
this->Transfers = other.Transfers;
this->CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
this->DeviceState = nullptr;
this->RefreshFlag = false;
this->Object = VirtualObject();
}
return *this;
}
VirtualObjectCache(VirtualObjectCache&& other)
: Target(other.Target)
, Transfers(other.Transfers)
, CurrentDevice(other.CurrentDevice)
, DeviceState(other.DeviceState)
, RefreshFlag(other.RefreshFlag)
, Object(other.Object)
{
other.CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
other.DeviceState = nullptr;
}
VirtualObjectCache& operator=(VirtualObjectCache&& other)
{
if (this != &other)
{
this->Target = other.Target;
this->Transfers = std::move(other.Transfers);
this->CurrentDevice = other.CurrentDevice;
this->DeviceState = other.DeviceState;
this->RefreshFlag = other.RefreshFlag;
this->Object = std::move(other.Object);
other.CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
other.DeviceState = nullptr;
}
return *this;
}
/// Reset to the default constructed state
void Reset()
{
this->ReleaseResources();
this->Target = nullptr;
this->Transfers.fill(TransferInterface());
}
void ReleaseResources()
{
if (this->CurrentDevice > 0)
{
this->GetCurrentTransfer().Cleanup(this->DeviceState);
this->CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
this->DeviceState = nullptr;
this->RefreshFlag = false;
this->Object = VirtualObject();
}
}
/// Get if in a valid state (a target is bound)
bool GetValid() const { return this->Target != nullptr; }
// Set/Get if the cached virtual object should be refreshed to the current
// state of the target
void SetRefreshFlag(bool value) { this->RefreshFlag = value; }
bool GetRefreshFlag() const { return this->RefreshFlag; }
/// Bind to \c target. The lifetime of target is expected to be managed
/// externally, and should be valid for as long as it is bound.
/// Also accepts a list-tag of device adapters where the virtual
/// object may be used (default = \c VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG).
///
template <typename TargetClass, typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
void Bind(const TargetClass* target, DeviceAdapterList devices = DeviceAdapterList())
{
this->Reset();
this->Target = target;
vtkm::ListForEach(CreateTransferInterface<TargetClass>(this->Transfers.data()), devices);
}
/// Get a \c VirtualObject for \c DeviceAdapter.
/// VirtualObjectCache and VirtualObject are analogous to ArrayHandle and Portal
/// The returned VirtualObject will be invalidated if:
/// 1. A new VirtualObject is requested for a different DeviceAdapter
/// 2. VirtualObjectCache is destroyed
/// 3. Reset or ReleaseResources is called
///
template <typename DeviceAdapter>
VirtualObject GetVirtualObject(DeviceAdapter)
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (!this->GetValid())
{
throw vtkm::cont::ErrorBadValue("No target object bound");
}
vtkm::cont::DeviceAdapterId deviceId = DeviceInfo::GetId();
if (deviceId < 0 || deviceId >= VTKM_MAX_DEVICE_ADAPTER_ID)
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(deviceId) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
if (this->CurrentDevice != deviceId)
{
this->ReleaseResources();
std::size_t idx = static_cast<std::size_t>(deviceId);
TransferInterface& transfer = this->Transfers[idx];
if (!TransferInterfaceValid(transfer))
{
std::string msg = DeviceInfo::GetName() + " was not in the list specified in Bind";
throw vtkm::cont::ErrorBadType(msg);
}
this->CurrentDevice = deviceId;
this->DeviceState = transfer.Create(this->Object, this->Target);
}
else if (this->RefreshFlag)
{
this->GetCurrentTransfer().Update(this->DeviceState, this->Target);
}
this->RefreshFlag = false;
return this->Object;
}
private:
struct TransferInterface
{
using CreateSig = void*(VirtualObject&, const void*);
using UpdateSig = void(void*, const void*);
using CleanupSig = void(void*);
CreateSig* Create = nullptr;
UpdateSig* Update = nullptr;
CleanupSig* Cleanup = nullptr;
};
static bool TransferInterfaceValid(const TransferInterface& t) { return t.Create != nullptr; }
TransferInterface& GetCurrentTransfer()
{
return this->Transfers[static_cast<std::size_t>(this->CurrentDevice)];
}
template <typename TargetClass>
class CreateTransferInterface
{
private:
template <typename DeviceAdapter>
using EnableIfValid = std::enable_if<vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
template <typename DeviceAdapter>
using EnableIfInvalid = std::enable_if<!vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
public:
CreateTransferInterface(TransferInterface* transfers)
: Transfers(transfers)
{
}
// Use SFINAE to create entries for valid device adapters only
template <typename DeviceAdapter>
typename EnableIfValid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (DeviceInfo::GetId() >= 0 && DeviceInfo::GetId() < VTKM_MAX_DEVICE_ADAPTER_ID)
{
using TransferImpl =
internal::VirtualObjectTransfer<VirtualObject, TargetClass, DeviceAdapter>;
std::size_t id = static_cast<std::size_t>(DeviceInfo::GetId());
TransferInterface& transfer = this->Transfers[id];
transfer.Create = &TransferImpl::Create;
transfer.Update = &TransferImpl::Update;
transfer.Cleanup = &TransferImpl::Cleanup;
}
else
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(DeviceInfo::GetId()) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
}
template <typename DeviceAdapter>
typename EnableIfInvalid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
}
private:
TransferInterface* Transfers;
};
const void* Target;
std::array<TransferInterface, VTKM_MAX_DEVICE_ADAPTER_ID> Transfers;
vtkm::cont::DeviceAdapterId CurrentDevice;
void* DeviceState;
bool RefreshFlag;
VirtualObject Object;
};
}
} // vtkm::cont
#undef VTKM_MAX_DEVICE_ADAPTER_ID
#endif // vtk_m_cont_VirtualObjectCache_h

@ -0,0 +1,277 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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_cont_VirtualObjectHandle_h
#define vtk_m_cont_VirtualObjectHandle_h
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <array>
#include <type_traits>
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
namespace vtkm
{
namespace cont
{
/// \brief Implements VTK-m's execution side <em> Virtual Methods </em> functionality.
///
/// The template parameter \c VirtualBaseType is the base class that acts as the
/// interface. This base clase must inherit from \c vtkm::VirtualObjectBase. See the
/// documentation of that class to see the other requirements.
///
/// A derived object can be bound to the handle either during construction or using the \c Reset
/// function on previously constructed handles. These function accept a control side pointer to
/// the derived class object, a boolean flag stating if the handle should acquire ownership of
/// the object (i.e. manage the lifetime), and a type-list of device adapter tags where the object
/// is expected to be used.
///
/// To get an execution side pointer call the \c PrepareForExecution function. The device adapter
/// passed to this function should be one of the device in the list passed during the set up of
/// the handle.
///
///
/// \sa vtkm::VirtualObjectBase
///
template <typename VirtualBaseType>
class VTKM_ALWAYS_EXPORT VirtualObjectHandle
{
VTKM_STATIC_ASSERT_MSG((std::is_base_of<vtkm::VirtualObjectBase, VirtualBaseType>::value),
"All virtual objects must be subclass of vtkm::VirtualObjectBase.");
public:
VTKM_CONT VirtualObjectHandle()
: Internals(new InternalStruct)
{
}
template <typename VirtualDerivedType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
VTKM_CONT explicit VirtualObjectHandle(VirtualDerivedType* derived,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Internals(new InternalStruct)
{
this->Reset(derived, acquireOwnership, devices);
}
/// Get if in a valid state (a target is bound)
VTKM_CONT bool GetValid() const { return this->Internals->VirtualObject != nullptr; }
/// Get if this handle owns the control side target object
VTKM_CONT bool OwnsObject() const { return this->Internals->Owner; }
/// Get the control side pointer to the virtual object
VTKM_CONT VirtualBaseType* Get() const { return this->Internals->VirtualObject; }
/// Reset the underlying derived type object
template <typename VirtualDerivedType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
VTKM_CONT void Reset(VirtualDerivedType* derived,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
{
this->Reset();
if (derived)
{
VTKM_STATIC_ASSERT_MSG((std::is_base_of<VirtualBaseType, VirtualDerivedType>::value),
"Tried to bind a type that is not a subclass of the base class.");
this->Internals->VirtualObject = derived;
this->Internals->Owner = acquireOwnership;
vtkm::cont::ForEachValidDevice(
devices,
CreateTransferInterface<VirtualDerivedType>(this->Internals->Transfers.data(), derived));
}
}
void Reset() { this->Internals->Reset(); }
/// Release all the execution side resources
VTKM_CONT void ReleaseExecutionResources() { this->Internals->ReleaseExecutionResources(); }
/// Get a valid \c VirtualBaseType* with the current control side state for \c DeviceAdapter.
/// VirtualObjectHandle and the returned pointer are analogous to ArrayHandle and Portal
/// The returned pointer will be invalidated if:
/// 1. A new pointer is requested for a different DeviceAdapter
/// 2. VirtualObjectHandle is destroyed
/// 3. Reset or ReleaseResources is called
///
template <typename DeviceAdapter>
VTKM_CONT const VirtualBaseType* PrepareForExecution(DeviceAdapter) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (!this->GetValid())
{
throw vtkm::cont::ErrorBadValue("No target object bound");
}
vtkm::cont::DeviceAdapterId deviceId = DeviceInfo::GetId();
if (deviceId < 0 || deviceId >= VTKM_MAX_DEVICE_ADAPTER_ID)
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(deviceId) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
if (!this->Internals->Current || this->Internals->Current->GetDeviceId() != deviceId)
{
if (!this->Internals->Transfers[static_cast<std::size_t>(deviceId)])
{
std::string msg = DeviceInfo::GetName() + " was not in the list specified in Bind";
throw vtkm::cont::ErrorBadType(msg);
}
if (this->Internals->Current)
{
this->Internals->Current->ReleaseResources();
}
this->Internals->Current =
this->Internals->Transfers[static_cast<std::size_t>(deviceId)].get();
}
return this->Internals->Current->PrepareForExecution();
}
private:
class TransferInterface
{
public:
VTKM_CONT virtual ~TransferInterface() = default;
VTKM_CONT virtual vtkm::cont::DeviceAdapterId GetDeviceId() const = 0;
VTKM_CONT virtual const VirtualBaseType* PrepareForExecution() = 0;
VTKM_CONT virtual void ReleaseResources() = 0;
};
template <typename VirtualDerivedType, typename DeviceAdapter>
class TransferInterfaceImpl : public TransferInterface
{
public:
VTKM_CONT TransferInterfaceImpl(const VirtualDerivedType* virtualObject)
: LastModifiedCount(-1)
, VirtualObject(virtualObject)
, Transfer(virtualObject)
{
}
VTKM_CONT vtkm::cont::DeviceAdapterId GetDeviceId() const override
{
return vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
}
VTKM_CONT const VirtualBaseType* PrepareForExecution() override
{
vtkm::Id modifiedCount = this->VirtualObject->GetModifiedCount();
bool updateData = (this->LastModifiedCount != modifiedCount);
const VirtualBaseType* executionObject = this->Transfer.PrepareForExecution(updateData);
this->LastModifiedCount = modifiedCount;
return executionObject;
}
VTKM_CONT void ReleaseResources() override { this->Transfer.ReleaseResources(); }
private:
vtkm::Id LastModifiedCount;
const VirtualDerivedType* VirtualObject;
vtkm::cont::internal::VirtualObjectTransfer<VirtualDerivedType, DeviceAdapter> Transfer;
};
template <typename VirtualDerivedType>
class CreateTransferInterface
{
public:
CreateTransferInterface(std::unique_ptr<TransferInterface>* transfers,
const VirtualDerivedType* virtualObject)
: Transfers(transfers)
, VirtualObject(virtualObject)
{
}
template <typename DeviceAdapter>
void operator()(DeviceAdapter) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (DeviceInfo::GetId() < 0 || DeviceInfo::GetId() >= VTKM_MAX_DEVICE_ADAPTER_ID)
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(DeviceInfo::GetId()) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
using TransferImpl = TransferInterfaceImpl<VirtualDerivedType, DeviceAdapter>;
this->Transfers[DeviceInfo::GetId()].reset(new TransferImpl(this->VirtualObject));
}
private:
std::unique_ptr<TransferInterface>* Transfers;
const VirtualDerivedType* VirtualObject;
};
struct InternalStruct
{
VirtualBaseType* VirtualObject = nullptr;
bool Owner = false;
std::array<std::unique_ptr<TransferInterface>, VTKM_MAX_DEVICE_ADAPTER_ID> Transfers;
TransferInterface* Current = nullptr;
VTKM_CONT void ReleaseExecutionResources()
{
if (this->Current)
{
this->Current->ReleaseResources();
this->Current = nullptr;
}
}
VTKM_CONT void Reset()
{
this->ReleaseExecutionResources();
for (auto& transfer : this->Transfers)
{
transfer.reset(nullptr);
}
if (this->Owner)
{
delete this->VirtualObject;
}
this->VirtualObject = nullptr;
this->Owner = false;
}
VTKM_CONT ~InternalStruct() { this->Reset(); }
};
std::shared_ptr<InternalStruct> Internals;
};
}
} // vtkm::cont
#undef VTKM_MAX_DEVICE_ADAPTER_ID
#endif // vtk_m_cont_VirtualObjectHandle_h

@ -20,6 +20,7 @@
#ifndef vtk_m_cont_cuda_internal_VirtualObjectTransferCuda_h
#define vtk_m_cont_cuda_internal_VirtualObjectTransferCuda_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/cuda/ErrorCuda.h>
#include <vtkm/cont/cuda/internal/DeviceAdapterTagCuda.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
@ -34,45 +35,108 @@ namespace internal
namespace detail
{
template <typename VirtualObject, typename TargetClass>
__global__ void CreateKernel(VirtualObject* object, const TargetClass* target)
template <typename VirtualDerivedType>
__global__ void ConstructVirtualObjectKernel(VirtualDerivedType* deviceObject,
const VirtualDerivedType* targetObject)
{
object->Bind(target);
// Use the "placement new" syntax to construct an object in pre-allocated memory
new (deviceObject) VirtualDerivedType(*targetObject);
}
template <typename VirtualDerivedType>
__global__ void UpdateVirtualObjectKernel(VirtualDerivedType* deviceObject,
const VirtualDerivedType* targetObject)
{
*deviceObject = *targetObject;
}
template <typename VirtualDerivedType>
__global__ void DeleteVirtualObjectKernel(VirtualDerivedType* deviceObject)
{
deviceObject->~VirtualDerivedType();
}
} // detail
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject, TargetClass, vtkm::cont::DeviceAdapterTagCuda>
template <typename VirtualDerivedType>
struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagCuda>
{
static void* Create(VirtualObject& object, const void* target)
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject)
: ControlObject(virtualObject)
, ExecutionObject(nullptr)
{
TargetClass* cutarget;
VTKM_CUDA_CALL(cudaMalloc(&cutarget, sizeof(TargetClass)));
VTKM_CUDA_CALL(cudaMemcpyAsync(
cutarget, target, sizeof(TargetClass), cudaMemcpyHostToDevice, cudaStreamPerThread));
VirtualObject* cuobject;
VTKM_CUDA_CALL(cudaMalloc(&cuobject, sizeof(VirtualObject)));
detail::CreateKernel<<<1, 1, 0, cudaStreamPerThread>>>(cuobject, cutarget);
VTKM_CUDA_CHECK_ASYNCHRONOUS_ERROR();
VTKM_CUDA_CALL(cudaMemcpyAsync(
&object, cuobject, sizeof(VirtualObject), cudaMemcpyDeviceToHost, cudaStreamPerThread));
VTKM_CUDA_CALL(cudaFree(cuobject));
return cutarget;
}
static void Update(void* deviceState, const void* target)
VTKM_CONT ~VirtualObjectTransfer() { this->ReleaseResources(); }
VirtualObjectTransfer(const VirtualObjectTransfer&) = delete;
void operator=(const VirtualObjectTransfer&) = delete;
VTKM_CONT const VirtualDerivedType* PrepareForExecution(bool updateData)
{
VTKM_CUDA_CALL(cudaMemcpyAsync(
deviceState, target, sizeof(TargetClass), cudaMemcpyHostToDevice, cudaStreamPerThread));
if (this->ExecutionObject == nullptr)
{
// deviceTarget will hold a byte copy of the host object on the device. The virtual table
// will be wrong.
VirtualDerivedType* deviceTarget;
VTKM_CUDA_CALL(cudaMalloc(&deviceTarget, sizeof(VirtualDerivedType)));
VTKM_CUDA_CALL(cudaMemcpy(
deviceTarget, this->ControlObject, sizeof(VirtualDerivedType), cudaMemcpyHostToDevice));
// Allocate memory for the object that will eventually be a correct copy on the device.
VTKM_CUDA_CALL(cudaMalloc(&this->ExecutionObject, sizeof(VirtualDerivedType)));
// Initialize the device object
detail::ConstructVirtualObjectKernel<<<1, 1>>>(this->ExecutionObject, deviceTarget);
VTKM_CUDA_CHECK_ASYNCHRONOUS_ERROR();
// Clean up intermediate copy
VTKM_CUDA_CALL(cudaFree(deviceTarget));
}
else if (updateData)
{
// deviceTarget will hold a byte copy of the host object on the device. The virtual table
// will be wrong.
VirtualDerivedType* deviceTarget;
VTKM_CUDA_CALL(cudaMalloc(&deviceTarget, sizeof(VirtualDerivedType)));
VTKM_CUDA_CALL(cudaMemcpy(
deviceTarget, this->ControlObject, sizeof(VirtualDerivedType), cudaMemcpyHostToDevice));
// Initialize the device object
detail::UpdateVirtualObjectKernel<<<1, 1>>>(this->ExecutionObject, deviceTarget);
VTKM_CUDA_CHECK_ASYNCHRONOUS_ERROR();
// Clean up intermediate copy
VTKM_CUDA_CALL(cudaFree(deviceTarget));
}
else
{
// Nothing to do. The device object is already up to date.
}
return this->ExecutionObject;
}
static void Cleanup(void* deviceState) { VTKM_CUDA_CALL(cudaFree(deviceState)); }
VTKM_CONT void ReleaseResources()
{
if (this->ExecutionObject != nullptr)
{
detail::DeleteVirtualObjectKernel<<<1, 1>>>(this->ExecutionObject);
VTKM_CUDA_CALL(cudaFree(this->ExecutionObject));
this->ExecutionObject = nullptr;
}
}
private:
const VirtualDerivedType* ControlObject;
VirtualDerivedType* ExecutionObject;
};
}
}
} // vtkm::cont::internal
#define VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(DerivedType) \
template class vtkm::cont::internal::VirtualObjectTransfer<DerivedType, \
vtkm::cont::DeviceAdapterTagCuda>
#endif // vtk_m_cont_cuda_internal_VirtualObjectTransferCuda_h

@ -29,6 +29,6 @@ set(unit_tests
UnitTestCudaMath.cu
UnitTestCudaShareUserProvidedManagedMemory.cu
UnitTestCudaPointLocatorUniformGrid.cxx
UnitTestCudaVirtualObjectCache.cu
UnitTestCudaVirtualObjectHandle.cu
)
vtkm_unit_tests(CUDA SOURCES ${unit_tests})

@ -17,22 +17,22 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/testing/TestingVirtualObjectCache.h>
#include <vtkm/cont/testing/TestingVirtualObjectHandle.h>
namespace
{
void TestVirtualObjectCache()
void TestVirtualObjectHandle()
{
using DeviceAdapterList =
vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagSerial, vtkm::cont::DeviceAdapterTagCuda>;
vtkm::cont::testing::TestingVirtualObjectCache<DeviceAdapterList>::Run();
vtkm::cont::testing::TestingVirtualObjectHandle<DeviceAdapterList>::Run();
}
} // anonymous namespace
int UnitTestCudaVirtualObjectCache(int, char* [])
int UnitTestCudaVirtualObjectHandle(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestVirtualObjectCache);
return vtkm::cont::testing::Testing::Run(TestVirtualObjectHandle);
}

@ -20,6 +20,8 @@
#ifndef vtk_m_cont_internal_VirtualObjectTransfer_h
#define vtk_m_cont_internal_VirtualObjectTransfer_h
#include <vtkm/VirtualObjectBase.h>
namespace vtkm
{
namespace cont
@ -27,23 +29,31 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass, typename DeviceAdapter>
template <typename VirtualDerivedType, typename DeviceAdapter>
struct VirtualObjectTransfer
#ifdef VTKM_DOXYGEN_ONLY
{
/// Takes a void* to host copy of the target object, transfers it to the
/// device, binds it to the VirtualObject, and returns a void* to an internal
/// state structure.
/// A VirtualObjectTransfer is constructed with a pointer to the derived type that (eventually)
/// gets transferred to the execution environment of the given DeviceAdapter.
///
static void* Create(VirtualObject& object, const void* hostTarget);
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject);
/// Performs cleanup of the device state used to track the VirtualObject on
/// the device.
/// \brief Transfers the virtual object to the execution environment.
///
static void Cleanup(void* deviceState);
/// This method transfers the virtual object to the execution environment and returns a pointer
/// to the object that can be used in the execution environment (but not necessarily the control
/// environment). If the \c updateData flag is true, then the data is always copied to the
/// execution environment (such as if the data were updated since the last call to \c
/// PrepareForExecution). If the \c updateData flag is false and the object was already
/// transferred previously, the previously created object is returned.
///
VTKM_CONT const VirtualDerivedType* PrepareForExecution(bool updateData);
/// Update the device state with the state of target
static void Update(void* deviceState, const void* target);
/// \brief Frees up any resources in the execution environment.
///
/// Any previously returned virtual object from \c PrepareForExecution becomes invalid.
///
VTKM_CONT void ReleaseResources();
}
#endif
;

@ -20,6 +20,11 @@
#ifndef vtk_m_cont_internal_VirtualObjectTransferShareWithControl_h
#define vtk_m_cont_internal_VirtualObjectTransferShareWithControl_h
#include <vtkm/StaticAssert.h>
#include <vtkm/VirtualObjectBase.h>
#include <typeinfo>
namespace vtkm
{
namespace cont
@ -27,19 +32,23 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass>
template <typename VirtualDerivedType>
struct VirtualObjectTransferShareWithControl
{
static void* Create(VirtualObject& object, const void* target)
VTKM_CONT VirtualObjectTransferShareWithControl(const VirtualDerivedType* virtualObject)
: VirtualObject(virtualObject)
{
static int dummyState = 0;
object.Bind(static_cast<const TargetClass*>(target));
return &dummyState;
}
static void Update(void*, const void*) {}
VTKM_CONT const VirtualDerivedType* PrepareForExecution(bool vtkmNotUsed(updateData))
{
return this->VirtualObject;
}
static void Cleanup(void*) {}
VTKM_CONT void ReleaseResources() {}
private:
const VirtualDerivedType* VirtualObject;
};
}
}

@ -31,10 +31,14 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject, TargetClass, vtkm::cont::DeviceAdapterTagSerial>
: public VirtualObjectTransferShareWithControl<VirtualObject, TargetClass>
template <typename VirtualDerivedType>
struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagSerial>
: VirtualObjectTransferShareWithControl<VirtualDerivedType>
{
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject)
: VirtualObjectTransferShareWithControl<VirtualDerivedType>(virtualObject)
{
}
};
}
}

@ -28,6 +28,6 @@ set(unit_tests
UnitTestSerialDeviceAdapter.cxx
UnitTestSerialImplicitFunction.cxx
UnitTestSerialPointLocatorUniformGrid.cxx
UnitTestSerialVirtualObjectCache.cxx
UnitTestSerialVirtualObjectHandle.cxx
)
vtkm_unit_tests(TBB SOURCES ${unit_tests})

@ -17,21 +17,21 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/testing/TestingVirtualObjectCache.h>
#include <vtkm/cont/testing/TestingVirtualObjectHandle.h>
namespace
{
void TestVirtualObjectCache()
void TestVirtualObjectHandle()
{
using DeviceAdapterList = vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagSerial>;
vtkm::cont::testing::TestingVirtualObjectCache<DeviceAdapterList>::Run();
vtkm::cont::testing::TestingVirtualObjectHandle<DeviceAdapterList>::Run();
}
} // anonymous namespace
int UnitTestSerialVirtualObjectCache(int, char* [])
int UnitTestSerialVirtualObjectHandle(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestVirtualObjectCache);
return vtkm::cont::testing::Testing::Run(TestVirtualObjectHandle);
}

@ -31,10 +31,14 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject, TargetClass, vtkm::cont::DeviceAdapterTagTBB>
: public VirtualObjectTransferShareWithControl<VirtualObject, TargetClass>
template <typename VirtualDerivedType>
struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagTBB>
: VirtualObjectTransferShareWithControl<VirtualDerivedType>
{
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject)
: VirtualObjectTransferShareWithControl<VirtualDerivedType>(virtualObject)
{
}
};
}
}

@ -28,6 +28,6 @@ set(unit_tests
UnitTestTBBDeviceAdapter.cxx
UnitTestTBBImplicitFunction.cxx
UnitTestTBBPointLocatorUniformGrid.cxx
UnitTestTBBVirtualObjectCache.cxx
UnitTestTBBVirtualObjectHandle.cxx
)
vtkm_unit_tests(TBB SOURCES ${unit_tests})

@ -17,22 +17,22 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/testing/TestingVirtualObjectCache.h>
#include <vtkm/cont/testing/TestingVirtualObjectHandle.h>
namespace
{
void TestVirtualObjectCache()
void TestVirtualObjectHandle()
{
using DeviceAdapterList =
vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagSerial, vtkm::cont::DeviceAdapterTagTBB>;
vtkm::cont::testing::TestingVirtualObjectCache<DeviceAdapterList>::Run();
vtkm::cont::testing::TestingVirtualObjectHandle<DeviceAdapterList>::Run();
}
} // anonymous namespace
int UnitTestTBBVirtualObjectCache(int, char* [])
int UnitTestTBBVirtualObjectHandle(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestVirtualObjectCache);
return vtkm::cont::testing::Testing::Run(TestVirtualObjectHandle);
}

@ -31,7 +31,7 @@ set(headers
TestingFancyArrayHandles.h
TestingImplicitFunction.h
TestingPointLocatorUniformGrid.h
TestingVirtualObjectCache.h
TestingVirtualObjectHandle.h
)
vtkm_declare_headers(${headers})

@ -316,44 +316,31 @@ public:
class VirtualObjectTransferKernel
{
public:
struct Interface
struct Interface : public vtkm::VirtualObjectBase
{
using FooSig = vtkm::Id(const void*);
template <typename T>
VTKM_EXEC void Bind(const T* target)
{
this->Target = target;
this->FooPtr = [](const void* t) { return static_cast<const T*>(t)->Foo(); };
}
VTKM_EXEC
vtkm::Id Foo() const { return this->FooPtr(this->Target); }
const void* Target;
FooSig* FooPtr;
VTKM_EXEC virtual vtkm::Id Foo() const = 0;
};
struct Concrete
struct Concrete : public Interface
{
vtkm::Id Foo() const { return this->Value; }
VTKM_EXEC vtkm::Id Foo() const override { return this->Value; }
vtkm::Id Value = 0;
};
VirtualObjectTransferKernel(const Interface& vo, IdArrayHandle& result)
VirtualObjectTransferKernel(const Interface* vo, IdArrayHandle& result)
: Virtual(vo)
, Result(result.PrepareForInPlace(DeviceAdapterTag()))
{
}
VTKM_EXEC
void operator()(vtkm::Id) const { this->Result.Set(0, this->Virtual.Foo()); }
void operator()(vtkm::Id) const { this->Result.Set(0, this->Virtual->Foo()); }
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
private:
Interface Virtual;
const Interface* Virtual;
IdPortalType Result;
};
@ -512,10 +499,9 @@ private:
VTKM_CONT
static void TestVirtualObjectTransfer()
{
using VirtualObject = typename VirtualObjectTransferKernel::Interface;
using BaseType = typename VirtualObjectTransferKernel::Interface;
using TargetType = typename VirtualObjectTransferKernel::Concrete;
using Transfer =
vtkm::cont::internal::VirtualObjectTransfer<VirtualObject, TargetType, DeviceAdapterTag>;
using Transfer = vtkm::cont::internal::VirtualObjectTransfer<TargetType, DeviceAdapterTag>;
IdArrayHandle result;
result.Allocate(1);
@ -524,21 +510,21 @@ private:
TargetType target;
target.Value = 5;
VirtualObject vo;
void* state = Transfer::Create(vo, &target);
Transfer transfer(&target);
const BaseType* base = transfer.PrepareForExecution(false);
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing VirtualObjectTransfer" << std::endl;
Algorithm::Schedule(VirtualObjectTransferKernel(vo, result), 1);
Algorithm::Schedule(VirtualObjectTransferKernel(base, result), 1);
VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(0) == 5, "Did not get expected result");
target.Value = 10;
Transfer::Update(state, &target);
Algorithm::Schedule(VirtualObjectTransferKernel(vo, result), 1);
base = transfer.PrepareForExecution(true);
Algorithm::Schedule(VirtualObjectTransferKernel(base, result), 1);
VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(0) == 10, "Did not get expected result");
Transfer::Cleanup(state);
transfer.ReleaseResources();
}
static VTKM_CONT void TestAlgorithmSchedule()

@ -22,7 +22,7 @@
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
@ -50,7 +50,7 @@ public:
typedef void ControlSignature(FieldIn<Vec3>, FieldOut<Scalar>);
typedef void ExecutionSignature(_1, _2);
EvaluateImplicitFunction(const vtkm::exec::ImplicitFunction& function)
EvaluateImplicitFunction(const vtkm::ImplicitFunction* function)
: Function(function)
{
}
@ -58,16 +58,16 @@ public:
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function.Value(point);
val = this->Function->Value(point);
}
private:
vtkm::exec::ImplicitFunction Function;
const vtkm::ImplicitFunction* Function;
};
template <typename DeviceAdapter>
void EvaluateOnCoordinates(vtkm::cont::CoordinateSystem points,
const vtkm::cont::ImplicitFunction& function,
const vtkm::cont::ImplicitFunctionHandle& function,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>& values,
DeviceAdapter device)
{
@ -141,13 +141,16 @@ private:
template <typename DeviceAdapter>
void TestBox(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Box on "
std::cout << "Testing vtkm::Box on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Box box({ 0.0f, -0.5f, -0.5f }, { 1.5f, 1.5f, 0.5f });
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), box, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(
vtkm::Box({ 0.0f, -0.5f, -0.5f }, { 1.5f, 1.5f, 0.5f })),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f }
@ -159,17 +162,20 @@ private:
template <typename DeviceAdapter>
void TestCylinder(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Cylinder on "
std::cout << "Testing vtkm::Cylinder on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Cylinder cylinder;
vtkm::Cylinder cylinder;
cylinder.SetCenter({ 0.0f, 0.0f, 1.0f });
cylinder.SetAxis({ 0.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), cylinder, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::ImplicitFunctionHandle(&cylinder, false),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f }
@ -181,7 +187,7 @@ private:
template <typename DeviceAdapter>
void TestFrustum(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Frustum on "
std::cout << "Testing vtkm::Frustum on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::Vec<vtkm::FloatDefault, 3> points[8] = {
@ -194,12 +200,15 @@ private:
{ 1.5f, 1.5f, 1.5f }, // 6
{ 0.5f, 1.5f, 1.5f } // 7
};
vtkm::cont::Frustum frustum;
vtkm::Frustum frustum;
frustum.CreateFromPoints(points);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), frustum, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(frustum),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 0.0f, 0.0f, 0.0f, 0.316228f, 0.316228f, -0.316228f, 0.316228f }
@ -211,23 +220,25 @@ private:
template <typename DeviceAdapter>
void TestPlane(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Plane on "
std::cout << "Testing vtkm::Plane on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Plane plane({ 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 1.0f });
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
auto planeHandle = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Plane>(
vtkm::make_Vec(0.5f, 0.5f, 0.5f), vtkm::make_Vec(1.0f, 0.0f, 1.0f));
auto plane = static_cast<vtkm::Plane*>(planeHandle.Get());
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), plane, values, device);
this->Input.GetCoordinateSystem(0), planeHandle, values, device);
std::array<vtkm::FloatDefault, 8> expected1 = {
{ -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected1),
"Result does not match expected values");
plane.SetNormal({ -1.0f, 0.0f, -1.0f });
plane->SetNormal({ -1.0f, 0.0f, -1.0f });
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), plane, values, device);
this->Input.GetCoordinateSystem(0), planeHandle, values, device);
std::array<vtkm::FloatDefault, 8> expected2 = {
{ 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f }
};
@ -238,13 +249,15 @@ private:
template <typename DeviceAdapter>
void TestSphere(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Sphere on "
std::cout << "Testing vtkm::Sphere on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Sphere sphere({ 0.0f, 0.0f, 0.0f }, 1.0f);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), sphere, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(vtkm::make_Vec(0.0f, 0.0f, 0.0f), 1.0f),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 1.0f }

@ -17,14 +17,14 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_testing_TestingVirtualObjectCache_h
#define vtk_m_cont_testing_TestingVirtualObjectCache_h
#ifndef vtk_m_cont_testing_TestingVirtualObjectHandle_h
#define vtk_m_cont_testing_TestingVirtualObjectHandle_h
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/VirtualObjectCache.h>
#include <vtkm/cont/VirtualObjectHandle.h>
#include <vtkm/cont/testing/Testing.h>
#define ARRAY_LEN 8
@ -39,62 +39,76 @@ namespace testing
namespace virtual_object_detail
{
class Transformer
class Transformer : public vtkm::VirtualObjectBase
{
public:
template <typename T>
VTKM_EXEC void Bind(const T* target)
VTKM_EXEC
virtual vtkm::FloatDefault Eval(vtkm::FloatDefault val) const = 0;
};
class Square : public Transformer
{
public:
VTKM_EXEC
vtkm::FloatDefault Eval(vtkm::FloatDefault val) const override { return val * val; }
};
class Multiply : public Transformer
{
public:
VTKM_CONT
void SetMultiplicand(vtkm::FloatDefault val)
{
this->Concrete = target;
this->Caller = [](const void* concrete, vtkm::FloatDefault val) {
return static_cast<const T*>(concrete)->operator()(val);
};
this->Multiplicand = val;
this->Modified();
}
VTKM_CONT
vtkm::FloatDefault GetMultiplicand() const { return this->Multiplicand; }
VTKM_EXEC
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const
vtkm::FloatDefault Eval(vtkm::FloatDefault val) const override
{
return this->Caller(this->Concrete, val);
return val * this->Multiplicand;
}
private:
using Signature = vtkm::FloatDefault(const void*, vtkm::FloatDefault);
const void* Concrete;
Signature* Caller;
vtkm::FloatDefault Multiplicand = 0.0f;
};
struct Square
class TransformerFunctor
{
VTKM_EXEC
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const { return val * val; }
};
public:
TransformerFunctor() = default;
explicit TransformerFunctor(const Transformer* impl)
: Impl(impl)
{
}
struct Multiply
{
VTKM_EXEC
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const { return val * this->Multiplicand; }
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const { return this->Impl->Eval(val); }
vtkm::FloatDefault Multiplicand;
private:
const Transformer* Impl;
};
} // virtual_object_detail
template <typename DeviceAdapterList>
class TestingVirtualObjectCache
class TestingVirtualObjectHandle
{
private:
using FloatArrayHandle = vtkm::cont::ArrayHandle<vtkm::FloatDefault>;
using ArrayTransform =
vtkm::cont::ArrayHandleTransform<FloatArrayHandle, virtual_object_detail::Transformer>;
using TransformerCache = vtkm::cont::VirtualObjectCache<virtual_object_detail::Transformer>;
vtkm::cont::ArrayHandleTransform<FloatArrayHandle, virtual_object_detail::TransformerFunctor>;
using TransformerHandle = vtkm::cont::VirtualObjectHandle<virtual_object_detail::Transformer>;
class TestStage1
{
public:
TestStage1(const FloatArrayHandle& input, TransformerCache& manager)
TestStage1(const FloatArrayHandle& input, TransformerHandle& handle)
: Input(&input)
, Manager(&manager)
, Handle(&handle)
{
}
@ -107,7 +121,9 @@ private:
for (int n = 0; n < 2; ++n)
{
ArrayTransform transformed(*this->Input, this->Manager->GetVirtualObject(device));
virtual_object_detail::TransformerFunctor tfnctr(this->Handle->PrepareForExecution(device));
ArrayTransform transformed(*this->Input, tfnctr);
FloatArrayHandle output;
Algorithm::Copy(transformed, output);
auto portal = output.GetPortalConstControl();
@ -120,14 +136,14 @@ private:
if (n == 0)
{
std::cout << "\tReleaseResources and test again..." << std::endl;
this->Manager->ReleaseResources();
this->Handle->ReleaseExecutionResources();
}
}
}
private:
const FloatArrayHandle* Input;
TransformerCache* Manager;
TransformerHandle* Handle;
};
class TestStage2
@ -135,10 +151,10 @@ private:
public:
TestStage2(const FloatArrayHandle& input,
virtual_object_detail::Multiply& mul,
TransformerCache& manager)
TransformerHandle& handle)
: Input(&input)
, Mul(&mul)
, Manager(&manager)
, Handle(&handle)
{
}
@ -149,17 +165,18 @@ private:
std::cout << "\tDeviceAdapter: " << vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName()
<< std::endl;
this->Mul->Multiplicand = 2;
this->Manager->SetRefreshFlag(true);
this->Mul->SetMultiplicand(2);
for (int n = 0; n < 2; ++n)
{
ArrayTransform transformed(*this->Input, this->Manager->GetVirtualObject(device));
virtual_object_detail::TransformerFunctor tfnctr(this->Handle->PrepareForExecution(device));
ArrayTransform transformed(*this->Input, tfnctr);
FloatArrayHandle output;
Algorithm::Copy(transformed, output);
auto portal = output.GetPortalConstControl();
for (vtkm::Id i = 0; i < ARRAY_LEN; ++i)
{
VTKM_TEST_ASSERT(portal.Get(i) == FloatDefault(i) * this->Mul->Multiplicand,
VTKM_TEST_ASSERT(portal.Get(i) == FloatDefault(i) * this->Mul->GetMultiplicand(),
"\tIncorrect result");
}
std::cout << "\tSuccess." << std::endl;
@ -167,8 +184,7 @@ private:
if (n == 0)
{
std::cout << "\tUpdate and test again..." << std::endl;
this->Mul->Multiplicand = 3;
this->Manager->SetRefreshFlag(true);
this->Mul->SetMultiplicand(3);
}
}
}
@ -176,7 +192,7 @@ private:
private:
const FloatArrayHandle* Input;
virtual_object_detail::Multiply* Mul;
TransformerCache* Manager;
TransformerHandle* Handle;
};
public:
@ -190,20 +206,20 @@ public:
portal.Set(i, vtkm::FloatDefault(i));
}
TransformerCache manager;
TransformerHandle handle;
std::cout << "Testing with concrete type 1 (Square)..." << std::endl;
virtual_object_detail::Square sqr;
manager.Bind(&sqr, DeviceAdapterList());
vtkm::ListForEach(TestStage1(input, manager), DeviceAdapterList());
handle.Reset(&sqr, false, DeviceAdapterList());
vtkm::ListForEach(TestStage1(input, handle), DeviceAdapterList());
std::cout << "Reset..." << std::endl;
manager.Reset();
handle.Reset();
std::cout << "Testing with concrete type 2 (Multiply)..." << std::endl;
virtual_object_detail::Multiply mul;
manager.Bind(&mul, DeviceAdapterList());
vtkm::ListForEach(TestStage2(input, mul, manager), DeviceAdapterList());
handle.Reset(&mul, false, DeviceAdapterList());
vtkm::ListForEach(TestStage2(input, mul, handle), DeviceAdapterList());
}
};
}

@ -90,12 +90,14 @@ public:
}
};
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject,
TargetClass,
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
: public VirtualObjectTransferShareWithControl<VirtualObject, TargetClass>
template <typename TargetClass>
struct VirtualObjectTransfer<TargetClass, vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
: public VirtualObjectTransferShareWithControl<TargetClass>
{
VirtualObjectTransfer(const TargetClass* target)
: VirtualObjectTransferShareWithControl<TargetClass>(target)
{
}
};
template <typename T>

@ -21,12 +21,10 @@
#ifndef vtk_m_filter_ClipWithImplicitFunction_h
#define vtk_m_filter_ClipWithImplicitFunction_h
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/Clip.h>
#include <memory>
namespace vtkm
{
namespace filter
@ -34,26 +32,18 @@ namespace filter
/// \brief Clip a dataset using an implicit function
///
/// Clip a dataset using a given implicit function value, such as vtkm::cont::Sphere
/// or vtkm::cont::Frustum.
/// Clip a dataset using a given implicit function value, such as vtkm::Sphere
/// or vtkm::Frustum.
/// The resulting geometry will not be water tight.
class ClipWithImplicitFunction : public vtkm::filter::FilterDataSet<ClipWithImplicitFunction>
{
public:
template <typename ImplicitFunctionType, typename DerivedPolicy>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename ImplicitFunctionType>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func)
void SetImplicitFunction(const vtkm::cont::ImplicitFunctionHandle& func)
{
this->Function = func;
}
std::shared_ptr<vtkm::cont::ImplicitFunction> GetImplicitFunction() const
{
return this->Function;
}
const vtkm::cont::ImplicitFunctionHandle& GetImplicitFunction() const { return this->Function; }
template <typename DerivedPolicy, typename DeviceAdapter>
vtkm::filter::Result DoExecute(const vtkm::cont::DataSet& input,
@ -70,7 +60,7 @@ public:
const DeviceAdapter& tag);
private:
std::shared_ptr<vtkm::cont::ImplicitFunction> Function;
vtkm::cont::ImplicitFunctionHandle Function;
vtkm::worklet::Clip Worklet;
};
}

@ -53,16 +53,6 @@ struct PointMapHelper
} // end namespace clipwithimplicitfunction
//-----------------------------------------------------------------------------
template <typename ImplicitFunctionType, typename DerivedPolicy>
inline void ClipWithImplicitFunction::SetImplicitFunction(
const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
func->ResetDevices(DerivedPolicy::DeviceAdapterList);
this->Function = func;
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy, typename DeviceAdapter>
inline vtkm::filter::Result ClipWithImplicitFunction::DoExecute(
@ -79,7 +69,7 @@ inline vtkm::filter::Result ClipWithImplicitFunction::DoExecute(
input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex());
vtkm::cont::CellSetExplicit<> outputCellSet = this->Worklet.Run(
vtkm::filter::ApplyPolicy(cells, policy), *this->Function, inputCoords, device);
vtkm::filter::ApplyPolicy(cells, policy), this->Function, inputCoords, device);
// compute output coordinates
vtkm::cont::DynamicArrayHandle outputCoordsArray;

@ -21,7 +21,7 @@
#ifndef vtk_m_filter_ExtractGeometry_h
#define vtk_m_filter_ExtractGeometry_h
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/ExtractGeometry.h>
@ -52,20 +52,12 @@ public:
ExtractGeometry();
// Set the volume of interest to extract
template <typename ImplicitFunctionType, typename DerivedPolicy>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename ImplicitFunctionType>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func)
void SetImplicitFunction(const vtkm::cont::ImplicitFunctionHandle& func)
{
this->Function = func;
}
std::shared_ptr<vtkm::cont::ImplicitFunction> GetImplicitFunction() const
{
return this->Function;
}
const vtkm::cont::ImplicitFunctionHandle& GetImplicitFunction() const { return this->Function; }
VTKM_CONT
bool GetExtractInside() { return this->ExtractInside; }
@ -111,7 +103,7 @@ private:
bool ExtractInside;
bool ExtractBoundaryCells;
bool ExtractOnlyBoundaryCells;
std::shared_ptr<vtkm::cont::ImplicitFunction> Function;
vtkm::cont::ImplicitFunctionHandle Function;
vtkm::worklet::ExtractGeometry Worklet;
};

@ -34,7 +34,7 @@ struct CallWorker
vtkm::cont::DynamicCellSet& Output;
vtkm::worklet::ExtractGeometry& Worklet;
const vtkm::cont::CoordinateSystem& Coords;
const vtkm::cont::ImplicitFunction& Function;
const vtkm::cont::ImplicitFunctionHandle& Function;
bool ExtractInside;
bool ExtractBoundaryCells;
bool ExtractOnlyBoundaryCells;
@ -42,7 +42,7 @@ struct CallWorker
CallWorker(vtkm::cont::DynamicCellSet& output,
vtkm::worklet::ExtractGeometry& worklet,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::ImplicitFunction& function,
const vtkm::cont::ImplicitFunctionHandle& function,
bool extractInside,
bool extractBoundaryCells,
bool extractOnlyBoundaryCells)
@ -76,15 +76,6 @@ namespace vtkm
namespace filter
{
//-----------------------------------------------------------------------------
template <typename ImplicitFunctionType, typename DerivedPolicy>
inline void ExtractGeometry::SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
func->ResetDevices(DerivedPolicy::DeviceAdapterList);
this->Function = func;
}
//-----------------------------------------------------------------------------
inline VTKM_CONT ExtractGeometry::ExtractGeometry()
: vtkm::filter::FilterDataSet<ExtractGeometry>()
@ -110,7 +101,7 @@ inline VTKM_CONT vtkm::filter::Result ExtractGeometry::DoExecute(
CallWorker<DeviceAdapter> worker(outCells,
this->Worklet,
coords,
*this->Function,
this->Function,
this->ExtractInside,
this->ExtractBoundaryCells,
this->ExtractOnlyBoundaryCells);

@ -21,7 +21,7 @@
#ifndef vtk_m_filter_ExtractPoints_h
#define vtk_m_filter_ExtractPoints_h
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/ExtractPoints.h>
@ -53,21 +53,12 @@ public:
void SetCompactPoints(bool value) { this->CompactPoints = value; }
/// Set the volume of interest to extract
template <typename ImplicitFunctionType, typename DerivedPolicy>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
/// Set the volume of interest to extract
template <typename ImplicitFunctionType>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func)
void SetImplicitFunction(const vtkm::cont::ImplicitFunctionHandle& func)
{
this->Function = func;
}
std::shared_ptr<vtkm::cont::ImplicitFunction> GetImplicitFunction() const
{
return this->Function;
}
const vtkm::cont::ImplicitFunctionHandle& GetImplicitFunction() const { return this->Function; }
VTKM_CONT
bool GetExtractInside() { return this->ExtractInside; }
@ -93,7 +84,7 @@ public:
private:
bool ExtractInside;
std::shared_ptr<vtkm::cont::ImplicitFunction> Function;
vtkm::cont::ImplicitFunctionHandle Function;
bool CompactPoints;
vtkm::filter::CleanGrid Compactor;

@ -44,15 +44,6 @@ namespace vtkm
namespace filter
{
//-----------------------------------------------------------------------------
template <typename ImplicitFunctionType, typename DerivedPolicy>
inline void ExtractPoints::SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
func->ResetDevices(DerivedPolicy::DeviceAdapterList);
this->Function = func;
}
//-----------------------------------------------------------------------------
inline VTKM_CONT ExtractPoints::ExtractPoints()
: vtkm::filter::FilterDataSet<ExtractPoints>()
@ -79,7 +70,7 @@ inline vtkm::filter::Result ExtractPoints::DoExecute(
outCellSet = worklet.Run(vtkm::filter::ApplyPolicy(cells, policy),
vtkm::filter::ApplyPolicy(coords, policy),
*this->Function,
this->Function,
this->ExtractInside,
device);

@ -60,11 +60,10 @@ void TestClipStructured()
vtkm::Vec<vtkm::FloatDefault, 3> center(1, 1, 0);
vtkm::FloatDefault radius(0.5);
auto sphere = std::make_shared<vtkm::cont::Sphere>(center, radius);
vtkm::filter::Result result;
vtkm::filter::ClipWithImplicitFunction clip;
clip.SetImplicitFunction(sphere);
clip.SetImplicitFunction(vtkm::cont::make_ImplicitFunctionHandle(vtkm::Sphere(center, radius)));
result = clip.Execute(ds);
clip.MapFieldOntoOutput(result, ds.GetField("scalars"));

@ -40,7 +40,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;
@ -76,7 +76,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;
@ -112,7 +112,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.5f, 0.5f, 0.5f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.5f, 3.5f, 3.5f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;
@ -147,7 +147,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.5f, 0.5f, 0.5f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.5f, 3.5f, 3.5f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;

@ -40,7 +40,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -82,7 +82,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -125,7 +125,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> center(2.f, 2.f, 2.f);
vtkm::FloatDefault radius(1.8f);
auto sphere = std::make_shared<vtkm::cont::Sphere>(center, radius);
auto sphere = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(center, radius);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -154,7 +154,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.f, 0.f, 0.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(1.f, 1.f, 1.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -183,7 +183,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.f, 0.f, 0.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(1.f, 1.f, 1.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;

@ -30,7 +30,7 @@
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/exec/ExecutionWholeArray.h>
@ -522,7 +522,7 @@ public:
VTKM_CONT
ClipWithImplicitFunction(Clip* clipper,
const DynamicCellSet& cellSet,
const vtkm::exec::ImplicitFunction& function,
const vtkm::ImplicitFunction* function,
vtkm::cont::CellSetExplicit<>* result)
: Clipper(clipper)
, CellSet(&cellSet)
@ -536,8 +536,8 @@ public:
{
// Evaluate the implicit function on the input coordinates using
// ArrayHandleTransform
vtkm::cont::ArrayHandleTransform<ArrayHandleType, vtkm::exec::ImplicitFunctionValue>
clipScalars(handle, this->Function);
vtkm::cont::ArrayHandleTransform<ArrayHandleType, vtkm::ImplicitFunctionValue> clipScalars(
handle, this->Function);
// Clip at locations where the implicit function evaluates to 0
*this->Result = this->Clipper->Run(*this->CellSet, clipScalars, 0.0, DeviceAdapter());
@ -546,13 +546,13 @@ public:
private:
Clip* Clipper;
const DynamicCellSet* CellSet;
const vtkm::exec::ImplicitFunctionValue Function;
vtkm::ImplicitFunctionValue Function;
vtkm::cont::CellSetExplicit<>* Result;
};
template <typename CellSetList, typename DeviceAdapter>
vtkm::cont::CellSetExplicit<> Run(const vtkm::cont::DynamicCellSetBase<CellSetList>& cellSet,
const vtkm::cont::ImplicitFunction& clipFunction,
const vtkm::cont::ImplicitFunctionHandle& clipFunction,
const vtkm::cont::CoordinateSystem& coords,
DeviceAdapter device)
{

@ -27,7 +27,7 @@
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
namespace vtkm
{
@ -58,7 +58,7 @@ public:
}
VTKM_CONT
ExtractCellsByVOI(const vtkm::exec::ImplicitFunction& function,
ExtractCellsByVOI(const vtkm::ImplicitFunction* function,
bool extractInside,
bool extractBoundaryCells,
bool extractOnlyBoundaryCells)
@ -77,11 +77,12 @@ public:
// Count points inside/outside volume of interest
vtkm::IdComponent inCnt = 0;
vtkm::IdComponent outCnt = 0;
for (vtkm::IdComponent indx = 0; indx < numIndices; indx++)
vtkm::Id indx;
for (indx = 0; indx < numIndices; indx++)
{
vtkm::Id ptId = connectivityIn[indx];
vtkm::Id ptId = connectivityIn[static_cast<vtkm::IdComponent>(indx)];
vtkm::Vec<FloatDefault, 3> coordinate = coordinates.Get(ptId);
vtkm::FloatDefault value = this->Function.Value(coordinate);
vtkm::FloatDefault value = this->Function->Value(coordinate);
if (value <= 0)
inCnt++;
if (value >= 0)
@ -106,7 +107,7 @@ public:
}
private:
vtkm::exec::ImplicitFunction Function;
const vtkm::ImplicitFunction* Function;
bool ExtractInside;
bool ExtractBoundaryCells;
bool ExtractOnlyBoundaryCells;
@ -155,7 +156,7 @@ public:
vtkm::cont::CellSetPermutation<CellSetType> Run(
const CellSetType& cellSet,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::ImplicitFunction& implicitFunction,
const vtkm::cont::ImplicitFunctionHandle& implicitFunction,
bool extractInside,
bool extractBoundaryCells,
bool extractOnlyBoundaryCells,

@ -26,7 +26,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
namespace vtkm
{
@ -51,7 +51,7 @@ public:
typedef _3 ExecutionSignature(_2);
VTKM_CONT
ExtractPointsByVOI(const vtkm::exec::ImplicitFunction& function, bool extractInside)
ExtractPointsByVOI(const vtkm::ImplicitFunction* function, bool extractInside)
: Function(function)
, passValue(extractInside)
, failValue(!extractInside)
@ -62,14 +62,14 @@ public:
bool operator()(const vtkm::Vec<vtkm::Float64, 3>& coordinate) const
{
bool pass = passValue;
vtkm::Float64 value = this->Function.Value(coordinate);
vtkm::Float64 value = this->Function->Value(coordinate);
if (value > 0)
pass = failValue;
return pass;
}
private:
vtkm::exec::ImplicitFunction Function;
const vtkm::ImplicitFunction* Function;
bool passValue;
bool failValue;
};
@ -97,7 +97,7 @@ public:
template <typename CellSetType, typename CoordinateType, typename DeviceAdapter>
vtkm::cont::CellSetSingleType<> Run(const CellSetType& cellSet,
const CoordinateType& coordinates,
const vtkm::cont::ImplicitFunction& implicitFunction,
const vtkm::cont::ImplicitFunctionHandle& implicitFunction,
bool extractInside,
DeviceAdapter device)
{

@ -30,7 +30,7 @@
#include <vtkm/cont/DataSetFieldAdd.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/testing/Testing.h>
#include <vector>
@ -243,13 +243,15 @@ void TestClippingWithImplicitFunction()
{
vtkm::Vec<vtkm::FloatDefault, 3> center(1, 1, 0);
vtkm::FloatDefault radius(0.5);
vtkm::cont::Sphere sphere(center, radius);
vtkm::cont::DataSet ds = MakeTestDatasetStructured();
vtkm::worklet::Clip clip;
vtkm::cont::CellSetExplicit<> outputCellSet =
clip.Run(ds.GetCellSet(0), sphere, ds.GetCoordinateSystem("coords"), DeviceAdapter());
clip.Run(ds.GetCellSet(0),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(center, radius),
ds.GetCoordinateSystem("coords"),
DeviceAdapter());
vtkm::cont::ArrayHandleUniformPointCoordinates coordsIn;
ds.GetCoordinateSystem("coords").GetData().CopyTo(coordsIn);

@ -77,7 +77,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.5f, 0.0f, 0.0f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(2.0f, 2.0f, 2.0f);
vtkm::cont::Box box(minPoint, maxPoint);
bool extractInside = true;
bool extractBoundaryCells = false;
@ -88,7 +87,7 @@ public:
vtkm::cont::DynamicCellSet outCellSet =
extractGeometry.Run(cellSet,
dataset.GetCoordinateSystem("coordinates"),
box,
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint),
extractInside,
extractBoundaryCells,
extractOnlyBoundaryCells,
@ -187,7 +186,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.0f, 1.0f, 1.0f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.0f, 3.0f, 3.0f);
vtkm::cont::Box box(minPoint, maxPoint);
bool extractInside = true;
bool extractBoundaryCells = false;
@ -198,7 +196,7 @@ public:
vtkm::cont::DynamicCellSet outCellSet =
extractGeometry.Run(cellSet,
dataset.GetCoordinateSystem("coords"),
box,
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint),
extractInside,
extractBoundaryCells,
extractOnlyBoundaryCells,
@ -229,7 +227,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> center(2.f, 2.f, 2.f);
vtkm::FloatDefault radius(1.8f);
vtkm::cont::Sphere sphere(center, radius);
bool extractInside = true;
bool extractBoundaryCells = false;
@ -240,7 +237,7 @@ public:
vtkm::cont::DynamicCellSet outCellSet =
extractGeometry.Run(cellSet,
dataset.GetCoordinateSystem("coords"),
sphere,
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(center, radius),
extractInside,
extractBoundaryCells,
extractOnlyBoundaryCells,

@ -68,7 +68,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
vtkm::cont::Box box(minPoint, maxPoint);
bool extractInside = true;
// Output dataset contains input coordinate system and point data
@ -77,11 +76,12 @@ public:
// Output data set with cell set containing extracted points
vtkm::worklet::ExtractPoints extractPoints;
OutCellSetType outCellSet = extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coords"),
box,
extractInside,
DeviceAdapter());
OutCellSetType outCellSet =
extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coords"),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint),
extractInside,
DeviceAdapter());
outDataSet.AddCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), 27),
@ -100,7 +100,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
vtkm::cont::Box box(minPoint, maxPoint);
bool extractInside = false;
// Output dataset contains input coordinate system and point data
@ -109,11 +108,12 @@ public:
// Output data set with cell set containing extracted points
vtkm::worklet::ExtractPoints extractPoints;
OutCellSetType outCellSet = extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coords"),
box,
extractInside,
DeviceAdapter());
OutCellSetType outCellSet =
extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coords"),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint),
extractInside,
DeviceAdapter());
outDataSet.AddCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), 98),
@ -132,7 +132,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> center(2.f, 2.f, 2.f);
vtkm::FloatDefault radius(1.8f);
vtkm::cont::Sphere sphere(center, radius);
bool extractInside = true;
// Output dataset contains input coordinate system and point data
@ -141,11 +140,12 @@ public:
// Output data set with cell set containing extracted points
vtkm::worklet::ExtractPoints extractPoints;
OutCellSetType outCellSet = extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coords"),
sphere,
extractInside,
DeviceAdapter());
OutCellSetType outCellSet =
extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coords"),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(center, radius),
extractInside,
DeviceAdapter());
outDataSet.AddCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), 27),
@ -164,7 +164,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.f, 0.f, 0.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(1.f, 1.f, 1.f);
vtkm::cont::Box box(minPoint, maxPoint);
bool extractInside = true;
// Output dataset contains input coordinate system and point data
@ -173,11 +172,12 @@ public:
// Output data set with cell set containing extracted points
vtkm::worklet::ExtractPoints extractPoints;
OutCellSetType outCellSet = extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coordinates"),
box,
extractInside,
DeviceAdapter());
OutCellSetType outCellSet =
extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coordinates"),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint),
extractInside,
DeviceAdapter());
outDataSet.AddCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), 8),
@ -196,7 +196,6 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.f, 0.f, 0.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(1.f, 1.f, 1.f);
vtkm::cont::Box box(minPoint, maxPoint);
bool extractInside = false;
// Output dataset contains input coordinate system and point data
@ -205,11 +204,12 @@ public:
// Output data set with cell set containing extracted points
vtkm::worklet::ExtractPoints extractPoints;
OutCellSetType outCellSet = extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coordinates"),
box,
extractInside,
DeviceAdapter());
OutCellSetType outCellSet =
extractPoints.Run(dataset.GetCellSet(0),
dataset.GetCoordinateSystem("coordinates"),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint),
extractInside,
DeviceAdapter());
outDataSet.AddCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), 3),