mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Refactor SimulatorFullyImplicitBlackoilEbos.hpp
A resubmission of commit bb20804
in PR #2403 and PR #2442 to work with the
current master.
Continues the work in #2619 and #2631 to refactor main simulation loop in
flow to work with the Python bindings.
The run() method in SimulatorFullyImplicitBlackoilEbos.hpp is refactored
in preparation for the implementation of a Python step() function in a
later commit. Currently run() is called from runSimulatorInitOrRun() in
FlowMainEbos.hpp using the runSimulatorRunCallback_(). Later, there
will be other callbacks like runSimulatorStepInitCallback_(), and
runSimulatorStepCallback_(), that will need to call different parts of
the code in run(). The run() function is thus refactored into run(),
runInit(), runStep(), and runLastStep(). Also, some of the local
variables in run() have to be made persistent between calls to
runStep(), this applies to variables report, solverTimer, totalTimer,
and adaptiveTimeStepping, which are made private class variables.
This commit is contained in:
parent
3766f19de3
commit
e8a4065192
@ -128,170 +128,183 @@ public:
|
||||
/// \param[in,out] state state of reservoir: pressure, fluxes
|
||||
/// \return simulation report, with timing data
|
||||
SimulatorReport run(SimulatorTimer& timer)
|
||||
{
|
||||
runInit(timer);
|
||||
// Main simulation loop.
|
||||
while (!timer.done()) {
|
||||
runStep(timer);
|
||||
}
|
||||
return runLastStep();
|
||||
}
|
||||
|
||||
void runInit(SimulatorTimer &timer)
|
||||
{
|
||||
ebosSimulator_.setEpisodeIndex(-1);
|
||||
|
||||
// Create timers and file for writing timing info.
|
||||
Opm::time::StopWatch solverTimer;
|
||||
Opm::time::StopWatch totalTimer;
|
||||
totalTimer.start();
|
||||
solverTimer_ = std::make_unique<Opm::time::StopWatch>();
|
||||
totalTimer_ = std::make_unique<Opm::time::StopWatch>();
|
||||
totalTimer_->start();
|
||||
|
||||
// adaptive time stepping
|
||||
const auto& events = schedule().getEvents();
|
||||
std::unique_ptr<TimeStepper > adaptiveTimeStepping;
|
||||
bool enableAdaptive = EWOMS_GET_PARAM(TypeTag, bool, EnableAdaptiveTimeStepping);
|
||||
bool enableTUNING = EWOMS_GET_PARAM(TypeTag, bool, EnableTuning);
|
||||
if (enableAdaptive) {
|
||||
if (enableTUNING) {
|
||||
adaptiveTimeStepping.reset(new TimeStepper(schedule().getTuning(timer.currentStepNum()), terminalOutput_));
|
||||
adaptiveTimeStepping_ = std::make_unique<TimeStepper>(
|
||||
schedule().getTuning(timer.currentStepNum()), terminalOutput_);
|
||||
}
|
||||
else {
|
||||
adaptiveTimeStepping.reset(new TimeStepper(terminalOutput_));
|
||||
adaptiveTimeStepping_ = std::make_unique<TimeStepper>(terminalOutput_);
|
||||
}
|
||||
|
||||
if (isRestart()) {
|
||||
// For restarts the ebosSimulator may have gotten some information
|
||||
// about the next timestep size from the OPMEXTRA field
|
||||
adaptiveTimeStepping->setSuggestedNextStep(ebosSimulator_.timeStepSize());
|
||||
adaptiveTimeStepping_->setSuggestedNextStep(ebosSimulator_.timeStepSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimulatorReport report;
|
||||
|
||||
// Main simulation loop.
|
||||
while (!timer.done()) {
|
||||
if (schedule().exitStatus().has_value()) {
|
||||
if (terminalOutput_) {
|
||||
OpmLog::info("Stopping simulation since EXIT was triggered by an action keyword.");
|
||||
}
|
||||
report.success.exit_status = schedule().exitStatus().value();
|
||||
break;
|
||||
}
|
||||
|
||||
// Report timestep.
|
||||
bool runStep(SimulatorTimer& timer)
|
||||
{
|
||||
if (schedule().exitStatus().has_value()) {
|
||||
if (terminalOutput_) {
|
||||
std::ostringstream ss;
|
||||
timer.report(ss);
|
||||
OpmLog::debug(ss.str());
|
||||
OpmLog::info("Stopping simulation since EXIT was triggered by an action keyword.");
|
||||
}
|
||||
report_.success.exit_status = schedule().exitStatus().value();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (terminalOutput_) {
|
||||
std::ostringstream stepMsg;
|
||||
boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
|
||||
stepMsg.imbue(std::locale(std::locale::classic(), facet));
|
||||
stepMsg << "\nReport step " << std::setw(2) <<timer.currentStepNum()
|
||||
<< "/" << timer.numSteps()
|
||||
<< " at day " << (double)unit::convert::to(timer.simulationTimeElapsed(), unit::day)
|
||||
<< "/" << (double)unit::convert::to(timer.totalTime(), unit::day)
|
||||
<< ", date = " << timer.currentDateTime();
|
||||
OpmLog::info(stepMsg.str());
|
||||
}
|
||||
// Report timestep.
|
||||
if (terminalOutput_) {
|
||||
std::ostringstream ss;
|
||||
timer.report(ss);
|
||||
OpmLog::debug(ss.str());
|
||||
}
|
||||
|
||||
// write the inital state at the report stage
|
||||
if (timer.initialStep()) {
|
||||
Dune::Timer perfTimer;
|
||||
perfTimer.start();
|
||||
if (terminalOutput_) {
|
||||
std::ostringstream stepMsg;
|
||||
boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
|
||||
stepMsg.imbue(std::locale(std::locale::classic(), facet));
|
||||
stepMsg << "\nReport step " << std::setw(2) <<timer.currentStepNum()
|
||||
<< "/" << timer.numSteps()
|
||||
<< " at day " << (double)unit::convert::to(timer.simulationTimeElapsed(), unit::day)
|
||||
<< "/" << (double)unit::convert::to(timer.totalTime(), unit::day)
|
||||
<< ", date = " << timer.currentDateTime();
|
||||
OpmLog::info(stepMsg.str());
|
||||
}
|
||||
|
||||
ebosSimulator_.setEpisodeIndex(-1);
|
||||
ebosSimulator_.setEpisodeLength(0.0);
|
||||
ebosSimulator_.setTimeStepSize(0.0);
|
||||
|
||||
wellModel_().beginReportStep(timer.currentStepNum());
|
||||
ebosSimulator_.problem().writeOutput();
|
||||
|
||||
report.success.output_write_time += perfTimer.stop();
|
||||
}
|
||||
|
||||
// Run a multiple steps of the solver depending on the time step control.
|
||||
solverTimer.start();
|
||||
|
||||
auto solver = createSolver(wellModel_());
|
||||
|
||||
ebosSimulator_.startNextEpisode(ebosSimulator_.startTime() + schedule().getTimeMap().getTimePassedUntil(timer.currentStepNum()),
|
||||
timer.currentStepLength());
|
||||
ebosSimulator_.setEpisodeIndex(timer.currentStepNum());
|
||||
solver->model().beginReportStep();
|
||||
|
||||
// If sub stepping is enabled allow the solver to sub cycle
|
||||
// in case the report steps are too large for the solver to converge
|
||||
//
|
||||
// \Note: The report steps are met in any case
|
||||
// \Note: The sub stepping will require a copy of the state variables
|
||||
if (adaptiveTimeStepping) {
|
||||
if (enableTUNING) {
|
||||
if (events.hasEvent(ScheduleEvents::TUNING_CHANGE,timer.currentStepNum())) {
|
||||
adaptiveTimeStepping->updateTUNING(schedule().getTuning(timer.currentStepNum()));
|
||||
}
|
||||
}
|
||||
|
||||
bool event = events.hasEvent(ScheduleEvents::NEW_WELL, timer.currentStepNum()) ||
|
||||
events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE, timer.currentStepNum()) ||
|
||||
events.hasEvent(ScheduleEvents::INJECTION_UPDATE, timer.currentStepNum()) ||
|
||||
events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE, timer.currentStepNum());
|
||||
auto stepReport = adaptiveTimeStepping->step(timer, *solver, event, nullptr);
|
||||
report += stepReport;
|
||||
} else {
|
||||
// solve for complete report step
|
||||
auto stepReport = solver->step(timer);
|
||||
report += stepReport;
|
||||
if (terminalOutput_) {
|
||||
std::ostringstream ss;
|
||||
stepReport.reportStep(ss);
|
||||
OpmLog::info(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
// write simulation state at the report stage
|
||||
// write the inital state at the report stage
|
||||
if (timer.initialStep()) {
|
||||
Dune::Timer perfTimer;
|
||||
perfTimer.start();
|
||||
const double nextstep = adaptiveTimeStepping ? adaptiveTimeStepping->suggestedNextStep() : -1.0;
|
||||
ebosSimulator_.problem().setNextTimeStepSize(nextstep);
|
||||
|
||||
ebosSimulator_.setEpisodeIndex(-1);
|
||||
ebosSimulator_.setEpisodeLength(0.0);
|
||||
ebosSimulator_.setTimeStepSize(0.0);
|
||||
|
||||
wellModel_().beginReportStep(timer.currentStepNum());
|
||||
ebosSimulator_.problem().writeOutput();
|
||||
report.success.output_write_time += perfTimer.stop();
|
||||
|
||||
solver->model().endReportStep();
|
||||
report_.success.output_write_time += perfTimer.stop();
|
||||
}
|
||||
|
||||
// take time that was used to solve system for this reportStep
|
||||
solverTimer.stop();
|
||||
// Run a multiple steps of the solver depending on the time step control.
|
||||
solverTimer_->start();
|
||||
|
||||
// update timing.
|
||||
report.success.solver_time += solverTimer.secsSinceStart();
|
||||
auto solver = createSolver(wellModel_());
|
||||
|
||||
// Increment timer, remember well state.
|
||||
++timer;
|
||||
ebosSimulator_.startNextEpisode(
|
||||
ebosSimulator_.startTime()
|
||||
+ schedule().getTimeMap().getTimePassedUntil(timer.currentStepNum()),
|
||||
timer.currentStepLength());
|
||||
ebosSimulator_.setEpisodeIndex(timer.currentStepNum());
|
||||
solver->model().beginReportStep();
|
||||
const auto& events = schedule().getEvents();
|
||||
bool enableTUNING = EWOMS_GET_PARAM(TypeTag, bool, EnableTuning);
|
||||
|
||||
|
||||
if (terminalOutput_) {
|
||||
if (!timer.initialStep()) {
|
||||
const std::string version = moduleVersionName();
|
||||
outputTimestampFIP(timer, version);
|
||||
// If sub stepping is enabled allow the solver to sub cycle
|
||||
// in case the report steps are too large for the solver to converge
|
||||
//
|
||||
// \Note: The report steps are met in any case
|
||||
// \Note: The sub stepping will require a copy of the state variables
|
||||
if (adaptiveTimeStepping_) {
|
||||
if (enableTUNING) {
|
||||
if (events.hasEvent(ScheduleEvents::TUNING_CHANGE,timer.currentStepNum())) {
|
||||
adaptiveTimeStepping_->updateTUNING(schedule().getTuning(timer.currentStepNum()));
|
||||
}
|
||||
}
|
||||
|
||||
bool event = events.hasEvent(ScheduleEvents::NEW_WELL, timer.currentStepNum()) ||
|
||||
events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE, timer.currentStepNum()) ||
|
||||
events.hasEvent(ScheduleEvents::INJECTION_UPDATE, timer.currentStepNum()) ||
|
||||
events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE, timer.currentStepNum());
|
||||
auto stepReport = adaptiveTimeStepping_->step(timer, *solver, event, nullptr);
|
||||
report_ += stepReport;
|
||||
} else {
|
||||
// solve for complete report step
|
||||
auto stepReport = solver->step(timer);
|
||||
report_ += stepReport;
|
||||
if (terminalOutput_) {
|
||||
std::string msg =
|
||||
"Time step took " + std::to_string(solverTimer.secsSinceStart()) + " seconds; "
|
||||
"total solver time " + std::to_string(report.success.solver_time) + " seconds.";
|
||||
OpmLog::debug(msg);
|
||||
std::ostringstream ss;
|
||||
stepReport.reportStep(ss);
|
||||
OpmLog::info(ss.str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// write simulation state at the report stage
|
||||
Dune::Timer perfTimer;
|
||||
perfTimer.start();
|
||||
const double nextstep = adaptiveTimeStepping_ ? adaptiveTimeStepping_->suggestedNextStep() : -1.0;
|
||||
ebosSimulator_.problem().setNextTimeStepSize(nextstep);
|
||||
ebosSimulator_.problem().writeOutput();
|
||||
report_.success.output_write_time += perfTimer.stop();
|
||||
|
||||
solver->model().endReportStep();
|
||||
|
||||
// take time that was used to solve system for this reportStep
|
||||
solverTimer_->stop();
|
||||
|
||||
// update timing.
|
||||
report_.success.solver_time += solverTimer_->secsSinceStart();
|
||||
|
||||
// Increment timer, remember well state.
|
||||
++timer;
|
||||
|
||||
if (terminalOutput_) {
|
||||
if (!timer.initialStep()) {
|
||||
const std::string version = moduleVersionName();
|
||||
outputTimestampFIP(timer, version);
|
||||
}
|
||||
}
|
||||
|
||||
if (terminalOutput_) {
|
||||
std::string msg =
|
||||
"Time step took " + std::to_string(solverTimer_->secsSinceStart()) + " seconds; "
|
||||
"total solver time " + std::to_string(report_.success.solver_time) + " seconds.";
|
||||
OpmLog::debug(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SimulatorReport runLastStep()
|
||||
{
|
||||
// make sure all output is written to disk before run is finished
|
||||
{
|
||||
Dune::Timer finalOutputTimer;
|
||||
finalOutputTimer.start();
|
||||
|
||||
ebosSimulator_.problem().finalizeOutput();
|
||||
report.success.output_write_time += finalOutputTimer.stop();
|
||||
report_.success.output_write_time += finalOutputTimer.stop();
|
||||
}
|
||||
|
||||
// Stop timer and create timing report
|
||||
totalTimer.stop();
|
||||
report.success.total_time = totalTimer.secsSinceStart();
|
||||
report.success.converged = true;
|
||||
totalTimer_->stop();
|
||||
report_.success.total_time = totalTimer_->secsSinceStart();
|
||||
report_.success.converged = true;
|
||||
|
||||
return report;
|
||||
return report_;
|
||||
}
|
||||
|
||||
const Grid& grid() const
|
||||
@ -353,6 +366,11 @@ protected:
|
||||
PhaseUsage phaseUsage_;
|
||||
// Misc. data
|
||||
bool terminalOutput_;
|
||||
|
||||
SimulatorReport report_;
|
||||
std::unique_ptr<Opm::time::StopWatch> solverTimer_;
|
||||
std::unique_ptr<Opm::time::StopWatch> totalTimer_;
|
||||
std::unique_ptr<TimeStepper> adaptiveTimeStepping_;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
Loading…
Reference in New Issue
Block a user