From aafafba4b18f460c1a8c3ebb7616a1d3d6aef8bd Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Mon, 2 Jan 2023 15:24:28 +0100 Subject: [PATCH] draft version of handling keyword WINJCLN --- opm/input/eclipse/Schedule/Schedule.hpp | 1 + .../eclipse/Schedule/Well/Connection.hpp | 11 +++++++- opm/input/eclipse/Schedule/Well/Well.hpp | 1 + .../eclipse/Schedule/KeywordHandlers.cpp | 14 ++++++++++ src/opm/input/eclipse/Schedule/Well/Well.cpp | 26 ++++++++++++++++++- 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/opm/input/eclipse/Schedule/Schedule.hpp b/opm/input/eclipse/Schedule/Schedule.hpp index 3abfb2fbe..7c3ed0cc3 100644 --- a/opm/input/eclipse/Schedule/Schedule.hpp +++ b/opm/input/eclipse/Schedule/Schedule.hpp @@ -748,6 +748,7 @@ namespace Opm void handleWPIMULT (HandlerContext&); void handleWINJDAM (HandlerContext&); void handleWINJFCNC (HandlerContext&); + void handleWINJCLN (HandlerContext&); void handleWINJMULT (HandlerContext&); void handleWPMITAB (HandlerContext&); void handleWPOLYMER (HandlerContext&); diff --git a/opm/input/eclipse/Schedule/Well/Connection.hpp b/opm/input/eclipse/Schedule/Well/Connection.hpp index f0a464bc2..73ca56371 100644 --- a/opm/input/eclipse/Schedule/Well/Connection.hpp +++ b/opm/input/eclipse/Schedule/Well/Connection.hpp @@ -95,6 +95,9 @@ namespace RestartIO { double poro{0.}; std::optional radius; std::optional flow_area; + // skin factor multiplier + // it is controlled by keyword WINJCLN + double sf_multiplier {1.}; FilterCake() = default; explicit FilterCake(const DeckRecord& record); @@ -107,6 +110,7 @@ namespace RestartIO { serializer(poro); serializer(radius); serializer(flow_area); + serializer(sf_multiplier); } bool operator==( const FilterCake& other ) const { @@ -114,12 +118,17 @@ namespace RestartIO { && perm == other.perm && poro == other.poro && radius == other.radius - && flow_area == other.flow_area; + && flow_area == other.flow_area + && sf_multiplier == other.sf_multiplier; } bool active() const { return this->geometry != FilterCakeGeometry::NONE; } + + void applyCleanMultiplier(const double factor) { + this->sf_multiplier *= factor; + } }; // TODO: the end of the filter cake model diff --git a/opm/input/eclipse/Schedule/Well/Well.hpp b/opm/input/eclipse/Schedule/Well/Well.hpp index 34eb85aa1..ede388f0d 100644 --- a/opm/input/eclipse/Schedule/Well/Well.hpp +++ b/opm/input/eclipse/Schedule/Well/Well.hpp @@ -482,6 +482,7 @@ public: bool handleCOMPLUMP(const DeckRecord& record); bool handleWPIMULT(const DeckRecord& record); bool handleWINJDAM(const DeckRecord& record, const KeywordLocation& location); + bool handleWINJCLN(const DeckRecord& record, const KeywordLocation& location); bool handleWINJMULT(const DeckRecord& record, const KeywordLocation& location); // TODO: makes it a handleWINJFCNC? void setFilterConc(const double conc); diff --git a/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp b/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp index e5a64fa65..636989c27 100644 --- a/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp +++ b/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp @@ -1983,6 +1983,19 @@ Well{0} entered with 'FIELD' parent group: } } + void Schedule::handleWINJCLN(HandlerContext& handlerContext) { + for (const auto& record : handlerContext.keyword) { + const std::string& wellNamePattern = record.getItem("WELL_NAME").getTrimmedString(0); + const auto well_names = this->wellNames(wellNamePattern, handlerContext); + // TODO: will check whether we should put all the filter cake related to a separate property + for (const auto& well_name: well_names) { + auto well = this->snapshots.back().wells(well_name); + well.handleWINJCLN(record, handlerContext.keyword.location()); + this->snapshots.back().wells.update(std::move(well)); + } + } + } + void Schedule::handleWPMITAB(HandlerContext& handlerContext) { for (const auto& record : handlerContext.keyword) { const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0); @@ -2580,6 +2593,7 @@ Well{0} entered with 'FIELD' parent group: { "WPIMULT" , &Schedule::handleWPIMULT }, { "WINJDAM" , &Schedule::handleWINJDAM }, { "WINJFCNC", &Schedule::handleWINJFCNC }, + { "WINJCLN", &Schedule::handleWINJCLN }, { "WPMITAB" , &Schedule::handleWPMITAB }, { "WPOLYMER", &Schedule::handleWPOLYMER }, { "WRFT" , &Schedule::handleWRFT }, diff --git a/src/opm/input/eclipse/Schedule/Well/Well.cpp b/src/opm/input/eclipse/Schedule/Well/Well.cpp index d9eaf9105..eb0006528 100644 --- a/src/opm/input/eclipse/Schedule/Well/Well.cpp +++ b/src/opm/input/eclipse/Schedule/Well/Well.cpp @@ -1318,12 +1318,36 @@ bool Well::handleWINJDAM(const DeckRecord& record, const KeywordLocation& /* loc for (auto c : *(this->connections)) { if (match(c)) { c.setFilterCake(filter_cake); - new_connections->add(c); } + new_connections->add(c); } return this->updateConnections(std::move(new_connections), false); } +bool Well::handleWINJCLN(const DeckRecord& record, const KeywordLocation& /* location */) +{ + 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; + }; + + const double fraction_removal = record.getItem("FRAC_REMOVE").getSIDouble(0); + // TODO: it should be between 0.0 and 1.0 + const double fraction_remain = std::min(1.0, std::max(fraction_removal, 0.)); + auto new_connections = std::make_shared(this->connections->ordering(), this->headI, this->headJ); + for (auto c : *(this->connections)) { + if (match(c)) { + auto filter_cake = c.getFilterCake(); + filter_cake.applyCleanMultiplier(fraction_remain); + c.setFilterCake(filter_cake); + } + new_connections->add(c); + } + return this->updateConnections(std::move(new_connections), false); +} bool Well::handleWINJMULT(const Opm::DeckRecord& record, const KeywordLocation& location) { // for this keyword, the default for I, J, K will be negative