Merge pull request #1797 from joakim-hove/GPMAINT
Add code to internalize GPMAINT keyword in Group objects
This commit is contained in:
@@ -99,6 +99,7 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Events.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/GasLiftOpt.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRate.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateConfig.cpp
|
||||
@@ -701,6 +702,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/ScheduleTypes.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group/GuideRate.hpp
|
||||
|
||||
75
opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.hpp
Normal file
75
opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2020 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 GPMAINT_HPP
|
||||
#define GPMAINT_HPP
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class DeckRecord;
|
||||
|
||||
class GPMaint {
|
||||
public:
|
||||
|
||||
enum class FlowTarget {
|
||||
RESV_PROD = 0,
|
||||
RESV_OINJ = 1,
|
||||
RESV_WINJ = 2,
|
||||
RESV_GINJ = 3,
|
||||
SURF_OINJ = 4,
|
||||
SURF_WINJ = 5,
|
||||
SURF_GINJ = 6,
|
||||
};
|
||||
|
||||
GPMaint() = default;
|
||||
explicit GPMaint(const DeckRecord& record);
|
||||
static GPMaint serializeObject();
|
||||
|
||||
double pressure_target() const;
|
||||
double prop_constant() const;
|
||||
double time_constant() const;
|
||||
std::optional<std::pair<std::string, int>> region() const;
|
||||
FlowTarget flow_target() const;
|
||||
bool operator==(const GPMaint& other) const;
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
serializeOp(m_flow_target);
|
||||
serializeOp(m_region_number);
|
||||
serializeOp(m_region_name);
|
||||
serializeOp(m_pressure_target);
|
||||
serializeOp(m_prop_constant);
|
||||
serializeOp(m_time_constant);
|
||||
}
|
||||
|
||||
private:
|
||||
static FlowTarget FlowTargetFromString(const std::string& stringvalue);
|
||||
FlowTarget m_flow_target;
|
||||
int m_region_number;
|
||||
std::string m_region_name;
|
||||
double m_pressure_target;
|
||||
double m_prop_constant;
|
||||
double m_time_constant;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Util/IOrderSet.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
namespace Opm {
|
||||
@@ -263,6 +264,9 @@ struct ProductionControls {
|
||||
bool has_control(InjectionCMode control) const;
|
||||
bool productionGroupControlAvailable() const;
|
||||
bool injectionGroupControlAvailable(const Phase phase) const;
|
||||
const std::optional<GPMaint>& gpmaint() const;
|
||||
void set_gpmaint(GPMaint gpmaint);
|
||||
void set_gpmaint();
|
||||
|
||||
bool operator==(const Group& data) const;
|
||||
const Phase& topup_phase() const;
|
||||
@@ -286,6 +290,7 @@ struct ProductionControls {
|
||||
serializer.map(injection_properties);
|
||||
production_properties.serializeOp(serializer);
|
||||
serializer(m_topup_phase);
|
||||
serializer(m_gpmaint);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -309,6 +314,7 @@ private:
|
||||
std::map<Phase, GroupInjectionProperties> injection_properties;
|
||||
GroupProductionProperties production_properties;
|
||||
std::pair<Phase, bool> m_topup_phase{Phase::WATER, false};
|
||||
std::optional<GPMaint> m_gpmaint;
|
||||
};
|
||||
|
||||
Group::GroupType operator |(Group::GroupType lhs, Group::GroupType rhs);
|
||||
|
||||
@@ -438,6 +438,7 @@ namespace Opm
|
||||
void handleTUNING( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handlePYACTION( std::shared_ptr<const Python> python, const std::string& input_path, const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleNUPCOL( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleGPMAINT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, const UnitSystem& unit_system, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleGRUPNET( const DeckKeyword& keyword, size_t currentStep, const UnitSystem& unit_system);
|
||||
void handleWRFT( const DeckKeyword& keyword, size_t currentStep);
|
||||
|
||||
101
src/opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.cpp
Normal file
101
src/opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright 2020 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/parser/eclipse/EclipseState/Schedule/Group/GPMaint.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/G.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
GPMaint::GPMaint(const DeckRecord& record)
|
||||
{
|
||||
using GP = ParserKeywords::GPMAINT;
|
||||
this->m_flow_target = FlowTargetFromString( record.getItem<GP::FLOW_TARGET>().get<std::string>(0) );
|
||||
this->m_region_number = record.getItem<GP::REGION>().get<int>(0);
|
||||
this->m_region_name = record.getItem<GP::FIP_FAMILY>().get<std::string>(0);
|
||||
this->m_pressure_target = record.getItem<GP::PRESSURE_TARGET>().getSIDouble(0);
|
||||
this->m_prop_constant = record.getItem<GP::PROP_CONSTANT>().getSIDouble(0);
|
||||
this->m_time_constant = record.getItem<GP::TIME_CONSTANT>().getSIDouble(0);
|
||||
}
|
||||
|
||||
|
||||
GPMaint::FlowTarget GPMaint::flow_target() const {
|
||||
return this->m_flow_target;
|
||||
}
|
||||
|
||||
double GPMaint::pressure_target() const {
|
||||
return this->m_pressure_target;
|
||||
}
|
||||
|
||||
double GPMaint::prop_constant() const {
|
||||
return this->m_prop_constant;
|
||||
}
|
||||
|
||||
double GPMaint::time_constant() const {
|
||||
return this->m_time_constant;
|
||||
}
|
||||
|
||||
GPMaint GPMaint::serializeObject() {
|
||||
GPMaint gpm;
|
||||
gpm.m_flow_target = FlowTarget::SURF_GINJ;
|
||||
gpm.m_region_name = "FIPNUM";
|
||||
gpm.m_region_number = 26;
|
||||
return gpm;
|
||||
}
|
||||
|
||||
std::optional<std::pair<std::string, int>> GPMaint::region() const {
|
||||
if (this->m_region_number == 0)
|
||||
return {};
|
||||
|
||||
return std::make_pair(this->m_region_name, this->m_region_number);
|
||||
}
|
||||
|
||||
GPMaint::FlowTarget GPMaint::FlowTargetFromString(const std::string& string_value) {
|
||||
if (string_value == "PROD")
|
||||
return GPMaint::FlowTarget::RESV_PROD;
|
||||
|
||||
if (string_value == "OINJ")
|
||||
return GPMaint::FlowTarget::RESV_OINJ;
|
||||
|
||||
if (string_value == "WINJ")
|
||||
return GPMaint::FlowTarget::RESV_WINJ;
|
||||
|
||||
if (string_value == "GINJ")
|
||||
return GPMaint::FlowTarget::RESV_GINJ;
|
||||
|
||||
if (string_value == "OINS")
|
||||
return GPMaint::FlowTarget::SURF_OINJ;
|
||||
|
||||
if (string_value == "WINS")
|
||||
return GPMaint::FlowTarget::SURF_WINJ;
|
||||
|
||||
if (string_value == "GINS")
|
||||
return GPMaint::FlowTarget::SURF_GINJ;
|
||||
|
||||
throw std::invalid_argument("The string: " + string_value + " could not be converted to a valid FLOW target");
|
||||
}
|
||||
|
||||
|
||||
bool GPMaint::operator==(const GPMaint& other) const {
|
||||
return this->m_flow_target == other.m_flow_target &&
|
||||
this->m_region_name == other.m_region_name &&
|
||||
this->m_region_number == other.m_region_number;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -486,6 +486,18 @@ bool Group::has_control(Group::ProductionCMode control) const {
|
||||
return detail::has_control(production_properties.production_controls, control);
|
||||
}
|
||||
|
||||
const std::optional<GPMaint>& Group::gpmaint() const {
|
||||
return this->m_gpmaint;
|
||||
}
|
||||
|
||||
void Group::set_gpmaint(GPMaint gpmaint) {
|
||||
this->m_gpmaint = std::move(gpmaint);
|
||||
}
|
||||
|
||||
void Group::set_gpmaint() {
|
||||
this->m_gpmaint = std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
const std::string Group::ExceedAction2String( ExceedAction enumValue ) {
|
||||
switch(enumValue) {
|
||||
@@ -665,6 +677,7 @@ bool Group::operator==(const Group& data) const
|
||||
this->m_groups == data.m_groups &&
|
||||
this->m_topup_phase == data.m_topup_phase &&
|
||||
this->injection_properties == data.injection_properties &&
|
||||
this->m_gpmaint == data.m_gpmaint &&
|
||||
this->productionProperties() == data.productionProperties();
|
||||
}
|
||||
|
||||
|
||||
@@ -410,6 +410,9 @@ Schedule::Schedule(const Deck& deck, const EclipseState& es, const ParseContext&
|
||||
else if (keyword.name() == "GRUPTREE")
|
||||
handleGRUPTREE(keyword, currentStep, unit_system, parseContext, errors);
|
||||
|
||||
else if (keyword.name() == "GPMAINT")
|
||||
handleGPMAINT(keyword, currentStep, parseContext, errors);
|
||||
|
||||
else if (keyword.name() == "GRUPNET")
|
||||
handleGRUPNET(keyword, currentStep, unit_system);
|
||||
|
||||
@@ -2145,7 +2148,7 @@ Schedule::Schedule(const Deck& deck, const EclipseState& es, const ParseContext&
|
||||
}
|
||||
}
|
||||
|
||||
void Schedule::handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, const UnitSystem& unit_system, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||
void Schedule::handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, const UnitSystem& unit_system, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||
for( const auto& record : keyword ) {
|
||||
const std::string& childName = trim_wgname(keyword, record.getItem("CHILD_GROUP").get<std::string>(0), parseContext, errors);
|
||||
const std::string& parentName = trim_wgname(keyword, record.getItem("PARENT_GROUP").get<std::string>(0), parseContext, errors);
|
||||
@@ -2161,6 +2164,30 @@ void Schedule::handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, c
|
||||
}
|
||||
|
||||
|
||||
void Schedule::handleGPMAINT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||
for( const auto& record : keyword ) {
|
||||
const std::string& groupNamePattern = record.getItem("GROUP").getTrimmedString(0);
|
||||
const auto group_names = this->groupNames(groupNamePattern);
|
||||
|
||||
if (group_names.empty())
|
||||
invalidNamePattern(groupNamePattern, currentStep, parseContext, errors, keyword);
|
||||
|
||||
using GP = ParserKeywords::GPMAINT;
|
||||
for (const auto& group_name : group_names) {
|
||||
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, currentStep));
|
||||
const auto& target_string = record.getItem<GP::FLOW_TARGET>().get<std::string>(0);
|
||||
if (target_string == "NONE")
|
||||
group_ptr->set_gpmaint();
|
||||
else {
|
||||
GPMaint gpmaint(record);
|
||||
group_ptr->set_gpmaint(std::move(gpmaint));
|
||||
}
|
||||
this->updateGroup(std::move(group_ptr), currentStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Schedule::handleGRUPNET( const DeckKeyword& keyword, size_t currentStep, const UnitSystem& unit_system) {
|
||||
for( const auto& record : keyword ) {
|
||||
const auto& groupName = record.getItem("NAME").getTrimmedString(0);
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
},
|
||||
{
|
||||
"name": "FIP_FAMILY",
|
||||
"value_type": "STRING"
|
||||
"value_type": "STRING",
|
||||
"default": "FIPNUM"
|
||||
},
|
||||
{
|
||||
"name": "PRESSURE_TARGET",
|
||||
|
||||
@@ -537,3 +537,62 @@ BOOST_AUTO_TEST_CASE(GCONINJE_GCONPROD) {
|
||||
BOOST_CHECK( g2.injectionGroupControlAvailable(Phase::GAS));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GPMAINT) {
|
||||
const auto input = R"(
|
||||
SCHEDULE
|
||||
|
||||
GRUPTREE
|
||||
'PROD' 'FIELD' /
|
||||
|
||||
'M5S' 'PLAT-A' /
|
||||
'M5N' 'PLAT-A' /
|
||||
|
||||
'C1' 'M5N' /
|
||||
'F1' 'M5N' /
|
||||
'B1' 'M5S' /
|
||||
'G1' 'M5S' /
|
||||
/
|
||||
|
||||
GPMAINT
|
||||
'PROD' 'WINJ' 2 1* 100 0.25 1.0 /
|
||||
'C1' 'GINJ' 0 1* 100 0.25 1.0 /
|
||||
/
|
||||
|
||||
TSTEP
|
||||
10 /
|
||||
|
||||
GPMAINT
|
||||
'PROD' 'NONE' /
|
||||
/
|
||||
|
||||
)";
|
||||
Opm::UnitSystem unitSystem = UnitSystem( UnitSystem::UnitType::UNIT_TYPE_METRIC );
|
||||
double siFactorG = unitSystem.parse("GasSurfaceVolume/Time").getSIScaling();
|
||||
const auto sched = create_schedule(input);
|
||||
{
|
||||
const auto& prod_group = sched.getGroup("PROD", 0);
|
||||
const auto& plat_group = sched.getGroup("PLAT-A", 0);
|
||||
const auto& c1_group = sched.getGroup("C1", 0);
|
||||
|
||||
const auto& gpm_prod = prod_group.gpmaint();
|
||||
BOOST_CHECK( gpm_prod );
|
||||
BOOST_CHECK(gpm_prod->flow_target() == GPMaint::FlowTarget::RESV_WINJ);
|
||||
|
||||
auto [name, number] = *gpm_prod->region();
|
||||
BOOST_CHECK_EQUAL(number, 2);
|
||||
BOOST_CHECK_EQUAL(name, "FIPNUM");
|
||||
|
||||
const auto& gpm_c1 = c1_group.gpmaint();
|
||||
BOOST_CHECK(!gpm_c1->region());
|
||||
|
||||
const auto& plat_prod = plat_group.gpmaint();
|
||||
BOOST_CHECK( !plat_prod );
|
||||
}
|
||||
{
|
||||
const auto& prod_group = sched.getGroup("PROD", 1);
|
||||
const auto& gpm_prod = prod_group.gpmaint();
|
||||
BOOST_CHECK( !gpm_prod );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user