/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2016 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 .
 */
/*
 * ExportGraph_ToJobsUnitTest.cpp
 *
 *  Created on: Mar 10, 2016
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
using namespace std;
#include 
#include 
#include 
#include "ExportGraph_ToJobsUnitTest.hpp"
#include 
#include 
#include 
#include "CodePatterns/Assert.hpp"
#include "Fragmentation/Exporters/ExportGraph_ToJobs.hpp"
#include "World.hpp"
#ifdef HAVE_TESTRUNNER
#include "UnitTestMain.hpp"
#endif /*HAVE_TESTRUNNER*/
/********************************************** Test classes **************************************/
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION( ExportGraph_ToJobsTest );
void ExportGraph_ToJobsTest::setUp()
{
  // failing asserts should be thrown
  ASSERT_DO(Assert::Throw);
//  setVerbosity(6);
}
void ExportGraph_ToJobsTest::tearDown()
{
  World::purgeInstance();
}
/** UnitTest for getGridExtentsForGivenBoundingBox().
 */
void ExportGraph_ToJobsTest::getGridExtentsForGivenBoundingBox_Test()
{
  double begin[NDIM] = { 0., 0., 0. };
  double end[NDIM] = { 40., 40., 40. };
  double level = 5;
  const SamplingGridProperties domain(begin, end, level);
  double empty_boundary = 5.;
  std::vector< Vector > fragment_extents =
      boost::assign::list_of
      ( Vector( 5.2, 5.2, 5.2) ) // simple test
      ( Vector( 5., 5., 5.) ); // simple test: higher and lower center is same point
  const double delta = 2.1;
  for (std::vector< Vector >::const_iterator iter = fragment_extents.begin();
      iter != fragment_extents.end(); ++iter)
  {
    const Vector &fragment_extent = *iter;
    for (double x = 0.; x <= end[0]-fragment_extent[0]; x+= delta)
      for (double y = 0.; y <= end[1]-fragment_extent[1]; y+= delta)
        for (double z = 0.; z <= end[2]-fragment_extent[2]; z+= delta) {
          Vector minimum( x, y, z);
          Vector maximum = minimum+fragment_extent;
          const SamplingGridProperties grid =
              ExportGraph_ToJobs::getGridExtentsForGivenBoundingBox(
                  std::make_pair(minimum, maximum), domain, empty_boundary);
          for (size_t i=0;i= domain.begin[i] );
            CPPUNIT_ASSERT( grid.end[i] <= domain.end[i] );
            // check the desired fragment extent plus boundary is contained
            const double extent = grid.end[i] - grid.begin[i];
            CPPUNIT_ASSERT (extent > (2.*empty_boundary+fragment_extent[i]));
            // check the number of grid points of the grid is divisible integer and ...
            const double delta = domain.getDeltaPerAxis(i); // grid would give a screwed delta that matches
            const unsigned int gridpoints = extent/delta;
            CPPUNIT_ASSERT ( fabs( extent/delta - (double)gridpoints) < std::numeric_limits::epsilon()*1e4 );
            // ... divisible by 2
            const double power = log(extent/delta)/log(2.);
            const unsigned int power_of_two = power;
            CPPUNIT_ASSERT_EQUAL( (int)power_of_two, grid.level );
            CPPUNIT_ASSERT ( fabs( power - (double)power_of_two) < std::numeric_limits::epsilon()*1e4 );
            CPPUNIT_ASSERT ( fabs( ::pow(2., power_of_two) - gridpoints) < std::numeric_limits::epsilon()*1e4);
            // check that fragment grid's begin and end are on domain discrete points
            const double lower_begin = domain.getNearestLowerGridPoint(grid.begin[i], i);
            const double higher_begin = domain.getNearestHigherGridPoint(grid.begin[i], i);
            CPPUNIT_ASSERT( fabs( lower_begin - higher_begin) < std::numeric_limits::epsilon()*1e4 );
            const double lower_end = domain.getNearestLowerGridPoint(grid.end[i], i);
            const double higher_end = domain.getNearestHigherGridPoint(grid.end[i], i);
            CPPUNIT_ASSERT( fabs( lower_end - higher_end) < std::numeric_limits::epsilon()*1e4 );
          }
        }
  }
}
/** UnitTest for setAcceptableFragmentLevel().
 */
void ExportGraph_ToJobsTest::setAcceptableFragmentLevel_Test()
{
  double begin[NDIM] = { 0., 0., 0. };
  double end[NDIM] = { 20., 20., 20. };
  double level = 5;
  const double min_meshwidth = 20./::pow(2., level);
  const unsigned int threshold_level = 9;
  const double threshold = 20./::pow(2., threshold_level);
  const double delta = 0.05;
  unsigned int oldlevel=0;
  for (double max_meshwidth = min_meshwidth+1.; max_meshwidth >= threshold; max_meshwidth -= delta) {
    SamplingGridProperties domain(begin, end, level);
    ExportGraph_ToJobs::setAcceptableFragmentLevel(domain, max_meshwidth);
    // must always be larger equal to old value
    CPPUNIT_ASSERT( (unsigned int)domain.level >= oldlevel );
    oldlevel = domain.level;
    // may never get smaller than minimal value
    CPPUNIT_ASSERT( (unsigned int)domain.level >= 1 );
    // cannot get larger than upper most level
    CPPUNIT_ASSERT( (unsigned int)domain.level <= threshold_level );
  }
}