From 12643b7d26dbc16cd13a1ed1aff96320aa5318a9 Mon Sep 17 00:00:00 2001
From: Felix Schindler <felix.schindler@wwu.de>
Date: Sun, 16 Aug 2020 09:45:47 +0200
Subject: [PATCH] update due to dune-xt: always keep a copy of functions/grid
 functions

---
 dune/gdt/discretefunction/default.hh          | 42 ++++++++------
 dune/gdt/discretefunction/dof-vector.hh       |  8 +++
 dune/gdt/functionals/l2.hh                    |  2 +
 .../gdt/functionals/localizable-functional.hh |  8 +--
 dune/gdt/interpolations/default.hh            | 15 +++--
 .../assembler/bilinear-form-accumulators.hh   | 22 ++++----
 .../assembler/functional-accumulators.hh      | 12 ++--
 dune/gdt/local/integrands/conversion.hh       | 28 ++++++----
 dune/gdt/local/integrands/div.hh              | 55 +++++--------------
 dune/gdt/local/integrands/gradient-value.hh   | 12 ++--
 dune/gdt/local/integrands/ipdg.hh             | 30 +++++-----
 dune/gdt/local/integrands/laplace-ipdg.hh     | 48 ++++++++--------
 dune/gdt/local/integrands/laplace.hh          | 12 ++--
 .../integrands/linear-advection-upwind.hh     | 30 +++++-----
 dune/gdt/local/integrands/linear-advection.hh | 12 ++--
 dune/gdt/local/integrands/product.hh          | 44 +++++++--------
 .../local/integrands/symmetrized-laplace.hh   | 29 +++-------
 dune/gdt/operators/advection-fv.hh            |  1 -
 dune/gdt/operators/bilinear-form.hh           | 26 +++++----
 dune/gdt/operators/lincomb.hh                 |  2 +-
 dune/gdt/operators/localizable-operator.hh    | 14 +++--
 .../gdt/tools/discretevalued-grid-function.hh | 13 ++++-
 .../gdt/discretefunction/discretefunction.hh  |  2 +-
 .../dune/gdt/discretefunction/dof-vector.cc   |  2 +-
 .../dune/gdt/local/integrands/conversion.hh   | 16 ++----
 .../gdt/local/integrands/element_product.cc   |  6 +-
 .../local/integrands/intersection_product.cc  | 17 +++---
 .../local/integrands/ipdg_boundary_penalty.cc | 12 ++--
 .../local/integrands/ipdg_inner_penalty.cc    | 12 ++--
 python/dune/gdt/local/integrands/laplace.cc   | 16 +++---
 .../laplace_ipdg_dirichlet_coupling.cc        | 32 +++++------
 .../integrands/laplace_ipdg_inner_coupling.cc | 21 ++++---
 .../gdt/local/integrands/linear_advection.cc  | 11 ++--
 ...ear_advection_upwind_dirichlet_coupling.cc | 31 +++++------
 .../linear_advection_upwind_inner_coupling.cc | 11 ++--
 35 files changed, 317 insertions(+), 337 deletions(-)

diff --git a/dune/gdt/discretefunction/default.hh b/dune/gdt/discretefunction/default.hh
index 0a6e79545..818611cc0 100644
--- a/dune/gdt/discretefunction/default.hh
+++ b/dune/gdt/discretefunction/default.hh
@@ -51,6 +51,7 @@ class ConstDiscreteFunction
         range_dim_cols,
         RangeField>
 {
+public:
   using BaseType = XT::Functions::GridFunctionInterface<
       typename internal::AssertArgumentsOfConstDiscreteFunction<Vector, GridView>::E,
       range_dim,
@@ -58,7 +59,6 @@ class ConstDiscreteFunction
       RangeField>;
   using ThisType = ConstDiscreteFunction;
 
-public:
   using ConstDofVectorType = ConstDofVector<Vector, GridView>;
   using SpaceType = SpaceInterface<GridView, range_dim, range_dim_cols, RangeField>;
   using VectorType = Vector;
@@ -77,10 +77,8 @@ public:
   {}
 
   ConstDiscreteFunction(const ThisType&) = default;
-  ConstDiscreteFunction(ThisType&&) = default;
 
-  ThisType& operator=(const ThisType&) = delete;
-  ThisType& operator=(ThisType&&) = delete;
+  ConstDiscreteFunction(ThisType&&) = default;
 
   const SpaceType& space() const
   {
@@ -104,11 +102,21 @@ public:
     return ldf;
   }
 
+  std::unique_ptr<ThisType> copy_as_discrete_function() const
+  {
+    return std::make_unique<ThisType>(*this);
+  }
+
   /**
    * \name ``These methods are required by XT::Functions::GridFunctionInterface.''
    * \{
    */
 
+  std::unique_ptr<BaseType> copy_as_grid_function() const override
+  {
+    return std::make_unique<ThisType>(*this);
+  }
+
   std::string name() const override final
   {
     return name_;
@@ -156,7 +164,6 @@ public:
     this->visualize_gradient(space_.grid_view(), filename, subsampling, vtk_output_type, param);
   }
 
-
 protected:
   const SpaceType& space_;
 
@@ -194,34 +201,29 @@ public:
   using DofVectorType = DofVector<Vector, GridView>;
   using LocalDiscreteFunctionType = LocalDiscreteFunction<Vector, GridView, range_dim, range_dim_cols, RangeField>;
 
-  DiscreteFunction(const SpaceType& spc, VectorType& vector, const std::string nm = "dune.gdt.discretefunction")
+  DiscreteFunction(const SpaceType& spc, VectorType& vector, const std::string nm = "DiscreteFunction")
     : VectorStorage(vector)
     , BaseType(spc, VectorStorage::access(), nm)
     , dofs_(space_.mapper(), VectorStorage::access())
   {}
 
-  DiscreteFunction(const SpaceType& spc, VectorType&& vector, const std::string nm = "dune.gdt.discretefunction")
+  DiscreteFunction(const SpaceType& spc, VectorType&& vector, const std::string nm = "DiscreteFunction")
     : VectorStorage(new VectorType(std::move(vector)))
     , BaseType(spc, VectorStorage::access(), nm)
     , dofs_(space_.mapper(), VectorStorage::access())
   {}
 
-  DiscreteFunction(const SpaceType& spc, const std::string nm = "dune.gdt.discretefunction")
+  DiscreteFunction(const SpaceType& spc, const std::string nm = "DiscreteFunction")
     : VectorStorage(new VectorType(spc.mapper().size(), 0.))
     , BaseType(spc, VectorStorage::access(), nm)
     , dofs_(space_.mapper(), VectorStorage::access())
   {}
 
-  DiscreteFunction(const ThisType& other)
-    : VectorStorage(new VectorType(other.access()))
-    , BaseType(other.space(), VectorStorage::access(), other.name())
-    , dofs_(other.space().mapper(), VectorStorage::access())
-  {}
+  DiscreteFunction(const ThisType&) = delete;
 
-  DiscreteFunction(ThisType&&) = default;
+  DiscreteFunction(ThisType& other) = delete;
 
-  ThisType& operator=(const ThisType&) = delete;
-  ThisType& operator=(ThisType&&) = delete;
+  DiscreteFunction(ThisType&&) = default;
 
   using BaseType::dofs;
 
@@ -243,6 +245,14 @@ public:
     ldf->bind(grid_element);
     return ldf;
   }
+
+  using BaseType::copy_as_discrete_function;
+
+  std::unique_ptr<ThisType> copy_as_discrete_function()
+  {
+    return std::make_unique<ThisType>(*this);
+  }
+
   /**
    * \}
    */
diff --git a/dune/gdt/discretefunction/dof-vector.hh b/dune/gdt/discretefunction/dof-vector.hh
index 5cb1739ad..93fd1e759 100644
--- a/dune/gdt/discretefunction/dof-vector.hh
+++ b/dune/gdt/discretefunction/dof-vector.hh
@@ -44,6 +44,10 @@ public:
                                      << "vector_.size() = " << vector_.size());
   }
 
+  ConstDofVector(const ThisType&) = default;
+
+  ConstDofVector(ThisType&&) = default;
+
   const VectorType& vector() const
   {
     return vector_;
@@ -81,6 +85,10 @@ public:
     , vector_(vec)
   {}
 
+  DofVector(const ThisType&) = default;
+
+  DofVector(ThisType&&) = default;
+
   using BaseType::vector;
 
   VectorType& vector()
diff --git a/dune/gdt/functionals/l2.hh b/dune/gdt/functionals/l2.hh
index 62f04978b..7a05e35b0 100644
--- a/dune/gdt/functionals/l2.hh
+++ b/dune/gdt/functionals/l2.hh
@@ -34,6 +34,8 @@ namespace GDT {
  * See also VectorBasedFunctional for the meaning of the different ctors. Some of these will not compile (if GV and
  * AssemblyGridView do not coincide), which is intended.
  *
+ * \todo Check if we still need this!
+ *
  * \sa VectorBasedFunctional
  * \sa FunctionalInterface
  */
diff --git a/dune/gdt/functionals/localizable-functional.hh b/dune/gdt/functionals/localizable-functional.hh
index 90c222464..cc435ee24 100644
--- a/dune/gdt/functionals/localizable-functional.hh
+++ b/dune/gdt/functionals/localizable-functional.hh
@@ -53,7 +53,7 @@ public:
 
   LocalizableFunctionalBase(GridViewType assembly_grid_view, const SourceType& src)
     : BaseType(assembly_grid_view)
-    , source_(src)
+    , source_(src.copy_as_grid_function())
     , assembled_(false)
   {
     // to detect assembly
@@ -63,7 +63,7 @@ public:
 
   const SourceType& source() const
   {
-    return source_;
+    return *source_;
   }
 
   using BaseType::append;
@@ -72,7 +72,7 @@ public:
                    const XT::Common::Parameter& param = {},
                    const ElementFilterType& filter = ApplyOnAllElements())
   {
-    local_accumulators_.emplace_back(make_local_element_functional_accumulator<GV>(local_functional, source_, param));
+    local_accumulators_.emplace_back(make_local_element_functional_accumulator<GV>(local_functional, &source_, param));
     this->append(*local_accumulators_.back(), filter);
     return *this;
   }
@@ -95,7 +95,7 @@ public:
   }
 
 protected:
-  const SourceType& source_;
+  const std::unique_ptr<SourceType> source_;
   bool assembled_;
   std::list<std::unique_ptr<LocalElementFunctionalAccumulator<GridView, r, rC, R, F>>> local_accumulators_;
 }; // class LocalizableFunctionalBase
