diff --git a/dune/gfe/localintegralenergy.hh b/dune/gfe/localintegralenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..e6d85ef1650633e8fadc113c135c6dc06bebf1f2
--- /dev/null
+++ b/dune/gfe/localintegralenergy.hh
@@ -0,0 +1,105 @@
+#ifndef DUNE_GFE_LOCALINTEGRALENERGY_HH
+#define DUNE_GFE_LOCALINTEGRALENERGY_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fmatrixev.hh>
+
+#include <dune/geometry/quadraturerules.hh>
+
+#include <dune/gfe/localenergy.hh>
+#include <dune/gfe/realtuple.hh>
+#include <dune/gfe/rigidbodymotion.hh>
+
+#include <dune/elasticity/materials/localdensity.hh>
+
+namespace Dune::GFE {
+
+  /**
+    \brief Assembles the elastic energy for a single element integrating the localdensity over one element.
+
+           This class works similarly to the class Dune::Elasticity::LocalIntegralEnergy, where Dune::Elasticity::LocalIntegralEnergy extends
+           Dune::Elasticity::LocalEnergy and Dune::GFE::LocalIntegralEnergy extends Dune::GFE::LocalEnergy.
+  */
+template<class Basis, class... TargetSpaces>
+class LocalIntegralEnergy
+  : public Dune::GFE::LocalEnergy<Basis,TargetSpaces...>
+{
+  using LocalView = typename Basis::LocalView;
+  using GridView = typename LocalView::GridView;
+  using DT = typename GridView::Grid::ctype;
+  using RT = typename Dune::GFE::LocalEnergy<Basis,TargetSpaces...>::RT;
+
+  enum {gridDim=GridView::dimension};
+
+public:
+
+  /** \brief Constructor with a local energy density
+    */
+  LocalIntegralEnergy(const std::shared_ptr<Dune::Elasticity::LocalDensity<gridDim,RT,DT>>& ld)
+  : localDensity_(ld)
+  {}
+
+  /** \brief Assemble the energy for a single element */
+  RT energy(const typename Basis::LocalView& localView,
+            const std::vector<TargetSpaces>&... localSolutions) const
+  { 
+    static_assert(sizeof...(TargetSpaces) > 0, "LocalIntegralEnergy needs at least one TargetSpace!");
+
+    using TargetSpace = typename std::tuple_element<0, std::tuple<TargetSpaces...> >::type;
+    static_assert( (std::is_same<TargetSpace, RigidBodyMotion<RT,gridDim>>::value)
+      or (std::is_same<TargetSpace, RealTuple<RT,gridDim>>::value), "The first TargetSpace of LocalIntegralEnergy needs to be RigidBodyMotion or RealTuple!" );
+    
+    const std::vector<TargetSpace>& localSolution = std::get<0>(std::forward_as_tuple(localSolutions...));
+
+    using namespace Dune::Indices;
+    // powerBasis: grab the finite element of the first child
+    const auto& localFiniteElement = localView.tree().child(_0,0).finiteElement();
+    const auto& element = localView.element();
+
+    RT energy = 0;
+
+    // store gradients of shape functions and base functions
+    std::vector<FieldMatrix<DT,1,gridDim> > referenceGradients(localFiniteElement.size());
+    std::vector<FieldVector<DT,gridDim> > gradients(localFiniteElement.size());
+
+    int quadOrder = (element.type().isSimplex()) ? localFiniteElement.localBasis().order()
+                                                 : localFiniteElement.localBasis().order() * gridDim;
+
+    const auto& quad = Dune::QuadratureRules<DT, gridDim>::rule(element.type(), quadOrder);
+
+    for (const auto& qp : quad)
+    {
+      const DT integrationElement = element.geometry().integrationElement(qp.position());
+
+      const auto jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(qp.position());
+
+      // Global position
+      auto x = element.geometry().global(qp.position());
+
+      // Get gradients of shape functions
+      localFiniteElement.localBasis().evaluateJacobian(qp.position(), referenceGradients);
+
+      // compute gradients of base functions
+      for (size_t i=0; i<gradients.size(); ++i)
+        jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]);
+
+      // Deformation gradient
+      FieldMatrix<RT,gridDim,gridDim> deformationGradient(0);
+      for (size_t i=0; i<gradients.size(); i++)
+        for (int j=0; j<gridDim; j++)
+          deformationGradient[j].axpy(localSolution[i][j], gradients[i]);
+      // Integrate the energy density
+      energy += qp.weight() * integrationElement * (*localDensity_)(x, deformationGradient);
+    }
+
+    return energy;
+  }
+
+protected:
+  const std::shared_ptr<Dune::Elasticity::LocalDensity<gridDim,RT,DT>> localDensity_ = nullptr;
+
+};
+
+}  // namespace Dune::GFE
+
+#endif   //#ifndef DUNE_GFE_LOCALINTEGRALENERGY_HH
diff --git a/dune/gfe/neumannenergy.hh b/dune/gfe/neumannenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..dd8f61b1c373c7958ee926244259a782ad5156d8
--- /dev/null
+++ b/dune/gfe/neumannenergy.hh
@@ -0,0 +1,103 @@
+#ifndef DUNE_GFE_NEUMANNENERGY_HH
+#define DUNE_GFE_NEUMANNENERGY_HH
+
+#include <dune/geometry/quadraturerules.hh>
+
+#include <dune/fufem/functions/virtualgridfunction.hh>
+#include <dune/fufem/boundarypatch.hh>
+
+#include <dune/elasticity/assemblers/localenergy.hh>
+
+namespace Dune::GFE {
+  /**
+    \brief Assembles the Neumann energy for a single element on the Neumann Boundary using the Neumann Function.
+    
+           This class works similarly to the class Dune::Elasticity::NeumannEnergy, where Dune::Elasticity::NeumannEnergy extends
+           Dune::Elasticity::LocalEnergy and Dune::GFE::NeumannEnergy extends Dune::GFE::LocalEnergy.
+  */
+template<class Basis, class... TargetSpaces>
+class NeumannEnergy
+  : public Dune::GFE::LocalEnergy<Basis,TargetSpaces...>
+{
+  using LocalView = typename Basis::LocalView;
+  using GridView = typename LocalView::GridView;
+  using DT = typename GridView::Grid::ctype;
+  using RT = typename Dune::GFE::LocalEnergy<Basis,TargetSpaces...>::RT;
+
+  enum {dim=GridView::dimension};
+
+public:
+
+  /** \brief Constructor with a set of material parameters
+   * \param parameters The material parameters
+   */
+  NeumannEnergy(const std::shared_ptr<BoundaryPatch<GridView>>& neumannBoundary,
+                std::function<Dune::FieldVector<double,dim>(Dune::FieldVector<DT,dim>)> neumannFunction)
+  : neumannBoundary_(neumannBoundary),
+    neumannFunction_(neumannFunction)
+  {}
+
+  /** \brief Assemble the energy for a single element */
+  RT energy(const typename Basis::LocalView& localView,
+            const std::vector<TargetSpaces>&... localSolutions) const
+  { 
+    static_assert(sizeof...(TargetSpaces) > 0, "NeumannEnergy needs at least one TargetSpace!");
+
+    using namespace Dune::Indices;
+    using TargetSpace = typename std::tuple_element<0, std::tuple<TargetSpaces...> >::type;
+    const std::vector<TargetSpace>& localSolution = std::get<0>(std::forward_as_tuple(localSolutions...));
+
+    const auto& localFiniteElement = localView.tree().child(_0,0).finiteElement();
+    const auto& element = localView.element();
+
+    RT energy = 0;
+
+    for (auto&& intersection : intersections(neumannBoundary_->gridView(), element)) {
+
+      if (not neumannBoundary_ or not neumannBoundary_->contains(intersection))
+        continue;
+
+      int quadOrder = localFiniteElement.localBasis().order();
+
+      const auto& quad = Dune::QuadratureRules<DT, dim-1>::rule(intersection.type(), quadOrder);
+
+      for (size_t pt=0; pt<quad.size(); pt++) {
+
+        // Local position of the quadrature point
+        const Dune::FieldVector<DT,dim>& quadPos = intersection.geometryInInside().global(quad[pt].position());
+
+        const auto integrationElement = intersection.geometry().integrationElement(quad[pt].position());
+
+        // The value of the local function
+        std::vector<Dune::FieldVector<DT,1> > shapeFunctionValues;
+        localFiniteElement.localBasis().evaluateFunction(quadPos, shapeFunctionValues);
+
+        Dune::FieldVector<RT,dim> value(0);
+        for (size_t i=0; i<localFiniteElement.size(); i++)
+          for (int j=0; j<dim; j++)
+            value[j] += shapeFunctionValues[i] * localSolution[i][j];
+
+        // Value of the Neumann data at the current position
+        auto neumannValue = neumannFunction_( intersection.geometry().global(quad[pt].position()) );
+
+        // Only translational dofs are affected by the Neumann force
+        for (size_t i=0; i<neumannValue.size(); i++)
+          energy += (neumannValue[i] * value[i]) * quad[pt].weight() * integrationElement;
+
+      }
+
+    }
+
+    return energy;
+  }
+
+private:
+  /** \brief The Neumann boundary */
+  const std::shared_ptr<BoundaryPatch<GridView>> neumannBoundary_;
+
+  /** \brief The function implementing the Neumann data */
+  std::function<Dune::FieldVector<double,dim>(Dune::FieldVector<DT,dim>)> neumannFunction_;
+};
+}  // namespace Dune::GFE
+
+#endif   //#ifndef DUNE_GFE_NEUMANNENERGY_HH
diff --git a/dune/gfe/sumcosseratenergy.hh b/dune/gfe/sumcosseratenergy.hh
deleted file mode 100644
index 51f6241a2090e51977d9fc79f0f426bf2e49911f..0000000000000000000000000000000000000000
--- a/dune/gfe/sumcosseratenergy.hh
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef DUNE_GFE_SUMCOSSERATENERGY_HH
-#define DUNE_GFE_SUMCOSSERATENERGY_HH
-
-#include <dune/elasticity/assemblers/localfestiffness.hh>
-
-#include <dune/gfe/localenergy.hh>
-
-namespace Dune {
-
-namespace GFE {
-template<class Basis, class TargetSpace, class field_type=double>
-class SumCosseratEnergy
-: public GFE::LocalEnergy<Basis, TargetSpace>
-{
- // grid types
-  typedef typename Basis::GridView GridView;
-  typedef typename GridView::ctype ctype;
-  typedef typename Basis::LocalView::Tree::FiniteElement LocalFiniteElement;
-  typedef typename GridView::ctype DT;
-  typedef typename TargetSpace::ctype RT;
-
-  enum {dim=GridView::dimension};
-
-public:
-
-  /** \brief Constructor with elastic energy and cosserat energy
-   * \param elasticEnergy The elastic energy
-   * \param cosseratEnergy The cosserat energy
-   */
-#if DUNE_VERSION_LT(DUNE_ELASTICITY, 2, 7)
-  SumCosseratEnergy(std::shared_ptr<LocalFEStiffness<GridView,LocalFiniteElement,std::vector<Dune::FieldVector<field_type,dim> > > > elasticEnergy,
-#elif DUNE_VERSION_GTE(DUNE_ELASTICITY, 2, 8)
-  SumCosseratEnergy(std::shared_ptr<Dune::LocalEnergy<GridView,LocalFiniteElement,std::vector<Dune::FieldVector<field_type,dim> > > > elasticEnergy,
-#else
-  SumCosseratEnergy(std::shared_ptr<Elasticity::LocalEnergy<GridView,LocalFiniteElement,std::vector<Dune::FieldVector<field_type,dim> > > > elasticEnergy,
-#endif
-            std::shared_ptr<GFE::LocalEnergy<Basis, TargetSpace>> cosseratEnergy)
-
-  : elasticEnergy_(elasticEnergy),
-    cosseratEnergy_(cosseratEnergy)
-  {}
-
-  /** \brief Assemble the energy for a single element */
-  RT energy (const typename Basis::LocalView& localView,
-               const std::vector<TargetSpace>& localSolution) const
-  { 
-    auto&& element = localView.element();
-    auto&& localFiniteElement = localView.tree().finiteElement();
-    std::vector<Dune::FieldVector<field_type,dim>> localConfiguration(localSolution.size());
-    for (int i = 0; i < localSolution.size(); i++) {
-      localConfiguration[i] = localSolution[i].r;
-    }
-    return elasticEnergy_->energy(element, localFiniteElement, localConfiguration) + cosseratEnergy_->energy(localView, localSolution);
-  }
-
-private:
-
-#if DUNE_VERSION_LT(DUNE_ELASTICITY, 2, 7)
-  std::shared_ptr<LocalFEStiffness<GridView,LocalFiniteElement,std::vector<Dune::FieldVector<field_type,dim> > > > elasticEnergy_;
-#elif DUNE_VERSION_GTE(DUNE_ELASTICITY, 2, 8)
-  std::shared_ptr<Dune::LocalEnergy<GridView,LocalFiniteElement,std::vector<Dune::FieldVector<field_type,dim> > > > elasticEnergy_;
-#else
-  std::shared_ptr<Elasticity::LocalEnergy<GridView,LocalFiniteElement,std::vector<Dune::FieldVector<field_type,dim> > > > elasticEnergy_;
-#endif
-
-  std::shared_ptr<GFE::LocalEnergy<Basis, TargetSpace> > cosseratEnergy_;
-};
-
-}  // namespace GFE
-
-}  // namespace Dune
-
-#endif   //#ifndef DUNE_GFE_SUMCOSSERATENERGY_HH
diff --git a/dune/gfe/surfacecosseratenergy.hh b/dune/gfe/surfacecosseratenergy.hh
index b7b5d1226c2e8279c7c44de3bc62be586cd8a63e..366e233747f0a98c2e986b40fb8c606be0963e4f 100644
--- a/dune/gfe/surfacecosseratenergy.hh
+++ b/dune/gfe/surfacecosseratenergy.hh
@@ -1,6 +1,7 @@
 #ifndef DUNE_GFE_SURFACECOSSERATENERGY_HH
 #define DUNE_GFE_SURFACECOSSERATENERGY_HH
 
+#include <dune/common/indices.hh>
 #include <dune/geometry/quadraturerules.hh>
 
 #include <dune/fufem/functions/virtualgridfunction.hh>
@@ -16,46 +17,21 @@
 #include <dune/gfe/tensor3.hh>
 #include <dune/gfe/vertexnormals.hh>
 
-template <class Basis, std::size_t i>
-class LocalFiniteElementFactory
-{
-public:
-  static auto get(const typename Basis::LocalView& localView,
-           std::integral_constant<std::size_t, i> iType)
-    -> decltype(localView.tree().child(iType).finiteElement())
-  {
-    return localView.tree().child(iType).finiteElement();
-  }
-};
-
-/** \brief Specialize for scalar bases, here we cannot call tree().child() */
-template <class GridView, int order, std::size_t i>
-class LocalFiniteElementFactory<Dune::Functions::LagrangeBasis<GridView,order>,i>
-{
-public:
-  static auto get(const typename Dune::Functions::LagrangeBasis<GridView,order>::LocalView& localView,
-           std::integral_constant<std::size_t, i> iType)
-    -> decltype(localView.tree().finiteElement())
-  {
-    return localView.tree().finiteElement();
-  }
-};
+namespace Dune::GFE {
 
-template<class Basis, class TargetSpace, class field_type=double, class GradientRT=double>
+template<class Basis, class... TargetSpaces>
 class SurfaceCosseratEnergy
-: public Dune::GFE::LocalEnergy<Basis,TargetSpace>
+: public Dune::GFE::LocalEnergy<Basis, TargetSpaces...>
 {
- // grid types
-  typedef typename Basis::GridView GridView;
-  typedef typename GridView::ctype ctype;
-  typedef typename Basis::LocalView::Tree::FiniteElement LocalFiniteElement;
-  typedef typename GridView::ctype DT;
-  typedef typename TargetSpace::ctype RT;
-  typedef typename GridView::template Codim<0>::Entity Entity;
-  typedef typename TargetSpace::template rebind<adouble>::other ATargetSpace;
-
-  enum {dim=GridView::dimension};
-  enum {dimworld=GridView::dimensionworld};
+  using GridView = typename Basis::GridView;
+  using DT = typename GridView::ctype ;
+  using RT = typename Dune::GFE::LocalEnergy<Basis, TargetSpaces...>::RT ;
+  using Entity = typename GridView::template Codim<0>::Entity ;
+  using RBM0 = RealTuple<RT,GridView::dimensionworld> ;
+  using RBM1 = Rotation<RT,GridView::dimensionworld> ;
+  using RBM = RigidBodyMotion<RT,GridView::dimensionworld> ;
+
+  enum {dimWorld=GridView::dimensionworld};
   enum {gridDim=GridView::dimension};
   static constexpr int boundaryDim = gridDim - 1;
 
@@ -64,9 +40,9 @@ class SurfaceCosseratEnergy
       \param derivative First derivative of the gfe function wrt x at that point, in quaternion coordinates
       \param DR First derivative of the gfe function wrt x at that point, in matrix coordinates
    */
-  static void computeDR(const RigidBodyMotion<field_type,dimworld>& value,
-                        const Dune::FieldMatrix<field_type,7,boundaryDim>& derivative,
-                        Tensor3<field_type,3,3,boundaryDim>& DR)
+  static void computeDR(const RBM& value,
+                        const Dune::FieldMatrix<RT,RBM::embeddedDim,boundaryDim>& derivative,
+                        Tensor3<RT,dimWorld,dimWorld,boundaryDim>& derivative_rotation)
   {
     // The LocalGFEFunction class gives us the derivatives of the orientation variable,
     // but as a map into quaternion space.  To obtain matrix coordinates we use the
@@ -77,15 +53,15 @@ class SurfaceCosseratEnergy
     // corresponding orthogonal matrix, we need to invert the i and j indices
     //
     // So, DR[i][j][k] contains \partial R_ij / \partial k
-    Tensor3<field_type,3 , 3, 4> dd_dq;
+    Tensor3<RT, dimWorld, dimWorld, 4> dd_dq;
     value.q.getFirstDerivativesOfDirectors(dd_dq);
 
-    DR = field_type(0);
-    for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++)
+    derivative_rotation = RT(0);
+    for (int i=0; i<dimWorld; i++)
+      for (int j=0; j<dimWorld; j++)
         for (int k=0; k<boundaryDim; k++)
           for (int l=0; l<4; l++)
-            DR[i][j][k] += dd_dq[j][i][l] * derivative[l+3][k];
+            derivative_rotation[i][j][k] += dd_dq[j][i][l] * derivative[l+3][k];
   }
 
 
@@ -96,11 +72,11 @@ public:
    * \param parameters The material parameters
    */
   SurfaceCosseratEnergy(const Dune::ParameterTree& parameters,
-    const std::vector<UnitVector<double,3> >& vertexNormals,
+    const std::vector<UnitVector<double,dimWorld> >& vertexNormals,
     const BoundaryPatch<GridView>* shellBoundary,
-    const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType,Dune::MultiLinearGeometry<double, dim-1, dim>>& geometriesOnShellBoundary,
-    const std::function<double(Dune::FieldVector<double,dim>)> thicknessF,
-    const std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dim>)> lameF)
+    const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType,Dune::MultiLinearGeometry<double, dimWorld-1, dimWorld>>& geometriesOnShellBoundary,
+    const std::function<double(Dune::FieldVector<double,dimWorld>)> thicknessF,
+    const std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dimWorld>)> lameF)
   : shellBoundary_(shellBoundary),
     vertexNormals_(vertexNormals),
     geometriesOnShellBoundary_(geometriesOnShellBoundary),
