opm-simulators
SimulatorFullyImplicit_impl.hpp
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>
28 #include <opm/simulators/flow/SimulatorFullyImplicit.hpp>
29 #endif
30 
31 #include <opm/input/eclipse/Units/UnitSystem.hpp>
32 
33 #include <opm/models/tpsa/tpsanewtonmethodparams.hpp>
34 
35 #include <opm/simulators/linalg/TPSALinearSolverParameters.hpp>
36 
37 #include <fmt/format.h>
38 
39 #include <filesystem>
40 #include <sstream>
41 
42 namespace Opm {
43 
44 template<class TypeTag>
46 SimulatorFullyImplicit(Simulator& simulator)
47  : simulator_(simulator)
48  , serializer_(*this,
49  FlowGenericVanguard::comm(),
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>())
55 {
56  // Only rank 0 does print to std::cout, and only if specifically requested.
57  this->terminalOutput_ = false;
58  if (this->grid().comm().rank() == 0) {
59  this->terminalOutput_ = Parameters::Get<Parameters::EnableTerminalOutput>();
60 
62  [compNames = typename Model::ComponentName{}](const int compIdx)
63  { return std::string_view { compNames.name(compIdx) }; }
64  };
65 
66  if (!simulator_.vanguard().eclState().getIOConfig().initOnly()) {
67  this->convergence_output_.
68  startThread(this->simulator_.vanguard().eclState(),
69  Parameters::Get<Parameters::OutputExtraConvergenceInfo>(),
70  R"(OutputExtraConvergenceInfo (--output-extra-convergence-info))",
71  getPhaseName);
72  }
73  }
74 }
75 
76 template<class TypeTag>
79 {
80  // Safe to call on all ranks, not just the I/O rank.
81  convergence_output_.endThread();
82 }
83 
84 template<class TypeTag>
85 void
88 {
89  ModelParameters::registerParameters();
90  SolverParameters::registerParameters();
91  TimeStepper::registerParameters();
92  detail::registerSimulatorParameters();
93 
96 }
97 
98 #ifdef RESERVOIR_COUPLING_ENABLED
99 template<class TypeTag>
102 run(SimulatorTimer& timer, int argc, char** argv)
103 {
104  init(timer, argc, argv);
105 #else
106 template<class TypeTag>
110 {
111  init(timer);
112 #endif
113  // Make cache up to date. No need for updating it in elementCtx.
114  // NB! Need to be at the correct step in case of restart
115  simulator_.setEpisodeIndex(timer.currentStepNum());
116  simulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
117  // Main simulation loop.
118  while (!timer.done()) {
119  simulator_.problem().writeReports(timer);
120  bool continue_looping = runStep(timer);
121  if (!continue_looping) break;
122  }
123  simulator_.problem().writeReports(timer);
124 
125 #ifdef RESERVOIR_COUPLING_ENABLED
126  // Clean up MPI intercommunicators before MPI_Finalize()
127  // Master sends terminate=1 signal; slave receives it and both call MPI_Comm_disconnect()
128  if (this->reservoirCouplingMaster_) {
129  this->reservoirCouplingMaster_->sendTerminateAndDisconnect();
130  }
131  else if (this->reservoirCouplingSlave_ && !this->reservoirCouplingSlave_->terminated()) {
132  // TODO: Implement GECON item 8: stop master process when a slave finishes
133  // Only call if not already terminated via maybeReceiveTerminateSignalFromMaster()
134  // (which happens when master finishes before slave reaches end of its loop)
135  this->reservoirCouplingSlave_->receiveTerminateAndDisconnect();
136  }
137 #endif
138 
139  return finalize();
140 }
141 
142 #ifdef RESERVOIR_COUPLING_ENABLED
143 template<class TypeTag>
144 bool
147 {
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();
152  // Master mode is enabled when SLAVES keyword is present.
153  // - Prediction mode: SLAVES + GRUPMAST (master allocates rates)
154  // - History mode: SLAVES only (master synchronizes time-stepping)
155  if (slave_count > 0) {
156  return true;
157  }
158  else if (master_group_count > 0) {
159  // GRUPMAST without SLAVES is invalid
160  throw ReservoirCouplingError(
161  "Inconsistent reservoir coupling master schedule: "
162  "Master group count is greater than 0 but slave count is 0"
163  );
164  }
165  }
166  return false;
167 }
168 #endif
169 
170 #ifdef RESERVOIR_COUPLING_ENABLED
171 template<class TypeTag>
172 void
174 init(const SimulatorTimer& timer, int argc, char** argv)
175 {
176  auto slave_mode = Parameters::Get<Parameters::Slave>();
177  if (slave_mode) {
178  this->reservoirCouplingSlave_ =
179  std::make_unique<ReservoirCouplingSlave<Scalar>>(
181  this->schedule(), timer
182  );
183  this->reservoirCouplingSlave_->sendAndReceiveInitialData();
184  this->simulator_.setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
185  wellModel_().setReservoirCouplingSlave(this->reservoirCouplingSlave_.get());
186  }
187  else {
188  auto master_mode = checkRunningAsReservoirCouplingMaster();
189  if (master_mode) {
190  this->reservoirCouplingMaster_ =
191  std::make_unique<ReservoirCouplingMaster<Scalar>>(
193  this->schedule(),
194  argc, argv
195  );
196  this->simulator_.setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
197  wellModel_().setReservoirCouplingMaster(this->reservoirCouplingMaster_.get());
198  }
199  }
200 #else
201 template<class TypeTag>
202 void
204 init(const SimulatorTimer& timer)
205 {
206 #endif
207  simulator_.setEpisodeIndex(-1);
208 
209  // Create timers and file for writing timing info.
210  solverTimer_ = std::make_unique<time::StopWatch>();
211  totalTimer_ = std::make_unique<time::StopWatch>();
212  totalTimer_->start();
213 
214  // adaptive time stepping
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();
219  const auto& sched_state = schedule()[timer.currentStepNum()];
220  auto max_next_tstep = sched_state.max_next_tstep(enableTUNING);
221  if (enableTUNING) {
222  adaptiveTimeStepping_ = std::make_unique<TimeStepper>(max_next_tstep,
223  sched_state.tuning(),
224  unitSystem, report_, terminalOutput_);
225  }
226  else {
227  adaptiveTimeStepping_ = std::make_unique<TimeStepper>(unitSystem, report_, max_next_tstep, terminalOutput_);
228  }
229  if (isRestart()) {
230  // For restarts the simulator may have gotten some information
231  // about the next timestep size from the OPMEXTRA field
232  adaptiveTimeStepping_->setSuggestedNextStep(simulator_.timeStepSize());
233  }
234  }
235 }
236 
237 template<class TypeTag>
238 void
240 updateTUNING(const Tuning& tuning)
241 {
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);
250  }
251 }
252 
253 template<class TypeTag>
254 void
256 updateTUNINGDP(const TuningDp& tuning_dp)
257 {
258  // NOTE: If TUNINGDP item is _not_ set it should be 0.0
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;
263 
264  // Terminal warnings
265  if (terminalOutput_) {
266  // Warnings unsupported items
267  if (tuning_dp.TRGLCV_has_value) {
268  OpmLog::warning("TUNINGDP item 1 (TRGLCV) is not supported.");
269  }
270  if (tuning_dp.XXXLCV_has_value) {
271  OpmLog::warning("TUNINGDP item 2 (XXXLCV) is not supported.");
272  }
273  }
274 }
275 
276 template<class TypeTag>
277 bool
280 {
281  if (schedule().exitStatus().has_value()) {
282  if (terminalOutput_) {
283  OpmLog::info("Stopping simulation since EXIT was triggered by an action keyword.");
284  }
285  report_.success.exit_status = schedule().exitStatus().value();
286  return false;
287  }
288 
289  if (serializer_.shouldLoad()) {
290  serializer_.loadTimerInfo(timer);
291  }
292 
293  // Report timestep.
294  if (terminalOutput_) {
295  std::ostringstream ss;
296  timer.report(ss);
297  OpmLog::debug(ss.str());
298  details::outputReportStep(timer);
299  }
300 
301  // write the inital state at the report stage
302  if (timer.initialStep()) {
303  Dune::Timer perfTimer;
304  perfTimer.start();
305 
306  simulator_.setEpisodeIndex(-1);
307  simulator_.setEpisodeLength(0.0);
308  simulator_.setTimeStepSize(0.0);
309  wellModel_().beginReportStep(timer.currentStepNum());
310  simulator_.problem().writeOutput(true);
311 
312  report_.success.output_write_time += perfTimer.stop();
313  }
314 
315  // Run a multiple steps of the solver depending on the time step control.
316  solverTimer_->start();
317 
318  if (!solver_) {
319  solver_ = createSolver(wellModel_());
320  }
321 
322  simulator_.startNextEpisode(
323  simulator_.startTime()
324  + schedule().seconds(timer.currentStepNum()),
325  timer.currentStepLength());
326  simulator_.setEpisodeIndex(timer.currentStepNum());
327 
328  if (serializer_.shouldLoad()) {
329  wellModel_().prepareDeserialize(serializer_.loadStep() - 1);
330  serializer_.loadState();
331  simulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
332  }
333 
334  this->solver_->model().beginReportStep();
335 
336  const bool enableTUNING = Parameters::Get<Parameters::EnableTuning>();
337 
338  // If sub stepping is enabled allow the solver to sub cycle
339  // in case the report steps are too large for the solver to converge
340  //
341  // \Note: The report steps are met in any case
342  // \Note: The sub stepping will require a copy of the state variables
343  if (adaptiveTimeStepping_) {
344  auto tuningUpdater = [enableTUNING, this,
345  reportStep = timer.currentStepNum()](const double curr_time,
346  double substep_length,
347  const int sub_step_number)
348  {
349  auto& schedule = this->simulator_.vanguard().schedule();
350  auto& events = this->schedule()[reportStep].events();
351 
352  bool result = false;
353  if (events.hasEvent(ScheduleEvents::TUNING_CHANGE)) {
354  // Unset the event to not trigger it again on the next sub step
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();
359 
360  if (enableTUNING) {
361  adaptiveTimeStepping_->updateTUNING(max_next_tstep, tuning);
362  // \Note: Assumes TUNING is only used with adaptive time-stepping
363  // \Note: Need to update both solver (model) and simulator since solver is re-created each report step.
364  solver_->model().updateTUNING(tuning);
365  this->updateTUNING(tuning);
366  substep_length = this->adaptiveTimeStepping_->suggestedNextStep();
367  } else {
368  substep_length = max_next_tstep;
369  this->adaptiveTimeStepping_->updateNEXTSTEP(max_next_tstep);
370  }
371  result = max_next_tstep > 0;
372  }
373 
374  if (events.hasEvent(ScheduleEvents::TUNINGDP_CHANGE)) {
375  // Unset the event to not trigger it again on the next sub step
376  schedule.clear_event(ScheduleEvents::TUNINGDP_CHANGE, reportStep);
377 
378  // Update TUNINGDP parameters
379  // NOTE: Need to update both solver (model) and simulator since solver is re-created each report
380  // step.
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);
385  }
386 
387  const auto& wcycle = schedule[reportStep].wcycle.get();
388  if (wcycle.empty()) {
389  return result;
390  }
391 
392  const auto& wmatcher = schedule.wellMatcher(reportStep);
393  double wcycle_time_step =
394  wcycle.nextTimeStep(curr_time,
395  substep_length,
396  wmatcher,
397  this->wellModel_().wellOpenTimes(),
398  this->wellModel_().wellCloseTimes(),
399  [sub_step_number,
400  &wg_events = this->wellModel_().reportStepStartEvents()]
401  (const std::string& name)
402  {
403  if (sub_step_number != 0) {
404  return false;
405  }
406  return wg_events.hasEvent(name, ScheduleEvents::REQUEST_OPEN_WELL);
407  });
408 
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);
412  return true;
413  }
414 
415  return result;
416  };
417 
418  tuningUpdater(timer.simulationTimeElapsed(),
419  this->adaptiveTimeStepping_->suggestedNextStep(), 0);
420 
421 #ifdef RESERVOIR_COUPLING_ENABLED
422  if (this->reservoirCouplingMaster_) {
423  this->reservoirCouplingMaster_->maybeSpawnSlaveProcesses(timer.currentStepNum());
424  this->reservoirCouplingMaster_->maybeActivate(timer.currentStepNum());
425  }
426  else if (this->reservoirCouplingSlave_) {
427  this->reservoirCouplingSlave_->maybeActivate(timer.currentStepNum());
428  }
429 #endif
430  const auto& events = schedule()[timer.currentStepNum()].events();
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
440  // If the master ended its schedule first (e.g. an END keyword truncates the master
441  // SCHEDULE), the slave received the terminate signal and disconnected its
442  // intercommunicator inside step() above. The coupled run is over for this slave:
443  // finish the current report step cleanly and stop the run loop instead of advancing
444  // to another report step, which would issue an MPI_Recv on the now-disconnected
445  // communicator and abort the job.
446  if (this->reservoirCouplingSlave_ && this->reservoirCouplingSlave_->terminated()) {
447  this->handleSlaveTerminated_();
448  return false; // breaks the while(!timer.done()) loop in run()
449  }
450 #endif
451  } else {
452  // solve for complete report step
453  auto stepReport = solver_->step(timer, nullptr);
454  report_ += stepReport;
455  // Pass simulation report to eclwriter for summary output
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());
463  }
464  }
465 
466  // write simulation state at the report stage
467  Dune::Timer perfTimer;
468  perfTimer.start();
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();
473 
474  solver_->model().endReportStep();
475 
476  // take time that was used to solve system for this reportStep
477  solverTimer_->stop();
478 
479  // update timing.
480  report_.success.solver_time += solverTimer_->secsSinceStart();
481 
482  if (this->grid().comm().rank() == 0) {
483  // Grab the step convergence reports that are new since last we
484  // were here.
485  const auto& reps = this->solver_->model().stepReports();
486  convergence_output_.write(reps);
487  }
488 
489  // Increment timer, remember well state.
490  ++timer;
491 
492  if (terminalOutput_) {
493  std::string msg =
494  "Time step took " + std::to_string(solverTimer_->secsSinceStart()) + " seconds; "
495  "total solver time " + std::to_string(report_.success.solver_time) + " seconds.";
496  OpmLog::debug(msg);
497  }
498 
499  serializer_.save(timer);
500 
501  return true;
502 }
503 
504 #ifdef RESERVOIR_COUPLING_ENABLED
505 template<class TypeTag>
506 void
509 {
510  if (terminalOutput_) {
511  OpmLog::info("Reservoir coupling: master simulation has ended; "
512  "stopping slave simulation gracefully.");
513  }
514  // The slave stops as soon as it is terminated, so no further substeps run for this report
515  // step. Per-substep SUMMARY output for any substeps already completed in this report step
516  // was written by the adaptive substep loop; the report-step-level restart write is
517  // intentionally skipped because a terminated report step is partial - the last completed
518  // report step is the clean restart point. finalize() flushes the remaining output.
519  // Balance the beginReportStep() issued earlier in runStep().
520  this->solver_->model().endReportStep();
521  // Account for this report step's solver time and leave the timer stopped: runStep()'s own
522  // solverTimer_->stop()/accumulation below is bypassed by the early return on termination.
523  this->solverTimer_->stop();
524  this->report_.success.solver_time += this->solverTimer_->secsSinceStart();
525 }
526 #endif
527 
528 template<class TypeTag>
529 SimulatorReport
532 {
533  // make sure all output is written to disk before run is finished
534  {
535  Dune::Timer finalOutputTimer;
536  finalOutputTimer.start();
537 
538  simulator_.problem().finalizeOutput();
539  report_.success.output_write_time += finalOutputTimer.stop();
540  }
541 
542  // Stop timer and create timing report
543  totalTimer_->stop();
544  report_.success.total_time = totalTimer_->secsSinceStart();
545  report_.success.converged = true;
546 
547  return report_;
548 }
549 
550 template<class TypeTag>
551 template<class Serializer>
552 void
554 serializeOp(Serializer& serializer)
555 {
556  serializer(simulator_);
557  serializer(report_);
558  serializer(adaptiveTimeStepping_);
559 }
560 
561 template<class TypeTag>
562 void
564 loadState([[maybe_unused]] HDF5Serializer& serializer,
565  [[maybe_unused]] const std::string& groupName)
566 {
567 #if HAVE_HDF5
568  serializer.read(*this, groupName, "simulator_data");
569 #endif
570 }
571 
572 template<class TypeTag>
573 void
575 saveState([[maybe_unused]] HDF5Serializer& serializer,
576  [[maybe_unused]] const std::string& groupName) const
577 {
578 #if HAVE_HDF5
579  serializer.write(*this, groupName, "simulator_data");
580 #endif
581 }
582 
583 template<class TypeTag>
584 std::array<std::string,5>
586 getHeader() const
587 {
588  std::ostringstream str;
589  Parameters::printValues(str);
590  return {"OPM Flow",
591  moduleVersion(),
593  simulator_.vanguard().caseName(),
594  str.str()};
595 }
596 
597 template<class TypeTag>
598 std::unique_ptr<typename SimulatorFullyImplicit<TypeTag>::Solver>
600 createSolver(WellModel& wellModel)
601 {
602  auto model = std::make_unique<Model>(simulator_,
603  modelParam_,
604  wellModel,
605  terminalOutput_);
606 
607  if (this->modelParam_.write_partitions_) {
608  const auto& iocfg = this->eclState().cfg().io();
609 
610  const auto odir = iocfg.getOutputDir()
611  / std::filesystem::path { "partition" }
612  / iocfg.getBaseName();
613 
614  if (this->grid().comm().rank() == 0) {
615  create_directories(odir);
616  }
617 
618  this->grid().comm().barrier();
619 
620  model->writePartitions(odir);
621 
622  this->modelParam_.write_partitions_ = false;
623  }
624 
625  return std::make_unique<Solver>(solverParam_, std::move(model));
626 }
627 
628 } // namespace Opm
629 
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&#39;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&#39;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