/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2012 University of Bonn. All rights reserved. * Copyright (C) 2013 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder 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. * * MoleCuilder 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 MoleCuilder. If not, see . */ /* * SamplingGridUnitTest.cpp * * Created on: Jul 29, 2012 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif using namespace std; #include #include #include // include headers that implement a archive in simple text format #include #include #include "SamplingGridUnitTest.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include #include #include #ifdef HAVE_TESTRUNNER #include "UnitTestMain.hpp" #endif /*HAVE_TESTRUNNER*/ using namespace boost::assign; /********************************************** Test classes **************************************/ const double grid_value=1.; #define NUMBEROFSAMPLES(n) (size_t)(pow(pow(2,n),(int)NDIM)) #define DOMAINVOLUME(l) (size_t)pow(l,(int)NDIM) // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( SamplingGridTest ); void SamplingGridTest::setUp() { // failing asserts should be thrown ASSERT_DO(Assert::Throw); // create the grid const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 1., 1., 1. }; for (size_t i=0; i< DOMAINVOLUME(1)*NUMBEROFSAMPLES(2); ++i) values += grid_value; grid = new SamplingGrid(begin, end, 2, values); CPPUNIT_ASSERT_EQUAL( grid_value, *(grid->sampled_grid.begin()) ); } void SamplingGridTest::tearDown() { delete grid; } /** UnitTest on equivalent combination of props and values */ void SamplingGridTest::equivalentGrids_Test() { // check illegal grid const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 1., 1., 1. }; SamplingGridProperties illegal_props(begin, end, 5); SamplingGridProperties legal_props(begin, end, 2); CPPUNIT_ASSERT( !grid->isEquivalent(illegal_props) ); CPPUNIT_ASSERT( grid->isEquivalent(legal_props) ); SamplingGrid::sampledvalues_t illegal_values; for (size_t i=0; i< NUMBEROFSAMPLES(1); ++i) illegal_values += 1.5; SamplingGrid::sampledvalues_t legal_values; for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i) legal_values += 1.5; #ifndef NDEBUG // throws because props and size of illegal_values don't match std::cout << "The following assertion is intended and does not indicate a failure of the test." << std::endl; CPPUNIT_ASSERT_THROW( SamplingGrid illegal_grid(illegal_props, illegal_values), Assert::AssertionFailure ); std::cout << "The following assertion is intended and does not indicate a failure of the test." << std::endl; CPPUNIT_ASSERT_THROW( SamplingGrid illegal_grid(legal_props, illegal_values), Assert::AssertionFailure ); std::cout << "The following assertion is intended and does not indicate a failure of the test." << std::endl; CPPUNIT_ASSERT_THROW( SamplingGrid illegal_grid(illegal_props, legal_values), Assert::AssertionFailure ); #endif // check that grid is still the same for (SamplingGrid::sampledvalues_t::const_iterator iter = grid->sampled_grid.begin(); iter != grid->sampled_grid.end(); ++iter) CPPUNIT_ASSERT_EQUAL( grid_value, *iter ); } /** UnitTest on compatible combination of props and values */ void SamplingGridTest::compatibleGrids_Test() { // check illegal grid const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 1., 1., 1. }; const double otherend[NDIM] = { 2.5, 2.5, 2.5 }; SamplingGridProperties illegal_props(begin, otherend, 5); SamplingGridProperties legal_props(begin, end, 3); CPPUNIT_ASSERT( !grid->isCompatible(illegal_props) ); CPPUNIT_ASSERT( grid->isCompatible(legal_props) ); SamplingGrid::sampledvalues_t illegal_values; for (size_t i=0; i< NUMBEROFSAMPLES(1); ++i) illegal_values += 1.5; SamplingGrid::sampledvalues_t legal_values; for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i) legal_values += 1.5; #ifndef NDEBUG // throws because props and size of illegal_values don't match std::cout << "The following assertion is intended and does not indicate a failure of the test." << std::endl; CPPUNIT_ASSERT_THROW( SamplingGrid illegal_grid(illegal_props, illegal_values), Assert::AssertionFailure ); std::cout << "The following assertion is intended and does not indicate a failure of the test." << std::endl; CPPUNIT_ASSERT_THROW( SamplingGrid illegal_grid(legal_props, illegal_values), Assert::AssertionFailure ); std::cout << "The following assertion is intended and does not indicate a failure of the test." << std::endl; CPPUNIT_ASSERT_THROW( SamplingGrid illegal_grid(illegal_props, legal_values), Assert::AssertionFailure ); #endif // check that grid is still the same for (SamplingGrid::sampledvalues_t::const_iterator iter = grid->sampled_grid.begin(); iter != grid->sampled_grid.end(); ++iter) CPPUNIT_ASSERT_EQUAL( grid_value, *iter ); } /** UnitTest for isCongruent() */ void SamplingGridTest::isCongruent_Test() { const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 2., 2., 2. }; const double otherbegin[NDIM] = { 0.1, 0.1, 0.1 }; const double otherend[NDIM] = { 1., 1., 1. }; SamplingGridProperties illegal_begin_props(otherbegin, end, 5); SamplingGridProperties illegal_end_props(begin, otherend, 5); SamplingGridProperties illegal_level_props(begin, end, 5); SamplingGridProperties legal_props(begin, end, 2); // differing windows // const double begin_window[NDIM] = { 0.5, 0.5, 0.5 }; // const double end_window[NDIM] = { 1., 1., 1. }; const double otherbegin_window[NDIM] = { 0.45, 0.45, 0.45 }; const double otherend_window[NDIM] = { 1.05, 1.05, 1.05 }; // check that incompatible grid are also incongruent SamplingGrid default_grid(legal_props); // note that we always construct a temporary SamplingGrid from given props CPPUNIT_ASSERT( default_grid.isEquivalent(illegal_begin_props) == default_grid.isCongruent(illegal_begin_props)); CPPUNIT_ASSERT( default_grid.isEquivalent(illegal_end_props) == default_grid.isCongruent(illegal_end_props)); CPPUNIT_ASSERT( default_grid.isEquivalent(illegal_level_props) == default_grid.isCongruent(illegal_level_props)); CPPUNIT_ASSERT( default_grid.isEquivalent(legal_props) == default_grid.isCongruent(legal_props) ); default_grid.setWindowSize(begin, end); // same window { SamplingGrid illegal_begin_grid(illegal_begin_props); SamplingGrid illegal_end_grid(illegal_end_props); SamplingGrid illegal_level_grid(illegal_level_props); SamplingGrid legal_grid(legal_props); illegal_begin_grid.setWindowSize(begin, end); illegal_end_grid.setWindowSize(begin, end); illegal_level_grid.setWindowSize(begin, end); legal_grid.setWindowSize(begin, end); CPPUNIT_ASSERT( !illegal_begin_grid.isCongruent(default_grid) ); CPPUNIT_ASSERT( !illegal_end_grid.isCongruent(default_grid) ); CPPUNIT_ASSERT( !illegal_level_grid.isCongruent(default_grid) ); CPPUNIT_ASSERT( legal_grid.isCongruent(default_grid) ); } // different begin { SamplingGrid illegal_begin_grid(illegal_begin_props); SamplingGrid illegal_end_grid(illegal_end_props); SamplingGrid illegal_level_grid(illegal_level_props); SamplingGrid legal_grid(legal_props); illegal_begin_grid.setWindowSize(otherbegin_window, end); illegal_end_grid.setWindowSize(otherbegin_window, end); illegal_level_grid.setWindowSize(otherbegin_window, end); legal_grid.setWindowSize(begin, end); CPPUNIT_ASSERT( !illegal_begin_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( !illegal_end_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( !illegal_level_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( legal_grid.isCongruent(default_grid) ); } // different end { SamplingGrid illegal_begin_grid(illegal_begin_props); SamplingGrid illegal_end_grid(illegal_end_props); SamplingGrid illegal_level_grid(illegal_level_props); SamplingGrid legal_grid(legal_props); illegal_begin_grid.setWindowSize(begin, otherend_window); illegal_end_grid.setWindowSize(begin, otherend_window); illegal_level_grid.setWindowSize(begin, otherend_window); legal_grid.setWindowSize(begin, end); CPPUNIT_ASSERT( !illegal_begin_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( !illegal_end_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( !illegal_level_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( legal_grid.isCongruent(default_grid) ); } // different begin and end { SamplingGrid illegal_begin_grid(illegal_begin_props); SamplingGrid illegal_end_grid(illegal_end_props); SamplingGrid illegal_level_grid(illegal_level_props); SamplingGrid legal_grid(legal_props); illegal_begin_grid.setWindowSize(otherbegin_window, otherend_window); illegal_end_grid.setWindowSize(otherbegin_window, otherend_window); illegal_level_grid.setWindowSize(otherbegin_window, otherend_window); legal_grid.setWindowSize(begin, end); CPPUNIT_ASSERT( !illegal_begin_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( !illegal_end_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( !illegal_level_grid.isCongruent(legal_grid) ); CPPUNIT_ASSERT( legal_grid.isCongruent(default_grid) ); } } /** UnitTest for integral() */ void SamplingGridTest::integral_Test() { double sum = 0.; sum = std::accumulate( grid->sampled_grid.begin(), grid->sampled_grid.end(), sum ); CPPUNIT_ASSERT_EQUAL( sum*grid->getVolume()/grid->getWindowGridPoints(), grid->integral() ); } /** UnitTest for getVolume() */ void SamplingGridTest::getVolume_Test() { CPPUNIT_ASSERT_EQUAL( 1., grid->getVolume() ); } /** UnitTest for getWindowSize() */ void SamplingGridTest::getWindowSize_Test() { // check size of default grid CPPUNIT_ASSERT_EQUAL( (size_t)(NUMBEROFSAMPLES(grid->level)), grid->getWindowGridPoints() ); // create another one and check its size, too const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 1., 1., 1. }; for (size_t level = 3; level<=6; ++level) { values.clear(); for (size_t i=0; i< NUMBEROFSAMPLES(level); ++i) values += grid_value; delete grid; // use other pointer in case something fails SamplingGrid *tmpgrid = new SamplingGrid(begin, end, level, values); grid = tmpgrid; CPPUNIT_ASSERT_EQUAL( (size_t)NUMBEROFSAMPLES(level), grid->getWindowGridPoints() ); } } /** UnitTest for extendWindow() */ void SamplingGridTest::extendWindow_Test() { // we have a grid with size of one, extend to twice the size and check const double begin[NDIM] = { 0., 0., 0. }; const double size = 2.; const double end[NDIM] = { size, size, size }; double offset[NDIM]; for (offset[0] = 0.; offset[0] <= 1.; offset[0] += .5) for (offset[1] = 0.; offset[1] <= 1.; offset[1] += .5) for (offset[2] = 0.; offset[2] <= 1.; offset[2] += .5) { const double window_begin[NDIM] = { 0.+offset[0], 0.+offset[1], 0.+offset[2]}; const double window_end[NDIM] = { 1.+offset[0], 1.+offset[1], 1.+offset[2]}; SamplingGrid newgrid(begin, end, 2); newgrid.setWindowSize(window_begin, window_end); // resize values by hand to new window size. Otherwise they get zero'd. newgrid.sampled_grid = values; newgrid.sampled_grid.resize(NUMBEROFSAMPLES(1)); newgrid.extendWindow(begin, end); // check integral CPPUNIT_ASSERT_EQUAL( grid_value/(NUMBEROFSAMPLES(grid->level)/NUMBEROFSAMPLES(grid->level)), grid->integral() ); // check number of points CPPUNIT_ASSERT_EQUAL( (size_t)NUMBEROFSAMPLES(grid->level), grid->getWindowGridPoints() ); } } /** UnitTest for extendWindow() with asymmetric values */ void SamplingGridTest::extendWindow_asymmetric_Test() { std::cout << "SamplingGridTest::extendWindow_asymmetric_Test()" << std::endl; const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 2., 2., 2. }; double offset[NDIM]; for (offset[0] = 0.; offset[0] <= 1.; offset[0] += .5) for (offset[1] = 0.; offset[1] <= 1.; offset[1] += .5) for (offset[2] = 0.; offset[2] <= 1.; offset[2] += .5) { const double window_begin[NDIM] = { 0.+offset[0], 0.+offset[1], 0.+offset[2]}; const double window_end[NDIM] = { 1.+offset[0], 1.+offset[1], 1.+offset[2]}; SamplingGrid newgrid(begin, end, 2); CPPUNIT_ASSERT_EQUAL( (size_t)0, newgrid.getWindowGridPoints() ); newgrid.setWindowSize(window_begin, window_end); // window size is only half of domain size const size_t max_samples = NUMBEROFSAMPLES(newgrid.level)*pow(0.5,(int)NDIM); for (size_t i=0; i< max_samples; ++i) newgrid.sampled_grid += grid_value*i; const size_t sum_weight = (max_samples)*(max_samples-1)/2; const double integral = newgrid.integral(); newgrid.extendWindow(begin, end); // check that integral has remained the same CPPUNIT_ASSERT_EQUAL( integral, newgrid.integral() ); CPPUNIT_ASSERT_EQUAL( grid_value*sum_weight/DOMAINVOLUME(2), newgrid.integral() ); } } /** UnitTest for addOntoWindow() */ void SamplingGridTest::addOntoWindow_Test() { // first window is from (0,0,0) to (1,1,1) CPPUNIT_ASSERT_EQUAL( 1.*grid_value, grid->integral() ); // create values for half-sized window values.clear(); for (size_t i=0; i< (size_t)pow(.5*pow(2,2),(int)NDIM); ++i) values += grid_value; // check that too large a window throws #ifndef NDEBUG const double begin[NDIM] = { .5, .5, .5 }; const double wrongend[NDIM] = { 1.5, 1.5, 1.5 }; std::cout << "The following assertion is intended and does not indicate a failure of the test." << std::endl; CPPUNIT_ASSERT_THROW( grid->addOntoWindow(begin, wrongend, values, +1.), Assert::AssertionFailure ); #endif // create another window from (.5,.5,.5) to (1., 1., 1.) double offset[NDIM]; for (offset[0] = 0.; offset[0] <= .5; offset[0] += .5) for (offset[1] = 0.; offset[1] <= .5; offset[1] += .5) for (offset[2] = 0.; offset[2] <= .5; offset[2] += .5) { const double window_begin[NDIM] = { 0.+offset[0], 0.+offset[1], 0.+offset[2]}; const double window_end[NDIM] = { .5+offset[0], .5+offset[1], .5+offset[2]}; SamplingGrid newgrid(*grid); // now perform working operation newgrid.addOntoWindow(window_begin, window_end, values, +1.); // check integral to be one and one eighth times the old value CPPUNIT_ASSERT_EQUAL( (1.+pow(.5,(int)NDIM))*grid_value, newgrid.integral() ); } } /** UnitTest for addOntoWindow() with asymmetric values */ void SamplingGridTest::addOntoWindow_asymmetric_Test() { const size_t size = grid->end[0]-grid->begin[0]; // check with asymmetric values grid->sampled_grid.clear(); grid->sampled_grid.resize(DOMAINVOLUME(size)*NUMBEROFSAMPLES(grid->level), 0.); for (size_t i=0;ilevel*(grid->end[0]-grid->begin[0]);++i) grid->sampled_grid[(i*2+0)*2+0] += .5*grid_value; for (size_t i=0;ilevel*(grid->end[1]-grid->begin[1]);++i) grid->sampled_grid[(0*2+i)*2+0] += 1.*grid_value; for (size_t i=0;ilevel*(grid->end[2]-grid->begin[2]);++i) grid->sampled_grid[(0*2+0)*2+i] += 1.5*grid_value; const double integral = grid->integral(); // now perform working operation grid->addOntoWindow(grid->begin, grid->end, values, +1.); // values is equal to integral of 1. CPPUNIT_ASSERT_EQUAL( 1.+integral, grid->integral() ); } /** UnitTest for operator+=() */ void SamplingGridTest::operatorPlusEqual_Test() { // create other grid const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 1., 1., 1. }; SamplingGrid::sampledvalues_t othervalues; const double othergrid_value = 1.5; for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i) othervalues += othergrid_value; SamplingGrid othergrid(begin, end, 2, othervalues); CPPUNIT_ASSERT_EQUAL( othergrid_value, *(othergrid.sampled_grid.begin()) ); // perform operation CPPUNIT_ASSERT_NO_THROW( *grid += othergrid ); // check the contents of the grid const double sum = grid_value+othergrid_value; for (SamplingGrid::sampledvalues_t::const_iterator iter = grid->sampled_grid.begin(); iter != grid->sampled_grid.end(); ++iter) CPPUNIT_ASSERT_EQUAL( sum, *iter ); } /** UnitTest for operator-=() */ void SamplingGridTest::operatorMinusEqual_Test() { // create other grid const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 1., 1., 1. }; SamplingGrid::sampledvalues_t othervalues; const double othergrid_value = 1.5; for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i) othervalues += othergrid_value; SamplingGrid othergrid(begin, end, 2, othervalues); CPPUNIT_ASSERT_EQUAL( othergrid_value, *(othergrid.sampled_grid.begin()) ); // perform operation CPPUNIT_ASSERT_NO_THROW( *grid -= othergrid ); // check the contents of the grid const double difference = grid_value-othergrid_value; for (SamplingGrid::sampledvalues_t::const_iterator iter = grid->sampled_grid.begin(); iter != grid->sampled_grid.end(); ++iter) CPPUNIT_ASSERT_EQUAL( difference, *iter ); } /** UnitTest for operator==() */ void SamplingGridTest::equality_Test() { const double begin[NDIM] = { 0., 0., 0. }; const double otherbegin[NDIM] = { .5, 0.1, -0.5 }; const double end[NDIM] = { 1., 1., 1. }; const double otherend[NDIM] = { 2., 2., 2. }; const double begin_window[NDIM] = { 0., 0., 0. }; const double otherbegin_window[NDIM] = { .75, 0.1, 0. }; const double end_window[NDIM] = { 1., 1., 1. }; const double otherend_window[NDIM] = { .9, .9, .9 }; // create other grid SamplingGrid samegrid(begin, end, 2, values); SamplingGrid differentbegin(otherbegin, end, 2, values); SamplingGrid differentend(begin, otherend, 2, values); SamplingGrid::sampledvalues_t morevalues; { const double othergrid_value = 1.5; for (size_t i=0; i< NUMBEROFSAMPLES(4); ++i) morevalues += othergrid_value; } SamplingGrid differentlevel(begin, end, 4, morevalues); SamplingGrid::sampledvalues_t othervalues; { const double othergrid_value = 1.5; for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i) othervalues += othergrid_value; } SamplingGrid differentvalues(begin, end, 2, othervalues); // check for same level, begin, and end CPPUNIT_ASSERT( *grid == *grid ); CPPUNIT_ASSERT( *grid == samegrid ); CPPUNIT_ASSERT( samegrid == *grid); CPPUNIT_ASSERT( *grid != differentbegin); CPPUNIT_ASSERT( differentbegin != *grid); CPPUNIT_ASSERT( *grid != differentend ); CPPUNIT_ASSERT( differentend != *grid ); CPPUNIT_ASSERT( *grid != differentlevel ); CPPUNIT_ASSERT( differentlevel != *grid ); // check for all but differing values CPPUNIT_ASSERT( *grid != differentvalues ); CPPUNIT_ASSERT( differentvalues != *grid ); // check for different windows SamplingGrid differentwindowbegin(begin, end, 2); differentwindowbegin.setWindow(otherbegin_window, end_window); SamplingGrid differentwindowend(begin, end, 2); differentwindowend.setWindow(begin_window, otherend_window); CPPUNIT_ASSERT( *grid != differentwindowbegin ); CPPUNIT_ASSERT( differentwindowbegin != *grid ); CPPUNIT_ASSERT( *grid != differentwindowend ); CPPUNIT_ASSERT( differentwindowend != *grid ); // check against ZeroInstance CPPUNIT_ASSERT( *grid != ZeroInstance() ); CPPUNIT_ASSERT( samegrid != ZeroInstance() ); CPPUNIT_ASSERT( differentbegin != ZeroInstance() ); CPPUNIT_ASSERT( differentend != ZeroInstance() ); CPPUNIT_ASSERT( differentlevel != ZeroInstance() ); CPPUNIT_ASSERT( differentvalues != ZeroInstance() ); CPPUNIT_ASSERT( differentwindowbegin != ZeroInstance() ); CPPUNIT_ASSERT( differentwindowend != ZeroInstance() ); } /** UnitTest for serialization */ void SamplingGridTest::serializeTest() { // serialize std::stringstream outputstream; boost::archive::text_oarchive oa(outputstream); oa << grid; // deserialize SamplingGrid *samegrid = NULL; std::stringstream returnstream(outputstream.str()); boost::archive::text_iarchive ia(returnstream); ia >> samegrid; CPPUNIT_ASSERT( samegrid != NULL ); CPPUNIT_ASSERT( *grid == *samegrid ); delete samegrid; } #ifdef HAVE_INLINE inline #endif static int calculateIndex(const int N[NDIM], const int &_length) { return N[2] + N[1]*_length + N[0]*_length*_length; } #ifdef HAVE_INLINE inline #endif static double calculateDistanceSquared(const int N[NDIM], const int &_length) { return ::pow(N[0]/(double)_length-.5,2) + ::pow(N[1]/(double)_length-.5,2) + ::pow(N[2]/(double)_length-.5,2); } #ifdef HAVE_INLINE inline #endif static double getBoundaryCaseFactor(const int N[NDIM], const int &_length) { static double third_two=::pow(4., 1./3.); double returnthreshold = 1.; for (size_t i=0;i 0 grid.getNearestHigherGridPoint(0.5, 2) }; // index 1 -> 0 const double window_end[NDIM] = { grid.getNearestLowerGridPoint(1.5, 0), // index 3 -> 4 grid.getNearestLowerGridPoint(1.5, 1), // index 3 -> 4 grid.getNearestLowerGridPoint(1.5, 2) }; // index 3 -> 4 grid.setWindow(window_begin, window_end); grid.addOntoWindow(window_begin, window_end, values, +1.); grid.padWithZerosForEvenNumberedSamples(); SamplingGrid checkgrid(begin, end, 2); const double check_window_begin[NDIM] = { checkgrid.getNearestHigherGridPoint(1., 0), checkgrid.getNearestHigherGridPoint(0., 1), checkgrid.getNearestHigherGridPoint(0., 2) }; const double check_window_end[NDIM] = { checkgrid.getNearestHigherGridPoint(2., 0), checkgrid.getNearestHigherGridPoint(2., 1), checkgrid.getNearestHigherGridPoint(2., 2) }; checkgrid.setWindow(check_window_begin, check_window_end); checkgrid.addOntoWindow(check_window_begin, check_window_end, checkvalues, +1.); std::cout << " grid value " << grid.sampled_grid << std::endl; std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl; CPPUNIT_ASSERT_EQUAL( checkgrid.sampled_grid.size(), grid.sampled_grid.size()); CPPUNIT_ASSERT_EQUAL( checkgrid, grid ); } } /** UnitTest for downsample() */ void SamplingGridTest::downsample_gridTest() { const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 1., 1., 1. }; // simple test, one level difference, same value everywhere { SamplingGrid::sampledvalues_t checkvalues; SamplingGrid::sampledvalues_t othervalues; const double othergrid_value = 1.5; for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i) checkvalues += othergrid_value; for (size_t i=0; i< NUMBEROFSAMPLES(3); ++i) othervalues += othergrid_value; SamplingGrid largegrid(begin, end, 3, othervalues); // std::cout << " largegrid value " << largegrid.sampled_grid << std::endl; SamplingGrid smallgrid(begin, end, 2); SamplingGrid::downsample(smallgrid, largegrid, 2); SamplingGrid checkgrid(begin, end, 2, checkvalues); // std::cout << " smallgrid value " << smallgrid.sampled_grid << std::endl; // std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl; CPPUNIT_ASSERT_EQUAL( smallgrid, checkgrid ); } // simple test, two level difference, same value everywhere { SamplingGrid::sampledvalues_t checkvalues; SamplingGrid::sampledvalues_t othervalues; const double othergrid_value = 1.5; for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i) checkvalues += othergrid_value; for (size_t i=0; i< NUMBEROFSAMPLES(4); ++i) othervalues += othergrid_value; SamplingGrid largegrid(begin, end, 4, othervalues); // std::cout << " largegrid value " << largegrid.sampled_grid << std::endl; SamplingGrid smallgrid(begin, end, 2); SamplingGrid::downsample(smallgrid, largegrid, 2); SamplingGrid checkgrid(begin, end, 2, checkvalues); // std::cout << " smallgrid value " << smallgrid.sampled_grid << std::endl; // std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl; CPPUNIT_ASSERT_EQUAL( smallgrid, checkgrid ); } // same grid, window equals grids, ever larger largegrids const int base_level = 2; for (int grid_difference = 1; grid_difference <= 3; ++grid_difference) { // LOG(2, "Checking with difference " << grid_difference); const int length_c = ::pow(2, base_level); const int length_f = ::pow(2, base_level+grid_difference); SamplingGrid::sampledvalues_t checkvalues((int)::pow(length_c, (int)NDIM), 0.); SamplingGrid::sampledvalues_t othervalues((int)::pow(length_f, (int)NDIM), 0.); int N[NDIM]; for (N[0]=0; N[0]< length_f; ++N[0]) { for (N[1]=0; N[1]< length_f; ++N[1]) { for (N[2]=0; N[2]< length_f; ++N[2]) { const int index = calculateIndex(N, length_f); const double dist = calculateDistanceSquared(N, length_f); othervalues[index] = cos(M_PI*dist/1.5); } } } for (N[0]=0; N[0]< length_c; ++N[0]) { for (N[1]=0; N[1]< length_c; ++N[1]) { for (N[2]=0; N[2]< length_c; ++N[2]) { const int index = calculateIndex(N, length_c); const double dist = calculateDistanceSquared(N, length_c); checkvalues[index] = cos(M_PI*dist/1.5); } } } SamplingGrid largegrid(begin, end, base_level+grid_difference, othervalues); // std::cout << " largegrid value " << largegrid.sampled_grid << std::endl; SamplingGrid smallgrid(begin, end, base_level); SamplingGrid::downsample(smallgrid, largegrid, base_level); SamplingGrid checkgrid(begin, end, base_level, checkvalues); // std::cout << " smallgrid value " << smallgrid.sampled_grid << std::endl; // std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl; const double threshold = 3.2e-2; // we skip the first value as checkvalues[0] is always zero, hard to get from downsampling for (N[0]=1; N[0]< length_c; ++N[0]) for (N[1]=0; N[1]< length_c; ++N[1]) for (N[2]=0; N[2]< length_c; ++N[2]) { const double check_threshold = threshold*(1.+grid_difference/4.)*getBoundaryCaseFactor(N, length_c); const int index = calculateIndex(N, length_c); // std::cout << "Comparing " // << fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index])) // << " < " << check_threshold << std::endl; CPPUNIT_ASSERT( fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index])) < check_threshold); // if (fabs(checkgrid.sampled_grid[index]) > 1e-10) { // std::cout << "Comparing " // << fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index])/checkgrid.sampled_grid[index]) // << " < " << check_threshold << std::endl; // CPPUNIT_ASSERT( // fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index])/checkgrid.sampled_grid[index]) < check_threshold); // } } } } /** UnitTest for downsample() */ void SamplingGridTest::downsample_smallerwindowTest() { const double begin[NDIM] = { 0., 0., 0. }; const double end[NDIM] = { 2., 2., 2. }; // same grid, window is half of grid, different level by one const int base_level = 3; for (int grid_difference = 1; grid_difference <= 3; ++grid_difference) { // LOG(2, "Checking with difference " << grid_difference); const int window_length_c = ::pow(2, base_level-1); const int window_length_f = ::pow(2, base_level+grid_difference-1); SamplingGrid::sampledvalues_t checkvalues((int)::pow(window_length_c, (int)NDIM), 0.); SamplingGrid::sampledvalues_t othervalues((int)::pow(window_length_f, (int)NDIM), 0.); int N[NDIM]; for (N[0]=0; N[0]< window_length_f; ++N[0]) { for (N[1]=0; N[1]< window_length_f; ++N[1]) { for (N[2]=0; N[2]< window_length_f; ++N[2]) { const int index = calculateIndex(N, window_length_f); const double dist = calculateDistanceSquared(N, window_length_f); othervalues[index] = cos(M_PI*dist/1.5); } } } for (N[0]=0; N[0]< window_length_c; ++N[0]) { for (N[1]=0; N[1]< window_length_c; ++N[1]) { for (N[2]=0; N[2]< window_length_c; ++N[2]) { const int index = calculateIndex(N, window_length_c); const double dist = calculateDistanceSquared(N, window_length_c); checkvalues[index] = cos(M_PI*dist/1.5); } } } /** Here, we must initialize the larger grid with zero window first and * then add the values into the smaller window. */ SamplingGrid largegrid(begin, end, base_level+grid_difference); const double window_begin[NDIM] = { largegrid.getNearestHigherGridPoint(0.5, 0), largegrid.getNearestHigherGridPoint(0.5, 1), largegrid.getNearestHigherGridPoint(0.5, 2) }; const double window_end[NDIM] = { largegrid.getNearestLowerGridPoint(1.5, 0), largegrid.getNearestLowerGridPoint(1.5, 1), largegrid.getNearestLowerGridPoint(1.5, 2) }; largegrid.setWindow(window_begin, window_end); largegrid.addOntoWindow(window_begin, window_end, othervalues, +1.); // std::cout << " largegrid value " << largegrid.sampled_grid << std::endl; // smallgrid is downsample from full large grid SamplingGrid smallgrid(begin, end, base_level); SamplingGrid::downsample(smallgrid, largegrid, base_level); // std::cout << " smallgrid value " << smallgrid.sampled_grid << std::endl; // checkgrid is created in the same way as the large grid (only with smaller level) SamplingGrid checkgrid(begin, end, base_level); checkgrid.setWindow(window_begin, window_end); checkgrid.addOntoWindow(window_begin, window_end, checkvalues, +1.); // std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl; // then we compare over the full length /** Note that the threshold does not get better with increasing grid_difference, * on the contrary! For a grid_difference of 1, the finer grid is exact as it * directly sampled from the function. For a larger grid_difference, the finer * grid (being one level away from the desired coarse grid) is just an * approximation although obtained from a finer sampling. Hence, the larger the * grid_difference, the worse is the smallgrid with respect to checkgrid. */ const double threshold = 3.2e-2; // we skip the first value as checkvalues[0] is always zero, hard to get from downsampling for (N[0]=1; N[0]< window_length_c; ++N[0]) for (N[1]=0; N[1]< window_length_c; ++N[1]) for (N[2]=0; N[2]< window_length_c; ++N[2]) { const double check_threshold = threshold*(1.+grid_difference/4.)*getBoundaryCaseFactor(N, window_length_c); const int index = calculateIndex(N, window_length_c); const double difference = fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index])); // std::cout << "Comparing |" // << scientific // << smallgrid.sampled_grid[index] << " - " // << checkgrid.sampled_grid[index] << "| = " // << fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index])) // << " < " << check_threshold << " => " // << fixed << setprecision(2) // << 100*difference/threshold // << " %, compare to " << 100*(1.+grid_difference/4.)*getBoundaryCaseFactor(N, window_length_c) // << " %" << std::endl; CPPUNIT_ASSERT( difference < check_threshold ); } } }