@@ -120,36 +96,66 @@ public:
   }
 
 RT energy(const typename Basis::LocalView& localView,
-       const std::vector<RigidBodyMotion<field_type,dim> >& localSolution) const
-{
+          const std::vector<TargetSpaces>&... localSolutions) const
+{ 
+  static_assert(sizeof...(TargetSpaces) == 2, "SurfaceCosseratEnergy needs exactly two TargetSpace!");
+
+  using namespace Dune::Indices;
+  using TargetSpace0 = typename std::tuple_element<0, std::tuple<TargetSpaces...> >::type;
+  const std::vector<TargetSpace0>& localSolution0 = std::get<0>(std::forward_as_tuple(localSolutions...));
+  using TargetSpace1 = typename std::tuple_element<1, std::tuple<TargetSpaces...> >::type;
+  const std::vector<TargetSpace1>& localSolution1 = std::get<1>(std::forward_as_tuple(localSolutions...));
+
   // The element geometry
   auto element = localView.element();
-
-  // The set of shape functions on this element
-  const auto& localFiniteElement = localView.tree().finiteElement();
+  auto gridView = localView.globalBasis().gridView();
 
   ////////////////////////////////////////////////////////////////////////////////////
   //  Construct a linear (i.e., non-constant!) normal field on each element
   ////////////////////////////////////////////////////////////////////////////////////
-  auto gridView = localView.globalBasis().gridView();
-
-  assert(vertexNormals_.size() == gridView.indexSet().size(gridDim));
-  std::vector<UnitVector<double,3> > cornerNormals(element.subEntities(gridDim));
-  for (size_t i=0; i<cornerNormals.size(); i++)
-    cornerNormals[i] = vertexNormals_[gridView.indexSet().subIndex(element,i,gridDim)];
-
   typedef typename Dune::PQkLocalFiniteElementCache<DT, double, gridDim, 1> P1FiniteElementCache;
   typedef typename P1FiniteElementCache::FiniteElementType P1LocalFiniteElement;
   //it.type()?
   P1FiniteElementCache p1FiniteElementCache;
   const auto& p1LocalFiniteElement = p1FiniteElementCache.get(element.type());
+
+  assert(vertexNormals_.size() == gridView.indexSet().size(gridDim));
+  std::vector<UnitVector<double,3> > cornerNormals(element.subEntities(gridDim));
+  for (size_t i=0; i<cornerNormals.size(); i++)
+    cornerNormals[i] = vertexNormals_[gridView.indexSet().subIndex(element,i,gridDim)];
   Dune::GFE::LocalProjectedFEFunction<gridDim, DT, P1LocalFiniteElement, UnitVector<double,3> > unitNormals(p1LocalFiniteElement, cornerNormals);
 
   ////////////////////////////////////////////////////////////////////////////////////
   //  Set up the local nonlinear finite element function
   ////////////////////////////////////////////////////////////////////////////////////
-  typedef LocalGeodesicFEFunction<gridDim, DT, LocalFiniteElement, TargetSpace> LocalGFEFunctionType;
-  LocalGFEFunctionType localGeodesicFEFunction(localFiniteElement,localSolution);
+  using namespace Dune::TypeTree::Indices;
+
+  // The set of shape functions on this element
+  const auto& deformationLocalFiniteElement = localView.tree().child(_0,0).finiteElement();
+  const auto& orientationLocalFiniteElement = localView.tree().child(_1,0).finiteElement();
+    
+  // to construt a local GFE function, in case they are the shape functions are the same, we can use use one GFE-Function
+#if MIXED_SPACE
+    std::vector<RBM0> localSolutionRBM0(localSolution0.size());
+    std::vector<RBM1> localSolutionRBM1(localSolution1.size());
+    for (int i = 0; i < localSolution0.size(); i++)
+      localSolutionRBM0[i] = localSolution0[i];
+    for (int i = 0; i< localSolution1.size(); i++)
+      localSolutionRBM1[i] = localSolution1[i];
+    typedef LocalGeodesicFEFunction<gridDim, DT, decltype(deformationLocalFiniteElement), RBM0> LocalGFEFunctionType0;
+    typedef LocalGeodesicFEFunction<gridDim, DT, decltype(orientationLocalFiniteElement), RBM1> LocalGFEFunctionType1;
+    LocalGFEFunctionType0 localGeodesicFEFunction0(deformationLocalFiniteElement,localSolutionRBM0);
+    LocalGFEFunctionType1 localGeodesicFEFunction1(orientationLocalFiniteElement,localSolutionRBM1);
+#else
+    std::vector<RBM> localSolutionRBM(localSolution0.size());
+    for (int i = 0; i < localSolution0.size(); i++) {
+      for (int j = 0; j < dimWorld; j++)
+        localSolutionRBM[i].r[j] = localSolution0[i][j];
+      localSolutionRBM[i].q = localSolution1[i];
+    }
+    typedef LocalGeodesicFEFunction<gridDim, DT, decltype(deformationLocalFiniteElement), RBM> LocalGFEFunctionType;
+    LocalGFEFunctionType localGeodesicFEFunction(deformationLocalFiniteElement,localSolutionRBM);
+#endif
 
   RT energy = 0;
 
@@ -161,8 +167,8 @@ RT energy(const typename Basis::LocalView& localView,
     
     auto id = idSet.subId(it.inside(), it.indexInInside(), 1);
     auto boundaryGeometry = geometriesOnShellBoundary_.at(id);
-    auto quadOrder = (it.type().isSimplex()) ? localFiniteElement.localBasis().order()
-                                                  : localFiniteElement.localBasis().order() * boundaryDim;
+    auto quadOrder = (it.type().isSimplex()) ? deformationLocalFiniteElement.localBasis().order()
+                                                  : deformationLocalFiniteElement.localBasis().order() * boundaryDim;
 
     const auto& quad = Dune::QuadratureRules<DT, boundaryDim>::rule(it.type(), quadOrder);
     for (size_t pt=0; pt<quad.size(); pt++) {
@@ -179,47 +185,71 @@ RT energy(const typename Basis::LocalView& localView,
 
       const DT integrationElement = boundaryGeometry.integrationElement(quad[pt].position());
 
-      // The value of the local function
-      RigidBodyMotion<field_type,dim> value = localGeodesicFEFunction.evaluate(quadPos);
-
-      // The derivative of the local function
-      auto derivative = localGeodesicFEFunction.evaluateDerivative(quadPos,value);
+      RBM value;
+      Dune::FieldMatrix<RT, RBM::embeddedDim, dimWorld> derivative;
+      Dune::FieldMatrix<RT, RBM::embeddedDim, boundaryDim> derivative2D;
 
-      Dune::FieldMatrix<RT,7,2> derivative2D;
-      for (int i = 0; i < 7; i++) {
-        for (int j = 0; j < 2; j++) {
-          derivative2D[i][j] = derivative[i][j];
+#if MIXED_SPACE
+      // The value of the local function
+      RBM0 value0 = localGeodesicFEFunction0.evaluate(quadPos);
+      RBM1 value1 = localGeodesicFEFunction1.evaluate(quadPos);
+      // The derivatives of the local functions
+      auto derivative0 = localGeodesicFEFunction0.evaluateDerivative(quadPos,value0);
+      auto derivative1 = localGeodesicFEFunction1.evaluateDerivative(quadPos,value1);
+
+      // Put the value and the derivatives together from the separated values
+      for (int i = 0; i < RBM0::dim; i++)
+          value.r[i] = value0[i];
+      value.q = value1;
+      for (int j = 0; j < dimWorld; j++) {
+        for (int i = 0; i < RBM0::embeddedDim; i++) {
+          derivative[i][j] = derivative0[i][j];
+          if (j < boundaryDim)
+            derivative2D[i][j] = derivative0[i][j];
+        }
+        for (int i = 0; i < RBM1::embeddedDim; i++) {
+          derivative[RBM0::embeddedDim + i][j] = derivative1[i][j];
+          if (j < boundaryDim)
+            derivative2D[RBM0::embeddedDim + i][j] = derivative1[i][j];
         }
       }
+#else
+      value = localGeodesicFEFunction.evaluate(quadPos);
+      derivative = localGeodesicFEFunction.evaluateDerivative(quadPos,value);
+      for (int i = 0; i < RBM::embeddedDim; i++)
+        for (int j = 0; j < boundaryDim; j++)
+          derivative2D[i][j] = derivative[i][j];
+#endif
+
       //////////////////////////////////////////////////////////
       //  The rotation and its derivative
       //  Note: we need it in matrix coordinates
       //////////////////////////////////////////////////////////
 
-      Dune::FieldMatrix<field_type,dim,dim> R;
+      Dune::FieldMatrix<RT,dimWorld,dimWorld> R;
       value.q.matrix(R);
-      auto RT = Dune::GFE::transpose(R);
+      auto rt = Dune::GFE::transpose(R);
 
-      Tensor3<field_type,3,3,boundaryDim> DR;
-      computeDR(value, derivative2D, DR);
+      Tensor3<RT,dimWorld,dimWorld,boundaryDim> derivative_rotation;
+      computeDR(value, derivative2D, derivative_rotation);
 
       //////////////////////////////////////////////////////////
       //  Fundamental forms and curvature
       //////////////////////////////////////////////////////////
 
       // First fundamental form
-      Dune::FieldMatrix<double,3,3> aCovariant;
+      Dune::FieldMatrix<double,dimWorld,dimWorld> aCovariant;
 
-      // If dimworld==3, then the first two lines of aCovariant are simply the jacobianTransposed
-      // of the element.  If dimworld<3 (i.e., ==2), we have to explicitly enters 0.0 in the last column.
+      // If dimWorld==3, then the first two lines of aCovariant are simply the jacobianTransposed
+      // of the element.  If dimWorld<3 (i.e., ==2), we have to explicitly enters 0.0 in the last column.
       const auto jacobianTransposed = boundaryGeometry.jacobianTransposed(quad[pt].position());
       // auto jacobianTransposed = geometry.jacobianTransposed(quadPos);
 
       for (int i=0; i<2; i++)
       {
-        for (int j=0; j<dimworld; j++)
+        for (int j=0; j<dimWorld; j++)
           aCovariant[i][j] = jacobianTransposed[i][j];
-        for (int j=dimworld; j<3; j++)
+        for (int j=dimWorld; j<3; j++)
           aCovariant[i][j] = 0.0;
       }
 
@@ -271,28 +301,28 @@ RT energy(const typename Basis::LocalView& localView,
       //////////////////////////////////////////////////////////
 
       // Elastic shell strain
-      Dune::FieldMatrix<field_type,3,3> Ee(0);
-      Dune::FieldMatrix<field_type,3,3> grad_s_m(0);
+      Dune::FieldMatrix<RT,3,3> Ee(0);
+      Dune::FieldMatrix<RT,3,3> grad_s_m(0);
       for (int alpha=0; alpha<boundaryDim; alpha++)
       {
-        Dune::FieldVector<field_type,3> vec;
+        Dune::FieldVector<RT,3> vec;
         for (int i=0; i<3; i++)
           vec[i] = derivative[i][alpha];
         grad_s_m += Dune::GFE::dyadicProduct(vec, aContravariant[alpha]);
       }
 
-      Ee = RT * grad_s_m - a;
+      Ee = rt * grad_s_m - a;
 
       // Elastic shell bending-curvature strain
-      Dune::FieldMatrix<field_type,3,3> Ke(0);
+      Dune::FieldMatrix<RT,3,3> Ke(0);
       for (int alpha=0; alpha<boundaryDim; alpha++)
       {
-        Dune::FieldMatrix<field_type,3,3> tmp;
+        Dune::FieldMatrix<RT,3,3> tmp;
         for (int i=0; i<3; i++)
           for (int j=0; j<3; j++)
-            tmp[i][j] = DR[i][j][alpha];
-        auto tmp2 = RT * tmp;
-        Ke += Dune::GFE::dyadicProduct(SkewMatrix<field_type,3>(tmp2).axial(), aContravariant[alpha]);
+            tmp[i][j] = derivative_rotation[i][j][alpha];
+        auto tmp2 = rt * tmp;
+        Ke += Dune::GFE::dyadicProduct(SkewMatrix<RT,3>(tmp2).axial(), aContravariant[alpha]);
       }
 
       //////////////////////////////////////////////////////////
@@ -318,24 +348,24 @@ RT energy(const typename Basis::LocalView& localView,
   return energy;
 }
 
-  RT W_m(const Dune::FieldMatrix<field_type,3,3>& S, double mu, double lambda) const
+  RT W_m(const Dune::FieldMatrix<RT,3,3>& S, double mu, double lambda) const
   {
     return W_mixt(S,S, mu, lambda);
   }
 
-  RT W_mixt(const Dune::FieldMatrix<field_type,3,3>& S, const Dune::FieldMatrix<field_type,3,3>& T, double mu, double lambda) const
+  RT W_mixt(const Dune::FieldMatrix<RT,3,3>& S, const Dune::FieldMatrix<RT,3,3>& T, double mu, double lambda) const
   {
     return mu * Dune::GFE::frobeniusProduct(Dune::GFE::sym(S), Dune::GFE::sym(T))
          + mu_c_ * Dune::GFE::frobeniusProduct(Dune::GFE::skew(S), Dune::GFE::skew(T))
          + lambda * mu / (lambda + 2*mu) * Dune::GFE::trace(S) * Dune::GFE::trace(T);
   }
 
-  RT W_mp(const Dune::FieldMatrix<field_type,3,3>& S, double mu, double lambda) const
+  RT W_mp(const Dune::FieldMatrix<RT,3,3>& S, double mu, double lambda) const
   {
     return mu * Dune::GFE::sym(S).frobenius_norm2() + mu_c_ * Dune::GFE::skew(S).frobenius_norm2() + lambda * 0.5 * Dune::GFE::traceSquared(S);
   }
 
-  RT W_curv(const Dune::FieldMatrix<field_type,3,3>& S, double mu) const
+  RT W_curv(const Dune::FieldMatrix<RT,3,3>& S, double mu) const
   {
     return mu * L_c_ * L_c_ * (b1_ * Dune::GFE::dev(Dune::GFE::sym(S)).frobenius_norm2()
          + b2_ * Dune::GFE::skew(S).frobenius_norm2() + b3_ * Dune::GFE::traceSquared(S));
@@ -346,16 +376,16 @@ private:
   const BoundaryPatch<GridView>* shellBoundary_;
 
   /** \brief Stress-free geometries of the shell elements*/
-  const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType, Dune::MultiLinearGeometry<double, dim-1, dim>> geometriesOnShellBoundary_;
+  const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType, Dune::MultiLinearGeometry<double, dimWorld-1, dimWorld>> geometriesOnShellBoundary_;
 
   /** \brief The normal vectors at the grid vertices. They are used to compute the reference surface curvature. */
   std::vector<UnitVector<double,3> > vertexNormals_;
 
   /** \brief The shell thickness as a function*/
-  std::function<double(Dune::FieldVector<double,dim>)> thicknessF_;
+  std::function<double(Dune::FieldVector<double,dimWorld>)> thicknessF_;
 
   /** \brief The Lamé-parameters as a function*/
-  std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dim>)> lameF_;
+  std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dimWorld>)> lameF_;
 
   /** \brief Lame constants */
   double mu_, lambda_;
@@ -370,5 +400,6 @@ private:
   double b1_, b2_, b3_;
 
 };
+}  // namespace Dune::GFE
 
 #endif   //#ifndef DUNE_GFE_SURFACECOSSERATENERGY_HH
diff --git a/problems/film-on-substrate.parset b/problems/film-on-substrate.parset
index 9bc4ce139b2090e48002f5bdbb4f4e8ddcb85e0c..fb745548e806d2deb25e33f2e07af4a05c2802c6 100644
--- a/problems/film-on-substrate.parset
+++ b/problems/film-on-substrate.parset
@@ -51,7 +51,7 @@ initialDeformation = "x"
 #############################################
 
 # Inner solver, cholmod or multigrid
-solvertype = cholmod
+solvertype = multigrid
 
 # Number of homotopy steps for the Dirichlet boundary conditions
 numHomotopySteps = 1
@@ -148,4 +148,4 @@ mooneyrivlin_energy = log # log, square or ciarlet; different ways to compute th
 # log: Generalized Rivlin model or polynomial hyperelastic model, using  0.5*mooneyrivlin_k*log(det(∇φ)) as the volume-preserving penalty term
 # square: Generalized Rivlin model or polynomial hyperelastic model, using mooneyrivlin_k*(det(∇φ)-1)² as the volume-preserving penalty term
 
-[]
\ No newline at end of file
+[]
diff --git a/src/film-on-substrate.cc b/src/film-on-substrate.cc
index f0843d81f4e46dca10975d882c9b15ff7e45390a..94c64915ad8ecb0540c32699bf78fd3a569a0f98 100644
--- a/src/film-on-substrate.cc
+++ b/src/film-on-substrate.cc
@@ -1,3 +1,4 @@
+#define MIXED_SPACE 0
 #include <iostream>
 #include <fstream>
 
@@ -12,59 +13,52 @@
 #include <dune/fufem/utilities/adolcnamespaceinjections.hh>
 
 #include <dune/common/bitsetvector.hh>
+#include <dune/common/indices.hh>
 #include <dune/common/parametertree.hh>
 #include <dune/common/parametertreeparser.hh>
 #include <dune/common/timer.hh>
+#include <dune/common/tuplevector.hh>
 #include <dune/common/version.hh>
 
-#include <dune/grid/uggrid.hh>
-#include <dune/grid/utility/structuredgridfactory.hh>
-
-#include <dune/grid/io/file/gmshreader.hh>
-#include <dune/grid/io/file/vtk.hh>
-
-#if DUNE_VERSION_GTE(DUNE_ELASTICITY, 2, 8)
 #include <dune/elasticity/materials/exphenckydensity.hh>
 #include <dune/elasticity/materials/henckydensity.hh>
 #include <dune/elasticity/materials/mooneyrivlindensity.hh>
 #include <dune/elasticity/materials/neohookedensity.hh>
 #include <dune/elasticity/materials/stvenantkirchhoffdensity.hh>
-#include <dune/elasticity/materials/sumenergy.hh>
-#include <dune/elasticity/materials/localintegralenergy.hh>
-#include <dune/elasticity/materials/neumannenergy.hh>
-#else
-#include <dune/elasticity/materials/exphenckyenergy.hh>
-#include <dune/elasticity/materials/henckyenergy.hh>
-#if !DUNE_VERSION_LT(DUNE_ELASTICITY, 2, 7)
-#include <dune/elasticity/materials/mooneyrivlinenergy.hh>
-#endif
-#include <dune/elasticity/materials/neohookeenergy.hh>
-#include <dune/elasticity/materials/neumannenergy.hh>
-#include <dune/elasticity/materials/sumenergy.hh>
-#include <dune/elasticity/materials/stvenantkirchhoffenergy.hh>
-#endif
-
 
 #include <dune/functions/functionspacebases/interpolate.hh>
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 #include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
+#include <dune/functions/functionspacebases/compositebasis.hh>
 #include <dune/functions/functionspacebases/powerbasis.hh>
 
-#include <dune/fufem/boundarypatch.hh>
 #include <dune/fufem/functiontools/boundarydofs.hh>
-#include <dune/fufem/functiontools/basisinterpolator.hh>
-#include <dune/fufem/functionspacebases/dunefunctionsbasis.hh>
 #include <dune/fufem/dunepython.hh>
 
-#include <dune/gfe/rigidbodymotion.hh>
-#include <dune/gfe/localgeodesicfeadolcstiffness.hh>
+#include <dune/grid/uggrid.hh>
+#include <dune/grid/utility/structuredgridfactory.hh>
+#include <dune/grid/io/file/gmshreader.hh>
+#include <dune/grid/io/file/vtk.hh>
+
 #include <dune/gfe/cosseratvtkwriter.hh>
-#include <dune/gfe/geodesicfeassembler.hh>
+#include <dune/gfe/localintegralenergy.hh>
+#include <dune/gfe/mixedgfeassembler.hh>
+#include <dune/gfe/mixedlocalgfeadolcstiffness.hh>
+#include <dune/gfe/neumannenergy.hh>
+#include <dune/gfe/surfacecosseratenergy.hh>
+#include <dune/gfe/sumenergy.hh>
+#include <dune/gfe/vertexnormals.hh>
+
+#if MIXED_SPACE
+#include <dune/gfe/mixedriemanniantrsolver.hh>
+#else
+#include <dune/gfe/geodesicfeassemblerwrapper.hh>
 #include <dune/gfe/riemannianpnsolver.hh>
 #include <dune/gfe/riemanniantrsolver.hh>
-#include <dune/gfe/vertexnormals.hh>
-#include <dune/gfe/surfacecosseratenergy.hh>
-#include <dune/gfe/sumcosseratenergy.hh>
+#include <dune/gfe/rigidbodymotion.hh>
+#endif
+
+#include <dune/istl/multitypeblockvector.hh>
 
 #include <dune/solvers/solvers/iterativesolver.hh>
 #include <dune/solvers/norms/energynorm.hh>
@@ -74,7 +68,15 @@
 #  define WORLD_DIM 3
 #endif
 const int dim = WORLD_DIM;
-const int order = 2;
+
+const int targetDim = WORLD_DIM;
+
+const int displacementOrder = 2;
+const int rotationOrder = 2;
+
+#if !MIXED_SPACE
+static_assert(displacementOrder==rotationOrder, "displacement and rotation order do not match!");
+#endif
 
 #if DUNE_VERSION_LT(DUNE_COMMON, 2, 7)
 template<>
@@ -100,8 +102,14 @@ int main (int argc, char *argv[]) try
   // initialize MPI, finalize is done automatically on exit
   Dune::MPIHelper& mpiHelper = MPIHelper::instance(argc, argv);
 
-  if (mpiHelper.rank()==0)
-    std::cout << "ORDER = " << order << std::endl;
+  if (mpiHelper.rank()==0) {
+    std::cout << "DISPLACEMENTORDER = " << displacementOrder << ", ROTATIONORDER = " << rotationOrder << std::endl;
+#if MIXED_SPACE
+    std::cout << "MIXED_SPACE = 1" << std::endl;
+#else
+    std::cout << "MIXED_SPACE = 0" << std::endl;
+#endif
+  }
 
   // Start Python interpreter
   Python::start();
@@ -115,12 +123,6 @@ int main (int argc, char *argv[]) try
         << std::endl << "sys.path.append(os.getcwd() + '/../../problems/')"
         << std::endl;
 
-  typedef BlockVector<FieldVector<double,dim> > SolutionType;
-  typedef RigidBodyMotion<double,dim> TargetSpace;
-  typedef std::vector<TargetSpace> SolutionTypeCosserat;
-
-  const int blocksize = TargetSpace::TangentVector::dimension;
-
   // parse data file
   ParameterTree parameterSet;
 
@@ -146,15 +148,16 @@ int main (int argc, char *argv[]) try
   const bool startFromFile              = parameterSet.get<bool>("startFromFile");
   const std::string resultPath          = parameterSet.get("resultPath", "");
 
-  // ///////////////////////////////////////
-  //    Create the grid
-  // ///////////////////////////////////////
+  /////////////////////////////////////////////////////////////
+  //                      CREATE THE GRID
+  /////////////////////////////////////////////////////////////
   typedef UGGrid<dim> GridType;
 
   std::shared_ptr<GridType> grid;
 
   FieldVector<double,dim> lower(0), upper(1);
 
+
   if (parameterSet.get<bool>("structuredGrid")) {
 
     lower = parameterSet.get<FieldVector<double,dim> >("lower");
@@ -206,17 +209,49 @@ int main (int argc, char *argv[]) try
   typedef GridType::LeafGridView GridView;
   GridView gridView = grid->leafGridView();
 
-  // FE basis spanning the FE space that we are working in
-  typedef Dune::Functions::LagrangeBasis<GridView, order> FEBasis;
-  FEBasis feBasis(gridView);
+  /////////////////////////////////////////////////////////////
+  //                      DATA TYPES 
+  /////////////////////////////////////////////////////////////
+
+  using namespace Dune::Indices;
 
-  // dune-fufem-style FE basis for the transition from dune-fufem to dune-functions
-  typedef DuneFunctionsBasis<FEBasis> FufemFEBasis;
-  FufemFEBasis fufemFEBasis(feBasis);
+  typedef std::vector<RealTuple<double,dim> > DisplacementVector;
+  typedef std::vector<Rotation<double,dim>> RotationVector;
+  const int dimRotation = Rotation<double,dim>::embeddedDim;
+  typedef TupleVector<DisplacementVector, RotationVector> SolutionType;
 
-  // /////////////////////////////////////////
-  //   Read Dirichlet values
-  // /////////////////////////////////////////
+  /////////////////////////////////////////////////////////////
+  //                      FUNCTION SPACE
+  /////////////////////////////////////////////////////////////
+
+  using namespace Dune::Functions::BasisFactory;
+  auto compositeBasis = makeBasis(
+    gridView,
+    composite(
+      power<dim>(
+        lagrange<displacementOrder>()
+      ),
+      power<dimRotation>(
+        lagrange<rotationOrder>()
+      )
+  ));
+
+  auto deformationPowerBasis = makeBasis(
+    gridView,
+    power<dim>(
+        lagrange<displacementOrder>()
+  ));
+  typedef Dune::Functions::LagrangeBasis<GridView,displacementOrder> DeformationFEBasis;
+  typedef Dune::Functions::LagrangeBasis<GridView,rotationOrder> OrientationFEBasis;
+  DeformationFEBasis deformationFEBasis(gridView);
+  OrientationFEBasis orientationFEBasis(gridView);
+
+  using CompositeBasis = decltype(compositeBasis);
+  using LocalView = typename CompositeBasis::LocalView;
+
+  /////////////////////////////////////////////////////////////
+  //                      BOUNDARY DATA
+  /////////////////////////////////////////////////////////////
 
   BitSetVector<1> dirichletVertices(gridView.size(dim), false);
   BitSetVector<1> neumannVertices(gridView.size(dim), false);
@@ -240,97 +275,64 @@ int main (int argc, char *argv[]) try
   auto neumannBoundary = std::make_shared<BoundaryPatch<GridView>>(gridView, neumannVertices);
   BoundaryPatch<GridView> surfaceShellBoundary(gridView, surfaceShellVertices);
 
+  std::cout << "On rank " << mpiHelper.rank() << ": Dirichlet boundary has " << dirichletBoundary.numFaces() << " faces\n";
   std::cout << "On rank " << mpiHelper.rank() << ": Neumann boundary has " << neumannBoundary->numFaces() << " faces\n";
   std::cout << "On rank " << mpiHelper.rank() << ": Shell boundary has " << surfaceShellBoundary.numFaces() << " faces\n";
 
-
-  BitSetVector<1> dirichletNodes(feBasis.size(), false);
-#if DUNE_VERSION_LT(DUNE_FUFEM, 2, 7)
-  using FufemFEBasis = DuneFunctionsBasis<FEBasis>;
-  FufemFEBasis fufemFeBasis(feBasis);
-  constructBoundaryDofs(dirichletBoundary,fufemFeBasis,dirichletNodes);
-#else
-  constructBoundaryDofs(dirichletBoundary,feBasis,dirichletNodes);
-#endif
-
-  BitSetVector<1> neumannNodes(feBasis.size(), false);
-#if DUNE_VERSION_LT(DUNE_FUFEM, 2, 7)
-  constructBoundaryDofs(*neumannBoundary,fufemFeBasis,neumannNodes);
-#else
-  constructBoundaryDofs(*neumannBoundary,feBasis,neumannNodes);
-#endif
-
-  BitSetVector<1> surfaceShellNodes(feBasis.size(), false);
-#if DUNE_VERSION_LT(DUNE_FUFEM, 2, 7)
-  constructBoundaryDofs(surfaceShellBoundary,fufemFeBasis,surfaceShellNodes);
-#else
-  constructBoundaryDofs(surfaceShellBoundary,feBasis,surfaceShellNodes);
-#endif
-
-  BitSetVector<blocksize> dirichletDofs(feBasis.size(), false);
-  for (size_t i=0; i<feBasis.size(); i++)
-    for (int j=0; j<blocksize; j++) {
-      if (dirichletNodes[i][0])
-        dirichletDofs[i][j] = true;
+  BitSetVector<1> dirichletNodes(compositeBasis.size({0}),false);
+  BitSetVector<1> surfaceShellNodes(compositeBasis.size({1}),false);
+  constructBoundaryDofs(dirichletBoundary,deformationFEBasis,dirichletNodes);
+  constructBoundaryDofs(surfaceShellBoundary,orientationFEBasis,surfaceShellNodes);
+
+  //Create BitVector matching the tangential space
+  const int dimRotationTangent = Rotation<double,dim>::TangentVector::dimension;
+  typedef MultiTypeBlockVector<std::vector<FieldVector<double,dim> >, std::vector<FieldVector<double,dimRotationTangent>> > VectorForBit;
+  typedef Solvers::DefaultBitVector_t<VectorForBit> BitVector;
+
+  BitVector dirichletDofs;
+  dirichletDofs[_0].resize(compositeBasis.size({0}));
+  dirichletDofs[_1].resize(compositeBasis.size({1}));
+  for (size_t i = 0; i < compositeBasis.size({0}); i++){
+    for (int j = 0; j < dim; j++){
+      dirichletDofs[_0][i][j] = dirichletNodes[i][0];
     }
-  for (size_t i=0; i<feBasis.size(); i++)
-    for (int j=3; j<blocksize; j++) {
-      if (not surfaceShellNodes[i][0])
-        dirichletDofs[i][j] = true;
+  }
+  for (size_t i = 0; i < compositeBasis.size({1}); i++) {
+    for (int j = 0; j < dimRotationTangent; j++){
+      dirichletDofs[_1][i][j] = (not surfaceShellNodes[i][0] or dirichletNodes[i][0]);
     }
+  }
 
-  // //////////////////////////
-  //   Initial iterate
-  // //////////////////////////
+  /////////////////////////////////////////////////////////////
+  //                      INITIAL DATA
+  /////////////////////////////////////////////////////////////
   
-  SolutionTypeCosserat x(feBasis.size());
+  SolutionType x;
+  x[_0].resize(compositeBasis.size({0}));
+  x[_1].resize(compositeBasis.size({1}));
 
-  BlockVector<FieldVector<double,3> > v;
-  
   //Initial deformation of the underlying substrate
+  BlockVector<FieldVector<double,dim> > displacement(compositeBasis.size({0}));
   lambda = std::string("lambda x: (") + parameterSet.get<std::string>("initialDeformation") + std::string(")");
   PythonFunction<FieldVector<double,dim>, FieldVector<double,dim> > pythonInitialDeformation(Python::evaluate(lambda));
-  ::Functions::interpolate(fufemFEBasis, v, pythonInitialDeformation);
-
-  //Copy over the initial deformation
-  for (size_t i=0; i<x.size(); i++) {
-      x[i].r = v[i];
-  }
-
-  ////////////////////////////////////////////////////////
-  //   Main homotopy loop
-  ////////////////////////////////////////////////////////
-
-  using namespace Dune::Functions::BasisFactory;
-  auto powerBasis = makeBasis(
-    gridView,
-    power<dim>(
-      lagrange<order>(),
-      blockedInterleaved()
-  ));
+  Dune::Functions::interpolate(deformationPowerBasis, displacement, pythonInitialDeformation);
 
-  BlockVector<FieldVector<double,dim>> identity;
-  Dune::Functions::interpolate(powerBasis, identity, [](FieldVector<double,dim> x){ return x; });
+  BlockVector<FieldVector<double,dim> > identity(compositeBasis.size({0}));
+  Dune::Functions::interpolate(deformationPowerBasis, identity, [](FieldVector<double,dim> x){ return x; });
 
-  BlockVector<FieldVector<double,dim> > displacement(v.size());
-  for (int i = 0; i < v.size(); i++) {
-    displacement[i] = v[i];
+  for (int i = 0; i < displacement.size(); i++) {
+    x[_0][i] = displacement[i]; //Copy over the initial deformation to the deformation part of x
+    displacement[i] -= identity[i]; //Subtract identity to get the initial displacement as a function
   }
-  displacement -= identity;
-
-  auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim>>(feBasis, displacement);
-  auto localDisplacementFunction = localFunction(displacementFunction);
-
-  FieldVector<double,dim> neumannValues {0,0,0};
-
-  if (parameterSet.hasKey("neumannValues"))
-    neumannValues = parameterSet.get<FieldVector<double,dim> >("neumannValues");
-  std::cout << "Neumann values: " << neumannValues << std::endl;
-
+  auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim>>(deformationPowerBasis, displacement);
   //  We need to subsample, because VTK cannot natively display real second-order functions
-  SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(order-1));
-  vtkWriter.addVertexData(localDisplacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::scalar, dim));
+  SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(displacementOrder-1));
+  vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::scalar, dim));
   vtkWriter.write(resultPath + "finite-strain_homotopy_" + parameterSet.get<std::string>("energy") + "_0");
+  
+  /////////////////////////////////////////////////////////////
+  //               INITIAL SURFACE SHELL DATA
+  /////////////////////////////////////////////////////////////
 
   typedef MultiLinearGeometry<double, dim-1, dim> ML;
   std::unordered_map<GridType::GlobalIdSet::IdType, ML> geometriesOnShellBoundary;
@@ -339,6 +341,7 @@ int main (int argc, char *argv[]) try
 
   // Read in the grid deformation
   if (startFromFile) {
+    // Create a basis of order 1 in order to deform the geometries on the surface shell boundary
     const std::string pathToGridDeformationFile = parameterSet.get("pathToGridDeformationFile", "");
     // for this, we create a basis of order 1 in order to deform the geometries on the surface shell boundary
     auto feBasisOrder1 = makeBasis(
@@ -427,15 +430,30 @@ int main (int argc, char *argv[]) try
     }
   }
 
+  /////////////////////////////////////////////////////////////
+  //                      MAIN HOMOTOPY LOOP
+  /////////////////////////////////////////////////////////////
+  FieldVector<double,dim> neumannValues {0,0,0};
+  if (parameterSet.hasKey("neumannValues"))
+    neumannValues = parameterSet.get<FieldVector<double,dim> >("neumannValues");
+  std::cout << "Neumann values: " << neumannValues << std::endl;
+
+  // Vertex Normals for the 3D-Part
+  std::vector<UnitVector<double,dim> > vertexNormals(gridView.size(dim));
+  Dune::FieldVector<double,dim> vertexNormalRaw = {0,0,1};
+  for (int i = 0; i< vertexNormals.size(); i++) {
+    UnitVector vertexNormal(vertexNormalRaw);
+    vertexNormals[i] = vertexNormal;
+  }
+  //Function for the Cosserat material parameters
   const ParameterTree& materialParameters = parameterSet.sub("materialParameters");
   Python::Reference surfaceShellClass = Python::import(materialParameters.get<std::string>("surfaceShellParameters"));
   Python::Callable surfaceShellCallable = surfaceShellClass.get("SurfaceShellParameters");
-
   Python::Reference pythonObject = surfaceShellCallable();
   PythonFunction<Dune::FieldVector<double, dim>, double> fThickness(pythonObject.get("thickness"));
   PythonFunction<Dune::FieldVector<double, dim>, Dune::FieldVector<double, 2>> fLame(pythonObject.get("lame"));
 
-  for (int i=0; i<numHomotopySteps; i++)
+  for (int i = 0; i < numHomotopySteps; i++)
   {
     double homotopyParameter = (i+1)*(1.0/numHomotopySteps);
 
@@ -444,17 +462,13 @@ int main (int argc, char *argv[]) try
     // ////////////////////////////////////////////////////////////
 
 
-#if DUNE_VERSION_LT(DUNE_ELASTICITY, 2, 8)
-    std::shared_ptr<NeumannFunction> neumannFunction;
-    neumannFunction = std::make_shared<NeumannFunction>(neumannValues, homotopyParameter);
-#else
       // A constant vector-valued function, for simple Neumann boundary values
     std::shared_ptr<std::function<Dune::FieldVector<double,dim>(Dune::FieldVector<double,dim>)>> neumannFunctionPtr;
     neumannFunctionPtr = std::make_shared<std::function<Dune::FieldVector<double,dim>(Dune::FieldVector<double,dim>)>>([&](FieldVector<double,dim> ) {
       return neumannValues * (-homotopyParameter);
     });
-#endif
 
+    const ParameterTree& materialParameters = parameterSet.sub("materialParameters");
     if (mpiHelper.rank() == 0)
     {
       std::cout << "Homotopy step: " << i << ",    parameter: " << homotopyParameter << std::endl;
@@ -462,9 +476,12 @@ int main (int argc, char *argv[]) try
       materialParameters.report();
     }
 
-    // Assembler using ADOL-C
     std::cout << "Selected energy is: " << parameterSet.get<std::string>("energy") << std::endl;
-#if DUNE_VERSION_GTE(DUNE_ELASTICITY, 2,8)
+
+    // /////////////////////////////////////////////////
+    //   Create the energy functional
+    // /////////////////////////////////////////////////
+
     std::shared_ptr<Elasticity::LocalDensity<dim,ValueType>> elasticDensity;
     if (parameterSet.get<std::string>("energy") == "stvenantkirchhoff")
       elasticDensity = std::make_shared<Elasticity::StVenantKirchhoffDensity<dim,ValueType>>(materialParameters);
@@ -477,123 +494,96 @@ int main (int argc, char *argv[]) try
     if (parameterSet.get<std::string>("energy") == "mooneyrivlin")
       elasticDensity = std::make_shared<Elasticity::MooneyRivlinDensity<dim,ValueType>>(materialParameters);
 
-    if(!elasticDensity)
-      DUNE_THROW(Exception, "Error: Selected energy not available!");
-
-    auto elasticEnergy = std::make_shared<LocalIntegralEnergy<GridView, FEBasis::LocalView::Tree::FiniteElement, ValueType>>(elasticDensity);
-    auto neumannEnergy = std::make_shared<NeumannEnergy<GridView,
-                                                        FEBasis::LocalView::Tree::FiniteElement,
-                                                        ValueType> >(neumannBoundary,neumannFunctionPtr);
 
-    auto elasticAndNeumann = std::make_shared<Dune::SumEnergy<GridView,
-          FEBasis::LocalView::Tree::FiniteElement,
-          ValueType>>(elasticEnergy, neumannEnergy);
-#else
-#if DUNE_VERSION_LT(DUNE_ELASTICITY, 2, 7)
-    std::shared_ptr<LocalFEStiffness<GridView,
-#else
-    std::shared_ptr<Elasticity::LocalEnergy<GridView,
-#endif
-                                     FEBasis::LocalView::Tree::FiniteElement,
-                                     std::vector<Dune::FieldVector<ValueType, dim>> > > elasticEnergy;
-
-    if (parameterSet.get<std::string>("energy") == "stvenantkirchhoff")
-      elasticEnergy = std::make_shared<StVenantKirchhoffEnergy<GridView,
-                                                               FEBasis::LocalView::Tree::FiniteElement,
-                                                               ValueType> >(materialParameters);
-#if !DUNE_VERSION_LT(DUNE_ELASTICITY, 2, 7)
-    if (parameterSet.get<std::string>("energy") == "mooneyrivlin")
-      elasticEnergy = std::make_shared<MooneyRivlinEnergy<GridView,
-                                                               FEBasis::LocalView::Tree::FiniteElement,
-                                                               ValueType> >(materialParameters);
-#endif
-
-    if (parameterSet.get<std::string>("energy") == "neohooke")
-      elasticEnergy = std::make_shared<NeoHookeEnergy<GridView,
-                                                      FEBasis::LocalView::Tree::FiniteElement,
-                                                      ValueType> >(materialParameters);
-
-    if (parameterSet.get<std::string>("energy") == "hencky")
-      elasticEnergy = std::make_shared<HenckyEnergy<GridView,
-                                                    FEBasis::LocalView::Tree::FiniteElement,
-                                                    ValueType> >(materialParameters);
-
-    if (parameterSet.get<std::string>("energy") == "exphencky")
-      elasticEnergy = std::make_shared<ExpHenckyEnergy<GridView,
-                                                       FEBasis::LocalView::Tree::FiniteElement,
-                                                       ValueType> >(materialParameters);
-
-    if(!elasticEnergy)
+    if(!elasticDensity)
       DUNE_THROW(Exception, "Error: Selected energy not available!");
 
-    auto neumannEnergy = std::make_shared<NeumannEnergy<GridView,
-                                                        FEBasis::LocalView::Tree::FiniteElement,
-                                                        ValueType> >(neumannBoundary.get(),neumannFunction.get());
-
-    auto elasticAndNeumann = std::make_shared<SumEnergy<GridView,
-          FEBasis::LocalView::Tree::FiniteElement,
-          ValueType>>(elasticEnergy, neumannEnergy);
-#endif
-
-    using LocalEnergyBase = GFE::LocalEnergy<FEBasis,RigidBodyMotion<adouble, dim> >;
-
-    std::shared_ptr<LocalEnergyBase> surfaceCosseratEnergy;
-    std::vector<UnitVector<double,3> > vertexNormals(gridView.size(3));
-    Dune::FieldVector<double,3> vertexNormalRaw = {0,0,1};
-    for (int i = 0; i< vertexNormals.size(); i++) {
-      UnitVector vertexNormal(vertexNormalRaw);
-      vertexNormals[i] = vertexNormal;
-    }
-
-    surfaceCosseratEnergy = std::make_shared<SurfaceCosseratEnergy<FEBasis,RigidBodyMotion<adouble, dim>, adouble, adouble>>(materialParameters, std::move(vertexNormals), &surfaceShellBoundary, std::move(geometriesOnShellBoundary), fThickness, fLame);
-
-    std::shared_ptr<LocalEnergyBase> totalEnergy;
-    totalEnergy = std::make_shared<GFE::SumCosseratEnergy<FEBasis,RigidBodyMotion<adouble, dim>, adouble>> (elasticAndNeumann, surfaceCosseratEnergy);
-
-
-    LocalGeodesicFEADOLCStiffness<FEBasis,
-                                  TargetSpace> localGFEADOLCStiffness(totalEnergy.get());
+    auto elasticEnergy = std::make_shared<GFE::LocalIntegralEnergy<CompositeBasis, RealTuple<ValueType,targetDim>, Rotation<ValueType,dim>>>(elasticDensity);
+    auto neumannEnergy = std::make_shared<GFE::NeumannEnergy<CompositeBasis, RealTuple<ValueType,targetDim>, Rotation<ValueType,dim>>>(neumannBoundary,*neumannFunctionPtr);
+    auto surfaceCosseratEnergy = std::make_shared<GFE::SurfaceCosseratEnergy<CompositeBasis, RealTuple<ValueType,dim>, Rotation<ValueType,dim> >>(materialParameters, std::move(vertexNormals), &surfaceShellBoundary, std::move(geometriesOnShellBoundary), fThickness, fLame);
 
-    GeodesicFEAssembler<FEBasis,TargetSpace> assembler(gridView, &localGFEADOLCStiffness);
+    GFE::SumEnergy<CompositeBasis, RealTuple<ValueType,targetDim>, Rotation<ValueType,targetDim>> sumEnergy;
+    sumEnergy.addLocalEnergy(neumannEnergy);
+    sumEnergy.addLocalEnergy(elasticEnergy);
+    sumEnergy.addLocalEnergy(surfaceCosseratEnergy);
 
+    MixedLocalGFEADOLCStiffness<CompositeBasis,
+                                RealTuple<double,dim>,
+                                Rotation<double,dim> > localGFEADOLCStiffness(&sumEnergy);
+    MixedGFEAssembler<CompositeBasis,
+                      RealTuple<double,dim>,
+                      Rotation<double,dim> > mixedAssembler(compositeBasis, &localGFEADOLCStiffness);
 
     ////////////////////////////////////////////////////////
     //   Set Dirichlet values
     ////////////////////////////////////////////////////////
 
-    Python::Reference dirichletValuesClass = Python::import(parameterSet.get<std::string>("dirichletValues"));
+    BitSetVector<RealTuple<double,dim>::TangentVector::dimension> deformationDirichletDofs(dirichletDofs[_0].size(), false);
+    for(int i = 0; i < dirichletDofs[_0].size(); i++)
+      for (int j = 0; j < RealTuple<double,dim>::TangentVector::dimension; j++)
+        deformationDirichletDofs[i][j] = dirichletDofs[_0][i][j];
+    BitSetVector<Rotation<double,dim>::TangentVector::dimension> orientationDirichletDofs(dirichletDofs[_1].size(), false);
+    for(int i = 0; i < dirichletDofs[_1].size(); i++)
+      for (int j = 0; j < Rotation<double,dim>::TangentVector::dimension; j++)
+        orientationDirichletDofs[i][j] = dirichletDofs[_1][i][j];
 
+    Python::Reference dirichletValuesClass = Python::import(parameterSet.get<std::string>("dirichletValues"));
     Python::Callable C = dirichletValuesClass.get("DirichletValues");
 
     // Call a constructor.
     Python::Reference dirichletValuesPythonObject = C(homotopyParameter);
 
     // Extract object member functions as Dune functions
-    PythonFunction<FieldVector<double,dim>, FieldVector<double,3> >   deformationDirichletValues(dirichletValuesPythonObject.get("deformation"));
-    PythonFunction<FieldVector<double,dim>, FieldMatrix<double,3,3> > orientationDirichletValues(dirichletValuesPythonObject.get("orientation"));
-
-    std::vector<FieldVector<double,3> > ddV;
-    ::Functions::interpolate(fufemFEBasis, ddV, deformationDirichletValues, dirichletDofs);
-
-    std::vector<FieldMatrix<double,3,3> > dOV;
-    ::Functions::interpolate(fufemFEBasis, dOV, orientationDirichletValues, dirichletDofs);
-
-    for (size_t j=0; j<x.size(); j++)
-      if (dirichletNodes[j][0])
-      {
-        x[j].r = ddV[j];
-        x[j].q.set(dOV[j]);
+    PythonFunction<FieldVector<double,dim>, FieldVector<double,targetDim> >   deformationDirichletValues(dirichletValuesPythonObject.get("deformation"));
+    PythonFunction<FieldVector<double,dim>, FieldMatrix<double,targetDim,targetDim> > rotationalDirichletValues(dirichletValuesPythonObject.get("orientation"));
+
+    BlockVector<FieldVector<double,targetDim> > ddV;
+    Dune::Functions::interpolate(deformationPowerBasis, ddV, deformationDirichletValues, deformationDirichletDofs);
+
+    BlockVector<FieldMatrix<double,targetDim,targetDim> > dOV;
+    Dune::Functions::interpolate(orientationFEBasis, dOV, rotationalDirichletValues, orientationDirichletDofs);
+
+    for (int i = 0; i < compositeBasis.size({0}); i++)
+      if (dirichletDofs[_0][i][0])
+        x[_0][i] = ddV[i];
+    for (int i = 0; i < compositeBasis.size({1}); i++)
+      if (dirichletDofs[_1][i][0])
+        x[_1][i].set(dOV[i]);
+
+#if !MIXED_SPACE
+    //The MixedRiemannianTrustRegionSolver can treat the Displacement and Orientation Space as separate ones
+    //The RiemannianTrustRegionSolver can only treat the Displacement and Rotation together in a RigidBodyMotion
+    //Therefore, x and the dirichletDofs are converted to a RigidBodyMotion structure, as well as the Hessian and Gradient that are returned by the assembler
+    typedef RigidBodyMotion<double, dim> RBM;
+    std::vector<RBM> xRBM(compositeBasis.size({0}));
+    BitSetVector<RBM::TangentVector::dimension> dirichletDofsRBM(compositeBasis.size({0}), false);
+    for (int i = 0; i < compositeBasis.size({0}); i++) {
+      for (int j = 0; j < dim; j ++) { // Displacement part
+        xRBM[i].r[j] = x[_0][i][j];
+        dirichletDofsRBM[i][j] = dirichletDofs[_0][i][j];
       }
-    // /////////////////////////////////////////////////
-    //   Create the solver and solve
-    // /////////////////////////////////////////////////
+      xRBM[i].q = x[_1][i]; // Rotation part
+      for (int j = dim; j < RBM::TangentVector::dimension; j ++)
+        dirichletDofsRBM[i][j] = dirichletDofs[_1][i][j-dim];
+    }
+    typedef Dune::GFE::GeodesicFEAssemblerWrapper<CompositeBasis, DeformationFEBasis, RBM, RealTuple<double, dim>, Rotation<double,dim>> GFEAssemblerWrapper;
+    GFEAssemblerWrapper assembler(&mixedAssembler, deformationFEBasis);
+#endif
+
+    ///////////////////////////////////////////////////
+    //   Create the chosen solver and solve!
+    ///////////////////////////////////////////////////
 
     if (parameterSet.get<std::string>("solvertype") == "multigrid") {
-      RiemannianTrustRegionSolver<FEBasis,TargetSpace> solver;
+#if MIXED_SPACE
+      MixedRiemannianTrustRegionSolver<GridType, CompositeBasis, DeformationFEBasis, RealTuple<double,dim>, OrientationFEBasis, Rotation<double,dim>> solver;
       solver.setup(*grid,
-                   &assembler,
+                   &mixedAssembler,
+                   deformationFEBasis,
+                   orientationFEBasis,
                    x,
-                   dirichletDofs,
+                   deformationDirichletDofs,
+                   orientationDirichletDofs,
                    tolerance,
                    maxSolverSteps,
                    initialTrustRegionRadius,
@@ -607,48 +597,75 @@ int main (int argc, char *argv[]) try
       solver.setScaling(parameterSet.get<FieldVector<double,6> >("trustRegionScaling"));
       solver.setInitialIterate(x);
       solver.solve();
-
       x = solver.getSol();
+#else
+      RiemannianTrustRegionSolver<DeformationFEBasis, RBM, GFEAssemblerWrapper> solver;
+      solver.setup(*grid,
+                   &assembler,
+                   xRBM,
+                   dirichletDofsRBM,
+                   tolerance,
+                   maxSolverSteps,
+                   initialTrustRegionRadius,
+                   multigridIterations,
+                   mgTolerance,
+                   mu, nu1, nu2,
+                   baseIterations,
+                   baseTolerance,
+                   instrumented);
+
+      solver.setScaling(parameterSet.get<FieldVector<double,6> >("trustRegionScaling"));
+      solver.setInitialIterate(xRBM);
+      solver.solve();
+      xRBM = solver.getSol();
+      for (int i = 0; i < xRBM.size(); i++) {
+        x[_0][i] = xRBM[i].r;
+        x[_1][i] = xRBM[i].q;
+      }
+#endif
     } else { //parameterSet.get<std::string>("solvertype") == "cholmod"
-      RiemannianProximalNewtonSolver<FEBasis,TargetSpace> solver;
+
+#if MIXED_SPACE
+    DUNE_THROW(Exception, "Error: There is no MixedRiemannianProximalNewtonSolver!");
+#else
+      RiemannianProximalNewtonSolver<DeformationFEBasis, RBM, GFEAssemblerWrapper> solver;
       solver.setup(*grid,
                    &assembler,
-                   x,
-                   dirichletDofs,
+                   xRBM,
+                   dirichletDofsRBM,
                    tolerance,
                    maxSolverSteps,
                    initialRegularization,
                    instrumented);
-      solver.setInitialIterate(x);
+      solver.setInitialIterate(xRBM);
       solver.solve();
-
-      x = solver.getSol();
+      xRBM = solver.getSol();
+      for (int i = 0; i < xRBM.size(); i++) {
+        x[_0][i] = xRBM[i].r;
+        x[_1][i] = xRBM[i].q;
+      }
+#endif
     }
-    // /////////////////////////////////////////////////////
-    //   Solve!
-    // /////////////////////////////////////////////////////
 
     std::cout << "Overall calculation took " << overallTimer.elapsed() << " sec." << std::endl;
 
     /////////////////////////////////
     //   Output result
     /////////////////////////////////
-    for (size_t i=0; i<x.size(); i++)
-      v[i] = x[i].r;
 
     // Compute the displacement
-    BlockVector<FieldVector<double,dim> > displacement(v.size());
-    for (int i = 0; i < v.size(); i++) {
-      displacement[i] = v[i];
+    BlockVector<FieldVector<double,dim> > displacement(compositeBasis.size({0}));
+    for (int i = 0; i < compositeBasis.size({0}); i++) {
+       for (int j = 0; j  < dim; j++) {
+        displacement[i][j] = x[_0][i][j];
+      }
+      displacement[i] -= identity[i];
     }
-    displacement -= identity;
-
-    auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim>>(feBasis, displacement);
-    auto localDisplacementFunction = localFunction(displacementFunction);
+    auto displacementFunction = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dim>>(deformationPowerBasis, displacement);
 
     //  We need to subsample, because VTK cannot natively display real second-order functions
-    SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(order-1));
-    vtkWriter.addVertexData(localDisplacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::scalar, dim));
+    SubsamplingVTKWriter<GridView> vtkWriter(gridView, Dune::refinementLevels(displacementOrder-1));
+    vtkWriter.addVertexData(displacementFunction, VTK::FieldInfo("displacement", VTK::FieldInfo::Type::scalar, dim));
     vtkWriter.write(resultPath + "finite-strain_homotopy_" + parameterSet.get<std::string>("energy") + "_" + std::to_string(neumannValues[0]) + "_" + std::to_string(i+1));
   }
 } catch (Exception& e) {