diff --git a/dune/solvers/test/Makefile.am b/dune/solvers/test/Makefile.am
index 2e23ad000fb1edc8d382c400d10d92156690f02f..3b8b4eaf102fdb6a56e073b87875f545e1477788 100644
--- a/dune/solvers/test/Makefile.am
+++ b/dune/solvers/test/Makefile.am
@@ -2,12 +2,13 @@
 # list of tests to run
 TESTS = lowrankoperatortest \
         nulloperatortest \
-        sumoperatortest
+        sumoperatortest \
+        obstacletnnmgtest
 
 # programs just to build when "make check" is used
 check_PROGRAMS = $(TESTS)
 
-noinst_HEADERS =
+noinst_HEADERS = common.hh
 
 # collect some common flags
 COMMON_CPPFLAGS = $(AM_CPPFLAGS) $(DUNEMPICPPFLAGS) -I$(top_srcdir)
@@ -35,4 +36,9 @@ sumoperatortest_CPPFLAGS = $(COMMON_CPPFLAGS) $(GRID_CPPFLAGS)
 sumoperatortest_LDADD = $(COMMON_LDADD) $(GRID_LDADD)
 sumoperatortest_LDFLAGS = $(COMMON_LDFLAGS) $(GRID_LDFLAGS)
 
+obstacletnnmgtest_SOURCES = obstacletnnmgtest.cc
+obstacletnnmgtest_CPPFLAGS = $(COMMON_CPPFLAGS) $(GRID_CPPFLAGS)
+obstacletnnmgtest_LDADD = $(COMMON_LDADD) $(GRID_LDADD)
+obstacletnnmgtest_LDFLAGS = $(COMMON_LDFLAGS) $(GRID_LDFLAGS)
+
 include $(top_srcdir)/am/global-rules
