From dabf988aa7c13879078a6b03aa901457377c075a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Mon, 19 Oct 2020 00:57:43 +0200 Subject: [PATCH] Split WELPI Application Into Two Parts First part, implemented in a new member function Well::getWellPIScalingFactor calculates a CTF scaling factor from stored WELPI information and a dynamically calculated well-level PI value. The second part, using the original name applyWellProdIndexScaling, applies an externally calculate CTF scaling factor to all eligble connections. This is needed to enable applying multiple scalings across the time direction. Update unit tests accordingly. --- .../EclipseState/Schedule/Well/Well.hpp | 1 + .../EclipseState/Schedule/Well/Well.cpp | 22 +++++++++++-- tests/parser/ScheduleTests.cpp | 10 ++++-- tests/parser/WellTests.cpp | 33 ++++++++++++++----- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp index ba3090422..51f4ba4ef 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp @@ -600,6 +600,7 @@ public: bool operator==(const Well& data) const; void setInsertIndex(std::size_t index); void applyWellProdIndexScaling(const double currentEffectivePI); + double getWellPIScalingFactor(const double currentEffectivePI) const; template void serializeOp(Serializer& serializer) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp index 858f48d50..96acf41b0 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp @@ -826,7 +826,23 @@ void Well::setInsertIndex(std::size_t index) { this->insert_index = index; } -void Well::applyWellProdIndexScaling(const double currentEffectivePI) { +double Well::getWellPIScalingFactor(const double currentEffectivePI) const { + if (this->connections->empty()) + // No connections for this well. Unexpected. + return 1.0; + + if (!this->productivity_index) + // WELPI not activated. Nothing to do. + return 1.0; + + if (this->productivity_index->pi_value == currentEffectivePI) + // No change in scaling. + return 1.0; + + return this->productivity_index->pi_value / currentEffectivePI; +} + +void Well::applyWellProdIndexScaling(const double scalingFactor) { if (this->connections->empty()) // No connections for this well. Unexpected. return; @@ -835,11 +851,11 @@ void Well::applyWellProdIndexScaling(const double currentEffectivePI) { // WELPI not activated. Nothing to do. return; - if (this->productivity_index->pi_value == currentEffectivePI) + if (scalingFactor == 1.0) // No change in scaling. return; - this->connections->applyWellPIScaling(this->productivity_index->pi_value / currentEffectivePI); + this->connections->applyWellPIScaling(scalingFactor); } const WellConnections& Well::getConnections() const { diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index b9f78cd90..838b6841f 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -3790,7 +3790,10 @@ END const auto expectCF = (200.0 / 100.0) * 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 1); - wellP.applyWellProdIndexScaling(100.0*liquid_PI_unit()); + const auto scalingFactor = wellP.getWellPIScalingFactor(100.0*liquid_PI_unit()); + BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); + + wellP.applyWellProdIndexScaling(scalingFactor); for (const auto& conn : wellP.getConnections()) { BOOST_CHECK_CLOSE(conn.CF(), expectCF, 1.0e-10); } @@ -3801,7 +3804,10 @@ END const auto expectCF = (200.0 / 100.0) * 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 2); - wellP.applyWellProdIndexScaling(100.0*liquid_PI_unit()); + const auto scalingFactor = wellP.getWellPIScalingFactor(100.0*liquid_PI_unit()); + BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); + + wellP.applyWellProdIndexScaling(scalingFactor); const auto& connP = wellP.getConnections(); BOOST_CHECK_CLOSE(connP[0].CF(), expectCF , 1.0e-10); BOOST_CHECK_CLOSE(connP[1].CF(), 50*cp_rm3_per_db(), 1.0e-10); diff --git a/tests/parser/WellTests.cpp b/tests/parser/WellTests.cpp index 8ee1f505e..94947a348 100644 --- a/tests/parser/WellTests.cpp +++ b/tests/parser/WellTests.cpp @@ -1229,15 +1229,25 @@ END "Second call to updateWellProductivityIndex() must NOT be a state change"); // Want PI=2, but actual/effective PI=1 => scale CF by 2.0/1.0. - wellP.applyWellProdIndexScaling(1.0); - for (const auto& conn : wellP.getConnections()) { - BOOST_CHECK_CLOSE(conn.CF(), 2.0*expectCF, 1.0e-10); + { + const auto scalingFactor = wellP.getWellPIScalingFactor(1.0); + BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); + + wellP.applyWellProdIndexScaling(scalingFactor); + for (const auto& conn : wellP.getConnections()) { + BOOST_CHECK_CLOSE(conn.CF(), 2.0*expectCF, 1.0e-10); + } } // Repeated application of WELPI multiplies scaling factors. - wellP.applyWellProdIndexScaling(1.0); - for (const auto& conn : wellP.getConnections()) { - BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10); + { + const auto scalingFactor = wellP.getWellPIScalingFactor(1.0); + BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); + + wellP.applyWellProdIndexScaling(scalingFactor); + for (const auto& conn : wellP.getConnections()) { + BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10); + } } // New WELPI record does not reset the scaling factors @@ -1247,9 +1257,14 @@ END } // Effective PI=desired PI => no scaling change - wellP.applyWellProdIndexScaling(3.0); - for (const auto& conn : wellP.getConnections()) { - BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10); + { + const auto scalingFactor = wellP.getWellPIScalingFactor(3.0); + BOOST_CHECK_CLOSE(scalingFactor, 1.0, 1.0e-10); + + wellP.applyWellProdIndexScaling(scalingFactor); + for (const auto& conn : wellP.getConnections()) { + BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10); + } } BOOST_CHECK_MESSAGE(wellP.updateWellProductivityIndex(WellPI{ 3.0, Phase::OIL }),