diff --git a/dune/gfe/mixedlocalgfeadolcstiffness.hh b/dune/gfe/mixedlocalgfeadolcstiffness.hh
index ddf89f9637cfe2bb06a2f1b28dd8f9cbadff10b8..75a34a0ae6ac4151be5c64ae9be782e43fb7e16b 100644
--- a/dune/gfe/mixedlocalgfeadolcstiffness.hh
+++ b/dune/gfe/mixedlocalgfeadolcstiffness.hh
@@ -86,12 +86,13 @@ energy(const typename Basis::LocalView& localView,
        const std::vector<TargetSpace0>& localConfiguration0,
        const std::vector<TargetSpace1>& localConfiguration1) const
 {
+    int rank = Dune::MPIHelper::getCollectiveCommunication().rank();
     double pureEnergy;
 
     std::vector<ATargetSpace0> localAConfiguration0(localConfiguration0.size());
     std::vector<ATargetSpace1> localAConfiguration1(localConfiguration1.size());
 
-    trace_on(1);
+    trace_on(rank);
 
     adouble energy = 0;
 
@@ -122,10 +123,14 @@ energy(const typename Basis::LocalView& localView,
     }
 
     using namespace Dune::TypeTree::Indices;
-    energy = localEnergy_->energy(localView,
+    try {
+        energy = localEnergy_->energy(localView,
                                   localAConfiguration0,
                                   localAConfiguration1);
-
+    } catch (Dune::Exception &e) {
+        trace_off();
+        throw e;
+    }
     energy >>= pureEnergy;
 
     trace_off();
@@ -197,6 +202,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView,
                            std::vector<typename TargetSpace0::TangentVector>& localGradient0,
                            std::vector<typename TargetSpace1::TangentVector>& localGradient1)
 {
+    int rank = Dune::MPIHelper::getCollectiveCommunication().rank();
     // Tape energy computation.  We may not have to do this every time, but it's comparatively cheap.
     energy(localView, localConfiguration0, localConfiguration1);
 
@@ -222,7 +228,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView,
 
   // Compute gradient
     std::vector<double> g(nDoubles);
-    gradient(1,nDoubles,xp.data(),g.data());                  // gradient evaluation
+    gradient(rank,nDoubles,xp.data(),g.data());                  // gradient evaluation
 
     // Copy into Dune type
     std::vector<typename TargetSpace0::EmbeddedTangentVector> localEmbeddedGradient0(localConfiguration0.size());
@@ -338,7 +344,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView,
       for (int i=0; i<embeddedBlocksize1; i++)
         tangent[nDofs0*embeddedBlocksize0 + (j/blocksize1)*embeddedBlocksize1+i][nDofs0*blocksize0 + j] = orthonormalFrame1[j/blocksize1][j%blocksize1][i];
 
-    hess_mat(1,nDoubles,nDirections,xp.data(),tangent,rawHessian);
+    hess_mat(rank,nDoubles,nDirections,xp.data(),tangent,rawHessian);
 
     // Copy Hessian into Dune data type
     size_t offset0 = nDofs0*embeddedBlocksize0;
diff --git a/dune/gfe/mixedriemanniantrsolver.cc b/dune/gfe/mixedriemanniantrsolver.cc
index c09c7bf0e2fef75761b54e8d6be06391031f7640..2cd74a7ee6a9956e54588af84fdc364137a4cad5 100644
--- a/dune/gfe/mixedriemanniantrsolver.cc
+++ b/dune/gfe/mixedriemanniantrsolver.cc
@@ -385,6 +385,7 @@ void MixedRiemannianTrustRegionSolver<GridType,Basis,Basis0,TargetSpace0,Basis1,
         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)
         {
@@ -405,35 +406,46 @@ void MixedRiemannianTrustRegionSolver<GridType,Basis,Basis0,TargetSpace0,Basis1,
 
             mmgStep1->preprocess();
 
+            ///////////////////////////////
+            //    Solve !
+            ///////////////////////////////
 
             std::cout << "Solve quadratic problem..." << std::endl;
             double oldEnergy = 0;
             Dune::Timer solutionTimer;
-            for (int ii=0; ii<innerIterations_; ii++)
-            {
-              residual[_0] = rhs_global[_0];
-              stiffnessMatrix[_0][_1].mmv(corr_global[_1], residual[_0]);
-              mmgStep0->setRhs(residual[_0]);
-              mmgStep0->iterate();
-
-              residual[_1] = rhs_global[_1];
-              stiffnessMatrix[_1][_0].mmv(corr_global[_0], residual[_1]);
-              mmgStep1->setRhs(residual[_1]);
-              mmgStep1->iterate();
-
-              // Compute energy
-              CorrectionType tmp(corr_global);
-              stiffnessMatrix.mv(corr_global,tmp);
-              double energy = 0.5 * (tmp*corr_global) - (rhs_global*corr_global);
-
-              if (energy > oldEnergy)
-                //DUNE_THROW(Dune::Exception, "energy increase!");
-                std::cout << "Warning: energy increase!" << std::endl;
-
-              oldEnergy = energy;
+            int ii = 0;
+            try {
+              for (; ii<innerIterations_; ii++) {
+                residual[_0] = rhs_global[_0];
+                stiffnessMatrix[_0][_1].mmv(corr_global[_1], residual[_0]);
+                mmgStep0->setRhs(residual[_0]);
+                mmgStep0->iterate();
+  
+                residual[_1] = rhs_global[_1];
+                stiffnessMatrix[_1][_0].mmv(corr_global[_0], residual[_1]);
+                mmgStep1->setRhs(residual[_1]);
+                mmgStep1->iterate();
+  
+                // Compute energy
+                CorrectionType tmp(corr_global);
+                stiffnessMatrix.mv(corr_global,tmp);
+                double energy = 0.5 * (tmp*corr_global) - (rhs_global*corr_global);
+  
+                if (energy > oldEnergy)
+                  //DUNE_THROW(Dune::Exception, "energy increase!");
+                  std::cout << "Warning: energy increase!" << std::endl;
+  
+                oldEnergy = energy;
+                if (corr_global.infinity_norm() < innerTolerance_)
+                  break;
+              }
+            } 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;
+            std::cout << "Solving the quadratic problem took " << solutionTimer.elapsed() << " seconds and " << ii << " steps." << std::endl;
 
             //std::cout << "Correction: " << std::endl << corr_global << std::endl;
 
@@ -445,73 +457,88 @@ void MixedRiemannianTrustRegionSolver<GridType,Basis,Basis0,TargetSpace0,Basis1,
 
         //corr = vectorComm.scatter(corr_global);
         corr = corr_global;
-
-        if (this->verbosity_ == NumProc::FULL)
-            std::cout << "Infinity norm of the correction: " << corr.infinity_norm() << std::endl;
-
-        if (corr_global.infinity_norm() < 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 << " trust-region steps were taken." << std::endl;
-            break;
-        }
-
-        // ////////////////////////////////////////////////////
-        //   Check whether trust-region step can be accepted
-        // ////////////////////////////////////////////////////
-
+        double energy = 0;
+        double modelDecrease = 0;
         SolutionType newIterate = x_;
-        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]);
-
-        double energy    = assembler_->computeEnergy(newIterate[_0],newIterate[_1]);
-        energy = mpiHelper.getCollectiveCommunication().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);
-        double modelDecrease = rhs*corr - 0.5 * (corr*tmp);
-        modelDecrease = mpiHelper.getCollectiveCommunication().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;
-        }
+        if (solvedByInnerSolver) {
+
+          if (this->verbosity_ == NumProc::FULL)
+              std::cout << "Infinity norm of the correction: " << corr.infinity_norm() << std::endl;
+
+          if (corr_global.infinity_norm() < 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 << " trust-region steps were taken." << std::endl;
+              break;
+          }
+
+          // ////////////////////////////////////////////////////
+          //   Check whether trust-region 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 trust region step with smaller radius..." << std::endl;
+            newIterate = x_;
+            solvedByInnerSolver = false;
+            energy = oldEnergy;
+          }
+
+          if (solvedByInnerSolver) {
+            energy = mpiHelper.getCollectiveCommunication().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 = mpiHelper.getCollectiveCommunication().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);
+            assert(modelDecrease >= 0);
 
