Merge pull request #3161 from GitPaean/support_winjmult

adding the parsing support for keyword WINJMULT
This commit is contained in:
Bård Skaflestad
2023-06-14 14:32:00 +02:00
committed by GitHub
7 changed files with 160 additions and 2 deletions

View File

@@ -746,6 +746,7 @@ namespace Opm
void handleWVFPEXP (HandlerContext&);
void handleWWPAVE (HandlerContext&);
void handleWPIMULT (HandlerContext&);
void handleWINJMULT (HandlerContext&);
void handleWPMITAB (HandlerContext&);
void handleWPOLYMER (HandlerContext&);
void handleWRFT (HandlerContext&);

View File

@@ -28,6 +28,7 @@
#include <string>
#include <vector>
#include <optional>
#include <limits>
namespace Opm {
@@ -77,6 +78,33 @@ namespace RestartIO {
};
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,
@@ -120,6 +148,10 @@ namespace RestartIO {
double connectionLength() const;
double skinFactor() const;
CTFKind kind() const;
const InjMult& injmult() 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);
@@ -163,6 +195,7 @@ namespace RestartIO {
serializer(ijk);
serializer(m_global_index);
serializer(m_ctfkind);
serializer(m_injmult);
serializer(m_sort_value);
serializer(m_perf_range);
serializer(m_defaultSatTabId);
@@ -186,6 +219,7 @@ namespace RestartIO {
std::array<int,3> ijk;
CTFKind m_ctfkind;
InjMult m_injmult;
std::size_t m_global_index;
/*
The sort_value member is a peculiar quantity. The connections are

View File

@@ -76,6 +76,15 @@ class Well {
public:
using Status = WellStatus;
enum class InjMultMode {
WREV,
CREV,
CIRR,
NONE,
};
static InjMultMode injMultModeFromString(const std::string& str, const KeywordLocation& location);
/*
The elements in this enum are used as bitmasks to keep track
of which controls are present, i.e. the 2^n structure must
@@ -383,6 +392,7 @@ public:
Status getStatus() const;
const std::string& groupName() const;
Phase getPreferredPhase() const;
InjMultMode getInjMultMode() const;
bool hasConnections() const;
const std::vector<const Connection *> getConnections(int completion) const;
@@ -472,6 +482,7 @@ public:
bool handleWELOPENConnections(const DeckRecord& record, Connection::State status);
bool handleCOMPLUMP(const DeckRecord& record);
bool handleWPIMULT(const DeckRecord& record);
bool handleWINJMULT(const DeckRecord& record, const KeywordLocation& location);
bool applyGlobalWPIMULT(double scale_factor);
void filterConnections(const ActiveGridCells& grid);
@@ -538,6 +549,7 @@ public:
serializer(wvfpexp);
serializer(m_pavg);
serializer(well_temperature);
serializer(inj_mult_mode);
}
private:
@@ -584,6 +596,7 @@ private:
Status status;
PAvg m_pavg;
double well_temperature;
InjMultMode inj_mult_mode = InjMultMode::NONE;
};
std::ostream& operator<<( std::ostream&, const Well::WellInjectionProperties& );

View File

@@ -1786,6 +1786,25 @@ Well{0} entered with 'FIELD' parent group:
}
}
void Schedule::handleWINJMULT(Opm::Schedule::HandlerContext& handlerContext) {
for (const auto& record : handlerContext.keyword) {
const std::string& wellNamePattern = record.getItem("WELL_NAME").getTrimmedString(0);
const auto well_names = wellNames(wellNamePattern);
for (const auto& well_name : well_names) {
auto well = this->snapshots.back().wells( well_name );
if (well.isProducer()) {
const std::string reason = fmt::format("Keyword WINJMULT can only apply to injectors,"
" but Well {} is a producer", well_name);
throw OpmInputError(reason, handlerContext.keyword.location());
}
if (well.handleWINJMULT(record, handlerContext.keyword.location())) {
this->snapshots.back().wells.update(std::move(well));
}
}
}
}
void Schedule::handleWINJTEMP(HandlerContext& handlerContext) {
// we do not support the "enthalpy" field yet. how to do this is a more difficult
// question.
@@ -2468,6 +2487,7 @@ Well{0} entered with 'FIELD' parent group:
{ "WFOAM" , &Schedule::handleWFOAM },
{ "WGRUPCON", &Schedule::handleWGRUPCON },
{ "WHISTCTL", &Schedule::handleWHISTCTL },
{ "WINJMULT", &Schedule::handleWINJMULT },
{ "WINJTEMP", &Schedule::handleWINJTEMP },
{ "WLIFTOPT", &Schedule::handleWLIFTOPT },
{ "WLIST" , &Schedule::handleWLIST },

View File

@@ -311,6 +311,7 @@ const std::optional<std::pair<double, double>>& Connection::perf_range() const {
&& this->m_re == rhs.m_re
&& this->m_connection_length == rhs.m_connection_length
&& this->m_skin_factor == rhs.m_skin_factor
&& this->m_injmult == rhs.m_injmult
&& this->m_Kh == rhs.m_Kh
&& this->sat_tableId == rhs.sat_tableId
&& this->open_state == rhs.open_state
@@ -355,6 +356,7 @@ Connection::State Connection::StateFromString( const std::string& stringValue )
}
std::string Connection::Direction2String(const Direction enumValue)
{
std::string stringValue;
@@ -442,4 +444,16 @@ Connection::CTFKind Connection::kind() const {
return m_ctfkind;
}
const Connection::InjMult& Connection::injmult() const {
return m_injmult;
}
void Connection::setInjMult(const Connection::InjMult& inj_mult) {
m_injmult = inj_mult;
}
void Connection::clearInjMult() {
this->setInjMult({});
}
}

View File

@@ -41,6 +41,7 @@
#include <opm/input/eclipse/Units/Units.hpp>
#include <opm/common/utility/OpmInputError.hpp>
#include <opm/common/utility/shmatch.hpp>
#include <opm/input/eclipse/Parser/ParserKeywords/S.hpp>
@@ -564,6 +565,17 @@ 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()) {
@@ -1300,6 +1312,63 @@ bool Well::handleWPIMULT(const DeckRecord& record) {
}
bool Well::handleWINJMULT(const Opm::DeckRecord& record, const KeywordLocation& location) {
// for this keyword, the default for I, J, K will be negative
// it is not totally clear how specifying 0 or a negative values will work
// current match_eq function only treats 0 and default values for all connections,
// we might need to revisit this part later when complication regarding this occurs.
// it is possible that changing (item.get<int>(0) == 0); to (item.get<int>(0) <= 0) is solution to go
// while it remains to be discussed.
auto match = [=] ( const Connection& c) -> bool {
if (!match_eq(c.getI() , record, "I", -1)) return false;
if (!match_eq(c.getJ() , record, "J", -1)) return false;
if (!match_eq(c.getK() , record, "K", -1)) return false;
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 bool mode_change = (this->inj_mult_mode != mode);
if (mode_change) {
this->inj_mult_mode = mode;
}
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};
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);
}
} 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);
}
}
return this->updateConnections(std::move(new_connections), false) || mode_change;
}
bool Opm::Well::applyGlobalWPIMULT(const double scaling_factor)
{
auto new_connections = std::make_shared<WellConnections>(this->connections->ordering(), this->headI, this->headJ);
@@ -1565,6 +1634,7 @@ bool Well::operator==(const Well& data) const {
&& (this->m_pavg == data.m_pavg)
&& (this->getInjectionProperties() == data.getInjectionProperties())
&& (this->well_temperature == data.well_temperature)
&& (this->inj_mult_mode == data.inj_mult_mode)
;
}
@@ -1645,3 +1715,7 @@ int Opm::Well::eclipseControlMode(const Well& well,
return eclipseControlMode(ctrl.cmode, well.injectorType());
}
}
Opm::Well::InjMultMode Opm::Well::getInjMultMode() const {
return this->inj_mult_mode;
}

View File

@@ -10,12 +10,14 @@
},
{
"name": "FRACTURING_PRESSURE",
"value_type": "DOUBLE"
"value_type": "DOUBLE",
"dimension": "Pressure"
},
{
"name": "MULTIPLIER_GRADIENT",
"value_type": "DOUBLE",
"default": 0
"default": 0,
"dimension": "1/Pressure"
},
{
"name": "MODE",