Refactor SimulatorReport system.

Now SimulatorReport object contains a vector of SimulatorReportSingle objects,
for both successful and failing steps.
This commit is contained in:
Atgeirr Flø Rasmussen 2020-05-07 16:13:39 +02:00
parent cfdb2b9be6
commit 8dd53a38e9
9 changed files with 88 additions and 140 deletions

View File

@ -229,12 +229,12 @@ namespace Opm {
/// \param[in, out] reservoir_state reservoir state variables
/// \param[in, out] well_state well state variables
template <class NonlinearSolverType>
SimulatorReportBase nonlinearIteration(const int iteration,
const SimulatorTimerInterface& timer,
NonlinearSolverType& nonlinear_solver)
SimulatorReportSingle nonlinearIteration(const int iteration,
const SimulatorTimerInterface& timer,
NonlinearSolverType& nonlinear_solver)
{
SimulatorReportBase report;
failureReport_ = SimulatorReportBase();
SimulatorReportSingle report;
failureReport_ = SimulatorReportSingle();
Dune::Timer perfTimer;
perfTimer.start();
@ -368,8 +368,8 @@ namespace Opm {
/// \param[in] reservoir_state reservoir state variables
/// \param[in, out] well_state well state variables
/// \param[in] initial_assembly pass true if this is the first call to assemble() in this timestep
SimulatorReport assembleReservoir(const SimulatorTimerInterface& /* timer */,
const int iterationIdx)
SimulatorReportSingle assembleReservoir(const SimulatorTimerInterface& /* timer */,
const int iterationIdx)
{
// -------- Mass balance equations --------
ebosSimulator_.model().newtonMethod().setIterationIndex(iterationIdx);
@ -854,7 +854,7 @@ namespace Opm {
{ return ebosSimulator_; }
/// return the statistics if the nonlinearIteration() method failed
const SimulatorReportBase& failureReport() const
const SimulatorReportSingle& failureReport() const
{ return failureReport_; }
struct StepReport
@ -885,7 +885,7 @@ namespace Opm {
const bool has_brine_;
ModelParameters param_;
SimulatorReportBase failureReport_;
SimulatorReportSingle failureReport_;
// Well Model
BlackoilWellModel<TypeTag>& well_model_;

View File

@ -504,8 +504,7 @@ namespace Opm
OpmLog::info(msg);
}
SimulatorReport successReport = simulator_->run(simtimer);
SimulatorReport failureReport = simulator_->failureReport();
SimulatorReport report = simulator_->run(simtimer);
if (output_cout) {
std::ostringstream ss;
ss << "\n\n================ End of simulation ===============\n\n";
@ -516,23 +515,18 @@ namespace Opm
int threads = 1;
#endif
ss << "Threads per MPI process: " << std::setw(5) << threads << "\n";
successReport.reportFullyImplicit(ss, &failureReport);
report.reportFullyImplicit(ss);
OpmLog::info(ss.str());
const std::string dir = eclState().getIOConfig().getOutputDir();
namespace fs = Opm::filesystem;
fs::path output_dir(dir);
{
fs::path fullpath = output_dir / "successreports.txt";
fs::path fullpath = output_dir / "confreports.txt";
std::ofstream os(fullpath.string());
successReport.fullReports(os);
report.fullReports(os);
}
{
fs::path fullpath = output_dir / "failedreports.txt";
std::ofstream os(fullpath.string());
failureReport.fullReports(os);
}
}
return successReport.exit_status;
return report.success.exit_status;
} else {
if (output_cout) {
std::cout << "\n\n================ Simulation turned off ===============\n" << std::flush;

View File

@ -149,13 +149,13 @@ namespace Opm {
}
SimulatorReport step(const SimulatorTimerInterface& timer)
SimulatorReportSingle step(const SimulatorTimerInterface& timer)
{
SimulatorReportBase iterReport;
SimulatorReportBase report;
report.global_time = timer.simulationTimeElapsed();
failureReport_ = SimulatorReport();
failureReport_.global_time = timer.simulationTimeElapsed();
SimulatorReportSingle iterReport;
SimulatorReportSingle report;
report.global_time = timer.simulationTimeElapsed();
failureReport_ = SimulatorReportSingle();
failureReport_.global_time = timer.simulationTimeElapsed();
// Do model-specific once-per-step calculations.
model_->prepareStep(timer);
@ -173,7 +173,7 @@ namespace Opm {
// model will usually do an early return without an expensive
// solve, unless the minIter() count has not been reached yet.
iterReport = model_->nonlinearIteration(iteration, timer, *this);
iterReport.global_time = timer.simulationTimeElapsed();
iterReport.global_time = timer.simulationTimeElapsed();
report += iterReport;
report.converged = iterReport.converged;
@ -200,14 +200,11 @@ namespace Opm {
// Do model-specific post-step actions.
model_->afterStep(timer);
report.converged = true;
SimulatorReport report_step;
report_step += report;
report_step.converged = true;
return report_step;
return report;
}
/// return the statistics if the step() method failed
const SimulatorReport& failureReport() const
const SimulatorReportSingle& failureReport() const
{ return failureReport_; }
/// Number of linearizations used in all calls to step().
@ -356,7 +353,7 @@ namespace Opm {
private:
// --------- Data members ---------
SimulatorReport failureReport_;
SimulatorReportSingle failureReport_;
SolverParameters param_;
std::unique_ptr<PhysicalModel> model_;
int linearizations_;

View File

@ -1,5 +1,5 @@
/*
Copyright 2013, 2015 SINTEF ICT, Applied Mathematics.
Copyright 2013, 2015, 2020 SINTEF Digital, Mathematics and Cybernetics.
Copyright 2015 Andreas Lauser
Copyright 2017 IRIS
@ -130,8 +130,6 @@ public:
/// \return simulation report, with timing data
SimulatorReport run(SimulatorTimer& timer)
{
failureReport_ = SimulatorReport();
ebosSimulator_.setEpisodeIndex(-1);
// Create timers and file for writing timing info.
@ -160,7 +158,6 @@ public:
}
SimulatorReport report;
SimulatorReport stepReport;
// Main simulation loop.
while (!timer.done()) {
@ -168,7 +165,7 @@ public:
if (terminalOutput_) {
OpmLog::info("Stopping simulation since EXIT was triggered by an action keyword.");
}
report.exit_status = schedule().exitStatus().value();
report.success.exit_status = schedule().exitStatus().value();
break;
}
@ -203,7 +200,7 @@ public:
wellModel_().beginReportStep(timer.currentStepNum());
ebosSimulator_.problem().writeOutput();
report.output_write_time += perfTimer.stop();
report.success.output_write_time += perfTimer.stop();
}
// Run a multiple steps of the solver depending on the time step control.
@ -232,16 +229,12 @@ public:
events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE, timer.currentStepNum()) ||
events.hasEvent(ScheduleEvents::INJECTION_UPDATE, timer.currentStepNum()) ||
events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE, timer.currentStepNum());
stepReport = adaptiveTimeStepping->step(timer, *solver, event, nullptr);
auto stepReport = adaptiveTimeStepping->step(timer, *solver, event, nullptr);
report += stepReport;
failureReport_ += adaptiveTimeStepping->failureReport();
}
else {
} else {
// solve for complete report step
stepReport = solver->step(timer);
auto stepReport = solver->step(timer);
report += stepReport;
failureReport_ += solver->failureReport();
if (terminalOutput_) {
std::ostringstream ss;
stepReport.reportStep(ss);
@ -255,7 +248,7 @@ public:
const double nextstep = adaptiveTimeStepping ? adaptiveTimeStepping->suggestedNextStep() : -1.0;
ebosSimulator_.problem().setNextTimeStepSize(nextstep);
ebosSimulator_.problem().writeOutput();
report.output_write_time += perfTimer.stop();
report.success.output_write_time += perfTimer.stop();
solver->model().endReportStep();
@ -263,7 +256,7 @@ public:
solverTimer.stop();
// update timing.
report.solver_time += solverTimer.secsSinceStart();
report.success.solver_time += solverTimer.secsSinceStart();
// Increment timer, remember well state.
++timer;
@ -279,7 +272,7 @@ public:
if (terminalOutput_) {
std::string msg =
"Time step took " + std::to_string(solverTimer.secsSinceStart()) + " seconds; "
"total solver time " + std::to_string(report.solver_time) + " seconds.";
"total solver time " + std::to_string(report.success.solver_time) + " seconds.";
OpmLog::debug(msg);
}
@ -291,22 +284,17 @@ public:
finalOutputTimer.start();
ebosSimulator_.problem().finalizeOutput();
report.output_write_time += finalOutputTimer.stop();
report.success.output_write_time += finalOutputTimer.stop();
}
// Stop timer and create timing report
totalTimer.stop();
report.total_time = totalTimer.secsSinceStart();
report.converged = true;
report.success.total_time = totalTimer.secsSinceStart();
report.success.converged = true;
return report;
}
/** \brief Returns the simulator report for the failed substeps of the simulation.
*/
const SimulatorReport& failureReport() const
{ return failureReport_; };
const Grid& grid() const
{ return ebosSimulator_.vanguard().grid(); }
@ -358,7 +346,6 @@ protected:
// Data.
Simulator& ebosSimulator_;
std::unique_ptr<WellConnectionAuxiliaryModule<TypeTag>> wellAuxMod_;
SimulatorReport failureReport_;
ModelParameters modelParam_;
SolverParameters solverParam_;

View File

@ -193,9 +193,9 @@ namespace Opm {
*/
template <class Solver>
SimulatorReport step(const SimulatorTimer& simulatorTimer,
Solver& solver,
const bool isEvent,
const std::vector<int>* fipnum = nullptr)
Solver& solver,
const bool isEvent,
const std::vector<int>* fipnum = nullptr)
{
SimulatorReport report;
const double timestep = simulatorTimer.currentStepLength();
@ -220,9 +220,6 @@ namespace Opm {
// create adaptive step timer with previously used sub step size
AdaptiveSimulatorTimer substepTimer(simulatorTimer, suggestedNextTimestep_, maxTimeStep_);
// reset the statistics for the failed substeps
failureReport_ = SimulatorReport();
// counter for solver restarts
int restarts = 0;
@ -242,12 +239,10 @@ namespace Opm {
OpmLog::info(ss.str());
}
SimulatorReport substepReport;
SimulatorReportSingle substepReport;
std::string causeOfFailure = "";
try {
substepReport = solver.step(substepTimer);
report += substepReport;
if (solverVerbose_) {
// report number of linear iterations
OpmLog::debug("Overall linear iterations used: " + std::to_string(substepReport.total_linear_iterations));
@ -293,6 +288,8 @@ namespace Opm {
// this can be thrown by ISTL's ILU0 in block mode, yet is not an ISTLError
}
report += substepReport;
if (substepReport.converged) {
// advance by current dt
++substepTimer;
@ -343,21 +340,19 @@ namespace Opm {
ebosProblem.writeOutput();
report.output_write_time += perfTimer.secsSinceStart();
report.success.output_write_time += perfTimer.secsSinceStart();
}
// set new time step length
substepTimer.provideTimeStepEstimate(dtEstimate);
report.converged = substepTimer.done();
report.success.converged = substepTimer.done();
substepTimer.setLastStepFailed(false);
}
else { // in case of no convergence
substepTimer.setLastStepFailed(true);
failureReport_ += substepReport;
// If we have restarted (i.e. cut the timestep) too
// many times, we have failed and throw an exception.
if (restarts >= solverRestartMax_) {
@ -457,9 +452,6 @@ namespace Opm {
/** \brief Returns the simulator report for the failed substeps of the last
* report step.
*/
const SimulatorReport& failureReport() const
{ return failureReport_; };
double suggestedNextStep() const
{ return suggestedNextTimestep_; }
@ -567,11 +559,8 @@ namespace Opm {
return failing_wells;
}
typedef std::unique_ptr<TimeStepControlInterface> TimeStepControlType;
SimulatorReport failureReport_; //!< statistics for the failed substeps of the last timestep
TimeStepControlType timeStepControl_; //!< time step control object
double restartFactor_; //!< factor to multiply time step with when solver fails to converge
double growthFactor_; //!< factor to multiply time step when solver recovered from failed convergence

View File

@ -29,7 +29,7 @@
namespace Opm
{
SimulatorReportBase::SimulatorReportBase(bool verbose)
SimulatorReportSingle::SimulatorReportSingle(bool verbose)
: pressure_time(0.0),
transport_time(0.0),
total_time(0.0),
@ -50,7 +50,7 @@ namespace Opm
{
}
void SimulatorReportBase::operator+=(const SimulatorReportBase& sr)
void SimulatorReportSingle::operator+=(const SimulatorReportSingle& sr)
{
pressure_time += sr.pressure_time;
transport_time += sr.transport_time;
@ -68,20 +68,8 @@ namespace Opm
global_time = sr.global_time;
}
// void SimulatorReportBase::report(std::ostream& os)
// {
// if ( verbose_ )
// {
// os << "Total time taken: " << total_time
// << "\n Pressure time: " << pressure_time
// << "\n Transport time: " << transport_time
// << "\n Overall Newton Iterations: " << total_newton_iterations
// << "\n Overall Linear Iterations: " << total_linear_iterations
// << std::endl;
// }
// }
void SimulatorReportBase::reportStep(std::ostringstream& ss)
void SimulatorReportSingle::reportStep(std::ostringstream& ss) const
{
if ( verbose_ )
{
@ -97,7 +85,7 @@ namespace Opm
}
}
void SimulatorReportBase::reportFullyImplicit(std::ostream& os, const SimulatorReportBase* failureReport)
void SimulatorReportSingle::reportFullyImplicit(std::ostream& os, const SimulatorReportSingle* failureReport) const
{
if ( verbose_ )
{
@ -182,13 +170,11 @@ namespace Opm
}
}
void SimulatorReport::fullReports(std::ostream& os)
void SimulatorReport::fullReports(std::ostream& os) const
{
os << " Time(sec) Time(day) Assembly LSolve LSetup Update Output WellIt Lins NewtIt LinIt Conv\n";
SimulatorReportBase all;
for (size_t i = 0; i < stepreports.size(); ++i) {
SimulatorReportBase& sr = stepreports[i];
all += sr;
for (size_t i = 0; i < this->stepreports.size(); ++i) {
const SimulatorReportSingle& sr = this->stepreports[i];
os.precision(10);
os << std::defaultfloat;
os << std::setw(11) << sr.global_time << " ";
@ -208,9 +194,6 @@ namespace Opm
os << std::setw(5) << sr.total_linear_iterations << " ";
os << std::setw(4) << sr.converged << "\n";
}
if (not(this->linear_solve_time == all.linear_solve_time)) {
OpmLog::debug("Inconsistency between timestep report and total report");
}
}
} // namespace Opm

View File

@ -1,5 +1,5 @@
/*
Copyright 2012 SINTEF ICT, Applied Mathematics.
Copyright 2012, 2020 SINTEF Digital, Mathematics and Cybernetics.
This file is part of the Open Porous Media project (OPM).
@ -27,7 +27,7 @@ namespace Opm
{
/// A struct for returning timing data from a simulator to its caller.
struct SimulatorReportBase
struct SimulatorReportSingle
{
double pressure_time;
double transport_time;
@ -49,51 +49,49 @@ namespace Opm
double global_time;
/// Default constructor initializing all times to 0.0.
explicit SimulatorReportBase(bool verbose=true);
/// Copy constructor
// SimulatorReportBase(const SimulatorReportBase&) = default;
explicit SimulatorReportSingle(const bool verbose = true);
/// Increment this report's times by those in sr.
void operator+=(const SimulatorReportBase& sr);
/// Print a report to the given stream.
// void report(std::ostream& os);
void reportStep(std::ostringstream& os);
/// Print a report, leaving out the transport time.
void reportFullyImplicit(std::ostream& os, const SimulatorReportBase* failedReport = nullptr);
// void reportParam(std::ostream& os);
void operator+=(const SimulatorReportSingle& sr);
/// Print a report suitable for a single simulation step.
void reportStep(std::ostringstream& os) const;
/// Print a report suitable for the end of a fully implicit case, leaving out the pressure/transport time.
void reportFullyImplicit(std::ostream& os, const SimulatorReportSingle* failedReport = nullptr) const;
private:
// Whether to print statistics to std::cout
bool verbose_;
};
struct SimulatorReport : public SimulatorReportBase {
std::vector<SimulatorReportBase> stepreports;
struct SimulatorReport
{
SimulatorReportSingle success;
SimulatorReportSingle failure;
std::vector<SimulatorReportSingle> stepreports;
explicit SimulatorReport(bool verbose = true)
: SimulatorReportBase(verbose)
, stepreports()
: success(verbose)
, failure(verbose)
{
}
void operator+=(const SimulatorReportBase& sr)
void operator+=(const SimulatorReportSingle& sr)
{
SimulatorReportBase::operator+=(sr);
// if(stepreports.size()>0){
// assert(stepreports.back().global_time != sr.global_time);
// }
if (sr.converged) {
success += sr;
} else {
failure += sr;
}
stepreports.push_back(sr);
}
void operator+=(const SimulatorReport& sr)
{
SimulatorReportBase::operator+=(sr);
// if(stepreports.size()>0){
// assert(stepreports.back().global_time != sr.global_time);
// }
if (sr.stepreports.size() > 0) {
stepreports.insert(stepreports.end(), sr.stepreports.begin(), sr.stepreports.end());
} else {
stepreports.push_back(sr);
}
// stepreports.push_back(sr);
success += sr.success;
failure += sr.failure;
stepreports.insert(stepreports.end(), sr.stepreports.begin(), sr.stepreports.end());
}
void fullReports(std::ostream& os);
void reportFullyImplicit(std::ostream& os) const
{
success.reportFullyImplicit(os, &failure);
}
void fullReports(std::ostream& os) const;
};
} // namespace Opm

View File

@ -253,7 +253,7 @@ namespace Opm {
// return the internal well state
const WellState& wellState() const;
const SimulatorReport& lastReport() const;
const SimulatorReportSingle& lastReport() const;
void addWellContributions(SparseMatrixAdapter& jacobian) const
{
@ -317,7 +317,7 @@ namespace Opm {
std::unique_ptr<RateConverterType> rateConverter_;
std::unique_ptr<VFPProperties<VFPInjProperties,VFPProdProperties>> vfp_properties_;
SimulatorReport last_report_;
SimulatorReportSingle last_report_;
WellTestState wellTestState_;
std::unique_ptr<GuideRate> guideRate_;
@ -377,7 +377,7 @@ namespace Opm {
/// at the beginning of the time step and no derivatives are included in these quantities
void calculateExplicitQuantities(Opm::DeferredLogger& deferred_logger) const;
SimulatorReport solveWellEq(const std::vector<Scalar>& B_avg, const double dt, Opm::DeferredLogger& deferred_logger);
SimulatorReportSingle solveWellEq(const std::vector<Scalar>& B_avg, const double dt, Opm::DeferredLogger& deferred_logger);
void initPrimaryVariablesEvaluation() const;

View File

@ -430,7 +430,7 @@ namespace Opm {
// called at the end of a report step
template<typename TypeTag>
const SimulatorReport&
const SimulatorReportSingle&
BlackoilWellModel<TypeTag>::
lastReport() const {return last_report_; }
@ -809,7 +809,7 @@ namespace Opm {
const double dt)
{
last_report_ = SimulatorReport();
last_report_ = SimulatorReportSingle();
if ( ! wellsActive() ) {
return;
@ -1027,7 +1027,7 @@ namespace Opm {
template<typename TypeTag>
SimulatorReport
SimulatorReportSingle
BlackoilWellModel<TypeTag>::
solveWellEq(const std::vector<Scalar>& B_avg, const double dt, Opm::DeferredLogger& deferred_logger)
{
@ -1095,7 +1095,7 @@ namespace Opm {
logAndCheckForExceptionsAndThrow(deferred_logger, exception_thrown, "solveWellEq() failed.", terminal_output_);
SimulatorReport report;
SimulatorReportSingle report;
report.converged = converged;
report.total_well_iterations = it;
return report;