Merge pull request #3577 from GitPaean/fixing_winjmult

separating the WINJMULT for well and connections
This commit is contained in:
Bård Skaflestad
2023-06-22 12:53:27 +02:00
committed by GitHub
7 changed files with 177 additions and 80 deletions

View File

@@ -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

View File

@@ -30,6 +30,8 @@
#include <optional>
#include <limits>
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
namespace Opm {
namespace RestartIO {
@@ -77,34 +79,6 @@ namespace RestartIO {
Defaulted,
};
struct InjMult {
bool is_active {false};
double fracture_pressure {std::numeric_limits<double>::max()};
double multiplier_gradient {0.};
bool active() const
{
return is_active;
}
template<class Serializer>
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<int,3> ijk;
CTFKind m_ctfkind;
InjMult m_injmult;
std::optional<InjMult> m_injmult;
std::size_t m_global_index;
/*
The sort_value member is a peculiar quantity. The connections are

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_WINJMULT_HPP
#define OPM_WINJMULT_HPP
#include <limits>
namespace Opm {
class KeywordLocation;
struct InjMult {
enum class InjMultMode {
WREV,
CREV,
CIRR,
NONE,
};
double fracture_pressure {std::numeric_limits<double>::max()};
double multiplier_gradient {0.};
static InjMultMode injMultModeFromString(const std::string& str, const KeywordLocation& location);
template <class Serializer>
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

View File

@@ -39,6 +39,7 @@
#include <opm/input/eclipse/Schedule/Well/WellEnums.hpp>
#include <opm/input/eclipse/Schedule/Well/WellInjectionControls.hpp>
#include <opm/input/eclipse/Schedule/Well/WellProductionControls.hpp>
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
#include <opm/input/eclipse/Units/UnitSystem.hpp>
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<const Connection *> 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<InjMult> well_inj_mult;
};
std::ostream& operator<<( std::ostream&, const Well::WellInjectionProperties& );

View File

@@ -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<std::pair<double, double>>& 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({});
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <opm/common/OpmLog/KeywordLocation.hpp>
#include <opm/common/utility/OpmInputError.hpp>
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
#include <fmt/format.h>
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

View File

@@ -52,6 +52,7 @@
#include "../MSW/Compsegs.hpp"
#include <cassert>
#include <cmath>
#include <cstddef>
#include <memory>
@@ -310,7 +311,8 @@ Well::Well(const RestartIO::RstWell& rst_well,
wvfpdp(std::make_shared<WVFPDP>()),
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<WellProductionProperties>(this->unit_system, wname);
@@ -489,8 +491,8 @@ Well::Well(const std::string& wname_arg,
wvfpdp(std::make_shared<WVFPDP>()),
wvfpexp(std::make_shared<WVFPEXP>()),
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<WellProductionProperties>(this->unit_system, this->wname);
p->whistctl_cmode = whistctl_cmode;
@@ -533,6 +535,7 @@ Well Well::serializationTestObject()
result.wvfpexp = std::make_shared<WVFPEXP>(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<WellFoamProperties> 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<Kw::MODE>().getTrimmedString(0), location);
const InjMultMode mode = InjMult::injMultModeFromString(record.getItem<Kw::MODE>().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<Kw::FRACTURING_PRESSURE>().getSIDouble(0);
const double multiple_gradient = record.getItem<Kw::MULTIPLIER_GRADIENT>().getSIDouble(0);
auto new_connections = std::make_shared<WellConnections>(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();
}