Table Output: Add Facility to Simplify Indexing Details

This commit introduces a new helper class, LinearisedOutputTable,
that is oriented towards managing tabular data such as the PVT or
saturation functions in an ECL result set (typically, .INIT file).
The class knows about row padding and the column oriented nature of
Fortran-like tables.

While here, and in anticipation of adding output of tabulated
saturation functions, also provide a mechanism for calculating
slopes of piecewise linear interpolants.  The ECL format stipulates
that function derivatives be output along with the actual table
data for most functions.
This commit is contained in:
Bård Skaflestad 2017-11-03 00:32:05 -05:00
parent e26d647252
commit e2bf7bf699
4 changed files with 923 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# Editor autosave files
*~
*.swp
# Compiled Object files
*.slo
*.lo
*.o
# Compiled Dynamic libraries
*.so
*.dylib
# Compiled Static libraries
*.lai
*.la
*.a
# Mac OS X debug info
*.dSYM
# emacs directory setting:
.dir-locals.el

View File

@ -0,0 +1,168 @@
/*
Copyright 2017 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/>.
*/
#ifndef LINEARISED_OUTPUT_TABLE_HPP_INCLUDED
#define LINEARISED_OUTPUT_TABLE_HPP_INCLUDED
#include <cstddef>
#include <vector>
namespace Opm {
/// Manage tables of column data, possibly with sub-tables, all with
/// equal number of rows (i.e., with padding), and possibly with
/// multiple tables pertaining to multiple subsets (i.e., cell regions).
///
/// Mainly intended for use with the output facility for tabular data.
class LinearisedOutputTable
{
public:
/// Constructor.
///
/// \param[in] numTables Number of tables managed by internal
/// buffer. Typically corresponds to maximum value of a region
/// ID vector such as SATNUM, IMBNUM, or PVTNUM.
///
/// \param[in] numPrimary Number of primary look-up keys for the
/// tabular data managed by the internal buffer. Mostly relevant
/// (i.e., greater than one) for miscible oil ("PVTO") or
/// miscible gas ("PVTG") tables and typically corresponds to the
/// number of Rs/Rv entries from the TABDIMS keyword.
///
/// \param[in] numRows Number of rows in each sub-table
/// corresponding to a single primary look-up key. Typically the
/// number of nodes (e.g., NSSFUN or NPPVT) of the corresponding
/// input keyword.
///
/// \param[in] numCols Number of columns in each sub-table (and main
/// table). Typically 5.
LinearisedOutputTable(const std::size_t numTables,
const std::size_t numPrimary,
const std::size_t numRows,
const std::size_t numCols);
/// Retrieve iterator to start of \c numRows (contiguous) column
/// elements of a particular sub-table of a particular main table.
///
/// \param[in] tableID Numeric ID of main table for which to
/// retrieve a column. Must be strictly less than \c numTables
/// constructor argument.
///
/// \param[in] primID Numeric ID of primary look-up key (sub-table)
/// for which to retrieve a column. Must be strictly less than
/// \c numPrimary constructor argument.
///
/// \param[in] colID Numeric ID of column to be retrieved from
/// particular sub-table of particular main table. Must be
/// strictly less than \c numCols constructor argument.
///
/// \return Iterator to start of contiguous column elements.
std::vector<double>::iterator
column(const std::size_t tableID,
const std::size_t primID,
const std::size_t colID);
/// Read-only access to internal data buffer.
///
/// Mostly to support outputting all table data to external storage.
const std::vector<double>& getData() const;
/// Destructive access to internal data buffer.
///
/// Mostly to support outputting all table data to external storage.
///
/// \return \code std::move() \endcode of the internal data buffer.
std::vector<double> getDataDestructively();
private:
/// Internal buffer for tabular data.
std::vector<double> data_;
/// Number of tables managed by \c data_.
std::size_t numTables_;
/// Number of primary look-up keys/sub-tables in \c data_.
std::size_t numPrimary_;
/// Number of rows per sub-table in \c data_.
std::size_t numRows_;
};
/// Apply piecewise linear differentiation (i.e., compute slopes) on a
/// set of dependent variables in a linearised output table.
///
namespace DifferentiateOutputTable {
/// Columnar data differentantiation table request.
///
/// Refers to the sub-table with a specific primary ID within a
/// specific table of a \c LinearisedOutputTable.
struct Descriptor {
/// Table ID--usually corresponds to the region ID of a
/// tabulated function pertaining to a specific region of a
/// simulation model.
std::size_t tableID{ 0 };
/// Primary ID--nontrivial (\c != 0) only for miscible PVT
/// tables for oil or gas in which case this entry refers to a
/// particular dissolved gas-oil ratio (Rs) or gas pressure
/// (Pg) node.
std::size_t primID{ 0 };
/// Number of active rows in this subtable.
std::size_t numActRows{ 0 };
};
/// Apply piecewise linear differentiation (i.e., compute slopes) on
/// a set of dependent variables in a linearised output table.
///
/// Assumes that the independent variable is stored in the first
/// column (column ID zero).
///
/// \param[in] numDependent Number of dependent variables. Usually
/// one or two. Dependent variables are assumed to be stored in
/// columns one through \p numDependent.
///
/// \param[in] desc Columnar data differentantiation table request.
/// Must refer to a particular sub-table of the linearised output
/// table.
///
/// \param[in,out] table Linearised output table. On input, column
/// zero contains the independent variable in each of \code
/// numActRows.size() \endcode sub-tables and columns one through
/// \p numDependent contain the dependent variables. On output,
/// columns \code numDependent + 1 \endcode through \code 2 *
/// numDependent \endcode contain the slopes of the dependent
/// variables.
///
/// In partcular, column \code numDependent + j \endcode for
/// \code j = 1..numDependent \endcode contains the derivatives
/// of column \c j with respect to column zero. We define the
/// slopes as
/// \code
/// s(i,j) = (c(i + 1, j) - c(i,j)) / (c(i + 1, 0) - c(i,0))
/// \endcode
/// for all \code i = 0 .. numActRows[k] - 2 \endcode (in table
/// \p k).
void calcSlopes(const std::size_t numDependent,
const Descriptor& desc,
LinearisedOutputTable& table);
} // DifferentiateOutputTable
} // Opm
#endif // LINEARISED_OUTPUT_TABLE_HPP_INCLUDED

