diff --git a/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.cpp b/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.cpp
index 290366d8e1b6385e458fe3a5b2ae80bb3715790a..13f816c95d1535b9b631e1a337b2d98dc3017019 100644
--- a/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.cpp
+++ b/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.cpp
@@ -21,6 +21,7 @@ std::unique_ptr<Process> createGroundwaterFlowProcess(
     MeshLib::Mesh& mesh,
     Process::NonlinearSolver& nonlinear_solver,
     std::unique_ptr<Process::TimeDiscretization>&& time_discretization,
+    std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
     std::vector<ProcessVariable> const& variables,
     std::vector<std::unique_ptr<ParameterBase>> const& parameters,
     BaseLib::ConfigTree const& config)
@@ -62,9 +63,9 @@ std::unique_ptr<Process> createGroundwaterFlowProcess(
 
     return std::unique_ptr<Process>{new GroundwaterFlowProcess{
         mesh, nonlinear_solver, std::move(time_discretization),
-        std::move(process_variables), std::move(process_data),
-        std::move(secondary_variables), std::move(process_output),
-        std::move(named_function_caller)}};
+        std::move(convergence_criterion), std::move(process_variables),
+        std::move(process_data), std::move(secondary_variables),
+        std::move(process_output), std::move(named_function_caller)}};
 }
 
 }  // namespace GroundwaterFlow
