diff --git a/dune.module b/dune.module
index e1179a02c978bbc88772b4ba37263371a8ea2736..f42cc5b4f7cefa8b219d6bf4e9b07bb7c06f0383 100644
--- a/dune.module
+++ b/dune.module
@@ -7,5 +7,5 @@ Module: dune-solvers
 Version: 2.6-git
 Maintainer: oliver.sander@tu-dresden.de
 #depending on
-Depends: dune-common dune-grid dune-istl dune-localfunctions dune-matrix-vector
+Depends: dune-common dune-grid dune-istl dune-localfunctions dune-matrix-vector dune-functions
 Suggests: dune-alugrid
diff --git a/dune/solvers/transferoperators/compressedmultigridtransfer.hh b/dune/solvers/transferoperators/compressedmultigridtransfer.hh
index 1cdd9ebd8891da21db9062fb4ec3fc30310dde3c..44088600daab085b022ca51bb067714a8301f520 100644
--- a/dune/solvers/transferoperators/compressedmultigridtransfer.hh
+++ b/dune/solvers/transferoperators/compressedmultigridtransfer.hh
@@ -64,11 +64,12 @@ public:
      * \param grid The grid
      * \param cL The coarse grid level
      * \param fL The fine grid level
+     * \param order The order of the lagrange basis
      */
-    template <class GridType>
-    void setup(const GridType& grid, int cL, int fL)
+    template <class GridType, int k = 1>
+    void setup(const GridType& grid, int cL, int fL, std::integral_constant<int,k> order = {})
     {
-        GenericMultigridTransfer::setup<TransferOperatorType, GridType, field_type>(*matrix_, grid, cL, fL);
+        GenericMultigridTransfer::setup<TransferOperatorType, GridType, field_type>(*matrix_, grid, cL, fL, order);
     }
 
 
@@ -121,7 +122,7 @@ public:
     }
 
 
-    /** \brief Set Occupation of Galerkin restricted coarse stiffness matrix   
+    /** \brief Set Occupation of Galerkin restricted coarse stiffness matrix
     *
     * Set occupation of Galerkin restricted coarse matrix. Call this one before
     * galerkinRestrict to ensure all non-zeroes are present
@@ -195,11 +196,12 @@ public:
      * \param grid The grid
      * \param cL The coarse grid level
      * \param fL The fine grid level
+     * \param order The order of the lagrange basis
      */
-    template <class GridType>
-    void setup(const GridType& grid, int cL, int fL)
+    template <class GridType, int k = 1>
+    void setup(const GridType& grid, int cL, int fL, std::integral_constant<int,k> order = {})
     {
-        GenericMultigridTransfer::setup<TransferOperatorType, GridType, field_type>(*matrix_, grid, cL, fL);
+        GenericMultigridTransfer::setup<TransferOperatorType, GridType, field_type>(*matrix_, grid, cL, fL, order);
     }
 
 
@@ -271,7 +273,7 @@ public:
     }
 
 
-    /** \brief Set Occupation of Galerkin restricted coarse stiffness matrix   
+    /** \brief Set Occupation of Galerkin restricted coarse stiffness matrix
     *
     * Set occupation of Galerkin restricted coarse matrix. Call this one before
     * galerkinRestrict to ensure all non-zeroes are present
diff --git a/dune/solvers/transferoperators/densemultigridtransfer.hh b/dune/solvers/transferoperators/densemultigridtransfer.hh
index 994a0036eee4facee3fc5ed473439e60d22f2e43..cc85a6c015b1cd40673308e03140acb0741276d3 100644
--- a/dune/solvers/transferoperators/densemultigridtransfer.hh
+++ b/dune/solvers/transferoperators/densemultigridtransfer.hh
@@ -46,11 +46,12 @@ public:
      * \param grid The grid
      * \param cL The coarse grid level
      * \param fL The fine grid level
+     * \param order The order of the lagrange basis
      */
