8 #ifndef OPENFPM_NUMERICS_SRC_INTERPOLATION_INTERPOLATION_HPP_ 
    9 #define OPENFPM_NUMERICS_SRC_INTERPOLATION_INTERPOLATION_HPP_ 
   11 #include "NN/Mem_type/MemFast.hpp" 
   12 #include "NN/CellList/CellList.hpp" 
   13 #include "Grid/grid_dist_key.hpp" 
   14 #include "Vector/vector_dist_key.hpp" 
   16 #define INTERPOLATION_ERROR_OBJECT std::runtime_error("Runtime interpolation error"); 
   18 constexpr 
int inte_m2p = 0;
 
   19 constexpr 
int inte_p2m = 1;
 
   27 template<
unsigned int n_ele>
 
   49     inline static void value(T & result, 
const T & coeff, 
const T & src)
 
   51         result += coeff * src;
 
   60 template<
typename T, 
unsigned int N1>
 
   70     inline static void value(T (& result)[N1], 
const T & coeff, 
const T (& src)[N1])
 
   72         for (
size_t i = 0 ; i < N1 ; i++)
 
   73             result[i] += coeff * src[i];
 
   82 template<
typename T, 
unsigned int N1, 
unsigned int N2>
 
   92     inline static void value(T (& result)[N1][N2], 
const T & coeff, 
const T (& src)[N1][N2])
 
   94         for (
size_t i = 0 ; i < N1 ; i++)
 
   95             for (
size_t j = 0 ; j < N2 ; j++)
 
   96                 result[i][j] += coeff * src[i][j];
 
  107 template<
unsigned int np, 
unsigned int prp_g, 
unsigned int prp_v,
unsigned int m2p_or_p2m>
 
  125     template<