diff --git a/dune/gdt/interpolations/default.hh b/dune/gdt/interpolations/default.hh
index b732b4742..32af35743 100644
--- a/dune/gdt/interpolations/default.hh
+++ b/dune/gdt/interpolations/default.hh
@@ -34,6 +34,7 @@ namespace GDT {
 template <class GV, size_t r, size_t rC, class R, class V, class IGV>
 class DefaultInterpolationElementFunctor : public XT::Grid::ElementFunctor<IGV>
 {
+  using ThisType = DefaultInterpolationElementFunctor;
   using BaseType = typename XT::Grid::ElementFunctor<IGV>;
 
 public:
@@ -45,10 +46,10 @@ public:
   using TargetBasisType = typename TargetType::SpaceType::GlobalBasisType::LocalizedType;
 
   DefaultInterpolationElementFunctor(SourceType source, TargetType& target)
-    : source_(source)
+    : source_(source.copy_as_grid_function())
     , target_(target)
     , local_dof_vector_(target.dofs().localize())
-    , local_source_(source_.local_function())
+    , local_source_(source_->local_function())
     , target_basis_(target.space().basis().localize())
   {
     DUNE_THROW_IF(target_.space().type() == SpaceType::raviart_thomas,
@@ -56,15 +57,17 @@ public:
                   "Use the correct one from interpolations/raviart-thomas.hh instead!");
   }
 
-  DefaultInterpolationElementFunctor(const DefaultInterpolationElementFunctor& other)
+  DefaultInterpolationElementFunctor(const ThisType& other)
     : BaseType(other)
-    , source_(other.source_)
+    , source_(other.source_->copy_as_grid_function())
     , target_(other.target_)
     , local_dof_vector_(target_.dofs().localize())
-    , local_source_(source_.local_function())
+    , local_source_(source_->local_function())
     , target_basis_(target_.space().basis().localize())
   {}
 
+  DefaultInterpolationElementFunctor(ThisType&&) = default;
+
   XT::Grid::ElementFunctor<IGV>* copy() override final
   {
     return new DefaultInterpolationElementFunctor(*this);
@@ -80,7 +83,7 @@ public:
   }
 
 private:
-  const SourceType source_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<XT::Grid::extract_entity_t<GV>, r, rC, R>> source_;
   TargetType& target_;
   LocalDofVectorType local_dof_vector_;
   std::unique_ptr<LocalSourceType> local_source_;
diff --git a/dune/gdt/local/assembler/bilinear-form-accumulators.hh b/dune/gdt/local/assembler/bilinear-form-accumulators.hh
index 66b96ff79..3ef499e02 100644
--- a/dune/gdt/local/assembler/bilinear-form-accumulators.hh
+++ b/dune/gdt/local/assembler/bilinear-form-accumulators.hh
@@ -78,12 +78,12 @@ public:
              logging_prefix.empty() ? "ElementBilinearFormAccumulator" : logging_prefix,
              /*logging_disabled=*/logging_prefix.empty())
     , local_bilinear_form_(local_bilinear_form.copy())
-    , source_(source)
-    , range_(range)
+    , source_(source.copy_as_grid_function())
+    , range_(range.copy_as_grid_function())
     , result_(0)
     , param_(param)
-    , local_source_(source_.local_function())
-    , local_range_(range_.local_function())
+    , local_source_(source_->local_function())
+    , local_range_(range_->local_function())
   {
     LOG__(Logger, info) << Logger::logging_id << "(local_bilinear_form=" << &local_bilinear_form
                         << ", source=" << &source << ", range=" << &range << ", param=" << param << ")";
@@ -94,14 +94,16 @@ public:
     , Propagator(other)
     , Logger(other)
     , local_bilinear_form_(other.local_bilinear_form_->copy())
-    , source_(other.source_)
-    , range_(other.range_)
+    , source_(other.source_->copy_as_grid_function())
+    , range_(other.range_->copy_as_grid_function())
     , result_(0)
     , param_(other.param_)
-    , local_source_(source_.local_function())
-    , local_range_(range_.local_function())
+    , local_source_(source_->local_function())
+    , local_range_(range_->local_function())
   {}
 
+  LocalElementBilinearFormAccumulator(ThisType&&) = default;
+
   BaseType* copy() override final
   {
     return Propagator::copy_imp();
@@ -140,8 +142,8 @@ protected:
 
 private:
   const std::unique_ptr<LocalBilinearFormType> local_bilinear_form_;
-  const SourceType& source_;
-  const RangeType& range_;
+  const std::unique_ptr<SourceType> source_;
+  const std::unique_ptr<RangeType> range_;
   ResultType result_;
   const XT::Common::Parameter param_;
   std::unique_ptr<typename SourceType::LocalFunctionType> local_source_;
diff --git a/dune/gdt/local/assembler/functional-accumulators.hh b/dune/gdt/local/assembler/functional-accumulators.hh
index c152f0103..e8f83844f 100644
--- a/dune/gdt/local/assembler/functional-accumulators.hh
+++ b/dune/gdt/local/assembler/functional-accumulators.hh
@@ -59,22 +59,24 @@ public:
     : BaseType()
     , Propagator(this)
     , local_functional_(local_functional.copy())
-    , source_(source)
+    , source_(source.copy_as_grid_function())
     , result_(0)
     , param_(param)
-    , local_source_(source_.local_function())
+    , local_source_(source_->local_function())
   {}
 
   LocalElementFunctionalAccumulator(const ThisType& other)
     : BaseType(other)
     , Propagator(other)
     , local_functional_(other.local_functional_->copy())
-    , source_(other.source_)
+    , source_(other.source_->copy_as_grid_function())
     , result_(0)
     , param_(other.param_)
-    , local_source_(source_.local_function())
+    , local_source_(source_->local_function())
   {}
 
+  LocalElementFunctionalAccumulator(ThisType&& other) = default;
+
   BaseType* copy() override final
   {
     return Propagator::copy_imp();
@@ -107,7 +109,7 @@ protected:
 
 private:
   const std::unique_ptr<LocalFunctionalType> local_functional_;
-  const SourceType& source_;
+  const std::unique_ptr<SourceType> source_;
   ResultType result_;
   const XT::Common::Parameter param_;
   std::unique_ptr<typename SourceType::LocalFunctionType> local_source_;
diff --git a/dune/gdt/local/integrands/conversion.hh b/dune/gdt/local/integrands/conversion.hh
index bdd319229..23dfadafd 100644
--- a/dune/gdt/local/integrands/conversion.hh
+++ b/dune/gdt/local/integrands/conversion.hh
@@ -58,8 +58,8 @@ public:
                logging_prefix.empty() ? "gdt" : "gdt.localbinarytounaryelementintegrand",
                logging_prefix.empty() ? "LocalBinaryToUnaryElementIntegrand" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
-    , inducing_function_as_ansatz_basis_(inducing_function_as_ansatz_basis)
-    , local_function_(inducing_function_as_ansatz_basis_.local_function())
+    , inducing_function_as_ansatz_basis_(inducing_function_as_ansatz_basis.copy_as_grid_function())
+    , local_function_(inducing_function_as_ansatz_basis_->local_function())
     , local_binary_integrand_(local_binary_integrand.copy_as_binary_element_integrand())
   {
     LOG_(debug) << this->logging_id << "(local_binary_integrand=" << &local_binary_integrand
@@ -68,11 +68,13 @@ public:
 
   LocalBinaryToUnaryElementIntegrand(const ThisType& other)
     : BaseType(other)
-    , inducing_function_as_ansatz_basis_(other.inducing_function_as_ansatz_basis_)
-    , local_function_(inducing_function_as_ansatz_basis_.local_function())
+    , inducing_function_as_ansatz_basis_(other.inducing_function_as_ansatz_basis_->copy_as_grid_function())
+    , local_function_(inducing_function_as_ansatz_basis_->local_function())
     , local_binary_integrand_(other.local_binary_integrand_->copy_as_binary_element_integrand())
   {}
 
+  LocalBinaryToUnaryElementIntegrand(ThisType&&) = default;
+
   std::unique_ptr<BaseType> copy_as_unary_element_integrand() const override final
   {
     return std::make_unique<ThisType>(*this);
@@ -117,8 +119,8 @@ public:
   } // ... evaluate(...)
 
 private:
-  const XT::Functions::GridFunction<E, a_r, a_rC, AF> inducing_function_as_ansatz_basis_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, a_r, a_rC, AF>::LocalFunctionType> local_function_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, a_r, a_rC, AF>> inducing_function_as_ansatz_basis_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, a_r, a_rC, AF>::LocalFunctionType> local_function_;
   std::unique_ptr<LocalBinaryElementIntegrandType> local_binary_integrand_;
   mutable DynamicMatrix<F> local_binary_integrand_result_;
 }; // class LocalBinaryToUnaryElementIntegrand
@@ -155,18 +157,20 @@ public:
   LocalBinaryToUnaryIntersectionIntegrand(
       const LocalBinaryIntersectionIntegrandType& local_binary_integrand,
       XT::Functions::GridFunction<E, a_r, a_rC, AF> inducing_function_as_ansatz_basis)
-    : inducing_function_as_ansatz_basis_(inducing_function_as_ansatz_basis)
-    , local_function_(inducing_function_as_ansatz_basis_.local_function())
+    : inducing_function_as_ansatz_basis_(inducing_function_as_ansatz_basis.copy_as_grid_function())
+    , local_function_(inducing_function_as_ansatz_basis_->local_function())
     , local_binary_integrand_(local_binary_integrand.copy_as_binary_intersection_integrand())
   {}
 
   LocalBinaryToUnaryIntersectionIntegrand(const ThisType& other)
     : BaseType(other)
-    , inducing_function_as_ansatz_basis_(other.inducing_function_as_ansatz_basis_)
-    , local_function_(inducing_function_as_ansatz_basis_.local_function())
+    , inducing_function_as_ansatz_basis_(other.inducing_function_as_ansatz_basis_->copy_as_grid_function())
+    , local_function_(inducing_function_as_ansatz_basis_->local_function())
     , local_binary_integrand_(other.local_binary_integrand_->copy_as_binary_intersection_integrand())
   {}
 
+  LocalBinaryToUnaryIntersectionIntegrand(ThisType&&) = default;
+
   std::unique_ptr<BaseType> copy_as_unary_intersection_integrand() const override final
   {
     return std::make_unique<ThisType>(*this);
@@ -212,8 +216,8 @@ public:
   } // ... evaluate(...)
 
 private:
-  const XT::Functions::GridFunction<E, a_r, a_rC, AF> inducing_function_as_ansatz_basis_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, a_r, a_rC, AF>::LocalFunctionType> local_function_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, a_r, a_rC, AF>> inducing_function_as_ansatz_basis_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, a_r, a_rC, AF>::LocalFunctionType> local_function_;
   std::unique_ptr<LocalBinaryIntersectionIntegrandType> local_binary_integrand_;
   mutable DynamicMatrix<F> local_binary_integrand_result_;
 }; // class LocalBinaryToUnaryIntersectionIntegrand
diff --git a/dune/gdt/local/integrands/div.hh b/dune/gdt/local/integrands/div.hh
index 3bdc34113..0937220e0 100644
--- a/dune/gdt/local/integrands/div.hh
+++ b/dune/gdt/local/integrands/div.hh
@@ -10,9 +10,7 @@
 #ifndef DUNE_GDT_LOCAL_INTEGRANDS_DIV_HH
 #define DUNE_GDT_LOCAL_INTEGRANDS_DIV_HH
 
-#include <dune/xt/common/memory.hh>
-#include <dune/xt/functions/constant.hh>
-#include <dune/xt/functions/base/function-as-grid-function.hh>
+#include <dune/xt/functions/grid-function.hh>
 #include <dune/xt/functions/interfaces/grid-function.hh>
 
 #include "interfaces.hh"
@@ -91,32 +89,18 @@ public:
 
   using GridFunctionType = XT::Functions::GridFunctionInterface<E, 1, 1, F>;
 
-  LocalElementAnsatzValueTestDivProductIntegrand(const F& inducing_value = F(1))
-    : BaseType()
-    , DivBaseType()
-    , inducing_function_(new XT::Functions::ConstantGridFunction<ElementType>(inducing_value))
-    , local_function_(inducing_function_.access().local_function())
-  {}
-
-  LocalElementAnsatzValueTestDivProductIntegrand(const XT::Functions::FunctionInterface<d, 1, 1, F>& inducing_function)
-    : BaseType()
-    , DivBaseType()
-    , inducing_function_(new XT::Functions::FunctionAsGridFunctionWrapper<E, 1, 1, F>(inducing_function))
-    , local_function_(inducing_function_.access().local_function())
-  {}
-
-  LocalElementAnsatzValueTestDivProductIntegrand(const GridFunctionType& inducing_function)
+  LocalElementAnsatzValueTestDivProductIntegrand(XT::Functions::GridFunction<E, 1, 1, F> inducing_function = F(1))
     : BaseType(inducing_function.parameter_type())
     , DivBaseType()
-    , inducing_function_(inducing_function)
-    , local_function_(inducing_function_.access().local_function())
+    , inducing_function_(inducing_function.copy_as_grid_function())
+    , local_function_(inducing_function_->local_function())
   {}
 
   LocalElementAnsatzValueTestDivProductIntegrand(const ThisType& other)
     : BaseType(other)
     , DivBaseType()
-    , inducing_function_(other.inducing_function_)
-    , local_function_(inducing_function_.access().local_function())
+    , inducing_function_(other.inducing_function_->copy_as_grid_function())
+    , local_function_(inducing_function_->local_function())
   {}
 
   LocalElementAnsatzValueTestDivProductIntegrand(ThisType&& source) = default;
@@ -159,7 +143,7 @@ public:
   } // ... evaluate(...)
 
 private:
-  const XT::Common::ConstStorageProvider<GridFunctionType> inducing_function_;
+  const std::unique_ptr<GridFunctionType> inducing_function_;
   std::unique_ptr<typename GridFunctionType::LocalFunctionType> local_function_;
   mutable std::vector<typename LocalTestBasisType::DerivativeRangeType> test_basis_jacobians_;
   mutable std::vector<typename LocalAnsatzBasisType::RangeType> ansatz_basis_values_;
@@ -190,29 +174,16 @@ public:
 
   using GridFunctionType = XT::Functions::GridFunctionInterface<E, 1, 1, F>;
 
-  LocalElementAnsatzDivTestValueProductIntegrand(const F& inducing_value = F(1))
-    : BaseType()
-    , inducing_function_(new XT::Functions::FunctionAsGridFunctionWrapper<E, 1, 1, F>(
-          new XT::Functions::ConstantFunction<d, 1, 1, F>(inducing_value)))
-    , local_function_(inducing_function_.access().local_function())
-  {}
-
-  LocalElementAnsatzDivTestValueProductIntegrand(const XT::Functions::FunctionInterface<d, 1, 1, F>& inducing_function)
+  LocalElementAnsatzDivTestValueProductIntegrand(XT::Functions::GridFunction<d, 1, 1, F> inducing_function = F(1))
     : BaseType()
-    , inducing_function_(new XT::Functions::FunctionAsGridFunctionWrapper<E, 1, 1, F>(inducing_function))
-    , local_function_(inducing_function_.access().local_function())
-  {}
-
-  LocalElementAnsatzDivTestValueProductIntegrand(const GridFunctionType& inducing_function)
-    : BaseType(inducing_function.parameter_type())
-    , inducing_function_(inducing_function)
-    , local_function_(inducing_function_.access().local_function())
+    , inducing_function_(inducing_function.copy_as_grid_function())
+    , local_function_(inducing_function_->local_function())
   {}
 
   LocalElementAnsatzDivTestValueProductIntegrand(const ThisType& other)
     : BaseType(other)
-    , inducing_function_(other.inducing_function_)
-    , local_function_(inducing_function_.access().local_function())
+    , inducing_function_(other.inducing_function_->copy_as_grid_function())
+    , local_function_(inducing_function_->local_function())
   {}
 
   LocalElementAnsatzDivTestValueProductIntegrand(ThisType&& source) = default;
@@ -256,7 +227,7 @@ public:
   } // ... evaluate(...)
 
 private:
-  const XT::Common::ConstStorageProvider<GridFunctionType> inducing_function_;
+  const std::unique_ptr<GridFunctionType> inducing_function_;
   std::unique_ptr<typename GridFunctionType::LocalFunctionType> local_function_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_values_;
   mutable std::vector<typename LocalAnsatzBasisType::DerivativeRangeType> ansatz_basis_jacobians_;
diff --git a/dune/gdt/local/integrands/gradient-value.hh b/dune/gdt/local/integrands/gradient-value.hh
index 6ac315b74..9fb19876e 100644
--- a/dune/gdt/local/integrands/gradient-value.hh
+++ b/dune/gdt/local/integrands/gradient-value.hh
@@ -55,16 +55,16 @@ public:
   using VectorGridFunctionType = XT::Functions::GridFunction<E, vector_size, 1, F>;
   using VectorValues = typename VectorGridFunctionType::LocalFunctionType::RangeReturnType;
 
-  LocalElementGradientValueIntegrand(const VectorGridFunctionType vector_in)
+  LocalElementGradientValueIntegrand(XT::Functions::GridFunction<E, vector_size, 1, F> vector_in)
     : BaseType()
-    , vector_(vector_in)
-    , local_function_(vector_.local_function())
+    , vector_(vector_in.copy_as_grid_function())
+    , local_function_(vector_->local_function())
   {}
 
   LocalElementGradientValueIntegrand(const ThisType& other)
     : BaseType(other)
-    , vector_(other.vector_)
-    , local_function_(vector_.local_function())
+    , vector_(other.vector_->copy_as_grid_function())
+    , local_function_(vector_->local_function())
   {}
 
   LocalElementGradientValueIntegrand(ThisType&& source) = default;
@@ -155,7 +155,7 @@ private:
     }
   };
 
