diff --git a/Applications/ApplicationsLib/UncoupledProcessesTimeLoop.h b/Applications/ApplicationsLib/UncoupledProcessesTimeLoop.h
index fe49dfeb5a6fcea9687f833de54c049d23f70a26..b8375887d2d80a72ee763554607da7fe0789d619 100644
--- a/Applications/ApplicationsLib/UncoupledProcessesTimeLoop.h
+++ b/Applications/ApplicationsLib/UncoupledProcessesTimeLoop.h
@@ -197,6 +197,33 @@ private:
             break;
         }
     }
+
+    //! Applies known solutions to the solution vector \c x, transparently
+    //! for equation systems linearized with either the Picard or Newton method.
+    template<NumLib::NonlinearSolverTag NLTag>
+    static void applyKnownSolutions(
+            EquationSystem const& eq_sys, Vector& x)
+    {
+        using EqSys = NumLib::NonlinearSystem<Matrix, Vector, NLTag>;
+        assert(dynamic_cast<EqSys const*> (&eq_sys) != nullptr);
+        auto& eq_sys_ = static_cast<EqSys const&> (eq_sys);
+
+        eq_sys_.applyKnownSolutions(x);
+    }
+
+    //! Applies known solutions to the solution vector \c x, transparently
+    //! for equation systems linearized with either the Picard or Newton method.
+    static void applyKnownSolutions(
+            EquationSystem const& eq_sys,
+            NumLib::NonlinearSolverTag const nl_tag, Vector& x)
+    {
+        using Tag = NumLib::NonlinearSolverTag;
+        switch (nl_tag)
+        {
+        case Tag::Picard: applyKnownSolutions<Tag::Picard>(eq_sys, x); break;
+        case Tag::Newton: applyKnownSolutions<Tag::Newton>(eq_sys, x); break;
+        }
+    }
 };
 
 //! Builds an UncoupledProcessesTimeLoop from the given configuration.
@@ -310,11 +337,17 @@ solveOneTimeStepOneProcess(
 
     setEquationSystem(nonlinear_solver, ode_sys, nl_tag);
 
-    process.preTimestep(x, t, delta_t);
+    // Note: Order matters!
+    // First advance to the next timestep, then set known solutions at that
+    // time, afterwards pass the right solution vector and time to the
+    // preTimestep() hook.
 
-    // INFO("time: %e, delta_t: %e", t, delta_t);
     time_disc.nextTimestep(t, delta_t);
 
+    applyKnownSolutions(ode_sys, nl_tag, x);
+
+    process.preTimestep(x, t, delta_t);
+
     bool nonlinear_solver_succeeded = nonlinear_solver.solve(x);
 
     auto& mat_strg = process_data.mat_strg;
diff --git a/MathLib/LinAlg/MatrixVectorTraits.cpp b/MathLib/LinAlg/MatrixVectorTraits.cpp
index d1036ed4347d240bd323dd387d49741e5f10e2c3..dceca5ee11c47bc09b40634d18e577a643ac1238 100644
--- a/MathLib/LinAlg/MatrixVectorTraits.cpp
+++ b/MathLib/LinAlg/MatrixVectorTraits.cpp
@@ -8,6 +8,7 @@
  */
 
 #include "AssemblerLib/LocalToGlobalIndexMap.h"
+#include "MatrixProviderUser.h"
 #include "MatrixVectorTraits.h"
 
 #ifdef OGS_USE_EIGEN
diff --git a/MathLib/LinAlg/MatrixVectorTraits.h b/MathLib/LinAlg/MatrixVectorTraits.h
index 793e6c2bf823c2ba16c6f2e2c8fc257bd481759e..44f9f4892fa2335b4f005077bbc6ce344eb5978a 100644
--- a/MathLib/LinAlg/MatrixVectorTraits.h
+++ b/MathLib/LinAlg/MatrixVectorTraits.h
@@ -12,12 +12,12 @@
 
 #include<memory>
 
-#include "MatrixProviderUser.h"
-
 namespace MathLib
 {
 template<typename Matrix>
 struct MatrixVectorTraits;
+
+struct MatrixSpecifications;
 }
 
 #define SPECIALIZE_MATRIX_VECTOR_TRAITS(MATVEC, IDX) \
diff --git a/MathLib/LinAlg/UnifiedMatrixSetters.cpp b/MathLib/LinAlg/UnifiedMatrixSetters.cpp
index 3b762f0a985ff111dca78236e68d45f2e0e2ea2f..00dbc7ce0ab9cd56fcb7613ac58b5b9cbfb8fa1b 100644
--- a/MathLib/LinAlg/UnifiedMatrixSetters.cpp
+++ b/MathLib/LinAlg/UnifiedMatrixSetters.cpp
@@ -67,6 +67,12 @@ void setVector(Eigen::VectorXd& v, std::initializer_list<double> values)
     for (std::size_t i=0; i<values.size(); ++i) v[i] = *(it++);
 }
 
