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
}