Evaluate UDA variuables for group rates

This commit is contained in:
Joakim Hove
2019-08-05 17:44:21 +02:00
parent 93b53df02a
commit 6016cd43b3
9 changed files with 128 additions and 45 deletions

View File

@@ -23,6 +23,7 @@
#include <string>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
#include <opm/parser/eclipse/EclipseState/Util/IOrderSet.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
@@ -30,42 +31,59 @@
namespace Opm {
class SummaryState;
class Group2 {
public:
struct GroupInjectionProperties {
Phase phase = Phase::WATER;
GroupInjection::ControlEnum cmode = GroupInjection::NONE;
double surface_max_rate = 0;
double resv_max_rate = 0;
double target_reinj_fraction = 0;
double target_void_fraction = 0;
UDAValue surface_max_rate;
UDAValue resv_max_rate;
UDAValue target_reinj_fraction;
UDAValue target_void_fraction;
bool operator==(const GroupInjectionProperties& other) const;
bool operator!=(const GroupInjectionProperties& other) const;
};
struct InjectionControls {
Phase phase;
GroupInjection::ControlEnum cmode;
double surface_max_rate;
double resv_max_rate;
double target_reinj_fraction;
double target_void_fraction;
};
struct GroupProductionProperties {
GroupProduction::ControlEnum cmode = GroupProduction::NONE;
GroupProductionExceedLimit::ActionEnum exceed_action = GroupProductionExceedLimit::NONE;
double oil_target = 0;
double water_target = 0;
double gas_target = 0;
double liquid_target = 0;
UDAValue oil_target;
UDAValue water_target;
UDAValue gas_target;
UDAValue liquid_target;
double resv_target = 0;
bool operator==(const GroupProductionProperties& other) const;
bool operator!=(const GroupProductionProperties& other) const;
};
Group2(const std::string& group_name, std::size_t insert_index_arg, std::size_t init_step_arg, const UnitSystem& unit_system_arg);
struct ProductionControls {
GroupProduction::ControlEnum cmode;
GroupProductionExceedLimit::ActionEnum exceed_action;
double oil_target;
double water_target;
double gas_target;
double liquid_target;
double resv_target = 0;
};
Group2(const std::string& group_name, std::size_t insert_index_arg, std::size_t init_step_arg, double udq_undefined_arg, const UnitSystem& unit_system);
bool defined(std::size_t timeStep) const;
std::size_t insert_index() const;
const std::string& name() const;
const GroupProductionProperties& productionProperties() const;
const GroupInjectionProperties& injectionProperties() const;
int getGroupNetVFPTable() const;
bool updateNetVFPTable(int vfp_arg);
bool update_gefac(double gefac, bool transfer_gefac);
@@ -92,13 +110,18 @@ struct GroupProductionProperties {
const std::vector<std::string>& wells() const;
const std::vector<std::string>& groups() const;
bool wellgroup() const;
ProductionControls productionControls(const SummaryState& st) const;
InjectionControls injectionControls(const SummaryState& st) const;
private:
bool hasType(GroupType gtype) const;
void addType(GroupType new_gtype);
const GroupProductionProperties& productionProperties() const;
const GroupInjectionProperties& injectionProperties() const;
std::string m_name;
std::size_t m_insert_index;
std::size_t init_step;
double udq_undefined;
UnitSystem unit_system;
GroupType group_type;
double gefac;
@@ -109,8 +132,8 @@ private:
IOrderSet<std::string> m_wells;
IOrderSet<std::string> m_groups;
GroupInjectionProperties injection_properties;
GroupProductionProperties production_properties;
GroupInjectionProperties injection_properties{};
GroupProductionProperties production_properties{};
};
}

View File

@@ -268,7 +268,7 @@ namespace Opm
void handleWCONINJH(const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWELOPEN( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors, const std::vector<std::string>& matching_wells = {});
void handleWELTARG( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleGCONINJE( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleGCONINJE( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleGCONPROD( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleGEFAC( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWEFAC( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);

View File

@@ -18,14 +18,18 @@
*/
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp>
#include "../eval_uda.hpp"
namespace Opm {
Group2::Group2(const std::string& name, std::size_t insert_index_arg, std::size_t init_step_arg, const UnitSystem& unit_system_arg) :
Group2::Group2(const std::string& name, std::size_t insert_index_arg, std::size_t init_step_arg, double udq_undefined_arg, const UnitSystem& unit_system_arg) :
m_name(name),
m_insert_index(insert_index_arg),
init_step(init_step_arg),
udq_undefined(udq_undefined_arg),
unit_system(unit_system_arg),
group_type(GroupType::NONE),
gefac(1),
@@ -257,5 +261,30 @@ bool Group2::updateParent(const std::string& parent) {
return false;
}
Group2::ProductionControls Group2::productionControls(const SummaryState& st) const {
Group2::ProductionControls pc;
pc.cmode = this->production_properties.cmode;
pc.exceed_action = this->production_properties.exceed_action;
pc.oil_target = UDA::eval_group_uda(this->production_properties.oil_target, this->m_name, st, this->udq_undefined);
pc.water_target = UDA::eval_group_uda(this->production_properties.water_target, this->m_name, st, this->udq_undefined);
pc.gas_target = UDA::eval_group_uda(this->production_properties.gas_target, this->m_name, st, this->udq_undefined);
pc.liquid_target = UDA::eval_group_uda(this->production_properties.liquid_target, this->m_name, st, this->udq_undefined);
pc.resv_target = this->production_properties.resv_target;
return pc;
}
Group2::InjectionControls Group2::injectionControls(const SummaryState& st) const {
Group2::InjectionControls ic;
ic.phase = this->injection_properties.phase;
ic.cmode = this->injection_properties.cmode;
ic.surface_max_rate = UDA::eval_group_uda_rate(this->injection_properties.surface_max_rate, this->m_name, st, this->udq_undefined, ic.phase, this->unit_system);
ic.resv_max_rate = UDA::eval_group_uda(this->injection_properties.resv_max_rate, this->m_name, st, this->udq_undefined);
ic.target_reinj_fraction = UDA::eval_group_uda(this->injection_properties.target_reinj_fraction, this->m_name, st, this->udq_undefined);
ic.target_void_fraction = UDA::eval_group_uda(this->injection_properties.target_void_fraction, this->m_name, st, this->udq_undefined);
return ic;
}
}

View File

@@ -297,7 +297,7 @@ namespace {
handleGRUPNET(keyword, currentStep, unit_system);
else if (keyword.name() == "GCONINJE")
handleGCONINJE(section, keyword, currentStep, parseContext, errors);
handleGCONINJE(keyword, currentStep, parseContext, errors);
else if (keyword.name() == "GCONPROD")
handleGCONPROD(keyword, currentStep, parseContext, errors);
@@ -1380,7 +1380,7 @@ namespace {
}
}
void Schedule::handleGCONINJE( const SCHEDULESection& section, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors) {
void Schedule::handleGCONINJE( 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);
@@ -1391,12 +1391,12 @@ namespace {
for (const auto& group_name : group_names){
GroupInjection::ControlEnum controlMode = GroupInjection::ControlEnumFromString( record.getItem("CONTROL_MODE").getTrimmedString(0) );
Phase phase = get_phase( record.getItem("PHASE").getTrimmedString(0));
double surfaceInjectionRate = record.getItem("SURFACE_TARGET").get< UDAValue >(0).get<double>();
double reservoirInjectionRate = record.getItem("RESV_TARGET").get<UDAValue>(0).get<double>();
double reinj_target = record.getItem("REINJ_TARGET").get<UDAValue>(0).get<double>();
double voidage_target = record.getItem("VOIDAGE_TARGET").get<UDAValue>(0).get<double>();
auto surfaceInjectionRate = record.getItem("SURFACE_TARGET").get< UDAValue >(0);
auto reservoirInjectionRate = record.getItem("RESV_TARGET").get<UDAValue>(0);
auto reinj_target = record.getItem("REINJ_TARGET").get<UDAValue>(0);
auto voidage_target = record.getItem("VOIDAGE_TARGET").get<UDAValue>(0);
surfaceInjectionRate = injection::rateToSI(surfaceInjectionRate, phase, section.unitSystem());
//surfaceInjectionRate = injection::rateToSI(surfaceInjectionRate, phase, section.unitSystem());
{
auto group_ptr = std::make_shared<Group2>(this->getGroup2(group_name, currentStep));
Group2::GroupInjectionProperties injection;
@@ -1425,10 +1425,10 @@ namespace {
for (const auto& group_name : group_names){
GroupProduction::ControlEnum controlMode = GroupProduction::ControlEnumFromString( record.getItem("CONTROL_MODE").getTrimmedString(0) );
GroupProductionExceedLimit::ActionEnum exceedAction = GroupProductionExceedLimit::ActionEnumFromString(record.getItem("EXCEED_PROC").getTrimmedString(0) );
auto oil_target = record.getItem("OIL_TARGET").get<UDAValue>(0).get<double>();
auto gas_target = record.getItem("GAS_TARGET").get<UDAValue>(0).get<double>();
auto water_target = record.getItem("WATER_TARGET").get<UDAValue>(0).get<double>();
auto liquid_target = record.getItem("LIQUID_TARGET").get<UDAValue>(0).get<double>();
auto oil_target = record.getItem("OIL_TARGET").get<UDAValue>(0);
auto gas_target = record.getItem("GAS_TARGET").get<UDAValue>(0);
auto water_target = record.getItem("WATER_TARGET").get<UDAValue>(0);
auto liquid_target = record.getItem("LIQUID_TARGET").get<UDAValue>(0);
auto resv_target = record.getItem("RESERVOIR_FLUID_TARGET").getSIDouble(0);
{
@@ -2180,7 +2180,7 @@ namespace {
const size_t gseqIndex = this->groups.size();
groups.insert( std::make_pair( groupName, DynamicState<std::shared_ptr<Group2>>(this->m_timeMap, nullptr)));
auto group_ptr = std::make_shared<Group2>(groupName, gseqIndex, timeStep, unit_system);
auto group_ptr = std::make_shared<Group2>(groupName, gseqIndex, timeStep, this->getUDQConfig(timeStep).params().undefinedValue(), unit_system);
auto& dynamic_state = this->groups.at(groupName);
dynamic_state.update(timeStep, group_ptr);

View File

@@ -52,5 +52,28 @@ double eval_well_uda_rate(const UDAValue& value, const std::string& well, const
}
double eval_group_uda(const UDAValue& value, const std::string& group, const SummaryState& st, double udq_undefined) {
if (value.is<double>())
return value.get<double>();
const std::string& string_var = value.get<std::string>();
double output_value = udq_undefined;
if (st.has_group_var(group, value.get<std::string>()))
output_value = st.get_group_var(group, string_var);
else if (st.has(string_var))
output_value = st.get(string_var);
// We do not handle negative rates.
output_value = std::max(0.0, output_value);
return value.get_dim().convertRawToSi(output_value);
}
double eval_group_uda_rate(const UDAValue& value, const std::string& name, const SummaryState& st, double udq_undefined, Phase phase, const UnitSystem& unitSystem) {
double raw_rate = eval_group_uda(value, name, st, udq_undefined);
return injection::rateToSI(raw_rate, phase, unitSystem);
}
}
}

View File

@@ -33,6 +33,9 @@ namespace UDA {
double eval_well_uda(const UDAValue& value, const std::string& name, const SummaryState& st, double udq_undefined);
double eval_well_uda_rate(const UDAValue& value, const std::string& name, const SummaryState& st, double udq_undefined, WellInjector::TypeEnum wellType, const UnitSystem& unitSystem);
double eval_group_uda(const UDAValue& value, const std::string& name, const SummaryState& st, double udq_undefined);
double eval_group_uda_rate(const UDAValue& value, const std::string& name, const SummaryState& st, double udq_undefined, Phase phase, const UnitSystem& unitSystem);
}
}

View File

@@ -32,6 +32,7 @@
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include "src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp"
#include "src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp"
@@ -41,13 +42,13 @@ using namespace Opm;
BOOST_AUTO_TEST_CASE(CreateGroup_CorrectNameAndDefaultValues) {
Opm::Group2 group("G1" , 1, 0, UnitSystem::newMETRIC());
Opm::Group2 group("G1" , 1, 0, 0, UnitSystem::newMETRIC());
BOOST_CHECK_EQUAL( "G1" , group.name() );
}
BOOST_AUTO_TEST_CASE(CreateGroupCreateTimeOK) {
Opm::Group2 group("G1" , 1, 5, UnitSystem::newMETRIC());
Opm::Group2 group("G1" , 1, 5, 0, UnitSystem::newMETRIC());
BOOST_CHECK_EQUAL( false, group.defined( 4 ));
BOOST_CHECK_EQUAL( true, group.defined( 5 ));
BOOST_CHECK_EQUAL( true, group.defined( 6 ));
@@ -56,8 +57,8 @@ BOOST_AUTO_TEST_CASE(CreateGroupCreateTimeOK) {
BOOST_AUTO_TEST_CASE(CreateGroup_SetInjectorProducer_CorrectStatusSet) {
Opm::Group2 group1("IGROUP" , 1, 0, UnitSystem::newMETRIC());
Opm::Group2 group2("PGROUP" , 2, 0, UnitSystem::newMETRIC());
Opm::Group2 group1("IGROUP" , 1, 0, 0, UnitSystem::newMETRIC());
Opm::Group2 group2("PGROUP" , 2, 0, 0, UnitSystem::newMETRIC());
group1.setProductionGroup();
BOOST_CHECK(group1.isProductionGroup());
@@ -71,16 +72,18 @@ BOOST_AUTO_TEST_CASE(CreateGroup_SetInjectorProducer_CorrectStatusSet) {
BOOST_AUTO_TEST_CASE(ControlModeOK) {
Opm::Group2 group("G1" , 1, 0, UnitSystem::newMETRIC());
const auto& prod = group.productionProperties();
Opm::Group2 group("G1" , 1, 0, 0, UnitSystem::newMETRIC());
Opm::SummaryState st;
const auto& prod = group.productionControls(st);
BOOST_CHECK_EQUAL( Opm::GroupInjection::NONE , prod.cmode);
}
BOOST_AUTO_TEST_CASE(GroupChangePhaseSameTimeThrows) {
Opm::Group2 group("G1" , 1, 0, UnitSystem::newMETRIC());
const auto& inj = group.injectionProperties();
Opm::Group2 group("G1" , 1, 0, 0, UnitSystem::newMETRIC());
Opm::SummaryState st;
const auto& inj = group.injectionControls(st);
BOOST_CHECK_EQUAL( Opm::Phase::WATER , inj.phase); // Default phase - assumed WATER
}
@@ -89,7 +92,7 @@ BOOST_AUTO_TEST_CASE(GroupChangePhaseSameTimeThrows) {
BOOST_AUTO_TEST_CASE(GroupDoesNotHaveWell) {
Opm::Group2 group("G1" , 1, 0, UnitSystem::newMETRIC());
Opm::Group2 group("G1" , 1, 0, 0, UnitSystem::newMETRIC());
BOOST_CHECK_EQUAL(false , group.hasWell("NO"));
BOOST_CHECK_EQUAL(0U , group.numWells());
@@ -233,8 +236,8 @@ BOOST_AUTO_TEST_CASE(createDeckWithGRUPNET) {
BOOST_AUTO_TEST_CASE(Group2Create) {
Opm::Group2 g1("NAME", 1, 1, UnitSystem::newMETRIC());
Opm::Group2 g2("NAME", 1, 1, UnitSystem::newMETRIC());
Opm::Group2 g1("NAME", 1, 1, 0, UnitSystem::newMETRIC());
Opm::Group2 g2("NAME", 1, 1, 0, UnitSystem::newMETRIC());
BOOST_CHECK( g1.addWell("W1") );
BOOST_CHECK( !g1.addWell("W1") );

View File

@@ -1137,21 +1137,22 @@ BOOST_AUTO_TEST_CASE(createDeckModifyMultipleGCONPROD) {
Eclipse3DProperties eclipseProperties ( deck , table, grid);
Runspec runspec (deck);
Opm::Schedule schedule(deck, grid, eclipseProperties, runspec);
Opm::SummaryState st;
Opm::UnitSystem unitSystem = deck.getActiveUnitSystem();
double siFactorL = unitSystem.parse("LiquidSurfaceVolume/Time").getSIScaling();
{
auto g = schedule.getGroup2("G1", 1);
BOOST_CHECK_EQUAL(g.productionProperties().oil_target, 1000 * siFactorL);
BOOST_CHECK_EQUAL(g.productionControls(st).oil_target, 1000 * siFactorL);
}
{
auto g = schedule.getGroup2("G1", 2);
BOOST_CHECK_EQUAL(g.productionProperties().oil_target, 2000 * siFactorL);
BOOST_CHECK_EQUAL(g.productionControls(st).oil_target, 2000 * siFactorL);
}
auto g2 = schedule.getGroup2("G2", 2);
BOOST_CHECK_EQUAL(g2.productionProperties().oil_target, 2000 * siFactorL);
BOOST_CHECK_EQUAL(g2.productionControls(st).oil_target, 2000 * siFactorL);
auto gh = schedule.getGroup2("H1", 1);
}

View File

@@ -336,6 +336,7 @@ BOOST_AUTO_TEST_CASE( WellTestGroups ) {
Eclipse3DProperties eclipseProperties ( deck , table, grid);
Runspec runspec (deck);
Schedule sched(deck, grid , eclipseProperties, runspec);
SummaryState st;
BOOST_CHECK_EQUAL( 3U , sched.numGroups() );
BOOST_CHECK( sched.hasGroup( "INJ" ));
@@ -343,7 +344,7 @@ BOOST_AUTO_TEST_CASE( WellTestGroups ) {
{
auto& group = sched.getGroup2("INJ", 3);
const auto& injection = group.injectionProperties();
const auto& injection = group.injectionControls(st);
BOOST_CHECK_EQUAL( Phase::WATER , injection.phase);
BOOST_CHECK_EQUAL( GroupInjection::VREP , injection.cmode);
BOOST_CHECK_CLOSE( 10/Metric::Time , injection.surface_max_rate, 0.001);
@@ -354,7 +355,7 @@ BOOST_AUTO_TEST_CASE( WellTestGroups ) {
}
{
auto& group = sched.getGroup2("INJ", 6);
const auto& injection = group.injectionProperties();
const auto& injection = group.injectionControls(st);
BOOST_CHECK_EQUAL( Phase::OIL , injection.phase);
BOOST_CHECK_EQUAL( GroupInjection::RATE , injection.cmode);
BOOST_CHECK_CLOSE( 1000/Metric::Time , injection.surface_max_rate, 0.0001);
@@ -363,7 +364,7 @@ BOOST_AUTO_TEST_CASE( WellTestGroups ) {
{
auto& group = sched.getGroup2("OP", 3);
const auto& production = group.productionProperties();
const auto& production = group.productionControls(st);
BOOST_CHECK_EQUAL( GroupProduction::ORAT , production.cmode);
BOOST_CHECK_CLOSE( 10/Metric::Time , production.oil_target , 0.001);
BOOST_CHECK_CLOSE( 20/Metric::Time , production.water_target , 0.001);