diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5537eb4b20e63bcfa30b0c60eadc6fb2b7219ec6..a42deff0475c4d050155499389d209f37db16180 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Master
 
+- Replaced the class `GlobalGeodesicFEFunction` by a new one called
+  `GlobalGFEFunction`.  There are two important changes:  First of all,
+  the new class implements the `dune-functions` interface rather than
+  the deprecated one based on inheritance from `VirtualGridViewFunction`.
+  Secondly, the new class does not hard-wire geodesic interpolation
+  anymore.  Rather, you can give it interpolation classes which then
+  govern how interpolation is done.
+
 - Added dune-gmsh4 as a dependency
 - Build cosserat-continuum for different combinations of LFE-orders and
   GFE-orders, the respective program is called
diff --git a/dune/gfe/globalgeodesicfefunction.hh b/dune/gfe/globalgeodesicfefunction.hh
deleted file mode 100644
index 1ed94f1aa4f12fbbed8e64d69c2a960b5e24de30..0000000000000000000000000000000000000000
--- a/dune/gfe/globalgeodesicfefunction.hh
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef GLOBAL_GEODESIC_FINITE_ELEMENT_FUNCTION_HH
-#define GLOBAL_GEODESIC_FINITE_ELEMENT_FUNCTION_HH
-
-#include <vector>
-
-#include <dune/common/fvector.hh>
-#include <dune/common/fmatrix.hh>
-
-#include <dune/gfe/localgeodesicfefunction.hh>
-
-template <class dctype, int DimDomain, class rctype, int DimRange>
-struct DerivativeTypefier<Dune::FieldVector<dctype, DimDomain>, UnitVector<rctype,DimRange> >
-{
-  typedef Dune::FieldMatrix<rctype, DimRange, DimDomain> DerivativeType;
-};
-
-template <class dctype, int DimDomain, class rctype, int DimRange>
-struct DerivativeTypefier<Dune::FieldVector<dctype, DimDomain>, RealTuple<rctype,DimRange> >
-{
-  typedef Dune::FieldMatrix<rctype, DimRange, DimDomain> DerivativeType;
-};
-
-
-
-/** \brief Global geodesic finite element function.
- *
- *  \tparam B  - The global basis type.
- *  \tparam TargetSpace - The manifold that this functions takes its values in.
- */
-template<class B, class TargetSpace>
-class GlobalGeodesicFEFunction
-: public VirtualGridViewFunction<typename B::GridView, TargetSpace>
-{
-
-public:
-    typedef B Basis;
-
-    typedef typename Basis::LocalFiniteElement LocalFiniteElement;
-    typedef typename Basis::GridView GridView;
-    typedef typename GridView::template Codim<0>::Entity Element;
-    typedef typename GridView::Grid::ctype  ctype;
-
-    typedef LocalGeodesicFEFunction<GridView::dimension, ctype, LocalFiniteElement, TargetSpace> LocalGFEFunction;
-    typedef typename TargetSpace::EmbeddedTangentVector EmbeddedTangentVector;
-
-    //! Dimension of the grid.
-    constexpr static int gridDim = GridView::dimension;
-
-    //! Dimension of the embedded tangent space
-    constexpr static int embeddedDim = EmbeddedTangentVector::dimension;
-
-
-    //! Create global function by a global basis and the corresponding coefficient vector
-    GlobalGeodesicFEFunction(const Basis& basis, const std::vector<TargetSpace>& coefficients) :
-        VirtualGridViewFunction<typename B::GridView, TargetSpace>(basis.getGridView()),
-        basis_(basis),
-        coefficients_(coefficients)
-    {}
-
-
-    /** \brief Evaluate the function at local coordinates. */
-    void evaluateLocal(const Element& element, const Dune::FieldVector<ctype,gridDim>& local, TargetSpace& out) const
-    {
-        int numOfBaseFct = basis_.getLocalFiniteElement(element).localBasis().size();
-
-        // Extract local coefficients
-        std::vector<TargetSpace> localCoeff(numOfBaseFct);
-
-        for (int i=0; i<numOfBaseFct; i++)
-            localCoeff[i] = coefficients_[basis_.index(element,i)];
-
-        // create local gfe function
-        LocalGFEFunction localGFE(basis_.getLocalFiniteElement(element),localCoeff);
-        out = localGFE.evaluate(local);
-    }
-
-    /** \brief Evaluate the derivative of the function at local coordinates. */
-    void evaluateDerivativeLocal(const Element& element, const Dune::FieldVector<ctype,gridDim>& local,
-                                 Dune::FieldMatrix<ctype, embeddedDim, gridDim>& out) const
-    {
-        int numOfBaseFct = basis_.getLocalFiniteElement(element).localBasis().size();
-
-        // Extract local coefficients
-        std::vector<TargetSpace> localCoeff(numOfBaseFct);
-
-        for (int i=0; i<numOfBaseFct; i++)
-            localCoeff[i] = coefficients_[basis_.index(element,i)];
-
-        // create local gfe function
-        LocalGFEFunction localGFE(basis_.getLocalFiniteElement(element),localCoeff);
-
-        // use it to evaluate the derivative
-        Dune::FieldMatrix<ctype, embeddedDim, gridDim> refJac = localGFE.evaluateDerivative(local);
-
-        out =0.0;
-        //transform the gradient
-        const auto jacInvTrans = element.geometry().jacobianInverseTransposed(local);
-        for (size_t k=0; k< refJac.N(); k++)
-            jacInvTrans.umv(refJac[k],out[k]);
-
-    }
-
-    /** \brief Export basis */
-    const Basis& basis() const
-    {
-        return basis_;
-    }
-
-    /** \brief Export coefficients. */
-    const std::vector<TargetSpace>& coefficients() const
-    {
-        return coefficients_;
-    }
-
-private:
-    //! The global basis
-    const Basis& basis_;
-    //! The coefficient vector
-    const std::vector<TargetSpace>& coefficients_;
-};
-#endif
diff --git a/dune/gfe/globalgfefunction.hh b/dune/gfe/globalgfefunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..bc18312af5be91d3e7310bd9e1e2293ae19d9c5f
--- /dev/null
+++ b/dune/gfe/globalgfefunction.hh
@@ -0,0 +1,459 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_GFE_GLOBALGFEFUNCTION_HH
+#define DUNE_GFE_GLOBALGFEFUNCTION_HH
+
+#include <memory>
+#include <optional>
+#include <vector>
+
+#include <dune/common/typetraits.hh>
+
+#include <dune/grid/utility/hierarchicsearch.hh>
+
+#include <dune/functions/gridfunctions/gridviewentityset.hh>
+#include <dune/functions/gridfunctions/gridfunction.hh>
+#include <dune/functions/backends/concepts.hh>
+
+namespace Dune::GFE {
+
+namespace Impl {
+
+/** \brief Common base class for GlobalGFEFunction and its derivative
+ *
+ * \tparam B Scalar(!) function-space basis
+ * \tparam V Container of coefficients
+ * \tparam LocalInterpolationRule How to interpolate manifold-valued data
+ */
+template<typename B, typename V, typename LocalInterpolationRule>
+class GlobalGFEFunctionBase
+{
+public:
+  using Basis = B;
+  using Vector = V;
+
+  // In order to make the cache work for proxy-references
+  // we have to use AutonomousValue<T> instead of std::decay_t<T>
+  using Coefficient = Dune::AutonomousValue<decltype(std::declval<Vector>()[std::declval<typename Basis::MultiIndex>()])>;
+
+  using GridView = typename Basis::GridView;
+  using EntitySet = Functions::GridViewEntitySet<GridView, 0>;
+  using Tree = typename Basis::LocalView::Tree;
+
+  using Domain = typename EntitySet::GlobalCoordinate;
+
+  using LocalDomain = typename EntitySet::LocalCoordinate;
+  using Element = typename EntitySet::Element;
+
+protected:
+
+  // This collects all data that is shared by all related
+  // global and local functions. This way we don't need to
+  // keep track of it individually.
+  struct Data
+  {
+    EntitySet entitySet;
+    std::shared_ptr<const Basis> basis;
+    std::shared_ptr<const Vector> coefficients;
+  };
+
+public:
+  class LocalFunctionBase
+  {
+    using LocalView = typename Basis::LocalView;
+    using size_type = typename Tree::size_type;
+
+  public:
+    using Domain = LocalDomain;
+    using Element = typename EntitySet::Element;
+
+  protected:
+    LocalFunctionBase(const std::shared_ptr<const Data>& data)
+      : data_(data)
+      , localView_(data_->basis->localView())
+    {
+      localDoFs_.reserve(localView_.maxSize());
+    }
+
+    /**
+     * \brief Copy-construct the local-function.
+     *
+     * This copy-constructor copies the cached local DOFs only
+     * if the `other` local-function is bound to an element.
+     **/
+    LocalFunctionBase(const LocalFunctionBase& other)
+      : data_(other.data_)
+      , localView_(other.localView_)
+    {
+      localDoFs_.reserve(localView_.maxSize());
+      if (bound())
+        localDoFs_ = other.localDoFs_;
+    }
+
+    /**
+     * \brief Copy-assignment of the local-function.
+     *
+     * Assign all members from `other` to `this`, except the
+     * local DOFs. Those are copied only if the `other`
+     * local-function is bound to an element.
+     **/
+    LocalFunctionBase& operator=(const LocalFunctionBase& other)
+    {
+      data_ = other.data_;
+      localView_ = other.localView_;
+      if (bound())
+        localDoFs_ = other.localDoFs_;
+      return *this;
+    }
+
+  public:
+    /**
+     * \brief Bind LocalFunction to grid element.
+     *
+     * You must call this method before `operator()`
+     * and after changes to the coefficient vector.
+     */
+    void bind(const Element& element)
+    {
+      localView_.bind(element);
+
+      localDoFs_.resize(localView_.size());
+      const auto& dofs = *data_->coefficients;
+      for (size_type i = 0; i < localView_.tree().size(); ++i)
+      {
+        // For a subspace basis the index-within-tree i
+        // is not the same as the localIndex within the
+        // full local view.
+        size_t localIndex = localView_.tree().localIndex(i);
+        localDoFs_[localIndex] = dofs[localView_.index(localIndex)];
+      }
+
+      // create local GFE function
+      // TODO Store this object by value
+      localInterpolationRule_ = std::make_unique<LocalInterpolationRule>(this->localView_.tree().finiteElement(),localDoFs_);
+    }
+
+    //! Unbind the local-function.
+    void unbind()
+    {
+      localView_.unbind();
+    }
+
+    //! Check if LocalFunction is already bound to an element.
+    bool bound() const
+    {
+      return localView_.bound();
+    }
+
+    //! Return the element the local-function is bound to.
+    const Element& localContext() const
+    {
+      return localView_.element();
+    }
+
+  protected:
+
+    std::shared_ptr<const Data> data_;
+    LocalView localView_;
+    std::vector<Coefficient> localDoFs_;
+    std::unique_ptr<LocalInterpolationRule> localInterpolationRule_;
+  };
+
+protected:
+  GlobalGFEFunctionBase(const std::shared_ptr<const Data>& data)
+    : data_(data)
+  {
+    /* Nothing. */
+  }
+
+public:
+
+  //! Return a const reference to the stored basis.
+  const Basis& basis() const
+  {
+    return *data_->basis;
+  }
+
+  //! Return the coefficients of this discrete function by reference.
+  const Vector& dofs() const
+  {
+    return *data_->coefficients;
+  }
+
+  //! Get associated set of entities the local-function can be bound to.
+  const EntitySet& entitySet() const
+  {
+    return data_->entitySet;
+  }
+
+protected:
+  std::shared_ptr<const Data> data_;
+};
+
+} // namespace Impl
+
+
+
+template<typename GGF>
+class GlobalGFEFunctionDerivative;
+
+/**
+ * \brief A global geometric finite element function
+ *
+ * \tparam B Type of global basis
+ * \tparam LIR Local interpolation rule for manifold-valued data
+ * \tparam TargetSpace Range type of this function
+ */
+template<typename B, typename LIR, typename TargetSpace>
+class GlobalGFEFunction
+  : public Impl::GlobalGFEFunctionBase<B, std::vector<TargetSpace>, LIR>
+{
+  using Base = Impl::GlobalGFEFunctionBase<B, std::vector<TargetSpace>, LIR>;
+  using Data = typename Base::Data;
+
+public:
+  using Basis = typename Base::Basis;
+  using Vector = typename Base::Vector;
+  using LocalInterpolationRule = LIR;
+
+  using Domain = typename Base::Domain;
+  using Range = typename TargetSpace::CoordinateType;
+
+  using Traits = Functions::Imp::GridFunctionTraits<Range(Domain), typename Base::EntitySet, Functions::DefaultDerivativeTraits, 16>;
+
+  class LocalFunction
+    : public Base::LocalFunctionBase
+  {
+    using LocalBase = typename Base::LocalFunctionBase;
+    using size_type = typename Base::Tree::size_type;
+
+  public:
+
+    using GlobalFunction = GlobalGFEFunction;
+    using Domain = typename LocalBase::Domain;
+    using Range = GlobalFunction::Range;
+    using Element = typename LocalBase::Element;
+
+    //! Create a local-function from the associated grid-function
+    LocalFunction(const GlobalGFEFunction& globalFunction)
+      : LocalBase(globalFunction.data_)
+    {
+      /* Nothing. */
+    }
+
+    /**
+     * \brief Evaluate this local-function in coordinates `x` in the bound element.
+     *
+     * The result of this method is undefined if you did
+     * not call bind() beforehand or changed the coefficient
+     * vector after the last call to bind(). In the latter case
+     * you have to call bind() again in order to make operator()
+     * usable.
+     */
+    Range operator()(const Domain& x) const
+    {
+      return this->localInterpolationRule_->evaluate(x).globalCoordinates();
+    }
+
+    //! Local function of the derivative
+    friend typename GlobalGFEFunctionDerivative<GlobalGFEFunction>::LocalFunction derivative(const LocalFunction& lf)
+    {
+      auto dlf = localFunction(GlobalGFEFunctionDerivative<GlobalGFEFunction>(lf.data_));
+      if (lf.bound())
+        dlf.bind(lf.localContext());
+      return dlf;
+    }
+  };
+
+  //! Create a grid-function, by wrapping the arguments in `std::shared_ptr`.
+  template<class B_T, class V_T>
+  GlobalGFEFunction(B_T && basis, V_T && coefficients)
+    : Base(std::make_shared<Data>(Data{{basis.gridView()}, wrap_or_move(std::forward<B_T>(basis)), wrap_or_move(std::forward<V_T>(coefficients))}))
+  {}
+
+  //! Create a grid-function, by moving the arguments in `std::shared_ptr`.
+  GlobalGFEFunction(std::shared_ptr<const Basis> basis, std::shared_ptr<const Vector> coefficients)
+    : Base(std::make_shared<Data>(Data{{basis->gridView()}, basis, coefficients}))
+  {}
+
+  /** \brief Evaluate at a point given in world coordinates
+   *
+   * \warning This has to find the element that the evaluation point is in.
+   *   It is therefore very slow.
+   */
+  Range operator() (const Domain& x) const
+  {
+    HierarchicSearch search(this->data_->basis->gridView().grid(), this->data_->basis->gridView().indexSet());
+
+    const auto e = search.findEntity(x);
+    auto localThis = localFunction(*this);
+    localThis.bind(e);
+    return localThis(e.geometry().local(x));
+  }
+
+  //! Derivative of the `GlobalGFEFunction`
+  friend GlobalGFEFunctionDerivative<GlobalGFEFunction> derivative(const GlobalGFEFunction& f)
+  {
+    return GlobalGFEFunctionDerivative<GlobalGFEFunction>(f.data_);
+  }
+
+  /**
+   * \brief Construct local function from a GlobalGFEFunction.
+   *
+   * The obtained local function satisfies the concept
+   * `Dune::Functions::Concept::LocalFunction`. It must be bound
+   * to an entity from the entity set of the GlobalGFEFunction
+   * before it can be used.
+   */
+  friend LocalFunction localFunction(const GlobalGFEFunction& t)
+  {
+    return LocalFunction(t);
+  }
+};
+
+
+/**
+ * \brief Derivative of a `GlobalGFEFunction`
+ *
+ * Function returning the derivative of the given `GlobalGFEFunction`
+ * with respect to global coordinates.
+ *
+ * \tparam GGF instance of the `GlobalGFEFunction` this is a derivative of
+ */
+template<typename GGF>
+class GlobalGFEFunctionDerivative
+  : public Impl::GlobalGFEFunctionBase<typename GGF::Basis, typename GGF::Vector, typename GGF::LocalInterpolationRule>
+{
+  using Base = Impl::GlobalGFEFunctionBase<typename GGF::Basis, typename GGF::Vector, typename GGF::LocalInterpolationRule>;
+  using Data = typename Base::Data;
+
+public:
+  using GlobalGFEFunction = GGF;
+
+  using Basis = typename Base::Basis;
+  using Vector = typename Base::Vector;
+
+  using Domain = typename Base::Domain;
+  using Range = typename Functions::SignatureTraits<typename GlobalGFEFunction::Traits::DerivativeInterface>::Range;
+
+  using Traits = Functions::Imp::GridFunctionTraits<Range(Domain), typename Base::EntitySet, Functions::DefaultDerivativeTraits, 16>;
+
+  /**
+   * \brief local function evaluating the derivative in reference coordinates
+   *
+   * Note that the function returns the derivative with respect to global
+   * coordinates even when the point is given in reference coordinates on
+   * an element.
+   */
+  class LocalFunction
+    : public Base::LocalFunctionBase
+  {
+    using LocalBase = typename Base::LocalFunctionBase;
+    using size_type = typename Base::Tree::size_type;
+
+  public:
+    using GlobalFunction = GlobalGFEFunctionDerivative;
+    using Domain = typename LocalBase::Domain;
+    using Range = GlobalFunction::Range;
+    using Element = typename LocalBase::Element;
+
+    //! Create a local function from the associated grid function
+    LocalFunction(const GlobalFunction& globalFunction)
+      : LocalBase(globalFunction.data_)
+    {
+      /* Nothing. */
+    }
+
+    /**
+     * \brief Bind LocalFunction to grid element.
+     *
+     * You must call this method before `operator()`
+     * and after changes to the coefficient vector.
+     */
+    void bind(const Element& element)
+    {
+      LocalBase::bind(element);
+      geometry_.emplace(element.geometry());
+    }
+
+    //! Unbind the local-function.
+    void unbind()
+    {
+      geometry_.reset();
+      LocalBase::unbind();
+    }
+
+    /**
+     * \brief Evaluate this local-function in coordinates `x` in the bound element.
+     *
+     * The result of this method is undefined if you did
+     * not call bind() beforehand or changed the coefficient
+     * vector after the last call to bind(). In the latter case
+     * you have to call bind() again in order to make operator()
+     * usable.
+     *
+     * Note that the function returns the derivative with respect to global
+     * coordinates even though the evaluation point is given in reference coordinates
+     * on the current element.
+     */
+    Range operator()(const Domain& x) const
+    {
+        // Jacobian with respect to local coordinates
+        auto refJac = this->localInterpolationRule_->evaluateDerivative(x);
+
+        // Transform to world coordinates
+        return refJac * geometry_->jacobianInverse(x);
+    }
+
+    //! Not implemented
+    friend typename Traits::LocalFunctionTraits::DerivativeInterface derivative(const LocalFunction&)
+    {
+      DUNE_THROW(NotImplemented, "derivative of derivative is not implemented");
+    }
+
+  private:
+    std::optional<typename Element::Geometry> geometry_;
+  };
+
+  /**
+   * \brief create object from `GlobalGFEFunction` data
+   *
+   * Please call `derivative(globalGFEFunction)` to create an instance
+   * of this class.
+   */
+  GlobalGFEFunctionDerivative(const std::shared_ptr<const Data>& data)
+    : Base(data)
+  {
+    /* Nothing. */
+  }
+
+  /** \brief Evaluate the discrete grid-function derivative in global coordinates
+   *
+   * \warning This has to find the element that the evaluation point is in.
+   *   It is therefore very slow.
+   */
+  Range operator()(const Domain& x) const
+  {
+    HierarchicSearch search(this->data_->basis->gridView().grid(), this->data_->basis->gridView().indexSet());
+
+    const auto e = search.findEntity(x);
+    auto localThis = localFunction(*this);
+    localThis.bind(e);
+    return localThis(e.geometry().local(x));
+  }
+
+  friend typename Traits::DerivativeInterface derivative(const GlobalGFEFunctionDerivative& f)
+  {
+    DUNE_THROW(NotImplemented, "derivative of derivative is not implemented");
+  }
+
+  //! Construct local function from a `GlobalGFEFunctionDerivative`
+  friend LocalFunction localFunction(const GlobalGFEFunctionDerivative& f)
+  {
+    return LocalFunction(f);
+  }
+};
+
+} // namespace Dune::GFE
+
+#endif // DUNE_GFE_GLOBALGFEFUNCTION_HH
diff --git a/dune/gfe/l2distancesquaredenergy.hh b/dune/gfe/l2distancesquaredenergy.hh
index 2546e70d5c5867f1f33bde7a8dc917e6dcec1c3b..05e460c9f6dad9546912aaa86dff055130352ffa 100644
--- a/dune/gfe/l2distancesquaredenergy.hh
+++ b/dune/gfe/l2distancesquaredenergy.hh
@@ -5,6 +5,7 @@
 
 #include <dune/geometry/quadraturerules.hh>
 
