diff --git a/dune/gfe/mixedcosseratenergy.hh b/dune/gfe/mixedcosseratenergy.hh
index 4239ede37e3d9beb851838e5dcb83dd259fab7a9..8c0bcf455dc7d4a4f31f402adab7ed1361087bc8 100644
--- a/dune/gfe/mixedcosseratenergy.hh
+++ b/dune/gfe/mixedcosseratenergy.hh
@@ -20,14 +20,16 @@
 //#define QUADRATIC_MEMBRANE_ENERGY
 
 
-template<class GridView, class DisplacementLocalFiniteElement, class OrientationLocalFiniteElement, int dim, class field_type=double>
+template<class DisplacementBasis, class OrientationBasis, int dim, class field_type=double>
 class MixedCosseratEnergy
-    : public MixedLocalGeodesicFEStiffness<GridView,
-                                           DisplacementLocalFiniteElement,RealTuple<field_type,dim>,
-                                           OrientationLocalFiniteElement,Rotation<field_type,dim> >
+    : public MixedLocalGeodesicFEStiffness<DisplacementBasis,RealTuple<field_type,dim>,
+                                           OrientationBasis,Rotation<field_type,dim> >
 {
     // grid types
-    typedef typename GridView::Grid::ctype DT;
+    typedef typename DisplacementBasis::LocalView::Tree::FiniteElement DisplacementLocalFiniteElement;
+    typedef typename OrientationBasis::LocalView::Tree::FiniteElement OrientationLocalFiniteElement;
+    typedef typename DisplacementBasis::GridView GridView;
+    typedef typename GridView::ctype DT;
     typedef field_type RT;
     typedef typename GridView::template Codim<0>::Entity Entity;
 
@@ -263,11 +265,11 @@ public:
     const Dune::VirtualFunction<Dune::FieldVector<double,gridDim>, Dune::FieldVector<double,3> >* neumannFunction_;
 };
 
-template <class GridView, class DeformationLocalFiniteElement, class OrientationLocalFiniteElement, int dim, class field_type>
-typename MixedCosseratEnergy<GridView,DeformationLocalFiniteElement,OrientationLocalFiniteElement,dim,field_type>::RT
-MixedCosseratEnergy<GridView,DeformationLocalFiniteElement,OrientationLocalFiniteElement,dim,field_type>::
+template <class DeformationBasis, class OrientationBasis, int dim, class field_type>
+typename MixedCosseratEnergy<DeformationBasis,OrientationBasis,dim,field_type>::RT
+MixedCosseratEnergy<DeformationBasis,OrientationBasis,dim,field_type>::
 energy(const Entity& element,
-       const DeformationLocalFiniteElement& deformationLocalFiniteElement,
+       const DisplacementLocalFiniteElement& deformationLocalFiniteElement,
        const std::vector<RealTuple<field_type,dim> >& localDeformationConfiguration,
        const OrientationLocalFiniteElement& orientationLocalFiniteElement,
        const std::vector<Rotation<field_type,dim> >& localOrientationConfiguration) const
