diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index 90343d178..d83d65a06 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -109,6 +109,7 @@ list (APPEND MAIN_SOURCE_FILES
opm/simulators/flow/partitionCells.cpp
opm/simulators/flow/RSTConv.cpp
opm/simulators/flow/RegionPhasePVAverage.cpp
+ opm/simulators/flow/SimulatorConvergenceOutput.cpp
opm/simulators/flow/SimulatorReportBanners.cpp
opm/simulators/flow/SimulatorSerializer.cpp
opm/simulators/flow/SolutionContainers.cpp
@@ -843,6 +844,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/simulators/flow/priVarsPacking.hpp
opm/simulators/flow/RSTConv.hpp
opm/simulators/flow/RegionPhasePVAverage.hpp
+ opm/simulators/flow/SimulatorConvergenceOutput.hpp
opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
opm/simulators/flow/SimulatorReportBanners.hpp
opm/simulators/flow/SimulatorSerializer.hpp
diff --git a/opm/simulators/flow/SimulatorConvergenceOutput.cpp b/opm/simulators/flow/SimulatorConvergenceOutput.cpp
new file mode 100644
index 000000000..a96028705
--- /dev/null
+++ b/opm/simulators/flow/SimulatorConvergenceOutput.cpp
@@ -0,0 +1,94 @@
+/*
+ Copyright 2013, 2015, 2020 SINTEF Digital, Mathematics and Cybernetics.
+ Copyright 2015 Andreas Lauser
+ Copyright 2017 IRIS
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OPM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OPM. If not, see .
+*/
+#include
+#include
+
+#include
+#include
+
+#include
+
+namespace Opm {
+
+void SimulatorConvergenceOutput::
+startThread(std::string_view convOutputOptions,
+ std::string_view optionName,
+ ConvergenceOutputThread::ComponentToPhaseName getPhaseName)
+{
+ const auto config = ConvergenceOutputConfiguration {
+ convOutputOptions, optionName
+ };
+
+ if (! config.want(ConvergenceOutputConfiguration::Option::Iterations)) {
+ return;
+ }
+
+ auto convertTime = ConvergenceOutputThread::ConvertToTimeUnits {
+ [usys = eclState_.getUnits()](const double time)
+ { return usys.from_si(UnitSystem::measure::time, time); }
+ };
+
+ this->convergenceOutputQueue_.emplace();
+ this->convergenceOutputObject_.emplace
+ (eclState_.getIOConfig().getOutputDir(),
+ eclState_.getIOConfig().getBaseName(),
+ std::move(getPhaseName),
+ std::move(convertTime),
+ config, *this->convergenceOutputQueue_);
+
+ this->convergenceOutputThread_
+ .emplace(&ConvergenceOutputThread::writeASynchronous,
+ &this->convergenceOutputObject_.value());
+}
+
+void SimulatorConvergenceOutput::
+write(const std::vector& reports)
+{
+ if (! this->convergenceOutputThread_.has_value()) {
+ return;
+ }
+
+ auto new_reports = std::vector {
+ reports.begin() + this->already_reported_steps_, reports.end()
+ };
+
+ auto requests = std::vector{};
+ requests.reserve(new_reports.size());
+
+ for (auto&& report : new_reports) {
+ requests.push_back({ report.report_step, report.current_step, std::move(report.report) });
+ }
+ this->already_reported_steps_ = reports.size();
+
+ this->convergenceOutputQueue_->enqueue(std::move(requests));
+}
+
+void SimulatorConvergenceOutput::endThread()
+{
+ if (! this->convergenceOutputThread_.has_value()) {
+ return;
+ }
+
+ this->convergenceOutputQueue_->signalLastOutputRequest();
+ this->convergenceOutputThread_->join();
+}
+
+} // namespace Opm
diff --git a/opm/simulators/flow/SimulatorConvergenceOutput.hpp b/opm/simulators/flow/SimulatorConvergenceOutput.hpp
new file mode 100644
index 000000000..37aebe86c
--- /dev/null
+++ b/opm/simulators/flow/SimulatorConvergenceOutput.hpp
@@ -0,0 +1,66 @@
+/*
+ Copyright 2013, 2015, 2020 SINTEF Digital, Mathematics and Cybernetics.
+ Copyright 2015 Andreas Lauser
+ Copyright 2017 IRIS
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OPM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OPM. If not, see .
+*/
+
+#ifndef OPM_SIMULATOR_CONVERGENCE_OUTPUT_HEADER_INCLUDED
+#define OPM_SIMULATOR_CONVERGENCE_OUTPUT_HEADER_INCLUDED
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Opm {
+
+class EclipseState;
+struct StepReport;
+
+/// Class handling convergence history output for a simulator.
+class SimulatorConvergenceOutput
+{
+public:
+ explicit SimulatorConvergenceOutput(const EclipseState& eclState)
+ : eclState_(eclState)
+ {}
+
+ void startThread(std::string_view convOutputOptions,
+ std::string_view optionName,
+ ConvergenceOutputThread::ComponentToPhaseName getPhaseName);
+
+ void write(const std::vector& reports);
+
+ void endThread();
+
+private:
+ const EclipseState& eclState_;
+
+ std::size_t already_reported_steps_ = 0;
+
+ std::optional convergenceOutputQueue_{};
+ std::optional convergenceOutputObject_{};
+ std::optional convergenceOutputThread_{};
+};
+
+} // namespace Opm
+
+#endif // OPM_SIMULATOR_CONVERGENCE_OUTPUT_HEADER_INCLUDED
diff --git a/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp b/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
index 14b663dc2..01ee43d34 100644
--- a/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
+++ b/opm/simulators/flow/SimulatorFullyImplicitBlackoil.hpp
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -45,18 +46,15 @@
#include
#endif
-#include
-
-#include
#include
#include
-#include
#include
#include
-#include
#include
#include
+#include
+
namespace Opm::Parameters {
struct EnableAdaptiveTimeStepping { static constexpr bool value = true; };
@@ -117,8 +115,9 @@ public:
/// \param[in] eclipse_state the object which represents an internalized ECL deck
/// \param[in] output_writer
/// \param[in] threshold_pressures_by_face if nonempty, threshold pressures that inhibit flow
- SimulatorFullyImplicitBlackoil(Simulator& simulator)
+ explicit SimulatorFullyImplicitBlackoil(Simulator& simulator)
: simulator_(simulator)
+ , convergence_output_(simulator_.vanguard().eclState())
, serializer_(*this,
FlowGenericVanguard::comm(),
simulator_.vanguard().eclState().getIOConfig(),
@@ -134,15 +133,22 @@ public:
if (this->grid().comm().rank() == 0) {
this->terminalOutput_ = Parameters::Get();
- this->startConvergenceOutputThread(Parameters::Get(),
- R"(OutputExtraConvergenceInfo (--output-extra-convergence-info))");
+ auto getPhaseName = ConvergenceOutputThread::ComponentToPhaseName {
+ [compNames = typename Model::ComponentName{}](const int compIdx)
+ { return std::string_view { compNames.name(compIdx) }; }
+ };
+
+ convergence_output_.
+ startThread(Parameters::Get(),
+ R"(OutputExtraConvergenceInfo (--output-extra-convergence-info))",
+ getPhaseName);
}
}
~SimulatorFullyImplicitBlackoil()
{
// Safe to call on all ranks, not just the I/O rank.
- this->endConvergenceOutputThread();
+ convergence_output_.endThread();
}
static void registerParameters()
@@ -420,14 +426,7 @@ public:
// Grab the step convergence reports that are new since last we
// were here.
const auto& reps = this->solver_->model().stepReports();
-
- auto reports = std::vector {
- reps.begin() + this->already_reported_steps_, reps.end()
- };
-
- this->writeConvergenceOutput(std::move(reports));
-
- this->already_reported_steps_ = reps.size();
+ convergence_output_.write(reps);
}
// Increment timer, remember well state.
@@ -563,65 +562,6 @@ protected:
const WellModel& wellModel_() const
{ return simulator_.problem().wellModel(); }
- void startConvergenceOutputThread(std::string_view convOutputOptions,
- std::string_view optionName)
- {
- const auto config = ConvergenceOutputConfiguration {
- convOutputOptions, optionName
- };
- if (! config.want(ConvergenceOutputConfiguration::Option::Iterations)) {
- return;
- }
-
- auto getPhaseName = ConvergenceOutputThread::ComponentToPhaseName {
- [compNames = typename Model::ComponentName{}](const int compIdx)
- { return std::string_view { compNames.name(compIdx) }; }
- };
-
- auto convertTime = ConvergenceOutputThread::ConvertToTimeUnits {
- [usys = this->eclState().getUnits()](const double time)
- { return usys.from_si(UnitSystem::measure::time, time); }
- };
-
- this->convergenceOutputQueue_.emplace();
- this->convergenceOutputObject_.emplace
- (this->eclState().getIOConfig().getOutputDir(),
- this->eclState().getIOConfig().getBaseName(),
- std::move(getPhaseName),
- std::move(convertTime),
- config, *this->convergenceOutputQueue_);
-
- this->convergenceOutputThread_
- .emplace(&ConvergenceOutputThread::writeASynchronous,
- &this->convergenceOutputObject_.value());
- }
-
- void writeConvergenceOutput(std::vector&& reports)
- {
- if (! this->convergenceOutputThread_.has_value()) {
- return;
- }
-
- auto requests = std::vector{};
- requests.reserve(reports.size());
-
- for (auto&& report : reports) {
- requests.push_back({ report.report_step, report.current_step, std::move(report.report) });
- }
-
- this->convergenceOutputQueue_->enqueue(std::move(requests));
- }
-
- void endConvergenceOutputThread()
- {
- if (! this->convergenceOutputThread_.has_value()) {
- return;
- }
-
- this->convergenceOutputQueue_->signalLastOutputRequest();
- this->convergenceOutputThread_->join();
- }
-
// Data.
Simulator& simulator_;
@@ -636,14 +576,11 @@ protected:
bool terminalOutput_;
SimulatorReport report_;
- std::size_t already_reported_steps_ = 0;
std::unique_ptr solverTimer_;
std::unique_ptr totalTimer_;
std::unique_ptr adaptiveTimeStepping_;
- std::optional convergenceOutputQueue_{};
- std::optional convergenceOutputObject_{};
- std::optional convergenceOutputThread_{};
+ SimulatorConvergenceOutput convergence_output_;
SimulatorSerializer serializer_;
};