+#include <dune/gfe/globalgfefunction.hh>
 #include <dune/gfe/localenergy.hh>
 #include <dune/gfe/localgeodesicfefunction.hh>
 
@@ -20,10 +21,12 @@ class L2DistanceSquaredEnergy
   // some other sizes
   constexpr static int gridDim = GridView::dimension;
 
+  using LocalInterpolationRule = LocalGeodesicFEFunction<gridDim, DT, typename Basis::LocalView::Tree::FiniteElement, typename TargetSpace::template rebind<double>::other>;
+
 public:
 
   // This is the function that we are computing the L2-distance to
-  std::shared_ptr<VirtualGridViewFunction<GridView,typename TargetSpace::template rebind<double>::other > > origin_;
+  std::shared_ptr<Dune::GFE::GlobalGFEFunction<Basis, LocalInterpolationRule, typename TargetSpace::template rebind<double>::other > > origin_;
 
   /** \brief Assemble the energy for a single element */
   RT energy (const typename Basis::LocalView& localView,
@@ -36,11 +39,13 @@ public:
     typedef LocalGeodesicFEFunction<gridDim, double, decltype(localFiniteElement), TargetSpace> LocalGFEFunctionType;
     LocalGFEFunctionType localGeodesicFEFunction(localFiniteElement,localSolution);
 
+    const auto element = localView.element();
+    auto localOrigin = localFunction(*origin_);
+    localOrigin.bind(element);
+
     // Just guessing an appropriate quadrature order
     auto quadOrder = localFiniteElement.localBasis().order() * 2 * gridDim;
 
-    const auto element = localView.element();
-
     const auto& quad = Dune::QuadratureRules<double, gridDim>::rule(localFiniteElement.type(), quadOrder);
 
     for (size_t pt=0; pt<quad.size(); pt++)
@@ -54,21 +59,14 @@ public:
 
       // The function value
       auto value = localGeodesicFEFunction.evaluate(quadPos);
-      typename TargetSpace::template rebind<double>::other originValue;
-      origin_->evaluateLocal(element,quadPos, originValue);
+      auto originValue = localOrigin(quadPos);
 
       // The derivative of the 'origin' function
       // First: as function defined on the reference element
-      typename VirtualGridViewFunction<GridView,typename TargetSpace::template rebind<double>::other>::DerivativeType originReferenceDerivative;
-      origin_->evaluateDerivativeLocal(element,quadPos,originReferenceDerivative);
+      auto originReferenceDerivative = derivative(localOrigin)(quadPos);
 
       // The derivative of the function defined on the actual element
-      typename VirtualGridViewFunction<GridView,typename TargetSpace::template rebind<double>::other >::DerivativeType originDerivative(0);
-
-      auto jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(quadPos);
-
-      for (size_t comp=0; comp<originReferenceDerivative.N(); comp++)
-        jacobianInverseTransposed.umv(originReferenceDerivative[comp], originDerivative[comp]);
+      auto originDerivative = originReferenceDerivative * element.geometry().jacobianInverse(quadPos);
 
       double weightFactor = originDerivative.frobenius_norm();
       // un-comment the following line to switch off the weight factor
diff --git a/src/gradient-flow.cc b/src/gradient-flow.cc
index ea1be930de232f2fb8b5f7dd6ccaa777f195886f..7ca443c6aeee032a7acd084179e888b7a2cf8753 100644
--- a/src/gradient-flow.cc
+++ b/src/gradient-flow.cc
@@ -25,11 +25,10 @@
 #include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
 #include <dune/functions/functionspacebases/interpolate.hh>
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
+#include <dune/functions/functionspacebases/powerbasis.hh>
 
 #include <dune/fufem/boundarypatch.hh>
 #include <dune/fufem/functiontools/boundarydofs.hh>
-#include <dune/fufem/functionspacebases/dunefunctionsbasis.hh>
-#include <dune/fufem/discretizationerror.hh>
 #include <dune/fufem/dunepython.hh>
 
 #include <dune/solvers/solvers/iterativesolver.hh>
@@ -39,7 +38,7 @@
 #include <dune/gfe/localgeodesicfeadolcstiffness.hh>
 #include <dune/gfe/geodesicfeassembler.hh>
 #include <dune/gfe/riemanniantrsolver.hh>
-#include <dune/gfe/globalgeodesicfefunction.hh>
+#include <dune/gfe/globalgfefunction.hh>
 #include <dune/gfe/embeddedglobalgfefunction.hh>
 #include <dune/gfe/harmonicenergy.hh>
 #include <dune/gfe/l2distancesquaredenergy.hh>
@@ -137,22 +136,19 @@ int main (int argc, char *argv[]) try
   }
 
   grid->globalRefine(numLevels-1);
