diff --git a/dumux/nonlinear/newtoncontroller.hh b/dumux/nonlinear/newtoncontroller.hh
index c2bf0118a458f77e0208cbffb658f79dee93ce0e..a611e62a4d321898fcef76fc432322deed9c136e 100644
--- a/dumux/nonlinear/newtoncontroller.hh
+++ b/dumux/nonlinear/newtoncontroller.hh
@@ -56,12 +56,6 @@ NEW_PROP_TAG(SolutionVector);
 //! Specifies the type of a global Jacobian matrix
 NEW_PROP_TAG(JacobianMatrix);
 
-//! Specifies the type of the Vertex mapper
-NEW_PROP_TAG(VertexMapper);
-
-//! specifies the type of the time manager
-NEW_PROP_TAG(TimeManager);
-
 //! specifies whether the convergence rate and the global residual
 //! gets written out to disk for every Newton iteration (default is false)
 NEW_PROP_TAG(NewtonWriteConvergence);
@@ -155,39 +149,30 @@ SET_INT_PROP(NewtonMethod, NewtonMaxSteps, 18);
 template <class TypeTag>
 class NewtonController
 {
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) Implementation;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
-    typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix;
-    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
-    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
-    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    using Scalar =  typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Implementation =  typename GET_PROP_TYPE(TypeTag, NewtonController);
+    using ConvergenceWriter =  typename GET_PROP_TYPE(TypeTag, NewtonConvergenceWriter);
+    using GridView =  typename GET_PROP_TYPE(TypeTag, GridView);
+    using Communicator = typename GridView::CollectiveCommunication;
 
     using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
-
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonConvergenceWriter) ConvergenceWriter;
-
-    typedef typename GET_PROP_TYPE(TypeTag, LinearSolver) LinearSolver;
+    using SolutionVector =  typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using JacobianMatrix =  typename GET_PROP_TYPE(TypeTag, JacobianMatrix);
+    using JacobianAssembler =  typename GET_PROP_TYPE(TypeTag, JacobianAssembler);
+    using LinearSolver =  typename GET_PROP_TYPE(TypeTag, LinearSolver);
 
     static constexpr int numEq = GET_PROP_VALUE(TypeTag, NumEq);
 
 public:
     /*!
-     * \brief Constructor
+     * \brief Constructor without convergence writer
      */
-    NewtonController(const Problem &problem)
-    : endIterMsgStream_(std::ostringstream::out),
-      linearSolver_(problem)
+    NewtonController(const Communicator& comm) : comm_(comm), endIterMsgStream_(std::ostringstream::out)
     {
         enablePartialReassemble_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnablePartialReassemble);
         enableJacobianRecycling_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableJacobianRecycling);
 
+        writeConvergence_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence);
         useLineSearch_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, UseLineSearch);
         enableAbsoluteResidualCriterion_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, EnableAbsoluteResidualCriterion);
         enableShiftCriterion_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, EnableShiftCriterion);
@@ -211,6 +196,13 @@ public:
         numSteps_ = 0;
     }
 
+    /*!
+     * \brief Constructor with a given convergence writer
+     */
+    NewtonController(const Communicator& comm, ConvergenceWriter&& writer)
+    : NewtonController(comm), convergenceWriter_(std::move(writer))
+    {}
+
     /*!
      * \brief Set the maximum acceptable difference of any primary variable
      * between two iterations for declaring convergence.
@@ -326,20 +318,14 @@ public:
      * \brief Called before the Newton method is applied to an
      *        non-linear system of equations.
      *
-     * \param method The object where the NewtonMethod is executed
      * \param u The initial solution
      */