-        if (energy >= oldEnergy and rank==0) {
-            if (this->verbosity_ == NumProc::FULL)
-                printf("Richtung ist keine Abstiegsrichtung!\n");
-        }
+            if (energy >= oldEnergy and rank==0) {
+                if (this->verbosity_ == NumProc::FULL)
+                    printf("Richtung ist keine Abstiegsrichtung!\n");
+            }
 
-        if (energy >= oldEnergy &&
-            (std::abs((oldEnergy-energy)/energy) < 1e-9 || relativeModelDecrease < 1e-9)) {
-            if (this->verbosity_ == NumProc::FULL and rank==0)
-                std::cout << "Suspecting rounding problems" << std::endl;
+            if (energy >= oldEnergy &&
+                (std::abs((oldEnergy-energy)/energy) < 1e-9 || relativeModelDecrease < 1e-9)) {
+                if (this->verbosity_ == NumProc::FULL and rank==0)
+                    std::cout << "Suspecting rounding problems" << std::endl;
 
-            if (this->verbosity_ != NumProc::QUIET and rank==0)
-                std::cout << i+1 << " trust-region steps were taken." << std::endl;
+                if (this->verbosity_ != NumProc::QUIET and rank==0)
+                    std::cout << i+1 << " trust-region steps were taken." << std::endl;
 
-            x_ = newIterate;
-            break;
-        }
+                x_ = newIterate;
+                break;
+            }
 