diff --git a/dune/solvers/test/common.hh b/dune/solvers/test/common.hh
new file mode 100644
index 0000000000000000000000000000000000000000..7b68d5fbc1e9f341d9ac746e0572a01e1a4dddc5
--- /dev/null
+++ b/dune/solvers/test/common.hh
@@ -0,0 +1,345 @@
+#ifndef DUNE_SOLVERS_TESTS_COMMON_HH
+#define DUNE_SOLVERS_TESTS_COMMON_HH
+
+
+#include <dune/common/fvector.hh>
+#include <dune/common/fmatrix.hh>
+
+#include <dune/istl/matrixindexset.hh>
+
+#include <dune/geometry/quadraturerules.hh>
+
+#include <dune/localfunctions/lagrange/pqkfactory.hh>
+
+
+template<class GridView, class Matrix>
+void constructPQ1Pattern(const GridView& gridView, Matrix& matrix)
+{
+    static const int dim = GridView::Grid::dimension;
+
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename Dune::PQkLocalFiniteElementCache<double, double, dim, 1> FiniteElementCache;
+    typedef typename FiniteElementCache::FiniteElementType FiniteElement;
+
+    const IndexSet& indexSet = gridView.indexSet();
+    FiniteElementCache cache;
+
+    int size = indexSet.size(dim);
+
+    Dune::MatrixIndexSet indices(size, size);
+
+    ElementIterator it = gridView.template begin<0>();
+    ElementIterator end = gridView.template end<0>();
+    for (; it != end; ++it)
+    {
+        Element& e = *it;
+        const FiniteElement& fe = cache.get(e.type());
+
+        int localSize = fe.localBasis().size();
+        for (int i = 0; i < localSize; ++i)
+        {
+            int iGlobal = indexSet.subIndex(e, fe.localCoefficients().localKey(i).subEntity(), dim);
+            for (int j = 0; j < localSize; ++j)
+            {
+                int jGlobal = indexSet.subIndex(e, fe.localCoefficients().localKey(j).subEntity(), dim);
+                indices.add(iGlobal, jGlobal);
+                indices.add(jGlobal, iGlobal);
+            }
+        }
+    }
+    indices.exportIdx(matrix);
+}
+
+
+template<class GridView, class Matrix>
+void assemblePQ1Stiffness(const GridView& gridView, Matrix& matrix)
+{
+    static const int dim = GridView::Grid::dimension;
+    static const int dimworld = GridView::Grid::dimensionworld;
+
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename Dune::PQkLocalFiniteElementCache<double, double, dim, 1> FiniteElementCache;
+    typedef typename FiniteElementCache::FiniteElementType FiniteElement;
+
+    typedef typename Dune::QuadratureRule<double,dim> QuadratureRule;
+    typedef typename Dune::template FieldVector<double,dim> LocalCoordinate;
+    typedef typename Dune::template FieldVector<double,dimworld> GlobalCoordinate;
+    typedef typename Dune::template FieldMatrix<double,dimworld,dim> InverseJacobianTransposed;
+    typedef typename FiniteElement::Traits::LocalBasisType::Traits::JacobianType JacobianType;
+
+    const IndexSet& indexSet = gridView.indexSet();
+    FiniteElementCache cache;
+
+    ElementIterator it = gridView.template begin<0>();
+    ElementIterator end = gridView.template end<0>();
+    for (; it != end; ++it)
+    {
+        Element& e = *it;
+        const FiniteElement& fe = cache.get(e.type());
+
+        int localSize = fe.localBasis().size();
+
+        // get quadrature rule of appropiate order (P1/Q1)
+        int order = 0;
+        if (e.type().isSimplex())
+            order = 2*(1-1);
+        else
+            order = 2*(dim-1);
+        const QuadratureRule& quad = Dune::template QuadratureRules<double, dim>::rule(e.type(), order);
+
+        // store gradients of shape functions and base functions
+        std::vector<JacobianType> referenceGradients(localSize);
+        std::vector<GlobalCoordinate> gradients(localSize);
+
+        for (size_t pt=0; pt < quad.size(); ++pt)
+        {
+            // get quadrature point
+            const LocalCoordinate& quadPos = quad[pt].position();
+
+            // get transposed inverse of Jacobian of transformation
+            const InverseJacobianTransposed& invJacobian = e.geometry().jacobianInverseTransposed(quadPos);
+
+            // get integration factor
+            const double integrationElement = e.geometry().integrationElement(quadPos);
+
+            // evaluate gradients of shape functions
+            fe.localBasis().evaluateJacobian(quadPos, referenceGradients);
+
+            // transform gradients
+            for (size_t i=0; i<gradients.size(); ++i)
+                invJacobian.mv(referenceGradients[i][0], gradients[i]);
+
+            // compute matrix entries
+            double z = quad[pt].weight() * integrationElement;
+            for (int i = 0; i < localSize; ++i)
+            {
+                int iGlobal = indexSet.subIndex(e, fe.localCoefficients().localKey(i).subEntity(), dim);
+                for (int j = i+1; j < localSize; ++j)
+                {
+                    int jGlobal = indexSet.subIndex(e, fe.localCoefficients().localKey(j).subEntity(), dim);
+
+                    double zij = (gradients[i] * gradients[j]) * z;
+                    matrix[iGlobal][jGlobal] += zij;
+                    matrix[jGlobal][iGlobal] += zij;
+                }
+                double zii = (gradients[i] * gradients[i]) * z;
+                matrix[iGlobal][iGlobal] += zii;
+            }
+        }
+    }
+}
+
+
+template<class GridView, class Matrix>
+void assemblePQ1Mass(const GridView& gridView, Matrix& matrix)
+{
+    static const int dim = GridView::Grid::dimension;
+
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename Dune::PQkLocalFiniteElementCache<double, double, dim, 1> FiniteElementCache;
+    typedef typename FiniteElementCache::FiniteElementType FiniteElement;
+
+    typedef typename Dune::QuadratureRule<double,dim> QuadratureRule;
+    typedef typename Dune::template FieldVector<double,dim> LocalCoordinate;
+    typedef typename FiniteElement::Traits::LocalBasisType::Traits::RangeType RangeType;
+
+    const IndexSet& indexSet = gridView.indexSet();
+    FiniteElementCache cache;
+
+    ElementIterator it = gridView.template begin<0>();
+    ElementIterator end = gridView.template end<0>();
+    for (; it != end; ++it)
+    {
+        Element& e = *it;
+        const FiniteElement& fe = cache.get(e.type());
+
+        int localSize = fe.localBasis().size();
+
+        // get quadrature rule of appropiate order (P1/Q1)
+        int order = 0;
+        if (e.type().isSimplex())
+            order = 2*1;
+        else
+            order = 2*dim;
+        const QuadratureRule& quad = Dune::template QuadratureRules<double, dim>::rule(e.type(), order);
+
+        // store values of shape functions
+        std::vector<RangeType> values(localSize);
+
+        for (size_t pt=0; pt < quad.size(); ++pt)
+        {
+            // get quadrature point
+            const LocalCoordinate& quadPos = quad[pt].position();
+
+            // get integration factor
+            const double integrationElement = e.geometry().integrationElement(quadPos);
+
+            // evaluate basis functions
+            fe.localBasis().evaluateFunction(quadPos, values);
+
+            // compute matrix entries
+            double z = quad[pt].weight() * integrationElement;
+            for (int i = 0; i < localSize; ++i)
+            {
+                int iGlobal = indexSet.subIndex(e, fe.localCoefficients().localKey(i).subEntity(), dim);
+                double zi = values[i]*z;
+                for (int j = i+1; j < localSize; ++j)
+                {
+                    int jGlobal = indexSet.subIndex(e, fe.localCoefficients().localKey(j).subEntity(), dim);
+
+                    double zij = values[j] * zi;
+                    matrix[iGlobal][jGlobal] += zij;
+                    matrix[jGlobal][iGlobal] += zij;
+                }
+                double zii = values[i] * zi;
+                matrix[iGlobal][iGlobal] += zii;
+            }
+        }
+    }
+}
+
+
+template<class GridView, class Vector, class Function>
+void assemblePQ1RHS(const GridView& gridView, Vector& r, const Function& f)
+{
+    static const int dim = GridView::Grid::dimension;
+
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename Dune::PQkLocalFiniteElementCache<double, double, dim, 1> FiniteElementCache;
+    typedef typename FiniteElementCache::FiniteElementType FiniteElement;
+
+    typedef typename Dune::QuadratureRule<double,dim> QuadratureRule;
+    typedef typename Dune::template FieldVector<double,dim> LocalCoordinate;
+    typedef typename FiniteElement::Traits::LocalBasisType::Traits::RangeType RangeType;
+    typedef typename Function::RangeType FunctionRangeType;
+
+    const IndexSet& indexSet = gridView.indexSet();
+    FiniteElementCache cache;
+
+    int size = indexSet.size(dim);
+
+    ElementIterator it = gridView.template begin<0>();
+    ElementIterator end = gridView.template end<0>();
+    for (; it != end; ++it)
+    {
+        Element& e = *it;
+        const FiniteElement& fe = cache.get(e.type());
+
+        int localSize = fe.localBasis().size();
+
+        // get quadrature rule of appropiate order (P1/Q1)
+        int order = 0;
+        if (e.type().isSimplex())
+            order = 2*1;
+        else
+            order = 2*dim;
+        const QuadratureRule& quad = Dune::template QuadratureRules<double, dim>::rule(e.type(), order);
+
+        // store values of shape functions
+        std::vector<RangeType> values(localSize);
+
+        for (size_t pt=0; pt < quad.size(); ++pt)
+        {
+            // get quadrature point
+            const LocalCoordinate& quadPos = quad[pt].position();
+
+            // get integration factor
+            const double integrationElement = e.geometry().integrationElement(quadPos);
+
+            // evaluate basis functions
+            fe.localBasis().evaluateFunction(quadPos, values);
+
+            // evaluate function
+            FunctionRangeType fAtPos;
+            f.evaluate(e.geometry().global(quadPos), fAtPos);
+
+            // add vector entries
+            double z = quad[pt].weight() * integrationElement;
+            for (int i = 0; i < localSize; ++i)
+            {
+                int iGlobal = indexSet.subIndex(e, fe.localCoefficients().localKey(i).subEntity(), dim);
+
+                r[iGlobal].axpy(values[i]*z, fAtPos);
+            }
+        }
+    }
+}
+
+
+template<class Intersection>
+bool intersectionContainsVertex(const Intersection& i, int vertexInInsideElement)
+{
+    static const int dim = Intersection::dimension;
+
+    int faceIdx = i.indexInInside();
+
+    const Dune::GenericReferenceElement<double,dim>& refElement
+        = Dune::GenericReferenceElements<double, dim>::general(i.inside()->type());
+
+    for (int j = 0; j<refElement.size(faceIdx, 1, dim); ++j)
+    {
+        int intersectionVertexInElement = refElement.subEntity(faceIdx, 1, j, dim);
+
+        if (intersectionVertexInElement == vertexInInsideElement)
+            return true;
+    }
+    return false;
+}
+
+
+template<class GridView, class BitVector>
+void markBoundaryDOFs(const GridView& gridView, BitVector& isBoundary)
+{
+    static const int dim = GridView::Grid::dimension;
+
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+    typedef typename GridView::Intersection Intersection;
+    typedef typename Dune::PQkLocalFiniteElementCache<double, double, dim, 1> FiniteElementCache;
+    typedef typename FiniteElementCache::FiniteElementType FiniteElement;
+
+    const IndexSet& indexSet = gridView.indexSet();
+    FiniteElementCache cache;
+
+    ElementIterator it = gridView.template begin<0>();
+    ElementIterator end = gridView.template end<0>();
+    for (; it != end; ++it)
+    {
+        Element& e = *it;
+        const FiniteElement& fe = cache.get(e.type());
+        int localSize = fe.localBasis().size();
+
+        IntersectionIterator nIt = gridView.ibegin(e);
+        IntersectionIterator nEnd = gridView.iend(e);
+
+        for (; nIt!=nEnd; ++nIt)
+        {
+            const Intersection& i = *nIt;
+
+            if (i.boundary())
+            {
+                for (int j = 0; j < localSize; ++j)
+                {
+                    unsigned int vertexInInsideElement = fe.localCoefficients().localKey(j).subEntity();
+                    int iGlobal = indexSet.subIndex(e, vertexInInsideElement, dim);
+                    if (intersectionContainsVertex(i, vertexInInsideElement))
+                        isBoundary[iGlobal] = true;
+                }
+            }
+        }
+    }
+}
+
+
+
+#endif
diff --git a/dune/solvers/test/obstacletnnmgtest.cc b/dune/solvers/test/obstacletnnmgtest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b3126ba02eda942394a9d493c1053b06c52536ea
--- /dev/null
+++ b/dune/solvers/test/obstacletnnmgtest.cc
@@ -0,0 +1,206 @@
+#include <config.h>
+
+// dune-common includes
+#include <dune/common/bitsetvector.hh>
+
+// dune-istl includes
+#include <dune/istl/bcrsmatrix.hh>
+
+// dune-grid includes
+#include <dune/grid/yaspgrid.hh>
+#include <dune/grid/io/file/vtk/vtkwriter.hh>
+
+// dune-solver includes
+#include <dune/solvers/iterationsteps/obstacletnnmgstep.hh>
+#include <dune/solvers/transferoperators/compressedmultigridtransfer.hh>
+#include <dune/solvers/norms/energynorm.hh>
+#include <dune/solvers/solvers/loopsolver.hh>
+
+
+#include "common.hh"
+
+#define DIMENSION 2
+
+template <class DomainType, class RangeType>
+class ConstantFunction :
+    public Dune::VirtualFunction<DomainType, RangeType>
+{
+    public:
+        ConstantFunction(double c):
+            c_(c)
+        {}
+
+        void evaluate(const DomainType& x, RangeType& y) const
+        {
+            y = c_;
+        }
+
+    private:
+        double c_;
+};
+
+
+
+template<class GridType, class MatrixType, class VectorType>
+void solveObstacleProblemByTNNMG(const GridType& grid, const MatrixType& mat, VectorType& x, const VectorType& rhs, int maxIterations=100, double tolerance=1.0e-10)
+{
+    // bit vector marking dofs to ignore
+    typedef typename ObstacleTNNMGStep<MatrixType, VectorType>::BitVector BitVector;
+    BitVector ignore(rhs.size());
+    ignore.unsetAll();
+
+    solveObstacleProblemByTNNMG(grid, mat, x, rhs, ignore, maxIterations, tolerance);
+}
+
+
+template<class GridType, class MatrixType, class VectorType, class BitVector>
+void solveObstacleProblemByTNNMG(const GridType& grid, const MatrixType& mat, VectorType& x, const VectorType& rhs, const BitVector& ignore, int maxIterations=100, double tolerance=1.0e-10)
+{
+    typedef VectorType Vector;
+    typedef MatrixType Matrix;
+    typedef EnergyNorm<Matrix, Vector> Norm;
+    typedef LoopSolver<Vector> Solver;
+    typedef ObstacleTNNMGStep<Matrix, Vector> TNNMGStep;
+    typedef typename TNNMGStep::Transfer Transfer;
+    typedef typename TNNMGStep::BoxConstraintVector BoxConstraintVector;
+    typedef CompressedMultigridTransfer<Vector, BitVector, Matrix> TransferImplementation;
+
+    const int blockSize = VectorType::block_type::dimension;
+
+    // we need a vector of pointers to the transfer operator base class
+    std::vector<Transfer*> transfer(grid.maxLevel());
+    for (int i = 0; i < transfer.size(); ++i)
+    {
+        // create transfer operator from level i to i+1
+        TransferImplementation* t = new TransferImplementation;
+        t->setup(grid, i, i+1);
+        transfer[i] = t;
+    }
+
+    // create double obstacle constraints
+    BoxConstraintVector boxConstraints(rhs.size());
+    for (int i = 0; i < boxConstraints.size(); ++i)
+    {
+        for (int j = 0; j < blockSize; ++j)
+        {
+            boxConstraints[i].lower(j) = -1;
+            boxConstraints[i].upper(j) = +1;
+        }
+    }
+
+    // we want to control errors with respect to the energy norm induced by the matrix
+    Norm norm(mat);
+
+    // create iteration step
+    TNNMGStep tnnmgStep(mat, x, rhs, ignore, boxConstraints, transfer);
+    tnnmgStep.preprocess();
+    tnnmgStep.nestedIteration();
+
+    // cretae loop solver
+    Solver solver(&tnnmgStep, maxIterations, tolerance, &norm, Solver::FULL);
+
+    // solve problem
+    solver.solve();
+}
+
+
+
+
+
+template <class GridType>
+bool checkWithGrid(const GridType& grid)
+{
+    bool passed = true;
+
+    static const int dim = GridType::dimension;
+
+    typedef typename Dune::FieldMatrix<double, 1, 1> MatrixBlock;
+    typedef typename Dune::FieldVector<double, 1> VectorBlock;
+    typedef typename Dune::BCRSMatrix<MatrixBlock> Matrix;
+    typedef typename Dune::BlockVector<VectorBlock> Vector;
+    typedef typename Dune::BitSetVector<1> BitVector;
+
+    typedef typename GridType::LeafGridView GridView;
+    typedef typename Dune::FieldVector<double, dim> DomainType;
+    typedef typename Dune::FieldVector<double, 1> RangeType;
+
+
+    const GridView gridView = grid.leafView();
+
+    Matrix A;
+    constructPQ1Pattern(gridView, A);
+    A=0.0;
+    assemblePQ1Stiffness(gridView, A);
+
+    Vector rhs(A.N());
+    rhs = 0;
+    ConstantFunction<DomainType, RangeType> f(50);
+    assemblePQ1RHS(gridView, rhs, f);
+
+    Vector u(A.N());
+    u = 0;
+
+    BitVector ignore(A.N());
+    ignore.unsetAll();
+    markBoundaryDOFs(gridView, ignore);
+
+
+    solveObstacleProblemByTNNMG(grid, A, u, rhs, ignore);
+
+    typename Dune::VTKWriter<GridView> vtkWriter(gridView);
+    vtkWriter.addVertexData(u, "solution");
+    vtkWriter.write("obstacletnnmgtest_solution");
+
+
+    return passed;
+}
+
+
+template <int dim>
+bool checkWithYaspGrid(int refine)
+{
+    bool passed = true;
+
+    typedef Dune::YaspGrid<dim> GridType;
+
+    typename Dune::FieldVector<typename GridType::ctype,dim> L(1.0);
+    typename Dune::FieldVector<int,dim> s(1);
+    typename Dune::FieldVector<bool,dim> periodic(false);
+
+    GridType grid(L, s, periodic, 0);
+
+    for (int i = 0; i < refine; ++i)
+        grid.globalRefine(1);
+
+    std::cout << "Testing with YaspGrid<" << dim << ">" << std::endl;
+    std::cout << "Number of levels: " << (grid.maxLevel()+1) << std::endl;
+    std::cout << "Number of leaf nodes: " << grid.leafView().size(dim) << std::endl;
+
+    passed = passed and checkWithGrid(grid);
+
+
+    return passed;
+}
+
+
+
+
+int main(int argc, char** argv) try
+{
+    static const int dim = DIMENSION;
+
+    bool passed(true);
+
+
+    passed = passed and checkWithYaspGrid<1>(15);
+    passed = passed and checkWithYaspGrid<2>(10);
+    passed = passed and checkWithYaspGrid<3>(5);
+
+    return passed ? 0 : 1;
+}
+catch (Dune::Exception e) {
+
+    std::cout << e << std::endl;
+
+}
+