-    template <class GridType>
-    void setup(const GridType& grid, int cL, int fL)
+    template <class GridType, int k = 1>
+    void setup(const GridType& grid, int cL, int fL, std::integral_constant<int,k> order = {})
     {
-        GenericMultigridTransfer::setup<TransferOperatorType, GridType, field_type>(matrix_, grid, cL, fL);
+        GenericMultigridTransfer::setup<TransferOperatorType, GridType, field_type>(*matrix_, grid, cL, fL, order);
     }
 
 
@@ -103,7 +104,7 @@ public:
     }
 
 
-    /** \brief Set Occupation of Galerkin restricted coarse stiffness matrix   
+    /** \brief Set Occupation of Galerkin restricted coarse stiffness matrix
     *
     * Set occupation of Galerkin restricted coarse matrix. Call this one before
     * galerkinRestrict to ensure all non-zeroes are present
diff --git a/dune/solvers/transferoperators/genericmultigridtransfer.hh b/dune/solvers/transferoperators/genericmultigridtransfer.hh
index 64352907d7f8edab35a3507727e3b5ee78be1a8e..07031d42f20c5a8ff5f962c2f189a9a613b8d8aa 100644
--- a/dune/solvers/transferoperators/genericmultigridtransfer.hh
+++ b/dune/solvers/transferoperators/genericmultigridtransfer.hh
@@ -8,6 +8,8 @@
 #include <dune/common/fmatrix.hh>
 #include <dune/common/bitsetvector.hh>
 
+#include <dune/functions/functionspacebases/pqknodalbasis.hh>
+
 #include <dune/geometry/referenceelements.hh>
 
 #include <dune/localfunctions/lagrange/pqkfactory.hh>
@@ -23,7 +25,7 @@
  * as a BCRSMatrix.  Therefore, the template parameter DiscFuncType
  * has to comply with the ISTL requirements.
 
- * \todo Currently only works for first-order Lagrangian elements!
+ * \todo Currently only works for Lagrangian elements!
  */
 //template<class DiscFuncType, class MatrixBlock, class TransferOperatorType>
 class GenericMultigridTransfer {
@@ -63,27 +65,46 @@ public:
     }
 
 
