2012-03-29 11:34:51 -05:00
/*
2013-01-29 06:42:24 -06:00
Copyright 2011 SINTEF ICT , Applied Mathematics .
2012-03-29 11:34:51 -05:00
2013-01-29 06:42:24 -06:00
This file is part of the Open Porous Media project ( OPM ) .
2012-03-29 11:34:51 -05:00
2013-01-29 06:42:24 -06:00
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 .
2012-03-29 11:34:51 -05:00
2013-01-29 06:42:24 -06:00
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 .
2012-03-29 11:34:51 -05:00
2013-01-29 06:42:24 -06:00
You should have received a copy of the GNU General Public License
along with OPM . If not , see < http : //www.gnu.org/licenses/>.
*/
2012-03-29 11:34:51 -05:00
2013-04-10 05:56:14 -05:00
# include "config.h"
2012-06-05 08:42:49 -05:00
# include <opm/core/wells/WellCollection.hpp>
2014-02-12 08:39:57 -06:00
# include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
# include <opm/parser/eclipse/EclipseState/Schedule/Group.hpp>
2014-02-14 06:43:25 -06:00
# include <boost/lexical_cast.hpp>
2013-08-08 05:32:01 -05:00
# include <memory>
2012-03-29 11:34:51 -05:00
namespace Opm
{
2016-10-05 08:24:14 -05:00
void WellCollection : : addField ( const Group & fieldGroup , size_t timeStep , const PhaseUsage & phaseUsage ) {
WellsGroupInterface * fieldNode = findNode ( fieldGroup . name ( ) ) ;
2014-02-13 09:00:39 -06:00
if ( fieldNode ) {
OPM_THROW ( std : : runtime_error , " Trying to add FIELD node, but this already exists. Can only have one FIELD node. " ) ;
}
roots_ . push_back ( createGroupWellsGroup ( fieldGroup , timeStep , phaseUsage ) ) ;
}
2016-10-05 08:24:14 -05:00
void WellCollection : : addGroup ( const Group & groupChild , std : : string parent_name ,
2014-02-12 08:39:57 -06:00
size_t timeStep , const PhaseUsage & phaseUsage ) {
2014-02-13 09:00:39 -06:00
WellsGroupInterface * parent = findNode ( parent_name ) ;
2014-02-12 08:39:57 -06:00
if ( ! parent ) {
2014-02-14 06:43:25 -06:00
OPM_THROW ( std : : runtime_error , " Trying to add child group to group named " < < parent_name < < " , but this does not exist in the WellCollection. " ) ;
2014-02-12 08:39:57 -06:00
}
2016-10-05 08:24:14 -05:00
if ( findNode ( groupChild . name ( ) ) ) {
OPM_THROW ( std : : runtime_error , " Trying to add child group named " < < groupChild . name ( ) < < " , but this group is already in the WellCollection. " ) ;
2014-02-12 08:39:57 -06:00
}
2016-11-17 07:20:01 -06:00
if ( groupChild . isProductionGroup ( timeStep ) | | groupChild . isInjectionGroup ( timeStep ) ) {
group_control_active_ = true ;
}
2014-02-13 09:00:39 -06:00
std : : shared_ptr < WellsGroupInterface > child = createGroupWellsGroup ( groupChild , timeStep , phaseUsage ) ;
2016-10-21 10:39:31 -05:00
if ( child - > injSpec ( ) . control_mode_ = = InjectionSpecification : : VREP ) {
having_vrep_groups_ = true ;
}
2014-02-12 08:39:57 -06:00
WellsGroup * parent_as_group = static_cast < WellsGroup * > ( parent ) ;
if ( ! parent_as_group ) {
2014-02-14 06:43:25 -06:00
OPM_THROW ( std : : runtime_error , " Trying to add child group to group named " < < parent - > name ( ) < < " , but it's not a group. " ) ;
2014-02-12 08:39:57 -06:00
}
parent_as_group - > addChild ( child ) ;
child - > setParent ( parent ) ;
}
2016-06-16 02:33:43 -05:00
void WellCollection : : addWell ( const Well * wellChild , size_t timeStep , const PhaseUsage & phaseUsage ) {
2016-04-08 08:47:49 -05:00
if ( wellChild - > getStatus ( timeStep ) = = WellCommon : : SHUT ) {
//SHUT wells are not added to the well collection
return ;
}
2014-02-13 09:00:39 -06:00
WellsGroupInterface * parent = findNode ( wellChild - > getGroupName ( timeStep ) ) ;
2014-02-12 08:39:57 -06:00
if ( ! parent ) {
2014-02-14 06:43:25 -06:00
OPM_THROW ( std : : runtime_error , " Trying to add well " < < wellChild - > name ( ) < < " Step: " < < boost : : lexical_cast < std : : string > ( timeStep ) < < " to group named " < < wellChild - > getGroupName ( timeStep ) < < " , but this group does not exist in the WellCollection. " ) ;
2014-02-12 08:39:57 -06:00
}
2014-02-13 09:00:39 -06:00
std : : shared_ptr < WellsGroupInterface > child = createWellWellsGroup ( wellChild , timeStep , phaseUsage ) ;
2014-02-12 08:39:57 -06:00
WellsGroup * parent_as_group = static_cast < WellsGroup * > ( parent ) ;
if ( ! parent_as_group ) {
2014-02-14 06:43:25 -06:00
OPM_THROW ( std : : runtime_error , " Trying to add well to group named " < < wellChild - > getGroupName ( timeStep ) < < " , but it's not a group. " ) ;
2014-02-12 08:39:57 -06:00
}
parent_as_group - > addChild ( child ) ;
2014-02-13 09:00:39 -06:00
leaf_nodes_ . push_back ( static_cast < WellNode * > ( child . get ( ) ) ) ;
2014-02-12 08:39:57 -06:00
child - > setParent ( parent ) ;
}
2012-04-25 07:19:47 -05:00
const std : : vector < WellNode * > & WellCollection : : getLeafNodes ( ) const {
2012-03-30 03:51:31 -05:00
return leaf_nodes_ ;
2012-03-29 11:34:51 -05:00
}
2012-04-25 09:42:55 -05:00
WellsGroupInterface * WellCollection : : findNode ( const std : : string & name )
2012-03-29 11:34:51 -05:00
{
2012-04-10 08:01:52 -05:00
for ( size_t i = 0 ; i < roots_ . size ( ) ; i + + ) {
2012-03-29 11:34:51 -05:00
WellsGroupInterface * result = roots_ [ i ] - > findGroup ( name ) ;
if ( result ) {
return result ;
}
}
return NULL ;
}
2013-07-28 06:34:13 -05:00
2012-04-25 09:42:55 -05:00
const WellsGroupInterface * WellCollection : : findNode ( const std : : string & name ) const
2012-04-23 06:24:47 -05:00
{
for ( size_t i = 0 ; i < roots_ . size ( ) ; i + + ) {
WellsGroupInterface * result = roots_ [ i ] - > findGroup ( name ) ;
if ( result ) {
return result ;
}
}
return NULL ;
}
2012-05-14 09:10:37 -05:00
2016-11-03 07:12:12 -05:00
2016-11-16 07:27:15 -06:00
WellNode & WellCollection : : findWellNode ( const std : : string & name ) const
2016-11-03 07:12:12 -05:00
{
auto well_node = std : : find_if ( leaf_nodes_ . begin ( ) , leaf_nodes_ . end ( ) ,
[ & ] ( WellNode * w ) {
return w - > name ( ) = = name ;
} ) ;
2016-11-16 07:27:15 -06:00
// Does not find the well
if ( well_node = = leaf_nodes_ . end ( ) ) {
OPM_THROW ( std : : runtime_error , " Could not find well " < < name < < " in the well collection! \n " ) ;
2016-11-03 07:12:12 -05:00
}
2016-11-16 07:27:15 -06:00
return * ( * well_node ) ;
2016-11-03 07:12:12 -05:00
}
2012-05-14 09:10:37 -05:00
/// Adds the child to the collection
/// and appends it to parent's children.
/// \param[in] child the child node
/// \param[in] parent name of parent node
2013-08-08 05:32:01 -05:00
void WellCollection : : addChild ( std : : shared_ptr < WellsGroupInterface > & child_node ,
2012-05-14 09:10:37 -05:00
const std : : string & parent_name )
{
WellsGroupInterface * parent = findNode ( parent_name ) ;
if ( parent = = NULL ) {
2013-08-28 06:59:03 -05:00
OPM_THROW ( std : : runtime_error , " Parent with name = " < < parent_name < < " not found. " ) ;
2012-05-14 09:10:37 -05:00
}
2013-08-28 07:00:35 -05:00
assert ( ! parent - > isLeafNode ( ) ) ;
2012-05-14 09:10:37 -05:00
static_cast < WellsGroup * > ( parent ) - > addChild ( child_node ) ;
if ( child_node - > isLeafNode ( ) ) {
leaf_nodes_ . push_back ( static_cast < WellNode * > ( child_node . get ( ) ) ) ;
}
}
/// Adds the node to the collection (as a root node)
2013-08-08 05:32:01 -05:00
void WellCollection : : addChild ( std : : shared_ptr < WellsGroupInterface > & child_node )
2012-05-14 09:10:37 -05:00
{
roots_ . push_back ( child_node ) ;
if ( child_node - > isLeafNode ( ) ) {
leaf_nodes_ . push_back ( static_cast < WellNode * > ( child_node . get ( ) ) ) ;
}
}
2013-07-28 06:34:13 -05:00
2012-04-25 09:14:40 -05:00
bool WellCollection : : conditionsMet ( const std : : vector < double > & well_bhp ,
2012-05-02 06:02:59 -05:00
const std : : vector < double > & well_reservoirrates_phase ,
const std : : vector < double > & well_surfacerates_phase )
2012-04-25 07:03:57 -05:00
{
2012-04-25 09:14:40 -05:00
for ( size_t i = 0 ; i < roots_ . size ( ) ; i + + ) {
WellPhasesSummed phases ;
2012-05-02 06:02:59 -05:00
if ( ! roots_ [ i ] - > conditionsMet ( well_bhp ,
well_reservoirrates_phase ,
well_surfacerates_phase ,
phases ) ) {
2012-04-25 09:14:40 -05:00
return false ;
}
}
return true ;
2012-04-12 07:25:39 -05:00
}
2013-07-28 06:34:13 -05:00
2012-04-25 09:14:40 -05:00
void WellCollection : : setWellsPointer ( Wells * wells ) {
2012-04-25 07:19:47 -05:00
for ( size_t i = 0 ; i < leaf_nodes_ . size ( ) ; i + + ) {
leaf_nodes_ [ i ] - > setWellsPointer ( wells , i ) ;
}
}
2013-07-28 06:34:13 -05:00
2012-05-02 06:02:59 -05:00
void WellCollection : : applyGroupControls ( )
{
for ( size_t i = 0 ; i < roots_ . size ( ) ; + + i ) {
roots_ [ i ] - > applyProdGroupControls ( ) ;
roots_ [ i ] - > applyInjGroupControls ( ) ;
}
2017-03-23 07:25:12 -05:00
group_control_applied_ = true ;
2012-05-02 06:02:59 -05:00
}
2012-05-09 06:03:37 -05:00
/// Applies explicit reinjection controls. This must be called at each timestep to be correct.
/// \param[in] well_reservoirrates_phase
/// A vector containing reservoir rates by phase for each well.
/// Is assumed to be ordered the same way as the related Wells-struct,
/// with all phase rates of a single well adjacent in the array.
/// \param[in] well_surfacerates_phase
/// A vector containing surface rates by phase for each well.
/// Is assumed to be ordered the same way as the related Wells-struct,
/// with all phase rates of a single well adjacent in the array.
void WellCollection : : applyExplicitReinjectionControls ( const std : : vector < double > & well_reservoirrates_phase ,
const std : : vector < double > & well_surfacerates_phase )
{
for ( size_t i = 0 ; i < roots_ . size ( ) ; + + i ) {
roots_ [ i ] - > applyExplicitReinjectionControls ( well_reservoirrates_phase , well_surfacerates_phase ) ;
}
}
2016-09-30 10:54:49 -05:00
2016-10-21 10:39:31 -05:00
void WellCollection : : applyVREPGroupControls ( const std : : vector < double > & well_voidage_rates ,
const std : : vector < double > & conversion_coeffs )
{
for ( size_t i = 0 ; i < roots_ . size ( ) ; + + i ) {
roots_ [ i ] - > applyVREPGroupControls ( well_voidage_rates , conversion_coeffs ) ;
}
}
2016-11-02 07:53:30 -05:00
// TODO: later, it should be extended to update group targets
2016-09-30 10:54:49 -05:00
bool WellCollection : : needUpdateWellTargets ( ) const
2016-10-07 07:54:53 -05:00
{
return needUpdateInjectionTargets ( ) | | needUpdateProductionTargets ( ) ;
}
bool WellCollection : : needUpdateInjectionTargets ( ) const
2016-09-30 10:54:49 -05:00
{
2016-11-02 07:53:30 -05:00
// TODO: it should based on individual group
// With current approach, it will potentially result in more update,
// thus more iterations, while it will not cause result wrong.
2016-11-04 07:37:50 -05:00
// If the group control and individual control is mixed, then it need to
// update the well targets
2016-10-06 11:00:08 -05:00
bool any_group_control_node = false ;
2016-11-04 07:37:50 -05:00
bool any_individual_control_node = false ;
2016-10-07 07:54:53 -05:00
2016-09-30 10:54:49 -05:00
for ( size_t i = 0 ; i < leaf_nodes_ . size ( ) ; + + i ) {
2016-10-07 07:54:53 -05:00
if ( leaf_nodes_ [ i ] - > isInjector ( ) ) {
2016-11-04 07:37:50 -05:00
if ( leaf_nodes_ [ i ] - > individualControl ( ) ) {
any_individual_control_node = true ;
} else {
2016-10-07 07:54:53 -05:00
any_group_control_node = true ;
}
2016-10-06 11:00:08 -05:00
}
2016-10-07 07:54:53 -05:00
}
2016-11-04 07:37:50 -05:00
return ( any_group_control_node & & any_individual_control_node ) ;
2016-10-07 07:54:53 -05:00
}
2016-11-04 07:37:50 -05:00
// These two functions should be made one
2016-10-10 07:47:19 -05:00
bool WellCollection : : needUpdateProductionTargets ( ) const
{
2016-11-02 07:53:30 -05:00
// TODO: it should based on individual group
// With current approach, it will potentially result in more update,
// thus more iterations, while it will not cause result wrong.
2016-11-04 07:37:50 -05:00
// If the group control and individual control is mixed, then it need to
// update the well targets
2016-10-07 07:54:53 -05:00
bool any_group_control_node = false ;
2016-11-04 07:37:50 -05:00
bool any_individual_control_node = false ;
2016-10-07 07:54:53 -05:00
for ( size_t i = 0 ; i < leaf_nodes_ . size ( ) ; + + i ) {
if ( leaf_nodes_ [ i ] - > isProducer ( ) ) {
2016-11-04 07:37:50 -05:00
if ( leaf_nodes_ [ i ] - > individualControl ( ) ) {
any_individual_control_node = true ;
} else {
2016-10-07 07:54:53 -05:00
any_group_control_node = true ;
}
2016-09-30 10:54:49 -05:00
}
}
2016-10-07 07:54:53 -05:00
2016-11-04 07:37:50 -05:00
return ( any_group_control_node & & any_individual_control_node ) ;
2016-09-30 10:54:49 -05:00
}
2016-11-16 02:51:06 -06:00
void WellCollection : : updateWellTargets ( const std : : vector < double > & well_rates )
2016-10-10 07:47:19 -05:00
{
2017-03-23 07:53:31 -05:00
// TODO: if it gets converged, should we still update targets?
2016-11-15 06:56:49 -06:00
2016-11-15 07:36:19 -06:00
// set the target_updated to be false
for ( WellNode * well_node : leaf_nodes_ ) {
well_node - > setTargetUpdated ( false ) ;
}
2016-10-10 07:47:19 -05:00
// TODO: currently, we only handle the level of the well groups for the moment, i.e. the level just above wells
// We believe the relations between groups are similar to the relations between different wells inside the same group.
// While there will be somre more complication invloved for sure.
for ( size_t i = 0 ; i < leaf_nodes_ . size ( ) ; + + i ) {
// find a node needs to update targets, then update targets for all the wellls inside the group.
2017-03-23 07:53:31 -05:00
if ( ! leaf_nodes_ [ i ] - > targetUpdated ( ) ) {
2016-10-10 08:30:15 -05:00
WellsGroupInterface * parent_node = leaf_nodes_ [ i ] - > getParent ( ) ;
2016-10-10 07:47:19 -05:00
// update the target within this group.
if ( leaf_nodes_ [ i ] - > isProducer ( ) ) {
2017-08-17 03:42:03 -05:00
if ( parent_node - > prodSpec ( ) . control_mode_ = = ProductionSpecification : : NONE ) {
continue ;
}
2016-10-10 07:47:19 -05:00
parent_node - > updateWellProductionTargets ( well_rates ) ;
}
if ( leaf_nodes_ [ i ] - > isInjector ( ) ) {
2017-08-17 03:42:03 -05:00
if ( parent_node - > injSpec ( ) . control_mode_ = = InjectionSpecification : : NONE ) {
continue ;
}
2016-10-10 07:47:19 -05:00
parent_node - > updateWellInjectionTargets ( well_rates ) ;
}
}
}
}
2016-11-16 04:40:10 -06:00
2016-11-17 07:20:01 -06:00
bool WellCollection : : havingVREPGroups ( ) const
{
2016-10-21 10:39:31 -05:00
return having_vrep_groups_ ;
}
2016-11-17 07:20:01 -06:00
bool WellCollection : : groupControlActive ( ) const
{
return group_control_active_ ;
}
2017-01-16 08:55:35 -06:00
2017-03-23 07:25:12 -05:00
bool WellCollection : : groupControlApplied ( ) const
{
return group_control_applied_ ;
}
2017-01-16 08:55:35 -06:00
bool WellCollection : : groupTargetConverged ( const std : : vector < double > & well_rates ) const
{
// TODO: eventually, there should be only one root node
// TODO: we also need to check the injection target, while we have not done that.
for ( const std : : shared_ptr < WellsGroupInterface > & root_node : roots_ ) {
if ( ! root_node - > groupProdTargetConverged ( well_rates ) ) {
return false ;
}
}
return true ;
}
2017-03-16 04:50:34 -05:00
void WellCollection : :
setGuideRatesWithPotentials ( const Wells * wells ,
const PhaseUsage & phase_usage ,
const std : : vector < double > & well_potentials ) const
{
// TODO: assuming the order of well_potentials is the same with the order in wells struct
// TODO: it will overwrite the well potentials from other means. It should be changed after
// fixing the other part of the code. It makes the current flow only support guide rates based on
// well potentials.
const int np = wells - > number_of_phases ;
const int nw = wells - > number_of_wells ;
for ( int w = 0 ; w < nw ; + + w ) {
const std : : string well_name = wells - > name [ w ] ;
WellNode & well_node = findWellNode ( well_name ) ;
const WellType well_type = wells - > type [ w ] ;
// TODO: eventually the following standard will be wrong, it will belong to FIELD group
if ( well_node . getParent ( ) ! = nullptr ) { // If it does not belong a group, will it belong to FIELD?
const WellsGroupInterface * group = well_node . getParent ( ) ;
if ( well_type = = PRODUCER ) {
// The guide rates is calculated based on the group control
// Currently only supporting WRAT, ORAT and GRAT.
ProductionSpecification : : ControlMode control_mode = group - > prodSpec ( ) . control_mode_ ;
if ( control_mode = = ProductionSpecification : : FLD ) {
if ( group - > getParent ( ) ! = nullptr ) {
// TODO: only handle one level FLD control
const WellsGroupInterface * higher_group = group - > getParent ( ) ;
control_mode = higher_group - > prodSpec ( ) . control_mode_ ;
} else {
OPM_THROW ( std : : runtime_error , " Group " < < group - > name ( ) < < " is under FLD control while no higher level of group is specified. " ) ;
}
}
switch ( control_mode ) {
case ProductionSpecification : : WRAT : {
if ( ! phase_usage . phase_used [ BlackoilPhases : : Aqua ] ) {
OPM_THROW ( std : : runtime_error , " Water phase not used, yet found water rate controlled well. " ) ;
}
const int water_index = phase_usage . phase_pos [ BlackoilPhases : : Aqua ] ;
well_node . prodSpec ( ) . guide_rate_ = well_potentials [ np * w + water_index ] ;
well_node . prodSpec ( ) . guide_rate_type_ = ProductionSpecification : : WATER ;
break ;
}
case ProductionSpecification : : ORAT : {
if ( ! phase_usage . phase_used [ BlackoilPhases : : Liquid ] ) {
OPM_THROW ( std : : runtime_error , " Oil phase not used, yet found oil rate controlled well. " ) ;
}
const int oil_index = phase_usage . phase_pos [ BlackoilPhases : : Liquid ] ;
well_node . prodSpec ( ) . guide_rate_ = well_potentials [ np * w + oil_index ] ;
well_node . prodSpec ( ) . guide_rate_type_ = ProductionSpecification : : OIL ;
break ;
}
case ProductionSpecification : : GRAT : {
if ( ! phase_usage . phase_used [ BlackoilPhases : : Vapour ] ) {
OPM_THROW ( std : : runtime_error , " Gas phase not used, yet found gas rate controlled well. " ) ;
}
const int gas_index = phase_usage . phase_pos [ BlackoilPhases : : Vapour ] ;
well_node . prodSpec ( ) . guide_rate_ = well_potentials [ np * w + gas_index ] ;
well_node . prodSpec ( ) . guide_rate_type_ = ProductionSpecification : : GAS ;
break ;
}
case ProductionSpecification : : FLD : {
OPM_THROW ( std : : logic_error , " Not support more than one continous level of FLD control " ) ;
}
case ProductionSpecification : : LRAT : {
double guide_rate = 0 ;
if ( phase_usage . phase_used [ BlackoilPhases : : Liquid ] ) {
const int oil_index = phase_usage . phase_pos [ BlackoilPhases : : Liquid ] ;
const double potential_oil = well_potentials [ np * w + oil_index ] ;
guide_rate + = potential_oil ;
}
if ( phase_usage . phase_used [ BlackoilPhases : : Aqua ] ) {
const int water_index = phase_usage . phase_pos [ BlackoilPhases : : Aqua ] ;
const double potential_water = well_potentials [ np * w + water_index ] ;
guide_rate + = potential_water ;
}
// not sure if no water and no oil, what will happen here, zero guide_rate?
well_node . prodSpec ( ) . guide_rate_ = guide_rate ;
well_node . prodSpec ( ) . guide_rate_type_ = ProductionSpecification : : LIQ ;
2017-04-04 07:50:15 -05:00
break ;
2017-03-16 04:50:34 -05:00
}
case ProductionSpecification : : NONE : {
// Group control is not in use for this group.
break ;
}
default :
OPM_THROW ( std : : logic_error , " Not supported control_mode for guide rate computed " < <
" from well potentials: " < < ProductionSpecification : : toString ( group - > prodSpec ( ) . control_mode_ ) ) ;
}
} else if ( well_type = = INJECTOR ) {
// The guide rates is calculated based on the group injector type
switch ( group - > injSpec ( ) . injector_type_ ) {
case InjectionSpecification : : WATER : {
if ( ! phase_usage . phase_used [ BlackoilPhases : : Aqua ] ) {
OPM_THROW ( std : : runtime_error , " Water phase not used, yet found water injecting well. " ) ;
}
const int water_index = phase_usage . phase_pos [ BlackoilPhases : : Aqua ] ;
well_node . injSpec ( ) . guide_rate_ = well_potentials [ np * w + water_index ] ;
// Guide rates applies to the phase that the well is injecting i.e water
well_node . injSpec ( ) . guide_rate_type_ = InjectionSpecification : : RAT ;
break ;
}
case InjectionSpecification : : OIL : {
if ( ! phase_usage . phase_used [ BlackoilPhases : : Liquid ] ) {
OPM_THROW ( std : : runtime_error , " Oil phase not used, yet found oil injecting well. " ) ;
}
const int oil_index = phase_usage . phase_pos [ BlackoilPhases : : Liquid ] ;
well_node . injSpec ( ) . guide_rate_ = well_potentials [ np * w + oil_index ] ;
// Guide rates applies to the phase that the well is injecting i.e. oil
well_node . injSpec ( ) . guide_rate_type_ = InjectionSpecification : : RAT ;
break ;
}
case InjectionSpecification : : GAS : {
if ( ! phase_usage . phase_used [ BlackoilPhases : : Vapour ] ) {
OPM_THROW ( std : : runtime_error , " Gas phase not used, yet found gas injecting well. " ) ;
}
const int gas_index = phase_usage . phase_pos [ BlackoilPhases : : Vapour ] ;
well_node . injSpec ( ) . guide_rate_ = well_potentials [ np * w + gas_index ] ;
// Guide rates applies to the phase that the well is injecting i.e gas
well_node . injSpec ( ) . guide_rate_type_ = InjectionSpecification : : RAT ;
break ;
}
default :
OPM_THROW ( std : : logic_error , " Not supported injector type for guide rate computed " < <
" from well potentials: " < < InjectionSpecification : : toString ( group - > injSpec ( ) . injector_type_ ) ) ;
}
} else { // neither injector nor producer
OPM_THROW ( std : : logic_error , " Expected well type to be either INJECTOR or PRODUCER for well " < < well_node . name ( ) ) ;
}
} // end of if (well_node.getParent() != nullptr)
} // end of for (int w = 0; w < nw; ++w)
}
2017-04-07 03:59:46 -05:00
bool WellCollection : : requireWellPotentials ( ) const
{
for ( const auto & well_node : leaf_nodes_ ) {
if ( well_node - > isGuideRateWellPotential ( ) ) {
return true ;
}
}
return false ;
}
2012-04-25 07:03:57 -05:00
}