-    void newtonBegin(NewtonMethod &method, const SolutionVector &u)
+    void newtonBegin(const SolutionVector &u)
     {
-        method_ = &method;
         numSteps_ = 0;
 
-        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence))
-        {
-            if (!convergenceWriter_)
-                convergenceWriter_ = std::make_unique<ConvergenceWriter>(asImp_(), problem_().gridView());
+        if (writeConvergence_)
             convergenceWriter_->advanceTimeStep();
-        }
     }
 
     /*!
@@ -381,14 +367,23 @@ public:
             typename SolutionVector::block_type uNewI = uLastIter[i];
             uNewI -= deltaU[i];
 
-            Scalar shiftAtDof = model_().relativeShiftAtDof(uLastIter[i],
-                                                            uNewI);
+            Scalar shiftAtDof = relativeShiftAtDof_(uLastIter[i], uNewI);
             using std::max;
             shift_ = max(shift_, shiftAtDof);
         }
 
-        if (gridView_().comm().size() > 1)
-            shift_ = gridView_().comm().max(shift_);
+        if (comm().size() > 1)
+            shift_ = comm().max(shift_);
+    }
+
+    /*!
+     * \brief Assemble the linear system of equations \f$\mathbf{A}x - b = 0\f$.
+     *
+     * \param assembler The jacobian assembler
+     */
+    void assembleLinearSystem(JacobianAssembler& assembler)
+    {
+        assembler.assembleJacobianAndResidual();
     }
 
     /*!
@@ -397,20 +392,22 @@ public:
      * Throws NumericalProblem if the linear solver didn't
      * converge.
      *
+     * \param ls The linear solver to be used
      * \param A The matrix of the linear system of equations
      * \param x The vector which solves the linear system
      * \param b The right hand side of the linear system
      */
