2012-03-29 18:34:51 +02:00
/*
2013-01-29 13:42:24 +01:00
Copyright 2011 SINTEF ICT , Applied Mathematics .
2012-03-29 18:34:51 +02:00
2013-01-29 13:42:24 +01:00
This file is part of the Open Porous Media project ( OPM ) .
2012-03-29 18:34:51 +02:00
2013-01-29 13:42:24 +01: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 18:34:51 +02:00
2013-01-29 13:42:24 +01: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 18:34:51 +02:00
2013-01-29 13:42:24 +01: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 18:34:51 +02:00
2013-04-10 12:56:14 +02:00
# include "config.h"
2012-06-05 15:42:49 +02:00
# include <opm/core/wells/WellCollection.hpp>
2014-02-12 15:39:57 +01:00
# include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
# include <opm/parser/eclipse/EclipseState/Schedule/Group.hpp>
2014-02-14 13:43:25 +01:00
# include <boost/lexical_cast.hpp>
2013-08-08 12:32:01 +02:00
# include <memory>
2012-03-29 18:34:51 +02:00
namespace Opm
{
2014-02-13 16:00:39 +01:00
void WellCollection : : addField ( GroupConstPtr fieldGroup , size_t timeStep , const PhaseUsage & phaseUsage ) {
WellsGroupInterface * fieldNode = findNode ( fieldGroup - > name ( ) ) ;
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 ) ) ;
}
void WellCollection : : addGroup ( GroupConstPtr groupChild , std : : string parent_name ,
2014-02-12 15:39:57 +01:00
size_t timeStep , const PhaseUsage & phaseUsage ) {
2014-02-13 16:00:39 +01:00
WellsGroupInterface * parent = findNode ( parent_name ) ;
2014-02-12 15:39:57 +01:00
if ( ! parent ) {
2014-02-14 13:43:25 +01: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 15:39:57 +01:00
}
2014-02-13 16:00:39 +01:00
if ( findNode ( groupChild - > name ( ) ) ) {
2014-02-14 13:43:25 +01:00
OPM_THROW ( std : : runtime_error , " Trying to add child group named " < < groupChild - > name ( ) < < " , but this group is already in the WellCollection. " ) ;
2014-02-12 15:39:57 +01:00
}
2014-02-13 16:00:39 +01:00
std : : shared_ptr < WellsGroupInterface > child = createGroupWellsGroup ( groupChild , timeStep , phaseUsage ) ;
2014-02-12 15:39:57 +01:00
WellsGroup * parent_as_group = static_cast < WellsGroup * > ( parent ) ;
if ( ! parent_as_group ) {
2014-02-14 13:43:25 +01: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 15:39:57 +01:00
}
parent_as_group - > addChild ( child ) ;
child - > setParent ( parent ) ;
}
2014-02-13 16:00:39 +01:00
void WellCollection : : addWell ( WellConstPtr wellChild , size_t timeStep , const PhaseUsage & phaseUsage ) {
WellsGroupInterface * parent = findNode ( wellChild - > getGroupName ( timeStep ) ) ;
2014-02-12 15:39:57 +01:00
if ( ! parent ) {
2014-02-14 13:43:25 +01: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 15:39:57 +01:00
}
2014-02-13 16:00:39 +01:00
std : : shared_ptr < WellsGroupInterface > child = createWellWellsGroup ( wellChild , timeStep , phaseUsage ) ;
2014-02-12 15:39:57 +01:00
WellsGroup * parent_as_group = static_cast < WellsGroup * > ( parent ) ;
if ( ! parent_as_group ) {
2014-02-14 13:43:25 +01: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 15:39:57 +01:00
}
parent_as_group - > addChild ( child ) ;
2014-02-13 16:00:39 +01:00
leaf_nodes_ . push_back ( static_cast < WellNode * > ( child . get ( ) ) ) ;
2014-02-12 15:39:57 +01:00
child - > setParent ( parent ) ;
}
2012-04-25 14:19:47 +02:00
const std : : vector < WellNode * > & WellCollection : : getLeafNodes ( ) const {
2012-03-30 10:51:31 +02:00
return leaf_nodes_ ;
2012-03-29 18:34:51 +02:00
}
2012-04-25 16:42:55 +02:00
WellsGroupInterface * WellCollection : : findNode ( const std : : string & name )
2012-03-29 18:34:51 +02:00
{
2012-04-10 15:01:52 +02:00
for ( size_t i = 0 ; i < roots_ . size ( ) ; i + + ) {
2012-03-29 18:34:51 +02:00
WellsGroupInterface * result = roots_ [ i ] - > findGroup ( name ) ;
if ( result ) {
return result ;
}
}
return NULL ;
}
2013-07-28 08:34:13 -03:00
2012-04-25 16:42:55 +02:00
const WellsGroupInterface * WellCollection : : findNode ( const std : : string & name ) const
2012-04-23 13:24:47 +02: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 16:10:37 +02: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 12:32:01 +02:00
void WellCollection : : addChild ( std : : shared_ptr < WellsGroupInterface > & child_node ,
2012-05-14 16:10:37 +02:00
const std : : string & parent_name )
{
WellsGroupInterface * parent = findNode ( parent_name ) ;
if ( parent = = NULL ) {
2013-08-28 13:59:03 +02:00
OPM_THROW ( std : : runtime_error , " Parent with name = " < < parent_name < < " not found. " ) ;
2012-05-14 16:10:37 +02:00
}
2013-08-28 14:00:35 +02:00
assert ( ! parent - > isLeafNode ( ) ) ;
2012-05-14 16:10:37 +02: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 12:32:01 +02:00
void WellCollection : : addChild ( std : : shared_ptr < WellsGroupInterface > & child_node )
2012-05-14 16:10:37 +02:00
{
roots_ . push_back ( child_node ) ;
if ( child_node - > isLeafNode ( ) ) {
leaf_nodes_ . push_back ( static_cast < WellNode * > ( child_node . get ( ) ) ) ;
}
}
2013-07-28 08:34:13 -03:00
2012-04-25 16:14:40 +02:00
bool WellCollection : : conditionsMet ( const std : : vector < double > & well_bhp ,
2012-05-02 13:02:59 +02:00
const std : : vector < double > & well_reservoirrates_phase ,
const std : : vector < double > & well_surfacerates_phase )
2012-04-25 14:03:57 +02:00
{
2012-04-25 16:14:40 +02:00
for ( size_t i = 0 ; i < roots_ . size ( ) ; i + + ) {
WellPhasesSummed phases ;
2012-05-02 13:02:59 +02:00
if ( ! roots_ [ i ] - > conditionsMet ( well_bhp ,
well_reservoirrates_phase ,
well_surfacerates_phase ,
phases ) ) {
2012-04-25 16:14:40 +02:00
return false ;
}
}
return true ;
2012-04-12 14:25:39 +02:00
}
2013-07-28 08:34:13 -03:00
2012-04-25 16:14:40 +02:00
void WellCollection : : setWellsPointer ( Wells * wells ) {
2012-04-25 14:19:47 +02:00
for ( size_t i = 0 ; i < leaf_nodes_ . size ( ) ; i + + ) {
leaf_nodes_ [ i ] - > setWellsPointer ( wells , i ) ;
}
}
2013-07-28 08:34:13 -03:00
2012-05-02 13:02:59 +02:00
void WellCollection : : applyGroupControls ( )
{
for ( size_t i = 0 ; i < roots_ . size ( ) ; + + i ) {
roots_ [ i ] - > applyProdGroupControls ( ) ;
roots_ [ i ] - > applyInjGroupControls ( ) ;
}
}
2012-05-09 13:03:37 +02: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 ) ;
}
}
2012-04-25 14:03:57 +02:00
}