diff --git a/Makefile.am b/Makefile.am
index b8bae41a..793aa8dd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,7 +57,9 @@ opm/core/utility/newwells.c \
opm/core/utility/writeVtkData.cpp \
opm/core/GridManager.cpp \
opm/core/WellsManager.cpp \
-opm/core/InjectionSpecification.cpp \
+opm/core/WellsGroup.cpp \
+opm/core/WellCollection.cpp \
+opm/core/InjectionSpecification.cpp \
opm/core/ProductionSpecification.cpp \
opm/core/linalg/sparse_sys.c \
opm/core/linalg/LinearSolverInterface.cpp \
@@ -164,6 +166,8 @@ opm/core/linalg/LinearSolverInterface.hpp \
opm/core/grid.h \
opm/core/well.h \
opm/core/newwells.h \
+opm/core/WellsGroup.hpp \
+opm/core/WellCollection.hpp \
opm/core/InjectionSpecification.hpp \
opm/core/ProductionSpecification.hpp \
opm/core/ColumnExtract.hpp \
diff --git a/opm/core/InjectionSpecification.cpp b/opm/core/InjectionSpecification.cpp
index 0400738d..641526d6 100644
--- a/opm/core/InjectionSpecification.cpp
+++ b/opm/core/InjectionSpecification.cpp
@@ -3,8 +3,8 @@ namespace Opm
{
InjectionSpecification::InjectionSpecification()
- : component_(WATER), control_mode_(NONE), surface_injection_target_(0.0),
- reinjection_fraction_target_(0.0), BHP_target_(0.0)
+ : injector_type_(WATER), control_mode_(NONE), surface_flow_max_rate_(0.0),
+ reinjection_fraction_target_(0.0), BHP_limit_(0.0)
{
}
diff --git a/opm/core/InjectionSpecification.hpp b/opm/core/InjectionSpecification.hpp
index 1ad6a3de..e986c8d4 100644
--- a/opm/core/InjectionSpecification.hpp
+++ b/opm/core/InjectionSpecification.hpp
@@ -10,16 +10,16 @@ namespace Opm
enum ControlMode
{
- NONE, RATE, REIN, RESV, VREP, WGRA, FLD
+ NONE, ORAT, REIN, RESV, VREP, WGRA, FLD, GRUP
};
InjectionSpecification();
- surface_component component_;
+ surface_component injector_type_;
ControlMode control_mode_;
- double surface_injection_target_;
+ double surface_flow_max_rate_;
double reinjection_fraction_target_;
- double BHP_target_;
+ double BHP_limit_;
};
}
#endif /* OPM_INJECTORSPECIFICATION_HPP */
diff --git a/opm/core/ProductionSpecification.cpp b/opm/core/ProductionSpecification.cpp
index 21f2d842..abc7d061 100644
--- a/opm/core/ProductionSpecification.cpp
+++ b/opm/core/ProductionSpecification.cpp
@@ -4,13 +4,13 @@ namespace Opm
{
ProductionSpecification::ProductionSpecification()
- : component_(OIL),
+ :
control_mode_(NONE_CM),
procedure_(NONE_P),
- oil_production_target_(-1.0),
+ oil_max_rate_(-1.0),
water_production_target_(-1.0),
- liquid_production_target_(-1.0),
- BHP_target_(-1.0)
+ fluid_volume_max_rate_(-1.0),
+ BHP_limit_(-1.0)
{
}
diff --git a/opm/core/ProductionSpecification.hpp b/opm/core/ProductionSpecification.hpp
index aa30e9f0..16243126 100644
--- a/opm/core/ProductionSpecification.hpp
+++ b/opm/core/ProductionSpecification.hpp
@@ -11,7 +11,7 @@ namespace Opm
enum ControlMode
{
- NONE_CM, ORAT, WRAT, REIN, RESV, VREP, WGRA, FLD
+ NONE_CM, ORAT, WRAT, REIN, RESV, VREP, WGRA, FLD, GRUP
};
enum Procedure
@@ -21,15 +21,15 @@ namespace Opm
ProductionSpecification();
- surface_component component_;
ControlMode control_mode_;
Procedure procedure_;
- double oil_production_target_;
+ double oil_max_rate_;
double water_production_target_;
- double liquid_production_target_;
- double BHP_target_;
-
+ double fluid_volume_max_rate_;
+ double BHP_limit_;
+ double gas_max_rate_;
+ double liquid_max_rate_;
};
}
diff --git a/opm/core/WellCollection.cpp b/opm/core/WellCollection.cpp
new file mode 100644
index 00000000..e2568f55
--- /dev/null
+++ b/opm/core/WellCollection.cpp
@@ -0,0 +1,80 @@
+/*
+Copyright 2011 SINTEF ICT, Applied Mathematics.
+
+
+This file is part of The Open Reservoir Simulator Project (OpenRS).
+
+OpenRS 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.
+
+OpenRS 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 OpenRS. If not, see .
+ */
+
+#include "WellCollection.hpp"
+
+namespace Opm
+{
+
+ WellCollection::WellCollection()
+ {
+ }
+
+ WellCollection::~WellCollection()
+ {
+ }
+
+ void WellCollection::addChild(std::string child_name, std::string parent_name,
+ const EclipseGridParser& deck)
+ {
+ WellsGroupInterface* parent = findNode(parent_name);
+ if (!parent) {
+ roots_.push_back(createWellsGroup(parent_name, deck));
+ parent = roots_[roots_.size() - 1].get();
+ }
+ std::tr1::shared_ptr child;
+
+ for (int i = 0; i < roots_.size(); ++i) {
+ if (roots_[i]->name() == child_name) {
+ child = roots_[i];
+ // We've found a new parent to the previously thought root, need to remove it
+ for(int j = i; j < roots_.size() - 1; ++j) {
+ roots_[j] = roots_[j+1];
+ }
+
+ roots_.resize(roots_.size()-1);
+ break;
+ }
+ }
+ if (!child.get()) {
+ child = createWellsGroup(child_name, deck);
+ }
+
+ WellsGroup* parent_as_group = static_cast (parent);
+ if (!parent_as_group) {
+ THROW("Trying to add child to group named " << parent_name << ", but it's not a group.");
+ }
+ parent_as_group->addChild(child);
+
+
+ }
+
+ WellsGroupInterface* WellCollection::findNode(std::string name)
+ {
+
+ for (int i = 0; i < roots_.size(); i++) {
+ WellsGroupInterface* result = roots_[i]->findGroup(name);
+ if (result) {
+ return result;
+ }
+ }
+ return NULL;
+ }
+}
\ No newline at end of file
diff --git a/opm/core/WellCollection.hpp b/opm/core/WellCollection.hpp
new file mode 100644
index 00000000..53ef008e
--- /dev/null
+++ b/opm/core/WellCollection.hpp
@@ -0,0 +1,49 @@
+/*
+Copyright 2011 SINTEF ICT, Applied Mathematics.
+
+
+This file is part of The Open Reservoir Simulator Project (OpenRS).
+
+OpenRS 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.
+
+OpenRS 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 OpenRS. If not, see .
+ */
+
+
+#ifndef OPM_WELLCOLLECTION_HPP
+#define OPM_WELLCOLLECTION_HPP
+
+#include
+#include
+#include
+
+namespace Opm
+{
+
+ class WellCollection
+ {
+ public:
+ WellCollection();
+ virtual ~WellCollection();
+
+ void addChild(std::string child, std::string parent,
+ const EclipseGridParser& deck);
+
+ private:
+ // To account for the possibility of a forest
+ std::vector > roots_;
+ WellsGroupInterface* findNode(std::string name);
+ };
+
+} // namespace Opm
+#endif /* OPM_WELLCOLLECTION_HPP */
+
diff --git a/opm/core/WellsGroup.cpp b/opm/core/WellsGroup.cpp
index 75a6cb95..4b36acf8 100644
--- a/opm/core/WellsGroup.cpp
+++ b/opm/core/WellsGroup.cpp
@@ -5,16 +5,247 @@
* Created on March 27, 2012, 9:27 AM
*/
-#include "WellsGroup.hpp"
-namespace Opm {
-WellsGroupInterface::AbstractWellsGroup() {
-}
+#include
-WellsGroupInterface::~WellsGroupInterface() {
-}
+namespace Opm
+{
-const std::string& WellsGroupInterface::name() {
- return name_;
-}
-}
+ WellsGroupInterface::WellsGroupInterface(const std::string& name, ProductionSpecification prod_spec,
+ InjectionSpecification inje_spec)
+ : name_(name), production_specification_(prod_spec),
+ injection_specification_(inje_spec)
+ {
+ }
+
+ WellsGroupInterface::~WellsGroupInterface()
+ {
+ }
+
+ const std::string& WellsGroupInterface::name()
+ {
+ return name_;
+ }
+
+ WellsGroup::WellsGroup(const std::string& name, ProductionSpecification prod_spec,
+ InjectionSpecification inj_spec)
+ : WellsGroupInterface(name, prod_spec, inj_spec)
+ {
+ }
+
+ WellsGroupInterface* WellsGroup::findGroup(std::string name_of_node)
+ {
+ if (name() == name_of_node) {
+ return this;
+ } else {
+ for (int i = 0; i < children_.size(); i++) {
+ WellsGroupInterface* result = children_[i]->findGroup(name_of_node);
+ if (result) {
+ return result;
+ }
+ }
+
+ // Not found in this node.
+ return NULL;
+ }
+ }
+
+ void WellsGroup::addChild(std::tr1::shared_ptr child) {
+ children_.push_back(child);
+ }
+
+ WellNode::WellNode(const std::string& name, ProductionSpecification prod_spec,
+ InjectionSpecification inj_spec)
+ : WellsGroupInterface(name, prod_spec, inj_spec)
+ {
+ }
+
+ WellsGroupInterface* WellNode::findGroup(std::string name_of_node)
+ {
+ if (name() == name_of_node) {
+ return this;
+ } else {
+ return NULL;
+ }
+
+ }
+
+ surface_component toSurfaceComponent(std::string type)
+ {
+ if (type == "OIL") {
+ return OIL;
+ }
+ if (type == "WATER") {
+ return WATER;
+ }
+ if (type == "GAS") {
+ return GAS;
+ }
+ THROW("Unknown type " << type << ", could not convert to surface_component");
+ }
+
+ InjectionSpecification::ControlMode toInjectionControlMode(std::string type)
+ {
+ if (type == "NONE") {
+ return InjectionSpecification::NONE;
+ }
+
+ if (type == "ORAT") {
+ return InjectionSpecification::ORAT;
+ }
+ if (type == "REIN") {
+ return InjectionSpecification::REIN;
+ }
+ if (type == "RESV") {
+ return InjectionSpecification::RESV;
+ }
+ if (type == "VREP") {
+ return InjectionSpecification::VREP;
+ }
+ if (type == "WGRA") {
+ return InjectionSpecification::WGRA;
+ }
+ if (type == "FLD") {
+ return InjectionSpecification::FLD;
+ }
+ if (type == "GRUP") {
+ return InjectionSpecification::GRUP;
+ }
+
+
+ THROW("Unknown type " << type << ", could not convert to ControlMode.");
+ }
+
+ ProductionSpecification::ControlMode toProductionControlMode(std::string type)
+ {
+ if (type == "NONE") {
+ return ProductionSpecification::NONE_CM;
+ }
+ if (type == "ORAT") {
+ return ProductionSpecification::ORAT;
+
+ }
+ if (type == "REIN") {
+ return ProductionSpecification::REIN;
+ }
+ if (type == "RESV") {
+ return ProductionSpecification::RESV;
+ }
+ if (type == "VREP") {
+ return ProductionSpecification::VREP;
+ }
+ if (type == "WGRA") {
+ return ProductionSpecification::WGRA;
+ }
+ if (type == "FLD") {
+ return ProductionSpecification::FLD;
+ }
+ if (type == "GRUP") {
+ return ProductionSpecification::GRUP;
+ }
+
+ THROW("Unknown type " << type << ", could not convert to ControlMode.");
+ }
+
+
+ ProductionSpecification::Procedure toProductionProcedure(std::string type)
+ {
+ if (type == "NONE") {
+ return ProductionSpecification::NONE_P;
+ }
+ if (type == "RATE") {
+ return ProductionSpecification::RATE;
+ }
+ if (type == "WELL") {
+ return ProductionSpecification::WELL;
+ }
+
+
+ THROW("Unknown type " << type << ", could not convert to ControlMode.");
+ }
+
+ std::tr1::shared_ptr createWellsGroup(std::string name, const EclipseGridParser& deck)
+ {
+
+ std::tr1::shared_ptr return_value;
+ // First we need to determine whether it's a group or just a well:
+ bool isWell = false;
+ if (deck.hasField("WELSPECS")) {
+ WELSPECS wspecs = deck.getWELSPECS();
+ for (int i = 0; i < wspecs.welspecs.size(); i++) {
+ if (wspecs.welspecs[i].name_ == name) {
+ isWell = true;
+ break;
+ }
+ }
+ }
+ // For now, assume that if it isn't a well, it's a group
+
+ if (isWell) {
+
+ InjectionSpecification injection_specification;
+ if (deck.hasField("WCONINJE")) {
+ WCONINJE wconinje = deck.getWCONINJE();
+ for (int i = 0; i < wconinje.wconinje.size(); i++) {
+ if (wconinje.wconinje[i].well_ == name) {
+ WconinjeLine line = wconinje.wconinje[i];
+ injection_specification.BHP_limit_ = line.BHP_limit_;
+ injection_specification.injector_type_ = toSurfaceComponent(line.injector_type_);
+ injection_specification.control_mode_ = toInjectionControlMode(line.control_mode_);
+ injection_specification.surface_flow_max_rate_ = line.surface_flow_max_rate_;
+ }
+ }
+ }
+
+ ProductionSpecification production_specification;
+ if (deck.hasField("WCONPROD")) {
+ WCONPROD wconprod = deck.getWCONPROD();
+ for (int i = 0; i < wconprod.wconprod.size(); i++) {
+ if (wconprod.wconprod[i].well_ == name) {
+ WconprodLine line = wconprod.wconprod[i];
+ production_specification.BHP_limit_ = line.BHP_limit_;
+ production_specification.fluid_volume_max_rate_ = line.fluid_volume_max_rate_;
+ production_specification.oil_max_rate_ = line.oil_max_rate_;
+ production_specification.control_mode_ = toProductionControlMode(line.control_mode_);
+ production_specification.water_production_target_ = line.water_max_rate_;
+ }
+ }
+ }
+
+ return_value.reset(new WellNode(name, production_specification, injection_specification));
+ } else {
+ InjectionSpecification injection_specification;
+ if (deck.hasField("GCONINJE")) {
+ GCONINJE gconinje = deck.getGCONINJE();
+ for (int i = 0; i < gconinje.gconinje.size(); i++) {
+ if (gconinje.gconinje[i].group_ == name) {
+ GconinjeLine line = gconinje.gconinje[i];
+ injection_specification.injector_type_ = toSurfaceComponent(line.injector_type_);
+ injection_specification.control_mode_ = toInjectionControlMode(line.control_mode_);
+ injection_specification.surface_flow_max_rate_ = line.surface_flow_max_rate_;
+ }
+ }
+ }
+
+ ProductionSpecification production_specification;
+ if (deck.hasField("GCONPROD")) {
+ GCONPROD gconprod = deck.getGCONPROD();
+ for (int i = 0; i < gconprod.gconprod.size(); i++) {
+ if (gconprod.gconprod[i].group_ == name) {
+ GconprodLine line = gconprod.gconprod[i];
+ production_specification.oil_max_rate_ = line.oil_max_rate_;
+ production_specification.control_mode_ = toProductionControlMode(line.control_mode_);
+ production_specification.water_production_target_ = line.water_max_rate_;
+ production_specification.gas_max_rate_ = line.gas_max_rate_;
+ production_specification.liquid_max_rate_ = line.liquid_max_rate_;
+ production_specification.procedure_ = toProductionProcedure(line.procedure_);
+ }
+ }
+ }
+
+ return_value.reset(new WellsGroup(name, production_specification, injection_specification));
+ }
+
+ return return_value;
+
+ }
}
\ No newline at end of file
diff --git a/opm/core/WellsGroup.hpp b/opm/core/WellsGroup.hpp
index 1b0ef904..9d5131ce 100644
--- a/opm/core/WellsGroup.hpp
+++ b/opm/core/WellsGroup.hpp
@@ -3,32 +3,62 @@
#include
#include
+#include
#include
+
namespace Opm
{
class WellsGroupInterface
{
public:
- WellsGroupInterface(const std::string& name);
+ WellsGroupInterface(const std::string& name, ProductionSpecification prod_spec,
+ InjectionSpecification inj_spec);
virtual ~WellsGroupInterface();
const std::string& name();
const ProductionSpecification& prodSpec() const;
const InjectionSpecification& injSpec() const;
+ /// \returns the pointer to the WellsGroupInterface with the given name. NULL if
+ /// the name is not found.a
+ virtual WellsGroupInterface* findGroup(std::string name_of_node) = 0;
private:
std::string name_;
ProductionSpecification production_specification_;
InjectionSpecification injection_specification_;
-
};
class WellsGroup : public WellsGroupInterface
{
+ public:
+ WellsGroup(const std::string& name, ProductionSpecification prod_spec,
+ InjectionSpecification inj_spec);
+
+ virtual WellsGroupInterface* findGroup(std::string name_of_node);
+
+ void addChild(std::tr1::shared_ptr child);
+ private:
+ std::vector > children_;
+
};
+ class WellNode : public WellsGroupInterface
+ {
+ public:
+ WellNode(const std::string& name, ProductionSpecification prod_spec,
+ InjectionSpecification inj_spec);
+
+ virtual WellsGroupInterface* findGroup(std::string name_of_node);
+
+ };
+
+
+ std::tr1::shared_ptr createWellsGroup(std::string name,
+ const EclipseGridParser& deck);
+
+
}
#endif /* OPM_WELLSGROUP_HPP */
diff --git a/opm/core/WellsManager.cpp b/opm/core/WellsManager.cpp
index cca39d4c..36bc12b5 100644
--- a/opm/core/WellsManager.cpp
+++ b/opm/core/WellsManager.cpp
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
@@ -504,6 +505,25 @@ namespace Opm
}
}
+ WellCollection well_collection;
+ if (deck.hasField("GRUPTREE")) {
+ std::cout << "Found gruptree" << std::endl;
+ const GRUPTREE& gruptree = deck.getGRUPTREE();
+
+ std::map::const_iterator it = gruptree.tree.begin();
+ for( ; it != gruptree.tree.end(); ++it) {
+ well_collection.addChild(it->first, it->second, deck);
+ }
+ }
+
+ if(deck.hasField("WELSPECS")) {
+ WELSPECS welspecs = deck.getWELSPECS();
+ for(int i = 0; i < welspecs.welspecs.size(); ++i) {
+ WelspecsLine line = welspecs.welspecs[i];
+ well_collection.addChild(line.name_, line.group_, deck);
+ }
+ }
+
}
diff --git a/opm/core/eclipse/SpecialEclipseFields.hpp b/opm/core/eclipse/SpecialEclipseFields.hpp
index 64a8a918..a2328e58 100644
--- a/opm/core/eclipse/SpecialEclipseFields.hpp
+++ b/opm/core/eclipse/SpecialEclipseFields.hpp
@@ -1247,6 +1247,10 @@ struct GCONPROD : public SpecialBase
GconprodLine gconprod_line;
gconprod_line.group_ = groupname;
gconprod_line.control_mode_ = readString(is);
+ if (gconprod_line.control_mode_[gconprod_line.control_mode_.size() - 1] == '*')
+ {
+ gconprod_line.control_mode_ = "NONE";
+ }
std::vector double_data(4, 1.0E20);
const int num_to_read = 4;
int num_read = readDefaultedVectorData(is, double_data, num_to_read);