-    void newtonSolveLinear(JacobianMatrix &A,
-                           SolutionVector &x,
-                           SolutionVector &b)
+    void solveLinearSystem(LinearSolver& ls,
+                           JacobianMatrix& A,
+                           SolutionVector& x,
+                           SolutionVector& b)
     {
         try {
             if (numSteps_ == 0)
             {
                 Scalar norm2 = b.two_norm2();
-                if (gridView_().comm().size() > 1)
-                    norm2 = gridView_().comm().sum(norm2);
+                if (comm().size() > 1)
+                    norm2 = comm().sum(norm2);
 
                 using std::sqrt;
                 initialResidual_ = sqrt(norm2);
@@ -427,7 +424,7 @@ public:
                 for (int j = 0; j < numEq; ++j)
                     bTmp[i][j] = b[i][j];
 
-            int converged = linearSolver_.solve(A, xTmp, bTmp);
+            int converged = ls.solve(A, xTmp, bTmp);
 
             for (int i = 0; i < x.size(); ++i)
                 for (int j = 0; j < numEq; ++j)
@@ -435,8 +432,8 @@ public:
 
             // make sure all processes converged
             int convergedRemote = converged;
-            if (gridView_().comm().size() > 1)
-                convergedRemote = gridView_().comm().min(converged);
+            if (comm().size() > 1)
+                convergedRemote = comm().min(converged);
 
             if (!converged) {
                 DUNE_THROW(NumericalProblem,
@@ -450,8 +447,8 @@ public:
         catch (Dune::MatrixBlockError e) {
             // make sure all processes converged
             int converged = 0;
-            if (gridView_().comm().size() > 1)
-                converged = gridView_().comm().min(converged);
+            if (comm().size() > 1)
+                converged = comm().min(converged);
 
             NumericalProblem p;
             std::string msg;
@@ -463,8 +460,8 @@ public:
         catch (const Dune::Exception &e) {
             // make sure all processes converged
             int converged = 0;
-            if (gridView_().comm().size() > 1)
-                converged = gridView_().comm().min(converged);
+            if (comm().size() > 1)
+                converged = comm().min(converged);
 
             NumericalProblem p;
             p.message(e.what());
@@ -483,13 +480,15 @@ public:
      * subtract deltaU from uLastIter, i.e.
      * \f[ u^{k+1} = u^k - \Delta u^k \f]
      *
+     * \param assembler The assembler (needed for global residual evaluation)
      * \param uCurrentIter The solution vector after the current iteration
      * \param uLastIter The solution vector after the last iteration
      * \param deltaU The delta as calculated from solving the linear
      *               system of equations. This parameter also stores
      *               the updated solution.
      */
-    void newtonUpdate(SolutionVector &uCurrentIter,
+    void newtonUpdate(const JacobianAssembler& assembler,
+                      SolutionVector &uCurrentIter,
                       const SolutionVector &uLastIter,
                       const SolutionVector &deltaU)
     {
@@ -500,7 +499,7 @@ public:
 
         if (useLineSearch_)
         {
-            lineSearchUpdate_(uCurrentIter, uLastIter, deltaU);
+            lineSearchUpdate_(assembler, uCurrentIter, uLastIter, deltaU);
         }
         else {
             for (unsigned int i = 0; i < uLastIter.size(); ++i) {
@@ -510,8 +509,15 @@ public:
 
             if (enableResidualCriterion_)
             {
-                SolutionVector tmp(uLastIter);
-                residual_ = this->method().model().globalResidual(tmp, uCurrentIter);
+                // Originally here we handed in uCurrentIter into
+                // the global residual function to evaluate the
+                // residual for the given solution. Currently, the
+                // assembler evaluates the residual for the curSol
+                // container only. However, uCurrentIter is a ref
+                // to this container, so we don't need to do the copying
+                // etc.
+                // TODO: Should we re-include this??????
+                residual_ = assembler.globalResidual();
                 reduction_ = residual_;
                 reduction_ /= initialResidual_;
             }
@@ -521,14 +527,24 @@ public:
     /*!
      * \brief Indicates that one Newton iteration was finished.
      *
+     * \param assembler The jacobian assembler
      * \param uCurrentIter The solution after the current Newton iteration
      * \param uLastIter The solution at the beginning of the current Newton iteration
      */
-    void newtonEndStep(SolutionVector &uCurrentIter,
+    void newtonEndStep(JacobianAssembler& assembler,
+                       SolutionVector &uCurrentIter,
                        const SolutionVector &uLastIter)
     {
-        // Update the volume variables
-        this->model_().newtonEndStep();
+        // TODO
+        // This is a hack in order to be able to realize an update
+        // of the gridVolumeVariables etc... How could we achieve
+        // this differently??
+        // Originally here we had model.newtonEndStep() which updated
+        // the variables... Should the NewtonMethod get access to these
+        // classes directly as well?
+        // -> The assembler has all the data w.r.t. the problem etc...
+        // -> also, how do we call this?
+        assembler.updateVariables()
 
         ++numSteps_;
 
@@ -546,7 +562,8 @@ public:
         endIterMsgStream_.str("");
 
         // When the Newton iterations are done: ask the model to check whether it makes sense
-        model_().checkPlausibility();
+        // TODO: how do we realize this?
+        // model_().checkPlausibility();
     }
 
     /*!
@@ -598,20 +615,6 @@ public:
         return oldTimeStep*(1.0 + percent/1.2);
     }
 
-    /*!
-     * \brief Returns a reference to the current Newton method
-     *        which is controlled by this controller.
-     */
-    NewtonMethod &method()
-    { return *method_; }
-
-    /*!
-     * \brief Returns a reference to the current Newton method
-     *        which is controlled by this controller.
-     */
-    const NewtonMethod &method() const
-    { return *method_; }
-
     std::ostringstream &endIterMsg()
     { return endIterMsgStream_; }
 
@@ -625,56 +628,9 @@ public:
      * \brief Returns true if the Newton method ought to be chatty.
      */
     bool verbose() const
-    { return verbose_ && gridView_().comm().rank() == 0; }
+    { return verbose_ && comm().rank() == 0; }
 
 protected:
-    /*!
-     * \brief Returns a reference to the grid view.
-     */
-    const GridView &gridView_() const
-    { return problem_().gridView(); }
-
-    /*!
-     * \brief Returns a reference to the vertex mapper.
-     */
-    const VertexMapper &vertexMapper_() const
-    { return model_().vertexMapper(); }
-
-    /*!
-     * \brief Returns a reference to the problem.
-     */
-    Problem &problem_()
-    { return method_->problem(); }
-
-    /*!
-     * \brief Returns a reference to the problem.
-     */
-    const Problem &problem_() const
-    { return method_->problem(); }
-
-    /*!
-     * \brief Returns a reference to the time manager.
-     */
-    TimeManager &timeManager_()
-    { return problem_().timeManager(); }
-
-    /*!
-     * \brief Returns a reference to the time manager.
-     */
-    const TimeManager &timeManager_() const
-    { return problem_().timeManager(); }
-
-    /*!
-     * \brief Returns a reference to the problem.
-     */
-    Model &model_()
-    { return problem_().model(); }
-
-    /*!
-     * \brief Returns a reference to the problem.
-     */
-    const Model &model_() const
-    { return problem_().model(); }
 
     // returns the actual implementation for the controller we do
     // it this way in order to allow "poor man's virtual methods",
@@ -688,14 +644,15 @@ protected:
     void writeConvergence_(const SolutionVector &uLastIter,
                            const SolutionVector &deltaU)
     {
-        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence))
+        if (writeConvergence_)
         {
             convergenceWriter_->advanceIteration();
             convergenceWriter_->write(uLastIter, deltaU);
         }
     }
 
-    void lineSearchUpdate_(SolutionVector &uCurrentIter,
+    void lineSearchUpdate_(const JacobianAssembler& assembler,
+                           SolutionVector &uCurrentIter,
                            const SolutionVector &uLastIter,
                            const SolutionVector &deltaU)
     {
@@ -708,12 +665,20 @@ protected:
            uCurrentIter += uLastIter;
 
            // calculate the residual of the current solution
-           residual_ = this->method().model().globalResidual(tmp, uCurrentIter);
+           // Originally here we handed in uCurrentIter into
+           // the global residual function to evaluate the
+           // residual for the given solution. Currently, the
+           // assembler evaluates the residual for the curSol
+           // container only. However, uCurrentIter is a ref
+           // to this container, so we don't need to do the copying
+           // etc.
+           // TODO: Should we re-include this??????
+           residual_ = assembler.globalResidual();
            reduction_ = residual_;
            reduction_ /= initialResidual_;
 
            if (reduction_ < lastReduction_ || lambda <= 0.125) {
-               this->endIterMsg() << ", residual reduction " << lastReduction_ << "->"  << reduction_ << "@lambda=" << lambda;
+               endIterMsg() << ", residual reduction " << lastReduction_ << "->"  << reduction_ << "@lambda=" << lambda;
                return;
            }
 
@@ -722,12 +687,39 @@ protected:
        }
     }
 
+    /*!
+     * \brief Returns the maximum relative shift between two vectors of
+     *        primary variables.
+     *
+     * \param priVars1 The first vector of primary variables
+     * \param priVars2 The second vector of primary variables
+     */
+    Scalar relativeShiftAtDof_(const PrimaryVariables &priVars1,
+                               const PrimaryVariables &priVars2)
+    {
+        Scalar result = 0.0;
+        using std::abs;
+        using std::max;
+        for (int j = 0; j < numEq; ++j) {
+            Scalar eqErr = abs(priVars1[j] - priVars2[j]);
+            eqErr /= max<Scalar>(1.0,abs(priVars1[j] + priVars2[j])/2);
+
+            result = max(result, eqErr);
+        }
+        return result;
+    }
+
+    // The grid view's communicator
+    const Communicator& comm_;
+
+    // message stream to be displayed at the end of iterations
     std::ostringstream endIterMsgStream_;
 
-    NewtonMethod *method_;
-    bool verbose_;
+    // writes an output file for each iteration
+    ConvergenceWriter convergenceWriter_;
 
-    std::unique_ptr<ConvergenceWriter> convergenceWriter_;
+    // switches on/off verbosity
+    bool verbose_;
 
     // shift criterion variables
     Scalar shift_;
@@ -749,9 +741,7 @@ protected:
     // actual number of steps done so far
     int numSteps_;
 
-    // the linear solver
-    LinearSolver linearSolver_;
-
+    // further parameters
     bool enablePartialReassemble_;
     bool enableJacobianRecycling_;
     bool useLineSearch_;
@@ -759,6 +749,9 @@ protected:
     bool enableShiftCriterion_;
     bool enableResidualCriterion_;
     bool satisfyResidualAndShiftCriterion_;
+
+    // specifies if we want to write down the intermediate solutions
+    bool writeConvergence_;
 };
 } // namespace Dumux
 
diff --git a/dumux/nonlinear/newtonconvergencewriter.hh b/dumux/nonlinear/newtonconvergencewriter.hh
index d0dcd8241fcfeb4d5b432b219b8db24066ffce2d..2ef85f6a5e6e1eba3f81427cf2e716e02a8d885c 100644
--- a/dumux/nonlinear/newtonconvergencewriter.hh
+++ b/dumux/nonlinear/newtonconvergencewriter.hh
@@ -29,17 +29,9 @@
 
 #include <dumux/common/basicproperties.hh>
 
-#include "newtoncontroller.hh"
-
 namespace Dumux
 {
 
-namespace Properties
-{
-NEW_PROP_TAG(NewtonController);
-NEW_PROP_TAG(SolutionVector);
-}
-
 /*!
  * \ingroup Newton
  * \brief Writes the intermediate solutions during
@@ -50,21 +42,19 @@ class NewtonConvergenceWriter
 {
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using NewtonController = typename GET_PROP_TYPE(TypeTag, NewtonController);
+    using LocalResidual = typename GET_PROP_TYPE(TypeTag, LocalResidual);
     using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
 
     static constexpr int numEq = GET_PROP_VALUE(TypeTag, NumEq);
     static constexpr bool isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox);
 
 public:
-    NewtonConvergenceWriter(NewtonController &ctl, const GridView& gridView)
-    : ctl_(ctl),
-      writer_(gridView, "convergence", "", "")
+    NewtonConvergenceWriter(const GridView& gridView, const std::size_t numDofs)
+    : writer_(gridView, "convergence", "", "")
     {
         timeStepIndex_ = 0;
         iteration_ = 0;
 
-        const auto numDofs = ctl_.method().model().numDofs();
         for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
         {
             def_[eqIdx].resize(numDofs);
@@ -106,9 +96,7 @@ public:
     void write(const SolutionVector &uLastIter,
                const SolutionVector &deltaU)
     {
-        SolutionVector residual(uLastIter);
-        ctl_.method().model().globalResidual(residual, uLastIter);
-
+        const auto residual = LocalResidual::globalResidual();
         for (unsigned int dofIdxGlobal = 0; dofIdxGlobal < deltaU.size(); dofIdxGlobal++)
         {
             for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
@@ -130,7 +118,6 @@ private:
     std::array<std::vector<Scalar>, numEq> delta_;
     std::array<std::vector<Scalar>, numEq> x_;
 
-    NewtonController &ctl_;
     Dune::VTKSequenceWriter<GridView> writer_;
 };
 
diff --git a/dumux/nonlinear/newtonmethod.hh b/dumux/nonlinear/newtonmethod.hh
index 55b5531036f4b9613929dd76505af9d57bc827b9..0b142216c5f5613043ca94ad76eca74190f204c1 100644
--- a/dumux/nonlinear/newtonmethod.hh
+++ b/dumux/nonlinear/newtonmethod.hh
@@ -43,8 +43,6 @@ namespace Properties
 NEW_TYPE_TAG(NewtonMethod);
 
 NEW_PROP_TAG(Scalar);
-NEW_PROP_TAG(Problem);
-NEW_PROP_TAG(Model);
 NEW_PROP_TAG(NewtonController);
 NEW_PROP_TAG(SolutionVector);
 NEW_PROP_TAG(JacobianAssembler);
@@ -59,51 +57,42 @@ NEW_PROP_TAG(JacobianAssembler);
 template <class TypeTag>
 class NewtonMethod
 {
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using NewtonController = typename GET_PROP_TYPE(TypeTag, NewtonController);
+    using ConvergenceWriter =  typename GET_PROP_TYPE(TypeTag, NewtonConvergenceWriter);
+    using JacobianAssembler = typename GET_PROP_TYPE(TypeTag, JacobianAssembler);
+    using LinearSolver = typename GET_PROP_TYPE(TypeTag, LinearSolver);
 
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
 public:
-    NewtonMethod(Problem &problem)
-        : problem_(problem)
-    { }
-
-    /*!
-     * \brief Returns a reference to the current numeric problem.
-     */
-    Problem &problem()
-    { return problem_; }
-
-    /*!
-     * \brief Returns a reference to the current numeric problem.
-     */
-    const Problem &problem() const
-    { return problem_; }
-
-    /*!
-     * \brief Returns a reference to the numeric model.
-     */
-    Model &model()
-    { return problem().model(); }
-
-    /*!
-     * \brief Returns a reference to the numeric model.
-     */
-    const Model &model() const
-    { return problem().model(); }
+    NewtonMethod(std::shared_ptr<JacobianAssembler> jacobianAssembler,
+                 std::shared_ptr<LinearSolver> linearSolver)
+    : jacobianAssembler_(jacobianAssembler)
+    , linearSolver_(linearSolver)
+    , matrix_ = std::make_shared<JacobianMatrix>()
+    , residual_ = std::make_shared<SolutionVector>()
+    {
+        // construct the newton controller with or without convergence writer
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence))
+        {
+            newtonController_ = std::make_unique<NewtonController>(assembler().gridView().comm(),
+                                                                   NewtonConvergenceWriter(gridView, assembler().numDofs()));
+        }
+        else
+            newtonController_ = std::make_unique<NewtonController>(assembler().gridView().comm());
 
+        // set the linear system (matrix & residual) in the assembler
+        assembler().setLinearSystem(matrix(), residual());
+    }
 
     /*!
      * \brief Run the newton method. The controller is responsible
      *        for all the strategic decisions.
      */
-    bool execute(NewtonController &ctl)
+    bool execute()
     {
         try {
-            return execute_(ctl);
+            return execute_();
         }
         catch (const NumericalProblem &e) {
             if (ctl.verbose())
@@ -113,32 +102,47 @@ public:
         }
     }
 
-protected:
-    bool execute_(NewtonController &ctl)
+    NewtonController& controller()
+    { return *newtonController_; }
+
+    JacobianAssembler& assembler()
+    { return *jacobianAssembler_; }
+
+    LinearSolver& linearSolver()
+    { return *linearSolver_; }
+
+    JacobianMatrix& matrix()
+    { return *matrix_; }
+
+    SolutionVector& residual()
+    { return residual_; }
+
+private:
+    bool execute_()
     {
-        SolutionVector &uCurrentIter = model().curSol();
+        // the current solution is the initial guess
+        SolutionVector& uCurrentIter = assembler.curSol();
         SolutionVector uLastIter(uCurrentIter);
         SolutionVector deltaU(uCurrentIter);
 
-        JacobianAssembler &jacobianAsm = model().jacobianAssembler();
-
         Dune::Timer assembleTimer(false);
         Dune::Timer solveTimer(false);
         Dune::Timer updateTimer(false);
 
         // tell the controller that we begin solving
-        ctl.newtonBegin(*this, uCurrentIter);
+        controller().newtonBegin(uCurrentIter);
 
         // execute the method as long as the controller thinks
         // that we should do another iteration
-        while (ctl.newtonProceed(uCurrentIter))
+        while (controller().newtonProceed(uCurrentIter))
         {
             // notify the controller that we're about to start
             // a new timestep
-            ctl.newtonBeginStep();
+            controller().newtonBeginStep();
 
             // make the current solution to the old one
-            uLastIter = uCurrentIter;
+            if (controller().newtonNumSteps() > 0)
+                uLastIter = uCurrentIter;
 
             if (ctl.verbose()) {
                 std::cout << "Assemble: r(x^k) = dS/dt + div F - q;   M = grad r";
@@ -151,7 +155,7 @@ protected:
 
             // linearize the problem at the current solution
             assembleTimer.start();
-            jacobianAsm.assemble();
+            controller().assembleLinearSystem(assembler());
             assembleTimer.stop();
 
             ///////////////
@@ -175,9 +179,10 @@ protected:
             // set the delta vector to zero before solving the linear system!
             deltaU = 0;
             // ask the controller to solve the linearized system
-            ctl.newtonSolveLinear(jacobianAsm.matrix(),
-                                  deltaU,
-                                  jacobianAsm.residual());
+            controller().solveLinearSystem(linearSolver(),
+                                           jacobianAsm.matrix(),
+                                           deltaU,
+                                           jacobianAsm.residual());
             solveTimer.stop();
 
             ///////////////
@@ -192,11 +197,11 @@ protected:
             updateTimer.start();
             // update the current solution (i.e. uOld) with the delta
             // (i.e. u). The result is stored in u
-            ctl.newtonUpdate(uCurrentIter, uLastIter, deltaU);
+            ctl.newtonUpdate(assembler(), uCurrentIter, uLastIter, deltaU);
             updateTimer.stop();
 
             // tell the controller that we're done with this iteration
-            ctl.newtonEndStep(uCurrentIter, uLastIter);
+            ctl.newtonEndStep(assembler(), uCurrentIter, uLastIter);
         }
 
         // tell the controller that we're done
@@ -220,8 +225,13 @@ protected:
         return true;
     }
 
-private:
-    Problem &problem_;
+    std::shared_ptr<JacobianAssembler> jacobianAssembler_;
+    std::shared_ptr<LinearSolver> linearSolver_;
+
+    std::unique_ptr<NewtonController> newtonController_;
+
+    std::shared_ptr<JacobianMatrix> matrix_;
+    std::shared_ptr<SolutionVector> residual_;
 };
 
 }