+  auto gridView = grid->leafGridView();
 
   //////////////////////////////////////////////////////////////////////////////////
   //  Construct the scalar function space basis corresponding to the GFE space
   //////////////////////////////////////////////////////////////////////////////////
 
   typedef Dune::Functions::LagrangeBasis<typename GridType::LeafGridView, order> FEBasis;
-  //typedef Dune::Functions::Periodic1DPQ1NodalBasis<typename GridType::LeafGridView> FEBasis;
   FEBasis feBasis(grid->leafGridView());
 
   ///////////////////////////////////////////
   //   Read Dirichlet values
   ///////////////////////////////////////////
 
-  typedef DuneFunctionsBasis<FEBasis> FufemFEBasis;
-  FufemFEBasis fufemFeBasis(feBasis);
-
   BitSetVector<1> dirichletVertices(grid->leafGridView().size(dim), false);
 
   const auto& indexSet = grid->leafGridView().indexSet();
@@ -171,7 +167,7 @@ int main (int argc, char *argv[]) try
   BoundaryPatch<GridType::LeafGridView> dirichletBoundary(grid->leafGridView(), dirichletVertices);
 
   BitSetVector<blocksize> dirichletNodes(feBasis.size(), false);
-  constructBoundaryDofs(dirichletBoundary,fufemFeBasis,dirichletNodes);
+  constructBoundaryDofs(dirichletBoundary,feBasis,dirichletNodes);
 
   ////////////////////////////
   //   Initial iterate
