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 28 #include <opm/simulators/flow/SimulatorFullyImplicit.hpp> 31 #include <opm/input/eclipse/Units/UnitSystem.hpp> 33 #include <opm/models/tpsa/tpsanewtonmethodparams.hpp> 35 #include <opm/simulators/linalg/TPSALinearSolverParameters.hpp> 37 #include <fmt/format.h> 44 template<
class TypeTag>
47 : simulator_(simulator)
50 simulator_.vanguard().eclState().getIOConfig(),
51 Parameters::Get<Parameters::SaveStep>(),
52 Parameters::Get<Parameters::LoadStep>(),
53 Parameters::Get<Parameters::SaveFile>(),
54 Parameters::Get<Parameters::LoadFile>())
58 if (this->grid().comm().rank() == 0) {
59 this->
terminalOutput_ = Parameters::Get<Parameters::EnableTerminalOutput>();
62 [compNames =
typename Model::ComponentName{}](
const int compIdx)
63 {
return std::string_view { compNames.name(compIdx) }; }
66 if (!
simulator_.vanguard().eclState().getIOConfig().initOnly()) {
68 startThread(this->
simulator_.vanguard().eclState(),
69 Parameters::Get<Parameters::OutputExtraConvergenceInfo>(),
70 R
"(OutputExtraConvergenceInfo (--output-extra-convergence-info))", 76 template<
class TypeTag>
81 convergence_output_.endThread();
84 template<
class TypeTag>
89 ModelParameters::registerParameters();
90 SolverParameters::registerParameters();
91 TimeStepper::registerParameters();
92 detail::registerSimulatorParameters();
98 #ifdef RESERVOIR_COUPLING_ENABLED 99 template<
class TypeTag>
104 init(timer, argc, argv);
106 template<
class TypeTag>
116 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
118 while (!timer.
done()) {
119 simulator_.problem().writeReports(timer);
120 bool continue_looping = runStep(timer);
121 if (!continue_looping)
break;
123 simulator_.problem().writeReports(timer);
125 #ifdef RESERVOIR_COUPLING_ENABLED 128 if (this->reservoirCouplingMaster_) {
129 this->reservoirCouplingMaster_->sendTerminateAndDisconnect();
131 else if (this->reservoirCouplingSlave_ && !this->reservoirCouplingSlave_->terminated()) {
135 this->reservoirCouplingSlave_->receiveTerminateAndDisconnect();
142 #ifdef RESERVOIR_COUPLING_ENABLED 143 template<
class TypeTag>
148 for (std::size_t report_step = 0; report_step < this->schedule().size(); ++report_step) {
149 auto rescoup = this->schedule()[report_step].rescoup();
150 auto slave_count = rescoup.slaveCount();
151 auto master_group_count = rescoup.masterGroupCount();
155 if (slave_count > 0) {
158 else if (master_group_count > 0) {
160 throw ReservoirCouplingError(
161 "Inconsistent reservoir coupling master schedule: " 162 "Master group count is greater than 0 but slave count is 0" 170 #ifdef RESERVOIR_COUPLING_ENABLED 171 template<
class TypeTag>
174 init(
const SimulatorTimer& timer,
int argc,
char** argv)
176 auto slave_mode = Parameters::Get<Parameters::Slave>();
178 this->reservoirCouplingSlave_ =
179 std::make_unique<ReservoirCouplingSlave<Scalar>>(
181 this->schedule(), timer
183 this->reservoirCouplingSlave_->sendAndReceiveInitialData();
184 this->simulator_.setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
185 wellModel_().setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
188 auto master_mode = checkRunningAsReservoirCouplingMaster();
190 this->reservoirCouplingMaster_ =
191 std::make_unique<ReservoirCouplingMaster<Scalar>>(
196 this->simulator_.setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
197 wellModel_().setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
201 template<
class TypeTag>
207 simulator_.setEpisodeIndex(-1);
210 solverTimer_ = std::make_unique<time::StopWatch>();
211 totalTimer_ = std::make_unique<time::StopWatch>();
212 totalTimer_->start();
215 bool enableAdaptive = Parameters::Get<Parameters::EnableAdaptiveTimeStepping>();
216 bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
217 if (enableAdaptive) {
218 const UnitSystem& unitSystem = this->simulator_.vanguard().eclState().getUnits();
220 auto max_next_tstep = sched_state.max_next_tstep(enableTUNING);
222 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(max_next_tstep,
223 sched_state.tuning(),
224 unitSystem, report_, terminalOutput_);
227 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(unitSystem, report_, max_next_tstep, terminalOutput_);
232 adaptiveTimeStepping_->setSuggestedNextStep(simulator_.timeStepSize());
237 template<
class TypeTag>
242 modelParam_.tolerance_cnv_ = tuning.TRGCNV;
243 modelParam_.tolerance_cnv_relaxed_ = tuning.XXXCNV;
244 modelParam_.tolerance_mb_ = tuning.TRGMBE;
245 modelParam_.tolerance_mb_relaxed_ = tuning.XXXMBE;
246 modelParam_.newton_max_iter_ = tuning.NEWTMX;
247 modelParam_.newton_min_iter_ = tuning.NEWTMN;
248 if (terminalOutput_) {
249 detail::logTuning(tuning);
253 template<
class TypeTag>
259 modelParam_.tolerance_max_dp_ = tuning_dp.TRGDDP;
260 modelParam_.tolerance_max_ds_ = tuning_dp.TRGDDS;
261 modelParam_.tolerance_max_drs_ = tuning_dp.TRGDDRS;
262 modelParam_.tolerance_max_drv_ = tuning_dp.TRGDDRV;
265 if (terminalOutput_) {
267 if (tuning_dp.TRGLCV_has_value) {
268 OpmLog::warning(
"TUNINGDP item 1 (TRGLCV) is not supported.");
270 if (tuning_dp.XXXLCV_has_value) {
271 OpmLog::warning(
"TUNINGDP item 2 (XXXLCV) is not supported.");
276 template<
class TypeTag>
281 if (schedule().exitStatus().has_value()) {
282 if (terminalOutput_) {
283 OpmLog::info(
"Stopping simulation since EXIT was triggered by an action keyword.");
285 report_.success.exit_status = schedule().exitStatus().value();
289 if (serializer_.shouldLoad()) {
290 serializer_.loadTimerInfo(timer);
294 if (terminalOutput_) {
295 std::ostringstream ss;
297 OpmLog::debug(ss.str());
298 details::outputReportStep(timer);
303 Dune::Timer perfTimer;
306 simulator_.setEpisodeIndex(-1);
307 simulator_.setEpisodeLength(0.0);
308 simulator_.setTimeStepSize(0.0);
310 simulator_.problem().writeOutput(
true);
312 report_.success.output_write_time += perfTimer.stop();
316 solverTimer_->start();
319 solver_ = createSolver(wellModel_());
322 simulator_.startNextEpisode(
323 simulator_.startTime()
328 if (serializer_.shouldLoad()) {
329 wellModel_().prepareDeserialize(serializer_.loadStep() - 1);
330 serializer_.loadState();
331 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
334 this->solver_->model().beginReportStep();
336 const bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
343 if (adaptiveTimeStepping_) {
344 auto tuningUpdater = [enableTUNING,
this,
346 double substep_length,
347 const int sub_step_number)
349 auto& schedule = this->simulator_.vanguard().schedule();
350 auto& events = this->schedule()[reportStep].events();
353 if (events.hasEvent(ScheduleEvents::TUNING_CHANGE)) {
355 schedule.clear_event(ScheduleEvents::TUNING_CHANGE, reportStep);
356 const auto& sched_state = schedule[reportStep];
357 const auto& max_next_tstep = sched_state.max_next_tstep(enableTUNING);
358 const auto& tuning = sched_state.tuning();
361 adaptiveTimeStepping_->updateTUNING(max_next_tstep, tuning);
364 solver_->model().updateTUNING(tuning);
365 this->updateTUNING(tuning);
366 substep_length = this->adaptiveTimeStepping_->suggestedNextStep();
368 substep_length = max_next_tstep;
369 this->adaptiveTimeStepping_->updateNEXTSTEP(max_next_tstep);
371 result = max_next_tstep > 0;
374 if (events.hasEvent(ScheduleEvents::TUNINGDP_CHANGE)) {
376 schedule.clear_event(ScheduleEvents::TUNINGDP_CHANGE, reportStep);
381 const auto& sched_state = schedule[reportStep];
382 const auto& tuning_dp = sched_state.tuning_dp();
383 solver_->model().updateTUNINGDP(tuning_dp);
384 this->updateTUNINGDP(tuning_dp);
387 const auto& wcycle = schedule[reportStep].wcycle.get();
388 if (wcycle.empty()) {
392 const auto& wmatcher = schedule.wellMatcher(reportStep);
393 double wcycle_time_step =
394 wcycle.nextTimeStep(curr_time,
397 this->wellModel_().wellOpenTimes(),
398 this->wellModel_().wellCloseTimes(),
400 &wg_events = this->wellModel_().reportStepStartEvents()]
401 (
const std::string& name)
403 if (sub_step_number != 0) {
406 return wg_events.hasEvent(name, ScheduleEvents::REQUEST_OPEN_WELL);
409 wcycle_time_step = this->grid().comm().min(wcycle_time_step);
410 if (substep_length != wcycle_time_step) {
411 this->adaptiveTimeStepping_->updateNEXTSTEP(wcycle_time_step);
419 this->adaptiveTimeStepping_->suggestedNextStep(), 0);
421 #ifdef RESERVOIR_COUPLING_ENABLED 422 if (this->reservoirCouplingMaster_) {
423 this->reservoirCouplingMaster_->maybeSpawnSlaveProcesses(timer.
currentStepNum());
424 this->reservoirCouplingMaster_->maybeActivate(timer.
currentStepNum());
426 else if (this->reservoirCouplingSlave_) {
427 this->reservoirCouplingSlave_->maybeActivate(timer.
currentStepNum());
431 bool event = events.hasEvent(ScheduleEvents::NEW_WELL) ||
432 events.hasEvent(ScheduleEvents::INJECTION_TYPE_CHANGED) ||
433 events.hasEvent(ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER) ||
434 events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE) ||
435 events.hasEvent(ScheduleEvents::INJECTION_UPDATE) ||
436 events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE);
437 auto stepReport = adaptiveTimeStepping_->step(timer, *solver_, event, tuningUpdater);
438 report_ += stepReport;
439 #ifdef RESERVOIR_COUPLING_ENABLED 446 if (this->reservoirCouplingSlave_ && this->reservoirCouplingSlave_->terminated()) {
447 this->handleSlaveTerminated_();
453 auto stepReport = solver_->step(timer,
nullptr);
454 report_ += stepReport;
456 simulator_.problem().setSubStepReport(stepReport);
457 simulator_.problem().setSimulationReport(report_);
458 simulator_.problem().endTimeStep();
459 if (terminalOutput_) {
460 std::ostringstream ss;
461 stepReport.reportStep(ss);
462 OpmLog::info(ss.str());
467 Dune::Timer perfTimer;
469 const double nextstep = adaptiveTimeStepping_ ? adaptiveTimeStepping_->suggestedNextStep() : -1.0;
470 simulator_.problem().setNextTimeStepSize(nextstep);
471 simulator_.problem().writeOutput(
true);
472 report_.success.output_write_time += perfTimer.stop();
474 solver_->model().endReportStep();
477 solverTimer_->stop();
480 report_.success.solver_time += solverTimer_->secsSinceStart();
482 if (this->grid().comm().rank() == 0) {
485 const auto& reps = this->solver_->model().stepReports();
486 convergence_output_.write(reps);
492 if (terminalOutput_) {
494 "Time step took " + std::to_string(solverTimer_->secsSinceStart()) +
" seconds; " 495 "total solver time " + std::to_string(report_.success.solver_time) +
" seconds.";
499 serializer_.save(timer);
504 #ifdef RESERVOIR_COUPLING_ENABLED 505 template<
class TypeTag>
510 if (terminalOutput_) {
511 OpmLog::info(
"Reservoir coupling: master simulation has ended; " 512 "stopping slave simulation gracefully.");
520 this->solver_->model().endReportStep();
523 this->solverTimer_->stop();
524 this->report_.success.solver_time += this->solverTimer_->secsSinceStart();
528 template<
class TypeTag>
535 Dune::Timer finalOutputTimer;
536 finalOutputTimer.start();
538 simulator_.problem().finalizeOutput();
539 report_.success.output_write_time += finalOutputTimer.stop();
544 report_.success.total_time = totalTimer_->secsSinceStart();
545 report_.success.converged =
true;
550 template<
class TypeTag>
551 template<
class Serializer>
556 serializer(simulator_);
558 serializer(adaptiveTimeStepping_);
561 template<
class TypeTag>
565 [[maybe_unused]]
const std::string& groupName)
568 serializer.read(*
this, groupName,
"simulator_data");
572 template<
class TypeTag>
576 [[maybe_unused]]
const std::string& groupName)
const 579 serializer.write(*
this, groupName,
"simulator_data");
583 template<
class TypeTag>
584 std::array<std::string,5>
588 std::ostringstream str;
589 Parameters::printValues(str);
593 simulator_.vanguard().caseName(),
597 template<
class TypeTag>
598 std::unique_ptr<typename SimulatorFullyImplicit<TypeTag>::Solver>
602 auto model = std::make_unique<Model>(simulator_,
607 if (this->modelParam_.write_partitions_) {
608 const auto& iocfg = this->eclState().cfg().io();
610 const auto odir = iocfg.getOutputDir()
611 / std::filesystem::path {
"partition" }
612 / iocfg.getBaseName();
614 if (this->grid().comm().rank() == 0) {
615 create_directories(odir);
618 this->grid().comm().barrier();
620 model->writePartitions(odir);
622 this->modelParam_.write_partitions_ =
false;
625 return std::make_unique<Solver>(solverParam_, std::move(model));
630 #endif // OPM_SIMULATOR_FULLY_IMPLICIT_IMPL_HEADER_INCLUDED double simulationTimeElapsed() const override
Time elapsed since the start of the simulation until the beginning of the current time step [s]...
Definition: SimulatorTimer.cpp:122
std::function< std::string_view(int)> ComponentToPhaseName
Protocol for converting a phase/component ID into a human readable phase/component name...
Definition: ExtraConvergenceOutputThread.hpp:109
void updateTUNINGDP(const TuningDp &tuning_dp)
Apply a TUNINGDP keyword to the cached model parameters.
Definition: SimulatorFullyImplicit_impl.hpp:256
Top-level driver for a fully implicit flow simulation.
Definition: SimulatorFullyImplicit.hpp:113
void report(std::ostream &os) const
Print a report with current and total time etc.
Definition: SimulatorTimer.cpp:149
SimulatorConvergenceOutput convergence_output_
Background thread for INFOSTEP / INFOITER files.
Definition: SimulatorFullyImplicit.hpp:373
bool runStep(SimulatorTimer &timer)
Advance the simulation by one report step.
Definition: SimulatorFullyImplicit_impl.hpp:279
std::string compileTimestamp()
Return a string "dd-mm-yyyy at HH::MM::SS hrs" which is the time the binary was compiled.
Definition: moduleVersion.cpp:57
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
Class for (de-)serializing using HDF5.
Definition: HDF5Serializer.hpp:37
double currentStepLength() const override
Current step length.
Definition: SimulatorTimer.cpp:109
static Parallel::Communication & comm()
Obtain global communicator.
Definition: FlowGenericVanguard.hpp:336
static void registerParameters()
Register runtime parameters for TPSA Newton method.
Definition: tpsanewtonmethodparams.cpp:39
Simulator & simulator_
Surrounding eWoms simulator; observed, not owned.
Definition: SimulatorFullyImplicit.hpp:346
SimulatorReport run(SimulatorTimer &timer)
Run the entire simulation to completion.
Definition: SimulatorFullyImplicit_impl.hpp:109
bool terminalOutput_
Emit high-level progress to std::cout (rank 0 only).
Definition: SimulatorFullyImplicit.hpp:358
std::unique_ptr< Solver > createSolver(WellModel &wellModel)
Build the Solver used during the current report step.
Definition: SimulatorFullyImplicit_impl.hpp:600
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:575
~SimulatorFullyImplicit() override
Ends the convergence-output thread cleanly on all ranks.
Definition: SimulatorFullyImplicit_impl.hpp:78
int currentStepNum() const override
Current step number.
Definition: SimulatorTimer.cpp:95
Definition: FlowGenericVanguard.hpp:108
bool done() const override
Return true if op++() has been called numSteps() times.
Definition: SimulatorTimer.cpp:168
std::array< std::string, 5 > getHeader() const override
Return the OPMRST header tuple: product name, module version, compile timestamp, deck case name...
Definition: SimulatorFullyImplicit_impl.hpp:586
SimulatorFullyImplicit(Simulator &simulator)
Construct from the surrounding eWoms Simulator.
Definition: SimulatorFullyImplicit_impl.hpp:46
std::string moduleVersion()
Return a string containing both the name and hash, if N is the name and H is the hash it will be "N (...
Definition: moduleVersion.cpp:50
static void registerParameters()
Register all parameters consumed by this class and its major collaborators.
Definition: SimulatorFullyImplicit_impl.hpp:87
void updateTUNING(const Tuning &tuning)
Apply a TUNING keyword to the cached model parameters.
Definition: SimulatorFullyImplicit_impl.hpp:240
bool initialStep() const override
Whether the current step is the first step.
Definition: SimulatorTimer.cpp:83
void serializeOp(Serializer &serializer)
Serialize the parts of this class needed for OPMRST round-tripping (the surrounding simulator state...
Definition: SimulatorFullyImplicit_impl.hpp:554
Definition: SimulatorReport.hpp:121
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:564
Definition: SimulatorTimer.hpp:38
SimulatorReport finalize()
Stop the timers and emit the final OPMRST output.
Definition: SimulatorFullyImplicit_impl.hpp:531
static void registerParameters()
Register TPSA linear solver runtime parameters.
Definition: TPSALinearSolverParameters.cpp:59
void init(const SimulatorTimer &timer)
One-shot setup performed before the first runStep.
Definition: SimulatorFullyImplicit_impl.hpp:204