From 8dd53a38e99a0f286fe3489db9f214bc1da29d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 7 May 2020 16:13:39 +0200 Subject: [PATCH] Refactor SimulatorReport system. Now SimulatorReport object contains a vector of SimulatorReportSingle objects, for both successful and failing steps. --- opm/simulators/flow/BlackoilModelEbos.hpp | 18 +++--- opm/simulators/flow/FlowMainEbos.hpp | 16 ++--- opm/simulators/flow/NonlinearSolverEbos.hpp | 23 +++---- .../SimulatorFullyImplicitBlackoilEbos.hpp | 37 ++++------- .../timestepping/AdaptiveTimeSteppingEbos.hpp | 27 +++----- .../timestepping/SimulatorReport.cpp | 31 +++------- .../timestepping/SimulatorReport.hpp | 62 +++++++++---------- opm/simulators/wells/BlackoilWellModel.hpp | 6 +- .../wells/BlackoilWellModel_impl.hpp | 8 +-- 9 files changed, 88 insertions(+), 140 deletions(-) diff --git a/opm/simulators/flow/BlackoilModelEbos.hpp b/opm/simulators/flow/BlackoilModelEbos.hpp index e5c7cc096..1fc0c210e 100644 --- a/opm/simulators/flow/BlackoilModelEbos.hpp +++ b/opm/simulators/flow/BlackoilModelEbos.hpp @@ -229,12 +229,12 @@ namespace Opm { /// \param[in, out] reservoir_state reservoir state variables /// \param[in, out] well_state well state variables template - 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& well_model_; diff --git a/opm/simulators/flow/FlowMainEbos.hpp b/opm/simulators/flow/FlowMainEbos.hpp index d56f10762..a647c5bbf 100644 --- a/opm/simulators/flow/FlowMainEbos.hpp +++ b/opm/simulators/flow/FlowMainEbos.hpp @@ -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; diff --git a/opm/simulators/flow/NonlinearSolverEbos.hpp b/opm/simulators/flow/NonlinearSolverEbos.hpp index 91731b7cd..1fc7ca206 100644 --- a/opm/simulators/flow/NonlinearSolverEbos.hpp +++ b/opm/simulators/flow/NonlinearSolverEbos.hpp @@ -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 model_; int linearizations_; diff --git a/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp b/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp index 26b10dbb3..f84667fdb 100644 --- a/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp +++ b/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp @@ -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> wellAuxMod_; - SimulatorReport failureReport_; ModelParameters modelParam_; SolverParameters solverParam_; diff --git a/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp b/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp index 211aa9a67..9225723f0 100644 --- a/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp +++ b/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp @@ -193,9 +193,9 @@ namespace Opm { */ template SimulatorReport step(const SimulatorTimer& simulatorTimer, - Solver& solver, - const bool isEvent, - const std::vector* fipnum = nullptr) + Solver& solver, + const bool isEvent, + const std::vector* 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 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 diff --git a/opm/simulators/timestepping/SimulatorReport.cpp b/opm/simulators/timestepping/SimulatorReport.cpp index 0a1987215..ddbb80911 100644 --- a/opm/simulators/timestepping/SimulatorReport.cpp +++ b/opm/simulators/timestepping/SimulatorReport.cpp @@ -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 diff --git a/opm/simulators/timestepping/SimulatorReport.hpp b/opm/simulators/timestepping/SimulatorReport.hpp index 9e96ec739..fa45b88a4 100644 --- a/opm/simulators/timestepping/SimulatorReport.hpp +++ b/opm/simulators/timestepping/SimulatorReport.hpp @@ -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 stepreports; + struct SimulatorReport + { + SimulatorReportSingle success; + SimulatorReportSingle failure; + std::vector 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 diff --git a/opm/simulators/wells/BlackoilWellModel.hpp b/opm/simulators/wells/BlackoilWellModel.hpp index b5e56002d..802282459 100644 --- a/opm/simulators/wells/BlackoilWellModel.hpp +++ b/opm/simulators/wells/BlackoilWellModel.hpp @@ -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 rateConverter_; std::unique_ptr> vfp_properties_; - SimulatorReport last_report_; + SimulatorReportSingle last_report_; WellTestState wellTestState_; std::unique_ptr 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& B_avg, const double dt, Opm::DeferredLogger& deferred_logger); + SimulatorReportSingle solveWellEq(const std::vector& B_avg, const double dt, Opm::DeferredLogger& deferred_logger); void initPrimaryVariablesEvaluation() const; diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index c63164f40..5dc7d4043 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -430,7 +430,7 @@ namespace Opm { // called at the end of a report step template - const SimulatorReport& + const SimulatorReportSingle& BlackoilWellModel:: 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 - SimulatorReport + SimulatorReportSingle BlackoilWellModel:: solveWellEq(const std::vector& 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;