Code indexing in gitaly is broken and leads to code not being visible to the user. We work on the issue with highest priority.

Skip to content
Snippets Groups Projects
Commit cb0e7bd4 authored by ext-rogers_c's avatar ext-rogers_c
Browse files

Fixing failing tests in PolynomialPatch routines

parent 0588272d
No related branches found
No related tags found
No related merge requests found
Showing
with 331 additions and 168 deletions
......@@ -180,5 +180,25 @@ bool operator!=(const Mesh::Iterator& lhs, const Mesh::Iterator& rhs) {
return false;
return true;
}
bool Mesh::Iterator::isOutOfBounds() const {
if (!mesh_m) {
return true;
}
Mesh::Iterator first = mesh_m->begin();
Mesh::Iterator last = mesh_m->end()-1;
for (size_t i = 0; i < state_m.size(); ++i) {
if (state_m[i] < first[i] || state_m[i] > last[i]) {
return true;
}
}
return false;
}
void Mesh::Iterator::addState(const Mesh::Iterator& it) {
for (size_t i = 0; i < state_m.size(); ++i)
state_m[i] += it.state_m[i];
}
}
......@@ -57,7 +57,7 @@ class Mesh {
virtual Mesh::Iterator begin() const = 0;
/** Return the last+1 point on the mesh */
virtual Mesh::Iterator end() const = 0;
virtual Mesh::Iterator end() const = 0;
/** Return a copy of child object */
virtual Mesh* clone() = 0;
......@@ -221,6 +221,12 @@ class Mesh::Iterator {
/** Return the mesh over which the iterator acts */
inline const Mesh* getMesh() const;
/** Return true if the iterator is off the edge of the mesh */
virtual inline bool isOutOfBounds() const;
/** Add the internal state vector of it onto this */
virtual inline void addState(const Mesh::Iterator& it);
friend class Mesh;
friend class TwoDGrid;
friend class ThreeDGrid;
......
......@@ -262,6 +262,16 @@ class NDGrid : public Mesh {
*/
Mesh::Iterator getNearest(const double* position) const;
/** Returns true if it is off the edge of the grid.
*
* @param it: iterator to check; dimensionality of it is not checked.
* Behaviour is undetermined if it is less than position
* dimension of the mesh - but likely to be memory error.
*
* @returns true if it is off the edge of the grid.
*/
inline bool isOutOfBounds(const Mesh::Iterator& it) const;
protected:
//Change position
......
......@@ -75,9 +75,8 @@ PPSolveFactory::PPSolveFactory(Mesh* points,
thisValues_m(),
derivPoints_m(),
derivValues_m(),
derivIndices_m(),
edgePoints_m(),
smoothingPoints_m() {
derivIterator_m(),
derivIndices_m() {
if (points == NULL) {
throw GeneralClassicException(
"PPSolveFactory::Solve",
......@@ -92,6 +91,11 @@ PPSolveFactory::PPSolveFactory(Mesh* points,
"PPSolveFactory::Solve",
ss.str());
}
if (polyPatchOrder < 1) {
throw GeneralClassicException(
"PPSolveFactory::Solve",
"Polynomial order must be at least 1.");
}
if (smoothingOrder < polyPatchOrder) {
throw GeneralClassicException(
"PPSolveFactory::Solve",
......@@ -103,39 +107,6 @@ PPSolveFactory::PPSolveFactory(Mesh* points,
"PPSolveFactory::Solve",
"Dual of Mesh was NULL");
polyDim_m = values[0].size();
int posDim = points->getPositionDimension();
edgePoints_m = std::vector< std::vector< std::vector<int> > >(posDim+1);
for (int i = 1; i <= posDim; ++i)
edgePoints_m[i] = getNearbyPointsSquares
(i, 0, smoothingOrder-polyPatchOrder);
smoothingPoints_m = getNearbyPointsSquares
(posDim, polyPatchOrder_m-1, polyPatchOrder_m);
}
std::vector<double> PPSolveFactory::outOfBoundsPosition(
Mesh::Iterator outOfBoundsIt) {
const Mesh* mesh = outOfBoundsIt.getMesh();
std::vector<int> state = outOfBoundsIt.getState();
std::vector<int> delta = std::vector<int>(state.size(), 2);
Mesh::Iterator end = mesh->end()-1;
std::vector<double> pos1 = mesh->begin().getPosition();
std::vector<double> pos2 = Mesh::Iterator(delta, mesh).getPosition();
for (size_t i = 0; i < state.size(); ++i)
if (state[i] < 1) {
state[i] = 1;
} else if (state[i] > end[i]) {
state[i] = end[i];
}
std::vector<double> position = Mesh::Iterator(state, mesh).getPosition();
state = outOfBoundsIt.getState();
for (size_t i = 0; i < state.size(); ++i)
if (state[i] < 1) {
position[i] = (pos2[i] - pos1[i])*(state[i]-1) + position[i];
} else if (state[i] > end[i]) {
position[i] = (pos2[i] - pos1[i])*(state[i]-end[i]) + position[i];
}
return position;
}
void PPSolveFactory::getPoints() {
......@@ -182,60 +153,99 @@ void PPSolveFactory::getValues(Mesh::Iterator it) {
}
}
/*
* calculate a list of Mesh::iterators, each corresponding to the offset of the
* point at which the derivative should be calculated relative to the central
* polynomial. Goes hand-in-hand with derivIndices.
* for e.g. 2d mesh with polyPatchOrder 2, derivatives are always taken from the
* 4th row/column:
* P o o x
* o o o x
* o o o x
* x x x x
* and derivatives used are for smoothOrder 4
* P . . - + - +
* . . . - + - +
* . . . - + - +
* | | | \
* + + + +
* | | | \
* + + + +
* where each "line" means take a derivative; diagonal line means take a double
* derivative (just like in the values, we take all derivatives up to
* d_1^n d_2^n for an "nth order" PolynomialSquareVector)
*
* Note that # marks the polynomial being fitted - derivatives are taken a few
* mesh points away from the polynomial (which may not be the ideal). Also note
* that the fit is one-sided; polynomials to the left of # are tasked with
* matching points to the right, possibly including #. # knows nothing about
* them. We might get a different solution if we reversed the order of fitting,
* which is a bit ugly.
*/
void PPSolveFactory::getDerivPoints() {
derivPoints_m = std::vector< std::vector<double> >();
derivIndices_m = std::vector< std::vector<int> >();
derivOrigins_m = std::vector< std::vector<int> >();
derivPolyVec_m = std::vector<MVector<double> >();
int posDim = points_m->getPositionDimension();
// get the outer layer of points
int deltaOrder = smoothingOrder_m - polyPatchOrder_m;
if (deltaOrder <= 0)
return;
std::vector<double> deltaPos = getDeltaPos(points_m);
// smoothingPoints_m is the last layer of points used for polynomial fit
// walk around smoothingPoints_m finding the points used for smoothing
for (size_t i = 0; i < smoothingPoints_m.size(); ++i) {
// make a list of the axes that are on the edge of the space
std::vector<int> equalAxes;
for (size_t j = 0; j < smoothingPoints_m[i].size(); ++j)
if (smoothingPoints_m[i][j] == polyPatchOrder_m)
equalAxes.push_back(j);
std::vector<std::vector<int> > edgePoints =
edgePoints_m[equalAxes.size()];
// note the first point, 0,0, is ignored
for (size_t j = 0; j < edgePoints.size(); ++j) {
derivIndices_m.push_back(std::vector<int>(posDim));
derivOrigins_m.push_back(smoothingPoints_m[i]);
derivPoints_m.push_back(std::vector<double>(posDim));
for (size_t k = 0; k < smoothingPoints_m[i].size(); ++k) {
derivPoints_m.back()[k] = (smoothingPoints_m[i][k]-0.5)*deltaPos[k];
}
for (size_t k = 0; k < edgePoints[j].size(); ++k) {
derivIndices_m.back()[equalAxes[k]] = edgePoints[j][k];
std::vector< std::vector<int> > indices = getNearbyPointsSquares(posDim,
polyPatchOrder_m,
smoothingOrder_m);
std::cerr << "PPSolveFactory::getDerivPoints" << std::endl;
// derivIterator_m points at the polynomial on which the derivative should
// be operated (relative offset to centre) - the "x" in comment above
derivIterator_m = std::vector< Mesh::Iterator >();
// derivative indexes the order of the derivative - the "+" in the comment
// above
derivIndices_m = std::vector< std::vector<int> >();
derivPoints_m = std::vector< std::vector<double> >();
for (auto deriv: indices) {
std::vector<int> derivPointState(deriv);
for (auto& i: derivPointState) {
if (i > polyPatchOrder_m) {
i = polyPatchOrder_m;
}
int index = 0;
// potential bug ... derivIndexByPower_m is never used, is it
// needed?
while (true) {
bool isEqual = true;
std::vector<int> polyIndex =
SquarePolynomialVector::IndexByPower(index, posDim);
for (int k = 0; k < posDim && isEqual; ++k) {
isEqual = polyIndex[k] == derivIndices_m.back()[k];
}
if (isEqual) {
derivIndexByPower_m.push_back(index);
break;
}
++index;
}
Mesh::Iterator it(derivPointState, polyMesh_m);
derivPoints_m.push_back(it.getPosition());
derivIterator_m.push_back(it);
for (auto& i: deriv) {
if (i > polyPatchOrder_m) {
i -= polyPatchOrder_m;
} else {
i = 0;
}
}
}
derivIndices_m.push_back(deriv);
}
getDerivPolyVec();
std::cerr << "PPSolveFactory::getDerivPoints 2" << std::endl;
for (size_t i = 0; i < derivIndices_m.size(); ++i) {
std::cerr << " ";
for (auto n: indices[i]) {
std::cerr << n << " ";
}
std::cerr << " * ";
for (auto n: derivIndices_m[i]) {
std::cerr << n << " ";
}
std::cerr << " * ";
for (auto n: derivIterator_m[i].getState()) {
std::cerr << n << " ";
}
std::cerr << " * ";
for (auto x: derivPoints_m[i]) {
std::cerr << x << " ";
}
std::cerr << std::endl;
}
return;
}
void PPSolveFactory::getDerivPolyVec() {
int posDim = points_m->getPositionDimension();
int nPolyCoeffs = SquarePolynomialVector::NumberOfPolynomialCoefficients
(posDim, smoothingOrder_m);
std::vector<double> deltaPos = getDeltaPos(points_m);
for (size_t i = 0; i < derivPoints_m.size(); ++i) {
derivPolyVec_m.push_back(MVector<double>(nPolyCoeffs, 1.));
// Product[x^{p_j-q_j}*p_j!/(p_j-q_j)!]
......@@ -255,39 +265,54 @@ void PPSolveFactory::getDerivPoints() {
}
}
// Aim is to extract derivatives in the region of "it" and place them into
// derivValues_m, where the derivValues_m correspond to the derivatives at
// each point in derivPoints_m
void PPSolveFactory::getDerivs(Mesh::Iterator it) {
derivValues_m = std::vector< std::vector<double> >(derivPoints_m.size());
std::vector<double> itPos = it.getPosition();
int posDim = it.getState().size();
// get the outer layer of points
Mesh::Iterator end = it.getMesh()->end()-1;
// deltaOrder corresponds to the number of derivatives required
int deltaOrder = smoothingOrder_m - polyPatchOrder_m;
if (deltaOrder <= 0)
return;
for (size_t i = 0; i < derivPoints_m.size(); ++i) {
std::vector<double> point = std::vector<double>(posDim, 0.);
Mesh::Iterator nearest = it;
for (int j = 0; j < posDim; ++j) {
point[j] = itPos[j]-derivPoints_m[i][j];
if (deltaOrder <= 0) {
return; // no derivatives need to be found
}
// derivValues_m is filled with the calc'd derivatives
derivValues_m = std::vector< std::vector<double> >(derivIterator_m.size());
std::cerr << " PPSolveFactory::getDerivs" << std::endl;
// now get the outer layer of points and put derivatives in for each point
for (size_t i = 0; i < derivIterator_m.size(); ++i) {
Mesh::Iterator derivPoint = derivIterator_m[i];
derivPoint.addState(it);
if (derivPoint.isOutOfBounds()) {
// off the edge of the grid - use boundary condition
std::cerr << " OOB" << std::endl;
derivValues_m[i] = std::vector<double>(polyDim_m, 0.);
continue;
}
for (int j = 0; j < posDim; ++j) {
nearest[j] += derivOrigins_m[i][j];
if (nearest[j] > end[j]) {
nearest = it;
break;
}
SquarePolynomialVector* poly = polynomials_m[derivPoint.toInteger()];
if (poly == NULL) {
// polynomial has not been found yet - this is an error condition
// we should only use a boundary condition when we are off the mesh;
// otherwise, we should have calculated a polynomial
std::cerr << "While working on " << it << std::endl;
std::cerr << " Failed with point " << derivPoint << std::endl;
std::cerr << " DerivIterator was " << derivIterator_m[i] << std::endl;
throw(GeneralClassicException("PPSolveFactory::getDerivs",
"Internal error in polynomial calculation"));
}
if (polynomials_m[nearest.toInteger()] == NULL) {
derivValues_m[i] = std::vector<double>(polyDim_m, 0.);
} else {
MMatrix<double> coeffs =
polynomials_m[nearest.toInteger()]->GetCoefficientsAsMatrix();
MVector<double> values = coeffs*derivPolyVec_m[i];
derivValues_m[i] = std::vector<double>(polyDim_m);
for(int j = 0; j < posDim; ++j) {
derivValues_m[i][j] = values(j+1);
}
// polynomial has been found; calculate derivatives
std::cerr << " Not NULL 0" << std::endl;
MMatrix<double> coeffs = poly->GetCoefficientsAsMatrix();
std::cerr << " Not NULL " << derivPolyVec_m.size() << " ** "
<< coeffs.num_row() << " " << coeffs.num_col() << " ** "
<< derivPolyVec_m[i].num_row() << std::endl;
MVector<double> values = coeffs*derivPolyVec_m[i];
std::cerr << " Not NULL 2" << std::endl;
derivValues_m[i] = std::vector<double>(polyDim_m);
std::cerr << " Not NULL 3" << std::endl;
for(int j = 0; j < polyDim_m; ++j) {
std::cerr << " Not NULL 4" << std::endl;
derivValues_m[i][j] = values(j+1);
}
}
}
......@@ -300,8 +325,7 @@ PolynomialPatch* PPSolveFactory::solve() {
// get the list of points that are needed to make a given poly vector
getPoints();
getDerivPoints();
SolveFactory solver(polyPatchOrder_m,
smoothingOrder_m,
SolveFactory solver(smoothingOrder_m,
polyMesh_m->getPositionDimension(),
polyDim_m,
thisPoints_m,
......@@ -317,12 +341,14 @@ PolynomialPatch* PPSolveFactory::solve() {
*gmsg << " Done " << newPercentage << " %" << endl;
oldPercentage = newPercentage;
}
std::cerr << "PPSolveFactory::solve at " << it << std::endl;
// find the set of values and derivatives for this point in the mesh
getValues(it);
getDerivs(it);
// The polynomial is found using simultaneous equation solve
polynomials_m[it.toInteger()] = solver.PolynomialSolve
(thisValues_m, derivValues_m);
std::cerr << " Done " << polynomials_m[it.toInteger()] << " " << it << std::endl;
}
return new PolynomialPatch(polyMesh_m, points_m, polynomials_m);
}
......
......@@ -61,6 +61,8 @@ class PolynomialPatch;
* The PPSolveFactory sits on top of SolveFactory; PPSolveFactory has the job
* of picking values and derivatives for fitting, SolveFactory then does the
* actual solve for each individual polynomial.
*
* There is a short note with some maths in attached to OPAL issue #439.
*/
class PPSolveFactory {
public:
......@@ -73,14 +75,16 @@ class PPSolveFactory {
* \param values Set of values to which we fit. Must be one value per mesh
* point and each value must have the same size.
* \param polyPatchOrder The order of the fitted part of the polynomial.
* This must be greater than 0 so that the fitted part at
* least matches values at adjacent mesh points.
* \param smoothingOrder The total order of the fitted and the smoothed
* part of the polynomial. Smoothing order should always be
* >= polyPatchOrder. So for example if polyPatchOrder
* is 2 and smoothing order is 2, we get a 2nd order
* function with no derivative matching. If polyPatchOrder
* is 2 and smoothing order is 3, we get a 3rd order
* function with derivative matching in first order at two
* mesh points from the centre.
* part of the polynomial. Smoothing order should always be
* >= polyPatchOrder. So for example if polyPatchOrder
* is 2 and smoothing order is 2, we get a 2nd order
* function with no derivative matching. If polyPatchOrder
* is 2 and smoothing order is 3, we get a 3rd order
* function with derivative matching in first order at two
* mesh points from the centre.
*/
PPSolveFactory(Mesh* points,
std::vector<std::vector<double> > values,
......@@ -121,10 +125,8 @@ class PPSolveFactory {
void getValues(Mesh::Iterator it);
void getDerivPoints();
void getDerivs(Mesh::Iterator it);
void getDerivPolyVec();
// nothing calls this method but I don't quite field brave enought to remove
// it...
std::vector<double> outOfBoundsPosition(Mesh::Iterator outOfBoundsIt);
static void nearbyPointsRecursive(
std::vector<int> check,
size_t checkIndex,
......@@ -147,14 +149,12 @@ class PPSolveFactory {
std::vector< std::vector<double> > thisValues_m;
std::vector< std::vector<double> > derivPoints_m;
std::vector< std::vector<double> > derivValues_m;
std::vector< std::vector<int> > derivOrigins_m;
std::vector< Mesh::Iterator > derivIterator_m;
std::vector< std::vector<int> > derivIndices_m;
std::vector< MVector<double> > derivPolyVec_m;
std::vector<int> derivIndexByPower_m;
std::vector<std::vector<std::vector<int> > > edgePoints_m;
std::vector< std::vector<int> > smoothingPoints_m;
};
}
......
......@@ -40,11 +40,11 @@ PolynomialPatch::PolynomialPatch(Mesh* grid_points,
// validate input data
if (grid_points_ == NULL)
throw GeneralClassicException(
"PolynomialPatch::PolynomialPatch",
"PolynomialPatch::PolynomialPatch",
"PolynomialPatch grid_points_ was NULL");
if (validity_region_ == NULL)
throw GeneralClassicException(
"PolynomialPatch::PolynomialPatch",
"PolynomialPatch::PolynomialPatch",
"PolynomialPatch validity_region_ was NULL");
if (points_.size() == 0) {
throw GeneralClassicException(
......
......@@ -25,6 +25,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sstream>
#include <gsl/gsl_sf_pow_int.h>
#include "Utilities/GeneralClassicException.h"
......@@ -34,19 +36,23 @@
namespace interpolation {
SolveFactory::SolveFactory(int polynomial_order,
int smoothing_order,
SolveFactory::SolveFactory(int smoothing_order,
int point_dim,
int value_dim,
std::vector< std::vector<double> > positions,
std::vector< std::vector<double> > deriv_positions,
std::vector< std::vector<int> >& deriv_indices)
// :FIXME: unused!
// : polynomial_order_(polynomial_order), smoothing_order_(smoothing_order)
{
std::vector< std::vector<int> >& deriv_indices) {
n_poly_coeffs_ = SquarePolynomialVector::NumberOfPolynomialCoefficients(point_dim, smoothing_order);
square_points_ = PPSolveFactory::getNearbyPointsSquares(point_dim, -1, smoothing_order);
square_deriv_nearby_points_ = PPSolveFactory::getNearbyPointsSquares(point_dim, -1, smoothing_order);
if (positions.size() + deriv_positions.size() - n_poly_coeffs_ != 0) {
std::stringstream ss;
ss << "Total size of positions and deriv_positions ("
<< positions.size() << "+" << deriv_positions.size() << ") should be "
<< n_poly_coeffs_;
throw GeneralClassicException(
"SolveFactory::SolveFactory",
ss.str());
}
BuildHInvMatrix(positions, deriv_positions, deriv_indices);
MMatrix<double> A_temp(value_dim, n_poly_coeffs_, 0.);
square_temp_ = SquarePolynomialVector(point_dim, A_temp);
......@@ -60,10 +66,11 @@ void SolveFactory::BuildHInvMatrix(
h_inv_ = MMatrix<double>(n_poly_coeffs_, n_poly_coeffs_, 0.);
for (int i = 0; i < nCoeffs; ++i) {
std::vector<double> poly_vec = MakeSquareVector(positions[i]);
for (int j = 0; j < n_poly_coeffs_; ++j) {
for (int j = 0; j < int(poly_vec.size()); ++j) {
h_inv_(i+1, j+1) = poly_vec[j];
}
}
for (size_t i = 0; i < deriv_positions.size(); ++i) {
std::vector<double> deriv_vec = MakeSquareDerivVector(deriv_positions[i],
deriv_indices[i]);
......@@ -84,22 +91,30 @@ std::vector<double> SolveFactory::MakeSquareVector(std::vector<double> x) {
return square_vector;
}
std::vector<double> SolveFactory::MakeSquareDerivVector(std::vector<double> positions, std::vector<int> deriv_indices) {
std::vector<double> deriv_vec(square_deriv_nearby_points_.size(), 1.);
int square_deriv_nearby_points_size = square_deriv_nearby_points_.size();
int dim = square_deriv_nearby_points_[0].size();
for (int i = 0; i < square_deriv_nearby_points_size; ++i) {
std::vector<double> SolveFactory::MakeSquareDerivVector(
std::vector<double> x,
std::vector<int> deriv_indices) {
// vector like Product_i [x_i^{a_i - m_i}*m_i!/(a_i-m_i)]
// where:
// m_i is given by deriv_indices
// a_i are the polynomial vector indices
std::vector<double> deriv_vec(square_points_.size(), 1.);
int square_points_size = square_points_.size();
int dim = square_points_[0].size();
for (int i = 0; i < square_points_size; ++i) {
std::vector<int>& point = square_points_[i];
for (int j = 0; j < dim; ++j) {
int power = square_deriv_nearby_points_[i][j] - deriv_indices[j]; // p_j - q_j
int power = point[j] - deriv_indices[j]; // p_j - q_j
if (power < 0) {
deriv_vec[i] = 0.;
break;
} else {
// x^(p_j-q_j)
deriv_vec[i] *= gsl_sf_pow_int(positions[j], power);
deriv_vec[i] *= gsl_sf_pow_int(x[j], power); // x_j^{power}
}
// p_j*(p_j-1)*(p_j-2)*...*(p_j-q_j)
for (int k = square_deriv_nearby_points_[i][j]; k > power; --k) {
for (int k = point[j]; k > power && k > 0; --k) {
deriv_vec[i] *= k;
}
}
......
......@@ -57,7 +57,7 @@ class SolveFactory {
* vector of length point_dim
* \param deriv_positions Position of the derivatives; should be a vector
* of length
* smoothing_oder^point_dim - polynomial_order^point_dim.
* smoothing_order^point_dim - polynomial_order^point_dim.
* Each element should be a vector of length point_dim.
* \param deriv_indices Index the derivatives. Should be a vector with
* same length as deriv_positions. Each element should
......@@ -71,8 +71,7 @@ class SolveFactory {
* as in PolynomialPatch, we get a lot faster). The matrix inversion can
* fail for badly formed sets of positions/deriv_positions; caveat emptor!
*/
SolveFactory(int polynomial_order,
int smoothing_order,
SolveFactory(int smoothing_order,
int point_dim,
int value_dim,
std::vector< std::vector<double> > positions,
......@@ -116,9 +115,6 @@ class SolveFactory {
void BuildHInvMatrix(std::vector< std::vector<double> > positions,
std::vector< std::vector<double> > deriv_positions,
std::vector< std::vector<int> >& deriv_indices);
// :FIXME: remove unused declaration
// int polynomial_order_;
// int smoothing_order_;
int n_poly_coeffs_;
std::vector< std::vector<int> > square_points_;
std::vector< std::vector<int> > square_deriv_nearby_points_;
......
#include "gtest/gtest.h"
#include <gsl/gsl_errno.h>
#include "mpi.h"
#include "Utilities/OpalException.h"
#include "Utility/IpplInfo.h" // ippl
Ippl *ippl;
......@@ -14,6 +16,15 @@ class NewLineAdder: public ::testing::EmptyTestEventListener {
}
};
namespace {
void errorHandlerGSL(const char *reason,
const char *file,
int line,
int gsl_errno) {
throw OpalException(file, reason);
}
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
gmsg = new Inform("UnitTests: ", std::cerr);
......@@ -21,6 +32,7 @@ int main(int argc, char **argv) {
return 1;
}
ippl = new Ippl(argc, argv);
gsl_set_error_handler(&errorHandlerGSL);
::testing::TestEventListeners &listeners =
::testing::UnitTest::GetInstance()->listeners();
......
......@@ -323,4 +323,9 @@ TEST_F(NDGridTest, DualTest) {
}
}
TEST_F(NDGridTest, IsOutOfBoundsTest) {
// nb isOutOfBounds is defined in Mesh.hh (but tested here for convenience
EXPECT_TRUE(false) << "Do the test" << std::endl;
}
} // namespace ndgridtest
\ No newline at end of file
......@@ -105,10 +105,10 @@ class PPSolveFactoryTestFixture : public ::testing::Test {
PPSolveFactoryTestFixture() {
// we make a reference poly vector
std::vector<double> data(2*27); // 2^3
std::vector<double> data(2*125); // 2^3
for (size_t i = 0; i < data.size(); ++i)
data[i] = i/10.;
refCoeffs = MMatrix<double>(2, 27, &data[0]);
refCoeffs = MMatrix<double>(2, 125, &data[0]);
ref = SquarePolynomialVector(3, refCoeffs);
// we get some data
np = 6;
......@@ -184,14 +184,19 @@ TEST_F(PPSolveFactoryTestFixture, TestSolvePolynomialQuadratic) {
// check smoothed quadratic fit exactly reproduces data on and off grid points
// except near to the boundary
TEST_F(PPSolveFactoryTestFixture, DISABLED_TestSolvePolynomialQuadraticSmoothed) {
OpalTestUtilities::SilenceTest silencer;
TEST_F(PPSolveFactoryTestFixture, TestSolvePolynomialQuadraticSmoothed) {
//OpalTestUtilities::SilenceTest silencer;
PPSolveFactory fac2(grid->clone(),
values,
1,
2);
PolynomialPatch* patch2 = fac2.solve();
2,
4);
PolynomialPatch* patch2 = NULL;
try {
patch2 = fac2.solve();
} catch (GeneralClassicException& exc) {
std::cerr << exc.what() << " " << exc.where() << std::endl;
throw;
}
// first check that the polynomial at 0, 0, 0 is the same as ref
std::vector<double> zero(3, 0.);
SquarePolynomialVector* test = patch2->getPolynomialVector(&zero[0]);
......@@ -202,23 +207,24 @@ TEST_F(PPSolveFactoryTestFixture, DISABLED_TestSolvePolynomialQuadraticSmoothed)
std::cout << testCoeffs << std::endl;
ASSERT_EQ(testCoeffs.num_row(), refCoeffs.num_row());
ASSERT_EQ(testCoeffs.num_col(), refCoeffs.num_col());
for (size_t i = 0; i < testCoeffs.num_row(); ++i)
for (size_t i = 0; i < testCoeffs.num_row(); ++i) {
for (size_t j = 0; j < testCoeffs.num_row(); ++j) {
EXPECT_NEAR(testCoeffs(i+1, j+1), refCoeffs(i+1, j+1), 1e-6)
<< "col " << i << " row " << j;
EXPECT_NEAR(testCoeffs(i+1, j+1), refCoeffs(i+1, j+1), 1e-6)
<< "col " << i << " row " << j;
}
}
// now check that the values in each polynomial are correct
return;
// now check that the values returned by each polynomial are correct
ThreeDGrid testGrid(1./4., 2./4., 3./4., -1., -2., -3., np*4-1, np*4-1, np*4-1);
for (Mesh::Iterator it = testGrid.begin(); it < testGrid.end(); ++it) {
std::vector<double> refValue(2);
std::vector<double> testValue(2);
ref.F(&it.getPosition()[0], &refValue[0]);
patch2->function(&it.getPosition()[0], &testValue[0]);
for (size_t i = 0; i < 2; ++i)
for (size_t i = 0; i < 2; ++i) {
EXPECT_NEAR(refValue[i], testValue[i], 1e-6) << std::endl << it;
}
}
}
......
......@@ -35,8 +35,14 @@
using namespace interpolation;
class SolveFactoryTestFixture : public ::testing::Test {
protected:
};
TEST(SolveFactoryTest, TestSolveNoDerivs) {
OpalTestUtilities::SilenceTest silencer;
//OpalTestUtilities::SilenceTest silencer;
// we make a reference poly vector
std::vector<double> data(27);
......@@ -59,13 +65,74 @@ TEST(SolveFactoryTest, TestSolveNoDerivs) {
// ref are identical
std::vector<std::vector<double> > deriv_pos;
std::vector< std::vector<int> > deriv_index;
SolveFactory fac(2, 2, 2, 3, positions, deriv_pos, deriv_index);
SolveFactory fac(2, 2, 3, positions, deriv_pos, deriv_index);
SquarePolynomialVector* vec = fac.PolynomialSolve(values,
deriv_pos);
MMatrix<double> testCoeffs = vec->GetCoefficientsAsMatrix();
ASSERT_EQ(testCoeffs.num_row(), (size_t)3);
ASSERT_EQ(testCoeffs.num_col(), (size_t)9);
for (size_t i = 0; i < 3; ++i) {
for (size_t j = 0; j < 3; ++j) {
EXPECT_NEAR(testCoeffs(i+1, j+1), refCoeffs(i+1, j+1), 1e-6);
}
}
delete vec;
}
TEST(SolveFactoryTest, TestSolveDerivs) {
// we make a reference poly vector
std::vector<double> data(27);
for (size_t i = 0; i < data.size(); ++i)
data[i] = i;
MMatrix<double> refCoeffs(3, 9, &data[0]);
SquarePolynomialVector ref(2, refCoeffs);
std::vector<int> derivIndex01({0, 1});
SquarePolynomialVector refDeriv01 = ref.Deriv(&derivIndex01[0]);
std::vector<int> derivIndex11({1, 1});
SquarePolynomialVector refDeriv11 = ref.Deriv(&derivIndex11[0]);
std::vector<int> derivIndex10({1, 0});
SquarePolynomialVector refDeriv10 = ref.Deriv(&derivIndex10[0]);
// Make a set of points
std::vector< std::vector<double> > positions;
std::vector< std::vector<double> > values;
std::vector<double> pos(2);
std::vector<double> val(3);
for (pos[0] = 0.; pos[0] < 1.5; pos[0] += 1.) {
for (pos[1] = 0.; pos[1] < 1.5; pos[1] += 1.) {
ref.F(&pos[0], &val[0]);
positions.push_back(pos);
values.push_back(val);
}
}
// fill by hand the
std::vector< std::vector<double> > deriv_pos( {
{2, 0}, {2, 1}, {2, 2}, {1, 2}, {0, 2}
});
std::vector< std::vector<int> > deriv_indices( {
{0,1}, {0,1}, {1,1}, {1,0}, {1,0}
});
std::vector<std::vector<double> > deriv_values(deriv_pos.size(),
std::vector<double>(2));
for (size_t i = 0; i < deriv_pos.size(); ++i) {
SquarePolynomialVector refDeriv = ref.Deriv(&deriv_indices[i][0]);
refDeriv.F(&deriv_pos[i][0], &deriv_values[i][0]);
}
// now try to solve for the test poly vector; should be that the test and
// ref are identical
SquarePolynomialVector* vec = NULL;
try {
SolveFactory fac(2, 2, 3, positions, deriv_pos, deriv_indices);
vec = fac.PolynomialSolve(values, deriv_values);
} catch (ClassicException& exc) {
std::cerr << exc.what() << std::endl;
ASSERT_TRUE(false) << "Should not throw";
}
MMatrix<double> testCoeffs = vec->GetCoefficientsAsMatrix();
ASSERT_EQ(testCoeffs.num_row(), (size_t)3);
ASSERT_EQ(testCoeffs.num_col(), (size_t)9);
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j)
EXPECT_NEAR(testCoeffs(i+1, j+1), refCoeffs(i+1, j+1), 1e-6);
}
\ No newline at end of file
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment