opm-common/tests/test_Tables.cpp

3199 lines
148 KiB
C++
Raw Permalink Normal View History

/*
Copyright 2019 Equinor.
Copyright 2016 Statoil ASA.
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 of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
#define BOOST_TEST_MODULE Tabular_INIT_Output
#include <boost/test/unit_test.hpp>
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
#include <opm/output/eclipse/Tables.hpp>
#include <cstddef>
#include <exception>
#include <initializer_list>
#include <stdexcept>
#include <vector>
#include <opm/input/eclipse/Deck/Deck.hpp>
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
#include <opm/input/eclipse/Parser/Parser.hpp>
#include <opm/input/eclipse/Units/UnitSystem.hpp>
#include <opm/output/eclipse/VectorItems/tabdims.hpp>
2018-09-13 10:25:33 -05:00
using Ix = ::Opm::RestartIO::Helpers::VectorItems::TabDims::index;
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
namespace {
template <class Collection1, class Collection2>
void check_is_close(const Collection1& c1, const Collection2& c2)
{
BOOST_REQUIRE_EQUAL(c1.size(), c2.size());
if (! c1.empty()) {
auto i1 = c1.begin(), e1 = c1.end();
auto i2 = c2.begin();
for (; i1 != e1; ++i1, ++i2) {
BOOST_CHECK_CLOSE(*i1, *i2, 1.0e-10);
}
}
}
std::vector<double>
makeTable(const std::size_t ncol,
std::initializer_list<double> data)
{
auto result = std::vector<double>(data.size(), 0.0);
const auto nrows = data.size() / ncol;
auto di = std::begin(data);
for (auto i = 0*nrows; i < nrows; ++i) {
for (auto j = 0*ncol; j < ncol; ++j, ++di) {
result[i + j*nrows] = *di;
}
}
return result;
}
namespace SPE1 { // Family II (SGFN, SOF{2,3}, SWFN)
namespace TwoPhase {
namespace GasOil {
Opm::EclipseState satfuncTables()
{
const auto* input = R"(
RUNSPEC
OIL
GAS
METRIC
DIMENS
1 1 1 /
TABDIMS
/
-- =======================================
GRID
DXV
1 /
DYV
1 /
DZV
0.1 /
DEPTHZ
4*2000.0 /
PERMX
100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
0.3 /
-- =======================================
PROPS
SGFN
-- SPE 1 Table
0 0 0
0.001 0 0
0.02 0 0
0.05 0.005 0
0.12 0.025 0
0.2 0.075 0
0.25 0.125 0
0.3 0.190 0
0.4 0.410 0
0.45 0.60 0
0.5 0.72 0
0.6 0.87 0
0.7 0.94 0
0.85 0.98 0
0.88 0.984 0 /
SOF2
-- SPE 1 Table
0 0
0.03 0
0.18 0
0.28 0.0001
0.38 0.001
0.43 0.01
0.48 0.021
0.58 0.09
0.63 0.2
0.68 0.35
0.76 0.7
0.83 0.98
0.86 0.997
0.879 1
0.88 1 /
DENSITY
853.0 1014.0 0.75 /
END
)";
const auto deck = Opm::Deck{
Opm::Parser{}.parseString(input)
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
};
return Opm::EclipseState{deck};
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SGFN()
{
return makeTable(5, {
0, 0, 0, 1.000000000000000e+20, 1.0e+20,
1.00e-03, 0, 0, 0, 0,
2.00e-02, 0, 0, 0, 0,
5.00e-02, 5.000000000000000e-03, 0, 1.666666666666667e-01, 0,
1.20e-01, 2.500000000000000e-02, 0, 2.857142857142858e-01, 0,
2.00e-01, 7.500000000000000e-02, 0, 6.249999999999998e-01, 0,
2.50e-01, 1.250000000000000e-01, 0, 1.000000000000000e+00, 0,
3.00e-01, 1.900000000000000e-01, 0, 1.300000000000000e+00, 0,
4.00e-01, 4.100000000000000e-01, 0, 2.199999999999999e+00, 0,
4.50e-01, 6.000000000000000e-01, 0, 3.800000000000001e+00, 0,
5.00e-01, 7.200000000000000e-01, 0, 2.400000000000000e+00, 0,
6.00e-01, 8.700000000000000e-01, 0, 1.500000000000001e+00, 0,
7.00e-01, 9.399999999999999e-01, 0, 6.999999999999996e-01, 0,
8.50e-01, 9.800000000000000e-01, 0, 2.666666666666669e-01, 0,
8.80e-01, 9.840000000000000e-01, 0, 1.333333333333333e-01, 0,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SOFN()
{
return makeTable(3, {
0, 0, 1.000000000000000e+20,
3.00e-02, 0, 0,
1.80e-01, 0, 0,
2.80e-01, 1.00e-04, 9.999999999999998e-04,
3.80e-01, 1.00e-03, 9.000000000000001e-03,
4.30e-01, 1.00e-02, 1.800000000000000e-01,
4.80e-01, 2.10e-02, 2.200000000000001e-01,
5.80e-01, 9.00e-02, 6.900000000000001e-01,
6.30e-01, 2.00e-01, 2.199999999999998e+00,
6.80e-01, 3.50e-01, 2.999999999999997e+00,
7.60e-01, 7.00e-01, 4.375000000000002e+00,
8.30e-01, 9.80e-01, 4.000000000000004e+00,
8.60e-01, 9.97e-01, 5.666666666666667e-01,
8.79e-01, 1.00e+00, 1.578947368421053e-01,
8.80e-01, 1.00e+00, 0,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
});
}
} // GasOil
namespace OilWater {
Opm::EclipseState satfuncTables()
{
const auto* input = R"(
RUNSPEC
WATER
OIL
METRIC
DIMENS
1 1 1 /
TABDIMS
/
-- =======================================
GRID
DXV
1 /
DYV
1 /
DZV
0.1 /
DEPTHZ
4*2000.0 /
PERMX
100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
0.3 /
-- =======================================
PROPS
SWFN
-- SPE 1 Table
0.12 0 0
0.18 4.64876033057851E-008 0
0.24 0.000000186 0
0.3 4.18388429752066E-007 0
0.36 7.43801652892562E-007 0
0.42 1.16219008264463E-006 0
0.48 1.67355371900826E-006 0
0.54 2.27789256198347E-006 0
0.6 2.97520661157025E-006 0
0.66 3.7654958677686E-006 0
0.72 4.64876033057851E-006 0
0.78 0.000005625 0
0.84 6.69421487603306E-006 0
0.91 8.05914256198347E-006 0
1 0.00001 0 /
SOF2
-- SPE 1 Table
0 0
0.03 0
0.18 0
0.28 0.0001
0.38 0.001
0.43 0.01
0.48 0.021
0.58 0.09
0.63 0.2
0.68 0.35
0.76 0.7
0.83 0.98
0.86 0.997
0.879 1
0.88 1
/
DENSITY
853.0 1014.0 0.75 /
END
)";
const auto deck = Opm::Deck{
Opm::Parser{}.parseString(input)
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
};
return Opm::EclipseState{deck};
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SOFN()
{
return makeTable(3, {
0, 0, 1.000000000000000e+20,
3.00e-02, 0, 0,
1.80e-01, 0, 0,
2.80e-01, 1.00e-04, 9.999999999999998e-04,
3.80e-01, 1.00e-03, 9.000000000000001e-03,
4.30e-01, 1.00e-02, 1.800000000000000e-01,
4.80e-01, 2.10e-02, 2.200000000000001e-01,
5.80e-01, 9.00e-02, 6.900000000000001e-01,
6.30e-01, 2.00e-01, 2.199999999999998e+00,
6.80e-01, 3.50e-01, 2.999999999999997e+00,
7.60e-01, 7.00e-01, 4.375000000000002e+00,
8.30e-01, 9.80e-01, 4.000000000000004e+00,
8.60e-01, 9.97e-01, 5.666666666666667e-01,
8.79e-01, 1.00e+00, 1.578947368421053e-01,
8.80e-01, 1.00e+00, 0,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.000000000000000e+20,
});
}
std::vector<double> expect_SWFN()
{
return makeTable(5, {
1.20e-01, 0, 0, 1.000000000000000e+20, 1.0e+20,
1.80e-01, 0, 0, 0, 0,
2.40e-01, 0, 0, 0, 0,
3.00e-01, 0, 0, 0, 0,
3.60e-01, 0, 0, 0, 0,
4.20e-01, 1.162190082644630e-06, 0, 1.936983471074384e-05, 0,
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
4.80e-01, 1.673553719008260e-06, 0, 8.522727272727165e-06, 0,
5.40e-01, 2.277892561983470e-06, 0, 1.007231404958682e-05, 0,
6.00e-01, 2.975206611570250e-06, 0, 1.162190082644635e-05, 0,
6.60e-01, 3.765495867768600e-06, 0, 1.317148760330582e-05, 0,
7.20e-01, 4.648760330578510e-06, 0, 1.472107438016518e-05, 0,
7.80e-01, 5.625000000000000e-06, 0, 1.627066115702482e-05, 0,
8.40e-01, 6.694214876033060e-06, 0, 1.782024793388435e-05, 0,
9.10e-01, 8.059142561983471e-06, 0, 1.949896694214870e-05, 0,
1.00e+00, 1.000000000000000e-05, 0, 2.156508264462812e-05, 0,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
} // OilWater
} // TwoPhase
namespace ThreePhase {
Opm::EclipseState satfuncTables()
{
const auto* input = R"(
RUNSPEC
WATER
OIL
GAS
METRIC
DIMENS
1 1 1 /
TABDIMS
/
-- =======================================
GRID
DXV
1 /
DYV
1 /
DZV
0.1 /
DEPTHZ
4*2000.0 /
PERMX
100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
0.3 /
-- =======================================
PROPS
SWFN
-- SPE 1 Table
0.12 0 0
0.18 4.64876033057851E-008 0
0.24 0.000000186 0
0.3 4.18388429752066E-007 0
0.36 7.43801652892562E-007 0
0.42 1.16219008264463E-006 0
0.48 1.67355371900826E-006 0
0.54 2.27789256198347E-006 0
0.6 2.97520661157025E-006 0
0.66 3.7654958677686E-006 0
0.72 4.64876033057851E-006 0
0.78 0.000005625 0
0.84 6.69421487603306E-006 0
0.91 8.05914256198347E-006 0
1 0.00001 0 /
SGFN
-- SPE 1 Table
0 0 0
0.001 0 0
0.02 0 0
0.05 0.005 0
0.12 0.025 0
0.2 0.075 0
0.25 0.125 0
0.3 0.190 0
0.4 0.410 0
0.45 0.60 0
0.5 0.72 0
0.6 0.87 0
0.7 0.94 0
0.85 0.98 0
0.88 0.984 0 /
SOF3
-- SPE 1 Table
0 0 0
0.03 0 0
0.18 0 0
0.28 0.0001 0.0001
0.38 0.001 0.001
0.43 0.01 0.01
0.48 0.021 0.021
0.58 0.09 0.09
0.63 0.2 0.2
0.68 0.35 0.35
0.76 0.7 0.7
0.83 0.98 0.98
0.86 0.997 0.997
0.879 1 1
0.88 1 1 /
DENSITY
853.0 1014.0 0.75 /
END
)";
const auto deck = Opm::Deck{
Opm::Parser{}.parseString(input)
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
};
return Opm::EclipseState{deck};
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SGFN()
{
return makeTable(5, {
0, 0, 0, 1.000000000000000e+20, 1.0e+20,
1.00e-03, 0, 0, 0, 0,
2.00e-02, 0, 0, 0, 0,
5.00e-02, 5.000000000000000e-03, 0, 1.666666666666667e-01, 0,
1.20e-01, 2.500000000000000e-02, 0, 2.857142857142858e-01, 0,
2.00e-01, 7.500000000000000e-02, 0, 6.249999999999998e-01, 0,
2.50e-01, 1.250000000000000e-01, 0, 1.000000000000000e+00, 0,
3.00e-01, 1.900000000000000e-01, 0, 1.300000000000000e+00, 0,
4.00e-01, 4.100000000000000e-01, 0, 2.199999999999999e+00, 0,
4.50e-01, 6.000000000000000e-01, 0, 3.800000000000001e+00, 0,
5.00e-01, 7.200000000000000e-01, 0, 2.400000000000000e+00, 0,
6.00e-01, 8.700000000000000e-01, 0, 1.500000000000001e+00, 0,
7.00e-01, 9.399999999999999e-01, 0, 6.999999999999996e-01, 0,
8.50e-01, 9.800000000000000e-01, 0, 2.666666666666669e-01, 0,
8.80e-01, 9.840000000000000e-01, 0, 1.333333333333333e-01, 0,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SOFN()
{
return makeTable(5, {
0, 0, 0, 1.000000000000000e+20, 1.000000000000000e+20,
3.00e-02, 0, 0, 0, 0,
1.80e-01, 0, 0, 0, 0,
2.80e-01, 1.00e-04, 1.00e-04, 9.999999999999998e-04, 9.999999999999998e-04,
3.80e-01, 1.00e-03, 1.00e-03, 9.000000000000001e-03, 9.000000000000001e-03,
4.30e-01, 1.00e-02, 1.00e-02, 1.800000000000000e-01, 1.800000000000000e-01,
4.80e-01, 2.10e-02, 2.10e-02, 2.200000000000001e-01, 2.200000000000001e-01,
5.80e-01, 9.00e-02, 9.00e-02, 6.900000000000001e-01, 6.900000000000001e-01,
6.30e-01, 2.00e-01, 2.00e-01, 2.199999999999998e+00, 2.199999999999998e+00,
6.80e-01, 3.50e-01, 3.50e-01, 2.999999999999997e+00, 2.999999999999997e+00,
7.60e-01, 7.00e-01, 7.00e-01, 4.375000000000002e+00, 4.375000000000002e+00,
8.30e-01, 9.80e-01, 9.80e-01, 4.000000000000004e+00, 4.000000000000004e+00,
8.60e-01, 9.97e-01, 9.97e-01, 5.666666666666667e-01, 5.666666666666667e-01,
8.79e-01, 1.00e+00, 1.00e+00, 1.578947368421053e-01, 1.578947368421053e-01,
8.80e-01, 1.00e+00, 1.00e+00, 0, 0,
1.00e+20, 1.00e+20, 1.00e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.00e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.00e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.00e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.00e+20, 1.00e+20, 1.00e+20, 1.000000000000000e+20, 1.000000000000000e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SWFN()
{
return makeTable(5, {
1.20e-01, 0, 0, 1.000000000000000e+20, 1.0e+20,
1.80e-01, 0, 0, 0, 0,
2.40e-01, 0, 0, 0, 0,
3.00e-01, 0, 0, 0, 0,
3.60e-01, 0, 0, 0, 0,
4.20e-01, 1.162190082644630e-06, 0, 1.936983471074384e-05, 0,
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
4.80e-01, 1.673553719008260e-06, 0, 8.522727272727165e-06, 0,
5.40e-01, 2.277892561983470e-06, 0, 1.007231404958682e-05, 0,
6.00e-01, 2.975206611570250e-06, 0, 1.162190082644635e-05, 0,
6.60e-01, 3.765495867768600e-06, 0, 1.317148760330582e-05, 0,
7.20e-01, 4.648760330578510e-06, 0, 1.472107438016518e-05, 0,
7.80e-01, 5.625000000000000e-06, 0, 1.627066115702482e-05, 0,
8.40e-01, 6.694214876033060e-06, 0, 1.782024793388435e-05, 0,
9.10e-01, 8.059142561983471e-06, 0, 1.949896694214870e-05, 0,
1.00e+00, 1.000000000000000e-05, 0, 2.156508264462812e-05, 0,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
1.00e+20, 1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20, 1.0e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
} // ThreePhase
} // SPE1
namespace SPE9 { // Family One (SGOF and SWOF)
namespace TwoPhase {
namespace GasOil {
Opm::EclipseState satfuncTables()
{
const auto* input = R"(
RUNSPEC
OIL
GAS
METRIC
DIMENS
1 1 1 /
TABDIMS
1 1 30 20 1 20 /
-- =======================================
GRID
DXV
1 /
DYV
1 /
DZV
0.1 /
DEPTHZ
4*2000.0 /
PERMX
100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
0.3 /
-- =======================================
PROPS
SGOF
-- SPE 9 Table
0 0 1.000000000000000e+00 0
4.000000000000000e-02 0 6.000000000000000e-01 1.378951458633672e-02
1.000000000000000e-01 2.200000000000000e-02 3.300000000000000e-01 3.447378646584180e-02
2.000000000000000e-01 1.000000000000000e-01 1.000000000000000e-01 6.894757293168360e-02
3.000000000000000e-01 2.400000000000000e-01 2.000000000000000e-02 1.034213593975254e-01
4.000000000000000e-01 3.400000000000000e-01 0 1.378951458633672e-01
5.000000000000000e-01 4.200000000000000e-01 0 1.723689323292090e-01
6.000000000000000e-01 5.000000000000000e-01 0 2.068427187950508e-01
7.000000000000000e-01 8.125000000000000e-01 0 2.413165052608926e-01
8.489100000000001e-01 9.635000000000000e-01 0 2.633797285990314e-01 /
DENSITY
853.0 1014.0 0.75 /
END
)";
const auto deck = Opm::Deck{
Opm::Parser{}.parseString(input)
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
};
return Opm::EclipseState{deck};
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SGFN()
{
// Columns 1, 2, 4 (+ derivatives) of SGOF
return makeTable(5, {
0, 0, 0, 1.000000000000000e+20, 1.000000000000000e+20,
4.0000e-02, 0, 1.378951458633672e-02, 0, 3.447378646584180e-01,
1.0000e-01, 2.200e-02, 3.447378646584180e-02, 3.666666666666666e-01, 3.447378646584180e-01,
2.0000e-01, 1.000e-01, 6.894757293168360e-02, 7.800000000000001e-01, 3.447378646584180e-01,
3.0000e-01, 2.400e-01, 1.034213593975254e-01, 1.400000000000000e+00, 3.447378646584180e-01,
4.0000e-01, 3.400e-01, 1.378951458633672e-01, 1.000000000000000e+00, 3.447378646584179e-01,
5.0000e-01, 4.200e-01, 1.723689323292090e-01, 7.999999999999998e-01, 3.447378646584180e-01,
6.0000e-01, 5.000e-01, 2.068427187950508e-01, 8.000000000000004e-01, 3.447378646584180e-01,
7.0000e-01, 8.125e-01, 2.413165052608926e-01, 3.125000000000001e+00, 3.447378646584180e-01,
8.4891e-01, 9.635e-01, 2.633797285990314e-01, 1.014035323349674e+00, 1.481648199458648e-01,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
});
}
std::vector<double> expect_SOFN()
{
// Columns 1 and 3 from SGOF (using So = 1 - Sg in 2p
// system) + derivatives
return makeTable(3, {
1.510899999999999e-01, 0, 1.000000000000000e+20,
3.000000000000000e-01, 0, 0,
4.000000000000000e-01, 0, 0,
5.000000000000000e-01, 0, 0,
6.000000000000000e-01, 0, 0,
7.000000000000000e-01, 2.0e-02, 2.000000000000000e-01,
8.000000000000000e-01, 1.0e-01, 7.999999999999993e-01,
9.000000000000000e-01, 3.3e-01, 2.300000000000001e+00,
9.600000000000000e-01, 6.0e-01, 4.500000000000004e+00,
1.000000000000000e+00, 1.0e+00, 9.999999999999991e+00,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.0e+20, 1.000000000000000e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
} // GasOil
namespace OilWater {
Opm::EclipseState satfuncTables()
{
const auto* input = R"(
RUNSPEC
WATER
OIL
METRIC
DIMENS
1 1 1 /
TABDIMS
1 1 30 20 1 20 /
-- =======================================
GRID
DXV
1 /
DYV
1 /
DZV
0.1 /
DEPTHZ
4*2000.0 /
PERMX
100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
0.3 /
-- =======================================
PROPS
SWOF
-- SPE 9 Table
1.510900000000000e-01 0 1.000000000000000e+00 2.757902917267344e+01
1.512300000000000e-01 0 9.999700000000000e-01 2.476527872133143e+01
1.517400000000000e-01 0 9.999300000000000e-01 1.778295801053983e+01
1.524600000000000e-01 0 9.999100000000000e-01 1.284562231290197e+01
1.564700000000000e-01 0 9.995100000000000e-01 5.450995115978905e+00
1.658500000000000e-01 0 9.962900000000000e-01 2.758592392996661e+00
1.783500000000000e-01 0 9.915900000000000e-01 1.925705711981923e+00
2.033500000000000e-01 1.000000000000000e-05 9.788300000000000e-01 1.406530487806345e+00
2.533500000000000e-01 3.000000000000000e-05 9.437300000000000e-01 1.072134759087680e+00
3.500000000000000e-01 2.800000000000000e-04 8.302300000000000e-01 8.035839625187723e-01
3.520000000000000e-01 2.292000000000000e-03 8.042770000000000e-01 6.012228359642811e-01
3.540000000000000e-01 4.304000000000000e-03 7.783260000000000e-01 4.100312162247224e-01
3.560000000000000e-01 6.316000000000000e-03 7.523740000000000e-01 2.286990994143945e-01
3.580000000000000e-01 8.328000000000000e-03 7.264220000000000e-01 8.032392246541140e-02
3.600000000000000e-01 1.034000000000000e-02 7.004700000000000e-01 3.192272626736951e-02
3.643950000000000e-01 1.554800000000000e-02 6.422580000000000e-01 -3.440483889291011e-02
3.687900000000000e-01 2.075600000000000e-02 5.840460000000000e-01 -7.853128556918762e-02
3.700000000000000e-01 2.219000000000000e-02 5.680200000000000e-01 -8.232340208043021e-02
3.800000000000000e-01 3.589000000000000e-02 4.349800000000000e-01 -1.066618953253145e-01
4.000000000000000e-01 6.952999999999999e-02 1.714300000000000e-01 -1.105919069824205e-01
4.334500000000000e-01 8.790000000000001e-02 1.253100000000000e-01 -1.179003497131789e-01
4.613900000000000e-01 1.049100000000000e-01 9.497999999999999e-02 -1.227266798183968e-01
4.893200000000000e-01 1.232900000000000e-01 7.053000000000000e-02 -1.282424856529315e-01
5.172500000000000e-01 1.430300000000000e-01 5.113000000000000e-02 -1.330688157581493e-01
5.731200000000000e-01 1.865900000000000e-01 2.464000000000000e-02 -1.427214759685850e-01
6.010600000000000e-01 2.103800000000000e-01 1.619000000000000e-02 -1.468583303444861e-01
6.569300000000000e-01 2.619000000000000e-01 5.940000000000000e-03 -1.558215148256049e-01
7.128000000000000e-01 3.186500000000000e-01 1.590000000000000e-03 -1.640952235774069e-01
8.111100000000000e-01 4.309200000000000e-01 2.000000000000000e-05 -1.792636896223773e-01
8.814900000000000e-01 4.900000000000000e-01 0 -1.896058255621299e-01 /
DENSITY
853.0 1014.0 0.75 /
END
)";
const auto deck = Opm::Deck{
Opm::Parser{}.parseString(input)
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
};
return Opm::EclipseState{deck};
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SOFN()
{
return makeTable(3, {
1.185100000000000e-01, 0, 1.000000000000000e+20,
1.888900000000000e-01, 2.000000000000000e-05, 2.841716396703610e-04,
2.872000000000000e-01, 1.590000000000000e-03, 1.596989116061438e-02,
3.430700000000000e-01, 5.940000000000000e-03, 7.785931626991233e-02,
3.989400000000000e-01, 1.619000000000000e-02, 1.834616073026670e-01,
4.268800000000000e-01, 2.464000000000000e-02, 3.024337866857543e-01,
4.827500000000000e-01, 5.113000000000000e-02, 4.741363880436731e-01,
5.106800000000000e-01, 7.053000000000000e-02, 6.945936269244535e-01,
5.386100000000000e-01, 9.497999999999999e-02, 8.754027926960254e-01,
5.665500000000000e-01, 1.253100000000000e-01, 1.085540443808162e+00,
6.000000000000000e-01, 1.714300000000000e-01, 1.378774289985053e+00,
6.200000000000000e-01, 4.349800000000000e-01, 1.317749999999999e+01,
6.300000000000000e-01, 5.680200000000000e-01, 1.330399999999999e+01,
6.312100000000000e-01, 5.840460000000000e-01, 1.324462809917306e+01,
6.356050000000000e-01, 6.422580000000000e-01, 1.324505119453948e+01,
6.400000000000000e-01, 7.004700000000000e-01, 1.324505119453914e+01,
6.420000000000000e-01, 7.264220000000000e-01, 1.297599999999998e+01,
6.440000000000000e-01, 7.523740000000000e-01, 1.297599999999998e+01,
6.460000000000000e-01, 7.783260000000000e-01, 1.297599999999998e+01,
6.480000000000000e-01, 8.042770000000000e-01, 1.297550000000002e+01,
6.500000000000000e-01, 8.302300000000000e-01, 1.297649999999999e+01,
7.466500000000000e-01, 9.437300000000000e-01, 1.174340403517847e+00,
7.966500000000000e-01, 9.788300000000000e-01, 7.020000000000013e-01,
8.216500000000000e-01, 9.915900000000000e-01, 5.103999999999993e-01,
8.341499999999999e-01, 9.962900000000000e-01, 3.760000000000043e-01,
8.435300000000000e-01, 9.995100000000000e-01, 3.432835820895503e-01,
8.475400000000000e-01, 9.999100000000000e-01, 9.975062344138656e-02,
8.482600000000000e-01, 9.999300000000000e-01, 2.777777777780348e-02,
8.487700000000000e-01, 9.999700000000000e-01, 7.843137254909643e-02,
8.489100000000001e-01, 1.000000000000000e+00, 2.142857142854877e-01,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SWFN()
{
// Columns 1, 2, 4 (+ derivatives) of SWOF
return makeTable(5, {
1.51090e-01, 0, 2.757902917267344e+01, 1.000000000000000e+20, 1.000000000000000e+20,
1.51230e-01, 0, 2.476527872133143e+01, 0, -2.009821750958577e+04,
1.51740e-01, 0, 1.778295801053983e+01, 0, -1.369082492312075e+04,
1.52460e-01, 0, 1.284562231290197e+01, 0, -6.857410691163744e+03,
1.56470e-01, 0, 5.450995115978905e+00, 0, -1.844046682524494e+03,
1.65850e-01, 0, 2.758592392996661e+00, 0, -2.870365376313702e+02,
1.78350e-01, 0, 1.925705711981923e+00, 0, -6.663093448117903e+01,
2.03350e-01, 1.000000000000000e-05, 1.406530487806345e+00, 4.000000000000000e-04, -2.076700896702310e+01,
2.53350e-01, 3.000000000000000e-05, 1.072134759087680e+00, 4.000000000000000e-04, -6.687914574373308e+00,
3.50000e-01, 2.800000000000000e-04, 8.035839625187723e-01, 2.586652871184700e-03, -2.778590756015570e+00,
3.52000e-01, 2.292000000000000e-03, 6.012228359642811e-01, 1.006000000000000e+00, -1.011805632772457e+02,
3.54000e-01, 4.304000000000000e-03, 4.100312162247224e-01, 1.006000000000000e+00, -9.559580986977932e+01,
3.56000e-01, 6.316000000000000e-03, 2.286990994143945e-01, 1.006000000000000e+00, -9.066605840516394e+01,
3.58000e-01, 8.328000000000000e-03, 8.032392246541140e-02, 1.006000000000000e+00, -7.418758847449155e+01,
3.60000e-01, 1.034000000000000e-02, 3.192272626736951e-02, 1.006000000000000e+00, -2.420059809902094e+01,
3.64395e-01, 1.554800000000000e-02, -3.440483889291011e-02, 1.184982935153600e+00, -1.509159616843634e+01,
3.68790e-01, 2.075600000000000e-02, -7.853128556918762e-02, 1.184982935153600e+00, -1.004014713908486e+01,
3.70000e-01, 2.219000000000000e-02, -8.232340208043021e-02, 1.185123966942200e+00, -3.133980587803838e+00,
3.80000e-01, 3.589000000000000e-02, -1.066618953253145e-01, 1.370000000000000e+00, -2.433849324488431e+00,
4.00000e-01, 6.952999999999999e-02, -1.105919069824205e-01, 1.682000000000000e+00, -1.965005828552983e-01,
4.33450e-01, 8.790000000000001e-02, -1.179003497131789e-01, 5.491778774290000e-01, -2.184885719210279e-01,
4.61390e-01, 1.049100000000000e-01, -1.227266798183968e-01, 6.088045812455301e-01, -1.727390875167428e-01,
4.89320e-01, 1.232900000000000e-01, -1.282424856529315e-01, 6.580737558181200e-01, -1.974867824752831e-01,
5.17250e-01, 1.430300000000000e-01, -1.330688157581493e-01, 7.067669172932300e-01, -1.728009346658736e-01,
5.73120e-01, 1.865900000000000e-01, -1.427214759685850e-01, 7.796670843028500e-01, -1.727700055563935e-01,
6.01060e-01, 2.103800000000000e-01, -1.468583303444861e-01, 8.514674302075900e-01, -1.480620750143510e-01,
6.56930e-01, 2.619000000000000e-01, -1.558215148256049e-01, 9.221406837300899e-01, -1.604292908737955e-01,
7.12800e-01, 3.186500000000000e-01, -1.640952235774069e-01, 1.015750850187900e+00, -1.480885761911974e-01,
8.11110e-01, 4.309200000000000e-01, -1.792636896223773e-01, 1.141999796561900e+00, -1.542921986061490e-01,
8.81490e-01, 4.900000000000000e-01, -1.896058255621299e-01, 8.394430235862500e-01, -1.469470863846619e-01,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
} // OilWater
} // TwoPhase
namespace ThreePhase {
Opm::EclipseState satfuncTables()
{
const auto* input = R"(
RUNSPEC
WATER
OIL
GAS
METRIC
DIMENS
1 1 1 /
TABDIMS
1 1 30 20 1 20 /
-- =======================================
GRID
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
DXV
1 /
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
DYV
1 /
DZV
0.1 /
DEPTHZ
4*2000.0 /
PERMX
100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
0.3 /
-- =======================================
PROPS
SWOF
-- SPE 9 Table
1.510900000000000e-01 0 1.000000000000000e+00 2.757902917267344e+01
1.512300000000000e-01 0 9.999700000000000e-01 2.476527872133143e+01
1.517400000000000e-01 0 9.999300000000000e-01 1.778295801053983e+01
1.524600000000000e-01 0 9.999100000000000e-01 1.284562231290197e+01
1.564700000000000e-01 0 9.995100000000000e-01 5.450995115978905e+00
1.658500000000000e-01 0 9.962900000000000e-01 2.758592392996661e+00
1.783500000000000e-01 0 9.915900000000000e-01 1.925705711981923e+00
2.033500000000000e-01 1.000000000000000e-05 9.788300000000000e-01 1.406530487806345e+00
2.533500000000000e-01 3.000000000000000e-05 9.437300000000000e-01 1.072134759087680e+00
3.500000000000000e-01 2.800000000000000e-04 8.302300000000000e-01 8.035839625187723e-01
3.520000000000000e-01 2.292000000000000e-03 8.042770000000000e-01 6.012228359642811e-01
3.540000000000000e-01 4.304000000000000e-03 7.783260000000000e-01 4.100312162247224e-01
3.560000000000000e-01 6.316000000000000e-03 7.523740000000000e-01 2.286990994143945e-01
3.580000000000000e-01 8.328000000000000e-03 7.264220000000000e-01 8.032392246541140e-02
3.600000000000000e-01 1.034000000000000e-02 7.004700000000000e-01 3.192272626736951e-02
3.643950000000000e-01 1.554800000000000e-02 6.422580000000000e-01 -3.440483889291011e-02
3.687900000000000e-01 2.075600000000000e-02 5.840460000000000e-01 -7.853128556918762e-02
3.700000000000000e-01 2.219000000000000e-02 5.680200000000000e-01 -8.232340208043021e-02
3.800000000000000e-01 3.589000000000000e-02 4.349800000000000e-01 -1.066618953253145e-01
4.000000000000000e-01 6.952999999999999e-02 1.714300000000000e-01 -1.105919069824205e-01
4.334500000000000e-01 8.790000000000001e-02 1.253100000000000e-01 -1.179003497131789e-01
4.613900000000000e-01 1.049100000000000e-01 9.497999999999999e-02 -1.227266798183968e-01
4.893200000000000e-01 1.232900000000000e-01 7.053000000000000e-02 -1.282424856529315e-01
5.172500000000000e-01 1.430300000000000e-01 5.113000000000000e-02 -1.330688157581493e-01
5.731200000000000e-01 1.865900000000000e-01 2.464000000000000e-02 -1.427214759685850e-01
6.010600000000000e-01 2.103800000000000e-01 1.619000000000000e-02 -1.468583303444861e-01
6.569300000000000e-01 2.619000000000000e-01 5.940000000000000e-03 -1.558215148256049e-01
7.128000000000000e-01 3.186500000000000e-01 1.590000000000000e-03 -1.640952235774069e-01
8.111100000000000e-01 4.309200000000000e-01 2.000000000000000e-05 -1.792636896223773e-01
8.814900000000000e-01 4.900000000000000e-01 0 -1.896058255621299e-01 /
SGOF
-- SPE 9 Table
0 0 1.000000000000000e+00 0
4.000000000000000e-02 0 6.000000000000000e-01 1.378951458633672e-02
1.000000000000000e-01 2.200000000000000e-02 3.300000000000000e-01 3.447378646584180e-02
2.000000000000000e-01 1.000000000000000e-01 1.000000000000000e-01 6.894757293168360e-02
3.000000000000000e-01 2.400000000000000e-01 2.000000000000000e-02 1.034213593975254e-01
4.000000000000000e-01 3.400000000000000e-01 0 1.378951458633672e-01
5.000000000000000e-01 4.200000000000000e-01 0 1.723689323292090e-01
6.000000000000000e-01 5.000000000000000e-01 0 2.068427187950508e-01
7.000000000000000e-01 8.125000000000000e-01 0 2.413165052608926e-01
8.489100000000001e-01 9.635000000000000e-01 0 2.633797285990314e-01 /
DENSITY
853.0 1014.0 0.75 /
END
)";
const auto deck = Opm::Deck{
Opm::Parser{}.parseString(input)
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
};
return Opm::EclipseState{deck};
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SGFN()
{
// Columns 1, 2, 4 (+ derivatives) of SGOF
return makeTable(5, {
0, 0, 0, 1.000000000000000e+20, 1.000000000000000e+20,
4.0000e-02, 0, 1.378951458633672e-02, 0, 3.447378646584180e-01,
1.0000e-01, 2.200e-02, 3.447378646584180e-02, 3.666666666666666e-01, 3.447378646584180e-01,
2.0000e-01, 1.000e-01, 6.894757293168360e-02, 7.800000000000001e-01, 3.447378646584180e-01,
3.0000e-01, 2.400e-01, 1.034213593975254e-01, 1.400000000000000e+00, 3.447378646584180e-01,
4.0000e-01, 3.400e-01, 1.378951458633672e-01, 1.000000000000000e+00, 3.447378646584179e-01,
5.0000e-01, 4.200e-01, 1.723689323292090e-01, 7.999999999999998e-01, 3.447378646584180e-01,
6.0000e-01, 5.000e-01, 2.068427187950508e-01, 8.000000000000004e-01, 3.447378646584180e-01,
7.0000e-01, 8.125e-01, 2.413165052608926e-01, 3.125000000000001e+00, 3.447378646584180e-01,
8.4891e-01, 9.635e-01, 2.633797285990314e-01, 1.014035323349674e+00, 1.481648199458648e-01,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0000e+20, 1.000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SOFN()
{
// Column 1 from SGOF merged with column 1 from SWOF, Column 3 from
// SWOF (+ piecewise linear interp), Column 3 from SGOF (+piecewise
// linear interp) + derivatives of those.
return makeTable(5, {
0, 0, 0, 1.000000000000000e+20, 1.000000000000000e+20,
1.185100000000000e-01, 0, 0, 0, 0,
1.489100000000001e-01, 8.638817845978999e-06, 0, 2.841716396703609e-04, 0,
1.888900000000000e-01, 2.000000000000000e-05, 0, 2.841716396703610e-04, 0,
2.489100000000001e-01, 9.785128674600764e-04, 0, 1.596989116061438e-02, 0,
2.872000000000000e-01, 1.590000000000000e-03, 0, 1.596989116061438e-02, 0,
3.430700000000000e-01, 5.940000000000000e-03, 0, 7.785931626991233e-02, 0,
3.489100000000001e-01, 7.011415786647587e-03, 0, 1.834616073026669e-01, 0,
3.989400000000000e-01, 1.619000000000000e-02, 0, 1.834616073026670e-01, 0,
4.268800000000000e-01, 2.464000000000000e-02, 0, 3.024337866857543e-01, 0,
4.489100000000000e-01, 3.508522462860211e-02, 0, 4.741363880436730e-01, 0,
4.827500000000000e-01, 5.113000000000000e-02, 6.767999999999998e-03, 4.741363880436731e-01, 2.000000000000000e-01,
5.106800000000000e-01, 7.053000000000000e-02, 1.235400000000000e-02, 6.945936269244535e-01, 2.000000000000000e-01,
5.386100000000000e-01, 9.497999999999999e-02, 1.794000000000000e-02, 8.754027926960254e-01, 2.000000000000001e-01,
5.489100000000000e-01, 1.061610665712240e-01, 2.000000000000000e-02, 1.085540443808162e+00, 2.000000000000001e-01,
5.665500000000000e-01, 1.253100000000000e-01, 3.411199999999998e-02, 1.085540443808162e+00, 7.999999999999990e-01,
6.000000000000000e-01, 1.714300000000000e-01, 6.087199999999994e-02, 1.378774289985053e+00, 7.999999999999994e-01,
6.200000000000000e-01, 4.349800000000000e-01, 7.687199999999994e-02, 1.317749999999999e+01, 7.999999999999993e-01,
6.300000000000000e-01, 5.680200000000000e-01, 8.487199999999995e-02, 1.330399999999999e+01, 8.000000000000000e-01,
6.312100000000000e-01, 5.840460000000000e-01, 8.583999999999999e-02, 1.324462809917306e+01, 8.000000000000023e-01,
6.356050000000000e-01, 6.422580000000000e-01, 8.935599999999992e-02, 1.324505119453948e+01, 7.999999999999987e-01,
6.400000000000000e-01, 7.004700000000000e-01, 9.287199999999994e-02, 1.324505119453914e+01, 7.999999999999975e-01,
6.420000000000000e-01, 7.264220000000000e-01, 9.447199999999994e-02, 1.297599999999998e+01, 8.000000000000014e-01,
6.440000000000000e-01, 7.523740000000000e-01, 9.607199999999995e-02, 1.297599999999998e+01, 8.000000000000014e-01,
6.460000000000000e-01, 7.783260000000000e-01, 9.767199999999995e-02, 1.297599999999998e+01, 8.000000000000014e-01,
6.480000000000000e-01, 8.042770000000000e-01, 9.927199999999994e-02, 1.297550000000002e+01, 7.999999999999945e-01,
6.489100000000001e-01, 8.160856150000010e-01, 1.000000000000000e-01, 1.297649999999996e+01, 8.000000000000000e-01,
6.500000000000000e-01, 8.302300000000000e-01, 1.025069999999998e-01, 1.297650000000002e+01, 2.300000000000002e+00,
7.466500000000000e-01, 9.437300000000000e-01, 3.248019999999999e-01, 1.174340403517847e+00, 2.300000000000000e+00,
7.489100000000001e-01, 9.453165200000000e-01, 3.300000000000000e-01, 7.020000000000034e-01, 2.300000000000000e+00,
7.966500000000000e-01, 9.788300000000000e-01, 5.448299999999997e-01, 7.020000000000013e-01, 4.500000000000004e+00,
8.089100000000000e-01, 9.850875040000000e-01, 6.000000000000000e-01, 5.104000000000000e-01, 4.500000000000004e+00,
8.216500000000000e-01, 9.915900000000000e-01, 7.273999999999996e-01, 5.103999999999986e-01, 9.999999999999991e+00,
8.341499999999999e-01, 9.962900000000000e-01, 8.523999999999990e-01, 3.760000000000043e-01, 9.999999999999991e+00,
8.435300000000000e-01, 9.995100000000000e-01, 9.461999999999995e-01, 3.432835820895503e-01, 9.999999999999988e+00,
8.475400000000000e-01, 9.999100000000000e-01, 9.862999999999991e-01, 9.975062344138656e-02, 1.000000000000000e+01,
8.482600000000000e-01, 9.999300000000000e-01, 9.934999999999996e-01, 2.777777777780348e-02, 1.000000000000000e+01,
8.487700000000000e-01, 9.999700000000000e-01, 9.985999999999997e-01, 7.843137254909643e-02, 1.000000000000000e+01,
8.489100000000001e-01, 1.000000000000000e+00, 1.000000000000000e+00, 2.142857142854877e-01, 1.000000000000000e+01,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
std::vector<double> expect_SWFN()
{
// Columns 1, 2, 4 (+ derivatives) of SWOF
return makeTable(5, {
1.51090e-01, 0, 2.757902917267344e+01, 1.000000000000000e+20, 1.000000000000000e+20,
1.51230e-01, 0, 2.476527872133143e+01, 0, -2.009821750958577e+04,
1.51740e-01, 0, 1.778295801053983e+01, 0, -1.369082492312075e+04,
1.52460e-01, 0, 1.284562231290197e+01, 0, -6.857410691163744e+03,
1.56470e-01, 0, 5.450995115978905e+00, 0, -1.844046682524494e+03,
1.65850e-01, 0, 2.758592392996661e+00, 0, -2.870365376313702e+02,
1.78350e-01, 0, 1.925705711981923e+00, 0, -6.663093448117903e+01,
2.03350e-01, 1.000000000000000e-05, 1.406530487806345e+00, 4.000000000000000e-04, -2.076700896702310e+01,
2.53350e-01, 3.000000000000000e-05, 1.072134759087680e+00, 4.000000000000000e-04, -6.687914574373308e+00,
3.50000e-01, 2.800000000000000e-04, 8.035839625187723e-01, 2.586652871184700e-03, -2.778590756015570e+00,
3.52000e-01, 2.292000000000000e-03, 6.012228359642811e-01, 1.006000000000000e+00, -1.011805632772457e+02,
3.54000e-01, 4.304000000000000e-03, 4.100312162247224e-01, 1.006000000000000e+00, -9.559580986977932e+01,
3.56000e-01, 6.316000000000000e-03, 2.286990994143945e-01, 1.006000000000000e+00, -9.066605840516394e+01,
3.58000e-01, 8.328000000000000e-03, 8.032392246541140e-02, 1.006000000000000e+00, -7.418758847449155e+01,
3.60000e-01, 1.034000000000000e-02, 3.192272626736951e-02, 1.006000000000000e+00, -2.420059809902094e+01,
3.64395e-01, 1.554800000000000e-02, -3.440483889291011e-02, 1.184982935153600e+00, -1.509159616843634e+01,
3.68790e-01, 2.075600000000000e-02, -7.853128556918762e-02, 1.184982935153600e+00, -1.004014713908486e+01,
3.70000e-01, 2.219000000000000e-02, -8.232340208043021e-02, 1.185123966942200e+00, -3.133980587803838e+00,
3.80000e-01, 3.589000000000000e-02, -1.066618953253145e-01, 1.370000000000000e+00, -2.433849324488431e+00,
4.00000e-01, 6.952999999999999e-02, -1.105919069824205e-01, 1.682000000000000e+00, -1.965005828552983e-01,
4.33450e-01, 8.790000000000001e-02, -1.179003497131789e-01, 5.491778774290000e-01, -2.184885719210279e-01,
4.61390e-01, 1.049100000000000e-01, -1.227266798183968e-01, 6.088045812455301e-01, -1.727390875167428e-01,
4.89320e-01, 1.232900000000000e-01, -1.282424856529315e-01, 6.580737558181200e-01, -1.974867824752831e-01,
5.17250e-01, 1.430300000000000e-01, -1.330688157581493e-01, 7.067669172932300e-01, -1.728009346658736e-01,
5.73120e-01, 1.865900000000000e-01, -1.427214759685850e-01, 7.796670843028500e-01, -1.727700055563935e-01,
6.01060e-01, 2.103800000000000e-01, -1.468583303444861e-01, 8.514674302075900e-01, -1.480620750143510e-01,
6.56930e-01, 2.619000000000000e-01, -1.558215148256049e-01, 9.221406837300899e-01, -1.604292908737955e-01,
7.12800e-01, 3.186500000000000e-01, -1.640952235774069e-01, 1.015750850187900e+00, -1.480885761911974e-01,
8.11110e-01, 4.309200000000000e-01, -1.792636896223773e-01, 1.141999796561900e+00, -1.542921986061490e-01,
8.81490e-01, 4.900000000000000e-01, -1.896058255621299e-01, 8.394430235862500e-01, -1.469470863846619e-01,
});
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
}
} // ThreePhase
} // SPE9
}
// #####################################################################
BOOST_AUTO_TEST_SUITE (Two_Phase)
BOOST_AUTO_TEST_CASE (Oil_Water_Family_One)
{
const auto es = SPE9::TwoPhase::OilWater::satfuncTables();
auto tables = Opm::Tables{ es.getUnits() };
tables.addSatFunc(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
// SOFN
{
const auto ibsofn = tabdims[ Ix::SofnTableStart ] - 1;
const auto nssofn = tabdims[ Ix::SofnNumSatNodes ];
const auto ntsofn = tabdims[ Ix::SofnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 3;
const auto sofn = std::vector<double> {
&tab[ ibsofn ] + 0,
&tab[ ibsofn ] + ntsofn*nssofn*ncol
};
BOOST_CHECK_EQUAL(nssofn, 30);
BOOST_CHECK_EQUAL(ntsofn, 1);
check_is_close(sofn, SPE9::TwoPhase::OilWater::expect_SOFN());
}
// SWFN
{
const auto ibswfn = tabdims[ Ix::SwfnTableStart ] - 1;
const auto nsswfn = tabdims[ Ix::SwfnNumSatNodes ];
const auto ntswfn = tabdims[ Ix::SwfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto swfn = std::vector<double> {
&tab[ ibswfn ] + 0,
&tab[ ibswfn ] + ntswfn*nsswfn*ncol
};
BOOST_CHECK_EQUAL(nsswfn, 30);
BOOST_CHECK_EQUAL(ntswfn, 1);
check_is_close(swfn, SPE9::TwoPhase::OilWater::expect_SWFN());
}
}
BOOST_AUTO_TEST_CASE (Oil_Water_Family_Two)
{
const auto es = SPE1::TwoPhase::OilWater::satfuncTables();
auto tables = Opm::Tables{ es.getUnits() };
tables.addSatFunc(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
// SOFN
{
const auto ibsofn = tabdims[ Ix::SofnTableStart ] - 1;
const auto nssofn = tabdims[ Ix::SofnNumSatNodes ];
const auto ntsofn = tabdims[ Ix::SofnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 3;
const auto sofn = std::vector<double> {
&tab[ ibsofn ] + 0,
&tab[ ibsofn ] + ntsofn*nssofn*ncol
};
BOOST_CHECK_EQUAL(nssofn, 20);
BOOST_CHECK_EQUAL(ntsofn, 1);
check_is_close(sofn, SPE1::TwoPhase::OilWater::expect_SOFN());
}
// SWFN
{
const auto ibswfn = tabdims[ Ix::SwfnTableStart ] - 1;
const auto nsswfn = tabdims[ Ix::SwfnNumSatNodes ];
const auto ntswfn = tabdims[ Ix::SwfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto swfn = std::vector<double> {
&tab[ ibswfn ] + 0,
&tab[ ibswfn ] + ntswfn*nsswfn*ncol
};
BOOST_CHECK_EQUAL(nsswfn, 20);
BOOST_CHECK_EQUAL(ntswfn, 1);
check_is_close(swfn, SPE1::TwoPhase::OilWater::expect_SWFN());
}
}
BOOST_AUTO_TEST_CASE (Gas_Oil_Familiy_One)
{
const auto es = SPE9::TwoPhase::GasOil::satfuncTables();
auto tables = Opm::Tables{ es.getUnits() };
tables.addSatFunc(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
// SGFN
{
const auto ibsgfn = tabdims[ Ix::SgfnTableStart ] - 1;
const auto nssgfn = tabdims[ Ix::SgfnNumSatNodes ];
const auto ntsgfn = tabdims[ Ix::SgfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto sgfn = std::vector<double> {
&tab[ ibsgfn ] + 0,
&tab[ ibsgfn ] + ntsgfn*nssgfn*ncol
};
BOOST_CHECK_EQUAL(nssgfn, 30);
BOOST_CHECK_EQUAL(ntsgfn, 1);
check_is_close(sgfn, SPE9::TwoPhase::GasOil::expect_SGFN());
}
// SOFN
{
const auto ibsofn = tabdims[ Ix::SofnTableStart ] - 1;
const auto nssofn = tabdims[ Ix::SofnNumSatNodes ];
const auto ntsofn = tabdims[ Ix::SofnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 3;
const auto sofn = std::vector<double> {
&tab[ ibsofn ] + 0,
&tab[ ibsofn ] + ntsofn*nssofn*ncol
};
BOOST_CHECK_EQUAL(nssofn, 30);
BOOST_CHECK_EQUAL(ntsofn, 1);
check_is_close(sofn, SPE9::TwoPhase::GasOil::expect_SOFN());
}
}
BOOST_AUTO_TEST_CASE (Gas_Oil_Familiy_Two)
{
const auto es = SPE1::TwoPhase::GasOil::satfuncTables();
auto tables = Opm::Tables{ es.getUnits() };
tables.addSatFunc(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
// SGFN
{
const auto ibsgfn = tabdims[ Ix::SgfnTableStart ] - 1;
const auto nssgfn = tabdims[ Ix::SgfnNumSatNodes ];
const auto ntsgfn = tabdims[ Ix::SgfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto sgfn = std::vector<double> {
&tab[ ibsgfn ] + 0,
&tab[ ibsgfn ] + ntsgfn*nssgfn*ncol
};
BOOST_CHECK_EQUAL(nssgfn, 20);
BOOST_CHECK_EQUAL(ntsgfn, 1);
check_is_close(sgfn, SPE1::TwoPhase::GasOil::expect_SGFN());
}
// SOFN
{
const auto ibsofn = tabdims[ Ix::SofnTableStart ] - 1;
const auto nssofn = tabdims[ Ix::SofnNumSatNodes ];
const auto ntsofn = tabdims[ Ix::SofnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 3;
const auto sofn = std::vector<double> {
&tab[ ibsofn ] + 0,
&tab[ ibsofn ] + ntsofn*nssofn*ncol
};
BOOST_CHECK_EQUAL(nssofn, 20);
BOOST_CHECK_EQUAL(ntsofn, 1);
check_is_close(sofn, SPE1::TwoPhase::GasOil::expect_SOFN());
}
}
BOOST_AUTO_TEST_SUITE_END ()
// #####################################################################
BOOST_AUTO_TEST_SUITE (Three_Phase)
BOOST_AUTO_TEST_CASE (Serialize_Family_One)
{
const auto es = SPE9::ThreePhase::satfuncTables();
auto tables = Opm::Tables{ es.getUnits() };
tables.addSatFunc(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
// SGFN
{
const auto ibsgfn = tabdims[ Ix::SgfnTableStart ] - 1;
const auto nssgfn = tabdims[ Ix::SgfnNumSatNodes ];
const auto ntsgfn = tabdims[ Ix::SgfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto sgfn = std::vector<double> {
&tab[ ibsgfn ] + 0,
&tab[ ibsgfn ] + ntsgfn*nssgfn*ncol
};
BOOST_CHECK_EQUAL(nssgfn, 30);
BOOST_CHECK_EQUAL(ntsgfn, 1);
check_is_close(sgfn, SPE9::ThreePhase::expect_SGFN());
}
// SOFN
{
const auto ibsofn = tabdims[ Ix::SofnTableStart ] - 1;
const auto nssofn = tabdims[ Ix::SofnNumSatNodes ];
const auto ntsofn = tabdims[ Ix::SofnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto sofn = std::vector<double> {
&tab[ ibsofn ] + 0,
&tab[ ibsofn ] + ntsofn*nssofn*ncol
};
BOOST_CHECK_EQUAL(nssofn, 2 * 30);
BOOST_CHECK_EQUAL(ntsofn, 1);
check_is_close(sofn, SPE9::ThreePhase::expect_SOFN());
}
// SWFN
{
const auto ibswfn = tabdims[ Ix::SwfnTableStart ] - 1;
const auto nsswfn = tabdims[ Ix::SwfnNumSatNodes ];
const auto ntswfn = tabdims[ Ix::SwfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto swfn = std::vector<double> {
&tab[ ibswfn ] + 0,
&tab[ ibswfn ] + ntswfn*nsswfn*ncol
};
BOOST_CHECK_EQUAL(nsswfn, 30);
BOOST_CHECK_EQUAL(ntswfn, 1);
check_is_close(swfn, SPE9::ThreePhase::expect_SWFN());
}
}
BOOST_AUTO_TEST_CASE (Serialize_Family_Two)
{
const auto es = SPE1::ThreePhase::satfuncTables();
auto tables = Opm::Tables{ es.getUnits() };
tables.addSatFunc(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
// SGFN
{
const auto ibsgfn = tabdims[ Ix::SgfnTableStart ] - 1;
const auto nssgfn = tabdims[ Ix::SgfnNumSatNodes ];
const auto ntsgfn = tabdims[ Ix::SgfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto sgfn = std::vector<double> {
&tab[ ibsgfn ] + 0,
&tab[ ibsgfn ] + ntsgfn*nssgfn*ncol
};
BOOST_CHECK_EQUAL(nssgfn, 20);
BOOST_CHECK_EQUAL(ntsgfn, 1);
check_is_close(sgfn, SPE1::ThreePhase::expect_SGFN());
}
// SOFN
{
const auto ibsofn = tabdims[ Ix::SofnTableStart ] - 1;
const auto nssofn = tabdims[ Ix::SofnNumSatNodes ];
const auto ntsofn = tabdims[ Ix::SofnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto sofn = std::vector<double> {
&tab[ ibsofn ] + 0,
&tab[ ibsofn ] + ntsofn*nssofn*ncol
};
BOOST_CHECK_EQUAL(nssofn, 20);
BOOST_CHECK_EQUAL(ntsofn, 1);
check_is_close(sofn, SPE1::ThreePhase::expect_SOFN());
}
// SWFN
{
const auto ibswfn = tabdims[ Ix::SwfnTableStart ] - 1;
const auto nsswfn = tabdims[ Ix::SwfnNumSatNodes ];
const auto ntswfn = tabdims[ Ix::SwfnNumTables ];
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
const auto ncol = 5;
const auto swfn = std::vector<double> {
&tab[ ibswfn ] + 0,
&tab[ ibswfn ] + ntswfn*nsswfn*ncol
};
BOOST_CHECK_EQUAL(nsswfn, 20);
BOOST_CHECK_EQUAL(ntswfn, 1);
check_is_close(swfn, SPE1::ThreePhase::expect_SWFN());
}
}
BOOST_AUTO_TEST_SUITE_END ()
// #####################################################################
BOOST_AUTO_TEST_SUITE (PVTTables)
namespace {
Opm::EclipseState parse(const std::string& rspec,
const std::string& props)
{
return Opm::EclipseState{
Opm::Parser{}.parseString(rspec + R"(GRID
INIT
DXV
10*200 /
DYV
10*200 /
DZV
10*25 /
TOPS
100*2500 /
PORO
1000*0.3 /
PERMX
1000*100 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PROPS
)" + props + R"(
END
)") };
}
}
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
BOOST_AUTO_TEST_SUITE (Gas)
BOOST_AUTO_TEST_CASE (PVDG_Regular)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVDG Output
GAS
FIELD
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 16 1* 1*
/
)" };
const auto props = std::string { R"(
PVDG
14.7 166.666 0.0080
264.7 12.093 0.0096
514.7 6.274 0.0112
1014.7 3.197 0.0140
2014.7 1.614 0.0189
2514.7 1.294 0.0208
3014.7 1.080 0.0228
4014.7 0.811 0.0268
5014.7 0.649 0.0309
9014.7 0.386 0.0470 /
400.0 5.900 0.0130
800.0 2.950 0.0135
1200.0 1.960 0.0140
1600.0 1.470 0.0145
2000.0 1.180 0.0150
2400.0 0.980 0.0155
2800.0 0.840 0.0160
3200.0 0.740 0.0165
3600.0 0.650 0.0170
4000.0 0.590 0.0175
4400.0 0.540 0.0180
4800.0 0.490 0.0185
5200.0 0.450 0.0190
5600.0 0.420 0.0195 /
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvtg = tabdims[ Ix::PvtgMainStart ] - 1;
const auto nppvtg = tabdims[ Ix::NumPvtgPressNodes ];
const auto ntpvtg = tabdims[ Ix::NumPvtgTables ];
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
const auto ncol = 5;
// Pg table defaulted
BOOST_CHECK_EQUAL(tabdims[Ix::PvtgPressStart], 1);
BOOST_CHECK_EQUAL(tabdims[Ix::NumPvtgCompNodes], 1);
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
BOOST_CHECK_EQUAL(nppvtg, 16);
BOOST_CHECK_EQUAL(ntpvtg, 2);
const auto pvdg = std::vector<double> {
&tab[ ibpvtg ] + 0,
&tab[ ibpvtg ] + ntpvtg*nppvtg*ncol
};
const auto expect_pvdg = makeTable(5, {
// Pg 1/Bg 1/(Bg*mu_g) d(1/Bg)/dPg d(1/(Bg*mu_g))/dPg
//
// Table 1 (10 pressure nodes)
1.470000000000000e+01, 6.000024000096002e-03, 7.500030000120003e-01, 2.000000000000000e+20, 2.000000000000000e+20,
2.647000000000000e+02, 8.269246671628215e-02, 8.613798616279391e+00, 3.067697708647446e-04, 3.145518246506956e-02,
5.147000000000000e+02, 1.593879502709595e-01, 1.423106698847853e+01, 3.067819342187094e-04, 2.246907348879655e-02,
1.014700000000000e+03, 3.127932436659369e-01, 2.234237454756692e+01, 3.068105867899547e-04, 1.622261511817678e-02,
2.014700000000000e+03, 6.195786864931847e-01, 3.278194108429548e+01, 3.067854428272479e-04, 1.043956653672856e-02,
2.514700000000000e+03, 7.727975270479135e-01, 3.715372726191892e+01, 3.064376811094576e-04, 8.743572355246868e-03,
3.014700000000000e+03, 9.259259259259259e-01, 4.061078622482131e+01, 3.062567977560249e-04, 6.914117925804789e-03,
4.014699999999999e+03, 1.233045622688040e+00, 4.600916502567312e+01, 3.071196967621139e-04, 5.398378800851812e-03,
5.014700000000000e+03, 1.540832049306626e+00, 4.986511486429210e+01, 3.077864266185862e-04, 3.855949838618981e-03,
9.014699999999999e+03, 2.590673575129534e+00, 5.512071436445817e+01, 2.624603814557271e-04, 1.313899875041518e-03,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// ===========================================================================================================================
// Table 2 (14 pressure nodes)
4.000000000000000e+02, 1.694915254237289e-01, 1.303780964797914e+01, 2.000000000000000e+20, 2.000000000000000e+20,
8.000000000000000e+02, 3.389830508474577e-01, 2.510985561833020e+01, 4.237288135593221e-04, 3.018011492587764e-02,
1.200000000000000e+03, 5.102040816326532e-01, 3.644314868804666e+01, 4.280525769629887e-04, 2.833323267429114e-02,
1.600000000000000e+03, 6.802721088435375e-01, 4.691531785127844e+01, 4.251700680272108e-04, 2.618042290807946e-02,
2.000000000000000e+03, 8.474576271186441e-01, 5.649717514124294e+01, 4.179637956877669e-04, 2.395464322491127e-02,
2.400000000000000e+03, 1.020408163265306e+00, 6.583278472679396e+01, 4.323763403666553e-04, 2.333902396387753e-02,
2.800000000000000e+03, 1.190476190476191e+00, 7.440476190476191e+01, 4.251700680272113e-04, 2.142994294491990e-02,
3.200000000000000e+03, 1.351351351351352e+00, 8.190008190008190e+01, 4.021879021879017e-04, 1.873829998829995e-02,
3.600000000000000e+03, 1.538461538461539e+00, 9.049773755656106e+01, 4.677754677754675e-04, 2.149413914119791e-02,
4.000000000000000e+03, 1.694915254237288e+00, 9.685230024213075e+01, 3.911342894393748e-04, 1.588640671392424e-02,
4.400000000000000e+03, 1.851851851851852e+00, 1.028806584362140e+02, 3.923414940364085e-04, 1.507089548520804e-02,
4.800000000000000e+03, 2.040816326530613e+00, 1.103143960286818e+02, 4.724111866969022e-04, 1.858434398116948e-02,
5.199999999999999e+03, 2.222222222222222e+00, 1.169590643274854e+02, 4.535147392290250e-04, 1.661167074700910e-02,
5.599999999999999e+03, 2.380952380952381e+00, 1.221001221001221e+02, 3.968253968253976e-04, 1.285264443159182e-02,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
});
check_is_close(pvdg, expect_pvdg);
}
BOOST_AUTO_TEST_CASE (PVDG_Exceed_Tabdims_Limits)
{
// This checks that Flow's extended table allocation scheme does what
// it's supposed to do. Normally, one would announce the maximum sizes
// in the RUNSPEC keyword 'TABDIMS'. Note that the maximum sizes need
// to be big enough in order to run the case in ECLIPSE. Other than
// NTPVT, Flow does not really care about these declared maximum sizes.
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVDG Output
GAS
FIELD
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 2 1* 1*
/
)" };
const auto props = std::string { R"(
PVDG
14.7 166.666 0.0080
264.7 12.093 0.0096
514.7 6.274 0.0112
1014.7 3.197 0.0140
2014.7 1.614 0.0189
2514.7 1.294 0.0208
3014.7 1.080 0.0228
4014.7 0.811 0.0268
5014.7 0.649 0.0309
9014.7 0.386 0.0470 /
400.0 5.900 0.0130
800.0 2.950 0.0135
1200.0 1.960 0.0140
1600.0 1.470 0.0145
2000.0 1.180 0.0150
2400.0 0.980 0.0155
2800.0 0.840 0.0160
3200.0 0.740 0.0165
3600.0 0.650 0.0170
4000.0 0.590 0.0175
4400.0 0.540 0.0180
4800.0 0.490 0.0185
5200.0 0.450 0.0190
5600.0 0.420 0.0195 /
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvtg = tabdims[ Ix::PvtgMainStart ] - 1;
const auto nppvtg = tabdims[ Ix::NumPvtgPressNodes ];
const auto ntpvtg = tabdims[ Ix::NumPvtgTables ];
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
const auto ncol = 5;
// Pg table defaulted
BOOST_CHECK_EQUAL(tabdims[Ix::PvtgPressStart], 1);
BOOST_CHECK_EQUAL(tabdims[Ix::NumPvtgCompNodes], 1);
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
BOOST_CHECK_EQUAL(nppvtg, 14); // Table 2
BOOST_CHECK_EQUAL(ntpvtg, 2);
const auto pvdg = std::vector<double> {
&tab[ ibpvtg ] + 0,
&tab[ ibpvtg ] + ntpvtg*nppvtg*ncol
};
const auto expect_pvdg = makeTable(5, {
// Pg 1/Bg 1/(Bg*mu_g) d(1/Bg)/dPg d(1/(Bg*mu_g))/dPg
//
// Table 1 (10 pressure nodes)
1.470000000000000e+01, 6.000024000096002e-03, 7.500030000120003e-01, 2.000000000000000e+20, 2.000000000000000e+20,
2.647000000000000e+02, 8.269246671628215e-02, 8.613798616279391e+00, 3.067697708647446e-04, 3.145518246506956e-02,
5.147000000000000e+02, 1.593879502709595e-01, 1.423106698847853e+01, 3.067819342187094e-04, 2.246907348879655e-02,
1.014700000000000e+03, 3.127932436659369e-01, 2.234237454756692e+01, 3.068105867899547e-04, 1.622261511817678e-02,
2.014700000000000e+03, 6.195786864931847e-01, 3.278194108429548e+01, 3.067854428272479e-04, 1.043956653672856e-02,
2.514700000000000e+03, 7.727975270479135e-01, 3.715372726191892e+01, 3.064376811094576e-04, 8.743572355246868e-03,
3.014700000000000e+03, 9.259259259259259e-01, 4.061078622482131e+01, 3.062567977560249e-04, 6.914117925804789e-03,
4.014699999999999e+03, 1.233045622688040e+00, 4.600916502567312e+01, 3.071196967621139e-04, 5.398378800851812e-03,
5.014700000000000e+03, 1.540832049306626e+00, 4.986511486429210e+01, 3.077864266185862e-04, 3.855949838618981e-03,
9.014699999999999e+03, 2.590673575129534e+00, 5.512071436445817e+01, 2.624603814557271e-04, 1.313899875041518e-03,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// ===========================================================================================================================
// Table 2 (14 pressure nodes)
4.000000000000000e+02, 1.694915254237289e-01, 1.303780964797914e+01, 2.000000000000000e+20, 2.000000000000000e+20,
8.000000000000000e+02, 3.389830508474577e-01, 2.510985561833020e+01, 4.237288135593221e-04, 3.018011492587764e-02,
1.200000000000000e+03, 5.102040816326532e-01, 3.644314868804666e+01, 4.280525769629887e-04, 2.833323267429114e-02,
1.600000000000000e+03, 6.802721088435375e-01, 4.691531785127844e+01, 4.251700680272108e-04, 2.618042290807946e-02,
2.000000000000000e+03, 8.474576271186441e-01, 5.649717514124294e+01, 4.179637956877669e-04, 2.395464322491127e-02,
2.400000000000000e+03, 1.020408163265306e+00, 6.583278472679396e+01, 4.323763403666553e-04, 2.333902396387753e-02,
2.800000000000000e+03, 1.190476190476191e+00, 7.440476190476191e+01, 4.251700680272113e-04, 2.142994294491990e-02,
3.200000000000000e+03, 1.351351351351352e+00, 8.190008190008190e+01, 4.021879021879017e-04, 1.873829998829995e-02,
3.600000000000000e+03, 1.538461538461539e+00, 9.049773755656106e+01, 4.677754677754675e-04, 2.149413914119791e-02,
4.000000000000000e+03, 1.694915254237288e+00, 9.685230024213075e+01, 3.911342894393748e-04, 1.588640671392424e-02,
4.400000000000000e+03, 1.851851851851852e+00, 1.028806584362140e+02, 3.923414940364085e-04, 1.507089548520804e-02,
4.800000000000000e+03, 2.040816326530613e+00, 1.103143960286818e+02, 4.724111866969022e-04, 1.858434398116948e-02,
5.199999999999999e+03, 2.222222222222222e+00, 1.169590643274854e+02, 4.535147392290250e-04, 1.661167074700910e-02,
5.599999999999999e+03, 2.380952380952381e+00, 1.221001221001221e+02, 3.968253968253976e-04, 1.285264443159182e-02,
});
check_is_close(pvdg, expect_pvdg);
}
BOOST_AUTO_TEST_CASE (PVTG_USat_Defaulted)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVTG Output
GAS
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 7 1* 2
/
)" };
const auto props = std::string { R"(
PVTG
30 0.00014 0.0523 0.0234
0 0.0521 0.0238 /
90 0.00012 0.0132 0.0252
0 0.0131 0.0253 /
150 0.00015 0.00877 0.0281
0 0.00861 0.0275 /
210 0.00019 0.00554 0.0318
0 0.00555 0.0302 /
270 0.00029 0.00417 0.0355
0 0.00421 0.0330 /
330 0.00049 0.00357 0.0392
0 0.00361 0.0358 /
530 0.00060 0.00356 0.0393
0 0.00360 0.0359 /
/
60 0.00014 0.0523 0.0234 /
120 0.00012 0.0132 0.0252 /
180 0.00015 0.00877 0.0281 /
240 0.00019 0.00554 0.0318 /
300 0.00029 0.00417 0.0355 /
360 0.00049 0.00357 0.0392 /
560 0.00060 0.00356 0.0393
0 0.00360 0.0359 /
/
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvtg = tabdims[ Ix::PvtgMainStart ] - 1;
const auto jbpvtg = tabdims[ Ix::PvtgPressStart ] - 1;
const auto nppvtg = tabdims[ Ix::NumPvtgPressNodes ];
const auto nrpvtg = tabdims[ Ix::NumPvtgCompNodes ];
const auto ntpvtg = tabdims[ Ix::NumPvtgTables ];
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
const auto ncol = 5;
BOOST_CHECK_EQUAL(nppvtg, 7);
BOOST_CHECK_EQUAL(nrpvtg, 2);
BOOST_CHECK_EQUAL(ntpvtg, 2);
const auto pvtg = std::vector<double> {
&tab[ ibpvtg ] + 0,
&tab[ ibpvtg ] + ntpvtg*nppvtg*nrpvtg*ncol
};
const auto pg = std::vector<double> {
&tab[ jbpvtg ] + 0,
&tab[ jbpvtg ] + ntpvtg*nppvtg
};
const auto expect_pvtg = makeTable(5, {
// Rv 1/Bg 1/(Bg*mu_g) d(1/Bg)/dRv d(1/(Bg*mu_g))/dRv
//
// Table 1 (Pg 1)
1.400000000000000e-04, 1.912045889101339e+01, 8.171136278210848e+02, -2.000000000000000e+20, -2.000000000000000e+20,
0, 1.919385796545106e+01, 8.064646203971031e+02, -5.242791031262176e+02, 7.606433874272674e+04,
// Table 1 (Pg 2) ------------------------------------------------------------------------------------------------------------
1.200000000000000e-04, 7.575757575757576e+01, 3.006253006253006e+03, -2.000000000000000e+20, -2.000000000000000e+20,
0, 7.633587786259541e+01, 3.017228374015629e+03, -4.819184208497044e+03, -9.146139802185188e+04,
// Table 1 (Pg 3) ------------------------------------------------------------------------------------------------------------
1.500000000000000e-04, 1.140250855188141e+02, 4.057832224868830e+03, -2.000000000000000e+20, -2.000000000000000e+20,
0, 1.161440185830430e+02, 4.223418857565199e+03, -1.412622042819227e+04, -1.103910884642458e+06,
// Table 1 (Pg 4) ------------------------------------------------------------------------------------------------------------
1.900000000000000e-04, 1.805054151624549e+02, 5.676270917058329e+03, -2.000000000000000e+20, -2.000000000000000e+20,
0, 1.801801801801802e+02, 5.966231131794045e+03, 1.711763064603725e+03, -1.526106393345871e+06,
// Table 1 (Pg 5) ------------------------------------------------------------------------------------------------------------
2.900000000000000e-04, 2.398081534772182e+02, 6.755159252879387e+03, -2.000000000000000e+20, -2.000000000000000e+20,
0, 2.375296912114014e+02, 7.197869430648528e+03, 7.856766433850982e+03, -1.526586819893588e+06,
// Table 1 (Pg 6) ------------------------------------------------------------------------------------------------------------
4.900000000000000e-04, 2.801120448179272e+02, 7.145715429028755e+03, -2.000000000000000e+20, -2.000000000000000e+20,
0, 2.770083102493075e+02, 7.737662297466691e+03, 6.334152180856531e+03, -1.208054833546807e+06,
// Table 1 (Pg 7) ------------------------------------------------------------------------------------------------------------
5.999999999999999e-04, 2.808988764044944e+02, 7.147554106984589e+03, -2.000000000000000e+20, -2.000000000000000e+20,
0, 2.777777777777778e+02, 7.737542556484059e+03, 5.201831044527695e+03, -9.833140824991158e+05,
// ==========================================================================================================================
// Table 2 (Pg 1)
1.400000000000000e-04, 1.912045889101339e+01, 8.171136278210848e+02, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 2) ------------------------------------------------------------------------------------------------------------
1.200000000000000e-04, 7.575757575757576e+01, 3.006253006253006e+03, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 3) ------------------------------------------------------------------------------------------------------------
1.500000000000000e-04, 1.140250855188141e+02, 4.057832224868830e+03, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 4) ------------------------------------------------------------------------------------------------------------
1.900000000000000e-04, 1.805054151624549e+02, 5.676270917058329e+03, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 5) ------------------------------------------------------------------------------------------------------------
2.900000000000000e-04, 2.398081534772182e+02, 6.755159252879387e+03, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 6) ------------------------------------------------------------------------------------------------------------
4.900000000000000e-04, 2.801120448179272e+02, 7.145715429028755e+03, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 7) ------------------------------------------------------------------------------------------------------------
5.999999999999999e-04, 2.808988764044944e+02, 7.147554106984589e+03, -2.000000000000000e+20, -2.000000000000000e+20,
0, 2.777777777777778e+02, 7.737542556484059e+03, 5.201831044527695e+03, -9.833140824991158e+05,
});
const auto expect_pg = makeTable(1, {
// Table 1
30, 90, 150, 210, 270, 330, 530,
// Table 2
60, 120, 180, 240, 300, 360, 560,
});
check_is_close(pvtg, expect_pvtg);
check_is_close(pg , expect_pg );
}
BOOST_AUTO_TEST_CASE (PVTG_USat_Full_Large_Tabdims)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVTG Output
GAS
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 1 1* 7 1* 5
/
)" };
const auto props = std::string { R"(
PVTG
50.00 0.00000497 0.024958 0.01441
0.00000248 0.024958 0.01440
0.00000000 0.024958 0.01440 /
70.00 0.00000521 0.017639 0.01491
0.00000261 0.017641 0.01490
0.00000000 0.017643 0.01490 /
90.00 0.00000627 0.013608 0.01547
0.00000313 0.013611 0.01546
0.00000000 0.013615 0.01544 /
110.00 0.00000798 0.011072 0.01609
0.00000399 0.011076 0.01607
0.00000000 0.011081 0.01605 /
/
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvtg = tabdims[ Ix::PvtgMainStart ] - 1;
const auto jbpvtg = tabdims[ Ix::PvtgPressStart ] - 1;
const auto nppvtg = tabdims[ Ix::NumPvtgPressNodes ];
const auto nrpvtg = tabdims[ Ix::NumPvtgCompNodes ];
const auto ntpvtg = tabdims[ Ix::NumPvtgTables ];
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
const auto ncol = 5;
BOOST_CHECK_EQUAL(nppvtg, 7);
BOOST_CHECK_EQUAL(nrpvtg, 5);
BOOST_CHECK_EQUAL(ntpvtg, 1);
const auto pvtg = std::vector<double> {
&tab[ ibpvtg ] + 0,
&tab[ ibpvtg ] + ntpvtg*nppvtg*nrpvtg*ncol
};
const auto pg = std::vector<double> {
&tab[ jbpvtg ] + 0,
&tab[ jbpvtg ] + ntpvtg*nppvtg
};
const auto expect_pvtg = makeTable(5, {
// Rv 1/Bg 1/(Bg*mu_g) d(1/Bg)/dRv d(1/(Bg*mu_g))/dRv
//
// Table 1 (Pg 1)
4.970000000000000e-06, 4.006731308598445e+01, 2.780521380012800e+03, -2.000000000000000e+20, -2.000000000000000e+20,
2.480000000000000e-06, 4.006731308598445e+01, 2.782452297637809e+03, 0, -7.754689257064208e+05,
0, 4.006731308598445e+01, 2.782452297637809e+03, 0, 0,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 1 (Pg 2) ------------------------------------------------------------------------------------------------------------
5.210000000000000e-06, 5.669255626736210e+01, 3.802317657100074e+03, -2.000000000000000e+20, -2.000000000000000e+20,
2.610000000000000e-06, 5.668612890425712e+01, 3.804438181493767e+03, 2.472062732683009e+03, -8.155863052665014e+05,
0, 5.667970299835629e+01, 3.804006912641362e+03, 2.462032912196776e+03, 1.652371082011811e+05,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 1 (Pg 3) ------------------------------------------------------------------------------------------------------------
6.270000000000000e-06, 7.348618459729570e+01, 4.750238176942192e+03, -2.000000000000000e+20, -2.000000000000000e+20,
3.130000000000000e-06, 7.346998751010213e+01, 4.752263098971676e+03, 5.158308023431543e+03, -6.448796272243677e+05,
0, 7.344840249724568e+01, 4.757020887127311e+03, 6.896170241676778e+03, -1.520060113621228e+06,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 1 (Pg 4) ------------------------------------------------------------------------------------------------------------
7.980000000000000e-06, 9.031791907514450e+01, 5.613295156938751e+03, -2.000000000000000e+20, -2.000000000000000e+20,
3.990000000000000e-06, 9.028530155290719e+01, 5.618251496758381e+03, 8.174817603337499e+03, -1.242190430985102e+06,
0, 9.024456276509339e+01, 5.622714190971551e+03, 1.021022250972279e+04, -1.118469727611510e+06,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 1 (Pg 5) ------------------------------------------------------------------------------------------------------------
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 1 (Pg 6) ------------------------------------------------------------------------------------------------------------
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 1 (Pg 7) ------------------------------------------------------------------------------------------------------------
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
});
const auto expect_pg = makeTable(1, {
// Table 1
50.00, 70.00, 90.00, 110.00, 2.0e20, 2.0e20, 2.0e20,
});
check_is_close(pvtg, expect_pvtg);
check_is_close(pg , expect_pg );
}
BOOST_AUTO_TEST_CASE (PVTG_Exceed_Tabdims_Limits)
{
// This checks that Flow's extended table allocation scheme does what
// it's supposed to do. Normally, one would announce the maximum sizes
// in the RUNSPEC keyword 'TABDIMS'. Note that the maximum sizes need
// to be big enough in order to run the case in ECLIPSE. Other than
// NTPVT, Flow does not really care about these declared maximum sizes.
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVTG Output
GAS
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 1 1* 1
/
)" };
const auto props = std::string { R"(
PVTG
50.00 0.00000497 0.024958 0.01441
0.00000248 0.024958 0.01440
0.00000000 0.024958 0.01440 /
70.00 0.00000521 0.017639 0.01491
0.00000261 0.017641 0.01490
0.00000000 0.017643 0.01490 /
90.00 0.00000627 0.013608 0.01547
0.00000313 0.013611 0.01546
0.00000000 0.013615 0.01544 /
110.00 0.00000798 0.011072 0.01609
0.00000399 0.011076 0.01607
0.00000000 0.011081 0.01605 /
130.00 0.00001041 0.009340 0.01677
0.00000520 0.009346 0.01674
0.00000000 0.009352 0.01671 /
/
50.00 0.00000497 0.024958 0.01441
0.00000248 0.024958 0.01440
0.00000000 0.024958 0.01440 /
/
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvtg = tabdims[ Ix::PvtgMainStart ] - 1;
const auto jbpvtg = tabdims[ Ix::PvtgPressStart ] - 1;
const auto nppvtg = tabdims[ Ix::NumPvtgPressNodes ];
const auto nrpvtg = tabdims[ Ix::NumPvtgCompNodes ];
const auto ntpvtg = tabdims[ Ix::NumPvtgTables ];
Tables: Add Structurally Correct Gas PVT Output from PVTG This commit expands the private member function Tables::addGasPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTG (wet gas) input table data when gas is an active phase in a simulation run. Specifically, the main result array has the columns [ Rv, 1/Bg, 1/(Bg*mu_g), d(1/Bg)/dRv, d(1/(Bg*mu_g))/dRv ] and the ancillary table (base pointer JBPVTG) holds the gas pressure nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared pressure nodes (TABDIMS item 4, NPPVT) times the number of declared composition nodes (TABDIMS item 6, NRPVT). In other words, the main result array is expanded to fill NRPVT rows per gas pressure node per PVT region. Fill value -2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to the number of declared pressure nodes for each PVT region. Here the fill value is +2.0e+20. As an OPM extension, we will use the maximum number of active composition and pressure nodes across all PVTG tables if the declared maximum pressure nodes in TABDIMS is too small. This will create TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all gas-related PVT tables.
2019-03-28 13:30:31 -05:00
const auto ncol = 5;
BOOST_CHECK_EQUAL(nppvtg, 5); // Table 1
BOOST_CHECK_EQUAL(nrpvtg, 3); // Table 1, Pg 1
BOOST_CHECK_EQUAL(ntpvtg, 2); // TABDIMS
const auto pvtg = std::vector<double> {
&tab[ ibpvtg ] + 0,
&tab[ ibpvtg ] + ntpvtg*nppvtg*nrpvtg*ncol
};
const auto pg = std::vector<double> {
&tab[ jbpvtg ] + 0,
&tab[ jbpvtg ] + ntpvtg*nppvtg
};
const auto expect_pvtg = makeTable(5, {
// Rv 1/Bg 1/(Bg*mu_g) d(1/Bg)/dRv d(1/(Bg*mu_g))/dRv
//
// Table 1 (Pg 1)
4.970000000000000e-06, 4.006731308598445e+01, 2.780521380012800e+03, -2.000000000000000e+20, -2.000000000000000e+20,
2.480000000000000e-06, 4.006731308598445e+01, 2.782452297637809e+03, 0, -7.754689257064208e+05,
0, 4.006731308598445e+01, 2.782452297637809e+03, 0, 0,
// Table 1 (Pg 2) ------------------------------------------------------------------------------------------------------------
5.210000000000000e-06, 5.669255626736210e+01, 3.802317657100074e+03, -2.000000000000000e+20, -2.000000000000000e+20,
2.610000000000000e-06, 5.668612890425712e+01, 3.804438181493767e+03, 2.472062732683009e+03, -8.155863052665014e+05,
0, 5.667970299835629e+01, 3.804006912641362e+03, 2.462032912196776e+03, 1.652371082011811e+05,
// Table 1 (Pg 3) ------------------------------------------------------------------------------------------------------------
6.270000000000000e-06, 7.348618459729570e+01, 4.750238176942192e+03, -2.000000000000000e+20, -2.000000000000000e+20,
3.130000000000000e-06, 7.346998751010213e+01, 4.752263098971676e+03, 5.158308023431543e+03, -6.448796272243677e+05,
0, 7.344840249724568e+01, 4.757020887127311e+03, 6.896170241676778e+03, -1.520060113621228e+06,
// Table 1 (Pg 4) ------------------------------------------------------------------------------------------------------------
7.980000000000000e-06, 9.031791907514450e+01, 5.613295156938751e+03, -2.000000000000000e+20, -2.000000000000000e+20,
3.990000000000000e-06, 9.028530155290719e+01, 5.618251496758381e+03, 8.174817603337499e+03, -1.242190430985102e+06,
0, 9.024456276509339e+01, 5.622714190971551e+03, 1.021022250972279e+04, -1.118469727611510e+06,
// Table 1 (Pg 5) ------------------------------------------------------------------------------------------------------------
1.041000000000000e-05, 1.070663811563169e+02, 6.384399591909179e+03, -2.000000000000000e+20, -2.000000000000000e+20,
5.200000000000000e-06, 1.069976460517869e+02, 6.391735128541628e+03, 1.319291833590461e+04, -1.407972482235984e+06,
0, 1.069289991445680e+02, 6.399102282738958e+03, 1.320132831131706e+04, -1.416760422563444e+06,
// ==========================================================================================================================
// Table 2 (Pg 1)
4.970000000000000e-06, 4.006731308598445e+01, 2.780521380012800e+03, -2.000000000000000e+20, -2.000000000000000e+20,
2.480000000000000e-06, 4.006731308598445e+01, 2.782452297637809e+03, 0, -7.754689257064208e+05,
0, 4.006731308598445e+01, 2.782452297637809e+03, 0, 0,
// Table 2 (Pg 2) ------------------------------------------------------------------------------------------------------------
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 3) ------------------------------------------------------------------------------------------------------------
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 4) ------------------------------------------------------------------------------------------------------------
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
// Table 2 (Pg 5) ------------------------------------------------------------------------------------------------------------
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
-2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20,
});
const auto expect_pg = makeTable(1, {
// Table 1
50.00, 70.00, 90.00, 110.00, 130.0,
// Table 2
50.00, 2.0e20, 2.0e20, 2.0e20, 2.0e20,
});
check_is_close(pvtg, expect_pvtg);
check_is_close(pg , expect_pg );
}
BOOST_AUTO_TEST_SUITE_END ()
// =====================================================================
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
BOOST_AUTO_TEST_SUITE (Oil)
BOOST_AUTO_TEST_CASE (PVCDO)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVCDO Output
OIL
WATER
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 4 1* 3
/
)" };
const auto props = std::string { R"(
PVCDO
-- Pref Bo(Pref) Co Vo(Pref) Cv
200 1.23 0.321e-4 0.25 0.654e-3 /
250 0.987 1.234e-5 0.314 0.9876e-5 /
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvto = tabdims[ Ix::PvtoMainStart ] - 1;
const auto nppvto = tabdims[ Ix::NumPvtoPressNodes ];
const auto ntpvto = tabdims[ Ix::NumPvtoTables ];
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
const auto ncol = 5;
// Rs table defaulted
BOOST_CHECK_EQUAL(tabdims[Ix::PvtoCompStart], 1);
BOOST_CHECK_EQUAL(tabdims[Ix::NumPvtoCompNodes], 1);
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
BOOST_CHECK_EQUAL(nppvto, 4);
BOOST_CHECK_EQUAL(ntpvto, 2);
const auto pvcdo = std::vector<double> {
&tab[ ibpvto ] + 0,
&tab[ ibpvto ] + ntpvto*nppvto*ncol
};
const auto expect_pvcdo = makeTable(5, {
// Po Bo Co Vo Cv
//
// Table 1
2.000000000000000e+02, 1.230000000000000e+00, 3.210000000000000e-05, 2.500000000000000e-01, 6.540000000000001e-04,
-1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20,
-1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20,
-1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20,
// ===========================================================================================================================
// Table 2
2.500000000000000e+02, 9.870000000000000e-01, 1.234000000000000e-05, 3.140000000000000e-01, 9.876000000000000e-06,
-1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20,
-1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20,
-1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20, -1.000000000000000e+20,
});
check_is_close(pvcdo, expect_pvcdo);
}
BOOST_AUTO_TEST_CASE (PVDO_Regular)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVDO Output
OIL
WATER
FIELD
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 8 1* 1*
/
)" };
const auto props = std::string { R"(
PVDO
400 1.012 1.16
1200 1.0040 1.164
2000 0.9960 1.167
2800 0.9880 1.172
3600 0.9802 1.177
4400 0.9724 1.181
5200 0.9646 1.185
5600 0.9607 1.19 /
800 1.0255 1.14
1600 1.0172 1.14
2400 1.0091 1.14
3200 1.0011 1.14
4000 0.9931 1.14
4800 0.9852 1.14
5600 0.9774 1.14 /
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvto = tabdims[ Ix::PvtoMainStart ] - 1;
const auto nppvto = tabdims[ Ix::NumPvtoPressNodes ];
const auto ntpvto = tabdims[ Ix::NumPvtoTables ];
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
const auto ncol = 5;
// Rs table defaulted
BOOST_CHECK_EQUAL(tabdims[Ix::PvtoCompStart], 1);
BOOST_CHECK_EQUAL(tabdims[Ix::NumPvtoCompNodes], 1);
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
BOOST_CHECK_EQUAL(nppvto, 8);
BOOST_CHECK_EQUAL(ntpvto, 2);
const auto pvdo = std::vector<double> {
&tab[ ibpvto ] + 0,
&tab[ ibpvto ] + ntpvto*nppvto*ncol
};
const auto expect_pvdo = makeTable(5, {
// Po 1/Bo 1/(Bo*mu_o) d(1/Bo)/dPo d(1/(Bo*mu_o))/dPo
//
// Table 1 (8 pressure nodes)
4.000000000000000e+02, 9.881422924901185e-01, 8.518468038707919e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.200000000000000e+03, 9.960159362549801e-01, 8.556837940334882e-01, 9.842054706076935e-06, 4.796237703370287e-06,
2.000000000000000e+03, 1.004016064257028e+00, 8.603393866812581e-01, 1.000016000256010e-05, 5.819490809712421e-06,
2.800000000000000e+03, 1.012145748987854e+00, 8.636055878735959e-01, 1.016210591353262e-05, 4.082751490422227e-06,
3.600000000000000e+03, 1.020199959192002e+00, 8.667799143517431e-01, 1.006776275518428e-05, 3.967908097683990e-06,
4.400000000000000e+03, 1.028383381324558e+00, 8.707733965491598e-01, 1.022927766569509e-05, 4.991852746770858e-06,
5.199999999999999e+03, 1.036699149906697e+00, 8.748516032967908e-01, 1.039471072767418e-05, 5.097758434538807e-06,
5.599999999999999e+03, 1.040907671489539e+00, 8.747123289828058e-01, 1.052130395710449e-05, -3.481857849624292e-07,
// ===========================================================================================================================
// Table 2 (7 pressure nodes)
8.000000000000000e+02, 9.751340809361286e-01, 8.553807727509901e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.600000000000000e+03, 9.830908375933936e-01, 8.623603838538541e-01, 9.945945821581148e-06, 8.724513878579920e-06,
2.400000000000000e+03, 9.909820632246555e-01, 8.692825116005751e-01, 9.864032039077486e-06, 8.652659683401343e-06,
3.200000000000000e+03, 9.989012086704624e-01, 8.762291304126864e-01, 9.898931807258565e-06, 8.683273515139035e-06,
4.000000000000000e+03, 1.006947940791461e+00, 8.832876673609308e-01, 1.005841515124826e-05, 8.823171185305545e-06,
4.800000000000000e+03, 1.015022330491271e+00, 8.903704653432202e-01, 1.009298712476236e-05, 8.853497477861732e-06,
5.599999999999999e+03, 1.023122570083896e+00, 8.974759386700842e-01, 1.012529949078135e-05, 8.881841658580091e-06,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
});
check_is_close(pvdo, expect_pvdo);
}
BOOST_AUTO_TEST_CASE (PVDO_Exceed_Tabdims_Limits)
{
// This checks that Flow's extended table allocation scheme does what
// it's supposed to do. Normally, one would announce the maximum sizes
// in the RUNSPEC keyword 'TABDIMS'. Note that the maximum sizes need
// to be big enough in order to run the case in ECLIPSE. Other than
// NTPVT, Flow does not really care about these declared maximum sizes.
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVDO Output
OIL
WATER
FIELD
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 2 1* 1*
/
)" };
const auto props = std::string { R"(
PVDO
400 1.012 1.16
1200 1.0040 1.164
2000 0.9960 1.167
2800 0.9880 1.172
3600 0.9802 1.177
4000 0.9752 1.179
4400 0.9724 1.181
5200 0.9646 1.185
5400 0.9630 1.187
5600 0.9607 1.19 /
800 1.0255 1.14
1600 1.0172 1.14
5600 0.9774 1.14 /
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvto = tabdims[ Ix::PvtoMainStart ] - 1;
const auto nppvto = tabdims[ Ix::NumPvtoPressNodes ];
const auto ntpvto = tabdims[ Ix::NumPvtoTables ];
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
const auto ncol = 5;
// Rs table defaulted
BOOST_CHECK_EQUAL(tabdims[Ix::PvtoCompStart], 1);
BOOST_CHECK_EQUAL(tabdims[Ix::NumPvtoCompNodes], 1);
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
BOOST_CHECK_EQUAL(nppvto, 10); // Table 1
BOOST_CHECK_EQUAL(ntpvto, 2);
// Verify declared TABDIMS from input
{
const auto& tabd = es.runspec().tabdims();
BOOST_CHECK_EQUAL(tabd.getNumPVTTables(), 2U);
BOOST_CHECK_EQUAL(tabd.getNumPressureNodes(), 2U);
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
}
const auto pvdo = std::vector<double> {
&tab[ ibpvto ] + 0,
&tab[ ibpvto ] + ntpvto*nppvto*ncol
};
const auto expect_pvdo = makeTable(5, {
// Po 1/Bo 1/(Bo*mu_o) d(1/Bo)/dPo d(1/(Bo*mu_o))/dPo
//
// Table 1 (10 pressure nodes)
4.000000000000000e+02, 9.881422924901185e-01, 8.518468038707919e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.200000000000000e+03, 9.960159362549801e-01, 8.556837940334882e-01, 9.842054706076935e-06, 4.796237703370287e-06,
2.000000000000000e+03, 1.004016064257028e+00, 8.603393866812581e-01, 1.000016000256010e-05, 5.819490809712421e-06,
2.800000000000000e+03, 1.012145748987854e+00, 8.636055878735959e-01, 1.016210591353262e-05, 4.082751490422227e-06,
3.600000000000000e+03, 1.020199959192002e+00, 8.667799143517431e-01, 1.006776275518428e-05, 3.967908097683990e-06,
4.000000000000000e+03, 1.025430680885972e+00, 8.697461245852181e-01, 1.307680423492609e-05, 7.415525583687474e-06,
4.400000000000000e+03, 1.028383381324558e+00, 8.707733965491598e-01, 7.381751096464098e-06, 2.568179909854249e-06,
5.199999999999999e+03, 1.036699149906697e+00, 8.748516032967908e-01, 1.039471072767418e-05, 5.097758434538807e-06,
5.400000000000000e+03, 1.038421599169263e+00, 8.748286429395642e-01, 8.612246312827937e-06, -1.148017861329892e-07,
5.599999999999999e+03, 1.040907671489539e+00, 8.747123289828058e-01, 1.243036160138106e-05, -5.815697837918713e-07,
// ===========================================================================================================================
// Table 2 (3 pressure nodes)
8.000000000000000e+02, 9.751340809361286e-01, 8.553807727509901e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.600000000000000e+03, 9.830908375933936e-01, 8.623603838538541e-01, 9.945945821581148e-06, 8.724513878579920e-06,
5.599999999999999e+03, 1.023122570083896e+00, 8.974759386700842e-01, 1.000793312262560e-05, 8.778888704057549e-06,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
});
check_is_close(pvdo, expect_pvdo);
}
BOOST_AUTO_TEST_CASE (PVTO_SPE1_USat_Defaulted)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVTO Output
OIL
WATER
FIELD
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 4 1* 3
/
)" };
const auto props = std::string { R"(
PVTO
0.3710 1014.7 1.2950 0.8300 /
0.9300 3014.7 1.5650 0.5940 /
1.6180 5014.7 1.8270 0.4490
9014.7 1.7370 0.6310 /
/
0.0010 14.7 1.0620 1.0400 /
1.2700 4014.7 1.6950 0.5100
9014.7 1.5790 0.7400 /
/
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvto = tabdims[ Ix::PvtoMainStart ] - 1;
const auto jbpvto = tabdims[ Ix::PvtoCompStart ] - 1;
const auto nppvto = tabdims[ Ix::NumPvtoPressNodes ];
const auto nrpvto = tabdims[ Ix::NumPvtoCompNodes ];
const auto ntpvto = tabdims[ Ix::NumPvtoTables ];
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
const auto ncol = 5;
BOOST_CHECK_EQUAL(nppvto, 4);
BOOST_CHECK_EQUAL(nrpvto, 3);
BOOST_CHECK_EQUAL(ntpvto, 2);
const auto pvto = std::vector<double> {
&tab[ ibpvto ] + 0,
&tab[ ibpvto ] + ntpvto*nrpvto*nppvto*ncol
};
const auto rs = std::vector<double> {
&tab[ jbpvto ] + 0,
&tab[ jbpvto ] + ntpvto*nrpvto
};
const auto expect_pvto = makeTable(5, {
// Po 1/Bo 1/(Bo*mu_o) d(1/Bo)/dPo d(1/(Bo*mu_o))/dPo
//
// Table 1 (Comp 1)
1.014700000000000e+03, 7.722007722007722e-01, 9.303623761455088e-01, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 1 (Comp 2) ----------------------------------------------------------------------------------------------------------
3.014700000000000e+03, 6.389776357827476e-01, 1.075719925560181e+00, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 1 (Comp 3) ----------------------------------------------------------------------------------------------------------
5.014700000000000e+03, 5.473453749315819e-01, 1.219032015437822e+00, 2.000000000000000e+20, 2.000000000000000e+20,
9.014699999999999e+03, 5.757052389176741e-01, 9.123696337839526e-01, 7.089965996523064e-06, -7.666559541346725e-05,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// ==========================================================================================================================
// Table 2 (Comp 1)
1.470000000000000e+01, 9.416195856873822e-01, 9.054034477763291e-01, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 2) ----------------------------------------------------------------------------------------------------------
4.014699999999999e+03, 5.899705014749262e-01, 1.156804904852797e+00, 2.000000000000000e+20, 2.000000000000000e+20,
9.014699999999999e+03, 6.333122229259025e-01, 8.558273282782466e-01, 8.668344290195251e-06, -6.019551531491001e-05,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 3, unused) --------------------------------------------------------------------------------------------------
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
});
const auto expect_rs = makeTable(1, {
// Table 1
0.3710, 0.9300, 1.6180,
// Table 2
0.0010, 1.2700, 2.0e+20,
});
check_is_close(pvto, expect_pvto);
check_is_close(rs , expect_rs );
}
BOOST_AUTO_TEST_CASE (PVTO_USat_Full)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVTO Output
OIL
WATER
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 5 1* 4
/
)" };
const auto props = std::string { R"(
PVTO
20.59 50.00 1.10615 1.180
75.00 1.10164 1.247
100.00 1.09744 1.315
125.00 1.09351 1.384
150.00 1.08984 1.453 /
28.19 70.00 1.12522 1.066
95.00 1.12047 1.124
120.00 1.11604 1.182
145.00 1.11191 1.241
170.00 1.10804 1.300 /
36.01 90.00 1.14458 0.964
115.00 1.13959 1.014
140.00 1.13494 1.064
165.00 1.13060 1.115
190.00 1.12653 1.166 /
44.09 110.00 1.16437 0.880
135.00 1.15915 0.924
160.00 1.15428 0.968
185.00 1.14973 1.012
210.00 1.14547 1.056 /
/
32.91 80.00 1.13304 1.04537
114.00 1.12837 1.10009
148.00 1.12401 1.15521
182.00 1.11994 1.21063 /
40.99 100.00 1.15276 0.97219
134.00 1.14786 1.02086
168.00 1.14328 1.06983
202.00 1.13900 1.11901 /
49.36 120.00 1.17297 0.91124
154.00 1.16783 0.95496
188.00 1.16303 0.99891
222.00 1.15854 1.04301 /
58.04 140.00 1.19374 0.85942
174.00 1.18836 0.89902
208.00 1.18334 0.93878
242.00 1.17864 0.97864 /
/
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvto = tabdims[ Ix::PvtoMainStart ] - 1;
const auto jbpvto = tabdims[ Ix::PvtoCompStart ] - 1;
const auto nppvto = tabdims[ Ix::NumPvtoPressNodes ];
const auto nrpvto = tabdims[ Ix::NumPvtoCompNodes ];
const auto ntpvto = tabdims[ Ix::NumPvtoTables ];
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
const auto ncol = 5;
BOOST_CHECK_EQUAL(nppvto, 5);
BOOST_CHECK_EQUAL(nrpvto, 4);
BOOST_CHECK_EQUAL(ntpvto, 2);
const auto pvto = std::vector<double> {
&tab[ ibpvto ] + 0,
&tab[ ibpvto ] + ntpvto*nrpvto*nppvto*ncol
};
const auto rs = std::vector<double> {
&tab[ jbpvto ] + 0,
&tab[ jbpvto ] + ntpvto*nrpvto
};
const auto expect_pvto = makeTable(5, {
// Po 1/Bo 1/(Bo*mu_o) d(1/Bo)/dPo d(1/(Bo*mu_o))/dPo
//
// Table 1 (Comp 1)
5.000000000000001e+01, 9.040365230755323e-01, 7.661326466741798e-01, 2.000000000000000e+20, 2.000000000000000e+20,
7.500000000000000e+01, 9.077375549181221e-01, 7.279370929575959e-01, 1.480412737035941e-04, -1.527822148663356e-03,
1.000000000000000e+02, 9.112115468727220e-01, 6.929365375457962e-01, 1.389596781839940e-04, -1.400022216471987e-03,
1.250000000000000e+02, 9.144863787253888e-01, 6.607560539923329e-01, 1.309932741066744e-04, -1.287219342138530e-03,
1.500000000000000e+02, 9.175658812302724e-01, 6.314975094496025e-01, 1.231801001953415e-04, -1.170341781709219e-03,
// Table 1 (Comp 2) ----------------------------------------------------------------------------------------------------------
7.000000000000000e+01, 8.887150957146157e-01, 8.336914593945738e-01, 2.000000000000000e+20, 2.000000000000000e+20,
9.500000000000001e+01, 8.924826189009969e-01, 7.940236822962605e-01, 1.507009274552472e-04, -1.586711083932530e-03,
1.200000000000000e+02, 8.960252320705352e-01, 7.580585719716880e-01, 1.417045267815320e-04, -1.438604412982900e-03,
1.450000000000000e+02, 8.993533649306149e-01, 7.247005358022682e-01, 1.331253144031886e-04, -1.334321446776793e-03,
1.700000000000000e+02, 9.024944947835819e-01, 6.942265344489090e-01, 1.256451941186798e-04, -1.218960054134368e-03,
// Table 1 (Comp 3) ----------------------------------------------------------------------------------------------------------
9.000000000000001e+01, 8.736829229935872e-01, 9.063100860929328e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.150000000000000e+02, 8.775085776463464e-01, 8.653930746019195e-01, 1.530261861103677e-04, -1.636680459640534e-03,
1.400000000000000e+02, 8.811038468993955e-01, 8.281051192663491e-01, 1.438107701219638e-04, -1.491518213422816e-03,
1.650000000000000e+02, 8.844861135680170e-01, 7.932610884018088e-01, 1.352906667448606e-04, -1.393761234581614e-03,
1.900000000000000e+02, 8.876816418559648e-01, 7.613050101680658e-01, 1.278211315179111e-04, -1.278243129349715e-03,
// Table 1 (Comp 4) ----------------------------------------------------------------------------------------------------------
1.100000000000000e+02, 8.588335322964350e-01, 9.759471957914034e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.350000000000000e+02, 8.627011171979468e-01, 9.336592177466957e-01, 1.547033960604739e-04, -1.691519121788311e-03,
1.600000000000000e+02, 8.663409224798143e-01, 8.949802918179900e-01, 1.455922112746988e-04, -1.547157037148228e-03,
1.850000000000000e+02, 8.697694241256644e-01, 8.594559526933443e-01, 1.371400658340026e-04, -1.420973564985826e-03,
2.100000000000000e+02, 8.730040943892027e-01, 8.267084227170479e-01, 1.293868105415319e-04, -1.309901199051855e-03,
// ===========================================================================================================================
// Table 2 (Comp 1)
8.000000000000000e+01, 8.825813740026830e-01, 8.442765470624592e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.140000000000000e+02, 8.862341253312299e-01, 8.056014738168967e-01, 1.074338626043212e-04, -1.137502154281250e-03,
1.480000000000000e+02, 8.896718000729531e-01, 7.701385895836714e-01, 1.011080806389172e-04, -1.043026006859568e-03,
1.820000000000000e+02, 8.929049770523422e-01, 7.375539818543586e-01, 9.509344057026681e-05, -9.583708155680233e-04,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 2) ----------------------------------------------------------------------------------------------------------
1.000000000000000e+02, 8.674832575731288e-01, 8.922980668111468e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.340000000000000e+02, 8.711863816144825e-01, 8.533847752037326e-01, 1.089154129809896e-04, -1.144508576688653e-03,
1.680000000000000e+02, 8.746763697431950e-01, 8.175844477563677e-01, 1.026467096680142e-04, -1.052950807275436e-03,
2.020000000000000e+02, 8.779631255487269e-01, 7.845891685943172e-01, 9.666928839799841e-05, -9.704493871191340e-04,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 3) ----------------------------------------------------------------------------------------------------------
1.200000000000000e+02, 8.525367230193440e-01, 9.355786873044905e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.540000000000000e+02, 8.562890146682309e-01, 8.966752687738030e-01, 1.103615190849091e-04, -1.144218192079043e-03,
1.880000000000000e+02, 8.598230484166358e-01, 8.607612782098846e-01, 1.039421690707318e-04, -1.056293840115247e-03,
2.220000000000000e+02, 8.631553507000190e-01, 8.275619128292337e-01, 9.800889068774162e-05, -9.764519229603183e-04,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 4) ----------------------------------------------------------------------------------------------------------
1.400000000000000e+02, 8.377033524888167e-01, 9.747310424342193e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.740000000000000e+02, 8.414958430105355e-01, 9.360145970173471e-01, 1.115438388740827e-04, -1.138718982849180e-03,
2.080000000000000e+02, 8.450656616019064e-01, 9.001743343508666e-01, 1.049946644520869e-04, -1.054125372543546e-03,
2.420000000000000e+02, 8.484354849657233e-01, 8.669536141642721e-01, 9.911245187696645e-05, -9.770800054880735e-04,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
});
const auto expect_rs = makeTable(1, {
// Table 1
20.59, 28.19, 36.01, 44.09,
// Table 2
32.91, 40.99, 49.36, 58.04,
});
check_is_close(pvto, expect_pvto);
check_is_close(rs , expect_rs );
}
BOOST_AUTO_TEST_CASE (PVTO_Exceed_Tabdims_Limits)
{
// This checks that Flow's extended table allocation scheme does what
// it's supposed to do. Normally, one would announce the maximum sizes
// in the RUNSPEC keyword 'TABDIMS'. Note that the maximum sizes need
// to be big enough in order to run the case in ECLIPSE. Other than
// NTPVT, Flow does not really care about these declared maximum sizes.
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVTO Output
OIL
WATER
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 2 1* 1
/
)" };
const auto props = std::string { R"(
PVTO
20.59 50.00 1.10615 1.180
75.00 1.10164 1.247 /
28.19 70.00 1.12522 1.066 /
44.09 110.00 1.16437 0.880
135.00 1.15915 0.924
160.00 1.15428 0.968
185.00 1.14973 1.012
210.00 1.14547 1.056 /
/
32.91 80.00 1.13304 1.04537
114.00 1.12837 1.10009 /
40.99 100.00 1.15276 0.97219
134.00 1.14786 1.02086
168.00 1.14328 1.06983 /
49.36 120.00 1.17297 0.91124
154.00 1.16783 0.95496 /
58.04 140.00 1.19374 0.85942
174.00 1.18836 0.89902 /
/
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvto = tabdims[ Ix::PvtoMainStart ] - 1;
const auto jbpvto = tabdims[ Ix::PvtoCompStart ] - 1;
const auto nppvto = tabdims[ Ix::NumPvtoPressNodes ];
const auto nrpvto = tabdims[ Ix::NumPvtoCompNodes ];
const auto ntpvto = tabdims[ Ix::NumPvtoTables ];
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
const auto ncol = 5;
// Verify declared TABDIMS from input
{
const auto& tabd = es.runspec().tabdims();
BOOST_CHECK_EQUAL(tabd.getNumPVTTables(), 2U);
BOOST_CHECK_EQUAL(tabd.getNumRSNodes(), 1U);
BOOST_CHECK_EQUAL(tabd.getNumPressureNodes(), 2U);
Tables: Add Structurally Correct Oil PVT Output from PVTO This commit expands the private member function Tables::addOilPVTTables(const EclipseState&) to create structurally correct TAB vector entries from the PVTO (live oil) input table data when oil is an active phase in a simulation run. Specifically, the main result array has the columns [ Po, 1/Bo, 1/(Bo*mu_o), d(1/Bo)/dPo, d(1/(Bo*mu_o))/dPo ] and the ancillary table (base pointer JBPVTO) holds the composition nodes. Note that while we do create structurally correct output tables, we do not fill in undersaturated states that have been defaulted in the input table. The number of table rows in the main table is equal to number of PVT regions times the number of declared composition nodes (TABDIMS item 6, NRPVT) times the number of declared pressure nodes (TABDIMS item 4, NPPVT). In other words, the main result array is expanded to fill NPPVT rows per Rs node per PVT region. Fill value +2.0e+20. We have verified the results with ECLIPSE 100. The ancillary table is expanded to number of declared composition nodes for each PVT region. Fill value +2.0e+20. As an OPM extension, we will use the maximum number of active pressure and composition nodes across all PVTO tables if the declared maximum pressure nodes in TABDIMS is too small. This will create a TAB vector representations that are not compatible with ECLIPSE, but which will nevertheless be useful in the context of ResInsight's flux calculation. Add unit tests for all supported oil-related PVT tables.
2019-03-28 11:45:05 -05:00
}
// Verify active TABDIMS from dynamic sizes
BOOST_CHECK_EQUAL(nppvto, 5); // Table 1, Comp 3
BOOST_CHECK_EQUAL(nrpvto, 4); // Table 2
BOOST_CHECK_EQUAL(ntpvto, 2);
const auto pvto = std::vector<double> {
&tab[ ibpvto ] + 0,
&tab[ ibpvto ] + ntpvto*nrpvto*nppvto*ncol
};
const auto rs = std::vector<double> {
&tab[ jbpvto ] + 0,
&tab[ jbpvto ] + ntpvto*nrpvto
};
const auto expect_pvto = makeTable(5, {
// Po 1/Bo 1/(Bo*mu_o) d(1/Bo)/dPo d(1/(Bo*mu_o))/dPo
//
// Table 1 (Comp 1)
5.000000000000001e+01, 9.040365230755323e-01, 7.661326466741798e-01, 2.000000000000000e+20, 2.000000000000000e+20,
7.500000000000000e+01, 9.077375549181221e-01, 7.279370929575959e-01, 1.480412737035941e-04, -1.527822148663356e-03,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 1 (Comp 2) ----------------------------------------------------------------------------------------------------------
7.000000000000000e+01, 8.887150957146157e-01, 8.336914593945738e-01, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 1 (Comp 3) ----------------------------------------------------------------------------------------------------------
1.100000000000000e+02, 8.588335322964350e-01, 9.759471957914034e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.350000000000000e+02, 8.627011171979468e-01, 9.336592177466957e-01, 1.547033960604739e-04, -1.691519121788311e-03,
1.600000000000000e+02, 8.663409224798143e-01, 8.949802918179900e-01, 1.455922112746988e-04, -1.547157037148228e-03,
1.850000000000000e+02, 8.697694241256644e-01, 8.594559526933443e-01, 1.371400658340026e-04, -1.420973564985826e-03,
2.100000000000000e+02, 8.730040943892027e-01, 8.267084227170479e-01, 1.293868105415319e-04, -1.309901199051855e-03,
// Table 1 (Comp 4 -- unused) ------------------------------------------------------------------------------------------------
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// ===========================================================================================================================
// Table 2 (Comp 1)
8.000000000000000e+01, 8.825813740026830e-01, 8.442765470624592e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.140000000000000e+02, 8.862341253312299e-01, 8.056014738168967e-01, 1.074338626043212e-04, -1.137502154281250e-03,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 2) ----------------------------------------------------------------------------------------------------------
1.000000000000000e+02, 8.674832575731288e-01, 8.922980668111468e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.340000000000000e+02, 8.711863816144825e-01, 8.533847752037326e-01, 1.089154129809896e-04, -1.144508576688653e-03,
1.680000000000000e+02, 8.746763697431950e-01, 8.175844477563677e-01, 1.026467096680142e-04, -1.052950807275436e-03,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 3) ----------------------------------------------------------------------------------------------------------
1.200000000000000e+02, 8.525367230193440e-01, 9.355786873044905e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.540000000000000e+02, 8.562890146682309e-01, 8.966752687738030e-01, 1.103615190849091e-04, -1.144218192079043e-03,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
// Table 2 (Comp 4) ----------------------------------------------------------------------------------------------------------
1.400000000000000e+02, 8.377033524888167e-01, 9.747310424342193e-01, 2.000000000000000e+20, 2.000000000000000e+20,
1.740000000000000e+02, 8.414958430105355e-01, 9.360145970173471e-01, 1.115438388740827e-04, -1.138718982849180e-03,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20,
});
const auto expect_rs = makeTable(1, {
// Table 1
20.59, 28.19, 44.09, +2.0e20,
// Table 2
32.91, 40.99, 49.36, 58.04,
});
check_is_close(pvto, expect_pvto);
check_is_close(rs , expect_rs );
}
BOOST_AUTO_TEST_SUITE_END ()
// =====================================================================
BOOST_AUTO_TEST_SUITE (Water)
BOOST_AUTO_TEST_CASE (PVTW)
{
const auto rspec = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test PVTW Output
WATER
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 2 1* 4 1* 3
/
)" };
const auto props = std::string { R"(
PVTW
-- Pref Bw(Pref) Cw Vw(Pref) Cv
200 1.23 0.321e-4 0.25 0.654e-3 /
250 0.987 1.234e-5 0.314 0.9876e-5 /
)" };
const auto es = parse(rspec, props);
auto tables = ::Opm::Tables(es.getUnits());
tables.addPVTTables(es);
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibpvtw = tabdims[ Ix::PvtwStart ] - 1;
const auto ntpvtw = tabdims[ Ix::NumPvtwTables ];
const auto ncol = 5;
BOOST_CHECK_EQUAL(ntpvtw, 2);
const auto pvtw = std::vector<double> {
&tab[ ibpvtw ] + 0,
&tab[ ibpvtw ] + ntpvtw*ncol
};
const auto expect_pvtw = makeTable(5, {
// Pw 1/Bw Cw 1/(Bw*mu_w) Cw - Cv
2.000000000000000e+02, 8.130081300813008e-01, 3.210000000000000e-05, 3.252032520325203e+00, -6.219000000000000e-04,
2.500000000000000e+02, 1.013171225937183e+00, 1.234000000000000e-05, 3.226659955213960e+00, 2.464000000000000e-06,
});
check_is_close(pvtw, expect_pvtw);
}
BOOST_AUTO_TEST_SUITE_END ()
// =====================================================================
BOOST_AUTO_TEST_SUITE_END ()
// =====================================================================
BOOST_AUTO_TEST_SUITE (Density)
BOOST_AUTO_TEST_CASE (Single_Region)
{
const auto input = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test DENSITY Output
OIL
WATER
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 1 1* 4 1* 3
/
GRID
INIT
DXV
10*100 /
DYV
10*100 /
DZV
10*10 /
DEPTHZ
121*2000 /
PERMX
1000*100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
1000*0.3 /
PROPS
DENSITY
859.1 1033.2 0.859 /
END
)" };
const auto es = ::Opm::EclipseState { Opm::Parser{}.parseString(input) };
auto tables = ::Opm::Tables(es.getUnits());
tables.addDensity(es.getTableManager().getDensityTable());
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibdens = tabdims[ Ix::DensityTableStart ] - 1;
const auto ntdens = tabdims[ Ix::DensityNumTables ];
const auto ncol = 3;
BOOST_CHECK_EQUAL(ntdens, 1);
const auto density = std::vector<double> {
&tab[ ibdens ] + 0,
&tab[ ibdens ] + ntdens*ncol
};
const auto expect_density = makeTable(ncol, {
// rhoOS rhoWS rhoGS
859.1, 1033.2, 0.859,
});
check_is_close(density, expect_density);
}
BOOST_AUTO_TEST_CASE (Multi_Region)
{
const auto input = std::string { R"(RUNSPEC
DIMENS
10 10 10 /
TITLE
Test DENSITY Output
OIL
WATER
METRIC
TABDIMS
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
1* 4 1* 4 1* 3
/
GRID
INIT
DXV
10*100 /
DYV
10*100 /
DZV
10*10 /
DEPTHZ
121*2000 /
PERMX
1000*100.0 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
PORO
1000*0.3 /
PROPS
DENSITY
859.1 1035.4 0.8591 /
860.2 1037.6 0.8592 /
861.3 1039.8 0.8593 /
862.4 1042.0 0.8594 /
END
)" };
const auto es = ::Opm::EclipseState { Opm::Parser{}.parseString(input) };
auto tables = ::Opm::Tables(es.getUnits());
tables.addDensity(es.getTableManager().getDensityTable());
const auto& tabdims = tables.tabdims();
const auto& tab = tables.tab();
const auto ibdens = tabdims[ Ix::DensityTableStart ] - 1;
const auto ntdens = tabdims[ Ix::DensityNumTables ];
const auto ncol = 3;
BOOST_CHECK_EQUAL(ntdens, 4);
const auto density = std::vector<double> {
&tab[ ibdens ] + 0,
&tab[ ibdens ] + ntdens*ncol
};
const auto expect_density = makeTable(ncol, {
// rhoOS rhoWS rhoGS
859.1, 1035.4, 0.8591,
860.2, 1037.6, 0.8592,
861.3, 1039.8, 0.8593,
862.4, 1042.0, 0.8594,
});
check_is_close(density, expect_density);
}
BOOST_AUTO_TEST_SUITE_END () // Density