-    template<class TransferOperatorType, class GridType, class field_type>
-    static void setup(TransferOperatorType& matrix, const GridType& grid, int cL, int fL)
+     /** \brief Set up transfer operator between two directly connected grid levels of the same grid
+
+       The 'fine' grid level (fL) is expected to be the first refinement of the 'coarse' one (cL).
+
+       \param matrix The matrix object to assemble into
+       \param grid The hierarchial grid
+       \param cL Coarse level
+       \param fL Fine level ( = cL+1 )
+       \tparam k compile time parameter: order of the larange basis
+     */
+    template<class TransferOperatorType, class GridType, class field_type, int k = 1>
+    static void setup(TransferOperatorType& matrix, const GridType& grid, int cL, int fL, std::integral_constant<int,k> = {})
     {
-        typedef typename TransferOperatorType::block_type TransferMatrixBlock;
-        typedef typename GridType::ctype ctype;
+        using TransferMatrixBlock = typename TransferOperatorType::block_type;
+        using ctype = typename GridType::ctype;
 
         if (fL != cL+1)
             DUNE_THROW(Dune::Exception, "The two function spaces don't belong to consecutive levels!");
 
         const int dim = GridType::dimension;
 
-        const typename GridType::Traits::LevelIndexSet& coarseIndexSet = grid.levelIndexSet(cL);
-        const typename GridType::Traits::LevelIndexSet& fineIndexSet   = grid.levelIndexSet(fL);
+        const auto& coarseIndexSet = grid.levelIndexSet(cL);
+        const auto& fineIndexSet   = grid.levelIndexSet(fL);
 
-        int rows = grid.size(fL, dim);
-        int cols = grid.size(cL, dim);
+        const auto& coarseLevelGridView = grid.levelGridView(cL);
+        const auto& fineLevelGridView    = grid.levelGridView(fL);
+
+        // construct a global basis to determine the size of the transfer matrix
+        Dune::Functions::PQkNodalBasis< typename GridType::LevelGridView, k> coarseBasis(coarseLevelGridView);
+        Dune::Functions::PQkNodalBasis< typename GridType::LevelGridView, k> fineBasis(fineLevelGridView);
+
+        const int rows = fineBasis.size();
+        const int cols = coarseBasis.size();
 
         // A factory for the shape functions
-        typedef typename Dune::PQkLocalFiniteElementCache<ctype, field_type, dim, 1> P1FECache;
-        typedef typename P1FECache::FiniteElementType FEType;
-        P1FECache p1FECache;
+        using PkFECache = typename Dune::PQkLocalFiniteElementCache<ctype, field_type, dim, k>;
+        PkFECache pkFECache;
+
+        // minimal value to be determined in the support
+        double tol = 0.001;
 
         matrix.setSize(rows,cols);
         matrix.setBuildMode(TransferOperatorType::random);
@@ -95,11 +116,8 @@ public:
 
         for (const auto& cIt : elements(grid.levelGridView(cL))) {
 
-            typedef typename GridType::template Codim<0>::Entity EntityType;
-
             // Get local finite element
-            const FEType& coarseBaseSet = p1FECache.get(cIt.type());
-
+            const auto& coarseBaseSet = pkFECache.get(cIt.type());
             const size_t numCoarseBaseFct = coarseBaseSet.localBasis().size();
 
             // preallocate vector for function evaluations
@@ -111,18 +129,15 @@ public:
                     continue;
 
                 const auto& fineRefElement = Dune::ReferenceElements<ctype, dim>::general(fIt.type());
-
-                const typename EntityType::LocalGeometry& fGeometryInFather = fIt.geometryInFather();
+                const auto& fGeometryInFather = fIt.geometryInFather();
 
                 // Get local finite element
-                const FEType& fineBaseSet = p1FECache.get(fIt.type());
-
+                const auto& fineBaseSet = pkFECache.get(fIt.type());
                 const size_t numFineBaseFct = fineBaseSet.localBasis().size();
 
-
                 for (size_t j=0; j<numFineBaseFct; j++)
                 {
-                    const Dune::LocalKey& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
+                    const auto& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
 
                     int globalFine = fineIndexSet.subIndex(fIt, jLocalKey.subEntity(), jLocalKey.codim());
 
@@ -134,17 +149,15 @@ public:
 
                     for (size_t i=0; i<numCoarseBaseFct; i++)
                     {
-                        if (values[i] > 0.001)
+                        if (values[i] > tol)
                         {
-                            const Dune::LocalKey& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
+                            const auto& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
                             int globalCoarse = coarseIndexSet.subIndex(cIt, iLocalKey.subEntity(), iLocalKey.codim());
                             indices.add(globalFine, globalCoarse);
                         }
                     }
                 }
-
             }
-
         }
 
         indices.exportIdx(matrix);
