22#ifndef OPM_SIMULATOR_FULLY_IMPLICIT_IMPL_HEADER_INCLUDED
23#define OPM_SIMULATOR_FULLY_IMPLICIT_IMPL_HEADER_INCLUDED
26#ifndef OPM_SIMULATOR_FULLY_IMPLICIT_HEADER_INCLUDED
31#include <opm/input/eclipse/Units/UnitSystem.hpp>
37#include <fmt/format.h>
45template<
class TypeTag>
48 : simulator_(simulator)
51 simulator_.vanguard().eclState().getIOConfig(),
52 Parameters::
Get<Parameters::SaveStep>(),
53 Parameters::
Get<Parameters::LoadStep>(),
54 Parameters::
Get<Parameters::SaveFile>(),
55 Parameters::
Get<Parameters::LoadFile>())
59 if (this->
grid().comm().rank() == 0) {
60 this->
terminalOutput_ = Parameters::Get<Parameters::EnableTerminalOutput>();
63 [compNames =
typename Model::ComponentName{}](
const int compIdx)
64 {
return std::string_view { compNames.name(compIdx) }; }
67 if (!
simulator_.vanguard().eclState().getIOConfig().initOnly()) {
69 startThread(this->
simulator_.vanguard().eclState(),
70 Parameters::Get<Parameters::OutputExtraConvergenceInfo>(),
71 R
"(OutputExtraConvergenceInfo (--output-extra-convergence-info))",
77template<
class TypeTag>
82 convergence_output_.endThread();
85template<
class TypeTag>
90 ModelParameters::registerParameters();
91 SolverParameters::registerParameters();
92 TimeStepper::registerParameters();
99#ifdef RESERVOIR_COUPLING_ENABLED
100template<
class TypeTag>
105 init(timer, argc, argv);
107template<
class TypeTag>
117 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
119 while (!timer.
done()) {
120 simulator_.problem().writeReports(timer);
121 bool continue_looping = runStep(timer);
122 if (!continue_looping)
break;
124 simulator_.problem().writeReports(timer);
126#ifdef RESERVOIR_COUPLING_ENABLED
129 if (this->reservoirCouplingMaster_) {
130 this->reservoirCouplingMaster_->sendTerminateAndDisconnect();
132 else if (this->reservoirCouplingSlave_ && !this->reservoirCouplingSlave_->terminated()) {
142 this->reservoirCouplingSlave_->notifyEndOfRunAndDisconnect();
149#ifdef RESERVOIR_COUPLING_ENABLED
150template<
class TypeTag>
155 for (std::size_t report_step = 0; report_step < this->schedule().size(); ++report_step) {
156 auto rescoup = this->schedule()[report_step].rescoup();
157 auto slave_count = rescoup.slaveCount();
158 auto master_group_count = rescoup.masterGroupCount();
162 if (slave_count > 0) {
165 else if (master_group_count > 0) {
167 throw ReservoirCouplingError(
168 "Inconsistent reservoir coupling master schedule: "
169 "Master group count is greater than 0 but slave count is 0"
177#ifdef RESERVOIR_COUPLING_ENABLED
178template<
class TypeTag>
181init(
const SimulatorTimer& timer,
int argc,
char** argv)
183 auto slave_mode = Parameters::Get<Parameters::Slave>();
185 this->reservoirCouplingSlave_ =
186 std::make_unique<ReservoirCouplingSlave<Scalar>>(
188 this->schedule(), timer
190 this->reservoirCouplingSlave_->sendAndReceiveInitialData();
191 this->simulator_.setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
192 wellModel_().setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
195 auto master_mode = checkRunningAsReservoirCouplingMaster();
197 this->reservoirCouplingMaster_ =
198 std::make_unique<ReservoirCouplingMaster<Scalar>>(
203 this->simulator_.setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
204 wellModel_().setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
208template<
class TypeTag>
214 simulator_.setEpisodeIndex(-1);
217 solverTimer_ = std::make_unique<time::StopWatch>();
218 totalTimer_ = std::make_unique<time::StopWatch>();
219 totalTimer_->start();
222 bool enableAdaptive = Parameters::Get<Parameters::EnableAdaptiveTimeStepping>();
223 bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
224 if (enableAdaptive) {
225 const UnitSystem& unitSystem = this->simulator_.vanguard().eclState().getUnits();
227 auto max_next_tstep = sched_state.max_next_tstep(enableTUNING);
229 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(max_next_tstep,
230 sched_state.tuning(),
231 unitSystem, report_, terminalOutput_);
234 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(unitSystem, report_, max_next_tstep, terminalOutput_);
239 adaptiveTimeStepping_->setSuggestedNextStep(simulator_.timeStepSize());
244template<
class TypeTag>
249 modelParam_.tolerance_cnv_ = tuning.TRGCNV;
250 modelParam_.tolerance_cnv_relaxed_ = tuning.XXXCNV;
251 modelParam_.tolerance_mb_ = tuning.TRGMBE;
252 modelParam_.tolerance_mb_relaxed_ = tuning.XXXMBE;
253 modelParam_.newton_max_iter_ = tuning.NEWTMX;
254 modelParam_.newton_min_iter_ = tuning.NEWTMN;
255 if (terminalOutput_) {
260template<
class TypeTag>
266 modelParam_.tolerance_max_dp_ = tuning_dp.TRGDDP;
267 modelParam_.tolerance_max_ds_ = tuning_dp.TRGDDS;
268 modelParam_.tolerance_max_drs_ = tuning_dp.TRGDDRS;
269 modelParam_.tolerance_max_drv_ = tuning_dp.TRGDDRV;
272 if (terminalOutput_) {
274 if (tuning_dp.TRGLCV_has_value) {
275 OpmLog::warning(
"TUNINGDP item 1 (TRGLCV) is not supported.");
277 if (tuning_dp.XXXLCV_has_value) {
278 OpmLog::warning(
"TUNINGDP item 2 (XXXLCV) is not supported.");
283template<
class TypeTag>
288 if (schedule().exitStatus().has_value()) {
289 if (terminalOutput_) {
290 OpmLog::info(
"Stopping simulation since EXIT was triggered by an action keyword.");
292 report_.success.exit_status = schedule().exitStatus().value();
296 if (serializer_.shouldLoad()) {
297 serializer_.loadTimerInfo(timer);
301 if (terminalOutput_) {
302 std::ostringstream ss;
304 OpmLog::debug(ss.str());
310 Dune::Timer perfTimer;
313 simulator_.setEpisodeIndex(-1);
314 simulator_.setEpisodeLength(0.0);
315 simulator_.setTimeStepSize(0.0);
317 simulator_.problem().writeOutput(
true);
319 report_.success.output_write_time += perfTimer.stop();
323 solverTimer_->start();
326 solver_ = createSolver(wellModel_());
329 simulator_.startNextEpisode(
330 simulator_.startTime()
335 if (serializer_.shouldLoad()) {
336 wellModel_().prepareDeserialize(serializer_.loadStep() - 1);
337 serializer_.loadState();
338 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
345 if (restoreStateHook_) {
349 this->solver_->model().beginReportStep();
351 const bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
358 if (adaptiveTimeStepping_) {
359 auto tuningUpdater = [enableTUNING,
this,
361 double substep_length,
362 const int sub_step_number)
364 auto& schedule = this->simulator_.vanguard().schedule();
365 auto& events = this->schedule()[reportStep].events();
369 const double problem_max_next_tstep =
370 this->simulator_.problem().maxNextTimeStepSize();
371 const bool problem_caps =
372 problem_max_next_tstep < std::numeric_limits<double>::max();
374 bool result = problem_caps;
376 this->adaptiveTimeStepping_->updateNEXTSTEP(problem_max_next_tstep);
378 if (events.hasEvent(ScheduleEvents::TUNING_CHANGE)) {
380 schedule.clear_event(ScheduleEvents::TUNING_CHANGE, reportStep);
381 const auto& sched_state = schedule[reportStep];
382 double max_next_tstep = sched_state.max_next_tstep(enableTUNING);
387 max_next_tstep = (max_next_tstep > 0.0)
388 ? std::min(max_next_tstep, problem_max_next_tstep)
389 : problem_max_next_tstep;
391 const auto& tuning = sched_state.tuning();
394 adaptiveTimeStepping_->updateTUNING(max_next_tstep, tuning);
397 solver_->model().updateTUNING(tuning);
398 this->updateTUNING(tuning);
399 substep_length = this->adaptiveTimeStepping_->suggestedNextStep();
401 substep_length = max_next_tstep;
402 this->adaptiveTimeStepping_->updateNEXTSTEP(max_next_tstep);
404 result = max_next_tstep > 0;
407 if (events.hasEvent(ScheduleEvents::TUNINGDP_CHANGE)) {
409 schedule.clear_event(ScheduleEvents::TUNINGDP_CHANGE, reportStep);
414 const auto& sched_state = schedule[reportStep];
415 const auto& tuning_dp = sched_state.tuning_dp();
416 solver_->model().updateTUNINGDP(tuning_dp);
417 this->updateTUNINGDP(tuning_dp);
420 const auto& wcycle = schedule[reportStep].wcycle.get();
421 if (wcycle.empty()) {
425 const auto& wmatcher = schedule.wellMatcher(reportStep);
426 double wcycle_time_step =
427 wcycle.nextTimeStep(curr_time,
430 this->wellModel_().wellOpenTimes(),
431 this->wellModel_().wellCloseTimes(),
433 &wg_events = this->wellModel_().reportStepStartEvents()]
434 (
const std::string& name)
436 if (sub_step_number != 0) {
439 return wg_events.hasEvent(name, ScheduleEvents::REQUEST_OPEN_WELL);
442 wcycle_time_step = this->grid().comm().min(wcycle_time_step);
443 if (substep_length != wcycle_time_step) {
444 this->adaptiveTimeStepping_->updateNEXTSTEP(wcycle_time_step);
452 this->adaptiveTimeStepping_->suggestedNextStep(), 0);
454#ifdef RESERVOIR_COUPLING_ENABLED
455 if (this->reservoirCouplingMaster_) {
456 this->reservoirCouplingMaster_->maybeSpawnSlaveProcesses(timer.
currentStepNum());
457 this->reservoirCouplingMaster_->maybeActivate(timer.
currentStepNum());
459 else if (this->reservoirCouplingSlave_) {
460 this->reservoirCouplingSlave_->maybeActivate(timer.
currentStepNum());
464 bool event = events.hasEvent(ScheduleEvents::NEW_WELL) ||
465 events.hasEvent(ScheduleEvents::INJECTION_TYPE_CHANGED) ||
466 events.hasEvent(ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER) ||
467 events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE) ||
468 events.hasEvent(ScheduleEvents::INJECTION_UPDATE) ||
469 events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE);
470 auto stepReport = adaptiveTimeStepping_->step(timer, *solver_, event, tuningUpdater);
471 report_ += stepReport;
472#ifdef RESERVOIR_COUPLING_ENABLED
479 if (this->reservoirCouplingSlave_ && this->reservoirCouplingSlave_->terminated()) {
480 this->handleSlaveTerminated_();
486 auto stepReport = solver_->step(timer,
nullptr);
487 report_ += stepReport;
489 simulator_.problem().setSubStepReport(stepReport);
490 simulator_.problem().setSimulationReport(report_);
491 simulator_.problem().endTimeStep();
492 if (terminalOutput_) {
493 std::ostringstream ss;
494 stepReport.reportStep(ss);
495 OpmLog::info(ss.str());
500 Dune::Timer perfTimer;
502 const double nextstep = adaptiveTimeStepping_ ? adaptiveTimeStepping_->suggestedNextStep() : -1.0;
503 simulator_.problem().setNextTimeStepSize(nextstep);
504 simulator_.problem().writeOutput(
true);
505 report_.success.output_write_time += perfTimer.stop();
507 solver_->model().endReportStep();
510 solverTimer_->stop();
513 report_.success.solver_time += solverTimer_->secsSinceStart();
515 if (this->grid().comm().rank() == 0) {
518 const auto& reps = this->solver_->model().stepReports();
519 convergence_output_.write(reps);
525 if (terminalOutput_) {
527 "Time step took " +
std::to_string(solverTimer_->secsSinceStart()) +
" seconds; "
528 "total solver time " +
std::to_string(report_.success.solver_time) +
" seconds.";
532 serializer_.save(timer);
537#ifdef RESERVOIR_COUPLING_ENABLED
538template<
class TypeTag>
543 if (terminalOutput_) {
544 OpmLog::info(
"Reservoir coupling: master simulation has ended; "
545 "stopping slave simulation gracefully.");
553 this->solver_->model().endReportStep();
556 this->solverTimer_->stop();
557 this->report_.success.solver_time += this->solverTimer_->secsSinceStart();
561template<
class TypeTag>
568 Dune::Timer finalOutputTimer;
569 finalOutputTimer.start();
571 simulator_.problem().finalizeOutput();
577 report_.success.total_time = totalTimer_->secsSinceStart();
578 report_.success.converged =
true;
583template<
class TypeTag>
584template<
class Serializer>
589 serializer(simulator_);
591 serializer(adaptiveTimeStepping_);
594template<
class TypeTag>
598 [[maybe_unused]]
const std::string& groupName)
601 serializer.read(*
this, groupName,
"simulator_data");
605template<
class TypeTag>
609 [[maybe_unused]]
const std::string& groupName)
const
612 serializer.write(*
this, groupName,
"simulator_data");
616template<
class TypeTag>
617std::array<std::string,5>
621 std::ostringstream str;
626 simulator_.vanguard().caseName(),
630template<
class TypeTag>
631std::unique_ptr<typename SimulatorFullyImplicit<TypeTag>::Solver>
635 auto model = std::make_unique<Model>(simulator_,
640 if (this->modelParam_.write_partitions_) {
641 const auto& iocfg = this->eclState().cfg().io();
643 const auto odir = iocfg.getOutputDir()
644 / std::filesystem::path {
"partition" }
645 / iocfg.getBaseName();
647 if (this->grid().comm().rank() == 0) {
648 create_directories(odir);
651 this->grid().comm().barrier();
653 model->writePartitions(odir);
655 this->modelParam_.write_partitions_ =
false;
658 return std::make_unique<Solver>(solverParam_, std::move(model));
std::function< std::string_view(int)> ComponentToPhaseName
Definition: ExtraConvergenceOutputThread.hpp:109
Definition: FlowGenericVanguard.hpp:108
static Parallel::Communication & comm()
Obtain global communicator.
Definition: FlowGenericVanguard.hpp:336
Class for (de-)serializing using HDF5.
Definition: HDF5Serializer.hpp:37
Top-level driver for a fully implicit flow simulation.
Definition: SimulatorFullyImplicit.hpp:115
SimulatorReport finalize()
Stop the timers and emit the final OPMRST output.
Definition: SimulatorFullyImplicit_impl.hpp:564
void init(const SimulatorTimer &timer)
One-shot setup performed before the first runStep.
Definition: SimulatorFullyImplicit_impl.hpp:211
void serializeOp(Serializer &serializer)
Definition: SimulatorFullyImplicit_impl.hpp:587
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: SimulatorFullyImplicit.hpp:119
void saveState(HDF5Serializer &serializer, const std::string &groupName) const override
Save this simulator's data block to an OPMRST file via HDF5.
Definition: SimulatorFullyImplicit_impl.hpp:608
SimulatorReport run(SimulatorTimer &timer)
Run the entire simulation to completion.
Definition: SimulatorFullyImplicit_impl.hpp:110
SimulatorFullyImplicit(Simulator &simulator)
Construct from the surrounding eWoms Simulator.
Definition: SimulatorFullyImplicit_impl.hpp:47
std::unique_ptr< Solver > createSolver(WellModel &wellModel)
Build the Solver used during the current report step.
Definition: SimulatorFullyImplicit_impl.hpp:633
bool terminalOutput_
Emit high-level progress to std::cout (rank 0 only).
Definition: SimulatorFullyImplicit.hpp:376
void updateTUNINGDP(const TuningDp &tuning_dp)
Apply a TUNINGDP keyword to the cached model parameters.
Definition: SimulatorFullyImplicit_impl.hpp:263
void loadState(HDF5Serializer &serializer, const std::string &groupName) override
Load this simulator's data block from an OPMRST file via HDF5.
Definition: SimulatorFullyImplicit_impl.hpp:597
std::array< std::string, 5 > getHeader() const override
Definition: SimulatorFullyImplicit_impl.hpp:619
static void registerParameters()
Register all parameters consumed by this class and its major collaborators.
Definition: SimulatorFullyImplicit_impl.hpp:88
SimulatorConvergenceOutput convergence_output_
Background thread for INFOSTEP / INFOITER files.
Definition: SimulatorFullyImplicit.hpp:391
Simulator & simulator_
Surrounding eWoms simulator; observed, not owned.
Definition: SimulatorFullyImplicit.hpp:364
~SimulatorFullyImplicit() override
Ends the convergence-output thread cleanly on all ranks.
Definition: SimulatorFullyImplicit_impl.hpp:79
const Grid & grid() const
Definition: SimulatorFullyImplicit.hpp:302
void updateTUNING(const Tuning &tuning)
Apply a TUNING keyword to the cached model parameters.
Definition: SimulatorFullyImplicit_impl.hpp:247
GetPropType< TypeTag, Properties::WellModel > WellModel
Definition: SimulatorFullyImplicit.hpp:141
bool runStep(SimulatorTimer &timer)
Advance the simulation by one report step.
Definition: SimulatorFullyImplicit_impl.hpp:286
Definition: SimulatorTimer.hpp:38
double currentStepLength() const override
bool initialStep() const override
Whether the current step is the first step.
void report(std::ostream &os) const
double simulationTimeElapsed() const override
int currentStepNum() const override
bool done() const override
Return true if op++() has been called numSteps() times.
void printValues(std::ostream &os)
Print values of the run-time parameters.
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hpp:191
void logTuning(const Tuning &tuning)
Log tuning parameters.
void registerSimulatorParameters()
void outputReportStep(const SimulatorTimer &timer)
Definition: blackoilbioeffectsmodules.hh:45
std::string compileTimestamp()
std::string moduleVersion()
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
Definition: SimulatorReport.hpp:125
SimulatorReportSingle success
Definition: SimulatorReport.hpp:126
double output_write_time
Definition: SimulatorReport.hpp:46
static void registerParameters()
static void registerParameters()