mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-11-03 20:56:43 -06:00
Merge pull request #6535 from hakonhagland/rf_wgh
Refactor WellGroupHelpers
This commit is contained in:
31 files changed
+3081
-3368
No files matched your search
@@ -243,7 +243,7 @@ list (APPEND MAIN_SOURCE_FILES
|
||||
opm/simulators/wells/WellFilterCake.cpp
|
||||
opm/simulators/wells/WellGroupConstraints.cpp
|
||||
opm/simulators/wells/WellGroupControls.cpp
|
||||
opm/simulators/wells/WellGroupHelpers.cpp
|
||||
opm/simulators/wells/WellGroupHelper.cpp
|
||||
opm/simulators/wells/WellHelpers.cpp
|
||||
opm/simulators/wells/WellInterfaceFluidSystem.cpp
|
||||
opm/simulators/wells/WellInterfaceGeneric.cpp
|
||||
@@ -1159,7 +1159,7 @@ list (APPEND PUBLIC_HEADER_FILES
|
||||
opm/simulators/wells/WellFilterCake.hpp
|
||||
opm/simulators/wells/WellGroupConstraints.hpp
|
||||
opm/simulators/wells/WellGroupControls.hpp
|
||||
opm/simulators/wells/WellGroupHelpers.hpp
|
||||
opm/simulators/wells/WellGroupHelper.hpp
|
||||
opm/simulators/wells/WellHelpers.hpp
|
||||
opm/simulators/wells/WellInterfaceFluidSystem.hpp
|
||||
opm/simulators/wells/WellInterfaceGeneric.hpp
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
#include <opm/simulators/wells/VFPInjProperties.hpp>
|
||||
#include <opm/simulators/wells/VFPProdProperties.hpp>
|
||||
#include <opm/simulators/wells/WellConnectionAuxiliaryModule.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellInterface.hpp>
|
||||
#include <opm/simulators/wells/WellProdIndexCalculator.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
@@ -115,8 +115,8 @@ template<class Scalar> class WellContributions;
|
||||
using ModelParameters = BlackoilModelParameters<Scalar>;
|
||||
|
||||
using WellConnectionModule = WellConnectionAuxiliaryModule<TypeTag, BlackoilWellModel<TypeTag>>;
|
||||
|
||||
using IndexTraits = typename FluidSystem::IndexTraitsType;
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
|
||||
constexpr static std::size_t pressureVarIndex = GetPropType<TypeTag, Properties::Indices>::pressureSwitchIdx;
|
||||
|
||||
@@ -143,8 +143,6 @@ template<class Scalar> class WellContributions;
|
||||
using AverageRegionalPressureType = RegionAverageCalculator::
|
||||
AverageRegionalPressure<FluidSystem, std::vector<int> >;
|
||||
|
||||
using WellGroupHelpersType = WellGroupHelpers<Scalar, IndexTraits>;
|
||||
|
||||
explicit BlackoilWellModel(Simulator& simulator);
|
||||
|
||||
void init();
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <opm/material/fluidsystems/BlackOilDefaultFluidSystemIndices.hpp>
|
||||
|
||||
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellInterfaceGeneric.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
@@ -46,7 +45,6 @@ checkGroupInjectionConstraints(const Group& group,
|
||||
const int reportStepIdx,
|
||||
const Phase& phase) const
|
||||
{
|
||||
const auto& well_state = wellModel_.wellState();
|
||||
const auto& pu = wellModel_.phaseUsage();
|
||||
|
||||
int phasePos;
|
||||
@@ -65,13 +63,7 @@ checkGroupInjectionConstraints(const Group& group,
|
||||
if (currentControl != Group::InjectionCMode::RATE)
|
||||
{
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate += WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
phasePos,
|
||||
/*isInjector*/true,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellSurfaceRates(group, phasePos, /*isInjector*/true);
|
||||
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
@@ -95,13 +87,7 @@ checkGroupInjectionConstraints(const Group& group,
|
||||
if (currentControl != Group::InjectionCMode::RESV)
|
||||
{
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate += WellGroupHelpersType::sumWellResRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
phasePos,
|
||||
/*isInjector*/true,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellResRates(group, phasePos, /*is_injector=*/true);
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
|
||||
@@ -126,25 +112,13 @@ checkGroupInjectionConstraints(const Group& group,
|
||||
Scalar production_Rate = 0.0;
|
||||
const auto& controls = group.injectionControls(phase, wellModel_.summaryState());
|
||||
const Group& groupRein = wellModel_.schedule().getGroup(controls.reinj_group, reportStepIdx);
|
||||
production_Rate += WellGroupHelpersType::sumWellSurfaceRates(groupRein,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
phasePos,
|
||||
/*isInjector*/false,
|
||||
wellModel_.summaryState());
|
||||
production_Rate += wgHelper().sumWellSurfaceRates(groupRein, phasePos, /*is_injector=*/false);
|
||||
|
||||
// sum over all nodes
|
||||
production_Rate = wellModel_.comm().sum(production_Rate);
|
||||
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate += WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
phasePos,
|
||||
/*isInjector*/true,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellSurfaceRates(group, phasePos, /*is_injector=*/true);
|
||||
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
@@ -164,52 +138,29 @@ checkGroupInjectionConstraints(const Group& group,
|
||||
Scalar voidage_rate = 0.0;
|
||||
const auto& controls = group.injectionControls(phase, wellModel_.summaryState());
|
||||
const Group& groupVoidage = wellModel_.schedule().getGroup(controls.voidage_group, reportStepIdx);
|
||||
voidage_rate += WellGroupHelpersType::sumWellResRates(groupVoidage,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
voidage_rate += WellGroupHelpersType::sumWellResRates(groupVoidage,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
voidage_rate += WellGroupHelpersType::sumWellResRates(groupVoidage,
|
||||
wellModel_.schedule(),
|
||||
well_state, reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
voidage_rate += wgHelper().sumWellResRates(groupVoidage,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
voidage_rate += wgHelper().sumWellResRates(groupVoidage,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
voidage_rate += wgHelper().sumWellResRates(groupVoidage,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
|
||||
// sum over all nodes
|
||||
voidage_rate = wellModel_.comm().sum(voidage_rate);
|
||||
|
||||
Scalar total_rate = 0.0;
|
||||
total_rate += WellGroupHelpersType::sumWellResRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
true,
|
||||
wellModel_.summaryState());
|
||||
total_rate += WellGroupHelpersType::sumWellResRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
true,
|
||||
wellModel_.summaryState());
|
||||
total_rate += WellGroupHelpersType::sumWellResRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
true,
|
||||
wellModel_.summaryState());
|
||||
total_rate += wgHelper().sumWellResRates(group,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
/*is_injector=*/true);
|
||||
total_rate += wgHelper().sumWellResRates(group,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
/*is_injector=*/true);
|
||||
total_rate += wgHelper().sumWellResRates(group,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
/*is_injector=*/true);
|
||||
|
||||
// sum over all nodes
|
||||
total_rate = wellModel_.comm().sum(total_rate);
|
||||
@@ -228,12 +179,8 @@ checkGroupInjectionConstraints(const Group& group,
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
std::pair<Group::ProductionCMode, Scalar>
|
||||
BlackoilWellModelConstraints<Scalar, IndexTraits>::
|
||||
checkGroupProductionConstraints(const Group& group,
|
||||
const int reportStepIdx,
|
||||
DeferredLogger& deferred_logger) const
|
||||
checkGroupProductionConstraints(const Group& group, DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const auto& well_state = wellModel_.wellState();
|
||||
|
||||
const auto controls = group.productionControls(wellModel_.summaryState());
|
||||
const Group::ProductionCMode& currentControl = wellModel_.groupState().production_control(group.name());
|
||||
const auto& pu = wellModel_.phaseUsage();
|
||||
@@ -242,13 +189,9 @@ checkGroupProductionConstraints(const Group& group,
|
||||
if (currentControl != Group::ProductionCMode::ORAT)
|
||||
{
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate += WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellSurfaceRates(group,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
@@ -267,13 +210,9 @@ checkGroupProductionConstraints(const Group& group,
|
||||
if (currentControl != Group::ProductionCMode::WRAT)
|
||||
{
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate += WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellSurfaceRates(group,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
@@ -291,13 +230,9 @@ checkGroupProductionConstraints(const Group& group,
|
||||
if (currentControl != Group::ProductionCMode::GRAT)
|
||||
{
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate += WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellSurfaceRates(group,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
@@ -314,20 +249,12 @@ checkGroupProductionConstraints(const Group& group,
|
||||
if (currentControl != Group::ProductionCMode::LRAT)
|
||||
{
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate += WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate += WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellSurfaceRates(group,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
current_rate += wgHelper().sumWellSurfaceRates(group,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
@@ -335,13 +262,9 @@ checkGroupProductionConstraints(const Group& group,
|
||||
bool skip = false;
|
||||
if (controls.liquid_target == controls.oil_target) {
|
||||
Scalar current_water_rate =
|
||||
WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
wgHelper().sumWellSurfaceRates(group,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
current_water_rate = wellModel_.comm().sum(current_water_rate);
|
||||
if (std::abs(current_water_rate) < 1e-12) {
|
||||
skip = true;
|
||||
@@ -367,30 +290,15 @@ checkGroupProductionConstraints(const Group& group,
|
||||
if (currentControl != Group::ProductionCMode::RESV)
|
||||
{
|
||||
Scalar current_rate = 0.0;
|
||||
current_rate +=
|
||||
WellGroupHelpersType::sumWellResRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate +=
|
||||
WellGroupHelpersType::sumWellResRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate +=
|
||||
WellGroupHelpersType::sumWellResRates(group,
|
||||
wellModel_.schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
false,
|
||||
wellModel_.summaryState());
|
||||
current_rate += wgHelper().sumWellResRates(group,
|
||||
pu.canonicalToActivePhaseIdx(waterPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
current_rate += wgHelper().sumWellResRates(group,
|
||||
pu.canonicalToActivePhaseIdx(oilPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
current_rate += wgHelper().sumWellResRates(group,
|
||||
pu.canonicalToActivePhaseIdx(gasPhaseIdx),
|
||||
/*is_injector=*/false);
|
||||
|
||||
// sum over all nodes
|
||||
current_rate = wellModel_.comm().sum(current_rate);
|
||||
@@ -434,9 +342,7 @@ checkGroupConstraints(const Group& group,
|
||||
}
|
||||
}
|
||||
if (group.isProductionGroup()) {
|
||||
const auto& check = this->checkGroupProductionConstraints(group,
|
||||
reportStepIdx,
|
||||
deferred_logger);
|
||||
const auto& check = this->checkGroupProductionConstraints(group, deferred_logger);
|
||||
if (check.first != Group::ProductionCMode::NONE)
|
||||
{
|
||||
return true;
|
||||
@@ -478,10 +384,8 @@ actionOnBrokenConstraints(const Group& group,
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
bool BlackoilWellModelConstraints<Scalar, IndexTraits>::
|
||||
actionOnBrokenConstraints(const Group& group,
|
||||
const int reportStepIdx,
|
||||
const Group::GroupLimitAction group_limit_action,
|
||||
const Group::ProductionCMode& newControl,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
std::optional<std::string>& worst_offending_well,
|
||||
GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
@@ -548,9 +452,7 @@ actionOnBrokenConstraints(const Group& group,
|
||||
}
|
||||
case Group::ExceedAction::WELL: {
|
||||
std::tie(worst_offending_well, std::ignore) =
|
||||
WellGroupHelpersType::worstOffendingWell(group, wellModel_.schedule(), reportStepIdx,
|
||||
newControl,
|
||||
wellModel_.comm(), well_state, deferred_logger);
|
||||
wgHelper().worstOffendingWell(group, newControl, wellModel_.comm(), deferred_logger);
|
||||
break;
|
||||
}
|
||||
case Group::ExceedAction::PLUG: {
|
||||
@@ -642,13 +544,10 @@ updateGroupIndividualControl(const Group& group,
|
||||
}
|
||||
this->actionOnBrokenConstraints(group, changed_this.first, phase,
|
||||
group_state, deferred_logger);
|
||||
WellGroupHelpersType::updateWellRatesFromGroupTargetScale(changed_this.second,
|
||||
group,
|
||||
wellModel_.schedule(),
|
||||
reportStepIdx,
|
||||
/* isInjector */ false,
|
||||
wellModel_.groupState(),
|
||||
well_state);
|
||||
wgHelper().updateWellRatesFromGroupTargetScale(changed_this.second,
|
||||
group,
|
||||
/*is_injector=*/false,
|
||||
well_state);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -676,32 +575,27 @@ updateGroupIndividualControl(const Group& group,
|
||||
}
|
||||
}
|
||||
|
||||
const auto& changed_this = this->checkGroupProductionConstraints(group,
|
||||
reportStepIdx,
|
||||
deferred_logger);
|
||||
const auto& changed_this = this->checkGroupProductionConstraints(group, deferred_logger);
|
||||
const auto controls = group.productionControls(wellModel_.summaryState());
|
||||
|
||||
if (changed_this.first != Group::ProductionCMode::NONE)
|
||||
{
|
||||
std::optional<std::string> worst_offending_well = std::nullopt;
|
||||
changed = this->actionOnBrokenConstraints(group, reportStepIdx,
|
||||
controls.group_limit_action,
|
||||
changed_this.first, well_state,
|
||||
worst_offending_well,
|
||||
group_state, deferred_logger);
|
||||
changed = this->actionOnBrokenConstraints(group,
|
||||
controls.group_limit_action,
|
||||
changed_this.first,
|
||||
worst_offending_well,
|
||||
group_state, deferred_logger);
|
||||
|
||||
if(changed) {
|
||||
if (update_group_switching_log || switched_prod[group.name()].empty()) {
|
||||
switched_prod[group.name()].push_back(currentControl);
|
||||
}
|
||||
|
||||
WellGroupHelpersType::updateWellRatesFromGroupTargetScale(changed_this.second,
|
||||
group,
|
||||
wellModel_.schedule(),
|
||||
reportStepIdx,
|
||||
/* isInjector */ false,
|
||||
wellModel_.groupState(),
|
||||
well_state);
|
||||
wgHelper().updateWellRatesFromGroupTargetScale(changed_this.second,
|
||||
group,
|
||||
/*is_injector=*/false,
|
||||
well_state);
|
||||
} else if (worst_offending_well) {
|
||||
closed_offending_wells.insert_or_assign(group.name(),
|
||||
std::make_pair(Group::ProductionCMode2String(changed_this.first), *worst_offending_well));
|
||||
|
||||
@@ -34,7 +34,7 @@ class DeferredLogger;
|
||||
template<class Scalar> class GroupState;
|
||||
class SummaryState;
|
||||
template<typename Scalar, typename IndexTraits> class WellState;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelpers;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelper;
|
||||
|
||||
/// Class for handling constraints for the blackoil well model.
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
constexpr static int oilPhaseIdx = IndexTraits::oilPhaseIdx;
|
||||
constexpr static int gasPhaseIdx = IndexTraits::gasPhaseIdx;
|
||||
|
||||
using WellGroupHelpersType = WellGroupHelpers<Scalar, IndexTraits>;
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
|
||||
//! \brief Constructor initializes reference to the well model.
|
||||
explicit BlackoilWellModelConstraints(const BlackoilWellModelGeneric<Scalar, IndexTraits>& wellModel)
|
||||
@@ -67,10 +67,8 @@ public:
|
||||
|
||||
//! \brief Execute action on broken constraint for a production well group. Return true if a group control is changed
|
||||
bool actionOnBrokenConstraints(const Group& group,
|
||||
const int reportStepIdx,
|
||||
const Group::GroupLimitAction group_limit_action,
|
||||
const Group::ProductionCMode& newControl,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
std::optional<std::string>& worst_offending_well,
|
||||
GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
@@ -97,9 +95,9 @@ private:
|
||||
//! \brief Check and return value and type of constraints for a production well group.
|
||||
std::pair<Group::ProductionCMode, Scalar>
|
||||
checkGroupProductionConstraints(const Group& group,
|
||||
const int reportStepIdx,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
const WellGroupHelperType& wgHelper() const { return wellModel_.wgHelper(); }
|
||||
const BlackoilWellModelGeneric<Scalar, IndexTraits>& wellModel_; //!< Reference to well model
|
||||
};
|
||||
|
||||
|
||||
@@ -334,7 +334,8 @@ updateWellPotentials(const Simulator& simulator,
|
||||
auto cur_exc_type = ExceptionType::NONE;
|
||||
try {
|
||||
std::vector<Scalar> potentials;
|
||||
well->computeWellPotentials(simulator, well_state_copy, potentials, deferred_logger);
|
||||
const auto& wgHelper = simulator.problem().wellModel().wgHelper();
|
||||
well->computeWellPotentials(simulator, well_state_copy, wgHelper, potentials, deferred_logger);
|
||||
auto& ws = wellState.well(well->indexOfWell());
|
||||
for (int p = 0; p < np; ++p) {
|
||||
// make sure the potentials are positive
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
#include <opm/simulators/wells/ParallelWBPCalculation.hpp>
|
||||
#include <opm/simulators/wells/VFPProperties.hpp>
|
||||
#include <opm/simulators/wells/WellFilterCake.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellInterfaceGeneric.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
@@ -109,6 +109,7 @@ BlackoilWellModelGeneric(Schedule& schedule,
|
||||
, active_wgstate_(pu)
|
||||
, last_valid_wgstate_(pu)
|
||||
, nupcol_wgstate_(pu)
|
||||
, wg_helper_(this->wellState(), this->groupState(), this->schedule(), summaryState, guideRate_, pu)
|
||||
{
|
||||
|
||||
const auto numProcs = comm_.size();
|
||||
@@ -505,20 +506,12 @@ checkGconsaleLimits(const Group& group,
|
||||
const Group::ProductionCMode& oldProductionControl = this->groupState().production_control(group.name());
|
||||
|
||||
const int gasPos = phase_usage_info_.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
|
||||
Scalar production_rate = WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
gasPos,
|
||||
/*isInjector*/false,
|
||||
this->summaryState_);
|
||||
Scalar injection_rate = WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
schedule(),
|
||||
well_state,
|
||||
reportStepIdx,
|
||||
gasPos,
|
||||
/*isInjector*/true,
|
||||
this->summaryState_);
|
||||
Scalar production_rate = this->wgHelper().sumWellSurfaceRates(
|
||||
group, gasPos, /*is_injector=*/false
|
||||
);
|
||||
Scalar injection_rate = this->wgHelper().sumWellSurfaceRates(
|
||||
group, gasPos, /*is_injector=*/true
|
||||
);
|
||||
// sum over all nodes
|
||||
injection_rate = comm_.sum(injection_rate);
|
||||
production_rate = comm_.sum(production_rate);
|
||||
@@ -655,13 +648,9 @@ checkGroupHigherConstraints(const Group& group,
|
||||
const std::vector<Scalar> reduction_rates = this->groupState().injection_reduction_rates(group.name());
|
||||
|
||||
for (int phasePos = 0; phasePos < this->numPhases(); ++phasePos) {
|
||||
const Scalar local_current_rate = WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
schedule(),
|
||||
this->wellState(),
|
||||
reportStepIdx,
|
||||
phasePos,
|
||||
/* isInjector */ true,
|
||||
this->summaryState_);
|
||||
const Scalar local_current_rate = this->wgHelper().sumWellSurfaceRates(
|
||||
group, phasePos, /*is_injector=*/true
|
||||
);
|
||||
// Sum over all processes
|
||||
rates[phasePos] = comm_.sum(local_current_rate) - reduction_rates[phasePos];
|
||||
}
|
||||
@@ -698,22 +687,17 @@ checkGroupHigherConstraints(const Group& group,
|
||||
// Check higher up only if under individual (not FLD) control.
|
||||
if (currentControl != Group::InjectionCMode::FLD && group.injectionGroupControlAvailable(phase)) {
|
||||
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
|
||||
const auto [is_changed, scaling_factor] =
|
||||
WellGroupHelpersType::checkGroupConstraintsInj(group.name(),
|
||||
group.parent(),
|
||||
parentGroup,
|
||||
this->wellState(),
|
||||
this->groupState(),
|
||||
reportStepIdx,
|
||||
&guideRate_,
|
||||
rates.data(),
|
||||
phase,
|
||||
group.getGroupEfficiencyFactor(),
|
||||
schedule(),
|
||||
summaryState_,
|
||||
resv_coeff_inj,
|
||||
/*check_guide_rate*/true,
|
||||
deferred_logger);
|
||||
const auto [is_changed, scaling_factor] = this->wgHelper().checkGroupConstraintsInj(
|
||||
group.name(),
|
||||
group.parent(),
|
||||
parentGroup,
|
||||
rates.data(),
|
||||
phase,
|
||||
group.getGroupEfficiencyFactor(),
|
||||
resv_coeff_inj,
|
||||
/*check_guide_rate*/true,
|
||||
deferred_logger
|
||||
);
|
||||
if (is_changed) {
|
||||
auto& group_log = switched_inj_groups_[group.name()][static_cast<std::underlying_type_t<Phase>>(phase)];
|
||||
if (update_group_switching_log || group_log.empty()) {
|
||||
@@ -723,13 +707,9 @@ checkGroupHigherConstraints(const Group& group,
|
||||
actionOnBrokenConstraints(group, Group::InjectionCMode::FLD,
|
||||
phase, this->groupState(),
|
||||
deferred_logger);
|
||||
WellGroupHelpersType::updateWellRatesFromGroupTargetScale(scaling_factor,
|
||||
group,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
/* isInjector */ true,
|
||||
this->groupState(),
|
||||
this->wellState());
|
||||
this->wgHelper().updateWellRatesFromGroupTargetScale(
|
||||
scaling_factor, group, /*is_injector=*/true, this->wellState()
|
||||
);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -762,13 +742,9 @@ checkGroupHigherConstraints(const Group& group,
|
||||
}
|
||||
}
|
||||
for (int phasePos = 0; phasePos < this->numPhases(); ++phasePos) {
|
||||
const Scalar local_current_rate = WellGroupHelpersType::sumWellSurfaceRates(group,
|
||||
schedule(),
|
||||
this->wellState(),
|
||||
reportStepIdx,
|
||||
phasePos,
|
||||
/* isInjector */ false,
|
||||
this->summaryState_);
|
||||
const Scalar local_current_rate = this->wgHelper().sumWellSurfaceRates(
|
||||
group, phasePos, /*is_injector=*/false
|
||||
);
|
||||
// Sum over all processes
|
||||
rates[phasePos] = -comm_.sum(local_current_rate) - reduction_rates[phasePos];
|
||||
}
|
||||
@@ -777,28 +753,23 @@ checkGroupHigherConstraints(const Group& group,
|
||||
// Check higher up only if under individual (not FLD) control.
|
||||
if (currentControl != Group::ProductionCMode::FLD && group.productionGroupControlAvailable()) {
|
||||
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
|
||||
const auto [is_changed, scaling_factor] =
|
||||
WellGroupHelpersType::checkGroupConstraintsProd(group.name(),
|
||||
group.parent(),
|
||||
parentGroup,
|
||||
this->wellState(),
|
||||
this->groupState(),
|
||||
reportStepIdx,
|
||||
&guideRate_,
|
||||
rates.data(),
|
||||
group.getGroupEfficiencyFactor(),
|
||||
schedule(),
|
||||
summaryState_,
|
||||
resv_coeff,
|
||||
/*check_guide_rate*/true,
|
||||
deferred_logger);
|
||||
const auto [is_changed, scaling_factor] = this->wgHelper().checkGroupConstraintsProd(
|
||||
group.name(),
|
||||
group.parent(),
|
||||
parentGroup,
|
||||
rates.data(),
|
||||
group.getGroupEfficiencyFactor(),
|
||||
resv_coeff,
|
||||
/*check_guide_rate*/true,
|
||||
deferred_logger
|
||||
);
|
||||
if (is_changed) {
|
||||
const auto group_limit_action = group.productionControls(summaryState_).group_limit_action;
|
||||
std::optional<std::string> worst_offending_well = std::nullopt;
|
||||
changed = BlackoilWellModelConstraints(*this).
|
||||
actionOnBrokenConstraints(group, reportStepIdx, group_limit_action,
|
||||
actionOnBrokenConstraints(group,
|
||||
group_limit_action,
|
||||
Group::ProductionCMode::FLD,
|
||||
this->wellState(),
|
||||
worst_offending_well,
|
||||
this->groupState(),
|
||||
deferred_logger);
|
||||
@@ -807,13 +778,9 @@ checkGroupHigherConstraints(const Group& group,
|
||||
if (update_group_switching_log || switched_prod_groups_[group.name()].empty()) {
|
||||
switched_prod_groups_[group.name()].push_back(currentControl);
|
||||
}
|
||||
WellGroupHelpersType::updateWellRatesFromGroupTargetScale(scaling_factor,
|
||||
group,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
/* isInjector */ false,
|
||||
this->groupState(),
|
||||
this->wellState());
|
||||
this->wgHelper().updateWellRatesFromGroupTargetScale(
|
||||
scaling_factor, group, /*is_injector=*/false, this->wellState()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1006,18 +973,12 @@ updateWsolvent(const Group& group,
|
||||
const int gasPos = phase_usage_info_.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
|
||||
const auto& controls = group.injectionControls(Phase::GAS, summaryState_);
|
||||
const Group& groupRein = schedule_.getGroup(controls.reinj_group, reportStepIdx);
|
||||
Scalar gasProductionRate = WellGroupHelpersType::sumWellSurfaceRates(groupRein,
|
||||
schedule_,
|
||||
wellState,
|
||||
reportStepIdx,
|
||||
gasPos,
|
||||
/*isInjector*/false,
|
||||
this->summaryState_);
|
||||
Scalar solventProductionRate = WellGroupHelpersType::sumSolventRates(groupRein,
|
||||
schedule_,
|
||||
wellState,
|
||||
reportStepIdx,
|
||||
/*isInjector*/false);
|
||||
Scalar gasProductionRate = this->wgHelper().sumWellSurfaceRates(
|
||||
groupRein, gasPos, /*is_injector=*/false
|
||||
);
|
||||
Scalar solventProductionRate = this->wgHelper().sumSolventRates(
|
||||
groupRein, /*is_injector=*/false
|
||||
);
|
||||
|
||||
solventProductionRate = comm_.sum(solventProductionRate);
|
||||
gasProductionRate = comm_.sum(gasProductionRate);
|
||||
@@ -1260,13 +1221,11 @@ assignNodeValues(std::map<std::string, data::NodeData>& nodevalues,
|
||||
return;
|
||||
}
|
||||
|
||||
auto converged_pressures = WellGroupHelpersType::computeNetworkPressures(network,
|
||||
this->wellState(),
|
||||
this->groupState(),
|
||||
*(vfp_properties_->getProd()),
|
||||
schedule(),
|
||||
comm_,
|
||||
reportStepIdx);
|
||||
auto converged_pressures = this->wgHelper().computeNetworkPressures(
|
||||
network,
|
||||
*(this->vfp_properties_->getProd()),
|
||||
this->comm_
|
||||
);
|
||||
for (const auto& [node, converged_pressure] : converged_pressures) {
|
||||
auto it = nodevalues.find(node);
|
||||
assert(it != nodevalues.end() );
|
||||
@@ -1327,6 +1286,7 @@ updateAndCommunicateGroupData(const int reportStepIdx,
|
||||
|
||||
this->wellState().updateGlobalIsGrup(comm_, well_status);
|
||||
|
||||
WellGroupHelperType &wg_helper = this->wgHelper();
|
||||
if (iterationIdx < nupcol) {
|
||||
OPM_TIMEBLOCK(updateNupcol);
|
||||
this->updateNupcolWGState();
|
||||
@@ -1342,26 +1302,27 @@ updateAndCommunicateGroupData(const int reportStepIdx,
|
||||
const Group& group = schedule().getGroup(gr_name, reportStepIdx);
|
||||
const int np = this->wellState().numPhases();
|
||||
Scalar gr_rate_nupcol = 0.0;
|
||||
for (int phaseIdx = 0; phaseIdx < np; ++phaseIdx) {
|
||||
gr_rate_nupcol += WellGroupHelpersType::sumWellPhaseRates(is_vrep,
|
||||
group,
|
||||
schedule(),
|
||||
this->nupcolWellState(),
|
||||
this->summaryState_,
|
||||
reportStepIdx,
|
||||
phaseIdx,
|
||||
/*isInjector*/ false);
|
||||
{
|
||||
// Temporarily use the nupcol well state for all helper functions
|
||||
// At the end of this scope, the well state will be restored to its original value
|
||||
auto guard = wg_helper.pushWellState(this->nupcolWellState());
|
||||
for (int phaseIdx = 0; phaseIdx < np; ++phaseIdx) {
|
||||
gr_rate_nupcol += wg_helper.sumWellPhaseRates(
|
||||
/*res_rates=*/is_vrep,
|
||||
group,
|
||||
phaseIdx,
|
||||
/*is_injector=*/false
|
||||
);
|
||||
}
|
||||
}
|
||||
Scalar gr_rate = 0.0;
|
||||
for (int phaseIdx = 0; phaseIdx < np; ++phaseIdx) {
|
||||
gr_rate += WellGroupHelpersType::sumWellPhaseRates(is_vrep,
|
||||
group,
|
||||
schedule(),
|
||||
this->wellState(),
|
||||
this->summaryState_,
|
||||
reportStepIdx,
|
||||
phaseIdx,
|
||||
/*isInjector*/ false);
|
||||
gr_rate += wg_helper.sumWellPhaseRates(
|
||||
/*res_rates=*/is_vrep,
|
||||
group,
|
||||
phaseIdx,
|
||||
/*is_injector=*/false
|
||||
);
|
||||
}
|
||||
// sum contributions from owned wells to everybody
|
||||
gr_rate_nupcol = comm_.sum(gr_rate_nupcol);
|
||||
@@ -1385,93 +1346,33 @@ updateAndCommunicateGroupData(const int reportStepIdx,
|
||||
}
|
||||
}
|
||||
}
|
||||
auto& well_state = this->wellState();
|
||||
const auto& well_state_nupcol = this->nupcolWellState();
|
||||
|
||||
constexpr int num_configs = 4;
|
||||
constexpr std::array<bool, num_configs> is_production_group = {true, false, false, false};
|
||||
constexpr std::array<Phase, num_configs> phases = { Phase::OIL, Phase::WATER, Phase::OIL, Phase::GAS };
|
||||
for (int i = 0; i < num_configs; i++) {
|
||||
WellGroupHelpersType::updateGroupControlledWells(schedule(),
|
||||
well_state,
|
||||
this->groupState(),
|
||||
summaryState_,
|
||||
&guideRate_,
|
||||
reportStepIdx,
|
||||
"FIELD",
|
||||
is_production_group[i],
|
||||
phases[i]);
|
||||
{
|
||||
constexpr int num_configs = 4;
|
||||
constexpr std::array<bool, num_configs> is_production_group = {true, false, false, false};
|
||||
constexpr std::array<Phase, num_configs> phases = { Phase::OIL, Phase::WATER, Phase::OIL, Phase::GAS };
|
||||
for (int i = 0; i < num_configs; i++) {
|
||||
wg_helper.updateGroupControlledWells(
|
||||
is_production_group[i], phases[i], this->groupState(), deferred_logger
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// the group target reduction rates needs to be update since wells may have switched to/from GRUP control
|
||||
// The group target reduction does not honor NUPCOL.
|
||||
std::vector<Scalar> groupTargetReduction(numPhases(), 0.0);
|
||||
WellGroupHelpersType::updateGroupTargetReduction(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
/*isInjector*/ false,
|
||||
guideRate_,
|
||||
well_state,
|
||||
summaryState_,
|
||||
this->groupState(),
|
||||
groupTargetReduction);
|
||||
std::vector<Scalar> groupTargetReductionInj(numPhases(), 0.0);
|
||||
WellGroupHelpersType::updateGroupTargetReduction(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
/*isInjector*/ true,
|
||||
guideRate_,
|
||||
well_state,
|
||||
summaryState_,
|
||||
this->groupState(),
|
||||
groupTargetReductionInj);
|
||||
|
||||
WellGroupHelpersType::updateREINForGroups(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
summaryState_,
|
||||
well_state_nupcol,
|
||||
this->groupState(),
|
||||
comm_.rank() == 0);
|
||||
WellGroupHelpersType::updateVREPForGroups(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
this->groupState(),
|
||||
this->summaryState_);
|
||||
|
||||
WellGroupHelpersType::updateReservoirRatesInjectionGroups(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
this->groupState(),
|
||||
this->summaryState_);
|
||||
WellGroupHelpersType::updateSurfaceRatesInjectionGroups(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
this->groupState(),
|
||||
this->summaryState_);
|
||||
WellGroupHelpersType::updateNetworkLeafNodeProductionRates(schedule(),
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
this->groupState(),
|
||||
this->summaryState_);
|
||||
|
||||
WellGroupHelpersType::updateGroupProductionRates(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
this->groupState(),
|
||||
this->summaryState_);
|
||||
|
||||
WellGroupHelpersType::updateWellRates(fieldGroup,
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
well_state_nupcol,
|
||||
well_state);
|
||||
|
||||
well_state.communicateGroupRates(comm_);
|
||||
wg_helper.updateGroupTargetReduction(fieldGroup, /*is_injector=*/false, this->groupState());
|
||||
wg_helper.updateGroupTargetReduction(fieldGroup, /*is_injector=*/true, this->groupState());
|
||||
{
|
||||
// Temporarily use the nupcol well state for all helper functions
|
||||
// At the end of this scope, the well state will be restored to its original value
|
||||
auto guard = wg_helper.pushWellState(this->nupcolWellState());
|
||||
wg_helper.updateREINForGroups(fieldGroup, /*sum_rank=*/comm_.rank() == 0, this->groupState());
|
||||
wg_helper.updateVREPForGroups(fieldGroup, this->groupState());
|
||||
wg_helper.updateReservoirRatesInjectionGroups(fieldGroup, this->groupState());
|
||||
wg_helper.updateSurfaceRatesInjectionGroups(fieldGroup, this->groupState());
|
||||
wg_helper.updateNetworkLeafNodeProductionRates(this->groupState());
|
||||
wg_helper.updateGroupProductionRates(fieldGroup, this->groupState());
|
||||
}
|
||||
wg_helper.updateWellRates(fieldGroup, this->nupcolWellState(), this->wellState());
|
||||
this->wellState().communicateGroupRates(comm_);
|
||||
this->groupState().communicate_rates(comm_);
|
||||
|
||||
if (update_wellgrouptarget) {
|
||||
@@ -1487,20 +1388,15 @@ updateAndCommunicateGroupData(const int reportStepIdx,
|
||||
// Translate injector type from control to Phase.
|
||||
Scalar group_target = std::numeric_limits<Scalar>::max();
|
||||
if (well->isProducer()) {
|
||||
group_target =
|
||||
WellGroupHelpersType::getWellGroupTargetProducer(well->name(),
|
||||
well->wellEcl().groupName(),
|
||||
group,
|
||||
this->wellState(),
|
||||
this->groupState(),
|
||||
well->currentStep(),
|
||||
well->guideRate(),
|
||||
ws.surface_rates.data(),
|
||||
efficiencyFactor,
|
||||
this->schedule(),
|
||||
summaryState_,
|
||||
resv_coeff,
|
||||
deferred_logger);
|
||||
group_target = wg_helper.getWellGroupTargetProducer(
|
||||
well->name(),
|
||||
well->wellEcl().groupName(),
|
||||
group,
|
||||
ws.surface_rates.data(),
|
||||
efficiencyFactor,
|
||||
resv_coeff,
|
||||
deferred_logger
|
||||
);
|
||||
} else {
|
||||
const auto& well_controls = well->wellEcl().injectionControls(summaryState_);
|
||||
auto injectorType = well_controls.injector_type;
|
||||
@@ -1524,21 +1420,16 @@ updateAndCommunicateGroupData(const int reportStepIdx,
|
||||
default:
|
||||
throw std::logic_error("MULTI-phase injection is not supported, but was requested for well " + well->name());
|
||||
}
|
||||
group_target =
|
||||
WellGroupHelpersType::getWellGroupTargetInjector(well->name(),
|
||||
well->wellEcl().groupName(),
|
||||
group,
|
||||
this->wellState(),
|
||||
this->groupState(),
|
||||
well->currentStep(),
|
||||
well->guideRate(),
|
||||
ws.surface_rates.data(),
|
||||
injectionPhase,
|
||||
efficiencyFactor,
|
||||
this->schedule(),
|
||||
summaryState_,
|
||||
resv_coeff,
|
||||
deferred_logger);
|
||||
group_target = wg_helper.getWellGroupTargetInjector(
|
||||
well->name(),
|
||||
well->wellEcl().groupName(),
|
||||
group,
|
||||
ws.surface_rates.data(),
|
||||
injectionPhase,
|
||||
efficiencyFactor,
|
||||
resv_coeff,
|
||||
deferred_logger
|
||||
);
|
||||
}
|
||||
auto& ws_update = this->wellState().well(well->indexOfWell());
|
||||
ws_update.group_target = group_target;
|
||||
@@ -1675,13 +1566,8 @@ updateNetworkPressures(const int reportStepIdx, const Scalar damping_factor, con
|
||||
|
||||
const auto previous_node_pressures = node_pressures_;
|
||||
|
||||
node_pressures_ = WellGroupHelpersType::computeNetworkPressures(network,
|
||||
this->wellState(),
|
||||
this->groupState(),
|
||||
*(vfp_properties_->getProd()),
|
||||
schedule(),
|
||||
comm_,
|
||||
reportStepIdx);
|
||||
node_pressures_ = this->wgHelper().computeNetworkPressures(
|
||||
network, *(vfp_properties_->getProd()), comm_);
|
||||
|
||||
// here, the network imbalance is the difference between the previous nodal pressure and the new nodal pressure
|
||||
Scalar network_imbalance = 0.;
|
||||
@@ -1748,11 +1634,10 @@ calculateEfficiencyFactors(const int reportStepIdx)
|
||||
const Well& wellEcl = well->wellEcl();
|
||||
Scalar well_efficiency_factor = wellEcl.getEfficiencyFactor() *
|
||||
wellState().getGlobalEfficiencyScalingFactor(well->name());
|
||||
WellGroupHelpersType::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(),
|
||||
reportStepIdx),
|
||||
schedule(),
|
||||
reportStepIdx,
|
||||
well_efficiency_factor);
|
||||
this->wgHelper().accumulateGroupEfficiencyFactor(
|
||||
schedule().getGroup(wellEcl.groupName(), reportStepIdx),
|
||||
well_efficiency_factor
|
||||
);
|
||||
well->setWellEfficiencyFactor(well_efficiency_factor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <opm/simulators/wells/ParallelWellInfo.hpp>
|
||||
#include <opm/simulators/wells/PerforationData.hpp>
|
||||
#include <opm/simulators/wells/WellFilterCake.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellProdIndexCalculator.hpp>
|
||||
#include <opm/simulators/wells/WellTracerRate.hpp>
|
||||
#include <opm/simulators/wells/WGState.hpp>
|
||||
@@ -69,7 +70,6 @@ namespace Opm {
|
||||
struct SimulatorUpdate;
|
||||
class SummaryConfig;
|
||||
template<typename Scalar, typename IndexTraits> class VFPProperties;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelpers;
|
||||
template<typename Scalar, typename IndexTraits> class WellInterfaceGeneric;
|
||||
template<typename Scalar, typename IndexTraits> class WellState;
|
||||
} // namespace Opm
|
||||
@@ -93,7 +93,7 @@ namespace Opm {
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
class BlackoilWellModelGeneric
|
||||
{
|
||||
using WellGroupHelpersType = WellGroupHelpers<Scalar, IndexTraits>;
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
public:
|
||||
BlackoilWellModelGeneric(Schedule& schedule,
|
||||
BlackoilWellModelGasLiftGeneric<Scalar, IndexTraits>& gaslift,
|
||||
@@ -165,11 +165,19 @@ public:
|
||||
/*
|
||||
Will return the currently active nupcolWellState; must update
|
||||
the internal nupcol wellstate with updateNupcolWGState() first.
|
||||
|
||||
Both const and non-const accessors are provided. The non-const
|
||||
accessor is required for the WellStateGuard pattern and pushWellState()
|
||||
in WellGroupHelper, which temporarily switches WellGroupHelper to use this state.
|
||||
*/
|
||||
const WellState<Scalar, IndexTraits>& nupcolWellState() const
|
||||
{
|
||||
return this->nupcol_wgstate_.well_state;
|
||||
}
|
||||
WellState<Scalar, IndexTraits>& nupcolWellState()
|
||||
{
|
||||
return this->nupcol_wgstate_.well_state;
|
||||
}
|
||||
GroupState<Scalar>& groupState() { return this->active_wgstate_.group_state; }
|
||||
|
||||
WellTestState& wellTestState() { return this->active_wgstate_.well_test_state; }
|
||||
@@ -295,6 +303,9 @@ public:
|
||||
const ConnectionIndexMap& connectionIndexMap(const std::size_t idx)
|
||||
{ return conn_idx_map_[idx]; }
|
||||
|
||||
WellGroupHelperType& wgHelper() { return wg_helper_; }
|
||||
const WellGroupHelperType& wgHelper() const { return wg_helper_; }
|
||||
|
||||
protected:
|
||||
/*
|
||||
The dynamic state of the well model is maintained with an instance
|
||||
@@ -352,6 +363,8 @@ protected:
|
||||
{
|
||||
this->active_wgstate_ = this->last_valid_wgstate_;
|
||||
this->node_pressures_ = this->last_valid_node_pressures_;
|
||||
// Update helper pointers to reference the restored active state
|
||||
this->wg_helper_.updateState(this->wellState(), this->groupState());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -575,6 +588,7 @@ protected:
|
||||
WGState<Scalar, IndexTraits> active_wgstate_;
|
||||
WGState<Scalar, IndexTraits> last_valid_wgstate_;
|
||||
WGState<Scalar, IndexTraits> nupcol_wgstate_;
|
||||
WellGroupHelperType wg_helper_;
|
||||
WellGroupEvents report_step_start_events_; //!< Well group events at start of report step
|
||||
|
||||
bool wellStructureChangedDynamically_{false};
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <opm/material/fluidsystems/BlackOilDefaultFluidSystemIndices.hpp>
|
||||
|
||||
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellInterfaceGeneric.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
@@ -331,8 +331,7 @@ getGuideRateValues(const Well& well) const
|
||||
return grval;
|
||||
}
|
||||
|
||||
const auto qs = WellGroupHelpers<Scalar, IndexTraits>::
|
||||
getWellRateVector(wellModel_.wellState(), wname);
|
||||
const auto qs = this->wgHelper().getWellRateVector(wname);
|
||||
|
||||
this->getGuideRateValues(qs, well.isInjector(), wname, grval);
|
||||
|
||||
@@ -359,8 +358,7 @@ getGuideRateValues(const Group& group) const
|
||||
return grval;
|
||||
}
|
||||
|
||||
const auto qs = WellGroupHelpers<Scalar, IndexTraits>::
|
||||
getProductionGroupRateVector(wellModel_.groupState(), wellModel_.phaseUsage(), gname);
|
||||
const auto qs = this->wgHelper().getProductionGroupRateVector(gname);
|
||||
|
||||
const auto is_inj = false; // This procedure only applies to G*PGR.
|
||||
this->getGuideRateValues(qs, is_inj, gname, grval);
|
||||
@@ -439,8 +437,7 @@ calculateWellGuideRates(const int reportStepIdx) const
|
||||
const auto get_gr = parent
|
||||
|| RetrieveWellGuideRate{wellModel_.guideRate(), wname};
|
||||
|
||||
const auto qs = WellGroupHelpers<Scalar, IndexTraits>::
|
||||
getWellRateVector(wellModel_.wellState(), wname);
|
||||
const auto qs = this->wgHelper().getWellRateVector(wname);
|
||||
|
||||
auto getGR = [this, &wname, &qs](const GuideRateModel::Target t)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
namespace Opm {
|
||||
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelper;
|
||||
template<typename Scalar, typename IndexTraits> class BlackoilWellModelGeneric;
|
||||
namespace data {
|
||||
struct GroupData;
|
||||
@@ -45,6 +46,8 @@ template<typename Scalar, typename IndexTraits>
|
||||
class BlackoilWellModelGuideRates
|
||||
{
|
||||
public:
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
|
||||
//! \brief Constructor initializes reference to the well model.
|
||||
explicit BlackoilWellModelGuideRates(const BlackoilWellModelGeneric<Scalar, IndexTraits>& wellModel)
|
||||
: wellModel_(wellModel)
|
||||
@@ -70,6 +73,8 @@ public:
|
||||
//! \brief Check if a guide rate update is needed.
|
||||
bool guideRateUpdateIsNeeded(const int reportStepIdx) const;
|
||||
|
||||
const WellGroupHelperType& wgHelper() const { return wellModel_.wgHelper(); }
|
||||
|
||||
private:
|
||||
//! \brief Obtain guide rate values.
|
||||
void getGuideRateValues(const GuideRate::RateVector& qs,
|
||||
|
||||
@@ -63,8 +63,8 @@ assembleWellEq(const double dt,
|
||||
if (this->well_domain().at(well->name()) == domain.index) {
|
||||
well->assembleWellEq(wellModel_.simulator(),
|
||||
dt,
|
||||
wellModel_.wgHelper(),
|
||||
wellModel_.wellState(),
|
||||
wellModel_.groupState(),
|
||||
deferred_logger);
|
||||
}
|
||||
}
|
||||
@@ -192,8 +192,8 @@ updateWellControls(DeferredLogger& deferred_logger,
|
||||
constexpr auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
|
||||
well->updateWellControl(wellModel_.simulator(),
|
||||
mode,
|
||||
wellModel_.wgHelper(),
|
||||
wellModel_.wellState(),
|
||||
wellModel_.groupState(),
|
||||
deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
#include <opm/simulators/wells/VFPProperties.hpp>
|
||||
#include <opm/simulators/wells/WellBhpThpCalculator.hpp>
|
||||
#include <opm/simulators/wells/WellGroupControls.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/TargetCalculator.hpp>
|
||||
|
||||
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
|
||||
@@ -195,6 +195,7 @@ namespace Opm {
|
||||
{
|
||||
DeferredLogger local_deferredLogger{};
|
||||
|
||||
this->wgHelper().setReportStep(timeStepIdx);
|
||||
this->report_step_starts_ = true;
|
||||
this->report_step_start_events_ = this->schedule()[timeStepIdx].wellgroup_events();
|
||||
|
||||
@@ -299,20 +300,16 @@ namespace Opm {
|
||||
const auto& fieldGroup =
|
||||
this->schedule().getGroup("FIELD", reportStepIdx);
|
||||
|
||||
WellGroupHelpersType::setCmodeGroup(fieldGroup,
|
||||
this->schedule(),
|
||||
this->summaryState(),
|
||||
reportStepIdx,
|
||||
this->groupState());
|
||||
this->wgHelper().setCmodeGroup(fieldGroup, this->groupState());
|
||||
|
||||
// Define per region average pressure calculators for use by
|
||||
// pressure maintenance groups (GPMAINT keyword).
|
||||
if (this->schedule()[reportStepIdx].has_gpmaint()) {
|
||||
WellGroupHelpersType::setRegionAveragePressureCalculator(fieldGroup,
|
||||
this->schedule(),
|
||||
reportStepIdx,
|
||||
this->eclState_.fieldProps(),
|
||||
this->regionalAveragePressureCalculator_);
|
||||
this->wgHelper().setRegionAveragePressureCalculator(
|
||||
fieldGroup,
|
||||
this->eclState_.fieldProps(),
|
||||
this->regionalAveragePressureCalculator_
|
||||
);
|
||||
}
|
||||
}
|
||||
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
|
||||
@@ -364,10 +361,8 @@ namespace Opm {
|
||||
}
|
||||
|
||||
this->resetWGState();
|
||||
|
||||
const int reportStepIdx = simulator_.episodeIndex();
|
||||
|
||||
|
||||
this->wellState().updateWellsDefaultALQ(this->schedule(), reportStepIdx, this->summaryState());
|
||||
this->wellState().gliftTimeStepInit();
|
||||
|
||||
@@ -482,13 +477,10 @@ namespace Opm {
|
||||
}
|
||||
const double dt = simulator_.timeStepSize();
|
||||
const Group& fieldGroup = this->schedule().getGroup("FIELD", reportStepIdx);
|
||||
WellGroupHelpers<Scalar, IndexTraits>::updateGpMaintTargetForGroups(fieldGroup,
|
||||
this->schedule_,
|
||||
regionalAveragePressureCalculator_,
|
||||
reportStepIdx,
|
||||
dt,
|
||||
this->wellState(),
|
||||
this->groupState());
|
||||
this->wgHelper().updateGpMaintTargetForGroups(fieldGroup,
|
||||
regionalAveragePressureCalculator_,
|
||||
dt,
|
||||
this->groupState());
|
||||
}
|
||||
|
||||
this->updateAndCommunicateGroupData(reportStepIdx,
|
||||
@@ -513,9 +505,11 @@ namespace Opm {
|
||||
try {
|
||||
well->scaleSegmentRatesAndPressure(this->wellState());
|
||||
well->calculateExplicitQuantities(simulator_, this->wellState(), local_deferredLogger);
|
||||
well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), local_deferredLogger);
|
||||
well->updateWellStateWithTarget(simulator_, this->wgHelper(), this->wellState(), local_deferredLogger);
|
||||
well->updatePrimaryVariables(simulator_, this->wellState(), local_deferredLogger);
|
||||
well->solveWellEquation(simulator_, this->wellState(), this->groupState(), local_deferredLogger);
|
||||
well->solveWellEquation(
|
||||
simulator_, this->wgHelper(), this->wellState(), local_deferredLogger
|
||||
);
|
||||
} catch (const std::exception& e) {
|
||||
const std::string msg = "Compute initial well solution for new well " + well->name() + " failed. Continue with zero initial rates";
|
||||
local_deferredLogger.warning("WELL_INITIAL_SOLVE_FAILED", msg);
|
||||
@@ -554,11 +548,10 @@ namespace Opm {
|
||||
|
||||
Scalar well_efficiency_factor = wellEcl.getEfficiencyFactor() *
|
||||
this->wellState().getGlobalEfficiencyScalingFactor(well_name);
|
||||
WellGroupHelpersType::accumulateGroupEfficiencyFactor(this->schedule().getGroup(wellEcl.groupName(),
|
||||
timeStepIdx),
|
||||
this->schedule(),
|
||||
timeStepIdx,
|
||||
well_efficiency_factor);
|
||||
this->wgHelper().accumulateGroupEfficiencyFactor(
|
||||
this->schedule().getGroup(wellEcl.groupName(), timeStepIdx),
|
||||
well_efficiency_factor
|
||||
);
|
||||
|
||||
well->setWellEfficiencyFactor(well_efficiency_factor);
|
||||
well->setVFPProperties(this->vfp_properties_.get());
|
||||
@@ -590,8 +583,8 @@ namespace Opm {
|
||||
gaslift_.initGliftEclWellMap(well_container_, ecl_well_map);
|
||||
well->wellTesting(simulator_,
|
||||
simulationTime,
|
||||
this->wgHelper(),
|
||||
this->wellState(),
|
||||
this->groupState(),
|
||||
this->wellTestState(),
|
||||
ecl_well_map,
|
||||
this->well_open_times_,
|
||||
@@ -1366,8 +1359,7 @@ namespace Opm {
|
||||
auto target = WellGroupControls<Scalar, IndexTraits>::getAutoChokeGroupProductionTargetRate(
|
||||
group.name(),
|
||||
parentGroup,
|
||||
well_state,
|
||||
group_state,
|
||||
this->wgHelper(),
|
||||
this->schedule(),
|
||||
summary_state,
|
||||
resv_coeff,
|
||||
@@ -1402,7 +1394,9 @@ namespace Opm {
|
||||
const Well& well_ecl = this->wells_ecl_[well->indexOfWell()];
|
||||
const auto inj_controls = Well::InjectionControls(0);
|
||||
const auto prod_controls = well_ecl.productionControls(summary_state);
|
||||
well->iterateWellEqWithSwitching(this->simulator_, dt, inj_controls, prod_controls, well_state, group_state, local_deferredLogger, false, false);
|
||||
well->iterateWellEqWithSwitching(
|
||||
this->simulator_, dt, inj_controls, prod_controls, this->wgHelper(), this->wellState(), local_deferredLogger, false, false
|
||||
);
|
||||
rate = -tcalc.calcModeRateFromRates(ws.surface_rates);
|
||||
group_rate += rate;
|
||||
}
|
||||
@@ -1490,7 +1484,9 @@ namespace Opm {
|
||||
const auto& ws = this->wellState().well(well->indexOfWell());
|
||||
const bool thp_is_limit = ws.production_cmode == Well::ProducerCMode::THP;
|
||||
if (thp_is_limit) {
|
||||
well->prepareWellBeforeAssembling(this->simulator_, dt, this->wellState(), this->groupState(), local_deferredLogger);
|
||||
well->prepareWellBeforeAssembling(
|
||||
this->simulator_, dt, this->wgHelper(), this->wellState(), local_deferredLogger
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1512,7 +1508,7 @@ namespace Opm {
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
for (auto& well : well_container_) {
|
||||
well->assembleWellEq(simulator_, dt, this->wellState(), this->groupState(), deferred_logger);
|
||||
well->assembleWellEq(simulator_, dt, this->wgHelper(), deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1524,7 +1520,9 @@ namespace Opm {
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
for (auto& well : well_container_) {
|
||||
well->prepareWellBeforeAssembling(simulator_, dt, this->wellState(), this->groupState(), deferred_logger);
|
||||
well->prepareWellBeforeAssembling(
|
||||
simulator_, dt, this->wgHelper(), this->wellState(), deferred_logger
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1806,7 +1804,9 @@ namespace Opm {
|
||||
OPM_BEGIN_PARALLEL_TRY_CATCH()
|
||||
for (const auto& well : well_container_) {
|
||||
const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Group;
|
||||
const bool changed_well = well->updateWellControl(simulator_, mode, this->wellState(), this->groupState(), deferred_logger);
|
||||
const bool changed_well = well->updateWellControl(
|
||||
simulator_, mode, this->wgHelper(), this->wellState(), deferred_logger
|
||||
);
|
||||
if (changed_well) {
|
||||
changed_well_to_group = changed_well || changed_well_to_group;
|
||||
}
|
||||
@@ -1829,7 +1829,9 @@ namespace Opm {
|
||||
OPM_BEGIN_PARALLEL_TRY_CATCH()
|
||||
for (const auto& well : well_container_) {
|
||||
const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
|
||||
const bool changed_well = well->updateWellControl(simulator_, mode, this->wellState(), this->groupState(), deferred_logger);
|
||||
const bool changed_well = well->updateWellControl(
|
||||
simulator_, mode, this->wgHelper(), this->wellState(), deferred_logger
|
||||
);
|
||||
if (changed_well) {
|
||||
changed_well_individual = changed_well || changed_well_individual;
|
||||
}
|
||||
@@ -1901,7 +1903,9 @@ namespace Opm {
|
||||
const auto& ws = this->wellState().well(well->indexOfWell());
|
||||
const bool thp_is_limit = ws.production_cmode == Well::ProducerCMode::THP;
|
||||
if (thp_is_limit) {
|
||||
well->prepareWellBeforeAssembling(this->simulator_, dt, this->wellState(), this->groupState(), deferred_logger);
|
||||
well->prepareWellBeforeAssembling(
|
||||
this->simulator_, dt, this->wgHelper(), this->wellState(), deferred_logger
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1937,8 +1941,9 @@ namespace Opm {
|
||||
if (ws.production_cmode == Well::ProducerCMode::GRUP ||
|
||||
ws.injection_cmode == Well::InjectorCMode::GRUP)
|
||||
{
|
||||
well->updateWellStateWithTarget(simulator_, this->groupState(),
|
||||
this->wellState(), deferred_logger);
|
||||
well->updateWellStateWithTarget(
|
||||
simulator_, this->wgHelper(), this->wellState(), deferred_logger
|
||||
);
|
||||
}
|
||||
}
|
||||
OPM_END_PARALLEL_TRY_CATCH("BlackoilWellModel::updateAndCommunicate failed: ",
|
||||
@@ -2007,6 +2012,7 @@ namespace Opm {
|
||||
const auto wasClosed = wellTestState.well_is_closed(wname);
|
||||
well->checkWellOperability(simulator_,
|
||||
this->wellState(),
|
||||
this->wgHelper(),
|
||||
local_deferredLogger);
|
||||
const bool under_zero_target =
|
||||
well->wellUnderZeroGroupRateTarget(this->simulator_,
|
||||
@@ -2091,7 +2097,7 @@ namespace Opm {
|
||||
std::string cur_exc_msg;
|
||||
auto cur_exc_type = ExceptionType::NONE;
|
||||
try {
|
||||
well->computeWellPotentials(simulator_, well_state_copy, potentials, deferred_logger);
|
||||
well->computeWellPotentials(simulator_, well_state_copy, this->wgHelper(), potentials, deferred_logger);
|
||||
}
|
||||
// catch all possible exception and store type and message.
|
||||
OPM_PARALLEL_CATCH_CLAUSE(cur_exc_type, cur_exc_msg);
|
||||
@@ -2185,7 +2191,9 @@ namespace Opm {
|
||||
for (const auto& well : well_container_) {
|
||||
auto& events = this->wellState().well(well->indexOfWell()).events;
|
||||
if (events.hasEvent(WellState<Scalar, IndexTraits>::event_mask)) {
|
||||
well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), deferred_logger);
|
||||
well->updateWellStateWithTarget(
|
||||
simulator_, this->wgHelper(), this->wellState(), deferred_logger
|
||||
);
|
||||
well->updatePrimaryVariables(simulator_, this->wellState(), deferred_logger);
|
||||
// There is no new well control change input within a report step,
|
||||
// so next time step, the well does not consider to have effective events anymore.
|
||||
@@ -2198,7 +2206,9 @@ namespace Opm {
|
||||
// solve the well equation initially to improve the initial solution of the well model
|
||||
if (param_.solve_welleq_initially_ && well->isOperableAndSolvable()) {
|
||||
try {
|
||||
well->solveWellEquation(simulator_, this->wellState(), this->groupState(), deferred_logger);
|
||||
well->solveWellEquation(
|
||||
simulator_, this->wgHelper(), this->wellState(), deferred_logger
|
||||
);
|
||||
} catch (const std::exception& e) {
|
||||
const std::string msg = "Compute initial well solution for " + well->name() + " initially failed. Continue with the previous rates";
|
||||
deferred_logger.warning("WELL_INITIAL_SOLVE_FAILED", msg);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <opm/material/fluidsystems/BlackOilDefaultFluidSystemIndices.hpp>
|
||||
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
#include <cassert>
|
||||
@@ -37,8 +37,7 @@ namespace Opm::WGHelpers {
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
FractionCalculator<Scalar, IndexTraits>::
|
||||
FractionCalculator(const Schedule& schedule,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
const int report_step,
|
||||
const GuideRate* guide_rate,
|
||||
@@ -46,8 +45,7 @@ FractionCalculator(const Schedule& schedule,
|
||||
const bool is_producer,
|
||||
const Phase injection_phase)
|
||||
: schedule_(schedule)
|
||||
, well_state_(well_state)
|
||||
, group_state_(group_state)
|
||||
, wgHelper_(wgHelper)
|
||||
, summary_state_(summary_state)
|
||||
, report_step_(report_step)
|
||||
, guide_rate_(guide_rate)
|
||||
@@ -129,11 +127,11 @@ guideRateSum(const Group& group,
|
||||
for (const std::string& child_group : group.groups()) {
|
||||
bool included = (child_group == always_included_child);
|
||||
if (is_producer_) {
|
||||
const auto ctrl = this->group_state_.production_control(child_group);
|
||||
const auto ctrl = this->wgHelper().groupState().production_control(child_group);
|
||||
included |= (ctrl == Group::ProductionCMode::FLD) ||
|
||||
(ctrl == Group::ProductionCMode::NONE);
|
||||
} else {
|
||||
const auto ctrl = this->group_state_.injection_control(child_group,
|
||||
const auto ctrl = this->wgHelper().groupState().injection_control(child_group,
|
||||
this->injection_phase_);
|
||||
included |= (ctrl == Group::InjectionCMode::FLD) ||
|
||||
(ctrl == Group::InjectionCMode::NONE);
|
||||
@@ -149,9 +147,9 @@ guideRateSum(const Group& group,
|
||||
for (const std::string& child_well : group.wells()) {
|
||||
bool included = (child_well == always_included_child);
|
||||
if (is_producer_) {
|
||||
included |= well_state_.isProductionGrup(child_well);
|
||||
included |= this->wgHelper().wellState().isProductionGrup(child_well);
|
||||
} else {
|
||||
included |= well_state_.isInjectionGrup(child_well);
|
||||
included |= this->wgHelper().wellState().isInjectionGrup(child_well);
|
||||
}
|
||||
if (included) {
|
||||
number_of_included_well_or_groups++;
|
||||
@@ -169,8 +167,7 @@ guideRate(const std::string& name,
|
||||
const bool always_use_potentials)
|
||||
{
|
||||
if (schedule_.hasWell(name, report_step_)) {
|
||||
return WellGroupHelpers<Scalar, IndexTraits>::getGuideRate(name, schedule_, well_state_, group_state_,
|
||||
report_step_, guide_rate_, target_);
|
||||
return this->wgHelper().getGuideRate(name, target_);
|
||||
} else {
|
||||
if (groupControlledWells(name, always_included_child) > 0) {
|
||||
if (is_producer_ && guide_rate_->has(name) && !always_use_potentials) {
|
||||
@@ -196,14 +193,9 @@ int FractionCalculator<Scalar, IndexTraits>::
|
||||
groupControlledWells(const std::string& group_name,
|
||||
const std::string& always_included_child)
|
||||
{
|
||||
return WellGroupHelpers<Scalar, IndexTraits>::groupControlledWells(schedule_,
|
||||
well_state_,
|
||||
this->group_state_,
|
||||
report_step_,
|
||||
group_name,
|
||||
always_included_child,
|
||||
is_producer_,
|
||||
injection_phase_);
|
||||
return this->wgHelper().groupControlledWells(
|
||||
group_name, always_included_child, is_producer_, injection_phase_
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
@@ -211,9 +203,7 @@ GuideRate::RateVector FractionCalculator<Scalar, IndexTraits>::
|
||||
getGroupRateVector(const std::string& group_name)
|
||||
{
|
||||
assert(is_producer_);
|
||||
return WellGroupHelpers<Scalar, IndexTraits>::getProductionGroupRateVector(this->group_state_,
|
||||
this->well_state_.phaseUsageInfo(),
|
||||
group_name);
|
||||
return this->wgHelper().getProductionGroupRateVector(group_name);
|
||||
}
|
||||
|
||||
template class FractionCalculator<double, BlackOilDefaultFluidSystemIndices>;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
namespace Opm {
|
||||
template<class Scalar> class GroupState;
|
||||
class Schedule;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelper;
|
||||
template<typename Scalar, typename IndexTraits> class WellState;
|
||||
}
|
||||
|
||||
@@ -37,9 +38,10 @@ template<typename Scalar, typename IndexTraits>
|
||||
class FractionCalculator
|
||||
{
|
||||
public:
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
|
||||
FractionCalculator(const Schedule& schedule,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
const int report_step,
|
||||
const GuideRate* guide_rate,
|
||||
@@ -66,9 +68,10 @@ private:
|
||||
int groupControlledWells(const std::string& group_name,
|
||||
const std::string& always_included_child);
|
||||
GuideRate::RateVector getGroupRateVector(const std::string& group_name);
|
||||
const WellGroupHelperType& wgHelper() const { return wgHelper_; }
|
||||
|
||||
const Schedule& schedule_;
|
||||
const WellState<Scalar, IndexTraits>& well_state_;
|
||||
const GroupState<Scalar>& group_state_;
|
||||
const WellGroupHelperType& wgHelper_;
|
||||
const SummaryState& summary_state_;
|
||||
int report_step_;
|
||||
const GuideRate* guide_rate_;
|
||||
|
||||
@@ -146,8 +146,10 @@ GasLiftSingleWell<TypeTag>::
|
||||
computeBhpAtThpLimit_(Scalar alq, bool debug_output) const
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
const auto& wgHelper = this->simulator_.problem().wellModel().wgHelper();
|
||||
auto bhp_at_thp_limit = this->well_.computeBhpAtThpLimitProdWithAlq(
|
||||
this->simulator_,
|
||||
wgHelper,
|
||||
this->summary_state_,
|
||||
alq,
|
||||
this->deferred_logger_,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
|
||||
|
||||
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
@@ -79,13 +79,9 @@ GroupEconomicLimitsChecker(const BlackoilWellModelGeneric<Scalar, IndexTraits>&
|
||||
auto phase_idx = this->phase_idx_map_[i];
|
||||
this->phase_idx_reverse_map_[phase_idx] = static_cast<int>(i);
|
||||
auto phase_pos = this->well_model_.phaseUsage().canonicalToActivePhaseIdx(phase_idx);
|
||||
Scalar production_rate = WellGroupHelpers<Scalar, IndexTraits>::sumWellSurfaceRates(this->group_,
|
||||
this->schedule_,
|
||||
this->well_state_,
|
||||
this->report_step_idx_,
|
||||
phase_pos,
|
||||
/*isInjector*/false,
|
||||
well_model_.summaryState());
|
||||
Scalar production_rate = this->well_model_.wgHelper().sumWellSurfaceRates(
|
||||
this->group_, phase_pos, /*isInjector*/false
|
||||
);
|
||||
this->production_rates_[i] = this->well_model_.comm().sum(production_rate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace Opm {
|
||||
using typename Base::SparseMatrixAdapter;
|
||||
using typename Base::FluidState;
|
||||
using typename Base::WellStateType;
|
||||
using typename Base::WellGroupHelperType;
|
||||
|
||||
using Base::has_solvent;
|
||||
using Base::has_polymer;
|
||||
@@ -90,7 +91,7 @@ namespace Opm {
|
||||
|
||||
/// updating the well state based the current control mode
|
||||
void updateWellStateWithTarget(const Simulator& simulator,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const override;
|
||||
|
||||
@@ -119,6 +120,7 @@ namespace Opm {
|
||||
/// computing the well potentials for group control
|
||||
void computeWellPotentials(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
@@ -160,6 +162,7 @@ namespace Opm {
|
||||
|
||||
std::optional<Scalar>
|
||||
computeBhpAtThpLimitProdWithAlq(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
const Scalar alq_value,
|
||||
DeferredLogger& deferred_logger,
|
||||
@@ -234,6 +237,7 @@ namespace Opm {
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
void computeWellRatesAtBhpLimit(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
@@ -244,16 +248,18 @@ namespace Opm {
|
||||
|
||||
void computeWellRatesWithBhpIterations(const Simulator& simulator,
|
||||
const Scalar& bhp,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const override;
|
||||
|
||||
std::vector<Scalar>
|
||||
computeWellPotentialWithTHP(const WellStateType& well_state,
|
||||
const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool computeWellPotentialsImplicit(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
@@ -263,16 +269,16 @@ namespace Opm {
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
bool iterateWellEqWithSwitching(const Simulator& simulator,
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control = false,
|
||||
const bool fixed_status = false) override;
|
||||
@@ -305,11 +311,13 @@ namespace Opm {
|
||||
std::optional<Scalar>
|
||||
computeBhpAtThpLimitProd(const WellStateType& well_state,
|
||||
const Simulator& ebos_simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
std::optional<Scalar>
|
||||
computeBhpAtThpLimitInj(const Simulator& ebos_simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
@@ -323,6 +331,7 @@ namespace Opm {
|
||||
// check whether the well is operable under THP limit with current reservoir condition
|
||||
void checkOperabilityUnderTHPLimit(const Simulator& ebos_simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
// updating the inflow based on the current reservoir condition
|
||||
|
||||
@@ -182,11 +182,11 @@ namespace Opm
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
updateWellStateWithTarget(const Simulator& simulator,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
Base::updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger);
|
||||
Base::updateWellStateWithTarget(simulator, wgHelper, well_state, deferred_logger);
|
||||
// scale segment rates based on the wellRates
|
||||
// and segment pressure based on bhp
|
||||
this->scaleSegmentRatesWithWellRates(this->segments_.inlets(),
|
||||
@@ -296,6 +296,7 @@ namespace Opm
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeWellPotentials(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
@@ -309,7 +310,7 @@ namespace Opm
|
||||
debug_cost_counter_ = 0;
|
||||
bool converged_implicit = false;
|
||||
if (this->param_.local_well_solver_control_switching_) {
|
||||
converged_implicit = computeWellPotentialsImplicit(simulator, well_state, well_potentials, deferred_logger);
|
||||
converged_implicit = computeWellPotentialsImplicit(simulator, wgHelper, well_potentials, deferred_logger);
|
||||
if (!converged_implicit) {
|
||||
deferred_logger.debug("Implicit potential calculations failed for well "
|
||||
+ this->name() + ", reverting to original aproach.");
|
||||
@@ -319,10 +320,10 @@ namespace Opm
|
||||
// does the well have a THP related constraint?
|
||||
const auto& summaryState = simulator.vanguard().summaryState();
|
||||
if (!Base::wellHasTHPConstraints(summaryState) || bhp_controlled_well) {
|
||||
computeWellRatesAtBhpLimit(simulator, well_potentials, deferred_logger);
|
||||
computeWellRatesAtBhpLimit(simulator, wgHelper, well_potentials, deferred_logger);
|
||||
} else {
|
||||
well_potentials = computeWellPotentialWithTHP(
|
||||
well_state, simulator, deferred_logger);
|
||||
well_state, simulator, wgHelper, deferred_logger);
|
||||
}
|
||||
}
|
||||
deferred_logger.debug("Cost in iterations of finding well potential for well "
|
||||
@@ -340,15 +341,16 @@ namespace Opm
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeWellRatesAtBhpLimit(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
if (this->well_ecl_.isInjector()) {
|
||||
const auto controls = this->well_ecl_.injectionControls(simulator.vanguard().summaryState());
|
||||
computeWellRatesWithBhpIterations(simulator, controls.bhp_limit, well_flux, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, controls.bhp_limit, wgHelper, well_flux, deferred_logger);
|
||||
} else {
|
||||
const auto controls = this->well_ecl_.productionControls(simulator.vanguard().summaryState());
|
||||
computeWellRatesWithBhpIterations(simulator, controls.bhp_limit, well_flux, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, controls.bhp_limit, wgHelper, well_flux, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,6 +406,7 @@ namespace Opm
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeWellRatesWithBhpIterations(const Simulator& simulator,
|
||||
const Scalar& bhp,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
@@ -415,9 +418,10 @@ namespace Opm
|
||||
|
||||
well_copy.debug_cost_counter_ = 0;
|
||||
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
// store a copy of the well state, we don't want to update the real well state
|
||||
WellStateType well_state_copy = simulator.problem().wellModel().wellState();
|
||||
const auto& group_state = simulator.problem().wellModel().groupState();
|
||||
WellStateType well_state_copy = wgHelper_copy.wellState();
|
||||
auto guard = wgHelper_copy.pushWellState(well_state_copy);
|
||||
auto& ws = well_state_copy.well(this->index_of_well_);
|
||||
|
||||
// Get the current controls.
|
||||
@@ -459,8 +463,8 @@ namespace Opm
|
||||
well_copy.calculateExplicitQuantities(simulator, well_state_copy, deferred_logger);
|
||||
const double dt = simulator.timeStepSize();
|
||||
// iterate to get a solution at the given bhp.
|
||||
well_copy.iterateWellEqWithControl(simulator, dt, inj_controls, prod_controls, well_state_copy, group_state,
|
||||
deferred_logger);
|
||||
well_copy.iterateWellEqWithControl(simulator, dt, inj_controls, prod_controls, wgHelper_copy,
|
||||
well_state_copy, deferred_logger);
|
||||
|
||||
// compute the potential and store in the flux vector.
|
||||
well_flux.clear();
|
||||
@@ -479,6 +483,7 @@ namespace Opm
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeWellPotentialWithTHP(const WellStateType& well_state,
|
||||
const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
std::vector<Scalar> potentials(this->number_of_phases_, 0.0);
|
||||
@@ -486,12 +491,12 @@ namespace Opm
|
||||
|
||||
const auto& well = this->well_ecl_;
|
||||
if (well.isInjector()) {
|
||||
auto bhp_at_thp_limit = computeBhpAtThpLimitInj(simulator, summary_state, deferred_logger);
|
||||
auto bhp_at_thp_limit = computeBhpAtThpLimitInj(simulator, wgHelper, summary_state, deferred_logger);
|
||||
if (bhp_at_thp_limit) {
|
||||
const auto& controls = well.injectionControls(summary_state);
|
||||
const Scalar bhp = std::min(*bhp_at_thp_limit,
|
||||
static_cast<Scalar>(controls.bhp_limit));
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, potentials, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, potentials, deferred_logger);
|
||||
deferred_logger.debug("Converged thp based potential calculation for well "
|
||||
+ this->name() + ", at bhp = " + std::to_string(bhp));
|
||||
} else {
|
||||
@@ -500,16 +505,16 @@ namespace Opm
|
||||
+ this->name() + ". Instead the bhp based value is used");
|
||||
const auto& controls = well.injectionControls(summary_state);
|
||||
const Scalar bhp = controls.bhp_limit;
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, potentials, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, potentials, deferred_logger);
|
||||
}
|
||||
} else {
|
||||
auto bhp_at_thp_limit = computeBhpAtThpLimitProd(
|
||||
well_state, simulator, summary_state, deferred_logger);
|
||||
well_state, simulator, wgHelper, summary_state, deferred_logger);
|
||||
if (bhp_at_thp_limit) {
|
||||
const auto& controls = well.productionControls(summary_state);
|
||||
const Scalar bhp = std::max(*bhp_at_thp_limit,
|
||||
static_cast<Scalar>(controls.bhp_limit));
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, potentials, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, potentials, deferred_logger);
|
||||
deferred_logger.debug("Converged thp based potential calculation for well "
|
||||
+ this->name() + ", at bhp = " + std::to_string(bhp));
|
||||
} else {
|
||||
@@ -518,7 +523,7 @@ namespace Opm
|
||||
+ this->name() + ". Instead the bhp based value is used");
|
||||
const auto& controls = well.productionControls(summary_state);
|
||||
const Scalar bhp = controls.bhp_limit;
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, potentials, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, potentials, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,7 +534,7 @@ namespace Opm
|
||||
bool
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeWellPotentialsImplicit(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
@@ -539,9 +544,10 @@ namespace Opm
|
||||
MultisegmentWell<TypeTag> well_copy(*this);
|
||||
well_copy.debug_cost_counter_ = 0;
|
||||
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
// store a copy of the well state, we don't want to update the real well state
|
||||
WellStateType well_state_copy = well_state;
|
||||
const auto& group_state = simulator.problem().wellModel().groupState();
|
||||
WellStateType well_state_copy = wgHelper_copy.wellState();
|
||||
auto guard = wgHelper_copy.pushWellState(well_state_copy);
|
||||
auto& ws = well_state_copy.well(this->index_of_well_);
|
||||
|
||||
// get current controls
|
||||
@@ -579,9 +585,13 @@ namespace Opm
|
||||
// solve equations
|
||||
bool converged = false;
|
||||
if (this->well_ecl_.isProducer()) {
|
||||
converged = well_copy.solveWellWithOperabilityCheck(simulator, dt, inj_controls, prod_controls, well_state_copy, group_state, deferred_logger);
|
||||
converged = well_copy.solveWellWithOperabilityCheck(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper_copy, well_state_copy, deferred_logger
|
||||
);
|
||||
} else {
|
||||
converged = well_copy.iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state_copy, group_state, deferred_logger);
|
||||
converged = well_copy.iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper_copy, well_state_copy, deferred_logger
|
||||
);
|
||||
}
|
||||
|
||||
// fetch potentials (sign is updated on the outside).
|
||||
@@ -1432,13 +1442,14 @@ namespace Opm
|
||||
MultisegmentWell<TypeTag>::
|
||||
checkOperabilityUnderTHPLimit(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
const auto& summaryState = simulator.vanguard().summaryState();
|
||||
const auto obtain_bhp = this->isProducer()
|
||||
? computeBhpAtThpLimitProd(
|
||||
well_state, simulator, summaryState, deferred_logger)
|
||||
: computeBhpAtThpLimitInj(simulator, summaryState, deferred_logger);
|
||||
well_state, simulator, wgHelper, summaryState, deferred_logger)
|
||||
: computeBhpAtThpLimitInj(simulator, wgHelper, summaryState, deferred_logger);
|
||||
|
||||
if (obtain_bhp) {
|
||||
this->operability_status_.can_obtain_bhp_with_thp_limit = true;
|
||||
@@ -1486,10 +1497,11 @@ namespace Opm
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
if (!this->isOperableAndSolvable() && !this->wellIsStopped()) return true;
|
||||
|
||||
const int max_iter_number = this->param_.max_inner_iter_ms_wells_;
|
||||
@@ -1610,12 +1622,13 @@ namespace Opm
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control /*false*/,
|
||||
const bool fixed_status /*false*/)
|
||||
{
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
const int max_iter_number = this->param_.max_inner_iter_ms_wells_;
|
||||
|
||||
{
|
||||
@@ -1664,10 +1677,10 @@ namespace Opm
|
||||
++its_since_last_switch;
|
||||
if (allow_switching && its_since_last_switch >= min_its_after_switch && status_switch_count < max_status_switch){
|
||||
const Scalar wqTotal = this->primary_variables_.getWQTotal().value();
|
||||
bool changed = this->updateWellControlAndStatusLocalIteration(simulator, well_state, group_state,
|
||||
inj_controls, prod_controls, wqTotal,
|
||||
deferred_logger, fixed_control,
|
||||
fixed_status);
|
||||
bool changed = this->updateWellControlAndStatusLocalIteration(
|
||||
simulator, wgHelper, inj_controls, prod_controls, wqTotal,
|
||||
well_state, deferred_logger, fixed_control, fixed_status
|
||||
);
|
||||
if (changed) {
|
||||
its_since_last_switch = 0;
|
||||
++switch_count;
|
||||
@@ -2059,11 +2072,13 @@ namespace Opm
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeBhpAtThpLimitProd(const WellStateType& well_state,
|
||||
const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
return this->MultisegmentWell<TypeTag>::computeBhpAtThpLimitProdWithAlq(
|
||||
simulator,
|
||||
wgHelper,
|
||||
summary_state,
|
||||
this->getALQ(well_state),
|
||||
deferred_logger,
|
||||
@@ -2076,6 +2091,7 @@ namespace Opm
|
||||
std::optional<typename MultisegmentWell<TypeTag>::Scalar>
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeBhpAtThpLimitProdWithAlq(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
const Scalar alq_value,
|
||||
DeferredLogger& deferred_logger,
|
||||
@@ -2109,12 +2125,12 @@ namespace Opm
|
||||
if (!iterate_if_no_solution)
|
||||
return std::nullopt;
|
||||
|
||||
auto fratesIter = [this, &simulator, &deferred_logger](const Scalar bhp) {
|
||||
auto fratesIter = [this, &simulator, &wgHelper, &deferred_logger](const Scalar bhp) {
|
||||
// Solver the well iterations to see if we are
|
||||
// able to get a solution with an update
|
||||
// solution
|
||||
std::vector<Scalar> rates(3);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, rates, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, rates, deferred_logger);
|
||||
return rates;
|
||||
};
|
||||
|
||||
@@ -2132,6 +2148,7 @@ namespace Opm
|
||||
std::optional<typename MultisegmentWell<TypeTag>::Scalar>
|
||||
MultisegmentWell<TypeTag>::
|
||||
computeBhpAtThpLimitInj(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
@@ -2159,12 +2176,12 @@ namespace Opm
|
||||
if (bhpAtLimit)
|
||||
return bhpAtLimit;
|
||||
|
||||
auto fratesIter = [this, &simulator, &deferred_logger](const Scalar bhp) {
|
||||
auto fratesIter = [this, &simulator, &wgHelper, &deferred_logger](const Scalar bhp) {
|
||||
// Solver the well iterations to see if we are
|
||||
// able to get a solution with an update
|
||||
// solution
|
||||
std::vector<Scalar> rates(3);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, rates, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, rates, deferred_logger);
|
||||
return rates;
|
||||
};
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ namespace Opm
|
||||
using typename Base::SparseMatrixAdapter;
|
||||
using typename Base::FluidState;
|
||||
using typename Base::RateVector;
|
||||
using typename Base::WellGroupHelperType;
|
||||
|
||||
using Base::has_solvent;
|
||||
using Base::has_zFraction;
|
||||
@@ -161,6 +162,7 @@ namespace Opm
|
||||
/// computing the well potentials for group control
|
||||
void computeWellPotentials(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) /* const */ override;
|
||||
|
||||
@@ -197,8 +199,8 @@ namespace Opm
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
// iterate well equations including control switching
|
||||
@@ -206,20 +208,22 @@ namespace Opm
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control = false,
|
||||
const bool fixed_status = false) override;
|
||||
|
||||
/* returns BHP */
|
||||
Scalar computeWellRatesAndBhpWithThpAlqProd(const Simulator& ebos_simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState &summary_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
std::vector<Scalar>& potentials,
|
||||
Scalar alq) const;
|
||||
|
||||
void computeWellRatesWithThpAlqProd(const Simulator& ebos_simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
std::vector<Scalar>& potentials,
|
||||
@@ -227,6 +231,7 @@ namespace Opm
|
||||
|
||||
std::optional<Scalar>
|
||||
computeBhpAtThpLimitProdWithAlq(const Simulator& ebos_simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
const Scalar alq_value,
|
||||
DeferredLogger& deferred_logger,
|
||||
@@ -309,16 +314,18 @@ namespace Opm
|
||||
|
||||
void computeWellRatesWithBhpIterations(const Simulator& ebosSimulator,
|
||||
const Scalar& bhp,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const override;
|
||||
|
||||
std::vector<Scalar>
|
||||
computeWellPotentialWithTHP(const Simulator& ebosSimulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger,
|
||||
const WellStateType& well_state) const;
|
||||
|
||||
bool computeWellPotentialsImplicit(const Simulator& ebos_simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
@@ -379,6 +386,7 @@ namespace Opm
|
||||
// check whether the well is operable under THP limit with current reservoir condition
|
||||
void checkOperabilityUnderTHPLimit(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger) override;
|
||||
|
||||
// updating the inflow based on the current reservoir condition
|
||||
@@ -445,11 +453,13 @@ namespace Opm
|
||||
std::optional<Scalar>
|
||||
computeBhpAtThpLimitProd(const WellStateType& well_state,
|
||||
const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
std::optional<Scalar>
|
||||
computeBhpAtThpLimitInj(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
|
||||
@@ -1036,11 +1036,12 @@ namespace Opm
|
||||
StandardWell<TypeTag>::
|
||||
checkOperabilityUnderTHPLimit(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
const auto& summaryState = simulator.vanguard().summaryState();
|
||||
const auto obtain_bhp = this->isProducer() ? computeBhpAtThpLimitProd(well_state, simulator, summaryState, deferred_logger)
|
||||
: computeBhpAtThpLimitInj(simulator, summaryState, deferred_logger);
|
||||
const auto obtain_bhp = this->isProducer() ? computeBhpAtThpLimitProd(well_state, simulator, wgHelper, summaryState, deferred_logger)
|
||||
: computeBhpAtThpLimitInj(simulator, wgHelper, summaryState, deferred_logger);
|
||||
|
||||
if (obtain_bhp) {
|
||||
this->operability_status_.can_obtain_bhp_with_thp_limit = true;
|
||||
@@ -1516,6 +1517,7 @@ namespace Opm
|
||||
StandardWell<TypeTag>::
|
||||
computeWellRatesWithBhpIterations(const Simulator& simulator,
|
||||
const Scalar& bhp,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
@@ -1527,8 +1529,12 @@ namespace Opm
|
||||
// iterate to get a more accurate well density
|
||||
// create a copy of the well_state to use. If the operability checking is sucessful, we use this one
|
||||
// to replace the original one
|
||||
WellStateType well_state_copy = simulator.problem().wellModel().wellState();
|
||||
const auto& group_state = simulator.problem().wellModel().groupState();
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
WellStateType well_state_copy = wgHelper_copy.wellState();
|
||||
// Ensure that wgHelper_copy uses well_state_copy as WellState for the rest of this function,
|
||||
// and the guard ensures that the original well state is restored at scope exit, i.e. at
|
||||
// the end of this function.
|
||||
auto guard = wgHelper_copy.pushWellState(well_state_copy);
|
||||
|
||||
// Get the current controls.
|
||||
const auto& summary_state = simulator.vanguard().summaryState();
|
||||
@@ -1561,7 +1567,9 @@ namespace Opm
|
||||
well_copy.computeAccumWell();
|
||||
|
||||
const double dt = simulator.timeStepSize();
|
||||
const bool converged = well_copy.iterateWellEqWithControl(simulator, dt, inj_controls, prod_controls, well_state_copy, group_state, deferred_logger);
|
||||
const bool converged = well_copy.iterateWellEqWithControl(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper_copy, well_state_copy, deferred_logger
|
||||
);
|
||||
if (!converged) {
|
||||
const std::string msg = " well " + name() + " did not get converged during well potential calculations "
|
||||
" potentials are computed based on unconverged solution";
|
||||
@@ -1579,6 +1587,7 @@ namespace Opm
|
||||
std::vector<typename StandardWell<TypeTag>::Scalar>
|
||||
StandardWell<TypeTag>::
|
||||
computeWellPotentialWithTHP(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger,
|
||||
const WellStateType& well_state) const
|
||||
{
|
||||
@@ -1588,7 +1597,7 @@ namespace Opm
|
||||
const auto& well = this->well_ecl_;
|
||||
if (well.isInjector()){
|
||||
const auto& controls = this->well_ecl_.injectionControls(summary_state);
|
||||
auto bhp_at_thp_limit = computeBhpAtThpLimitInj(simulator, summary_state, deferred_logger);
|
||||
auto bhp_at_thp_limit = computeBhpAtThpLimitInj(simulator, wgHelper, summary_state, deferred_logger);
|
||||
if (bhp_at_thp_limit) {
|
||||
const Scalar bhp = std::min(*bhp_at_thp_limit,
|
||||
static_cast<Scalar>(controls.bhp_limit));
|
||||
@@ -1602,7 +1611,7 @@ namespace Opm
|
||||
}
|
||||
} else {
|
||||
computeWellRatesWithThpAlqProd(
|
||||
simulator, summary_state,
|
||||
simulator, wgHelper, summary_state,
|
||||
deferred_logger, potentials, this->getALQ(well_state)
|
||||
);
|
||||
}
|
||||
@@ -1614,7 +1623,7 @@ namespace Opm
|
||||
bool
|
||||
StandardWell<TypeTag>::
|
||||
computeWellPotentialsImplicit(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
@@ -1624,8 +1633,12 @@ namespace Opm
|
||||
StandardWell<TypeTag> well_copy(*this);
|
||||
|
||||
// store a copy of the well state, we don't want to update the real well state
|
||||
WellStateType well_state_copy = well_state;
|
||||
const auto& group_state = simulator.problem().wellModel().groupState();
|
||||
WellStateType well_state_copy = wgHelper.wellState();
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
// Ensure that wgHelper_copy uses well_state_copy as WellState for the rest of this function,
|
||||
// and the guard ensures that the original well state is restored at scope exit, i.e. at
|
||||
// the end of this function.
|
||||
auto guard = wgHelper_copy.pushWellState(well_state_copy);
|
||||
auto& ws = well_state_copy.well(this->index_of_well_);
|
||||
|
||||
// get current controls
|
||||
@@ -1663,9 +1676,13 @@ namespace Opm
|
||||
// iterate to get a solution at the given bhp.
|
||||
bool converged = false;
|
||||
if (this->well_ecl_.isProducer()) {
|
||||
converged = well_copy.solveWellWithOperabilityCheck(simulator, dt, inj_controls, prod_controls, well_state_copy, group_state, deferred_logger);
|
||||
converged = well_copy.solveWellWithOperabilityCheck(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper_copy, well_state_copy, deferred_logger
|
||||
);
|
||||
} else {
|
||||
converged = well_copy.iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state_copy, group_state, deferred_logger);
|
||||
converged = well_copy.iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper_copy, well_state_copy, deferred_logger
|
||||
);
|
||||
}
|
||||
|
||||
// fetch potentials (sign is updated on the outside).
|
||||
@@ -1693,6 +1710,7 @@ namespace Opm
|
||||
typename StandardWell<TypeTag>::Scalar
|
||||
StandardWell<TypeTag>::
|
||||
computeWellRatesAndBhpWithThpAlqProd(const Simulator &simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState &summary_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
std::vector<Scalar>& potentials,
|
||||
@@ -1700,7 +1718,7 @@ namespace Opm
|
||||
{
|
||||
Scalar bhp;
|
||||
auto bhp_at_thp_limit = computeBhpAtThpLimitProdWithAlq(
|
||||
simulator, summary_state, alq, deferred_logger, /*iterate_if_no_solution */ true);
|
||||
simulator, wgHelper, summary_state, alq, deferred_logger, /*iterate_if_no_solution */ true);
|
||||
if (bhp_at_thp_limit) {
|
||||
const auto& controls = this->well_ecl_.productionControls(summary_state);
|
||||
bhp = std::max(*bhp_at_thp_limit,
|
||||
@@ -1722,6 +1740,7 @@ namespace Opm
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
computeWellRatesWithThpAlqProd(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
std::vector<Scalar>& potentials,
|
||||
@@ -1729,6 +1748,7 @@ namespace Opm
|
||||
{
|
||||
/*double bhp =*/
|
||||
computeWellRatesAndBhpWithThpAlqProd(simulator,
|
||||
wgHelper,
|
||||
summary_state,
|
||||
deferred_logger,
|
||||
potentials,
|
||||
@@ -1740,6 +1760,7 @@ namespace Opm
|
||||
StandardWell<TypeTag>::
|
||||
computeWellPotentials(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) // const
|
||||
{
|
||||
@@ -1755,7 +1776,9 @@ namespace Opm
|
||||
// group controlled wells with defaulted guiderates will have zero targets as
|
||||
// the potentials are used to compute the well fractions.
|
||||
if (this->param_.local_well_solver_control_switching_ && !(this->changed_to_open_this_step_ && this->wellUnderZeroRateTarget(simulator, well_state, deferred_logger))) {
|
||||
converged_implicit = computeWellPotentialsImplicit(simulator, well_state, well_potentials, deferred_logger);
|
||||
converged_implicit = computeWellPotentialsImplicit(
|
||||
simulator, wgHelper, well_potentials, deferred_logger
|
||||
);
|
||||
}
|
||||
if (!converged_implicit) {
|
||||
// does the well have a THP related constraint?
|
||||
@@ -1777,10 +1800,10 @@ namespace Opm
|
||||
bhp = std::min(ws.bhp, bhp);
|
||||
|
||||
assert(std::abs(bhp) != std::numeric_limits<Scalar>::max());
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, well_potentials, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, well_potentials, deferred_logger);
|
||||
} else {
|
||||
// the well has a THP related constraint
|
||||
well_potentials = computeWellPotentialWithTHP(simulator, deferred_logger, well_state);
|
||||
well_potentials = computeWellPotentialWithTHP(simulator, wgHelper, deferred_logger, well_state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2210,10 +2233,12 @@ namespace Opm
|
||||
StandardWell<TypeTag>::
|
||||
computeBhpAtThpLimitProd(const WellStateType& well_state,
|
||||
const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
return computeBhpAtThpLimitProdWithAlq(simulator,
|
||||
wgHelper,
|
||||
summary_state,
|
||||
this->getALQ(well_state),
|
||||
deferred_logger,
|
||||
@@ -2224,6 +2249,7 @@ namespace Opm
|
||||
std::optional<typename StandardWell<TypeTag>::Scalar>
|
||||
StandardWell<TypeTag>::
|
||||
computeBhpAtThpLimitProdWithAlq(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
const Scalar alq_value,
|
||||
DeferredLogger& deferred_logger,
|
||||
@@ -2273,12 +2299,12 @@ namespace Opm
|
||||
if (!iterate_if_no_solution)
|
||||
return std::nullopt;
|
||||
|
||||
auto fratesIter = [this, &simulator, &deferred_logger](const Scalar bhp) {
|
||||
auto fratesIter = [this, &simulator, &wgHelper, &deferred_logger](const Scalar bhp) {
|
||||
// Solver the well iterations to see if we are
|
||||
// able to get a solution with an update
|
||||
// solution
|
||||
std::vector<Scalar> rates(3);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, rates, deferred_logger);
|
||||
computeWellRatesWithBhpIterations(simulator, bhp, wgHelper, rates, deferred_logger);
|
||||
this->adaptRatesForVFP(rates);
|
||||
return rates;
|
||||
};
|
||||
@@ -2310,9 +2336,15 @@ namespace Opm
|
||||
std::optional<typename StandardWell<TypeTag>::Scalar>
|
||||
StandardWell<TypeTag>::
|
||||
computeBhpAtThpLimitInj(const Simulator& simulator,
|
||||
[[maybe_unused]] const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// Note: wgHelper parameter is currently unused in StandardWell but kept for consistency
|
||||
// with MultisegmentWell::computeBhpAtThpLimitInj which uses it in fratesIter lambda.
|
||||
// This maintains parallel API structure between well types and allows for future
|
||||
// enhancements without breaking the interface.
|
||||
|
||||
// Make the frates() function.
|
||||
auto frates = [this, &simulator, &deferred_logger](const Scalar bhp) {
|
||||
// Not solving the well equations here, which means we are
|
||||
@@ -2345,10 +2377,11 @@ namespace Opm
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
updatePrimaryVariables(simulator, well_state, deferred_logger);
|
||||
|
||||
const int max_iter = this->param_.max_inner_iter_wells_;
|
||||
@@ -2392,12 +2425,13 @@ namespace Opm
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control /*false*/,
|
||||
const bool fixed_status /*false*/)
|
||||
{
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
updatePrimaryVariables(simulator, well_state, deferred_logger);
|
||||
|
||||
const int max_iter = this->param_.max_inner_iter_wells_;
|
||||
@@ -2436,9 +2470,10 @@ namespace Opm
|
||||
its_since_last_switch++;
|
||||
if (allow_switching && its_since_last_switch >= min_its_after_switch && status_switch_count < max_status_switch){
|
||||
const Scalar wqTotal = this->primary_variables_.eval(WQTotal).value();
|
||||
changed = this->updateWellControlAndStatusLocalIteration(simulator, well_state, group_state,
|
||||
inj_controls, prod_controls, wqTotal,
|
||||
deferred_logger, fixed_control, fixed_status);
|
||||
changed = this->updateWellControlAndStatusLocalIteration(
|
||||
simulator, wgHelper, inj_controls, prod_controls, wqTotal,
|
||||
well_state, deferred_logger, fixed_control, fixed_status
|
||||
);
|
||||
if (changed){
|
||||
its_since_last_switch = 0;
|
||||
switch_count++;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <opm/material/fluidsystems/BlackOilDefaultFluidSystemIndices.hpp>
|
||||
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellInterfaceGeneric.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
@@ -38,15 +38,15 @@ template<typename Scalar, typename IndexTraits>
|
||||
std::pair<bool, Scalar>
|
||||
WellGroupConstraints<Scalar, IndexTraits>::
|
||||
checkGroupConstraintsInj(const Group& group,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const RateConvFunc& rateConverter,
|
||||
const bool check_guide_rate,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const auto& well_state = wgHelper.wellState();
|
||||
|
||||
// Translate injector type from control to Phase.
|
||||
const auto& well_controls = well_.wellEcl().injectionControls(summaryState);
|
||||
auto injectorType = well_controls.injector_type;
|
||||
@@ -77,65 +77,55 @@ checkGroupConstraintsInj(const Group& group,
|
||||
|
||||
const auto& ws = well_state.well(well_.indexOfWell());
|
||||
// Call check for the well's injection phase.
|
||||
return WellGroupHelpers<Scalar, IndexTraits>::checkGroupConstraintsInj(well_.name(),
|
||||
well_.wellEcl().groupName(),
|
||||
group,
|
||||
well_state,
|
||||
group_state,
|
||||
well_.currentStep(),
|
||||
well_.guideRate(),
|
||||
ws.surface_rates.data(),
|
||||
injectionPhase,
|
||||
efficiencyFactor,
|
||||
schedule,
|
||||
summaryState,
|
||||
resv_coeff,
|
||||
check_guide_rate,
|
||||
deferred_logger);
|
||||
return wgHelper.checkGroupConstraintsInj(
|
||||
well_.name(),
|
||||
well_.wellEcl().groupName(),
|
||||
group,
|
||||
ws.surface_rates.data(),
|
||||
injectionPhase,
|
||||
efficiencyFactor,
|
||||
resv_coeff,
|
||||
check_guide_rate,
|
||||
deferred_logger
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
std::pair<bool, Scalar>
|
||||
WellGroupConstraints<Scalar, IndexTraits>::
|
||||
checkGroupConstraintsProd(const Group& group,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const RateConvFunc& rateConverter,
|
||||
const bool check_guide_rate,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const auto& well_state = wgHelper.wellState();
|
||||
|
||||
// Make conversion factors for RESV <-> surface rates.
|
||||
std::vector<Scalar> resv_coeff(well_.phaseUsage().numActivePhases(), 1.0);
|
||||
rateConverter(0, well_.pvtRegionIdx(), group.name(), resv_coeff); // FIPNUM region 0 here, should use FIPNUM from WELSPECS.
|
||||
|
||||
const auto& ws = well_state.well(well_.indexOfWell());
|
||||
return WellGroupHelpers<Scalar, IndexTraits>::checkGroupConstraintsProd(well_.name(),
|
||||
well_.wellEcl().groupName(),
|
||||
group,
|
||||
well_state,
|
||||
group_state,
|
||||
well_.currentStep(),
|
||||
well_.guideRate(),
|
||||
ws.surface_rates.data(),
|
||||
efficiencyFactor,
|
||||
schedule,
|
||||
summaryState,
|
||||
resv_coeff,
|
||||
check_guide_rate,
|
||||
deferred_logger);
|
||||
return wgHelper.checkGroupConstraintsProd(well_.name(),
|
||||
well_.wellEcl().groupName(),
|
||||
group,
|
||||
ws.surface_rates.data(),
|
||||
efficiencyFactor,
|
||||
resv_coeff,
|
||||
check_guide_rate,
|
||||
deferred_logger
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
bool WellGroupConstraints<Scalar, IndexTraits>::
|
||||
checkGroupConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
checkGroupConstraints(const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const RateConvFunc& rateConverter,
|
||||
const bool check_guide_rate,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const auto& well = well_.wellEcl();
|
||||
@@ -156,9 +146,8 @@ checkGroupConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const Scalar efficiencyFactor = well.getEfficiencyFactor() *
|
||||
well_state[well.name()].efficiency_scaling_factor;
|
||||
const std::pair<bool, Scalar> group_constraint =
|
||||
this->checkGroupConstraintsInj(group, well_state,
|
||||
group_state, efficiencyFactor,
|
||||
schedule, summaryState,
|
||||
this->checkGroupConstraintsInj(group, wgHelper, efficiencyFactor,
|
||||
summaryState,
|
||||
rateConverter,
|
||||
check_guide_rate,
|
||||
deferred_logger);
|
||||
@@ -189,10 +178,11 @@ checkGroupConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const Scalar efficiencyFactor = well.getEfficiencyFactor() *
|
||||
well_state[well.name()].efficiency_scaling_factor;
|
||||
const std::pair<bool, Scalar> group_constraint =
|
||||
this->checkGroupConstraintsProd(group, well_state,
|
||||
group_state, efficiencyFactor,
|
||||
schedule, summaryState,
|
||||
rateConverter, check_guide_rate, deferred_logger);
|
||||
this->checkGroupConstraintsProd(group, wgHelper,
|
||||
efficiencyFactor,
|
||||
rateConverter,
|
||||
check_guide_rate,
|
||||
deferred_logger);
|
||||
// If a group constraint was broken, we set the current well control to
|
||||
// be GRUP.
|
||||
if (group_constraint.first) {
|
||||
|
||||
@@ -40,6 +40,7 @@ enum class InjectorType;
|
||||
using RegionId = int;
|
||||
class Schedule;
|
||||
class SummaryState;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelper;
|
||||
template<typename Scalar, typename IndexTraits> class WellInterfaceGeneric;
|
||||
template<typename Scalar, typename IndexTraits> class WellState;
|
||||
|
||||
@@ -54,22 +55,22 @@ public:
|
||||
const int,
|
||||
const std::optional<std::string>&,
|
||||
std::vector<Scalar>&)>;
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
using WellStateType = WellState<Scalar, IndexTraits>;
|
||||
|
||||
bool checkGroupConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
bool checkGroupConstraints(const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const RateConvFunc& rateConverter,
|
||||
const bool check_guide_rate,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
private:
|
||||
std::pair<bool, Scalar>
|
||||
checkGroupConstraintsInj(const Group& group,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const RateConvFunc& rateConverter,
|
||||
const bool check_guide_rate,
|
||||
@@ -77,11 +78,8 @@ private:
|
||||
|
||||
std::pair<bool, Scalar>
|
||||
checkGroupConstraintsProd(const Group& group,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const RateConvFunc& rateConverter,
|
||||
const bool check_guide_rate,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <opm/simulators/wells/FractionCalculator.hpp>
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
#include <opm/simulators/wells/TargetCalculator.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellInterfaceGeneric.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
@@ -358,8 +358,7 @@ template<typename Scalar, typename IndexTraits>
|
||||
std::pair<Scalar, Group::ProductionCMode> WellGroupControls<Scalar, IndexTraits>::
|
||||
getAutoChokeGroupProductionTargetRate(const std::string& name,
|
||||
const Group& group,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
@@ -368,6 +367,8 @@ getAutoChokeGroupProductionTargetRate(const std::string& name,
|
||||
const GuideRate* guideRate,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
const auto& well_state = wgHelper.wellState();
|
||||
const Group::ProductionCMode& currentGroupControl = group_state.production_control(group.name());
|
||||
if (currentGroupControl == Group::ProductionCMode::FLD ||
|
||||
currentGroupControl == Group::ProductionCMode::NONE) {
|
||||
@@ -377,7 +378,7 @@ getAutoChokeGroupProductionTargetRate(const std::string& name,
|
||||
// Produce share of parents control
|
||||
const auto& parent = schedule.getGroup(group.parent(), reportStepIdx);
|
||||
efficiencyFactor *= group.getGroupEfficiencyFactor();
|
||||
return getAutoChokeGroupProductionTargetRate(name, parent, well_state, group_state,
|
||||
return getAutoChokeGroupProductionTargetRate(name, parent, wgHelper,
|
||||
schedule, summaryState,
|
||||
resv_coeff, efficiencyFactor, reportStepIdx,
|
||||
guideRate, deferred_logger);
|
||||
@@ -398,7 +399,7 @@ getAutoChokeGroupProductionTargetRate(const std::string& name,
|
||||
// gconsale may adjust the grat target.
|
||||
// the adjusted rates is send to the targetCalculator
|
||||
Scalar gratTargetFromSales = 0.0;
|
||||
if (group_state.has_grat_sales_target(group.name()))
|
||||
if (wgHelper.groupState().has_grat_sales_target(group.name()))
|
||||
gratTargetFromSales = group_state.grat_sales_target(group.name());
|
||||
|
||||
WGHelpers::TargetCalculator<Scalar, IndexTraits> tcalc(currentGroupControl,
|
||||
@@ -410,8 +411,7 @@ getAutoChokeGroupProductionTargetRate(const std::string& name,
|
||||
group.has_gpmaint_control(currentGroupControl));
|
||||
|
||||
WGHelpers::FractionCalculator<Scalar, IndexTraits> fcalc(schedule,
|
||||
well_state,
|
||||
group_state,
|
||||
wgHelper,
|
||||
summaryState,
|
||||
reportStepIdx,
|
||||
guideRate,
|
||||
@@ -433,8 +433,7 @@ getAutoChokeGroupProductionTargetRate(const std::string& name,
|
||||
ctrl = group.productionControls(summaryState);
|
||||
|
||||
const Scalar orig_target = tcalc.groupTarget(ctrl, deferred_logger);
|
||||
const auto chain = WellGroupHelpers<Scalar, IndexTraits>::groupChainTopBot(name, group.name(),
|
||||
schedule, reportStepIdx);
|
||||
const auto chain = wgHelper.groupChainTopBot(name, group.name());
|
||||
// Because 'name' is the last of the elements, and not an ancestor, we subtract one below.
|
||||
const std::size_t num_ancestors = chain.size() - 1;
|
||||
Scalar target = orig_target;
|
||||
|
||||
@@ -40,6 +40,7 @@ enum class InjectorType;
|
||||
using RegionId = int;
|
||||
class Schedule;
|
||||
class SummaryState;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelper;
|
||||
template<typename Scalar, typename IndexTraits> class WellInterfaceGeneric;
|
||||
template<typename Scalar, typename IndexTraits> class WellState;
|
||||
|
||||
@@ -52,6 +53,7 @@ public:
|
||||
|
||||
using RateConvFunc = std::function<void(const RegionId, const int,
|
||||
const std::optional<std::string>&, std::vector<Scalar>&)>;
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
|
||||
template<class EvalWell>
|
||||
void getGroupInjectionControl(const Group& group,
|
||||
@@ -101,9 +103,8 @@ public:
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
static std::pair<Scalar, Group::ProductionCMode> getAutoChokeGroupProductionTargetRate(const std::string& name,
|
||||
const Group& parent,
|
||||
const WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const Group& group,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
Copyright 2025 Equinor ASA
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef OPM_WELLGROUPHELPER_HEADER_INCLUDED
|
||||
#define OPM_WELLGROUPHELPER_HEADER_INCLUDED
|
||||
|
||||
#include <opm/common/TimingMacros.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GPMaint.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GSatProd.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/ScheduleState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/material/fluidsystems/PhaseUsageInfo.hpp>
|
||||
#include <opm/simulators/utils/DeferredLogger.hpp>
|
||||
#include <opm/simulators/wells/GroupState.hpp>
|
||||
#include <opm/simulators/wells/VFPProdProperties.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
#include <opm/simulators/utils/ParallelCommunication.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
template <typename Scalar, typename IndexTraits>
|
||||
class WellGroupHelper
|
||||
{
|
||||
public:
|
||||
// RAII guard for temporarily setting wellstate pointer
|
||||
class WellStateGuard
|
||||
{
|
||||
public:
|
||||
WellStateGuard(WellGroupHelper& wgHelper, WellState<Scalar, IndexTraits>& well_state)
|
||||
: wgHelper_ {wgHelper}
|
||||
, previous_state_ptr_ {wgHelper_.well_state_}
|
||||
{
|
||||
// Set the new state directly
|
||||
wgHelper_.well_state_ = &well_state;
|
||||
}
|
||||
|
||||
~WellStateGuard()
|
||||
{
|
||||
// Restore the previous state
|
||||
wgHelper_.well_state_ = previous_state_ptr_;
|
||||
}
|
||||
|
||||
// Delete copy and move operations
|
||||
WellStateGuard(const WellStateGuard&) = delete;
|
||||
WellStateGuard& operator=(const WellStateGuard&) = delete;
|
||||
WellStateGuard(WellStateGuard&&) = delete;
|
||||
WellStateGuard& operator=(WellStateGuard&&) = delete;
|
||||
|
||||
private:
|
||||
WellGroupHelper& wgHelper_;
|
||||
const WellState<Scalar, IndexTraits>* previous_state_ptr_;
|
||||
};
|
||||
|
||||
// RAII guard for temporarily setting groupstate pointer
|
||||
class GroupStateGuard
|
||||
{
|
||||
public:
|
||||
GroupStateGuard(WellGroupHelper& wgHelper, GroupState<Scalar>& group_state)
|
||||
: wgHelper_ {wgHelper}
|
||||
, previous_state_ptr_ {wgHelper_.group_state_}
|
||||
{
|
||||
// Set the new state directly
|
||||
wgHelper_.group_state_ = &group_state;
|
||||
}
|
||||
|
||||
~GroupStateGuard()
|
||||
{
|
||||
// Restore the previous state
|
||||
wgHelper_.group_state_ = previous_state_ptr_;
|
||||
}
|
||||
|
||||
// Delete copy and move operations
|
||||
GroupStateGuard(const GroupStateGuard&) = delete;
|
||||
GroupStateGuard& operator=(const GroupStateGuard&) = delete;
|
||||
GroupStateGuard(GroupStateGuard&&) = delete;
|
||||
GroupStateGuard& operator=(GroupStateGuard&&) = delete;
|
||||
|
||||
private:
|
||||
WellGroupHelper& wgHelper_;
|
||||
const GroupState<Scalar>* previous_state_ptr_;
|
||||
};
|
||||
|
||||
WellGroupHelper(WellState<Scalar, IndexTraits>& well_state,
|
||||
GroupState<Scalar>& group_state,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summary_state,
|
||||
const GuideRate& guide_rate,
|
||||
const PhaseUsageInfo<IndexTraits>& phase_usage_info);
|
||||
|
||||
void accumulateGroupEfficiencyFactor(const Group& group, Scalar& factor) const;
|
||||
|
||||
std::pair<bool, Scalar> checkGroupConstraintsInj(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const Scalar* rates,
|
||||
const Phase injection_phase,
|
||||
const Scalar efficiency_factor,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
const bool check_guide_rate,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
std::pair<bool, Scalar> checkGroupConstraintsProd(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const Scalar* rates,
|
||||
const Scalar efficiency_factor,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
const bool check_guide_rate,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
std::map<std::string, Scalar> computeNetworkPressures(const Network::ExtNetwork& network,
|
||||
const VFPProdProperties<Scalar>& vfp_prod_props,
|
||||
const Parallel::Communication& comm) const;
|
||||
|
||||
Scalar getGuideRate(const std::string& name, const GuideRateModel::Target target) const;
|
||||
|
||||
GuideRate::RateVector getProductionGroupRateVector(const std::string& group_name) const;
|
||||
|
||||
Scalar getWellGroupTargetInjector(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const Scalar* rates,
|
||||
const Phase injection_phase,
|
||||
const Scalar efficiency_factor,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
Scalar getWellGroupTargetProducer(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const Scalar* rates,
|
||||
const Scalar efficiency_factor,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
GuideRate::RateVector getWellRateVector(const std::string& name) const;
|
||||
|
||||
std::vector<std::string> groupChainTopBot(const std::string& bottom, const std::string& top) const;
|
||||
|
||||
/// returns the number of wells that are actively under group control for a given group with name given
|
||||
/// by group_name
|
||||
int groupControlledWells(const std::string& group_name,
|
||||
const std::string& always_included_child,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase) const;
|
||||
|
||||
const GroupState<Scalar>& groupState() const
|
||||
{
|
||||
return *this->group_state_;
|
||||
}
|
||||
|
||||
const PhaseUsageInfo<IndexTraits>& phaseUsageInfo() const
|
||||
{
|
||||
return this->phase_usage_info_;
|
||||
}
|
||||
|
||||
GroupStateGuard pushGroupState(GroupState<Scalar>& group_state)
|
||||
{
|
||||
return GroupStateGuard(*this, group_state);
|
||||
}
|
||||
|
||||
WellStateGuard pushWellState(WellState<Scalar, IndexTraits>& well_state)
|
||||
{
|
||||
return WellStateGuard(*this, well_state);
|
||||
}
|
||||
|
||||
void setCmodeGroup(const Group& group, GroupState<Scalar>& group_state) const;
|
||||
|
||||
template <class AverageRegionalPressureType>
|
||||
void
|
||||
setRegionAveragePressureCalculator(const Group& group,
|
||||
const FieldPropsManager& fp,
|
||||
std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>&
|
||||
regional_average_pressure_calculator) const;
|
||||
|
||||
void setReportStep(int report_step)
|
||||
{
|
||||
report_step_ = report_step;
|
||||
}
|
||||
|
||||
Scalar sumSolventRates(const Group& group, const bool is_injector) const;
|
||||
|
||||
Scalar sumWellResRates(const Group& group, const int phase_pos, const bool injector) const;
|
||||
|
||||
Scalar sumWellSurfaceRates(const Group& group, const int phase_pos, const bool injector) const;
|
||||
|
||||
Scalar sumWellPhaseRates(bool res_rates,
|
||||
const Group& group,
|
||||
const int phase_pos,
|
||||
const bool injector,
|
||||
const bool network = false) const;
|
||||
|
||||
template <class RegionalValues>
|
||||
void updateGpMaintTargetForGroups(const Group& group,
|
||||
const RegionalValues& regional_values,
|
||||
const double dt,
|
||||
GroupState<Scalar>& group_state) const;
|
||||
|
||||
/// update the number of wells that are actively under group control for a given group with name given by
|
||||
/// group_name its main usage is to detect cases where there is no wells under group control
|
||||
int updateGroupControlledWells(const bool is_production_group,
|
||||
const Phase injection_phase,
|
||||
GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
void updateGroupProductionRates(const Group& group, GroupState<Scalar>& group_state) const;
|
||||
|
||||
void updateGroupTargetReduction(const Group& group,
|
||||
const bool is_injector,
|
||||
GroupState<Scalar>& group_state) const;
|
||||
|
||||
void updateNetworkLeafNodeProductionRates(GroupState<Scalar>& group_state) const;
|
||||
|
||||
void updateREINForGroups(const Group& group, bool sum_rank, GroupState<Scalar>& group_state) const;
|
||||
|
||||
void updateReservoirRatesInjectionGroups(const Group& group, GroupState<Scalar>& group_state) const;
|
||||
|
||||
void updateVREPForGroups(const Group& group, GroupState<Scalar>& group_state) const;
|
||||
|
||||
void updateState(WellState<Scalar, IndexTraits>& well_state, GroupState<Scalar>& group_state);
|
||||
|
||||
void updateSurfaceRatesInjectionGroups(const Group& group, GroupState<Scalar>& group_state) const;
|
||||
|
||||
void updateWellRates(const Group& group,
|
||||
const WellState<Scalar, IndexTraits>& well_state_nupcol,
|
||||
WellState<Scalar, IndexTraits>& well_state) const;
|
||||
|
||||
const WellState<Scalar, IndexTraits>& wellState() const
|
||||
{
|
||||
return *this->well_state_;
|
||||
}
|
||||
|
||||
void updateWellRatesFromGroupTargetScale(const Scalar scale,
|
||||
const Group& group,
|
||||
bool is_injector,
|
||||
WellState<Scalar, IndexTraits>& well_state) const;
|
||||
|
||||
/// Returns the name of the worst offending well and its fraction (i.e. violated_phase / preferred_phase)
|
||||
std::pair<std::optional<std::string>, Scalar>
|
||||
worstOffendingWell(const Group& group,
|
||||
const Group::ProductionCMode& offended_control,
|
||||
const Parallel::Communication& comm,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
private:
|
||||
std::string controlGroup_(const Group& group) const;
|
||||
|
||||
GuideRate::RateVector getGuideRateVector_(const std::vector<Scalar>& rates) const;
|
||||
|
||||
/// check if well/group bottom is a sub well/group of the group top
|
||||
bool isInGroupChainTopBot_(const std::string& bottom, const std::string& top) const;
|
||||
|
||||
int phaseToActivePhaseIdx_(const Phase phase) const;
|
||||
|
||||
Scalar satelliteInjectionRate_(const ScheduleState& sched,
|
||||
const Group& group,
|
||||
const int phase_pos,
|
||||
bool res_rates) const;
|
||||
|
||||
Scalar satelliteProductionRate_(const ScheduleState& sched,
|
||||
const Group& group,
|
||||
const GSatProd::GSatProdGroupProp::Rate rate_comp,
|
||||
bool res_rates) const;
|
||||
|
||||
std::optional<GSatProd::GSatProdGroupProp::Rate> selectRateComponent_(const int phase_pos) const;
|
||||
|
||||
int updateGroupControlledWellsRecursive_(const std::string& group_name,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase,
|
||||
GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
void updateGroupTargetReductionRecursive_(const Group& group,
|
||||
const bool is_injector,
|
||||
std::vector<Scalar>& group_target_reduction,
|
||||
GroupState<Scalar>& group_state) const;
|
||||
|
||||
const WellState<Scalar, IndexTraits>* well_state_ {nullptr};
|
||||
const GroupState<Scalar>* group_state_ {nullptr};
|
||||
const Schedule& schedule_;
|
||||
const SummaryState& summary_state_;
|
||||
const GuideRate& guide_rate_;
|
||||
int report_step_ {0};
|
||||
// NOTE: The phase usage info seems to be read-only throughout the simulation, so it should be safe
|
||||
// to store a reference to it here.
|
||||
const PhaseUsageInfo<IndexTraits>& phase_usage_info_;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Template member function implementations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// NOTE: This template member function is defined here in the header because the
|
||||
// AverageRegionalPressureType type parameter depends on derived class types that are
|
||||
// not available when WellGroupHelper.cpp is compiled. Template functions
|
||||
// must be visible at their instantiation point.
|
||||
// See WellGroupHelper.cpp for detailed rationale.
|
||||
template <typename Scalar, typename IndexTraits>
|
||||
template <class AverageRegionalPressureType>
|
||||
void
|
||||
WellGroupHelper<Scalar, IndexTraits>::setRegionAveragePressureCalculator(
|
||||
const Group& group,
|
||||
const FieldPropsManager& fp,
|
||||
std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>& regional_average_pressure_calculator)
|
||||
const
|
||||
{
|
||||
for (const std::string& groupName : group.groups()) {
|
||||
this->setRegionAveragePressureCalculator(this->schedule_.getGroup(groupName, this->report_step_),
|
||||
fp,
|
||||
regional_average_pressure_calculator);
|
||||
}
|
||||
const auto& gpm = group.gpmaint();
|
||||
if (!gpm)
|
||||
return;
|
||||
|
||||
const auto& reg = gpm->region();
|
||||
if (!reg)
|
||||
return;
|
||||
|
||||
if (regional_average_pressure_calculator.count(reg->first) == 0) {
|
||||
const std::string name = (reg->first.rfind("FIP", 0) == 0) ? reg->first : "FIP" + reg->first;
|
||||
const auto& fipnum = fp.get_int(name);
|
||||
regional_average_pressure_calculator[reg->first]
|
||||
= std::make_unique<AverageRegionalPressureType>(fipnum);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This template member function is defined in the header because the
|
||||
// RegionalValues type parameter depends on derived class types that are
|
||||
// not available when WellGroupHelper.cpp is compiled. Template functions
|
||||
// must be visible at their instantiation point.
|
||||
// See WellGroupHelper.cpp for detailed rationale.
|
||||
template <typename Scalar, typename IndexTraits>
|
||||
template <class RegionalValues>
|
||||
void
|
||||
WellGroupHelper<Scalar, IndexTraits>::updateGpMaintTargetForGroups(const Group& group,
|
||||
const RegionalValues& regional_values,
|
||||
const double dt,
|
||||
GroupState<Scalar>& group_state) const
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
for (const std::string& group_name : group.groups()) {
|
||||
const Group& group_tmp = this->schedule_.getGroup(group_name, this->report_step_);
|
||||
this->updateGpMaintTargetForGroups(group_tmp, regional_values, dt, group_state);
|
||||
}
|
||||
const auto& gpm = group.gpmaint();
|
||||
if (!gpm)
|
||||
return;
|
||||
|
||||
const auto& region = gpm->region();
|
||||
if (!region)
|
||||
return;
|
||||
|
||||
const auto [name, number] = *region;
|
||||
const Scalar error = gpm->pressure_target() - regional_values.at(name)->pressure(number);
|
||||
Scalar current_rate = 0.0;
|
||||
const auto& pu = this->phase_usage_info_;
|
||||
bool injection = true;
|
||||
Scalar sign = 1.0;
|
||||
switch (gpm->flow_target()) {
|
||||
case GPMaint::FlowTarget::RESV_PROD: {
|
||||
current_rate = -this->groupState().injection_vrep_rate(group.name());
|
||||
injection = false;
|
||||
sign = -1.0;
|
||||
break;
|
||||
}
|
||||
case GPMaint::FlowTarget::RESV_OINJ: {
|
||||
if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
|
||||
const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
|
||||
current_rate = group_state.injection_reservoir_rates(group.name())[io];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPMaint::FlowTarget::RESV_WINJ: {
|
||||
if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
|
||||
const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
|
||||
current_rate = group_state.injection_reservoir_rates(group.name())[iw];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPMaint::FlowTarget::RESV_GINJ: {
|
||||
if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
|
||||
const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
|
||||
current_rate = group_state.injection_reservoir_rates(group.name())[ig];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPMaint::FlowTarget::SURF_OINJ: {
|
||||
if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
|
||||
const auto io = pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx);
|
||||
current_rate = group_state.injection_surface_rates(group.name())[io];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPMaint::FlowTarget::SURF_WINJ: {
|
||||
if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
|
||||
const auto iw = pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx);
|
||||
current_rate = group_state.injection_surface_rates(group.name())[iw];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GPMaint::FlowTarget::SURF_GINJ: {
|
||||
if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
|
||||
const auto ig = pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx);
|
||||
current_rate = group_state.injection_surface_rates(group.name())[ig];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::invalid_argument("Invalid Flow target type in GPMAINT");
|
||||
}
|
||||
auto& gpmaint_state = group_state.gpmaint(group.name());
|
||||
// we only activate gpmaint if pressure is lower than the target regional pressure for injectors
|
||||
// (i.e. error > 0) and higher for producers.
|
||||
bool activate = (injection && error > 0) || (!injection && error < 0);
|
||||
Scalar rate = 0.0;
|
||||
if (activate) {
|
||||
rate = gpm->rate(gpmaint_state, current_rate, error, dt);
|
||||
} else {
|
||||
gpm->resetState(gpmaint_state);
|
||||
}
|
||||
group_state.update_gpmaint_target(group.name(), std::max(Scalar {0.0}, sign * rate));
|
||||
}
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,351 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 Norce.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OPM_WELLGROUPHELPERS_HEADER_INCLUDED
|
||||
#define OPM_WELLGROUPHELPERS_HEADER_INCLUDED
|
||||
|
||||
#include "opm/material/fluidsystems/PhaseUsageInfo.hpp"
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GSatProd.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/simulators/utils/ParallelCommunication.hpp>
|
||||
#include <opm/input/eclipse/Schedule/ScheduleState.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class DeferredLogger;
|
||||
class Group;
|
||||
template<class Scalar> class GroupState;
|
||||
namespace Network { class ExtNetwork; }
|
||||
class Schedule;
|
||||
template<class Scalar> class VFPProdProperties;
|
||||
template<typename Scalar, typename IndexTraits> class WellState;
|
||||
class FieldPropsManager;
|
||||
|
||||
namespace Network { class ExtNetwork; }
|
||||
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
class WellGroupHelpers
|
||||
{
|
||||
public:
|
||||
|
||||
using WellStateType = WellState<Scalar, IndexTraits>;
|
||||
|
||||
static Scalar sumWellPhaseRates(bool res_rates,
|
||||
const Opm::Group& group,
|
||||
const Opm::Schedule& schedule,
|
||||
const WellStateType& wellState,
|
||||
const SummaryState& summaryState,
|
||||
const int reportStepIdx,
|
||||
const int phasePos,
|
||||
const bool injector,
|
||||
const bool network = false);
|
||||
|
||||
static Scalar satelliteInjectionRate(const ScheduleState& sched,
|
||||
const Group& group,
|
||||
const PhaseUsageInfo<IndexTraits>& pu,
|
||||
const int phase_pos,
|
||||
bool res_rates);
|
||||
|
||||
static Scalar satelliteProductionRate(const SummaryState& summaryState,
|
||||
const ScheduleState& sched,
|
||||
const Group& group,
|
||||
const GSatProd::GSatProdGroupProp::Rate rateComp,
|
||||
bool res_rates);
|
||||
|
||||
static std::optional<GSatProd::GSatProdGroupProp::Rate>
|
||||
selectRateComponent(const PhaseUsageInfo<IndexTraits>& pu, const int phasePos);
|
||||
|
||||
static void setCmodeGroup(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const int reportStepIdx,
|
||||
GroupState<Scalar>& group_state);
|
||||
|
||||
static void accumulateGroupEfficiencyFactor(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
Scalar& factor);
|
||||
|
||||
static Scalar sumWellSurfaceRates(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const WellStateType& wellState,
|
||||
const int reportStepIdx,
|
||||
const int phasePos,
|
||||
const bool injector,
|
||||
const SummaryState& summaryState);
|
||||
|
||||
/// Returns the name of the worst offending well and its fraction (i.e. violated_phase / preferred_phase)
|
||||
static std::pair<std::optional<std::string>, Scalar>
|
||||
worstOffendingWell(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const Group::ProductionCMode& offendedControl,
|
||||
const Parallel::Communication& comm,
|
||||
const WellStateType& wellState,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
static Scalar sumWellResRates(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const WellStateType& wellState,
|
||||
const int reportStepIdx,
|
||||
const int phasePos,
|
||||
const bool injector,
|
||||
const SummaryState& summaryState);
|
||||
|
||||
static Scalar sumSolventRates(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const WellStateType& wellState,
|
||||
const int reportStepIdx,
|
||||
const bool injector);
|
||||
|
||||
static void updateGroupTargetReduction(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const bool isInjector,
|
||||
const GuideRate& guide_rate,
|
||||
const WellStateType& wellState,
|
||||
const SummaryState& summaryState,
|
||||
GroupState<Scalar>& group_state,
|
||||
std::vector<Scalar>& groupTargetReduction);
|
||||
|
||||
static void updateVREPForGroups(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellStateType& wellState,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summaryState);
|
||||
|
||||
template <class RegionalValues>
|
||||
static void updateGpMaintTargetForGroups(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const RegionalValues& regional_values,
|
||||
const int reportStepIdx,
|
||||
const double dt,
|
||||
const WellStateType& well_state,
|
||||
GroupState<Scalar>& group_state);
|
||||
|
||||
static void updateReservoirRatesInjectionGroups(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellStateType& wellState,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summaryState);
|
||||
|
||||
static void updateSurfaceRatesInjectionGroups(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellStateType& wellState,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summaryState);
|
||||
|
||||
static void updateWellRates(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellStateType& wellStateNupcol,
|
||||
WellStateType& wellState);
|
||||
|
||||
static void updateGroupProductionRates(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellStateType& wellState,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summaryState);
|
||||
|
||||
static void updateNetworkLeafNodeProductionRates(const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const WellStateType& wellState,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summaryState);
|
||||
|
||||
|
||||
static void updateWellRatesFromGroupTargetScale(const Scalar scale,
|
||||
const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
bool isInjector,
|
||||
const GroupState<Scalar>& group_state,
|
||||
WellStateType& wellState);
|
||||
|
||||
static void updateREINForGroups(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const SummaryState& st,
|
||||
const WellStateType& wellState,
|
||||
GroupState<Scalar>& group_state,
|
||||
bool sum_rank);
|
||||
|
||||
|
||||
static std::map<std::string, Scalar>
|
||||
computeNetworkPressures(const Network::ExtNetwork& network,
|
||||
const WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const VFPProdProperties<Scalar>& vfp_prod_props,
|
||||
const Schedule& schedule,
|
||||
const Parallel::Communication& comm,
|
||||
const int report_time_step);
|
||||
|
||||
static GuideRate::RateVector
|
||||
getWellRateVector(const WellStateType& well_state,
|
||||
const std::string& name);
|
||||
|
||||
static GuideRate::RateVector
|
||||
getProductionGroupRateVector(const GroupState<Scalar>& group_state,
|
||||
const PhaseUsageInfo<IndexTraits>& pu,
|
||||
const std::string& group_name);
|
||||
|
||||
static Scalar getGuideRate(const std::string& name,
|
||||
const Schedule& schedule,
|
||||
const WellStateType& wellState,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int reportStepIdx,
|
||||
const GuideRate* guideRate,
|
||||
const GuideRateModel::Target target);
|
||||
|
||||
static Scalar getGuideRateInj(const std::string& name,
|
||||
const Schedule& schedule,
|
||||
const WellStateType& wellState,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int reportStepIdx,
|
||||
const GuideRate* guideRate,
|
||||
const GuideRateModel::Target target,
|
||||
const Phase& injectionPhase);
|
||||
|
||||
/// update the number of wells that are actively under group control for a given group with name given by group_name
|
||||
/// its main usage is to detect cases where there is no wells under group control
|
||||
static int updateGroupControlledWells(const Schedule& schedule,
|
||||
const WellStateType& well_state,
|
||||
GroupState<Scalar>& group_state,
|
||||
const SummaryState& summary_state,
|
||||
const GuideRate* guideRate,
|
||||
const int report_step,
|
||||
const std::string& group_name,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase);
|
||||
|
||||
/// returns the number of wells that are actively under group control for a given group with name given by group_name
|
||||
static int groupControlledWells(const Schedule& schedule,
|
||||
const WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int report_step,
|
||||
const std::string& group_name,
|
||||
const std::string& always_included_child,
|
||||
const bool is_production_group,
|
||||
const Phase injection_phase);
|
||||
|
||||
static std::pair<bool, Scalar>
|
||||
checkGroupConstraintsInj(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const WellStateType& wellState,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int reportStepIdx,
|
||||
const GuideRate* guideRate,
|
||||
const Scalar* rates,
|
||||
Phase injectionPhase,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
const bool check_guide_rate,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
static Scalar
|
||||
getWellGroupTargetInjector(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const WellStateType& wellState,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int reportStepIdx,
|
||||
const GuideRate* guideRate,
|
||||
const Scalar* rates,
|
||||
Phase injectionPhase,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
static std::vector<std::string>
|
||||
groupChainTopBot(const std::string& bottom,
|
||||
const std::string& top,
|
||||
const Schedule& schedule,
|
||||
const int report_step);
|
||||
|
||||
|
||||
// check if well/group bottom is a sub well/group of the group top
|
||||
static bool
|
||||
isInGroupChainTopBot(const std::string& bottom,
|
||||
const std::string& top,
|
||||
const Schedule& schedule,
|
||||
const int report_step);
|
||||
|
||||
static std::string
|
||||
control_group(const Group& group,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int reportStepIdx,
|
||||
const Schedule& schedule);
|
||||
|
||||
static std::pair<bool, Scalar>
|
||||
checkGroupConstraintsProd(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const WellStateType& wellState,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int reportStepIdx,
|
||||
const GuideRate* guideRate,
|
||||
const Scalar* rates,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
const bool check_guide_rate,
|
||||
DeferredLogger& deferred_logger);
|
||||
static Scalar
|
||||
getWellGroupTargetProducer(const std::string& name,
|
||||
const std::string& parent,
|
||||
const Group& group,
|
||||
const WellStateType& wellState,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const int reportStepIdx,
|
||||
const GuideRate* guideRate,
|
||||
const Scalar* rates,
|
||||
const Scalar efficiencyFactor,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const std::vector<Scalar>& resv_coeff,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
template <class AverageRegionalPressureType>
|
||||
static void setRegionAveragePressureCalculator(const Group& group,
|
||||
const Schedule& schedule,
|
||||
const int reportStepIdx,
|
||||
const FieldPropsManager& fp,
|
||||
std::map<std::string, std::unique_ptr<AverageRegionalPressureType>>& regionalAveragePressureCalculator);
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
||||
@@ -69,6 +69,7 @@ namespace Opm
|
||||
|
||||
class WellInjectionProperties;
|
||||
class WellProductionProperties;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelper;
|
||||
|
||||
template<typename TypeTag>
|
||||
class WellInterface : public WellInterfaceIndices<GetPropType<TypeTag, Properties::FluidSystem>,
|
||||
@@ -98,6 +99,7 @@ public:
|
||||
|
||||
using WellStateType = WellState<Scalar, IndexTraits>;
|
||||
using SingleWellStateType = SingleWellState<Scalar, IndexTraits>;
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
|
||||
using RateConverterType =
|
||||
typename WellInterfaceFluidSystem<FluidSystem>::RateConverterType;
|
||||
@@ -167,8 +169,8 @@ public:
|
||||
|
||||
void assembleWellEq(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
void assembleWellEqWithoutIteration(const Simulator& simulator,
|
||||
@@ -180,8 +182,8 @@ public:
|
||||
// TODO: better name or further refactoring the function to make it more clear
|
||||
void prepareWellBeforeAssembling(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
|
||||
@@ -191,6 +193,7 @@ public:
|
||||
|
||||
virtual std::optional<Scalar>
|
||||
computeBhpAtThpLimitProdWithAlq(const Simulator& ebos_simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
const Scalar alq_value,
|
||||
DeferredLogger& deferred_logger,
|
||||
@@ -212,11 +215,12 @@ public:
|
||||
// TODO: before we decide to put more information under mutable, this function is not const
|
||||
virtual void computeWellPotentials(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_potentials,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
virtual void updateWellStateWithTarget(const Simulator& simulator,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
@@ -224,6 +228,7 @@ public:
|
||||
|
||||
virtual void computeWellRatesWithBhpIterations(const Simulator& simulator,
|
||||
const Scalar& bhp,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
std::vector<Scalar>& well_flux,
|
||||
DeferredLogger& deferred_logger) const = 0;
|
||||
|
||||
@@ -242,21 +247,22 @@ public:
|
||||
|
||||
bool updateWellStateWithTHPTargetProd(const Simulator& simulator,
|
||||
WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
enum class IndividualOrGroup { Individual, Group, Both };
|
||||
bool updateWellControl(const Simulator& simulator,
|
||||
const IndividualOrGroup iog,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) /* const */;
|
||||
|
||||
bool updateWellControlAndStatusLocalIteration(const Simulator& simulator,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const Scalar WQTotal,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control = false,
|
||||
const bool fixed_status = false);
|
||||
@@ -291,8 +297,8 @@ public:
|
||||
// Simulator is not const is because that assembleWellEq is non-const Simulator
|
||||
void wellTesting(const Simulator& simulator,
|
||||
const double simulation_time,
|
||||
/* const */ WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
WellTestState& welltest_state,
|
||||
GLiftEclWells& ecl_well_map,
|
||||
std::map<std::string, double>& open_times,
|
||||
@@ -300,6 +306,7 @@ public:
|
||||
|
||||
void checkWellOperability(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
void gliftBeginTimeStepWellTestUpdateALQ(const Simulator& simulator,
|
||||
@@ -312,10 +319,11 @@ public:
|
||||
// mostly related to BHP limit and THP limit
|
||||
void updateWellOperability(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
bool updateWellOperabilityFromWellEq(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
// update perforation water throughput based on solved water rate
|
||||
@@ -336,8 +344,8 @@ public:
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
void solveWellEquation(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
const std::vector<RateVector>& connectionRates() const
|
||||
@@ -360,8 +368,8 @@ public:
|
||||
const double dt,
|
||||
const WellInjectionControls& inj_controls,
|
||||
const WellProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control = false,
|
||||
const bool fixed_status = false) = 0;
|
||||
@@ -394,6 +402,7 @@ protected:
|
||||
// check whether the well is operable under THP limit with current reservoir condition
|
||||
virtual void checkOperabilityUnderTHPLimit(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
virtual void updateIPR(const Simulator& simulator,
|
||||
@@ -412,8 +421,8 @@ protected:
|
||||
const double dt,
|
||||
const WellInjectionControls& inj_controls,
|
||||
const WellProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
virtual void updateIPRImplicit(const Simulator& simulator,
|
||||
@@ -422,39 +431,42 @@ protected:
|
||||
|
||||
bool iterateWellEquations(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
bool solveWellWithOperabilityCheck(const Simulator& simulator,
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
std::optional<Scalar>
|
||||
estimateOperableBhp(const Simulator& ebos_simulator,
|
||||
const double dt,
|
||||
WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
bool solveWellWithBhp(const Simulator& simulator,
|
||||
const double dt,
|
||||
const Scalar bhp,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
bool solveWellWithZeroRate(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
bool solveWellForTesting(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger);
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <opm/simulators/wells/WellConstraints.hpp>
|
||||
#include <opm/simulators/wells/WellGroupConstraints.hpp>
|
||||
#include <opm/simulators/wells/WellGroupControls.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelpers.hpp>
|
||||
#include <opm/simulators/wells/WellGroupHelper.hpp>
|
||||
#include <opm/simulators/wells/WellState.hpp>
|
||||
|
||||
namespace Opm
|
||||
@@ -179,13 +179,16 @@ checkIndividualConstraints(SingleWellState<Scalar, IndexTraits>& ws,
|
||||
template<typename FluidSystem>
|
||||
bool
|
||||
WellInterfaceFluidSystem<FluidSystem>::
|
||||
checkGroupConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
checkGroupConstraints(const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const bool check_guide_rate,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
|
||||
|
||||
if (!this->wellEcl().isAvailableForGroupControl())
|
||||
return false;
|
||||
|
||||
@@ -201,18 +204,18 @@ checkGroupConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
this->rateConverter().calcInjCoeff(id, region, coeff);
|
||||
};
|
||||
|
||||
return WellGroupConstraints(*this).checkGroupConstraints(well_state, group_state,
|
||||
return WellGroupConstraints(*this).checkGroupConstraints(wgHelper,
|
||||
schedule, summaryState,
|
||||
rCoeff, check_guide_rate, deferred_logger);
|
||||
rCoeff, check_guide_rate, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
template<typename FluidSystem>
|
||||
bool
|
||||
WellInterfaceFluidSystem<FluidSystem>::
|
||||
checkConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
checkConstraints(const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const bool ind_broken = checkIndividualConstraints(well_state.well(this->index_of_well_),
|
||||
@@ -220,8 +223,8 @@ checkConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
if (ind_broken) {
|
||||
return true;
|
||||
} else {
|
||||
return checkGroupConstraints(well_state, group_state, schedule,
|
||||
summaryState, true, deferred_logger);
|
||||
return checkGroupConstraints(wgHelper, schedule,
|
||||
summaryState, true, well_state, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ class Schedule;
|
||||
struct RatioLimitCheckReport;
|
||||
template<typename Scalar, typename IndexTraits> class SingleWellState;
|
||||
template<typename Scalar, typename IndexTraits> class WellState;
|
||||
template<typename Scalar, typename IndexTraits> class WellGroupHelper;
|
||||
|
||||
template<class FluidSystem>
|
||||
class WellInterfaceFluidSystem : public WellInterfaceGeneric<typename FluidSystem::Scalar, typename FluidSystem::IndexTraitsType>
|
||||
@@ -57,6 +58,8 @@ public:
|
||||
using Scalar = typename FluidSystem::Scalar;
|
||||
using IndexTraits = typename FluidSystem::IndexTraitsType;
|
||||
using ModelParameters = typename WellInterfaceGeneric<Scalar, IndexTraits>::ModelParameters;
|
||||
using WellGroupHelperType = WellGroupHelper<Scalar, IndexTraits>;
|
||||
using WellStateType = WellState<Scalar, IndexTraits>;
|
||||
|
||||
static constexpr int Water = IndexTraits::waterPhaseIdx;
|
||||
static constexpr int Oil = IndexTraits::oilPhaseIdx;
|
||||
@@ -88,17 +91,17 @@ protected:
|
||||
const std::optional<Well::InjectionControls>& inj_controls = std::nullopt,
|
||||
const std::optional<Well::ProductionControls>& prod_controls = std::nullopt) const;
|
||||
|
||||
bool checkGroupConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
bool checkGroupConstraints(const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
const bool check_guide_rate,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
bool checkConstraints(WellState<Scalar, IndexTraits>& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
bool checkConstraints(const WellGroupHelperType& wgHelper,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& summaryState,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const;
|
||||
|
||||
std::optional<Scalar>
|
||||
|
||||
@@ -188,8 +188,8 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
updateWellControl(const Simulator& simulator,
|
||||
const IndividualOrGroup iog,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger) /* const */
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
@@ -233,10 +233,12 @@ namespace Opm
|
||||
if (iog == IndividualOrGroup::Individual) {
|
||||
changed = this->checkIndividualConstraints(ws, summaryState, deferred_logger);
|
||||
} else if (iog == IndividualOrGroup::Group) {
|
||||
changed = this->checkGroupConstraints(well_state, group_state, schedule, summaryState, true, deferred_logger);
|
||||
changed = this->checkGroupConstraints(
|
||||
wgHelper, schedule, summaryState, true, well_state, deferred_logger
|
||||
);
|
||||
} else {
|
||||
assert(iog == IndividualOrGroup::Both);
|
||||
changed = this->checkConstraints(well_state, group_state, schedule, summaryState, deferred_logger);
|
||||
changed = this->checkConstraints(wgHelper, schedule, summaryState, well_state, deferred_logger);
|
||||
}
|
||||
Parallel::Communication cc = simulator.vanguard().grid().comm();
|
||||
// checking whether control changed
|
||||
@@ -262,7 +264,7 @@ namespace Opm
|
||||
if (iterationIdx >= nupcol || this->well_control_log_.empty()) {
|
||||
this->well_control_log_.push_back(from);
|
||||
}
|
||||
updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger);
|
||||
updateWellStateWithTarget(simulator, wgHelper, well_state, deferred_logger);
|
||||
updatePrimaryVariables(simulator, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
@@ -273,11 +275,11 @@ namespace Opm
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
updateWellControlAndStatusLocalIteration(const Simulator& simulator,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const Scalar wqTotal,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger,
|
||||
const bool fixed_control,
|
||||
const bool fixed_status)
|
||||
@@ -317,7 +319,9 @@ namespace Opm
|
||||
changed = this->checkIndividualConstraints(ws, summary_state, deferred_logger, inj_controls, prod_controls);
|
||||
}
|
||||
if (hasGroupControl && this->param_.check_group_constraints_inner_well_iterations_) {
|
||||
changed = changed || this->checkGroupConstraints(well_state, group_state, schedule, summary_state, false, deferred_logger);
|
||||
changed = changed || this->checkGroupConstraints(
|
||||
wgHelper, schedule, summary_state, false, well_state, deferred_logger
|
||||
);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
@@ -327,7 +331,7 @@ namespace Opm
|
||||
ws.thp = this->getTHPConstraint(summary_state);
|
||||
} else {
|
||||
// don't call for thp since this might trigger additional local solve
|
||||
updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger);
|
||||
updateWellStateWithTarget(simulator, wgHelper, well_state, deferred_logger);
|
||||
}
|
||||
updatePrimaryVariables(simulator, well_state, deferred_logger);
|
||||
}
|
||||
@@ -382,17 +386,23 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
wellTesting(const Simulator& simulator,
|
||||
const double simulation_time,
|
||||
/* const */ WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
WellTestState& well_test_state,
|
||||
GLiftEclWells& ecl_well_map,
|
||||
std::map<std::string, double>& open_times,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
deferred_logger.info(" well " + this->name() + " is being tested");
|
||||
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
WellStateType well_state_copy = well_state;
|
||||
// Ensure that wgHelper uses well_state_copy as WellState for the well testing
|
||||
// and the guard ensures that the original well state is restored at scope exit, i.e. at
|
||||
// the end of this function.
|
||||
auto guard = wgHelper_copy.pushWellState(well_state_copy);
|
||||
auto& ws = well_state_copy.well(this->indexOfWell());
|
||||
|
||||
const auto& summary_state = simulator.vanguard().summaryState();
|
||||
@@ -430,7 +440,7 @@ namespace Opm
|
||||
// untill the number of closed completions do not increase anymore.
|
||||
while (testWell) {
|
||||
const std::size_t original_number_closed_completions = welltest_state_temp.num_closed_completions();
|
||||
bool converged = solveWellForTesting(simulator, well_state_copy, group_state, deferred_logger);
|
||||
bool converged = solveWellForTesting(simulator, wgHelper_copy, well_state_copy, deferred_logger);
|
||||
if (!converged) {
|
||||
const auto msg = fmt::format("WTEST: Well {} is not solvable (physical)", this->name());
|
||||
deferred_logger.debug(msg);
|
||||
@@ -438,7 +448,7 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
updateWellOperability(simulator, well_state_copy, deferred_logger);
|
||||
updateWellOperability(simulator, well_state_copy, wgHelper_copy, deferred_logger);
|
||||
if ( !this->isOperableAndSolvable() ) {
|
||||
const auto msg = fmt::format("WTEST: Well {} is not operable (physical)", this->name());
|
||||
deferred_logger.debug(msg);
|
||||
@@ -446,7 +456,7 @@ namespace Opm
|
||||
}
|
||||
std::vector<Scalar> potentials;
|
||||
try {
|
||||
computeWellPotentials(simulator, well_state_copy, potentials, deferred_logger);
|
||||
computeWellPotentials(simulator, well_state_copy, wgHelper_copy, potentials, deferred_logger);
|
||||
} catch (const std::exception& e) {
|
||||
const std::string msg = fmt::format("well {}: computeWellPotentials() "
|
||||
"failed during testing for re-opening: ",
|
||||
@@ -502,8 +512,8 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
iterateWellEquations(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
@@ -517,12 +527,16 @@ namespace Opm
|
||||
try {
|
||||
// TODO: the following two functions will be refactored to be one to reduce the code duplication
|
||||
if (!this->param_.local_well_solver_control_switching_){
|
||||
converged = this->iterateWellEqWithControl(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = this->iterateWellEqWithControl(simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger);
|
||||
} else {
|
||||
if (this->param_.use_implicit_ipr_ && this->well_ecl_.isProducer() && (well_state.well(this->index_of_well_).status == WellStatus::OPEN)) {
|
||||
converged = solveWellWithOperabilityCheck(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = solveWellWithOperabilityCheck(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
} else {
|
||||
converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = this->iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,8 +581,8 @@ namespace Opm
|
||||
const double dt,
|
||||
const Well::InjectionControls& inj_controls,
|
||||
const Well::ProductionControls& prod_controls,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
@@ -578,14 +592,16 @@ namespace Opm
|
||||
// if well is stopped, check if we can reopen
|
||||
if (this->wellIsStopped()) {
|
||||
this->openWell();
|
||||
auto bhp_target = estimateOperableBhp(simulator, dt, well_state, summary_state, deferred_logger);
|
||||
auto bhp_target = estimateOperableBhp(
|
||||
simulator, dt, wgHelper, summary_state, well_state, deferred_logger
|
||||
);
|
||||
if (!bhp_target.has_value()) {
|
||||
// no intersection with ipr
|
||||
const auto msg = fmt::format("estimateOperableBhp: Did not find operable BHP for well {}", this->name());
|
||||
deferred_logger.debug(msg);
|
||||
// well can't operate using explicit fractions stop the well
|
||||
// solve with zero rates
|
||||
converged = solveWellWithZeroRate(simulator, dt, well_state, deferred_logger);
|
||||
converged = solveWellWithZeroRate(simulator, dt, wgHelper, well_state, deferred_logger);
|
||||
this->stopWell();
|
||||
this->operability_status_.can_obtain_bhp_with_thp_limit = false;
|
||||
this->operability_status_.obey_thp_limit_under_bhp_limit = false;
|
||||
@@ -595,11 +611,13 @@ namespace Opm
|
||||
ws.thp = this->getTHPConstraint(summary_state);
|
||||
const Scalar bhp = std::max(bhp_target.value(),
|
||||
static_cast<Scalar>(prod_controls.bhp_limit));
|
||||
solveWellWithBhp(simulator, dt, bhp, well_state, deferred_logger);
|
||||
solveWellWithBhp(simulator, dt, bhp, wgHelper, well_state, deferred_logger);
|
||||
}
|
||||
}
|
||||
// solve well-equation
|
||||
converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = this->iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
|
||||
|
||||
const bool isThp = ws.production_cmode == Well::ProducerCMode::THP;
|
||||
@@ -619,10 +637,14 @@ namespace Opm
|
||||
if (bhp_stable.has_value() && cur_bhp - bhp_stable.value() > cur_bhp*reltol){
|
||||
const auto msg = fmt::format("Well {} converged to an unstable solution, re-solving", this->name());
|
||||
deferred_logger.debug(msg);
|
||||
solveWellWithBhp(simulator, dt, bhp_stable.value(), well_state, deferred_logger);
|
||||
solveWellWithBhp(
|
||||
simulator, dt, bhp_stable.value(), wgHelper, well_state, deferred_logger
|
||||
);
|
||||
// re-solve with hopefully good initial guess
|
||||
ws.thp = this->getTHPConstraint(summary_state);
|
||||
converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = this->iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -631,11 +653,13 @@ namespace Opm
|
||||
// Well did not converge, switch to explicit fractions
|
||||
this->operability_status_.use_vfpexplicit = true;
|
||||
this->openWell();
|
||||
auto bhp_target = estimateOperableBhp(simulator, dt, well_state, summary_state, deferred_logger);
|
||||
auto bhp_target = estimateOperableBhp(
|
||||
simulator, dt, wgHelper, summary_state, well_state, deferred_logger
|
||||
);
|
||||
if (!bhp_target.has_value()) {
|
||||
// solve with zero rate
|
||||
// well can't operate using explicit fractions stop the well
|
||||
converged = solveWellWithZeroRate(simulator, dt, well_state, deferred_logger);
|
||||
converged = solveWellWithZeroRate(simulator, dt, wgHelper, well_state, deferred_logger);
|
||||
this->stopWell();
|
||||
this->operability_status_.can_obtain_bhp_with_thp_limit = false;
|
||||
this->operability_status_.obey_thp_limit_under_bhp_limit = false;
|
||||
@@ -644,15 +668,17 @@ namespace Opm
|
||||
// solve well with the estimated target bhp (or limit)
|
||||
const Scalar bhp = std::max(bhp_target.value(),
|
||||
static_cast<Scalar>(prod_controls.bhp_limit));
|
||||
solveWellWithBhp(simulator, dt, bhp, well_state, deferred_logger);
|
||||
solveWellWithBhp(
|
||||
simulator, dt, bhp, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
ws.thp = this->getTHPConstraint(summary_state);
|
||||
const auto msg = fmt::format("Well {} did not converge, re-solving with explicit fractions for VFP caculations.", this->name());
|
||||
deferred_logger.debug(msg);
|
||||
converged = this->iterateWellEqWithSwitching(simulator, dt,
|
||||
inj_controls,
|
||||
prod_controls,
|
||||
wgHelper,
|
||||
well_state,
|
||||
group_state,
|
||||
deferred_logger);
|
||||
}
|
||||
}
|
||||
@@ -667,13 +693,16 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
estimateOperableBhp(const Simulator& simulator,
|
||||
const double dt,
|
||||
WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
const SummaryState& summary_state,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
if (!this->wellHasTHPConstraints(summary_state)) {
|
||||
const Scalar bhp_limit = WellBhpThpCalculator(*this).mostStrictBhpFromBhpLimits(summary_state);
|
||||
const bool converged = solveWellWithBhp(simulator, dt, bhp_limit, well_state, deferred_logger);
|
||||
const bool converged = solveWellWithBhp(
|
||||
simulator, dt, bhp_limit, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
if (!converged || this->wellIsStopped()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -685,7 +714,9 @@ namespace Opm
|
||||
// Get minimal bhp from vfp-curve
|
||||
Scalar bhp_min = WellBhpThpCalculator(*this).calculateMinimumBhpFromThp(well_state, this->well_ecl_, summary_state, this->getRefDensity());
|
||||
// Solve
|
||||
const bool converged = solveWellWithBhp(simulator, dt, bhp_min, well_state, deferred_logger);
|
||||
const bool converged = solveWellWithBhp(
|
||||
simulator, dt, bhp_min, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
if (!converged || this->wellIsStopped()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -701,12 +732,19 @@ namespace Opm
|
||||
solveWellWithBhp(const Simulator& simulator,
|
||||
const double dt,
|
||||
const Scalar bhp,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
// Solve a well using single bhp-constraint (but close if not operable under this)
|
||||
auto group_state = GroupState<Scalar>(); // empty group
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
// Ensure that wgHelper_copy uses the empty group state as GroupState for iterateWellEqWithSwitching()
|
||||
// and the guard ensures that the original group state is restored at scope exit, i.e. at
|
||||
// the end of this function.
|
||||
auto group_guard = wgHelper_copy.pushGroupState(group_state);
|
||||
|
||||
auto inj_controls = Well::InjectionControls(0);
|
||||
auto prod_controls = Well::ProductionControls(0);
|
||||
auto& ws = well_state.well(this->index_of_well_);
|
||||
@@ -726,7 +764,10 @@ namespace Opm
|
||||
// update well-state
|
||||
ws.bhp = bhp;
|
||||
// solve
|
||||
const bool converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger, /*fixed_control*/true);
|
||||
const bool converged = this->iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper_copy,
|
||||
well_state, deferred_logger, /*fixed_control*/true
|
||||
);
|
||||
ws.injection_cmode = cmode_inj;
|
||||
ws.production_cmode = cmode_prod;
|
||||
return converged;
|
||||
@@ -737,6 +778,7 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
solveWellWithZeroRate(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
@@ -746,9 +788,18 @@ namespace Opm
|
||||
this->stopWell();
|
||||
|
||||
auto group_state = GroupState<Scalar>(); // empty group
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
// Ensure that wgHelper_copy uses the empty group state as GroupState for iterateWellEqWithSwitching()
|
||||
// and the guard ensures that the original group state is restored at scope exit, i.e. at
|
||||
// the end of this function.
|
||||
auto group_guard = wgHelper_copy.pushGroupState(group_state);
|
||||
|
||||
auto inj_controls = Well::InjectionControls(0);
|
||||
auto prod_controls = Well::ProductionControls(0);
|
||||
const bool converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger, /*fixed_control*/true, /*fixed_status*/ true);
|
||||
const bool converged = this->iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper_copy, well_state,
|
||||
deferred_logger, /*fixed_control*/true, /*fixed_status*/ true
|
||||
);
|
||||
this->wellStatus_ = well_status_orig;
|
||||
return converged;
|
||||
}
|
||||
@@ -757,8 +808,8 @@ namespace Opm
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
solveWellForTesting(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
@@ -773,12 +824,18 @@ namespace Opm
|
||||
try {
|
||||
// TODO: the following two functions will be refactored to be one to reduce the code duplication
|
||||
if (!this->param_.local_well_solver_control_switching_){
|
||||
converged = this->iterateWellEqWithControl(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = this->iterateWellEqWithControl(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
} else {
|
||||
if (this->param_.use_implicit_ipr_ && this->well_ecl_.isProducer() && (well_state.well(this->index_of_well_).status == WellStatus::OPEN)) {
|
||||
converged = solveWellWithOperabilityCheck(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = this->solveWellWithOperabilityCheck(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
} else {
|
||||
converged = this->iterateWellEqWithSwitching(simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
|
||||
converged = this->iterateWellEqWithSwitching(
|
||||
simulator, dt, inj_controls, prod_controls, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,8 +860,8 @@ namespace Opm
|
||||
void
|
||||
WellInterface<TypeTag>::
|
||||
solveWellEquation(const Simulator& simulator,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
@@ -814,7 +871,7 @@ namespace Opm
|
||||
// keep a copy of the original well state
|
||||
const WellStateType well_state0 = well_state;
|
||||
const double dt = simulator.timeStepSize();
|
||||
bool converged = iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
|
||||
bool converged = iterateWellEquations(simulator, dt, wgHelper, well_state, deferred_logger);
|
||||
|
||||
// Newly opened wells with THP control sometimes struggles to
|
||||
// converge due to bad initial guess. Or due to the simple fact
|
||||
@@ -847,7 +904,7 @@ namespace Opm
|
||||
const std::string msg = std::string("The newly opened well ") + this->name()
|
||||
+ std::string(" with THP control did not converge during inner iterations, we try again with bhp control");
|
||||
deferred_logger.debug(msg);
|
||||
converged = this->iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
|
||||
converged = this->iterateWellEquations(simulator, dt, wgHelper, well_state, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -866,12 +923,13 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
assembleWellEq(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
prepareWellBeforeAssembling(simulator, dt, well_state, group_state, deferred_logger);
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
prepareWellBeforeAssembling(simulator, dt, wgHelper, well_state, deferred_logger);
|
||||
assembleWellEqWithoutIteration(simulator, dt, well_state, group_state, deferred_logger);
|
||||
}
|
||||
|
||||
@@ -902,15 +960,15 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
prepareWellBeforeAssembling(const Simulator& simulator,
|
||||
const double dt,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
const GroupState<Scalar>& group_state,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
const bool old_well_operable = this->operability_status_.isOperableAndSolvable();
|
||||
|
||||
if (this->param_.check_well_operability_iter_)
|
||||
checkWellOperability(simulator, well_state, deferred_logger);
|
||||
checkWellOperability(simulator, well_state, wgHelper, deferred_logger);
|
||||
|
||||
// only use inner well iterations for the first newton iterations.
|
||||
const int iteration_idx = simulator.model().newtonMethod().numIterations();
|
||||
@@ -933,7 +991,9 @@ namespace Opm
|
||||
}
|
||||
this->stopWell();
|
||||
changed_to_stopped_this_step_ = true;
|
||||
bool converged_zero_rate = this->solveWellWithZeroRate(simulator, dt, well_state, deferred_logger);
|
||||
bool converged_zero_rate = this->solveWellWithZeroRate(
|
||||
simulator, dt, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
if (this->param_.shut_unsolvable_wells_ && !converged_zero_rate ) {
|
||||
this->operability_status_.solvable = false;
|
||||
}
|
||||
@@ -941,7 +1001,9 @@ namespace Opm
|
||||
number_of_well_reopenings_++;
|
||||
return;
|
||||
}
|
||||
bool converged = this->iterateWellEquations(simulator, dt, well_state, group_state, deferred_logger);
|
||||
bool converged = this->iterateWellEquations(
|
||||
simulator, dt, wgHelper, well_state, deferred_logger
|
||||
);
|
||||
|
||||
if (converged) {
|
||||
const bool zero_target = this->wellUnderZeroRateTarget(simulator, well_state, deferred_logger);
|
||||
@@ -965,7 +1027,7 @@ namespace Opm
|
||||
auto well_state_copy = well_state;
|
||||
std::vector<Scalar> potentials;
|
||||
try {
|
||||
computeWellPotentials(simulator, well_state_copy, potentials, deferred_logger);
|
||||
computeWellPotentials(simulator, well_state_copy, wgHelper, potentials, deferred_logger);
|
||||
} catch (const std::exception& e) {
|
||||
const std::string msg = fmt::format("well {}: computeWellPotentials() failed "
|
||||
"during attempt to recompute potentials for well: ",
|
||||
@@ -1038,6 +1100,7 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
checkWellOperability(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
@@ -1049,12 +1112,12 @@ namespace Opm
|
||||
return;
|
||||
}
|
||||
|
||||
updateWellOperability(simulator, well_state, deferred_logger);
|
||||
updateWellOperability(simulator, well_state, wgHelper, deferred_logger);
|
||||
if (!this->operability_status_.isOperableAndSolvable()) {
|
||||
this->operability_status_.use_vfpexplicit = true;
|
||||
deferred_logger.debug("EXPLICIT_LOOKUP_VFP",
|
||||
"well not operable, trying with explicit vfp lookup: " + this->name());
|
||||
updateWellOperability(simulator, well_state, deferred_logger);
|
||||
updateWellOperability(simulator, well_state, wgHelper, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1127,11 +1190,12 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
updateWellOperability(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
if (this->param_.local_well_solver_control_switching_) {
|
||||
const bool success = updateWellOperabilityFromWellEq(simulator, well_state, deferred_logger);
|
||||
const bool success = updateWellOperabilityFromWellEq(simulator, wgHelper, deferred_logger);
|
||||
if (!success) {
|
||||
this->operability_status_.solvable = false;
|
||||
deferred_logger.debug("Operability check using well equations did not converge for well "
|
||||
@@ -1155,7 +1219,7 @@ namespace Opm
|
||||
}
|
||||
// we do some extra checking for wells under THP control.
|
||||
if (check_thp) {
|
||||
checkOperabilityUnderTHPLimit(simulator, well_state, deferred_logger);
|
||||
checkOperabilityUnderTHPLimit(simulator, well_state, wgHelper, deferred_logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1163,18 +1227,22 @@ namespace Opm
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
updateWellOperabilityFromWellEq(const Simulator& simulator,
|
||||
const WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
// only makes sense if we're using this parameter is true
|
||||
assert(this->param_.local_well_solver_control_switching_);
|
||||
this->operability_status_.resetOperability();
|
||||
WellStateType well_state_copy = well_state;
|
||||
const auto& group_state = simulator.problem().wellModel().groupState();
|
||||
WellGroupHelperType wgHelper_copy = wgHelper;
|
||||
WellStateType well_state_copy = wgHelper_copy.wellState();
|
||||
const double dt = simulator.timeStepSize();
|
||||
// Ensure that wgHelper uses well_state_copy as WellState for iterateWellEquations()
|
||||
// and the guard ensures that the original well state is restored at scope exit, i.e. at
|
||||
// the end of this function.
|
||||
auto guard = wgHelper_copy.pushWellState(well_state_copy);
|
||||
// equations should be converged at this stage, so only one it is needed
|
||||
bool converged = iterateWellEquations(simulator, dt, well_state_copy, group_state, deferred_logger);
|
||||
bool converged = iterateWellEquations(simulator, dt, wgHelper_copy, well_state_copy, deferred_logger);
|
||||
return converged;
|
||||
}
|
||||
|
||||
@@ -1190,11 +1258,12 @@ namespace Opm
|
||||
void
|
||||
WellInterface<TypeTag>::
|
||||
updateWellStateWithTarget(const Simulator& simulator,
|
||||
const GroupState<Scalar>& group_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
WellStateType& well_state,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
const auto& group_state = wgHelper.groupState();
|
||||
// only bhp and wellRates are used to initilize the primaryvariables for standard wells
|
||||
const auto& well = this->well_ecl_;
|
||||
const int well_index = this->index_of_well_;
|
||||
@@ -1515,7 +1584,7 @@ namespace Opm
|
||||
}
|
||||
case Well::ProducerCMode::THP:
|
||||
{
|
||||
const bool update_success = updateWellStateWithTHPTargetProd(simulator, well_state, deferred_logger);
|
||||
const bool update_success = updateWellStateWithTHPTargetProd(simulator, well_state, wgHelper, deferred_logger);
|
||||
|
||||
if (!update_success) {
|
||||
// the following is the original way of initializing well state with THP constraint
|
||||
@@ -2037,18 +2106,19 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
updateWellStateWithTHPTargetProd(const Simulator& simulator,
|
||||
WellStateType& well_state,
|
||||
const WellGroupHelperType& wgHelper,
|
||||
DeferredLogger& deferred_logger) const
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
const auto& summary_state = simulator.vanguard().summaryState();
|
||||
|
||||
auto bhp_at_thp_limit = computeBhpAtThpLimitProdWithAlq(
|
||||
simulator, summary_state, this->getALQ(well_state), deferred_logger, /*iterate_if_no_solution */ false);
|
||||
simulator, wgHelper, summary_state, this->getALQ(well_state), deferred_logger, /*iterate_if_no_solution */ false);
|
||||
if (bhp_at_thp_limit) {
|
||||
std::vector<Scalar> rates(this->number_of_phases_, 0.0);
|
||||
if (thp_update_iterations) {
|
||||
computeWellRatesWithBhpIterations(simulator, *bhp_at_thp_limit,
|
||||
rates, deferred_logger);
|
||||
wgHelper, rates, deferred_logger);
|
||||
} else {
|
||||
computeWellRatesWithBhp(simulator, *bhp_at_thp_limit,
|
||||
rates, deferred_logger);
|
||||
|
||||
Reference in new issue
Block a user