Repository: OPM/opm-simulators
Pull request #6009: Time step rejection if tolerance test fails
Author: login: erikhide
Labels: name: manual:new-feature
description: This is a new feature and should be described in the manual
Created: 2025-02-18T16:32:45Z | Merged: 2025-05-14T12:06:05Z

I've implemented rejection of a completed time step if the relative change is larger than the time step control tolerance (only for the general 3rd order controller). The code seems to work as it should, but I might have missed something, so please let me know if you find anything wrong.

An earlier version of this can be found in #5317, but the current one is up to date with the current master.

For manual:
If the relative change in the solution variables from one time step to the next becomes to large, it might be best to discard the computations even though the time step completed without numerical errors. The time step size will then be adjusted down before retrying the same time step. This option is only available when using the `general3rdorder` option for `time-step-control`.


Diff:
diff --git a/opm/simulators/flow/NonlinearSolver.hpp b/opm/simulators/flow/NonlinearSolver.hpp
index dae4aa1a8df..4ac3f3b7c57 100644
--- a/opm/simulators/flow/NonlinearSolver.hpp
+++ b/opm/simulators/flow/NonlinearSolver.hpp
@@ -35,6 +35,7 @@
 
 #include <opm/simulators/timestepping/SimulatorReport.hpp>
 #include <opm/simulators/timestepping/SimulatorTimerInterface.hpp>
+#include <opm/simulators/timestepping/TimeStepControl.hpp>
 
 #include <memory>
 
@@ -128,7 +129,7 @@ struct NonlinearSolverParameters
         }
 
 
-        SimulatorReportSingle step(const SimulatorTimerInterface& timer)
+        SimulatorReportSingle step(const SimulatorTimerInterface& timer, const TimeStepControlInterface *timeStepControl)
         {
             SimulatorReportSingle report;
             report.global_time = timer.simulationTimeElapsed();
@@ -174,6 +175,14 @@ struct NonlinearSolverParameters
                 std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
                 OPM_THROW_NOLOG(TooManyIterations, msg);
             }
+            auto relativeChange = model_->relativeChange();
+            if (timeStepControl && !timeStepControl->timeStepAccepted(relativeChange)) {
+                report.converged = false;
+                failureReport_ = report;
+
+                std::string msg = "Relative change in solution for time step was " + std::to_string(relativeChange) + ", which is larger than the tolerance accepted by the timestepping algorithm.";
+                OPM_THROW_NOLOG(TimeSteppingBreakdown, msg);
+            }
 
             // Do model-specific post-step actions.
             report += model_->afterStep(timer);
diff --git a/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp b/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
index 2ccbfaaa240..78824bcce4b 100644
--- a/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
+++ b/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
@@ -468,7 +468,7 @@ class SimulatorFullyImplicitBlackoil : private SerializableSim
             simulator_.problem().setSimulationReport(report_);
         } else {
             // solve for complete report step
-            auto stepReport = solver_->step(timer);
+            auto stepReport = solver_->step(timer, nullptr);
             report_ += stepReport;
             if (terminalOutput_) {
                 std::ostringstream ss;
diff --git a/opm/simulators/timestepping/AdaptiveTimeStepping.cpp b/opm/simulators/timestepping/AdaptiveTimeStepping.cpp
index 12f9e98ab81..da9fdbb881e 100644
--- a/opm/simulators/timestepping/AdaptiveTimeStepping.cpp
+++ b/opm/simulators/timestepping/AdaptiveTimeStepping.cpp
@@ -139,6 +139,9 @@ void registerAdaptiveParameters()
     Parameters::Register<Parameters::TimeStepControlSafetyFactor>
         ("Value to be multiplied with the time step control tolerance to ensure that the target "
          "relative change is lower than the tolerance");
+    Parameters::Register<Parameters::TimeStepControlRejectCompletedStep>
+        ("(Only applicable for the general 3rd order controller.) Include rejection of completed "
+         "time steps if the relative change is larger than the time step control tolerance");
 }
 
 std::tuple<TimeStepControlType, std::unique_ptr<TimeStepControlInterface>, bool>
@@ -218,10 +221,12 @@ createController(const UnitSystem& unitSystem)
         {"general3rdorder",
          [tol]() {
              const double safetyFactor = Parameters::Get<Parameters::TimeStepControlSafetyFactor>(); // 0.8
+             const bool rejectCompletedStep = Parameters::Get<Parameters::TimeStepControlRejectCompletedStep>(); // false
              return RetVal{
                  TimeStepControlType::General3rdOrder,
                  std::make_unique<General3rdOrderController>(tol,
-                                                             safetyFactor),
+                                                             safetyFactor,
+                                                             rejectCompletedStep),
                  false
              };
         }},
