diff --git a/dumux/nonlinear/CMakeLists.txt b/dumux/nonlinear/CMakeLists.txt
index 25e858ce85f0f5ac17e31978b1e4bce7802f26f2..0bc9109ce18c7c9e323562815743f4ba860a1d37 100644
--- a/dumux/nonlinear/CMakeLists.txt
+++ b/dumux/nonlinear/CMakeLists.txt
@@ -1,7 +1,6 @@
 
 #install headers
 install(FILES
-newtoncontroller.hh
 newtonconvergencewriter.hh
-newtonmethod.hh
+newtonsolver.hh
 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/nonlinear)
diff --git a/dumux/nonlinear/newtoncontroller.hh b/dumux/nonlinear/newtoncontroller.hh
deleted file mode 100644
index a64002a69d5fcd5655e4ee20c968fcb34613f5ef..0000000000000000000000000000000000000000
--- a/dumux/nonlinear/newtoncontroller.hh
+++ /dev/null
@@ -1,651 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \ingroup Nonlinear
- * \brief Reference implementation of a controller class for the Newton solver.
- *
- * Usually this controller should be sufficient.
- */
-#ifndef DUMUX_NEWTON_CONTROLLER_HH
-#define DUMUX_NEWTON_CONTROLLER_HH
-
-#include <cmath>
-
-#include <dune/common/exceptions.hh>
-#include <dune/common/parallel/mpicollectivecommunication.hh>
-#include <dune/common/parallel/mpihelper.hh>
-#include <dune/istl/bvector.hh>
-
-#include <dumux/common/exceptions.hh>
-#include <dumux/common/timeloop.hh>
-#include <dune/common/deprecated.hh>
-
-#warning "This file is deprecated. Use NewtonSolver instead."
-
-namespace Dumux {
-
-/*!
- * \ingroup Nonlinear
- * \brief An implementation of a Newton controller
- * \tparam Scalar the scalar type
- * \tparam Comm the communication object used to communicate with all processes
- * \note If you want to specialize only some methods but are happy with the
- *       defaults of the reference controller, derive your controller from
- *       this class and simply overload the required methods.
- */
-template <class Scalar,
-          class Comm = Dune::CollectiveCommunication<Dune::MPIHelper::MPICommunicator> >
-class DUNE_DEPRECATED_MSG("Use NewtonSolver instead.") NewtonController
-{
-
-public:
-    //! the communication type used to communicate with all processes
-    using Communication = Comm;
-
-    /*!
-     * \brief Constructor for stationary problems
-     */
-    NewtonController(const Communication& comm = Dune::MPIHelper::getCollectiveCommunication(),
-                     const std::string& paramGroup = "")
-    : comm_(comm)
-    , endIterMsgStream_(std::ostringstream::out)
-    , paramGroup_(paramGroup)
-    {
-        initParams_(paramGroup);
-    }
-
-    /*!
-     * \brief Constructor for instationary problems
-     */
-    NewtonController(std::shared_ptr<TimeLoop<Scalar>> timeLoop,
-                     const Communication& comm = Dune::MPIHelper::getCollectiveCommunication(),
-                     const std::string& paramGroup = "")
-    : comm_(comm)
-    , timeLoop_(timeLoop)
-    , endIterMsgStream_(std::ostringstream::out)
-    , paramGroup_(paramGroup)
-    {
-        initParams_(paramGroup);
-    }
-
-    //! the communicator for parallel runs
-    const Communication& comm() const
-    { return comm_; }
-
-    /*!
-     * \brief Set the maximum acceptable difference of any primary variable
-     * between two iterations for declaring convergence.
-     *
-     * \param tolerance The maximum relative shift between two Newton
-     *                  iterations at which the scheme is considered finished
-     */
-    void setMaxRelativeShift(Scalar tolerance)
-    { shiftTolerance_ = tolerance; }
-
-    /*!
-     * \brief Set the maximum acceptable absolute residual for declaring convergence.
-     *
-     * \param tolerance The maximum absolute residual at which
-     *                  the scheme is considered finished
-     */
-    void setMaxAbsoluteResidual(Scalar tolerance)
-    { residualTolerance_ = tolerance; }
-
-    /*!
-     * \brief Set the maximum acceptable residual norm reduction.
-     *
-     * \param tolerance The maximum reduction of the residual norm
-     *                  at which the scheme is considered finished
-     */
-    void setResidualReduction(Scalar tolerance)
-    { reductionTolerance_ = tolerance; }
-
-    /*!
-     * \brief Set the number of iterations at which the Newton method
-     *        should aim at.
-     *
-     * This is used to control the time-step size. The heuristic used
-     * is to scale the last time-step size by the deviation of the
-     * number of iterations used from the target steps.
-     *
-     * \param targetSteps Number of iterations which are considered "optimal"
-     */
-    void setTargetSteps(int targetSteps)
-    { targetSteps_ = targetSteps; }
-
-    /*!
-     * \brief Set the number of iterations after which the Newton
-     *        method gives up.
-     *
-     * \param maxSteps Number of iterations after we give up
-     */
-    void setMaxSteps(int maxSteps)
-    { maxSteps_ = maxSteps; }
-
-    /*!
-     * \brief Returns true if another iteration should be done.
-     *
-     * \param uCurrentIter The solution of the current Newton iteration
-     * \param converged if the Newton method's convergence criterion was met in this step
-     */
-    template<class SolutionVector>
-    bool newtonProceed(const SolutionVector &uCurrentIter, bool converged)
-    {
-        if (numSteps_ < 2)
-            return true; // we always do at least two iterations
-        else if (converged) {
-            return false; // we are below the desired tolerance
-        }
-        else if (numSteps_ >= maxSteps_) {
-            // We have exceeded the allowed number of steps. If the
-            // maximum relative shift was reduced by a factor of at least 4,
-            // we proceed even if we are above the maximum number of steps.
-            if (enableShiftCriterion_)
-                return shift_*4.0 < lastShift_;
-            else
-                return reduction_*4.0 < lastReduction_;
-        }
-
-        return true;
-    }
-
-    /*!
-     * \brief Returns true if the error of the solution is below the
-     *        tolerance.
-     */
-    bool newtonConverged() const
-    {
-        if (enableShiftCriterion_ && !enableResidualCriterion_)
-        {
-            return shift_ <= shiftTolerance_;
-        }
-        else if (!enableShiftCriterion_ && enableResidualCriterion_)
-        {
-            if(enableAbsoluteResidualCriterion_)
-                return residualNorm_ <= residualTolerance_;
-            else
-                return reduction_ <= reductionTolerance_;
-        }
-        else if (satisfyResidualAndShiftCriterion_)
-        {
-            if(enableAbsoluteResidualCriterion_)
-                return shift_ <= shiftTolerance_
-                        && residualNorm_ <= residualTolerance_;
-            else
-                return shift_ <= shiftTolerance_
-                        && reduction_ <= reductionTolerance_;
-        }
-        else
-        {
-            return shift_ <= shiftTolerance_
-                    || reduction_ <= reductionTolerance_
-                    || residualNorm_ <= residualTolerance_;
-        }
-
-        return false;
-    }
-
-    /*!
-     * \brief Called before the Newton method is applied to an
-     *        non-linear system of equations.
-     *
-     * \param u The initial solution
-     */
-    template<class SolutionVector>
-    void newtonBegin(const SolutionVector& u)
-    {
-        numSteps_ = 0;
-    }
-
-    /*!
-     * \brief Indicates the beginning of a Newton iteration.
-     */
-    template<class SolutionVector>
-    void newtonBeginStep(const SolutionVector& u)
-    {
-        lastShift_ = shift_;
-        if (numSteps_ == 0)
-        {
-            lastReduction_ = 1.0;
-        }
-        else
-        {
-            lastReduction_ = reduction_;
-        }
-    }
-
-    /*!
-     * \brief Returns the number of steps done since newtonBegin() was
-     *        called.
-     */
-    int newtonNumSteps()
-    { return numSteps_; }
-
-    /*!
-     * \brief Update the maximum relative shift of the solution compared to
-     *        the previous iteration.
-     *
-     * \param uLastIter The current iterative solution
-     * \param deltaU The difference between the current and the next solution
-     */
-    template<class SolutionVector>
-    void newtonUpdateShift(const SolutionVector &uLastIter,
-                           const SolutionVector &deltaU)
-    {
-        shift_ = 0;
-
-        for (int i = 0; i < int(uLastIter.size()); ++i) {
-            typename SolutionVector::block_type uNewI = uLastIter[i];
-            uNewI -= deltaU[i];
-
-            Scalar shiftAtDof = relativeShiftAtDof_(uLastIter[i], uNewI);
-            using std::max;
-            shift_ = max(shift_, shiftAtDof);
-        }
-
-        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
-     * \param uCurrentIter The current iteration's solution vector
-     */
-    template<class JacobianAssembler, class SolutionVector>
-    void assembleLinearSystem(JacobianAssembler& assembler,
-                              const SolutionVector& uCurrentIter)
-    {
-        assembler.assembleJacobianAndResidual(uCurrentIter);
-    }
-
-    /*!
-     * \brief Solve the linear system of equations \f$\mathbf{A}x - b = 0\f$.
-     *
-     * \throws Dumux::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
-     */
-    template<class LinearSolver, class JacobianMatrix, class SolutionVector>
-    void solveLinearSystem(LinearSolver& ls,
-                           JacobianMatrix& A,
-                           SolutionVector& x,
-                           SolutionVector& b)
-    {
-        try {
-            if (numSteps_ == 0)
-            {
-                Scalar norm2 = b.two_norm2();
-                if (comm().size() > 1)
-                    norm2 = comm().sum(norm2);
-
-                using std::sqrt;
-                initialResidual_ = sqrt(norm2);
-            }
-
-            //! Copy into a standard block vector.
-            //! This is necessary for all model _not_ using a FieldVector<Scalar, blockSize> as
-            //! primary variables vector in combination with UMFPack or SuperLU as their interfaces are hard coded
-            //! to this field vector type in Dune ISTL
-            //! Could be avoided for vectors that already have the right type using SFINAE
-            //! but it shouldn't impact performance too much
-            constexpr auto blockSize = JacobianMatrix::block_type::rows;
-            using BlockType = Dune::FieldVector<Scalar, blockSize>;
-            Dune::BlockVector<BlockType> xTmp; xTmp.resize(b.size());
-            Dune::BlockVector<BlockType> bTmp(xTmp);
-            for (unsigned int i = 0; i < b.size(); ++i)
-                for (unsigned int j = 0; j < blockSize; ++j)
-                    bTmp[i][j] = b[i][j];
-
-            int converged = ls.solve(A, xTmp, bTmp);
-
-            for (unsigned int i = 0; i < x.size(); ++i)
-                for (unsigned int j = 0; j < blockSize; ++j)
-                    x[i][j] = xTmp[i][j];
-
-            // make sure all processes converged
-            int convergedRemote = converged;
-            if (comm().size() > 1)
-                convergedRemote = comm().min(converged);
-
-            if (!converged) {
-                DUNE_THROW(NumericalProblem,
-                           "Linear solver did not converge");
-            }
-            else if (!convergedRemote) {
-                DUNE_THROW(NumericalProblem,
-                           "Linear solver did not converge on a remote process");
-            }
-        }
-        catch (const Dune::Exception &e) {
-            // make sure all processes converged
-            int converged = 0;
-            if (comm().size() > 1)
-                converged = comm().min(converged);
-
-            NumericalProblem p;
-            p.message(e.what());
-            throw p;
-        }
-    }
-
-    /*!
-     * \brief Update the current solution with a delta vector.
-     *
-     * The error estimates required for the newtonConverged() and
-     * newtonProceed() methods should be updated inside this method.
-     *
-     * Different update strategies, such as line search and chopped
-     * updates can be implemented. The default behavior is just to
-     * 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.
-     */
-    template<class JacobianAssembler, class SolutionVector>
-    void newtonUpdate(JacobianAssembler& assembler,
-                      SolutionVector &uCurrentIter,
-                      const SolutionVector &uLastIter,
-                      const SolutionVector &deltaU)
-    {
-        if (enableShiftCriterion_)
-            newtonUpdateShift(uLastIter, deltaU);
-
-        if (useLineSearch_)
-        {
-            lineSearchUpdate_(assembler, uCurrentIter, uLastIter, deltaU);
-        }
-        else {
-            for (unsigned int i = 0; i < uLastIter.size(); ++i) {
-                uCurrentIter[i] = uLastIter[i];
-                uCurrentIter[i] -= deltaU[i];
-            }
-
-            if (enableResidualCriterion_)
-            {
-                residualNorm_ = assembler.residualNorm(uCurrentIter);
-                reduction_ = residualNorm_;
-                reduction_ /= initialResidual_;
-            }
-            else
-            {
-                // If we get here, the convergence criterion does not require
-                // additional residual evalutions. Thus, the grid variables have
-                // not yet been updated to the new uCurrentIter.
-                assembler.gridVariables().update(uCurrentIter);
-            }
-        }
-    }
-
-    /*!
-     * \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
-     */
-    template<class JacobianAssembler, class SolutionVector>
-    void newtonEndStep(JacobianAssembler& assembler,
-                       SolutionVector &uCurrentIter,
-                       const SolutionVector &uLastIter)
-    {
-        ++numSteps_;
-
-        if (verbose())
-        {
-            std::cout << "\rNewton iteration " << numSteps_ << " done";
-            if (enableShiftCriterion_)
-                std::cout << ", maximum relative shift = " << shift_;
-            if (enableResidualCriterion_ && enableAbsoluteResidualCriterion_)
-                std::cout << ", residual = " << residualNorm_;
-            else if (enableResidualCriterion_)
-                std::cout << ", residual reduction = " << reduction_;
-            std::cout << endIterMsg().str() << "\n";
-        }
-        endIterMsgStream_.str("");
-
-        // When the Newton iterations are done: ask the model to check whether it makes sense
-        // TODO: how do we realize this? -> do this here in the newton controller
-        // model_().checkPlausibility();
-    }
-
-    /*!
-     * \brief Called if the Newton method ended
-     *        (not known yet if we failed or succeeded)
-     */
-    void newtonEnd() {}
-
-    /*!
-     * \brief Called if the Newton method ended succcessfully
-     * This method is called _after_ newtonEnd()
-     */
-    void newtonSucceed() {}
-
-    /*!
-     * \brief Called if the Newton method broke down.
-     * This method is called _after_ newtonEnd()
-     */
-    template<class Assembler, class SolutionVector>
-    void newtonFail(Assembler& assembler, SolutionVector& u)
-    {
-        if (!assembler.isStationaryProblem())
-        {
-            // set solution to previous solution
-            u = assembler.prevSol();
-
-            // reset the grid variables to the previous solution
-            assembler.gridVariables().resetTimeStep(u);
-
-            if (verbose())
-            {
-                std::cout << "Newton solver did not converge with dt = "
-                          << timeLoop_->timeStepSize() << " seconds. Retrying with time step of "
-                          << timeLoop_->timeStepSize()/2 << " seconds\n";
-            }
-
-            // try again with dt = dt/2
-            timeLoop_->setTimeStepSize(timeLoop_->timeStepSize()/2);
-        }
-        else
-            DUNE_THROW(Dune::MathError, "Newton solver did not converge");
-    }
-
-    /*!
-     * \brief Suggest a new time-step size based on the old time-step
-     *        size.
-     *
-     * The default behavior is to suggest the old time-step size
-     * scaled by the ratio between the target iterations and the
-     * iterations required to actually solve the last time-step.
-     */
-    Scalar suggestTimeStepSize(Scalar oldTimeStep) const
-    {
-        // be aggressive reducing the time-step size but
-        // conservative when increasing it. the rationale is
-        // that we want to avoid failing in the next Newton
-        // iteration which would require another linearization
-        // of the problem.
-        if (numSteps_ > targetSteps_) {
-            Scalar percent = Scalar(numSteps_ - targetSteps_)/targetSteps_;
-            return oldTimeStep/(1.0 + percent);
-        }
-
-        Scalar percent = Scalar(targetSteps_ - numSteps_)/targetSteps_;
-        return oldTimeStep*(1.0 + percent/1.2);
-    }
-
-    std::ostringstream &endIterMsg()
-    { return endIterMsgStream_; }
-
-    /*!
-     * \brief Specifies if the Newton method ought to be chatty.
-     */
-    void setVerbose(bool val)
-    { verbose_ = val; }
-
-    /*!
-     * \brief Returns true if the Newton method ought to be chatty.
-     */
-    bool verbose() const
-    { return verbose_ && comm().rank() == 0; }
-
-    /*!
-     * \brief Returns the parameter group
-     */
-    const std::string& paramGroup() const
-    { return paramGroup_; }
-
-protected:
-
-    //! initialize the parameters by reading from the parameter tree
-    void initParams_(const std::string& group = "")
-    {
-        useLineSearch_ = getParamFromGroup<bool>(group, "Newton.UseLineSearch");
-        enableAbsoluteResidualCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableAbsoluteResidualCriterion");
-        enableShiftCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableShiftCriterion");
-        enableResidualCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableResidualCriterion") || enableAbsoluteResidualCriterion_;
-        satisfyResidualAndShiftCriterion_ = getParamFromGroup<bool>(group, "Newton.SatisfyResidualAndShiftCriterion");
-        if (!enableShiftCriterion_ && !enableResidualCriterion_)
-        {
-            DUNE_THROW(Dune::NotImplemented,
-                       "at least one of NewtonEnableShiftCriterion or "
-                       << "NewtonEnableResidualCriterion has to be set to true");
-        }
-
-        setMaxRelativeShift(getParamFromGroup<Scalar>(group, "Newton.MaxRelativeShift"));
-        setMaxAbsoluteResidual(getParamFromGroup<Scalar>(group, "Newton.MaxAbsoluteResidual"));
-        setResidualReduction(getParamFromGroup<Scalar>(group, "Newton.ResidualReduction"));
-        setTargetSteps(getParamFromGroup<int>(group, "Newton.TargetSteps"));
-        setMaxSteps(getParamFromGroup<int>(group, "Newton.MaxSteps"));
-
-        verbose_ = true;
-        numSteps_ = 0;
-    }
-
-    template<class JacobianAssembler, class SolutionVector>
-    void lineSearchUpdate_(JacobianAssembler& assembler,
-                           SolutionVector &uCurrentIter,
-                           const SolutionVector &uLastIter,
-                           const SolutionVector &deltaU)
-    {
-        Scalar lambda = 1.0;
-        SolutionVector tmp(uLastIter);
-
-        while (true)
-        {
-            uCurrentIter = deltaU;
-            uCurrentIter *= -lambda;
-            uCurrentIter += uLastIter;
-
-            residualNorm_ = assembler.residualNorm(uCurrentIter);
-            reduction_ = residualNorm_;
-            reduction_ /= initialResidual_;
-
-            if (reduction_ < lastReduction_ || lambda <= 0.125) {
-                endIterMsg() << ", residual reduction " << lastReduction_ << "->"  << reduction_ << "@lambda=" << lambda;
-                return;
-            }
-
-            // try with a smaller update
-            lambda /= 2.0;
-        }
-    }
-
-    /*!
-     * \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
-     */
-    template<class PrimaryVariables>
-    Scalar relativeShiftAtDof_(const PrimaryVariables &priVars1,
-                               const PrimaryVariables &priVars2)
-    {
-        Scalar result = 0.0;
-        using std::abs;
-        using std::max;
-        // iterate over all primary variables
-        for (int j = 0; j < PrimaryVariables::dimension; ++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 communication object
-    Communication comm_;
-
-    //! The time loop for stationary simulations
-    std::shared_ptr<TimeLoop<Scalar>> timeLoop_;
-
-    //! message stream to be displayed at the end of iterations
-    std::ostringstream endIterMsgStream_;
-
-    //! switches on/off verbosity
-    bool verbose_;
-
-    // shift criterion variables
-    Scalar shift_;
-    Scalar lastShift_;
-    Scalar shiftTolerance_;
-
-    // residual criterion variables
-    Scalar reduction_;
-    Scalar residualNorm_;
-    Scalar lastReduction_;
-    Scalar initialResidual_;
-    Scalar reductionTolerance_;
-    Scalar residualTolerance_;
-
-    //! optimal number of iterations we want to achieve
-    int targetSteps_;
-    //! maximum number of iterations we do before giving up
-    int maxSteps_;
-    //! actual number of steps done so far
-    int numSteps_;
-
-    // further parameters
-    bool enablePartialReassemble_;
-    bool useLineSearch_;
-    bool enableAbsoluteResidualCriterion_;
-    bool enableShiftCriterion_;
-    bool enableResidualCriterion_;
-    bool satisfyResidualAndShiftCriterion_;
-
-    //! the parameter group for getting parameters from the parameter tree
-    std::string paramGroup_;
-};
-
-} // end namespace Dumux
-
-#endif
diff --git a/dumux/nonlinear/newtonmethod.hh b/dumux/nonlinear/newtonmethod.hh
deleted file mode 100644
index 7264b3cedff741530657ae7a4a9e5a5ffae4a748..0000000000000000000000000000000000000000
--- a/dumux/nonlinear/newtonmethod.hh
+++ /dev/null
@@ -1,222 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \ingroup Nonlinear
- * \brief The algorithmic part of the multi dimensional newton method.
- *
- * In order to use the method you need a Newtoncontroller
- */
-#ifndef DUMUX_NEWTONMETHOD_HH
-#define DUMUX_NEWTONMETHOD_HH
-
-#include <memory>
-#include <iostream>
-
-#include <dune/common/timer.hh>
-#include <dune/istl/istlexception.hh>
-
-#include <dumux/common/exceptions.hh>
-#include <dumux/common/properties.hh>
-#include <dumux/common/parameters.hh>
-#include <dune/common/deprecated.hh>
-
-#warning "This file is deprecated. Use NewtonSolver instead."
-
-namespace Dumux {
-
-/*!
- * \ingroup Newton
- * \ingroup Nonlinear
- * \brief The algorithmic part of the multi dimensional newton method.
- *
- * \tparam NewtonController the controller class is the driver implementation
- * \tparam JacobianAssembler an assembler for the Jacobian and the residual
- * \tparam LinearSolver the linear solver used to solve one iteration
- */
-template <class NewtonController, class JacobianAssembler, class LinearSolver>
-class DUNE_DEPRECATED_MSG("Use NewtonSolver instead.") NewtonMethod
-{
-    //! provide an interface as a form of type erasure
-    //! this is the minimal requirements a convergence write passed to a newton method has to fulfill
-    struct ConvergenceWriterInferface
-    {
-        template<class SolutionVector>
-        void write(const SolutionVector &uLastIter, const SolutionVector &deltaU, const SolutionVector &residual) {}
-    };
-
-public:
-    NewtonMethod(std::shared_ptr<NewtonController> controller,
-                 std::shared_ptr<JacobianAssembler> assembler,
-                 std::shared_ptr<LinearSolver> linearSolver,
-                 const std::string& modelParamGroup = "")
-    : controller_(controller)
-    , assembler_(assembler)
-    , linearSolver_(linearSolver)
-    {
-        // set the linear system (matrix & residual) in the assembler
-        assembler_->setLinearSystem();
-
-        // set a different default for the linear solver residual reduction
-        // within the Newton the linear solver doesn't need to solve too exact
-        using Scalar = typename LinearSolver::Scalar;
-        linearSolver_->setResidualReduction(getParamFromGroup<Scalar>(modelParamGroup, "LinearSolver.ResidualReduction", 1e-6));
-    }
-
-    /*!
-     * \brief Run the newton method to solve a non-linear system.
-     *        The controller is responsible for all the strategic decisions.
-     */
-    template<class SolutionVector, class ConvergenceWriter = ConvergenceWriterInferface>
-    bool solve(SolutionVector& uCurrentIter, const std::unique_ptr<ConvergenceWriter>& convWriter = nullptr)
-    {
-        try
-        {
-            // the given solution is the initial guess
-            SolutionVector uLastIter(uCurrentIter);
-            SolutionVector deltaU(uCurrentIter);
-
-            Dune::Timer assembleTimer(false);
-            Dune::Timer solveTimer(false);
-            Dune::Timer updateTimer(false);
-
-            // tell the controller that we begin solving
-            controller_->newtonBegin(uCurrentIter);
-
-            // execute the method as long as the controller thinks
-            // that we should do another iteration
-            while (controller_->newtonProceed(uCurrentIter, controller_->newtonConverged()))
-            {
-                // notify the controller that we're about to start
-                // a new timestep
-                controller_->newtonBeginStep(uCurrentIter);
-
-                // make the current solution to the old one
-                if (controller_->newtonNumSteps() > 0)
-                    uLastIter = uCurrentIter;
-
-                if (controller_->verbose()) {
-                    std::cout << "Assemble: r(x^k) = dS/dt + div F - q;   M = grad r";
-                    std::cout.flush();
-                }
-
-                ///////////////
-                // assemble
-                ///////////////
-
-                // linearize the problem at the current solution
-                assembleTimer.start();
-                controller_->assembleLinearSystem(*assembler_, uCurrentIter);
-                assembleTimer.stop();
-
-                ///////////////
-                // linear solve
-                ///////////////
-
-                // Clear the current line using an ansi escape
-                // sequence.  for an explanation see
-                // http://en.wikipedia.org/wiki/ANSI_escape_code
-                const char clearRemainingLine[] = { 0x1b, '[', 'K', 0 };
-
-                if (controller_->verbose()) {
-                    std::cout << "\rSolve: M deltax^k = r";
-                    std::cout << clearRemainingLine;
-                    std::cout.flush();
-                }
-
-                // solve the resulting linear equation system
-                solveTimer.start();
-
-                // set the delta vector to zero before solving the linear system!
-                deltaU = 0;
-                // ask the controller to solve the linearized system
-                controller_->solveLinearSystem(*linearSolver_,
-                                               assembler_->jacobian(),
-                                               deltaU,
-                                               assembler_->residual());
-                solveTimer.stop();
-
-                ///////////////
-                // update
-                ///////////////
-                if (controller_->verbose()) {
-                    std::cout << "\rUpdate: x^(k+1) = x^k - deltax^k";
-                    std::cout << clearRemainingLine;
-                    std::cout.flush();
-                }
-
-                updateTimer.start();
-                // update the current solution (i.e. uOld) with the delta
-                // (i.e. u). The result is stored in u
-                controller_->newtonUpdate(*assembler_, uCurrentIter, uLastIter, deltaU);
-                updateTimer.stop();
-
-                // tell the controller that we're done with this iteration
-                controller_->newtonEndStep(*assembler_, uCurrentIter, uLastIter);
-
-                // if a convergence writer was specified compute residual and write output
-                if (convWriter)
-                {
-                    assembler_->assembleResidual(uCurrentIter);
-                    convWriter->write(uLastIter, deltaU, assembler_->residual());
-                }
-            }
-
-            // tell controller we are done
-            controller_->newtonEnd();
-
-            // reset state if newton failed
-            if (!controller_->newtonConverged())
-            {
-                controller_->newtonFail(*assembler_, uCurrentIter);
-                return false;
-            }
-
-            // tell controller we converged successfully
-            controller_->newtonSucceed();
-
-            if (controller_->verbose()) {
-                const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed();
-                std::cout << "Assemble/solve/update time: "
-                          <<  assembleTimer.elapsed() << "(" << 100*assembleTimer.elapsed()/elapsedTot << "%)/"
-                          <<  solveTimer.elapsed() << "(" << 100*solveTimer.elapsed()/elapsedTot << "%)/"
-                          <<  updateTimer.elapsed() << "(" << 100*updateTimer.elapsed()/elapsedTot << "%)"
-                          << "\n";
-            }
-            return true;
-
-        }
-        catch (const NumericalProblem &e)
-        {
-            if (controller_->verbose())
-                std::cout << "Newton: Caught exception: \"" << e.what() << "\"\n";
-            controller_->newtonFail(*assembler_, uCurrentIter);
-            return false;
-        }
-    }
-
-private:
-    std::shared_ptr<NewtonController> controller_;
-    std::shared_ptr<JacobianAssembler> assembler_;
-    std::shared_ptr<LinearSolver> linearSolver_;
-};
-
-} // end namespace Dumux
-
-#endif
diff --git a/dumux/nonlinear/newtonsolver.hh b/dumux/nonlinear/newtonsolver.hh
index b50dbd7c63ca6454e4dbd1c36eb56bad8235b2ac..82f9eca3de8b4fe84564362b67d6c6630fe32759 100644
--- a/dumux/nonlinear/newtonsolver.hh
+++ b/dumux/nonlinear/newtonsolver.hh
@@ -19,9 +19,9 @@
 /*!
  * \file
  * \ingroup Nonlinear
- * \brief Reference implementation of a controller class for the Newton solver.
+ * \brief Reference implementation of the Newton solver.
  *
- * Usually this controller should be sufficient.
+ * Usually this solver should be sufficient.
  */
 #ifndef DUMUX_NEWTON_SOLVER_HH
 #define DUMUX_NEWTON_SOLVER_HH
@@ -61,11 +61,12 @@ struct supportsPartialReassembly
 
 /*!
  * \ingroup Nonlinear
- * \brief An implementation of a Newton controller
- * \tparam Scalar the scalar type
+ * \brief An implementation of a Newton solver
+ * \tparam Assembler the assembler
+ * \tparam LinearSolver the linear solver
  * \tparam Comm the communication object used to communicate with all processes
  * \note If you want to specialize only some methods but are happy with the
- *       defaults of the reference controller, derive your controller from
+ *       defaults of the reference solver, derive your solver from
  *       this class and simply overload the required methods.
  */
 template <class Assembler, class LinearSolver,
@@ -214,7 +215,7 @@ public:
 
     /*!
      * \brief Run the newton method to solve a non-linear system.
-     *        The controller is responsible for all the strategic decisions.
+     *        The solver is responsible for all the strategic decisions.
      */
     void solve(SolutionVector& uCurrentIter, const std::unique_ptr<ConvergenceWriter>& convWriter = nullptr)
     {
@@ -471,7 +472,7 @@ public:
         endIterMsgStream_.str("");
 
         // When the Newton iterations are done: ask the model to check whether it makes sense
-        // TODO: how do we realize this? -> do this here in the newton controller
+        // TODO: how do we realize this? -> do this here in the newton solver
         // model_().checkPlausibility();
     }
 
@@ -620,7 +621,7 @@ private:
 
     /*!
      * \brief Run the newton method to solve a non-linear system.
-     *        The controller is responsible for all the strategic decisions.
+     *        The solver is responsible for all the strategic decisions.
      */
     bool solve_(SolutionVector& uCurrentIter, const std::unique_ptr<ConvergenceWriter>& convWriter = nullptr)
     {
@@ -643,11 +644,11 @@ private:
         {
             newtonBegin(uCurrentIter);
 
-            // execute the method as long as the controller thinks
+            // execute the method as long as the solver thinks
             // that we should do another iteration
             while (newtonProceed(uCurrentIter, newtonConverged()))
             {
-                // notify the controller that we're about to start
+                // notify the solver that we're about to start
                 // a new timestep
                 newtonBeginStep(uCurrentIter);
 
@@ -708,7 +709,7 @@ private:
                 newtonUpdate(uCurrentIter, uLastIter, deltaU);
                 updateTimer.stop();
 
-                // tell the controller that we're done with this iteration
+                // tell the solver that we're done with this iteration
                 newtonEndStep(uCurrentIter, uLastIter);
 
                 // if a convergence writer was specified compute residual and write output
@@ -719,7 +720,7 @@ private:
                 }
             }
 
-            // tell controller we are done
+            // tell solver we are done
             newtonEnd();
 
             // reset state if newton failed
@@ -729,7 +730,7 @@ private:
                 return false;
             }
 
-            // tell controller we converged successfully
+            // tell solver we converged successfully
             newtonSucceed();
 
             if (verbose_) {
diff --git a/dumux/nonlinear/privarswitchnewtonsolver.hh b/dumux/nonlinear/privarswitchnewtonsolver.hh
index 39359fdc1ec8fd18a40e5ff8340fe9d4fbac7b25..f28bb46a38d52e0d3120049d6dc2cea037788db9 100644
--- a/dumux/nonlinear/privarswitchnewtonsolver.hh
+++ b/dumux/nonlinear/privarswitchnewtonsolver.hh
@@ -19,9 +19,7 @@
 /*!
  * \file
  * \ingroup PorousmediumCompositional
- * \brief Reference implementation of a controller class for the Newton solver.
- *
- * Usually this controller should be sufficient.
+ * \copydoc Dumux::PriVarSwitchNewtonSolver
  */
 #ifndef DUMUX_PRIVARSWITCH_NEWTON_SOLVER_HH
 #define DUMUX_PRIVARSWITCH_NEWTON_SOLVER_HH
@@ -37,9 +35,7 @@ namespace Dumux {
 
 /*!
  * \ingroup PorousmediumCompositional
- * \brief A newton controller that handles primary variable switches
- * \todo make this independent of TypeTag by making PrimaryVariableSwitch a template argument
- *       and extracting everything model specific from there
+ * \brief A newton solver that handles primary variable switches
  */
 template <class Assembler, class LinearSolver, class PrimaryVariableSwitch>
 class PriVarSwitchNewtonSolver : public NewtonSolver<Assembler, LinearSolver>
diff --git a/dumux/nonlinear/staggerednewtoncontroller.hh b/dumux/nonlinear/staggerednewtoncontroller.hh
deleted file mode 100644
index bedcf6d4ad2770325dfdddf33514827b232d5b3d..0000000000000000000000000000000000000000
--- a/dumux/nonlinear/staggerednewtoncontroller.hh
+++ /dev/null
@@ -1,299 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \ingroup Nonlinear
- * \ingroup StaggeredDiscretization
- * \brief A newton controller for staggered finite volume schemes
- */
-#ifndef DUMUX_STAGGERED_NEWTON_CONTROLLER_HH
-#define DUMUX_STAGGERED_NEWTON_CONTROLLER_HH
-
-#include <dune/common/indices.hh>
-#include <dune/common/hybridutilities.hh>
-#include <dune/common/fvector.hh>
-#include <dune/istl/bvector.hh>
-
-#include <dumux/common/exceptions.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dumux/linear/linearsolveracceptsmultitypematrix.hh>
-#include <dumux/linear/matrixconverter.hh>
-#include <dune/common/deprecated.hh>
-
-#warning "This file is deprecated. Use NewtonSolver instead."
-
-namespace Dumux {
-
-/*!
- * \ingroup Nonlinear
- * \ingroup StaggeredDiscretization
- * \brief A newton controller for staggered finite volume schemes
- */
-
-template <class Scalar,
-          class Comm = Dune::CollectiveCommunication<Dune::MPIHelper::MPICommunicator> >
-class DUNE_DEPRECATED_MSG("Use NewtonSolver instead.")
-StaggeredNewtonController : public NewtonController<Scalar, Comm>
-{
-    using ParentType = NewtonController<Scalar, Comm>;
-
-public:
-    using ParentType::ParentType;
-
-    /*!
-     * \brief Solve the linear system of equations \f$\mathbf{A}x - b = 0\f$.
-     *
-     * Throws Dumux::NumericalProblem if the linear solver didn't
-     * converge.
-     *
-     * If the linear solver doesn't accept multitype matrices we copy the matrix
-     * into a 1x1 block BCRS matrix for solving.
-     *
-     * \param ls the linear solver
-     * \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
-     */
-    template<class LinearSolver, class JacobianMatrix, class SolutionVector>
-    void solveLinearSystem(LinearSolver& ls,
-                           JacobianMatrix& A,
-                           SolutionVector& x,
-                           SolutionVector& b)
-    {
-        // check matrix sizes
-        assert(checkMatrix_(A) && "Sub blocks of MultiType matrix have wrong sizes!");
-
-        try
-        {
-            if (this->numSteps_ == 0)
-            {
-                Scalar norm2 = b.two_norm2();
-                if (this->comm().size() > 1)
-                    norm2 = this->comm().sum(norm2);
-
-                using std::sqrt;
-                this->initialResidual_ = sqrt(norm2);
-            }
-
-            // solve by calling the appropriate implementation depending on whether the linear solver
-            // is capable of handling MultiType matrices or not
-            bool converged = solveLinearSystem_(ls, A, x, b,
-                                                std::integral_constant<bool, linearSolverAcceptsMultiTypeMatrix<LinearSolver>::value>());
-
-            // make sure all processes converged
-            int convergedRemote = converged;
-            if (this->comm().size() > 1)
-                convergedRemote = this->comm().min(converged);
-
-            if (!converged) {
-                DUNE_THROW(NumericalProblem,
-                           "Linear solver did not converge");
-            }
-            else if (!convergedRemote) {
-                DUNE_THROW(NumericalProblem,
-                           "Linear solver did not converge on a remote process");
-            }
-        }
-        catch (const Dune::Exception &e) {
-            // make sure all processes converged
-            int converged = 0;
-            if (this->comm().size() > 1)
-                converged = this->comm().min(converged);
-
-            NumericalProblem p;
-            p.message(e.what());
-            throw p;
-        }
-    }
-
-
-
-    /*!
-    * \brief Update the current solution with a delta vector.
-    *
-    * The error estimates required for the newtonConverged() and
-    * newtonProceed() methods should be updated inside this method.
-    *
-    * Different update strategies, such as line search and chopped
-    * updates can be implemented. The default behavior is just to
-    * subtract deltaU from uLastIter, i.e.
-    * \f[ u^{k+1} = u^k - \Delta u^k \f]
-    *
-    * \param assembler The assembler for Jacobian and residual
-    * \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.
-    */
-    template<class JacobianAssembler, class SolutionVector>
-    void newtonUpdate(JacobianAssembler& assembler,
-                      SolutionVector &uCurrentIter,
-                      const SolutionVector &uLastIter,
-                      const SolutionVector &deltaU)
-    {
-        if (this->enableShiftCriterion_)
-            this->newtonUpdateShift(uLastIter, deltaU);
-
-        if (this->useLineSearch_)
-        {
-            this->lineSearchUpdate_(assembler, uCurrentIter, uLastIter, deltaU);
-        }
-        else {
-            using namespace Dune::Hybrid;
-            forEach(integralRange(Dune::Hybrid::size(uLastIter)), [&](const auto dofTypeIdx)
-            {
-                for (unsigned int i = 0; i < uLastIter[dofTypeIdx].size(); ++i)
-                {
-                    uCurrentIter[dofTypeIdx][i] = uLastIter[dofTypeIdx][i];
-                    uCurrentIter[dofTypeIdx][i] -= deltaU[dofTypeIdx][i];
-                }
-            });
-
-            if (this->enableResidualCriterion_)
-            {
-                this->residualNorm_ = assembler.residualNorm(uCurrentIter);
-                this->reduction_ = this->residualNorm_;
-                this->reduction_ /= this->initialResidual_;
-            }
-        }
-
-        // update the variables class to the new solution
-        assembler.gridVariables().update(uCurrentIter);
-    }
-
-     /*!
-     * \brief Update the maximum relative shift of the solution compared to
-     *        the previous iteration.
-     *
-     * \param uLastIter The current iterative solution
-     * \param deltaU The difference between the current and the next solution
-     */
-    template<class SolutionVector>
-    void newtonUpdateShift(const SolutionVector &uLastIter,
-                           const SolutionVector &deltaU)
-    {
-        this->shift_ = 0;
-
-        using namespace Dune::Hybrid;
-        forEach(integralRange(Dune::Hybrid::size(uLastIter)), [&](const auto dofTypeIdx)
-        {
-            for (int i = 0; i < int(uLastIter[dofTypeIdx].size()); ++i)
-            {
-                auto uNewI = uLastIter[dofTypeIdx][i];
-                uNewI -= deltaU[dofTypeIdx][i];
-
-                Scalar shiftAtDof = this->relativeShiftAtDof_(uLastIter[dofTypeIdx][i], uNewI);
-                this->shift_ = std::max(this->shift_, shiftAtDof);
-            }
-        });
-
-        if (this->comm().size() > 1)
-            this->shift_ = this->comm().max(this->shift_);
-    }
-
-private:
-    /*!
-     * \brief Solve the linear system of equations \f$\mathbf{A}x - b = 0\f$.
-     *
-     * Throws Dumux::NumericalProblem if the linear solver didn't
-     * converge.
-     *
-     * Specialization for linear solvers that can handle MultiType matrices.
-     *
-     */
-    template<class LinearSolver, class JacobianMatrix, class SolutionVector>
-    bool solveLinearSystem_(LinearSolver& ls,
-                            JacobianMatrix& A,
-                            SolutionVector& x,
-                            SolutionVector& b,
-                            std::true_type)
-    {
-        // TODO: automatically derive the precondBlockLevel
-        return ls.template solve</*precondBlockLevel=*/2>(A, x, b);
-    }
-
-    /*!
-     * \brief Solve the linear system of equations \f$\mathbf{A}x - b = 0\f$.
-     *
-     * Throws Dumux::NumericalProblem if the linear solver didn't
-     * converge.
-     *
-     * Specialization for linear solvers that cannot handle MultiType matrices.
-     * We copy the matrix into a 1x1 block BCRS matrix before solving.
-     *
-     */
-    template<class LinearSolver, class JacobianMatrix, class SolutionVector>
-    bool solveLinearSystem_(LinearSolver& ls,
-                            JacobianMatrix& A,
-                            SolutionVector& x,
-                            SolutionVector& b,
-                            std::false_type)
-    {
-        // create the bcrs matrix the IterativeSolver backend can handle
-        const auto M = MatrixConverter<JacobianMatrix>::multiTypeToBCRSMatrix(A);
-
-        // get the new matrix sizes
-        const std::size_t numRows = M.N();
-        assert(numRows == M.M());
-
-        // create the vector the IterativeSolver backend can handle
-        const auto bTmp = VectorConverter<SolutionVector>::multiTypeToBlockVector(b);
-        assert(bTmp.size() == numRows);
-
-        // create a blockvector to which the linear solver writes the solution
-        using VectorBlock = typename Dune::FieldVector<Scalar, 1>;
-        using BlockVector = typename Dune::BlockVector<VectorBlock>;
-        BlockVector y(numRows);
-
-        // solve
-        const bool converged = ls.solve(M, y, bTmp);
-
-        // copy back the result y into x
-        if(converged)
-            VectorConverter<SolutionVector>::retrieveValues(x, y);
-
-        return converged;
-    }
-
-    //! helper method to assure the MultiType matrix's sub blocks have the correct sizes
-    template<class JacobianMatrix>
-    bool checkMatrix_(const JacobianMatrix& A)
-    {
-        bool matrixHasCorrectSize = true;
-        using namespace Dune::Hybrid;
-        using namespace Dune::Indices;
-        forEach(A, [&matrixHasCorrectSize](const auto& rowOfMultiTypeMatrix)
-        {
-            const auto numRowsLeftMostBlock = rowOfMultiTypeMatrix[_0].N();
-
-            forEach(rowOfMultiTypeMatrix, [&matrixHasCorrectSize, &numRowsLeftMostBlock](const auto& subBlock)
-            {
-                if (subBlock.N() != numRowsLeftMostBlock)
-                    matrixHasCorrectSize = false;
-            });
-        });
-        return matrixHasCorrectSize;
-    }
-
-};
-
-} // end namespace Dumux
-
-#endif
diff --git a/dumux/porousmediumflow/2pnc/CMakeLists.txt b/dumux/porousmediumflow/2pnc/CMakeLists.txt
index 612765aa72256d6bb3e314a3c613c4ce6021f072..5e3c930c89509e68756c958178cff2e748398917 100644
--- a/dumux/porousmediumflow/2pnc/CMakeLists.txt
+++ b/dumux/porousmediumflow/2pnc/CMakeLists.txt
@@ -3,7 +3,6 @@
 install(FILES
 indices.hh
 model.hh
-newtoncontroller.hh
 primaryvariableswitch.hh
 volumevariables.hh
 vtkoutputfields.hh
diff --git a/dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh b/dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh
deleted file mode 100644
index 553414dbbcfd293ea1ea8d7755b2444fd5f2ead4..0000000000000000000000000000000000000000
--- a/dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh
+++ /dev/null
@@ -1,220 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \ingroup PorousmediumCompositional
- * \brief Reference implementation of a controller class for the Newton solver.
- *
- * Usually this controller should be sufficient.
- */
-#ifndef DUMUX_PRIVARSWITCH_NEWTON_CONTROLLER_HH
-#define DUMUX_PRIVARSWITCH_NEWTON_CONTROLLER_HH
-
-#include <memory>
-
-#include <dumux/common/properties.hh>
-#include <dumux/common/parameters.hh>
-#include <dumux/discretization/methods.hh>
-#include <dumux/discretization/elementsolution.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dune/common/deprecated.hh>
-
-#warning "This file is deprecated. Use PriVarSwitchNewtonSolver instead."
-
-namespace Dumux {
-
-/*!
- * \ingroup PorousmediumCompositional
- * \brief A newton controller that handles primary variable switches
- * \todo make this independent of TypeTag by making PrimaryVariableSwitch a template argument
- *       and extracting everything model specific from there
- * \todo Implement for volume variable caching enabled
- */
-template <class TypeTag>
-class DUNE_DEPRECATED_MSG("Use PriVarSwitchNewtonSolver instead.")
-PriVarSwitchNewtonController : public NewtonController<typename GET_PROP_TYPE(TypeTag, Scalar)>
-{
-    using Scalar =  typename GET_PROP_TYPE(TypeTag, Scalar);
-    using ParentType = NewtonController<Scalar>;
-    using PrimaryVariableSwitch =  typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch);
-
-    static constexpr bool isBox = GET_PROP_TYPE(TypeTag, FVGridGeometry)::discMethod == DiscretizationMethod::box;
-
-public:
-    using ParentType::ParentType;
-
-    /*!
-     * \brief Returns true if the error of the solution is below the
-     *        tolerance.
-     */
-    bool newtonConverged() const
-    {
-        if (switchedInLastIteration_)
-            return false;
-
-        return ParentType::newtonConverged();
-    }
-
-    /*!
-     *
-     * \brief Called before the Newton method is applied to an
-     *        non-linear system of equations.
-     *
-     * \param u The initial solution
-     */
-    template<class SolutionVector>
-    void newtonBegin(const SolutionVector &u)
-    {
-        ParentType::newtonBegin(u);
-        priVarSwitch_ = std::make_unique<PrimaryVariableSwitch>(u.size());
-    }
-
-    /*!
-     * \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
-     */
-    template<class JacobianAssembler, class SolutionVector>
-    void newtonEndStep(JacobianAssembler& assembler,
-                       SolutionVector &uCurrentIter,
-                       const SolutionVector &uLastIter)
-    {
-        ParentType::newtonEndStep(assembler, uCurrentIter, uLastIter);
-
-        // update the variable switch (returns true if the pri vars at at least one dof were switched)
-        // for disabled grid variable caching
-        const auto& fvGridGeometry = assembler.fvGridGeometry();
-        const auto& problem = assembler.problem();
-        auto& gridVariables = assembler.gridVariables();
-
-        // invoke the primary variable switch
-        switchedInLastIteration_ = priVarSwitch_->update(uCurrentIter, gridVariables,
-                                                         problem, fvGridGeometry);
-
-        if(switchedInLastIteration_)
-        {
-            for (const auto& element : elements(fvGridGeometry.gridView()))
-            {
-                // if the volume variables are cached globally, we need to update those where the primary variables have been switched
-                updateSwitchedVolVars_(std::integral_constant<bool, GET_PROP_VALUE(TypeTag, EnableGridVolumeVariablesCache)>(),
-                                       element, assembler, uCurrentIter, uLastIter);
-
-                // if the flux variables are cached globally, we need to update those where the primary variables have been switched
-                // (not needed for box discretization)
-                updateSwitchedFluxVarsCache_(std::integral_constant<bool, (GET_PROP_VALUE(TypeTag, EnableGridFluxVariablesCache) && !isBox)>(),
-                                             element, assembler, uCurrentIter, uLastIter);
-            }
-        }
-    }
-
-    /*!
-     * \brief Called if the Newton method ended
-     *        (not known yet if we failed or succeeded)
-     */
-    void newtonEnd()
-    {
-        ParentType::newtonEnd();
-
-        // in any way, we have to reset the switch flag
-        switchedInLastIteration_ = false;
-        // free some memory
-        priVarSwitch_.release();
-    }
-
-private:
-
-    /*!
-     * \brief Update the volume variables whose primary variables were
-              switched. Required when volume variables are cached globally.
-     */
-    template<class Element, class JacobianAssembler, class SolutionVector>
-    void updateSwitchedVolVars_(std::true_type,
-                                const Element& element,
-                                JacobianAssembler& assembler,
-                                const SolutionVector &uCurrentIter,
-                                const SolutionVector &uLastIter)
-    {
-        const auto& fvGridGeometry = assembler.fvGridGeometry();
-        const auto& problem = assembler.problem();
-        auto& gridVariables = assembler.gridVariables();
-
-        // make sure FVElementGeometry is bound to the element
-        auto fvGeometry = localView(fvGridGeometry);
-        fvGeometry.bindElement(element);
-
-        // update the secondary variables if global caching is enabled
-        for (auto&& scv : scvs(fvGeometry))
-        {
-            const auto dofIdxGlobal = scv.dofIndex();
-            if (priVarSwitch_->wasSwitched(dofIdxGlobal))
-            {
-                const auto elemSol = elementSolution(element, uCurrentIter, fvGridGeometry);
-                auto& volVars = gridVariables.curGridVolVars().volVars(scv);
-                volVars.update(elemSol, problem, element, scv);
-            }
-        }
-    }
-
-    /*!
-     * \brief Update the fluxVars cache for dof whose primary variables were
-              switched. Required when flux variables are cached globally.
-     */
-     template<class Element, class JacobianAssembler, class SolutionVector>
-     void updateSwitchedFluxVarsCache_(std::true_type,
-                                       const Element& element,
-                                       JacobianAssembler& assembler,
-                                       const SolutionVector &uCurrentIter,
-                                       const SolutionVector &uLastIter)
-    {
-        const auto& fvGridGeometry = assembler.fvGridGeometry();
-        auto& gridVariables = assembler.gridVariables();
-
-        // update the flux variables if global caching is enabled
-        const auto dofIdxGlobal = fvGridGeometry.dofMapper().index(element);
-
-        if (priVarSwitch_->wasSwitched(dofIdxGlobal))
-        {
-            // make sure FVElementGeometry and the volume variables are bound
-            auto fvGeometry = localView(fvGridGeometry);
-            fvGeometry.bind(element);
-            auto curElemVolVars = localView(gridVariables.curGridVolVars());
-            curElemVolVars.bind(element, fvGeometry, uCurrentIter);
-            gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
-        }
-    }
-
-     //! brief Do nothing when volume variables are not cached globally.
-    template <typename... Args>
-    void updateSwitchedVolVars_(std::false_type, Args&&... args) const {}
-
-    //! brief Do nothing when flux variables are not cached globally.
-    template <typename... Args>
-    void updateSwitchedFluxVarsCache_(std::false_type, Args&&... args) const {}
-
-    //! the class handling the primary variable switch
-    std::unique_ptr<PrimaryVariableSwitch> priVarSwitch_;
-    //! if we switched primary variables in the last iteration
-    bool switchedInLastIteration_ = false;
-};
-
-} // end namespace Dumux
-
-#endif
diff --git a/dumux/porousmediumflow/nonequilibrium/CMakeLists.txt b/dumux/porousmediumflow/nonequilibrium/CMakeLists.txt
index 31fa8eb04f184261a2a39e84587cba7c9357a556..09252e0484f9b439732e7a35f88ab9c56104cc24 100644
--- a/dumux/porousmediumflow/nonequilibrium/CMakeLists.txt
+++ b/dumux/porousmediumflow/nonequilibrium/CMakeLists.txt
@@ -4,8 +4,8 @@ install(FILES
 localresidual.hh
 gridvariables.hh
 indices.hh
-newtoncontroller.hh
 volumevariables.hh
 vtkoutputfields.hh
 model.hh
+newtonsolver.hh
 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/porousmediumflow/nonequilibrium)
diff --git a/dumux/porousmediumflow/nonequilibrium/newtoncontroller.hh b/dumux/porousmediumflow/nonequilibrium/newtonsolver.hh
similarity index 58%
rename from dumux/porousmediumflow/nonequilibrium/newtoncontroller.hh
rename to dumux/porousmediumflow/nonequilibrium/newtonsolver.hh
index b1bfec283b6bdd84b3ff7c11e2059bb879cab7df..838d2f5e1c480b20ad31f731eaf1bba2d794eada 100644
--- a/dumux/porousmediumflow/nonequilibrium/newtoncontroller.hh
+++ b/dumux/porousmediumflow/nonequilibrium/newtonsolver.hh
@@ -19,43 +19,35 @@
 /*!
  * \file
  * \ingroup PorousmediumNonEquilibriumModel
- * \brief A MpNc specific controller for the newton solver.
- *  This controller calls the velocity averaging in the model after each iteration.
+ * \brief A MpNc specific newton solver.
+ *  This solver calls the velocity averaging in the model after each iteration.
  */
-#ifndef DUMUX_NONEQUILIBRIUM_NEWTON_CONTROLLER_HH
-#define DUMUX_NONEQUILIBRIUM_NEWTON_CONTROLLER_HH
+#ifndef DUMUX_NONEQUILIBRIUM_NEWTON_SOLVER_HH
+#define DUMUX_NONEQUILIBRIUM_NEWTON_SOLVER_HH
 
-#include <algorithm>
-
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 namespace Dumux {
 /*!
  * \ingroup PorousmediumNonEquilibriumModel
- * \brief A nonequilibrium specific controller for the newton solver.
- * This controller calls the velocity averaging in the problem after each iteration.
+ * \brief A nonequilibrium specific newton solver.
+ * This solver calls the velocity averaging in the problem after each iteration.
  */
-template <class Scalar,
-          class Comm = Dune::CollectiveCommunication<Dune::MPIHelper::MPICommunicator> >
-class NonEquilibriumNewtonController : public NewtonController<Scalar, Comm>
+template <class Assembler, class LinearSolver>
+class NonEquilibriumNewtonSolver : public NewtonSolver<Assembler, LinearSolver>
 {
-    using ParentType = NewtonController<Scalar, Comm>;
+    using ParentType = NewtonSolver<Assembler, LinearSolver>;
+    using SolutionVector = typename Assembler::ResidualType;
 
 public:
     using ParentType::ParentType;
 
-    template<class JacobianAssembler, class SolutionVector>
-    void newtonUpdate(JacobianAssembler& assembler,
-                      SolutionVector &uCurrentIter,
-                      const SolutionVector &uLastIter,
-                      const SolutionVector &deltaU)
+    void newtonEndStep(SolutionVector &uCurrentIter,
+                       const SolutionVector &uLastIter) final
     {
-        ParentType::newtonUpdate(assembler,
-                                 uCurrentIter,
-                                 uLastIter,
-                                 deltaU);
+        ParentType::newtonEndStep(uCurrentIter, uLastIter);
 
-        auto& gridVariables = assembler.gridVariables();
+        auto& gridVariables = this->assembler().gridVariables();
         // Averages the face velocities of a vertex. Implemented in the model.
         // The velocities are stored in the model.
         gridVariables.calcVelocityAverage(uCurrentIter);
@@ -63,4 +55,4 @@ public:
 };
 
 } // end namespace Dumux
-#endif // DUMUX_VELO_PROB_AVERAGE_NEWTON_CONTROLLER_HH
+#endif // DUMUX_NONEQUILIBRIUM_NEWTON_SOLVER_HH
diff --git a/dumux/porousmediumflow/richards/CMakeLists.txt b/dumux/porousmediumflow/richards/CMakeLists.txt
index 2929d226a4f0d49ebe59f30739c2c4973dfaf5cf..199fc1455f2ec91649605c0ee3ca855fedddc01e 100644
--- a/dumux/porousmediumflow/richards/CMakeLists.txt
+++ b/dumux/porousmediumflow/richards/CMakeLists.txt
@@ -4,7 +4,8 @@ install(FILES
 indices.hh
 localresidual.hh
 model.hh
-newtoncontroller.hh
+newtonsolver.hh
+privarswitchnewtonsolver.hh
 primaryvariableswitch.hh
 volumevariables.hh
 vtkoutputfields.hh
diff --git a/dumux/porousmediumflow/richards/newtoncontroller.hh b/dumux/porousmediumflow/richards/newtoncontroller.hh
deleted file mode 100644
index e6a7cccd48230c9d34d1cdc9df2434dad029a446..0000000000000000000000000000000000000000
--- a/dumux/porousmediumflow/richards/newtoncontroller.hh
+++ /dev/null
@@ -1,122 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \ingroup RichardsModel
- * \brief A Richards model specific controller for the newton solver.
- */
-#ifndef DUMUX_RICHARDS_NEWTON_CONTROLLER_HH
-#define DUMUX_RICHARDS_NEWTON_CONTROLLER_HH
-
-#include <dumux/common/properties.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dumux/discretization/elementsolution.hh>
-#include <dune/common/deprecated.hh>
-
-#warning "This file is deprecated. Use RichardsNewtonSolver instead."
-
-namespace Dumux {
-/*!
- * \ingroup RichardsModel
- * \brief A Richards model specific controller for the newton solver.
- *
- * This controller 'knows' what a 'physically meaningful' solution is
- * and can thus do update smarter than the plain Newton controller.
- *
- * \todo make this typetag independent by extracting anything model specific from assembler
- *       or from possible ModelTraits.
- */
-template <class TypeTag>
-class DUNE_DEPRECATED_MSG("Use RichardsNewtonSolver instead.")
-RichardsNewtonController : public NewtonController<typename GET_PROP_TYPE(TypeTag, Scalar)>
-{
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using ParentType = NewtonController<Scalar>;
-
-    using MaterialLaw = typename GET_PROP_TYPE(TypeTag, MaterialLaw);
-    using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
-    enum { pressureIdx = Indices::pressureIdx };
-
-public:
-    using ParentType::ParentType;
-
-    /*!
-     * \brief Update the current solution of the newton method
-     *
-     * This is basically the step
-     * \f[ u^{k+1} = u^k - \Delta u^k \f]
-     *
-     * \param assembler The Jacobian assembler
-     * \param uCurrentIter The solution after the current Newton iteration \f$ u^{k+1} \f$
-     * \param uLastIter The solution after the last Newton iteration \f$ u^k \f$
-     * \param deltaU The vector of differences between the last
-     *               iterative solution and the next one \f$ \Delta u^k \f$
-     */
-    template<class JacobianAssembler, class SolutionVector>
-    void newtonUpdate(JacobianAssembler& assembler,
-                      SolutionVector &uCurrentIter,
-                      const SolutionVector &uLastIter,
-                      const SolutionVector &deltaU)
-    {
-        ParentType::newtonUpdate(assembler, uCurrentIter, uLastIter, deltaU);
-        if (!this->useLineSearch_ && getParamFromGroup<bool>(this->paramGroup(), "Newton.EnableChop"))
-        {
-            // do not clamp anything after 5 iterations
-            if (this->numSteps_ > 4)
-                return;
-
-            // clamp saturation change to at most 20% per iteration
-            const auto& fvGridGeometry = assembler.fvGridGeometry();
-            for (const auto& element : elements(fvGridGeometry.gridView()))
-            {
-                auto fvGeometry = localView(fvGridGeometry);
-                fvGeometry.bindElement(element);
-
-                for (auto&& scv : scvs(fvGeometry))
-                {
-                    auto dofIdxGlobal = scv.dofIndex();
-
-                    // calculate the old wetting phase saturation
-                    const auto& spatialParams = assembler.problem().spatialParams();
-                    const auto elemSol = elementSolution(element, uCurrentIter, fvGridGeometry);
-                    const auto& materialLawParams = spatialParams.materialLawParams(element, scv, elemSol);
-                    const Scalar pcMin = MaterialLaw::pc(materialLawParams, 1.0);
-                    const Scalar pw = uLastIter[dofIdxGlobal][pressureIdx];
-                    using std::max;
-                    const Scalar pn = max(assembler.problem().nonWettingReferencePressure(), pw + pcMin);
-                    const Scalar pcOld = pn - pw;
-                    const Scalar SwOld = max(0.0, MaterialLaw::sw(materialLawParams, pcOld));
-
-                    // convert into minimum and maximum wetting phase
-                    // pressures
-                    const Scalar pwMin = pn - MaterialLaw::pc(materialLawParams, SwOld - 0.2);
-                    const Scalar pwMax = pn - MaterialLaw::pc(materialLawParams, SwOld + 0.2);
-
-                    // clamp the result
-                    using std::min; using std::max;
-                    uCurrentIter[dofIdxGlobal][pressureIdx] = max(pwMin, min(uCurrentIter[dofIdxGlobal][pressureIdx], pwMax));
-                }
-            }
-        }
-    }
-};
-
-} // end namespace Dumux
-
-#endif
diff --git a/dumux/porousmediumflow/richards/newtonsolver.hh b/dumux/porousmediumflow/richards/newtonsolver.hh
index 1cd9e43786968cf36d7ea6ad787d2a19444934f6..0c89333066704885e2da39a4bb01a5b7e436f4b4 100644
--- a/dumux/porousmediumflow/richards/newtonsolver.hh
+++ b/dumux/porousmediumflow/richards/newtonsolver.hh
@@ -33,7 +33,7 @@ namespace Dumux {
  * \ingroup RichardsModel
  * \brief A Richards model specific newton solver.
  *
- * This controller 'knows' what a 'physically meaningful' solution is
+ * This solver 'knows' what a 'physically meaningful' solution is
  * and can thus do update smarter than the plain Newton solver.
  *
  * \todo make this typetag independent by extracting anything model specific from assembler
diff --git a/dumux/porousmediumflow/richardsnc/model.hh b/dumux/porousmediumflow/richardsnc/model.hh
index 5dad8ad9cf306c896f0dd2328063dd788f8f807e..91720a3e1cf335b8c422f38e6ed20df4ac1220bb 100644
--- a/dumux/porousmediumflow/richardsnc/model.hh
+++ b/dumux/porousmediumflow/richardsnc/model.hh
@@ -70,7 +70,6 @@
 #include <dumux/common/properties.hh>
 
 #include <dumux/porousmediumflow/compositional/localresidual.hh>
-#include <dumux/porousmediumflow/richards/newtoncontroller.hh>
 
 #include <dumux/material/spatialparams/fv1p.hh>
 #include <dumux/material/fluidmatrixinteractions/diffusivitymillingtonquirk.hh>
@@ -148,6 +147,10 @@ SET_INT_PROP(RichardsNC, ReplaceCompEqIdx, 0);
 //! define the VolumeVariables
 SET_TYPE_PROP(RichardsNC, VolumeVariables, RichardsNCVolumeVariables<TypeTag>);
 
+//! The default richardsnc model computes no diffusion in the air phase
+//! Turning this on leads to the extended Richards equation (see e.g. Vanderborght et al. 2017)
+SET_BOOL_PROP(RichardsNC, EnableWaterDiffusionInAir, false);
+
 /*!
  *\brief The fluid system used by the model.
  *
diff --git a/dumux/porousmediumflow/richardsnc/volumevariables.hh b/dumux/porousmediumflow/richardsnc/volumevariables.hh
index 668e212a7a8a126f9a358098bfc7ad00024317c5..cb12812843d6a462b98a67f56ee56ad73123b8fa 100644
--- a/dumux/porousmediumflow/richardsnc/volumevariables.hh
+++ b/dumux/porousmediumflow/richardsnc/volumevariables.hh
@@ -319,6 +319,8 @@ class RichardsNCVolumeVariables : public RichardsBaseVolumeVariables<TypeTag>
     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
     using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
 
+    static_assert(!GET_PROP_VALUE(TypeTag, EnableWaterDiffusionInAir), "Water diffusion in air is not implement for RichardsNC");
+
     enum
     {
         wPhaseIdx = Indices::wPhaseIdx,
diff --git a/test/porousmediumflow/1p/implicit/compressible/test_1p.cc b/test/porousmediumflow/1p/implicit/compressible/test_1p.cc
index 82c70f15ca2d9fb8f5a8f182ee010447b7889cd8..0681e6b11993174f06fbe0de52d61b06ecc6a40c 100644
--- a/test/porousmediumflow/1p/implicit/compressible/test_1p.cc
+++ b/test/porousmediumflow/1p/implicit/compressible/test_1p.cc
@@ -41,9 +41,8 @@
 #include <dumux/common/dumuxmessage.hh>
 #include <dumux/common/defaultusagemessage.hh>
 
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 
@@ -108,7 +107,6 @@ int main(int argc, char** argv) try
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-    auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
 
     // intialize the vtk output module
@@ -130,9 +128,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod<NewtonController, Assembler, LinearSolver> nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // set some check points for the time loop
     timeLoop->setPeriodicCheckPoint(tEnd/10.0);
@@ -143,24 +140,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // linearize & solve
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -176,8 +157,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1p/implicit/compressible/test_1p_stationary.cc b/test/porousmediumflow/1p/implicit/compressible/test_1p_stationary.cc
index 9426c67764dc989e797914962751d606603d0e8c..61a955a939b6bbd8df9013b8e1ada7eb6837ac69 100644
--- a/test/porousmediumflow/1p/implicit/compressible/test_1p_stationary.cc
+++ b/test/porousmediumflow/1p/implicit/compressible/test_1p_stationary.cc
@@ -39,9 +39,8 @@
 #include <dumux/common/dumuxmessage.hh>
 #include <dumux/common/defaultusagemessage.hh>
 
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 
@@ -115,10 +114,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    auto newtonController = std::make_shared<NewtonController>();
-    NewtonMethod<NewtonController, Assembler, LinearSolver> nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // linearize & solve
     Dune::Timer timer;
diff --git a/test/porousmediumflow/1p/implicit/incompressible/test_1pfv.cc b/test/porousmediumflow/1p/implicit/incompressible/test_1pfv.cc
index 3691b9f81d4e21f5c29183607c7bdfa4ec1ce2c4..5380c2f0fa8c2ef2e62f062ee217b09048e3e304 100644
--- a/test/porousmediumflow/1p/implicit/incompressible/test_1pfv.cc
+++ b/test/porousmediumflow/1p/implicit/incompressible/test_1pfv.cc
@@ -34,7 +34,6 @@
 #include <dumux/linear/seqsolverbackend.hh>
 
 #include <dumux/common/properties.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
 #include <dumux/common/parameters.hh>
 #include <dumux/common/valgrind.hh>
 #include <dumux/common/dumuxmessage.hh>
diff --git a/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources.cc b/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources.cc
index d15462abb62029249ff4b508f074c71eebf533d6..92abc5b34e108093d2e5e708dc9aefe59d1791fb 100644
--- a/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources.cc
+++ b/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -104,7 +103,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -132,10 +130,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -143,24 +139,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // linearize & solve
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -175,8 +155,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources_timedependent.cc b/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources_timedependent.cc
index 077d34ad205b6a78c23886724e858218b03ae31f..f0fbf2fe90b19ae767f1c45f5d39728762de4da7 100644
--- a/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources_timedependent.cc
+++ b/test/porousmediumflow/1p/implicit/pointsources/test_1pfv_pointsources_timedependent.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -104,7 +103,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -132,10 +130,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -146,24 +142,8 @@ int main(int argc, char** argv) try
         // set the time in the problem for implicit Euler scheme
         problem->setTime(timeLoop->time() + timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // linearize & solve
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -178,8 +158,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1p/implicit/test_1pfv.cc b/test/porousmediumflow/1p/implicit/test_1pfv.cc
index 527af70e84179af3d0f8873c4a70cf19d6b70b60..20b487087d3487e380ae631a3caf3c199d9119b4 100644
--- a/test/porousmediumflow/1p/implicit/test_1pfv.cc
+++ b/test/porousmediumflow/1p/implicit/test_1pfv.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -134,7 +133,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -167,10 +165,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -178,24 +174,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // linearize & solve
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -210,8 +190,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1p/implicit/test_1pfv_fracture2d3d.cc b/test/porousmediumflow/1p/implicit/test_1pfv_fracture2d3d.cc
index 957420d57279b02cbff94ddfd4439d3e891798e3..661a2eacd5451bde016255477413c9f10318e14b 100644
--- a/test/porousmediumflow/1p/implicit/test_1pfv_fracture2d3d.cc
+++ b/test/porousmediumflow/1p/implicit/test_1pfv_fracture2d3d.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -128,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -156,10 +154,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -167,24 +163,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // linearize & solve
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -199,8 +179,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1p/implicit/test_1pfv_network1d3d.cc b/test/porousmediumflow/1p/implicit/test_1pfv_network1d3d.cc
index 6b61ab1ce58842cf9f2f7a007ca33be90d57c5f2..8002c628157d72f13e7f9e306b962a84ddbc5497 100644
--- a/test/porousmediumflow/1p/implicit/test_1pfv_network1d3d.cc
+++ b/test/porousmediumflow/1p/implicit/test_1pfv_network1d3d.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -128,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -156,10 +154,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -167,24 +163,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // linearize & solve
+        nonLinearSolver.solve(x, *timeLoop);
 
         // output l2 norm for convergence analysis
         problem->outputL2Norm(x);
@@ -202,8 +182,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1p/implicit/test_1pnifv.cc b/test/porousmediumflow/1p/implicit/test_1pnifv.cc
index f9f83626ebb2adb65ba7436cbe30f7fee8a49c06..cda24e587c1dda4f7a2b378ef20eb4bb1b86446b 100644
--- a/test/porousmediumflow/1p/implicit/test_1pnifv.cc
+++ b/test/porousmediumflow/1p/implicit/test_1pnifv.cc
@@ -42,8 +42,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -130,7 +129,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -162,10 +160,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -173,24 +169,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // linearize & solve
+        nonLinearSolver.solve(x, *timeLoop);
 
         // compute the new analytical temperature field for the output
         problem->updateExactTemperature(x, timeLoop->time()+timeLoop->timeStepSize());
@@ -205,8 +185,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         if (timeLoop->timeStepIndex()==0 || timeLoop->timeStepIndex() % vtkOutputInterval == 0 || timeLoop->willBeFinished())
             vtkWriter.write(timeLoop->time());
diff --git a/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc b/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc
index 3bd306cfd80b5b3b7570a1635b4de5f8068fd409..d9bb15ae6442ab0714a135338485aa40319776de 100644
--- a/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc
+++ b/test/porousmediumflow/1pnc/implicit/test_1p2c_fv.cc
@@ -152,7 +152,7 @@
          // report statistics of this time step
          timeLoop->reportTimeStep();
 
-         // set new dt as suggested by newton controller
+         // set new dt as suggested by the newton solver
          timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
      } while (!timeLoop->finished());
diff --git a/test/porousmediumflow/1pnc/implicit/test_1p2cni_conduction_fv.cc b/test/porousmediumflow/1pnc/implicit/test_1p2cni_conduction_fv.cc
index 39b9bd5270c7d704441adc6224b5696974886006..d259b5725782e5ec79c47929b0a35b41e183e947 100644
--- a/test/porousmediumflow/1pnc/implicit/test_1p2cni_conduction_fv.cc
+++ b/test/porousmediumflow/1pnc/implicit/test_1p2cni_conduction_fv.cc
@@ -41,9 +41,8 @@
  #include <dumux/common/dumuxmessage.hh>
  #include <dumux/common/defaultusagemessage.hh>
 
- #include <dumux/nonlinear/newtoncontroller.hh>
+ #include <dumux/nonlinear/newtonsolver.hh>
  #include <dumux/linear/seqsolverbackend.hh>
- #include <dumux/nonlinear/newtonmethod.hh>
 
  #include <dumux/assembly/fvassembler.hh>
 
@@ -108,7 +107,6 @@
      using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
      auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
      auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-     auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
      auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
 
      // intialize the vtk output module
@@ -134,9 +132,8 @@
      auto linearSolver = std::make_shared<LinearSolver>();
 
      // the non-linear solver
-     using NewtonController = Dumux::NewtonController<Scalar>;
-     auto newtonController = std::make_shared<NewtonController>(timeLoop);
-     NewtonMethod<NewtonController, Assembler, LinearSolver> nonLinearSolver(newtonController, assembler, linearSolver);
+     using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+     NewtonSolver nonLinearSolver(assembler, linearSolver);
 
      // time loop
      timeLoop->start(); do
@@ -144,24 +141,8 @@
          // set previous solution for storage evaluations
          assembler->setPreviousSolution(xOld);
 
-         // try solving the non-linear system
-         for (int i = 0; i < maxDivisions; ++i)
-         {
-             // linearize & solve
-             auto converged = nonLinearSolver.solve(x);
-
-             if (converged)
-                 break;
-
-             if (!converged && i == maxDivisions-1)
-                 DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-         }
+         // linearize & solve
+         nonLinearSolver.solve(x, *timeLoop);
 
          // update the exact time temperature
          problem->updateExactTemperature(x, timeLoop->time()+timeLoop->timeStepSize());
@@ -180,8 +161,8 @@
          // report statistics of this time step
          timeLoop->reportTimeStep();
 
-         // set new dt as suggested by newton controller
-         timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+         // set new dt as suggested by the newton solver
+         timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
      } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1pnc/implicit/test_1p2cni_convection_fv.cc b/test/porousmediumflow/1pnc/implicit/test_1p2cni_convection_fv.cc
index 2d99ef79f9e29cd0abc11d29143628809fa3353d..8bfdfd015db407ae1e8ac9c08cbff03e79ceb90f 100644
--- a/test/porousmediumflow/1pnc/implicit/test_1p2cni_convection_fv.cc
+++ b/test/porousmediumflow/1pnc/implicit/test_1p2cni_convection_fv.cc
@@ -41,9 +41,8 @@
  #include <dumux/common/dumuxmessage.hh>
  #include <dumux/common/defaultusagemessage.hh>
 
- #include <dumux/nonlinear/newtoncontroller.hh>
+ #include <dumux/nonlinear/newtonsolver.hh>
  #include <dumux/linear/seqsolverbackend.hh>
- #include <dumux/nonlinear/newtonmethod.hh>
 
  #include <dumux/assembly/fvassembler.hh>
 
@@ -108,7 +107,6 @@
      using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
      auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
      auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-     auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
      auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
 
      // intialize the vtk output module
@@ -134,9 +132,8 @@
      auto linearSolver = std::make_shared<LinearSolver>();
 
      // the non-linear solver
-     using NewtonController = Dumux::NewtonController<Scalar>;
-     auto newtonController = std::make_shared<NewtonController>(timeLoop);
-     NewtonMethod<NewtonController, Assembler, LinearSolver> nonLinearSolver(newtonController, assembler, linearSolver);
+     using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+     NewtonSolver nonLinearSolver(assembler, linearSolver);
 
      // time loop
      timeLoop->start(); do
@@ -144,24 +141,8 @@
          // set previous solution for storage evaluations
          assembler->setPreviousSolution(xOld);
 
-         // try solving the non-linear system
-         for (int i = 0; i < maxDivisions; ++i)
-         {
-             // linearize & solve
-             auto converged = nonLinearSolver.solve(x);
-
-             if (converged)
-                 break;
-
-             if (!converged && i == maxDivisions-1)
-                 DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-         }
+         // linearize & solve
+         nonLinearSolver.solve(x, *timeLoop);
 
          // update the exact time temperature
          problem->updateExactTemperature(x, timeLoop->time()+timeLoop->timeStepSize());
@@ -180,8 +161,8 @@
          // report statistics of this time step
          timeLoop->reportTimeStep();
 
-         // set new dt as suggested by newton controller
-         timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+         // set new dt as suggested by the newton solver
+         timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
      } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/1pncmin/implicit/test_1pncminni_fv.cc b/test/porousmediumflow/1pncmin/implicit/test_1pncminni_fv.cc
index ad96a94b3d81d0b1e05a3b4acbcf68973f8052f6..1c2903a3fe5f399126a9e4b70a918ee2c523165e 100644
--- a/test/porousmediumflow/1pncmin/implicit/test_1pncminni_fv.cc
+++ b/test/porousmediumflow/1pncmin/implicit/test_1pncminni_fv.cc
@@ -30,8 +30,7 @@
 #include <dumux/common/parameters.hh>
 #include <dumux/common/dumuxmessage.hh>
 
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 #include <dumux/linear/seqsolverbackend.hh>
 
 #include <dumux/assembly/fvassembler.hh>
@@ -134,7 +133,6 @@ int main(int argc, char** argv) try
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-    auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
 
     // intialize the vtk output module
@@ -164,9 +162,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod<NewtonController, Assembler, LinearSolver> nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -177,43 +174,27 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                        "Newton solver didn't converge after "
-                        << maxDivisions
-                        << " time-step divisions. dt="
-                        << timeLoop->timeStepSize()
-                        << ".\nThe solutions of the current and the previous time steps "
-                        << "have been saved to restart files.");
-        }
-
-    // make the new solution the old solution
-    xOld = x;
-    gridVariables->advanceTimeStep();
-
-    // advance to the time loop to the next step
-    timeLoop->advanceTimeStep();
-
-    // update the output fields before write
-    problem->updateVtkOutput(x);
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
+
+        // make the new solution the old solution
+        xOld = x;
+        gridVariables->advanceTimeStep();
+
+        // advance to the time loop to the next step
+        timeLoop->advanceTimeStep();
+
+        // update the output fields before write
+        problem->updateVtkOutput(x);
 
-    // write vtk output
-    vtkWriter.write(timeLoop->time());
+        // write vtk output
+        vtkWriter.write(timeLoop->time());
 
-    // report statistics of this time step
-    timeLoop->reportTimeStep();
+        // report statistics of this time step
+        timeLoop->reportTimeStep();
 
-    // set new dt as suggested by newton controller
-    timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2p/implicit/adaptive/test_2p_adaptive_fv.cc b/test/porousmediumflow/2p/implicit/adaptive/test_2p_adaptive_fv.cc
index dd1c181f569597e90d454985e027eae007e0ce5a..7ef24730c3b591cc8a312b37cec2e18d4048c2b2 100644
--- a/test/porousmediumflow/2p/implicit/adaptive/test_2p_adaptive_fv.cc
+++ b/test/porousmediumflow/2p/implicit/adaptive/test_2p_adaptive_fv.cc
@@ -38,8 +38,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -180,7 +179,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -208,10 +206,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -241,23 +237,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -272,8 +253,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2p/implicit/fracture/test_2p_fracture_fv.cc b/test/porousmediumflow/2p/implicit/fracture/test_2p_fracture_fv.cc
index d56429596de482be6b3d23b7f1452a73ab913db3..6090dc310d7054ba982bd8740ca3e91eb2aa1186 100644
--- a/test/porousmediumflow/2p/implicit/fracture/test_2p_fracture_fv.cc
+++ b/test/porousmediumflow/2p/implicit/fracture/test_2p_fracture_fv.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -117,7 +116,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -145,10 +143,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -156,24 +152,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -188,8 +168,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2p/implicit/nonisothermal/test_2pni_fv.cc b/test/porousmediumflow/2p/implicit/nonisothermal/test_2pni_fv.cc
index 1354069095ea056847819ea48ed8c4844015ddc8..22b8215f5ec39379dcaa08e241f8b835cd691a55 100644
--- a/test/porousmediumflow/2p/implicit/nonisothermal/test_2pni_fv.cc
+++ b/test/porousmediumflow/2p/implicit/nonisothermal/test_2pni_fv.cc
@@ -38,8 +38,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 
@@ -128,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -156,10 +154,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -167,24 +163,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -199,8 +179,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2p1c/implicit/test_2p1c_fv.cc b/test/porousmediumflow/2p1c/implicit/test_2p1c_fv.cc
index d87098fa99b663dc78a2a9b57440d73ef4746785..f6ec0b61d786ab39e0aef9b6e4e7a04899e6badd 100644
--- a/test/porousmediumflow/2p1c/implicit/test_2p1c_fv.cc
+++ b/test/porousmediumflow/2p1c/implicit/test_2p1c_fv.cc
@@ -41,9 +41,8 @@
  #include <dumux/common/dumuxmessage.hh>
  #include <dumux/common/defaultusagemessage.hh>
 
- #include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
  #include <dumux/linear/seqsolverbackend.hh>
- #include <dumux/nonlinear/newtonmethod.hh>
+ #include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
  #include <dumux/assembly/fvassembler.hh>
 
@@ -108,7 +107,6 @@
      using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
      auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
      auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-     auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
      auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
 
      // intialize the vtk output module
@@ -130,9 +128,9 @@
      auto linearSolver = std::make_shared<LinearSolver>();
 
      // the non-linear solver
-     using NewtonController = Dumux::PriVarSwitchNewtonController<TypeTag>;
-     auto newtonController = std::make_shared<NewtonController>(timeLoop);
-     NewtonMethod<NewtonController, Assembler, LinearSolver> nonLinearSolver(newtonController, assembler, linearSolver);
+     using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch);
+     using NewtonSolver = Dumux::PriVarSwitchNewtonSolver<Assembler, LinearSolver, PrimaryVariableSwitch>;
+     NewtonSolver nonLinearSolver(assembler, linearSolver);
 
      // time loop
      timeLoop->start(); do
@@ -140,24 +138,8 @@
          // set previous solution for storage evaluations
          assembler->setPreviousSolution(xOld);
 
-         // try solving the non-linear system
-         for (int i = 0; i < maxDivisions; ++i)
-         {
-             // linearize & solve
-             auto converged = nonLinearSolver.solve(x);
-
-             if (converged)
-                 break;
-
-             if (!converged && i == maxDivisions-1)
-                 DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-         }
+         // solve the non-linear system with time step control
+         nonLinearSolver.solve(x, *timeLoop);
 
          // make the new solution the old solution
          xOld = x;
@@ -172,8 +154,8 @@
          // report statistics of this time step
          timeLoop->reportTimeStep();
 
-         // set new dt as suggested by newton controller
-         timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+         // set new dt as suggested by the newton solver
+         timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
      } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2p2c/implicit/mpnccomparison/test_2p2c_comparison_fv.cc b/test/porousmediumflow/2p2c/implicit/mpnccomparison/test_2p2c_comparison_fv.cc
index e8835a9e6d45fb52696e8a450d7e4b903460f2b8..6d481bae8a91015375be13b0530b793d6c3441c8 100644
--- a/test/porousmediumflow/2p2c/implicit/mpnccomparison/test_2p2c_comparison_fv.cc
+++ b/test/porousmediumflow/2p2c/implicit/mpnccomparison/test_2p2c_comparison_fv.cc
@@ -38,8 +38,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -129,7 +128,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -157,10 +155,9 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = PriVarSwitchNewtonSolver<Assembler, LinearSolver,
+                                                 typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch)>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -168,24 +165,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -200,8 +181,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc b/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc
index c7fc2a9a98d281fe268b3a2de6e079494535c446..1b86e04ba7cc00ff355e3f9513ed3c0ede80ef9b 100644
--- a/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc
+++ b/test/porousmediumflow/2p2c/implicit/test_2p2c_fv.cc
@@ -153,7 +153,7 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
+        // set new dt as suggested by the newton solver
         timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // write vtk output
diff --git a/test/porousmediumflow/2pnc/implicit/test_2pnc_fv.cc b/test/porousmediumflow/2pnc/implicit/test_2pnc_fv.cc
index 9b75b3116f2c9a82f31f0731bc9d44ffca2f5579..21750d4981c2680cb3fca3793e36fdd17fa8a795 100644
--- a/test/porousmediumflow/2pnc/implicit/test_2pnc_fv.cc
+++ b/test/porousmediumflow/2pnc/implicit/test_2pnc_fv.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -128,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -157,10 +155,9 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = PriVarSwitchNewtonSolver<Assembler, LinearSolver,
+                                                  typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch)>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -168,24 +165,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -203,8 +184,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2pnc/implicit/test_cc2pnc_diffusion.cc b/test/porousmediumflow/2pnc/implicit/test_cc2pnc_diffusion.cc
index 88ee0bfbbe0af2dbe61d95e6dfecece4ffa6c211..31870b972c8c13143b81ff9cbfb81d2d8e9296ea 100644
--- a/test/porousmediumflow/2pnc/implicit/test_cc2pnc_diffusion.cc
+++ b/test/porousmediumflow/2pnc/implicit/test_cc2pnc_diffusion.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -126,7 +125,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -154,10 +152,9 @@ int main(int argc, char** argv) try
     auto linearSolver =  std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = PriVarSwitchNewtonSolver<Assembler, LinearSolver,
+                                                  typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch)>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -165,24 +162,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -197,8 +178,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/2pncmin/implicit/test_2pncmin_fv.cc b/test/porousmediumflow/2pncmin/implicit/test_2pncmin_fv.cc
index f40e7f9e16a8677d037d2b5c75318d52752da34e..1ccc7b74a2a18bc6bca8b7b1e58e3fa2f759b190 100644
--- a/test/porousmediumflow/2pncmin/implicit/test_2pncmin_fv.cc
+++ b/test/porousmediumflow/2pncmin/implicit/test_2pncmin_fv.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -126,7 +125,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -158,10 +156,9 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = PriVarSwitchNewtonSolver<Assembler, LinearSolver,
+                                                  typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch)>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -173,24 +170,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -208,8 +189,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/3p/implicit/test_3p_fv.cc b/test/porousmediumflow/3p/implicit/test_3p_fv.cc
index 8f7a7eda6ae38371bd2a2cd18eeb762b9cad41fa..6a17a142b3806e16db6dd03e1ccc42b79202c405 100644
--- a/test/porousmediumflow/3p/implicit/test_3p_fv.cc
+++ b/test/porousmediumflow/3p/implicit/test_3p_fv.cc
@@ -39,8 +39,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -133,7 +132,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -161,10 +159,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -176,24 +172,8 @@ int main(int argc, char** argv) try
         // the boundary conditions for the implicit Euler scheme
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -205,8 +185,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // write vtk output
         vtkWriter.write(timeLoop->time());
diff --git a/test/porousmediumflow/3p/implicit/test_3pni_fv_conduction.cc b/test/porousmediumflow/3p/implicit/test_3pni_fv_conduction.cc
index d57c83212ceb2fa9c65d9ba520e22f23a2413e87..7ea429bfedf02c61fa632761c3d5943c2e562df7 100644
--- a/test/porousmediumflow/3p/implicit/test_3pni_fv_conduction.cc
+++ b/test/porousmediumflow/3p/implicit/test_3pni_fv_conduction.cc
@@ -39,8 +39,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -133,7 +132,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -164,10 +162,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -175,24 +171,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // update the exact time temperature
         problem->updateExactTemperature(x, timeLoop->time()+timeLoop->timeStepSize());
@@ -207,8 +187,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
        if (timeLoop->timeStepIndex()==0 || timeLoop->timeStepIndex() % vtkOutputInterval == 0 || timeLoop->willBeFinished())
             vtkWriter.write(timeLoop->time());
diff --git a/test/porousmediumflow/3p/implicit/test_3pni_fv_convection.cc b/test/porousmediumflow/3p/implicit/test_3pni_fv_convection.cc
index b608af5e75da70b78f3eca4ae133bd111807c9f7..dcaf2bcac876a466e0ed91a20cad72ae5a7accde 100644
--- a/test/porousmediumflow/3p/implicit/test_3pni_fv_convection.cc
+++ b/test/porousmediumflow/3p/implicit/test_3pni_fv_convection.cc
@@ -39,8 +39,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -133,7 +132,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -164,10 +162,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -175,24 +171,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // compute the new analytical temperature field for the output
         problem->updateExactTemperature(x, timeLoop->time()+timeLoop->timeStepSize());
@@ -207,8 +187,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // write vtk output
         if(timeLoop->timeStepIndex()==0 || timeLoop->timeStepIndex() % vtkOutputInterval == 0 || timeLoop->willBeFinished())
diff --git a/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.cc b/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.cc
index a9d8a49efb04e8ccebf8b4cd397fb1874f12acb0..d656cad00b0712e86d79e25f0fc4f1232f8669f8 100644
--- a/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.cc
+++ b/test/porousmediumflow/3p3c/implicit/test_3p3c_fv.cc
@@ -37,8 +37,7 @@
 #include <dumux/common/timeloop.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -133,7 +132,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -162,10 +160,9 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = PriVarSwitchNewtonSolver<Assembler, LinearSolver,
+                                                  typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch)>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start();
@@ -174,24 +171,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -208,8 +189,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
     }
 
     timeLoop->finalize(leafGridView.comm());
diff --git a/test/porousmediumflow/3pwateroil/implicit/test_box3pwateroil.cc b/test/porousmediumflow/3pwateroil/implicit/test_box3pwateroil.cc
index fd42d373843a2e199a2c14f7c31e80d8f462b238..bbf72d26335a1ffa26e950b4122b69ca3bbd6e13 100644
--- a/test/porousmediumflow/3pwateroil/implicit/test_box3pwateroil.cc
+++ b/test/porousmediumflow/3pwateroil/implicit/test_box3pwateroil.cc
@@ -180,7 +180,7 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
+        // set new dt as suggested by the newton solver
         timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // write vtk output
diff --git a/test/porousmediumflow/co2/implicit/test_co2_fv.cc b/test/porousmediumflow/co2/implicit/test_co2_fv.cc
index 88162d0d8066da78058cf86bf451db7bb1cd766a..c9e2297ebec09eee239847eaaf193c411d45a88c 100644
--- a/test/porousmediumflow/co2/implicit/test_co2_fv.cc
+++ b/test/porousmediumflow/co2/implicit/test_co2_fv.cc
@@ -38,8 +38,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -103,7 +102,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -132,10 +130,9 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = PriVarSwitchNewtonSolver<Assembler, LinearSolver,
+                                                  typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch)>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -143,24 +140,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -172,8 +153,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // write vtk output
         vtkWriter.write(timeLoop->time());
diff --git a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/test_mpnc_comparison_fv.cc b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/test_mpnc_comparison_fv.cc
index 6b64b18c152a171e708da08da24478feca43baf9..4b01fdd4f908a32686c378aec52b5d744945c4a8 100644
--- a/test/porousmediumflow/mpnc/implicit/2p2ccomparison/test_mpnc_comparison_fv.cc
+++ b/test/porousmediumflow/mpnc/implicit/2p2ccomparison/test_mpnc_comparison_fv.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -135,7 +134,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -163,10 +161,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -174,24 +170,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -206,8 +186,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/mpnc/implicit/test_boxmpnckinetic.cc b/test/porousmediumflow/mpnc/implicit/test_boxmpnckinetic.cc
index 8fd4d91754c317486c639cfb00728a72a3513b7a..2f6e9f2ef03e7a99a21e99b61d24fab545df1e9f 100644
--- a/test/porousmediumflow/mpnc/implicit/test_boxmpnckinetic.cc
+++ b/test/porousmediumflow/mpnc/implicit/test_boxmpnckinetic.cc
@@ -40,8 +40,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/nonequilibrium/newtoncontroller.hh>
+#include <dumux/porousmediumflow/nonequilibrium/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -134,7 +133,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -162,10 +160,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = NonEquilibriumNewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NonEquilibriumNewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -173,24 +169,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -205,8 +185,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
 
     } while (!timeLoop->finished());
diff --git a/test/porousmediumflow/mpnc/implicit/test_boxmpncthermalnonequil.cc b/test/porousmediumflow/mpnc/implicit/test_boxmpncthermalnonequil.cc
index 8974eecafa9b25094420ca9e6084e6baa0724ebd..7501c698c7c12e55683a6e5e56d95ca81c033a5f 100644
--- a/test/porousmediumflow/mpnc/implicit/test_boxmpncthermalnonequil.cc
+++ b/test/porousmediumflow/mpnc/implicit/test_boxmpncthermalnonequil.cc
@@ -40,8 +40,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/nonequilibrium/newtoncontroller.hh>
+#include <dumux/porousmediumflow/nonequilibrium/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -133,7 +132,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -161,10 +159,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = NonEquilibriumNewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NonEquilibriumNewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -172,24 +168,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -205,8 +185,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
 
     } while (!timeLoop->finished());
diff --git a/test/porousmediumflow/mpnc/implicit/test_mpnc_obstacle_fv.cc b/test/porousmediumflow/mpnc/implicit/test_mpnc_obstacle_fv.cc
index fc999af2a1320bb380d7b1b790cc8777dd23acaf..86bdae2d55617673846ec7e4dc7ff17c93c18dcc 100644
--- a/test/porousmediumflow/mpnc/implicit/test_mpnc_obstacle_fv.cc
+++ b/test/porousmediumflow/mpnc/implicit/test_mpnc_obstacle_fv.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -135,7 +134,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -163,10 +161,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -174,24 +170,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -206,8 +186,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/richards/implicit/test_ccrichardsanalytical.cc b/test/porousmediumflow/richards/implicit/test_ccrichardsanalytical.cc
index e5c0bd42a0de3bd93cf9cd07821540b9f0a36049..8b9be9df435726b7c1f96153589fcdcd9d7eb885 100644
--- a/test/porousmediumflow/richards/implicit/test_ccrichardsanalytical.cc
+++ b/test/porousmediumflow/richards/implicit/test_ccrichardsanalytical.cc
@@ -41,9 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dumux/porousmediumflow/richards/newtoncontroller.hh>
+#include <dumux/porousmediumflow/richards/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 
@@ -129,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -157,10 +154,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using NewtonController = Dumux::RichardsNewtonController<TypeTag>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::RichardsNewtonSolver<TypeTag, Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -169,24 +164,8 @@ int main(int argc, char** argv) try
         assembler->setPreviousSolution(xOld);
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -203,8 +182,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc b/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc
index 9d260e610e4532a6cdc41a9902cce78c46d5f890..1550ec49da78fe7301c5ce8b9cdbbb6deb171409 100644
--- a/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc
+++ b/test/porousmediumflow/richards/implicit/test_richardslens_fv.cc
@@ -179,7 +179,7 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
+        // set new dt as suggested by the newton solver
         timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
diff --git a/test/porousmediumflow/richards/implicit/test_richardsniconduction_fv.cc b/test/porousmediumflow/richards/implicit/test_richardsniconduction_fv.cc
index 49a276444d79b79d33169bc0f6f612719710a844..82f3c629c1ff7fe3cec09ff145c205a5b7294605 100644
--- a/test/porousmediumflow/richards/implicit/test_richardsniconduction_fv.cc
+++ b/test/porousmediumflow/richards/implicit/test_richardsniconduction_fv.cc
@@ -41,9 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dumux/porousmediumflow/richards/newtoncontroller.hh>
+#include <dumux/porousmediumflow/richards/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 
@@ -129,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -158,10 +155,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using NewtonController = Dumux::RichardsNewtonController<TypeTag>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::RichardsNewtonSolver<TypeTag, Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -169,24 +164,9 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
+
          // compute the new analytical temperature field for the output
         problem->updateExactTemperature(x, timeLoop->time()+timeLoop->timeStepSize());
 
@@ -203,8 +183,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/richards/implicit/test_richardsniconvection_fv.cc b/test/porousmediumflow/richards/implicit/test_richardsniconvection_fv.cc
index 4b549054c9e408daa33d16c83ede5219fec8f69c..ba18b9ce986dedf404ac039b60b0934e6807aea4 100644
--- a/test/porousmediumflow/richards/implicit/test_richardsniconvection_fv.cc
+++ b/test/porousmediumflow/richards/implicit/test_richardsniconvection_fv.cc
@@ -41,9 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dumux/porousmediumflow/richards/newtoncontroller.hh>
+#include <dumux/porousmediumflow/richards/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 
@@ -129,7 +127,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -158,10 +155,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using NewtonController = Dumux::RichardsNewtonController<TypeTag>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::RichardsNewtonSolver<TypeTag, Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -169,24 +164,9 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
+
          // compute the new analytical temperature field for the output
         problem->updateExactTemperature(x, timeLoop->time()+timeLoop->timeStepSize());
 
@@ -203,8 +183,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/richards/implicit/test_richardsnievaporation_fv.cc b/test/porousmediumflow/richards/implicit/test_richardsnievaporation_fv.cc
index bf53af86c7a712d480f61f29bda2c1684696206a..3464a371f31613bbdf685ae0bc61f7e8b2c419cb 100644
--- a/test/porousmediumflow/richards/implicit/test_richardsnievaporation_fv.cc
+++ b/test/porousmediumflow/richards/implicit/test_richardsnievaporation_fv.cc
@@ -147,7 +147,7 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
+        // set new dt as suggested by the newton solver
         timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
diff --git a/test/porousmediumflow/richardsnc/implicit/test_richardsnc_fv.cc b/test/porousmediumflow/richardsnc/implicit/test_richardsnc_fv.cc
index 8fcd51145eec108863e3fc08aa3e5c820f078b8f..22decb0f0484c57307e9089684e7a29ae2732523 100644
--- a/test/porousmediumflow/richardsnc/implicit/test_richardsnc_fv.cc
+++ b/test/porousmediumflow/richardsnc/implicit/test_richardsnc_fv.cc
@@ -41,9 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include <dumux/porousmediumflow/richards/newtoncontroller.hh>
+#include <dumux/porousmediumflow/richards/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 
@@ -130,7 +128,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -158,10 +155,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>();
 
     // the non-linear solver
-    using NewtonController = Dumux::RichardsNewtonController<TypeTag>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::RichardsNewtonSolver<TypeTag, Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -169,24 +164,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                            "Newton solver didn't converge after "
-                            << maxDivisions
-                            << " time-step divisions. dt="
-                            << timeLoop->timeStepSize()
-                            << ".\nThe solutions of the current and the previous time steps "
-                            << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -202,8 +181,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/test/porousmediumflow/tracer/1ptracer/test_cctracer.cc b/test/porousmediumflow/tracer/1ptracer/test_cctracer.cc
index 9187fa02573ac558b7da740ad22f752ceebe81e9..010fa973806c4bfdd533c387f3d10841f41993ab 100644
--- a/test/porousmediumflow/tracer/1ptracer/test_cctracer.cc
+++ b/test/porousmediumflow/tracer/1ptracer/test_cctracer.cc
@@ -39,7 +39,6 @@
 #include <dumux/common/dumuxmessage.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -286,7 +285,7 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
+        // set new dt
         timeLoop->setTimeStepSize(dt);
 
     } while (!timeLoop->finished());
diff --git a/test/porousmediumflow/tracer/constvel/test_tracer.cc b/test/porousmediumflow/tracer/constvel/test_tracer.cc
index f75e2b5a3ab7aac04746c0dad413066b3e2947e1..b710725758a67fa11365ef8b161f5635e390f695 100644
--- a/test/porousmediumflow/tracer/constvel/test_tracer.cc
+++ b/test/porousmediumflow/tracer/constvel/test_tracer.cc
@@ -37,7 +37,6 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
 #include <dumux/assembly/fvassembler.hh>
 
 #include <dumux/io/vtkoutputmodule.hh>
@@ -183,7 +182,7 @@ int main(int argc, char** argv) try
         if (timeLoop->isCheckPoint() || timeLoop->finished())
             vtkWriter.write(timeLoop->time());
 
-        // set new dt as suggested by newton controller
+        // set new dt
         timeLoop->setTimeStepSize(dt);
     }
 
diff --git a/test/porousmediumflow/tracer/multicomp/test_tracer_maxwellstefan.cc b/test/porousmediumflow/tracer/multicomp/test_tracer_maxwellstefan.cc
index 07d3eb609dc3a6bf818053aaf5df7e6c305ec450..a03b1a28a8ea0f57010f1c869fe4199256d67a6a 100644
--- a/test/porousmediumflow/tracer/multicomp/test_tracer_maxwellstefan.cc
+++ b/test/porousmediumflow/tracer/multicomp/test_tracer_maxwellstefan.cc
@@ -41,8 +41,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -135,7 +134,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -163,10 +161,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = Dumux::NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -174,24 +170,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -207,8 +187,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
     } while (!timeLoop->finished());
 
diff --git a/tutorial/ex1/exercise1.cc b/tutorial/ex1/exercise1.cc
index b7655dac87ecae2ece2ff2d22b752f3949480d42..d6bb2599a084c7f1bad7d919d712ae5984dd3015 100644
--- a/tutorial/ex1/exercise1.cc
+++ b/tutorial/ex1/exercise1.cc
@@ -36,8 +36,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -103,7 +102,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -125,10 +123,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start();
@@ -140,24 +136,8 @@ int main(int argc, char** argv) try
         //set time in problem (is used in time-dependent Neumann boundary condition)
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -169,8 +149,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // output to vtk
         vtkWriter.write(timeLoop->time());
diff --git a/tutorial/ex1/exercise1_2p.cc b/tutorial/ex1/exercise1_2p.cc
index 9cba2e73b24ccfb432e32ef27b140bd7be5f401c..7ae3bca427fb0c6c88341a0cd7ef04937b148ea2 100644
--- a/tutorial/ex1/exercise1_2p.cc
+++ b/tutorial/ex1/exercise1_2p.cc
@@ -36,8 +36,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -106,7 +105,6 @@ int main(int argc, char** argv) try
     // of type TYPE given in the group GROUPNAME from the input file
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -128,10 +126,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start();
@@ -143,24 +139,8 @@ int main(int argc, char** argv) try
         //set time in problem (is used in time-dependent Neumann boundary condition)
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -172,8 +152,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // output to vtk
         vtkWriter.write(timeLoop->time());
diff --git a/tutorial/ex1/exercise1_2p2c.cc b/tutorial/ex1/exercise1_2p2c.cc
index a0b5ebb0355f62ab47f1197d96e56c3605845448..6f7e515c043a634b3673b4fe554f22a46a8cc3e1 100644
--- a/tutorial/ex1/exercise1_2p2c.cc
+++ b/tutorial/ex1/exercise1_2p2c.cc
@@ -36,8 +36,7 @@
 #include <dumux/common/dumuxmessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -106,7 +105,6 @@ int main(int argc, char** argv) try
     // of type TYPE given in the group GROUPNAME from the input file
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -128,10 +126,9 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch);
+    using NewtonSolver = Dumux::PriVarSwitchNewtonSolver<Assembler, LinearSolver, PrimaryVariableSwitch>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start();
@@ -143,24 +140,8 @@ int main(int argc, char** argv) try
         //set time in problem (is used in time-dependent Neumann boundary condition)
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -172,8 +153,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // output to vtk
         vtkWriter.write(timeLoop->time());
diff --git a/tutorial/ex2/exercise2.cc b/tutorial/ex2/exercise2.cc
index dba708fbc1d911d01f20eb28cf8edf3731489d86..d031e8753b39eba25ae4979d5cdb563ba534608e 100644
--- a/tutorial/ex2/exercise2.cc
+++ b/tutorial/ex2/exercise2.cc
@@ -37,8 +37,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -101,7 +100,6 @@ int main(int argc, char** argv)try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -128,10 +126,9 @@ int main(int argc, char** argv)try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch);
+    using NewtonSolver = Dumux::PriVarSwitchNewtonSolver<Assembler, LinearSolver, PrimaryVariableSwitch>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -142,24 +139,8 @@ int main(int argc, char** argv)try
         //set time in problem (is used in time-dependent Neumann boundary condition)
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -171,8 +152,8 @@ int main(int argc, char** argv)try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         vtkWriter.write(timeLoop->time());
 
diff --git a/tutorial/ex3/exercise3.cc b/tutorial/ex3/exercise3.cc
index 7111c6a3e0144e77a8e28c78e50b46fcdc631388..4669ea7f18988da5a659b439437820b1aff4f84c 100644
--- a/tutorial/ex3/exercise3.cc
+++ b/tutorial/ex3/exercise3.cc
@@ -42,8 +42,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -140,7 +139,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -167,10 +165,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -178,24 +174,8 @@ int main(int argc, char** argv) try
         // set previous solution for storage evaluations
         assembler->setPreviousSolution(xOld);
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -207,8 +187,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // write solution and grid to vtk
         vtkWriter.write(timeLoop->time());
diff --git a/tutorial/solution/ex1/exercise1_2p2c.cc b/tutorial/solution/ex1/exercise1_2p2c.cc
index 313486242dd1ff4880cd67647268cbf6b1c9b410..779a668a6196d5518f716d04dfd7fb43d6daa0df 100644
--- a/tutorial/solution/ex1/exercise1_2p2c.cc
+++ b/tutorial/solution/ex1/exercise1_2p2c.cc
@@ -36,8 +36,7 @@
 #include <dumux/common/dumuxmessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -103,7 +102,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -125,10 +123,9 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch);
+    using NewtonSolver = Dumux::PriVarSwitchNewtonSolver<Assembler, LinearSolver, PrimaryVariableSwitch>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start();
@@ -140,24 +137,8 @@ int main(int argc, char** argv) try
         //set time in problem (is used in time-dependent Neumann boundary condition)
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -169,8 +150,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // output to vtk
         vtkWriter.write(timeLoop->time());
diff --git a/tutorial/solution/ex1/exercise1_2pni_solution.cc b/tutorial/solution/ex1/exercise1_2pni_solution.cc
index bd2b3e835761050c448a7aee5e1d4b1d64b0f82a..877fe41e393c4bc984133291466a52f85132f745 100644
--- a/tutorial/solution/ex1/exercise1_2pni_solution.cc
+++ b/tutorial/solution/ex1/exercise1_2pni_solution.cc
@@ -36,8 +36,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -103,7 +102,6 @@ int main(int argc, char** argv) try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -125,10 +123,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = Dumux::NewtonController<Scalar>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start();
@@ -140,24 +136,8 @@ int main(int argc, char** argv) try
         //set time in problem (is used in time-dependent Neumann boundary condition)
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -169,8 +149,8 @@ int main(int argc, char** argv) try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         // output to vtk
         vtkWriter.write(timeLoop->time());
diff --git a/tutorial/solution/ex2/exercise2_solution.cc b/tutorial/solution/ex2/exercise2_solution.cc
index dba708fbc1d911d01f20eb28cf8edf3731489d86..d031e8753b39eba25ae4979d5cdb563ba534608e 100644
--- a/tutorial/solution/ex2/exercise2_solution.cc
+++ b/tutorial/solution/ex2/exercise2_solution.cc
@@ -37,8 +37,7 @@
 #include <dumux/common/defaultusagemessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-#include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
 
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
@@ -101,7 +100,6 @@ int main(int argc, char** argv)try
     // get some time loop parameters
     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
@@ -128,10 +126,9 @@ int main(int argc, char** argv)try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using NewtonController = PriVarSwitchNewtonController<TypeTag>;
-    using NewtonMethod = NewtonMethod<NewtonController, Assembler, LinearSolver>;
-    auto newtonController = std::make_shared<NewtonController>(timeLoop);
-    NewtonMethod nonLinearSolver(newtonController, assembler, linearSolver);
+    using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch);
+    using NewtonSolver = Dumux::PriVarSwitchNewtonSolver<Assembler, LinearSolver, PrimaryVariableSwitch>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
     timeLoop->start(); do
@@ -142,24 +139,8 @@ int main(int argc, char** argv)try
         //set time in problem (is used in time-dependent Neumann boundary condition)
         problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
 
-        // try solving the non-linear system
-        for (int i = 0; i < maxDivisions; ++i)
-        {
-            // linearize & solve
-            auto converged = nonLinearSolver.solve(x);
-
-            if (converged)
-                break;
-
-            if (!converged && i == maxDivisions-1)
-                DUNE_THROW(Dune::MathError,
-                           "Newton solver didn't converge after "
-                           << maxDivisions
-                           << " time-step divisions. dt="
-                           << timeLoop->timeStepSize()
-                           << ".\nThe solutions of the current and the previous time steps "
-                           << "have been saved to restart files.");
-        }
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
 
         // make the new solution the old solution
         xOld = x;
@@ -171,8 +152,8 @@ int main(int argc, char** argv)try
         // report statistics of this time step
         timeLoop->reportTimeStep();
 
-        // set new dt as suggested by newton controller
-        timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
 
         vtkWriter.write(timeLoop->time());