From 47f79d16cd59d56bc8430a19eb9f1fa2157f05f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20He=C3=9F?= <rene.hess@iwr.uni-heidelberg.de>
Date: Tue, 20 Sep 2016 13:50:56 +0200
Subject: [PATCH] Add Marians matrix free stuff from exadune

---
 dune/perftool/matrixfree.hh             |  34 ++
 dune/perftool/matrixfreeistlbackends.hh | 111 +++++
 dune/perftool/matrixfreenewton.hh       | 521 ++++++++++++++++++++++++
 dune/perftool/newtonbase.hh             |  50 +++
 4 files changed, 716 insertions(+)
 create mode 100644 dune/perftool/matrixfreeistlbackends.hh
 create mode 100644 dune/perftool/matrixfreenewton.hh
 create mode 100644 dune/perftool/newtonbase.hh

diff --git a/dune/perftool/matrixfree.hh b/dune/perftool/matrixfree.hh
index b5bf65ff..180885fc 100644
--- a/dune/perftool/matrixfree.hh
+++ b/dune/perftool/matrixfree.hh
@@ -5,6 +5,9 @@
 
 #include <dune/pdelab/backend/istl/seqistlsolverbackend.hh>
 
+#include <dune/perftool/matrixfreeistlbackends.hh>
+#include <dune/perftool/matrixfreenewton.hh>
+
 namespace Dune{
   namespace PDELab{
 
@@ -25,6 +28,37 @@ namespace Dune{
       solverb.apply(z,r,stat);
       x -= z;
     }
+
+
+    template <typename GO, typename V>
+    void solveNonlinearMatrixFree(GO& go, V& x ){
+      // Matrix free operator
+      using ISTLOnTheFlyOperator = Dune::PDELab::NonlinearOnTheFlyOperator<V,V,GO>;
+      ISTLOnTheFlyOperator op(go);
+
+      // Matrix free linear solver
+      using LinearSolver = ISTLBackend_SEQ_MatrixFree_Richardson<ISTLOnTheFlyOperator, Dune::BiCGSTABSolver>;
+      LinearSolver ls(op);
+
+      using SNP = MatrixFreeNewton<GO, LinearSolver, V>;
+      SNP snp(go, x, ls);
+
+      snp.apply();
+
+      // Dune::Richardson<V,V> richardson(1.0);
+      // Dune::BiCGSTABSolver<V> solverb(opb,richardson,1E-10,5000,2);
+      // Dune::InverseOperatorResult stat;
+      // evaluate residual w.r.t initial guess
+      // using TrialGridFunctionSpace = typename GO::Traits::TrialGridFunctionSpace;
+      // using W = Dune::PDELab::Backend::Vector<TrialGridFunctionSpace,typename V::ElementType>;
+      // W r(go.testGridFunctionSpace(),0.0);
+      // go.residual(x,r);
+      // // solve the jacobian system
+      // V z(go.trialGridFunctionSpace(),0.0);
+      // solverb.apply(z,r,stat);
+      // x -= z;
+    }
+
   }
 }
 #endif