-  const VectorGridFunctionType vector_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, vector_size, 1, F>> vector_;
   std::unique_ptr<typename VectorGridFunctionType::LocalFunctionType> local_function_;
   mutable VectorValues vector_values_;
   mutable BasisValues values_;
diff --git a/dune/gdt/local/integrands/ipdg.hh b/dune/gdt/local/integrands/ipdg.hh
index fe784fe3c..68b11e38b 100644
--- a/dune/gdt/local/integrands/ipdg.hh
+++ b/dune/gdt/local/integrands/ipdg.hh
@@ -68,19 +68,19 @@ public:
                logging_prefix.empty() ? "LocalIPDGIntegrands::InnerPenalty" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
     , penalty_(penalty)
-    , weight_(weight_function)
+    , weight_(weight_function.copy_as_grid_function())
     , intersection_diameter_(intersection_diameter)
-    , local_weight_in_(weight_.local_function())
-    , local_weight_out_(weight_.local_function())
+    , local_weight_in_(weight_->local_function())
+    , local_weight_out_(weight_->local_function())
   {}
 
   InnerPenalty(const ThisType& other)
     : BaseType(other)
     , penalty_(other.penalty_)
-    , weight_(other.weight_)
+    , weight_(other.weight_->copy_as_grid_function())
     , intersection_diameter_(other.intersection_diameter_)