View File

@ -0,0 +1,101 @@
#include <opm/output/eclipse/LinearisedOutputTable.hpp>
#include <algorithm>
#include <cmath>
#include <cassert>
#include <utility>
Opm::LinearisedOutputTable::
LinearisedOutputTable(const std::size_t numTables,
const std::size_t numPrimary,
const std::size_t numRows,
const std::size_t numCols)
: data_ (numTables * numPrimary * numRows * numCols, 1.0e20)
, numTables_ (numTables)
, numPrimary_(numPrimary)
, numRows_ (numRows)
{}
std::vector<double>::iterator
Opm::LinearisedOutputTable::column(const std::size_t tableID,
const std::size_t primID,
const std::size_t colID)
{
// Table format: numRows_ * numPrimary_ * numTables_ values for first
// column (ID == 0), followed by same number of entries for second
// column &c.
const auto offset =
0 + this->numRows_*(primID + this->numPrimary_*(tableID + this->numTables_*colID));
assert (offset + this->numRows_ <= this->data_.size());
return this->data_.begin() + offset;
}
const std::vector<double>&
Opm::LinearisedOutputTable::getData() const
{
return this->data_;
}
std::vector<double>
Opm::LinearisedOutputTable::getDataDestructively()
{
return std::move(this->data_);
}
// ---------------------------------------------------------------------
void
Opm::DifferentiateOutputTable::calcSlopes(const std::size_t nDep,
const Descriptor& desc,
LinearisedOutputTable& table)
{
if ((nDep == 0) || (desc.numActRows < 2)) {
// No dependent columns or too few rows to compute any derivatives.
// Likely to be user error. Can't do anything here.
return;
}
auto x = table.column(desc.tableID, desc.primID, 0);
using colIT = decltype(x);
auto y = std::vector<colIT>{}; y .reserve(nDep);
auto dy = std::vector<colIT>{}; dy.reserve(nDep);
auto y0 = std::vector<double>(nDep);
auto y1 = y0;
for (auto j = 0*nDep; j < nDep; ++j) {
y .push_back(table.column(desc.tableID, desc.primID, j + 1 + 0*nDep));
dy.push_back(table.column(desc.tableID, desc.primID, j + 1 + 1*nDep));
y1[j] = *y.back(); ++y.back();
}
using std::swap;
auto x1 = *x; ++x; auto x0 = 0 * x1;
// Recall: Number of slope intervals one less than number of active
// table rows.
for (auto n = desc.numActRows - 1, i = 0*n; i < n; ++i) {
// Save previous right-hand point as this left-hand point, clear
// space for new right-hand point.
swap(x0, x1); x1 = *x; ++x;
swap(y0, y1);
const auto dx = x1 - x0;
for (auto j = 0*nDep; j < nDep; ++j) {
y1[j] = *y[j];
const auto delta = y1[j] - y0[j];
// Choice for dx==0 somewhat debatable.
*dy[j] = (std::abs(dx) > 0.0) ? (delta / dx) : 0.0;
// Advance column iterators;
++y[j]; ++dy[j];
}
}
}

