diff --git a/dune/gfe/mixedriemannianpnsolver.cc b/dune/gfe/mixedriemannianpnsolver.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eea8d8cbe295aa3186f6d59bdb223e00f7dcbd75
--- /dev/null
+++ b/dune/gfe/mixedriemannianpnsolver.cc
@@ -0,0 +1,381 @@
+#include <dune/common/bitsetvector.hh>
+#include <dune/common/timer.hh>
+
+#include <dune/gfe/parallel/matrixcommunicator.hh>
+#include <dune/gfe/parallel/vectorcommunicator.hh>
+
+template <class MixedBasis,
+    class Basis0,
+    class TargetSpace0,
+    class Basis1,
+    class TargetSpace1,
+    class BitVector>
+void Dune::GFE::MixedRiemannianProximalNewtonSolver<MixedBasis,Basis0,TargetSpace0,Basis1,TargetSpace1,BitVector>::
+setup(const GridType& grid,
+      const MixedGFEAssembler<MixedBasis, TargetSpace0, TargetSpace1>* assembler,
+      const SolutionType& x,
+      const BitVector& dirichletNodes,
+      double tolerance,
+      int maxProximalNewtonSteps,
+      double initialRegularization,
+      bool instrumented)
+{
+  grid_                     = &grid;
+  assembler_                = assembler;
+  x_                        = x;
+  tolerance_                = tolerance;
+  maxProximalNewtonSteps_   = maxProximalNewtonSteps;
+  initialRegularization_    = initialRegularization;
+
+  //////////////////////////////////////////////////////////////////
+  //  Create global numbering for matrix and vector transfer
+  //////////////////////////////////////////////////////////////////
+#if HAVE_MPI
+  globalMapper0_ = std::make_unique<GlobalMapper0>(grid_->leafGridView());
+  globalMapper1_ = std::make_unique<GlobalMapper1>(grid_->leafGridView());
+
+  // Transfer all Dirichlet data to the master processor
+  using VectorCommunicator0 = VectorCommunicator<GlobalMapper0, typename GridType::LeafGridView::Communication, Dune::BitSetVector<blocksize0> >;
+  VectorCommunicator0 vectorComm0(*globalMapper0_,
+                                  grid_->leafGridView().comm(),
+                                  0);
+  using VectorCommunicator1 = VectorCommunicator<GlobalMapper1, typename GridType::LeafGridView::Communication, Dune::BitSetVector<blocksize1> >;
+  VectorCommunicator1 vectorComm1(*globalMapper1_,
+                                  grid_->leafGridView().comm(),
+                                  0);
+
+  using namespace Dune::Indices;
+  Dune::BitSetVector<blocksize0> dirichletNodes0(dirichletNodes[_0].size(),false);
+  Dune::BitSetVector<blocksize1> dirichletNodes1(dirichletNodes[_1].size(),false);
+  for (std::size_t i = 0; i < dirichletNodes[_0].size(); i++)
+    for (int j = 0; j < blocksize0; j++)
+      dirichletNodes0[i][j] = dirichletNodes[_0][i][j];
+  for (std::size_t i = 0; i < dirichletNodes[_1].size(); i++)
+    for (int j = 0; j < blocksize1; j++)
+      dirichletNodes1[i][j] = dirichletNodes[_1][i][j];
+
+  auto globalDirichletNodes0 = vectorComm0.reduceCopy(dirichletNodes0);
+  auto globalDirichletNodes1 = vectorComm1.reduceCopy(dirichletNodes1);
+
+  BitVector globalDirichletNodes01;
+  globalDirichletNodes01[_0].resize(globalDirichletNodes0.size());
+  globalDirichletNodes01[_1].resize(globalDirichletNodes1.size());
+  for (std::size_t i = 0; i < globalDirichletNodes0.size(); i++)
+    for (int j = 0; j < blocksize0; j++)
+      globalDirichletNodes01[_0][i][j] = globalDirichletNodes0[i][j];
+  for (std::size_t i = 0; i < globalDirichletNodes1.size(); i++)
+    for (int j = 0; j < blocksize1; j++)
+      globalDirichletNodes01[_1][i][j] = globalDirichletNodes1[i][j];
+
+  auto globalDirichletNodes = new BitVector(globalDirichletNodes01);
+#else
+  auto globalDirichletNodes = new BitVector(dirichletNodes);
+#endif
+
+  //////////////////////////////////////////////////////////////////
+  //   Create the inner solver using a direct solver
+  //////////////////////////////////////////////////////////////////
+
+  innerSolver_ = std::make_shared<Solvers::CholmodSolver<MatrixType,CorrectionType,BitVector> >();
+
+  innerSolver_->setIgnore(*globalDirichletNodes);
+  hessianMatrix_ = std::make_unique<MatrixType>();
+}
+
+
+template <class MixedBasis,
+    class Basis0,
+    class TargetSpace0,
+    class Basis1,
+    class TargetSpace1,
+    class BitVector>
+void Dune::GFE::MixedRiemannianProximalNewtonSolver<MixedBasis,Basis0,TargetSpace0,Basis1,TargetSpace1,BitVector>::solve()
+{
+  int rank = grid_->comm().rank();
+
+  // /////////////////////////////////////////////////////
+  //   Proximal Newton Solver
+  // /////////////////////////////////////////////////////
+
+  using namespace Dune::TypeTree::Indices;
+
+  Dune::Timer energyTimer;
+  double oldEnergy = assembler_->computeEnergy(x_[_0], x_[_1]);
+  if (this->verbosity_ == Solver::FULL)
+    std::cout << "Energy computation took " << energyTimer.elapsed() << " sec." << std::endl;
+
+  oldEnergy = grid_->comm().sum(oldEnergy);
+
+  bool recomputeGradientHessian = true;
+  CorrectionType rhs, rhs_global;
+  MatrixType stiffnessMatrix;
+#if HAVE_MPI
+  using VectorCommunicator0 = VectorCommunicator<GlobalMapper0, typename GridType::LeafGridView::Communication, CorrectionType0>;
+  VectorCommunicator0 vectorComm0(*globalMapper0_,
+                                  grid_->leafGridView().comm(),
+                                  0);
+  using VectorCommunicator1 = VectorCommunicator<GlobalMapper1, typename GridType::LeafGridView::Communication, CorrectionType1>;
+  VectorCommunicator1 vectorComm1(*globalMapper1_,
+                                  grid_->leafGridView().comm(),
+                                  0);
+
+  LocalMapper0 localMapper0 = MapperFactory<Basis0>::createLocalMapper(grid_->leafGridView());
+  LocalMapper1 localMapper1 = MapperFactory<Basis1>::createLocalMapper(grid_->leafGridView());
+
+  MatrixCommunicator<GlobalMapper0,
+      typename GridType::LeafGridView,
+      typename GridType::LeafGridView,
+      MatrixType00,
+      LocalMapper0,
+      LocalMapper0> matrixComm00(*globalMapper0_,
+                                 grid_->leafGridView(),
+                                 localMapper0,
+                                 localMapper0,
+                                 0);
+  MatrixCommunicator<GlobalMapper1,
+      typename GridType::LeafGridView,
+      typename GridType::LeafGridView,
+      MatrixType11,
+      LocalMapper1,
+      LocalMapper1> matrixComm11(*globalMapper1_,
+                                 grid_->leafGridView(),
+                                 localMapper1,
+                                 localMapper1,
+                                 0);
+  MatrixCommunicator<GlobalMapper0,
+      typename GridType::LeafGridView,
+      typename GridType::LeafGridView,
+      MatrixType01,
+      LocalMapper0,
+      LocalMapper1,
+      GlobalMapper1> matrixComm01(*globalMapper0_,
+                                  *globalMapper1_,
+                                  grid_->leafGridView(),
+                                  grid_->leafGridView(),
+                                  localMapper0,
+                                  localMapper1,
+                                  0);
+  MatrixCommunicator<GlobalMapper1,
+      typename GridType::LeafGridView,
+      typename GridType::LeafGridView,
+      MatrixType10,
+      LocalMapper1,
+      LocalMapper0,
+      GlobalMapper0> matrixComm10(*globalMapper1_,
+                                  *globalMapper0_,
+                                  grid_->leafGridView(),
+                                  grid_->leafGridView(),
+                                  localMapper1,
+                                  localMapper0,
+                                  0);
+#endif
+  double totalAssemblyTime = 0.0;
+  double totalSolverTime = 0.0;
+  double regularization = initialRegularization_;
+  for (std::size_t i=0; i<maxProximalNewtonSteps_; i++)
+  {
+
+    Dune::Timer totalTimer;
+    if (this->verbosity_ == Solver::FULL and rank==0) {
+      std::cout << "----------------------------------------------------" << std::endl;
+      std::cout << "      Mixed Proximal Newton Step Number: " << i
+                << ",     regularization parameter: " << regularization
+                << ",     energy: " << oldEnergy << std::endl;
+      std::cout << "----------------------------------------------------" << std::endl;
+    }
+
+    CorrectionType corr;
+    corr[_0].resize(x_[_0].size());
+    corr[_1].resize(x_[_1].size());
+    corr = 0;
+
+    if (recomputeGradientHessian) {
+      Dune::Timer assemblyTimer;
+      assembler_->assembleGradientAndHessian(x_[_0],
+                                             x_[_1],
+                                             rhs[_0],
+                                             rhs[_1],
+                                             *hessianMatrix_,
+                                             i==0          // assemble occupation pattern only for the first call
+                                             );
+
+      rhs *= -1;              // The right hand side is the _negative_ gradient
+
+      if (this->verbosity_ == Solver::FULL)
+        std::cout << "Assembly took " << assemblyTimer.elapsed() << " sec." << std::endl;
+      totalAssemblyTime += assemblyTimer.elapsed();
+
+#if HAVE_MPI
+      // Transfer matrix data
+      stiffnessMatrix[_0][_0] = matrixComm00.reduceAdd((*hessianMatrix_)[_0][_0]);
+      stiffnessMatrix[_0][_1] = matrixComm01.reduceAdd((*hessianMatrix_)[_0][_1]);
+      stiffnessMatrix[_1][_0] = matrixComm10.reduceAdd((*hessianMatrix_)[_1][_0]);
+      stiffnessMatrix[_1][_1] = matrixComm11.reduceAdd((*hessianMatrix_)[_1][_1]);
+
+      // Transfer vector data
+      rhs_global[_0] = vectorComm0.reduceAdd(rhs[_0]);
+      rhs_global[_1] = vectorComm1.reduceAdd(rhs[_1]);
+#else
+      stiffnessMatrix = *hessianMatrix_;
+      rhs_global = rhs;
+#endif
+      recomputeGradientHessian = false;
+    }
+
+    CorrectionType corr_global;
+    corr_global[_0].resize(rhs_global[_0].size());
+    corr_global[_1].resize(rhs_global[_1].size());
+    corr_global = 0;
+    bool solvedByInnerSolver = true;
+
+    if (rank==0)
+    {
+      // Add the regularization - Identity Matrix for now
+      for (std::size_t i=0; i<stiffnessMatrix[_0][_0].N(); i++)
+        for (int j=0; j<blocksize0; j++)
+          stiffnessMatrix[_0][_0][i][i][j][j] += regularization;
+      for (std::size_t i=0; i<stiffnessMatrix[_1][_1].N(); i++)
+        for (int j=0; j<blocksize1; j++)
+          stiffnessMatrix[_1][_1][i][i][j][j] += regularization;
+
+      innerSolver_->setProblem(stiffnessMatrix,corr_global,rhs_global);
+      innerSolver_->preprocess();
+
+      ///////////////////////////////
+      //    Solve !
+      ///////////////////////////////
+
+      std::cout << "Solve quadratic problem using cholmod solver..." << std::endl;
+      Dune::Timer solutionTimer;
+      try {
+        innerSolver_->solve();
+      } catch (Dune::Exception &e) {
+        std::cerr << "Error while solving: " << e << std::endl;
+        solvedByInnerSolver = false;
+        corr_global = 0;
+      }
+      std::cout << "Solving the quadratic problem took " << solutionTimer.elapsed() << " seconds." << std::endl;
+      totalSolverTime += solutionTimer.elapsed();
+    }
+#if HAVE_MPI
+    // Distribute solution
+    if (grid_->comm().size()>1 and rank==0)
+      std::cout << "Transfer solution back to root process ..." << std::endl;
+
+    corr[_0] = vectorComm0.scatter(corr_global[_0]);
+    corr[_1] = vectorComm1.scatter(corr_global[_1]);
+#else
+    corr = corr_global;
+#endif
+    double corrNorm = corr.infinity_norm();
+    double corrGlobalInfinityNorm = grid_->comm().max(corrNorm);
+    if (std::isnan(corrGlobalInfinityNorm))
+      solvedByInnerSolver = false;
+
+    double energy = 0;
+    double modelDecrease = 0;
+    SolutionType newIterate = x_;
+    if (i == maxProximalNewtonSteps_ - 1)
+      std::cout << i+1 << " proximal newton steps were taken, the maximum was reached." << std::endl << "Total solver time: " << totalSolverTime << " sec., total assembly time: " << totalAssemblyTime << " sec." << std::endl;
+
+    if (solvedByInnerSolver) {
+      if (this->verbosity_ == NumProc::FULL && rank==0)
+        std::cout << "Infinity norm of the correction: " << corrGlobalInfinityNorm << std::endl;
+
+      if (corrGlobalInfinityNorm < tolerance_) {
+        if (verbosity_ == NumProc::FULL and rank==0)
+          std::cout << "CORRECTION IS SMALL ENOUGH" << std::endl;
+
+        if (verbosity_ != NumProc::QUIET and rank==0)
+          std::cout << i+1 << " proximal newton steps were taken" << std::endl << "Total solver time: " << totalSolverTime << " sec., total assembly time: " << totalAssemblyTime << " sec." << std::endl;
+        break;
+      }
+
+      // ////////////////////////////////////////////////////
+      //   Check whether proximal newton step can be accepted
+      // ////////////////////////////////////////////////////
+
+      for (size_t j=0; j<newIterate[_0].size(); j++)
+        newIterate[_0][j] = TargetSpace0::exp(newIterate[_0][j], corr[_0][j]);
+
+      for (size_t j=0; j<newIterate[_1].size(); j++)
+        newIterate[_1][j] = TargetSpace1::exp(newIterate[_1][j], corr[_1][j]);
+      try {
+        energy = assembler_->computeEnergy(newIterate[_0],newIterate[_1]);
+      } catch (Dune::Exception &e) {
+        std::cerr << "Error while computing the energy of the new Iterate: " << e << std::endl;
+        std::cerr << "Redoing proximal newton step with higher regularization parameter ..." << std::endl;
+        solvedByInnerSolver = false;
+      }
+      solvedByInnerSolver = grid_->comm().min(solvedByInnerSolver);
+      if (!solvedByInnerSolver) {
+        newIterate = x_;
+        energy = oldEnergy;
+      } else {
+        energy = grid_->comm().sum(energy);
+
+        // compute the model decrease
+        // It is $ m(x) - m(x+s) = -<g,s> - 0.5 <s, Hs>
+        // Note that rhs = -g
+        CorrectionType tmp(corr);
+        hessianMatrix_->mv(corr,tmp);
+        modelDecrease = rhs*corr - 0.5 * (corr*tmp);
+        modelDecrease = grid_->comm().sum(modelDecrease);
+
+        double relativeModelDecrease = modelDecrease / std::fabs(energy);
+
+        if (verbosity_ == NumProc::FULL and rank==0) {
+          std::cout << "Absolute model decrease: " << modelDecrease
+                    << ",  functional decrease: " << oldEnergy - energy << std::endl;
+          std::cout << "Relative model decrease: " << relativeModelDecrease
+                    << ",  functional decrease: " << (oldEnergy - energy)/energy << std::endl;
+        }
+
+        assert(modelDecrease >= 0);
+
+        if (energy >= oldEnergy and rank==0) {
+          if (this->verbosity_ == NumProc::FULL)
+            std::cout << "Direction is not a descent direction!" << std::endl;
+        }
+      }
+    }
+    // //////////////////////////////////////////////
+    //   Check for acceptance of the step
+    // //////////////////////////////////////////////
+    if ( solvedByInnerSolver && oldEnergy >= energy && (oldEnergy-energy) / modelDecrease > 0.9)
+    {
+      // very successful iteration
+
+      x_ = newIterate;
+      regularization *= 0.5;
+
+      // current energy becomes 'oldEnergy' for the next iteration
+      oldEnergy = energy;
+
+      recomputeGradientHessian = true;
+
+    } else if ((solvedByInnerSolver && oldEnergy >= energy && (oldEnergy-energy) / modelDecrease > 0.01)
+               || std::abs(oldEnergy-energy) < 1e-12) {
+      // successful iteration
+      x_ = newIterate;
+
+      // current energy becomes 'oldEnergy' for the next iteration
+      oldEnergy = energy;
+
+      recomputeGradientHessian = true;
+
+    } else {
+
+      // unsuccessful iteration
+
+      // Increase the regularization parameter
+      regularization *= 2;
+
+      if (this->verbosity_ == NumProc::FULL and rank==0)
+        std::cout << "Unsuccessful iteration!" << std::endl;
+    }
+
+    if (rank==0)
+      std::cout << "iteration took " << totalTimer.elapsed() << " sec." << std::endl;
+  }
+}
diff --git a/dune/gfe/mixedriemannianpnsolver.hh b/dune/gfe/mixedriemannianpnsolver.hh
new file mode 100644
index 0000000000000000000000000000000000000000..a0314bbd02f5dc22db8807d9e7a3f299f5cfe608
--- /dev/null
+++ b/dune/gfe/mixedriemannianpnsolver.hh
@@ -0,0 +1,118 @@
+#ifndef DUNE_GFE_MIXED_RIEMANNIAN_PROXIMAL_NEWTON_SOLVER_HH
+#define DUNE_GFE_MIXED_RIEMANNIAN_PROXIMAL_NEWTON_SOLVER_HH
+
+#include <vector>
+
+#include <dune/common/bitsetvector.hh>
+
+#include <dune/istl/bcrsmatrix.hh>
+#include <dune/istl/bvector.hh>
+#include <dune/istl/multitypeblockmatrix.hh>
+
+#include <dune/grid/utility/globalindexset.hh>
+
+#include <dune/solvers/solvers/cholmodsolver.hh>
+
+#include <dune/gfe/parallel/mapperfactory.hh>
+
+
+namespace Dune::GFE
+{
+
+  /** \brief Riemannian proximal Newton solver for geodesic finite-element problems */
+  template <class MixedBasis,
+      class Basis0,
+      class TargetSpace0,
+      class Basis1,
+      class TargetSpace1,
+      class BitVector>
+  class MixedRiemannianProximalNewtonSolver
+    : public NumProc
+  {
+    using GridType = typename MixedBasis::GridView::Grid;
+
+    const static int blocksize0 = TargetSpace0::TangentVector::dimension;
+    const static int blocksize1 = TargetSpace1::TangentVector::dimension;
+
+    const static int gridDim = GridType::dimension;
+
+    // Centralize the field type here
+    using field_type = double;
+
+    using MatrixType00 = BCRSMatrix<FieldMatrix<field_type, blocksize0, blocksize0> >;
+    using MatrixType01 = BCRSMatrix<FieldMatrix<field_type, blocksize0, blocksize1> >;
+    using MatrixType10 = BCRSMatrix<FieldMatrix<field_type, blocksize1, blocksize0> >;
+    using MatrixType11 = BCRSMatrix<FieldMatrix<field_type, blocksize1, blocksize1> >;
+    typedef MultiTypeBlockMatrix<MultiTypeBlockVector<MatrixType00,MatrixType01>,
+        MultiTypeBlockVector<MatrixType10,MatrixType11> > MatrixType;
+
+    using CorrectionType0 = BlockVector<FieldVector<field_type, blocksize0> >;
+    using CorrectionType1 = BlockVector<FieldVector<field_type, blocksize1> >;
+    using CorrectionType  = MultiTypeBlockVector<CorrectionType0, CorrectionType1>;
+    using SolutionType    = TupleVector<std::vector<TargetSpace0>, std::vector<TargetSpace1> >;
+#if HAVE_MPI
+    typedef typename MapperFactory<Basis0>::GlobalMapper GlobalMapper0;
+    typedef typename MapperFactory<Basis1>::GlobalMapper GlobalMapper1;
+    typedef typename MapperFactory<Basis0>::LocalMapper LocalMapper0;
+    typedef typename MapperFactory<Basis1>::LocalMapper LocalMapper1;
+#endif
+
+  public:
+
+    MixedRiemannianProximalNewtonSolver()
+      : NumProc(NumProc::FULL)
+    {}
+
+    void setup(const GridType& grid,
+               const MixedGFEAssembler<MixedBasis, TargetSpace0, TargetSpace1>* assembler,
+               const SolutionType& x,
+               const BitVector& dirichletNodes,
+               double tolerance,
+               int maxProximalNewtonSteps,
+               double initialRegularization,
+               bool instrumented);
+    void solve();
+
+    void setInitialIterate(const SolutionType& x)
+    {
+      x_ = x;
+    }
+
+    SolutionType getSol() const
+    {
+      return x_;
+    }
+
+  protected:
+#if HAVE_MPI
+    std::unique_ptr<GlobalMapper0> globalMapper0_;
+    std::unique_ptr<GlobalMapper1> globalMapper1_;
+#endif
+    /** \brief The grid */
+    const GridType* grid_;
+
+    /** \brief The solution vectors */
+    SolutionType x_;
+
+    /** \brief The initial regularization parameter for the proximal Newton step */
+    double initialRegularization_;
+    double tolerance_;
+
+    /** \brief Maximum number of proximal-newton steps */
+    std::size_t maxProximalNewtonSteps_;
+
+    /** \brief Hesse matrix */
+    std::unique_ptr<MatrixType> hessianMatrix_;
+
+    /** \brief The assembler for the material law */
+    const MixedGFEAssembler<MixedBasis, TargetSpace0, TargetSpace1>* assembler_;
+
+    /** \brief The solver for the quadratic inner problems */
+    std::shared_ptr<Solvers::CholmodSolver<MatrixType, CorrectionType, BitVector> > innerSolver_;
+  };
+
+}  // namespace Dune::GFE
+
+#include "mixedriemannianpnsolver.cc"
+
+#endif
diff --git a/dune/gfe/parallel/mapperfactory.hh b/dune/gfe/parallel/mapperfactory.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4bd2bf23a37651fe543cf90b537e8c4295897bf2
--- /dev/null
+++ b/dune/gfe/parallel/mapperfactory.hh
@@ -0,0 +1,50 @@
+#ifndef DUNE_GFE_PARALLEL_MAPPERFACTORY_HH
+#define DUNE_GFE_PARALLEL_MAPPERFACTORY_HH
+
+#include <dune/grid/utility/globalindexset.hh>
+#include <dune/gfe/parallel/globalmapper.hh>
+#include <dune/gfe/parallel/globalp1mapper.hh>
+#include <dune/gfe/parallel/globalp2mapper.hh>
+#include <dune/gfe/parallel/p2mapper.hh>
+
+namespace Dune::GFE
+{
+
+  /** \brief Assign GlobalMapper and LocalMapper types to a dune-functions function space basis */
+  template <typename Basis>
+  struct MapperFactory
+  {};
+
+  /** \brief Specialization for LagrangeBasis<1> */
+  template <typename GridView>
+  struct MapperFactory<Functions::LagrangeBasis<GridView,1> >
+  {
+    typedef Dune::GlobalP1Mapper<Functions::LagrangeBasis<GridView,1> > GlobalMapper;
+    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView> LocalMapper;
+    static LocalMapper createLocalMapper(const GridView& gridView)
+    {
+      return LocalMapper(gridView, Dune::mcmgVertexLayout());
+    }
+  };
+
+  template <typename GridView>
+  struct MapperFactory<Dune::Functions::LagrangeBasis<GridView,2> >
+  {
+    typedef Dune::GlobalP2Mapper<Functions::LagrangeBasis<GridView,2> > GlobalMapper;
+    typedef P2BasisMapper<GridView> LocalMapper;
+    static LocalMapper createLocalMapper(const GridView& gridView)
+    {
+      return LocalMapper(gridView);
+    }
+  };
+
+  /** \brief Specialization for LagrangeBasis<3> */
+  template <typename GridView>
+  struct MapperFactory<Dune::Functions::LagrangeBasis<GridView,3> >
+  {
+    // Error: we don't currently have a global P3 mapper
+  };
+
+}  // namespace Dune::GFE
+
+#endif
diff --git a/dune/gfe/riemannianpnsolver.cc b/dune/gfe/riemannianpnsolver.cc
index 2637f196b38f4415c6b638f031aeec6b94433d05..836d5b73efd0dbcaeb591a67864a642357fc5aa0 100644
--- a/dune/gfe/riemannianpnsolver.cc
+++ b/dune/gfe/riemannianpnsolver.cc
@@ -101,7 +101,7 @@ setup(const GridType& grid,
   operatorAssembler.assembleBulk(Dune::Fufem::istlMatrixBackend(localA), laplaceStiffness);
 
 #if HAVE_MPI
-  LocalMapper localMapper = MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
+  LocalMapper localMapper = Dune::GFE::MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
 
   MatrixCommunicator<GlobalMapper,
       typename GridType::LeafGridView,
@@ -194,7 +194,7 @@ void RiemannianProximalNewtonSolver<Basis,TargetSpace,Assembler>::solve()
   VectorCommunicator<GlobalMapper, typename GridType::LeafGridView::Communication, CorrectionType> vectorComm(*globalMapper_,
                                                                                                               grid_->leafGridView().comm(),
                                                                                                               0);
-  LocalMapper localMapper = MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
+  LocalMapper localMapper = Dune::GFE::MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
   MatrixCommunicator<GlobalMapper,
       typename GridType::LeafGridView,
       typename GridType::LeafGridView,
diff --git a/dune/gfe/riemannianpnsolver.hh b/dune/gfe/riemannianpnsolver.hh
index 03127e120da75f5167d91bb48ddd564b3edbbbfa..a0a0e7f611a7d115550f1037d7bda0e5c3b76af2 100644
--- a/dune/gfe/riemannianpnsolver.hh
+++ b/dune/gfe/riemannianpnsolver.hh
@@ -16,12 +16,9 @@
 #include <dune/solvers/solvers/iterativesolver.hh>
 #include <dune/solvers/solvers/cholmodsolver.hh>
 
-#include "riemanniantrsolver.hh"
-#include <dune/grid/utility/globalindexset.hh>
-#include <dune/gfe/parallel/globalmapper.hh>
-#include <dune/gfe/parallel/globalp1mapper.hh>
-#include <dune/gfe/parallel/globalp2mapper.hh>
-#include <dune/gfe/parallel/p2mapper.hh>
+#include <dune/gfe/assemblers/geodesicfeassembler.hh>
+#include <dune/gfe/parallel/mapperfactory.hh>
+
 
 /** \brief Riemannian proximal-newton solver for geodesic finite-element problems */
 template <class Basis, class TargetSpace, class Assembler = GeodesicFEAssembler<Basis,TargetSpace> >
@@ -44,8 +41,8 @@ class RiemannianProximalNewtonSolver
   typedef std::vector<TargetSpace>                                               SolutionType;
 
 #if HAVE_MPI
-  typedef typename MapperFactory<Basis>::GlobalMapper GlobalMapper;
-  typedef typename MapperFactory<Basis>::LocalMapper LocalMapper;
+  typedef typename Dune::GFE::MapperFactory<Basis>::GlobalMapper GlobalMapper;
+  typedef typename Dune::GFE::MapperFactory<Basis>::LocalMapper LocalMapper;
 #endif
 
   /** \brief Records information about the last run of the RiemannianProximalNewtonSolver
diff --git a/dune/gfe/riemanniantrsolver.cc b/dune/gfe/riemanniantrsolver.cc
index 941fdd15e3e2830dd648a8826f108ad4dec1dec5..c681055b06ae76e6d621305109c29ce3408bcdb6 100644
--- a/dune/gfe/riemanniantrsolver.cc
+++ b/dune/gfe/riemanniantrsolver.cc
@@ -164,7 +164,7 @@ setup(const GridType& grid,
   operatorAssembler.assembleBulk(Dune::Fufem::istlMatrixBackend(localA), laplaceStiffness);
 
 #if HAVE_MPI
-  LocalMapper localMapper = MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
+  LocalMapper localMapper = Dune::GFE::MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
 
   MatrixCommunicator<GlobalMapper,
       typename GridType::LeafGridView,
@@ -384,7 +384,7 @@ void RiemannianTrustRegionSolver<Basis,TargetSpace,Assembler>::solve()
   VectorCommunicator<GlobalMapper, typename GridType::LeafGridView::Communication, CorrectionType> vectorComm(*globalMapper_,
                                                                                                               grid_->leafGridView().comm(),
                                                                                                               0);
-  LocalMapper localMapper = MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
+  LocalMapper localMapper = Dune::GFE::MapperFactory<Basis>::createLocalMapper(grid_->leafGridView());
   MatrixCommunicator<GlobalMapper,
       typename GridType::LeafGridView,
       typename GridType::LeafGridView,
diff --git a/dune/gfe/riemanniantrsolver.hh b/dune/gfe/riemanniantrsolver.hh
index 5893dc357148ace6e59a4f17417f0005bfa52bd7..d2b000ac681a7606701f5dbc2f1cc703e315713a 100644
--- a/dune/gfe/riemanniantrsolver.hh
+++ b/dune/gfe/riemanniantrsolver.hh
@@ -17,46 +17,8 @@
 #include <dune/solvers/solvers/loopsolver.hh>
 
 #include <dune/gfe/assemblers/geodesicfeassembler.hh>
-#include <dune/grid/utility/globalindexset.hh>
-#include <dune/gfe/parallel/globalmapper.hh>
-#include <dune/gfe/parallel/globalp1mapper.hh>
-#include <dune/gfe/parallel/globalp2mapper.hh>
-#include <dune/gfe/parallel/p2mapper.hh>
-
-/** \brief Assign GlobalMapper and LocalMapper types to a dune-fufem FunctionSpaceBasis */
-template <typename Basis>
-struct MapperFactory
-{};
-
-/** \brief Specialization for LagrangeBasis<1> */
-template <typename GridView>
-struct MapperFactory<Dune::Functions::LagrangeBasis<GridView,1> >
-{
-  typedef Dune::GlobalP1Mapper<Dune::Functions::LagrangeBasis<GridView,1> > GlobalMapper;
-  typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView> LocalMapper;
-  static LocalMapper createLocalMapper(const GridView& gridView)
-  {
-    return LocalMapper(gridView, Dune::mcmgVertexLayout());
-  }
-};
+#include <dune/gfe/parallel/mapperfactory.hh>
 
-template <typename GridView>
-struct MapperFactory<Dune::Functions::LagrangeBasis<GridView,2> >
-{
-  typedef Dune::GlobalP2Mapper<Dune::Functions::LagrangeBasis<GridView,2> > GlobalMapper;
-  typedef P2BasisMapper<GridView> LocalMapper;
-  static LocalMapper createLocalMapper(const GridView& gridView)
-  {
-    return LocalMapper(gridView);
-  }
-};
-
-/** \brief Specialization for LagrangeBasis<3> */
-template <typename GridView>
-struct MapperFactory<Dune::Functions::LagrangeBasis<GridView,3> >
-{
-  // Error: we don't currently have a global P3 mapper
-};
 
 /** \brief Riemannian trust-region solver for geodesic finite-element problems */
 template <class Basis, class TargetSpace, class Assembler = GeodesicFEAssembler<Basis,TargetSpace> >
@@ -79,8 +41,8 @@ class RiemannianTrustRegionSolver
   typedef std::vector<TargetSpace>                                               SolutionType;
 
 #if HAVE_MPI
-  typedef typename MapperFactory<Basis>::GlobalMapper GlobalMapper;
-  typedef typename MapperFactory<Basis>::LocalMapper LocalMapper;
+  typedef typename Dune::GFE::MapperFactory<Basis>::GlobalMapper GlobalMapper;
+  typedef typename Dune::GFE::MapperFactory<Basis>::LocalMapper LocalMapper;
 #endif
 
   /** \brief Records information about the last run of the RiemannianTrustRegionSolver
diff --git a/problems/cosserat-continuum-cantilever.parset b/problems/cosserat-continuum-cantilever.parset
index bfa21a8436ebefa2092dc2b059faac5f2d8323fd..ac1a07651c4e668550e5797e222e597df6073367 100644
--- a/problems/cosserat-continuum-cantilever.parset
+++ b/problems/cosserat-continuum-cantilever.parset
@@ -20,6 +20,9 @@ numLevels = 1
 # Number of homotopy steps for the Dirichlet boundary conditions
 numHomotopySteps = 1
 
+# Solver type: trustRegion or proximalNewton
+solvertype = trustRegion
+
 # Tolerance of the trust region solver
 tolerance = 1e-3
 
diff --git a/problems/film-on-substrate.parset b/problems/film-on-substrate.parset
index 1ce5db4b6676909c3c747f427fddc174dccbc3c7..8bfd20122b0ba089f52c008e4f21f3da2e779291 100644
--- a/problems/film-on-substrate.parset
+++ b/problems/film-on-substrate.parset
@@ -61,7 +61,7 @@ initialDeformation = "x"
 #  Solver parameters
 #############################################
 
-# Inner solver, cholmod or multigrid
+# Solver type: trustRegion or proximalNewton
 solvertype = trustRegion
 
 # Number of homotopy steps for the Dirichlet boundary conditions
diff --git a/src/cosserat-continuum.cc b/src/cosserat-continuum.cc
index ee4f3bd2335f24f577613a8605ecc0cc6762cca1..be9c92887f27d075a9bb6b765eab451d8a1733db 100644
--- a/src/cosserat-continuum.cc
+++ b/src/cosserat-continuum.cc
@@ -43,6 +43,8 @@
 #include <dune/foamgrid/foamgrid.hh>
 #endif
 
+#include <dune/istl/multitypeblockvector.hh>
+
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 #include <dune/functions/functionspacebases/compositebasis.hh>
 #include <dune/functions/functionspacebases/powerbasis.hh>
@@ -66,6 +68,7 @@
 #include <dune/gfe/assemblers/mixedgfeassembler.hh>
 
 #if MIXED_SPACE
+#include <dune/gfe/mixedriemannianpnsolver.hh>
 #include <dune/gfe/mixedriemanniantrsolver.hh>
 #else
 #include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>
@@ -504,31 +507,65 @@ int main (int argc, char *argv[]) try
           RealTuple<double,3>,
           Rotation<double,3> > mixedAssembler(compositeBasis, &localGFEADOLCStiffness);
 #if MIXED_SPACE
-      MixedRiemannianTrustRegionSolver<GridType,
-          CompositeBasis,
-          DeformationFEBasis, RealTuple<double,3>,
-          OrientationFEBasis, Rotation<double,3> > solver;
-      solver.setup(*grid,
-                   &mixedAssembler,
-                   deformationFEBasis,
-                   orientationFEBasis,
-                   x,
-                   deformationDirichletDofs,
-                   orientationDirichletDofs, tolerance,
-                   maxSolverSteps,
-                   initialTrustRegionRadius,
-                   multigridIterations,
-                   mgTolerance,
-                   mu, nu1, nu2,
-                   baseIterations,
-                   baseTolerance,
-                   instrumented);
+      if (parameterSet.get<std::string>("solvertype", "trustRegion") == "trustRegion")
+      {
 
-      solver.setScaling(parameterSet.get<FieldVector<double,6> >("solverScaling"));
+        MixedRiemannianTrustRegionSolver<GridType,
+            CompositeBasis,
+            DeformationFEBasis, RealTuple<double,3>,
+            OrientationFEBasis, Rotation<double,3> > solver;
+        solver.setup(*grid,
+                     &mixedAssembler,
+                     deformationFEBasis,
+                     orientationFEBasis,
+                     x,
+                     deformationDirichletDofs,
+                     orientationDirichletDofs, tolerance,
+                     maxSolverSteps,
+                     initialTrustRegionRadius,
+                     multigridIterations,
+                     mgTolerance,
+                     mu, nu1, nu2,
+                     baseIterations,
+                     baseTolerance,
+                     instrumented);
 
-      solver.setInitialIterate(x);
-      solver.solve();
-      x = solver.getSol();
+        solver.setScaling(parameterSet.get<FieldVector<double,6> >("solverScaling"));
+
+        solver.setInitialIterate(x);
+        solver.solve();
+        x = solver.getSol();
+      }
+      else
+      {
+        //Create BitVector matching the tangential space
+        const int dimRotationTangent = Rotation<double,3>::TangentVector::dimension;
+        using VectorForBit = MultiTypeBlockVector<std::vector<FieldVector<double,3> >, std::vector<FieldVector<double,dimRotationTangent> > >;
+        using BitVector = Solvers::DefaultBitVector_t<VectorForBit>;
+        BitVector dirichletDofs;
+        dirichletDofs[_0].resize(compositeBasis.size({0}));
+        dirichletDofs[_1].resize(compositeBasis.size({1}));
+        for (size_t i = 0; i < compositeBasis.size({0}); i++) {
+          for (size_t j = 0; j < 3; j++)
+            dirichletDofs[_0][i][j] = deformationDirichletDofs[i][j];
+        }
+        for (size_t i = 0; i < compositeBasis.size({1}); i++) {
+          for (int j = 0; j < dimRotationTangent; j++)
+            dirichletDofs[_1][i][j] = orientationDirichletDofs[i][j];
+        }
+        GFE::MixedRiemannianProximalNewtonSolver<CompositeBasis, DeformationFEBasis, RealTuple<double,3>, OrientationFEBasis, Rotation<double,3>, BitVector> solver;
+        solver.setup(*grid,
+                     &mixedAssembler,
+                     x,
+                     dirichletDofs,
+                     tolerance,
+                     maxSolverSteps,
+                     initialRegularization,
+                     instrumented);
+        solver.setInitialIterate(x);
+        solver.solve();
+        x = solver.getSol();
+      }
 #else
       //The MixedRiemannianTrustRegionSolver can treat the Displacement and Orientation Space as separate ones
       //The RiemannianTrustRegionSolver can only treat the Displacement and Rotation together in a ProductManifold.
diff --git a/src/film-on-substrate.cc b/src/film-on-substrate.cc
index 0630bf58bb61cff74976e897171a95bc4248ed0f..97fc8ef8d204ed73bf7a83099e9be19e6980a47b 100644
--- a/src/film-on-substrate.cc
+++ b/src/film-on-substrate.cc
@@ -64,6 +64,7 @@
 #include <dune/gfe/assemblers/sumenergy.hh>
 
 #if MIXED_SPACE
+#include <dune/gfe/mixedriemannianpnsolver.hh>
 #include <dune/gfe/mixedriemanniantrsolver.hh>
 #else
 #include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>
@@ -650,7 +651,18 @@ int main (int argc, char *argv[]) try
     } else { //parameterSet.get<std::string>("solvertype") == "proximalNewton"
 
 #if MIXED_SPACE
-      DUNE_THROW(Exception, "Error: There is no MixedRiemannianProximalNewtonSolver!");
+      GFE::MixedRiemannianProximalNewtonSolver<CompositeBasis, DeformationFEBasis, RealTuple<double,dim>, OrientationFEBasis, Rotation<double,dim>, BitVector> solver;
+      solver.setup(*grid,
+                   &mixedAssembler,
+                   x,
+                   dirichletDofs,
+                   tolerance,
+                   maxSolverSteps,
+                   initialRegularization,
+                   instrumented);
+      solver.setInitialIterate(x);
+      solver.solve();
+      x = solver.getSol();
 #else
       RiemannianProximalNewtonSolver<DeformationFEBasis, RBM, GFEAssemblerWrapper> solver;
       solver.setup(*grid,
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ffc3b7de3a65709af4186567953694f9f1c0b114..62f600662aa5d725784d125a0f335efc9b5f48a7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -53,6 +53,11 @@ dune_add_test(SOURCES geodesicfeassemblerwrappertest.cc
               TIMEOUT 600
               CMAKE_GUARD MPI_FOUND)
 
+dune_add_test(SOURCES mixedriemannianpnsolvertest.cc
+              MPI_RANKS 1 4
+              TIMEOUT 600
+              CMAKE_GUARD MPI_FOUND)
+
 # Copy the example grid used for testing into the build dir
 file(COPY grids/irregular-square.msh DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/grids)
 
diff --git a/test/filmonsubstratetest.cc b/test/filmonsubstratetest.cc
index 876871dfe33adb8ae69c98dd06ffce1f65f6cbff..c9b40dda93a72713d1e2cc7b0034606e64856fed 100644
--- a/test/filmonsubstratetest.cc
+++ b/test/filmonsubstratetest.cc
@@ -47,6 +47,7 @@
 #include <dune/gfe/assemblers/sumenergy.hh>
 
 #if MIXED_SPACE
+#include <dune/gfe/mixedriemannianpnsolver.hh>
 #include <dune/gfe/mixedriemanniantrsolver.hh>
 #else
 #include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>
@@ -458,7 +459,18 @@ int main (int argc, char *argv[])
   } else {    // solverType == "proximalNewton"
 
 #if MIXED_SPACE
-    DUNE_THROW(Exception, "Error: There is no MixedRiemannianProximalNewtonSolver!");
+    GFE::MixedRiemannianProximalNewtonSolver<CompositeBasis, DeformationFEBasis, RealTuple<double,dim>, OrientationFEBasis, Rotation<double,dim>, BitVector> solver;
+    solver.setup(*grid,
+                 &mixedAssembler,
+                 x,
+                 dirichletDofs,
+                 tolerance,
+                 maxSolverSteps,
+                 1.0 /* initialRegularization */,
+                 false /* instrumented */);
+    solver.setInitialIterate(x);
+    solver.solve();
+    x = solver.getSol();
 #else
     RiemannianProximalNewtonSolver<DeformationFEBasis, RBM, GFEAssemblerWrapper> solver;
     solver.setup(*grid,
diff --git a/test/geodesicfeassemblerwrappertest.cc b/test/geodesicfeassemblerwrappertest.cc
index 175cc0b900b8536a2a4f8d3f5687e6ce9b074971..ae8ab8457fafb6adf4c4a58c3afa270f63f43c36 100644
--- a/test/geodesicfeassemblerwrappertest.cc
+++ b/test/geodesicfeassemblerwrappertest.cc
@@ -15,7 +15,6 @@
 #include <dune/functions/functionspacebases/interpolate.hh>
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 #include <dune/functions/functionspacebases/powerbasis.hh>
-#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
 
 #include <dune/fufem/boundarypatch.hh>
 
@@ -25,9 +24,7 @@
 #include <dune/gfe/assemblers/cosseratenergystiffness.hh>
 #include <dune/gfe/assemblers/geodesicfeassembler.hh>
 #include <dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh>
-#include <dune/gfe/localprojectedfefunction.hh>
 #include <dune/gfe/assemblers/mixedgfeassembler.hh>
-#include <dune/gfe/riemanniantrsolver.hh>
 #include <dune/gfe/spaces/productmanifold.hh>
 #include <dune/gfe/spaces/realtuple.hh>
 #include <dune/gfe/spaces/rotation.hh>
@@ -50,8 +47,6 @@ const int rotationOrder = 2;
 using namespace Dune;
 using namespace Indices;
 
-//differentiation method: ADOL-C
-using ValueType = adouble;
 
 //Types for the mixed space
 using DisplacementVector = std::vector<RealTuple<double,dim> >;
diff --git a/test/mixedriemannianpnsolvertest.cc b/test/mixedriemannianpnsolvertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..db6b4affb5d126dfa1c82089508a37a78443dee3
--- /dev/null
+++ b/test/mixedriemannianpnsolvertest.cc
@@ -0,0 +1,276 @@
+#include <config.h>
+
+// Includes for the ADOL-C automatic differentiation library
+// Need to come before (almost) all others.
+#include <adolc/adouble.h>
+#include <dune/fufem/utilities/adolcnamespaceinjections.hh>
+
+#include <dune/common/bitsetvector.hh>
+#include <dune/common/typetraits.hh>
+#include <dune/common/tuplevector.hh>
+
+#include <dune/functions/functionspacebases/compositebasis.hh>
+#include <dune/functions/functionspacebases/interpolate.hh>
+#include <dune/functions/functionspacebases/lagrangebasis.hh>
+#include <dune/functions/functionspacebases/powerbasis.hh>
+
+#include <dune/fufem/boundarypatch.hh>
+#include <dune/fufem/functiontools/boundarydofs.hh>
+
+#include <dune/grid/utility/structuredgridfactory.hh>
+#include <dune/grid/uggrid.hh>
+
+#include <dune/gfe/assemblers/cosseratenergystiffness.hh>
+#include <dune/gfe/assemblers/geodesicfeassembler.hh>
+#include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>
+#include <dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh>
+#include <dune/gfe/assemblers/mixedgfeassembler.hh>
+#include <dune/gfe/mixedriemannianpnsolver.hh>
+#include <dune/gfe/riemannianpnsolver.hh>
+#include <dune/gfe/spaces/productmanifold.hh>
+#include <dune/gfe/spaces/realtuple.hh>
+#include <dune/gfe/spaces/rotation.hh>
+
+/** \file
+ * \brief This test compares the MixedRiemannianPNSolver to the RiemannianPNSolver.
+ */
+
+// grid dimension
+const int gridDim = 2;
+
+// target dimension
+const int dim = 3;
+
+//order of the finite element spaces, they need to be the same to compare!
+const int displacementOrder = 2;
+const int rotationOrder = displacementOrder;
+
+using namespace Dune;
+using namespace Indices;
+
+//differentiation method: ADOL-C
+using ValueType = adouble;
+
+//Types for the mixed space
+using DisplacementVector = std::vector<RealTuple<double,dim> >;
+using RotationVector =  std::vector<Rotation<double,dim> >;
+using Vector = TupleVector<DisplacementVector, RotationVector>;
+using BlockTupleVector = TupleVector<BlockVector<RealTuple<double,dim> >, BlockVector<Rotation<double,dim> > >;
+const int dimRotationTangent = Rotation<double,dim>::TangentVector::dimension;
+
+
+int main (int argc, char *argv[])
+{
+  MPIHelper::instance(argc, argv);
+
+  /////////////////////////////////////////////////////////////////////////
+  //    Create the grid
+  /////////////////////////////////////////////////////////////////////////
+  using GridType = UGGrid<gridDim>;
+  auto grid = StructuredGridFactory<GridType>::createCubeGrid({0.0,0.0}, {1.0,1.0}, {2,2});
+  grid->globalRefine(2);
+  grid->loadBalance();
+
+  using GridView = GridType::LeafGridView;
+  GridView gridView = grid->leafGridView();
+
+  /////////////////////////////////////////////////////////////////////////
+  //  Create a composite basis and a Lagrange FE basis
+  /////////////////////////////////////////////////////////////////////////
+
+  using namespace Functions::BasisFactory;
+
+  auto compositeBasis = makeBasis(
+    gridView,
+    composite(
+      power<dim>(
+        lagrange<displacementOrder>()
+        ),
+      power<dim>(
+        lagrange<rotationOrder>()
+        )
+      ));
+
+  using CompositeBasis = decltype(compositeBasis);
+
+  using DeformationFEBasis = Functions::LagrangeBasis<GridView,displacementOrder>;
+  DeformationFEBasis deformationFEBasis(gridView);
+
+  /////////////////////////////////////////////////////////////////////////
+  //  Create the Neumann and Dirichlet boundary
+  /////////////////////////////////////////////////////////////////////////
+
+  std::function<bool(FieldVector<double,gridDim>)> isNeumann = [](FieldVector<double,gridDim> coordinate) {
+                                                                 return coordinate[0] > 0.99; //Neumann for upper boundary
+                                                               };
+  std::function<bool(FieldVector<double,gridDim>)> isDirichlet = [](FieldVector<double,gridDim> coordinate) {
+                                                                   return coordinate[0] < 0.01; //Dircichlet for lower boundary
+                                                                 };
+
+  BitSetVector<1> neumannVertices(gridView.size(gridDim), false);
+  BitSetVector<1> dirichletVertices(gridView.size(gridDim), false);
+  const GridView::IndexSet& indexSet = gridView.indexSet();
+
+  for (auto&& vertex : vertices(gridView)) {
+    neumannVertices[indexSet.index(vertex)] = isNeumann(vertex.geometry().corner(0));
+    dirichletVertices[indexSet.index(vertex)] = isDirichlet(vertex.geometry().corner(0));
+  }
+
+  BoundaryPatch<GridView> neumannBoundary(gridView, neumannVertices);
+  BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices);
+
+  BitSetVector<1> dirichletNodes(compositeBasis.size({0}),false);
+#if DUNE_VERSION_GTE(DUNE_FUFEM, 2, 10)
+  Fufem::markBoundaryPatchDofs(dirichletBoundary, deformationFEBasis, dirichletNodes);
+#else
+  constructBoundaryDofs(dirichletBoundary, deformationFEBasis, dirichletNodes);
+#endif
+
+  typedef MultiTypeBlockVector<std::vector<FieldVector<double,dim> >, std::vector<FieldVector<double,dimRotationTangent> > > VectorForBit;
+  using BitVector = Solvers::DefaultBitVector_t<VectorForBit>;
+
+  BitVector dirichletDofs;
+  dirichletDofs[_0].resize(compositeBasis.size({0}));
+  dirichletDofs[_1].resize(compositeBasis.size({1}));
+  for (size_t i = 0; i < compositeBasis.size({0}); i++) {
+    for (size_t j = 0; j < dim; j++)
+      dirichletDofs[_0][i][j] = dirichletNodes[i][0];
+    for (size_t j = 0; j < dimRotationTangent; j++)
+      dirichletDofs[_1][i][j] = dirichletNodes[i][0];
+  }
+
+  /////////////////////////////////////////////////////////////////////////
+  //  Create the energy functions with their parameters
+  /////////////////////////////////////////////////////////////////////////
+
+  //Surface-Cosserat-Energy-Parameters
+  ParameterTree parameters;
+  parameters["thickness"] = "1";
+  parameters["mu"] = "2.7191e+4";
+  parameters["lambda"] = "4.4364e+4";
+  parameters["mu_c"] = "0";
+  parameters["L_c"] = "0.01";
+  parameters["q"] = "2";
+  parameters["kappa"] = "1";
+
+  parameters["b1"] = "1";
+  parameters["b2"] = "1";
+  parameters["b3"] = "1";
+
+
+  FieldVector<double,dim> values_ = {3e4,2e4,1e4};
+  auto neumannFunction = [&](FieldVector<double, gridDim>){
+                           return values_;
+                         };
+
+  CosseratEnergyLocalStiffness<decltype(compositeBasis), dim, ValueType> cosseratEnergy(parameters,
+                                                                                        &neumannBoundary,
+                                                                                        neumannFunction,
+                                                                                        nullptr);
+
+  using RBM = GFE::ProductManifold<RealTuple<double,dim>, Rotation<double, dim> >;
+
+  LocalGeodesicFEADOLCStiffness<CompositeBasis,RBM> mixedLocalGFEADOLCStiffness(&cosseratEnergy);
+
+  MixedGFEAssembler<CompositeBasis,
+      RealTuple<double,dim>,
+      Rotation<double,dim> > mixedAssembler(compositeBasis, &mixedLocalGFEADOLCStiffness);
+
+  using GFEAssemblerWrapper = GFE::GeodesicFEAssemblerWrapper<CompositeBasis, DeformationFEBasis, RBM, RealTuple<double, dim>, Rotation<double,dim> >;
+  GFEAssemblerWrapper assembler(&mixedAssembler, deformationFEBasis);
+
+  /////////////////////////////////////////////////////////////////////////
+  //  Prepare the iterate x where we want to assemble - identity in 2D with z = 0
+  /////////////////////////////////////////////////////////////////////////
+  auto deformationPowerBasis = makeBasis(
+    gridView,
+    power<gridDim>(
+      lagrange<displacementOrder>()
+      ));
+  BlockVector<FieldVector<double,gridDim> > identity(compositeBasis.size({0}));
+  Functions::interpolate(deformationPowerBasis, identity, [](FieldVector<double,gridDim> x){
+    return x;
+  });
+  BlockVector<FieldVector<double,dim> > initialDeformation(compositeBasis.size({0}));
+  initialDeformation = 0;
+
+  Vector x;
+  x[_0].resize(compositeBasis.size({0}));
+  x[_1].resize(compositeBasis.size({1}));
+  std::vector<RBM> xRBM(compositeBasis.size({0}));
+  BitSetVector<RBM::TangentVector::dimension> dirichletDofsRBM(compositeBasis.size({0}), false);
+
+  for (std::size_t i = 0; i < compositeBasis.size({0}); i++) {
+    for (int j = 0; j < gridDim; j++)
+      initialDeformation[i][j] = identity[i][j];
+    x[_0][i] = initialDeformation[i];
+    xRBM[i][_0] = x[_0][i];
+    for (int j = 0; j < dim; j ++) { // Displacement part
+      dirichletDofsRBM[i][j] = dirichletDofs[_0][i][j];
+    }
+    xRBM[i][_1] = x[_1][i]; // Rotation part
+    for (int j = dim; j < RBM::TangentVector::dimension; j ++)
+      dirichletDofsRBM[i][j] = dirichletDofs[_1][i][j-dim];
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //  Create a MixedRiemannianPNSolver and a normal RiemannianPNSolver
+  //  and compare one solver step!
+  //////////////////////////////////////////////////////////////////////////////
+
+  const double tolerance = 1e-7;
+  const int maxSolverSteps = 1;
+  const double initialRegularization = 100;
+  const bool instrumented = false;
+  GFE::MixedRiemannianProximalNewtonSolver<CompositeBasis, DeformationFEBasis, RealTuple<double,dim>, DeformationFEBasis, Rotation<double,dim>, BitVector> mixedSolver;
+  mixedSolver.setup(*grid,
+                    &mixedAssembler,
+                    x,
+                    dirichletDofs,
+                    tolerance,
+                    maxSolverSteps,
+                    initialRegularization,
+                    instrumented);
+  mixedSolver.setInitialIterate(x);
+  mixedSolver.solve();
+  x = mixedSolver.getSol();
+
+  RiemannianProximalNewtonSolver<DeformationFEBasis, RBM, GFEAssemblerWrapper> solver;
+  solver.setup(*grid,
+               &assembler,
+               xRBM,
+               dirichletDofsRBM,
+               tolerance,
+               maxSolverSteps,
+               initialRegularization,
+               instrumented);
+  solver.setInitialIterate(xRBM);
+  solver.solve();
+  xRBM = solver.getSol();
+
+  BlockTupleVector xMixed;
+  BlockTupleVector xNotMixed;
+  xNotMixed[_0].resize(compositeBasis.size({0}));
+  xNotMixed[_1].resize(compositeBasis.size({1}));
+  xMixed[_0].resize(compositeBasis.size({0}));
+  xMixed[_1].resize(compositeBasis.size({1}));
+  for (std::size_t i = 0; i < xRBM.size(); i++)
+  {
+    xNotMixed[_0][i] = xRBM[i][_0];
+    xNotMixed[_1][i] = xRBM[i][_1];
+    xMixed[_0][i] = x[_0][i];
+    xMixed[_1][i] = x[_1][i];
+    auto difference0 = xMixed[_0][i].globalCoordinates();
+    auto difference1 = xMixed[_1][i].globalCoordinates();
+    difference0 -= xNotMixed[_0][i].globalCoordinates();
+    difference1 -= xNotMixed[_1][i].globalCoordinates();
+    if (difference0.two_norm() > 1e-1 || difference1.two_norm() > 1e-1) {
+      std::cerr << std::setprecision(9);
+      std::cerr << "At index " << i << " the solution calculated by the MixedRiemannianPNSolver is "
+                << xMixed[_0][i] << " and " << xMixed[_1][i] << " but "
+                << xNotMixed[_0][i] << " and " << xNotMixed[_1][i]
+                << " (calculated by the RiemannianProximalNewtonSolver) was expected!" << std::endl;
+      return 1;
+    }
+  }
+}