unsigned int np_a_
int, 
typename gr
id, 
typename vector, 
typename iterator> 
inline static void value(
grid & gd,
 
  129                                                                       typename vector::stype (& a_int)[np_a_int],
 
  132         mul_inte<
typename std::remove_reference<decltype(gd.template get<prp_g>(k_dist))>::type>
::value(gd.template get<prp_g>(k_dist),a_int[key],vd.template getProp<prp_v>(key_p));
 
  143 template<
unsigned int np, 
unsigned int prp_g, 
unsigned int prp_v>
 
  161     template<
unsigned int np_a_
int, 
typename gr
id, 
typename vector, 
typename iterator> 
inline static void value(
grid & gd,
 
  165                                                                       typename vector::stype (& a_int)[np_a_int],
 
  168         mul_inte<
typename std::remove_reference<decltype(gd.template get<prp_g>(k_dist))>::type>
::value(vd.template getProp<prp_v>(key_p),a_int[key],gd.template get<prp_g>(k_dist));
 
  177 template<
unsigned int dims, 
typename vector, 
unsigned int np>
 
  191     static inline void value(
size_t (& sz)[vector::dims],
 
  192                              typename vector::stype a_int[openfpm::math::pow(np,vector::dims)],
 
  193                              typename vector::stype (& a)[vector::dims][np])
 
  205             for (
size_t i = 0 ; i < vector::dims ; i++)
 
  206                 a_int[s] *= a[i][
key.get(i)];
 
  218 template<
typename vector, 
unsigned int np>
 
  233     static inline void value(
size_t (& sz)[vector::dims],
 
  234                              typename vector::stype a_int[openfpm::math::pow(np,vector::dims)],
 
  235                              typename vector::stype (& a)[vector::dims][np])
 
  238         for (
size_t i = 0 ; i < np ; i++)
 
  240             for (
size_t j = 0 ; j < np ; j++)
 
  242                 a_int[s] = a[0][j]*a[1][i];
 
  254 template<
typename vector, 
unsigned int np>
 
  268     static inline void value(
size_t (& sz)[vector::dims],
 
  269                              typename vector::stype a_int[openfpm::math::pow(np,vector::dims)],
 
  270                              typename vector::stype (& a)[vector::dims][np])
 
  273         for (
size_t i = 0 ; i < np ; i++)
 
  275             for (
size_t j = 0 ; j < np ; j++)
 
  277                 for (
size_t k = 0 ; k < np ; k++)
 
  279                     a_int[s] = a[0][k]*a[1][j]*a[2][i];
 
  295 template<
typename vector, 
typename gr
id>
 
  300     size_t cell = geo_cell.getCell(p);
 
  302     for (
size_t i = 0 ; i < geo_cell.getNelements(cell) ; i++)
 
  304         size_t ns = geo_cell.get(cell,i);
 
  306         if (gd.getDecomposition().getSubDomain(ns).isInside(p))
 
  313     typename vector::stype dx[vector::dims];
 
  314     typename vector::stype best_dx[vector::dims];
 
  315     typename vector::stype best_tot_dx;
 
  320     for (
size_t j = 0 ; j < vector::dims ; j++)
 
  323             {dx[j] = 2*(sub_dom.
getLow(j) - p.
get(j));}
 
  329     typename vector::stype tot_dx = 0.0;
 
  331     for (
size_t j = 0 ; j < vector::dims ; j++)
 
  332     {tot_dx += fabs(dx[j]);}
 
  334     best_tot_dx = tot_dx;
 
  335     for (
size_t j = 0 ; j < vector::dims ; j++)
 
  336     {best_dx[j] = dx[j];}
 
  339     for (
size_t i = 1 ; i < gd.getDecomposition().getNSubDomain() ; i++)
 
  343         for (
size_t j = 0 ; j < vector::dims ; j++)
 
  346             {dx[j] = 2*(sub_dom.
getLow(j) - p.
get(j));}
 
  352         typename vector::stype tot_dx = 0.0;
 
  354         for (
size_t j = 0 ; j < vector::dims ; j++)
 
  355         {tot_dx += fabs(dx[j]);}
 
  357         if (tot_dx < best_tot_dx)
 
  359             best_tot_dx = tot_dx;
 
  360             for (
size_t j = 0 ; j < vector::dims ; j++)
 
  361             {best_dx[j] = dx[j];}
 
  368     for (
size_t j = 0 ; j < vector::dims ; j++)
 
  369     {p.
get(j) += best_dx[j];}
 
  380 template<
typename vector,
typename kernel>
 
  411     template<
unsigned int prp_g, 
unsigned int prp_v, 
unsigned int m2p_or_p2m, 
unsigned int np_a_
int, 
typename gr
id>
 
  415                                                                      int (& ip)[vector::dims][kernel::np],
 
  417                                                                      const typename vector::stype (& dx)[vector::dims],
 
  418                                                                      typename vector::stype (& xp)[vector::dims],
 
  419                                                                      typename vector::stype (& a_int)[np_a_int],
 
  420                                                                      typename vector::stype (& a)[vector::dims][kernel::np],
 
  421                                                                      typename vector::stype (& x)[vector::dims][kernel::np],
 
  422                                                                      size_t (& sz)[vector::dims],
 
  429         size_t sub = getSub<vector>(p,geo_cell,gd);
 
  431         typename vector::stype x0[vector::dims];
 
  435         for (
size_t i = 0 ; i < vector::dims ; i++)
 
  436             x0[i] = (p.get(i)-domain.
getLow(i))*dx[i];
 
  439         for (
size_t i = 0 ; i < vector::dims ; i++)
 
  440             ip[i][0] = (
int)x0[i];
 
  445         for (
size_t i = 0 ; i < vector::dims ; i++)
 
  446             base.
set_d(i,ip[i][0] - gd.getLocalGridsInfo().get(sub).origin.get(i) - (
long int)kernel::np/2 + 1);
 
  450         for (
size_t j = 0 ; j < kernel::np-1 ; j++)
 
  452             for (
size_t i = 0 ; i < vector::dims ; i++)
 
  453                 ip[i][j+1] = (
int)ip[i][j]+1;
 
  456         for (
size_t i = 0 ; i < vector::dims ; i++)
 
  457             xp[i] = x0[i] - ip[i][0];
 
  459         for (
long int j = 0 ; j < kernel::np ; j++)
 
  461             for (
size_t i = 0 ; i < vector::dims ; i++)
 
  462                 x[i][j] = - xp[i] + 
typename vector::stype((
long int)j - (
long int)kernel::np/2 + 1);
 
  465         for (
size_t j = 0 ; j < kernel::np ; j++)
 
  467             for (
size_t i = 0 ; i < vector::dims ; i++)
 
  468                 a[i][j] = kernel::value(x[i][j],j);
 
  477         auto & gs_info = gd.get_loc_grid(sub).getGrid();
 
  479         size_t lin_base = gs_info.LinId(base);
 
  481         for (
size_t i = 0 ; i < openfpm::math::pow(kernel::np,vector::dims) ; i++)
 
  483             size_t lin = offsets.get(sub).ele[k] + lin_base;
 
  502 template<
typename vector,
typename gr
id, 
typename kernel>
 
  547     size_t sz[vector::dims];
 
  550     typename vector::stype dx[vector::dims];
 
  564         offsets.resize(gd.getN_loc_grid());
 
  568             auto & loc_grid = gd.get_loc_grid(i);
 
  607         size_t div[vector::dims];
 
  609         for (
size_t i = 0 ; i < vector::dims ; i++)
 
  616         auto & dec = gd.getDecomposition();
 
  618         for (
size_t i = 0 ; i < dec.getNSubDomain() ; i++)
 
  639         for (
size_t i = 0 ; i < vector::dims ; i++)
 
  640         {
sz[i] = kernel::np;}
 
  645         for (
size_t i = 0 ; i < vector::dims ; i++)
 
  646         {dx[i] = 1.0/gd.spacing(i);}
 
  649         domain = vd.getDecomposition().getDomain();
 
  662     template<
unsigned int prp_v, 
unsigned int prp_g> 
void p2m(vector & vd, 
grid & gd)
 
  666         if (!vd.getDecomposition().is_equal_ng(gd.getDecomposition()) )
 
  668             std::cerr << __FILE__ << 
":" << __LINE__ << 
" Error: the distribution of the vector of particles" <<
 
  669                     " and the grid is different. In order to interpolate the two data structure must have the" <<
 
  670                     " same decomposition" << std::endl;
 
  672             ACTION_ON_ERROR(INTERPOLATION_ERROR_OBJECT)
 
  678         typename vector::stype xp[vector::dims];
 
  680         int ip[vector::dims][kernel::np];
 
  681         typename vector::stype x[vector::dims][kernel::np];
 
  682         typename vector::stype a[vector::dims][kernel::np];
 
  684         typename vector::stype a_int[openfpm::math::pow(kernel::np,vector::dims)];
 
  686         auto it = vd.getDomainIterator();
 
  688         while (it.isNext() == 
true)
 
  690             auto key_p = it.get();
 
  692             inte_calc_impl<vector,kernel>::template inte_calc<prp_g,prp_v,inte_p2m,openfpm::math::pow(kernel::np,vector::dims)>(key_p,
vd,
domain,ip,
gd,
dx,xp,a_int,a,x,
sz,
geo_cell,
offsets);
 
  708     template<
unsigned int prp_g, 
unsigned int prp_v> 
void m2p(
grid & gd, vector & vd)
 
  712         if (!vd.getDecomposition().is_equal_ng(gd.getDecomposition()) )
 
  714             std::cerr << __FILE__ << 
":" << __LINE__ << 
" Error: the distribution of the vector of particles" <<
 
  715                     " and the grid is different. In order to interpolate the two data structure must have the" <<
 
  716                     " same decomposition" << std::endl;
 
  718             ACTION_ON_ERROR(INTERPOLATION_ERROR_OBJECT)
 
  724         typename vector::stype xp[vector::dims];
 
  726         int ip[vector::dims][kernel::np];
 
  727         typename vector::stype x[vector::dims][kernel::np];
 
  728         typename vector::stype a[vector::dims][kernel::np];
 
  732         typename vector::stype a_int[openfpm::math::pow(kernel::np,vector::dims)];
 
  734         auto it = vd.getDomainIterator();
 
  736         while (it.isNext() == 
true)
 
  738             auto key_p = it.get();
 
  740             inte_calc_impl<vector,kernel>::template inte_calc<prp_g,prp_v,inte_m2p,openfpm::math::pow(kernel::np,vector::dims)>(key_p,
vd,
domain,ip,
gd,
dx,xp,a_int,a,x,
sz,
geo_cell,
offsets);
 
  762         if (!vd.getDecomposition().is_equal_ng(gd.getDecomposition()) )
 
  764             std::cerr << __FILE__ << 
":" << __LINE__ << 
" Error: the distribution of the vector of particles" <<
 
  765                     " and the grid is different. In order to interpolate the two data structure must have the" <<
 
  766                     " same decomposition" << std::endl;
 
  768             ACTION_ON_ERROR(INTERPOLATION_ERROR_OBJECT)
 
  774         typename vector::stype xp[vector::dims];
 
  776         int ip[vector::dims][kernel::np];
 
  777         typename vector::stype x[vector::dims][kernel::np];
 
  778         typename vector::stype a[vector::dims][kernel::np];
 
  780         typename vector::stype a_int[openfpm::math::pow(kernel::np,vector::dims)];
 
  782         inte_calc_impl<vector,kernel>::template inte_calc<prp_g,prp_v,inte_p2m,openfpm::math::pow(kernel::np,vector::dims)>(p,
vd,
domain,ip,
gd,
dx,xp,a_int,a,x,
sz,
geo_cell,
offsets);
 
  800         if (!vd.getDecomposition().is_equal_ng(gd.getDecomposition()) )
 
  802             std::cerr << __FILE__ << 
":" << __LINE__ << 
" Error: the distribution of the vector of particles" <<
 
  803                     " and the grid is different. In order to interpolate the two data structure must have the" <<
 
  804                     " same decomposition" << std::endl;
 
  806             ACTION_ON_ERROR(INTERPOLATION_ERROR_OBJECT)
 
  812         typename vector::stype xp[vector::dims];
 
  814         int ip[vector::dims][kernel::np];
 
  815         typename vector::stype x[vector::dims][kernel::np];
 
  816         typename vector::stype a[vector::dims][kernel::np];
 
  820         typename vector::stype a_int[openfpm::math::pow(kernel::np,vector::dims)];
 
  822         inte_calc_impl<vector,kernel>::template inte_calc<prp_g,prp_v,inte_m2p,openfpm::math::pow(kernel::np,vector::dims)>(p,
vd,
domain,ip,
gd,
dx,xp,a_int,a,x,
sz,
geo_cell,
offsets);
 
size_t vol
Calculated volume. 
 
mem_id LinId(const grid_key_dx< N > &gk, const char sum_id[N]) const 
Linearization of the grid_key_dx with a specified shift. 
 
static void value(grid &gd, vector &vd, const grid_dist_lin_dx &k_dist, iterator &key_p, typename vector::stype(&a_int)[np_a_int], const size_t &key)
Evaluate the interpolation. 
 
size_t & getKeyRef()
Get the reference key. 
 
static void value(T &result, const T &coeff, const T &src)
multiply the src by coeff for several types T 
 
calculate the interpolation for one point 
 
void p2m(vector &vd, grid &gd)
Interpolate particles to mesh. 
 
T getLow(int i) const 
get the i-coordinate of the low bound interval of the box 
 
grid_key_dx is the key to access any element in the grid 
 
size_t ele[n_ele]
offset of the interpolation points 
 
void m2p(grid &gd, vector &vd, const vect_dist_key_dx &p)
Interpolate mesh to particle. 
 
It store the offsets of the interpolation points. 
 
openfpm::vector< agg_arr< openfpm::math::pow(kernel::np, vector::dims)> > offsets
the offset for each sub-sub-domain 
 
bool operator<(const Box_vol &bv)
operator to reorder 
 
void calculate_the_offsets(openfpm::vector< agg_arr< openfpm::math::pow(kernel::np, vector::dims)>> &offsets, size_t(&sz)[vector::dims])
It calculate the interpolation stencil offsets. 
 
void Initialize(CellDecomposer_sm< dim, T, transform > &cd_sm, const Box< dim, T > &dom_box, const size_t pad=1, size_t slot=STARTING_NSLOT)
 
T getHigh(int i) const 
get the high interval of the box 
 
static void value(size_t(&sz)[vector::dims], typename vector::stype a_int[openfpm::math::pow(np, vector::dims)], typename vector::stype(&a)[vector::dims][np])
Calculate the coefficients of the interpolation a_int for one particles having the 1D kernel values...
 
static void value(T(&result)[N1], const T &coeff, const T(&src)[N1])
multiply the src by coeff for several types T 
 
CellList< vector::dims, typename vector::stype, Mem_fast<>, shift< vector::dims, typename vector::stype > > geo_cell
Cell list used to convert particles position to sub-domain. 
 
This class implement the point shape in an N-dimensional space. 
 
Grid key for a distributed grid. 
 
Point< dim, T > getP1() const 
Get the point p1. 
 
void setSub(size_t sub)
Set the local grid. 
 
static void value(grid &gd, vector &vd, const grid_dist_lin_dx &k_dist, iterator &key_p, typename vector::stype(&a_int)[np_a_int], const size_t &key)
Evaluate the interpolation. 
 
size_t sz[vector::dims]
kernel size 
 
const grid_key_dx< dim > & get() const 
Get the actual key. 
 
static void value(size_t(&sz)[vector::dims], typename vector::stype a_int[openfpm::math::pow(np, vector::dims)], typename vector::stype(&a)[vector::dims][np])
Calculate the coefficients of the interpolation a_int for one particles having the 1D kernel values...
 
interpolate(vector &vd, grid &gd)
construct an interpolation object between a grid and a vector 
 
vector::stype arr_type
Type of the calculations. 
 
const T & get(size_t i) const 
Get coordinate. 
 
static void value(T(&result)[N1][N2], const T &coeff, const T(&src)[N1][N2])
multiply the src by coeff for several types T 
 
bool isNext()
Check if there is the next element. 
 
grid_key_dx< dim > get() const 
Return the actual grid key iterator. 
 
This class is a trick to indicate the compiler a specific specialization pattern. ...
 
vector::stype dx[vector::dims]
grid spacing 
 
Box< vector::dims, size_t > bv
Box. 
 
const grid_sm< dim, void > & getGrid()
Return the underlying grid information of the cell list. 
 
void m2p(grid &gd, vector &vd)
Interpolate mesh to particle. 
 
Declaration grid_key_dx_iterator_sub. 
 
void addCell(size_t cell_id, typename base::value_type ele)
Add to the cell. 
 
multiply the src by coeff for several types T 
 
static void inte_calc(const vect_dist_key_dx &key_p, vector &vd, const Box< vector::dims, typename vector::stype > &domain, int(&ip)[vector::dims][kernel::np], grid &gd, const typename vector::stype(&dx)[vector::dims], typename vector::stype(&xp)[vector::dims], typename vector::stype(&a_int)[np_a_int], typename vector::stype(&a)[vector::dims][kernel::np], typename vector::stype(&x)[vector::dims][kernel::np], size_t(&sz)[vector::dims], const CellList< vector::dims, typename vector::stype, Mem_fast<>, shift< vector::dims, typename vector::stype >> &geo_cell, openfpm::vector< agg_arr< openfpm::math::pow(kernel::np, vector::dims)>> &offsets)
M2P or P2M for one particle. 
 
void p2m(vector &vd, grid &gd, const vect_dist_key_dx &p)
Interpolate particles to mesh. 
 
Box< vector::dims, typename vector::stype > domain
Simulation domain. 
 
void set_d(size_t i, mem_id id)
Set the i index. 
 
Class that select the operation to do differently if we are doing Mesh to particle (m2p) or particle ...
 
static void value(size_t(&sz)[vector::dims], typename vector::stype a_int[openfpm::math::pow(np, vector::dims)], typename vector::stype(&a)[vector::dims][np])
Calculate the coefficients of the interpolation a_int for one particles having the 1D kernel values...
 
Implementation of 1-D std::vector like structure. 
 
Class for FAST cell list implementation. 
 
bool isNext()
Check if there is the next element. 
 
vector::stype arr_type
Type of the calculations. 
 
Point< dim, T > getP2() const 
Get the point p2. 
 
Main class for interpolation Particle to mest p2m and Mesh to particle m2p. 
 
Distributed linearized key.