Support GCONSUMP on multiple levels in the group hierarchy

This commit is contained in:
Vegard Kippe 2024-11-14 12:43:50 +01:00
parent 99f3226926
commit 74fa148cd7
4 changed files with 91 additions and 16 deletions

View File

@ -489,14 +489,12 @@ checkGconsaleLimits(const Group& group,
Scalar production_target = gconsale.sales_target + injection_rate;
// add import rate and subtract consumption rate for group for gas
if (schedule()[reportStepIdx].gconsump().has(group.name())) {
const auto& gconsump = schedule()[reportStepIdx].gconsump().get(group.name(), summaryState_);
if (phase_usage_.phase_used[BlackoilPhases::Vapour]) {
sales_rate += gconsump.import_rate;
sales_rate -= gconsump.consumption_rate;
production_target -= gconsump.import_rate;
production_target += gconsump.consumption_rate;
}
if (phase_usage_.phase_used[BlackoilPhases::Vapour]) {
const auto& [consumption_rate, import_rate] = this->groupState().gconsump_rates(group.name());
sales_rate += import_rate;
sales_rate -= consumption_rate;
production_target -= import_rate;
production_target += consumption_rate;
}
if (sales_rate > gconsale.max_sales_rate) {
@ -1192,6 +1190,11 @@ updateAndCommunicateGroupData(const int reportStepIdx,
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
const int nupcol = schedule()[reportStepIdx].nupcol();
// Update accumulated group consumption/import rates for current report step
if(iterationIdx == 0) {
this->groupState().update_gconsump(schedule(), reportStepIdx, this->summaryState_);
}
// This builds some necessary lookup structures, so it must be called
// before we copy to well_state_nupcol_.
this->wellState().updateGlobalIsGrup(comm_);
@ -1200,6 +1203,7 @@ updateAndCommunicateGroupData(const int reportStepIdx,
this->updateNupcolWGState();
}
auto& well_state = this->wellState();
const auto& well_state_nupcol = this->nupcolWellState();
// the group target reduction rates needs to be update since wells may have switched to/from GRUP control

View File

@ -24,9 +24,11 @@
#include <iterator>
#include <opm/json/JsonObject.hpp>
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
#include <opm/input/eclipse/Schedule/Schedule.hpp>
#include <opm/simulators/wells/GroupState.hpp>
namespace Opm {
template<class Scalar>
@ -50,6 +52,7 @@ GroupState<Scalar> GroupState<Scalar>::serializationTestObject()
result.m_gpmaint_target = {{"test11", 15.0}};
result.injection_controls = {{{Phase::FOAM, "test12"}, Group::InjectionCMode::REIN}};
result.gpmaint_state.add("foo", GPMaint::State::serializationTestObject());
result.m_gconsump_rates = {{"testA", {0.2, 0.1}}};
return result;
}
@ -67,7 +70,8 @@ bool GroupState<Scalar>::operator==(const GroupState& other) const
this->inj_surface_rates == other.inj_surface_rates &&
this->m_grat_sales_target == other.m_grat_sales_target &&
this->injection_controls == other.injection_controls &&
this->gpmaint_state == other.gpmaint_state;
this->gpmaint_state == other.gpmaint_state &&
this->m_gconsump_rates == other.m_gconsump_rates;
}
//-------------------------------------------------------------------------
@ -419,6 +423,63 @@ has_gpmaint_target(const std::string& gname) const
return (this->m_gpmaint_target.count(gname) > 0);
}
template<class Scalar>
void GroupState<Scalar>::
update_gconsump(const Schedule& schedule, const int report_step, const SummaryState& summary_state) {
this->m_gconsump_rates.clear();
const auto& sched_state = schedule[report_step];
const auto& gconsump = sched_state.gconsump();
auto gcr_recursive =
[this, &sched_state, &gconsump, &summary_state](auto self,
const std::string& group_name,
std::pair<Scalar, Scalar>& rates,
const double parent_gefac = 1.0) -> bool
{
// If group already has been computed, update parent rates and return true
const auto it = this->m_gconsump_rates.find(group_name);
if (it != this->m_gconsump_rates.end()) {
rates.first += static_cast<Scalar>(it->second.first * parent_gefac);
rates.second += static_cast<Scalar>(it->second.second * parent_gefac);
return true;
}
// Accumulate from sub-groups and keep track of any updates in 'has_values'
bool has_values = false;
if (sched_state.groups.has(group_name)) {
for (const auto& child_gname : sched_state.groups(group_name).groups()) {
const auto gefac = sched_state.groups(child_gname).getGroupEfficiencyFactor();
has_values = has_values || self(self, child_gname, rates, gefac);
}
}
// Add consumption/import rates at current level
if (gconsump.has(group_name)) {
const auto& group_gc = gconsump.get(group_name, summary_state);
rates.first += static_cast<Scalar>(group_gc.consumption_rate);
rates.second += static_cast<Scalar>(group_gc.import_rate);
has_values = true;
}
// Update map if values are set
if (has_values) this->m_gconsump_rates[group_name] = rates;
return has_values;
};
std::pair<Scalar, Scalar> rates = {0.0, 0.0};
gcr_recursive(gcr_recursive, "FIELD", rates);
}
template<class Scalar>
const std::pair<Scalar, Scalar>& GroupState<Scalar>::
gconsump_rates(const std::string& gname) const {
const auto it = this->m_gconsump_rates.find(gname);
if (it != this->m_gconsump_rates.end()) {
return it->second;
}
return zero_pair;
}
template class GroupState<double>;
#if FLOW_INSTANTIATE_FLOAT

View File

@ -31,9 +31,14 @@
#include <map>
#include <vector>
#include <utility>
namespace Opm {
class GConSump;
class Schedule;
class SummaryState;
template<class Scalar>
class GroupState {
public:
@ -95,6 +100,10 @@ public:
void injection_control(const std::string& gname, Phase phase, Group::InjectionCMode cmode);
Group::InjectionCMode injection_control(const std::string& gname, Phase phase) const;
void update_gconsump(const Schedule& schedule, const int report_step, const SummaryState& summary_state);
const std::pair<Scalar, Scalar>& gconsump_rates(const std::string& gname) const;
std::size_t data_size() const;
std::size_t collect(Scalar* data) const;
std::size_t distribute(const Scalar* data);
@ -189,6 +198,7 @@ public:
serializer(m_gpmaint_target);
serializer(injection_controls);
serializer(gpmaint_state);
serializer(m_gconsump_rates);
}
private:
@ -207,6 +217,8 @@ private:
std::map<std::pair<Phase, std::string>, Group::InjectionCMode> injection_controls;
WellContainer<GPMaint::State> gpmaint_state;
std::map<std::string, std::pair<Scalar, Scalar>> m_gconsump_rates; // Pair with {consumption_rate, import_rate} for each group
static constexpr std::pair<Scalar, Scalar> zero_pair = {0.0, 0.0};
};
}

View File

@ -700,12 +700,10 @@ updateREINForGroups(const Group& group,
// add import rate and subtract consumption rate for group for gas
if (sum_rank) {
if (schedule[reportStepIdx].gconsump().has(group.name())) {
const auto& gconsump = schedule[reportStepIdx].gconsump().get(group.name(), st);
if (pu.phase_used[BlackoilPhases::Vapour]) {
rein[pu.phase_pos[BlackoilPhases::Vapour]] += gconsump.import_rate;
rein[pu.phase_pos[BlackoilPhases::Vapour]] -= gconsump.consumption_rate;
}
if (pu.phase_used[BlackoilPhases::Vapour]) {
const auto& [consumption_rate, import_rate] = group_state.gconsump_rates(group.name());
rein[pu.phase_pos[BlackoilPhases::Vapour]] += import_rate;
rein[pu.phase_pos[BlackoilPhases::Vapour]] -= consumption_rate;
}
}