-    , local_weight_in_(weight_.local_function())
-    , local_weight_out_(weight_.local_function())
+    , local_weight_in_(weight_->local_function())
+    , local_weight_out_(weight_->local_function())
   {}
 
   InnerPenalty(ThisType&& source) = default;
@@ -173,10 +173,10 @@ public:
 
 private:
   const double penalty_;
-  XT::Functions::GridFunction<E, d, d> weight_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d, d>> weight_;
   const std::function<double(const I&)> intersection_diameter_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, d, d>::LocalFunctionType> local_weight_in_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, d, d>::LocalFunctionType> local_weight_out_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d>::LocalFunctionType> local_weight_in_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d>::LocalFunctionType> local_weight_out_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_in_values_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_out_values_;
   mutable std::vector<typename LocalAnsatzBasisType::RangeType> ansatz_basis_in_values_;
@@ -209,17 +209,17 @@ public:
                logging_prefix.empty() ? "LocalIPDGIntegrands::BoundaryPenalty" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
     , penalty_(penalty)
-    , weight_(weight_function)
+    , weight_(weight_function.copy_as_grid_function())
     , intersection_diameter_(intersection_diameter)
-    , local_weight_(weight_.local_function())
+    , local_weight_(weight_->local_function())
   {}
 
   BoundaryPenalty(const ThisType& other)
     : BaseType(other)
     , penalty_(other.penalty_)
-    , weight_(other.weight_)
+    , weight_(other.weight_->copy_as_grid_function())
     , intersection_diameter_(other.intersection_diameter_)
-    , local_weight_(weight_.local_function())
+    , local_weight_(weight_->local_function())
   {}
 
   BoundaryPenalty(ThisType&& source) = default;
@@ -282,9 +282,9 @@ public:
 
 private:
   const double penalty_;
-  XT::Functions::GridFunction<E, d, d> weight_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d, d>> weight_;
   const std::function<double(const I&)> intersection_diameter_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, d, d>::LocalFunctionType> local_weight_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d>::LocalFunctionType> local_weight_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_values_;
   mutable std::vector<typename LocalAnsatzBasisType::RangeType> ansatz_basis_values_;
 }; // BoundaryPenalty
diff --git a/dune/gdt/local/integrands/laplace-ipdg.hh b/dune/gdt/local/integrands/laplace-ipdg.hh
index 4f0008f49..1b6143e72 100644
--- a/dune/gdt/local/integrands/laplace-ipdg.hh
+++ b/dune/gdt/local/integrands/laplace-ipdg.hh
@@ -53,23 +53,23 @@ public:
                logging_prefix.empty() ? "LocalLaplaceIPDGIntegrands::InnerCoupling" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
     , symmetry_prefactor_(symmetry_prefactor)
-    , diffusion_(diffusion)
-    , weight_(weight_function)
-    , local_diffusion_in_(diffusion_.local_function())
-    , local_diffusion_out_(diffusion_.local_function())
-    , local_weight_in_(weight_.local_function())
-    , local_weight_out_(weight_.local_function())
+    , diffusion_(diffusion.copy_as_grid_function())
+    , weight_(weight_function.copy_as_grid_function())
+    , local_diffusion_in_(diffusion_->local_function())
+    , local_diffusion_out_(diffusion_->local_function())
+    , local_weight_in_(weight_->local_function())
+    , local_weight_out_(weight_->local_function())
   {}
 
   InnerCoupling(const ThisType& other)
     : BaseType(other)
     , symmetry_prefactor_(other.symmetry_prefactor_)
-    , diffusion_(other.diffusion_)
-    , weight_(other.weight_)
-    , local_diffusion_in_(diffusion_.local_function())
-    , local_diffusion_out_(diffusion_.local_function())
-    , local_weight_in_(weight_.local_function())
-    , local_weight_out_(weight_.local_function())
+    , diffusion_(other.diffusion_->copy_as_grid_function())
+    , weight_(other.weight_->copy_as_grid_function())
+    , local_diffusion_in_(diffusion_->local_function())
+    , local_diffusion_out_(diffusion_->local_function())
+    , local_weight_in_(weight_->local_function())
+    , local_weight_out_(weight_->local_function())
   {}
 
   InnerCoupling(ThisType&& source) = default;
@@ -188,8 +188,8 @@ public:
 
 private:
   const double symmetry_prefactor_;
-  XT::Functions::GridFunction<E, d, d> diffusion_;
-  XT::Functions::GridFunction<E, d, d> weight_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d, d>> diffusion_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d, d>> weight_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d>::LocalFunctionType> local_diffusion_in_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d>::LocalFunctionType> local_diffusion_out_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d>::LocalFunctionType> local_weight_in_;
@@ -248,20 +248,20 @@ public:
                      logging_prefix.empty() ? "LocalLaplaceIPDGIntegrands::DirichletCoupling" : logging_prefix,
                      /*logging_disabled=*/logging_prefix.empty())
     , symmetry_prefactor_(symmetry_prefactor)
-    , diffusion_(diffusion)
-    , dirichlet_data_(dirichlet_data)
-    , local_diffusion_(diffusion_.local_function())
-    , local_dirichlet_data_(dirichlet_data_.local_function())
+    , diffusion_(diffusion.copy_as_grid_function())
+    , dirichlet_data_(dirichlet_data.copy_as_grid_function())
+    , local_diffusion_(diffusion_->local_function())
+    , local_dirichlet_data_(dirichlet_data_->local_function())
   {}
 
   DirichletCoupling(const ThisType& other)
     : BaseUnaryType(other)
     , BaseBinaryType(other)
     , symmetry_prefactor_(other.symmetry_prefactor_)
-    , diffusion_(other.diffusion_)
-    , dirichlet_data_(other.dirichlet_data_)
-    , local_diffusion_(diffusion_.local_function())
-    , local_dirichlet_data_(dirichlet_data_.local_function())
+    , diffusion_(other.diffusion_->copy_as_grid_function())
+    , dirichlet_data_(other.dirichlet_data_->copy_as_grid_function())
+    , local_diffusion_(diffusion_->local_function())
+    , local_dirichlet_data_(dirichlet_data_->local_function())
   {}
 
   DirichletCoupling(ThisType&& source) = default;
@@ -370,8 +370,8 @@ public:
 
 private:
   const double symmetry_prefactor_;
-  XT::Functions::GridFunction<E, d, d> diffusion_;
-  XT::Functions::GridFunction<E> dirichlet_data_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d, d>> diffusion_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E>> dirichlet_data_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d>::LocalFunctionType> local_diffusion_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E>::LocalFunctionType> local_dirichlet_data_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_values_;
diff --git a/dune/gdt/local/integrands/laplace.hh b/dune/gdt/local/integrands/laplace.hh
index 4f8d91b19..8768ab9fb 100644
--- a/dune/gdt/local/integrands/laplace.hh
+++ b/dune/gdt/local/integrands/laplace.hh
@@ -43,14 +43,14 @@ public:
     : BaseType(diffusion.parameter_type(),
                logging_prefix.empty() ? "LocalLaplaceIntegrand" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
-    , weight_(diffusion)
-    , local_weight_(weight_.local_function())
+    , weight_(diffusion.copy_as_grid_function())
+    , local_weight_(weight_->local_function())
   {}
 
   LocalLaplaceIntegrand(const ThisType& other)
     : BaseType(other)
-    , weight_(other.weight_)
-    , local_weight_(weight_.local_function())
+    , weight_(other.weight_->copy_as_grid_function())
+    , local_weight_(weight_->local_function())
   {}
 
   LocalLaplaceIntegrand(ThisType&& source) = default;
@@ -102,8 +102,8 @@ public:
   } // ... evaluate(...)
 
 private:
-  XT::Functions::GridFunction<E, d, d, F> weight_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, d, d, F>::LocalFunctionType> local_weight_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d, d, F>> weight_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, d, F>::LocalFunctionType> local_weight_;
   mutable std::vector<typename LocalTestBasisType::DerivativeRangeType> test_basis_grads_;
   mutable std::vector<typename LocalAnsatzBasisType::DerivativeRangeType> ansatz_basis_grads_;
 }; // class LocalLaplaceIntegrand
diff --git a/dune/gdt/local/integrands/linear-advection-upwind.hh b/dune/gdt/local/integrands/linear-advection-upwind.hh
index fc032d2d9..ee0311fc2 100644
--- a/dune/gdt/local/integrands/linear-advection-upwind.hh
+++ b/dune/gdt/local/integrands/linear-advection-upwind.hh
@@ -45,16 +45,16 @@ public:
                logging_prefix.empty() ? "gdt" : "gdt.AdvectionUpwdInn",
                logging_prefix.empty() ? "LocalLinearAdvectionUpwindIntegrands::InnerCoupling" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
-    , direction_(direction)
-    , local_direction_in_(direction_.local_function())
+    , direction_(direction.copy_as_grid_function())
+    , local_direction_in_(direction_->local_function())
   {
     LOG_(info) << this->logging_id << "(direction=" << &direction << ")" << std::endl;
   }
 
   InnerCoupling(const ThisType& other)
     : BaseType(other)
-    , direction_(other.direction_)
-    , local_direction_in_(direction_.local_function())
+    , direction_(other.direction_->copy_as_grid_function())
+    , local_direction_in_(direction_->local_function())
   {}
 
   InnerCoupling(ThisType&& source) = default;
@@ -145,7 +145,7 @@ public:
   } // ... evaluate(...)
 
 private:
-  XT::Functions::GridFunction<E, d> direction_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d>> direction_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d>::LocalFunctionType> local_direction_in_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_in_values_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_out_values_;
@@ -193,10 +193,10 @@ public:
                      logging_prefix.empty() ? "LocalLinearAdvectionUpwindIntegrands::DirichletCoupling"
                                             : logging_prefix,
                      /*logging_disabled=*/logging_prefix.empty())
-    , direction_(direction)
-    , dirichlet_data_(dirichlet_data)
-    , local_direction_(direction_.local_function())
-    , local_dirichlet_data_(dirichlet_data_.local_function())
+    , direction_(direction.copy_as_grid_function())
+    , dirichlet_data_(dirichlet_data.copy_as_grid_function())
+    , local_direction_(direction_->local_function())
+    , local_dirichlet_data_(dirichlet_data_->local_function())
   {
     LOG_(info) << this->logging_id << "(direction=" << &direction << ", dirichlet_data=" << &dirichlet_data << ")"
                << std::endl;
@@ -205,10 +205,10 @@ public:
   DirichletCoupling(const ThisType& other)
     : BaseUnaryType(other)
     , BaseBinaryType(other)
-    , direction_(other.direction_)
-    , dirichlet_data_(other.dirichlet_data_)
-    , local_direction_(direction_.local_function())
-    , local_dirichlet_data_(dirichlet_data_.local_function())
+    , direction_(other.direction_->copy_as_grid_function())
+    , dirichlet_data_(other.dirichlet_data_->copy_as_grid_function())
+    , local_direction_(direction_->local_function())
+    , local_dirichlet_data_(dirichlet_data_->local_function())
   {}
 
   DirichletCoupling(ThisType&& source) = default;
@@ -327,8 +327,8 @@ public:
   /// \}
 
 private:
-  XT::Functions::GridFunction<E, d> direction_;
-  XT::Functions::GridFunction<E> dirichlet_data_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d>> direction_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E>> dirichlet_data_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d>::LocalFunctionType> local_direction_;
   std::unique_ptr<typename XT::Functions::GridFunctionInterface<E>::LocalFunctionType> local_dirichlet_data_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_values_;
diff --git a/dune/gdt/local/integrands/linear-advection.hh b/dune/gdt/local/integrands/linear-advection.hh
index eb600425e..2d4eb5e78 100644
--- a/dune/gdt/local/integrands/linear-advection.hh
+++ b/dune/gdt/local/integrands/linear-advection.hh
@@ -44,16 +44,16 @@ public:
     : BaseType(direction.parameter_type(),
                logging_prefix.empty() ? "LocalLinearAdvectionIntegrand" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
-    , direction_(direction)
-    , local_direction_(direction_.local_function())
+    , direction_(direction.copy_as_grid_function())
+    , local_direction_(direction_->local_function())
   {
     LOG_(info) << "LocalLinearAdvectionIntegrand(this=" << this << ", direction=" << &direction << ")" << std::endl;
   }
 
   LocalLinearAdvectionIntegrand(const ThisType& other)
     : BaseType(other)
-    , direction_(other.direction_)
-    , local_direction_(direction_.local_function())
+    , direction_(other.direction_->copy_as_grid_function())
+    , local_direction_(direction_->local_function())
   {}
 
   LocalLinearAdvectionIntegrand(ThisType&& source) = default;
@@ -109,8 +109,8 @@ public:
   } // ... evaluate(...)
 
 private:
-  XT::Functions::GridFunction<E, d, 1, F> direction_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, d, 1, F>::LocalFunctionType> local_direction_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, d, 1, F>> direction_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, d, 1, F>::LocalFunctionType> local_direction_;
   mutable std::vector<typename LocalTestBasisType::DerivativeRangeType> test_basis_grads_;
   mutable std::vector<typename LocalAnsatzBasisType::RangeType> ansatz_basis_values_;
 }; // class LocalLinearAdvectionIntegrand
diff --git a/dune/gdt/local/integrands/product.hh b/dune/gdt/local/integrands/product.hh
index 9f0ee69b6..4edadf415 100644
--- a/dune/gdt/local/integrands/product.hh
+++ b/dune/gdt/local/integrands/product.hh
@@ -58,16 +58,16 @@ public:
     : BaseType({},
                logging_prefix.empty() ? "ElementProductIntegrand" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
-    , weight_(weight)
-    , local_weight_(weight_.local_function())
+    , weight_(weight.copy_as_grid_function())
+    , local_weight_(weight_->local_function())
   {
     LOG_(info) << "LocalElementProductIntegrand(this=" << this << ", weight=" << &weight << ")" << std::endl;
   }
 
   LocalElementProductIntegrand(const ThisType& other)
     : BaseType(other)
-    , weight_(other.weight_)
-    , local_weight_(weight_.local_function())
+    , weight_(other.weight_->copy_as_grid_function())
+    , local_weight_(weight_->local_function())
   {}
 
   LocalElementProductIntegrand(ThisType&& source) = default;
@@ -130,8 +130,8 @@ public:
   } // ... evaluate(...)
 
 private:
-  XT::Functions::GridFunction<E, r, r, F> weight_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, r, r, F>::LocalFunctionType> local_weight_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, r, r, F>> weight_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, r, r, F>::LocalFunctionType> local_weight_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_values_;
   mutable std::vector<typename LocalAnsatzBasisType::RangeType> ansatz_basis_values_;
 }; // class LocalElementProductIntegrand
@@ -166,16 +166,16 @@ public:
                logging_prefix.empty() ? "gdt" : "gdt.localcouplingintersectionproductintegrand",
                logging_prefix.empty() ? "LocalCouplingIntersectionProductIntegrand" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
-    , weight_(weight)
-    , local_weight_in_(weight_.local_function())
-    , local_weight_out_(weight_.local_function())
+    , weight_(weight.copy_as_grid_function())
+    , local_weight_in_(weight_->local_function())
+    , local_weight_out_(weight_->local_function())
   {}
 
   LocalCouplingIntersectionProductIntegrand(const ThisType& other)
     : BaseType(other)
-    , weight_(other.weight_)
-    , local_weight_in_(weight_.local_function())
-    , local_weight_out_(weight_.local_function())
+    , weight_(other.weight_->copy_as_grid_function())
+    , local_weight_in_(weight_->local_function())
+    , local_weight_out_(weight_->local_function())
   {}
 
   LocalCouplingIntersectionProductIntegrand(ThisType&& source) = default;
@@ -262,9 +262,9 @@ public:
   } // ... evaluate(...)
 
 private:
-  XT::Functions::GridFunction<E, r, r, F> weight_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, r, r, F>::LocalFunctionType> local_weight_in_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, r, r, F>::LocalFunctionType> local_weight_out_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, r, r, F>> weight_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, r, r, F>::LocalFunctionType> local_weight_in_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, r, r, F>::LocalFunctionType> local_weight_out_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_in_values_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_out_values_;
   mutable std::vector<typename LocalAnsatzBasisType::RangeType> ansatz_basis_in_values_;
@@ -300,15 +300,15 @@ public:
                logging_prefix.empty() ? "gdt" : "gdt.localintersectionproductintegrand",
                logging_prefix.empty() ? "LocalIntersectionProductIntegrand" : logging_prefix,
                /*logging_disabled=*/logging_prefix.empty())
-    , weight_(weight)
-    , local_weight_(weight_.local_function())
+    , weight_(weight.copy_as_grid_function())
+    , local_weight_(weight_->local_function())
     , inside_(use_inside_bases)
   {}
 
   LocalIntersectionProductIntegrand(const ThisType& other)
     : BaseType(other)
-    , weight_(other.weight_)
-    , local_weight_(weight_.local_function())
+    , weight_(other.weight_->copy_as_grid_function())
+    , local_weight_(weight_->local_function())
     , inside_(other.inside_)
   {}
 
@@ -354,7 +354,7 @@ public:
     // prepare sotrage
     this->ensure_size_and_clear_results(test_basis, ansatz_basis, result, param);
     // evaluate
-    typename XT::Functions::GridFunction<E, r, r, F>::LocalFunctionType::RangeReturnType weight;
+    typename XT::Functions::GridFunctionInterface<E, r, r, F>::LocalFunctionType::RangeReturnType weight;
     if (inside_) {
       const auto point_in_inside_reference_element =
           this->intersection().geometryInInside().global(point_in_reference_intersection);
@@ -377,8 +377,8 @@ public:
   } // ... evaluate(...)
 
 private:
-  XT::Functions::GridFunction<E, r, r, F> weight_;
-  std::unique_ptr<typename XT::Functions::GridFunction<E, r, r, F>::LocalFunctionType> local_weight_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, r, r, F>> weight_;
+  std::unique_ptr<typename XT::Functions::GridFunctionInterface<E, r, r, F>::LocalFunctionType> local_weight_;
   const bool inside_;
   mutable std::vector<typename LocalTestBasisType::RangeType> test_basis_values_;
   mutable std::vector<typename LocalAnsatzBasisType::RangeType> ansatz_basis_values_;
diff --git a/dune/gdt/local/integrands/symmetrized-laplace.hh b/dune/gdt/local/integrands/symmetrized-laplace.hh
index 4725cc001..9bbfc013e 100644
--- a/dune/gdt/local/integrands/symmetrized-laplace.hh
+++ b/dune/gdt/local/integrands/symmetrized-laplace.hh
@@ -10,10 +10,8 @@
 #ifndef DUNE_GDT_LOCAL_INTEGRANDS_SYMMETRIZED_LAPLACE_HH
 #define DUNE_GDT_LOCAL_INTEGRANDS_SYMMETRIZED_LAPLACE_HH
 
-#include <dune/xt/common/memory.hh>
 #include <dune/xt/la/container/eye-matrix.hh>
-#include <dune/xt/functions/base/function-as-grid-function.hh>
-#include <dune/xt/functions/constant.hh>
+#include <dune/xt/functions/grid-function.hh>
 #include <dune/xt/functions/interfaces/grid-function.hh>
 
 #include "interfaces.hh"
