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>
37#include <opm/grid/utility/StopWatch.hpp>
39#include <opm/input/eclipse/Schedule/Tuning.hpp>
41#include <opm/input/eclipse/Units/Units.hpp>
42#include <opm/input/eclipse/Units/UnitSystem.hpp>
54#include <boost/date_time/posix_time/posix_time.hpp>
55#include <fmt/format.h>
56#include <fmt/ranges.h>
64template<
class TypeTag>
68 const double max_next_tstep,
69 const bool terminal_output
71 : time_step_control_{}
72 , restart_factor_{Parameters::
Get<Parameters::SolverRestartFactor<Scalar>>()}
73 , growth_factor_{Parameters::
Get<Parameters::SolverGrowthFactor<Scalar>>()}
74 , max_growth_{Parameters::
Get<Parameters::SolverMaxGrowth<Scalar>>()}
76 Parameters::
Get<Parameters::SolverMaxTimeStepInDays<Scalar>>() * 24 * 60 * 60}
78 unit_system.to_si(UnitSystem::measure::time,
79 Parameters::
Get<Parameters::SolverMinTimeStep<Scalar>>())}
80 , ignore_convergence_failure_{
81 Parameters::
Get<Parameters::SolverContinueOnConvergenceFailure>()}
82 , solver_restart_max_{Parameters::
Get<Parameters::SolverMaxRestarts>()}
83 , solver_verbose_{Parameters::
Get<Parameters::SolverVerbosity>() > 0 && terminal_output}
84 , timestep_verbose_{Parameters::
Get<Parameters::TimeStepVerbosity>() > 0 && terminal_output}
85 , suggested_next_timestep_{
86 (max_next_tstep <= 0 ? Parameters::
Get<Parameters::InitialTimeStepInDays>()
87 : max_next_tstep) * 24 * 60 * 60}
88 , full_timestep_initially_{Parameters::
Get<Parameters::FullTimeStepInitially>()}
89 , timestep_after_event_{
90 Parameters::
Get<Parameters::TimeStepAfterEventInDays<Scalar>>() * 24 * 60 * 60}
91 , use_newton_iteration_{false}
92 , min_time_step_before_shutting_problematic_wells_{
93 Parameters::
Get<Parameters::MinTimeStepBeforeShuttingProblematicWellsInDays>() * unit::day}
105template<
class TypeTag>
108 const Tuning& tuning,
109 const UnitSystem& unit_system,
111 const bool terminal_output
113 : time_step_control_{}
114 , restart_factor_{tuning.TSFCNV}
115 , growth_factor_{tuning.TFDIFF}
116 , max_growth_{tuning.TSFMAX}
117 , max_time_step_{tuning.TSMAXZ}
118 , min_time_step_{tuning.TSMINZ}
119 , ignore_convergence_failure_{true}
120 , solver_restart_max_{Parameters::
Get<Parameters::SolverMaxRestarts>()}
121 , solver_verbose_{Parameters::
Get<Parameters::SolverVerbosity>() > 0 && terminal_output}
122 , timestep_verbose_{Parameters::
Get<Parameters::TimeStepVerbosity>() > 0 && terminal_output}
123 , suggested_next_timestep_{
124 max_next_tstep <= 0 ? Parameters::
Get<Parameters::InitialTimeStepInDays>() * 24 * 60 * 60
126 , full_timestep_initially_{Parameters::
Get<Parameters::FullTimeStepInitially>()}
127 , timestep_after_event_{tuning.TMAXWC}
128 , use_newton_iteration_{false}
129 , min_time_step_before_shutting_problematic_wells_{
130 Parameters::
Get<Parameters::MinTimeStepBeforeShuttingProblematicWellsInDays>() * unit::day}
136template<
class TypeTag>
148 switch (this->time_step_control_type_) {
150 result = castAndComp<HardcodedTimeStepControl>(rhs);
153 result = castAndComp<PIDAndIterationCountTimeStepControl>(rhs);
156 result = castAndComp<SimpleIterationCountTimeStepControl>(rhs);
159 result = castAndComp<PIDTimeStepControl>(rhs);
162 result = castAndComp<General3rdOrderController>(rhs);
178 this->min_time_step_before_shutting_problematic_wells_ ==
182template<
class TypeTag>
187 registerEclTimeSteppingParameters<Scalar>();
199template<
class TypeTag>
200template <
class Solver>
208 SubStepper<Solver> sub_stepper{
209 *
this, simulator_timer, solver, is_event, tuning_updater,
211 return sub_stepper.run();
214template<
class TypeTag>
215template<
class Serializer>
220 serializer(this->time_step_control_type_);
221 switch (this->time_step_control_type_) {
223 allocAndSerialize<HardcodedTimeStepControl>(serializer);
226 allocAndSerialize<PIDAndIterationCountTimeStepControl>(serializer);
229 allocAndSerialize<SimpleIterationCountTimeStepControl>(serializer);
232 allocAndSerialize<PIDTimeStepControl>(serializer);
235 allocAndSerialize<General3rdOrderController>(serializer);
238 serializer(this->restart_factor_);
239 serializer(this->growth_factor_);
240 serializer(this->max_growth_);
241 serializer(this->max_time_step_);
242 serializer(this->min_time_step_);
243 serializer(this->ignore_convergence_failure_);
244 serializer(this->solver_restart_max_);
245 serializer(this->solver_verbose_);
246 serializer(this->timestep_verbose_);
247 serializer(this->suggested_next_timestep_);
248 serializer(this->full_timestep_initially_);
249 serializer(this->timestep_after_event_);
250 serializer(this->use_newton_iteration_);
251 serializer(this->min_time_step_before_shutting_problematic_wells_);
254template<
class TypeTag>
262template<
class TypeTag>
267 return serializationTestObject_<HardcodedTimeStepControl>();
270template<
class TypeTag>
275 return serializationTestObject_<PIDTimeStepControl>();
278template<
class TypeTag>
283 return serializationTestObject_<PIDAndIterationCountTimeStepControl>();
286template<
class TypeTag>
291 return serializationTestObject_<SimpleIterationCountTimeStepControl>();
294template<
class TypeTag>
299 return serializationTestObject_<General3rdOrderController>();
303template<
class TypeTag>
308 this->suggested_next_timestep_ = x;
311template<
class TypeTag>
316 return this->suggested_next_timestep_;
319template<
class TypeTag>
324 return *this->time_step_control_;
328template<
class TypeTag>
335 if (max_next_tstep > 0) {
336 this->suggested_next_timestep_ = max_next_tstep;
340template<
class TypeTag>
343updateTUNING(
double max_next_tstep,
const Tuning& tuning)
345 this->restart_factor_ = tuning.TSFCNV;
346 this->growth_factor_ = tuning.TFDIFF;
347 this->max_growth_ = tuning.TSFMAX;
348 this->max_time_step_ = tuning.TSMAXZ;
349 updateNEXTSTEP(max_next_tstep);
350 this->timestep_after_event_ = tuning.TMAXWC;
357template<
class TypeTag>
358template<
class T,
class Serializer>
363 if (!serializer.isSerializing()) {
364 this->time_step_control_ = std::make_unique<T>();
366 serializer(*
static_cast<T*
>(this->time_step_control_.get()));
369template<
class TypeTag>
372AdaptiveTimeStepping<TypeTag>::
373castAndComp(
const AdaptiveTimeStepping<TypeTag>& Rhs)
const
375 const T* lhs =
static_cast<const T*
>(this->time_step_control_.get());
376 const T* rhs =
static_cast<const T*
>(Rhs.time_step_control_.get());
380template<
class TypeTag>
382AdaptiveTimeStepping<TypeTag>::
383maybeModifySuggestedTimeStepAtBeginningOfReportStep_(
const double original_time_step,
387 if (this->suggested_next_timestep_ < 0) {
388 this->suggested_next_timestep_ = this->restart_factor_ * original_time_step;
391 if (this->full_timestep_initially_) {
392 this->suggested_next_timestep_ = original_time_step;
396 if (is_event && this->timestep_after_event_ > 0) {
397 this->suggested_next_timestep_ = this->timestep_after_event_;
401template<
class TypeTag>
402template<
class Controller>
403AdaptiveTimeStepping<TypeTag>
404AdaptiveTimeStepping<TypeTag>::
405serializationTestObject_()
407 AdaptiveTimeStepping<TypeTag> result;
409 result.restart_factor_ = 1.0;
410 result.growth_factor_ = 2.0;
411 result.max_growth_ = 3.0;
412 result.max_time_step_ = 4.0;
413 result.min_time_step_ = 5.0;
414 result.ignore_convergence_failure_ =
true;
415 result.solver_restart_max_ = 6;
416 result.solver_verbose_ =
true;
417 result.timestep_verbose_ =
true;
418 result.suggested_next_timestep_ = 7.0;
419 result.full_timestep_initially_ =
true;
420 result.use_newton_iteration_ =
true;
421 result.min_time_step_before_shutting_problematic_wells_ = 9.0;
422 result.time_step_control_type_ = Controller::Type;
423 result.time_step_control_ =
424 std::make_unique<Controller>(Controller::serializationTestObject());
433template<
class TypeTag>
435init_(
const UnitSystem& unitSystem)
437 std::tie(time_step_control_type_,
441 if (this->growth_factor_ < 1.0) {
442 OPM_THROW(std::runtime_error,
443 "Growth factor cannot be less than 1.");
453template<
class TypeTag>
454template<
class Solver>
460 const TuningUpdateCallback& tuning_updater)
461 : adaptive_time_stepping_{adaptive_time_stepping}
462 , simulator_timer_{simulator_timer}
464 , is_event_{is_event}
465 , tuning_updater_{tuning_updater}
469template<
class TypeTag>
470template<
class Solver>
471AdaptiveTimeStepping<TypeTag>&
472AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
473getAdaptiveTimerStepper()
475 return adaptive_time_stepping_;
478template<
class TypeTag>
479template<
class Solver>
481AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
484#ifdef RESERVOIR_COUPLING_ENABLED
485 if (isReservoirCouplingSlave_() && reservoirCouplingSlave_().activated()) {
486 return runStepReservoirCouplingSlave_();
488 else if (isReservoirCouplingMaster_() && reservoirCouplingMaster_().activated()) {
489 return runStepReservoirCouplingMaster_();
492 return runStepOriginal_();
495 return runStepOriginal_();
503#ifdef RESERVOIR_COUPLING_ENABLED
504template<
class TypeTag>
505template<
class Solver>
507AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
508isReservoirCouplingMaster_()
const
510 return this->solver_.model().simulator().reservoirCouplingMaster() !=
nullptr;
513template<
class TypeTag>
514template<
class Solver>
516AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
517isReservoirCouplingSlave_()
const
519 return this->solver_.model().simulator().reservoirCouplingSlave() !=
nullptr;
523template<
class TypeTag>
524template<
class Solver>
526AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
527maybeModifySuggestedTimeStepAtBeginningOfReportStep_(
const double original_time_step)
529 this->adaptive_time_stepping_.maybeModifySuggestedTimeStepAtBeginningOfReportStep_(
530 original_time_step, this->is_event_
537template<
class TypeTag>
538template<
class Solver>
540AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
541maybeUpdateTuning_(
double elapsed,
double dt,
int sub_step_number)
const
543 return this->tuning_updater_(elapsed, dt, sub_step_number);
546template<
class TypeTag>
547template<
class Solver>
549AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
552 return this->adaptive_time_stepping_.max_time_step_;
555template <
class TypeTag>
556template <
class Solver>
558AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
561 const auto elapsed = this->simulator_timer_.simulationTimeElapsed();
562 const auto original_time_step = this->simulator_timer_.currentStepLength();
563 const auto report_step = this->simulator_timer_.reportStepNum();
564 maybeUpdateTuning_(elapsed, original_time_step, report_step);
565 maybeModifySuggestedTimeStepAtBeginningOfReportStep_(original_time_step);
567 AdaptiveSimulatorTimer substep_timer{
568 this->simulator_timer_.startDateTime(),
571 suggestedNextTimestep_(),
575 SubStepIteration<Solver> substepIteration{*
this, substep_timer, original_time_step,
true};
576 return substepIteration.run();
579#ifdef RESERVOIR_COUPLING_ENABLED
580template <
class TypeTag>
581template <
class Solver>
582ReservoirCouplingMaster<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
583AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
584reservoirCouplingMaster_()
586 return *(this->solver_.model().simulator().reservoirCouplingMaster());
590#ifdef RESERVOIR_COUPLING_ENABLED
591template <
class TypeTag>
592template <
class Solver>
593ReservoirCouplingSlave<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
594AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
595reservoirCouplingSlave_()
597 return *(this->solver_.model().simulator().reservoirCouplingSlave());
601#ifdef RESERVOIR_COUPLING_ENABLED
632template <
class TypeTag>
633template <
class Solver>
635AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
636runStepReservoirCouplingMaster_()
639 const double original_time_step = this->simulator_timer_.currentStepLength();
640 double current_time{this->simulator_timer_.simulationTimeElapsed()};
641 double step_end_time = current_time + original_time_step;
642 auto current_step_length = original_time_step;
643 auto report_step_idx = this->simulator_timer_.currentStepNum();
644 if (report_step_idx == 0 && iteration == 0) {
645 reservoirCouplingMaster_().initTimeStepping();
647 SimulatorReport report;
649 reservoirCouplingMaster_().maybeReceiveActivationHandshakeFromSlaves(current_time);
651 reservoirCouplingMaster_().receiveNextReportDateFromSlaves();
652 bool start_of_report_step = (iteration == 0);
653 if (start_of_report_step) {
654 reservoirCouplingMaster_().initStartOfReportStep(report_step_idx);
656 current_step_length = reservoirCouplingMaster_().maybeChopSubStep(
657 current_step_length, current_time);
658 reservoirCouplingMaster_().sendNextTimeStepToSlaves(current_step_length);
659 if (start_of_report_step) {
660 maybeUpdateTuning_(current_time, current_step_length, 0);
661 maybeModifySuggestedTimeStepAtBeginningOfReportStep_(current_step_length);
663 AdaptiveSimulatorTimer substep_timer{
664 this->simulator_timer_.startDateTime(),
667 suggestedNextTimestep_(),
668 this->simulator_timer_.reportStepNum(),
672 current_time + current_step_length, step_end_time
677 reservoirCouplingMaster_().setFirstSubstepOfSyncTimestep(
true);
678 SubStepIteration<Solver> substepIteration{*
this, substep_timer, current_step_length, final_step};
679 const auto sub_steps_report = substepIteration.run();
680 report += sub_steps_report;
681 current_time += current_step_length;
691#ifdef RESERVOIR_COUPLING_ENABLED
692template <
class TypeTag>
693template <
class Solver>
695AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
696runStepReservoirCouplingSlave_()
699 const double original_time_step = this->simulator_timer_.currentStepLength();
700 double current_time{this->simulator_timer_.simulationTimeElapsed()};
701 double step_end_time = current_time + original_time_step;
702 SimulatorReport report;
703 auto report_step_idx = this->simulator_timer_.currentStepNum();
704 if (report_step_idx == 0 && iteration == 0) {
705 reservoirCouplingSlave_().initTimeStepping();
708 bool start_of_report_step = (iteration == 0);
709 reservoirCouplingSlave_().sendNextReportDateToMasterProcess();
710 const auto timestep = reservoirCouplingSlave_().receiveNextTimeStepFromMaster();
711 if (start_of_report_step) {
712 maybeUpdateTuning_(current_time, original_time_step, 0);
713 maybeModifySuggestedTimeStepAtBeginningOfReportStep_(timestep);
715 AdaptiveSimulatorTimer substep_timer{
716 this->simulator_timer_.startDateTime(),
719 suggestedNextTimestep_(),
720 this->simulator_timer_.reportStepNum(),
724 current_time + timestep, step_end_time
729 reservoirCouplingSlave_().setFirstSubstepOfSyncTimestep(
true);
730 SubStepIteration<Solver> substepIteration{*
this, substep_timer, timestep, final_step};
731 const auto sub_steps_report = substepIteration.run();
732 report += sub_steps_report;
733 current_time += timestep;
744template <
class TypeTag>
745template <
class Solver>
747AdaptiveTimeStepping<TypeTag>::SubStepper<Solver>::
748suggestedNextTimestep_()
const
750 return this->adaptive_time_stepping_.suggestedNextStep();
759template<
class TypeTag>
760template<
class Solver>
761AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
762SubStepIteration(SubStepper<Solver>& substepper,
763 AdaptiveSimulatorTimer& substep_timer,
764 const double original_time_step,
766 : substepper_{substepper}
767 , substep_timer_{substep_timer}
768 , original_time_step_{original_time_step}
769 , final_step_{final_step}
770 , adaptive_time_stepping_{substepper.getAdaptiveTimerStepper()}
774template <
class TypeTag>
775template <
class Solver>
777AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
780 auto& simulator = solver_().model().simulator();
781 auto& problem = simulator.problem();
784 SimulatorReport report;
787 while (!this->substep_timer_.done()) {
791 maybeUpdateTuningAndTimeStep_();
793 const double dt = this->substep_timer_.currentStepLength();
794 if (timeStepVerbose_()) {
798 auto substep_report = runSubStep_();
799 markFirstSubStepAsFinished_();
801 if (substep_report.converged || checkContinueOnUnconvergedSolution_(dt)) {
802 Dune::Timer perfTimer;
805 problem.setSubStepReport(substep_report);
806 auto& full_report = adaptive_time_stepping_.report();
807 full_report += substep_report;
808 problem.setSimulationReport(full_report);
809 problem.endTimeStep();
810 substep_report.pre_post_time += perfTimer.stop();
812 report += substep_report;
814 ++this->substep_timer_;
816 const int iterations = getNumIterations_(substep_report);
817 auto dt_estimate = timeStepControlComputeEstimate_(
818 dt, iterations, this->substep_timer_);
820 assert(dt_estimate > 0);
821 dt_estimate = maybeRestrictTimeStepGrowth_(dt, dt_estimate, restarts);
824 maybeReportSubStep_(substep_report);
825 if (this->final_step_ && this->substep_timer_.done()) {
830 report.success.output_write_time += writeOutput_();
834 setTimeStep_(dt_estimate);
836 report.success.converged = this->substep_timer_.done();
837 this->substep_timer_.setLastStepFailed(
false);
840 report += substep_report;
841 this->substep_timer_.setLastStepFailed(
true);
842 checkTimeStepMaxRestartLimit_(restarts);
844 double new_time_step = restartFactor_() * dt;
845 if (substep_report.time_step_rejected) {
846 const double tol = Parameters::Get<Parameters::TimeStepControlTolerance>();
847 const double safetyFactor = Parameters::Get<Parameters::TimeStepControlSafetyFactor>();
848 const double temp_time_step = std::sqrt(safetyFactor * tol / solver_().model().relativeChange()) * dt;
849 if (temp_time_step < dt) {
850 new_time_step = temp_time_step;
853 checkTimeStepMinLimit_(new_time_step);
854 bool wells_shut =
false;
855 if (new_time_step > minTimeStepBeforeClosingWells_()) {
856 chopTimeStep_(new_time_step);
858 wells_shut = chopTimeStepOrCloseFailingWells_(new_time_step);
867 problem.setNextTimeStepSize(this->substep_timer_.currentStepLength());
869 updateSuggestedNextStep_();
879template<
class TypeTag>
880template<
class Solver>
882AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
883checkContinueOnUnconvergedSolution_(
double dt)
const
885 const bool continue_on_uncoverged_solution = ignoreConvergenceFailure_() && dt <= minTimeStep_();
886 if (continue_on_uncoverged_solution && solverVerbose_()) {
888 const auto msg = fmt::format(
889 "Solver failed to converge but timestep {} is smaller or equal to {}\n"
890 "which is the minimum threshold given by option --solver-min-time-step\n",
893 OpmLog::problem(msg);
895 return continue_on_uncoverged_solution;
898template<
class TypeTag>
899template<
class Solver>
901AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
902checkTimeStepMaxRestartLimit_(
const int restarts)
const
906 if (restarts >= solverRestartMax_()) {
907 const auto msg = fmt::format(
908 "Solver failed to converge after cutting timestep {} times.", restarts
910 if (solverVerbose_()) {
914 throw TimeSteppingBreakdown{msg};
918template<
class TypeTag>
919template<
class Solver>
921AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
922checkTimeStepMinLimit_(
const double new_time_step)
const
924 using Meas = UnitSystem::measure;
927 if (new_time_step < minTimeStep_()) {
928 auto msg = fmt::format(
"Solver failed to converge after cutting timestep to ");
929 if (Parameters::Get<Parameters::EnableTuning>()) {
930 const UnitSystem& unit_system = solver_().model().simulator().vanguard().eclState().getDeckUnitSystem();
932 "{:.3E} {}\nwhich is the minimum threshold given by the TUNING keyword\n",
933 unit_system.from_si(Meas::time, minTimeStep_()),
934 unit_system.name(Meas::time)
939 "{:.3E} DAYS\nwhich is the minimum threshold given by option --solver-min-time-step\n",
940 minTimeStep_() / 86400.0
943 if (solverVerbose_()) {
947 throw TimeSteppingBreakdown{msg};
951template<
class TypeTag>
952template<
class Solver>
954AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
955chopTimeStep_(
const double new_time_step)
957 setTimeStep_(new_time_step);
958 if (solverVerbose_()) {
959 const auto msg = fmt::format(
"{}\nTimestep chopped to {} days\n",
960 this->cause_of_failure_,
961 unit::convert::to(this->substep_timer_.currentStepLength(), unit::day));
962 OpmLog::problem(msg);
966template<
class TypeTag>
967template<
class Solver>
969AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
970chopTimeStepOrCloseFailingWells_(
const double new_time_step)
972 bool wells_shut =
false;
979 const bool requireRepeatedFailures =
980 new_time_step > (minTimeStepBeforeClosingWells_() * restartFactor_() * restartFactor_());
981 const std::set<std::string> failing_wells =
984 if (failing_wells.empty()) {
986 chopTimeStep_(new_time_step);
989 std::vector<std::string> shut_wells;
990 for (
const auto& well : failing_wells) {
991 const bool was_shut =
992 solver_().model().wellModel().forceShutWellByName(well,
993 this->substep_timer_.simulationTimeElapsed(),
996 shut_wells.push_back(well);
1000 if (shut_wells.empty()) {
1001 for (
const auto& well : failing_wells) {
1002 const bool was_shut =
1003 solver_().model().wellModel().forceShutWellByName(well,
1004 this->substep_timer_.simulationTimeElapsed(),
1007 shut_wells.push_back(well);
1012 if (shut_wells.empty()) {
1013 chopTimeStep_(new_time_step);
1016 if (solverVerbose_()) {
1017 const std::string msg =
1018 fmt::format(
"\nProblematic well(s) were shut: {}"
1019 "(retrying timestep)\n",
1020 fmt::join(shut_wells,
" "));
1021 OpmLog::problem(msg);
1028template<
class TypeTag>
1029template<
class Solver>
1030boost::posix_time::ptime
1031AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1032currentDateTime_()
const
1034 return simulatorTimer_().currentDateTime();
1037template<
class TypeTag>
1038template<
class Solver>
1040AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1041getNumIterations_(
const SimulatorReportSingle &substep_report)
const
1043 if (useNewtonIteration_()) {
1044 return substep_report.total_newton_iterations;
1047 return substep_report.total_linear_iterations;
1051template<
class TypeTag>
1052template<
class Solver>
1054AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1055growthFactor_()
const
1057 return this->adaptive_time_stepping_.growth_factor_;
1060template<
class TypeTag>
1061template<
class Solver>
1063AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1064ignoreConvergenceFailure_()
const
1066 return adaptive_time_stepping_.ignore_convergence_failure_;
1069template<
class TypeTag>
1070template<
class Solver>
1072AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1073isReservoirCouplingMaster_()
const
1075 return this->substepper_.isReservoirCouplingMaster_();
1078template<
class TypeTag>
1079template<
class Solver>
1081AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1082isReservoirCouplingSlave_()
const
1084 return this->substepper_.isReservoirCouplingSlave_();
1087template<
class TypeTag>
1088template<
class Solver>
1090AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1091markFirstSubStepAsFinished_()
const
1093#ifdef RESERVOIR_COUPLING_ENABLED
1097 if (isReservoirCouplingMaster_()) {
1098 reservoirCouplingMaster_().setFirstSubstepOfSyncTimestep(
false);
1100 else if (isReservoirCouplingSlave_()) {
1101 reservoirCouplingSlave_().setFirstSubstepOfSyncTimestep(
false);
1107template<
class TypeTag>
1108template<
class Solver>
1110AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1113 return this->adaptive_time_stepping_.max_growth_;
1116template<
class TypeTag>
1117template<
class Solver>
1119AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1120maybeReportSubStep_(SimulatorReportSingle substep_report)
const
1122 if (timeStepVerbose_()) {
1123 std::ostringstream ss;
1124 substep_report.reportStep(ss);
1125 OpmLog::info(ss.str());
1129template<
class TypeTag>
1130template<
class Solver>
1132AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1133maybeRestrictTimeStepGrowth_(
const double dt,
double dt_estimate,
const int restarts)
const
1136 dt_estimate = std::min(dt_estimate,
double(maxGrowth_() * dt));
1137 assert(dt_estimate > 0);
1140 dt_estimate = std::min(growthFactor_() * dt, dt_estimate);
1149template<
class TypeTag>
1150template<
class Solver>
1152AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1153maybeUpdateTuningAndTimeStep_()
1161 const auto old_value = suggestedNextTimestep_();
1162 if (this->substepper_.maybeUpdateTuning_(this->substep_timer_.simulationTimeElapsed(),
1163 this->substep_timer_.currentStepLength(),
1164 this->substep_timer_.currentStepNum()))
1171 setTimeStep_(suggestedNextTimestep_());
1172 setSuggestedNextStep_(old_value);
1176template<
class TypeTag>
1177template<
class Solver>
1179AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1180minTimeStepBeforeClosingWells_()
const
1182 return this->adaptive_time_stepping_.min_time_step_before_shutting_problematic_wells_;
1185template<
class TypeTag>
1186template<
class Solver>
1188AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1191 return this->adaptive_time_stepping_.min_time_step_;
1194#ifdef RESERVOIR_COUPLING_ENABLED
1195template<
class TypeTag>
1196template<
class Solver>
1197ReservoirCouplingMaster<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
1198AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1199reservoirCouplingMaster_()
const
1201 return this->substepper_.reservoirCouplingMaster_();
1204template<
class TypeTag>
1205template<
class Solver>
1206ReservoirCouplingSlave<typename AdaptiveTimeStepping<TypeTag>::Scalar>&
1207AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1208reservoirCouplingSlave_()
const
1210 return this->substepper_.reservoirCouplingSlave_();
1214template<
class TypeTag>
1215template<
class Solver>
1217AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1218restartFactor_()
const
1220 return this->adaptive_time_stepping_.restart_factor_;
1223template<
class TypeTag>
1224template<
class Solver>
1225SimulatorReportSingle
1226AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1229 SimulatorReportSingle substep_report;
1231 auto handleFailure = [
this, &substep_report]
1232 (
const std::string& failure_reason,
const std::exception& e,
bool log_exception =
true)
1234 substep_report = solver_().failureReport();
1235 this->cause_of_failure_ = failure_reason;
1236 if (log_exception && solverVerbose_()) {
1237 OpmLog::debug(std::string(
"Caught Exception: ") + e.what());
1242 substep_report = solver_().step(this->substep_timer_, &this->adaptive_time_stepping_.timeStepControl());
1243 if (solverVerbose_()) {
1245 OpmLog::debug(
"Overall linear iterations used: "
1249 catch (
const TooManyIterations& e) {
1250 handleFailure(
"Solver convergence failure - Iteration limit reached", e);
1252 catch (
const TimeSteppingBreakdown& e) {
1253 handleFailure(e.what(), e);
1255 catch (
const ConvergenceMonitorFailure& e) {
1256 handleFailure(
"Convergence monitor failure", e,
false);
1258 catch (
const LinearSolverProblem& e) {
1259 handleFailure(
"Linear solver convergence failure", e);
1261 catch (
const NumericalProblem& e) {
1262 handleFailure(
"Solver convergence failure - Numerical problem encountered", e);
1264 catch (
const std::runtime_error& e) {
1265 handleFailure(
"Runtime error encountered", e);
1267 catch (
const Dune::ISTLError& e) {
1268 handleFailure(
"ISTL error - Time step too large", e);
1270 catch (
const Dune::MatrixBlockError& e) {
1271 handleFailure(
"Matrix block error", e);
1274 return substep_report;
1277template<
class TypeTag>
1278template<
class Solver>
1280AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1281setTimeStep_(
double dt_estimate)
1283 this->substep_timer_.provideTimeStepEstimate(dt_estimate);
1286template<
class TypeTag>
1287template<
class Solver>
1289AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1292 return this->substepper_.solver_;
1296template<
class TypeTag>
1297template<
class Solver>
1299AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1300solverRestartMax_()
const
1302 return this->adaptive_time_stepping_.solver_restart_max_;
1305template<
class TypeTag>
1306template<
class Solver>
1308AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1309setSuggestedNextStep_(
double step)
1311 this->adaptive_time_stepping_.setSuggestedNextStep(step);
1314template <
class TypeTag>
1315template <
class Solver>
1316const SimulatorTimer&
1317AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1318simulatorTimer_()
const
1320 return this->substepper_.simulator_timer_;
1323template <
class TypeTag>
1324template <
class Solver>
1326AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1327solverVerbose_()
const
1329 return this->adaptive_time_stepping_.solver_verbose_;
1332template<
class TypeTag>
1333template<
class Solver>
1334boost::posix_time::ptime
1335AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1336startDateTime_()
const
1338 return simulatorTimer_().startDateTime();
1341template <
class TypeTag>
1342template <
class Solver>
1344AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1345suggestedNextTimestep_()
const
1347 return this->adaptive_time_stepping_.suggestedNextStep();
1350template <
class TypeTag>
1351template <
class Solver>
1353AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1354timeStepControlComputeEstimate_(
const double dt,
const int iterations,
1355 const AdaptiveSimulatorTimer& substepTimer)
const
1358 const SolutionTimeErrorSolverWrapper<Solver> relative_change{solver_()};
1359 return this->adaptive_time_stepping_.time_step_control_->computeTimeStepSize(
1360 dt, iterations, relative_change, substepTimer);
1363template <
class TypeTag>
1364template <
class Solver>
1366AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1367timeStepVerbose_()
const
1369 return this->adaptive_time_stepping_.timestep_verbose_;
1379template <
class TypeTag>
1380template <
class Solver>
1382AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1383updateSuggestedNextStep_()
1385 auto suggested_next_step = this->substep_timer_.currentStepLength();
1386 if (! std::isfinite(suggested_next_step)) {
1387 suggested_next_step = this->original_time_step_;
1389 if (timeStepVerbose_()) {
1390 std::ostringstream ss;
1391 this->substep_timer_.report(ss);
1392 ss <<
"Suggested next step size = "
1393 << unit::convert::to(suggested_next_step, unit::day) <<
" (days)" << std::endl;
1394 OpmLog::debug(ss.str());
1396 setSuggestedNextStep_(suggested_next_step);
1399template <
class TypeTag>
1400template <
class Solver>
1402AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1403useNewtonIteration_()
const
1405 return this->adaptive_time_stepping_.use_newton_iteration_;
1408template <
class TypeTag>
1409template <
class Solver>
1411AdaptiveTimeStepping<TypeTag>::SubStepIteration<Solver>::
1414 time::StopWatch perf_timer;
1416 auto& problem = solver_().model().simulator().problem();
1417 problem.writeOutput(
true);
1418 return perf_timer.secsSinceStart();
1425template<
class TypeTag>
1426template<
class Solver>
1427AdaptiveTimeStepping<TypeTag>::
1428SolutionTimeErrorSolverWrapper<Solver>::
1429SolutionTimeErrorSolverWrapper(
const Solver& solver)
1433template<
class TypeTag>
1434template<
class Solver>
1435double AdaptiveTimeStepping<TypeTag>::SolutionTimeErrorSolverWrapper<Solver>::relativeChange()
const
1438 return solver_.model().relativeChange();
Definition: AdaptiveTimeStepping.hpp:76
double max_growth_
factor that limits the maximum growth of a time step
Definition: AdaptiveTimeStepping.hpp:257
double max_time_step_
maximal allowed time step size in days
Definition: AdaptiveTimeStepping.hpp:258
bool solver_verbose_
solver verbosity
Definition: AdaptiveTimeStepping.hpp:262
int solver_restart_max_
how many restart of solver are allowed
Definition: AdaptiveTimeStepping.hpp:261
double timestep_after_event_
suggested size of timestep after an event
Definition: AdaptiveTimeStepping.hpp:266
void init_(const UnitSystem &unitSystem)
Definition: AdaptiveTimeStepping_impl.hpp:435
void setSuggestedNextStep(const double x)
Definition: AdaptiveTimeStepping_impl.hpp:306
double suggestedNextStep() const
Definition: AdaptiveTimeStepping_impl.hpp:314
std::function< bool(const double, const double, const int)> TuningUpdateCallback
Definition: AdaptiveTimeStepping.hpp:78
bool operator==(const AdaptiveTimeStepping< TypeTag > &rhs) const
Definition: AdaptiveTimeStepping_impl.hpp:139
static AdaptiveTimeStepping< TypeTag > serializationTestObjectSimple()
Definition: AdaptiveTimeStepping_impl.hpp:289
bool ignore_convergence_failure_
continue instead of stop when minimum time step is reached
Definition: AdaptiveTimeStepping.hpp:260
void serializeOp(Serializer &serializer)
Definition: AdaptiveTimeStepping_impl.hpp:218
void updateTUNING(double max_next_tstep, const Tuning &tuning)
Definition: AdaptiveTimeStepping_impl.hpp:343
TimeStepControlType time_step_control_type_
type of time step control object
Definition: AdaptiveTimeStepping.hpp:253
const TimeStepControlInterface & timeStepControl() const
Definition: AdaptiveTimeStepping_impl.hpp:322
bool full_timestep_initially_
beginning with the size of the time step from data file
Definition: AdaptiveTimeStepping.hpp:265
SimulatorReport step(const SimulatorTimer &simulator_timer, Solver &solver, const bool is_event, const TuningUpdateCallback &tuning_updater)
step method that acts like the solver::step method in a sub cycle of time steps
Definition: AdaptiveTimeStepping_impl.hpp:203
double growth_factor_
factor to multiply time step when solver recovered from failed convergence
Definition: AdaptiveTimeStepping.hpp:256
double restart_factor_
factor to multiply time step with when solver fails to converge
Definition: AdaptiveTimeStepping.hpp:255
double min_time_step_
minimal allowed time step size before throwing
Definition: AdaptiveTimeStepping.hpp:259
void updateNEXTSTEP(double max_next_tstep)
Definition: AdaptiveTimeStepping_impl.hpp:331
static AdaptiveTimeStepping< TypeTag > serializationTestObjectHardcoded()
Definition: AdaptiveTimeStepping_impl.hpp:265
AdaptiveTimeStepping()=default
TimeStepController time_step_control_
time step control object
Definition: AdaptiveTimeStepping.hpp:254
static AdaptiveTimeStepping< TypeTag > serializationTestObjectPIDIt()
Definition: AdaptiveTimeStepping_impl.hpp:281
double min_time_step_before_shutting_problematic_wells_
< shut problematic wells when time step size in days are less than this
Definition: AdaptiveTimeStepping.hpp:270
static AdaptiveTimeStepping< TypeTag > serializationTestObject3rdOrder()
Definition: AdaptiveTimeStepping_impl.hpp:297
SimulatorReport & report()
Definition: AdaptiveTimeStepping_impl.hpp:257
static AdaptiveTimeStepping< TypeTag > serializationTestObjectPID()
Definition: AdaptiveTimeStepping_impl.hpp:273
static void registerParameters()
Definition: AdaptiveTimeStepping_impl.hpp:185
bool use_newton_iteration_
use newton iteration count for adaptive time step control
Definition: AdaptiveTimeStepping.hpp:267
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:43
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