View File

@ -0,0 +1,631 @@
/*
Copyright 2017 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/>.
*/
#if defined(HAVE_CONFIG_H)
#include <config.h>
#endif // defined(HAVE_CONFIG_H)
#if HAVE_DYNAMIC_BOOST_TEST
#define BOOST_TEST_DYN_LINK
#endif
#define NVERBOSE
#define BOOST_TEST_MODULE TEST_LINEARISEDOUTPUTTABLE
#include <boost/test/unit_test.hpp>
#include <opm/output/eclipse/LinearisedOutputTable.hpp>
#include <cstddef>
#include <initializer_list>
#include <vector>
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;
}
std::vector<double> spe1_swof()
{
return makeTable(4, {
0.12, 0, 1, 0, // 0
0.18, 4.64876033057851E-008, 1, 0, // 1
0.24, 0.000000186, 0.997, 0, // 2
0.3 , 4.18388429752066E-007, 0.98, 0, // 3
0.36, 7.43801652892562E-007, 0.7, 0, // 4
0.42, 1.16219008264463E-006, 0.35, 0, // 5
0.48, 1.67355371900826E-006, 0.2, 0, // 6
0.54, 2.27789256198347E-006, 0.09, 0, // 7
0.6 , 2.97520661157025E-006, 0.021, 0, // 8
0.66, 3.7654958677686E-006, 0.01, 0, // 9
0.72, 4.64876033057851E-006, 0.001, 0, // 10
0.78, 0.000005625, 0.0001, 0, // 11
0.84, 6.69421487603306E-006, 0, 0, // 12
0.91, 8.05914256198347E-006, 0, 0, // 13
1 , 0.00001, 0, 0, }); // 14
}
std::vector<double> norne_pvto_1_1_incl_der()
{
return makeTable(5, {
5.00e+01, 9.040365230755323e-01, 7.661326466741799e-01, 2.000000000000000e+20, 2.000000000000000e+20,
7.50e+01, 9.077375549181221e-01, 7.279370929575959e-01, 1.480412737035941e-04, -1.527822148663360e-03,
1.00e+02, 9.112115468727220e-01, 6.929365375457962e-01, 1.389596781839941e-04, -1.400022216471988e-03,
1.25e+02, 9.144863787253888e-01, 6.607560539923331e-01, 1.309932741066744e-04, -1.287219342138526e-03,
1.50e+02, 9.175658812302724e-01, 6.314975094496025e-01, 1.231801001953414e-04, -1.170341781709223e-03,
});
}
std::vector<double> norne_pvto_1_2_incl_der()
{
return makeTable(5, {
7.00e+01, 8.887150957146157e-01, 8.336914593945738e-01, -2.015977284331128e-03, 8.889317463209720e-03,
9.50e+01, 8.924826189009969e-01, 7.940236822962605e-01, 1.507009274552473e-04, -1.586711083932530e-03,
1.20e+02, 8.960252320705352e-01, 7.580585719716880e-01, 1.417045267815320e-04, -1.438604412982900e-03,
1.45e+02, 8.993533649306149e-01, 7.247005358022682e-01, 1.331253144031885e-04, -1.334321446776792e-03,
1.70e+02, 9.024944947835819e-01, 6.942265344489091e-01, 1.256451941186798e-04, -1.218960054134364e-03,
});
}
std::vector<double> norne_pvto_1_3_incl_der()
{
return makeTable(5, {
9.00e+01, 8.736829229935872e-01, 9.063100860929328e-01, -1.922272726474237e-03, 9.286269398767148e-03,
1.15e+02, 8.775085776463464e-01, 8.653930746019195e-01, 1.530261861103677e-04, -1.636680459640534e-03,
1.40e+02, 8.811038468993955e-01, 8.281051192663491e-01, 1.438107701219638e-04, -1.491518213422815e-03,
1.65e+02, 8.844861135680170e-01, 7.932610884018090e-01, 1.352906667448606e-04, -1.393761234581605e-03,
1.90e+02, 8.876816418559648e-01, 7.613050101680658e-01, 1.278211315179112e-04, -1.278243129349725e-03,
});
}
std::vector<double> norne_sgfn_incl_der()
{
return makeTable(5, {
0, 0, 0, 0, 0,
5.000000000000000e-02, 1.655000000000000e-03, 0, 3.310000000000000e-02, 0,
1.000000000000000e-01, 6.913000000000000e-03, 0, 1.051600000000000e-01, 0,
1.500000000000000e-01, 1.621300000000000e-02, 0, 1.860000000000001e-01, 0,
2.000000000000000e-01, 2.999000000000000e-02, 0, 2.755399999999998e-01, 0,
2.500000000000000e-01, 4.865500000000000e-02, 0, 3.733000000000000e-01, 0,
3.000000000000000e-01, 7.257300000000000e-02, 0, 4.783600000000001e-01, 0,
3.500000000000000e-01, 1.020460000000000e-01, 0, 5.894600000000001e-01, 0,
4.000000000000000e-01, 1.372870000000000e-01, 0, 7.048199999999992e-01, 0,
4.500000000000000e-01, 1.784020000000000e-01, 0, 8.223000000000005e-01, 0,
5.000000000000000e-01, 2.253680000000000e-01, 0, 9.393200000000004e-01, 0,
5.500000000000000e-01, 2.780300000000000e-01, 0, 1.053239999999999e+00, 0,
6.000000000000000e-01, 3.360930000000000e-01, 0, 1.161260000000001e+00, 0,
6.500000000000000e-01, 3.991350000000000e-01, 0, 1.260840000000000e+00, 0,
7.000000000000000e-01, 4.666310000000000e-01, 0, 1.349920000000002e+00, 0,
7.500000000000000e-01, 5.380000000000000e-01, 0, 1.427379999999999e+00, 0,
8.000000000000000e-01, 6.126650000000000e-01, 0, 1.493299999999998e+00, 0,
8.500000000000000e-01, 6.901690000000000e-01, 0, 1.550080000000002e+00, 0,
9.000000000000000e-01, 7.703950000000001e-01, 0, 1.604519999999999e+00, 0,
9.500000000000000e-01, 8.542180000000000e-01, 0, 1.676460000000002e+00, 0,
9.999000000000000e-01, 9.499000000000000e-01, 0, 1.917474949899796e+00, 0,
1.000000000000000e+00, 9.500000000000000e-01, 0, 1.000000000000000e+00, 0,
});
}
} // Anonymous
// ---------------------------------------------------------------------
// Saturation Functions
BOOST_AUTO_TEST_SUITE (Tabulated_Functions)
BOOST_AUTO_TEST_CASE (SGFN)
{
const auto inputData = norne_sgfn_incl_der();
const auto tableRows = inputData.size() / 5;
const auto numTables = std::size_t{1};
const auto numPrimary = std::size_t{1};
const auto numRows = std::size_t{30};
const auto numCols = std::size_t{5};
auto sgfn = ::Opm::LinearisedOutputTable {
numTables, numPrimary, numRows, numCols
};
// Sg
{
const auto tableID = std::size_t{0};
const auto primID = std::size_t{0};
const auto colID = std::size_t{0};
std::copy(inputData.begin() + 0*tableRows,
inputData.begin() + 1*tableRows,
sgfn.column(tableID, primID, colID));
}
// Krg
{
const auto tableID = std::size_t{0};
const auto primID = std::size_t{0};
const auto colID = std::size_t{1};
std::copy(inputData.begin() + 1*tableRows,
inputData.begin() + 2*tableRows,
sgfn.column(tableID, primID, colID));
}
// Pcgo
{
const auto tableID = std::size_t{0};
const auto primID = std::size_t{0};
const auto colID = std::size_t{2};
std::copy(inputData.begin() + 2*tableRows,
inputData.begin() + 3*tableRows,
sgfn.column(tableID, primID, colID));
}
// d[Krg]/dSg
{
const auto tableID = std::size_t{0};
const auto primID = std::size_t{0};
const auto colID = std::size_t{3};
std::copy(inputData.begin() + 3*tableRows,
inputData.begin() + 4*tableRows,
sgfn.column(tableID, primID, colID));
}
// d[Pcgo]/dSg
{
const auto tableID = std::size_t{0};
const auto primID = std::size_t{0};
const auto colID = std::size_t{4};
std::copy(inputData.begin() + 4*tableRows,
inputData.begin() + 5*tableRows,
sgfn.column(tableID, primID, colID));
}
const auto expect = makeTable(5,
{
0, 0, 0, 0, 0,
5.000e-02, 1.65500e-03, 0, 3.310000000000000e-02, 0,
1.000e-01, 6.91300e-03, 0, 1.051600000000000e-01, 0,
1.500e-01, 1.62130e-02, 0, 1.860000000000001e-01, 0,
2.000e-01, 2.99900e-02, 0, 2.755399999999998e-01, 0,
2.500e-01, 4.86550e-02, 0, 3.733000000000000e-01, 0,
3.000e-01, 7.25730e-02, 0, 4.783600000000001e-01, 0,
3.500e-01, 1.02046e-01, 0, 5.894600000000001e-01, 0,
4.000e-01, 1.37287e-01, 0, 7.048199999999992e-01, 0,
4.500e-01, 1.78402e-01, 0, 8.223000000000005e-01, 0,
5.000e-01, 2.25368e-01, 0, 9.393200000000004e-01, 0,
5.500e-01, 2.78030e-01, 0, 1.053239999999999e+00, 0,
6.000e-01, 3.36093e-01, 0, 1.161260000000001e+00, 0,
6.500e-01, 3.99135e-01, 0, 1.260840000000000e+00, 0,
7.000e-01, 4.66631e-01, 0, 1.349920000000002e+00, 0,
7.500e-01, 5.38000e-01, 0, 1.427379999999999e+00, 0,
8.000e-01, 6.12665e-01, 0, 1.493299999999998e+00, 0,
8.500e-01, 6.90169e-01, 0, 1.550080000000002e+00, 0,
9.000e-01, 7.70395e-01, 0, 1.604519999999999e+00, 0,
9.500e-01, 8.54218e-01, 0, 1.676460000000002e+00, 0,
9.999e-01, 9.49900e-01, 0, 1.917474949899796e+00, 0,
1.000e+00, 9.50000e-01, 0, 1.000000000000000e+00, 0,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
1.000e+20, 1.00000e+20, 1.e+20, 1.000000000000000e+20, 1.e+20,
});
check_is_close(sgfn.getData(), expect);
}
// ---------------------------------------------------------------------
// PVT
BOOST_AUTO_TEST_CASE (PVTO)
{
const auto inputData = std::vector< std::vector<double> >
{
norne_pvto_1_1_incl_der(),
norne_pvto_1_2_incl_der(),
norne_pvto_1_3_incl_der(),
};
const auto numTables = std::size_t{1};
const auto numPrimary = std::size_t{5};
const auto numRows = std::size_t{8};
const auto numCols = std::size_t{5};
auto pvto = ::Opm::LinearisedOutputTable {
numTables, numPrimary, numRows, numCols
};
{
auto primID = std::size_t{0};
for (const auto& subTab : inputData) {
const auto tableRows = subTab.size() / numCols;
// Po
{
const auto tableID = std::size_t{0};
const auto colID = std::size_t{0};
std::copy(subTab.begin() + 0*tableRows,
subTab.begin() + 1*tableRows,
pvto.column(tableID, primID, colID));
}
// 1/Bo
{
const auto tableID = std::size_t{0};
const auto colID = std::size_t{1};
std::copy(subTab.begin() + 1*tableRows,
subTab.begin() + 2*tableRows,
pvto.column(tableID, primID, colID));
}
// 1/(Bo*mu_o)
{
const auto tableID = std::size_t{0};
const auto colID = std::size_t{2};
std::copy(subTab.begin() + 2*tableRows,
subTab.begin() + 3*tableRows,
pvto.column(tableID, primID, colID));
}
// d[1/Bo]/dPo
{
const auto tableID = std::size_t{0};
const auto colID = std::size_t{3};
std::copy(subTab.begin() + 3*tableRows,
subTab.begin() + 4*tableRows,
pvto.column(tableID, primID, colID));
}
// d[1/(Bo*mu_o)]/dPo
{
const auto tableID = std::size_t{0};
const auto colID = std::size_t{4};
std::copy(subTab.begin() + 4*tableRows,
subTab.begin() + 5*tableRows,
pvto.column(tableID, primID, colID));
}
primID += 1;
}
}
const auto expect = makeTable(5, {
5.000000000000000e+01, 9.040365230755323e-01, 7.661326466741799e-01, 2.000000000000000e+20, 2.000000000000000e+20,
7.500000000000000e+01, 9.077375549181221e-01, 7.279370929575959e-01, 1.480412737035941e-04, -1.527822148663360e-03,
1.000000000000000e+02, 9.112115468727220e-01, 6.929365375457962e-01, 1.389596781839941e-04, -1.400022216471988e-03,
1.250000000000000e+02, 9.144863787253888e-01, 6.607560539923331e-01, 1.309932741066744e-04, -1.287219342138526e-03,
1.500000000000000e+02, 9.175658812302724e-01, 6.314975094496025e-01, 1.231801001953414e-04, -1.170341781709223e-03,
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,
7.000000000000000e+01, 8.887150957146157e-01, 8.336914593945738e-01, -2.015977284331128e-03, 8.889317463209720e-03,
9.500000000000000e+01, 8.924826189009969e-01, 7.940236822962605e-01, 1.507009274552473e-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.331253144031885e-04, -1.334321446776792e-03,
1.700000000000000e+02, 9.024944947835819e-01, 6.942265344489091e-01, 1.256451941186798e-04, -1.218960054134364e-03,
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,
9.000000000000000e+01, 8.736829229935872e-01, 9.063100860929328e-01, -1.922272726474237e-03, 9.286269398767148e-03,
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.491518213422815e-03,
1.650000000000000e+02, 8.844861135680170e-01, 7.932610884018090e-01, 1.352906667448606e-04, -1.393761234581605e-03,
1.900000000000000e+02, 8.876816418559648e-01, 7.613050101680658e-01, 1.278211315179112e-04, -1.278243129349725e-03,
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,
});
check_is_close(pvto.getData(), expect);
}
BOOST_AUTO_TEST_SUITE_END ()
// ---------------------------------------------------------------------
// Derivatives of tabulated, piecewise linear functions
BOOST_AUTO_TEST_SUITE (Calculated_Slopes)
BOOST_AUTO_TEST_CASE (No_Derivatives)
{
auto descr = ::Opm::DifferentiateOutputTable::Descriptor{};
descr.tableID = 0;
descr.primID = 0;
descr.numActRows = 1;
auto linTable = ::Opm::LinearisedOutputTable {
1, 1, 3, 3 // Single table, one prim. key, 3 declared rows, 3 cols.
};
{
auto x = 0.0;
auto y = x;
*linTable.column(descr.tableID, descr.primID, 0) = x;
*linTable.column(descr.tableID, descr.primID, 1) = y;
}
// Argument dependent symbol lookup.
calcSlopes(1, descr, linTable); // One dependent column.
// Too few active rows (< 2). Leave derivatives alone
const auto expect = makeTable(3, {
0, 0, 1.e+20,
1.e+20, 1.e+20, 1.e+20,
1.e+20, 1.e+20, 1.e+20,
});
check_is_close(linTable.getData(), expect);
}
BOOST_AUTO_TEST_CASE (Constant_Function)
{
auto descr = ::Opm::DifferentiateOutputTable::Descriptor{};
descr.tableID = 0;
descr.primID = 0;
descr.numActRows = 11;
auto linTable = ::Opm::LinearisedOutputTable {
1, 1, 15, 3 // Single table, one prim. key, 15 declared rows, 3 cols.
};
{
auto x = std::vector<double> {
0.0, 0.1, 0.2, 0.3, 0.4,
0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
auto y = std::vector<double>(x.size(), 1.25);
std::copy(x.begin(), x.end(),
linTable.column(descr.tableID, descr.primID, 0));
std::copy(y.begin(), y.end(),
linTable.column(descr.tableID, descr.primID, 1));
}
// Argument dependent symbol lookup.
calcSlopes(1, descr, linTable); // One dependent column.
// Compute slopes for all intervals, store in left end point.
// Non-active rows left at defaulted values.
const auto expect = makeTable(3, {
0, 1.25e+00, 0,
1.0e-01, 1.25e+00, 0,
2.0e-01, 1.25e+00, 0,
3.0e-01, 1.25e+00, 0,
4.0e-01, 1.25e+00, 0,
5.0e-01, 1.25e+00, 0,
6.0e-01, 1.25e+00, 0,
7.0e-01, 1.25e+00, 0,
8.0e-01, 1.25e+00, 0,
9.0e-01, 1.25e+00, 0,
1.0e+00, 1.25e+00, 1.0e+20,
1.0e+20, 1.00e+20, 1.0e+20,
1.0e+20, 1.00e+20, 1.0e+20,
1.0e+20, 1.00e+20, 1.0e+20,
1.0e+20, 1.00e+20, 1.0e+20,
});
check_is_close(linTable.getData(), expect);
}
BOOST_AUTO_TEST_CASE (Linear_Function)
{
auto descr = ::Opm::DifferentiateOutputTable::Descriptor{};
descr.tableID = 0;
descr.primID = 0;
descr.numActRows = 11;
auto linTable = ::Opm::LinearisedOutputTable {
1, 1, 11, 3 // Single table, one prim. key, 11 declared rows, 3 cols.
};
{
auto x = std::vector<double> {
0.0, 0.1, 0.2, 0.3, 0.4,
0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
auto y = x;
std::copy(x.begin(), x.end(),
linTable.column(descr.tableID, descr.primID, 0));
std::copy(y.begin(), y.end(),
linTable.column(descr.tableID, descr.primID, 1));
}
// Argument dependent symbol lookup.
calcSlopes(1, descr, linTable); // One dependent column.
// Compute slopes for all intervals, store in left end point.
const auto expect = makeTable(3, {
0, 0, 1.0,
1.0e-01, 1.0e-01, 1.0,
2.0e-01, 2.0e-01, 1.0,
3.0e-01, 3.0e-01, 1.0,
4.0e-01, 4.0e-01, 1.0,
5.0e-01, 5.0e-01, 1.0,
6.0e-01, 6.0e-01, 1.0,
7.0e-01, 7.0e-01, 1.0,
8.0e-01, 8.0e-01, 1.0,
9.0e-01, 9.0e-01, 1.0,
1.0e+00, 1.0e+00, 1.0e+20,
});
check_is_close(linTable.getData(), expect);
}
BOOST_AUTO_TEST_CASE (Nonlinear_Functions)
{
auto descr = ::Opm::DifferentiateOutputTable::Descriptor{};
descr.tableID = 0;
descr.primID = 0;
descr.numActRows = 11;
auto linTable = ::Opm::LinearisedOutputTable {
1, 1, 15, 7 // Single table, one prim. key, 15 declared rows, 7 cols.
};
{
const auto x = std::vector<double> {
0.0, 0.1, 0.2, 0.3, 0.4,
0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
// sin(2*pi * x)
const auto s = std::vector<double> {
0,
5.877852522924731e-01,
9.510565162951535e-01,
9.510565162951536e-01,
5.877852522924732e-01,
1.224646799147353e-16,
-5.877852522924730e-01,
-9.510565162951535e-01,
-9.510565162951536e-01,
-5.877852522924734e-01,
-2.449293598294706e-16,
};
// cos(4*pi * x)^2
const auto c = std::vector<double> {
1.000000000000000e+00,
9.549150281252630e-02,
6.545084971874736e-01,
6.545084971874737e-01,
9.549150281252616e-02,
1.000000000000000e+00,
9.549150281252648e-02,
6.545084971874734e-01,
6.545084971874742e-01,
9.549150281252602e-02,
1.000000000000000e+00,
};
// exp(-x) / (1 + x)
const auto f = std::vector<double> {
1.000000000000000e+00,
8.225794709417813e-01,
6.822756275649848e-01,
5.698601697551676e-01,
4.788000328825995e-01,
4.043537731417556e-01,
3.430072725587666e-01,
2.921090022302409e-01,
2.496272022873453e-01,
2.139840314424206e-01,
1.839397205857212e-01,
};
std::copy(x.begin(), x.end(),
linTable.column(descr.tableID, descr.primID, 0));
std::copy(s.begin(), s.end(),
linTable.column(descr.tableID, descr.primID, 1));
std::copy(c.begin(), c.end(),
linTable.column(descr.tableID, descr.primID, 2));
std::copy(f.begin(), f.end(),
linTable.column(descr.tableID, descr.primID, 3));
}
// Argument dependent symbol lookup.
calcSlopes(3, descr, linTable); // Three dependent columns.
// Compute slopes for all intervals, store in left end point.
const auto expect = makeTable(7, {
0, 0, 1.000000000000000e+00, 1.000000000000000e+00, 5.877852522924731e+00, -9.045084971874736e+00, -1.774205290582187e+00,
1.0e-01, 5.877852522924731e-01, 9.549150281252630e-02, 8.225794709417813e-01, 3.632712640026804e+00, 5.590169943749473e+00, -1.403038433767965e+00,
2.0e-01, 9.510565162951535e-01, 6.545084971874736e-01, 6.822756275649848e-01, 1.110223024625157e-15, 1.110223024625157e-15, -1.124154578098172e+00,
3.0e-01, 9.510565162951536e-01, 6.545084971874737e-01, 5.698601697551676e-01, -3.632712640026803e+00, -5.590169943749474e+00, -9.106013687256805e-01,
4.0e-01, 5.877852522924732e-01, 9.549150281252616e-02, 4.788000328825995e-01, -5.877852522924733e+00, 9.045084971874740e+00, -7.444625974084391e-01,
5.0e-01, 1.224646799147353e-16, 1.000000000000000e+00, 4.043537731417556e-01, -5.877852522924733e+00, -9.045084971874736e+00, -6.134650058298908e-01,
6.0e-01, -5.877852522924730e-01, 9.549150281252648e-02, 3.430072725587666e-01, -3.632712640026806e+00, 5.590169943749470e+00, -5.089827032852569e-01,
7.0e-01, -9.510565162951535e-01, 6.545084971874734e-01, 2.921090022302409e-01, -1.110223024625156e-15, 7.771561172376089e-15, -4.248179994289554e-01,
8.0e-01, -9.510565162951536e-01, 6.545084971874742e-01, 2.496272022873453e-01, 3.632712640026804e+00, -5.590169943749483e+00, -3.564317084492472e-01,
9.0e-01, -5.877852522924734e-01, 9.549150281252602e-02, 2.139840314424206e-01, 5.877852522924733e+00, 9.045084971874742e+00, -3.004431085669943e-01,
1.0e+00, -2.449293598294706e-16, 1.000000000000000e+00, 1.839397205857212e-01, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
1.0e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20, 1.000000000000000e+20,
});
check_is_close(linTable.getData(), expect);
}
BOOST_AUTO_TEST_SUITE_END ()