From a87bf579f9f45912e71b8a0d977e70cb4033bddb Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Fri, 28 Nov 2025 13:27:08 +0100 Subject: [PATCH 1/5] adding functions to output MultisegmentWellPrimaryVariables only the values for now. --- .../MultisegmentWellPrimaryVariables.cpp | 21 +++++++++++++++++++ .../MultisegmentWellPrimaryVariables.hpp | 3 +++ 2 files changed, 24 insertions(+) diff --git a/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp b/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp index b1b585d9126..68d920b8a08 100644 --- a/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp +++ b/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp @@ -702,6 +702,27 @@ outputLowLimitPressureSegments(DeferredLogger& deferred_logger) const } } +template +std::string +MultisegmentWellPrimaryVariables:: +debugInfo() const +{ + std::string msg = fmt::format("Well {} primary variables:\n", this->well_.name()); + for (std::size_t seg = 0; seg < value_.size(); ++seg) { + fmt::format_to(std::back_inserter(msg), " Segment {:4}: ", seg); + fmt::format_to(std::back_inserter(msg), " SPres: {:8.2e} Pa, ", value_[seg][SPres]); + fmt::format_to(std::back_inserter(msg), " WQTotal: {:8.2e} m3/s, ", value_[seg][WQTotal]); + if (has_wfrac_variable) { + fmt::format_to(std::back_inserter(msg), " WFrac: {:5.3f}, ", value_[seg][WFrac]); + } + if (has_gfrac_variable) { + fmt::format_to(std::back_inserter(msg), " GFrac: {:5.3f},", value_[seg][GFrac]); + } + fmt::format_to(std::back_inserter(msg), "\n"); + } + return msg; +} + #include INSTANTIATE_TYPE_INDICES(MultisegmentWellPrimaryVariables, double) diff --git a/opm/simulators/wells/MultisegmentWellPrimaryVariables.hpp b/opm/simulators/wells/MultisegmentWellPrimaryVariables.hpp index 590f87c7b83..ae284f5b06c 100644 --- a/opm/simulators/wells/MultisegmentWellPrimaryVariables.hpp +++ b/opm/simulators/wells/MultisegmentWellPrimaryVariables.hpp @@ -146,6 +146,9 @@ class MultisegmentWellPrimaryVariables //! output the segments with pressure close to lower pressure limit for debugging purpose void outputLowLimitPressureSegments(DeferredLogger& deferred_logger) const; + //! output the debug information of the primary variables for debugging purpose + std::string debugInfo() const; + private: //! \brief Initialize evaluations from values. void setEvaluationsFromValues(); From 587e929a222ad85dd7af87c7ee75f46f8ef846a3 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Fri, 28 Nov 2025 14:06:24 +0100 Subject: [PATCH 2/5] outputting the well state info for debugging purpose. --- opm/simulators/wells/MultisegmentWell.hpp | 3 ++ opm/simulators/wells/MultisegmentWellEval.cpp | 9 +++++ opm/simulators/wells/MultisegmentWellEval.hpp | 2 + .../wells/MultisegmentWell_impl.hpp | 19 +++++++++ opm/simulators/wells/SegmentState.cpp | 23 +++++++++++ opm/simulators/wells/SegmentState.hpp | 2 + opm/simulators/wells/SingleWellState.cpp | 40 +++++++++++++++++++ opm/simulators/wells/SingleWellState.hpp | 2 + 8 files changed, 100 insertions(+) diff --git a/opm/simulators/wells/MultisegmentWell.hpp b/opm/simulators/wells/MultisegmentWell.hpp index 9064f566269..c92db56880b 100644 --- a/opm/simulators/wells/MultisegmentWell.hpp +++ b/opm/simulators/wells/MultisegmentWell.hpp @@ -348,6 +348,9 @@ namespace Opm { DeferredLogger& deferred_logger) const override; FSInfo getFirstPerforationFluidStateInfo(const Simulator& simulator) const; + + void outputDebugInfoNumericalProblem(const SingleWellState& ws, + DeferredLogger& deferred_logger) const; }; } diff --git a/opm/simulators/wells/MultisegmentWellEval.cpp b/opm/simulators/wells/MultisegmentWellEval.cpp index 1c4a6344445..6349cc0725d 100644 --- a/opm/simulators/wells/MultisegmentWellEval.cpp +++ b/opm/simulators/wells/MultisegmentWellEval.cpp @@ -574,6 +574,15 @@ getResidualMeasureValue(const WellState& well_state, return sum; } +template +std::string +MultisegmentWellEval:: +debugInfo() const +{ + // only outputing the primary variables for now + return primary_variables_.debugInfo(); +} + #include INSTANTIATE_TYPE_INDICES(MultisegmentWellEval, double) diff --git a/opm/simulators/wells/MultisegmentWellEval.hpp b/opm/simulators/wells/MultisegmentWellEval.hpp index 667e0b01052..f6ac055f51c 100644 --- a/opm/simulators/wells/MultisegmentWellEval.hpp +++ b/opm/simulators/wells/MultisegmentWellEval.hpp @@ -136,6 +136,8 @@ class MultisegmentWellEval : public MultisegmentWellGeneric& baseif_; + std::string debugInfo() const; + Equations linSys_; //!< The equation system PrimaryVariables primary_variables_; //!< The primary variables MSWSegments segments_; //!< Segment properties diff --git a/opm/simulators/wells/MultisegmentWell_impl.hpp b/opm/simulators/wells/MultisegmentWell_impl.hpp index 28668958e94..9ae28571e6f 100644 --- a/opm/simulators/wells/MultisegmentWell_impl.hpp +++ b/opm/simulators/wells/MultisegmentWell_impl.hpp @@ -283,6 +283,8 @@ namespace Opm // this is the process with rank zero) deferred_logger.problem("In MultisegmentWell::recoverWellSolutionAndUpdateWellState for well " + this->name() +": "+exp.what()); + const auto& ws = well_state.well(this->index_of_well_); + this->outputDebugInfoNumericalProblem(ws, deferred_logger); throw; } } @@ -632,6 +634,8 @@ namespace Opm // this is the process with rank zero) deferred_logger.problem("In MultisegmentWell::solveEqAndUpdateWellState for well " + this->name() +": "+exp.what()); + const auto& ws = well_state.well(this->index_of_well_); + this->outputDebugInfoNumericalProblem(ws, deferred_logger); throw; } } @@ -1607,6 +1611,8 @@ namespace Opm // this is the process with rank zero) deferred_logger.problem("In MultisegmentWell::iterateWellEqWithControl for well " + this->name() +": "+exp.what()); + const auto& ws = well_state.well(this->index_of_well_); + this->outputDebugInfoNumericalProblem(ws, deferred_logger); throw; } } @@ -1788,6 +1794,8 @@ namespace Opm // this is the process with rank zero) deferred_logger.problem("In MultisegmentWell::iterateWellEqWithSwitching for well " + this->name() +": "+exp.what()); + const auto& ws = well_state.well(this->index_of_well_); + this->outputDebugInfoNumericalProblem(ws, deferred_logger); throw; } } @@ -2379,6 +2387,17 @@ namespace Opm return this->parallel_well_info_.communication().size() == 1 ? info : this->pw_info_.broadcastFirstPerforationValue(info); } + template + void + MultisegmentWell:: + outputDebugInfoNumericalProblem(const SingleWellState& ws, + DeferredLogger& deferred_logger) const + { + std::string msg = ws.debugInfo(); + msg += this->primary_variables_.debugInfo(); + deferred_logger.debug(msg); + } + } // namespace Opm #endif diff --git a/opm/simulators/wells/SegmentState.cpp b/opm/simulators/wells/SegmentState.cpp index 8392e87945a..a2ce28b0f7c 100644 --- a/opm/simulators/wells/SegmentState.cpp +++ b/opm/simulators/wells/SegmentState.cpp @@ -31,6 +31,8 @@ #include #include +#include + namespace { std::vector make_segment_number(const Opm::WellSegments& segments) @@ -147,6 +149,27 @@ bool SegmentState::operator==(const SegmentState& rhs) const this->m_segment_number == rhs.m_segment_number; } +template +std::string +SegmentState::debugInfo() const +{ + if (this->empty()) { + return ""; + } + const std::size_t num_phases = this->rates.size() / this->size(); + std::string info = "SegmentState:\n"; + for (std::size_t i = 0; i < this->size(); ++i) { + info += fmt::format(" Segment {:4}: Segment number {:4}, Pressure = {:8.2e} Pa, Rate: ", + i, this->m_segment_number[i], this->pressure[i]); + for (std::size_t p = 0; p < num_phases; ++p) { + info += fmt::format(" {: 8.2e}", this->rates[i * num_phases + p]); + } + info += fmt::format("\n"); + } + return info; +} + + template class SegmentState; #if FLOW_INSTANTIATE_FLOAT diff --git a/opm/simulators/wells/SegmentState.hpp b/opm/simulators/wells/SegmentState.hpp index 7c6724bb1f1..0f9447c56bd 100644 --- a/opm/simulators/wells/SegmentState.hpp +++ b/opm/simulators/wells/SegmentState.hpp @@ -22,6 +22,7 @@ #include #include +#include namespace Opm { class WellSegments; @@ -104,6 +105,7 @@ class SegmentState std::vector pressure_drop_hydrostatic; std::vector pressure_drop_accel; + std::string debugInfo() const; private: std::vector m_segment_number; }; diff --git a/opm/simulators/wells/SingleWellState.cpp b/opm/simulators/wells/SingleWellState.cpp index a55756d2050..3e42209f55a 100644 --- a/opm/simulators/wells/SingleWellState.cpp +++ b/opm/simulators/wells/SingleWellState.cpp @@ -28,6 +28,8 @@ #include +#include + namespace Opm { template @@ -415,6 +417,44 @@ bool SingleWellState::operator==(const SingleWellState& rhs this->group_target == rhs.group_target; } +template +std::string +SingleWellState:: +debugInfo() const +{ + std::string info = "Well name: " + this->name + " well state:\n"; + fmt::format_to(std::back_inserter(info), " type: {}, staus: {}, control type: {}, BHP: {:8.2e} Pa, THP: {:8.2e} Pa\n", + this->producer? "Producer" : " Injector", WellStatus2String(this->status), + this->producer ? WellProducerCMode2String(this->production_cmode) + : WellInjectorCMode2String(this->injection_cmode), + this->bhp / Opm::unit::barsa, + this->thp / Opm::unit::barsa); + + fmt::format_to(std::back_inserter(info), " Surface rates (m3/s): "); + for (const auto& r : this->surface_rates) { + fmt::format_to(std::back_inserter(info), " {:8.2e}", r); + } + fmt::format_to(std::back_inserter(info), "\n"); + fmt::format_to(std::back_inserter(info), " Connection pressures and connection rates:\n"); + for (std::size_t perf = 0; perf < this->perf_data.size(); perf++) { + fmt::format_to(std::back_inserter(info), + " Connection {:4}: Pressure: {:8.2e} Pa, Rate:", + perf, + this->perf_data.pressure[perf]); + const auto& connection_rates = this->perf_data.phase_rates; + const std::size_t num_phases = this->pu.numActivePhases(); + + for (std::size_t p = 0; p < num_phases; ++p) { + fmt::format_to(std::back_inserter(info), " {: 8.2e} m3/s", connection_rates[perf * num_phases + p]); + } + fmt::format_to(std::back_inserter(info), "\n"); + } + + info += this->segments.debugInfo(); + + return info; +} + template class SingleWellState; #if FLOW_INSTANTIATE_FLOAT diff --git a/opm/simulators/wells/SingleWellState.hpp b/opm/simulators/wells/SingleWellState.hpp index 47907f56b49..0eb7eafdb88 100644 --- a/opm/simulators/wells/SingleWellState.hpp +++ b/opm/simulators/wells/SingleWellState.hpp @@ -169,6 +169,8 @@ class SingleWellState { Scalar sum_filtrate_rate() const; Scalar sum_filtrate_total() const; + std::string debugInfo() const; + private: Scalar sum_connection_rates(const std::vector& connection_rates) const; }; From 2fbe9910a6a48ed8ea0bde65c210c2e50c2d50d3 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Fri, 5 Dec 2025 16:08:26 +0100 Subject: [PATCH 3/5] adjusting the order a little bit, connection comes to the end --- opm/simulators/wells/MultisegmentWell_impl.hpp | 7 +++++-- opm/simulators/wells/SingleWellState.cpp | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/opm/simulators/wells/MultisegmentWell_impl.hpp b/opm/simulators/wells/MultisegmentWell_impl.hpp index 9ae28571e6f..f115681b7ac 100644 --- a/opm/simulators/wells/MultisegmentWell_impl.hpp +++ b/opm/simulators/wells/MultisegmentWell_impl.hpp @@ -2393,8 +2393,11 @@ namespace Opm outputDebugInfoNumericalProblem(const SingleWellState& ws, DeferredLogger& deferred_logger) const { - std::string msg = ws.debugInfo(); - msg += this->primary_variables_.debugInfo(); + // TODO: it might be the general information from well state + // then primary variables, + // then segment info + // then connection info + const std::string msg = this->primary_variables_.debugInfo() + ws.debugInfo(); deferred_logger.debug(msg); } diff --git a/opm/simulators/wells/SingleWellState.cpp b/opm/simulators/wells/SingleWellState.cpp index 3e42209f55a..ca9b6c1eb33 100644 --- a/opm/simulators/wells/SingleWellState.cpp +++ b/opm/simulators/wells/SingleWellState.cpp @@ -435,6 +435,9 @@ debugInfo() const fmt::format_to(std::back_inserter(info), " {:8.2e}", r); } fmt::format_to(std::back_inserter(info), "\n"); + + info += this->segments.debugInfo(); + fmt::format_to(std::back_inserter(info), " Connection pressures and connection rates:\n"); for (std::size_t perf = 0; perf < this->perf_data.size(); perf++) { fmt::format_to(std::back_inserter(info), @@ -450,8 +453,6 @@ debugInfo() const fmt::format_to(std::back_inserter(info), "\n"); } - info += this->segments.debugInfo(); - return info; } From 97aa2019a460a6337d5607922447ad55672b1be8 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Fri, 5 Dec 2025 16:25:06 +0100 Subject: [PATCH 4/5] more adjustments --- .../wells/MultisegmentWell_impl.hpp | 9 ++-- opm/simulators/wells/SingleWellState.cpp | 47 ++++++++++++------- opm/simulators/wells/SingleWellState.hpp | 4 +- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/opm/simulators/wells/MultisegmentWell_impl.hpp b/opm/simulators/wells/MultisegmentWell_impl.hpp index f115681b7ac..d3e8fddeb70 100644 --- a/opm/simulators/wells/MultisegmentWell_impl.hpp +++ b/opm/simulators/wells/MultisegmentWell_impl.hpp @@ -2393,11 +2393,10 @@ namespace Opm outputDebugInfoNumericalProblem(const SingleWellState& ws, DeferredLogger& deferred_logger) const { - // TODO: it might be the general information from well state - // then primary variables, - // then segment info - // then connection info - const std::string msg = this->primary_variables_.debugInfo() + ws.debugInfo(); + const std::string msg = ws.briefDebugInfo() + + this->primary_variables_.debugInfo() + + ws.segmentsDebugInfo() + + ws.connectionDebugInfo(); deferred_logger.debug(msg); } diff --git a/opm/simulators/wells/SingleWellState.cpp b/opm/simulators/wells/SingleWellState.cpp index ca9b6c1eb33..e734c031fd7 100644 --- a/opm/simulators/wells/SingleWellState.cpp +++ b/opm/simulators/wells/SingleWellState.cpp @@ -420,25 +420,17 @@ bool SingleWellState::operator==(const SingleWellState& rhs template std::string SingleWellState:: -debugInfo() const +segmentsDebugInfo() const { - std::string info = "Well name: " + this->name + " well state:\n"; - fmt::format_to(std::back_inserter(info), " type: {}, staus: {}, control type: {}, BHP: {:8.2e} Pa, THP: {:8.2e} Pa\n", - this->producer? "Producer" : " Injector", WellStatus2String(this->status), - this->producer ? WellProducerCMode2String(this->production_cmode) - : WellInjectorCMode2String(this->injection_cmode), - this->bhp / Opm::unit::barsa, - this->thp / Opm::unit::barsa); - - fmt::format_to(std::back_inserter(info), " Surface rates (m3/s): "); - for (const auto& r : this->surface_rates) { - fmt::format_to(std::back_inserter(info), " {:8.2e}", r); - } - fmt::format_to(std::back_inserter(info), "\n"); - - info += this->segments.debugInfo(); + return this->segments.debugInfo(); +} - fmt::format_to(std::back_inserter(info), " Connection pressures and connection rates:\n"); +template +std::string +SingleWellState:: +connectionDebugInfo() const +{ + std::string info {" Connection pressures and connection rates:\n"}; for (std::size_t perf = 0; perf < this->perf_data.size(); perf++) { fmt::format_to(std::back_inserter(info), " Connection {:4}: Pressure: {:8.2e} Pa, Rate:", @@ -456,6 +448,27 @@ debugInfo() const return info; } +template +std::string +SingleWellState:: +briefDebugInfo() const +{ + std::string info = "Well name: " + this->name + " well state:\n"; + fmt::format_to(std::back_inserter(info), " type: {}, staus: {}, control type: {}, BHP: {:8.2e} Pa, THP: {:8.2e} Pa\n", + this->producer? "Producer" : " Injector", WellStatus2String(this->status), + this->producer ? WellProducerCMode2String(this->production_cmode) + : WellInjectorCMode2String(this->injection_cmode), + this->bhp / Opm::unit::barsa, + this->thp / Opm::unit::barsa); + + fmt::format_to(std::back_inserter(info), " Surface rates (m3/s): "); + for (const auto& r : this->surface_rates) { + fmt::format_to(std::back_inserter(info), " {:8.2e}", r); + } + fmt::format_to(std::back_inserter(info), "\n"); + return info; +} + template class SingleWellState; #if FLOW_INSTANTIATE_FLOAT diff --git a/opm/simulators/wells/SingleWellState.hpp b/opm/simulators/wells/SingleWellState.hpp index 0eb7eafdb88..58ee614d23f 100644 --- a/opm/simulators/wells/SingleWellState.hpp +++ b/opm/simulators/wells/SingleWellState.hpp @@ -169,7 +169,9 @@ class SingleWellState { Scalar sum_filtrate_rate() const; Scalar sum_filtrate_total() const; - std::string debugInfo() const; + std::string briefDebugInfo() const; + std::string segmentsDebugInfo() const; + std::string connectionDebugInfo() const; private: Scalar sum_connection_rates(const std::vector& connection_rates) const; From 14bb4e6d74383a2891332849049b9b37231f3a89 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Mon, 8 Dec 2025 12:28:57 +0100 Subject: [PATCH 5/5] some adjustment --- .../wells/MultisegmentWellPrimaryVariables.cpp | 4 ++-- opm/simulators/wells/SegmentState.cpp | 6 ++++-- opm/simulators/wells/SingleWellState.cpp | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp b/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp index 68d920b8a08..99706ec7e66 100644 --- a/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp +++ b/opm/simulators/wells/MultisegmentWellPrimaryVariables.cpp @@ -710,8 +710,8 @@ debugInfo() const std::string msg = fmt::format("Well {} primary variables:\n", this->well_.name()); for (std::size_t seg = 0; seg < value_.size(); ++seg) { fmt::format_to(std::back_inserter(msg), " Segment {:4}: ", seg); - fmt::format_to(std::back_inserter(msg), " SPres: {:8.2e} Pa, ", value_[seg][SPres]); - fmt::format_to(std::back_inserter(msg), " WQTotal: {:8.2e} m3/s, ", value_[seg][WQTotal]); + fmt::format_to(std::back_inserter(msg), " SPres: {:8.2e} bar, ", value_[seg][SPres] / unit::barsa); + fmt::format_to(std::back_inserter(msg), " WQTotal: {: 8.2e} m3/s, ", value_[seg][WQTotal]); if (has_wfrac_variable) { fmt::format_to(std::back_inserter(msg), " WFrac: {:5.3f}, ", value_[seg][WFrac]); } diff --git a/opm/simulators/wells/SegmentState.cpp b/opm/simulators/wells/SegmentState.cpp index a2ce28b0f7c..7b515340110 100644 --- a/opm/simulators/wells/SegmentState.cpp +++ b/opm/simulators/wells/SegmentState.cpp @@ -21,6 +21,8 @@ #include "config.h" #endif // HAVE_CONFIG_H +#include "opm/input/eclipse/Units/Units.hpp" + #include #include @@ -159,8 +161,8 @@ SegmentState::debugInfo() const const std::size_t num_phases = this->rates.size() / this->size(); std::string info = "SegmentState:\n"; for (std::size_t i = 0; i < this->size(); ++i) { - info += fmt::format(" Segment {:4}: Segment number {:4}, Pressure = {:8.2e} Pa, Rate: ", - i, this->m_segment_number[i], this->pressure[i]); + info += fmt::format(" Segment {:4}: Segment number {:4}, Pressure = {:8.2e} bar, Rate {m3/s}: ", + i, this->m_segment_number[i], this->pressure[i] / unit::barsa); for (std::size_t p = 0; p < num_phases; ++p) { info += fmt::format(" {: 8.2e}", this->rates[i * num_phases + p]); } diff --git a/opm/simulators/wells/SingleWellState.cpp b/opm/simulators/wells/SingleWellState.cpp index e734c031fd7..476b9adfc42 100644 --- a/opm/simulators/wells/SingleWellState.cpp +++ b/opm/simulators/wells/SingleWellState.cpp @@ -433,9 +433,9 @@ connectionDebugInfo() const std::string info {" Connection pressures and connection rates:\n"}; for (std::size_t perf = 0; perf < this->perf_data.size(); perf++) { fmt::format_to(std::back_inserter(info), - " Connection {:4}: Pressure: {:8.2e} Pa, Rate:", + " Connection {:4}: Pressure: {:8.2e} bar, Rate:", perf, - this->perf_data.pressure[perf]); + this->perf_data.pressure[perf] / unit::barsa); const auto& connection_rates = this->perf_data.phase_rates; const std::size_t num_phases = this->pu.numActivePhases(); @@ -454,12 +454,12 @@ SingleWellState:: briefDebugInfo() const { std::string info = "Well name: " + this->name + " well state:\n"; - fmt::format_to(std::back_inserter(info), " type: {}, staus: {}, control type: {}, BHP: {:8.2e} Pa, THP: {:8.2e} Pa\n", + fmt::format_to(std::back_inserter(info), " type: {}, staus: {}, control type: {}, BHP: {:8.2e} Bar, THP: {:8.2e} Bar\n", this->producer? "Producer" : " Injector", WellStatus2String(this->status), this->producer ? WellProducerCMode2String(this->production_cmode) : WellInjectorCMode2String(this->injection_cmode), - this->bhp / Opm::unit::barsa, - this->thp / Opm::unit::barsa); + this->bhp / unit::barsa, + this->thp / unit::barsa); fmt::format_to(std::back_inserter(info), " Surface rates (m3/s): "); for (const auto& r : this->surface_rates) {