diff --git a/src/05-poisson-problem.cc b/src/05-poisson-problem.cc
index 23baf461bc04a1657844c90375df02b0ff362e22..0dc6d8cb39e95df528284511b2db978426ed257b 100644
--- a/src/05-poisson-problem.cc
+++ b/src/05-poisson-problem.cc
@@ -41,200 +41,9 @@
 #include <dune/fu-tutorial/referenceelementutility.hh>
 
 
-
-template<class Grid>
-auto createCubeGrid()
-{
-  static const int dim = Grid::dimension;
-
-  auto lowerLeft = Dune::FieldVector<double,dim>(0);
-  auto upperRight = Dune::FieldVector<double,dim>(1);
-  auto elementsPerDirection = std::array<unsigned int,dim>();
-  for(auto& e : elementsPerDirection)
-    e = 2;
-
-  return Dune::StructuredGridFactory<Grid>::createCubeGrid(lowerLeft, upperRight, elementsPerDirection);
-}
-
-template<class Grid>
-auto createSimplexGrid()
-{
-  static const int dim = Grid::dimension;
-
-  auto lowerLeft = Dune::FieldVector<double,dim>(0);
-  auto upperRight = Dune::FieldVector<double,dim>(1);
-  auto elementsPerDirection = std::array<unsigned int,dim>();
-  for(auto& e : elementsPerDirection)
-    e = 2;
-
-  return Dune::StructuredGridFactory<Grid>::createSimplexGrid(lowerLeft, upperRight, elementsPerDirection);
-}
-
-
-template<class GridView>
-void writeGridView(const GridView& gridView, std::string postFix)
-{
-  Dune::VTKWriter<GridView> vtkWriter(gridView);
-  vtkWriter.write(std::string("04-gridviews-")+postFix);
-}
-
-
-
-// Compute local per element matrix
-template <class Element, class LocalFiniteElement, class MatrixType>
-void assembleLocalStiffnessMatrix(const Element& element, const LocalFiniteElement& localFiniteElement, MatrixType& elementMatrix)
-{
-  auto geometryType = element.type();
-  const auto& geometry = element.geometry();
-  const int dim = Element::dimension;
-  std::size_t localSize = localFiniteElement.localBasis().size();
-
-  // Resize and initialize matrix
-  elementMatrix.setSize(localSize, localSize);
-  elementMatrix = 0;      // fills the entire matrix with zeroes
-
-  // Get a quadrature rule
-  int order = 2*(dim*localFiniteElement.localBasis().order()-1);
-  const auto& quad = Dune::template QuadratureRules<double, dim>::rule(geometryType, order);
-
-  // Loop over all quadrature points
-  for (size_t k=0; k < quad.size(); ++k)
-  {
-    const auto& quadPos = quad[k].position();
-    const auto& weight = quad[k].weight();
-
-    // The transposed inverse Jacobian of the map from the reference element to the element
-    const auto& jacobian = geometry.jacobianInverseTransposed(quadPos);
-
-    // The multiplicative factor in the integral transformation formula
-    const auto& integrationElement = geometry.integrationElement(quadPos);
-
-    // The gradients of the shape functions on the reference element
-    std::vector<Dune::FieldMatrix<double,1,dim> > referenceGradients;
-    localFiniteElement.localBasis().evaluateJacobian(quadPos, referenceGradients);
-
-    // Compute the shape function gradients on the real basis functions
-    std::vector<Dune::FieldVector<double,dim> > gradients(referenceGradients.size());
-    for (size_t i=0; i<gradients.size(); i++)
-      jacobian.mv(referenceGradients[i][0], gradients[i]);
-
-    // Compute the actual matrix entries
-    for (size_t i=0; i<elementMatrix.N(); i++)
-      for (size_t j=0; j<elementMatrix.M(); j++ )
-        elementMatrix[i][j] += ( gradients[i] * gradients[j] ) * weight * integrationElement;
-  }
-}
-
-
-
-// Compute local per element right hand side
-template <class Element, class LocalFiniteElement, class LocalRHSVector, class RHSFunction>
-void assembleLocalRHS(
-  const Element& element,
-  const LocalFiniteElement& localFiniteElement,
-  LocalRHSVector& localRhs,
-  const RHSFunction& rhsFunction)
-{
-  auto geometryType = element.type();
-  const auto& geometry = element.geometry();
-  const int dim = Element::dimension;
-  std::size_t localSize = localFiniteElement.localBasis().size();
-
-  // Resize and initialize vector
-  localRhs.resize(localSize);
-  localRhs = 0;
-
-  // Get a quadrature rule
-  int order = 2*(dim*localFiniteElement.localBasis().order());
-  const auto& quad = Dune::template QuadratureRules<double, dim>::rule(geometryType, order);
-
-  // Loop over all quadrature points
-  for (size_t k=0; k < quad.size(); ++k)
-  {
-    const auto& quadPos = quad[k].position();
-    const auto& weight = quad[k].weight();
-
-    // Quadrature position in global world coordinates
-    const auto& globalQuadPos = geometry.global(quadPos);
-
-    // The multiplicative factor in the integral transformation formula
-    const auto& integrationElement = geometry.integrationElement(quadPos);
-
-    double functionValue = rhsFunction(globalQuadPos);
-
-    // Evaluate all shape function values at this point
-    std::vector<Dune::FieldVector<double,1> > shapeFunctionValues;
-    localFiniteElement.localBasis().evaluateFunction(quadPos, shapeFunctionValues);
-
-    // Actually compute the vector entries
-    for (size_t i=0; i<localSize; i++)
-      localRhs[i] += shapeFunctionValues[i] * functionValue * weight * integrationElement;
-  }
-}
-
-
-template<class GridView, class RHSFunction>
-void assemblePoissonProblem(
-    const GridView& gridView,
-    Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1>>& matrix,
-    Dune::BlockVector<Dune::FieldVector<double,1>>& rhs,
-    const RHSFunction& rhsFunction)
-{
-  static const int dim = GridView::dimension;
-  const auto& indexSet = gridView.indexSet();
-  std::size_t size = indexSet.size(dim);
-
-  using Matrix = Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1>>;
-  using ElementMatrix = Dune::Matrix<Dune::FieldMatrix<double,1,1>>;
-  using ElementRhs = Dune::BlockVector<Dune::FieldVector<double,1>>;
-
-  rhs.resize(size);
-  rhs = 0;
-  Dune::ImplicitMatrixBuilder<Matrix> matrixBuilder(matrix, size, size, 10, 0.1);
-
-  Dune::PQkLocalFiniteElementCache<double, double, dim, 1> feCache;
-
-  ElementMatrix elementMatrix;
-  ElementRhs elementRhs;
-
-  for(const auto& e: Dune::elements(gridView))
-  {
-    const auto& localFiniteElement = feCache.get(e.type());
-    std::size_t localSize = localFiniteElement.localBasis().size();
-
-    assembleLocalStiffnessMatrix(e, localFiniteElement, elementMatrix);
-    assembleLocalRHS(e, localFiniteElement, elementRhs, rhsFunction);
-
-    for(std::size_t i=0; i<localSize; ++i)
-    {
-      std::size_t globalI = indexSet.subIndex(e, localFiniteElement.localCoefficients().localKey(i).subEntity(), dim);
-      for(std::size_t j=0; j<localSize; ++j)
-      {
-        std::size_t globalJ = indexSet.subIndex(e, localFiniteElement.localCoefficients().localKey(j).subEntity(), dim);
-        matrixBuilder[globalI][globalJ] += elementMatrix[i][j];
-      }
-
-      rhs[globalI] = elementRhs[i];
-    }
-  }
-  matrix.compress();
-}
-
-
-
-template<class GridView, class BitVector>
-void computeBoundaryVertices(const GridView& gridView, BitVector& isBoundary)
-{
-  using namespace Dune;
-  using namespace Dune::FuTutorial;
-
-  const auto& indexSet = gridView.indexSet();
-  for(const auto& element: elements(gridView))
-    for(const auto& intersection: intersections(gridView, element))
-      if (intersection.boundary())
-        for(const auto& vertex: subVertices(referenceElement(element), insideFacet(intersection)))
-          isBoundary[subIndex(indexSet, element, vertex)] = true;
-}
+// included dune-fu-tutorial headers
+#include "04-gridviews.hh"
+#include "05-poisson-problem.hh"
 
 
 
diff --git a/src/05-poisson-problem.hh b/src/05-poisson-problem.hh
new file mode 100644
index 0000000000000000000000000000000000000000..5d8d6129157d65ab1a4de7c76a43eda9ac1b16b2
--- /dev/null
+++ b/src/05-poisson-problem.hh
@@ -0,0 +1,197 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_FUTUTORIAL_SRC_05POISSON_PROBLEM_HH
+#define DUNE_FUTUTORIAL_SRC_05POISSON_PROBLEM_HH
+
+// included standard library headers
+#include <iostream>
+#include <array>
+
+// included dune-common headers
+#include <dune/common/parallel/mpihelper.hh>
+#include <dune/common/exceptions.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/stringutility.hh>
+
+// included dune-geometry headers
+#include <dune/geometry/quadraturerules.hh>
+
+// included dune-grid headers
+#include <dune/grid/yaspgrid.hh>
+#include <dune/grid/uggrid.hh>
+
+// included dune-istl headers
+#include <dune/istl/matrix.hh>
+#include <dune/istl/bcrsmatrix.hh>
+#include <dune/istl/bvector.hh>
+#include <dune/istl/preconditioners.hh>
+#include <dune/istl/solvers.hh>
+
+
+// included dune-localfunctions headers
+#include <dune/localfunctions/lagrange/pqkfactory.hh>
+
+// included dune-fu-tutorial headers
+#include <dune/fu-tutorial/referenceelementutility.hh>
+
+
+
+// Compute local per element matrix
+template <class Element, class LocalFiniteElement, class MatrixType>
+void assembleLocalStiffnessMatrix(const Element& element, const LocalFiniteElement& localFiniteElement, MatrixType& elementMatrix)
+{
+  auto geometryType = element.type();
+  const auto& geometry = element.geometry();
+  const int dim = Element::dimension;
+  std::size_t localSize = localFiniteElement.localBasis().size();
+
+  // Resize and initialize matrix
+  elementMatrix.setSize(localSize, localSize);
+  elementMatrix = 0;      // fills the entire matrix with zeroes
+
+  // Get a quadrature rule
+  int order = 2*(dim*localFiniteElement.localBasis().order()-1);
+  const auto& quad = Dune::template QuadratureRules<double, dim>::rule(geometryType, order);
+
+  // Loop over all quadrature points
+  for (size_t k=0; k < quad.size(); ++k)
+  {
+    const auto& quadPos = quad[k].position();
+    const auto& weight = quad[k].weight();
+
+    // The transposed inverse Jacobian of the map from the reference element to the element
+    const auto& jacobian = geometry.jacobianInverseTransposed(quadPos);
+
+    // The multiplicative factor in the integral transformation formula
+    const auto& integrationElement = geometry.integrationElement(quadPos);
+
+    // The gradients of the shape functions on the reference element
+    std::vector<Dune::FieldMatrix<double,1,dim> > referenceGradients;
+    localFiniteElement.localBasis().evaluateJacobian(quadPos, referenceGradients);
+
+    // Compute the shape function gradients on the real basis functions
+    std::vector<Dune::FieldVector<double,dim> > gradients(referenceGradients.size());
+    for (size_t i=0; i<gradients.size(); i++)
+      jacobian.mv(referenceGradients[i][0], gradients[i]);
+
+    // Compute the actual matrix entries
+    for (size_t i=0; i<elementMatrix.N(); i++)
+      for (size_t j=0; j<elementMatrix.M(); j++ )
+        elementMatrix[i][j] += ( gradients[i] * gradients[j] ) * weight * integrationElement;
+  }
+}
+
+
+
+// Compute local per element right hand side
+template <class Element, class LocalFiniteElement, class LocalRHSVector, class RHSFunction>
+void assembleLocalRHS(
+  const Element& element,
+  const LocalFiniteElement& localFiniteElement,
+  LocalRHSVector& localRhs,
+  const RHSFunction& rhsFunction)
+{
+  auto geometryType = element.type();
+  const auto& geometry = element.geometry();
+  const int dim = Element::dimension;
+  std::size_t localSize = localFiniteElement.localBasis().size();
+
+  // Resize and initialize vector
+  localRhs.resize(localSize);
+  localRhs = 0;
+
+  // Get a quadrature rule
+  int order = 2*(dim*localFiniteElement.localBasis().order());
+  const auto& quad = Dune::template QuadratureRules<double, dim>::rule(geometryType, order);
+
+  // Loop over all quadrature points
+  for (size_t k=0; k < quad.size(); ++k)
+  {
+    const auto& quadPos = quad[k].position();
+    const auto& weight = quad[k].weight();
+
+    // Quadrature position in global world coordinates
+    const auto& globalQuadPos = geometry.global(quadPos);
+
+    // The multiplicative factor in the integral transformation formula
+    const auto& integrationElement = geometry.integrationElement(quadPos);
+
+    double functionValue = rhsFunction(globalQuadPos);
+
+    // Evaluate all shape function values at this point
+    std::vector<Dune::FieldVector<double,1> > shapeFunctionValues;
+    localFiniteElement.localBasis().evaluateFunction(quadPos, shapeFunctionValues);
+
+    // Actually compute the vector entries
+    for (size_t i=0; i<localSize; i++)
+      localRhs[i] += shapeFunctionValues[i] * functionValue * weight * integrationElement;
+  }
+}
+
+
+template<class GridView, class RHSFunction>
+void assemblePoissonProblem(
+    const GridView& gridView,
+    Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1>>& matrix,
+    Dune::BlockVector<Dune::FieldVector<double,1>>& rhs,
+    const RHSFunction& rhsFunction)
+{
+  static const int dim = GridView::dimension;
+  const auto& indexSet = gridView.indexSet();
+  std::size_t size = indexSet.size(dim);
+
+  using Matrix = Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1>>;
+  using ElementMatrix = Dune::Matrix<Dune::FieldMatrix<double,1,1>>;
+  using ElementRhs = Dune::BlockVector<Dune::FieldVector<double,1>>;
+
+  rhs.resize(size);
+  rhs = 0;
+  Dune::ImplicitMatrixBuilder<Matrix> matrixBuilder(matrix, size, size, 10, 0.1);
+
+  Dune::PQkLocalFiniteElementCache<double, double, dim, 1> feCache;
+
+  ElementMatrix elementMatrix;
+  ElementRhs elementRhs;
+
+  for(const auto& e: Dune::elements(gridView))
+  {
+    const auto& localFiniteElement = feCache.get(e.type());
+    std::size_t localSize = localFiniteElement.localBasis().size();
+
+    assembleLocalStiffnessMatrix(e, localFiniteElement, elementMatrix);
+    assembleLocalRHS(e, localFiniteElement, elementRhs, rhsFunction);
+
+    for(std::size_t i=0; i<localSize; ++i)
+    {
+      std::size_t globalI = indexSet.subIndex(e, localFiniteElement.localCoefficients().localKey(i).subEntity(), dim);
+      for(std::size_t j=0; j<localSize; ++j)
+      {
+        std::size_t globalJ = indexSet.subIndex(e, localFiniteElement.localCoefficients().localKey(j).subEntity(), dim);
+        matrixBuilder[globalI][globalJ] += elementMatrix[i][j];
+      }
+
+      rhs[globalI] = elementRhs[i];
+    }
+  }
+  matrix.compress();
+}
+
+
+
+template<class GridView, class BitVector>
+void computeBoundaryVertices(const GridView& gridView, BitVector& isBoundary)
+{
+  using namespace Dune;
+  using namespace Dune::FuTutorial;
+
+  const auto& indexSet = gridView.indexSet();
+  for(const auto& element: elements(gridView))
+    for(const auto& intersection: intersections(gridView, element))
+      if (intersection.boundary())
+        for(const auto& vertex: subVertices(referenceElement(element), insideFacet(intersection)))
+          isBoundary[subIndex(indexSet, element, vertex)] = true;
+}
+
+
+
+#endif // DUNE_FUTUTORIAL_SRC_05POISSON_PROBLEM_HH