2016-11-16 09:12:59 -06:00
|
|
|
/*
|
2019-03-28 09:46:41 -05:00
|
|
|
Copyright 2019 Equinor.
|
2016-11-16 09:12:59 -06:00
|
|
|
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
|
2016-11-16 09:12:59 -06:00
|
|
|
#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>
|
2016-11-16 09:12:59 -06:00
|
|
|
|
|
|
|
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
|
|
|
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
2019-10-01 17:17:14 -05:00
|
|
|
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
2016-11-16 09:12:59 -06:00
|
|
|
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
|
|
|
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
2019-10-01 17:17:14 -05:00
|
|
|
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
2016-11-16 09:12:59 -06:00
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
#include <opm/output/eclipse/VectorItems/tabdims.hpp>
|
2018-09-13 10:25:33 -05:00
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::TabDims::index;
|
2016-11-16 09:12:59 -06:00
|
|
|
|
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{
|
2019-01-03 11:05:19 -06:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
return {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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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{
|
2019-01-03 11:05:19 -06:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
return {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, 4.648760330578510e-08, 0, 7.747933884297517e-07, 0,
|
|
|
|
2.40e-01, 1.860000000000000e-07, 0, 2.325206611570248e-06, 0,
|
|
|
|
3.00e-01, 4.183884297520660e-07, 0, 3.873140495867767e-06, 0,
|
|
|
|
3.60e-01, 7.438016528925620e-07, 0, 5.423553719008267e-06, 0,
|
|
|
|
4.20e-01, 1.162190082644630e-06, 0, 6.973140495867802e-06, 0,
|
|
|
|
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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} // 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{
|
2019-01-03 11:05:19 -06:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
return {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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<double> expect_SWFN()
|
|
|
|
{
|
|
|
|
return makeTable(5, {
|
|
|
|
1.20e-01, 0, 0, 1.000000000000000e+20, 1.0e+20,
|
|
|
|
1.80e-01, 4.648760330578510e-08, 0, 7.747933884297517e-07, 0,
|
|
|
|
2.40e-01, 1.860000000000000e-07, 0, 2.325206611570248e-06, 0,
|
|
|
|
3.00e-01, 4.183884297520660e-07, 0, 3.873140495867767e-06, 0,
|
|
|
|
3.60e-01, 7.438016528925620e-07, 0, 5.423553719008267e-06, 0,
|
|
|
|
4.20e-01, 1.162190082644630e-06, 0, 6.973140495867802e-06, 0,
|
|
|
|
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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} // 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{
|
2019-01-03 11:05:19 -06:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
return {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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} // 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{
|
2019-01-03 11:05:19 -06:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
return {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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} // 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
|
2016-11-16 09:12:59 -06:00
|
|
|
|
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 /
|
2016-11-16 09:12:59 -06:00
|
|
|
|
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{
|
2019-01-03 11:05:19 -06:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
return {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()
|
|
|
|
{
|
|
|
|
// 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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} // 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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
|
|
|
{
|
2019-10-02 16:11:56 -05:00
|
|
|
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 ()
|
2019-03-28 09:46:41 -05:00
|
|
|
|
|
|
|
// #####################################################################
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE (PVTTables)
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
Opm::EclipseState parse(const std::string& rspec,
|
|
|
|
const std::string& props)
|
|
|
|
{
|
|
|
|
return {
|
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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
|
2019-10-02 16:11:56 -05:00
|
|
|
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(), 2);
|
|
|
|
BOOST_CHECK_EQUAL(tabd.getNumPressureNodes(), 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 (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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
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(), 2);
|
|
|
|
BOOST_CHECK_EQUAL(tabd.getNumRSNodes(), 1);
|
|
|
|
BOOST_CHECK_EQUAL(tabd.getNumPressureNodes(), 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 ()
|
|
|
|
|
|
|
|
// =====================================================================
|
|
|
|
|
2019-03-28 09:46:41 -05:00
|
|
|
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();
|
|
|
|
|
2019-10-02 16:11:56 -05:00
|
|
|
const auto ibpvtw = tabdims[ Ix::PvtwStart ] - 1;
|
|
|
|
const auto ntpvtw = tabdims[ Ix::NumPvtwTables ];
|
2019-03-28 09:46:41 -05:00
|
|
|
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 ()
|
2019-10-21 00:16:30 -05:00
|
|
|
|
|
|
|
// =====================================================================
|
|
|
|
|
|
|
|
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
|