SimulatorFullyImplicit_impl.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013, 2015, 2020 SINTEF Digital, Mathematics and Cybernetics.
3 Copyright 2015 Andreas Lauser
4 Copyright 2017 IRIS
5
6 This file is part of the Open Porous Media project (OPM).
7
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#ifndef OPM_SIMULATOR_FULLY_IMPLICIT_IMPL_HEADER_INCLUDED
23#define OPM_SIMULATOR_FULLY_IMPLICIT_IMPL_HEADER_INCLUDED
24
25// Improve IDE experience
26#ifndef OPM_SIMULATOR_FULLY_IMPLICIT_HEADER_INCLUDED
27#include <config.h>
29#endif
30
31#include <opm/input/eclipse/Units/UnitSystem.hpp>
32
34
36
37#include <fmt/format.h>
38
39#include <filesystem>
40#include <limits>
41#include <sstream>
42
43namespace Opm {
44
45template<class TypeTag>
48 : simulator_(simulator)
49 , serializer_(*this,
50 FlowGenericVanguard::comm(),
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>())
56{
57 // Only rank 0 does print to std::cout, and only if specifically requested.
58 this->terminalOutput_ = false;
59 if (this->grid().comm().rank() == 0) {
60 this->terminalOutput_ = Parameters::Get<Parameters::EnableTerminalOutput>();
61
63 [compNames = typename Model::ComponentName{}](const int compIdx)
64 { return std::string_view { compNames.name(compIdx) }; }
65 };
66
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))",
72 getPhaseName);
73 }
74 }
75}
76
77template<class TypeTag>
80{
81 // Flush any convergence reports that were never written because the
82 // run terminated before completing its report step -- exactly the
83 // failed runs whose convergence history is most valuable. write() is
84 // idempotent for already-reported steps and a no-op when convergence
85 // output is not active.
86 if (this->solver_ != nullptr) {
87 try {
88 this->convergence_output_.write(this->solver_->model().stepReports());
89 } catch (...) {
90 // Never let diagnostics output escape a destructor.
91 }
92 }
93
94 // Safe to call on all ranks, not just the I/O rank.
95 convergence_output_.endThread();
96}
97
98template<class TypeTag>
99void
102{
103 ModelParameters::registerParameters();
104 SolverParameters::registerParameters();
105 TimeStepper::registerParameters();
107
110}
111
112#ifdef RESERVOIR_COUPLING_ENABLED
113template<class TypeTag>
116run(SimulatorTimer& timer, int argc, char** argv)
117{
118 init(timer, argc, argv);
119#else
120template<class TypeTag>
123run(SimulatorTimer& timer)
124{
125 init(timer);
126#endif
127 // Make cache up to date. No need for updating it in elementCtx.
128 // NB! Need to be at the correct step in case of restart
129 simulator_.setEpisodeIndex(timer.currentStepNum());
130 simulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
131 // Main simulation loop.
132 while (!timer.done()) {
133 simulator_.problem().writeReports(timer);
134 bool continue_looping = runStep(timer);
135 if (!continue_looping) break;
136 }
137 simulator_.problem().writeReports(timer);
138
139#ifdef RESERVOIR_COUPLING_ENABLED
140 // Clean up MPI intercommunicators before MPI_Finalize()
141 // Master sends terminate=1 signal; slave receives it and both call MPI_Comm_disconnect()
142 if (this->reservoirCouplingMaster_) {
143 this->reservoirCouplingMaster_->sendTerminateAndDisconnect();
144 }
145 else if (this->reservoirCouplingSlave_ && !this->reservoirCouplingSlave_->terminated()) {
146 // We got here by running out of report steps of our own. If the master is still
147 // running, notifyEndOfRunAndDisconnect() tells it so, and the master then continues
148 // with no flow from this slave.
149 //
150 // TODO: Implement GECON item 8, which lets a master deck ask for the opposite: stop
151 // the master run when one of its slaves finishes, rather than continuing without it.
152 //
153 // Only call if not already terminated via maybeReceiveTerminateSignalFromMaster()
154 // (which happens when master finishes before slave reaches end of its loop)
155 this->reservoirCouplingSlave_->notifyEndOfRunAndDisconnect();
156 }
157#endif
158
159 return finalize();
160}
161
162#ifdef RESERVOIR_COUPLING_ENABLED
163template<class TypeTag>
164bool
167{
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();
172 // Master mode is enabled when SLAVES keyword is present.
173 // - Prediction mode: SLAVES + GRUPMAST (master allocates rates)
174 // - History mode: SLAVES only (master synchronizes time-stepping)
175 if (slave_count > 0) {
176 return true;
177 }
178 else if (master_group_count > 0) {
179 // GRUPMAST without SLAVES is invalid
180 throw ReservoirCouplingError(
181 "Inconsistent reservoir coupling master schedule: "
182 "Master group count is greater than 0 but slave count is 0"
183 );
184 }
185 }
186 return false;
187}
188#endif
189
190#ifdef RESERVOIR_COUPLING_ENABLED
191template<class TypeTag>
192void
194init(const SimulatorTimer& timer, int argc, char** argv)
195{
196 auto slave_mode = Parameters::Get<Parameters::Slave>();
197 if (slave_mode) {
198 this->reservoirCouplingSlave_ =
199 std::make_unique<ReservoirCouplingSlave<Scalar>>(
201 this->schedule(), timer
202 );
203 this->reservoirCouplingSlave_->sendAndReceiveInitialData();
204 this->simulator_.setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
205 wellModel_().setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
206 }
207 else {
208 auto master_mode = checkRunningAsReservoirCouplingMaster();
209 if (master_mode) {
210 this->reservoirCouplingMaster_ =
211 std::make_unique<ReservoirCouplingMaster<Scalar>>(
213 this->schedule(),
214 argc, argv
215 );
216 this->simulator_.setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
217 wellModel_().setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
218 }
219 }
220#else
221template<class TypeTag>
222void
224init(const SimulatorTimer& timer)
225{
226#endif
227 simulator_.setEpisodeIndex(-1);
228
229 // Create timers and file for writing timing info.
230 solverTimer_ = std::make_unique<time::StopWatch>();
231 totalTimer_ = std::make_unique<time::StopWatch>();
232 totalTimer_->start();
233
234 // adaptive time stepping
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();
239 const auto& sched_state = schedule()[timer.currentStepNum()];
240 auto max_next_tstep = sched_state.max_next_tstep(enableTUNING);
241 if (enableTUNING) {
242 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(max_next_tstep,
243 sched_state.tuning(),
244 unitSystem, report_, terminalOutput_);
245 }
246 else {
247 adaptiveTimeStepping_ = std::make_unique<TimeStepper>(unitSystem, report_, max_next_tstep, terminalOutput_);
248 }
249 if (isRestart()) {
250 // For restarts the simulator may have gotten some information
251 // about the next timestep size from the OPMEXTRA field
252 adaptiveTimeStepping_->setSuggestedNextStep(simulator_.timeStepSize());
253
254 // The time stepper above is initialised from the TUNING settings at
255 // the restart step, so apply the Newton settings from the same
256 // TUNING as well. These come from the restart file, or from the deck
257 // when the restart runs with --sched-restart=true (no TUNING_CHANGE
258 // event is raised at the restart step then).
259 if (enableTUNING) {
260 this->updateTUNING(sched_state.tuning());
261 }
262 }
263 }
264}
265
266template<class TypeTag>
267void
269updateTUNING(const Tuning& tuning)
270{
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_) {
278 detail::logTuning(tuning);
279 }
280}
281
282template<class TypeTag>
283void
285updateTUNINGDP(const TuningDp& tuning_dp)
286{
287 // NOTE: If TUNINGDP item is _not_ set it should be 0.0
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;
292
293 // Terminal warnings
294 if (terminalOutput_) {
295 // Warnings unsupported items
296 if (tuning_dp.TRGLCV_has_value) {
297 OpmLog::warning("TUNINGDP item 1 (TRGLCV) is not supported.");
298 }
299 if (tuning_dp.XXXLCV_has_value) {
300 OpmLog::warning("TUNINGDP item 2 (XXXLCV) is not supported.");
301 }
302 }
303}
304
305template<class TypeTag>
306bool
309{
310 if (schedule().exitStatus().has_value()) {
311 if (terminalOutput_) {
312 OpmLog::info("Stopping simulation since EXIT was triggered by an action keyword.");
313 }
314 report_.success.exit_status = schedule().exitStatus().value();
315 return false;
316 }
317
318 if (serializer_.shouldLoad()) {
319 serializer_.loadTimerInfo(timer);
320 }
321
322 // Report timestep.
323 if (terminalOutput_) {
324 std::ostringstream ss;
325 timer.report(ss);
326 OpmLog::debug(ss.str());
328 }
329
330 // write the inital state at the report stage
331 if (timer.initialStep() && !serializer_.shouldLoad()) {
332 Dune::Timer perfTimer;
333 perfTimer.start();
334
335 simulator_.setEpisodeIndex(-1);
336 simulator_.setEpisodeLength(0.0);
337 simulator_.setTimeStepSize(0.0);
338 wellModel_().beginReportStep(timer.currentStepNum());
339 simulator_.problem().writeOutput(true);
340
341 report_.success.output_write_time += perfTimer.stop();
342 }
343
344 simulator_.startNextEpisode(
345 simulator_.startTime()
346 + schedule().seconds(timer.currentStepNum()),
347 timer.currentStepLength());
348 simulator_.setEpisodeIndex(timer.currentStepNum());
349
350 if (serializer_.shouldLoad()) {
351 wellModel_().prepareDeserialize(serializer_.loadStep() - 1);
352 serializer_.loadState();
353 simulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
354 simulator_.model().rebuildStorageCache(/*timeIdx=*/0);
355 if (simulator_.problem().intensiveQuantityHistorySize() > 1) {
356 simulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/1);
357 simulator_.model().rebuildStorageCache(/*timeIdx=*/1);
358 }
359 wellModel_().beginReportStep(timer.currentStepNum());
360 }
361
362 // Run a multiple steps of the solver depending on the time step control.
363 solverTimer_->start();
364
365 if (!solver_) {
366 solver_ = createSolver(wellModel_());
367 }
368
369 // Same position as the OPMRST restore above -- after the episode has been
370 // set up and before the solve -- for callers that keep their own state
371 // store. Used by the adjoint's checkpoint/recompute driver, which restores
372 // from its own archive rather than from an .OPMRST file. Off unless set.
373 if (restoreStateHook_) {
374 restoreStateHook_(timer.currentStepNum());
375 }
376
377 this->solver_->model().beginReportStep();
378
379 const bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
380
381 // If sub stepping is enabled allow the solver to sub cycle
382 // in case the report steps are too large for the solver to converge
383 //
384 // \Note: The report steps are met in any case
385 // \Note: The sub stepping will require a copy of the state variables
386 if (adaptiveTimeStepping_) {
387 auto tuningUpdater = [enableTUNING, this,
388 reportStep = timer.currentStepNum()](const double curr_time,
389 double substep_length,
390 const int sub_step_number)
391 {
392 auto& schedule = this->simulator_.vanguard().schedule();
393 auto& events = this->schedule()[reportStep].events();
394
395 // The problem may cap the next time step (e.g. a geomechanical
396 // fracture model limiting steps while the fracture grows).
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();
401
402 bool result = problem_caps;
403 if (problem_caps) {
404 this->adaptiveTimeStepping_->updateNEXTSTEP(problem_max_next_tstep);
405 }
406 if (events.hasEvent(ScheduleEvents::TUNING_CHANGE)) {
407 // Unset the event to not trigger it again on the next sub step
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);
411 // Both are upper bounds on the next step, so the effective cap is
412 // the smaller one. max_next_tstep() is -1 when the schedule sets
413 // no limit at all, and then the problem's limit stands alone.
414 if (problem_caps) {
415 max_next_tstep = (max_next_tstep > 0.0)
416 ? std::min(max_next_tstep, problem_max_next_tstep)
417 : problem_max_next_tstep;
418 }
419 const auto& tuning = sched_state.tuning();
420
421 if (enableTUNING) {
422 adaptiveTimeStepping_->updateTUNING(max_next_tstep, tuning);
423 // \Note: Assumes TUNING is only used with adaptive time-stepping
424 // \Note: Need to update both solver (model) and simulator since solver is re-created each report step.
425 solver_->model().updateTUNING(tuning);
426 this->updateTUNING(tuning);
427 substep_length = this->adaptiveTimeStepping_->suggestedNextStep();
428 } else {
429 substep_length = max_next_tstep;
430 this->adaptiveTimeStepping_->updateNEXTSTEP(max_next_tstep);
431 }
432 result = max_next_tstep > 0;
433 }
434
435 if (events.hasEvent(ScheduleEvents::TUNINGDP_CHANGE)) {
436 // Unset the event to not trigger it again on the next sub step
437 schedule.clear_event(ScheduleEvents::TUNINGDP_CHANGE, reportStep);
438
439 // Update TUNINGDP parameters
440 // NOTE: Need to update both solver (model) and simulator since solver is re-created each report
441 // step.
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);
446 }
447
448 const auto& wcycle = schedule[reportStep].wcycle.get();
449 if (wcycle.empty()) {
450 return result;
451 }
452
453 const auto& wmatcher = schedule.wellMatcher(reportStep);
454 double wcycle_time_step =
455 wcycle.nextTimeStep(curr_time,
456 substep_length,
457 wmatcher,
458 this->wellModel_().wellOpenTimes(),
459 this->wellModel_().wellCloseTimes(),
460 [sub_step_number,
461 &wg_events = this->wellModel_().reportStepStartEvents()]
462 (const std::string& name)
463 {
464 if (sub_step_number != 0) {
465 return false;
466 }
467 return wg_events.hasEvent(name, ScheduleEvents::REQUEST_OPEN_WELL);
468 });
469
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);
473 return true;
474 }
475
476 return result;
477 };
478
479 tuningUpdater(timer.simulationTimeElapsed(),
480 this->adaptiveTimeStepping_->suggestedNextStep(), 0);
481
482#ifdef RESERVOIR_COUPLING_ENABLED
483 if (this->reservoirCouplingMaster_) {
484 this->reservoirCouplingMaster_->maybeSpawnSlaveProcesses(timer.currentStepNum());
485 this->reservoirCouplingMaster_->maybeActivate(timer.currentStepNum());
486 }
487 else if (this->reservoirCouplingSlave_) {
488 this->reservoirCouplingSlave_->maybeActivate(timer.currentStepNum());
489 }
490#endif
491 const auto& events = schedule()[timer.currentStepNum()].events();
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
501 // If the master ended its schedule first (e.g. an END keyword truncates the master
502 // SCHEDULE), the slave received the terminate signal and disconnected its
503 // intercommunicator inside step() above. The coupled run is over for this slave:
504 // finish the current report step cleanly and stop the run loop instead of advancing
505 // to another report step, which would issue an MPI_Recv on the now-disconnected
506 // communicator and abort the job.
507 if (this->reservoirCouplingSlave_ && this->reservoirCouplingSlave_->terminated()) {
508 this->handleSlaveTerminated_();
509 return false; // breaks the while(!timer.done()) loop in run()
510 }
511#endif
512 } else {
513 // solve for complete report step
514 auto stepReport = solver_->step(timer, nullptr);
515 report_ += stepReport;
516 // Pass simulation report to eclwriter for summary output
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());
524 }
525 }
526
527 // write simulation state at the report stage
528 Dune::Timer perfTimer;
529 perfTimer.start();
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();
534
535 solver_->model().endReportStep();
536
537 // take time that was used to solve system for this reportStep
538 solverTimer_->stop();
539
540 // update timing.
541 report_.success.solver_time += solverTimer_->secsSinceStart();
542
543 if (this->grid().comm().rank() == 0) {
544 // Grab the step convergence reports that are new since last we
545 // were here.
546 const auto& reps = this->solver_->model().stepReports();
547 convergence_output_.write(reps);
548 }
549
550 // Increment timer, remember well state.
551 ++timer;
552
553 if (terminalOutput_) {
554 std::string msg =
555 "Time step took " + std::to_string(solverTimer_->secsSinceStart()) + " seconds; "
556 "total solver time " + std::to_string(report_.success.solver_time) + " seconds.";
557 OpmLog::debug(msg);
558 }
559
560 serializer_.save(timer);
561
562 return true;
563}
564
565#ifdef RESERVOIR_COUPLING_ENABLED
566template<class TypeTag>
567void
570{
571 if (terminalOutput_) {
572 OpmLog::info("Reservoir coupling: master simulation has ended; "
573 "stopping slave simulation gracefully.");
574 }
575 // The slave stops as soon as it is terminated, so no further substeps run for this report
576 // step. Per-substep SUMMARY output for any substeps already completed in this report step
577 // was written by the adaptive substep loop; the report-step-level restart write is
578 // intentionally skipped because a terminated report step is partial - the last completed
579 // report step is the clean restart point. finalize() flushes the remaining output.
580 // Balance the beginReportStep() issued earlier in runStep().
581 this->solver_->model().endReportStep();
582 // Account for this report step's solver time and leave the timer stopped: runStep()'s own
583 // solverTimer_->stop()/accumulation below is bypassed by the early return on termination.
584 this->solverTimer_->stop();
585 this->report_.success.solver_time += this->solverTimer_->secsSinceStart();
586}
587#endif
588
589template<class TypeTag>
590SimulatorReport
592finalize()
593{
594 // make sure all output is written to disk before run is finished
595 {
596 Dune::Timer finalOutputTimer;
597 finalOutputTimer.start();
598
599 simulator_.problem().finalizeOutput();
600 report_.success.output_write_time += finalOutputTimer.stop();
601 }
602
603 // Stop timer and create timing report
604 totalTimer_->stop();
605 report_.success.total_time = totalTimer_->secsSinceStart();
606 report_.success.converged = true;
607
608 return report_;
609}
610
611template<class TypeTag>
612template<class Serializer>
613void
615serializeOp(Serializer& serializer)
616{
617 serializer(simulator_);
618 serializer(report_);
619 serializer(adaptiveTimeStepping_);
620 serializer(modelParam_);
621}
622
623template<class TypeTag>
624void
626loadState([[maybe_unused]] HDF5Serializer& serializer,
627 [[maybe_unused]] const std::string& groupName)
628{
629#if HAVE_HDF5
630 serializer.read(*this, groupName, "simulator_data");
631#endif
632}
633
634template<class TypeTag>
635void
637saveState([[maybe_unused]] HDF5Serializer& serializer,
638 [[maybe_unused]] const std::string& groupName) const
639{
640#if HAVE_HDF5
641 serializer.write(*this, groupName, "simulator_data");
642#endif
643}
644
645template<class TypeTag>
646std::array<std::string,5>
648getHeader() const
649{
650 std::ostringstream str;
652 return {"OPM Flow",
655 simulator_.vanguard().caseName(),
656 str.str()};
657}
658
659template<class TypeTag>
660std::unique_ptr<typename SimulatorFullyImplicit<TypeTag>::Solver>
662createSolver(WellModel& wellModel)
663{
664 auto model = std::make_unique<Model>(simulator_,
665 modelParam_,
666 wellModel,
667 terminalOutput_);
668
669 if (this->modelParam_.write_partitions_) {
670 const auto& iocfg = this->eclState().cfg().io();
671
672 const auto odir = iocfg.getOutputDir()
673 / std::filesystem::path { "partition" }
674 / iocfg.getBaseName();
675
676 if (this->grid().comm().rank() == 0) {
677 create_directories(odir);
678 }
679
680 this->grid().comm().barrier();
681
682 model->writePartitions(odir);
683
684 this->modelParam_.write_partitions_ = false;
685 }
686
687 return std::make_unique<Solver>(solverParam_, std::move(model));
688}
689
690} // namespace Opm
691
692#endif // OPM_SIMULATOR_FULLY_IMPLICIT_IMPL_HEADER_INCLUDED
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()