diff --git a/opm/simulators/timestepping/AdaptiveTimeStepping.hpp b/opm/simulators/timestepping/AdaptiveTimeStepping.hpp
index c2c215221b5..4754c4d99cd 100644
--- a/opm/simulators/timestepping/AdaptiveTimeStepping.hpp
+++ b/opm/simulators/timestepping/AdaptiveTimeStepping.hpp
@@ -48,6 +48,7 @@ struct TimeStepControlFileName { static constexpr auto value = "timesteps"; };
 struct MinTimeStepBeforeShuttingProblematicWellsInDays { static constexpr double value = 0.01; };
 struct MinTimeStepBasedOnNewtonIterations { static constexpr double value = 0.0; };
 struct TimeStepControlSafetyFactor { static constexpr double value = 0.8; };
+struct TimeStepControlRejectCompletedStep { static constexpr bool value = false; };
 
 } // namespace Opm::Parameters
 
@@ -203,6 +204,7 @@ class AdaptiveTimeStepping
 #endif
     void setSuggestedNextStep(const double x);
     double suggestedNextStep() const;
+    const TimeStepControlInterface& timeStepControl() const;
 
     template <class Solver>
     SimulatorReport step(const SimulatorTimer& simulator_timer,
diff --git a/opm/simulators/timestepping/AdaptiveTimeStepping_impl.hpp b/opm/simulators/timestepping/AdaptiveTimeStepping_impl.hpp
index 75854b89bb1..39c1eb6e870 100644
--- a/opm/simulators/timestepping/AdaptiveTimeStepping_impl.hpp
+++ b/opm/simulators/timestepping/AdaptiveTimeStepping_impl.hpp
@@ -327,6 +327,14 @@ suggestedNextStep() const
     return this->suggested_next_timestep_;
 }
 
+template<class TypeTag>
+const TimeStepControlInterface&
+AdaptiveTimeStepping<TypeTag>::
+timeStepControl() const
+{
+    return *this->time_step_control_;
+}
+
 
 template<class TypeTag>
 void
@@ -813,7 +821,7 @@ run()
             report.success.converged = this->substep_timer_.done();
             this->substep_timer_.setLastStepFailed(false);
         }