diff --git a/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.h b/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.h
index 0434c1e35379ea15bb961015b70aa07cc5b7adaf..3e964c246f8653e4963fc56ed828e7f01e80108e 100644
--- a/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.h
+++ b/ProcessLib/GroundwaterFlow/CreateGroundwaterFlowProcess.h
@@ -18,12 +18,11 @@ namespace ProcessLib
 {
 namespace GroundwaterFlow
 {
-
-std::unique_ptr<Process>
-createGroundwaterFlowProcess(
+std::unique_ptr<Process> createGroundwaterFlowProcess(
     MeshLib::Mesh& mesh,
     Process::NonlinearSolver& nonlinear_solver,
     std::unique_ptr<Process::TimeDiscretization>&& time_discretization,
+    std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
     std::vector<ProcessVariable> const& variables,
     std::vector<std::unique_ptr<ParameterBase>> const& parameters,
     BaseLib::ConfigTree const& config);
diff --git a/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.cpp b/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.cpp
index 8fa3b80717208e6882a8c6d125992bf8616d847e..f8345c265566f76d6efc53de745cbfe2f0d0beb6 100644
--- a/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.cpp
+++ b/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.cpp
@@ -21,14 +21,16 @@ GroundwaterFlowProcess::GroundwaterFlowProcess(
     MeshLib::Mesh& mesh,
     Base::NonlinearSolver& nonlinear_solver,
     std::unique_ptr<Base::TimeDiscretization>&& time_discretization,
+    std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
     std::vector<std::reference_wrapper<ProcessVariable>>&& process_variables,
     GroundwaterFlowProcessData&& process_data,
     SecondaryVariableCollection&& secondary_variables,
     ProcessOutput&& process_output,
     NumLib::NamedFunctionCaller&& named_function_caller)
     : Process(mesh, nonlinear_solver, std::move(time_discretization),
-              std::move(process_variables), std::move(secondary_variables),
-              std::move(process_output), std::move(named_function_caller)),
+              std::move(convergence_criterion), std::move(process_variables),
+              std::move(secondary_variables), std::move(process_output),
+              std::move(named_function_caller)),
       _process_data(std::move(process_data))
 {
     if (dynamic_cast<NumLib::ForwardEuler*>(
diff --git a/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.h b/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.h
index 4cac997d91a817a9f1d564cd6e484308fdb4a7fd..8856d8213c6cbb54f2f9f15af4f8c334427d14cb 100644
--- a/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.h
+++ b/ProcessLib/GroundwaterFlow/GroundwaterFlowProcess.h
@@ -29,6 +29,7 @@ public:
         MeshLib::Mesh& mesh,
         Base::NonlinearSolver& nonlinear_solver,
         std::unique_ptr<Base::TimeDiscretization>&& time_discretization,
+        std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
         std::vector<std::reference_wrapper<ProcessVariable>>&&
             process_variables,
         GroundwaterFlowProcessData&& process_data,
diff --git a/ProcessLib/Process.cpp b/ProcessLib/Process.cpp
index e88265b0649b233d11485013eb95a8b8ca0cd05e..d52b3c892b74b1e533d45fb5484e08012583ada1 100644
--- a/ProcessLib/Process.cpp
+++ b/ProcessLib/Process.cpp
@@ -12,6 +12,7 @@
 #include "BaseLib/Functional.h"
 #include "NumLib/DOF/ComputeSparsityPattern.h"
 #include "NumLib/Extrapolation/LocalLinearLeastSquaresExtrapolator.h"
+#include "NumLib/ODESolver/ConvergenceCriterionPerComponent.h"
 #include "GlobalVectorFromNamedFunction.h"
 #include "ProcessVariable.h"
 
@@ -21,6 +22,7 @@ Process::Process(
     MeshLib::Mesh& mesh,
     NonlinearSolver& nonlinear_solver,
     std::unique_ptr<TimeDiscretization>&& time_discretization,
+    std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
     std::vector<std::reference_wrapper<ProcessVariable>>&& process_variables,
     SecondaryVariableCollection&& secondary_variables,
     ProcessOutput&& process_output,
@@ -31,6 +33,7 @@ Process::Process(
       _named_function_caller(std::move(named_function_caller)),
       _nonlinear_solver(nonlinear_solver),
       _time_discretization(std::move(time_discretization)),
+      _convergence_criterion(std::move(convergence_criterion)),
       _process_variables(std::move(process_variables))
 {
 }
@@ -156,6 +159,12 @@ void Process::constructDofTable()
 
     _local_to_global_index_map.reset(new NumLib::LocalToGlobalIndexMap(
         std::move(all_mesh_subsets), NumLib::ComponentOrder::BY_LOCATION));
+
+    if (auto* conv_crit =
+            dynamic_cast<NumLib::ConvergenceCriterionPerComponent*>(
+                _convergence_criterion.get())) {
+        conv_crit->setDOFTable(*_local_to_global_index_map, _mesh);
+    }
 }
 
 void Process::initializeExtrapolator()
diff --git a/ProcessLib/Process.h b/ProcessLib/Process.h
index 426f3452883b522c087ea61f162d8f5c79184617..b3ca1c3479d98ccf693dfcda5c20b114531aa5df 100644
--- a/ProcessLib/Process.h
+++ b/ProcessLib/Process.h
@@ -38,14 +38,16 @@ public:
     using NonlinearSolver = NumLib::NonlinearSolverBase;
     using TimeDiscretization = NumLib::TimeDiscretization;
 
-    Process(MeshLib::Mesh& mesh,
-            NonlinearSolver& nonlinear_solver,
-            std::unique_ptr<TimeDiscretization>&& time_discretization,
-            std::vector<std::reference_wrapper<ProcessVariable>>&&
-                process_variables,
-            SecondaryVariableCollection&& secondary_variables,
-            ProcessOutput&& process_output,
-            NumLib::NamedFunctionCaller&& named_function_caller);
+    Process(
+        MeshLib::Mesh& mesh,
+        NonlinearSolver& nonlinear_solver,
+        std::unique_ptr<TimeDiscretization>&& time_discretization,
+        std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
+        std::vector<std::reference_wrapper<ProcessVariable>>&&
+            process_variables,
+        SecondaryVariableCollection&& secondary_variables,
+        ProcessOutput&& process_output,
+        NumLib::NamedFunctionCaller&& named_function_caller);
 
     /// Preprocessing before starting assembly for new timestep.
     virtual void preTimestep(GlobalVector const& /*x*/, const double /*t*/,
@@ -96,6 +98,11 @@ public:
         return *_time_discretization;
     }
 
+    NumLib::ConvergenceCriterion& getConvergenceCriterion() const
+    {
+        return *_convergence_criterion;
+    }
+
 protected:
     NumLib::Extrapolator& getExtrapolator() const
     {
@@ -172,6 +179,7 @@ private:
 
     NonlinearSolver& _nonlinear_solver;
     std::unique_ptr<TimeDiscretization> _time_discretization;
+    std::unique_ptr<NumLib::ConvergenceCriterion> _convergence_criterion;
 
     /// Variables used by this process.
     std::vector<std::reference_wrapper<ProcessVariable>> _process_variables;
diff --git a/ProcessLib/TES/CreateTESProcess.cpp b/ProcessLib/TES/CreateTESProcess.cpp
index 4564bb50bc3c0ec9418d3d6362badec6901ee21a..f14bb0b3af10f080c732a14e3ce95a6e949d5e22 100644
--- a/ProcessLib/TES/CreateTESProcess.cpp
+++ b/ProcessLib/TES/CreateTESProcess.cpp
@@ -15,11 +15,11 @@ namespace ProcessLib
 {
 namespace TES
 {
-
 std::unique_ptr<Process> createTESProcess(
     MeshLib::Mesh& mesh,
     Process::NonlinearSolver& nonlinear_solver,
     std::unique_ptr<Process::TimeDiscretization>&& time_discretization,
+    std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
     std::vector<ProcessVariable> const& variables,
     std::vector<std::unique_ptr<ParameterBase>> const& /*parameters*/,
     BaseLib::ConfigTree const& config)
@@ -46,8 +46,9 @@ std::unique_ptr<Process> createTESProcess(
 
     return std::unique_ptr<Process>{new TESProcess{
         mesh, nonlinear_solver, std::move(time_discretization),
-        std::move(process_variables), std::move(secondary_variables),
-        std::move(process_output), std::move(named_function_caller), config}};
+        std::move(convergence_criterion), std::move(process_variables),
+        std::move(secondary_variables), std::move(process_output),
+        std::move(named_function_caller), config}};
 }
 
 }  // namespace TES
diff --git a/ProcessLib/TES/CreateTESProcess.h b/ProcessLib/TES/CreateTESProcess.h
index d45c8d06d761fb4b8702a580f04964dce516e425..f51d00030e62f638f5625092cccca88c82b9304e 100644
--- a/ProcessLib/TES/CreateTESProcess.h
+++ b/ProcessLib/TES/CreateTESProcess.h
@@ -17,12 +17,11 @@ namespace ProcessLib
 {
 namespace TES
 {
-
 std::unique_ptr<Process> createTESProcess(
     MeshLib::Mesh& mesh,
     Process::NonlinearSolver& nonlinear_solver,
-    std::unique_ptr<Process::TimeDiscretization>&&
-        time_discretization,
+    std::unique_ptr<Process::TimeDiscretization>&& time_discretization,
+    std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
     std::vector<ProcessVariable> const& variables,
     std::vector<std::unique_ptr<ParameterBase>> const& /*parameters*/,
     BaseLib::ConfigTree const& config);
diff --git a/ProcessLib/TES/TESProcess.cpp b/ProcessLib/TES/TESProcess.cpp
index 6b2d69706fef4aed4e90fdecf2c55b9c0a4a7381..77493a774f4666587d4cfb25f69969e3691f661f 100644
--- a/ProcessLib/TES/TESProcess.cpp
+++ b/ProcessLib/TES/TESProcess.cpp
@@ -56,18 +56,17 @@ namespace TES
 TESProcess::TESProcess(
     MeshLib::Mesh& mesh,
     Process::NonlinearSolver& nonlinear_solver,
-    std::unique_ptr<Process::TimeDiscretization>&&
-        time_discretization,
+    std::unique_ptr<Process::TimeDiscretization>&& time_discretization,
+    std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
     std::vector<std::reference_wrapper<ProcessVariable>>&& process_variables,
     SecondaryVariableCollection&& secondary_variables,
     ProcessOutput&& process_output,
     NumLib::NamedFunctionCaller&& named_function_caller,
     const BaseLib::ConfigTree& config)
-    : Process(
-          mesh, nonlinear_solver, std::move(time_discretization),
-          std::move(process_variables), std::move(secondary_variables),
-          std::move(process_output),
-          std::move(named_function_caller))
+    : Process(mesh, nonlinear_solver, std::move(time_discretization),
+              std::move(convergence_criterion), std::move(process_variables),
+              std::move(secondary_variables), std::move(process_output),
+              std::move(named_function_caller))
 {
     DBUG("Create TESProcess.");
 
diff --git a/ProcessLib/TES/TESProcess.h b/ProcessLib/TES/TESProcess.h
index c7d2be021eda4f46083cab78da9d2e591cade388..33a0f883b181f67dd5915c3b9732a84cff1002c0 100644
--- a/ProcessLib/TES/TESProcess.h
+++ b/ProcessLib/TES/TESProcess.h
@@ -35,6 +35,7 @@ public:
         MeshLib::Mesh& mesh,
         Process::NonlinearSolver& nonlinear_solver,
         std::unique_ptr<Process::TimeDiscretization>&& time_discretization,
+        std::unique_ptr<NumLib::ConvergenceCriterion>&& convergence_criterion,
         std::vector<std::reference_wrapper<ProcessVariable>>&&
             process_variables,
         SecondaryVariableCollection&& secondary_variables,