/* * Copyright (c) 2017, Chris Rogers * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STFC nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "gtest/gtest.h" #include "Fields/Interpolation/NDGrid.h" #include "Fields/Interpolation/Mesh.h" #include "opal_test_utilities/SilenceTest.h" namespace ndgridtest { class NDGridTest : public ::testing::Test { public: NDGridTest() : grid_m(NULL) { } void SetUp( ) { std::vector< std::vector<double> > gridCoordinates(2); gridCoordinates[0] = std::vector<double>(2, 0.); gridCoordinates[0][1] = 3.; gridCoordinates[1] = std::vector<double>(3, 1.); gridCoordinates[1][1] = 5.; gridCoordinates[1][2] = 9.; grid_m = new interpolation::NDGrid(gridCoordinates); gridCoordinates[1][2] = 10.; // force it to not be regular grid2_m = new interpolation::NDGrid(gridCoordinates); } void TearDown( ) { delete grid_m; grid_m = NULL; delete grid2_m; grid2_m = NULL; } ~NDGridTest() { } interpolation::NDGrid* grid_m; interpolation::NDGrid* grid2_m; OpalTestUtilities::SilenceTest silencer; private: }; TEST_F(NDGridTest, DefaultConstructorTest) { interpolation::NDGrid grid; EXPECT_EQ(grid.begin(), grid.end()); } // also tests size TEST_F(NDGridTest, Constructor1Test) { int size[] = {5, 6, 7, 8}; double spacing[] = {1., 2., 3., 4.}; double min[] = {-1., -2., -3., -4.}; interpolation::NDGrid grid(4, size, spacing, min); ASSERT_EQ(grid.getPositionDimension(), 4); for (int i = 0; i < 4; ++i) { ASSERT_EQ(grid.size(i), size[i]); EXPECT_NEAR(grid.coord(1, i), min[i], 1e-12) << "Failed for i " << i; EXPECT_NEAR(grid.coord(size[i], i), min[i]+spacing[i]*(size[i]-1), 1e-12) << "Failed for i " << i; } } TEST_F(NDGridTest, Constructor2Test) { std::vector<int> size(2); size[0] = 2; size[1] = 3; std::vector<const double*> gridCoordinates(2, NULL); const double vec1[] = {0., 2.}; const double vec2[] = {1., 5., 9.}; gridCoordinates[0] = vec1; gridCoordinates[1] = vec2; interpolation::NDGrid grid1(size, gridCoordinates); ASSERT_EQ(grid1.getPositionDimension(), 2); for (int i = 0; i < 2; ++i) { ASSERT_EQ(grid1.size(i), size[i]); EXPECT_NEAR(grid1.coord(1, i), gridCoordinates[i][0], 1e-12) << "Failed for i " << i; EXPECT_NEAR(grid1.coord(i+2, i), gridCoordinates[i][size[i]-1], 1e-12) << "Failed for i " << i; } } TEST_F(NDGridTest, Constructor3Test) { std::vector< std::vector<double> > gridCoordinates(2); gridCoordinates[0] = std::vector<double>(2, 0.); gridCoordinates[1] = std::vector<double>(3, 1.); gridCoordinates[1][2] = 9.; interpolation::NDGrid grid1(gridCoordinates); ASSERT_EQ(grid1.getPositionDimension(), 2); for (int i = 0; i < 2; ++i) { int size = gridCoordinates[i].size(); ASSERT_EQ(grid1.size(i), size); EXPECT_NEAR(grid1.coord(1, i), gridCoordinates[i][0], 1e-12) << "Failed for i " << i; EXPECT_NEAR(grid1.coord(i+2, i), gridCoordinates[i][size-1], 1e-12) << "Failed for i " << i; } } TEST_F(NDGridTest, CoordTest) { std::vector< std::vector<double> > gridCoordinates(2); gridCoordinates[0] = std::vector<double>(2, 0.); gridCoordinates[1] = std::vector<double>(3, 1.); gridCoordinates[1][2] = 9.; interpolation::NDGrid grid_var(gridCoordinates); const interpolation::NDGrid grid_const(gridCoordinates); for (int i = 0; i < 2; ++i) { EXPECT_NEAR(grid_var.coord(1, i), gridCoordinates[i][0], 1e-12) << "Failed for i " << i; EXPECT_NEAR(grid_const.coord(1, i), gridCoordinates[i][0], 1e-12) << "Failed for i " << i; } } TEST_F(NDGridTest, CoordVectorTest) { // and newCoordArray std::vector< std::vector<double> > gridCoordinates(2); gridCoordinates[0] = std::vector<double>(2, 0.); gridCoordinates[1] = std::vector<double>(3, 1.); gridCoordinates[1][2] = 9.; interpolation::NDGrid grid(gridCoordinates); for (int i = 0; i < 2; ++i) { std::vector<double> coords_v = grid.coordVector(i); double* coords_a = grid.newCoordArray(i); ASSERT_EQ(coords_v.size(), gridCoordinates[i].size()); for (size_t j = 0; j < gridCoordinates[i].size(); j++) { EXPECT_NEAR(coords_v[j], gridCoordinates[i][j], 1e-12); EXPECT_NEAR(coords_a[j], gridCoordinates[i][j], 1e-12); } delete[] coords_a; } } TEST_F(NDGridTest, CoordLowerBoundTest) { // first dimension ... 0., 3.; int index = -1; grid_m->coordLowerBound(-1., 0, index); EXPECT_EQ(index, -1); index = -2; grid_m->coordLowerBound(0.0001, 0, index); EXPECT_EQ(index, 0); index = -2; grid_m->coordLowerBound(2.999, 0, index); EXPECT_EQ(index, 0); index = -2; grid_m->coordLowerBound(3.001, 0, index); EXPECT_EQ(index, 1); index = -2; grid_m->coordLowerBound(1000.0001, 0, index); EXPECT_EQ(index, 1); // second dimension ... 1., 5., 9. index = -2; grid_m->coordLowerBound(0.999, 1, index); EXPECT_EQ(index, -1); index = -2; grid_m->coordLowerBound(4.999, 1, index); EXPECT_EQ(index, 0); index = -2; grid_m->coordLowerBound(8.999, 1, index); EXPECT_EQ(index, 1); index = -2; grid_m->coordLowerBound(9.0001, 1, index); EXPECT_EQ(index, 2); index = -2; grid_m->coordLowerBound(1000.0001, 1, index); EXPECT_EQ(index, 2); } TEST_F(NDGridTest, LowerBoundTest) { // first dimension ... 0., 3.; // second dimension ... 1., 5., 9. std::vector<int> index1(2, -2); std::vector<double> pos1(2, -1.); grid_m->lowerBound(pos1, index1); EXPECT_EQ(index1[0], -1); EXPECT_EQ(index1[1], -1); std::vector<int> index2(2, -2); std::vector<double> pos2(2, 4.); grid_m->lowerBound(pos2, index2); EXPECT_EQ(index2[0], 1); EXPECT_EQ(index2[1], 0); std::vector<int> index3(2, -2); std::vector<double> pos3(2, 100.); grid_m->lowerBound(pos3, index3); EXPECT_EQ(index3[0], 1); EXPECT_EQ(index3[1], 2); } TEST_F(NDGridTest, MinMaxTest) { EXPECT_EQ(grid_m->min(0), 0.); EXPECT_EQ(grid_m->min(1), 1.); EXPECT_EQ(grid_m->max(0), 3.); EXPECT_EQ(grid_m->max(1), 9.); } TEST_F(NDGridTest, SetCoordTest) { double xNew[] = {5., 10., 12., 15.}; grid_m->setCoord(0, 4, xNew); std::vector<double> xTest = grid_m->coordVector(0); EXPECT_EQ(xTest.size(), (unsigned int)4); for (size_t i = 0; i < 4; ++i) { EXPECT_EQ(xTest[i], xNew[i]); } } TEST_F(NDGridTest, BeginEndTest) { ASSERT_EQ(grid_m->begin().getState().size(), (unsigned int)2); EXPECT_EQ(grid_m->begin().getState()[0], 1); EXPECT_EQ(grid_m->begin().getState()[1], 1); ASSERT_EQ(grid_m->end().getState().size(), (unsigned int)2); EXPECT_EQ(grid_m->end().getState()[0], 3); // one past the last (2, 3) EXPECT_EQ(grid_m->end().getState()[1], 1); } TEST_F(NDGridTest, GetPositionTest) { std::vector<double> position(3, -1); interpolation::Mesh::Iterator it = grid_m->begin(); grid_m->getPosition(it, &position[0]); EXPECT_EQ(grid_m->getPositionDimension(), 2); EXPECT_EQ(position[0], 0.); EXPECT_EQ(position[1], 1.); it[0] = 2; it[1] = 3; grid_m->getPosition(it, &position[0]); EXPECT_EQ(position[0], 3.); EXPECT_EQ(position[1], 9.); } TEST_F(NDGridTest, GetSetConstantSpacingTest) { EXPECT_TRUE(grid_m->getConstantSpacing()); grid_m->setConstantSpacing(false); EXPECT_FALSE(grid_m->getConstantSpacing()); grid_m->setConstantSpacing(true); EXPECT_TRUE(grid_m->getConstantSpacing()); grid_m->setConstantSpacing(false); grid_m->setConstantSpacing(); EXPECT_TRUE(grid_m->getConstantSpacing()); EXPECT_FALSE(grid2_m->getConstantSpacing()); grid2_m->setConstantSpacing(true); EXPECT_TRUE(grid2_m->getConstantSpacing()); grid2_m->setConstantSpacing(false); EXPECT_FALSE(grid2_m->getConstantSpacing()); grid2_m->setConstantSpacing(true); grid2_m->setConstantSpacing(0.1); EXPECT_FALSE(grid2_m->getConstantSpacing()); grid2_m->setConstantSpacing(2.01); EXPECT_TRUE(grid2_m->getConstantSpacing()); } TEST_F(NDGridTest, ToIntegerTest) { interpolation::Mesh::Iterator it = grid_m->begin(); EXPECT_EQ(grid_m->toInteger(it), 0); it[0] = 2; it[1] = 3; EXPECT_EQ(grid_m->toInteger(it), 5); } TEST_F(NDGridTest, GetNearestTest) { // first dimension ... 0., 3.; // second dimension ... 1., 5., 9. std::vector<double> pos(2, 0.); interpolation::Mesh::Iterator it; pos[0] = 1.49; pos[1] = 2.99; it = grid_m->getNearest(&pos[0]); EXPECT_EQ(it[0], 1); EXPECT_EQ(it[1], 1); pos[0] = 0.49; it = grid_m->getNearest(&pos[0]); EXPECT_EQ(it[0], 1); EXPECT_EQ(it[1], 1); pos[1] = 9.49; it = grid_m->getNearest(&pos[0]); EXPECT_EQ(it[0], 1); EXPECT_EQ(it[1], 3); pos[0] = 3.49; it = grid_m->getNearest(&pos[0]); EXPECT_EQ(it[0], 2); EXPECT_EQ(it[1], 3); } TEST_F(NDGridTest, DualTest) { using interpolation::NDGrid; NDGrid* new_grid = dynamic_cast<NDGrid*>(grid2_m->dual()); std::vector<std::vector<double> > ref = { {1.5}, {3.0, 7.5} }; ASSERT_EQ(new_grid->getPositionDimension(), int(ref.size())); for (size_t i = 0; i < ref.size(); ++i) { ASSERT_EQ(new_grid->size(i), int(ref[i].size())); for (size_t j = 0; j < ref[i].size(); ++j) { EXPECT_NEAR(new_grid->coordVector(i)[j], ref[i][j], 1e-9) << i << " " << j; } } } } // namespace ndgridtest