Files
opm-common/tests/test_2dtables.cpp
Andreas Lauser a6499a01aa fix most of the warnings enabled by masochists
most of these people like to inflict pain on themselfs (i.e., warnings
in their own code), but they usually don't like if pain is inflicted
on them by others (i.e., warnings produced by external code which they
use). This patch should make these kinds of people happy. I'm not
really sure if the code is easier to understand with this, but at
least clang does not complain for most of the warnings of
"-Weverything" anymore.
2015-09-23 12:36:52 +02:00

379 lines
12 KiB
C++

// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
Copyright (C) 2014 by Andreas Lauser
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/
/*!
* \file
*
* \brief This is the unit test for the 2D tabulation classes.
*
* I.e., for the UniformTabulated2DFunction and UniformXTabulated2DFunction classes.
*/
#include "config.h"
#include <opm/material/common/UniformXTabulated2DFunction.hpp>
#include <opm/material/common/UniformTabulated2DFunction.hpp>
#include <memory>
#include <cmath>
#include <iostream>
typedef double Scalar;
// prototypes
Scalar testFn1(Scalar x, Scalar y);
Scalar testFn2(Scalar x, Scalar y);
Scalar testFn3(Scalar x, Scalar y);
Scalar testFn1(Scalar x, Scalar /* y */)
{ return x; }
Scalar testFn2(Scalar /* x */, Scalar y)
{ return y; }
Scalar testFn3(Scalar x, Scalar y)
{ return x*y; }
template <class Fn>
std::shared_ptr<Opm::UniformTabulated2DFunction<Scalar> >
createUniformTabulatedFunction(Fn &f)
{
Scalar xMin = -2.0;
Scalar xMax = 3.0;
unsigned m = 50;
Scalar yMin = -1/2.0;
Scalar yMax = 1/3.0;
unsigned n = 40;
auto tab = std::make_shared<Opm::UniformTabulated2DFunction<Scalar>>(
xMin, xMax, m,
yMin, yMax, n);
for (unsigned i = 0; i < m; ++i) {
Scalar x = xMin + Scalar(i)/(m - 1) * (xMax - xMin);
for (unsigned j = 0; j < n; ++j) {
Scalar y = yMin + Scalar(j)/(n - 1) * (yMax - yMin);
tab->setSamplePoint(i, j, f(x, y));
}
}
return tab;
}
template <class Fn>
std::shared_ptr<Opm::UniformXTabulated2DFunction<Scalar> >
createUniformXTabulatedFunction(Fn &f)
{
Scalar xMin = -2.0;
Scalar xMax = 3.0;
unsigned m = 50;
Scalar yMin = -1/2.0;
Scalar yMax = 1/3.0;
unsigned n = 40;
auto tab = std::make_shared<Opm::UniformXTabulated2DFunction<Scalar>>();
for (unsigned i = 0; i < m; ++i) {
Scalar x = xMin + Scalar(i)/(m - 1) * (xMax - xMin);
tab->appendXPos(x);
for (unsigned j = 0; j < n; ++j) {
Scalar y = yMin + Scalar(j)/(n -1) * (yMax - yMin);
tab->appendSamplePoint(i, y, f(x, y));
}
}
return tab;
}
template <class Fn>
std::shared_ptr<Opm::UniformXTabulated2DFunction<Scalar> >
createUniformXTabulatedFunction2(Fn &f)
{
Scalar xMin = -2.0;
Scalar xMax = 3.0;
Scalar m = 50;
auto tab = std::make_shared<Opm::UniformXTabulated2DFunction<Scalar>>();
for (unsigned i = 0; i < m; ++i) {
Scalar x = xMin + Scalar(i)/(m - 1) * (xMax - xMin);
tab->appendXPos(x);
Scalar n = i + 10;
Scalar yMin = - (x + 1);
Scalar yMax = (x + 1);
for (unsigned j = 0; j < n; ++j) {
Scalar y = yMin + Scalar(j)/(n -1) * (yMax - yMin);
tab->appendSamplePoint(i, y, f(x, y));
}
}
return tab;
}
template <class Fn, class Table>
bool compareTableWithAnalyticFn(const Table &table,
Scalar xMin,
Scalar xMax,
unsigned numX,
Scalar yMin,
Scalar yMax,
unsigned numY,
Fn &f,
Scalar tolerance = 1e-8)
{
// make sure that the tabulated function evaluates to the same thing as the analytic
// one (modulo tolerance)
for (unsigned i = 1; i <= numX; ++i) {
Scalar x = xMin + Scalar(i)/numX*(xMax - xMin);
for (unsigned j = 0; j < numY; ++j) {
Scalar y = yMin + Scalar(j)/numY*(yMax - yMin);
if (std::abs(table->eval(x, y) - f(x, y)) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": table->eval("<<x<<","<<y<<") != f("<<x<<","<<y<<"): " << table->eval(x,y) << " != " << f(x,y) << "\n";
return false;
}
}
}
return true;
}
template <class UniformTablePtr, class UniformXTablePtr, class Fn>
bool compareTables(const UniformTablePtr uTable,
const UniformXTablePtr uXTable,
Fn &f,
Scalar tolerance = 1e-8)
{
// make sure the uniform and the non-uniform tables exhibit the same dimensions
if (std::abs(uTable->xMin() - uXTable->xMin()) > 1e-8) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->xMin() != uXTable->xMin(): " << uTable->xMin() << " != " << uXTable->xMin() << "\n";
return false;
}
if (std::abs(uTable->xMax() - uXTable->xMax()) > 1e-8) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->xMax() != uXTable->xMax(): " << uTable->xMax() << " != " << uXTable->xMax() << "\n";
return false;
}
if (uTable->numX() != uXTable->numX()) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->numX() != uXTable->numX(): " << uTable->numX() << " != " << uXTable->numX() << "\n";
return false;
}
for (unsigned i = 0; i < uTable->numX(); ++i) {
if (std::abs(uTable->yMin() - uXTable->yMin(i)) > 1e-8) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->yMin() != uXTable->yMin("<<i<<"): " << uTable->yMin() << " != " << uXTable->yMin(i) << "\n";
return false;
}
if (std::abs(uTable->yMax() - uXTable->yMax(i)) > 1e-8) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->yMax() != uXTable->yMax("<<i<<"): " << uTable->yMax() << " != " << uXTable->yMax(i) << "\n";
return false;
}
if (uTable->numY() != uXTable->numY(i)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->numY() != uXTable->numY("<<i<<"): " << uTable->numY() << " != " << uXTable->numY(i) << "\n";
return false;
}
}
// make sure that the x and y values are identical
for (unsigned i = 0; i < uTable->numX(); ++i) {
if (std::abs(uTable->iToX(i) - uXTable->iToX(i)) > 1e-8) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->iToX("<<i<<") != uXTable->iToX("<<i<<"): " << uTable->iToX(i) << " != " << uXTable->iToX(i) << "\n";
return false;
}
for (unsigned j = 0; j < uTable->numY(); ++j) {
if (std::abs(uTable->jToY(j) - uXTable->jToY(i, j)) > 1e-8) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->jToY("<<j<<") != uXTable->jToY("<<i<<","<<j<<"): " << uTable->jToY(i) << " != " << uXTable->jToY(i, j) << "\n";
return false;
}
}
}
// check that the appicable range is correct. Note that due to rounding errors it is
// undefined whether the table applies to the boundary of the tabulated domain or not
Scalar xMin = uTable->xMin();
Scalar yMin = uTable->yMin();
Scalar xMax = uTable->xMax();
Scalar yMax = uTable->yMax();
Scalar x = xMin - 1e-8;
Scalar y = yMin - 1e-8;
if (uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
x = xMin - 1e-8;
y = yMin + 1e-8;
if (uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
x = xMin + 1e-8;
y = yMin - 1e-8;
if (uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
x = xMin + 1e-8;
y = yMin + 1e-8;
if (!uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": !uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (!uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": !uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
x = xMax + 1e-8;
y = yMax + 1e-8;
if (uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
x = xMax - 1e-8;
y = yMax + 1e-8;
if (uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
x = xMax + 1e-8;
y = yMax - 1e-8;
if (uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
x = xMax - 1e-8;
y = yMax - 1e-8;
if (!uTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": !uTable->applies("<<x<<","<<y<<")\n";
return false;
}
if (!uXTable->applies(x, y)) {
std::cerr << __FILE__ << ":" << __LINE__ << ": !uXTable->applies("<<x<<","<<y<<")\n";
return false;
}
// make sure that the function values at the sampling points are identical and that
// they correspond to the analytic function
unsigned m2 = uTable->numX()*5;
unsigned n2 = uTable->numY()*5;
if (!compareTableWithAnalyticFn(uTable,
xMin, xMax, m2,
yMin, yMax, n2,
f,
tolerance))
return false;
if (!compareTableWithAnalyticFn(uXTable,
xMin, xMax, m2,
yMin, yMax, n2,
f,
tolerance))
return false;
return true;
}
int main()
{
auto uniformTab = createUniformTabulatedFunction(testFn1);
auto uniformXTab = createUniformXTabulatedFunction(testFn1);
if (!compareTables(uniformTab, uniformXTab, testFn1, /*tolerance=*/1e-12))
return 1;
uniformTab = createUniformTabulatedFunction(testFn2);
uniformXTab = createUniformXTabulatedFunction(testFn2);
if (!compareTables(uniformTab, uniformXTab, testFn2, /*tolerance=*/1e-12))
return 1;
uniformTab = createUniformTabulatedFunction(testFn3);
uniformXTab = createUniformXTabulatedFunction(testFn3);
if (!compareTables(uniformTab, uniformXTab, testFn3, /*tolerance=*/1e-2))
return 1;
uniformXTab = createUniformXTabulatedFunction2(testFn3);
if (!compareTableWithAnalyticFn(uniformXTab,
-10, 10, 100,
-10, 10, 100,
testFn3,
/*tolerance=*/1e-2))
return 1;
// CSV output for debugging
#if 0
int m = 100;
int n = 100;
Scalar xMin = -3.0;
Scalar xMax = 4.0;
Scalar yMin = -1;
Scalar yMax = 1;
for (int i = 0; i < m; ++i) {
Scalar x = xMin + Scalar(i)/m * (xMax - xMin);
for (int j = 0; j < n; ++j) {
Scalar y = yMin + Scalar(j)/n * (yMax - yMin);
std::cout << x << " "
<< y << " "
<< uniformXTab->eval(x,y,true) << "\n";
}
std::cout << "\n";
}
#endif
return 0;
}