From a23ecf47f2a7e1cca0852c5a082db55f4040d898 Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Tue, 28 Aug 2018 12:46:43 +0200 Subject: [PATCH] added new type erasure for vtkfunctions --- dune/vtk/vtkfunction.hh | 272 ++++++++++++++++--------- dune/vtk/writers/vtkwriterinterface.hh | 4 +- 2 files changed, 175 insertions(+), 101 deletions(-) diff --git a/dune/vtk/vtkfunction.hh b/dune/vtk/vtkfunction.hh index 11a61ec..1e71acb 100644 --- a/dune/vtk/vtkfunction.hh +++ b/dune/vtk/vtkfunction.hh @@ -4,13 +4,13 @@ #include <dune/common/std/type_traits.hh> #include <dune/functions/common/signature.hh> -#include <dune/functions/common/typeerasure.hh> +#include <dune/grid/io/file/vtk/function.hh> namespace Dune { namespace experimental { /// An abstract base class for LocalFunctions template <class GridView> - class VTKLocalFunctionInterface + class VtkLocalFunctionInterface { public: using Entity = typename GridView::template Codim<0>::Entity; @@ -26,140 +26,208 @@ namespace Dune { namespace experimental virtual double evaluate (int comp, LocalCoordinate const& xi) const = 0; /// Virtual destructor - virtual ~VTKLocalFunctionInterface () = default; + virtual ~VtkLocalFunctionInterface () = default; }; - template <class GridView> - struct VTKLocalFunctionImpl + /// Type erasure for dune-functions LocalFunction interface + template <class GridView, class LocalFunction> + class LocalFunctionWrapper + : public VtkLocalFunctionInterface<GridView> { - template <class Wrapper> - class Model : public Wrapper - { - public: - using Wrapper::Wrapper; - using Function = typename Wrapper::Wrapped; - using Interface = VTKLocalFunctionInterface<GridView>; - - using Entity = typename Interface::Entity; - using LocalCoordinate = typename Interface::LocalCoordinate; - - template <class F, class D> - using Range = std::decay_t<decltype(std::declval<F>()(std::declval<D>()))>; - - template <class F, class D> - using VectorValued = decltype(std::declval<Range<F,D>>()[0u]); - - virtual void bind (Entity const& entity) override - { - this->get().bind(entity); - } - - virtual void unbind () override - { - this->get().unbind(); - } - - virtual double evaluate (int comp, LocalCoordinate const& xi) const override - { - return evaluateImpl(comp, xi, Std::is_detected<VectorValued,Function,LocalCoordinate>{}); - } - - private: - // Evaluate a component of a vector valued data - double evaluateImpl (int comp, LocalCoordinate const& xi, std::true_type) const - { - auto y = this->get()(xi); - return comp < y.size() ? y[comp] : 0.0; - } - - // Return the scalar values - double evaluateImpl (int comp, LocalCoordinate const& xi, std::false_type) const - { - assert(comp == 0); - return this->get()(xi); - } - }; + using Self = LocalFunctionWrapper; + using Interface = VtkLocalFunctionInterface<GridView>; + using Entity = typename Interface::Entity; + using LocalCoordinate = typename Interface::LocalCoordinate; + + template <class F, class D> + using Range = std::decay_t<decltype(std::declval<F>()(std::declval<D>()))>; + + template <class F, class D> + using VectorValued = decltype(std::declval<Range<F,D>>()[0u]); + + public: + template <class LocalFct, disableCopyMove<Self, LocalFct> = 0> + LocalFunctionWrapper (LocalFct&& localFct) + : localFct_(std::forward<LocalFct>(localFct)) + {} + + virtual void bind (Entity const& entity) override + { + localFct_.bind(entity); + } + + virtual void unbind () override + { + localFct_.unbind(); + } + + virtual double evaluate (int comp, LocalCoordinate const& xi) const override + { + return evaluateImpl(comp, xi, Std::is_detected<VectorValued,LocalFunction,LocalCoordinate>{}); + } + + private: + // Evaluate a component of a vector valued data + double evaluateImpl (int comp, LocalCoordinate const& xi, std::true_type) const + { + auto y = localFct_(xi); + return comp < y.size() ? y[comp] : 0.0; + } + + // Return the scalar values + double evaluateImpl (int comp, LocalCoordinate const& xi, std::false_type) const + { + assert(comp == 0); + return localFct_(xi); + } + + private: + LocalFunction localFct_; }; + /// Type erasure for Legacy VTKFunction template <class GridView> - class VTKLocalFunction - : public Functions::TypeErasureBase<VTKLocalFunctionInterface<GridView>, - VTKLocalFunctionImpl<GridView>::template Model> + class VTKLocalFunctionWrapper + : public VtkLocalFunctionInterface<GridView> { - using Super = Functions::TypeErasureBase<VTKLocalFunctionInterface<GridView>, - VTKLocalFunctionImpl<GridView>::template Model>; + using Interface = VtkLocalFunctionInterface<GridView>; + using Entity = typename Interface::Entity; + using LocalCoordinate = typename Interface::LocalCoordinate; + + public: + VTKLocalFunctionWrapper (std::shared_ptr<VTKFunction<GridView> const> const& fct) + : fct_(fct) + {} + + virtual void bind (Entity const& entity) override + { + entity_ = &entity; + } + + virtual void unbind () override + { + entity_ = nullptr; + } + + virtual double evaluate (int comp, LocalCoordinate const& xi) const override + { + return fct_->evaluate(comp, *entity_, xi); + } + + private: + std::shared_ptr<VTKFunction<GridView> const> fct_; + Entity const* entity_; + }; + + template <class GridView> + class VtkLocalFunction + { + using Self = VtkLocalFunction; using Entity = typename GridView::template Codim<0>::Entity; using LocalCoordinate = typename Entity::Geometry::LocalCoordinate; + template <class LF, class E> + using HasBind = decltype(std::declval<LF>().bind(std::declval<E>())); + public: - template <class F, disableCopyMove<VTKLocalFunction, F> = 0> - VTKLocalFunction (F&& f) - : Super(std::forward<F>(f)) + // Store wrapper around dune-function LocalFunction + template <class LocalFct, disableCopyMove<Self, LocalFct> = 0, + std::enable_if_t<Std::is_detected<HasBind, LocalFct, Entity>::value,int> = 0> + VtkLocalFunction (LocalFct&& lf) + : localFct_(std::make_unique<LocalFunctionWrapper<GridView, std::decay_t<LocalFct>>>(std::forward<LocalFct>(lf))) + {} + + // store wrapper around legacy VTKFunction + VtkLocalFunction (std::shared_ptr<VTKFunction<GridView> const> const& lf) + : localFct_(std::make_unique<VTKLocalFunctionWrapper<GridView>>(lf)) {} - VTKLocalFunction () = default; + VtkLocalFunction () = default; /// Bind the function to the grid entity void bind (Entity const& entity) { - this->asInterface().bind(entity); + localFct_->bind(entity); } /// Unbind from the currently bound entity void unbind () { - this->asInterface().unbind(); + localFct_->unbind(); } /// Evaluate the `comp` component of the Range value at local coordinate `xi` double evaluate (int comp, LocalCoordinate const& xi) const { - return this->asInterface().evaluate(comp, xi); + return localFct_->evaluate(comp, xi); } + + private: + std::shared_ptr<VtkLocalFunctionInterface<GridView>> localFct_; }; // --------------------------------------------------------------------------- /// An abstract base class for GlobalFunctions template <class GridView> - class VTKFunctionInterface + class VtkFunctionInterface { public: /// Create a local function - virtual VTKLocalFunction<GridView> makeLocalFunction () const = 0; + virtual VtkLocalFunction<GridView> makeLocalFunction () const = 0; /// Virtual destructor - virtual ~VTKFunctionInterface () = default; + virtual ~VtkFunctionInterface () = default; }; - template <class GridView> - struct VTKFunctionImpl + template <class GridView, class GridViewFunction> + class GridViewFunctionWrapper + : public VtkFunctionInterface<GridView> { - template <class Wrapper> - class Model : public Wrapper - { - public: - using Wrapper::Wrapper; - virtual VTKLocalFunction<GridView> makeLocalFunction () const override - { - return VTKLocalFunction<GridView>{localFunction(this->get())}; - } - }; + using Self = GridViewFunctionWrapper; + + public: + template <class GVFct, disableCopyMove<Self, GVFct> = 0> + GridViewFunctionWrapper (GVFct&& gvFct) + : gvFct_(std::forward<GVFct>(gvFct)) + {} + + virtual VtkLocalFunction<GridView> makeLocalFunction () const override + { + return VtkLocalFunction<GridView>{localFunction(gvFct_)}; + } + + private: + GridViewFunction gvFct_; }; template <class GridView> - class VTKFunction - : public Functions::TypeErasureBase<VTKFunctionInterface<GridView>, - VTKFunctionImpl<GridView>::template Model> + class VTKFunctionWrapper + : public VtkFunctionInterface<GridView> { - using Super = Functions::TypeErasureBase<VTKFunctionInterface<GridView>, - VTKFunctionImpl<GridView>::template Model>; + public: + VTKFunctionWrapper (std::shared_ptr<VTKFunction<GridView> const> const& fct) + : fct_(fct) + {} + virtual VtkLocalFunction<GridView> makeLocalFunction () const override + { + return VtkLocalFunction<GridView>{fct_}; + } + + private: + std::shared_ptr<VTKFunction<GridView> const> fct_; + }; + + + template <class GridView> + class VtkFunction + { template <class F> using HasLocalFunction = decltype(localFunction(std::declval<F>())); @@ -168,37 +236,42 @@ namespace Dune { namespace experimental public: template <class F, + std::enable_if_t<Std::is_detected<HasLocalFunction,F>::value, int> = 0, class Range = typename Functions::SignatureTraits<Signature<F>>::Range> - VTKFunction (F&& f, std::string name, int ncomps = 1, + VtkFunction (F&& f, std::string name, int ncomps = 1, Vtk::DataTypes type = Vtk::Map::type<Range>) - : Super(std::forward<F>(f)) + : fct_(std::make_unique<GridViewFunctionWrapper<GridView,std::decay_t<F>>>(std::forward<F>(f))) , name_(std::move(name)) , ncomps_(ncomps > 3 ? 9 : ncomps > 1 ? 3 : 1) // tensor, vector, or scalar , type_(type) - { - static_assert(Std::is_detected<HasLocalFunction,F>::value, - "Requires A GridFunction to be passed to the VTKFunction."); - } + {} template <class F, + std::enable_if_t<Std::is_detected<HasLocalFunction,F>::value, int> = 0, std::enable_if_t<not Std::is_detected<Signature,F>::value,int> = 0> - VTKFunction (F&& f, std::string name, int ncomps = 1, + VtkFunction (F&& f, std::string name, int ncomps = 1, Vtk::DataTypes type = Vtk::FLOAT32) - : Super(std::forward<F>(f)) + : fct_(std::make_unique<GridViewFunctionWrapper<GridView,std::decay_t<F>>>(std::forward<F>(f))) , name_(std::move(name)) , ncomps_(ncomps > 3 ? 9 : ncomps > 1 ? 3 : 1) // tensor, vector, or scalar , type_(type) - { - static_assert(Std::is_detected<HasLocalFunction,F>::value, - "Requires A GridFunction to be passed to the VTKFunction."); - } + {} + + VtkFunction (std::shared_ptr<VTKFunction<GridView> const> const& fct, + std::string name, int ncomps = 1, + Vtk::DataTypes type = Vtk::FLOAT32) + : fct_(std::make_unique<VTKFunctionWrapper<GridView>>(fct)) + , name_(std::move(name)) + , ncomps_(ncomps > 3 ? 9 : ncomps > 1 ? 3 : 1) // tensor, vector, or scalar + , type_(type) + {} - VTKFunction () = default; + VtkFunction () = default; /// Create a LocalFunction - friend VTKLocalFunction<GridView> localFunction (VTKFunction const& self) + friend VtkLocalFunction<GridView> localFunction (VtkFunction const& self) { - return self.asInterface().makeLocalFunction(); + return self.fct_->makeLocalFunction(); } /// Return a name associated with the function @@ -220,6 +293,7 @@ namespace Dune { namespace experimental } private: + std::shared_ptr<VtkFunctionInterface<GridView>> fct_; std::string name_; int ncomps_ = 1; Vtk::DataTypes type_; diff --git a/dune/vtk/writers/vtkwriterinterface.hh b/dune/vtk/writers/vtkwriterinterface.hh index caf6e43..c86609e 100644 --- a/dune/vtk/writers/vtkwriterinterface.hh +++ b/dune/vtk/writers/vtkwriterinterface.hh @@ -21,8 +21,8 @@ namespace Dune { namespace experimental protected: static constexpr int dimension = GridView::dimension; - using GlobalFunction = VTKFunction<GridView>; - using LocalFunction = VTKLocalFunction<GridView>; + using GlobalFunction = VtkFunction<GridView>; + using LocalFunction = VtkLocalFunction<GridView>; using pos_type = typename std::ostream::pos_type; enum PositionTypes { -- GitLab