Ignore:
Timestamp:
Sep 14, 2016, 6:42:53 PM (8 years ago)
Author:
Frederik Heber <heber@…>
Branches:
Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_StructOpt_integration_tests, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, GeometryObjects, Gui_displays_atomic_force_velocity, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, RotateToPrincipalAxisSystem_UndoRedo, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, Ubuntu_1604_changes, stable
Children:
91e7658
Parents:
cb30d9
git-author:
Frederik Heber <heber@…> (06/08/16 13:22:11)
git-committer:
Frederik Heber <heber@…> (09/14/16 18:42:53)
Message:

SamplingGrid has downsample() function.

  • we need this when small fragment grids are calculated at a higher resolution than full_sample grid is supposed to be calculated at.
  • extended SamplingGridUnitTest to downsample() function, needed special attention on boundary of grid.
Location:
src/Fragmentation/Summation/SetValues
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/Fragmentation/Summation/SetValues/SamplingGrid.cpp

    rcb30d9 r06653a  
    4343#include "Fragmentation/Summation/SetValues/SamplingGrid.hpp"
    4444
     45#include <boost/assign.hpp>
    4546#include <boost/bind.hpp>
    4647#include <algorithm>
     
    610611            "SamplingGrid::addWindowOntoWindow() - destiter is already at end of window.");
    611612        ASSERT( sourceiter != source_sampled_grid.end(),
    612             "SamplingGrid::addWindowOntoWindow() - destiter is already at end of window.");
     613            "SamplingGrid::addWindowOntoWindow() - sourceiter is already at end of window.");
    613614        op(*destiter, *sourceiter);
    614615        ++destiter;
     
    658659}
    659660
     661/** Struct contains a single point with displacements from the
     662 * central point and the weight in the restriction.
     663 */
     664struct PointWeight_t {
     665  PointWeight_t(const int &d1, const int &d2, const int &d3, const double &_weight) :
     666    displacement(NDIM),
     667    weight(_weight)
     668  {
     669    displacement[0] = d1; displacement[1] = d2; displacement[2] = d3;
     670  }
     671  typedef std::vector<int>  displacement_t;
     672  displacement_t displacement;
     673  double weight;
     674};
     675
     676static void getLengthsOfGrid(
     677    int _total[NDIM],
     678    const SamplingGrid &_grid)
     679{
     680        const size_t gridpoints_axis = _grid.getGridPointsPerAxis();
     681        static const double round_offset =
     682            (std::numeric_limits<size_t>::round_style == std::round_toward_zero) ?
     683                0.5 : 0.; // need offset to get to round_toward_nearest behavior
     684        for (size_t index=0; index<NDIM; ++index) {
     685          if (fabs(_grid.end[index] - _grid.begin[index]) > std::numeric_limits<double>::epsilon()*1e4) {
     686            const double delta = (double)gridpoints_axis/(_grid.end[index] - _grid.begin[index]);
     687            _total[index] = delta*(_grid.end_window[index] - _grid.begin_window[index])+round_offset;
     688          } else
     689            _total[index] = 0;
     690          ASSERT (_total[index] == ::pow(2, _grid.level),
     691              "SamplingGrid::downsample() - total "+toString(_total[index])
     692              +" does not match 2^level: "+toString(_grid.level));
     693        }
     694}
     695
     696//!> stencil for full weight restriction, see vmg's stencils.hpp
     697static const std::vector< PointWeight_t > FullWeightNearestNeighbor =
     698    boost::assign::list_of
     699    ( PointWeight_t( 0,  0,  0, 0.125) )
     700    ( PointWeight_t( 1,  0,  0, 0.0625) )
     701    ( PointWeight_t(-1,  0,  0, 0.0625) )
     702    ( PointWeight_t( 0,  1,  0, 0.0625) )
     703    ( PointWeight_t( 0, -1,  0, 0.0625) )
     704    ( PointWeight_t( 0,  0,  1, 0.0625) )
     705    ( PointWeight_t( 0,  0, -1, 0.0625) )
     706    ( PointWeight_t( 1,  1,  0, 0.03125) )
     707    ( PointWeight_t( 1, -1,  0, 0.03125) )
     708    ( PointWeight_t(-1,  1,  0, 0.03125) )
     709    ( PointWeight_t(-1, -1,  0, 0.03125) )
     710    ( PointWeight_t( 0,  1,  1, 0.03125) )
     711    ( PointWeight_t( 0,  1, -1, 0.03125) )
     712    ( PointWeight_t( 0, -1,  1, 0.03125) )
     713    ( PointWeight_t( 0, -1, -1, 0.03125) )
     714    ( PointWeight_t( 1,  0,  1, 0.03125) )
     715    ( PointWeight_t( 1,  0, -1, 0.03125) )
     716    ( PointWeight_t(-1,  0,  1, 0.03125) )
     717    ( PointWeight_t(-1,  0, -1, 0.03125) )
     718    ( PointWeight_t( 1,  1,  1, 0.015625) )
     719    ( PointWeight_t( 1,  1, -1, 0.015625) )
     720    ( PointWeight_t( 1, -1,  1, 0.015625) )
     721    ( PointWeight_t(-1,  1,  1, 0.015625) )
     722    ( PointWeight_t( 1, -1, -1, 0.015625) )
     723    ( PointWeight_t(-1,  1, -1, 0.015625) )
     724    ( PointWeight_t(-1, -1,  1, 0.015625) )
     725    ( PointWeight_t(-1, -1, -1, 0.015625) )
     726;
     727
     728int getValidIndex(
     729    const PointWeight_t::displacement_t &_disp,
     730    const int N[NDIM],
     731    const int length[NDIM])
     732{
     733  int index = 0;
     734  // we simply truncate in case of out of bounds access
     735  if ((N[2]+_disp[2] >= 0) && (N[2]+_disp[2] < length[2]))
     736    index += _disp[2];
     737  if ((N[1]+_disp[1] >= 0) && (N[1]+_disp[1] < length[1]))
     738    index += _disp[1]*length[2];
     739  if ((N[0]+_disp[0] >= 0) && (N[0]+_disp[0] < length[0]))
     740    index += _disp[0]*length[1]*length[2];
     741  return index;
     742}
     743
     744void restrictFullWeight(
     745    SamplingGrid::sampledvalues_t &_coarse_level,
     746    const int length_c[NDIM],
     747    const SamplingGrid::sampledvalues_t &_fine_level,
     748    const int length_f[NDIM])
     749{
     750  int N_c[NDIM];
     751  int N_f[NDIM];
     752  SamplingGrid::sampledvalues_t::iterator coarseiter = _coarse_level.begin();
     753  for(N_c[0]=0, N_f[0]=0; (N_c[0] < length_c[0]) && (N_f[0] < length_f[0]); ++N_c[0], N_f[0] +=2) {
     754    for(N_c[1]=0, N_f[1]=0; (N_c[1] < length_c[1]) && (N_f[1] < length_f[1]); ++N_c[1], N_f[1] +=2) {
     755      for(N_c[2]=0, N_f[2]=0; (N_c[2] < length_c[2]) && (N_f[2] < length_f[2]); ++N_c[2], N_f[2] +=2) {
     756        const int index_base = N_f[2] + (N_f[1] + N_f[0]*length_f[1])*length_f[2];
     757        // go through stencil and add each point relative to displacement with weight
     758        for (std::vector< PointWeight_t >::const_iterator weightiter = FullWeightNearestNeighbor.begin();
     759            weightiter != FullWeightNearestNeighbor.end(); ++weightiter) {
     760          const PointWeight_t::displacement_t disp = weightiter->displacement;
     761          const int index_disp = getValidIndex(disp, N_f, length_f);
     762          *coarseiter += _fine_level[index_base+index_disp]*weightiter->weight;
     763        }
     764        ++coarseiter;
     765      }
     766      ASSERT ( (N_c[2] == length_c[2]) && (N_f[2] == length_f[2]),
     767          "restrictFullWeight() - N_c "+toString(N_c[2])+" != length_c "+toString(length_c[2])
     768          +" or N_f "+toString(N_f[2])+" != length_f "+toString(length_f[2]));
     769    }
     770    ASSERT ( (N_c[1] == length_c[1]) && (N_f[1] == length_f[1]),
     771        "restrictFullWeight() - N_c "+toString(N_c[1])+" != length_c "+toString(length_c[1])
     772        +" or N_f "+toString(N_f[1])+" != length_f "+toString(length_f[1]));
     773  }
     774  ASSERT ( (N_c[0] == length_c[0]) && (N_f[0] == length_f[0]),
     775      "restrictFullWeight() - N_c "+toString(N_c[0])+" != length_c "+toString(length_c[0])
     776      +" or N_f "+toString(N_f[0])+" != length_f "+toString(length_f[0]));
     777  ASSERT( coarseiter ==  _coarse_level.end(),
     778      "restrictFullWeight() - coarseiter is not at end of values.");
     779}
     780
     781void SamplingGrid::downsample(
     782    SamplingGrid& instance,
     783    const SamplingGrid& other,
     784    const int _level)
     785{
     786  if (&instance != &other) {
     787    // take over properties
     788    static_cast<SamplingGridProperties &>(instance) = other;
     789    instance.setWindowSize(other.begin_window, other.end_window);
     790    if (_level >= other.level) {
     791      instance.sampled_grid = other.sampled_grid;
     792    } else {
     793      // if desired level is smaller we need to downsample
     794      // we do this similarly to vmg::RestrictionFullWeight (i.e. a full nearest
     795      // neighbor interpolation) and always one grid level at a time till we
     796      // have reached the desired one
     797
     798      // the reference such that we never have to copy the full grid but only
     799      // downsampled ones
     800      const sampledvalues_t * sourcevalues = &other.sampled_grid;
     801      int length_d[3];
     802      int length_s[3];
     803      getLengthsOfGrid(length_s, other);
     804      for (instance.level = other.level-1; instance.level >= _level; --instance.level) {
     805        getLengthsOfGrid(length_d, instance);
     806        // we always have an eighth of the number of sample points as we stop
     807        sampledvalues_t downsampled(sourcevalues->size()/(size_t)8, 0.);
     808        restrictFullWeight(downsampled, length_d, *sourcevalues, length_s);
     809        // then copy the downsampled values
     810        instance.sampled_grid = downsampled;
     811        sourcevalues = &instance.sampled_grid;
     812        // and exchange lengths
     813        for (size_t i=0;i<3;++i) {
     814          length_s[i] = length_d[i];
     815        }
     816      }
     817      instance.level = _level;
     818
     819      // and finally, renormalize downsampled grid to old value
     820//      instance *= other.integral()/instance.integral();
     821    }
     822  }
     823}
     824
    660825std::ostream & operator<<(std::ostream &ost, const SamplingGrid& other)
    661826{
  • src/Fragmentation/Summation/SetValues/SamplingGrid.hpp

    rcb30d9 r06653a  
    166166  }
    167167
     168  /** Sample a given grid \a other down to grid level \a _level and store
     169   * in \a instance.
     170   *
     171   * \param instance given instance to store downsampled grid in
     172   * \param other instance to get grid from
     173   * \param _level level to sample down to
     174   */
     175  static void downsample(SamplingGrid& instance, const SamplingGrid& other, const int _level);
     176
    168177  /** Returns the numeric integral over the grid.
    169178   *
  • src/Fragmentation/Summation/SetValues/unittests/SamplingGridUnitTest.cpp

    rcb30d9 r06653a  
    4949
    5050#include <boost/assign.hpp>
     51
    5152#include <cmath>
    5253#include <numeric>
     
    549550}
    550551
     552#ifdef HAVE_INLINE
     553inline
     554#endif
     555static int calculateIndex(const int N[NDIM], const int &_length)
     556{
     557  return N[2] + N[1]*_length + N[0]*_length*_length;
     558}
     559
     560#ifdef HAVE_INLINE
     561inline
     562#endif
     563static double calculateDistanceSquared(const int N[NDIM], const int &_length)
     564{
     565  return
     566      ::pow(N[0]/(double)_length-.5,2)
     567      + ::pow(N[1]/(double)_length-.5,2)
     568      + ::pow(N[2]/(double)_length-.5,2);
     569}
     570/** UnitTest for downsample()
     571 */
     572void SamplingGridTest::downsampleTest()
     573{
     574  const double begin[NDIM] = { 0., 0., 0. };
     575  const double end[NDIM] = { 1., 1., 1. };
     576
     577  // simple test, one level difference, same value everywhere
     578  {
     579    SamplingGrid::sampledvalues_t checkvalues;
     580    SamplingGrid::sampledvalues_t othervalues;
     581    const double othergrid_value = 1.5;
     582    for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i)
     583      checkvalues += othergrid_value;
     584    for (size_t i=0; i< NUMBEROFSAMPLES(3); ++i)
     585      othervalues += othergrid_value;
     586
     587    SamplingGrid largegrid(begin, end, 3, othervalues);
     588//    std::cout << " largegrid value " << largegrid.sampled_grid << std::endl;
     589    SamplingGrid smallgrid(begin, end, 2);
     590    SamplingGrid::downsample(smallgrid, largegrid, 2);
     591    SamplingGrid checkgrid(begin, end, 2, checkvalues);
     592//    std::cout << " smallgrid value " << smallgrid.sampled_grid << std::endl;
     593//    std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl;
     594    CPPUNIT_ASSERT_EQUAL( smallgrid, checkgrid );
     595  }
     596
     597  // simple test, two level difference, same value everywhere
     598  {
     599    SamplingGrid::sampledvalues_t checkvalues;
     600    SamplingGrid::sampledvalues_t othervalues;
     601    const double othergrid_value = 1.5;
     602    for (size_t i=0; i< NUMBEROFSAMPLES(2); ++i)
     603      checkvalues += othergrid_value;
     604    for (size_t i=0; i< NUMBEROFSAMPLES(4); ++i)
     605      othervalues += othergrid_value;
     606
     607    SamplingGrid largegrid(begin, end, 4, othervalues);
     608//    std::cout << " largegrid value " << largegrid.sampled_grid << std::endl;
     609    SamplingGrid smallgrid(begin, end, 2);
     610    SamplingGrid::downsample(smallgrid, largegrid, 2);
     611    SamplingGrid checkgrid(begin, end, 2, checkvalues);
     612//    std::cout << " smallgrid value " << smallgrid.sampled_grid << std::endl;
     613//    std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl;
     614    CPPUNIT_ASSERT_EQUAL( smallgrid, checkgrid );
     615  }
     616
     617  // same grid, window equals grids, different values
     618  {
     619    const int length_c = ::pow(2,2);
     620    const int length_f = ::pow(2,3);
     621    SamplingGrid::sampledvalues_t checkvalues((int)::pow(length_c, NDIM), 0.);
     622    SamplingGrid::sampledvalues_t othervalues((int)::pow(length_f, NDIM), 0.);
     623    int N[NDIM];
     624    for (N[0]=0; N[0]< length_f; ++N[0]) {
     625      for (N[1]=0; N[1]< length_f; ++N[1]) {
     626        for (N[2]=0; N[2]< length_f; ++N[2]) {
     627          const int index = calculateIndex(N, length_f);
     628          const double dist = calculateDistanceSquared(N, length_f);
     629          othervalues[index] = cos(M_PI*dist/1.5);
     630        }
     631      }
     632    }
     633    for (N[0]=0; N[0]< length_c; ++N[0]) {
     634      for (N[1]=0; N[1]< length_c; ++N[1]) {
     635        for (N[2]=0; N[2]< length_c; ++N[2]) {
     636          const int index = calculateIndex(N, length_c);
     637          const double dist = calculateDistanceSquared(N, length_c);
     638          checkvalues[index] = cos(M_PI*dist/1.5);
     639        }
     640      }
     641    }
     642
     643    SamplingGrid largegrid(begin, end, 3, othervalues);
     644//    std::cout << " largegrid value " << largegrid.sampled_grid << std::endl;
     645    SamplingGrid smallgrid(begin, end, 2);
     646    SamplingGrid::downsample(smallgrid, largegrid, 2);
     647    SamplingGrid checkgrid(begin, end, 2, checkvalues);
     648//    std::cout << " smallgrid value " << smallgrid.sampled_grid << std::endl;
     649//    std::cout << " checkgrid value " << checkgrid.sampled_grid << std::endl;
     650    static const double threshold = 1.2e-1;
     651    for (N[0]=0; N[0]< length_c; ++N[0])
     652      for (N[1]=0; N[1]< length_c; ++N[1])
     653        for (N[2]=0; N[2]< length_c; ++N[2]) {
     654          const double check_threshold =
     655                    (((N[0] == 0) || (N[0] == length_c-1))
     656                  && ((N[1] == 0) || (N[1] == length_c-1))
     657                  && ((N[2] == 0) || (N[2] == length_c-1)))
     658              ? 2.*threshold : threshold;
     659          const int index = calculateIndex(N, length_c);
     660//          std::cout << "Comparing "
     661//              << fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index]))
     662//              << " < " << threshold << std::endl;
     663          CPPUNIT_ASSERT(
     664              fabs((smallgrid.sampled_grid[index] - checkgrid.sampled_grid[index])) < check_threshold);
     665        }
     666  }
     667}
  • src/Fragmentation/Summation/SetValues/unittests/SamplingGridUnitTest.hpp

    rcb30d9 r06653a  
    3838    CPPUNIT_TEST ( equality_Test );
    3939    CPPUNIT_TEST ( serializeTest );
     40    CPPUNIT_TEST ( downsampleTest );
    4041    CPPUNIT_TEST_SUITE_END();
    4142
     
    5758      void equality_Test();
    5859      void serializeTest();
     60      void downsampleTest();
    5961
    6062private:
Note: See TracChangeset for help on using the changeset viewer.