Ignore:
Timestamp:
Jun 8, 2016, 10:45:28 PM (9 years ago)
Author:
Frederik Heber <heber@…>
Children:
6c0b3f
Parents:
c739b3
git-author:
Frederik Heber <heber@…> (06/08/16 13:22:11)
git-committer:
Frederik Heber <heber@…> (06/08/16 22:45:28)
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.
File:
1 edited

Legend:

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

    rc739b3 r6369bc  
    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{
Note: See TracChangeset for help on using the changeset viewer.