115 using ModelParameters =
typename Model::ModelParameters;
141 : simulator_(simulator)
145 Parameters::Get<Parameters::SaveStep>(),
146 Parameters::Get<Parameters::LoadStep>(),
147 Parameters::Get<Parameters::SaveFile>(),
148 Parameters::Get<Parameters::LoadFile>())
153 this->terminalOutput_ =
false;
154 if (this->grid().comm().rank() == 0) {
155 this->terminalOutput_ = Parameters::Get<Parameters::EnableTerminalOutput>();
158 [compNames =
typename Model::ComponentName{}](
const int compIdx)
159 {
return std::string_view { compNames.name(
compIdx) }; }
162 this->convergence_output_.
163 startThread(this->simulator_.vanguard().eclState(),
164 Parameters::Get<Parameters::OutputExtraConvergenceInfo>(),
165 R
"(OutputExtraConvergenceInfo (--output-extra-convergence-info))",
176 static void registerParameters()
178 ModelParameters::registerParameters();
179 SolverParameters::registerParameters();
180 TimeStepper::registerParameters();
181 detail::registerSimulatorParameters();
190#ifdef RESERVOIR_COUPLING_ENABLED
191 SimulatorReport
run(SimulatorTimer& timer,
int argc,
char**
argv)
202 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
204 while (!timer.
done()) {
205 simulator_.problem().writeReports(timer);
209 simulator_.problem().writeReports(timer);
213#ifdef RESERVOIR_COUPLING_ENABLED
220 for (std::size_t report_step = 0; report_step < this->schedule().size(); ++report_step) {
221 auto rescoup = this->schedule()[report_step].rescoup();
231 "Inconsistent reservoir coupling master schedule: "
232 "Slave count is greater than 0 but master group count is 0"
237 "Inconsistent reservoir coupling master schedule: "
238 "Master group count is greater than 0 but slave count is 0"
246#ifdef RESERVOIR_COUPLING_ENABLED
248 void init(
const SimulatorTimer& timer,
int argc,
char**
argv)
250 auto slave_mode = Parameters::Get<Parameters::Slave>();
253 std::make_unique<ReservoirCouplingSlave>(
255 this->schedule(), timer
265 std::make_unique<ReservoirCouplingMaster>(
273 void init(
const SimulatorTimer& timer)
276 simulator_.setEpisodeIndex(-1);
279 solverTimer_ = std::make_unique<time::StopWatch>();
280 totalTimer_ = std::make_unique<time::StopWatch>();
281 totalTimer_->start();
284 bool enableAdaptive = Parameters::Get<Parameters::EnableAdaptiveTimeStepping>();
285 bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
288 const auto&
sched_state = schedule()[timer.currentStepNum()];
291 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(
max_next_tstep,
298#ifdef RESERVOIR_COUPLING_ENABLED
309 adaptiveTimeStepping_->setSuggestedNextStep(simulator_.timeStepSize());
316 modelParam_.tolerance_mb_ =
tuning.XXXMBE;
317 if (terminalOutput_) {
318 OpmLog::debug(fmt::format(
"Setting SimulatorFullyImplicitBlackoil mass balance limit (XXXMBE) to {:.2e}",
tuning.XXXMBE));
322 bool runStep(SimulatorTimer& timer)
325 if (terminalOutput_) {
326 OpmLog::info(
"Stopping simulation since EXIT was triggered by an action keyword.");
328 report_.success.exit_status = schedule().exitStatus().value();
337 if (terminalOutput_) {
338 std::ostringstream
ss;
340 OpmLog::debug(
ss.str());
341 details::outputReportStep(timer);
345 if (timer.initialStep()) {
349 simulator_.setEpisodeIndex(-1);
350 simulator_.setEpisodeLength(0.0);
351 simulator_.setTimeStepSize(0.0);
352 wellModel_().beginReportStep(timer.currentStepNum());
353 simulator_.problem().writeOutput(
true);
355 report_.success.output_write_time +=
perfTimer.stop();
359 solverTimer_->start();
362 solver_ = createSolver(wellModel_());
365 simulator_.startNextEpisode(
366 simulator_.startTime()
367 + schedule().
seconds(timer.currentStepNum()),
368 timer.currentStepLength());
369 simulator_.setEpisodeIndex(timer.currentStepNum());
372 wellModel_().prepareDeserialize(serializer_.
loadStep() - 1);
374 simulator_.model().invalidateAndUpdateIntensiveQuantities(0);
377 this->solver_->model().beginReportStep();
379 const bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
386 if (adaptiveTimeStepping_) {
388 reportStep = timer.currentStepNum()](
const double curr_time,
391 auto& schedule = this->simulator_.vanguard().schedule();
392 auto& events = this->schedule()[reportStep].events();
395 if (events.hasEvent(ScheduleEvents::TUNING_CHANGE)) {
397 schedule.clear_event(ScheduleEvents::TUNING_CHANGE, reportStep);
406 solver_->model().updateTUNING(
tuning);
407 this->updateTUNING(
tuning);
408 dt = this->adaptiveTimeStepping_->suggestedNextStep();
416 const auto&
wcycle = schedule[reportStep].wcycle.get();
421 const auto&
wmatcher = schedule.wellMatcher(reportStep);
426 this->wellModel_().wellOpenTimes(),
427 this->wellModel_().wellCloseTimes(),
429 &
wg_events = this->wellModel_().reportStepStartEvents()]
430 (
const std::string& name)
435 return wg_events.hasEvent(name, ScheduleEvents::REQUEST_OPEN_WELL);
448 this->adaptiveTimeStepping_->suggestedNextStep(), 0);
450#ifdef RESERVOIR_COUPLING_ENABLED
458 const auto& events = schedule()[timer.currentStepNum()].events();
459 bool event = events.hasEvent(ScheduleEvents::NEW_WELL) ||
460 events.hasEvent(ScheduleEvents::INJECTION_TYPE_CHANGED) ||
461 events.hasEvent(ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER) ||
462 events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE) ||
463 events.hasEvent(ScheduleEvents::INJECTION_UPDATE) ||
464 events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE);
468 simulator_.problem().setSimulationReport(report_);
473 if (terminalOutput_) {
474 std::ostringstream
ss;
476 OpmLog::info(
ss.str());
483 const double nextstep = adaptiveTimeStepping_ ? adaptiveTimeStepping_->suggestedNextStep() : -1.0;
484 simulator_.problem().setNextTimeStepSize(
nextstep);
485 simulator_.problem().writeOutput(
true);
486 report_.success.output_write_time +=
perfTimer.stop();
488 solver_->model().endReportStep();
491 solverTimer_->stop();
494 report_.success.solver_time += solverTimer_->secsSinceStart();
496 if (this->grid().comm().rank() == 0) {
499 const auto&
reps = this->solver_->model().stepReports();
506 if (terminalOutput_) {
508 "Time step took " + std::to_string(solverTimer_->secsSinceStart()) +
" seconds; "
509 "total solver time " + std::to_string(report_.success.solver_time) +
" seconds.";
513 serializer_.
save(timer);
518 SimulatorReport finalize()
525 simulator_.problem().finalizeOutput();
531 report_.success.total_time = totalTimer_->secsSinceStart();
532 report_.success.converged =
true;
537 const Grid& grid()
const
538 {
return simulator_.vanguard().grid(); }
540 template<
class Serializer>
548 const Model& model()
const
549 {
return solver_->model(); }
573 std::ostringstream
str;
574 Parameters::printValues(
str);
578 simulator_.vanguard().caseName(),
585 return simulator_.vanguard().globalCell();
588 std::unique_ptr<Solver> createSolver(WellModel& wellModel)
590 auto model = std::make_unique<Model>(simulator_,
595 if (this->modelParam_.write_partitions_) {
596 const auto&
iocfg = this->eclState().cfg().io();
599 / std::filesystem::path {
"partition" }
600 /
iocfg.getBaseName();
602 if (this->grid().comm().rank() == 0) {
606 this->grid().comm().barrier();
608 model->writePartitions(
odir);
610 this->modelParam_.write_partitions_ =
false;
613 return std::make_unique<Solver>(solverParam_, std::move(model));
616 const EclipseState& eclState()
const
617 {
return simulator_.vanguard().eclState(); }
621 {
return simulator_.vanguard().schedule(); }
623 bool isRestart()
const
625 const auto&
initconfig = eclState().getInitConfig();
629 WellModel& wellModel_()
630 {
return simulator_.problem().wellModel(); }
632 const WellModel& wellModel_()
const
633 {
return simulator_.problem().wellModel(); }
636 Simulator& simulator_;
638 ModelParameters modelParam_;
639 SolverParameters solverParam_;
641 std::unique_ptr<Solver> solver_;
644 PhaseUsage phaseUsage_;
646 bool terminalOutput_;
648 SimulatorReport report_;
649 std::unique_ptr<time::StopWatch> solverTimer_;
650 std::unique_ptr<time::StopWatch> totalTimer_;
651 std::unique_ptr<TimeStepper> adaptiveTimeStepping_;
653 SimulatorConvergenceOutput convergence_output_{};
655#ifdef RESERVOIR_COUPLING_ENABLED
661 SimulatorSerializer serializer_;