Merge pull request #1778 from joakim-hove/gas-lift-opt

Internalize keywords for Gas Lift Optimization
This commit is contained in:
Joakim Hove 2020-05-07 20:07:58 +02:00 committed by GitHub
commit 310bd82b8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 549 additions and 3 deletions

View File

@ -98,6 +98,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/Action/Condition.cpp
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/Group.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRate.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateConfig.cpp
@ -668,6 +669,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/Action/ASTNode.hpp
opm/parser/eclipse/EclipseState/Schedule/Action/PyAction.hpp
opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.hpp
opm/parser/eclipse/EclipseState/Schedule/GasLiftOpt.hpp
opm/parser/eclipse/EclipseState/Schedule/Network/Branch.hpp
opm/parser/eclipse/EclipseState/Schedule/Network/ExtNetwork.hpp
opm/parser/eclipse/EclipseState/Schedule/Network/Node.hpp

View File

@ -0,0 +1,251 @@
/*
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 GAS_LIFT_OPT_HPP
#define GAS_LIFT_OPT_HPP
#include <optional>
#include <string>
#include <map>
namespace Opm {
class GasLiftOpt {
public:
class Group {
public:
Group() = default;
Group(const std::string& name) :
m_name(name)
{}
const std::optional<double>& max_lift_gas() const {
return this->m_max_lift_gas;
}
void max_lift_gas(double value) {
if (value >= 0)
this->m_max_lift_gas = value;
}
const std::optional<double>& max_total_gas() const {
return this->m_max_total_gas;
}
void max_total_gas(double value) {
if (value >= 0)
this->m_max_total_gas = value;
}
const std::string& name() const {
return this->m_name;
}
template<class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(m_name);
serializer(m_max_lift_gas);
serializer(m_max_total_gas);
}
static Group serializeObject() {
Group group;
group.m_name = "GR";
group.m_max_lift_gas = 100;
group.m_max_total_gas = 200;
return group;
}
bool operator==(const Group& other) const {
return this->m_name == other.m_name &&
this->m_max_lift_gas == other.m_max_lift_gas &&
this->m_max_total_gas == other.m_max_total_gas;
}
private:
std::string m_name;
std::optional<double> m_max_lift_gas;
std::optional<double> m_max_total_gas;
};
class Well {
public:
Well() = default;
Well(const std::string& name, bool use_glo) :
m_name(name),
m_use_glo(use_glo)
{}
const std::string& name() const {
return this->m_name;
}
bool use_glo() const {
return this->m_use_glo;
}
void max_rate(double value) {
this->m_max_rate = value;
}
/*
The semantics of the max_rate is quite complicated:
1. If the std::optional<double> has a value that value should be
used as the maximum rate and all is fine.
2. If the std::optional<double> does not a have well we must check
the value of Well::use_glo():
False: The maximum gas lift should have been set with WCONPROD /
WELTARG - this code does not provide a value in that case.
True: If the well should be controlled with gas lift optimization
the value to use should be the largest ALQ value in the wells
VFP table.
*/
const std::optional<double>& max_rate() const {
return this->m_max_rate;
}
void weight_factor(double value) {
if (this->m_use_glo)
this->m_weight = value;
}
double weight_factor() const {
return this->m_weight;
}
void inc_weight_factor(double value) {
if (this->m_use_glo)
this->m_inc_weight = value;
}
double inc_weight_factor() const {
return this->m_inc_weight;
}
void min_rate(double value) {
if (this->m_use_glo)
this->m_min_rate = value;
}
double min_rate() const {
return this->m_min_rate;
}
void alloc_extra_gas(bool value) {
if (this->m_use_glo)
this->m_alloc_extra_gas = value;
}
bool alloc_extra_gas() const {
return this->m_alloc_extra_gas;
}
template<class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(m_name);
serializer(m_use_glo);
serializer(m_max_rate);
serializer(m_min_rate);
serializer(m_weight);
serializer(m_inc_weight);
serializer(m_alloc_extra_gas);
}
static Well serializeObject() {
Well well;
well.m_name = "WELL";
well.m_max_rate = 2000;
well.m_min_rate = 56;
well.m_use_glo = true;
well.m_weight = 1.25;
well.m_inc_weight = 0.25;
well.m_alloc_extra_gas = false;
return well;
}
bool operator==(const Well& other) const {
return this->m_name == other.m_name &&
this->m_max_rate == other.m_max_rate &&
this->m_min_rate == other.m_min_rate &&
this->m_use_glo == other.m_use_glo &&
this->m_weight == other.m_weight &&
this->m_inc_weight == other.m_inc_weight &&
this->m_alloc_extra_gas == other.m_alloc_extra_gas;
}
private:
std::string m_name;
std::optional<double> m_max_rate;
double m_min_rate = 0;
bool m_use_glo;
double m_weight = 1;
double m_inc_weight = 0;
bool m_alloc_extra_gas = false;
};
GasLiftOpt() = default;
const Group& group(const std::string& gname) const;
const Well& well(const std::string& wname) const;
void gaslift_increment(double gaslift_increment);
void min_eco_gradient(double min_eco_gradient);
void min_wait(double min_wait);
void all_newton(double all_newton);
void add_group(const Group& group);
void add_well(const Well& well);
bool active() const;
static GasLiftOpt serializeObject();
bool operator==(const GasLiftOpt& other) const;
template<class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(m_increment);
serializer(m_min_eco_gradient);
serializer(m_min_wait);
serializer(m_all_newton);
serializer.map(m_groups);
serializer.map(m_wells);
}
private:
double m_increment = 0;
double m_min_eco_gradient;
double m_min_wait;
bool m_all_newton = true;
std::map<std::string, GasLiftOpt::Group> m_groups;
std::map<std::string, GasLiftOpt::Well> m_wells;
};
}
#endif

