diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index ad6e43ae1..756136d62 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -221,6 +221,7 @@ if(ENABLE_ECL_INPUT) src/opm/input/eclipse/Schedule/Well/WellTestState.cpp src/opm/input/eclipse/Schedule/WellTraj/RigEclipseWellLogExtractor.cpp src/opm/input/eclipse/Schedule/Well/WellTracerProperties.cpp + src/opm/input/eclipse/Schedule/Well/WINJMULT.cpp src/opm/input/eclipse/Schedule/Well/WList.cpp src/opm/input/eclipse/Schedule/Well/WListManager.cpp src/opm/input/eclipse/Schedule/Well/WVFPDP.cpp @@ -1233,6 +1234,7 @@ if(ENABLE_ECL_INPUT) opm/input/eclipse/Schedule/Well/WellMICPProperties.hpp opm/input/eclipse/Schedule/Well/WellPolymerProperties.hpp opm/input/eclipse/Schedule/Well/WellTracerProperties.hpp + opm/input/eclipse/Schedule/Well/WINJMULT.hpp opm/input/eclipse/Schedule/Well/WVFPDP.hpp opm/input/eclipse/Schedule/Well/WVFPEXP.hpp opm/input/eclipse/Schedule/Well/WellTestConfig.hpp diff --git a/opm/input/eclipse/Schedule/Well/Connection.hpp b/opm/input/eclipse/Schedule/Well/Connection.hpp index 0f9575147..e607b0e30 100644 --- a/opm/input/eclipse/Schedule/Well/Connection.hpp +++ b/opm/input/eclipse/Schedule/Well/Connection.hpp @@ -30,6 +30,8 @@ #include #include +#include + namespace Opm { namespace RestartIO { @@ -77,34 +79,6 @@ namespace RestartIO { Defaulted, }; - - - struct InjMult { - bool is_active {false}; - double fracture_pressure {std::numeric_limits::max()}; - double multiplier_gradient {0.}; - - bool active() const - { - return is_active; - } - - template - void serializeOp(Serializer& serializer) - { - serializer(is_active); - serializer(fracture_pressure); - serializer(multiplier_gradient); - } - - bool operator==( const InjMult& rhs ) const { - return is_active == rhs.is_active - && fracture_pressure == rhs.fracture_pressure - && multiplier_gradient == rhs.multiplier_gradient; - } - }; - - Connection(); Connection(int i, int j , int k , std::size_t global_index, @@ -149,9 +123,8 @@ namespace RestartIO { double skinFactor() const; CTFKind kind() const; const InjMult& injmult() const; + bool activeInjMult() const; void setInjMult(const InjMult& inj_mult); - // remove the injMult setting and INJMULT is not active for this connection - void clearInjMult(); void setState(State state); void setComplnum(int compnum); @@ -219,7 +192,7 @@ namespace RestartIO { std::array ijk; CTFKind m_ctfkind; - InjMult m_injmult; + std::optional m_injmult; std::size_t m_global_index; /* The sort_value member is a peculiar quantity. The connections are diff --git a/opm/input/eclipse/Schedule/Well/WINJMULT.hpp b/opm/input/eclipse/Schedule/Well/WINJMULT.hpp new file mode 100644 index 000000000..9e43f04dc --- /dev/null +++ b/opm/input/eclipse/Schedule/Well/WINJMULT.hpp @@ -0,0 +1,59 @@ +/* +Copyright 2023 Equinor. + +This file is part of the Open Porous Media project (OPM). + + 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. + + 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. + +You should have received a copy of the GNU General Public License +along with OPM. If not, see . +*/ + +#ifndef OPM_WINJMULT_HPP +#define OPM_WINJMULT_HPP + +#include + + +namespace Opm { + +class KeywordLocation; + +struct InjMult { + + enum class InjMultMode { + WREV, + CREV, + CIRR, + NONE, + }; + + double fracture_pressure {std::numeric_limits::max()}; + double multiplier_gradient {0.}; + + static InjMultMode injMultModeFromString(const std::string& str, const KeywordLocation& location); + + template + void serializeOp(Serializer& serializer) + { + serializer(fracture_pressure); + serializer(multiplier_gradient); + } + + bool operator==(const InjMult& rhs) const; + + static InjMult serializationTestObject(); + static std::string InjMultToString(const InjMult&); +}; + +} + +#endif // OPM_WINJMULT_HPP diff --git a/opm/input/eclipse/Schedule/Well/Well.hpp b/opm/input/eclipse/Schedule/Well/Well.hpp index 046bd5162..1bc1b9556 100644 --- a/opm/input/eclipse/Schedule/Well/Well.hpp +++ b/opm/input/eclipse/Schedule/Well/Well.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include namespace Opm { @@ -76,14 +77,10 @@ class Well { public: using Status = WellStatus; - enum class InjMultMode { - WREV, - CREV, - CIRR, - NONE, - }; - - static InjMultMode injMultModeFromString(const std::string& str, const KeywordLocation& location); + /* + * The mode for the keyword WINJMULT. It can have four different values: WREV, CREV, CIRR and NONE. + */ + using InjMultMode = InjMult::InjMultMode; /* The elements in this enum are used as bitmasks to keep track @@ -393,6 +390,8 @@ public: const std::string& groupName() const; Phase getPreferredPhase() const; InjMultMode getInjMultMode() const; + const InjMult& getWellInjMult() const; + bool aciveWellInjMult() const; bool hasConnections() const; const std::vector getConnections(int completion) const; @@ -550,6 +549,7 @@ public: serializer(m_pavg); serializer(well_temperature); serializer(inj_mult_mode); + serializer(well_inj_mult); } private: @@ -597,6 +597,7 @@ private: PAvg m_pavg; double well_temperature; InjMultMode inj_mult_mode = InjMultMode::NONE; + std::optional well_inj_mult; }; std::ostream& operator<<( std::ostream&, const Well::WellInjectionProperties& ); diff --git a/src/opm/input/eclipse/Schedule/Well/Connection.cpp b/src/opm/input/eclipse/Schedule/Well/Connection.cpp index 3e701499d..da5b0de80 100644 --- a/src/opm/input/eclipse/Schedule/Well/Connection.cpp +++ b/src/opm/input/eclipse/Schedule/Well/Connection.cpp @@ -131,6 +131,7 @@ Connection::Connection(const RestartIO::RstConnection& rst_connection, const Sch result.m_ctfkind = CTFKind::Defaulted; result.m_global_index = 12; result.m_perf_range = std::make_pair(14,15); + result.m_injmult = InjMult::serializationTestObject(); result.m_sort_value = 14; result.m_defaultSatTabId = true; result.segment_number = 16; @@ -297,6 +298,9 @@ const std::optional>& Connection::perf_range() const { ss << "segment_nr " << this->segment_number << std::endl; ss << "center_depth " << this->center_depth << std::endl; ss << "sort_value" << this->m_sort_value<< std::endl; + if (this->m_injmult.has_value()) { + ss << "INJMULT " << InjMult::InjMultToString(this->m_injmult.value()) << std::endl; + } return ss.str(); } @@ -444,16 +448,17 @@ Connection::CTFKind Connection::kind() const { return m_ctfkind; } -const Connection::InjMult& Connection::injmult() const { - return m_injmult; +const InjMult& Connection::injmult() const { + assert(this->activeInjMult()); + return m_injmult.value(); } -void Connection::setInjMult(const Connection::InjMult& inj_mult) { +bool Connection::activeInjMult() const { + return this->m_injmult.has_value(); +} + +void Connection::setInjMult(const InjMult& inj_mult) { m_injmult = inj_mult; } -void Connection::clearInjMult() { - this->setInjMult({}); -} - } diff --git a/src/opm/input/eclipse/Schedule/Well/WINJMULT.cpp b/src/opm/input/eclipse/Schedule/Well/WINJMULT.cpp new file mode 100644 index 000000000..1025ce20c --- /dev/null +++ b/src/opm/input/eclipse/Schedule/Well/WINJMULT.cpp @@ -0,0 +1,63 @@ +/* +Copyright 2023 Equinor. + +This file is part of the Open Porous Media project (OPM). + + 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. + + 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. + +You should have received a copy of the GNU General Public License +along with OPM. If not, see . +*/ + + +#include +#include + +#include + +#include + +namespace Opm { + +InjMult::InjMultMode InjMult::injMultModeFromString(const std::string& str, const KeywordLocation& location) { + if (str == "WREV") + return InjMultMode::WREV; + else if (str == "CREV") + return InjMultMode::CREV; + else if (str == "CIRR") + return InjMultMode::CIRR; + else + throw OpmInputError(fmt::format("Unknown mode {} is specified in WINJMULT keyword", str), location); +} + + +bool InjMult::operator==(const InjMult& rhs) const +{ + return fracture_pressure == rhs.fracture_pressure + && multiplier_gradient == rhs.multiplier_gradient; +} + + +InjMult InjMult::serializationTestObject() { + InjMult result; + result.fracture_pressure = 1.e9; + result.multiplier_gradient = 2.; + return result; +} + + +std::string InjMult::InjMultToString(const InjMult& mult) { + std::string ss = fmt::format("fracture_pressure {}, multiplier_gradient {}", + mult.fracture_pressure, mult.multiplier_gradient); + return ss; +} + +} // end of namespace Opm \ No newline at end of file diff --git a/src/opm/input/eclipse/Schedule/Well/Well.cpp b/src/opm/input/eclipse/Schedule/Well/Well.cpp index eefcdc03e..044161548 100644 --- a/src/opm/input/eclipse/Schedule/Well/Well.cpp +++ b/src/opm/input/eclipse/Schedule/Well/Well.cpp @@ -52,6 +52,7 @@ #include "../MSW/Compsegs.hpp" +#include #include #include #include @@ -310,7 +311,8 @@ Well::Well(const RestartIO::RstWell& rst_well, wvfpdp(std::make_shared()), wvfpexp(explicitTHPOptions(rst_well)), status(status_from_int(rst_well.well_status)), - well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue) + well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue), + well_inj_mult(std::nullopt) { if (this->wtype.producer()) { auto p = std::make_shared(this->unit_system, wname); @@ -489,8 +491,8 @@ Well::Well(const std::string& wname_arg, wvfpdp(std::make_shared()), wvfpexp(std::make_shared()), status(Status::SHUT), - well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue) - + well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue), + well_inj_mult(std::nullopt) { auto p = std::make_shared(this->unit_system, this->wname); p->whistctl_cmode = whistctl_cmode; @@ -533,6 +535,7 @@ Well Well::serializationTestObject() result.wvfpexp = std::make_shared(WVFPEXP::serializationTestObject()); result.m_pavg = PAvg(); result.well_temperature = 10.0; + result.well_inj_mult = InjMult::serializationTestObject(); return result; } @@ -565,17 +568,6 @@ bool Well::updateWellGuideRate(double guide_rate_arg) { return false; } -Well::InjMultMode Well::injMultModeFromString(const std::string& str, const KeywordLocation& location) { - if (str == "WREV") - return InjMultMode::WREV; - else if (str == "CREV") - return InjMultMode::CREV; - else if (str == "CIRR") - return InjMultMode::CIRR; - else - throw OpmInputError(fmt::format("Unknown mode {} is specified in WINJMULT keyword", str), location); -} - bool Well::updateFoamProperties(std::shared_ptr foam_properties_arg) { if (this->wtype.producer()) { @@ -1327,11 +1319,8 @@ bool Well::handleWINJMULT(const Opm::DeckRecord& record, const KeywordLocation& return true; }; - // check whether it was under WREV previously. - // if yes, we need to reset all the connections for INJMULT specification - const bool is_prev_wrev = this->inj_mult_mode == InjMultMode::WREV; using Kw = ParserKeywords::WINJMULT; - const InjMultMode mode = injMultModeFromString(record.getItem().getTrimmedString(0), location); + const InjMultMode mode = InjMult::injMultModeFromString(record.getItem().getTrimmedString(0), location); const bool mode_change = (this->inj_mult_mode != mode); if (mode_change) { this->inj_mult_mode = mode; @@ -1339,33 +1328,26 @@ bool Well::handleWINJMULT(const Opm::DeckRecord& record, const KeywordLocation& const double fracture_pressure = record.getItem().getSIDouble(0); const double multiple_gradient = record.getItem().getSIDouble(0); auto new_connections = std::make_shared(this->connections->ordering(), this->headI, this->headJ); - const Connection::InjMult inj_mult {true, fracture_pressure, multiple_gradient}; + const InjMult inj_mult {fracture_pressure, multiple_gradient}; + bool connections_update = false; + bool well_inj_update = false; if (mode == InjMultMode::WREV) { - // all the connections will share the same INJMULT setup - for (auto c : *this->connections) { - c.setInjMult(inj_mult); - new_connections->add(c); - } + // all the connections will share the same INJMULT setup when under WREV + // it is stored in the Well object + this->well_inj_mult = inj_mult; + well_inj_update = true; } else if (mode == InjMultMode::CREV || mode == InjMultMode::CIRR){ for (auto c : *this->connections) { if (match(c)) { c.setInjMult(inj_mult); - } else { - // if previously defined with WREV for the well, for all the connections - // not specified in the new CREV or CIRR records, we do not consider they have - // an active WINJMULT setup - if (is_prev_wrev) { - // reset the injMult information for this connection - // basically, disable the injMult for this connection - c.clearInjMult(); - } } new_connections->add(c); } + connections_update = this->updateConnections(std::move(new_connections), false); } - return this->updateConnections(std::move(new_connections), false) || mode_change; + return mode_change || connections_update || well_inj_update; } @@ -1635,6 +1617,7 @@ bool Well::operator==(const Well& data) const { && (this->getInjectionProperties() == data.getInjectionProperties()) && (this->well_temperature == data.well_temperature) && (this->inj_mult_mode == data.inj_mult_mode) + && (this->well_inj_mult == data.well_inj_mult) ; } @@ -1719,3 +1702,14 @@ int Opm::Well::eclipseControlMode(const Well& well, Opm::Well::InjMultMode Opm::Well::getInjMultMode() const { return this->inj_mult_mode; } + +const Opm::InjMult& Opm::Well::getWellInjMult() const { + assert(this->aciveWellInjMult()); + return this->well_inj_mult.value(); +} + +bool Opm::Well::aciveWellInjMult() const { + return this->well_inj_mult.has_value(); +} + +