@@ -45,29 +43,16 @@ public:
 
   using DiffusionFactorType = XT::Functions::GridFunctionInterface<E, 1, 1, F>;
 
-  LocalSymmetrizedLaplaceIntegrand(const F& diffusion_factor = F(1))
-    : BaseType()
-    , diffusion_factor_(new XT::Functions::FunctionAsGridFunctionWrapper<E, 1, 1, F>(
-          new XT::Functions::ConstantFunction<d, 1, 1, F>(diffusion_factor)))
-    , local_diffusion_factor_(diffusion_factor_.access().local_function())
-  {}
-
-  LocalSymmetrizedLaplaceIntegrand(const XT::Functions::FunctionInterface<d, 1, 1, F>& diffusion_factor)
-    : BaseType(diffusion_factor.parameter_type())
-    , diffusion_factor_(new XT::Functions::FunctionAsGridFunctionWrapper<E, 1, 1, F>(diffusion_factor))
-    , local_diffusion_factor_(diffusion_factor_.access().local_function())
-  {}
-
-  LocalSymmetrizedLaplaceIntegrand(const DiffusionFactorType& diffusion_factor)
+  LocalSymmetrizedLaplaceIntegrand(XT::Functions::GridFunctionInterface<d, 1, 1, F> diffusion_factor = F(1))
     : BaseType(diffusion_factor.parameter_type())
-    , diffusion_factor_(diffusion_factor)
-    , local_diffusion_factor_(diffusion_factor_.access().local_function())
+    , diffusion_factor_(diffusion_factor.copy_as_grid_function())
+    , local_diffusion_factor_(diffusion_factor_->local_function())
   {}
 
   LocalSymmetrizedLaplaceIntegrand(const ThisType& other)
     : BaseType(other)
-    , diffusion_factor_(other.diffusion_factor_)
-    , local_diffusion_factor_(diffusion_factor_.access().local_function())
+    , diffusion_factor_(other.diffusion_factor_->copy_as_grid_function())
+    , local_diffusion_factor_(diffusion_factor_->local_function())
   {}
 
   LocalSymmetrizedLaplaceIntegrand(ThisType&& source) = default;
@@ -122,7 +107,7 @@ public:
   } // ... evaluate(...)
 
 private:
-  const XT::Common::ConstStorageProvider<DiffusionFactorType> diffusion_factor_;
+  const std::unique_ptr<DiffusionFactorType> diffusion_factor_;
   std::unique_ptr<typename DiffusionFactorType::LocalFunctionType> local_diffusion_factor_;
   mutable std::vector<typename LocalTestBasisType::DerivativeRangeType> test_basis_grads_;
   mutable std::vector<typename LocalAnsatzBasisType::DerivativeRangeType> ansatz_basis_grads_;
diff --git a/dune/gdt/operators/advection-fv.hh b/dune/gdt/operators/advection-fv.hh
index 8f3b2b31f..e5ea87235 100644
--- a/dune/gdt/operators/advection-fv.hh
+++ b/dune/gdt/operators/advection-fv.hh
@@ -57,7 +57,6 @@ public:
       LocalAdvectionFvBoundaryTreatmentByCustomNumericalFluxOperator<I, V, SGV, m, F, F, RGV, V>;
   using BoundaryTreatmentByCustomExtrapolationOperatorType =
       LocalAdvectionFvBoundaryTreatmentByCustomExtrapolationOperator<I, V, SGV, m, F, F, RGV, V>;
-  using SourceType = XT::Functions::GridFunctionInterface<E, s_r, s_rC, F>;
 
   using typename BaseType::MatrixOperatorType;
   using typename BaseType::RangeSpaceType;
diff --git a/dune/gdt/operators/bilinear-form.hh b/dune/gdt/operators/bilinear-form.hh
index c1f7533b0..fceb1b8f9 100644
--- a/dune/gdt/operators/bilinear-form.hh
+++ b/dune/gdt/operators/bilinear-form.hh
@@ -106,10 +106,10 @@ public:
              logging_prefix.empty() ? "BilinearForm" : logging_prefix,
              /*logging_disabled=*/logging_prefix.empty())
     , grid_view_(grd_vw)
-    , source_(src)
-    , range_(rng)
-    , local_source_(source_.local_function())
-    , local_range_(range_.local_function())
+    , source_(src.copy_as_grid_function())
+    , range_(rng.copy_as_grid_function())
+    , local_source_(source_->local_function())
+    , local_range_(range_->local_function())
     , bilinear_form_value_(1, 1, 0.)
     , result_(0)
   {
@@ -122,10 +122,10 @@ public:
     , Propagator(other)
     , Logger(other)
     , grid_view_(other.grid_view_)
-    , source_(other.source_)
-    , range_(other.range_)
-    , local_source_(source_.local_function())
-    , local_range_(range_.local_function())
+    , source_(other.source_->copy_as_grid_function())
+    , range_(other.range_->copy_as_grid_function())
+    , local_source_(source_->local_function())
+    , local_range_(range_->local_function())
     , bilinear_form_value_(other.bilinear_form_value_)
     , result_(other.result_)
   {
@@ -137,6 +137,8 @@ public:
     }
   } // BilinearForm(...)
 
+  BilinearForm(ThisType&&) = default;
+
   BaseType* copy() override final
   {
     return Propagator::copy_imp();
@@ -149,12 +151,12 @@ public:
 
   const SourceType& source() const
   {
-    return source_;
+    return *source_;
   }
 
   const RangeType& range() const
   {
-    return range_;
+    return *range_;
   }
 
   ThisType&
@@ -262,8 +264,8 @@ protected:
   }
 
   const GridViewType grid_view_;
-  XT::Functions::GridFunction<E, s_r, s_rC, SR> source_;
-  XT::Functions::GridFunction<E, r_r, r_rC, RR> range_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, s_r, s_rC, SR>> source_;
+  const std::unique_ptr<XT::Functions::GridFunctionInterface<E, r_r, r_rC, RR>> range_;
   std::unique_ptr<typename SourceType::LocalFunctionType> local_source_;
   std::unique_ptr<typename RangeType::LocalFunctionType> local_range_;
   DynamicMatrix<Result> bilinear_form_value_;
diff --git a/dune/gdt/operators/lincomb.hh b/dune/gdt/operators/lincomb.hh
index c5d93f1b1..75c1eca89 100644
--- a/dune/gdt/operators/lincomb.hh
+++ b/dune/gdt/operators/lincomb.hh
@@ -514,7 +514,7 @@ public:
 
   using BaseType::operator*;
 
-  LincombOperatorType operator*(const FieldType& alpha)override final
+  LincombOperatorType operator*(const FieldType& alpha) override final
   {
     LincombOperatorType ret(*this); // logging is inherited by copy ctor
     ret *= alpha;
diff --git a/dune/gdt/operators/localizable-operator.hh b/dune/gdt/operators/localizable-operator.hh
index 7a43f61af..196b3e0db 100644
--- a/dune/gdt/operators/localizable-operator.hh
+++ b/dune/gdt/operators/localizable-operator.hh
@@ -93,19 +93,23 @@ public:
 
   LocalizableDiscreteOperatorApplicator(AssemblyGridViewType assembly_grid_view, const SourceType& src, RangeType& rng)
     : BaseType(assembly_grid_view)
-    , source_(src)
+    , source_(src.copy_as_grid_function())
     , range_(rng)
   {}
 
   LocalizableDiscreteOperatorApplicator(const ThisType&) = delete;
 
-  LocalizableDiscreteOperatorApplicator(ThisType&) = default;
+  LocalizableDiscreteOperatorApplicator(ThisType& other)
+    : BaseType(other)
+    , source_(other.source_->copy_as_grid_function())
+    , range_(other.range_)
+  {}
 
   LocalizableDiscreteOperatorApplicator(ThisType&&) = default;
 
   const SourceType& source() const
   {
-    return source_;
+    return *source_;
   }
 
   const RangeType& range() const
@@ -160,7 +164,7 @@ public:
   }
 
 protected:
-  const SourceType& source_;
+  const std::unique_ptr<SourceType> source_;
   RangeType& range_;
 }; // class LocalizableDiscreteOperatorApplicator
 
@@ -377,7 +381,7 @@ public:
     apply(source_function, range, param);
   } // ... apply(...)
 
-  // additional convenience apply methods to mathc the correct one above
+  // additional convenience apply methods to match the correct one above
   void apply(const SourceFunctionInterfaceType& source,
              RangeFunctionType& range,
              const XT::Common::Parameter& param = {}) const
diff --git a/dune/gdt/tools/discretevalued-grid-function.hh b/dune/gdt/tools/discretevalued-grid-function.hh
index 74d146064..401b0ac90 100644
--- a/dune/gdt/tools/discretevalued-grid-function.hh
+++ b/dune/gdt/tools/discretevalued-grid-function.hh
@@ -24,7 +24,7 @@ namespace GDT {
 
 
 /**
- * \brief Wrapper for the map of reconstructed values that fulfills the XT::Functions::LocalizableFunctionInterface
+ * \brief Wrapper for the map of reconstructed values that fulfills the XT::Functions::GridFunctionInterface
  */
 template <class GV, size_t rangeDim, size_t rangeDimCols, class RangeField>
 class DiscreteValuedGridFunction
@@ -122,6 +122,15 @@ public:
     assert(grid_view.size(0) >= 0);
   }
 
+  DiscreteValuedGridFunction(const ThisType&) = default;
+
+  DiscreteValuedGridFunction(ThisType&&) = default;
+
+  std::unique_ptr<BaseType> copy_as_grid_function() const override final
+  {
+    return std::make_unique<ThisType>(*this);
+  }
+
   std::unique_ptr<LocalFunctionType> local_function() const override final
   {
     return std::make_unique<DiscreteValuedLocalFunction>(values_, index_set_);
@@ -134,7 +143,7 @@ public:
 
 private:
   const IndexSetType& index_set_;
-  std::vector<LocalFunctionValuesType>& values_;
+  const std::vector<LocalFunctionValuesType>& values_;
 }; // class DiscreteValuedGridFunction
 
 