diff --git a/dune/perftool/matrixfreeistlbackends.hh b/dune/perftool/matrixfreeistlbackends.hh
new file mode 100644
index 00000000..05c37e95
--- /dev/null
+++ b/dune/perftool/matrixfreeistlbackends.hh
@@ -0,0 +1,111 @@
+#ifndef DUNE_PERFTOOL_MATRIXFREEISTLBACKENDS_HH
+#define DUNE_PERFTOOL_MATRIXFREEISTLBACKENDS_HH
+namespace Dune {
+  namespace PDELab {
+
+
+    /** \brief Application of jacobian from nonlinear problems.
+
+        \tparam X  Trial vector.
+        \tparam Y  Test vector.
+        \tparam GO Grid operator implementing the operator application.
+    */
+    template<typename X, typename Y, typename GO>
+    class NonlinearOnTheFlyOperator : public Dune::LinearOperator<X,Y>
+    {
+    public :
+      typedef X domain_type;
+      typedef Y range_type;
+      typedef typename X::field_type field_type;
+
+      enum { category = Dune::SolverCategory::sequential };
+
+      NonlinearOnTheFlyOperator(const GO& go)
+        : go_(go)
+        , u_(static_cast<X*>(0))
+      {}
+
+      //! Set position of jacobian. This is different to linear problems.
+      //! Must be called before both apply() and applyscaleadd().
+      void setLinearizationPoint(const X& u)
+      {
+        u_ = &u;
+      }
+
+      virtual void apply(const X& x, Y& y) const
+      {
+        y = 0.0;
+        go_.nonlinear_jacobian_apply(*u_,x,y);
+      }
+
+      virtual void applyscaleadd(field_type alpha, const X& x, Y& y) const
+      {
+        Y temp(y);
+        temp = 0.0;
+        go_.nonlinear_jacobian_apply(*u_,x,temp);
+        y.axpy(alpha,temp);
+      }
+
+    private :
+      const GO& go_;
+      const X* u_;
+    };
+
+
+    template<class Operator, template<class> class Solver>
+    class ISTLBackend_SEQ_MatrixFree_Richardson
+      : public SequentialNorm, public LinearResultStorage
+    {
+    public:
+      /*! \brief make a linear solver object
+
+        \param[in] maxiter_ maximum number of iterations to do
+        \param[in] verbose_ print messages if true
+      */
+      explicit ISTLBackend_SEQ_MatrixFree_Richardson(Operator& op, unsigned maxiter=5000, int verbose=1)
+        : opa_(op), u_(static_cast<typename Operator::domain_type*>(0))
+        , maxiter_(maxiter)
+        , verbose_(verbose)
+      {}
+
+
+
+      /*! \brief solve the given linear system
+
+        \param[in] A the given matrix
+        \param[out] z the solution vector to be computed
+        \param[in] r right hand side
+        \param[in] reduction to be achieved
+      */
+      template<class V, class W>
+      void apply(V& z, W& r, typename Dune::template FieldTraits<typename W::ElementType >::real_type reduction)
+      {
+        Dune::Richardson<V,W> prec(0.7);
+        Solver<V> solver(opa_, prec, reduction, maxiter_, verbose_);
+        Dune::InverseOperatorResult stat;
+        solver.apply(z, r, stat);
+        res.converged  = stat.converged;
+        res.iterations = stat.iterations;
+        res.elapsed    = stat.elapsed;
+        res.reduction  = stat.reduction;
+        res.conv_rate  = stat.conv_rate;
+      }
+
+      //! Set position of jacobian.
+      //! Must be called before apply().
+      void setLinearizationPoint(const typename Operator::domain_type& u)
+      {
+        u_ = &u;
+        opa_.setLinearizationPoint(u);
+      }
+
+    private:
+      Operator& opa_;
+      const typename Operator::domain_type* u_;
+      unsigned maxiter_;
+      int verbose_;
+    };
+
+  } // end namespace PDELab
+} // end namespace Dune
+#endif
diff --git a/dune/perftool/matrixfreenewton.hh b/dune/perftool/matrixfreenewton.hh
new file mode 100644
index 00000000..728bafc0
--- /dev/null
+++ b/dune/perftool/matrixfreenewton.hh
@@ -0,0 +1,521 @@
+// -*- tab-width: 2; indent-tabs-mode: nil -*-
+// vi: set et ts=2 sw=2 sts=2:
+#ifndef DUNE_PDELAB_NEWTON_MATRIXFREENEWTON_HH
+#define DUNE_PDELAB_NEWTON_MATRIXFREENEWTON_HH
+
+#include <iostream>
+#include <iomanip>
+#include <cmath>
+#include <memory>
+
+#include <math.h>
+
+#include <dune/common/ios_state.hh>
+#include <dune/common/timer.hh>
+#include <dune/common/parametertree.hh>
+
+#include <dune/perftool/newtonbase.hh>
+
+namespace Dune {
+  namespace PDELab {
+
+    template<typename GO, typename S, typename TrlV, typename TstV = TrlV>
+    class MatrixFreeNewton
+    {
+      typedef GO GridOperator;
+      typedef S Solver;
+      typedef TrlV TrialVector;
+      typedef TstV TestVector;
+
+      typedef typename TestVector::ElementType RFType;
+
+    public :
+      //! export result type
+      using Result = NewtonResult<RFType>;
+
+      MatrixFreeNewton(const GridOperator& go, TrialVector& u, Solver& solver)
+        : gridoperator_(go)
+        , u_(&u)
+        , solver_(solver)
+        , verbosity_level_(1), maxit_(40), force_iteration_(false)
+        , min_linear_reduction_(1e-3), fixed_linear_reduction_(false)
+        , strategy_(LineSearchStrategy::hackbuschReusken), linesearch_maxit_(10), damping_factor_(0.5)
+        , reduction_(1e-8), abs_limit_(1e-12), result_valid_(false)
+      {
+        if (gridoperator_.trialGridFunctionSpace().gridView().comm().rank()>0)
+          verbosity_level_ = 0;
+      }
+      MatrixFreeNewton(const GridOperator& go, Solver& solver)
+        : gridoperator_(go)
+        , u_(static_cast<TrialVector*>(0))
+        , solver_(solver)
+        , verbosity_level_(1), maxit_(40), force_iteration_(false)
+        , min_linear_reduction_(1e-3), fixed_linear_reduction_(false)
+        , strategy_(LineSearchStrategy::hackbuschReusken), linesearch_maxit_(10), damping_factor_(0.5)
+        , reduction_(1e-8), abs_limit_(1e-12), result_valid_(false)
+      {
+        if (gridoperator_.trialGridFunctionSpace().gridView().comm().rank()>0)
+          verbosity_level_ = 0;
+      }
+      //! interpret a parameter tree as a set of options for the newton solver
+      /**
+
+         example configuration:
+
+         \code
+         [NewtonParameters]
+
+         LineSearchMaxIterations = 10
+         MaxIterations = 7
+         AbsoluteLimit = 1e-6
+         Reduction = 1e-4
+         LinearReduction = 1e-3
+         LineSearchDamping  = 0.9
+         \endcode
+
+         and invocation in the code:
+         \code
+         newton.setParameters(param.sub("NewtonParameters"));
+         \endcode
+      */
+      void setParameters(Dune::ParameterTree & param)
+      {
+        typedef typename TstV::ElementType RFType;
+        if (param.hasKey("VerbosityLevel"))
+          setVerbosityLevel(
+            param.get<unsigned int>("VerbosityLevel"));
+        if (param.hasKey("Reduction"))
+          setReduction(
+            param.get<RFType>("Reduction"));
+        if (param.hasKey("MaxIterations"))
+          setMaxIterations(
+            param.get<unsigned int>("MaxIterations"));
+        if (param.hasKey("ForceIteration"))
+          setForceIteration(
+            param.get<bool>("ForceIteration"));
+        if (param.hasKey("AbsoluteLimit"))
+          setAbsoluteLimit(
+            param.get<RFType>("AbsoluteLimit"));
+        if (param.hasKey("MinLinearReduction"))
+          setMinLinearReduction(
+            param.get<RFType>("MinLinearReduction"));
+        if (param.hasKey("FixedLinearReduction"))
+          setFixedLinearReduction(
+            param.get<bool>("FixedLinearReduction"));
+        if (param.hasKey("LineSearchStrategy"))
+          setLineSearchStrategy(
+            param.get<std::string>("LineSearchStrategy"));
+        if (param.hasKey("LineSearchMaxIterations"))
+          setLineSearchMaxIterations(
+            param.get<unsigned int>("LineSearchMaxIterations"));
+        if (param.hasKey("LineSearchDampingFactor"))
+          setLineSearchDampingFactor(
+            param.get<RFType>("LineSearchDampingFactor"));
+      }
+
+      //! set verbosity level
+      void setVerbosityLevel(unsigned int verbosity_level)
+      {
+        if (gridoperator_.trialGridFunctionSpace().gridView().comm().rank()>0)
+          verbosity_level_ = 0;
+        else
+          verbosity_level_ = verbosity_level;
+      }
+
+      //! set reduction in Newton
+      void setReduction(RFType reduction)
+      {
+        reduction_ = reduction;
+      }
+
+      //! set maximum of nonlinear iterations
+      void setMaxIterations(unsigned int maxit)
+      {
+        maxit_ = maxit;
+      }
+
+      void setForceIteration(bool force_iteration)
+      {
+        force_iteration_ = force_iteration;
+      }
+
+      //! set absolute limit to achieve for the norm of the residual
+      void setAbsoluteLimit(RFType abs_limit)
+      {
+        abs_limit_ = abs_limit;
+      }
+
+      /**\brief set the minimal reduction in the linear solver
+
+         \note with min_linear_reduction > 0, the linear reduction will be
+         determined as mininum of the min_linear_reduction and the
+         linear_reduction needed to achieve second order
+         Newton convergence. */
+      void setMinLinearReduction(RFType min_linear_reduction)
+      {
+        min_linear_reduction_ = min_linear_reduction;
+      }
+
+      /**\brief set a fixed reduction in the linear solver (overwrites setMinLinearReduction)
+
+         \note with fixed_linear_reduction > 0, the linear reduction
+         rate will always be fixed to min_linear_reduction. */
+      void setFixedLinearReduction(bool fixed_linear_reduction)
+      {
+        fixed_linear_reduction_ = fixed_linear_reduction;
+      }
+
+      //! set line search strategy
+      void setLineSearchStrategy(LineSearchStrategy strategy)
+      {
+        strategy_ = strategy;
+      }
+
+      void setLineSearchStrategy(std::string strategy)
+      {
+        // read strategy from string
+        if(strategy == "noLineSearch") {
+          strategy_ = LineSearchStrategy::noLineSearch;
+          return;
+        }
+        if(strategy == "hackbuschReusken") {
+          strategy_ = LineSearchStrategy::hackbuschReusken;
+          return;
+        }
+        if(strategy == "hackbuschReuskenAcceptBest") {
+          strategy_ = LineSearchStrategy::hackbuschReuskenAcceptBest;
+          return;
+        }
+        DUNE_THROW(Exception, "unknown linesearch strategy" << strategy);
+      }
+
+      //! set maximum number of line search iterations
+      void setLineSearchMaxIterations(unsigned int linesearch_maxit)
+      {
+        linesearch_maxit_ = linesearch_maxit;
+      }
+
+      //! set damping factor for line search parameter
+      void setLineSearchDampingFactor(RFType damping_factor)
+      {
+        damping_factor_ = damping_factor;
+      }
+
+      //! stopping criteria for Newton
+      bool terminate()
+      {
+        if(force_iteration_ and res_.iterations == 0)
+          return false;
+
+        // standard criterion
+        res_.converged = (res_.defect < abs_limit_) or (res_.defect < res_.first_defect * reduction_);
+
+        if(res_.iterations >= maxit_ and (not res_.converged))
+          DUNE_THROW(NewtonNotConverged,
+                     "NewtonTerminate::terminate(): Maximum iteration count reached");
+        return res_.converged;
+      }
+
+      //! line search in Newton
+      void lineSearch(TrialVector& z, TrialVector& r)
+      {
+        if (strategy_ == LineSearchStrategy::noLineSearch)
+          {
+            u_->axpy(-1.0, z);
+            r = 0.0;
+            gridoperator_.residual(*u_,r);
+            res_.defect = solver_.norm(r);
+            if(not std::isfinite(res_.defect))
+              DUNE_THROW(NewtonDefectError,
+                         "Non linear residual is NaN or Inf!");
+            return;
+          }
+        if (verbosity_level_ >= 4)
+          std::cout << "      Performing line search..." << std::endl;
+        RFType lambda = 1.0;
+        RFType best_lambda = 0.0;
+        RFType best_defect = res_.defect;
+        TrialVector prev_u(*u_);
+        unsigned int i = 0;
+        ios_base_all_saver restorer(std::cout); // store old ios flags
+
+        while (1)
+          {
+            if (verbosity_level_ >= 4)
+              std::cout << "          trying line search damping factor:   "
+                        << std::setw(12) << std::setprecision(4) << std::scientific
+                        << lambda
+                        << std::endl;
+
+            u_->axpy(-lambda, z);
+            try {
+              r = 0.0;
+              gridoperator_.residual(*u_,r);
+              res_.defect = solver_.norm(r);
+              if(not std::isfinite(res_.defect))
+                DUNE_THROW(NewtonDefectError,
+                           "Non linear residual is NaN or Inf!");
+            }
+             catch (NewtonDefectError)
+              {
+                if (verbosity_level_ >= 4)
+                  std::cout << "          Nans detected" << std::endl;
+              }       // ignore NaNs and try again with lower lambda
+
+            if (res_.defect <= (1.0 - lambda/4) * prev_defect_)
+              {
+                if (verbosity_level_ >= 4)
+                  std::cout << "          line search converged" << std::endl;
+                break;
+              }
+
+            if (res_.defect < best_defect)
+              {
+                best_defect = res_.defect;
+                best_lambda = lambda;
+              }
+
+            if (++i >= maxit_)
+              {
+                if (verbosity_level_ >= 4)
+                  std::cout << "          max line search iterations exceeded" << std::endl;
+                switch (strategy_)
+                  {
+                  case LineSearchStrategy::hackbuschReusken:
+                    *u_ = prev_u;
+                    r = 0.0;
+                    gridoperator_.residual(*u_,r);
+                    res_.defect = solver_.norm(r);
+                    if(not std::isfinite(res_.defect))
+                      DUNE_THROW(NewtonDefectError,
+                                 "Non linear residual is NaN or Inf!");
+                    DUNE_THROW(NewtonLineSearchError,
+                               "NewtonLineSearch::line_search(): line search failed, "
+                               "max iteration count reached, "
+                               "defect did not improve enough");
+                  case LineSearchStrategy::hackbuschReuskenAcceptBest:
+                    if (best_lambda == 0.0)
+                      {
+                        *u_ = prev_u;
+                        r = 0.0;
+                        gridoperator_.residual(*u_,r);
+                        res_.defect = solver_.norm(r);
+                        if(not std::isfinite(res_.defect))
+                          DUNE_THROW(NewtonDefectError,
+                                     "Non linear residual is NaN or Inf!");
+                        DUNE_THROW(NewtonLineSearchError,
+                                   "NewtonLineSearch::line_search(): line search failed, "
+                                   "max iteration count reached, "
+                                   "defect did not improve in any of the iterations");
+                      }
+                    if (best_lambda != lambda)
+                      {
+                        *u_ = prev_u;
+                        u_->axpy(-best_lambda, z);
+                        r = 0.0;
+                        gridoperator_.residual(*u_,r);
+                        res_.defect = solver_.norm(r);
+                        if(not std::isfinite(res_.defect))
+                          DUNE_THROW(NewtonDefectError,
+                                     "Non linear residual is NaN or Inf!");
+                      }
+                    break;
+                  case LineSearchStrategy::noLineSearch:
+                    break;
+                  }
+                break;
+              }
+
+            lambda *= damping_factor_;
+            *u_ = prev_u;
+          }
+        if (verbosity_level_ >= 4)
+          std::cout << "          line search damping factor:   "
+                    << std::setw(12) << std::setprecision(4) << std::scientific
+                    << lambda << std::endl;
+      } // end lineSearch
+
+      const Result& result() const
+      {
+        return res_;
+      }
+
+      void apply(TrialVector& u)
+      {
+        u_ = &u;
+        apply();
+      }
+
+      void apply()
+      {
+        // reset solver statistics
+        res_.iterations = 0;
+        res_.converged = false;
+        res_.reduction = 1.0;
+        res_.conv_rate = 1.0;
+        res_.elapsed = 0.0;
+        res_.linear_solver_time = 0.0;
+        res_.linear_solver_iterations = 0;
+        result_valid_ = true;
+        Timer timer;
+
+        // allocate only once the residual vector
+        if(not r_)
+          r_ = std::make_shared<TestVector>(gridoperator_.testGridFunctionSpace());
+
+        //============================================
+        // calculate initial residual and its norm
+        //============================================
+        *r_ = 0.0;
+        gridoperator_.residual(*u_,*r_);
+        res_.defect = solver_.norm(*r_);
+        if(not std::isfinite(res_.defect))
+          DUNE_THROW(NewtonDefectError,
+                     "Non linear residual is NaN or Inf!");
+        res_.first_defect = res_.defect;
+        prev_defect_ = res_.defect;
+
+        if(verbosity_level_ >= 2) {
+          // store old ios flags
+          ios_base_all_saver restorer(std::cout);
+          std::cout << "  Initial defect: "
+                    << std::setw(12) << std::setprecision(4) << std::scientific
+                    << res_.defect << std::endl;
+        }
+
+        // allocate the correction vector only one
+        if(not z_)
+          z_ = std::make_shared<TrialVector>(gridoperator_.trialGridFunctionSpace());
+
+        //============================================
+        // the nonlinear iteration loop
+        //============================================
+        while(not terminate()) {
+          if(verbosity_level_ >= 3)
+            std::cout << "  Newton iteration " << res_.iterations
+                      << " --------------------------------" << std::endl;
+
+          //============================================
+          // solution of linear system
+          //============================================
+          Timer linear_solver_timer;
+          if(verbosity_level_ >= 4)
+            std::cout << "      Solving linear system..." << std::endl;
+          // <<<1>>> set linear reduction
+          if(fixed_linear_reduction_ == true)
+            linear_reduction_ = min_linear_reduction_;
+          else {
+            // determine maximum defect, where Newton is converged.
+            auto stop_defect =
+              std::max(res_.first_defect * reduction_, abs_limit_);
+
+            /*
+              To achieve second order convergence of newton
+              we need a linear reduction of at least
+              current_defect^2/prev_defect^2.
+              For the last newton step a linear reduction of
+              1/10*end_defect/current_defect
+              is sufficient for convergence.
+            */
+            if ( stop_defect/(10*res_.defect) >
+                 res_.defect*res_.defect/(prev_defect_*prev_defect_) )
+              linear_reduction_ =
+                stop_defect/(10*res_.defect);
+            else
+              linear_reduction_ =
+                std::min(min_linear_reduction_,res_.defect*res_.defect/(prev_defect_*prev_defect_));
+          }
+
+          ios_base_all_saver restorer(std::cout); // store old ios flags
+
+          if (verbosity_level_ >= 3)
+            std::cout << "      requested linear reduction:       "
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << linear_reduction_ << std::endl;
+
+          // <<<2>>> set position of jacobian for its application
+          solver_.setLinearizationPoint(*u_);
+
+          // <<<3>>> call linear solver
+          *z_ = 0.0;
+          solver_.apply(*z_, *r_, linear_reduction_);
+          res_.linear_solver_time += linear_solver_timer.elapsed();
+          res_.linear_solver_iterations += solver_.result().iterations;
+          auto linear_solver_time = linear_solver_timer.elapsed();
+          res_.linear_solver_time += linear_solver_time;
+          res_.linear_solver_iterations += solver_.result().iterations;
+
+          //============================================
+          // line search with correction z
+          // the undamped version is also covered in here
+          //============================================
+          lineSearch(*z_,*r_);
+
+          // store statistics and output per nonlinear iteration
+          res_.reduction = res_.defect/res_.first_defect;
+          res_.iterations++;
+          res_.conv_rate = std::pow(res_.reduction, 1.0/res_.iterations);
+
+          if (verbosity_level_ >= 3)
+            std::cout << "      linear solver time:               "
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << linear_solver_time << std::endl
+                      << "      defect reduction (this iteration):"
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << res_.defect/prev_defect_ << std::endl
+                      << "      defect reduction (total):         "
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << res_.reduction << std::endl
+                      << "      new defect:                       "
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << res_.defect << std::endl;
+          if (verbosity_level_ == 2)
+            std::cout << "  Newton iteration " << std::setw(2) << res_.iterations
+                      << ".  New defect: "
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << res_.defect
+                      << ".  Reduction (this): "
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << res_.defect/prev_defect_
+                      << ".  Reduction (total): "
+                      << std::setw(12) << std::setprecision(4) << std::scientific
+                      << res_.reduction << std::endl;
+        } // end while
+
+        res_.elapsed = timer.elapsed();
+
+        ios_base_all_saver restorer(std::cout); // store old ios flags
+
+        if (verbosity_level_ == 1)
+          std::cout << "  Newton converged after " << std::setw(2) << res_.iterations
+                    << " iterations.  Reduction: "
+                    << std::setw(12) << std::setprecision(4) << std::scientific
+                    << res_.reduction
+                    << "   (" << std::setprecision(4) << res_.elapsed << "s)"
+                    << std::endl;
+      } // end apply
+
+    private :
+      const GridOperator& gridoperator_;
+      TrialVector *u_;
+      Solver& solver_;
+      std::shared_ptr<TrialVector> z_;
+      std::shared_ptr<TestVector> r_;
+      Result res_;
+      unsigned int verbosity_level_;
+      unsigned int maxit_;
+      bool force_iteration_;
+      RFType min_linear_reduction_;
+      bool fixed_linear_reduction_;
+      LineSearchStrategy strategy_;
+      unsigned int linesearch_maxit_;
+      RFType damping_factor_;
+      RFType prev_defect_;
+      RFType linear_reduction_;
+      RFType reduction_;
+      RFType abs_limit_;
+      bool result_valid_;
+    }; // end class MatrixFreeNewton
+  } // end namespace PDELab
+} // end namespace Dune
+#endif
diff --git a/dune/perftool/newtonbase.hh b/dune/perftool/newtonbase.hh
new file mode 100644
index 00000000..9f264d41
--- /dev/null
+++ b/dune/perftool/newtonbase.hh
@@ -0,0 +1,50 @@
+// -*- tab-width: 2; indent-tabs-mode: nil -*-
+// vi: set et ts=2 sw=2 sts=2:
+#ifndef DUNE_PDELAB_NEWTON_NEWTONBASE_HH
+#define DUNE_PDELAB_NEWTON_NEWTONBASE_HH
+
+#include <dune/common/exceptions.hh>
+#include <dune/pdelab/backend/solver.hh>
+
+namespace Dune {
+  namespace PDELab {
+
+    // Exception classes used in NewtonSolver
+    class NewtonError : public Exception {};
+    class NewtonDefectError : public NewtonError {};
+    class NewtonLinearSolverError : public NewtonError {};
+    class NewtonLineSearchError : public NewtonError {};
+    class NewtonNotConverged : public NewtonError {};
+
+    // Status information of Newton's method
+    template<class RFType>
+    struct NewtonResult : LinearSolverResult<RFType>
+    {
+      RFType first_defect;       // the first defect
+      RFType defect;             // the final defect
+      double assembler_time;     // Cumulative time for matrix assembly
+      double linear_solver_time; // Cumulative time for linear sovler
+      int linear_solver_iterations; // Total number of linear iterations
+
+      NewtonResult() :
+        first_defect(0.0), defect(0.0), assembler_time(0.0), linear_solver_time(0.0),
+        linear_solver_iterations(0) {}
+    };
+
+    enum struct LineSearchStrategy {
+
+      /** \brief don't do any linesearch or damping */
+      noLineSearch,
+
+      /** \brief perform a linear search for the optimal damping parameter with multiples of damping
+
+          the strategy was described in <a href="http://dx.doi.org/10.1007/BF01406516">[Hackbusch and Reusken, 1989]</a> */
+     hackbuschReusken,
+
+      /** \brief same as hackbuschReusken, but doesn't fail if the best update is still not good enough */
+      hackbuschReuskenAcceptBest
+      };
+
+  } // end namespace PDELab
+} // end namespace Dune
+#endif
-- 
GitLab