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
}
2014-02-13 09:00:39 -06:00
std : : shared_ptr < WellsGroupInterface > child = createGroupWellsGroup ( groupChild , 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 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
/// 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 ( ) ;
}
}
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
//TODO: later, it should be extended to update group targets
bool WellCollection : : needUpdateWellTargets ( ) const
{
for ( size_t i = 0 ; i < leaf_nodes_ . size ( ) ; + + i ) {
if ( leaf_nodes_ [ i ] - > shouldUpdateWellTargets ( ) & & ! leaf_nodes_ [ i ] - > individualControl ( ) ) {
return true ;
}
}
return false ;
}
const size_t WellCollection : : numNode ( ) const
{
return leaf_nodes_ . size ( ) ;
}
WellNode * WellCollection : : getNode ( size_t i ) const
{
assert ( i < numNode ( ) ) ;
return leaf_nodes_ [ i ] ;
}
2012-04-25 07:03:57 -05:00
}