@@ -156,12 +169,9 @@ public:
         for (const auto& cIt : elements(grid.levelGridView(cL))) {
 
             // Get local finite element
-            const FEType& coarseBaseSet = p1FECache.get(cIt.type());
-
+            const auto& coarseBaseSet = pkFECache.get(cIt.type());
             const size_t numCoarseBaseFct = coarseBaseSet.localBasis().size();
 
-            typedef typename GridType::template Codim<0>::Entity EntityType;
-
             // preallocate vector for function evaluations
             std::vector<Dune::FieldVector<field_type,1> > values(numCoarseBaseFct);
 
@@ -171,18 +181,15 @@ public:
                     continue;
 
                 const auto& fineRefElement = Dune::ReferenceElements<ctype, dim>::general(fIt.type());
-
-                const typename EntityType::LocalGeometry& fGeometryInFather = fIt.geometryInFather();
+                const auto& fGeometryInFather = fIt.geometryInFather();
 
                 // Get local finite element
-                const FEType& fineBaseSet = p1FECache.get(fIt.type());
-
+                const auto& fineBaseSet = pkFECache.get(fIt.type());
                 const size_t numFineBaseFct = fineBaseSet.localBasis().size();
 
                 for (size_t j=0; j<numFineBaseFct; j++)
                 {
-                    const Dune::LocalKey& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
-
+                    const auto& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
                     int globalFine = fineIndexSet.subIndex(fIt, jLocalKey.subEntity(), jLocalKey.codim());
 
                     Dune::FieldVector<ctype, dim> fineBasePosition = fineRefElement.position(jLocalKey.subEntity(), jLocalKey.codim());
@@ -193,11 +200,10 @@ public:
 
                     for (size_t i=0; i<numCoarseBaseFct; i++)
                     {
-                        if (values[i] > 0.001)
+                        if (values[i] > tol)
                         {
-                            const Dune::LocalKey& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
+                            const auto& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
                             int globalCoarse = coarseIndexSet.subIndex(cIt, iLocalKey.subEntity(), iLocalKey.codim());
-
                             matrix[globalFine][globalCoarse] = Dune::ScaledIdentityMatrix<ctype,TransferMatrixBlock::rows>(values[i]);
                         }
                     }
@@ -212,25 +218,34 @@ public:
        The 'fine' grid view gvFine is expected to be a refinement of the 'coarse' one gvCoarse.
 
        \param matrix The matrix object to assemble into
+       \param gvCoarse The coarse grid
+       \param gvFine The fine grid level
+       \tparam k compile time parameter: order of the larange basis
      */
-    template<class TransferOperatorType, class GridViewCoarse, class GridViewFine, class field_type>
-    static void setup(TransferOperatorType& matrix, const GridViewCoarse& gvCoarse, const GridViewFine& gvFine)
+    template<class TransferOperatorType, class GridViewCoarse, class GridViewFine, class field_type, int k = 1>
+    static void setup(TransferOperatorType& matrix, const GridViewCoarse& gvCoarse, const GridViewFine& gvFine, std::integral_constant<int,k> = {})
     {
-        typedef typename TransferOperatorType::block_type TransferMatrixBlock;
-        typedef typename GridViewCoarse::ctype ctype;
+        using TransferMatrixBlock = typename TransferOperatorType::block_type;
+        using ctype = typename GridViewCoarse::ctype;
 
         const int dim = GridViewCoarse::dimension;
 
-        const typename GridViewCoarse::IndexSet& coarseIndexSet = gvCoarse.indexSet();
-        const typename GridViewFine::IndexSet&   fineIndexSet   = gvFine.indexSet();
+        const auto& coarseIndexSet = gvCoarse.indexSet();
+        const auto&   fineIndexSet = gvFine.indexSet();
 
-        int rows = gvFine.size(dim);
-        int cols = gvCoarse.size(dim);
+        // construct a global basis to determine the size of the transfer matrix
+        Dune::Functions::PQkNodalBasis< GridViewCoarse, k> coarseBasis(gvCoarse);
+        Dune::Functions::PQkNodalBasis< GridViewFine  , k> fineBasis(gvFine);
+
+        const int rows = fineBasis.size();
+        const int cols = coarseBasis.size();
 
         // A factory for the shape functions
-        typedef typename Dune::PQkLocalFiniteElementCache<ctype, field_type, dim, 1> P1FECache;
-        typedef typename P1FECache::FiniteElementType FEType;
-        P1FECache p1FECache;
+        using PkFECache = typename Dune::PQkLocalFiniteElementCache<ctype, field_type, dim, k>;
+        PkFECache pkFECache;
+
+        // minimal value to be determined in the support
+        double tol = 0.001;
 
         matrix.setSize(rows,cols);
         matrix.setBuildMode(TransferOperatorType::random);
@@ -246,8 +261,7 @@ public:
             const auto& fineRefElement = Dune::ReferenceElements<ctype, dim>::general(fIt.type());
 
             // Get local finite element
-            const FEType& fineBaseSet = p1FECache.get(fIt.type());;
-
+            const auto& fineBaseSet = pkFECache.get(fIt.type());;
             const size_t numFineBaseFct = fineBaseSet.localBasis().size();
 
             std::vector<Dune::FieldVector<ctype,dim> > local(numFineBaseFct);
@@ -264,7 +278,6 @@ public:
             while (not gvCoarse.contains(ancestor) && ancestor.level() != 0 ) {
 
                 auto geometryInFather = ancestor.geometryInFather();
-
                 for (size_t i=0; i<numFineBaseFct; i++)
                     local[i] = geometryInFather.global(local[i]);
                 ancestor = ancestor.father();
@@ -276,8 +289,7 @@ public:
             for (size_t j=0; j<numFineBaseFct; j++)
             {
                 // Get local finite element
-                const FEType& coarseBaseSet = p1FECache.get(ancestor.type());
-
+                const auto& coarseBaseSet = pkFECache.get(ancestor.type());
                 const size_t numCoarseBaseFct = coarseBaseSet.localBasis().size();
 
                 // preallocate vector for function evaluations
@@ -291,15 +303,14 @@ public:
 
                 for (size_t i=0; i<numCoarseBaseFct; i++)
                 {
-                    if (values[i] > 0.001)
+                    if (values[i] > tol)
                     {
-                        const Dune::LocalKey& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
+                        const auto& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
                         int globalCoarse = coarseIndexSet.subIndex(ancestor, iLocalKey.subEntity(), iLocalKey.codim());
                         indices.add(globalFine, globalCoarse);
                     }
                 }
             }
-
         }
 
         indices.exportIdx(matrix);
@@ -309,19 +320,17 @@ public:
         // /////////////////////////////////////////////
         for (const auto& fIt : elements(gvFine)) {
 
-
             const auto& fineRefElement = Dune::ReferenceElements<ctype, dim>::general(fIt.type());
 
             // Get local finite element
-            const FEType& fineBaseSet = p1FECache.get(fIt.type());;
-
+            const auto& fineBaseSet = pkFECache.get(fIt.type());;
             const size_t numFineBaseFct = fineBaseSet.localBasis().size();
 
             std::vector<Dune::FieldVector<ctype,dim> > local(numFineBaseFct);
 
             for (size_t i=0; i<numFineBaseFct; i++)
             {
-                const Dune::LocalKey& iLocalKey = fineBaseSet.localCoefficients().localKey(i);
+                const auto& iLocalKey = fineBaseSet.localCoefficients().localKey(i);
                 local[i] = fineRefElement.position(iLocalKey.subEntity(), iLocalKey.codim());
             }
 
@@ -343,8 +352,7 @@ public:
             for (size_t j=0; j<numFineBaseFct; j++)
             {
                 // Get local finite element
-                const FEType& coarseBaseSet = p1FECache.get(ancestor.type());
-
+                const auto& coarseBaseSet = pkFECache.get(ancestor.type());
                 const size_t numCoarseBaseFct = coarseBaseSet.localBasis().size();
 
                 // preallocate vector for function evaluations
@@ -353,16 +361,15 @@ public:
                 // Evaluate coarse grid base functions
                 coarseBaseSet.localBasis().evaluateFunction(local[j], values);
 
-                const Dune::LocalKey& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
+                const auto& jLocalKey = fineBaseSet.localCoefficients().localKey(j);
                 int globalFine = fineIndexSet.subIndex(fIt, jLocalKey.subEntity(), jLocalKey.codim());
 
                 for (size_t i=0; i<numCoarseBaseFct; i++)
                 {
-                    if (values[i] > 0.001)
+                    if (values[i] > tol)
                     {
-                        const Dune::LocalKey& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
+                        const auto& iLocalKey = coarseBaseSet.localCoefficients().localKey(i);
                         int globalCoarse = coarseIndexSet.subIndex(ancestor, iLocalKey.subEntity(), iLocalKey.codim());
-
                         matrix[globalFine][globalCoarse] = Dune::ScaledIdentityMatrix<ctype,TransferMatrixBlock::rows>(values[i]);
                     }
                 }