diff --git a/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp b/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp index 66082785a..39c9860ef 100644 --- a/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp +++ b/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp @@ -30,31 +30,128 @@ namespace Opm { namespace Opm { namespace satfunc { + /// Collection of unscaled/raw saturation range endpoints extracted + /// directly from tables of tabulated saturation functions. struct RawTableEndPoints { + /// Connate saturation endpoints struct { + /// Connate gas saturation. One value for each saturation region. + /// All zero values unless gas is an active phase. std::vector gas; + + /// Connate water saturation. One value for each saturation region. + /// All zero values unless water is an active phase. std::vector water; } connate; + /// Critical saturation endpoints struct { + /// Critical saturation of oil in oil/gas two-phase system. One + /// value for each saturation region. All zero values unless oil + /// is an active phase. std::vector oil_in_gas; + + /// Critical saturation of oil in oil/water two-phase system. One + /// value for each saturation region. All zero values unless oil + /// is an active phase. std::vector oil_in_water; + + /// Critical saturation of gas. One value for each saturation + /// region. All zero values unless oil is an active phase. std::vector gas; + + /// Critical saturation of water. One value for each saturation + /// region. All zero values unless oil is an active phase. std::vector water; } critical; + /// Maximum saturation endpoints struct { + /// Maximum gas saturation value. One value for each saturation + /// region All zero values unless gas is an active phase. std::vector gas; + + /// Maximum water saturation value. One value for each saturation + /// region All zero values unless gas is an active phase. std::vector water; } maximum; }; + /// Collection of unscaled/raw saturation function value range endpoints + /// extracted directly from tables of tabulated saturation functions. + struct RawFunctionValues + { + /// Function values for relative permeability of oil. + struct { + /// Maximum relative permeability value of oil in both oil/gas and + /// oil/water two-phase systems. One value for each saturation + /// region. All zero values unless oil is an active phase. + std::vector max; + + /// Relative permeability of oil at critical saturation of + /// displacing phase in oil/gas two-phase system. One value for + /// each saturation region. All zero values unless oil is + /// an active phase. + std::vector rg; + + /// Relative permeability of oil at critical saturation of + /// displacing phase in oil/water two-phase system. One value + /// for each saturation region. All zero values unless oil is + /// an active phase. + std::vector rw; + } kro; + + /// Function values for relative permeability of gas. + struct { + /// Maximum relative permeability value of gas. One value for + /// each saturation region. All zero values unless gas is + /// an active phase. + std::vector max; + + /// Relative permeability of gas at critical saturation of + /// displacing phase. One value for each saturation region. + /// All zero values unless gas is an active phase. + std::vector r; + } krg; + + /// Function values for relative permeability of gas. + struct { + /// Maximum relative permeability value of water. One value for + /// each saturation region. All zero values unless water is + /// an active phase. + std::vector max; + + /// Relative permeability of water at critical saturation of + /// displacing phase. One value for each saturation region. + /// All zero values unless water is an active phase. + std::vector r; + } krw; + + /// Maximum capillary function values. + struct { + /// Maximum gas/oil capillary pressure value (Pg - Po). One + /// value for each saturation region. All zero values unless + /// both gas and oil are active phase. + std::vector g; + + /// Maximum oil/eater capillary pressure value (Po - Pw). One + /// value for each saturation region. All zero values unless + /// both oil and water are active phase. + std::vector w; + } pc; + }; + std::shared_ptr getRawTableEndpoints(const Opm::TableManager& tm, const Opm::Phases& phases, const double tolcrit); + std::shared_ptr + getRawFunctionValues(const Opm::TableManager& tm, + const Opm::Phases& phases, + const RawTableEndPoints& ep); + std::vector init(const std::string& kewyord, const TableManager& tables, const Phases& phases, diff --git a/src/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.cpp b/src/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.cpp index d117c986e..0d8da0e49 100644 --- a/src/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.cpp @@ -1,4 +1,7 @@ /* + Copyright 2019-2020 Equinor ASA + Copyright 2014 Andreas Lauser + 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 @@ -1595,6 +1598,29 @@ Opm::satfunc::getRawTableEndpoints(const Opm::TableManager& tm, return ep; } +std::shared_ptr +Opm::satfunc::getRawFunctionValues(const Opm::TableManager& tm, + const Opm::Phases& phases, + const RawTableEndPoints& ep) +{ + auto fval = std::make_shared(); + + fval->kro.max = findMaxKro(tm, phases); + fval->kro.rg = findKrorg(tm, phases, ep); + fval->kro.rw = findKrorw(tm, phases, ep); + + fval->krg.max = findMaxKrg(tm, phases); + fval->krg.r = findKrgr(tm, phases, ep); + + fval->krw.max = findMaxKrw(tm, phases); + fval->krw.r = findKrwr(tm, phases, ep); + + fval->pc.g = findMaxPcog(tm, phases); + fval->pc.w = findMaxPcow(tm, phases); + + return fval; +} + std::vector Opm::satfunc::init(const std::string& keyword, const TableManager& tables, diff --git a/tests/parser/FieldPropsTests.cpp b/tests/parser/FieldPropsTests.cpp index 21efe1807..cc779f120 100644 --- a/tests/parser/FieldPropsTests.cpp +++ b/tests/parser/FieldPropsTests.cpp @@ -1218,6 +1218,166 @@ BOOST_AUTO_TEST_CASE(RawTableEndPoints_Family_II_TolCrit_Large) { // ===================================================================== +BOOST_AUTO_TEST_CASE(RawFunctionValues_Family_I_Tolcrit_Zero) { + const auto es = ::Opm::EclipseState { + ::Opm::Parser{}.parseString(satfunc_model_setup() + satfunc_family_I() + end()) + }; + + const auto& tm = es.getTableManager(); + const auto& ph = es.runspec().phases(); + const auto tolcrit = 0.0; + + const auto rtepPtr = satfunc::getRawTableEndpoints(tm, ph, tolcrit); + const auto rfuncPtr = satfunc::getRawFunctionValues(tm, ph, *rtepPtr); + + // Oil values (TOLCRIT = 0.0) + BOOST_CHECK_CLOSE(rfuncPtr->kro.rw [0], 1.0, 1.0e-10); // Krow(So=1-Swcr-Sgl) = Krow(So=0.928996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.rg [0], 0.896942, 1.0e-10); // Krog(So=1-Sgcr-Swl) = Krog(So=0.898996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.max[0], 1.0, 1.0e-10); // Krow(So=Somax) = Krog(So=Somax) + + // Gas values + BOOST_CHECK_CLOSE(rfuncPtr->krg.r [0], 0.866135, 1.0e-10); // Krg(Sg=1-Sogcr-Swl) = Krg(Sg=0.858996) + BOOST_CHECK_CLOSE(rfuncPtr->krg.max[0], 1.0 , 1.0e-10); // Krg(Sgmax) = Krg(Sg=0.928996) + + // Water values + BOOST_CHECK_CLOSE(rfuncPtr->krw.r [0], 0.911429, 1.0e-10); // Krw(Sw=1-Sowcr-Sgl) = Krw(Sw=0.791004) + BOOST_CHECK_CLOSE(rfuncPtr->krw.max[0], 1.0 , 1.0e-10); // Krw(Swmax) = Krw(Sw=1) +} + +BOOST_AUTO_TEST_CASE(RawFunctionValues_Family_II_Tolcrit_Zero) { + const auto es = ::Opm::EclipseState { + ::Opm::Parser{}.parseString(satfunc_model_setup() + satfunc_family_II() + end()) + }; + + const auto& tm = es.getTableManager(); + const auto& ph = es.runspec().phases(); + const auto tolcrit = 0.0; + + const auto rtepPtr = satfunc::getRawTableEndpoints(tm, ph, tolcrit); + const auto rfuncPtr = satfunc::getRawFunctionValues(tm, ph, *rtepPtr); + + // Oil values + BOOST_CHECK_CLOSE(rfuncPtr->kro.rw [0], 1.0, 1.0e-10); // Krow(So=1-Swcr-Sgl) = Krow(So=0.928996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.rg [0], 0.896942, 1.0e-10); // Krog(So=1-Sgcr-Swl) = Krog(So=0.898996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.max[0], 1.0, 1.0e-10); // Krow(So=Somax) = Krog(So=Somax) + + // Gas values + BOOST_CHECK_CLOSE(rfuncPtr->krg.r [0], 0.866135, 1.0e-10); // Krg(Sg=1-Sogcr-Swl) = Krg(Sg=0.858996) + BOOST_CHECK_CLOSE(rfuncPtr->krg.max[0], 1.0 , 1.0e-10); // Krg(Sgmax) = Krg(Sg=0.928996) + + // Water values + BOOST_CHECK_CLOSE(rfuncPtr->krw.r [0], 0.911429, 1.0e-10); // Krw(Sw=1-Sowcr-Sgl) = Krw(Sw=0.791004) + BOOST_CHECK_CLOSE(rfuncPtr->krw.max[0], 1.0 , 1.0e-10); // Krw(Swmax) = Krw(Sw=1) +} + +BOOST_AUTO_TEST_CASE(RawFunctionValues_Family_I_Tolcrit_Default) { + const auto es = ::Opm::EclipseState { + ::Opm::Parser{}.parseString(satfunc_model_setup() + satfunc_family_I() + end()) + }; + + const auto& tm = es.getTableManager(); + const auto& ph = es.runspec().phases(); + const auto tolcrit = es.runspec().saturationFunctionControls() + .minimumRelpermMobilityThreshold(); // 1.0e-6. + + const auto rtepPtr = satfunc::getRawTableEndpoints(tm, ph, tolcrit); + const auto rfuncPtr = satfunc::getRawFunctionValues(tm, ph, *rtepPtr); + + // Oil values + BOOST_CHECK_CLOSE(rfuncPtr->kro.rw [0], 0.882459, 1.0e-10); // Krow(So=1-Swcr-Sgl) = Krow(So=0.908996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.rg [0], 0.896942, 1.0e-10); // Krog(So=1-Sgcr-Swl) = Krog(So=0.898996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.max[0], 1.0, 1.0e-10); // Krow(So=Somax) = Krog(So=Somax) + + // Gas values + BOOST_CHECK_CLOSE(rfuncPtr->krg.r [0], 0.866135, 1.0e-10); // Krg(Sg=1-Sogcr-Swl) = Krg(Sg=0.858996) + BOOST_CHECK_CLOSE(rfuncPtr->krg.max[0], 1.0 , 1.0e-10); // Krg(Sgmax) = Krg(Sg=0.928996) + + // Water values + BOOST_CHECK_CLOSE(rfuncPtr->krw.r [0], 0.835916, 1.0e-10); // Krw(Sw=1-Sowcr-Sgl) = Krw(Sw=0.771004) + BOOST_CHECK_CLOSE(rfuncPtr->krw.max[0], 1.0 , 1.0e-10); // Krw(Swmax) = Krw(Sw=1) +} + +BOOST_AUTO_TEST_CASE(RawFunctionValues_Family_II_Tolcrit_Default) { + const auto es = ::Opm::EclipseState { + ::Opm::Parser{}.parseString(satfunc_model_setup() + satfunc_family_II() + end()) + }; + + const auto& tm = es.getTableManager(); + const auto& ph = es.runspec().phases(); + const auto tolcrit = es.runspec().saturationFunctionControls() + .minimumRelpermMobilityThreshold(); // 1.0e-6. + + const auto rtepPtr = satfunc::getRawTableEndpoints(tm, ph, tolcrit); + const auto rfuncPtr = satfunc::getRawFunctionValues(tm, ph, *rtepPtr); + + // Oil values + BOOST_CHECK_CLOSE(rfuncPtr->kro.rw [0], 0.882459, 1.0e-10); // Krow(So=1-Swcr-Sgl) = Krow(So=0.908996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.rg [0], 0.896942, 1.0e-10); // Krog(So=1-Sgcr-Swl) = Krog(So=0.898996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.max[0], 1.0 , 1.0e-10); // Krow(So=Somax) = Krog(So=Somax) + + // Gas values + BOOST_CHECK_CLOSE(rfuncPtr->krg.r [0], 0.866135, 1.0e-10); // Krg(Sg=1-Sogcr-Swl) = Krg(Sg=0.858996) + BOOST_CHECK_CLOSE(rfuncPtr->krg.max[0], 1.0 , 1.0e-10); // Krg(Sgmax) = Krg(Sg=0.928996) + + // Water values + BOOST_CHECK_CLOSE(rfuncPtr->krw.r [0], 0.835916, 1.0e-10); // Krw(Sw=1-Sowcr-Sgl) = Krw(Sw=0.771004) + BOOST_CHECK_CLOSE(rfuncPtr->krw.max[0], 1.0 , 1.0e-10); // Krw(Swmax) = Krw(Sw=1) +} + +BOOST_AUTO_TEST_CASE(RawFunctionValues_Family_I_Tolcrit_Large) { + const auto es = ::Opm::EclipseState { + ::Opm::Parser{}.parseString(satfunc_model_setup() + satfunc_family_I() + end()) + }; + + const auto& tm = es.getTableManager(); + const auto& ph = es.runspec().phases(); + const auto tolcrit = 0.01; + + const auto rtepPtr = satfunc::getRawTableEndpoints(tm, ph, tolcrit); + const auto rfuncPtr = satfunc::getRawFunctionValues(tm, ph, *rtepPtr); + + // Oil values + BOOST_CHECK_CLOSE(rfuncPtr->kro.rw [0], 0.328347, 1.0e-10); // Krow(So=1-Swcr-Sgl) = Krow(So=0.768996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.rg [0], 0.712749, 1.0e-10); // Krog(So=1-Sgcr-Swl) = Krog(So=0.838996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.max[0], 1.0, 1.0e-10); // Krow(So=Somax) = Krog(So=Somax) + + // Gas values + BOOST_CHECK_CLOSE(rfuncPtr->krg.r [0], 0.578171, 1.0e-10); // Krg(Sg=1-Sogcr-Swl) = Krg(Sg=0.690000) + BOOST_CHECK_CLOSE(rfuncPtr->krg.max[0], 1.0 , 1.0e-10); // Krg(Sgmax) = Krg(Sg=0.928996) + + // Water values + BOOST_CHECK_CLOSE(rfuncPtr->krw.r [0], 0.261115, 1.0e-10); // Krw(Sw=1-Sowcr-Sgl) = Krw(Sw=0.551004) + BOOST_CHECK_CLOSE(rfuncPtr->krw.max[0], 1.0 , 1.0e-10); // Krw(Swmax) = Krw(Sw=1) +} + +BOOST_AUTO_TEST_CASE(RawFunctionValues_Family_II_Tolcrit_Large) { + const auto es = ::Opm::EclipseState { + ::Opm::Parser{}.parseString(satfunc_model_setup() + satfunc_family_II() + end()) + }; + + const auto& tm = es.getTableManager(); + const auto& ph = es.runspec().phases(); + const auto tolcrit = 0.01; + + const auto rtepPtr = satfunc::getRawTableEndpoints(tm, ph, tolcrit); + const auto rfuncPtr = satfunc::getRawFunctionValues(tm, ph, *rtepPtr); + + // Oil values + BOOST_CHECK_CLOSE(rfuncPtr->kro.rw [0], 0.328347, 1.0e-10); // Krow(So=1-Swcr-Sgl) = Krow(So=0.768996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.rg [0], 0.712749, 1.0e-10); // Krog(So=1-Sgcr-Swl) = Krog(So=0.838996) + BOOST_CHECK_CLOSE(rfuncPtr->kro.max[0], 1.0, 1.0e-10); // Krow(So=Somax) = Krog(So=Somax) + + // Gas values + BOOST_CHECK_CLOSE(rfuncPtr->krg.r [0], 0.562914, 1.0e-10); // Krg(Sg=1-Sogcr-Swl) = Krg(Sg=0.680000) + BOOST_CHECK_CLOSE(rfuncPtr->krg.max[0], 1.0 , 1.0e-10); // Krg(Sgmax) = Krg(Sg=0.928996) + + // Water values + BOOST_CHECK_CLOSE(rfuncPtr->krw.r [0], 0.261115, 1.0e-10); // Krw(Sw=1-Sowcr-Sgl) = Krw(Sw=0.551004) + BOOST_CHECK_CLOSE(rfuncPtr->krw.max[0], 1.0 , 1.0e-10); // Krw(Swmax) = Krw(Sw=1) +} + +// ===================================================================== + BOOST_AUTO_TEST_CASE(SatFunc_EndPts_Family_I_TolCrit_Zero) { const auto es = ::Opm::EclipseState { ::Opm::Parser{}.parseString(satfunc_model_setup() + tolCrit(0.0) + satfunc_family_I() + end()) @@ -1576,6 +1736,8 @@ BOOST_AUTO_TEST_CASE(SatFunc_EndPts_Family_II_TolCrit_Large) { } } +// ===================================================================== + BOOST_AUTO_TEST_CASE(GET_FIPXYZ) { std::string deck_string = R"( GRID