@@ -278,7 +280,7 @@ energy(const Entity& element,
 
     RT energy = 0;
 
-    typedef LocalGeodesicFEFunction<gridDim, DT, DeformationLocalFiniteElement, RealTuple<field_type,dim> > LocalDeformationGFEFunctionType;
+    typedef LocalGeodesicFEFunction<gridDim, DT, DisplacementLocalFiniteElement, RealTuple<field_type,dim> > LocalDeformationGFEFunctionType;
     LocalDeformationGFEFunctionType localDeformationGFEFunction(deformationLocalFiniteElement,localDeformationConfiguration);
 
     typedef LocalGeodesicFEFunction<gridDim, DT, OrientationLocalFiniteElement, Rotation<field_type,dim> > LocalOrientationGFEFunctionType;
@@ -363,20 +365,20 @@ energy(const Entity& element,
     if (not neumannFunction_)
         return energy;
 
-    for (typename Entity::LeafIntersectionIterator it = element.ileafbegin(); it != element.ileafend(); ++it) {
-
-        if (not neumannBoundary_ or not neumannBoundary_->contains(*it))
+    for (auto&& it : intersections(neumannBoundary_->gridView(),element) )
+    {
+        if (not neumannBoundary_ or not neumannBoundary_->contains(it))
             continue;
 
         const Dune::QuadratureRule<DT, gridDim-1>& quad
-            = Dune::QuadratureRules<DT, gridDim-1>::rule(it->type(), quadOrder);
+            = Dune::QuadratureRules<DT, gridDim-1>::rule(it.type(), quadOrder);
 
         for (size_t pt=0; pt<quad.size(); pt++) {
 
             // Local position of the quadrature point
-            const Dune::FieldVector<DT,gridDim>& quadPos = it->geometryInInside().global(quad[pt].position());
+            const Dune::FieldVector<DT,gridDim>& quadPos = it.geometryInInside().global(quad[pt].position());
 
-            const DT integrationElement = it->geometry().integrationElement(quad[pt].position());
+            const DT integrationElement = it.geometry().integrationElement(quad[pt].position());
 
             // The value of the local function
             RealTuple<field_type,dim> deformationValue = localDeformationGFEFunction.evaluate(quadPos);
@@ -387,7 +389,7 @@ energy(const Entity& element,
             if (dynamic_cast<const VirtualGridViewFunction<GridView,Dune::FieldVector<double,3> >*>(neumannFunction_))
                 dynamic_cast<const VirtualGridViewFunction<GridView,Dune::FieldVector<double,3> >*>(neumannFunction_)->evaluateLocal(element, quadPos, neumannValue);
             else
-                neumannFunction_->evaluate(it->geometry().global(quad[pt].position()), neumannValue);
+                neumannFunction_->evaluate(it.geometry().global(quad[pt].position()), neumannValue);
 
             // Only translational dofs are affected by the Neumann force
             for (size_t i=0; i<neumannValue.size(); i++)
@@ -400,5 +402,5 @@ energy(const Entity& element,
     return energy;
 }
 
-#endif   //#ifndef COSSERAT_ENERGY_LOCAL_STIFFNESS_HH
+#endif   //#ifndef DUNE_GFE_MIXEDCOSSERATENERGY_HH
 
diff --git a/dune/gfe/mixedgfeassembler.hh b/dune/gfe/mixedgfeassembler.hh
index cfa4bc65a44dc8988d770c8ea64199797fbee1d6..ae917ea165044c01d8a33f15d8950ae538954a9c 100644
--- a/dune/gfe/mixedgfeassembler.hh
+++ b/dune/gfe/mixedgfeassembler.hh
@@ -35,20 +35,16 @@ public:
     const Basis0 basis0_;
     const Basis1 basis1_;
 
-    MixedLocalGeodesicFEStiffness<GridView,
-                                  typename Basis0::LocalFiniteElement,
-                                  TargetSpace0,
-                                  typename Basis1::LocalFiniteElement,
-                                  TargetSpace1>* localStiffness_;
+    MixedLocalGeodesicFEStiffness<Basis0, TargetSpace0,
+                                  Basis1, TargetSpace1>* localStiffness_;
 
 public:
 
     /** \brief Constructor for a given grid */
     MixedGFEAssembler(const Basis0& basis0,
                       const Basis1& basis1,
-                      MixedLocalGeodesicFEStiffness<GridView,
-                                               typename Basis0::LocalFiniteElement, TargetSpace0,
-                                               typename Basis0::LocalFiniteElement, TargetSpace1>* localStiffness)
+                      MixedLocalGeodesicFEStiffness<Basis0, TargetSpace0,
+                                                    Basis1, TargetSpace1>* localStiffness)
         : basis0_(basis0),
           basis1_(basis1),
           localStiffness_(localStiffness)
@@ -94,50 +90,57 @@ getMatrixPattern(Dune::MatrixIndexSet& nb00,
                  Dune::MatrixIndexSet& nb10,
                  Dune::MatrixIndexSet& nb11) const
 {
-    nb00.resize(basis0_.size(), basis0_.size());
-    nb01.resize(basis0_.size(), basis1_.size());
-    nb10.resize(basis1_.size(), basis0_.size());
-    nb11.resize(basis1_.size(), basis1_.size());
+    nb00.resize(basis0_.indexSet().size(), basis0_.indexSet().size());
+    nb01.resize(basis0_.indexSet().size(), basis1_.indexSet().size());
+    nb10.resize(basis1_.indexSet().size(), basis0_.indexSet().size());
+    nb11.resize(basis1_.indexSet().size(), basis1_.indexSet().size());
+
+    // A view on the FE basis on a single element
+    typename Basis0::LocalView localView0(&basis0_);
+    typename Basis1::LocalView localView1(&basis1_);
+    auto localIndexSet0 = basis0_.indexSet().localIndexSet();
+    auto localIndexSet1 = basis1_.indexSet().localIndexSet();
 
     // Grid view must be the same for both bases
-    ElementIterator it    = basis0_.getGridView().template begin<0,Dune::Interior_Partition>();
-    ElementIterator endit = basis0_.getGridView().template end<0,Dune::Interior_Partition>  ();
+    ElementIterator it    = basis0_.gridView().template begin<0,Dune::Interior_Partition>();
+    ElementIterator endit = basis0_.gridView().template end<0,Dune::Interior_Partition>  ();
 
     for (; it!=endit; ++it) {
 
-        const typename Basis0::LocalFiniteElement& lfe0 = basis0_.getLocalFiniteElement(*it);
-        const typename Basis1::LocalFiniteElement& lfe1 = basis1_.getLocalFiniteElement(*it);
+        // Bind the local FE basis view to the current element
+        localView0.bind(*it);
+        localView1.bind(*it);
+        localIndexSet0.bind(localView0);
+        localIndexSet1.bind(localView1);
 
-        for (size_t i=0; i<lfe0.localBasis().size(); i++) {
+        for (size_t i=0; i<localView0.size(); i++) {
 
-            int iIdx = basis0_.index(*it,i);
+            int iIdx = localIndexSet0.index(i)[0];
 
-            for (size_t j=0; j<lfe0.localBasis().size(); j++) {
-                int jIdx = basis0_.index(*it,j);
+            for (size_t j=0; j<localView0.size(); j++) {
+                int jIdx = localIndexSet0.index(j)[0];
                 nb00.add(iIdx, jIdx);
             }
 
-            for (size_t j=0; j<lfe1.localBasis().size(); j++) {
-                int jIdx = basis1_.index(*it,j);
+            for (size_t j=0; j<localView1.size(); j++) {
+                int jIdx = localIndexSet1.index(j)[0];
                 nb01.add(iIdx, jIdx);
-
             }
 
         }
 
-        for (size_t i=0; i<lfe1.localBasis().size(); i++) {
+        for (size_t i=0; i<localView1.size(); i++) {
 
-            int iIdx = basis1_.index(*it,i);
+            int iIdx = localIndexSet1.index(i)[0];
 
-            for (size_t j=0; j<lfe0.localBasis().size(); j++) {
-                int jIdx = basis0_.index(*it,j);
+            for (size_t j=0; j<localView0.size(); j++) {
+                int jIdx = localIndexSet0.index(j)[0];
                 nb10.add(iIdx, jIdx);
             }
 
-            for (size_t j=0; j<lfe1.localBasis().size(); j++) {
-                int jIdx = basis1_.index(*it,j);
+            for (size_t j=0; j<localView1.size(); j++) {
+                int jIdx = localIndexSet1.index(j)[0];
                 nb11.add(iIdx, jIdx);
-
             }
 
         }
@@ -184,70 +187,82 @@ assembleGradientAndHessian(const std::vector<TargetSpace0>& configuration0,
     gradient1.resize(configuration1.size());
     gradient1 = 0;
 
-    ElementIterator it    = basis0_.getGridView().template begin<0,Dune::Interior_Partition>();
-    ElementIterator endit = basis0_.getGridView().template end<0,Dune::Interior_Partition>  ();
+    // A view on the FE basis on a single element
+    typename Basis0::LocalView localView0(&basis0_);
+    typename Basis1::LocalView localView1(&basis1_);
+    auto localIndexSet0 = basis0_.indexSet().localIndexSet();
+    auto localIndexSet1 = basis1_.indexSet().localIndexSet();
+
+    ElementIterator it    = basis0_.gridView().template begin<0,Dune::Interior_Partition>();
+    ElementIterator endit = basis0_.gridView().template end<0,Dune::Interior_Partition>  ();
 
     for( ; it != endit; ++it ) {
 
-        const int nDofs0 = basis0_.getLocalFiniteElement(*it).localBasis().size();
-        const int nDofs1 = basis1_.getLocalFiniteElement(*it).localBasis().size();
+        // Bind the local FE basis view to the current element
+        localView0.bind(*it);
+        localView1.bind(*it);
+        localIndexSet0.bind(localView0);
+        localIndexSet1.bind(localView1);
+
+        const int nDofs0 = localView0.size();
+        const int nDofs1 = localView1.size();
 
         // Extract local solution
         std::vector<TargetSpace0> localConfiguration0(nDofs0);
         std::vector<TargetSpace1> localConfiguration1(nDofs1);
 
         for (int i=0; i<nDofs0; i++)
-            localConfiguration0[i] = configuration0[basis0_.index(*it,i)];
+            localConfiguration0[i] = configuration0[localIndexSet0.index(i)[0]];
 
         for (int i=0; i<nDofs1; i++)
-            localConfiguration1[i] = configuration1[basis1_.index(*it,i)];
+            localConfiguration1[i] = configuration1[localIndexSet1.index(i)[0]];
 
         std::vector<Dune::FieldVector<double,blocksize0> > localGradient0(nDofs0);
         std::vector<Dune::FieldVector<double,blocksize1> > localGradient1(nDofs1);
 
         // setup local matrix and gradient
         localStiffness_->assembleGradientAndHessian(*it,
-                                                    basis0_.getLocalFiniteElement(*it), localConfiguration0,
-                                                    basis1_.getLocalFiniteElement(*it), localConfiguration1,
+                                                    localView0.tree().finiteElement(), localConfiguration0,
+                                                    localView1.tree().finiteElement(), localConfiguration1,
                                                     localGradient0, localGradient1);
 
         // Add element matrix to global stiffness matrix
         for (int i=0; i<nDofs0; i++) {
 
-            int row = basis0_.index(*it,i);
+            int row = localIndexSet0.index(i)[0];
 
             for (int j=0; j<nDofs0; j++ ) {
-                int col = basis0_.index(*it,j);
+                int col = localIndexSet0.index(j)[0];
                 hessian00[row][col] += localStiffness_->A00_[i][j];
             }
 
             for (int j=0; j<nDofs1; j++ ) {
-                int col = basis1_.index(*it,j);
+                int col = localIndexSet1.index(j)[0];
                 hessian01[row][col] += localStiffness_->A01_[i][j];
             }
         }
 
         for (int i=0; i<nDofs1; i++) {
 
-            int row = basis1_.index(*it,i);
+            int row = localIndexSet1.index(i)[0];
 
             for (int j=0; j<nDofs0; j++ ) {
-                int col = basis0_.index(*it,j);
+                int col = localIndexSet0.index(j)[0];
                 hessian10[row][col] += localStiffness_->A10_[i][j];
             }
 
             for (int j=0; j<nDofs1; j++ ) {
-                int col = basis1_.index(*it,j);
+                int col = localIndexSet1.index(j)[0];
                 hessian11[row][col] += localStiffness_->A11_[i][j];
             }
         }
 
         // Add local gradient to global gradient
         for (int i=0; i<nDofs0; i++)
-            gradient0[basis0_.index(*it,i)] += localGradient0[i];
+            gradient0[localIndexSet0.index(i)[0]] += localGradient0[i];
 
         for (int i=0; i<nDofs1; i++)
-            gradient1[basis1_.index(*it,i)] += localGradient1[i];
+            gradient1[localIndexSet1.index(i)[0]] += localGradient1[i];
     }
 
 }
@@ -300,34 +315,46 @@ computeEnergy(const std::vector<TargetSpace0>& configuration0,
 {
     double energy = 0;
 
-    if (configuration0.size()!=basis0_.size())
-        DUNE_THROW(Dune::Exception, "Configuration vector doesn't match the grid!");
+    if (configuration0.size()!=basis0_.indexSet().size())
+        DUNE_THROW(Dune::Exception, "Configuration vector 0 doesn't match the basis!");
+
+    if (configuration1.size()!=basis1_.indexSet().size())
+        DUNE_THROW(Dune::Exception, "Configuration vector 1 doesn't match the basis!");
 
-    if (configuration1.size()!=basis1_.size())
-        DUNE_THROW(Dune::Exception, "Configuration vector doesn't match the grid!");
+    // A view on the FE basis on a single element
+    typename Basis0::LocalView localView0(&basis0_);
+    typename Basis1::LocalView localView1(&basis1_);
+    auto localIndexSet0 = basis0_.indexSet().localIndexSet();
+    auto localIndexSet1 = basis1_.indexSet().localIndexSet();
 
-    ElementIterator it    = basis0_.getGridView().template begin<0,Dune::Interior_Partition>();
-    ElementIterator endIt = basis0_.getGridView().template end<0,Dune::Interior_Partition>();
+    ElementIterator it    = basis0_.gridView().template begin<0,Dune::Interior_Partition>();
+    ElementIterator endIt = basis0_.gridView().template end<0,Dune::Interior_Partition>();
 
     // Loop over all elements
     for (; it!=endIt; ++it) {
 
+        // Bind the local FE basis view to the current element
+        localView0.bind(*it);
+        localView1.bind(*it);
+        localIndexSet0.bind(localView0);
+        localIndexSet1.bind(localView1);
+
         // Number of degrees of freedom on this element
-        size_t nDofs0 = basis0_.getLocalFiniteElement(*it).localBasis().size();
-        size_t nDofs1 = basis1_.getLocalFiniteElement(*it).localBasis().size();
+        size_t nDofs0 = localView0.size();
+        size_t nDofs1 = localView1.size();
 
         std::vector<TargetSpace0> localConfiguration0(nDofs0);
         std::vector<TargetSpace1> localConfiguration1(nDofs1);
 
         for (size_t i=0; i<nDofs0; i++)
-            localConfiguration0[i] = configuration0[basis0_.index(*it,i)];
+            localConfiguration0[i] = configuration0[localIndexSet0.index(i)[0]];
 
         for (size_t i=0; i<nDofs1; i++)
-            localConfiguration1[i] = configuration1[basis1_.index(*it,i)];
+            localConfiguration1[i] = configuration1[localIndexSet1.index(i)[0]];
 
         energy += localStiffness_->energy(*it,
-                                          basis0_.getLocalFiniteElement(*it), localConfiguration0,
-                                          basis1_.getLocalFiniteElement(*it), localConfiguration1);
+                                          localView0.tree().finiteElement(), localConfiguration0,
+                                          localView1.tree().finiteElement(), localConfiguration1);
 
     }
 
diff --git a/dune/gfe/mixedlocalgeodesicfestiffness.hh b/dune/gfe/mixedlocalgeodesicfestiffness.hh
index 82a903570aca4624f3e9f3253f3cdbd89c8e4fea..bc0a827cb0fd8da3fe10631f800e4be5595f5f25 100644
--- a/dune/gfe/mixedlocalgeodesicfestiffness.hh
+++ b/dune/gfe/mixedlocalgeodesicfestiffness.hh
@@ -7,12 +7,17 @@
 #include <dune/istl/matrix.hh>
 
 
-template<class GridView,
-         class DeformationLocalFiniteElement, class DeformationTargetSpace,
-         class OrientationLocalFiniteElement, class OrientationTargetSpace>
+template<class DeformationBasis, class DeformationTargetSpace,
+         class OrientationBasis, class OrientationTargetSpace>
 class MixedLocalGeodesicFEStiffness
 {
+    static_assert(std::is_same<typename DeformationBasis::GridView, typename OrientationBasis::GridView>::value,
+                  "DeformationBasis and OrientationBasis must be designed on the same GridView!");
+
     // grid types
+    typedef typename DeformationBasis::LocalView::Tree::FiniteElement DeformationLocalFiniteElement;
+    typedef typename OrientationBasis::LocalView::Tree::FiniteElement OrientationLocalFiniteElement;
+    typedef typename DeformationBasis::GridView GridView;
     typedef typename GridView::Grid::ctype DT;
     typedef typename DeformationTargetSpace::ctype RT;
     typedef typename GridView::template Codim<0>::Entity Entity;
diff --git a/dune/gfe/mixedlocalgfeadolcstiffness.hh b/dune/gfe/mixedlocalgfeadolcstiffness.hh
index a40212ca6781ee9a883a50a03120b1c1f531eff5..14d92b6adf05bcab90174becfdb181970ce61c29 100644
--- a/dune/gfe/mixedlocalgfeadolcstiffness.hh
+++ b/dune/gfe/mixedlocalgfeadolcstiffness.hh
@@ -18,15 +18,19 @@
 
 /** \brief Assembles energy gradient and Hessian with ADOL-C (automatic differentiation)
  */
-template<class GridView,
-         class LocalFiniteElement0, class TargetSpace0,
-         class LocalFiniteElement1, class TargetSpace1>
+template<class Basis0, class TargetSpace0,
+         class Basis1, class TargetSpace1>
 class MixedLocalGFEADOLCStiffness
-    : public MixedLocalGeodesicFEStiffness<GridView,
-                                           LocalFiniteElement0,TargetSpace0,
-                                           LocalFiniteElement1,TargetSpace1>
+    : public MixedLocalGeodesicFEStiffness<Basis0,TargetSpace0,
+                                           Basis1,TargetSpace1>
 {
+    static_assert(std::is_same<typename Basis0::GridView, typename Basis1::GridView>::value,
+                  "Basis0 and Basis1 must be designed on the same GridView!");
+
     // grid types
+    typedef typename Basis0::GridView GridView;
+    typedef typename Basis0::LocalView::Tree::FiniteElement LocalFiniteElement0;
+    typedef typename Basis1::LocalView::Tree::FiniteElement LocalFiniteElement1;
     typedef typename GridView::Grid::ctype DT;
     typedef typename TargetSpace0::ctype RT;
     typedef typename GridView::template Codim<0>::Entity Entity;
@@ -48,9 +52,8 @@ public:
     enum { embeddedBlocksize0 = TargetSpace0::EmbeddedTangentVector::dimension };
     enum { embeddedBlocksize1 = TargetSpace1::EmbeddedTangentVector::dimension };
 
-    MixedLocalGFEADOLCStiffness(const MixedLocalGeodesicFEStiffness<GridView,
-                                                               LocalFiniteElement0, ATargetSpace0,
-                                                               LocalFiniteElement1, ATargetSpace1>* energy)
+    MixedLocalGFEADOLCStiffness(const MixedLocalGeodesicFEStiffness<Basis0, ATargetSpace0,
+                                                                    Basis1, ATargetSpace1>* energy)
     : localEnergy_(energy)
     {}
 
@@ -82,14 +85,14 @@ public:
                                             std::vector<typename TargetSpace0::TangentVector>& localGradient0,
                                             std::vector<typename TargetSpace1::TangentVector>& localGradient1);
 
-    const MixedLocalGeodesicFEStiffness<GridView, LocalFiniteElement0, ATargetSpace0, LocalFiniteElement1, ATargetSpace1>* localEnergy_;
+    const MixedLocalGeodesicFEStiffness<Basis0, ATargetSpace0, Basis1, ATargetSpace1>* localEnergy_;
 
 };
 
 
-template <class GridView, class LocalFiniteElement0, class TargetSpace0, class LocalFiniteElement1, class TargetSpace1>
-typename MixedLocalGFEADOLCStiffness<GridView, LocalFiniteElement0, TargetSpace0, LocalFiniteElement1, TargetSpace1>::RT
-MixedLocalGFEADOLCStiffness<GridView, LocalFiniteElement0, TargetSpace0, LocalFiniteElement1, TargetSpace1>::
+template <class Basis0, class TargetSpace0, class Basis1, class TargetSpace1>
+typename MixedLocalGFEADOLCStiffness<Basis0, TargetSpace0, Basis1, TargetSpace1>::RT
+MixedLocalGFEADOLCStiffness<Basis0, TargetSpace0, Basis1, TargetSpace1>::
 energy(const Entity& element,
        const LocalFiniteElement0& localFiniteElement0,
        const std::vector<TargetSpace0>& localConfiguration0,
@@ -198,8 +201,8 @@ assembleGradient(const Entity& element,
 //   To compute the Hessian we need to compute the gradient anyway, so we may
 //   as well return it.  This saves assembly time.
 // ///////////////////////////////////////////////////////////
-template <class GridType, class LocalFiniteElement0, class TargetSpace0, class LocalFiniteElement1, class TargetSpace1>
-void MixedLocalGFEADOLCStiffness<GridType, LocalFiniteElement0, TargetSpace0, LocalFiniteElement1, TargetSpace1>::
+template <class Basis0, class TargetSpace0, class Basis1, class TargetSpace1>
+void MixedLocalGFEADOLCStiffness<Basis0, TargetSpace0, Basis1, TargetSpace1>::
 assembleGradientAndHessian(const Entity& element,
                            const LocalFiniteElement0& localFiniteElement0,
                            const std::vector<TargetSpace0>& localConfiguration0,
diff --git a/dune/gfe/mixedriemanniantrsolver.cc b/dune/gfe/mixedriemanniantrsolver.cc
index 32cf12dfd46c878c5a62b697cb52a22bde327b25..b334c8a4080b161aa4d723b6939b7c8e76bdda56 100644
--- a/dune/gfe/mixedriemanniantrsolver.cc
+++ b/dune/gfe/mixedriemanniantrsolver.cc
@@ -7,17 +7,16 @@
 #include <dune/istl/io.hh>
 
 #include <dune/fufem/functionspacebases/p1nodalbasis.hh>
+#include <dune/fufem/functionspacebases/dunefunctionsbasis.hh>
 #include <dune/fufem/assemblers/operatorassembler.hh>
 #include <dune/fufem/assemblers/localassemblers/laplaceassembler.hh>
 #include <dune/fufem/assemblers/localassemblers/massassembler.hh>
+#include <dune/fufem/assemblers/basisinterpolationmatrixassembler.hh>
 
 // Using a monotone multigrid as the inner solver
 #include <dune/solvers/iterationsteps/trustregiongsstep.hh>
 #include <dune/solvers/iterationsteps/mmgstep.hh>
 #include <dune/solvers/transferoperators/truncatedcompressedmgtransfer.hh>
-#if defined THIRD_ORDER || defined SECOND_ORDER
-#include <dune/gfe/pktop1mgtransfer.hh>
-#endif
 #include <dune/solvers/transferoperators/mandelobsrestrictor.hh>
 #include <dune/solvers/solvers/iterativesolver.hh>
 #include "maxnormtrustregion.hh"
@@ -135,11 +134,16 @@ setup(const GridType& grid,
     mmgStep1->obstacleRestrictor_= new MandelObstacleRestrictor<CorrectionType1>();
     mmgStep1->verbosity_         = Solver::FULL;
 
-#if 0
     // //////////////////////////////////////////////////////////////////////////////////////
     //   Assemble a Laplace matrix to create a norm that's equivalent to the H1-norm
     // //////////////////////////////////////////////////////////////////////////////////////
+    typedef DuneFunctionsBasis<Basis0> FufemBasis0;
+    FufemBasis0 basis0(grid.leafGridView());
+
+    typedef DuneFunctionsBasis<Basis1> FufemBasis1;
+    FufemBasis1 basis1(grid.leafGridView());
 
+#if 0
     BasisType basis(grid.leafGridView());
     OperatorAssembler<BasisType,BasisType> operatorAssembler(basis, basis);
 
@@ -189,47 +193,27 @@ setup(const GridType& grid,
     mmgStep0->mgTransfer_.resize(numLevels-1);
     mmgStep1->mgTransfer_.resize(numLevels-1);
 
-    if (assembler->basis0_.getLocalFiniteElement(*grid.leafGridView().template begin<0>()).localBasis().order() > 1)
+    if (basis0.getLocalFiniteElement(*grid.leafGridView().template begin<0>()).localBasis().order() > 1)
     {
       if (numLevels>1) {
+        typedef typename TruncatedCompressedMGTransfer<CorrectionType0>::TransferOperatorType TransferOperatorType;
         P1NodalBasis<typename GridType::LeafGridView,double> p1Basis(grid_->leafGridView());
 
-        PKtoP1MGTransfer<CorrectionType0>* topTransferOp0 = new PKtoP1MGTransfer<CorrectionType0>;
-        topTransferOp0->setup(assembler->basis0_,p1Basis);
-        #if 1
-        mmgStep0->mgTransfer_.back() = topTransferOp0;
-        #else
-        // If we are on more than 1 processors, join all local transfer matrices on rank 0,
-        // and construct a single global transfer operator there.
-        typedef GlobalUniqueIndex<typename GridType::LeafGridView, gridDim> LeafP1GUIndex;
-        LeafP1GUIndex p1Index(grid_->leafGridView());
-
-        typedef typename TruncatedCompressedMGTransfer<CorrectionType>::TransferOperatorType TransferOperatorType;
-        MatrixCommunicator<GUIndex, TransferOperatorType, LeafP1GUIndex> matrixComm(*guIndex_, p1Index, 0);
-
-        mmgStep->mgTransfer_.back() = new PKtoP1MGTransfer<CorrectionType>
-        (Dune::make_shared<TransferOperatorType>(matrixComm.reduceCopy(topTransferOp->getMatrix())));
-        #endif
-        for (int i=0; i<mmgStep0->mgTransfer_.size()-1; i++){
+        TransferOperatorType pkToP1TransferMatrix;
+        assembleBasisInterpolationMatrix<TransferOperatorType,
+                                         P1NodalBasis<typename GridType::LeafGridView,double>,
+                                         FufemBasis0>(pkToP1TransferMatrix,p1Basis,assembler->basis0_);
+
+        mmgStep0->mgTransfer_.back() = new TruncatedCompressedMGTransfer<CorrectionType0>;
+        Dune::shared_ptr<TransferOperatorType> topTransferOperator = Dune::make_shared<TransferOperatorType>(pkToP1TransferMatrix);
+        dynamic_cast<TruncatedCompressedMGTransfer<CorrectionType0>*>(mmgStep0->mgTransfer_.back())->setMatrix(topTransferOperator);
+
+        for (size_t i=0; i<mmgStep0->mgTransfer_.size()-1; i++){
           // Construct the local multigrid transfer matrix
           TruncatedCompressedMGTransfer<CorrectionType0>* newTransferOp0 = new TruncatedCompressedMGTransfer<CorrectionType0>;
           newTransferOp0->setup(*grid_,i+1,i+2);
 
-          #if 1
           mmgStep0->mgTransfer_[i] = newTransferOp0;
-          #else
-          // If we are on more than 1 processors, join all local transfer matrices on rank 0,
-          // and construct a single global transfer operator there.
-          typedef GlobalUniqueIndex<typename GridType::LevelGridView, gridDim> LevelGUIndex;
-          LevelGUIndex fineGUIndex(grid_->levelGridView(i+2));
-          LevelGUIndex coarseGUIndex(grid_->levelGridView(i+1));
-
-          typedef typename TruncatedCompressedMGTransfer<CorrectionType>::TransferOperatorType TransferOperatorType;
-          MatrixCommunicator<LevelGUIndex, TransferOperatorType> matrixComm(fineGUIndex, coarseGUIndex, 0);
-
-          mmgStep->mgTransfer_[i] = new TruncatedCompressedMGTransfer<CorrectionType>
-          (Dune::make_shared<TransferOperatorType>(matrixComm.reduceCopy(newTransferOp->getMatrix())));
-          #endif
         }
 
       }
@@ -244,35 +228,27 @@ setup(const GridType& grid,
         TruncatedCompressedMGTransfer<CorrectionType0>* newTransferOp0 = new TruncatedCompressedMGTransfer<CorrectionType0>;
         newTransferOp0->setup(*grid_,i,i+1);
 
-        #if 1
         mmgStep0->mgTransfer_[i] = newTransferOp0;
-        #else
-        // If we are on more than 1 processors, join all local transfer matrices on rank 0,
-        // and construct a single global transfer operator there.
-        typedef GlobalUniqueIndex<typename GridType::LevelGridView, gridDim> LevelGUIndex;
-        LevelGUIndex fineGUIndex(grid_->levelGridView(i+1));
-        LevelGUIndex coarseGUIndex(grid_->levelGridView(i));
-
-        typedef typename TruncatedCompressedMGTransfer<CorrectionType>::TransferOperatorType TransferOperatorType;
-        MatrixCommunicator<LevelGUIndex, TransferOperatorType> matrixComm(fineGUIndex, coarseGUIndex, 0);
-
-        mmgStep->mgTransfer_[i] = new TruncatedCompressedMGTransfer<CorrectionType>
-        (Dune::make_shared<TransferOperatorType>(matrixComm.reduceCopy(newTransferOp->getMatrix())));
-        #endif
       }
 
     }
 
-    if (assembler->basis1_.getLocalFiniteElement(*grid.leafGridView().template begin<0>()).localBasis().order() > 1)
+    if (basis1.getLocalFiniteElement(*grid.leafGridView().template begin<0>()).localBasis().order() > 1)
     {
       if (numLevels>1) {
+        typedef typename TruncatedCompressedMGTransfer<CorrectionType1>::TransferOperatorType TransferOperatorType;
         P1NodalBasis<typename GridType::LeafGridView,double> p1Basis(grid_->leafGridView());
 
-        PKtoP1MGTransfer<CorrectionType1>* topTransferOp1 = new PKtoP1MGTransfer<CorrectionType1>;
-        topTransferOp1->setup(assembler->basis1_,p1Basis);
-        mmgStep1->mgTransfer_.back() = topTransferOp1;
+        TransferOperatorType pkToP1TransferMatrix;
+        assembleBasisInterpolationMatrix<TransferOperatorType,
+                                         P1NodalBasis<typename GridType::LeafGridView,double>,
+                                         FufemBasis1>(pkToP1TransferMatrix,p1Basis,assembler->basis1_);
+
+        mmgStep0->mgTransfer_.back() = new TruncatedCompressedMGTransfer<CorrectionType1>;
+        Dune::shared_ptr<TransferOperatorType> topTransferOperator = Dune::make_shared<TransferOperatorType>(pkToP1TransferMatrix);
+        dynamic_cast<TruncatedCompressedMGTransfer<CorrectionType1>*>(mmgStep1->mgTransfer_.back())->setMatrix(topTransferOperator);
 
-        for (int i=0; i<mmgStep1->mgTransfer_.size()-1; i++){
+        for (size_t i=0; i<mmgStep1->mgTransfer_.size()-1; i++){
           // Construct the local multigrid transfer matrix
           TruncatedCompressedMGTransfer<CorrectionType1>* newTransferOp1 = new TruncatedCompressedMGTransfer<CorrectionType1>;
           newTransferOp1->setup(*grid_,i+1,i+2);
@@ -303,8 +279,8 @@ setup(const GridType& grid,
       #if 0
       hasObstacle0_.resize(guIndex_->nGlobalEntity(), true);
       #else
-      hasObstacle0_.resize(assembler->basis0_.size(), true);
-      hasObstacle1_.resize(assembler->basis1_.size(), true);
+      hasObstacle0_.resize(assembler->basis0_.indexSet().size(), true);
+      hasObstacle1_.resize(assembler->basis1_.indexSet().size(), true);
       #endif
       mmgStep0->hasObstacle_ = &hasObstacle0_;
       mmgStep1->hasObstacle_ = &hasObstacle1_;
@@ -323,15 +299,9 @@ void MixedRiemannianTrustRegionSolver<GridType,Basis0,TargetSpace0,Basis1,Target
     Dune::MPIHelper& mpiHelper = Dune::MPIHelper::instance(argc,argv);
     int rank = grid_->comm().rank();
 
-    MonotoneMGStep<MatrixType00,CorrectionType0>* mgStep0 = nullptr;
-
-    // if the inner solver is a monotone multigrid set up a max-norm trust-region
-    if (dynamic_cast<LoopSolver<CorrectionType0>*>(innerSolver_.get()))
-        mgStep0 = dynamic_cast<MonotoneMGStep<MatrixType00,CorrectionType0>*>(dynamic_cast<LoopSolver<CorrectionType0>*>(innerSolver_.get())->iterationStep_);
-
     // \todo Use global index set instead of basis for parallel computations
-    MaxNormTrustRegion<blocksize0> trustRegion0(assembler_->basis0_.size(), initialTrustRegionRadius_);
-    MaxNormTrustRegion<blocksize1> trustRegion1(assembler_->basis1_.size(), initialTrustRegionRadius_);
+    MaxNormTrustRegion<blocksize0> trustRegion0(assembler_->basis0_.indexSet().size(), initialTrustRegionRadius_);
+    MaxNormTrustRegion<blocksize1> trustRegion1(assembler_->basis1_.indexSet().size(), initialTrustRegionRadius_);
 
     std::vector<BoxConstraint<field_type,blocksize0> > trustRegionObstacles0;
     std::vector<BoxConstraint<field_type,blocksize1> > trustRegionObstacles1;
@@ -607,10 +577,12 @@ void MixedRiemannianTrustRegionSolver<GridType,Basis0,TargetSpace0,Basis1,Target
         }
 
         // Output each iterate, to better understand what the algorithm does
+        DuneFunctionsBasis<Basis0> fufemBasis0(assembler_->basis0_);
+        DuneFunctionsBasis<Basis1> fufemBasis1(assembler_->basis1_);
         std::stringstream iAsAscii;
         iAsAscii << i+1;
-        CosseratVTKWriter<GridType>::template writeMixed<Basis0,Basis1>(assembler_->basis0_,x0_,
-                                                                        assembler_->basis1_,x1_,
+        CosseratVTKWriter<GridType>::template writeMixed<DuneFunctionsBasis<Basis0>, DuneFunctionsBasis<Basis1> >(fufemBasis0,x0_,
+                                                                        fufemBasis1,x1_,
                                                                         "mixed-cosserat_iterate_" + iAsAscii.str());
 
         if (rank==0)
diff --git a/dune/gfe/rodassembler.cc b/dune/gfe/rodassembler.cc
index d3c64fc2fb034aa2a012b6494b2e361c9b79a917..df3186ffb8bd759ce10b105888be5304f520c793 100644
--- a/dune/gfe/rodassembler.cc
+++ b/dune/gfe/rodassembler.cc
@@ -11,25 +11,32 @@
 
 
 
-template <class GridView>
-void RodAssembler<GridView,3>::
+template <class Basis>
+void RodAssembler<Basis,3>::
 assembleGradient(const std::vector<RigidBodyMotion<double,3> >& sol,
                  Dune::BlockVector<Dune::FieldVector<double, blocksize> >& grad) const
 {
     using namespace Dune;
 
-    if (sol.size()!=this->basis_.size())
+    if (sol.size()!=this->basis_.indexSet().size())
         DUNE_THROW(Exception, "Solution vector doesn't match the grid!");
 
     grad.resize(sol.size());
     grad = 0;
 
-    ElementIterator it    = this->basis_.getGridView().template begin<0>();
-    ElementIterator endIt = this->basis_.getGridView().template end<0>();
+    // A view on the FE basis on a single element
+    typename Basis::LocalView localView(&this->basis_);
+    auto localIndexSet = this->basis_.indexSet().localIndexSet();
+
+    ElementIterator it    = this->basis_.gridView().template begin<0>();
+    ElementIterator endIt = this->basis_.gridView().template end<0>();
 
     // Loop over all elements
     for (; it!=endIt; ++it) {
 
+        localView.bind(*it);
+        localIndexSet.bind(localView);
+
         // A 1d grid has two vertices
         static const int nDofs = 2;
 
@@ -37,19 +44,19 @@ assembleGradient(const std::vector<RigidBodyMotion<double,3> >& sol,
         std::vector<RigidBodyMotion<double,3> > localSolution(nDofs);
 
         for (int i=0; i<nDofs; i++)
-            localSolution[i] = sol[this->basis_.index(*it,i)];
+            localSolution[i] = sol[localIndexSet.index(i)[0]];
 
         // Assemble local gradient
         std::vector<FieldVector<double,blocksize> > localGradient(nDofs);
 
         this->localStiffness_->assembleGradient(*it,
-                                                this->basis_.getLocalFiniteElement(*it),
+                                                localView.tree().finiteElement(),
                                                 localSolution,
                                                 localGradient);
 
         // Add to global gradient
         for (int i=0; i<nDofs; i++)
-            grad[this->basis_.index(*it,i)] += localGradient[i];
+            grad[localIndexSet.index(i)[0]] += localGradient[i];
 
     }
 
diff --git a/dune/gfe/rodassembler.hh b/dune/gfe/rodassembler.hh
index a40dcb99e89c6280e732b0a7c04ca5b2fca68e8a..40fadb719b3b62b5a1ce215fbc6dbe412364cb22 100644
--- a/dune/gfe/rodassembler.hh
+++ b/dune/gfe/rodassembler.hh
@@ -14,7 +14,7 @@
 
 /** \brief The FEM operator for an extensible, shearable rod in 3d
  */
-template <class GridView, int spaceDim>
+template <class Basis, int spaceDim>
 class RodAssembler
 {
     static_assert(spaceDim==2 || spaceDim==3,
@@ -23,12 +23,11 @@ class RodAssembler
 
 /** \brief The FEM operator for an extensible, shearable rod in 3d
  */
-template <class GridView>
-class RodAssembler<GridView,3> : public GeodesicFEAssembler<P1NodalBasis<GridView>, RigidBodyMotion<double,3> >
+template <class Basis>
+class RodAssembler<Basis,3> : public GeodesicFEAssembler<Basis, RigidBodyMotion<double,3> >
 {
+  typedef typename Basis::GridView GridView;
 
-    //typedef typename GridType::template Codim<0>::Entity EntityType;
-    //typedef typename GridType::template Codim<0>::EntityPointer EntityPointer;
     typedef typename GridView::template Codim<0>::Iterator ElementIterator;
 
         //! Dimension of the grid.  This needs to be one!
@@ -44,18 +43,18 @@ class RodAssembler<GridView,3> : public GeodesicFEAssembler<P1NodalBasis<GridVie
 
 public:
         //! ???
-    RodAssembler(const GridView &gridView,
+    RodAssembler(const Basis& basis,
                  RodLocalStiffness<GridView,double>* localStiffness)
-        : GeodesicFEAssembler<P1NodalBasis<GridView>, RigidBodyMotion<double,3> >(gridView,localStiffness)
+        : GeodesicFEAssembler<Basis, RigidBodyMotion<double,3> >(basis,localStiffness)
         {
-            std::vector<RigidBodyMotion<double,3> > referenceConfiguration(gridView.size(gridDim));
+            std::vector<RigidBodyMotion<double,3> > referenceConfiguration(basis.indexSet().size());
 
-            typename GridView::template Codim<gridDim>::Iterator it    = gridView.template begin<gridDim>();
-            typename GridView::template Codim<gridDim>::Iterator endIt = gridView.template end<gridDim>();
+            auto it    = basis.gridView().template begin<gridDim>();
+            auto endIt = basis.gridView().template end<gridDim>();
 
             for (; it != endIt; ++it) {
 
-                int idx = gridView.indexSet().index(*it);
+                int idx = basis.gridView().indexSet().index(*it);
 
                 referenceConfiguration[idx].r[0] = 0;
                 referenceConfiguration[idx].r[1] = 0;
@@ -91,10 +90,11 @@ public:
 
 /** \brief The FEM operator for a 2D extensible, shearable rod
  */
-template <class GridView>
-class RodAssembler<GridView,2> : public GeodesicFEAssembler<P1NodalBasis<GridView>, RigidBodyMotion<double,2> >
+template <class Basis>
+class RodAssembler<Basis,2> : public GeodesicFEAssembler<Basis, RigidBodyMotion<double,2> >
 {
 
+    typedef typename Basis::GridView GridView;
     typedef typename GridView::template Codim<0>::Entity EntityType;
     typedef typename GridView::template Codim<0>::Iterator ElementIterator;
 
@@ -118,7 +118,7 @@ public:
 
     //! ???
     RodAssembler(const GridView &gridView)
-        : GeodesicFEAssembler<P1NodalBasis<GridView>, RigidBodyMotion<double,2> >(gridView,NULL)
+        : GeodesicFEAssembler<Basis, RigidBodyMotion<double,2> >(gridView,NULL)
     {
         B = 1;
         A1 = 1;
diff --git a/dune/gfe/rodlocalstiffness.hh b/dune/gfe/rodlocalstiffness.hh
index 3b03fa8057a90e073177025f1d17eec2bbb737c6..e191817aabd602df8418f56ec96dce3308ae5059 100644
--- a/dune/gfe/rodlocalstiffness.hh
+++ b/dune/gfe/rodlocalstiffness.hh
@@ -4,16 +4,15 @@
 #include <dune/common/fmatrix.hh>
 #include <dune/istl/matrix.hh>
 #include <dune/geometry/quadraturerules.hh>
-#include <dune/localfunctions/lagrange/p1.hh>
 
-#include <dune/fufem/functionspacebases/p1nodalbasis.hh>
+#include <dune/functions/functionspacebases/pqknodalbasis.hh>
 
 #include "localgeodesicfestiffness.hh"
 #include "rigidbodymotion.hh"
 
 template<class GridView, class RT>
 class RodLocalStiffness
-    : public LocalGeodesicFEStiffness<GridView, typename P1NodalBasis<GridView>::LocalFiniteElement, RigidBodyMotion<RT,3> >
+    : public LocalGeodesicFEStiffness<Dune::Functions::PQKNodalBasis<GridView,1>, RigidBodyMotion<RT,3> >
 {
     typedef RigidBodyMotion<RT,3> TargetSpace;
 
@@ -102,7 +101,7 @@ public:
                        const Dune::array<RigidBodyMotion<RT,3>, dim+1>& localSolution) const;
 
     virtual RT energy (const Entity& e,
-                       const typename P1NodalBasis<GridView>::LocalFiniteElement& localFiniteElement,
+                       const typename Dune::Functions::PQKNodalBasis<GridView,1>::LocalView::Tree::FiniteElement& localFiniteElement,
                        const std::vector<RigidBodyMotion<RT,3> >& localSolution) const
     {
         assert(localSolution.size()==2);