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);