diff --git a/python/dune/gdt/discretefunction/discretefunction.hh b/python/dune/gdt/discretefunction/discretefunction.hh
index d0676b205..8c43d92f9 100644
--- a/python/dune/gdt/discretefunction/discretefunction.hh
+++ b/python/dune/gdt/discretefunction/discretefunction.hh
@@ -20,7 +20,7 @@
 #include <dune/xt/grid/type_traits.hh>
 #include <dune/xt/la/container.hh>
 #include <python/dune/xt/common/exceptions.bindings.hh>
-#include <python/dune/xt/functions/gridfunction-interface.hh>
+#include <python/dune/xt/functions/interfaces/grid-function.hh>
 #include <python/dune/xt/grid/grids.bindings.hh>
 #include <python/dune/xt/grid/traits.hh>
 #include <python/dune/xt/la/container.bindings.hh>
diff --git a/python/dune/gdt/discretefunction/dof-vector.cc b/python/dune/gdt/discretefunction/dof-vector.cc
index 9551c8962..e1753a5db 100644
--- a/python/dune/gdt/discretefunction/dof-vector.cc
+++ b/python/dune/gdt/discretefunction/dof-vector.cc
@@ -20,7 +20,7 @@
 #include <dune/xt/grid/type_traits.hh>
 #include <dune/xt/la/container.hh>
 #include <python/dune/xt/common/exceptions.bindings.hh>
-#include <python/dune/xt/functions/gridfunction-interface.hh>
+#include <python/dune/xt/functions/interfaces/grid-function.hh>
 #include <python/dune/xt/grid/grids.bindings.hh>
 #include <python/dune/xt/grid/traits.hh>
 #include <python/dune/xt/la/container.bindings.hh>
diff --git a/python/dune/gdt/local/integrands/conversion.hh b/python/dune/gdt/local/integrands/conversion.hh
index 0016c0e80..88c173db1 100644
--- a/python/dune/gdt/local/integrands/conversion.hh
+++ b/python/dune/gdt/local/integrands/conversion.hh
@@ -87,9 +87,7 @@ public:
                    const std::string&>(),
           "local_binary_integrand"_a,
           "inducing_function_as_ansatz_basis"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>(),
-          py::keep_alive<1, 3>());
+          "logging_prefix"_a = "");
 
     m.def(
         XT::Common::to_camel_case(class_id).c_str(),
@@ -100,9 +98,7 @@ public:
         },
         "local_binary_integrand"_a,
         "inducing_function_as_ansatz_basis"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 1>(),
-        py::keep_alive<0, 2>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
@@ -167,9 +163,7 @@ public:
     c.def(py::init<const typename type::LocalBinaryIntersectionIntegrandType&,
                    const XT::Functions::GridFunctionInterface<E, a_r, a_rC, AF>&>(),
           "local_binary_integrand"_a,
-          "inducing_function_as_ansatz_basis"_a,
-          py::keep_alive<1, 2>(),
-          py::keep_alive<1, 3>());
+          "inducing_function_as_ansatz_basis"_a);
 
     m.def(
         XT::Common::to_camel_case(class_id).c_str(),
@@ -178,9 +172,7 @@ public:
           return new type(local_binary_integrand, inducing_function_as_ansatz_basis);
         },
         "local_binary_integrand"_a,
-        "inducing_function_as_ansatz_basis"_a,
-        py::keep_alive<0, 1>(),
-        py::keep_alive<0, 2>());
+        "inducing_function_as_ansatz_basis"_a);
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/element_product.cc b/python/dune/gdt/local/integrands/element_product.cc
index 5bcf89701..4c18959fc 100644
--- a/python/dune/gdt/local/integrands/element_product.cc
+++ b/python/dune/gdt/local/integrands/element_product.cc
@@ -58,8 +58,7 @@ public:
     c.def(py::init([](const XT::Functions::GridFunctionInterface<E, r, r, F>& weight,
                       const std::string logging_prefix) { return new type(weight, logging_prefix); }),
           "weight"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>());
+          "logging_prefix"_a = "");
 
     // factory
     const auto FactoryName = XT::Common::to_camel_case(class_id);
@@ -69,8 +68,7 @@ public:
           return new type(weight, logging_prefix);
         },
         "weight"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 1>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/intersection_product.cc b/python/dune/gdt/local/integrands/intersection_product.cc
index 5fa0d677f..a869679a3 100644
--- a/python/dune/gdt/local/integrands/intersection_product.cc
+++ b/python/dune/gdt/local/integrands/intersection_product.cc
@@ -58,23 +58,24 @@ public:
       class_name += "_" + XT::Common::Typename<F>::value(/*fail_wo_typeid=*/true);
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
-    c.def(py::init<XT::Functions::GridFunction<E, 1, 1, F>, const bool, const std::string&>(),
-          "weight"_a,
-          "use_inside_bases"_a = true,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>());
+    c.def(
+        py::init([](const XT::Functions::GridFunctionInterface<E, 1, 1, F>& weight,
+                    const bool use_inside_bases,
+                    const std::string& logging_prefix) { return new type(weight, use_inside_bases, logging_prefix); }),
+        "weight"_a,
+        "use_inside_bases"_a = true,
+        "logging_prefix"_a = "");
 
     // factories
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
-        [](XT::Functions::GridFunction<E, 1, 1, F> weight,
+        [](const XT::Functions::GridFunctionInterface<E, 1, 1, F>& weight,
            const bool use_inside_bases,
            const std::string& logging_prefix) { return new type(weight, use_inside_bases, logging_prefix); },
         "weight"_a,
         "use_inside_bases"_a = true,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 1>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/ipdg_boundary_penalty.cc b/python/dune/gdt/local/integrands/ipdg_boundary_penalty.cc
index adff83e7b..b459f7986 100644
--- a/python/dune/gdt/local/integrands/ipdg_boundary_penalty.cc
+++ b/python/dune/gdt/local/integrands/ipdg_boundary_penalty.cc
@@ -60,7 +60,7 @@ public:
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
     c.def(py::init([](const double& penalty,
-                      XT::Functions::GridFunction<E, d, d, F> weight,
+                      const XT::Functions::GridFunctionInterface<E, d, d, F>& weight,
                       const std::string& logging_prefix) {
             return new type(penalty,
                             weight,
@@ -69,21 +69,21 @@ public:
           }),
           "penalty"_a,
           "weight"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 3>());
+          "logging_prefix"_a = "");
 
     // factories
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
-        [](const double& penalty, XT::Functions::GridFunction<E, d, d, F> weight, const std::string& logging_prefix) {
+        [](const double& penalty,
+           const XT::Functions::GridFunctionInterface<E, d, d, F>& weight,
+           const std::string& logging_prefix) {
           return new type(
               penalty, weight, GDT::LocalIPDGIntegrands::internal::default_intersection_diameter<I>(), logging_prefix);
         },
         "penalty"_a,
         "weight"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 2>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/ipdg_inner_penalty.cc b/python/dune/gdt/local/integrands/ipdg_inner_penalty.cc
index 4cfa4d306..15cf26a95 100644
--- a/python/dune/gdt/local/integrands/ipdg_inner_penalty.cc
+++ b/python/dune/gdt/local/integrands/ipdg_inner_penalty.cc
@@ -60,7 +60,7 @@ public:
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
     c.def(py::init([](const double& penalty,
-                      XT::Functions::GridFunction<E, d, d, F> weight,
+                      const XT::Functions::GridFunctionInterface<E, d, d, F>& weight,
                       const std::string& logging_prefix) {
             return new type(penalty,
                             weight,
@@ -69,21 +69,21 @@ public:
           }),
           "penalty"_a,
           "weight"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 3>());
+          "logging_prefix"_a = "");
 
     // factory
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
-        [](const double& penalty, XT::Functions::GridFunction<E, d, d, F> weight, const std::string& logging_prefix) {
+        [](const double& penalty,
+           const XT::Functions::GridFunctionInterface<E, d, d, F>& weight,
+           const std::string& logging_prefix) {
           return new type(
               penalty, weight, GDT::LocalIPDGIntegrands::internal::default_intersection_diameter<I>(), logging_prefix);
         },
         "penalty"_a,
         "weight"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 2>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/laplace.cc b/python/dune/gdt/local/integrands/laplace.cc
index da1d11843..5580c9422 100644
--- a/python/dune/gdt/local/integrands/laplace.cc
+++ b/python/dune/gdt/local/integrands/laplace.cc
@@ -58,33 +58,31 @@ public:
       class_name += "_" + XT::Common::Typename<F>::value(/*fail_wo_typeid=*/true);
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
-    c.def(py::init<XT::Functions::GridFunction<E, d, d, F>, const std::string&>(),
+    c.def(py::init([](const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
+                      const std::string& logging_prefix) { return new type(diffusion, logging_prefix); }),
           "diffusion"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>());
+          "logging_prefix"_a = "");
 
     // factory
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     if (r == 1)
       m.def(
           FactoryName.c_str(),
-          [](XT::Functions::GridFunction<E, d, d, F> diffusion,
+          [](const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
              const XT::Grid::bindings::Dimension<r>&,
              const std::string& logging_prefix) { return new type(diffusion, logging_prefix); },
           "diffusion"_a,
           "dim_range_bases"_a = XT::Grid::bindings::Dimension<r>(),
-          "logging_prefix"_a = "",
-          py::keep_alive<0, 1>());
+          "logging_prefix"_a = "");
     else
       m.def(
           FactoryName.c_str(),
-          [](XT::Functions::GridFunction<E, d, d, F> diffusion,
+          [](const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
              const XT::Grid::bindings::Dimension<r>&,
              const std::string& logging_prefix) { return new type(diffusion, logging_prefix); },
           "diffusion"_a,
           "dim_range_bases"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<0, 1>());
+          "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/laplace_ipdg_dirichlet_coupling.cc b/python/dune/gdt/local/integrands/laplace_ipdg_dirichlet_coupling.cc
index 902817476..192b15afb 100644
--- a/python/dune/gdt/local/integrands/laplace_ipdg_dirichlet_coupling.cc
+++ b/python/dune/gdt/local/integrands/laplace_ipdg_dirichlet_coupling.cc
@@ -61,52 +61,48 @@ public:
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
     c.def(py::init([](const double& symmetry_prefactor,
-                      XT::Functions::GridFunction<E, d, d, F> diffusion,
+                      const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
                       const std::string& logging_prefix) {
             return new type(symmetry_prefactor, diffusion, /*dirichlet_data=*/0., logging_prefix);
           }),
           "symmetry_prefactor"_a,
           "diffusion"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 3>());
-    c.def(py::init<const double&,
-                   XT::Functions::GridFunction<E, d, d, F>,
-                   XT::Functions::GridFunction<E>,
-                   const std::string&>(),
+          "logging_prefix"_a = "");
+    c.def(py::init([](const double& symmetry_prefactor,
+                      const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
+                      const XT::Functions::GridFunctionInterface<E, 1, 1, F>& dirichlet_data,
+                      const std::string& logging_prefix) {
+            return new type(symmetry_prefactor, diffusion, dirichlet_data, logging_prefix);
+          }),
           "symmetry_prefactor"_a,
           "diffusion"_a,
           "dirichlet_data"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 3>(),
-          py::keep_alive<1, 4>());
+          "logging_prefix"_a = "");
 
     // factories
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
         [](const double& symmetry_prefactor,
-           XT::Functions::GridFunction<E, d, d, F> diffusion,
+           const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
            const std::string& logging_prefix) {
           return new type(symmetry_prefactor, diffusion, /*dirichlet_data=*/0., logging_prefix);
         },
         "symmetry_prefactor"_a,
         "diffusion"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 2>());
+        "logging_prefix"_a = "");
     m.def(
         FactoryName.c_str(),
         [](const double& symmetry_prefactor,
-           XT::Functions::GridFunction<E, d, d, F> diffusion,
-           XT::Functions::GridFunction<E> dirichlet_data,
+           const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
+           const XT::Functions::GridFunctionInterface<E, 1, 1, F>& dirichlet_data,
            const std::string& logging_prefix) {
           return new type(symmetry_prefactor, diffusion, dirichlet_data, logging_prefix);
         },
         "symmetry_prefactor"_a,
         "diffusion"_a,
         "dirichlet_data"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 2>(),
-        py::keep_alive<0, 3>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/laplace_ipdg_inner_coupling.cc b/python/dune/gdt/local/integrands/laplace_ipdg_inner_coupling.cc
index c29347d16..6e2ecacbb 100644
--- a/python/dune/gdt/local/integrands/laplace_ipdg_inner_coupling.cc
+++ b/python/dune/gdt/local/integrands/laplace_ipdg_inner_coupling.cc
@@ -59,32 +59,31 @@ public:
       class_name += "_" + XT::Common::Typename<F>::value(/*fail_wo_typeid=*/true);
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
-    c.def(py::init<const double&,
-                   XT::Functions::GridFunction<E, d, d, F>,
-                   XT::Functions::GridFunction<E, d, d, F>,
-                   const std::string&>(),
+    c.def(py::init([](const double& symmetry_prefactor,
+                      const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
+                      const XT::Functions::GridFunctionInterface<E, d, d, F>& weight,
+                      const std::string& logging_prefix) {
+            return new type(symmetry_prefactor, diffusion, weight, logging_prefix);
+          }),
           "symmetry_prefactor"_a,
           "diffusion"_a,
           "weight"_a = F(1),
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 3>(),
-          py::keep_alive<1, 4>());
+          "logging_prefix"_a = "");
 
     // factory
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
         [](const double& symmetry_prefactor,
-           XT::Functions::GridFunction<E, d, d, F> diffusion,
-           XT::Functions::GridFunction<E, d, d, F> weight,
+           const XT::Functions::GridFunctionInterface<E, d, d, F>& diffusion,
+           const XT::Functions::GridFunctionInterface<E, d, d, F>& weight,
            const std::string& logging_prefix) {
           return new type(symmetry_prefactor, diffusion, weight, logging_prefix);
         },
         "symmetry_prefactor"_a,
         "diffusion"_a,
         "weight"_a = F(1),
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 2>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/linear_advection.cc b/python/dune/gdt/local/integrands/linear_advection.cc
index 656225207..fa8894ef5 100644
--- a/python/dune/gdt/local/integrands/linear_advection.cc
+++ b/python/dune/gdt/local/integrands/linear_advection.cc
@@ -56,21 +56,20 @@ public:
       class_name += "_" + XT::Common::Typename<F>::value(/*fail_wo_typeid=*/true);
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
-    c.def(py::init<XT::Functions::GridFunction<E, d, 1, F>, const std::string&>(),
+    c.def(py::init([](const XT::Functions::GridFunctionInterface<E, d, 1, F>& direction,
+                      const std::string& logging_prefix) { return new type(direction, logging_prefix); }),
           "direction"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>());
+          "logging_prefix"_a = "");
 
     // factories
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
-        [](XT::Functions::GridFunction<E, d, 1, F> direction, const std::string& logging_prefix) {
+        [](const XT::Functions::GridFunctionInterface<E, d, 1, F>& direction, const std::string& logging_prefix) {
           return new type(direction, logging_prefix);
         },
         "direction"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 1>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/linear_advection_upwind_dirichlet_coupling.cc b/python/dune/gdt/local/integrands/linear_advection_upwind_dirichlet_coupling.cc
index 885ae348b..c4e9ee0ae 100644
--- a/python/dune/gdt/local/integrands/linear_advection_upwind_dirichlet_coupling.cc
+++ b/python/dune/gdt/local/integrands/linear_advection_upwind_dirichlet_coupling.cc
@@ -60,39 +60,36 @@ public:
       class_name += "_" + XT::Common::Typename<F>::value(/*fail_wo_typeid=*/true);
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
-    c.def(py::init([](XT::Functions::GridFunction<E, d> direction, const std::string& logging_prefix) {
+    c.def(py::init([](const XT::Functions::GridFunctionInterface<E, d>& direction, const std::string& logging_prefix) {
             return new type(direction, /*dirichlet_data=*/0., logging_prefix);
           }),
           "direction"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>());
-    c.def(py::init<XT::Functions::GridFunction<E, d>, XT::Functions::GridFunction<E>, const std::string&>(),
-          "direction"_a,
-          "dirichlet_data"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>(),
-          py::keep_alive<1, 3>());
+          "logging_prefix"_a = "");
+    c.def(
+        py::init([](const XT::Functions::GridFunctionInterface<E, d>& direction,
+                    const XT::Functions::GridFunctionInterface<E>& dirichlet_data,
+                    const std::string& logging_prefix) { return new type(direction, dirichlet_data, logging_prefix); }),
+        "direction"_a,
+        "dirichlet_data"_a,
+        "logging_prefix"_a = "");
 
     // factories
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
-        [](XT::Functions::GridFunction<E, d> direction, const std::string& logging_prefix) {
+        [](const XT::Functions::GridFunctionInterface<E, d>& direction, const std::string& logging_prefix) {
           return new type(direction, /*dirichlet_data=*/0., logging_prefix);
         },
         "direction"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 1>());
+        "logging_prefix"_a = "");
     m.def(
         FactoryName.c_str(),
-        [](XT::Functions::GridFunction<E, d> direction,
-           XT::Functions::GridFunction<E> dirichlet_data,
+        [](const XT::Functions::GridFunctionInterface<E, d>& direction,
+           const XT::Functions::GridFunctionInterface<E>& dirichlet_data,
            const std::string& logging_prefix) { return new type(direction, dirichlet_data, logging_prefix); },
         "direction"_a,
         "dirichlet_data"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 1>(),
-        py::keep_alive<0, 2>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
diff --git a/python/dune/gdt/local/integrands/linear_advection_upwind_inner_coupling.cc b/python/dune/gdt/local/integrands/linear_advection_upwind_inner_coupling.cc
index f343aca72..acaa67611 100644
--- a/python/dune/gdt/local/integrands/linear_advection_upwind_inner_coupling.cc
+++ b/python/dune/gdt/local/integrands/linear_advection_upwind_inner_coupling.cc
@@ -59,21 +59,20 @@ public:
       class_name += "_" + XT::Common::Typename<F>::value(/*fail_wo_typeid=*/true);
     const auto ClassName = XT::Common::to_camel_case(class_name);
     bound_type c(m, ClassName.c_str(), ClassName.c_str());
-    c.def(py::init<XT::Functions::GridFunction<E, d, 1, F>, const std::string&>(),
+    c.def(py::init([](const XT::Functions::GridFunctionInterface<E, d, 1, F>& direction,
+                      const std::string& logging_prefix) { return new type(direction, logging_prefix); }),
           "direction"_a,
-          "logging_prefix"_a = "",
-          py::keep_alive<1, 2>());
+          "logging_prefix"_a = "");
 
     // factory
     const auto FactoryName = XT::Common::to_camel_case(class_id);
     m.def(
         FactoryName.c_str(),
-        [](XT::Functions::GridFunction<E, d, 1, F> direction, const std::string& logging_prefix) {
+        [](const XT::Functions::GridFunctionInterface<E, d, 1, F>& direction, const std::string& logging_prefix) {
           return new type(direction, logging_prefix);
         },
         "direction"_a,
-        "logging_prefix"_a = "",
-        py::keep_alive<0, 1>());
+        "logging_prefix"_a = "");
 
     return c;
   } // ... bind(...)
-- 
GitLab