+          }
+        }
         // //////////////////////////////////////////////
         //   Check for acceptance of the step
         // //////////////////////////////////////////////
-        if ( (oldEnergy-energy) / modelDecrease > 0.9) {
+        if ( solvedByInnerSolver && (oldEnergy-energy) / modelDecrease > 0.9) {
             // very successful iteration
 
             x_ = newIterate;
@@ -523,7 +550,7 @@ void MixedRiemannianTrustRegionSolver<GridType,Basis,Basis0,TargetSpace0,Basis1,
 
             recomputeGradientHessian = true;
 
-        } else if ( (oldEnergy-energy) / modelDecrease > 0.01
+        } else if (solvedByInnerSolver && (oldEnergy-energy) / modelDecrease > 0.01
                     || std::abs(oldEnergy-energy) < 1e-12) {
             // successful iteration
             x_ = newIterate;
diff --git a/dune/gfe/realtuple.hh b/dune/gfe/realtuple.hh
index 5d47b0d178b959b9b8465589e8b66b5a66042ff0..c1f52db2e40acabdc6345ae94e88ed3beddf0616 100644
--- a/dune/gfe/realtuple.hh
+++ b/dune/gfe/realtuple.hh
@@ -66,6 +66,17 @@ public:
         return *this;
     }
 
+    RealTuple& operator-=(const Dune::FieldVector<T,N>& other) {
+        data_ -= other;
+        return *this;
+    }
+
+    template <class T2>
+    RealTuple& operator-=(const RealTuple<T2,N>& other) {
+        data_ -= other.data_;
+        return *this;
+    }
+
     /** \brief Assigment from RealTuple with different type -- used for automatic differentiation with ADOL-C */
     template <class T2>
     RealTuple& operator <<= (const RealTuple<T2,N>& other) {
@@ -74,6 +85,11 @@ public:
         return *this;
     }
 
+    /** \brief Const random-access operator*/
+    T operator[] (const size_t indexVariable ) const {
+        return data_[indexVariable];
+    }
+
      /** \brief Rebind the RealTuple to another coordinate type */
     template<class U>
     struct rebind
diff --git a/dune/gfe/riemannianpnsolver.cc b/dune/gfe/riemannianpnsolver.cc
index 0324629b6f6603a7d0c6d56932b0f645e80dcd55..4937720c4adabd0abb1ce46a66eed4ab1a2605be 100644
--- a/dune/gfe/riemannianpnsolver.cc
+++ b/dune/gfe/riemannianpnsolver.cc
@@ -22,10 +22,10 @@
 #include <dune/gfe/parallel/vectorcommunicator.hh>
 #endif
 
-template <class Basis, class TargetSpace>
-void RiemannianProximalNewtonSolver<Basis,TargetSpace>::
+template <class Basis, class TargetSpace, class Assembler>
+void RiemannianProximalNewtonSolver<Basis,TargetSpace,Assembler>::
 setup(const GridType& grid,
-      const GeodesicFEAssembler<Basis, TargetSpace>* assembler,
+      const Assembler* assembler,
       const SolutionType& x,
       const Dune::BitSetVector<blocksize>& dirichletNodes,
       double tolerance,
@@ -150,8 +150,8 @@ setup(const GridType& grid,
 }
 
 
-template <class Basis, class TargetSpace>
-void RiemannianProximalNewtonSolver<Basis,TargetSpace>::solve()
+template <class Basis, class TargetSpace, class Assembler>
+void RiemannianProximalNewtonSolver<Basis,TargetSpace,Assembler>::solve()
 {
     int rank = grid_->comm().rank();
 
diff --git a/dune/gfe/riemannianpnsolver.hh b/dune/gfe/riemannianpnsolver.hh
index a1c1aca5605b2e1c6fd8a579f562295ecfc39f9a..1024a72a7aaa1fe36268c2a84a02f98af279c8b4 100644
--- a/dune/gfe/riemannianpnsolver.hh
+++ b/dune/gfe/riemannianpnsolver.hh
@@ -17,7 +17,6 @@
 
 #include <dune/gfe/periodic1dpq1nodalbasis.hh>
 
-#include "geodesicfeassembler.hh"
 #include "riemanniantrsolver.hh"
 #include <dune/grid/utility/globalindexset.hh>
 #include <dune/gfe/parallel/globalmapper.hh>
@@ -26,7 +25,7 @@
 #include <dune/gfe/parallel/p2mapper.hh>
 
 /** \brief Riemannian proximal-newton solver for geodesic finite-element problems */
-template <class Basis, class TargetSpace>
+template <class Basis, class TargetSpace, class Assembler = GeodesicFEAssembler<Basis,TargetSpace>>
 class RiemannianProximalNewtonSolver
     : public IterativeSolver<std::vector<TargetSpace>,
                              Dune::BitSetVector<TargetSpace::TangentVector::dimension> >
@@ -70,7 +69,7 @@ public:
 
     /** \brief Set up the solver using a choldmod solver as the inner solver */
     void setup(const GridType& grid,
-               const GeodesicFEAssembler<Basis, TargetSpace>* assembler,
+               const Assembler* assembler,
                const SolutionType& x,
                const Dune::BitSetVector<blocksize>& dirichletNodes,
                double tolerance,
@@ -121,7 +120,7 @@ protected:
     std::unique_ptr<MatrixType> hessianMatrix_;
 
     /** \brief The assembler for the material law */
-    const GeodesicFEAssembler<Basis, TargetSpace>* assembler_;
+    const Assembler* assembler_;
 
     /** \brief The solver for the quadratic inner problems */
     std::shared_ptr<typename Dune::Solvers::CholmodSolver<MatrixType,CorrectionType>> innerSolver_;
diff --git a/dune/gfe/riemanniantrsolver.cc b/dune/gfe/riemanniantrsolver.cc
index b8604dfc6c94f033342cbc61addc33454fd577fa..b45d502d01d5cf19495d1430d9e31c572112b456 100644
--- a/dune/gfe/riemanniantrsolver.cc
+++ b/dune/gfe/riemanniantrsolver.cc
@@ -28,10 +28,10 @@
 #include <dune/gfe/parallel/vectorcommunicator.hh>
 #endif
 
-template <class Basis, class TargetSpace>
-void RiemannianTrustRegionSolver<Basis,TargetSpace>::
+template <class Basis, class TargetSpace, class Assembler>
+void RiemannianTrustRegionSolver<Basis,TargetSpace,Assembler>::
 setup(const GridType& grid,
-      const GeodesicFEAssembler<Basis, TargetSpace>* assembler,
+      const Assembler* assembler,
          const SolutionType& x,
          const Dune::BitSetVector<blocksize>& dirichletNodes,
          double tolerance,
@@ -306,8 +306,8 @@ setup(const GridType& grid,
 }
 
 
-template <class Basis, class TargetSpace>
-void RiemannianTrustRegionSolver<Basis,TargetSpace>::solve()
+template <class Basis, class TargetSpace, class Assembler>
+void RiemannianTrustRegionSolver<Basis,TargetSpace,Assembler>::solve()
 {
     int rank = grid_->comm().rank();
 
diff --git a/dune/gfe/riemanniantrsolver.hh b/dune/gfe/riemanniantrsolver.hh
index 70c69ffa7a518e134910d8a9a23c439205e7bec1..3184c86f91dfbcbbd56177908ae5366f53a4fb03 100644
--- a/dune/gfe/riemanniantrsolver.hh
+++ b/dune/gfe/riemanniantrsolver.hh
@@ -69,7 +69,7 @@ struct MapperFactory<Dune::Functions::LagrangeBasis<GridView,3> >
 };
 
 /** \brief Riemannian trust-region solver for geodesic finite-element problems */
-template <class Basis, class TargetSpace>
+template <class Basis, class TargetSpace, class Assembler = GeodesicFEAssembler<Basis,TargetSpace>>
 class RiemannianTrustRegionSolver
     : public IterativeSolver<std::vector<TargetSpace>,
                              Dune::BitSetVector<TargetSpace::TangentVector::dimension> >
@@ -115,7 +115,7 @@ public:
 
     /** \brief Set up the solver using a monotone multigrid method as the inner solver */
     void setup(const GridType& grid,
-               const GeodesicFEAssembler<Basis, TargetSpace>* assembler,
+               const Assembler* assembler,
                const SolutionType& x,
                const Dune::BitSetVector<blocksize>& dirichletNodes,
                double tolerance,
@@ -188,7 +188,7 @@ protected:
     std::unique_ptr<MatrixType> hessianMatrix_;
 
     /** \brief The assembler for the material law */
-    const GeodesicFEAssembler<Basis, TargetSpace>* assembler_;
+    const Assembler* assembler_;
 
     /** \brief The solver for the quadratic inner problems */
     std::shared_ptr<Solver> innerSolver_;