View File

@ -24,6 +24,7 @@
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/parser/eclipse/EclipseState/IOConfig/RestartConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/GasLiftOpt.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/DynamicState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/DynamicVector.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
@ -266,6 +267,7 @@ namespace Opm
const Network::ExtNetwork& network(std::size_t report_step) const;
const GasLiftOpt& glo(std::size_t report_step) const;
bool operator==(const Schedule& data) const;
std::shared_ptr<const Python> python() const;
@ -310,6 +312,7 @@ namespace Opm
global_whistctl_mode.template serializeOp<Serializer, false>(serializer);
m_actions.serializeOp(serializer);
m_network.serializeOp(serializer);
m_glo.serializeOp(serializer);
rft_config.serializeOp(serializer);
m_nupcol.template serializeOp<Serializer, false>(serializer);
restart_config.serializeOp(serializer);
@ -346,6 +349,7 @@ namespace Opm
DynamicState<Well::ProducerCMode> global_whistctl_mode;
DynamicState<std::shared_ptr<Action::Actions>> m_actions;
DynamicState<std::shared_ptr<Network::ExtNetwork>> m_network;
DynamicState<std::shared_ptr<GasLiftOpt>> m_glo;
RFTConfig rft_config;
DynamicState<int> m_nupcol;
RestartConfig restart_config;
@ -429,7 +433,9 @@ namespace Opm
void handleBRANPROP( const DeckKeyword& keyword, size_t currentStep);
void handleNODEPROP( const DeckKeyword& keyword, size_t currentStep);
void handleLIFTOPT(const DeckKeyword& keyword, std::size_t currentStep);
void handleGLIFTOPT(const DeckKeyword& keyword, std::size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWLIFTOPT(const DeckKeyword& keyword, std::size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
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);

View File

@ -0,0 +1,100 @@
/*
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 <stdexcept>
#include <opm/parser/eclipse/EclipseState/Schedule/GasLiftOpt.hpp>
namespace Opm {
bool GasLiftOpt::active() const {
return (this->m_increment > 0);
}
void GasLiftOpt::gaslift_increment(double gaslift_increment) {
this->m_increment = gaslift_increment;
}
void GasLiftOpt::min_eco_gradient(double min_eco_gradient) {
this->m_min_eco_gradient = min_eco_gradient;
}
void GasLiftOpt::min_wait(double min_wait) {
this->m_min_wait = min_wait;
}
void GasLiftOpt::all_newton(double all_newton) {
this->m_all_newton = all_newton;
}
const GasLiftOpt::Group& GasLiftOpt::group(const std::string& gname) const {
const auto iter = this->m_groups.find(gname);
if (iter == this->m_groups.end())
throw std::out_of_range("No such group: " + gname + " configured for gas lift optimization");
return iter->second;
}
void GasLiftOpt::add_group(const Group& group) {
auto iter = this->m_groups.find(group.name());
if (iter == this->m_groups.end())
this->m_groups.insert( std::make_pair(group.name(), group) );
else
iter->second = group;
}
void GasLiftOpt::add_well(const Well& well) {
auto iter = this->m_wells.find(well.name());
if (iter == this->m_wells.end())
this->m_wells.insert( std::make_pair(well.name(), well) );
else
iter->second = well;
}
const GasLiftOpt::Well& GasLiftOpt::well(const std::string& wname) const {
const auto iter = this->m_wells.find(wname);
if (iter == this->m_wells.end())
throw std::out_of_range("No such well: " + wname + " configured for gas lift optimization");
return iter->second;
}
GasLiftOpt GasLiftOpt::serializeObject() {
GasLiftOpt glo;
glo.m_increment = 0;
glo.m_min_eco_gradient = 100;
glo.m_min_wait = 1;
glo.m_all_newton = true;
return glo;
}
bool GasLiftOpt::operator==(const GasLiftOpt& other) const {
return this->m_increment == other.m_increment &&
this->m_min_eco_gradient == other.m_min_eco_gradient &&
this->m_min_wait == other.m_min_wait &&
this->m_all_newton == other.m_all_newton &&
this->m_groups == other.m_groups &&
this->m_wells == other.m_wells;
}
}

View File

@ -149,6 +149,7 @@ std::pair<std::time_t, std::size_t> restart_info(const RestartIO::RstState * rst
global_whistctl_mode(this->m_timeMap, Well::ProducerCMode::CMODE_UNDEFINED),
m_actions(this->m_timeMap, std::make_shared<Action::Actions>()),
m_network(this->m_timeMap, std::make_shared<Network::ExtNetwork>()),
m_glo(this->m_timeMap, std::make_shared<GasLiftOpt>()),
rft_config(this->m_timeMap),
m_nupcol(this->m_timeMap, ParserKeywords::NUPCOL::NUM_ITER::defaultValue),
restart_config(m_timeMap, deck, parseContext, errors),
@ -263,6 +264,7 @@ Schedule::Schedule(const Deck& deck, const EclipseState& es, const ParseContext&
result.wlist_manager = {{std::make_shared<WListManager>(WListManager::serializeObject())}, 1};
result.udq_config = {{std::make_shared<UDQConfig>(UDQConfig::serializeObject())}, 1};
result.m_network = {{std::make_shared<Network::ExtNetwork>(Network::ExtNetwork::serializeObject())}, 1};
result.m_glo = {{std::make_shared<GasLiftOpt>(GasLiftOpt::serializeObject())}, 1};
result.udq_active = {{std::make_shared<UDQActive>(UDQActive::serializeObject())}, 1};
result.guide_rate_config = {{std::make_shared<GuideRateConfig>(GuideRateConfig::serializeObject())}, 1};
result.gconsale = {{std::make_shared<GConSale>(GConSale::serializeObject())}, 1};
@ -492,6 +494,15 @@ Schedule::Schedule(const Deck& deck, const EclipseState& es, const ParseContext&
else if (keyword.name() == "BRANPROP")
handleBRANPROP(keyword, currentStep);
else if (keyword.name() == "LIFTOPT")
handleLIFTOPT(keyword, currentStep);
else if (keyword.name() == "GLIFTOPT")
handleGLIFTOPT(keyword, currentStep, parseContext, errors);
else if (keyword.name() == "WLIFTOPT")
handleWLIFTOPT(keyword, currentStep, parseContext, errors);
else if (keyword.name() == "PYACTION")
handlePYACTION(python, input_path, keyword, currentStep);
@ -3031,6 +3042,7 @@ void Schedule::invalidNamePattern( const std::string& namePattern, std::size_t
compareMap(this->vfpprod_tables, data.vfpprod_tables) &&
compareMap(this->vfpinj_tables, data.vfpinj_tables) &&
compareDynState(this->m_network, data.m_network) &&
compareDynState(this->m_glo, data.m_glo) &&
compareDynState(this->wtest_config, data.wtest_config) &&
compareDynState(this->wlist_manager, data.wlist_manager) &&
compareDynState(this->udq_config, data.udq_config) &&
@ -3175,6 +3187,93 @@ void Schedule::handleNODEPROP(const DeckKeyword& keyword, std::size_t report_ste
this->updateNetwork(ext_network, report_step);
}
const GasLiftOpt& Schedule::glo(std::size_t report_step) const {
return *this->m_glo[report_step];
}
void Schedule::handleLIFTOPT(const DeckKeyword& keyword, std::size_t report_step) {
using LO = ParserKeywords::LIFTOPT;
auto glo = std::make_shared<GasLiftOpt>( this->glo(report_step) );
const auto& record = keyword.getRecord(0);
double gaslift_increment = record.getItem<LO::INCREMENT_SIZE>().getSIDouble(0);
double min_eco_gradient = record.getItem<LO::MIN_ECONOMIC_GRADIENT>().getSIDouble(0);
double min_wait = record.getItem<LO::MIN_INTERVAL_BETWEEN_GAS_LIFT_OPTIMIZATIONS>().getSIDouble(0);
bool all_newton = DeckItem::to_bool( record.getItem<LO::OPTIMISE_GAS_LIFT>().get<std::string>(0) );
glo->gaslift_increment(gaslift_increment);
glo->min_eco_gradient(min_eco_gradient);
glo->min_wait(min_wait);
glo->all_newton(all_newton);
this->m_glo.update(report_step, std::move(glo));
}
void Schedule::handleGLIFTOPT(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors) {
using GLO = ParserKeywords::GLIFTOPT;
auto glo = std::make_shared<GasLiftOpt>( this->glo(report_step) );
for (const auto& record : keyword) {
const std::string& groupNamePattern = record.getItem<GLO::GROUP_NAME>().getTrimmedString(0);
const auto group_names = this->groupNames(groupNamePattern);
if (group_names.empty())
invalidNamePattern(groupNamePattern, report_step, parseContext, errors, keyword);
const auto& max_total_item = record.getItem<GLO::MAX_TOTAL_GAS_RATE>();
const auto& max_gas_item = record.getItem<GLO::MAX_LIFT_GAS_SUPPLY>();
double max_lift_gas_value = -1;
double max_total_gas_value = -1;
if (max_gas_item.hasValue(0))
max_lift_gas_value = max_gas_item.getSIDouble(0);
if (max_total_item.hasValue(0))
max_total_gas_value = max_total_item.getSIDouble(0);
for (const auto& gname : group_names) {
auto group = GasLiftOpt::Group(gname);
group.max_lift_gas(max_lift_gas_value);
group.max_total_gas(max_total_gas_value);
glo->add_group(group);
}
}
this->m_glo.update(report_step, std::move(glo));
}
void Schedule::handleWLIFTOPT(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors) {
using WLO = ParserKeywords::WLIFTOPT;
auto glo = std::make_shared<GasLiftOpt>( this->glo(report_step) );
for (const auto& record : keyword) {
const std::string& wellNamePattern = record.getItem<WLO::WELL>().getTrimmedString(0);
bool use_glo = DeckItem::to_bool( record.getItem<WLO::USE_OPTIMIZER>().get<std::string>(0));
bool alloc_extra_gas = DeckItem::to_bool( record.getItem<WLO::ALLOCATE_EXTRA_LIFT_GAS>().get<std::string>(0));
double weight_factor = record.getItem<WLO::WEIGHT_FACTOR>().get<double>(0);
double inc_weight_factor = record.getItem<WLO::DELTA_GAS_RATE_WEIGHT_FACTOR>().get<double>(0);
double min_rate = record.getItem<WLO::MIN_LIFT_GAS_RATE>().getSIDouble(0);
const auto& max_rate_item = record.getItem<WLO::MAX_LIFT_GAS_RATE>();
const auto well_names = this->wellNames(wellNamePattern);
if (well_names.empty())
invalidNamePattern(wellNamePattern, report_step, parseContext, errors, keyword);
for (const auto& wname : well_names) {
auto well = GasLiftOpt::Well(wname, use_glo);
if (max_rate_item.hasValue(0))
well.max_rate( max_rate_item.getSIDouble(0) );
well.weight_factor(weight_factor);
well.inc_weight_factor(inc_weight_factor);
well.min_rate(min_rate);
well.alloc_extra_gas(alloc_extra_gas);
glo->add_well(well);
}
}
this->m_glo.update(report_step, std::move(glo));
}
void Schedule::handleBRANPROP(const DeckKeyword& keyword, std::size_t report_step) {
using BP = ParserKeywords::BRANPROP;

View File

@ -11,11 +11,13 @@
{
"name": "MAX_LIFT_GAS_SUPPLY",
"value_type": "DOUBLE",
"dimension" : "GasSurfaceVolume/Time",
"default": -1e+20
},
{
"name": "MAX_TOTAL_GAS_RATE",
"value_type": "DOUBLE",
"dimension" : "GasSurfaceVolume/Time",
"default": -1e+20
}
]

View File

@ -7,15 +7,18 @@
"items": [
{
"name": "INCREMENT_SIZE",
"value_type": "DOUBLE"
"value_type": "DOUBLE",
"dimension" : "GasSurfaceVolume/Time"
},
{
"name": "MIN_ECONOMIC_GRADIENT",
"value_type": "DOUBLE"
"value_type": "DOUBLE",
"dimension" : "LiquidSurfaceVolume/GasSurfaceVolume"
},
{
"name": "MIN_INTERVAL_BETWEEN_GAS_LIFT_OPTIMIZATIONS",
"value_type": "DOUBLE",
"dimension" : "Time",
"default": 0
},
{

View File

@ -39,6 +39,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellConnections.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/GasLiftOpt.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
@ -3604,3 +3605,85 @@ BOOST_AUTO_TEST_CASE(SKIPREST_VFP) {
const auto& tables = sched.getVFPProdTables(3);
BOOST_CHECK( !tables.empty() );
}
BOOST_AUTO_TEST_CASE(GASLIFT_OPT) {
GasLiftOpt glo;
BOOST_CHECK(!glo.active());
BOOST_CHECK_THROW(glo.group("NO_SUCH_GROUP"), std::out_of_range);
BOOST_CHECK_THROW(glo.well("NO_SUCH_WELL"), std::out_of_range);
}
BOOST_AUTO_TEST_CASE(GASLIFT_OPT_DECK) {
const auto input = R"(-- Turns on gas lift optimization
SCHEDULE
GRUPTREE
'PROD' 'FIELD' /
'M5S' 'PLAT-A' /
'M5N' 'PLAT-A' /
'C1' 'M5N' /
'F1' 'M5N' /
'B1' 'M5S' /
'G1' 'M5S' /
/
LIFTOPT
12500 5E-3 0.0 YES /
-- Group lift gas limits for gas lift optimization
GLIFTOPT
'PLAT-A' 200000 / --
/
WELSPECS
--WELL GROUP IHEEL JHEEL DREF PHASE DRAD INFEQ SIINS XFLOW PRTAB DENS
'B-1H' 'B1' 11 3 1* OIL 1* 1* SHUT 1* 1* 1* /
'B-2H' 'B1' 4 7 1* OIL 1* 1* SHUT 1* 1* 1* /
'B-3H' 'B1' 11 12 1* OIL 1* 1* SHUT 1* 1* 1* /
'C-1H' 'C1' 13 20 1* OIL 1* 1* SHUT 1* 1* 1* /
'C-2H' 'C1' 12 27 1* OIL 1* 1* SHUT 1* 1* 1* /
/
-- well savailable for gass lift
-- minimum gas lift rate, enough to keep well flowing
WLIFTOPT
'B-1H' YES 150000 1.01 -1.0 /
'B-2H' YES 150000 1.01 -1.0 /
'B-3H' YES 150000 1.01 -1.0 /
'C-1H' YES 150000 1.01 -1.0 1.0 YES/
'C-2H' NO 150000 1.01 -1.0 /
/
)";
Opm::UnitSystem unitSystem = UnitSystem( UnitSystem::UnitType::UNIT_TYPE_METRIC );
double siFactorG = unitSystem.parse("GasSurfaceVolume/Time").getSIScaling();
const auto sched = make_schedule(input);
const auto& glo = sched.glo(0);
const auto& plat_group = glo.group("PLAT-A");
BOOST_CHECK_EQUAL( *plat_group.max_lift_gas(), siFactorG * 200000);
BOOST_CHECK(!plat_group.max_total_gas().has_value());
const auto& w1 = glo.well("B-1H");
BOOST_CHECK(w1.use_glo());
BOOST_CHECK_EQUAL(*w1.max_rate(), 150000 * siFactorG);
BOOST_CHECK_EQUAL(w1.weight_factor(), 1.01);
const auto& w2 = glo.well("C-2H");
BOOST_CHECK_EQUAL(w2.weight_factor(), 1.00);
BOOST_CHECK_EQUAL(w2.min_rate(), 0.00);
BOOST_CHECK_EQUAL(w2.inc_weight_factor(), 0.00);
BOOST_CHECK(!w2.alloc_extra_gas());
const auto& w3 = glo.well("C-1H");
BOOST_CHECK_EQUAL(w3.min_rate(), -1.00 * siFactorG);
BOOST_CHECK_EQUAL(w3.inc_weight_factor(), 1.00);
BOOST_CHECK(w3.alloc_extra_gas());
}