Merge pull request #968 from joakim-hove/guiderate-model
Adds GuideRateModel
This commit is contained in:
@@ -88,6 +88,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/Group/Group2.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Well/injection.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/MessageLimits.cpp
|
||||
@@ -555,6 +556,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/MessageLimits.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Events.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2019 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 GUIDE_RATE_MODEL_HPP
|
||||
#define GUIDE_RATE_MODEL_HPP
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class GuideRateModel {
|
||||
public:
|
||||
GuideRateModel(double time_interval_arg,
|
||||
GuideRateTarget phase_arg,
|
||||
double A_arg,
|
||||
double B_arg,
|
||||
double C_arg,
|
||||
double D_arg,
|
||||
double E_arg,
|
||||
double F_arg,
|
||||
bool allow_increase_arg,
|
||||
double damping_factor_arg,
|
||||
bool use_free_gas_arg);
|
||||
|
||||
GuideRateModel() = default;
|
||||
double eval(double pot, double R1, double R2) const;
|
||||
double update_delay() const;
|
||||
bool operator==(const GuideRateModel& other) const;
|
||||
bool operator!=(const GuideRateModel& other) const;
|
||||
|
||||
private:
|
||||
/*
|
||||
Unfortunately the default values will give a GuideRateModel which can not
|
||||
be evaluated, due to a division by zero problem.
|
||||
*/
|
||||
double time_interval = 0;
|
||||
GuideRateTarget phase = GuideRateTarget::NONE;
|
||||
double A = 0;
|
||||
double B = 0;
|
||||
double C = 0;
|
||||
double D = 0;
|
||||
double E = 0;
|
||||
double F = 0;
|
||||
bool allow_increase = true;
|
||||
double damping_factor = 1.0;
|
||||
bool use_free_gas = false;
|
||||
bool default_model = true;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp>
|
||||
@@ -195,6 +196,7 @@ namespace Opm
|
||||
const Tuning& getTuning() const;
|
||||
const MessageLimits& getMessageLimits() const;
|
||||
void invalidNamePattern (const std::string& namePattern, const ParseContext& parseContext, ErrorGuard& errors, const DeckKeyword& keyword) const;
|
||||
const GuideRateModel& guideRateModel(size_t timeStep) const;
|
||||
|
||||
const RFTConfig& rftConfig() const;
|
||||
const Events& getEvents() const;
|
||||
@@ -230,6 +232,7 @@ namespace Opm
|
||||
DynamicState<std::shared_ptr<WListManager>> wlist_manager;
|
||||
DynamicState<std::shared_ptr<UDQConfig>> udq_config;
|
||||
DynamicState<std::shared_ptr<UDQActive>> udq_active;
|
||||
DynamicState<std::shared_ptr<GuideRateModel>> guide_rate_model;
|
||||
DynamicState<WellProducer::ControlModeEnum> global_whistctl_mode;
|
||||
RFTConfig rft_config;
|
||||
|
||||
@@ -275,6 +278,7 @@ namespace Opm
|
||||
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 handleGUIDERAT( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleWEFAC( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleTUNING( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, const UnitSystem& unit_system, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
|
||||
@@ -203,6 +203,18 @@ namespace Opm {
|
||||
GroupType operator |(GroupType lhs, GroupType rhs);
|
||||
GroupType operator &(GroupType lhs, GroupType rhs);
|
||||
|
||||
|
||||
enum class GuideRateTarget {
|
||||
OIL = 0,
|
||||
LIQ = 1,
|
||||
GAS = 2,
|
||||
RES = 3,
|
||||
COMB = 4,
|
||||
NONE = 5
|
||||
};
|
||||
GuideRateTarget GuideRateTargetFromString(const std::string& s);
|
||||
|
||||
|
||||
namespace GroupProduction {
|
||||
|
||||
enum ControlEnum {
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright 2019 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 <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
GuideRateModel::GuideRateModel(double time_interval_arg,
|
||||
GuideRateTarget phase_arg,
|
||||
double A_arg,
|
||||
double B_arg,
|
||||
double C_arg,
|
||||
double D_arg,
|
||||
double E_arg,
|
||||
double F_arg,
|
||||
bool allow_increase_arg,
|
||||
double damping_factor_arg,
|
||||
bool use_free_gas_arg) :
|
||||
time_interval(time_interval_arg),
|
||||
phase(phase_arg),
|
||||
A(A_arg),
|
||||
B(B_arg),
|
||||
C(C_arg),
|
||||
D(D_arg),
|
||||
E(E_arg),
|
||||
F(F_arg),
|
||||
allow_increase(allow_increase_arg),
|
||||
damping_factor(damping_factor_arg),
|
||||
use_free_gas(use_free_gas_arg),
|
||||
default_model(false)
|
||||
{
|
||||
if (this->A > 3 || this->A < -3)
|
||||
throw std::invalid_argument("Invalid value for A must be in interval [-3,3]");
|
||||
|
||||
if (this->B < 0)
|
||||
throw std::invalid_argument("Invalid value for B must be > 0");
|
||||
|
||||
if (this->D > 3 || this->D < -3)
|
||||
throw std::invalid_argument("Invalid value for D must be in interval [-3,3]");
|
||||
|
||||
if (this->F > 3 || this->F < -3)
|
||||
throw std::invalid_argument("Invalid value for F must be in interval [-3,3]");
|
||||
}
|
||||
|
||||
|
||||
double GuideRateModel::update_delay() const {
|
||||
return this->time_interval;
|
||||
}
|
||||
|
||||
|
||||
double GuideRateModel::eval(double pot, double R1, double R2) const {
|
||||
if (this->default_model)
|
||||
throw std::invalid_argument("The default GuideRateModel can not be evaluated - must enter GUIDERAT information explicitly.");
|
||||
|
||||
double denom = this->B + this->C*std::pow(R1, this->D) + this->E*std::pow(R2, this->F);
|
||||
/*
|
||||
The values pot, R1 and R2 are runtime simulation results, so here
|
||||
basically anything could happen. Quite dangerous to have hard error
|
||||
handling here?
|
||||
*/
|
||||
if (denom <= 0)
|
||||
throw std::range_error("Invalid denominator: " + std::to_string(denom));
|
||||
|
||||
return std::pow(pot, this->A) / denom;
|
||||
}
|
||||
|
||||
bool GuideRateModel::operator==(const GuideRateModel& other) const {
|
||||
return (this->time_interval == other.time_interval) &&
|
||||
(this->phase == other.phase) &&
|
||||
(this->A == other.A) &&
|
||||
(this->B == other.B) &&
|
||||
(this->C == other.C) &&
|
||||
(this->D == other.D) &&
|
||||
(this->E == other.E) &&
|
||||
(this->F == other.F) &&
|
||||
(this->allow_increase == other.allow_increase) &&
|
||||
(this->damping_factor == other.damping_factor) &&
|
||||
(this->use_free_gas == other.use_free_gas);
|
||||
}
|
||||
|
||||
bool GuideRateModel::operator!=(const GuideRateModel& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <opm/parser/eclipse/Deck/Section.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/C.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/G.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/V.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/W.hpp>
|
||||
|
||||
@@ -120,6 +121,7 @@ namespace {
|
||||
wlist_manager( this->m_timeMap, std::make_shared<WListManager>()),
|
||||
udq_config(this->m_timeMap, std::make_shared<UDQConfig>(deck)),
|
||||
udq_active(this->m_timeMap, std::make_shared<UDQActive>()),
|
||||
guide_rate_model(this->m_timeMap, std::make_shared<GuideRateModel>()),
|
||||
global_whistctl_mode(this->m_timeMap, WellProducer::CMODE_UNDEFINED),
|
||||
rft_config(this->m_timeMap)
|
||||
{
|
||||
@@ -332,6 +334,9 @@ namespace {
|
||||
else if (keyword.name() == "GEFAC")
|
||||
handleGEFAC(keyword, currentStep, parseContext, errors);
|
||||
|
||||
else if (keyword.name() == "GUIDERAT")
|
||||
handleGUIDERAT(keyword, currentStep);
|
||||
|
||||
else if (keyword.name() == "TUNING")
|
||||
handleTUNING(keyword, currentStep);
|
||||
|
||||
@@ -1561,6 +1566,27 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
void Schedule::handleGUIDERAT( const DeckKeyword& keyword, size_t currentStep) {
|
||||
const auto& record = keyword.getRecord(0);
|
||||
|
||||
double min_calc_delay = record.getItem<ParserKeywords::GUIDERAT::MIN_CALC_TIME>().getSIDouble(0);
|
||||
auto phase = GuideRateTargetFromString(record.getItem<ParserKeywords::GUIDERAT::NOMINATED_PHASE>().getTrimmedString(0));
|
||||
double A = record.getItem<ParserKeywords::GUIDERAT::A>().get<double>(0);
|
||||
double B = record.getItem<ParserKeywords::GUIDERAT::B>().get<double>(0);
|
||||
double C = record.getItem<ParserKeywords::GUIDERAT::C>().get<double>(0);
|
||||
double D = record.getItem<ParserKeywords::GUIDERAT::D>().get<double>(0);
|
||||
double E = record.getItem<ParserKeywords::GUIDERAT::E>().get<double>(0);
|
||||
double F = record.getItem<ParserKeywords::GUIDERAT::F>().get<double>(0);
|
||||
bool allow_increase = DeckItem::to_bool( record.getItem<ParserKeywords::GUIDERAT::ALLOW_INCREASE>().getTrimmedString(0));
|
||||
double damping_factor = record.getItem<ParserKeywords::GUIDERAT::DAMPING_FACTOR>().get<double>(0);
|
||||
bool use_free_gas = DeckItem::to_bool( record.getItem<ParserKeywords::GUIDERAT::USE_FREE_GAS>().getTrimmedString(0));
|
||||
|
||||
auto new_model = std::make_shared<GuideRateModel>(min_calc_delay, phase, A, B, C, D, E, F, allow_increase, damping_factor, use_free_gas);
|
||||
const auto& current_model = this->guide_rate_model.get(currentStep);
|
||||
if (*current_model != *new_model)
|
||||
this->guide_rate_model.update( currentStep, new_model );
|
||||
}
|
||||
|
||||
|
||||
void Schedule::handleTUNING( const DeckKeyword& keyword, size_t currentStep) {
|
||||
|
||||
@@ -2494,6 +2520,13 @@ void Schedule::handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, c
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
const GuideRateModel& Schedule::guideRateModel(size_t timeStep) const {
|
||||
const auto& ptr = this->guide_rate_model.get(timeStep);
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error("Tried to dereference invalid GuideRateModel - internal error in opm/flow");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
|
||||
size_t Schedule::size() const {
|
||||
return this->m_timeMap.size();
|
||||
|
||||
@@ -760,4 +760,25 @@ namespace Opm {
|
||||
return static_cast<GroupType>(static_cast<std::underlying_type<GroupType>::type>(lhs) & static_cast<std::underlying_type<GroupType>::type>(rhs));
|
||||
}
|
||||
|
||||
GuideRateTarget GuideRateTargetFromString(const std::string& s) {
|
||||
if (s == "OIL")
|
||||
return GuideRateTarget::OIL;
|
||||
|
||||
if (s == "LIQ")
|
||||
return GuideRateTarget::LIQ;
|
||||
|
||||
if (s == "GAS")
|
||||
return GuideRateTarget::GAS;
|
||||
|
||||
if (s == "RES")
|
||||
return GuideRateTarget::RES;
|
||||
|
||||
if (s == "COMB")
|
||||
return GuideRateTarget::COMB;
|
||||
|
||||
if (s == "NONE")
|
||||
return GuideRateTarget::NONE;
|
||||
|
||||
throw std::invalid_argument("Could not convert: " + s + " to a valid GuideRateTarget enum value");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/Group/GuideRateModel.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp>
|
||||
@@ -295,3 +296,12 @@ BOOST_AUTO_TEST_CASE(createDeckWithGCONPROD) {
|
||||
BOOST_CHECK_EQUAL(ctrl2.exceed_action, GroupProductionExceedLimit::CON);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TESTGuideRateModel) {
|
||||
Opm::GuideRateModel grc_default;
|
||||
BOOST_CHECK_THROW(Opm::GuideRateModel(0.0,GuideRateTarget::NONE, -5,0,0,0,0,0,true,1,true), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(grc_default.eval(1,0.50,0.50), std::invalid_argument);
|
||||
|
||||
Opm::GuideRateModel grc_delay(10, GuideRateTarget::NONE, 1,1,0,0,0,0,true,1,true);
|
||||
BOOST_CHECK_NO_THROW(grc_delay.eval(1.0, 0.5, 0.5));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user