fix some coding style isses in new class XYTabulated2DFunction and its test

This commit is contained in:
Andreas Lauser 2018-12-19 14:07:16 +01:00
parent 20b6068a87
commit 7a4c6546b4
2 changed files with 423 additions and 403 deletions

View File

@ -42,91 +42,69 @@
namespace Opm {
/*!
* \brief Implements a scalar function that depends on two variables, which are sampled
* in X and Y directions with sampling points, respectively.
* The table might be able to be extrapolated in certian directions.
* \brief Implements a function that depends on two variables.
*
* The function is sampled in regular intervals in both directions, i.e., the
* interpolation cells are rectangles. The table can be specified to be extrapolated in
* either direction.
*/
template <class Scalar>
class XYTabulated2DFunction
{
public:
XYTabulated2DFunction()
{ }
XYTabulated2DFunction(const std::vector<Scalar>& x_pos,
const std::vector<Scalar>& y_pos,
const std::vector<std::vector<Scalar> >& data,
const bool x_extrapolate = false,
const bool y_extrapolate = false)
: xPos_(x_pos)
, yPos_(y_pos)
template <class DataContainer>
XYTabulated2DFunction(const std::vector<Scalar>& xPos,
const std::vector<Scalar>& yPos,
const DataContainer& data,
const bool xExtrapolate = false,
const bool yExtrapolate = false)
: xPos_(xPos)
, yPos_(yPos)
, samples_(data)
, xExtrapolate_(x_extrapolate)
, yExtrapolate_(y_extrapolate)
, xExtrapolate_(xExtrapolate)
, yExtrapolate_(yExtrapolate)
{
// make sure the size is correct
if (numX() != samples_.size()) {
throw std::runtime_error("numX() is not equal to the number of rows of the sample points");
#ifndef NDEBUG
// in debug mode, ensure that the x and y positions arrays are strictly
// mononically increasing.
for (unsigned i = 0; i < xPos.size() - 1; ++ i) {
if (xPos[i + 1] <= xPos[i])
throw std::runtime_error("The array for the x-positions is not strictly increasing!");
}
for (unsigned ix = 0; ix < numX(); ++ix) {
if (samples_[ix].size() != numY()) {
for (unsigned i = 0; i < yPos.size() - 1; ++ i) {
if (yPos[i + 1] <= yPos[i])
throw std::runtime_error("The array for the y-positions is not strictly increasing!");
}
#endif
// make sure the size is correct
if (numX() != samples_.size())
throw std::runtime_error("numX() is not equal to the number of rows of the sampling points");
for (unsigned xIdx = 0; xIdx < numX(); ++xIdx) {
if (samples_[xIdx].size() != numY()) {
std::ostringstream oss;
oss << "the " << ix << "th row of the sample points has different number of data from numY() ";
oss << "The " << xIdx << "-th row of the sampling points has different size than numY() ";
throw std::runtime_error(oss.str());
}
}
}
/*!
* \brief Evaluate the function at a given (x,y) position.
*
* If this method is called for a value outside of the tabulated
* range, and extrapolation is not allowed in the corresponding direction,
* a \c Opm::NumericalIssue exception is thrown.
* \brief Returns the number of sampling points in X direction.
*/
template <typename DataType>
void eval(const DataType& x, const DataType& y, DataType& result) const
{
if ( (!xExtrapolate_ && !appliesX(x)) ||
(!yExtrapolate_ && !appliesY(y)) ) {
std::ostringstream oss;
oss << "Attempt to get undefined table value (" << x << ", " << y << ")";
throw NumericalIssue(oss.str());
};
size_t numX() const
{ return xPos_.size(); }
// bi-linear interpolation: first, calculate the x and y indices in the lookup
// table ...
const unsigned i = xSegmentIndex(x);
const unsigned j = ySegmentIndex(y);
// bi-linear interpolation / extrapolation
const DataType alpha = xToAlpha(x, i);
const DataType beta = yToBeta(y, j);
const DataType s1 = valueAt(i, j) * (1.0 - beta) + valueAt(i, j + 1) * beta;
const DataType s2 = valueAt(i + 1, j) * (1.0 - beta) + valueAt(i + 1, j + 1) * beta;
Valgrind::CheckDefined(s1);
Valgrind::CheckDefined(s2);
// ... and combine them using the x position
result = s1 * (1.0 - alpha) + s2 * alpha;
Valgrind::CheckDefined(result);
}
private:
// the sampling points in the x-drection
std::vector<Scalar> xPos_;
// the sampling points in the y-drection
std::vector<Scalar> yPos_;
// data at the sampling points
std::vector<std::vector<Scalar> > samples_;
bool xExtrapolate_ = false;
bool yExtrapolate_ = false;
/*!
* \brief Returns the number of sampling points in Y direction.
*/
size_t numY() const
{ return yPos_.size(); }
/*!
* \brief Returns the minimum of the X coordinate of the sampling points.
@ -158,83 +136,126 @@ private:
Scalar valueAt(size_t i, size_t j) const
{ return samples_[i][j]; }
/*!
* \brief Returns true if a coordinate lies in the tabulated range
*/
template <class Evaluation>
bool applies(const Evaluation& x, const Evaluation& y) const
{ return appliesX(x) && appliesY(y); }
/*!
* \brief Returns true if a coordinate lies in the tabulated range on the x direction
*/
template <class Evaluation>
bool appliesX(const Evaluation& x) const
{
if (x < xMin() || xMax() < x) {
return false;
} else {
return true;
}
}
{ return xMin() <= x && x <= xMax(); }
/*!
* \brief Returns true if a coordinate lies in the tabulated range on the y direction
*/
template <class Evaluation>
bool appliesY(const Evaluation& y) const
{ return yMin() <= y && y <= yMax(); }
/*!
* \brief Evaluate the function at a given (x,y) position.
*
* If this method is called for a value outside of the tabulated
* range, and extrapolation is not allowed in the corresponding direction,
* a \c Opm::NumericalIssue exception is thrown.
*/
template <typename Evaluation>
void eval(const Evaluation& x, const Evaluation& y, Evaluation& result) const
{
if (y < yMin() || yMax() < y) {
return false;
} else {
return true;
}
if ((!xExtrapolate_ && !appliesX(x)) || (!yExtrapolate_ && !appliesY(y))) {
std::ostringstream oss;
oss << "Attempt to get undefined table value (" << x << ", " << y << ")";
throw NumericalIssue(oss.str());
};
// bi-linear interpolation: first, calculate the x and y indices in the lookup
// table ...
const unsigned i = xSegmentIndex_(x);
const unsigned j = ySegmentIndex_(y);
// bi-linear interpolation / extrapolation
const Evaluation alpha = xToAlpha(x, i);
const Evaluation beta = yToBeta(y, j);
const Evaluation s1 = valueAt(i, j) * (1.0 - beta) + valueAt(i, j + 1) * beta;
const Evaluation s2 = valueAt(i + 1, j) * (1.0 - beta) + valueAt(i + 1, j + 1) * beta;
Valgrind::CheckDefined(s1);
Valgrind::CheckDefined(s2);
// ... and combine them using the x position
result = s1 * (1.0 - alpha) + s2 * alpha;
Valgrind::CheckDefined(result);
}
/*!
* \brief Returns the number of sampling points in X direction.
*/
size_t numX() const
{ return xPos_.size(); }
private:
// the sampling points in the x-drection
std::vector<Scalar> xPos_;
// the sampling points in the y-drection
std::vector<Scalar> yPos_;
// data at the sampling points
std::vector<std::vector<Scalar> > samples_;
/*!
* \brief Returns the number of sampling points in Y direction.
*/
size_t numY() const
{ return yPos_.size(); }
bool xExtrapolate_ = false;
bool yExtrapolate_ = false;
/*!
* \brief Return the interval index of a given position on the x-axis.
*/
template <class Evaluation>
unsigned xSegmentIndex(const Evaluation& x) const
unsigned xSegmentIndex_(const Evaluation& x) const
{
assert(xExtrapolate_ || appliesX(x) );
return segmentIndex(x, xPos_);
return segmentIndex_(x, xPos_);
}
/*!
* \brief Return the interval index of a given position on the y-axis.
*/
template <class Evaluation>
unsigned ySegmentIndex(const Evaluation& y) const
unsigned ySegmentIndex_(const Evaluation& y) const
{
assert(yExtrapolate_ || appliesY(y) );
return segmentIndex(y, yPos_);
return segmentIndex_(y, yPos_);
}
template <class Evaluation>
static unsigned segmentIndex(const Evaluation& y, const std::vector<Scalar>& pos)
static unsigned segmentIndex_(const Evaluation& v, const std::vector<Scalar>& vPos)
{
const unsigned n = vPos.size();
assert(n >= 2);
const unsigned num_pos = pos.size();
assert(num_pos >= 2);
if (y <= pos.front() || num_pos == 2) {
if (v <= vPos.front() || n == 2)
return 0;
} else if (y >= pos.back()) {
return num_pos - 2;
} else {
assert(num_pos >= 3);
else if (v >= vPos.back())
return n - 2;
return --std::lower_bound(pos.begin(), pos.end(), y) - pos.begin();
assert(n > 2 && v > vPos.front() && v < vPos.back());
// bisection. this assumes that the vPos array is strictly mononically
// increasing.
size_t lowerIdx = 0;
size_t upperIdx = vPos.size() - 1;
while (lowerIdx + 1 < upperIdx) {
size_t pivotIdx = (lowerIdx + upperIdx) / 2;
if (v < vPos[pivotIdx])
upperIdx = pivotIdx;
else
lowerIdx = pivotIdx;
}
assert(vPos[lowerIdx] <= v);
assert(v <= vPos[lowerIdx + 1]);
return lowerIdx;
}
/*!

View File

@ -39,363 +39,362 @@
#include <cmath>
#include <iostream>
template <class ScalarT>
struct Test
{
typedef ScalarT Scalar;
typedef ScalarT Scalar;
static Scalar testFn1(Scalar x, Scalar /* y */)
{ return x; }
static Scalar testFn1(Scalar x, Scalar /* y */)
{ return x; }
static Scalar testFn2(Scalar /* x */, Scalar y)
{ return y; }
static Scalar testFn2(Scalar /* x */, Scalar y)
{ return y; }
static Scalar testFn3(Scalar x, Scalar y)
{ return x*y; }
static 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;
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;
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));
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;
}
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;
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;
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));
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;
}
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;
template <class Fn>
std::shared_ptr<Opm::UniformXTabulated2DFunction<Scalar> >
createUniformXTabulatedFunction2(Fn& f)
{
Scalar xMin = -2.0;
Scalar xMax = 3.0;
Scalar m = 50;
Scalar yMin = - 4.0;
Scalar yMax = 5.0;
Scalar yMin = - 4.0;
Scalar yMax = 5.0;
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);
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 n = i + 10;
for (unsigned j = 0; j < n; ++j) {
Scalar y = yMin + Scalar(j)/(n -1) * (yMax - yMin);
tab->appendSamplePoint(i, y, f(x, y));
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;
}
return tab;
}
template <class Fn>
std::shared_ptr<Opm::XYTabulated2DFunction<Scalar> >
createXYTabulated2DFunction(Fn& f)
{
const Scalar xMin = -2.0;
const Scalar xMax = 3.0;
const unsigned m = 50;
template <class Fn>
std::shared_ptr<Opm::XYTabulated2DFunction<Scalar> >
createXYTabulated2DFunction(Fn& f)
{
const Scalar xMin = -2.0;
const Scalar xMax = 3.0;
const unsigned m = 50;
const Scalar yMin = -1/2.0;
const Scalar yMax = 1/3.0;
const unsigned n = 40;
const Scalar yMin = -1/2.0;
const Scalar yMax = 1/3.0;
const unsigned n = 40;
std::vector<Scalar> x_samples(m);
std::vector<Scalar> y_samples(n);
std::vector<std::vector<Scalar>> data(m, std::vector<Scalar>(n));
std::vector<Scalar> x_samples(m);
std::vector<Scalar> y_samples(n);
std::vector<std::vector<Scalar>> data(m, std::vector<Scalar>(n));
for (unsigned i = 0; i < m; ++i) {
x_samples[i] = xMin + Scalar(i)/(m - 1) * (xMax - xMin);
for (unsigned i = 0; i < m; ++i) {
x_samples[i] = xMin + Scalar(i)/(m - 1) * (xMax - xMin);
for (unsigned j = 0; j < n; ++j) {
y_samples[j] = yMin + Scalar(j)/(n -1) * (yMax - yMin);
data[i][j] = f(x_samples[i], y_samples[j]);
for (unsigned j = 0; j < n; ++j) {
y_samples[j] = yMin + Scalar(j)/(n -1) * (yMax - yMin);
data[i][j] = f(x_samples[i], y_samples[j]);
}
}
auto tab = std::make_shared<Opm::XYTabulated2DFunction<Scalar>>(x_samples, y_samples, data, true, true);
return tab;
}
auto tab = std::make_shared<Opm::XYTabulated2DFunction<Scalar>>(x_samples, y_samples, data, true, true);
template <class Fn, class Table>
bool compareTableWithAnalyticFn(const Table& table,
Scalar xMin,
Scalar xMax,
unsigned numX,
return tab;
}
Scalar yMin,
Scalar yMax,
unsigned numY,
template <class Fn, class Table>
bool compareTableWithAnalyticFn(const Table& table,
Scalar xMin,
Scalar xMax,
unsigned numX,
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);
Scalar yMin,
Scalar yMax,
unsigned numY,
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;
}
}
}
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);
return true;
}
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";
template <class Fn, class Table>
bool compareTableWithAnalyticFn2(const Table& table,
const Scalar xMin,
const Scalar xMax,
unsigned numX,
const Scalar yMin,
const 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);
Scalar result;
table->eval(x, y, result);
if (std::abs(result - f(x, y)) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": table->eval("<<x<<","<<y<<") != f("<<x<<","<<y<<"): " << result << " != " << 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()) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->xMin() != uXTable->xMin(): " << uTable->xMin() << " != " << uXTable->xMin() << "\n";
return false;
}
if (std::abs(uTable->xMax() - uXTable->xMax()) > tolerance) {
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)) > tolerance) {
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)) > tolerance) {
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;
}
}
}
return true;
}
template <class Fn, class Table>
bool compareTableWithAnalyticFn2(const Table& table,
const Scalar xMin,
const Scalar xMax,
unsigned numX,
const Scalar yMin,
const 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);
Scalar result;
table->eval(x, y, result);
if (std::abs(result - f(x, y)) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": table->eval("<<x<<","<<y<<") != f("<<x<<","<<y<<"): " << result << " != " << f(x,y) << "\n";
// 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)) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->iToX("<<i<<") != uXTable->iToX("<<i<<"): " << uTable->iToX(i) << " != " << uXTable->iToX(i) << "\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()) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->xMin() != uXTable->xMin(): " << uTable->xMin() << " != " << uXTable->xMin() << "\n";
return false;
}
if (std::abs(uTable->xMax() - uXTable->xMax()) > tolerance) {
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)) > tolerance) {
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)) > tolerance) {
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)) > tolerance) {
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)) > tolerance) {
std::cerr << __FILE__ << ":" << __LINE__ << ": uTable->jToY("<<j<<") != uXTable->jToY("<<i<<","<<j<<"): " << uTable->jToY(i) << " != " << uXTable->jToY(i, j) << "\n";
return false;
for (unsigned j = 0; j < uTable->numY(); ++j) {
if (std::abs(uTable->jToY(j) - uXTable->jToY(i, j)) > tolerance) {
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();
// 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 - tolerance;
Scalar y = yMin - tolerance;
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;
}
Scalar x = xMin - tolerance;
Scalar y = yMin - tolerance;
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 - tolerance;
y = yMin + tolerance;
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 - tolerance;
y = yMin + tolerance;
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 + tolerance;
y = yMin - tolerance;
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 + tolerance;
y = yMin - tolerance;
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 + tolerance;
y = yMin + tolerance;
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 + tolerance;
y = yMin + tolerance;
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 + tolerance;
y = yMax + tolerance;
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 + tolerance;
y = yMax + tolerance;
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 - tolerance;
y = yMax + tolerance;
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 - tolerance;
y = yMax + tolerance;
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 + tolerance;
y = yMax - tolerance;
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 + tolerance;
y = yMax - tolerance;
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 - tolerance;
y = yMax - tolerance;
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 - tolerance;
y = yMax - tolerance;
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;
// 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;
}
return true;
}
};
template <class TestType>
inline int testAll( const typename TestType::Scalar tolerance = 1e-6 )
inline int testAll(const typename TestType::Scalar tolerance = 1e-6)
{
TestType test;
auto uniformTab = test.createUniformTabulatedFunction(TestType::testFn1);
@ -415,10 +414,10 @@ inline int testAll( const typename TestType::Scalar tolerance = 1e-6 )
uniformXTab = test.createUniformXTabulatedFunction2(TestType::testFn3);
if (!test.compareTableWithAnalyticFn(uniformXTab,
-2.0, 3.0, 100,
-4.0, 5.0, 100,
TestType::testFn3,
/*tolerance=*/1e-2))
-2.0, 3.0, 100,
-4.0, 5.0, 100,
TestType::testFn3,
/*tolerance=*/1e-2))
return 1;
{
@ -434,19 +433,19 @@ inline int testAll( const typename TestType::Scalar tolerance = 1e-6 )
const unsigned n = 170;
// extrapolation and interpolation involved, the tolerance needs to be bigger
const ScalarType temp_tolerance = 1000. * tolerance;
const ScalarType tmpTolerance = 1000. * tolerance;
if (!test.compareTableWithAnalyticFn2(xytab, xMin, xMax, m, yMin, yMax, n, TestType::testFn1, temp_tolerance))
if (!test.compareTableWithAnalyticFn2(xytab, xMin, xMax, m, yMin, yMax, n, TestType::testFn1, tmpTolerance))
return 1;
xytab = test.createXYTabulated2DFunction(TestType::testFn2);
if (!test.compareTableWithAnalyticFn2(xytab, xMin, xMax, m, yMin, yMax, n, TestType::testFn2, temp_tolerance))
if (!test.compareTableWithAnalyticFn2(xytab, xMin, xMax, m, yMin, yMax, n, TestType::testFn2, tmpTolerance))
return 1;
xytab = test.createXYTabulated2DFunction(TestType::testFn3);
if (!test.compareTableWithAnalyticFn2(xytab, xMin, xMax, m, yMin, yMax, n, TestType::testFn3, temp_tolerance))
if (!test.compareTableWithAnalyticFn2(xytab, xMin, xMax, m, yMin, yMax, n, TestType::testFn3, tmpTolerance))
return 1;
}