+void setVector(Eigen::VectorXd& v, MatrixVectorTraits<Eigen::VectorXd>::Index const index,
+               double const value)
+{
+    v[index] = value;
+}
+
 } // namespace MathLib
 
 #endif // OGS_USE_EIGEN
@@ -97,6 +103,12 @@ void setVector(PETScVector& v,
     v.set(idcs, vals);
 }
 
+void setVector(PETScVector& v, MatrixVectorTraits<PETScVector>::Index const index,
+               double const value)
+{
+    v.set(index, value); // TODO handle negative indices
+}
+
 void setMatrix(PETScMatrix& m,
                std::initializer_list<double> values)
 {
@@ -173,6 +185,13 @@ void setVector(EigenVector& v,
     setVector(v.getRawVector(), values);
 }
 
+void setVector(EigenVector& v, MatrixVectorTraits<EigenVector>::Index const index,
+               double const value)
+{
+    v.getRawVector()[index] = value;
+}
+
+
 void setMatrix(EigenMatrix& m,
                std::initializer_list<double> values)
 {
diff --git a/MathLib/LinAlg/UnifiedMatrixSetters.h b/MathLib/LinAlg/UnifiedMatrixSetters.h
index 4ece2dd9400627a442b4c44f95c585baee9ce50b..d7402b25139b7ade1185489fba30248b763d683e 100644
--- a/MathLib/LinAlg/UnifiedMatrixSetters.h
+++ b/MathLib/LinAlg/UnifiedMatrixSetters.h
@@ -13,6 +13,7 @@
 #define MATHLIB_UNIFIED_MATRIX_SETTERS_H
 
 #include <initializer_list>
+#include "MatrixVectorTraits.h"
 
 #ifdef OGS_USE_EIGEN
 
@@ -35,6 +36,9 @@ double norm(Eigen::VectorXd const& x);
 
 void setVector(Eigen::VectorXd& v, std::initializer_list<double> values);
 
+void setVector(Eigen::VectorXd& v, MatrixVectorTraits<Eigen::VectorXd>::Index const index,
+               double const value);
+
 } // namespace MathLib
 
 #endif // OGS_USE_EIGEN
@@ -55,6 +59,9 @@ double norm(PETScVector const& x);
 void setVector(PETScVector& v,
                std::initializer_list<double> values);
 
+void setVector(PETScVector& v, MatrixVectorTraits<PETScVector>::Index const index,
+               double const value);
+
 void setMatrix(PETScMatrix& m, Eigen::MatrixXd const& tmp);
 
 void addToMatrix(PETScMatrix& m,
@@ -79,6 +86,9 @@ class EigenMatrix;
 void setVector(EigenVector& v,
                std::initializer_list<double> values);
 
+void setVector(EigenVector& v, MatrixVectorTraits<EigenVector>::Index const index,
+               double const value);
+
 void setMatrix(EigenMatrix& m,
                std::initializer_list<double> values);
 
diff --git a/NumLib/ODESolver/NonlinearSystem.h b/NumLib/ODESolver/NonlinearSystem.h
index d466da77e121c99a781dc86007a710bef5ea2c13..17c9f169cd18e6dbd7544697271777468f699624 100644
--- a/NumLib/ODESolver/NonlinearSystem.h
+++ b/NumLib/ODESolver/NonlinearSystem.h
@@ -64,6 +64,9 @@ public:
      */
     virtual void getJacobian(Matrix& Jac) const = 0;
 
+    //! Apply known solutions to the solution vector \c x.
+    virtual void applyKnownSolutions(Vector& x) const = 0;
+
     //! Apply known solutions to the linearized equation system
     //! \f$ \mathit{Jac} \cdot (-\Delta x) = \mathit{res} \f$.
     virtual void applyKnownSolutionsNewton(
@@ -93,6 +96,9 @@ public:
     //! Writes the linearized equation system right-hand side to \c rhs.
     virtual void getRhs(Vector& rhs) const = 0;
 
+    //! Apply known solutions to the solution vector \c x.
+    virtual void applyKnownSolutions(Vector& x) const = 0;
+
     //! Apply known solutions to the linearized equation system
     //! \f$ A \cdot x = \mathit{rhs} \f$.
     virtual void applyKnownSolutionsPicard(
diff --git a/NumLib/ODESolver/TimeDiscretizedODESystem.h b/NumLib/ODESolver/TimeDiscretizedODESystem.h
index 5acc2d6e26eca63f59e4053eacdd23ce716841a7..22d1d1414737fe100e8114ffe547a12eef410edd 100644
--- a/NumLib/ODESolver/TimeDiscretizedODESystem.h
+++ b/NumLib/ODESolver/TimeDiscretizedODESystem.h
@@ -13,6 +13,7 @@
 #include <memory>
 
 #include "MathLib/LinAlg/ApplyKnownSolution.h"
+#include "MathLib/LinAlg/UnifiedMatrixSetters.h"
 #include "ProcessLib/DirichletBc.h"
 
 #include "ODESystem.h"
@@ -20,6 +21,23 @@
 #include "TimeDiscretization.h"
 #include "MatrixTranslator.h"
 
+namespace detail
+{
+//! Applies known solutions to the solution vector \c x.
+template<typename Solutions, typename Vector>
+void applyKnownSolutions(std::vector<Solutions> const*const known_solutions,
+                         Vector& x)
+{
+    if (!known_solutions) return;
+
+    for (auto const& bc : *known_solutions) {
+        for (std::size_t i=0; i<bc.global_ids.size(); ++i) {
+            // TODO that might have bad performance for some Vector types, e.g., PETSc.
+            MathLib::setVector(x, bc.global_ids[i], bc.values[i]);
+        }
+    }
+}
+}
 
 namespace NumLib
 {
@@ -174,11 +192,29 @@ public:
         _mat_trans->computeJacobian(*_Jac, Jac);
     }
 
+    void applyKnownSolutions(Vector& x) const override
+    {
+        ::detail::applyKnownSolutions(
+                    _ode.getKnownSolutions(_time_disc.getCurrentTime()), x);
+    }
+
     void applyKnownSolutionsNewton(Matrix& Jac, Vector& res,
                                     Vector& minus_delta_x) override
     {
-        (void) Jac; (void) res; (void) minus_delta_x;
-        INFO("Method applyKnownSolutionsNewton() not implemented."); // TODO implement
+        auto const* known_solutions =
+            _ode.getKnownSolutions(_time_disc.getCurrentTime());
+
+        if (known_solutions) {
+            std::vector<double> values;
+
+            for (auto const& bc : *known_solutions) {
+                // TODO this is the quick and dirty and bad performance solution.
+                values.resize(bc.values.size(), 0.0);
+
+                // TODO maybe it would be faster to apply all at once
+                MathLib::applyKnownSolution(Jac, res, minus_delta_x, bc.global_ids, values);
+            }
+        }
     }
 
     bool isLinear() const override
@@ -308,6 +344,12 @@ public:
         _mat_trans->computeRhs(*_M, *_K, *_b, rhs);
     }
 
+    void applyKnownSolutions(Vector& x) const override
+    {
+        ::detail::applyKnownSolutions(
+                    _ode.getKnownSolutions(_time_disc.getCurrentTime()), x);
+    }
+
     void applyKnownSolutionsPicard(Matrix& A, Vector& rhs, Vector& x) override
     {
         auto const* known_solutions =