Merge pull request #3657 from hakonhagland/gecon2

Implement support for GECON keyword
This commit is contained in:
Tor Harald Sandve
2023-09-01 15:06:36 +02:00
committed by GitHub
12 changed files with 552 additions and 15 deletions

View File

@@ -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

View 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

View File

@@ -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&);

View File

@@ -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> )

View File

@@ -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

View File

@@ -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 },

View File

@@ -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() );

View File

@@ -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() );

View File

@@ -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",

View File

@@ -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"));

View File

@@ -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) {

View File

@@ -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)