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>
86 if (this->solver_ !=
nullptr) {
88 this->convergence_output_.write(this->solver_->model().stepReports());
95 convergence_output_.endThread();
98template<
class TypeTag>
103 ModelParameters::registerParameters();
104 SolverParameters::registerParameters();
105 TimeStepper::registerParameters();
112#ifdef RESERVOIR_COUPLING_ENABLED
113template<
class TypeTag>
118 init(timer, argc, argv);
120template<
class TypeTag>
130 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
132 while (!timer.
done()) {
133 simulator_.problem().writeReports(timer);
134 bool continue_looping = runStep(timer);
135 if (!continue_looping)
break;
137 simulator_.problem().writeReports(timer);
139#ifdef RESERVOIR_COUPLING_ENABLED
142 if (this->reservoirCouplingMaster_) {
143 this->reservoirCouplingMaster_->sendTerminateAndDisconnect();
145 else if (this->reservoirCouplingSlave_ && !this->reservoirCouplingSlave_->terminated()) {
155 this->reservoirCouplingSlave_->notifyEndOfRunAndDisconnect();
162#ifdef RESERVOIR_COUPLING_ENABLED
163template<
class TypeTag>
168 for (std::size_t report_step = 0; report_step < this->schedule().size(); ++report_step) {
169 auto rescoup = this->schedule()[report_step].rescoup();
170 auto slave_count = rescoup.slaveCount();
171 auto master_group_count = rescoup.masterGroupCount();
175 if (slave_count > 0) {
178 else if (master_group_count > 0) {
180 throw ReservoirCouplingError(
181 "Inconsistent reservoir coupling master schedule: "
182 "Master group count is greater than 0 but slave count is 0"
190#ifdef RESERVOIR_COUPLING_ENABLED
191template<
class TypeTag>
194init(
const SimulatorTimer& timer,
int argc,
char** argv)
196 auto slave_mode = Parameters::Get<Parameters::Slave>();
198 this->reservoirCouplingSlave_ =
199 std::make_unique<ReservoirCouplingSlave<Scalar>>(
201 this->schedule(), timer
203 this->reservoirCouplingSlave_->sendAndReceiveInitialData();
204 this->simulator_.setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
205 wellModel_().setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
208 auto master_mode = checkRunningAsReservoirCouplingMaster();
210 this->reservoirCouplingMaster_ =
211 std::make_unique<ReservoirCouplingMaster<Scalar>>(
216 this->simulator_.setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
217 wellModel_().setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
221template<
class TypeTag>
227 simulator_.setEpisodeIndex(-1);
230 solverTimer_ = std::make_unique<time::StopWatch>();
231 totalTimer_ = std::make_unique<time::StopWatch>();
232 totalTimer_->start();
235 bool enableAdaptive = Parameters::Get<Parameters::EnableAdaptiveTimeStepping>();
236 bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
237 if (enableAdaptive) {
238 const UnitSystem& unitSystem = this->simulator_.vanguard().eclState().getUnits();
240 auto max_next_tstep = sched_state.max_next_tstep(enableTUNING);
242 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(max_next_tstep,
243 sched_state.tuning(),
244 unitSystem, report_, terminalOutput_);
247 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(unitSystem, report_, max_next_tstep, terminalOutput_);
252 adaptiveTimeStepping_->setSuggestedNextStep(simulator_.timeStepSize());
260 this->updateTUNING(sched_state.tuning());
266template<
class TypeTag>
271 modelParam_.tolerance_cnv_ = tuning.TRGCNV;
272 modelParam_.tolerance_cnv_relaxed_ = tuning.XXXCNV;
273 modelParam_.tolerance_mb_ = tuning.TRGMBE;
274 modelParam_.tolerance_mb_relaxed_ = tuning.XXXMBE;
275 modelParam_.newton_max_iter_ = tuning.NEWTMX;
276 modelParam_.newton_min_iter_ = tuning.NEWTMN;
277 if (terminalOutput_) {
282template<
class TypeTag>
288 modelParam_.tolerance_max_dp_ = tuning_dp.TRGDDP;
289 modelParam_.tolerance_max_ds_ = tuning_dp.TRGDDS;
290 modelParam_.tolerance_max_drs_ = tuning_dp.TRGDDRS;
291 modelParam_.tolerance_max_drv_ = tuning_dp.TRGDDRV;
294 if (terminalOutput_) {
296 if (tuning_dp.TRGLCV_has_value) {
297 OpmLog::warning(
"TUNINGDP item 1 (TRGLCV) is not supported.");
299 if (tuning_dp.XXXLCV_has_value) {
300 OpmLog::warning(
"TUNINGDP item 2 (XXXLCV) is not supported.");
305template<
class TypeTag>
310 if (schedule().exitStatus().has_value()) {
311 if (terminalOutput_) {
312 OpmLog::info(
"Stopping simulation since EXIT was triggered by an action keyword.");
314 report_.success.exit_status = schedule().exitStatus().value();
318 if (serializer_.shouldLoad()) {
319 serializer_.loadTimerInfo(timer);
323 if (terminalOutput_) {
324 std::ostringstream ss;
326 OpmLog::debug(ss.str());
331 if (timer.
initialStep() && !serializer_.shouldLoad()) {
332 Dune::Timer perfTimer;
335 simulator_.setEpisodeIndex(-1);
336 simulator_.setEpisodeLength(0.0);
337 simulator_.setTimeStepSize(0.0);
339 simulator_.problem().writeOutput(
true);
341 report_.success.output_write_time += perfTimer.stop();
344 simulator_.startNextEpisode(
345 simulator_.startTime()
350 if (serializer_.shouldLoad()) {
351 wellModel_().prepareDeserialize(serializer_.loadStep() - 1);
352 serializer_.loadState();
353 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
354 simulator_.model().rebuildStorageCache(0);
355 if (simulator_.problem().intensiveQuantityHistorySize() > 1) {
356 simulator_.model().invalidateAndUpdateIntensiveQuantities(1);
357 simulator_.model().rebuildStorageCache(1);
363 solverTimer_->start();
366 solver_ = createSolver(wellModel_());
373 if (restoreStateHook_) {
377 this->solver_->model().beginReportStep();
379 const bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
386 if (adaptiveTimeStepping_) {
387 auto tuningUpdater = [enableTUNING,
this,
389 double substep_length,
390 const int sub_step_number)
392 auto& schedule = this->simulator_.vanguard().schedule();
393 auto& events = this->schedule()[reportStep].events();
397 const double problem_max_next_tstep =
398 this->simulator_.problem().maxNextTimeStepSize();
399 const bool problem_caps =
400 problem_max_next_tstep < std::numeric_limits<double>::max();
402 bool result = problem_caps;
404 this->adaptiveTimeStepping_->updateNEXTSTEP(problem_max_next_tstep);
406 if (events.hasEvent(ScheduleEvents::TUNING_CHANGE)) {
408 schedule.clear_event(ScheduleEvents::TUNING_CHANGE, reportStep);
409 const auto& sched_state = schedule[reportStep];
410 double max_next_tstep = sched_state.max_next_tstep(enableTUNING);
415 max_next_tstep = (max_next_tstep > 0.0)
416 ? std::min(max_next_tstep, problem_max_next_tstep)
417 : problem_max_next_tstep;
419 const auto& tuning = sched_state.tuning();
422 adaptiveTimeStepping_->updateTUNING(max_next_tstep, tuning);
425 solver_->model().updateTUNING(tuning);
426 this->updateTUNING(tuning);
427 substep_length = this->adaptiveTimeStepping_->suggestedNextStep();
429 substep_length = max_next_tstep;
430 this->adaptiveTimeStepping_->updateNEXTSTEP(max_next_tstep);
432 result = max_next_tstep > 0;
435 if (events.hasEvent(ScheduleEvents::TUNINGDP_CHANGE)) {
437 schedule.clear_event(ScheduleEvents::TUNINGDP_CHANGE, reportStep);
442 const auto& sched_state = schedule[reportStep];
443 const auto& tuning_dp = sched_state.tuning_dp();
444 solver_->model().updateTUNINGDP(tuning_dp);
445 this->updateTUNINGDP(tuning_dp);
448 const auto& wcycle = schedule[reportStep].wcycle.get();
449 if (wcycle.empty()) {
453 const auto& wmatcher = schedule.wellMatcher(reportStep);
454 double wcycle_time_step =
455 wcycle.nextTimeStep(curr_time,
458 this->wellModel_().wellOpenTimes(),
459 this->wellModel_().wellCloseTimes(),
461 &wg_events = this->wellModel_().reportStepStartEvents()]
462 (
const std::string& name)
464 if (sub_step_number != 0) {
467 return wg_events.hasEvent(name, ScheduleEvents::REQUEST_OPEN_WELL);
470 wcycle_time_step = this->grid().comm().min(wcycle_time_step);
471 if (substep_length != wcycle_time_step) {
472 this->adaptiveTimeStepping_->updateNEXTSTEP(wcycle_time_step);
480 this->adaptiveTimeStepping_->suggestedNextStep(), 0);
482#ifdef RESERVOIR_COUPLING_ENABLED
483 if (this->reservoirCouplingMaster_) {
484 this->reservoirCouplingMaster_->maybeSpawnSlaveProcesses(timer.
currentStepNum());
485 this->reservoirCouplingMaster_->maybeActivate(timer.
currentStepNum());
487 else if (this->reservoirCouplingSlave_) {
488 this->reservoirCouplingSlave_->maybeActivate(timer.
currentStepNum());
492 bool event = events.hasEvent(ScheduleEvents::NEW_WELL) ||
493 events.hasEvent(ScheduleEvents::INJECTION_TYPE_CHANGED) ||
494 events.hasEvent(ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER) ||
495 events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE) ||
496 events.hasEvent(ScheduleEvents::INJECTION_UPDATE) ||
497 events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE);
498 auto stepReport = adaptiveTimeStepping_->step(timer, *solver_, event, tuningUpdater);
499 report_ += stepReport;
500#ifdef RESERVOIR_COUPLING_ENABLED
507 if (this->reservoirCouplingSlave_ && this->reservoirCouplingSlave_->terminated()) {
508 this->handleSlaveTerminated_();
514 auto stepReport = solver_->step(timer,
nullptr);
515 report_ += stepReport;
517 simulator_.problem().setSubStepReport(stepReport);
518 simulator_.problem().setSimulationReport(report_);
519 simulator_.problem().endTimeStep();
520 if (terminalOutput_) {
521 std::ostringstream ss;
522 stepReport.reportStep(ss);
523 OpmLog::info(ss.str());
528 Dune::Timer perfTimer;
530 const double nextstep = adaptiveTimeStepping_ ? adaptiveTimeStepping_->suggestedNextStep() : -1.0;
531 simulator_.problem().setNextTimeStepSize(nextstep);
532 simulator_.problem().writeOutput(
true);
533 report_.success.output_write_time += perfTimer.stop();
535 solver_->model().endReportStep();
538 solverTimer_->stop();
541 report_.success.solver_time += solverTimer_->secsSinceStart();
543 if (this->grid().comm().rank() == 0) {
546 const auto& reps = this->solver_->model().stepReports();
547 convergence_output_.write(reps);
553 if (terminalOutput_) {
555 "Time step took " +
std::to_string(solverTimer_->secsSinceStart()) +
" seconds; "
556 "total solver time " +
std::to_string(report_.success.solver_time) +
" seconds.";
560 serializer_.save(timer);
565#ifdef RESERVOIR_COUPLING_ENABLED
566template<
class TypeTag>
571 if (terminalOutput_) {
572 OpmLog::info(
"Reservoir coupling: master simulation has ended; "
573 "stopping slave simulation gracefully.");
581 this->solver_->model().endReportStep();
584 this->solverTimer_->stop();
585 this->report_.success.solver_time += this->solverTimer_->secsSinceStart();
589template<
class TypeTag>
596 Dune::Timer finalOutputTimer;
597 finalOutputTimer.start();
599 simulator_.problem().finalizeOutput();
605 report_.success.total_time = totalTimer_->secsSinceStart();
606 report_.success.converged =
true;
611template<
class TypeTag>
612template<
class Serializer>
617 serializer(simulator_);
619 serializer(adaptiveTimeStepping_);
620 serializer(modelParam_);
623template<
class TypeTag>
627 [[maybe_unused]]
const std::string& groupName)
630 serializer.read(*
this, groupName,
"simulator_data");
634template<
class TypeTag>
638 [[maybe_unused]]
const std::string& groupName)
const
641 serializer.write(*
this, groupName,
"simulator_data");
645template<
class TypeTag>
646std::array<std::string,5>
650 std::ostringstream str;
655 simulator_.vanguard().caseName(),
659template<
class TypeTag>
660std::unique_ptr<typename SimulatorFullyImplicit<TypeTag>::Solver>
664 auto model = std::make_unique<Model>(simulator_,
669 if (this->modelParam_.write_partitions_) {
670 const auto& iocfg = this->eclState().cfg().io();
672 const auto odir = iocfg.getOutputDir()
673 / std::filesystem::path {
"partition" }
674 / iocfg.getBaseName();
676 if (this->grid().comm().rank() == 0) {
677 create_directories(odir);
680 this->grid().comm().barrier();
682 model->writePartitions(odir);
684 this->modelParam_.write_partitions_ =
false;
687 return std::make_unique<Solver>(solverParam_, std::move(model));
std::function< std::string_view(int)> ComponentToPhaseName
Definition: ExtraConvergenceOutputThread.hpp:116
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:592
void init(const SimulatorTimer &timer)
One-shot setup performed before the first runStep.
Definition: SimulatorFullyImplicit_impl.hpp:224
void serializeOp(Serializer &serializer)
Definition: SimulatorFullyImplicit_impl.hpp:615
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:637
SimulatorReport run(SimulatorTimer &timer)
Run the entire simulation to completion.
Definition: SimulatorFullyImplicit_impl.hpp:123
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:662
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:285
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:626
std::array< std::string, 5 > getHeader() const override
Definition: SimulatorFullyImplicit_impl.hpp:648
static void registerParameters()
Register all parameters consumed by this class and its major collaborators.
Definition: SimulatorFullyImplicit_impl.hpp:101
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:269
GetPropType< TypeTag, Properties::WellModel > WellModel
Definition: SimulatorFullyImplicit.hpp:141
bool runStep(SimulatorTimer &timer)
Advance the simulation by one report step.
Definition: SimulatorFullyImplicit_impl.hpp:308
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:192
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:202
SimulatorReportSingle success
Definition: SimulatorReport.hpp:203
double output_write_time
Definition: SimulatorReport.hpp:46
static void registerParameters()
static void registerParameters()