Merge pull request #3657 from hakonhagland/gecon2
Implement support for GECON keyword
This commit is contained in:
@@ -174,6 +174,7 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/input/eclipse/Schedule/Group/GuideRateModel.cpp
|
||||
src/opm/input/eclipse/Schedule/Group/GConSale.cpp
|
||||
src/opm/input/eclipse/Schedule/Group/GConSump.cpp
|
||||
src/opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.cpp
|
||||
src/opm/input/eclipse/Schedule/Group/GTNode.cpp
|
||||
src/opm/input/eclipse/Schedule/KeywordHandlers.cpp
|
||||
src/opm/input/eclipse/Schedule/MessageLimits.cpp
|
||||
@@ -1274,6 +1275,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/input/eclipse/Schedule/Group/GuideRate.hpp
|
||||
opm/input/eclipse/Schedule/Group/GConSale.hpp
|
||||
opm/input/eclipse/Schedule/Group/GConSump.hpp
|
||||
opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp
|
||||
opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp
|
||||
opm/input/eclipse/Schedule/Group/GuideRateModel.hpp
|
||||
opm/input/eclipse/Schedule/MessageLimits.hpp
|
||||
|
||||
146
opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp
Normal file
146
opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright 2023 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 GROUP_ECON_PRODUCTION_LIMITS_H
|
||||
#define GROUP_ECON_PRODUCTION_LIMITS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include <opm/input/eclipse/Deck/UDAValue.hpp>
|
||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/common/utility/Serializer.hpp>
|
||||
#include <opm/common/utility/MemPacker.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class DeckRecord;
|
||||
|
||||
class GroupEconProductionLimits {
|
||||
public:
|
||||
enum class EconWorkover {
|
||||
NONE = 0,
|
||||
CON = 1, // CON
|
||||
CONP = 2, // +CON
|
||||
WELL = 3,
|
||||
PLUG = 4,
|
||||
ALL = 5
|
||||
};
|
||||
|
||||
class GEconGroup {
|
||||
public:
|
||||
GEconGroup() = default;
|
||||
GEconGroup(const DeckRecord &record, const int report_step);
|
||||
bool endRun() const;
|
||||
UDAValue minOilRate() const;
|
||||
UDAValue minGasRate() const;
|
||||
UDAValue maxWaterCut() const;
|
||||
UDAValue maxGasOilRatio() const;
|
||||
UDAValue maxWaterGasRatio() const;
|
||||
int maxOpenWells() const;
|
||||
bool operator==(const GEconGroup& other) const;
|
||||
int reportStep() const;
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
serializer(m_min_oil_rate);
|
||||
serializer(m_min_gas_rate);
|
||||
serializer(m_max_water_cut);
|
||||
serializer(m_max_gas_oil_ratio);
|
||||
serializer(m_max_water_gas_ratio);
|
||||
serializer(m_workover);
|
||||
serializer(m_end_run);
|
||||
serializer(m_max_open_wells);
|
||||
}
|
||||
static GEconGroup serializationTestObject();
|
||||
EconWorkover workover() const;
|
||||
|
||||
private:
|
||||
UDAValue m_min_oil_rate;
|
||||
UDAValue m_min_gas_rate;
|
||||
UDAValue m_max_water_cut;
|
||||
UDAValue m_max_gas_oil_ratio;
|
||||
UDAValue m_max_water_gas_ratio;
|
||||
EconWorkover m_workover;
|
||||
bool m_end_run;
|
||||
int m_max_open_wells;
|
||||
int m_report_step; // Used to get UDQ undefined value
|
||||
};
|
||||
|
||||
class GEconGroupProp {
|
||||
/* Same as GEconGroup but with UDA values realized at given report step*/
|
||||
public:
|
||||
GEconGroupProp(const double min_oil_rate,
|
||||
const double min_gas_rate,
|
||||
const double max_water_cut,
|
||||
const double max_gas_oil_ratio,
|
||||
const double max_water_gas_ratio,
|
||||
EconWorkover workover,
|
||||
bool end_run,
|
||||
int max_open_wells);
|
||||
bool endRun() const;
|
||||
std::optional<double> minOilRate() const;
|
||||
std::optional<double> minGasRate() const;
|
||||
std::optional<double> maxWaterCut() const;
|
||||
std::optional<double> maxGasOilRatio() const;
|
||||
std::optional<double> maxWaterGasRatio() const;
|
||||
int maxOpenWells() const;
|
||||
EconWorkover workover() const;
|
||||
|
||||
private:
|
||||
std::optional<double> m_min_oil_rate;
|
||||
std::optional<double> m_min_gas_rate;
|
||||
std::optional<double> m_max_water_cut;
|
||||
std::optional<double> m_max_gas_oil_ratio;
|
||||
std::optional<double> m_max_water_gas_ratio;
|
||||
EconWorkover m_workover;
|
||||
bool m_end_run;
|
||||
int m_max_open_wells;
|
||||
};
|
||||
|
||||
GroupEconProductionLimits() = default;
|
||||
//explicit GroupEconProductionLimits(const RestartIO::RstWell& rstWell);
|
||||
|
||||
void add_group(const int report_step, const std::string &group_name, const DeckRecord &record);
|
||||
static EconWorkover econWorkoverFromString(const std::string& string_value);
|
||||
const GEconGroup& get_group(const std::string& gname) const;
|
||||
GEconGroupProp get_group_prop(
|
||||
const Schedule &schedule, const SummaryState &st, const std::string& gname) const;
|
||||
bool has_group(const std::string& gname) const;
|
||||
bool operator==(const GroupEconProductionLimits& other) const;
|
||||
bool operator!=(const GroupEconProductionLimits& other) const;
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer) const
|
||||
{
|
||||
serializer(m_groups);
|
||||
}
|
||||
static GroupEconProductionLimits serializationTestObject();
|
||||
size_t size() const;
|
||||
|
||||
private:
|
||||
std::map<std::string, GEconGroup> m_groups;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
|
||||
#endif
|
||||
@@ -350,6 +350,7 @@ namespace Opm
|
||||
this->template pack_unpack<WellTestConfig>(serializer);
|
||||
this->template pack_unpack<GConSale>(serializer);
|
||||
this->template pack_unpack<GConSump>(serializer);
|
||||
this->template pack_unpack<GroupEconProductionLimits>(serializer);
|
||||
this->template pack_unpack<WListManager>(serializer);
|
||||
this->template pack_unpack<Network::ExtNetwork>(serializer);
|
||||
this->template pack_unpack<Network::Balance>(serializer);
|
||||
@@ -697,6 +698,7 @@ namespace Opm
|
||||
void handleGCONPROD (HandlerContext&);
|
||||
void handleGCONSALE (HandlerContext&);
|
||||
void handleGCONSUMP (HandlerContext&);
|
||||
void handleGECON (HandlerContext&);
|
||||
void handleGEFAC (HandlerContext&);
|
||||
void handleGEOKeyword(HandlerContext&);
|
||||
void handleGLIFTOPT (HandlerContext&);
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace Opm {
|
||||
class GasLiftOpt;
|
||||
class GConSale;
|
||||
class GConSump;
|
||||
class GroupEconProductionLimits;
|
||||
class GroupOrder;
|
||||
class GuideRateConfig;
|
||||
class NameOrder;
|
||||
@@ -359,6 +360,7 @@ namespace Opm {
|
||||
|
||||
ptr_member<GConSale> gconsale;
|
||||
ptr_member<GConSump> gconsump;
|
||||
ptr_member<GroupEconProductionLimits> gecon;
|
||||
ptr_member<GuideRateConfig> guide_rate;
|
||||
|
||||
ptr_member<WListManager> wlist_manager;
|
||||
@@ -391,6 +393,8 @@ namespace Opm {
|
||||
return this->gconsale;
|
||||
else if constexpr ( std::is_same_v<T, GConSump> )
|
||||
return this->gconsump;
|
||||
else if constexpr ( std::is_same_v<T, GroupEconProductionLimits> )
|
||||
return this->gecon;
|
||||
else if constexpr ( std::is_same_v<T, WListManager> )
|
||||
return this->wlist_manager;
|
||||
else if constexpr ( std::is_same_v<T, Network::ExtNetwork> )
|
||||
@@ -431,6 +435,8 @@ namespace Opm {
|
||||
return this->gconsale;
|
||||
else if constexpr ( std::is_same_v<T, GConSump> )
|
||||
return this->gconsump;
|
||||
else if constexpr ( std::is_same_v<T, GroupEconProductionLimits> )
|
||||
return this->gecon;
|
||||
else if constexpr ( std::is_same_v<T, WListManager> )
|
||||
return this->wlist_manager;
|
||||
else if constexpr ( std::is_same_v<T, Network::ExtNetwork> )
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
Copyright 2023 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/>.
|
||||
*/
|
||||
|
||||
#include <opm/input/eclipse/Deck/UDAValue.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/input/eclipse/Schedule/UDQ/UDQConfig.hpp>
|
||||
#include "../eval_uda.hpp"
|
||||
|
||||
namespace {
|
||||
template <class T>
|
||||
std::optional<T> get_positive_value(T value)
|
||||
{
|
||||
std::optional<T> result;
|
||||
if (value > 0.0) {
|
||||
result = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Opm {
|
||||
|
||||
void GroupEconProductionLimits::add_group(
|
||||
const int report_step, const std::string &group_name, const DeckRecord& record)
|
||||
{
|
||||
// NOTE: report_step is needed when retrieving UDA values later.
|
||||
// To get the correct UDQ config for the UDQ-undefined value
|
||||
auto group = GEconGroup {record, report_step};
|
||||
this->m_groups.insert_or_assign(group_name, group);
|
||||
}
|
||||
|
||||
bool GroupEconProductionLimits::has_group(const std::string& gname) const {
|
||||
const auto iter = this->m_groups.find(gname);
|
||||
return (iter != this->m_groups.end());
|
||||
}
|
||||
|
||||
const GroupEconProductionLimits::GEconGroup& GroupEconProductionLimits::get_group(
|
||||
const std::string& name) const
|
||||
{
|
||||
auto it = this->m_groups.find(name);
|
||||
if (it == this->m_groups.end())
|
||||
throw std::invalid_argument("GroupEconProdctionLimits object does not contain group '" + name + "'.");
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
GroupEconProductionLimits::GEconGroupProp GroupEconProductionLimits::get_group_prop(
|
||||
const Schedule &schedule, const SummaryState &st, const std::string& name) const
|
||||
{
|
||||
const GEconGroup& group0 = this->get_group(name);
|
||||
auto udq_undefined = schedule.getUDQConfig(group0.reportStep()).params().undefinedValue();
|
||||
auto min_oil_rate = UDA::eval_group_uda(group0.minOilRate(), name, st, udq_undefined);
|
||||
auto min_gas_rate = UDA::eval_group_uda(group0.minGasRate(), name, st, udq_undefined);
|
||||
auto max_water_cut = UDA::eval_group_uda(group0.maxWaterCut(), name, st, udq_undefined);
|
||||
auto max_gas_oil_ratio = UDA::eval_group_uda(group0.maxGasOilRatio(), name, st, udq_undefined);
|
||||
auto max_water_gas_ratio = UDA::eval_group_uda(group0.maxWaterGasRatio(), name, st, udq_undefined);
|
||||
|
||||
return GEconGroupProp {
|
||||
min_oil_rate,
|
||||
min_gas_rate,
|
||||
max_water_cut,
|
||||
max_gas_oil_ratio,
|
||||
max_water_gas_ratio,
|
||||
group0.workover(),
|
||||
group0.endRun(),
|
||||
group0.maxOpenWells()
|
||||
};
|
||||
}
|
||||
|
||||
bool GroupEconProductionLimits::operator==(const GroupEconProductionLimits& other) const
|
||||
{
|
||||
return this->m_groups == other.m_groups;
|
||||
}
|
||||
|
||||
bool GroupEconProductionLimits::operator!=(const GroupEconProductionLimits& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GroupEconProductionLimits GroupEconProductionLimits::serializationTestObject()
|
||||
{
|
||||
GroupEconProductionLimits gecon;
|
||||
gecon.m_groups["P1"] = {GEconGroup::serializationTestObject()};
|
||||
return gecon;
|
||||
}
|
||||
|
||||
size_t GroupEconProductionLimits::size() const {
|
||||
return this->m_groups.size();
|
||||
}
|
||||
|
||||
/* Methods for inner class GEconGroup */
|
||||
|
||||
GroupEconProductionLimits::GEconGroup::GEconGroup(const DeckRecord &record, const int report_step)
|
||||
: m_min_oil_rate{record.getItem("MIN_OIL_RATE").get<UDAValue>(0)}
|
||||
, m_min_gas_rate{record.getItem("MIN_GAS_RATE").get<UDAValue>(0)}
|
||||
, m_max_water_cut{record.getItem("MAX_WCT").get<UDAValue>(0)}
|
||||
, m_max_gas_oil_ratio{record.getItem("MAX_GOR").get<UDAValue>(0)}
|
||||
, m_max_water_gas_ratio{record.getItem("MAX_WATER_GAS_RATIO").get<UDAValue>(0)}
|
||||
, m_workover{econWorkoverFromString(record.getItem("WORKOVER").getTrimmedString(0))}
|
||||
, m_end_run{false}
|
||||
, m_max_open_wells{record.getItem("MAX_OPEN_WELLS").get<int>(0)}
|
||||
, m_report_step{report_step}
|
||||
{
|
||||
if (record.getItem("END_RUN").hasValue(0)) {
|
||||
std::string string_endrun = record.getItem("END_RUN").getTrimmedString(0);
|
||||
if (string_endrun == "YES") {
|
||||
m_end_run = true;
|
||||
} else if (string_endrun != "NO") {
|
||||
throw std::invalid_argument("Unknown input: " + string_endrun + " for END_RUN in GECON");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupEconProductionLimits::EconWorkover
|
||||
GroupEconProductionLimits::econWorkoverFromString(const std::string& string_value)
|
||||
{
|
||||
if (string_value == "NONE")
|
||||
return EconWorkover::NONE;
|
||||
else if (string_value == "CON")
|
||||
return EconWorkover::CON;
|
||||
else if (string_value == "+CON")
|
||||
return EconWorkover::CONP;
|
||||
else if (string_value == "WELL")
|
||||
return EconWorkover::WELL;
|
||||
else if (string_value == "PLUG")
|
||||
return EconWorkover::PLUG;
|
||||
else if (string_value == "ALL")
|
||||
return EconWorkover::ALL;
|
||||
else
|
||||
throw std::invalid_argument("GroupEconProductionLimits: Unknown enum string value '"
|
||||
+ string_value + "' for EconWorkover enum");
|
||||
}
|
||||
|
||||
bool GroupEconProductionLimits::GEconGroup::endRun() const {
|
||||
return m_end_run;
|
||||
}
|
||||
|
||||
UDAValue GroupEconProductionLimits::GEconGroup::maxGasOilRatio() const
|
||||
{
|
||||
return m_max_gas_oil_ratio;
|
||||
}
|
||||
|
||||
UDAValue GroupEconProductionLimits::GEconGroup::maxWaterCut() const
|
||||
{
|
||||
return m_max_water_cut;
|
||||
}
|
||||
|
||||
UDAValue GroupEconProductionLimits::GEconGroup::maxWaterGasRatio() const
|
||||
{
|
||||
return m_max_water_gas_ratio;
|
||||
}
|
||||
|
||||
int GroupEconProductionLimits::GEconGroup::maxOpenWells() const
|
||||
{
|
||||
return m_max_open_wells;
|
||||
}
|
||||
|
||||
UDAValue GroupEconProductionLimits::GEconGroup::minGasRate() const
|
||||
{
|
||||
return m_min_gas_rate;
|
||||
}
|
||||
|
||||
UDAValue GroupEconProductionLimits::GEconGroup::minOilRate() const
|
||||
{
|
||||
return m_min_oil_rate;
|
||||
}
|
||||
|
||||
bool GroupEconProductionLimits::GEconGroup::operator==(const GEconGroup& other) const
|
||||
{
|
||||
return this->m_min_oil_rate == other.m_min_oil_rate &&
|
||||
this->m_min_gas_rate == other.m_min_gas_rate &&
|
||||
this->m_max_water_cut == other.m_max_water_cut &&
|
||||
this->m_max_gas_oil_ratio == other.m_max_gas_oil_ratio &&
|
||||
this->m_max_water_gas_ratio == other.m_max_water_gas_ratio &&
|
||||
this->m_workover == other.m_workover &&
|
||||
this->m_end_run == other.m_end_run &&
|
||||
this->m_max_open_wells == other.m_max_open_wells;
|
||||
}
|
||||
|
||||
int GroupEconProductionLimits::GEconGroup::reportStep() const {
|
||||
return m_report_step;
|
||||
}
|
||||
|
||||
GroupEconProductionLimits::GEconGroup GroupEconProductionLimits::GEconGroup::serializationTestObject()
|
||||
{
|
||||
GEconGroup group;
|
||||
group.m_min_oil_rate = UDAValue{1.0};
|
||||
group.m_min_gas_rate = UDAValue{2.0};
|
||||
group.m_max_water_cut = UDAValue{3.0};
|
||||
group.m_max_gas_oil_ratio = UDAValue{4.0};
|
||||
group.m_max_water_gas_ratio = UDAValue{5.0};
|
||||
group.m_workover = EconWorkover::CON;
|
||||
group.m_end_run = false;
|
||||
group.m_max_open_wells = 6;
|
||||
return group;
|
||||
}
|
||||
|
||||
GroupEconProductionLimits::EconWorkover GroupEconProductionLimits::GEconGroup::workover() const {
|
||||
return m_workover;
|
||||
}
|
||||
|
||||
|
||||
/* Methods for inner class GEconGroupProp */
|
||||
|
||||
GroupEconProductionLimits::GEconGroupProp::GEconGroupProp(
|
||||
const double min_oil_rate,
|
||||
const double min_gas_rate,
|
||||
const double max_water_cut,
|
||||
const double max_gas_oil_ratio,
|
||||
const double max_water_gas_ratio,
|
||||
EconWorkover workover,
|
||||
bool end_run,
|
||||
int max_open_wells)
|
||||
: m_min_oil_rate{get_positive_value(min_oil_rate)}
|
||||
, m_min_gas_rate{get_positive_value(min_gas_rate)}
|
||||
, m_max_water_cut{get_positive_value(max_water_cut)}
|
||||
, m_max_gas_oil_ratio{get_positive_value(max_gas_oil_ratio)}
|
||||
, m_max_water_gas_ratio{get_positive_value(max_water_gas_ratio)}
|
||||
, m_workover{workover}
|
||||
, m_end_run{end_run}
|
||||
, m_max_open_wells{max_open_wells}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool GroupEconProductionLimits::GEconGroupProp::endRun() const {
|
||||
return m_end_run;
|
||||
}
|
||||
|
||||
std::optional<double> GroupEconProductionLimits::GEconGroupProp::minOilRate() const
|
||||
{
|
||||
return m_min_oil_rate;
|
||||
}
|
||||
|
||||
std::optional<double> GroupEconProductionLimits::GEconGroupProp::minGasRate() const
|
||||
{
|
||||
return m_min_gas_rate;
|
||||
}
|
||||
|
||||
std::optional<double> GroupEconProductionLimits::GEconGroupProp::maxWaterCut() const
|
||||
{
|
||||
return m_max_water_cut;
|
||||
}
|
||||
|
||||
std::optional<double> GroupEconProductionLimits::GEconGroupProp::maxGasOilRatio() const
|
||||
{
|
||||
return m_max_gas_oil_ratio;
|
||||
}
|
||||
|
||||
int GroupEconProductionLimits::GEconGroupProp::maxOpenWells() const
|
||||
{
|
||||
return m_max_open_wells;
|
||||
}
|
||||
|
||||
std::optional<double> GroupEconProductionLimits::GEconGroupProp::maxWaterGasRatio() const
|
||||
{
|
||||
return m_max_water_gas_ratio;
|
||||
}
|
||||
|
||||
GroupEconProductionLimits::EconWorkover GroupEconProductionLimits::GEconGroupProp::workover() const {
|
||||
return m_workover;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/MSW/SICD.hpp>
|
||||
#include <opm/input/eclipse/Schedule/MSW/Valve.hpp>
|
||||
@@ -690,6 +691,25 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
||||
this->snapshots.back().gconsump.update( std::move(new_gconsump) );
|
||||
}
|
||||
|
||||
void
|
||||
Schedule::handleGECON(HandlerContext& handlerContext)
|
||||
{
|
||||
auto gecon = this->snapshots.back().gecon();
|
||||
const auto& keyword = handlerContext.keyword;
|
||||
auto report_step = handlerContext.currentStep;
|
||||
for (const auto& record : keyword) {
|
||||
const std::string& groupNamePattern
|
||||
= record.getItem<ParserKeywords::GECON::GROUP>().getTrimmedString(0);
|
||||
const auto group_names = this->groupNames(groupNamePattern);
|
||||
if (group_names.empty())
|
||||
this->invalidNamePattern(groupNamePattern, handlerContext);
|
||||
for (const auto& gname : group_names) {
|
||||
gecon.add_group(report_step, gname, record);
|
||||
}
|
||||
}
|
||||
this->snapshots.back().gecon.update(std::move(gecon));
|
||||
}
|
||||
|
||||
void Schedule::handleGEFAC(HandlerContext& handlerContext) {
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const std::string& groupNamePattern = record.getItem("GROUP").getTrimmedString(0);
|
||||
@@ -2573,6 +2593,7 @@ Well{0} entered with 'FIELD' parent group:
|
||||
{ "GCONPROD", &Schedule::handleGCONPROD },
|
||||
{ "GCONSALE", &Schedule::handleGCONSALE },
|
||||
{ "GCONSUMP", &Schedule::handleGCONSUMP },
|
||||
{ "GECON", &Schedule::handleGECON },
|
||||
{ "GEFAC" , &Schedule::handleGEFAC },
|
||||
{ "GLIFTOPT", &Schedule::handleGLIFTOPT },
|
||||
{ "GPMAINT" , &Schedule::handleGPMAINT },
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <opm/input/eclipse/Schedule/Action/SimulatorUpdate.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GTNode.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
|
||||
@@ -2293,6 +2294,7 @@ void Schedule::create_first(const time_point& start_time, const std::optional<ti
|
||||
sched_state.wtest_config.update( WellTestConfig() );
|
||||
sched_state.gconsale.update( GConSale() );
|
||||
sched_state.gconsump.update( GConSump() );
|
||||
sched_state.gecon.update( GroupEconProductionLimits() );
|
||||
sched_state.wlist_manager.update( WListManager() );
|
||||
sched_state.network.update( Network::ExtNetwork() );
|
||||
sched_state.rpt_config.update( RPTConfig() );
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Network/Balance.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
|
||||
@@ -319,6 +320,7 @@ ScheduleState ScheduleState::serializationTestObject() {
|
||||
ts.wtest_config.update( WellTestConfig::serializationTestObject() );
|
||||
ts.gconsump.update( GConSump::serializationTestObject() );
|
||||
ts.gconsale.update( GConSale::serializationTestObject() );
|
||||
ts.gecon.update( GroupEconProductionLimits::serializationTestObject() );
|
||||
ts.wlist_manager.update( WListManager::serializationTestObject() );
|
||||
ts.rpt_config.update( RPTConfig::serializationTestObject() );
|
||||
ts.actions.update( Action::Actions::serializationTestObject() );
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
{
|
||||
"name": "MIN_OIL_RATE",
|
||||
"value_type": "UDA",
|
||||
"default": 0
|
||||
"default": 0,
|
||||
"dimension": "LiquidSurfaceVolume/Time"
|
||||
},
|
||||
{
|
||||
"name": "MIN_GAS_RATE",
|
||||
"value_type": "UDA",
|
||||
"default": 0
|
||||
"default": 0,
|
||||
"dimension": "GasSurfaceVolume/Time"
|
||||
},
|
||||
{
|
||||
"name": "MAX_WCT",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateModel.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||
@@ -316,6 +317,11 @@ GRUPTREE
|
||||
'G2' 'FIELD' /
|
||||
/
|
||||
|
||||
GECON
|
||||
'G1' 1* 200000.0 /
|
||||
'G2' 100000.0 1* 0.5 3* 'YES' /
|
||||
/
|
||||
|
||||
GCONSALE
|
||||
'G1' 50000 55000 45000 WELL /
|
||||
/
|
||||
@@ -327,20 +333,59 @@ GCONSUMP
|
||||
|
||||
auto schedule = create_schedule(input);
|
||||
double metric_to_si = 1.0 / (24.0 * 3600.0); //cubic meters / day
|
||||
SummaryState st(TimeService::now());
|
||||
|
||||
const auto& gconsale = schedule[0].gconsale.get();
|
||||
BOOST_CHECK_EQUAL(gconsale.size(), 1U);
|
||||
BOOST_CHECK(gconsale.has("G1"));
|
||||
BOOST_CHECK(!gconsale.has("G2"));
|
||||
const GConSale::GCONSALEGroup& group = gconsale.get("G1");
|
||||
BOOST_CHECK_EQUAL(group.sales_target.get<double>(), 50000);
|
||||
BOOST_CHECK_EQUAL(group.max_sales_rate.get<double>(), 55000);
|
||||
BOOST_CHECK_EQUAL(group.min_sales_rate.get<double>(), 45000);
|
||||
BOOST_CHECK_EQUAL(group.sales_target.getSI(), 50000 * metric_to_si);
|
||||
BOOST_CHECK_EQUAL(group.max_sales_rate.getSI(), 55000 * metric_to_si);
|
||||
BOOST_CHECK_EQUAL(group.min_sales_rate.getSI(), 45000 * metric_to_si);
|
||||
BOOST_CHECK(group.max_proc == GConSale::MaxProcedure::WELL);
|
||||
|
||||
{
|
||||
const auto& gconsale = schedule[0].gconsale.get();
|
||||
BOOST_CHECK_EQUAL(gconsale.size(), 1U);
|
||||
BOOST_CHECK(gconsale.has("G1"));
|
||||
BOOST_CHECK(!gconsale.has("G2"));
|
||||
const GConSale::GCONSALEGroup& group = gconsale.get("G1");
|
||||
BOOST_CHECK_EQUAL(group.sales_target.get<double>(), 50000);
|
||||
BOOST_CHECK_EQUAL(group.max_sales_rate.get<double>(), 55000);
|
||||
BOOST_CHECK_EQUAL(group.min_sales_rate.get<double>(), 45000);
|
||||
BOOST_CHECK_EQUAL(group.sales_target.getSI(), 50000 * metric_to_si);
|
||||
BOOST_CHECK_EQUAL(group.max_sales_rate.getSI(), 55000 * metric_to_si);
|
||||
BOOST_CHECK_EQUAL(group.min_sales_rate.getSI(), 45000 * metric_to_si);
|
||||
BOOST_CHECK(group.max_proc == GConSale::MaxProcedure::WELL);
|
||||
}
|
||||
{
|
||||
const auto& gecon = schedule[0].gecon.get();
|
||||
BOOST_CHECK_EQUAL(gecon.size(), 2U);
|
||||
BOOST_CHECK(gecon.has_group("G1"));
|
||||
BOOST_CHECK(gecon.has_group("G2"));
|
||||
{
|
||||
const GroupEconProductionLimits::GEconGroupProp group = gecon.get_group_prop(schedule, st, "G1");
|
||||
BOOST_CHECK(group.minOilRate().has_value() == false);
|
||||
BOOST_CHECK(group.minGasRate().has_value() == true);
|
||||
if (group.minGasRate()) {
|
||||
BOOST_CHECK_EQUAL(group.minGasRate().value(), 200000.0 * metric_to_si);
|
||||
}
|
||||
BOOST_CHECK(group.maxWaterCut().has_value() == false);
|
||||
BOOST_CHECK(group.maxGasOilRatio().has_value() == false);
|
||||
BOOST_CHECK(group.maxWaterGasRatio().has_value() == false);
|
||||
BOOST_CHECK(group.workover() == GroupEconProductionLimits::EconWorkover::NONE);
|
||||
BOOST_CHECK(group.endRun() == false);
|
||||
BOOST_CHECK_EQUAL(group.maxOpenWells(), 0);
|
||||
}
|
||||
{
|
||||
const GroupEconProductionLimits::GEconGroupProp group = gecon.get_group_prop(schedule, st, "G2");
|
||||
BOOST_CHECK(group.minOilRate().has_value() == true);
|
||||
if (group.minOilRate()) {
|
||||
BOOST_CHECK_EQUAL(group.minOilRate().value(), 100000.0 * metric_to_si);
|
||||
}
|
||||
BOOST_CHECK(group.minGasRate().has_value() == false);
|
||||
BOOST_CHECK(group.maxWaterCut().has_value() == true);
|
||||
if (group.maxWaterCut()) {
|
||||
BOOST_CHECK_EQUAL(group.maxWaterCut().value(), 0.5);
|
||||
}
|
||||
BOOST_CHECK(group.maxGasOilRatio().has_value() == false);
|
||||
BOOST_CHECK(group.maxWaterGasRatio().has_value() == false);
|
||||
BOOST_CHECK(group.workover() == GroupEconProductionLimits::EconWorkover::NONE);
|
||||
BOOST_CHECK(group.endRun() == true);
|
||||
BOOST_CHECK_EQUAL(group.maxOpenWells(), 0);
|
||||
}
|
||||
}
|
||||
const auto& gconsump = schedule[0].gconsump.get();
|
||||
BOOST_CHECK_EQUAL(gconsump.size(), 2U);
|
||||
BOOST_CHECK(gconsump.has("G1"));
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||
|
||||
@@ -227,6 +228,11 @@ GCONSALE
|
||||
'G1' 50000 55000 45000 WELL /
|
||||
/
|
||||
|
||||
GECON
|
||||
'G1' 1* 200000.0 /
|
||||
'G2' 1* 200000.0 /
|
||||
/
|
||||
|
||||
GCONSUMP
|
||||
'G1' 20 50 'a_node' /
|
||||
'G2' 30 60 /
|
||||
@@ -385,6 +391,21 @@ BOOST_AUTO_TEST_CASE(SerializeWList) {
|
||||
BOOST_CHECK( wlm2 == sched0[5].wlist_manager());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SerializeGECON) {
|
||||
auto sched = make_schedule(GCONSALE_deck);
|
||||
auto sched0 = make_schedule(deck0);
|
||||
auto gecon1 = sched[0].gecon.get();
|
||||
|
||||
{
|
||||
std::vector<Opm::GroupEconProductionLimits> value_list;
|
||||
std::vector<std::size_t> index_list;
|
||||
sched.pack_state<Opm::GroupEconProductionLimits>( value_list, index_list );
|
||||
BOOST_CHECK_EQUAL( value_list.size(), 1 );
|
||||
sched0.unpack_state<Opm::GroupEconProductionLimits>( value_list, index_list );
|
||||
}
|
||||
BOOST_CHECK( gecon1 == sched0[0].gecon());
|
||||
BOOST_CHECK( gecon1 == sched0[1].gecon());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SerializeGCONSALE) {
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include <opm/input/eclipse/Schedule/Events.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSale.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GConSump.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GroupEconProductionLimits.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateModel.hpp>
|
||||
@@ -239,6 +240,7 @@ TEST_FOR_TYPE(FoamConfig)
|
||||
TEST_FOR_TYPE(FoamData)
|
||||
TEST_FOR_TYPE(GConSale)
|
||||
TEST_FOR_TYPE(GConSump)
|
||||
TEST_FOR_TYPE(GroupEconProductionLimits)
|
||||
TEST_FOR_TYPE(GridDims)
|
||||
TEST_FOR_TYPE(Group)
|
||||
TEST_FOR_TYPE_NAMED(Group::GroupInjectionProperties, GroupInjectionProperties)
|
||||
|
||||
Reference in New Issue
Block a user