// -*- 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 . */ /*! * \file * * \brief This is the unit test for the 2D tabulation classes. * * I.e., for the UniformTabulated2DFunction and UniformXTabulated2DFunction classes. */ #include "config.h" #include #include #include #include #include typedef double Scalar; 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 std::shared_ptr > createUniformTabulatedFunction(Fn &f) { Scalar xMin = -2.0; Scalar xMax = 3.0; Scalar m = 50; Scalar yMin = -1/2.0; Scalar yMax = 1/3.0; Scalar n = 40; auto tab = std::make_shared>( xMin, xMax, m, yMin, yMax, n); for (int i = 0; i < m; ++i) { Scalar x = xMin + Scalar(i)/(m - 1) * (xMax - xMin); for (int j = 0; j < n; ++j) { Scalar y = yMin + Scalar(j)/(n - 1) * (yMax - yMin); tab->setSamplePoint(i, j, f(x, y)); } } return tab; } template std::shared_ptr > createUniformXTabulatedFunction(Fn &f) { Scalar xMin = -2.0; Scalar xMax = 3.0; Scalar m = 50; Scalar yMin = -1/2.0; Scalar yMax = 1/3.0; Scalar n = 40; auto tab = std::make_shared>(); for (int i = 0; i < m; ++i) { Scalar x = xMin + Scalar(i)/(m - 1) * (xMax - xMin); tab->appendXPos(x); for (int j = 0; j < n; ++j) { Scalar y = yMin + Scalar(j)/(n -1) * (yMax - yMin); tab->appendSamplePoint(i, y, f(x, y)); } } return tab; } template std::shared_ptr > createUniformXTabulatedFunction2(Fn &f) { Scalar xMin = -2.0; Scalar xMax = 3.0; Scalar m = 50; auto tab = std::make_shared>(); for (int 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 (int j = 0; j < n; ++j) { Scalar y = yMin + Scalar(j)/(n -1) * (yMax - yMin); tab->appendSamplePoint(i, y, f(x, y)); } } return tab; } template bool compareTableWithAnalyticFn(const Table &table, Scalar xMin, Scalar xMax, int numX, Scalar yMin, Scalar yMax, int 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 (int i = 1; i <= numX; ++i) { Scalar x = xMin + Scalar(i)/numX*(xMax - xMin); for (int 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("<eval(x,y) << " != " << f(x,y) << "\n"; return false; } } } return true; } template 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 (int i = 0; i < uTable->numX(); ++i) { if (std::abs(uTable->yMin() - uXTable->yMin(i)) > 1e-8) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->yMin() != uXTable->yMin("<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("<yMax() << " != " << uXTable->yMax(i) << "\n"; return false; } if (uTable->numY() != uXTable->numY(i)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->numY() != uXTable->numY("<numY() << " != " << uXTable->numY(i) << "\n"; return false; } } // make sure that the x and y values are identical for (int i = 0; i < uTable->numX(); ++i) { if (std::abs(uTable->iToX(i) - uXTable->iToX(i)) > 1e-8) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->iToX("<iToX("<iToX(i) << " != " << uXTable->iToX(i) << "\n"; return false; } for (int j = 0; j < uTable->numY(); ++j) { if (std::abs(uTable->jToY(j) - uXTable->jToY(i, j)) > 1e-8) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->jToY("<jToY("<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("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": !uTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": !uXTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": uXTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": !uTable->applies("<applies(x, y)) { std::cerr << __FILE__ << ":" << __LINE__ << ": !uXTable->applies("<numX()*5; int 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; }