From 6f124fb47882a0cedec77a815fdcf95cba0e6411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Wed, 28 Oct 2020 21:25:33 +0100 Subject: [PATCH 1/4] Revert "Capture Preferred Phase When Processing WELPI Keyword" There and back again. We don't actually need the preferred phase at the time of encountering the WELPI request. [at]joakim-hove was right, the preferred phase of an injector must reflect the state at the same report step as the WELPI keyword. In other words, if the injected phase is reset at the same report step as a WELPI keyword, then the new preferred phase must be that of the new injected phase. This reverts commit 3eef45e87d644285a026d91a6360579346840ff8. --- .../EclipseState/Schedule/Well/Well.hpp | 29 ++----------------- .../EclipseState/Schedule/KeywordHandlers.cpp | 12 ++------ .../EclipseState/Schedule/Well/Well.cpp | 19 +++--------- tests/parser/WellTests.cpp | 13 ++------- 4 files changed, 13 insertions(+), 60 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp index 3524c3627..c49031c8e 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp @@ -433,28 +433,6 @@ public: double getBHPLimit() const; }; - struct WellProductivityIndex { - double pi_value; - Phase preferred_phase; - - bool operator==(const WellProductivityIndex& rhs) const - { - return (this->pi_value == rhs.pi_value) - && (this->preferred_phase == rhs.preferred_phase); - } - - bool operator!=(const WellProductivityIndex& rhs) const - { - return ! (*this == rhs); - } - - template - void serializeOp(Serializer& serializer) - { - serializer(this->pi_value); - serializer(this->preferred_phase); - } - }; Well() = default; Well(const std::string& wname, @@ -520,7 +498,6 @@ public: const WellPolymerProperties& getPolymerProperties() const; const WellBrineProperties& getBrineProperties() const; const WellTracerProperties& getTracerProperties() const; - const WellProductivityIndex& getWellProductivityIndex() const; /* The rate of a given phase under the following assumptions: * * Returns zero if production is requested for an injector (and vice * versa) @@ -580,7 +557,7 @@ public: bool updateEconLimits(std::shared_ptr econ_limits); bool updateProduction(std::shared_ptr production); bool updateInjection(std::shared_ptr injection); - bool updateWellProductivityIndex(const WellProductivityIndex& prodIndex); + bool updateWellProductivityIndex(const double prodIndex); bool updateWSEGSICD(const std::vector >& sicd_pairs); bool updateWSEGVALV(const std::vector >& valve_pairs); @@ -639,7 +616,7 @@ public: serializer(has_produced); serializer(has_injected); serializer(prediction_mode); - serializer.optional(productivity_index); + serializer(productivity_index); serializer(econ_limits); serializer(foam_properties); serializer(polymer_properties); @@ -677,7 +654,7 @@ private: bool has_produced = false; bool has_injected = false; bool prediction_mode = true; - std::optional productivity_index{ std::nullopt }; + std::optional productivity_index{ std::nullopt }; std::shared_ptr econ_limits; std::shared_ptr foam_properties; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index b023dd355..0dd271ed8 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -1124,14 +1124,8 @@ namespace { const auto rawProdIndex = record.getItem().get(0); for (const auto& well_name : well_names) { // All wells in a single record *hopefully* have the same preferred phase... - const auto& well = this->getWell(well_name, handlerContext.currentStep); - const auto preferred = well.getPreferredPhase(); - const auto unitPI = (preferred == Phase::GAS) ? gasPI : liqPI; - - const auto wellPI = Well::WellProductivityIndex { - usys.to_si(unitPI, rawProdIndex), - preferred - }; + const auto& well = this->getWell(well_name, handlerContext.currentStep); + const auto unitPI = (well.getPreferredPhase() == Phase::GAS) ? gasPI : liqPI; // Note: Need to ensure we have an independent copy of // well's connections because @@ -1140,7 +1134,7 @@ namespace { auto well2 = std::make_shared(well); auto connections = std::make_shared(well2->getConnections()); well2->forceUpdateConnections(std::move(connections)); - if (well2->updateWellProductivityIndex(wellPI)) + if (well2->updateWellProductivityIndex(usys.to_si(unitPI, rawProdIndex))) this->updateWell(std::move(well2), handlerContext.currentStep); this->addWellGroupEvent(well_name, ScheduleEvents::WELL_PRODUCTIVITY_INDEX, handlerContext.currentStep); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp index f330c2d07..3b558b768 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include namespace Opm { @@ -376,7 +375,7 @@ Well Well::serializeObject() result.efficiency_factor = 8.0; result.solvent_fraction = 9.0; result.prediction_mode = false; - result.productivity_index = WellProductivityIndex { 10.0, Phase::GAS }; + result.productivity_index = 10.0; result.econ_limits = std::make_shared(Opm::WellEconProductionLimits::serializeObject()); result.foam_properties = std::make_shared(WellFoamProperties::serializeObject()); result.polymer_properties = std::make_shared(WellPolymerProperties::serializeObject()); @@ -492,7 +491,7 @@ bool Well::updateInjection(std::shared_ptr injection_ar return update; } -bool Well::updateWellProductivityIndex(const WellProductivityIndex& prodIndex) { +bool Well::updateWellProductivityIndex(const double prodIndex) { const auto update = this->productivity_index != prodIndex; if (update) this->productivity_index = prodIndex; @@ -846,11 +845,11 @@ double Well::getWellPIScalingFactor(const double currentEffectivePI) const { // WELPI not activated. Nothing to do. return 1.0; - if (this->productivity_index->pi_value == currentEffectivePI) + if (this->productivity_index == currentEffectivePI) // No change in scaling. return 1.0; - return this->productivity_index->pi_value / currentEffectivePI; + return *this->productivity_index / currentEffectivePI; } void Well::applyWellProdIndexScaling(const double scalingFactor, std::vector& scalingApplicable) { @@ -898,16 +897,6 @@ const WellTracerProperties& Well::getTracerProperties() const { return *this->tracer_properties; } -const Well::WellProductivityIndex& Well::getWellProductivityIndex() const -{ - if (this->productivity_index) - return *this->productivity_index; - else - throw std::logic_error { - "WELPI not activated in well " + this->name() - }; -} - const WellEconProductionLimits& Well::getEconLimits() const { return *this->econ_limits; } diff --git a/tests/parser/WellTests.cpp b/tests/parser/WellTests.cpp index a56620a0e..56a63e84f 100644 --- a/tests/parser/WellTests.cpp +++ b/tests/parser/WellTests.cpp @@ -1199,8 +1199,6 @@ COMPDAT END )"); - using WellPIType = Well::WellProductivityIndex; - const auto es = EclipseState{ deck }; const auto sched = Schedule{ deck, es }; @@ -1232,9 +1230,9 @@ END // / // // (ignoring units of measure) - BOOST_CHECK_MESSAGE(wellP.updateWellProductivityIndex(WellPIType{ 2.0, Phase::GAS }), + BOOST_CHECK_MESSAGE(wellP.updateWellProductivityIndex(2.0), "First call to updateWellProductivityIndex() must be a state change"); - BOOST_CHECK_MESSAGE(!wellP.updateWellProductivityIndex(WellPIType{ 2.0, Phase::GAS }), + BOOST_CHECK_MESSAGE(!wellP.updateWellProductivityIndex(2.0), "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. @@ -1270,7 +1268,7 @@ END } // New WELPI record does not reset the scaling factors - wellP.updateWellProductivityIndex(WellPIType{ 3.0, Phase::GAS }); + wellP.updateWellProductivityIndex(3.0); for (const auto& conn : wellP.getConnections()) { BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10); } @@ -1290,11 +1288,6 @@ END BOOST_CHECK_MESSAGE(applicable, "All connections must be eligible for WELPI scaling"); } } - - BOOST_CHECK_MESSAGE(wellP.updateWellProductivityIndex(WellPIType{ 3.0, Phase::OIL }), - "Fourth call to updateWellProductivityIndex() must be a state change"); - BOOST_CHECK_MESSAGE(!wellP.updateWellProductivityIndex(WellPIType{ 3.0, Phase::OIL }), - "Fifth call to updateWellProductivityIndex() must NOT be a state change"); } BOOST_AUTO_TEST_CASE(Has_Same_Connections_Pointers) { From 54e2eb55977078c8ae8552ba1cc396a1baae75f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Wed, 28 Oct 2020 22:13:01 +0100 Subject: [PATCH 2/4] Store Raw WELPI in Well::productivity_index This makes the interface less convenient to use, but it is the only way to guarantee that we have a consistent notion of preferred phase for injectors. The downside is that the users of Well::getWellPIScalingFactor() must convert the argument to raw/input units before calling the function. --- .../EclipseState/Schedule/KeywordHandlers.cpp | 11 ++--------- tests/parser/ScheduleTests.cpp | 15 +++++---------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index 0dd271ed8..e7714599a 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -1108,10 +1108,6 @@ namespace { using WELL_NAME = ParserKeywords::WELPI::WELL_NAME; using PI = ParserKeywords::WELPI::STEADY_STATE_PRODUCTIVITY_OR_INJECTIVITY_INDEX_VALUE; - const auto& usys = handlerContext.section.unitSystem(); - const auto gasPI = UnitSystem::measure::gas_productivity_index; - const auto liqPI = UnitSystem::measure::liquid_productivity_index; - for (const auto& record : handlerContext.keyword) { const auto well_names = this->wellNames(record.getItem().getTrimmedString(0), handlerContext.currentStep); @@ -1123,18 +1119,15 @@ namespace { const auto rawProdIndex = record.getItem().get(0); for (const auto& well_name : well_names) { - // All wells in a single record *hopefully* have the same preferred phase... - const auto& well = this->getWell(well_name, handlerContext.currentStep); - const auto unitPI = (well.getPreferredPhase() == Phase::GAS) ? gasPI : liqPI; + auto well2 = std::make_shared(this->getWell(well_name, handlerContext.currentStep)); // Note: Need to ensure we have an independent copy of // well's connections because // Well::updateWellProductivityIndex() implicitly mutates // internal state in the WellConnections class. - auto well2 = std::make_shared(well); auto connections = std::make_shared(well2->getConnections()); well2->forceUpdateConnections(std::move(connections)); - if (well2->updateWellProductivityIndex(usys.to_si(unitPI, rawProdIndex))) + if (well2->updateWellProductivityIndex(rawProdIndex)) this->updateWell(std::move(well2), handlerContext.currentStep); this->addWellGroupEvent(well_name, ScheduleEvents::WELL_PRODUCTIVITY_INDEX, handlerContext.currentStep); diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 20f41f9a7..1cbe62256 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -60,11 +60,6 @@ using namespace Opm; namespace { - double liquid_PI_unit() - { - return UnitSystem::newMETRIC().to_si(UnitSystem::measure::liquid_productivity_index, 1.0); - } - double cp_rm3_per_db() { return prefix::centi*unit::Poise * unit::cubic(unit::meter) @@ -3816,7 +3811,7 @@ END const auto expectCF = (200.0 / 100.0) * 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 1); - const auto scalingFactor = wellP.getWellPIScalingFactor(100.0*liquid_PI_unit()); + const auto scalingFactor = wellP.getWellPIScalingFactor(100.0); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); std::vector scalingApplicable; @@ -3835,7 +3830,7 @@ END const auto expectCF = (200.0 / 100.0) * 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 2); - const auto scalingFactor = wellP.getWellPIScalingFactor(100.0*liquid_PI_unit()); + const auto scalingFactor = wellP.getWellPIScalingFactor(100.0); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); std::vector scalingApplicable; @@ -3959,7 +3954,7 @@ END // Apply WELPI scaling after end of time series => no change to CTFs { const auto report_step = std::size_t{1}; - const auto scalingFactor = getScalingFactor(report_step, 100.0*liquid_PI_unit()); + const auto scalingFactor = getScalingFactor(report_step, 100.0); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); @@ -4025,7 +4020,7 @@ END // Apply WELPI scaling after first WELPI specification { const auto report_step = std::size_t{1}; - const auto scalingFactor = getScalingFactor(report_step, 100.0*liquid_PI_unit()); + const auto scalingFactor = getScalingFactor(report_step, 100.0); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); @@ -4093,7 +4088,7 @@ END // Apply WELPI scaling after second WELPI specification { const auto report_step = std::size_t{3}; - const auto scalingFactor = getScalingFactor(report_step, 200.0*liquid_PI_unit()); + const auto scalingFactor = getScalingFactor(report_step, 200.0); BOOST_CHECK_CLOSE(scalingFactor, 0.25, 1.0e-10); From 354351daeea4cb3d0bb38b58ff13c94079e06351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Wed, 28 Oct 2020 22:31:46 +0100 Subject: [PATCH 3/4] Record General Event When Processing WELPI This commit ensures that we record a general, Schedule-level WELL_PRODUCTIVITY_INDEX event in addition to the well-specific event already recorded when we encounter a WELPI keyword. We need this information in order to trigger a PI calculation across all MPI processes in opm-simulators. --- .../eclipse/EclipseState/Schedule/KeywordHandlers.cpp | 2 ++ tests/parser/ScheduleTests.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index e7714599a..1c61eeacc 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -1133,6 +1133,8 @@ namespace { this->addWellGroupEvent(well_name, ScheduleEvents::WELL_PRODUCTIVITY_INDEX, handlerContext.currentStep); } } + + this->m_events.addEvent(ScheduleEvents::WELL_PRODUCTIVITY_INDEX, handlerContext.currentStep); } void Schedule::handleWELSEGS(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 1cbe62256..08d49e2d6 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -3931,9 +3931,15 @@ END BOOST_REQUIRE_EQUAL(sched.getTimeMap().last(), std::size_t{5}); BOOST_REQUIRE_MESSAGE(sched.hasWellGroupEvent("P", ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX, 1), - "Schedule must have WELL_PRODUCTIVITY_INDEX Event at report step 1"); + R"(Schedule must have WELL_PRODUCTIVITY_INDEX Event for well "P" at report step 1)"); BOOST_REQUIRE_MESSAGE(sched.hasWellGroupEvent("P", ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX, 3), + R"(Schedule must have WELL_PRODUCTIVITY_INDEX Event for well "P" at report step 3)"); + + BOOST_REQUIRE_MESSAGE(sched.getEvents().hasEvent(ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX, 1), + "Schedule must have WELL_PRODUCTIVITY_INDEX Event at report step 1"); + + BOOST_REQUIRE_MESSAGE(sched.getEvents().hasEvent(ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX, 3), "Schedule must have WELL_PRODUCTIVITY_INDEX Event at report step 3"); auto getScalingFactor = [&sched](const std::size_t report_step, const double wellPI) -> double From 94af88c3a1446d639b6d37e953e05c61532d0b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 30 Oct 2020 13:04:36 +0100 Subject: [PATCH 4/4] Switch Back to Consuming Strictly SI Convention PI Values Heed advice from [at]joakim-hove to keep client code as close to strictly SI as possible. We must nevertheless continue to store the raw (input/output units) requested PI value internally as this is the only way to ensure that both the client and implementation has consistent view of the well's preferred phase. This means pushing the unit conversion into Well::getWellPIScalingFactor(). Thanks to [at]joakim-hove for pointing out that the Well already maintains an internal UnitSystem data member which makes the process of converting the PI units trivial. --- .../EclipseState/Schedule/Well/Well.cpp | 35 ++++++++++++++++--- tests/parser/ScheduleTests.cpp | 18 ++++++---- tests/parser/WellTests.cpp | 14 +++++--- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp index 3b558b768..df7f862b9 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include namespace Opm { @@ -836,6 +838,32 @@ void Well::setInsertIndex(std::size_t index) { this->insert_index = index; } +namespace { + double convertWellPIToSI(const double rawWellPI, + const Phase preferred_phase, + const UnitSystem& unit_system) + { + using M = UnitSystem::measure; + + // XXX: Should really have LIQUID here too, but the 'Phase' type does + // not provide that enumerator. + switch (preferred_phase) { + case Phase::GAS: + return unit_system.to_si(M::gas_productivity_index, rawWellPI); + + case Phase::OIL: + case Phase::WATER: + return unit_system.to_si(M::liquid_productivity_index, rawWellPI); + + default: + throw std::invalid_argument { + "Preferred phase " + std::to_string(static_cast(preferred_phase)) + + " is not supported. Must be one of 'OIL', 'GAS', or 'WATER'" + }; + } + } +} + double Well::getWellPIScalingFactor(const double currentEffectivePI) const { if (this->connections->empty()) // No connections for this well. Unexpected. @@ -845,11 +873,10 @@ double Well::getWellPIScalingFactor(const double currentEffectivePI) const { // WELPI not activated. Nothing to do. return 1.0; - if (this->productivity_index == currentEffectivePI) - // No change in scaling. - return 1.0; + const double requestedWellPI_SI = + convertWellPIToSI(*this->productivity_index, this->getPreferredPhase(), this->unit_system); - return *this->productivity_index / currentEffectivePI; + return requestedWellPI_SI / currentEffectivePI; } void Well::applyWellProdIndexScaling(const double scalingFactor, std::vector& scalingApplicable) { diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 08d49e2d6..4896a9ac7 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -60,10 +60,14 @@ using namespace Opm; namespace { + double liquid_PI_unit() + { + return UnitSystem::newMETRIC().to_si(UnitSystem::measure::liquid_productivity_index, 1.0); + } + double cp_rm3_per_db() { - return prefix::centi*unit::Poise * unit::cubic(unit::meter) - / (unit::day * unit::barsa); + return UnitSystem::newMETRIC().to_si(UnitSystem::measure::transmissibility, 1.0); } } @@ -3811,7 +3815,7 @@ END const auto expectCF = (200.0 / 100.0) * 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 1); - const auto scalingFactor = wellP.getWellPIScalingFactor(100.0); + const auto scalingFactor = wellP.getWellPIScalingFactor(100.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); std::vector scalingApplicable; @@ -3830,7 +3834,7 @@ END const auto expectCF = (200.0 / 100.0) * 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 2); - const auto scalingFactor = wellP.getWellPIScalingFactor(100.0); + const auto scalingFactor = wellP.getWellPIScalingFactor(100.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); std::vector scalingApplicable; @@ -3960,7 +3964,7 @@ END // Apply WELPI scaling after end of time series => no change to CTFs { const auto report_step = std::size_t{1}; - const auto scalingFactor = getScalingFactor(report_step, 100.0); + const auto scalingFactor = getScalingFactor(report_step, 100.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); @@ -4026,7 +4030,7 @@ END // Apply WELPI scaling after first WELPI specification { const auto report_step = std::size_t{1}; - const auto scalingFactor = getScalingFactor(report_step, 100.0); + const auto scalingFactor = getScalingFactor(report_step, 100.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); @@ -4094,7 +4098,7 @@ END // Apply WELPI scaling after second WELPI specification { const auto report_step = std::size_t{3}; - const auto scalingFactor = getScalingFactor(report_step, 200.0); + const auto scalingFactor = getScalingFactor(report_step, 200.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 0.25, 1.0e-10); diff --git a/tests/parser/WellTests.cpp b/tests/parser/WellTests.cpp index 56a63e84f..a47a9ac18 100644 --- a/tests/parser/WellTests.cpp +++ b/tests/parser/WellTests.cpp @@ -53,10 +53,14 @@ using namespace Opm; namespace { + double liquid_PI_unit() + { + return UnitSystem::newMETRIC().to_si(UnitSystem::measure::liquid_productivity_index, 1.0); + } + double cp_rm3_per_db() { - return prefix::centi*unit::Poise * unit::cubic(unit::meter) - / (unit::day * unit::barsa); + return UnitSystem::newMETRIC().to_si(UnitSystem::measure::transmissibility, 1.0); } } @@ -1237,7 +1241,7 @@ END // Want PI=2, but actual/effective PI=1 => scale CF by 2.0/1.0. { - const auto scalingFactor = wellP.getWellPIScalingFactor(1.0); + const auto scalingFactor = wellP.getWellPIScalingFactor(1.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); std::vector scalingApplicable; @@ -1253,7 +1257,7 @@ END // Repeated application of WELPI multiplies scaling factors. { - const auto scalingFactor = wellP.getWellPIScalingFactor(1.0); + const auto scalingFactor = wellP.getWellPIScalingFactor(1.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10); std::vector scalingApplicable; @@ -1275,7 +1279,7 @@ END // Effective PI=desired PI => no scaling change { - const auto scalingFactor = wellP.getWellPIScalingFactor(3.0); + const auto scalingFactor = wellP.getWellPIScalingFactor(3.0*liquid_PI_unit()); BOOST_CHECK_CLOSE(scalingFactor, 1.0, 1.0e-10); std::vector scalingApplicable;