-        else { // in case of no convergence
+        else { // in case of no convergence or time step tolerance test failure
             this->substep_timer_.setLastStepFailed(true);
             checkTimeStepMaxRestartLimit_(restarts);
 
@@ -1138,7 +1146,7 @@ runSubStep_()
     };
 
     try {
-        substep_report = solver_().step(this->substep_timer_);
+        substep_report = solver_().step(this->substep_timer_, &this->adaptive_time_stepping_.timeStepControl());
         if (solverVerbose_()) {
             // report number of linear iterations
             OpmLog::debug("Overall linear iterations used: "
@@ -1148,6 +1156,9 @@ runSubStep_()
     catch (const TooManyIterations& e) {
         handleFailure("Solver convergence failure - Iteration limit reached", e);
     }
+    catch (const TimeSteppingBreakdown& e) {
+        handleFailure(e.what(), e);
+    }
     catch (const ConvergenceMonitorFailure& e) {
         handleFailure("Convergence monitor failure", e, /*log_exception=*/false);
     }
diff --git a/opm/simulators/timestepping/TimeStepControl.cpp b/opm/simulators/timestepping/TimeStepControl.cpp
index 3d1513a3cf2..fbe1fc2a65c 100644
--- a/opm/simulators/timestepping/TimeStepControl.cpp
+++ b/opm/simulators/timestepping/TimeStepControl.cpp
@@ -291,9 +291,11 @@ namespace Opm
 
     General3rdOrderController::General3rdOrderController( const double tolerance,
                                                           const double safetyFactor,
+                                                          const bool rejectCompletedStep,
                                                           const bool verbose)
         : tolerance_( tolerance )
         , safetyFactor_( safetyFactor )
+        , rejectCompletedStep_( rejectCompletedStep )
         , errors_( 3, tolerance_ )
         , timeSteps_ ( 3, 1.0 )
         , verbose_( verbose )
@@ -361,10 +363,19 @@ namespace Opm
         }
     }
 
+    bool General3rdOrderController::
+    timeStepAccepted(const double error) const
+    {
+        if (rejectCompletedStep_ && error > tolerance_)
+            return false;
+        return true;
+    }
+
     bool General3rdOrderController::operator==(const General3rdOrderController& ctrl) const
     {
         return this->tolerance_ == ctrl.tolerance_ &&
                this->safetyFactor_ == ctrl.safetyFactor_ &&
+               this->rejectCompletedStep_ == ctrl.rejectCompletedStep_ &&
                this->errors_ == ctrl.errors_ &&
                this->timeSteps_ == ctrl.timeSteps_ &&
                this->verbose_ == ctrl.verbose_;
diff --git a/opm/simulators/timestepping/TimeStepControl.hpp b/opm/simulators/timestepping/TimeStepControl.hpp
index 2c59865c65d..370ee179cb2 100644
--- a/opm/simulators/timestepping/TimeStepControl.hpp
+++ b/opm/simulators/timestepping/TimeStepControl.hpp
@@ -65,6 +65,8 @@ namespace Opm
                                    const int iterations,
                                    const RelativeChangeInterface& /* relativeChange */,
                                    const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
+        
+        bool timeStepAccepted(const double /* error */) const override { return true; }
 
         template<class Serializer>
         void serializeOp(Serializer& serializer)
@@ -117,6 +119,8 @@ namespace Opm
                                    const RelativeChangeInterface& relativeChange,
                                    const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
 
+        bool timeStepAccepted(const double /* error */) const override { return true; }
+
         template<class Serializer>
         void serializeOp(Serializer& serializer)
         {
@@ -166,6 +170,8 @@ namespace Opm
                                    const RelativeChangeInterface& relativeChange,
                                    const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
 
+        bool timeStepAccepted(const double /* error */) const override { return true; }
+
         template<class Serializer>
         void serializeOp(Serializer& serializer)
         {
@@ -197,6 +203,7 @@ namespace Opm
 
         General3rdOrderController( const double tolerance = 1e-3,
                                    const double safetyFactor = 0.8,
+                                   const bool rejectCompletedStep = false,
                                    const bool verbose = false );
 
         static General3rdOrderController serializationTestObject();
@@ -206,11 +213,14 @@ namespace Opm
                                    const RelativeChangeInterface& relativeChange,
                                    const AdaptiveSimulatorTimer& substepTimer) const override;
 
+        bool timeStepAccepted(const double error) const override;
+
         template<class Serializer>
         void serializeOp(Serializer& serializer)
         {
             serializer(tolerance_);
             serializer(safetyFactor_);
+            serializer(rejectCompletedStep_);
             serializer(errors_);
             serializer(timeSteps_);
             serializer(verbose_);
@@ -222,6 +232,7 @@ namespace Opm
     protected:
         const double tolerance_ = 1e-3;
         const double safetyFactor_ = 0.8;
+        const bool rejectCompletedStep_ = false;
         mutable std::vector<double> errors_{};
         mutable std::vector<double> timeSteps_{};
         mutable int counterSinceFailure_ = 0;
@@ -255,6 +266,8 @@ namespace Opm
                                    const RelativeChangeInterface& /*relativeChange */,
                                    const AdaptiveSimulatorTimer& substepTimer) const override;
 
+        bool timeStepAccepted(const double /* error */) const override { return true; }
+
         template<class Serializer>
         void serializeOp(Serializer& serializer)
         {
diff --git a/opm/simulators/timestepping/TimeStepControlInterface.hpp b/opm/simulators/timestepping/TimeStepControlInterface.hpp
index 3a04e22ace7..240eac2baa0 100644
--- a/opm/simulators/timestepping/TimeStepControlInterface.hpp
+++ b/opm/simulators/timestepping/TimeStepControlInterface.hpp
@@ -60,6 +60,8 @@ namespace Opm
         /// \return suggested time step size for the next step
         virtual double computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& relativeChange , const AdaptiveSimulatorTimer& substepTimer) const = 0;
 
+        virtual bool timeStepAccepted(const double error) const = 0;
+
         /// virtual destructor (empty)
         virtual ~TimeStepControlInterface () {}
     };


Reviews:
user: login: atgeirr
body: I think this is mostly fine, sorry for the long wait for a review.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-08T14:48:55Z
user: login: erikhide
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T11:04:43Z
user: login: atgeirr
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-09T11:23:29Z
user: login: erikhide
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T11:42:33Z
user: login: erikhide
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T11:54:37Z
user: login: erikhide
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T11:55:06Z
user: login: atgeirr
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-13T14:19:34Z
user: login: bska
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-13T14:25:05Z
user: login: akva2
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-13T14:30:09Z
user: login: erikhide
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T18:52:05Z
user: login: akva2
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T06:24:48Z
user: login: atgeirr
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T08:05:10Z
user: login: erikhide
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T09:01:21Z
user: login: bska
body: I defer full review to those who have already started reviewing the PR, but I noticed that the patch currently introduces some new warnings.  Please try to fix those.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T09:52:30Z
user: login: erikhide
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T10:48:52Z
user: login: bska
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-14T11:04:50Z

Review comments:
diff_hunk: @@ -1139,6 +1147,9 @@ runSubStep_()
     catch (const TooManyIterations& e) {
         handleFailure("Solver convergence failure - Iteration limit reached", e);
     }
+    catch (const TimeSteppingBreakdown& e) {
+        handleFailure("Time step was too large", e);
path: opm/simulators/timestepping/AdaptiveTimeStepping_impl.hpp
user: login: atgeirr
body: This message is misleading, see the other comment. Maybe pass e.what() as the first string, if the message is modified as suggested above (it will be repeated in the DBG file, but show up once on the terminal).
created_at: 2025-05-08T14:33:21Z
author_association: MEMBER
diff_hunk: @@ -174,6 +175,13 @@ struct NonlinearSolverParameters
                 std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
                 OPM_THROW_NOLOG(TooManyIterations, msg);
             }
+            if (!timeStepControl.timeStepAccepted(model_->relativeChange())) {
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: atgeirr
body: The relativeChange() method still needs to be changed to not add saturations and pressures unscaled... I would really like to get in that, is there a PR for it already?
created_at: 2025-05-08T14:39:58Z
author_association: MEMBER
diff_hunk: @@ -174,6 +175,13 @@ struct NonlinearSolverParameters
                 std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
                 OPM_THROW_NOLOG(TooManyIterations, msg);
             }
+            if (!timeStepControl.timeStepAccepted(model_->relativeChange())) {
+                report.converged = false;
+                failureReport_ = report;
+
+                std::string msg = "Time step was too large. Tolerance test failed.";
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: atgeirr
body: I think this message is misleading, better would be "Relative change in solution for time step was {}, which is larger than the tolerance accepted by the timestepping algorithm." (and then insert the relative change in the output). I.e. it is the change and not the step that is too large.
created_at: 2025-05-08T14:43:56Z
author_association: MEMBER
diff_hunk: @@ -174,6 +175,13 @@ struct NonlinearSolverParameters
                 std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
                 OPM_THROW_NOLOG(TooManyIterations, msg);
             }
+            if (!timeStepControl.timeStepAccepted(model_->relativeChange())) {
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: erikhide
body: Agreed! The PR #6026 aims to fix this. There is one issue I noticed some time after creating this PR: The relative change in saturation (at least for some models) is very high after the initial time step, since the saturation values for some reason jumps quite a lot. This does not seem to happen later in the simulation. One fix is to just use pressure for the first time step, and then both pressure and saturation after that. I've implemented this fix locally. I do not know what to do if we're only using saturation, however. Maybe we should remove that option altogether?
created_at: 2025-05-09T11:04:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -174,6 +175,13 @@ struct NonlinearSolverParameters
                 std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
                 OPM_THROW_NOLOG(TooManyIterations, msg);
             }
+            if (!timeStepControl.timeStepAccepted(model_->relativeChange())) {
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: atgeirr
body: > the saturation values for some reason jumps quite a lot 

Even in average, not just for some cells? Sounds strange, I suggest you investigate that a little to understand why. Does this apply to any public cases?
created_at: 2025-05-09T11:23:29Z
author_association: MEMBER
diff_hunk: @@ -174,6 +175,13 @@ struct NonlinearSolverParameters
                 std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
                 OPM_THROW_NOLOG(TooManyIterations, msg);
             }
+            if (!timeStepControl.timeStepAccepted(model_->relativeChange())) {
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: erikhide
body: More specifically, what seems to happen is that e.g. the oil saturation and water saturation values for one cell "switch places"  with one going from something like 0.95 to 0.02, and the other to the opposite. This has happened for the Norne prediction cases, although I haven't checked all of them.
created_at: 2025-05-09T11:42:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -174,6 +175,13 @@ struct NonlinearSolverParameters
                 std::string msg = "Solver convergence failure - Failed to complete a time step within " + std::to_string(maxIter()) + " iterations.";
                 OPM_THROW_NOLOG(TooManyIterations, msg);
             }
+            if (!timeStepControl.timeStepAccepted(model_->relativeChange())) {
+                report.converged = false;
+                failureReport_ = report;
+
+                std::string msg = "Time step was too large. Tolerance test failed.";
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: erikhide
body: I agree! The proposed text is much better. I've updated the error message now.
created_at: 2025-05-09T11:54:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1139,6 +1147,9 @@ runSubStep_()
     catch (const TooManyIterations& e) {
         handleFailure("Solver convergence failure - Iteration limit reached", e);
     }
+    catch (const TimeSteppingBreakdown& e) {
+        handleFailure("Time step was too large", e);
path: opm/simulators/timestepping/AdaptiveTimeStepping_impl.hpp
user: login: erikhide
body: Done!
created_at: 2025-05-09T11:55:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -468,7 +468,7 @@ class SimulatorFullyImplicitBlackoil : private SerializableSim
             simulator_.problem().setSimulationReport(report_);
         } else {
             // solve for complete report step
-            auto stepReport = solver_->step(timer);
+            auto stepReport = solver_->step(timer, adaptiveTimeStepping_->timeStepControl());
path: opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
user: login: atgeirr
body: I believe this line is the problem. It assumes there always is a non-null adaptiveTimeStepping_ member, which is false: if you run with `--enable-adaptive-time-stepping=false` it is indeed a null pointer. So a slightly different approach is needed.
created_at: 2025-05-13T14:19:34Z
author_association: MEMBER
diff_hunk: @@ -468,7 +468,7 @@ class SimulatorFullyImplicitBlackoil : private SerializableSim
             simulator_.problem().setSimulationReport(report_);
         } else {
             // solve for complete report step
-            auto stepReport = solver_->step(timer);
+            auto stepReport = solver_->step(timer, adaptiveTimeStepping_->timeStepControl());
path: opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
user: login: bska
body: >  So a slightly different approach is needed.

We should obviously always check for null, but there's likely to be a deeper problem here too.  If it were "only" `--enable-adaptive-time-stepping=false` that got us into this situation, then the problem would not consistently show up for restarted runs, and mostly in parallel.
created_at: 2025-05-13T14:25:05Z
author_association: MEMBER
diff_hunk: @@ -468,7 +468,7 @@ class SimulatorFullyImplicitBlackoil : private SerializableSim
             simulator_.problem().setSimulationReport(report_);
         } else {
             // solve for complete report step
-            auto stepReport = solver_->step(timer);
+            auto stepReport = solver_->step(timer, adaptiveTimeStepping_->timeStepControl());
path: opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
user: login: akva2
body: the crash set is exactly those tests that use --enable-adaptive-time-stepping=false. there is no need for a null check, we in fact know it will be null as we are in the else branch of the if (adaptiveTimeSteppingEnabled). it's simply a logic error in the code added by this PR.
created_at: 2025-05-13T14:30:09Z
author_association: MEMBER
diff_hunk: @@ -468,7 +468,7 @@ class SimulatorFullyImplicitBlackoil : private SerializableSim
             simulator_.problem().setSimulationReport(report_);
         } else {
             // solve for complete report step
-            auto stepReport = solver_->step(timer);
+            auto stepReport = solver_->step(timer, adaptiveTimeStepping_->timeStepControl());
path: opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
user: login: erikhide
body: Thanks for finding the bug! I've fixed the issue now. Please let me now if you'd like me to do any adjustments.
created_at: 2025-05-13T18:52:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -122,14 +124,15 @@ struct NonlinearSolverParameters
             , nonlinearIterationsLast_(0)
             , linearIterationsLast_(0)
             , wellIterationsLast_(0)
+            , enableAdaptiveTimeStepping_(true)
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: akva2
body: this feels like a layer violation. it would, imo, be better to use the old approach, but pass the TimeStepControlInterface by ptr so you can pass nullptr from the non-adaptive case (and check for null on the inside).
created_at: 2025-05-14T06:24:48Z
author_association: MEMBER
diff_hunk: @@ -122,14 +124,15 @@ struct NonlinearSolverParameters
             , nonlinearIterationsLast_(0)
             , linearIterationsLast_(0)
             , wellIterationsLast_(0)
+            , enableAdaptiveTimeStepping_(true)
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: atgeirr
body: I agree.
created_at: 2025-05-14T08:05:10Z
author_association: MEMBER
diff_hunk: @@ -122,14 +124,15 @@ struct NonlinearSolverParameters
             , nonlinearIterationsLast_(0)
             , linearIterationsLast_(0)
             , wellIterationsLast_(0)
+            , enableAdaptiveTimeStepping_(true)
path: opm/simulators/flow/NonlinearSolver.hpp
user: login: erikhide
body: I too agree! Your suggestion was much better. I've fixed it now.
created_at: 2025-05-14T09:01:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -65,6 +65,8 @@ namespace Opm
                                    const int iterations,
                                    const RelativeChangeInterface& /* relativeChange */,
                                    const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
+        
+        bool timeStepAccepted(const double error) const override { return true; }
path: opm/simulators/timestepping/TimeStepControl.hpp
user: login: bska
body: Please tag the `error` parameter as `[[maybe_unused]]`&ndash;or remove the name altogether&ndash;so as to ensure we do not get [additional warnings](https://ci.opm-project.org/job/opm-simulators-PR-builder/8108/gcc/) when this PR gets merged.
created_at: 2025-05-14T09:48:08Z
author_association: MEMBER
diff_hunk: @@ -117,6 +119,8 @@ namespace Opm
                                    const RelativeChangeInterface& relativeChange,
                                    const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
 
+        bool timeStepAccepted(const double error) const override { return true; }
path: opm/simulators/timestepping/TimeStepControl.hpp
user: login: bska
body: Please tag the `error` parameter as `[[maybe_unused]]`&ndash;or remove the name altogether&ndash;so as to ensure we do not get [additional warnings](https://ci.opm-project.org/job/opm-simulators-PR-builder/8108/gcc/) when this PR gets merged.
created_at: 2025-05-14T09:48:14Z
author_association: MEMBER
diff_hunk: @@ -166,6 +170,8 @@ namespace Opm
                                    const RelativeChangeInterface& relativeChange,
                                    const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
 
+        bool timeStepAccepted(const double error) const override { return true; }
path: opm/simulators/timestepping/TimeStepControl.hpp
user: login: bska
body: Please tag the `error` parameter as `[[maybe_unused]]`&ndash;or remove the name altogether&ndash;so as to ensure we do not get [additional warnings](https://ci.opm-project.org/job/opm-simulators-PR-builder/8108/gcc/) when this PR gets merged.
created_at: 2025-05-14T09:48:20Z
author_association: MEMBER
diff_hunk: @@ -255,6 +266,8 @@ namespace Opm
                                    const RelativeChangeInterface& /*relativeChange */,
                                    const AdaptiveSimulatorTimer& substepTimer) const override;
 
+        bool timeStepAccepted(const double error) const override { return true; }
path: opm/simulators/timestepping/TimeStepControl.hpp
user: login: bska
body: Please tag the `error` parameter as `[[maybe_unused]]`&ndash;or remove the name altogether&ndash;so as to ensure we do not get [additional warnings](https://ci.opm-project.org/job/opm-simulators-PR-builder/8108/gcc/) when this PR gets merged.
created_at: 2025-05-14T09:48:43Z
author_association: MEMBER
diff_hunk: @@ -255,6 +266,8 @@ namespace Opm
                                    const RelativeChangeInterface& /*relativeChange */,
                                    const AdaptiveSimulatorTimer& substepTimer) const override;
 
+        bool timeStepAccepted(const double error) const override { return true; }
path: opm/simulators/timestepping/TimeStepControl.hpp
user: login: erikhide
body: Fixed all of the above.
created_at: 2025-05-14T10:48:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -255,6 +266,8 @@ namespace Opm
                                    const RelativeChangeInterface& /*relativeChange */,
                                    const AdaptiveSimulatorTimer& substepTimer) const override;
 
+        bool timeStepAccepted(const double error) const override { return true; }
path: opm/simulators/timestepping/TimeStepControl.hpp
user: login: bska
body: > Fixed all of the above.

Much appreciated!
created_at: 2025-05-14T11:04:49Z
author_association: MEMBER

PR comments:
user: login: bska
created_at: 2025-02-20T15:59:10Z
body: jenkins build this please
author_association: MEMBER
user: login: atgeirr
created_at: 2025-05-09T12:12:50Z
body: jenkins build this please
author_association: MEMBER
user: login: atgeirr
created_at: 2025-05-09T15:10:36Z
body: I do not see an obvious reason for the segfaults in the tests. In fact, I expected no test failures at all! I think the best is to investigate this in a debugger to see why it faults. Give me a hint if you need help.
author_association: MEMBER
user: login: atgeirr
created_at: 2025-05-13T11:38:11Z
body: jenkins build this please
author_association: MEMBER
user: login: atgeirr
created_at: 2025-05-14T09:24:34Z
body: jenkins build this please
author_association: MEMBER
user: login: atgeirr
created_at: 2025-05-14T11:03:04Z
body: jenkins build this please
author_association: MEMBER
user: login: akva2
created_at: 2025-05-14T11:19:00Z
body: this contains a merge commit. please rebase on master.
author_association: MEMBER
user: login: erikhide
created_at: 2025-05-14T11:25:56Z
body: > please rebase on master.

Done!
author_association: CONTRIBUTOR
user: login: akva2
created_at: 2025-05-14T11:30:57Z
body: jenkins build this please
author_association: MEMBER
user: login: atgeirr
created_at: 2025-05-14T12:06:01Z
body: Thanks, merging!

Please edit the PR description to add a few sentences of description for the manual.
author_association: MEMBER