diff --git a/dune-solvers/iterationsteps/multigridstep.cc b/dune-solvers/iterationsteps/multigridstep.cc
new file mode 100644
index 0000000000000000000000000000000000000000..214ba2efaf8f5c19179b6e6d4cd4c9d559192029
--- /dev/null
+++ b/dune-solvers/iterationsteps/multigridstep.cc
@@ -0,0 +1,229 @@
+#include <typeinfo>
+
+#include <dune/ag-common/transferoperators/multigridtransfer.hh>
+#include <dune/ag-common/solvers/loopsolver.hh>
+#include "blockgsstep.hh"
+#include "dune/ag-common/genericvectortools.hh"
+
+#ifdef HAVE_IPOPT
+#include "quadraticipopt.hh"
+#endif
+
+template <class OperatorType, class VectorType, class BitVectorType>
+VectorType MultigridStep<OperatorType, VectorType, BitVectorType>::
+getSol()
+{
+    return this->x_[numLevels_-1];
+}
+
+template<class OperatorType, class VectorType, class BitVectorType>
+inline
+const OperatorType* MultigridStep<OperatorType, VectorType, BitVectorType>::
+getMatrix()
+{
+    return this->mat_[this->mat_.size()-1];
+}
+
+template<class OperatorType, class VectorType, class BitVectorType>
+inline
+void MultigridStep<OperatorType, VectorType, BitVectorType>::
+setMGType(int mu, int nu1, int nu2)
+{
+    mu_ = mu;
+    nu1_ = nu1;
+    nu2_ = nu2;
+}
+
+template<class OperatorType, class VectorType, class BitVectorType>
+void MultigridStep<OperatorType, VectorType, BitVectorType>::preprocess()
+{
+    if(preprocessCalled)
+        std::cout << "Preprocess has already been called without calling iterate afterwards!" << std::endl;
+    preprocessCalled = true;
+
+    int i;
+    this->level_ = this->numLevels_-1;
+    
+    // //////////////////////////////////////////////////////////
+    //   Check that transfer operators have been supplied
+    // //////////////////////////////////////////////////////////
+    if (this->mgTransfer_.size()!=this->numLevels_-1)
+        DUNE_THROW(SolverError, "You requested " << this->numLevels_ << " levels "
+                   << "but you supplied " << this->mgTransfer_.size() << " transfer operators!");
+
+    for (i=0; i<this->mgTransfer_.size(); i++)
+        if (this->mgTransfer_[i] == NULL)
+            DUNE_THROW(SolverError, "You have not supplied a multigrid restriction operator "
+                       "for level " << i);
+
+    // The matrices for the linear correction problems
+    for (i=this->numLevels_-2; i>=0; i--) {
+        
+
+        // Delete coarse grid matrix if it exists already
+        if (this->mat_[i]) {
+            delete(this->mat_[i]);
+            this->mat_[i] = NULL;
+        }
+//        int nDofs = this->mgTransfer_[i]->getMatrix().M();
+//        this->mat_[i] = new OperatorType(nDofs, nDofs, OperatorType::row_wise);
+        this->mat_[i] = new OperatorType;
+        
+        // Compute which entries are present in the (sparse) coarse grid stiffness
+        // matrices. 
+        this->mgTransfer_[i]->galerkinRestrictSetOccupation(*this->mat_[i+1], *(const_cast<OperatorType*>(this->mat_[i])));
+
+        // Set solution vector sizes for the lower levels
+        GenericVector::resize(this->x_[i],*this->mat_[i]);
+    }
+
+    // /////////////////////////////////////////////////////
+    //   Assemble the complete hierarchy of matrices
+    // /////////////////////////////////////////////////////
+    for (i=this->mgTransfer_.size()-1; i>=0; i--) 
+        this->mgTransfer_[i]->galerkinRestrict(*this->mat_[i+1], *(const_cast<OperatorType*>(this->mat_[i])));
+
+    // /////////////////////////////////////////////////////
+    //   Setup dirichlet bitfields
+    // /////////////////////////////////////////////////////
+    for (size_t i=0; i<ignoreNodesHierarchy_.size()-1; i++)
+        delete(ignoreNodesHierarchy_[i]);
+    
+    if (this->ignoreNodes_!=0)
+    {
+        ignoreNodesHierarchy_[this->numLevels_-1] = const_cast<BitVectorType*>(this->ignoreNodes_);
+        for (i=this->numLevels_-2; i>=0; --i)
+        {
+            ignoreNodesHierarchy_[i] = new BitVectorType();
+            this->mgTransfer_[i]->restrictToFathers(*ignoreNodesHierarchy_[i+1], *ignoreNodesHierarchy_[i]);
+        }
+    } else 
+        DUNE_THROW(SolverError, "We need a set of nodes to ignore");
+
+    for (i=this->mgTransfer_.size()-1; i>=0; i--) 
+        this->mgTransfer_[i]->galerkinRestrict(*this->mat_[i+1], *(const_cast<OperatorType*>(this->mat_[i])));
+
+    // /////////////////////////////////////////////
+    //   Set up base solver
+    // /////////////////////////////////////////////
+
+    if (this->basesolver_ == NULL)
+        DUNE_THROW(SolverError, "You have not provided a base solver!");
+
+    if (typeid(*this->basesolver_) == typeid(LoopSolver<VectorType>)) {
+
+        LoopSolver<VectorType>* loopBaseSolver = dynamic_cast<LoopSolver<VectorType>* > (this->basesolver_);
+     
+        typedef LinearIterationStep<OperatorType, VectorType> SmootherType;
+        assert(dynamic_cast<SmootherType*>(loopBaseSolver->iterationStep_));
+
+        dynamic_cast<SmootherType*>(loopBaseSolver->iterationStep_)->setProblem(*(this->mat_[0]), this->x_[0], this->rhs_[0]);
+        dynamic_cast<SmootherType*>(loopBaseSolver->iterationStep_)->ignoreNodes_ = ignoreNodesHierarchy_[0];
+        
+    }
+#ifdef HAVE_IPOPT
+    else if (typeid(*this->basesolver_) == typeid(QuadraticIPOptSolver<OperatorType,VectorType>)) {
+
+        QuadraticIPOptSolver<OperatorType,VectorType>* ipoptBaseSolver = dynamic_cast<QuadraticIPOptSolver<OperatorType,VectorType>*> (this->basesolver_);
+     
+        ipoptBaseSolver->setProblem(*(this->mat_[0]), this->x_[0], this->rhs_[0]);
+        ipoptBaseSolver->ignoreNodes_ = ignoreNodesHierarchy_[0];
+
+    } 
+#endif
+else {
+        DUNE_THROW(SolverError, "You can't use " << typeid(*this->basesolver_).name()
+                   << " as a base solver for contact problems!");
+    }
+}
+
+
+
+template<class OperatorType, class VectorType, class BitVectorType>
+void MultigridStep<OperatorType, VectorType, BitVectorType>::nestedIteration()
+{
+
+    for (level_ = 0; level_<numLevels_; level_++) {
+    
+        iterate();
+
+        mgTransfer_[level_]->prolong(x_[level_], x_[level_+1]);
+
+    }
+     
+    iterate();
+}
+
+
+template<class OperatorType, class VectorType, class BitVectorType>
+void MultigridStep<OperatorType, VectorType, BitVectorType>::postprocess()
+{
+
+}
+
+
+template<class OperatorType, class VectorType, class BitVectorType>
+void MultigridStep<OperatorType, VectorType, BitVectorType>::iterate()
+{
+    preprocessCalled = false;
+
+    int& level = this->level_;
+
+    // Define references just for ease of notation
+    std::vector<const OperatorType*>& mat = this->mat_;
+    std::vector<VectorType>& x   = this->x_;
+    std::vector<VectorType>& rhs = this->rhs_;
+
+    // Solve directly if we're looking at the coarse problem
+    if (level == 0) {
+        basesolver_->solve();
+        return;
+    }
+    
+    // Presmoothing
+    presmoother_->setProblem(*(this->mat_[level]), x[level], rhs[level]);
+    presmoother_->ignoreNodes_ = ignoreNodesHierarchy_[level];
+
+    for (int i=0; i<this->nu1_; i++)
+        presmoother_->iterate();
+
+    // /////////////////////////
+    // Restriction
+    
+    // compute residual
+    // fineResidual = rhs[level] - mat[level] * x[level];
+    VectorType fineResidual = rhs[level];
+    mat[level]->mmv(x[level], fineResidual);
+
+    // restrict residuum
+    this->mgTransfer_[level-1]->restrict(fineResidual, rhs[level-1]);
+
+
+    // Set Dirichlet values.
+    GenericVector::truncate(rhs[level-1], *ignoreNodesHierarchy_[level-1]);
+
+    // Choose all zeros as the initial correction
+    x[level-1] = 0;
+
+    // ///////////////////////////////////////
+    // Recursively solve the coarser system
+    level--;
+    iterate();
+    level++;
+
+    // ////////////////////////////////////////
+    // Prolong
+
+    // add correction to the presmoothed solution
+    VectorType tmp;
+    this->mgTransfer_[level-1]->prolong(x[level-1], tmp);
+    x[level] += tmp;
+
+    // Postsmoothing
+    postsmoother_->setProblem(*(mat[level]), x[level], rhs[level]);
+    postsmoother_->ignoreNodes_ = ignoreNodesHierarchy_[level];
+
+    for (int i=0; i<this->nu2_; i++)
+        postsmoother_->iterate();
+
+}
diff --git a/dune-solvers/iterationsteps/multigridstep.hh b/dune-solvers/iterationsteps/multigridstep.hh
new file mode 100644
index 0000000000000000000000000000000000000000..8913f97f6ec5932b1efcda4a28bd87c191d8a17f
--- /dev/null
+++ b/dune-solvers/iterationsteps/multigridstep.hh
@@ -0,0 +1,214 @@
+#ifndef MULTIGRID_STEP_HH
+#define MULTIGRID_STEP_HH
+
+#include <vector>
+#include <dune/common/bitsetvector.hh>
+#include "iterativesolver.hh"
+#include "lineariterationstep.hh"
+
+#include <dune/ag-common/transferoperators/multigridtransfer.hh>
+
+    template<
+        class OperatorType,
+        class VectorType,
+        class BitVectorType = Dune::BitSetVector<VectorType::block_type::dimension> >
+    class MultigridStep : public LinearIterationStep<OperatorType, VectorType, BitVectorType>
+    {
+
+        static const int blocksize = VectorType::block_type::dimension;
+
+    public:
+
+        MultigridStep() :
+            numLevels_(0),
+            presmoother_(0),
+            postsmoother_(0),
+            basesolver_(0),
+            ignoreNodesHierarchy_(0),
+            preprocessCalled(false)
+        {}
+
+        MultigridStep(const OperatorType& mat, 
+                      VectorType& x, 
+                      VectorType& rhs, int numLevels,
+                      int mu, int nu1, int nu2,
+                      LinearIterationStep<OperatorType, VectorType>* preSmoother,
+                      LinearIterationStep<OperatorType, VectorType>* postSmoother,
+                      Solver* baseSolver,
+                      const BitVectorType* ignoreNodes) :
+            LinearIterationStep<OperatorType, VectorType>(mat, x, rhs),
+            mat_(numLevels),
+            ignoreNodesHierarchy_(numLevels),
+            x_(numLevels),
+            rhs_(numLevels),
+            preprocessCalled(false)
+        {
+            numLevels_ = numLevels;
+            level_ = numLevels-1;
+
+            mat_[level_] = &mat;
+            x_[level_]   = x;
+            rhs_[level_] = rhs;
+
+            mu_  = mu;
+            nu1_ = nu1;
+            nu2_ = nu2;
+
+            presmoother_  = preSmoother;
+            postsmoother_ = postSmoother;
+            basesolver_   = baseSolver;
+
+            this->ignoreNodes_ = ignoreNodes;
+        }
+
+        MultigridStep(const OperatorType& mat, 
+                      VectorType& x, 
+                      VectorType& rhs, int numLevels) :
+            LinearIterationStep<OperatorType, VectorType>(mat, x, rhs),
+            presmoother_(0),
+            postsmoother_(0),
+            basesolver_(0),
+            mat_(numLevels),
+            ignoreNodesHierarchy_(numLevels),
+            x_(numLevels),
+            rhs_(numLevels),
+            preprocessCalled(false)
+        {
+            numLevels_ = numLevels;
+            level_ = numLevels-1;
+
+            mat_[level_] = &mat;
+            x_[level_]   = x;
+            rhs_[level_] = rhs;
+        }
+
+
+        virtual ~MultigridStep() {
+            // Delete all matrices but the top one, which has been supplied from the outside
+            for (size_t i=0; i<mat_.size()-1; i++)
+            {
+                delete(mat_[i]);
+                delete(ignoreNodesHierarchy_[i]);
+            }
+        }
+
+        virtual void setProblem(const OperatorType& mat, 
+                                VectorType& x, 
+                                VectorType& rhs,
+                                int numLevels)
+        {
+            setNumberOfLevels(numLevels);
+            setProblem(mat, x, rhs);
+        }
+
+        virtual void setNumberOfLevels(int numLevels)
+        {
+            numLevels_ = numLevels;
+
+            for (int i=0; i<int(mat_.size())-1; i++)
+                if (mat_[i])
+                    delete(mat_[i]);
+
+            for (int i=0; i<int(ignoreNodesHierarchy_.size())-1; i++)
+                if (ignoreNodesHierarchy_[i])
+                    delete(ignoreNodesHierarchy_[i]);
+
+            mat_.resize(numLevels);
+            ignoreNodesHierarchy_.resize(numLevels);
+
+            for (int i=0; i<int(mat_.size())-1; i++)
+            {
+                mat_[i] = NULL;
+                ignoreNodesHierarchy_[i] = NULL;
+            }
+
+            x_.resize(numLevels);
+            rhs_.resize(numLevels);
+        }
+
+        virtual void setProblem(const OperatorType& mat, 
+                                VectorType& x, 
+                                VectorType& rhs)
+        {
+            level_ = numLevels_-1;
+
+            mat_[level_] = &mat;
+            x_[level_]   = x;
+            rhs_[level_] = rhs;
+        }
+
+        template <class DerivedTransferHierarchy>
+        void setTransferOperators(const DerivedTransferHierarchy& transfer)
+        {
+            mgTransfer_.resize(transfer.size());
+            for(int j=0; j<transfer.size(); ++j)
+                mgTransfer_[j] = transfer[j];
+        }
+
+        virtual void iterate();
+
+        virtual void nestedIteration();
+
+        virtual void preprocess();
+
+        virtual void postprocess();
+
+        virtual VectorType getSol();
+
+        virtual const OperatorType* getMatrix();
+
+        virtual int level() const {return level_;}
+
+        /** \brief Sets the number of pre- and postsmoothing steps 
+            and of coarse corrections.
+            \param mu Number of coarse corrections
+            \param nu1 Number of presmoothing steps
+            \param nu2 Number of postsmoothing steps
+        */
+        virtual void setMGType(int mu, int nu1, int nu2);
+
+        LinearIterationStep<OperatorType, VectorType>* presmoother_;
+
+        LinearIterationStep<OperatorType, VectorType>* postsmoother_;
+
+        Solver* basesolver_;
+
+    protected:
+        //! Number of presmoothing steps
+        int nu1_;
+
+        //! Number of postsmoothing steps
+        int nu2_;
+
+        //! Number of coarse corrections
+        int mu_;
+    public:
+        //! Variable used to store the current level
+        int level_;
+
+        //! The total number of levels of the underlying grid
+        int numLevels_;
+
+    public:
+        //! The linear operators on each level
+        std::vector<const OperatorType*> mat_;
+
+    protected:
+        //! Flags specifying the dirichlet nodes on each level
+        std::vector<BitVectorType*> ignoreNodesHierarchy_;
+
+    public:
+        std::vector<VectorType> x_;
+
+        std::vector<VectorType> rhs_;
+
+        //protected:
+        std::vector<MultigridTransfer<VectorType, BitVectorType, OperatorType>* > mgTransfer_;
+
+    protected:
+        bool preprocessCalled;
+    };
+
+#include "multigridstep.cc"
+
+#endif