mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-10-26 23:50:08 -05:00
Include satellite injection, update satellite production
This commit is contained in:
1 parent
490f70d91c
commit
934134ec9d
4 files changed
+81
-40
No files matched your search
@@ -577,6 +577,12 @@ partiallySupported()
|
||||
{20,{true, allow_values<double> {}, "GCONPROD(COMBRATE): linearly combined rate is not used and should be defaulted (1*)"}}, // LINEAR_COMBINED_TARGET
|
||||
},
|
||||
},
|
||||
{
|
||||
"GSATINJE",
|
||||
{
|
||||
{4,{true, allow_values<double> {.0}, "GSATINJE(RESV): reservoir volume rate is not supported and should be defaulted (1*)"}}, // RESERVOIR_VOLUME_RATE
|
||||
},
|
||||
},
|
||||
{
|
||||
"GUIDERAT",
|
||||
{
|
||||
|
||||
@@ -246,7 +246,6 @@ const KeywordValidation::UnsupportedKeywords& unsupportedKeywords()
|
||||
{"GRUPRIG", {true, std::nullopt}},
|
||||
{"GRUPSLAV", {true, std::nullopt}},
|
||||
{"GRUPTARG", {true, std::nullopt}},
|
||||
{"GSATINJE", {true, std::nullopt}},
|
||||
{"GSEPCOND", {true, std::nullopt}},
|
||||
{"GSSCPTST", {true, std::nullopt}},
|
||||
{"GSWINGF", {true, std::nullopt}},
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GSatProd.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupSatelliteInjection.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GPMaint.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
@@ -94,25 +95,27 @@ namespace Opm {
|
||||
const bool injector,
|
||||
const bool network)
|
||||
{
|
||||
|
||||
// Only obtain satellite rates once (on rank 0)
|
||||
Scalar rate = 0.0;
|
||||
if (wellState.isRank0() && (group.hasSatelliteProduction() || group.hasSatelliteInjection())) {
|
||||
if (injector) {
|
||||
rate = satelliteInjectionRate(schedule[reportStepIdx], group, wellState.phaseUsageInfo(), phasePos, res_rates);
|
||||
} else {
|
||||
const auto rateComp = selectRateComponent(wellState.phaseUsageInfo(), phasePos);
|
||||
if (rateComp.has_value()) {
|
||||
rate = satelliteProductionRate(summaryState, schedule[reportStepIdx], group, *rateComp, res_rates);
|
||||
}
|
||||
}
|
||||
// Satellite groups have no sub groups/wells so we're done
|
||||
return rate;
|
||||
}
|
||||
|
||||
for (const std::string& groupName : group.groups()) {
|
||||
const auto& groupTmp = schedule.getGroup(groupName, reportStepIdx);
|
||||
const auto& gefac = groupTmp.getGroupEfficiencyFactor(network);
|
||||
rate += gefac * sumWellPhaseRates(res_rates, groupTmp, schedule, wellState, summaryState, reportStepIdx, phasePos, injector, network);
|
||||
}
|
||||
|
||||
// only sum satellite production once
|
||||
// With the current treatment, satellite production must also explicitly be accounted for in
|
||||
// updateGroupTargetReduction. A cleaner solution would perhaps be to let sumWellPhaseRates return
|
||||
// the satellite production directly (it currently returns zero for satellite groups).
|
||||
if (wellState.isRank0() && !injector) {
|
||||
const auto rateComp = selectRateComponent(wellState.phaseUsageInfo(), phasePos);
|
||||
if (rateComp.has_value()) {
|
||||
rate += satelliteProduction(summaryState, schedule[reportStepIdx], group.groups(), *rateComp);
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& wellName : group.wells()) {
|
||||
const auto well_index = wellState.index(wellName);
|
||||
if (!well_index.has_value())
|
||||
@@ -152,20 +155,58 @@ namespace Opm {
|
||||
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
Scalar WellGroupHelpers<Scalar, IndexTraits>::
|
||||
satelliteProduction(const SummaryState& summaryState,
|
||||
const ScheduleState& sched,
|
||||
const std::vector<std::string>& groups,
|
||||
const GSatProd::GSatProdGroupProp::Rate rateComp)
|
||||
satelliteInjectionRate(const ScheduleState& sched,
|
||||
const Group& group,
|
||||
const PhaseUsageInfo<IndexTraits>& pu,
|
||||
const int phase_pos,
|
||||
bool res_rates)
|
||||
{
|
||||
auto gsatProdRate = Scalar{};
|
||||
const auto& gsatProd = sched.gsatprod();
|
||||
for (const auto& group : groups) {
|
||||
if (! gsatProd.has(group)) {
|
||||
continue;
|
||||
Scalar rate = 0.0;
|
||||
if (group.hasSatelliteInjection()) {
|
||||
std::optional<Phase> ph;
|
||||
for (const auto& [bo_phase, phase] : std::array {
|
||||
std::pair( IndexTraits::waterPhaseIdx, Phase::WATER),
|
||||
std::pair( IndexTraits::oilPhaseIdx, Phase::OIL),
|
||||
std::pair( IndexTraits::gasPhaseIdx, Phase::GAS) })
|
||||
{
|
||||
if (pu.phaseIsActive(bo_phase) && (pu.canonicalToActivePhaseIdx(bo_phase) == phase_pos)) {
|
||||
ph = phase;
|
||||
}
|
||||
}
|
||||
if (ph.has_value()) {
|
||||
const auto& satellite_inj = sched.satelliteInjection(group.name());
|
||||
const auto& rate_ix = satellite_inj.rateIndex(ph.value());
|
||||
if (rate_ix.has_value()) {
|
||||
const auto& satrates = satellite_inj[*rate_ix];
|
||||
if (!res_rates) { // surface rates
|
||||
if (const auto& qs = satrates.surface(); qs.has_value()) {
|
||||
rate = *qs;
|
||||
}
|
||||
// We don't support reservoir rates for satellite injection groups
|
||||
}
|
||||
}
|
||||
}
|
||||
gsatProdRate += gsatProd.get(group, summaryState).rate[rateComp];
|
||||
}
|
||||
return gsatProdRate;
|
||||
return rate;
|
||||
}
|
||||
|
||||
template <typename Scalar, typename IndexTraits>
|
||||
Scalar WellGroupHelpers<Scalar, IndexTraits>::
|
||||
satelliteProductionRate(const SummaryState& summaryState,
|
||||
const ScheduleState& sched,
|
||||
const Group& group,
|
||||
const GSatProd::GSatProdGroupProp::Rate rateComp,
|
||||
bool res_rates)
|
||||
{
|
||||
Scalar rate = 0.0;
|
||||
if (group.hasSatelliteProduction()) {
|
||||
const auto& gsatProd = sched.gsatprod();
|
||||
if (!res_rates) {
|
||||
rate = gsatProd.get(group.name(), summaryState).rate[rateComp];
|
||||
}
|
||||
// We don't support reservoir rates for satellite production groups
|
||||
}
|
||||
return rate;
|
||||
}
|
||||
|
||||
template<typename Scalar, typename IndexTraits>
|
||||
@@ -439,18 +480,6 @@ updateGroupTargetReduction(const Group& group,
|
||||
}
|
||||
}
|
||||
|
||||
// only sum satellite production once
|
||||
// With the current treatment, satellite rates here must be added to target reduction excactly the same
|
||||
// way as in sumWellPhaseRates (see comment there)
|
||||
if (wellState.isRank0()) {
|
||||
for (int phase = 0; phase < np; phase++) {
|
||||
const auto rateComp = selectRateComponent(wellState.phaseUsageInfo(), phase);
|
||||
if (rateComp.has_value()) {
|
||||
groupTargetReduction[phase] += satelliteProduction(summaryState, schedule[reportStepIdx], group.groups(), *rateComp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& wellName : group.wells()) {
|
||||
const auto& wellTmp = schedule.getWell(wellName, reportStepIdx);
|
||||
|
||||
|
||||
@@ -63,10 +63,17 @@ public:
|
||||
const bool injector,
|
||||
const bool network = false);
|
||||
|
||||
static Scalar satelliteProduction(const SummaryState& summaryState,
|
||||
const ScheduleState& sched,
|
||||
const std::vector<std::string>& groups,
|
||||
const GSatProd::GSatProdGroupProp::Rate rateComp);
|
||||
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);
|
||||
|
||||
Reference in new issue
Block a user