Debugging code to dump guide rates

Added debugging code to dump all guide rates
This commit is contained in:
Håkon Hægland committed 2025-06-22 10:57:27 +02:00
1 parent 827cda4f79
commit 006be80de0
6 files changed
+367 -24

No files matched your search

@@ -232,6 +232,7 @@ public:
const SummaryState& summaryState() const { return summaryState_; }
const GuideRate& guideRate() const { return guideRate_; }
GuideRate& guideRate() { return guideRate_; }
const std::map<std::string, double>& wellOpenTimes() const { return well_open_times_; }
const std::map<std::string, double>& wellCloseTimes() const { return well_close_times_; }
@@ -388,9 +388,9 @@ getGuideRateInjectionGroupValues(const Group& group) const
}
template<class Scalar>
void BlackoilWellModelGuideRates<Scalar>::
assignWellGuideRates(data::Wells& wsrpt,
const int reportStepIdx) const
std::unordered_map<std::string, data::GuideRateValue>
BlackoilWellModelGuideRates<Scalar>::
calculateWellGuideRates(const int reportStepIdx) const
{
auto all = std::unordered_map<std::string, data::GuideRateValue>{};
auto retrieve = std::unordered_map<std::string, RetrieveWellGuideRate>{};
@@ -470,7 +470,15 @@ assignWellGuideRates(data::Wells& wsrpt,
// Upon completion, 'all' contains guide rate values for all wells
// reachable from 'FIELD' at this time/report step.
walker.traversePreOrder();
return all;
}
template<class Scalar>
void BlackoilWellModelGuideRates<Scalar>::
assignWellGuideRates(data::Wells& wsrpt,
const int reportStepIdx) const
{
auto all = calculateWellGuideRates(reportStepIdx);
for (const auto* well : wellModel_.genericWells()) {
auto xwPos = wsrpt.find(well->name());
if (xwPos == wsrpt.end()) { // No well results. Unexpected.
@@ -50,6 +50,10 @@ public:
: wellModel_(wellModel)
{}
//! \brief Calculate guide rate values for all wells.
std::unordered_map<std::string, data::GuideRateValue>
calculateWellGuideRates(const int reportStepIdx) const;
//! \brief Assign well guide rates.
void assignWellGuideRates(data::Wells& wsrpt,
const int reportStepIdx) const;
@@ -79,16 +79,11 @@ namespace Opm {
phase_usage,
simulator.gridView().comm())
, simulator_(simulator)
, guide_rate_handler_{simulator.vanguard().schedule(),
// NOTE: The reference phase_usage passed to this constructor should be copied
// as it will be destroyed by the caller. This is also what is done in
// the parent class BlackoilWellModelGeneric and why we below use a reference
// to that copy (this->phase_usage_) instead of the the constructor parameter
// phase_usage
this->phase_usage_,
, guide_rate_handler_{
*this,
simulator.vanguard().schedule(),
simulator.vanguard().summaryState(),
simulator.vanguard().grid().comm(),
this->guideRate_
simulator.vanguard().grid().comm()
}
, gaslift_(this->terminal_output_, this->phase_usage_)
{
@@ -1295,7 +1290,6 @@ namespace Opm {
this->guide_rate_handler_.updateGuideRates(
reportStepIdx, simulationTime, this->wellState(), this->groupState()
);
}
// we need to re-iterate the network when the well group controls changed or gaslift/alq is changed or
// the inner iterations are did not converge
+299 -7
View File
@@ -17,11 +17,17 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <opm/input/eclipse/EclipseState/Phase.hpp>
#include <opm/output/data/GuideRateValue.hpp>
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
#include <opm/simulators/utils/ParallelCommunication.hpp>
#include <opm/simulators/wells/GuideRateHandler.hpp>
#include <opm/common/TimingMacros.hpp>
#include <utility>
#include <fmt/format.h>
namespace Opm {
// ---------------------------------------------
@@ -29,18 +35,19 @@ namespace Opm {
// ---------------------------------------------
template <class Scalar>
GuideRateHandler<Scalar>::GuideRateHandler(
BlackoilWellModelGeneric<Scalar>& well_model,
const Schedule& schedule,
const PhaseUsage& phase_usage,
const SummaryState& summary_state,
const Parallel::Communication& comm,
GuideRate& guide_rate
const Parallel::Communication& comm
) :
schedule_{schedule}
, phase_usage_{phase_usage}
well_model_{well_model}
, schedule_{schedule}
, summary_state_{summary_state}
, comm_{comm}
, guide_rate_{guide_rate}
{ }
, phase_usage_{well_model_.phaseUsage()}
, guide_rate_{well_model_.guideRate()}
{
}
// ----------------------------------------------------------
@@ -56,6 +63,31 @@ deferredLogger()
return *this->deferred_logger_;
}
// This is an alternative to plotting the summary keywords:
// - GOPGR (group oil production guide rate),
// - WOPGR (well oil production guide rate),
// - GWPGR (group water production guide rate),
// - WWPGR (well water production guide rate),
// - GGPGR (group gas production guide rate),
// - WGPGR (well gas production guide rate),
// - GGIGR (group gas injection guide rate),
// - WGIGR (well gas injection guide rate),
// - GWIGR (group water injection guide rate),
// - WWIGR (well water injection guide rate),
// - GVPGR (group reservoir volume production guide rate),
// - WVPGR (well reservoir volume production guide rate),
template <class Scalar>
void
GuideRateHandler<Scalar>::
debugDumpGuideRates(const int report_step_idx, const double sim_time)
{
if (this->comm_.rank() == 0) {
GuideRateDumper dumper{*this, report_step_idx, sim_time};
dumper.dumpGuideRates();
}
}
#ifdef RESERVOIR_COUPLING_ENABLED
template <class Scalar>
void
@@ -137,6 +169,266 @@ updateGuideRates(
}
// ------------------------------------------
// Inner class GuideRateDumper constructor
// ------------------------------------------
template <class Scalar>
GuideRateHandler<Scalar>::GuideRateDumper::
GuideRateDumper(
GuideRateHandler<Scalar> &parent, const int report_step_idx, const double sim_time
) : parent_{parent}
, report_step_idx_{report_step_idx}
, sim_time_{sim_time}
, well_model_{parent.wellModel()}
, schedule_{parent.schedule()}
, comm_{parent.getComm()}
{
}
// ---------------------------------------------------------------------
// Public methods for inner class GuideRateDumper sorted alphabetically
// ---------------------------------------------------------------------
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
dumpGuideRates()
{
if (this->comm_.rank() == 0) {
auto calcGR = BlackoilWellModelGuideRates{this->well_model_};
this->well_guide_rates_ = calcGR.calculateWellGuideRates(this->report_step_idx_);
this->group_guide_rates_ = calcGR.calculateAllGroupGuideRates(this->report_step_idx_);
const auto& group = this->schedule_.getGroup("FIELD", this->report_step_idx_);
printHeader_();
int level = 0; // 0 is the root level
this->dumpGuideRatesRecursive_(group, level);
printTrailer_();
}
}
// ----------------------------------------------------------
// Private methods for GuideRateHandler sorted alphabetically
// -----------------------------------------------------------
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
dumpGuideRatesRecursive_(const Group& group, int level)
{
if (group.name() != "FIELD") {
this->printGroupGuideRates_(group, level);
}
for (const std::string& group_name : group.groups()) {
const Group& group_tmp = this->schedule_.getGroup(group_name, this->report_step_idx_);
this->dumpGuideRatesRecursive_(group_tmp, level+1);
}
for (const std::string& well_name : group.wells()) {
const auto& well_tmp = this->schedule_.getWell(well_name, this->report_step_idx_);
printWellGuideRates_(well_tmp, level+1);
}
}
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
getGroupGuideRatesInjection_(
const Group& group,
const data::GroupGuideRates& group_guide_rate,
std::vector<std::string>& msg_items
) const
{
// NOTE: See comment in getGroupGuideRatesProduction_() for a discussion of the
// different types of group guiderate enums.
const auto& wm_guide_rate = this->well_model_.guideRate();
const auto& name = group.name();
using Value = data::GuideRateValue::Item;
constexpr std::pair<Phase, Value> phase_value_pairs[] = {
{Phase::OIL, Value::Oil},
{Phase::GAS, Value::Gas},
{Phase::WATER, Value::Water}
};
const auto& guide_rate_value = group_guide_rate.production;
for (const auto& [phase, value] : phase_value_pairs) {
if (wm_guide_rate.has(name, phase)) {
if (guide_rate_value.has(value)) {
msg_items.push_back(
fmt::format(
"{}(Group Inj, {}): {}",
guide_rate_value.itemName(value),
guide_rate_value.get(value)
)
);
}
}
}
}
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
getGroupGuideRatesProduction_(
const Group& group,
const data::GroupGuideRates& group_guide_rate,
std::vector<std::string>& msg_items
) const
{
// NOTE: There are many different types of group guide rate phase target enums that are
// used in different contexts:
// - Group.hpp defines Group::GuideRateProdTarget and Group::GuideRateInjTarget
// - Production: OIL, WAT, GAS, LIQ, RES, COMB, WGA, CVAL, INJV, POTN, FORM
// - These are defined by item 9 of GCONPROD and used if item 10 of GCONPROD is not
// set to FORM.
// - Injection: RATE, VOID, NETV, RESV
// - GuideRateModel.hpp defines GuideRateModel::Target
// - OIL, LIQ, GAS, WAT, RES, COMB, NONE
// - These are defined by item 2 of GUIDERAT.
// - These are used if item 10 of GCONPROD is set to FORM, then the guide rate set in
// item 9 of GCONPROD is ignored.
// - Phase.hpp defines the Phase enum which is used by BlackoilWellModelGuideRates.cpp and
// GuideRate.cpp
// - OIL, GAS, WATER, SOLVENT, POLYMER, ENERGY, POLYMW, FOAM, BRINE
// - Only OIL, GAS, WATER are used in the context of guide rates and only for
// injection groups. And only GAS and WATER are checked for in
// getGuideRateInjectionGroupValues() in BlackoilWellModelGuideRates.cpp.
// - GuideRateValue.hpp defines GuideRateValue::Item which is used by
// BlackoilWellModelGuideRates.cpp to assign guide rates. The values are:
// - Oil, Gas, Water, ResV
// - However, ResV is not implemented, see getGuideRateValues() in
// BlackoilWellModelGuideRates.cpp. This, despite the summary keywords GVPGR and WVPGR
// are using it, see Summary.cpp. TODO: Check if this is a bug.
const auto& wm_guide_rate = this->well_model_.guideRate();
const auto& name = group.name();
if (wm_guide_rate.has(name)) { // Check if group has production guiderates
constexpr data::GuideRateValue::Item value_types[] = {
data::GuideRateValue::Item::Oil,
data::GuideRateValue::Item::Gas,
data::GuideRateValue::Item::Water,
data::GuideRateValue::Item::ResV
};
const auto& guide_rate_value = group_guide_rate.production;
for (const auto& value_type : value_types) {
if (guide_rate_value.has(value_type)) {
msg_items.push_back(
fmt::format(
"{}(Group Prod, {}): {}",
name,
guide_rate_value.itemName(value_type),
guide_rate_value.get(value_type)
)
);
}
}
}
}
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
printGroupGuideRates_(const Group& group, int level)
{
const auto& name = group.name();
assert( level >= 1 );
std::string indent(level - 1, ' ');
auto gr_itr = this->group_guide_rates_.find(name);
if (gr_itr == this->group_guide_rates_.end()) {
this->deferredLogger().debug(
fmt::format("{}{}: <NO GUIDERATE>", indent, name)
);
return;
}
const auto& group_guide_rate = gr_itr->second;
std::vector<std::string> msg_items;
getGroupGuideRatesProduction_(group, group_guide_rate, msg_items);
getGroupGuideRatesInjection_(group, group_guide_rate, msg_items);
if (msg_items.empty()) {
this->deferredLogger().debug(
fmt::format("{}{}(Group): <NO GUIDERATES FOUND>", indent, name)
);
return;
}
this->deferredLogger().debug(
fmt::format("{}{}", indent, fmt::join(msg_items, ", "))
);
}
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
printHeader_()
{
this->deferredLogger().debug(
fmt::format(
"\n---- GUIDE RATE REPORT: step {}, simtime {} ----",
this->report_step_idx_,
this->sim_time_
)
);
}
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
printTrailer_()
{
this->deferredLogger().debug(
fmt::format(
"---- END GUIDE RATE REPORT: step {}, simtime {} ----\n",
this->report_step_idx_,
this->sim_time_
)
);
}
template <class Scalar>
void
GuideRateHandler<Scalar>::GuideRateDumper::
printWellGuideRates_(const Well& well, int level)
{
const auto& name = well.name();
assert( level >= 1 );
std::string indent(level - 1, ' ');
auto gr_itr = this->well_guide_rates_.find(name);
if (gr_itr == this->well_guide_rates_.end()) {
this->deferredLogger().debug(
fmt::format("{}{}: <NO GUIDERATE>", indent, name)
);
return;
}
const auto& guide_rate_value = gr_itr->second;
std::vector<std::string> msg_items;
constexpr data::GuideRateValue::Item value_types[] = {
data::GuideRateValue::Item::Oil,
data::GuideRateValue::Item::Gas,
data::GuideRateValue::Item::Water
};
const std::string well_type = well.isInjector() ? "Inj" : "Prod";
for (const auto& value_type : value_types) {
if (guide_rate_value.has(value_type)) {
msg_items.push_back(
fmt::format(
"{}(Well {}, {}): {}",
name,
well_type,
guide_rate_value.itemName(value_type),
guide_rate_value.get(value_type)
)
);
}
}
if (msg_items.empty()) {
this->deferredLogger().debug(
fmt::format("{}{}(Well {}): <NO GUIDERATES FOUND>", indent, name, well_type)
);
return;
}
this->deferredLogger().debug(
fmt::format("{}{}", indent, fmt::join(msg_items, ", "))
);
}
// ------------------------------------------
// Inner class UpdateGuideRates constructor
// ------------------------------------------
+48 -4
View File
@@ -29,8 +29,12 @@
#include <opm/simulators/flow/ReservoirCouplingSlave.hpp>
#endif
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
#include <opm/output/data/Groups.hpp>
#include <opm/output/data/GuideRateValue.hpp>
#include <opm/simulators/utils/BlackoilPhases.hpp>
#include <opm/simulators/utils/DeferredLogger.hpp>
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
#include <opm/simulators/wells/BlackoilWellModelGuideRates.hpp>
#include <opm/simulators/wells/GroupState.hpp>
#include <opm/simulators/wells/WellState.hpp>
namespace Opm {
@@ -40,6 +44,41 @@ class GuideRateHandler {
public:
using Potentials = ReservoirCoupling::Potentials;
class GuideRateDumper {
public:
GuideRateDumper(
GuideRateHandler<Scalar> &parent, const int report_step_idx, const double sim_time
);
DeferredLogger &deferredLogger() { return this->parent_.deferredLogger(); }
void dumpGuideRates();
private:
void dumpGuideRatesRecursive_(const Group& group, int level);
void getGroupGuideRatesInjection_(
const Group& group,
const data::GroupGuideRates& group_guide_rate,
std::vector<std::string>& msg_items
) const;
void getGroupGuideRatesProduction_(
const Group& group,
const data::GroupGuideRates& group_guide_rate,
std::vector<std::string>& msg_items
) const;
void printGroupGuideRates_(const Group& group, int level);
void printHeader_();
void printTrailer_();
void printWellGuideRates_(const Well& well, int level);
GuideRateHandler<Scalar> &parent_;
const int report_step_idx_;
const double sim_time_;
const BlackoilWellModelGeneric<Scalar>& well_model_;
const Schedule& schedule_;
const Parallel::Communication& comm_;
std::unordered_map<std::string, data::GuideRateValue> well_guide_rates_;
std::unordered_map<std::string, data::GroupGuideRates> group_guide_rates_;
};
class UpdateGuideRates {
public:
UpdateGuideRates(
@@ -87,11 +126,10 @@ public:
};
GuideRateHandler(
BlackoilWellModelGeneric<Scalar>& well_model,
const Schedule& schedule,
const PhaseUsage& phase_usage,
const SummaryState& summary_state,
const Parallel::Communication& comm,
GuideRate& guide_rate
const Parallel::Communication& comm
);
#ifdef RESERVOIR_COUPLING_ENABLED
@@ -113,18 +151,24 @@ public:
}
#endif
DeferredLogger& deferredLogger();
void debugDumpGuideRates(const int report_step_idx, const double sim_time);
const Parallel::Communication& getComm() const { return comm_; }
void setLogger(DeferredLogger *deferred_logger);
const Schedule& schedule() const { return schedule_; }
void updateGuideRates(
const int report_step_idx,
const double sim_time,
WellState<Scalar> &well_state,
GroupState<Scalar> &group_state
);
const BlackoilWellModelGeneric<Scalar>& wellModel() const { return well_model_; }
private:
void debugDumpGuideRatesRecursive_(const Group& group) const;
BlackoilWellModelGeneric<Scalar>& well_model_;
const Schedule& schedule_;
const PhaseUsage& phase_usage_;
const SummaryState& summary_state_;
const Parallel::Communication& comm_;
const PhaseUsage& phase_usage_;
GuideRate& guide_rate_;
DeferredLogger *deferred_logger_ = nullptr;
#ifdef RESERVOIR_COUPLING_ENABLED