@@ -182,7 +178,16 @@ int main (int argc, char *argv[]) try
   auto pythonInitialIterate = Python::make_function<TargetSpace::CoordinateType>(module.get("f"));
 
   std::vector<TargetSpace::CoordinateType> v;
-  Functions::interpolate(feBasis, v, pythonInitialIterate);
+  using namespace Functions::BasisFactory;
+
+  auto powerBasis = makeBasis(
+    gridView,
+    power<TargetSpace::CoordinateType::dimension>(
+      lagrange<order>(),
+      blockedInterleaved()
+  ));
+
+  Functions::interpolate(powerBasis, v, pythonInitialIterate);
 
   SolutionType x(feBasis.size());
 
@@ -259,7 +264,7 @@ int main (int argc, char *argv[]) try
 
   for (int i=0; i<numTimeSteps; i++)
   {
-    auto previousTimeStepFct = std::make_shared<GlobalGeodesicFEFunction<FufemFEBasis,TargetSpace> >(fufemFeBasis,previousTimeStep);
+    auto previousTimeStepFct = std::make_shared<GFE::GlobalGFEFunction<FEBasis,GeodesicInterpolationRule::rebind<TargetSpace>::other,TargetSpace> >(feBasis,previousTimeStep);
     l2DistanceSquaredEnergy->origin_ = previousTimeStepFct;
 
     solver.setInitialIterate(x);