20#ifndef OPM_ADAPTIVE_TIME_STEPPING_IMPL_HPP
21#define OPM_ADAPTIVE_TIME_STEPPING_IMPL_HPP
24#ifndef OPM_ADAPTIVE_TIME_STEPPING_HPP
30#include <dune/common/timer.hh>
31#include <dune/istl/istlexception.hh>
33#include <opm/common/Exceptions.hpp>
34#include <opm/common/ErrorMacros.hpp>
35#include <opm/common/OpmLog/OpmLog.hpp>
36#include <opm/common/TimingMacros.hpp>
38#include <opm/grid/utility/StopWatch.hpp>
40#include <opm/input/eclipse/Schedule/Tuning.hpp>
42#include <opm/input/eclipse/Units/Units.hpp>
43#include <opm/input/eclipse/Units/UnitSystem.hpp>
55#include <boost/date_time/posix_time/posix_time.hpp>
56#include <fmt/format.h>
57#include <fmt/ranges.h>
65template<
class TypeTag>
69 const double max_next_tstep,
70 const bool terminal_output
72 : time_step_control_{}
73 , restart_factor_{Parameters::
Get<Parameters::SolverRestartFactor<Scalar>>()}
74 , growth_factor_{Parameters::
Get<Parameters::SolverGrowthFactor<Scalar>>()}
75 , max_growth_{Parameters::
Get<Parameters::SolverMaxGrowth<Scalar>>()}
77 Parameters::
Get<Parameters::SolverMaxTimeStepInDays<Scalar>>() * 24 * 60 * 60}
79 unit_system.to_si(UnitSystem::measure::time,
80 Parameters::
Get<Parameters::SolverMinTimeStep<Scalar>>())}
81 , ignore_convergence_failure_{
82 Parameters::
Get<Parameters::SolverContinueOnConvergenceFailure>()}
83 , solver_restart_max_{Parameters::
Get<Parameters::SolverMaxRestarts>()}
84 , solver_verbose_{Parameters::
Get<Parameters::SolverVerbosity>() > 0 && terminal_output}
85 , timestep_verbose_{Parameters::
Get<Parameters::TimeStepVerbosity>() > 0 && terminal_output}
86 , suggested_next_timestep_{
87 (max_next_tstep <= 0 ? Parameters::
Get<Parameters::InitialTimeStepInDays>()
88 : max_next_tstep) * 24 * 60 * 60}
89 , full_timestep_initially_{Parameters::
Get<Parameters::FullTimeStepInitially>()}
90 , timestep_after_event_{
91 Parameters::
Get<Parameters::TimeStepAfterEventInDays<Scalar>>() * 24 * 60 * 60}
92 , use_newton_iteration_{false}
93 , min_time_step_before_shutting_problematic_wells_{
94 Parameters::
Get<Parameters::MinTimeStepBeforeShuttingProblematicWellsInDays>() * unit::day}
106template<
class TypeTag>
109 const Tuning& tuning,
110 const UnitSystem& unit_system,
112 const bool terminal_output
114 : time_step_control_{}
115 , restart_factor_{tuning.TSFCNV}
116 , growth_factor_{tuning.TFDIFF}
117 , max_growth_{tuning.TSFMAX}
118 , max_time_step_{tuning.TSMAXZ}
119 , min_time_step_{tuning.TSMINZ}
120 , ignore_convergence_failure_{true}
121 , solver_restart_max_{Parameters::
Get<Parameters::SolverMaxRestarts>()}
122 , solver_verbose_{Parameters::
Get<Parameters::SolverVerbosity>() > 0 && terminal_output}
123 , timestep_verbose_{Parameters::
Get<Parameters::TimeStepVerbosity>() > 0 && terminal_output}
124 , suggested_next_timestep_{
125 max_next_tstep <= 0 ? Parameters::
Get<Parameters::InitialTimeStepInDays>() * 24 * 60 * 60
127 , full_timestep_initially_{Parameters::
Get<Parameters::FullTimeStepInitially>()}
128 , timestep_after_event_{tuning.TMAXWC}
129 , use_newton_iteration_{false}
130 , min_time_step_before_shutting_problematic_wells_{
131 Parameters::
Get<Parameters::MinTimeStepBeforeShuttingProblematicWellsInDays>() * unit::day}
137template<
class TypeTag>
149 switch (this->time_step_control_type_) {
151 result = castAndComp<HardcodedTimeStepControl>(rhs);
154 result = castAndComp<PIDAndIterationCountTimeStepControl>(rhs);
157 result = castAndComp<SimpleIterationCountTimeStepControl>(rhs);
160 result = castAndComp<PIDTimeStepControl>(rhs);
163 result = castAndComp<General3rdOrderController>(rhs);
179 this->min_time_step_before_shutting_problematic_wells_ ==
183template<
class TypeTag>
188 registerEclTimeSteppingParameters<Scalar>();
193template<
class TypeTag>
194template <
class Solver>
202 SubStepper<Solver> sub_stepper{
203 *
this, simulator_timer, solver, is_event, tuning_updater,
205 return sub_stepper.run();
208template<
class TypeTag>
209template<
class Serializer>
214 serializer(this->time_step_control_type_);
215 switch (this->time_step_control_type_) {
217 allocAndSerialize<HardcodedTimeStepControl>(serializer);
220 allocAndSerialize<PIDAndIterationCountTimeStepControl>(serializer);
223 allocAndSerialize<SimpleIterationCountTimeStepControl>(serializer);
226 allocAndSerialize<PIDTimeStepControl>(serializer);
229 allocAndSerialize<General3rdOrderController>(serializer);
232 serializer(this->restart_factor_);
233 serializer(this->growth_factor_);
234 serializer(this->max_growth_);
235 serializer(this->max_time_step_);
236 serializer(this->min_time_step_);
237 serializer(this->ignore_convergence_failure_);
238 serializer(this->solver_restart_max_);
239 serializer(this->solver_verbose_);
240 serializer(this->timestep_verbose_);
241 serializer(this->suggested_next_timestep_);
242 serializer(this->full_timestep_initially_);
243 serializer(this->timestep_after_event_);
244 serializer(this->use_newton_iteration_);
245 serializer(this->min_time_step_before_shutting_problematic_wells_);
248template<
class TypeTag>
256template<
class TypeTag>
261 return serializationTestObject_<HardcodedTimeStepControl>();
264template<
class TypeTag>
269 return serializationTestObject_<PIDTimeStepControl>();
272template<
class TypeTag>
277 return serializationTestObject_<PIDAndIterationCountTimeStepControl>();
280template<
class TypeTag>
285 return serializationTestObject_<SimpleIterationCountTimeStepControl>();
288template<
class TypeTag>
293 return serializationTestObject_<General3rdOrderController>();
297template<
class TypeTag>
302 this->suggested_next_timestep_ = x;
305template<
class TypeTag>
310 return this->suggested_next_timestep_;
313template<
class TypeTag>
318 return *this->time_step_control_;
322template<
class TypeTag>
329 if (max_next_tstep > 0) {
330 this->suggested_next_timestep_ = max_next_tstep;
334template<
class TypeTag>
337updateTUNING(
double max_next_tstep,
const Tuning& tuning)
339 this->restart_factor_ = tuning.TSFCNV;
340 this->growth_factor_ = tuning.TFDIFF;
341 this->max_growth_ = tuning.TSFMAX;
342 this->max_time_step_ = tuning.TSMAXZ;
343 updateNEXTSTEP(max_next_tstep);
344 this->timestep_after_event_ = tuning.TMAXWC;
351template<
class TypeTag>
352template<
class T,
class Serializer>
357 if (!serializer.isSerializing()) {
358 this->time_step_control_ = std::make_unique<T>();
360 serializer(*
static_cast<T*
>(this->time_step_control_.get()));
363template<
class TypeTag>
366AdaptiveTimeStepping<TypeTag>::
367castAndComp(
const AdaptiveTimeStepping<TypeTag>& Rhs)
const
369 const T* lhs =
static_cast<const T*
>(this->time_step_control_.get());
370 const T* rhs =
static_cast<const T*
>(Rhs.time_step_control_.get());
374template<
class TypeTag>
376AdaptiveTimeStepping<TypeTag>::
377maybeModifySuggestedTimeStepAtBeginningOfReportStep_(
const double original_time_step,
381 if (this->suggested_next_timestep_ < 0) {
382 this->suggested_next_timestep_ = this->restart_factor_ * original_time_step;
385 if (this->full_timestep_initially_) {
386 this->suggested_next_timestep_ = original_time_step;
390 if (is_event && this->timestep_after_event_ > 0) {
391 this->suggested_next_timestep_ = this->timestep_after_event_;
395template<
class TypeTag>
396template<
class Controller>
397AdaptiveTimeStepping<TypeTag>
398AdaptiveTimeStepping<TypeTag>::
399serializationTestObject_()
401 AdaptiveTimeStepping<TypeTag> result;
403 result.restart_factor_ = 1.0;
404 result.growth_factor_ = 2.0;
405 result.max_growth_ = 3.0;
406 result.max_time_step_ = 4.0;
407 result.min_time_step_ = 5.0;
408 result.ignore_convergence_failure_ =
true;
409 result.solver_restart_max_ = 6;
410 result.solver_verbose_ =
true;
411 result.timestep_verbose_ =
true;
412 result.suggested_next_timestep_ = 7.0;
413 result.full_timestep_initially_ =
true;
414 result.use_newton_iteration_ =
true;
415 result.min_time_step_before_shutting_problematic_wells_ = 9.0;
416 result.time_step_control_type_ = Controller::Type;
417 result.time_step_control_ =
418 std::make_unique<Controller>(Controller::serializationTestObject());
427template<
class TypeTag>
429init_(
const UnitSystem& unitSystem)
431 std::tie(time_step_control_type_,
435 if (this->growth_factor_ < 1.0) {
436 OPM_THROW(std::runtime_error,
437 "Growth factor cannot be less than 1.");
447template<
class TypeTag>
448template<
class Solver>
454 const TuningUpdateCallback& tuning_updater)
455 : adaptive_time_stepping_{adaptive_time_stepping}
456 , simulator_timer_{simulator_timer}
458 , is_event_{is_event}
459 , tuning_updater_{tuning_updater}
463template<
class TypeTag>
464template<
class Solver>
465AdaptiveTimeStepping<TypeTag>&
466AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
467getAdaptiveTimerStepper()
469 return adaptive_time_stepping_;
472template<
class TypeTag>
473template<
class Solver>
475AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
478#ifdef RESERVOIR_COUPLING_ENABLED
479 if (isReservoirCouplingSlave_() && reservoirCouplingSlave_().activated()) {
480 return runStepReservoirCouplingSlave_();
482 else if (isReservoirCouplingMaster_() && reservoirCouplingMaster_().activated()) {
483 return runStepReservoirCouplingMaster_();
486 return runStepOriginal_();
489 return runStepOriginal_();
497#ifdef RESERVOIR_COUPLING_ENABLED
498template<
class TypeTag>
499template<
class Solver>
501AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
502isReservoirCouplingMaster_()
const
504 return this->solver_.model().simulator().reservoirCouplingMaster() !=
nullptr;
507template<
class TypeTag>
508template<
class Solver>
510AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
511isReservoirCouplingSlave_()
const
513 return this->solver_.model().simulator().reservoirCouplingSlave() !=
nullptr;
517template<
class TypeTag>
518template<
class Solver>
520AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
521maybeModifySuggestedTimeStepAtBeginningOfReportStep_(
const double original_time_step)
523 this->adaptive_time_stepping_.maybeModifySuggestedTimeStepAtBeginningOfReportStep_(
524 original_time_step, this->is_event_
531template<
class TypeTag>
532template<
class Solver>
534AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
535maybeUpdateTuning_(
double elapsed,
double substep_length,
int sub_step_number)
const
537 return this->tuning_updater_(elapsed, substep_length, sub_step_number);
540template<
class TypeTag>
541template<
class Solver>
543AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
546 return this->adaptive_time_stepping_.max_time_step_;
549template <
class TypeTag>
550template <
class Solver>
552AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
555 const auto elapsed = this->simulator_timer_.simulationTimeElapsed();
556 const auto original_time_step = this->simulator_timer_.currentStepLength();
557 const auto report_step = this->simulator_timer_.reportStepNum();
558 maybeUpdateTuning_(elapsed, suggestedNextTimestep_(), 0);
559 maybeModifySuggestedTimeStepAtBeginningOfReportStep_(original_time_step);
561 AdaptiveSimulatorTimer substep_timer{
562 this->simulator_timer_.startDateTime(),
565 suggestedNextTimestep_(),
569 SubStepIteration<Solver> substepIteration{*
this, substep_timer, original_time_step,
true};
570 return substepIteration.run();
573template <
class TypeTag>
574template <
class Solver>
576AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
577suggestedNextTimestep_()
const
579 return this->adaptive_time_stepping_.suggestedNextStep();
583#ifdef RESERVOIR_COUPLING_ENABLED
599template <
class TypeTag>
600template <
class Solver>
602AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
603getRcMasterSyncStepLength_(
double prev_step,
605 double step_end_time)
607 const bool sync_at_report_steps = reservoirCouplingMaster_().syncAtReportSteps();
608 double current_step_length;
609 if (sync_at_report_steps) {
610 current_step_length = prev_step;
612 const double remaining = step_end_time - current_time;
613 current_step_length = std::min({suggestedNextTimestep_(), maxTimeStep_(), remaining});
626 current_step_length = reservoirCouplingMaster_().maybeChopSubStep(current_step_length, current_time);
627 auto num_active = reservoirCouplingMaster_().numActivatedSlaves();
628 OpmLog::info(fmt::format(
629 "\nChoosing next sync time{} between master and {} active slave {}: {:.2f} days",
630 sync_at_report_steps ?
" (RSYNC)" :
"",
631 num_active, (num_active == 1 ?
"process" :
"processes"),
632 current_step_length / unit::day
634 return current_step_length;
637template <
class TypeTag>
638template <
class Solver>
639ReservoirCouplingMaster<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
640AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
641reservoirCouplingMaster_()
643 return *(this->solver_.model().simulator().reservoirCouplingMaster());
646template <
class TypeTag>
647template <
class Solver>
648ReservoirCouplingSlave<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
649AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
650reservoirCouplingSlave_()
652 return *(this->solver_.model().simulator().reservoirCouplingSlave());
709template <
class TypeTag>
710template <
class Solver>
712AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
713runStepReservoirCouplingMaster_()
716 const double original_time_step = this->simulator_timer_.currentStepLength();
717 double current_time{this->simulator_timer_.simulationTimeElapsed()};
718 double step_end_time = current_time + original_time_step;
725 auto current_step_length = original_time_step;
726 auto report_step_idx = this->simulator_timer_.currentStepNum();
727 if (report_step_idx == 0 && iteration == 0) {
728 reservoirCouplingMaster_().initTimeStepping();
730 SimulatorReport report;
732 reservoirCouplingMaster_().maybeReceiveActivationHandshakeFromSlaves(current_time);
734 reservoirCouplingMaster_().sendDontTerminateSignalToSlaves();
735 reservoirCouplingMaster_().receiveNextReportDateFromSlaves();
736 const bool start_of_report_step = (iteration == 0);
737 if (start_of_report_step) {
738 reservoirCouplingMaster_().initStartOfReportStep(report_step_idx);
739 maybeUpdateTuning_(current_time, suggestedNextTimestep_(), 0);
740 maybeModifySuggestedTimeStepAtBeginningOfReportStep_(original_time_step);
742 current_step_length = getRcMasterSyncStepLength_(
743 current_step_length, current_time, step_end_time);
744 reservoirCouplingMaster_().sendNextTimeStepToSlaves(current_step_length);
745 AdaptiveSimulatorTimer substep_timer{
746 this->simulator_timer_.startDateTime(),
749 suggestedNextTimestep_(),
750 this->simulator_timer_.reportStepNum(),
754 current_time + current_step_length, step_end_time
759 reservoirCouplingMaster_().setFirstSubstepOfSyncTimestep(
true);
763 reservoirCouplingMaster_().setNeedsSlaveDataReceive(
true);
764 SubStepIteration<Solver> substepIteration{*
this, substep_timer, current_step_length, final_step};
765 const auto sub_steps_report = substepIteration.run();
766 report += sub_steps_report;
767 current_time += current_step_length;
776template <
class TypeTag>
777template <
class Solver>
779AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
780runStepReservoirCouplingSlave_()
783 const double original_time_step = this->simulator_timer_.currentStepLength();
784 double current_time{this->simulator_timer_.simulationTimeElapsed()};
785 double step_end_time = current_time + original_time_step;
786 SimulatorReport report;
787 auto report_step_idx = this->simulator_timer_.currentStepNum();
788 if (report_step_idx == 0 && iteration == 0) {
789 reservoirCouplingSlave_().initTimeStepping();
792 bool start_of_report_step = (iteration == 0);
793 if (reservoirCouplingSlave_().maybeReceiveTerminateSignalFromMaster()) {
797 reservoirCouplingSlave_().sendNextReportDateToMasterProcess();
798 const auto timestep = reservoirCouplingSlave_().receiveNextTimeStepFromMaster();
799 if (start_of_report_step) {
800 maybeUpdateTuning_(current_time, suggestedNextTimestep_(), 0);
801 maybeModifySuggestedTimeStepAtBeginningOfReportStep_(timestep);
803 AdaptiveSimulatorTimer substep_timer{
804 this->simulator_timer_.startDateTime(),
807 suggestedNextTimestep_(),
808 this->simulator_timer_.reportStepNum(),
812 current_time + timestep, step_end_time
817 reservoirCouplingSlave_().setFirstSubstepOfSyncTimestep(
true);
818 SubStepIteration<Solver> substepIteration{*
this, substep_timer, timestep, final_step};
819 const auto sub_steps_report = substepIteration.run();
820 report += sub_steps_report;
821 current_time += timestep;
836template<
class TypeTag>
837template<
class Solver>
838AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
839SubStepIteration(SubStepper<Solver>& substepper,
840 AdaptiveSimulatorTimer& substep_timer,
841 const double original_time_step,
843 : substepper_{substepper}
844 , substep_timer_{substep_timer}
845 , original_time_step_{original_time_step}
846 , final_step_{final_step}
847 , adaptive_time_stepping_{substepper.getAdaptiveTimerStepper()}
851template <
class TypeTag>
852template <
class Solver>
854AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
857 auto& simulator = solver_().model().simulator();
858 auto& problem = simulator.problem();
861 SimulatorReport report;
864 while (!this->substep_timer_.done()) {
868 maybeUpdateTuningAndTimeStep_();
870 const double dt = this->substep_timer_.currentStepLength();
871 if (timeStepVerbose_()) {
875 maybeUpdateLastSubstepOfSyncTimestep_(dt);
876 auto substep_report = runSubStep_();
877 markFirstSubStepAsFinished_();
879 if (substep_report.converged || checkContinueOnUnconvergedSolution_(dt)) {
880 Dune::Timer perfTimer;
883 problem.setSubStepReport(substep_report);
884 auto& full_report = adaptive_time_stepping_.report();
885 full_report += substep_report;
886 problem.setSimulationReport(full_report);
887 problem.endTimeStep();
888 substep_report.pre_post_time += perfTimer.stop();
890 report += substep_report;
892 OPM_TIMEBLOCK(convergenceSucceeded);
893 ++this->substep_timer_;
895 const int iterations = getNumIterations_(substep_report);
896 auto dt_estimate = timeStepControlComputeEstimate_(
897 dt, iterations, this->substep_timer_);
899 assert(dt_estimate > 0);
900 dt_estimate = maybeRestrictTimeStepGrowth_(dt, dt_estimate, restarts);
903 maybeReportSubStep_(substep_report);
904 if (this->final_step_ && this->substep_timer_.done()) {
909 report.success.output_write_time += writeOutput_();
913 setTimeStep_(dt_estimate);
915 report.success.converged = this->substep_timer_.done();
916 this->substep_timer_.setLastStepFailed(
false);
919 OPM_TIMEBLOCK(convergenceFailed);
920 report += substep_report;
921 this->substep_timer_.setLastStepFailed(
true);
922 checkTimeStepMaxRestartLimit_(restarts);
924 double new_time_step = restartFactor_() * dt;
925 if (substep_report.time_step_rejected) {
926 const double tol = Parameters::Get<Parameters::TimeStepControlTolerance>();
927 const double safetyFactor = Parameters::Get<Parameters::TimeStepControlSafetyFactor>();
928 const double temp_time_step = std::sqrt(safetyFactor * tol / solver_().model().relativeChange()) * dt;
929 if (temp_time_step < dt) {
930 new_time_step = temp_time_step;
933 checkTimeStepMinLimit_(new_time_step);
934 bool wells_shut =
false;
935 if (new_time_step > minTimeStepBeforeClosingWells_()) {
936 chopTimeStep_(new_time_step);
938 wells_shut = chopTimeStepOrCloseFailingWells_(new_time_step);
947 problem.setNextTimeStepSize(this->substep_timer_.currentStepLength());
949 updateSuggestedNextStep_();
959template<
class TypeTag>
960template<
class Solver>
962AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
963checkContinueOnUnconvergedSolution_(
double dt)
const
965 const bool continue_on_uncoverged_solution = ignoreConvergenceFailure_() && dt <= minTimeStep_();
966 if (continue_on_uncoverged_solution && solverVerbose_()) {
968 const auto msg = fmt::format(
969 "Solver failed to converge but timestep {} is smaller or equal to {}\n"
970 "which is the minimum threshold given by option --solver-min-time-step\n",
973 OpmLog::problem(msg);
975 return continue_on_uncoverged_solution;
978template<
class TypeTag>
979template<
class Solver>
981AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
982checkTimeStepMaxRestartLimit_(
const int restarts)
const
986 if (restarts >= solverRestartMax_()) {
987 const auto msg = fmt::format(
988 fmt::runtime(
"Solver failed to converge after cutting timestep {} times."), restarts
990 if (solverVerbose_()) {
994 throw TimeSteppingBreakdown{msg};
998template<
class TypeTag>
999template<
class Solver>
1001AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1002checkTimeStepMinLimit_(
const double new_time_step)
const
1004 using Meas = UnitSystem::measure;
1007 if (new_time_step < minTimeStep_()) {
1008 std::string msg =
"Solver failed to converge after cutting timestep to ";
1009 if (Parameters::Get<Parameters::EnableTuning>()) {
1010 const UnitSystem& unit_system = solver_().model().simulator().vanguard().eclState().getDeckUnitSystem();
1012 "{:.3E} {}\nwhich is the minimum threshold given by the TUNING keyword\n",
1013 unit_system.from_si(Meas::time, minTimeStep_()),
1014 unit_system.name(Meas::time)
1019 "{:.3E} DAYS\nwhich is the minimum threshold given by option --solver-min-time-step\n",
1020 minTimeStep_() / 86400.0
1023 if (solverVerbose_()) {
1027 throw TimeSteppingBreakdown{msg};
1031template<
class TypeTag>
1032template<
class Solver>
1034AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1035chopTimeStep_(
const double new_time_step)
1037 setTimeStep_(new_time_step);
1038 if (solverVerbose_()) {
1039 const auto msg = fmt::format(fmt::runtime(
"{}\nTimestep chopped to {} days\n"),
1040 this->cause_of_failure_,
1041 unit::convert::to(this->substep_timer_.currentStepLength(), unit::day));
1042 OpmLog::problem(msg);
1046template<
class TypeTag>
1047template<
class Solver>
1049AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1050chopTimeStepOrCloseFailingWells_(
const double new_time_step)
1052 bool wells_shut =
false;
1059 const bool requireRepeatedFailures =
1060 new_time_step > (minTimeStepBeforeClosingWells_() * restartFactor_() * restartFactor_());
1061 const std::set<std::string> failing_wells =
1064 if (failing_wells.empty()) {
1066 chopTimeStep_(new_time_step);
1069 std::vector<std::string> shut_wells;
1070 for (
const auto& well : failing_wells) {
1071 const bool was_shut =
1072 solver_().model().wellModel().forceShutWellByName(well,
1073 this->substep_timer_.simulationTimeElapsed(),
1076 shut_wells.push_back(well);
1080 if (shut_wells.empty()) {
1081 for (
const auto& well : failing_wells) {
1082 const bool was_shut =
1083 solver_().model().wellModel().forceShutWellByName(well,
1084 this->substep_timer_.simulationTimeElapsed(),
1087 shut_wells.push_back(well);
1092 if (shut_wells.empty()) {
1093 chopTimeStep_(new_time_step);
1096 if (solverVerbose_()) {
1097 const std::string msg =
1098 fmt::format(fmt::runtime(
"\nProblematic well(s) were shut: {}"
1099 "(retrying timestep)\n"),
1100 fmt::join(shut_wells,
" "));
1101 OpmLog::problem(msg);
1108template<
class TypeTag>
1109template<
class Solver>
1110boost::posix_time::ptime
1111AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1112currentDateTime_()
const
1114 return simulatorTimer_().currentDateTime();
1117template<
class TypeTag>
1118template<
class Solver>
1120AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1121getNumIterations_(
const SimulatorReportSingle &substep_report)
const
1123 if (useNewtonIteration_()) {
1124 return substep_report.total_newton_iterations;
1127 return substep_report.total_linear_iterations;
1131template<
class TypeTag>
1132template<
class Solver>
1134AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1135growthFactor_()
const
1137 return this->adaptive_time_stepping_.growth_factor_;
1140template<
class TypeTag>
1141template<
class Solver>
1143AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1144ignoreConvergenceFailure_()
const
1146 return adaptive_time_stepping_.ignore_convergence_failure_;
1149template<
class TypeTag>
1150template<
class Solver>
1152AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1153isReservoirCouplingMaster_()
const
1155 return this->substepper_.isReservoirCouplingMaster_();
1158template<
class TypeTag>
1159template<
class Solver>
1161AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1162isReservoirCouplingSlave_()
const
1164 return this->substepper_.isReservoirCouplingSlave_();
1167template<
class TypeTag>
1168template<
class Solver>
1170AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1171markFirstSubStepAsFinished_()
const
1173#ifdef RESERVOIR_COUPLING_ENABLED
1177 if (isReservoirCouplingMaster_()) {
1178 reservoirCouplingMaster_().setFirstSubstepOfSyncTimestep(
false);
1180 else if (isReservoirCouplingSlave_()) {
1181 reservoirCouplingSlave_().setFirstSubstepOfSyncTimestep(
false);
1187template<
class TypeTag>
1188template<
class Solver>
1190AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1193 return this->adaptive_time_stepping_.max_growth_;
1196template<
class TypeTag>
1197template<
class Solver>
1199AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1200maybeReportSubStep_(SimulatorReportSingle substep_report)
const
1202 if (timeStepVerbose_()) {
1203 std::ostringstream ss;
1204 substep_report.reportStep(ss);
1205 OpmLog::info(ss.str());
1209template<
class TypeTag>
1210template<
class Solver>
1212AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1213maybeRestrictTimeStepGrowth_(
const double dt,
double dt_estimate,
const int restarts)
const
1216 dt_estimate = std::min(dt_estimate,
double(maxGrowth_() * dt));
1217 assert(dt_estimate > 0);
1220 dt_estimate = std::min(growthFactor_() * dt, dt_estimate);
1227template<
class TypeTag>
1228template<
class Solver>
1230AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1231maybeUpdateLastSubstepOfSyncTimestep_([[maybe_unused]]
const double dt)
1233#ifdef RESERVOIR_COUPLING_ENABLED
1238 if (isReservoirCouplingSlave_()) {
1240 this->substep_timer_.simulationTimeElapsed() + dt,
1241 this->substep_timer_.totalTime()
1243 reservoirCouplingSlave_().setLastSubstepOfSyncTimestep(is_last);
1251template<
class TypeTag>
1252template<
class Solver>
1254AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1255maybeUpdateTuningAndTimeStep_()
1263 const auto old_value = suggestedNextTimestep_();
1264 if (this->substepper_.maybeUpdateTuning_(this->substep_timer_.simulationTimeElapsed(),
1265 this->substep_timer_.currentStepLength(),
1266 this->substep_timer_.currentStepNum()))
1273 setTimeStep_(suggestedNextTimestep_());
1274 setSuggestedNextStep_(old_value);
1278template<
class TypeTag>
1279template<
class Solver>
1281AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1282minTimeStepBeforeClosingWells_()
const
1284 return this->adaptive_time_stepping_.min_time_step_before_shutting_problematic_wells_;
1287template<
class TypeTag>
1288template<
class Solver>
1290AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1293 return this->adaptive_time_stepping_.min_time_step_;
1296#ifdef RESERVOIR_COUPLING_ENABLED
1297template<
class TypeTag>
1298template<
class Solver>
1299ReservoirCouplingMaster<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
1300AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1301reservoirCouplingMaster_()
const
1303 return this->substepper_.reservoirCouplingMaster_();
1306template<
class TypeTag>
1307template<
class Solver>
1308ReservoirCouplingSlave<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
1309AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1310reservoirCouplingSlave_()
const
1312 return this->substepper_.reservoirCouplingSlave_();
1316template<
class TypeTag>
1317template<
class Solver>
1319AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1320restartFactor_()
const
1322 return this->adaptive_time_stepping_.restart_factor_;
1325template<
class TypeTag>
1326template<
class Solver>
1327SimulatorReportSingle
1328AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1332 SimulatorReportSingle substep_report;
1334 auto handleFailure = [
this, &substep_report]
1335 (
const std::string& failure_reason,
const std::exception& e,
bool log_exception =
true)
1337 substep_report = solver_().failureReport();
1338 this->cause_of_failure_ = failure_reason;
1339 if (log_exception && solverVerbose_()) {
1340 OpmLog::debug(std::string(
"Caught Exception: ") + e.what());
1345 substep_report = solver_().step(this->substep_timer_, &this->adaptive_time_stepping_.timeStepControl());
1346 if (solverVerbose_()) {
1348 OpmLog::debug(
"Overall linear iterations used: "
1352 catch (
const TooManyIterations& e) {
1353 handleFailure(
"Solver convergence failure - Iteration limit reached", e);
1355 catch (
const TimeSteppingBreakdown& e) {
1356 handleFailure(e.what(), e);
1358 catch (
const ConvergenceMonitorFailure& e) {
1359 handleFailure(
"Convergence monitor failure", e,
false);
1361 catch (
const LinearSolverProblem& e) {
1362 handleFailure(
"Linear solver convergence failure", e);
1364 catch (
const NumericalProblem& e) {
1365 handleFailure(
"Solver convergence failure - Numerical problem encountered", e);
1367 catch (
const std::runtime_error& e) {
1368 handleFailure(
"Runtime error encountered", e);
1370 catch (
const Dune::ISTLError& e) {
1371 handleFailure(
"ISTL error - Time step too large", e);
1373 catch (
const Dune::MatrixBlockError& e) {
1374 handleFailure(
"Matrix block error", e);
1377 return substep_report;
1380template<
class TypeTag>
1381template<
class Solver>
1383AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1384setTimeStep_(
double dt_estimate)
1386 this->substep_timer_.provideTimeStepEstimate(dt_estimate);
1389template<
class TypeTag>
1390template<
class Solver>
1392AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1395 return this->substepper_.solver_;
1399template<
class TypeTag>
1400template<
class Solver>
1402AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1403solverRestartMax_()
const
1405 return this->adaptive_time_stepping_.solver_restart_max_;
1408template<
class TypeTag>
1409template<
class Solver>
1411AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1412setSuggestedNextStep_(
double step)
1414 this->adaptive_time_stepping_.setSuggestedNextStep(step);
1417template <
class TypeTag>
1418template <
class Solver>
1419const SimulatorTimer&
1420AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1421simulatorTimer_()
const
1423 return this->substepper_.simulator_timer_;
1426template <
class TypeTag>
1427template <
class Solver>
1429AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1430solverVerbose_()
const
1432 return this->adaptive_time_stepping_.solver_verbose_;
1435template<
class TypeTag>
1436template<
class Solver>
1437boost::posix_time::ptime
1438AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1439startDateTime_()
const
1441 return simulatorTimer_().startDateTime();
1444template <
class TypeTag>
1445template <
class Solver>
1447AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1448suggestedNextTimestep_()
const
1450 return this->adaptive_time_stepping_.suggestedNextStep();
1453template <
class TypeTag>
1454template <
class Solver>
1456AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1457timeStepControlComputeEstimate_(
const double dt,
const int iterations,
1458 const AdaptiveSimulatorTimer& substepTimer)
const
1461 const SolutionTimeErrorSolverWrapper<Solver> relative_change{solver_()};
1462 return this->adaptive_time_stepping_.time_step_control_->computeTimeStepSize(
1463 dt, iterations, relative_change, substepTimer);
1466template <
class TypeTag>
1467template <
class Solver>
1469AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1470timeStepVerbose_()
const
1472 return this->adaptive_time_stepping_.timestep_verbose_;
1482template <
class TypeTag>
1483template <
class Solver>
1485AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1486updateSuggestedNextStep_()
1488 auto suggested_next_step = this->substep_timer_.currentStepLength();
1489 if (! std::isfinite(suggested_next_step)) {
1490 suggested_next_step = this->original_time_step_;
1492 if (timeStepVerbose_()) {
1493 std::ostringstream ss;
1494 this->substep_timer_.report(ss);
1495 ss <<
"Suggested next step size = "
1496 << unit::convert::to(suggested_next_step, unit::day) <<
" (days)" << std::endl;
1497 OpmLog::debug(ss.str());
1499 setSuggestedNextStep_(suggested_next_step);
1502template <
class TypeTag>
1503template <
class Solver>
1505AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1506useNewtonIteration_()
const
1508 return this->adaptive_time_stepping_.use_newton_iteration_;
1511template <
class TypeTag>
1512template <
class Solver>
1514AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1517 time::StopWatch perf_timer;
1519 auto& problem = solver_().model().simulator().problem();
1520 problem.writeOutput(
true);
1521 return perf_timer.secsSinceStart();
1528template<
class TypeTag>
1529template<
class Solver>
1530AdaptiveTimeStepping<TypeTag>::
1531SolutionTimeErrorSolverWrapper<Solver>::
1532SolutionTimeErrorSolverWrapper(
const Solver& solver)
1536template<
class TypeTag>
1537template<
class Solver>
1538double AdaptiveTimeStepping<TypeTag>::SolutionTimeErrorSolverWrapper<Solver>::relativeChange()
const
1541 return solver_.model().relativeChange();
Adaptive time-stepping coordinator for the black-oil simulator.
Definition: AdaptiveTimeStepping.hpp:93
double max_growth_
factor that limits the maximum growth of a time step
Definition: AdaptiveTimeStepping.hpp:427
double max_time_step_
maximal allowed time step size in days
Definition: AdaptiveTimeStepping.hpp:428
bool solver_verbose_
solver verbosity
Definition: AdaptiveTimeStepping.hpp:432
int solver_restart_max_
how many restart of solver are allowed
Definition: AdaptiveTimeStepping.hpp:431
double timestep_after_event_
suggested size of timestep after an event
Definition: AdaptiveTimeStepping.hpp:436
void init_(const UnitSystem &unitSystem)
Definition: AdaptiveTimeStepping_impl.hpp:429
void setSuggestedNextStep(const double x)
Set the suggested length for the next substep [s].
Definition: AdaptiveTimeStepping_impl.hpp:300
double suggestedNextStep() const
Definition: AdaptiveTimeStepping_impl.hpp:308
bool operator==(const AdaptiveTimeStepping< TypeTag > &rhs) const
Definition: AdaptiveTimeStepping_impl.hpp:140
static AdaptiveTimeStepping< TypeTag > serializationTestObjectSimple()
Definition: AdaptiveTimeStepping_impl.hpp:283
bool ignore_convergence_failure_
continue instead of stop when minimum time step is reached
Definition: AdaptiveTimeStepping.hpp:430
void serializeOp(Serializer &serializer)
Definition: AdaptiveTimeStepping_impl.hpp:212
void updateTUNING(double max_next_tstep, const Tuning &tuning)
Apply TUNING keyword parameters.
Definition: AdaptiveTimeStepping_impl.hpp:337
TimeStepControlType time_step_control_type_
type of time step control object
Definition: AdaptiveTimeStepping.hpp:423
const TimeStepControlInterface & timeStepControl() const
Definition: AdaptiveTimeStepping_impl.hpp:316
std::function< bool(double elapsed, double substep_length, int sub_step_number)> TuningUpdateCallback
Callback invoked at the start of each substep to apply TUNING, NEXTSTEP (via ACTIONX),...
Definition: AdaptiveTimeStepping.hpp:119
bool full_timestep_initially_
beginning with the size of the time step from data file
Definition: AdaptiveTimeStepping.hpp:435
SimulatorReport step(const SimulatorTimer &simulator_timer, Solver &solver, const bool is_event, const TuningUpdateCallback &tuning_updater)
Run one report step by orchestrating adaptive substepping.
Definition: AdaptiveTimeStepping_impl.hpp:197
double growth_factor_
factor to multiply time step when solver recovered from failed convergence
Definition: AdaptiveTimeStepping.hpp:426
double restart_factor_
factor to multiply time step with when solver fails to converge
Definition: AdaptiveTimeStepping.hpp:425
double min_time_step_
minimal allowed time step size before throwing
Definition: AdaptiveTimeStepping.hpp:429
void updateNEXTSTEP(double max_next_tstep)
Set suggested_next_timestep_ to max_next_tstep iff max_next_tstep > 0.
Definition: AdaptiveTimeStepping_impl.hpp:325
static AdaptiveTimeStepping< TypeTag > serializationTestObjectHardcoded()
Definition: AdaptiveTimeStepping_impl.hpp:259
AdaptiveTimeStepping()=default
TimeStepController time_step_control_
time step control object
Definition: AdaptiveTimeStepping.hpp:424
static AdaptiveTimeStepping< TypeTag > serializationTestObjectPIDIt()
Definition: AdaptiveTimeStepping_impl.hpp:275
double min_time_step_before_shutting_problematic_wells_
< shut problematic wells when time step size in days are less than this
Definition: AdaptiveTimeStepping.hpp:440
static AdaptiveTimeStepping< TypeTag > serializationTestObject3rdOrder()
Definition: AdaptiveTimeStepping_impl.hpp:291
SimulatorReport & report()
Definition: AdaptiveTimeStepping_impl.hpp:251
static AdaptiveTimeStepping< TypeTag > serializationTestObjectPID()
Definition: AdaptiveTimeStepping_impl.hpp:267
static void registerParameters()
Definition: AdaptiveTimeStepping_impl.hpp:186
bool use_newton_iteration_
use newton iteration count for adaptive time step control
Definition: AdaptiveTimeStepping.hpp:437
Definition: SimulatorTimer.hpp:39
Definition: TimeStepControlInterface.hpp:51
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hpp:187
void logTimer(const AdaptiveSimulatorTimer &substep_timer)
void registerAdaptiveParameters()
std::set< std::string > consistentlyFailingWells(const std::vector< StepReport > &sr, bool requireRepeatedFailures)
std::tuple< TimeStepControlType, std::unique_ptr< TimeStepControlInterface >, bool > createController(const UnitSystem &unitSystem)
Definition: blackoilbioeffectsmodules.hh:45
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
This file provides the infrastructure to retrieve run-time parameters.
static bool compare_gt_or_eq(double a, double b)
Determines if a is greater than b within the specified tolerance.
Definition: SimulatorReport.hpp:122