Commit 91fc69fd authored by Kenneth Moreland's avatar Kenneth Moreland Committed by Kitware Robot
Browse files

Merge topic 'implicit-functions-no-virtual'

662998f1 Remove make_ImplicitFunctionFunctor functions
27cc99ac Add documentation for Multiplexer and General implicit functions
6a445ebc Do not return a reference from ImplicitFunction::PrepareForExecution
b0fcab5d Do not capture references to execution objects
096e7457 Fix CUDA issues
8c662373 Suppress deprecation warnings in deprecated class
a6725b3a Remove use of deprecated ImplicitFunctions with virtual methods
180d11e7

 Add ImplicitFunctionGeneral
...

Acked-by: default avatarKitware Robot <kwrobot@kitware.com>
Acked-by: default avatarNickolas Davis <nadavi@sandia.gov>
Merge-request: !2413
parents 00762fe5 662998f1
......@@ -8,13 +8,13 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/ImplicitFunction.h>
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleMultiplexer.h>
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/Invoker.h>
#include <vtkm/cont/Timer.h>
......@@ -248,50 +248,35 @@ public:
}
};
template <typename ImplicitFunction>
class EvaluateImplicitFunction : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
EvaluateImplicitFunction(const ImplicitFunction* function)
: Function(function)
{
}
using ControlSignature = void(FieldIn, FieldOut, ExecObject);
using ExecutionSignature = void(_1, _2, _3);
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
template <typename VecType, typename ScalarType, typename FunctionType>
VTKM_EXEC void operator()(const VecType& point,
ScalarType& val,
const FunctionType& function) const
{
val = this->Function->Value(point);
val = function.Value(point);
}
private:
const ImplicitFunction* Function;
};
template <typename T1, typename T2>
class Evaluate2ImplicitFunctions : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
Evaluate2ImplicitFunctions(const T1* f1, const T2* f2)
: Function1(f1)
, Function2(f2)
{
}
using ControlSignature = void(FieldIn, FieldOut, ExecObject, ExecObject);
using ExecutionSignature = void(_1, _2, _3, _4);
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
template <typename VecType, typename ScalarType, typename FType1, typename FType2>
VTKM_EXEC void operator()(const VecType& point,
ScalarType& val,
const FType1& function1,
const FType2& function2) const
{
val = this->Function1->Value(point) + this->Function2->Value(point);
val = function1.Value(point) + function2.Value(point);
}
private:
const T1* Function1;
const T2* Function2;
};
struct PassThroughFunctor
......@@ -821,7 +806,7 @@ static ImplicitFunctionBenchData MakeImplicitFunctionBenchData()
void BenchImplicitFunction(::benchmark::State& state)
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::Sphere>;
using EvalWorklet = EvaluateImplicitFunction;
const vtkm::cont::DeviceAdapterId device = Config.Device;
......@@ -833,10 +818,7 @@ void BenchImplicitFunction(::benchmark::State& state)
state.SetLabel(desc.str());
}
vtkm::cont::Token token;
auto handle = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
auto function = static_cast<const vtkm::Sphere*>(handle.PrepareForExecution(device, token));
EvalWorklet eval(function);
EvalWorklet eval;
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
......@@ -845,7 +827,7 @@ void BenchImplicitFunction(::benchmark::State& state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
invoker(eval, data.Points, data.Result, data.Sphere1);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());
......@@ -855,7 +837,7 @@ VTKM_BENCHMARK(BenchImplicitFunction);
void BenchVirtualImplicitFunction(::benchmark::State& state)
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::ImplicitFunction>;
using EvalWorklet = EvaluateImplicitFunction;
const vtkm::cont::DeviceAdapterId device = Config.Device;
......@@ -867,9 +849,7 @@ void BenchVirtualImplicitFunction(::benchmark::State& state)
state.SetLabel(desc.str());
}
vtkm::cont::Token token;
auto sphere = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
EvalWorklet eval(sphere.PrepareForExecution(device, token));
EvalWorklet eval;
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
......@@ -878,7 +858,7 @@ void BenchVirtualImplicitFunction(::benchmark::State& state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
invoker(eval, data.Points, data.Result, data.Sphere1);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());
......@@ -888,7 +868,7 @@ VTKM_BENCHMARK(BenchVirtualImplicitFunction);
void Bench2ImplicitFunctions(::benchmark::State& state)
{
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::Sphere, vtkm::Sphere>;
using EvalWorklet = Evaluate2ImplicitFunctions;
const vtkm::cont::DeviceAdapterId device = Config.Device;
......@@ -900,12 +880,7 @@ void Bench2ImplicitFunctions(::benchmark::State& state)
state.SetLabel(desc.str());
}
vtkm::cont::Token token;
auto h1 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
auto h2 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere2);
auto f1 = static_cast<const vtkm::Sphere*>(h1.PrepareForExecution(device, token));
auto f2 = static_cast<const vtkm::Sphere*>(h2.PrepareForExecution(device, token));
EvalWorklet eval(f1, f2);
EvalWorklet eval;
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
......@@ -914,7 +889,7 @@ void Bench2ImplicitFunctions(::benchmark::State& state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
invoker(eval, data.Points, data.Result, data.Sphere1, data.Sphere2);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());
......@@ -922,40 +897,6 @@ void Bench2ImplicitFunctions(::benchmark::State& state)
}
VTKM_BENCHMARK(Bench2ImplicitFunctions);
void Bench2VirtualImplicitFunctions(::benchmark::State& state)
{
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::ImplicitFunction, vtkm::ImplicitFunction>;
const vtkm::cont::DeviceAdapterId device = Config.Device;
auto data = MakeImplicitFunctionBenchData();
{
std::ostringstream desc;
desc << data.Points.GetNumberOfValues() << " points";
state.SetLabel(desc.str());
}
vtkm::cont::Token token;
auto s1 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
auto s2 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere2);
EvalWorklet eval(s1.PrepareForExecution(device, token), s2.PrepareForExecution(device, token));
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
for (auto _ : state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());
}
}
VTKM_BENCHMARK(Bench2VirtualImplicitFunctions);
} // end anon namespace
int main(int argc, char* argv[])
......
......@@ -52,7 +52,7 @@ class Redistributor
vtkm::filter::ExtractPoints extractor;
extractor.SetCompactPoints(true);
extractor.SetImplicitFunction(vtkm::cont::make_ImplicitFunctionHandle(box));
extractor.SetImplicitFunction(box);
return extractor.Execute(input);
}
......
......@@ -11,15 +11,26 @@
#define vtk_m_ImplicitFunction_h
#include <vtkm/Bounds.h>
#include <vtkm/Deprecated.h>
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/exec/internal/Variant.h>
// For interface class only.
#include <vtkm/cont/ExecutionAndControlObjectBase.h>
#ifndef VTKM_NO_DEPRECATED_VIRTUAL
#include <vtkm/VirtualObjectBase.h>
#endif // VTKM_NO_DEPRECATED_VIRTUAL
namespace vtkm
{
//============================================================================
class VTKM_ALWAYS_EXPORT ImplicitFunction : public vtkm::VirtualObjectBase
#ifndef VTKM_NO_DEPRECATED_VIRTUAL
class VTKM_DEPRECATED(1.6, "ImplicitFunction with virtual methods no longer supported.")
VTKM_ALWAYS_EXPORT ImplicitFunction : public vtkm::VirtualObjectBase
{
public:
using Scalar = vtkm::FloatDefault;
......@@ -28,6 +39,7 @@ public:
VTKM_EXEC_CONT virtual Scalar Value(const Vector& point) const = 0;
VTKM_EXEC_CONT virtual Vector Gradient(const Vector& point) const = 0;
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const
{
return this->Value(Vector(x, y, z));
......@@ -37,14 +49,60 @@ public:
{
return this->Gradient(Vector(x, y, z));
}
VTKM_DEPRECATED_SUPPRESS_END
};
#endif // VTKM_NO_DEPRECATED_VIRTUAL
//============================================================================
namespace internal
{
/// \brief Base class for all `ImplicitFunction` classes.
///
/// `ImplicitFunctionBase` uses the curiously recurring template pattern (CRTP). Subclasses
/// must provide their own type for the template parameter. Subclasses must implement
/// `Value` and `Gradient` methods.
///
/// Also, all subclasses must be trivially copiable. This is so they can be copied among
/// host and devices.
///
template <typename Derived>
class ImplicitFunctionBase : public vtkm::cont::ExecutionAndControlObjectBase
{
public:
using Scalar = vtkm::FloatDefault;
using Vector = vtkm::Vec<Scalar, 3>;
VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const
{
return reinterpret_cast<const Derived*>(this)->Value(Vector(x, y, z));
}
VTKM_EXEC_CONT Vector Gradient(Scalar x, Scalar y, Scalar z) const
{
return reinterpret_cast<const Derived*>(this)->Gradient(Vector(x, y, z));
}
VTKM_CONT Derived PrepareForExecution(vtkm::cont::DeviceAdapterId, vtkm::cont::Token&) const
{
return *reinterpret_cast<const Derived*>(this);
}
VTKM_CONT Derived PrepareForControl() const { return *reinterpret_cast<const Derived*>(this); }
};
} // namespace vtkm::internal
//============================================================================
#ifndef VTKM_NO_DEPRECATED_VIRTUAL
VTKM_DEPRECATED_SUPPRESS_BEGIN
/// 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
class VTKM_DEPRECATED(1.6,
"Use ImplicitFunctionValueFunctor.") VTKM_ALWAYS_EXPORT ImplicitFunctionValue
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
......@@ -73,7 +131,8 @@ private:
/// passed to things that expect a functor instead of an ImplictFunction class (like an array
/// transform).
///
class VTKM_ALWAYS_EXPORT ImplicitFunctionGradient
class VTKM_DEPRECATED(1.6, "Use ImplicitFunctionGradientFunctor.")
VTKM_ALWAYS_EXPORT ImplicitFunctionGradient
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
......@@ -98,6 +157,76 @@ private:
const vtkm::ImplicitFunction* Function;
};
VTKM_DEPRECATED_SUPPRESS_END
#endif // VTKM_NO_DEPRECATED_VIRTUAL
//============================================================================
/// A helpful functor that calls the value method of a given `ImplicitFunction`. Can be
/// passed to things that expect a functor instead of an `ImplictFunction` class (like an array
/// transform).
///
template <typename FunctionType>
class ImplicitFunctionValueFunctor
{
public:
using Scalar = typename FunctionType::Scalar;
using Vector = typename FunctionType::Vector;
ImplicitFunctionValueFunctor() = default;
VTKM_EXEC_CONT ImplicitFunctionValueFunctor(
const vtkm::internal::ImplicitFunctionBase<FunctionType>& function)
: Function(reinterpret_cast<const FunctionType&>(function))
{
}
VTKM_EXEC_CONT ImplicitFunctionValueFunctor(const FunctionType& function)
: Function(function)
{
}
VTKM_EXEC_CONT Scalar operator()(const Vector& point) const
{
return this->Function.Value(point);
}
private:
FunctionType Function;
};
/// A helpful functor that calls the gradient method of a given `ImplicitFunction`. Can be
/// passed to things that expect a functor instead of an `ImplictFunction` class (like an array
/// transform).
///
template <typename FunctionType>
class ImplicitFunctionGradientFunctor
{
public:
using Scalar = typename FunctionType::Scalar;
using Vector = typename FunctionType::Vector;
ImplicitFunctionGradientFunctor() = default;
VTKM_EXEC_CONT ImplicitFunctionGradientFunctor(
const vtkm::internal::ImplicitFunctionBase<FunctionType>& function)
: Function(reinterpret_cast<const FunctionType&>(function))
{
}
VTKM_EXEC_CONT ImplicitFunctionGradientFunctor(const FunctionType& function)
: Function(function)
{
}
VTKM_EXEC_CONT Vector operator()(const Vector& point) const
{
return this->Function->Gradient(point);
}
private:
FunctionType Function;
};
//============================================================================
/// \brief Implicit function for a box
///
......@@ -106,7 +235,7 @@ private:
/// meeting along shared edges and all faces are orthogonal to the x-y-z
/// coordinate axes.
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunction
class VTKM_ALWAYS_EXPORT Box : public internal::ImplicitFunctionBase<Box>
{
public:
/// \brief Construct box with center at (0,0,0) and each side of length 1.0.
......@@ -130,17 +259,9 @@ public:
VTKM_CONT Box(const vtkm::Bounds& bounds) { this->SetBounds(bounds); }
VTKM_CONT void SetMinPoint(const Vector& point)
{
this->MinPoint = point;
this->Modified();
}
VTKM_CONT void SetMinPoint(const Vector& point) { this->MinPoint = point; }
VTKM_CONT void SetMaxPoint(const Vector& point)
{
this->MaxPoint = point;
this->Modified();
}
VTKM_CONT void SetMaxPoint(const Vector& point) { this->MaxPoint = point; }
VTKM_EXEC_CONT const Vector& GetMinPoint() const { return this->MinPoint; }
......@@ -159,7 +280,7 @@ public:
vtkm::Range(this->MinPoint[2], this->MaxPoint[2]));
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar minDistance = vtkm::NegativeInfinity32();
Scalar diff, t, dist;
......@@ -227,7 +348,7 @@ public:
}
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const final
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
vtkm::IdComponent minAxis = 0;
Scalar dist = 0.0;
......@@ -349,6 +470,11 @@ public:
return normal;
}
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Box* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Box* operator->() const { return this; }
private:
Vector MinPoint;
Vector MaxPoint;
......@@ -365,7 +491,7 @@ private:
///
/// Note that the cylinder is infinite in extent.
///
class VTKM_ALWAYS_EXPORT Cylinder final : public vtkm::ImplicitFunction
class VTKM_ALWAYS_EXPORT Cylinder : public vtkm::internal::ImplicitFunctionBase<Cylinder>
{
public:
/// Construct cylinder radius of 0.5; centered at origin with axis
......@@ -391,32 +517,20 @@ public:
{
}
VTKM_CONT void SetCenter(const Vector& center)
{
this->Center = center;
this->Modified();
}
VTKM_CONT void SetCenter(const Vector& center) { this->Center = center; }
VTKM_CONT void SetAxis(const Vector& axis)
{
this->Axis = vtkm::Normal(axis);
this->Modified();
}
VTKM_CONT void SetAxis(const Vector& axis) { this->Axis = vtkm::Normal(axis); }
VTKM_CONT void SetRadius(Scalar radius)
{
this->Radius = radius;
this->Modified();
}
VTKM_CONT void SetRadius(Scalar radius) { this->Radius = radius; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
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 final
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Vector x2c = point - this->Center;
FloatDefault t = this->Axis[0] * x2c[0] + this->Axis[1] * x2c[1] + this->Axis[2] * x2c[2];
......@@ -424,6 +538,10 @@ public:
return (point - closestPoint) * FloatDefault(2);
}
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Cylinder* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Cylinder* operator->() const { return this; }
private:
Vector Center;
......@@ -433,7 +551,7 @@ private:
//============================================================================
/// \brief Implicit function for a frustum
class VTKM_ALWAYS_EXPORT Frustum final : public vtkm::ImplicitFunction
class VTKM_ALWAYS_EXPORT Frustum : public vtkm::internal::ImplicitFunctionBase<Frustum>
{
public:
/// \brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0.
......@@ -456,7 +574,6 @@ public:
{
this->Normals[index] = normals[index];
}
this->Modified();
}
VTKM_EXEC void SetPlane(int idx, const Vector& point, const Vector& normal)
......@@ -464,7 +581,6 @@ public:
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
......@@ -502,10 +618,9 @@ public:
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::TriangleNormal(v0, v1, v2));
}
this->Modified();
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
......@@ -518,7 +633,7 @@ public:
return maxVal;
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const final
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
vtkm::Id maxValIdx = 0;
......@@ -536,6 +651,11 @@ public:
return this->Normals[maxValIdx];
}
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Frustum* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Frustum* operator->() const { return this; }
private:
Vector Points[6] = { { -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, { 0.0f, -0.5f, 0.0f },
{ 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } };
......@@ -550,7 +670,7 @@ private:
/// The normal does not have to be a unit vector. The implicit function will
/// still evaluate to 0 at the plane, but the values outside the plane
/// (and the gradient) will be scaled by the length of the normal vector.
class VTKM_ALWAYS_EXPORT Plane final : public vtkm::ImplicitFunction
class VTKM_ALWAYS_EXPORT Plane : public vtkm::internal::ImplicitFunctionBase<Plane>
{
public:
/// Construct plane passing through origin and normal to z-axis.
......@@ -574,27 +694,24 @@ public:
{
}
VTKM_CONT void SetOrigin(const Vector& origin)
{
this->Origin = origin;
this->Modified();
}
VTKM_CONT void SetOrigin(const Vector& origin) { this->Origin = origin; }
VTKM_CONT void SetNormal(const Vector& normal)
{
this->Normal = normal;
this->Modified();
}
VTKM_CONT void SetNormal(const Vector& normal) { this->Normal = normal; }
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 final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
return vtkm::Dot(point - this->Origin, this->Normal);
}
VTKM_EXEC_CONT Vector Gradient(const Vector&) const final { return this->Normal; }
VTKM_EXEC_CONT Vector Gradient(const Vector&) const { return this->Normal; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Plane* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Plane* operator->() const { return this; }
private:
Vector Origin;
......@@ -609,7 +726,7 @@ private: