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");
18constexpr int inte_m2p = 0;
19constexpr int inte_p2m = 1;
27template<
unsigned int n_ele>
49 inline static void value(T & result,
const T & coeff,
const T & src)
51 result += coeff * src;
60template<
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];
82template<
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];
107template<
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));
143template<
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));
177template<
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])
201 auto key = kit.
get();
205 for (
size_t i = 0 ; i < vector::dims ; i++)
206 a_int[s] *= a[i][key.get(i)];
218template<
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];
254template<
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];
295template<
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).isInsideNP(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];}
380template<
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;
502template<
typename vector,
typename gr
id,
typename kernel>
547 size_t sz[vector::dims];
550 typename vector::stype
dx[vector::dims];
568 auto & loc_grid =
gd.get_loc_grid(i);
578 auto key = kit2.
get();
580 long int lin = gs.
LinId(key);
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++)
633 auto key = g_sub.
get();
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)];
783 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);
801 if (!
vd.getDecomposition().is_equal_ng(
gd.getDecomposition()) )
803 std::cerr << __FILE__ <<
":" << __LINE__ <<
" Error: the distribution of the vector of particles" <<
804 " and the grid is different. In order to interpolate the two data structure must have the" <<
805 " same decomposition" << std::endl;
807 ACTION_ON_ERROR(INTERPOLATION_ERROR_OBJECT)
813 typename vector::stype xp[vector::dims];
815 int ip[vector::dims][kernel::np];
816 typename vector::stype x[vector::dims][kernel::np];
817 typename vector::stype a[vector::dims][kernel::np];
821 typename vector::stype a_int[openfpm::math::pow(kernel::np,vector::dims)];
823 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);
This class represent an N-dimensional box.
Point< dim, T > getP2() const
Get the point p2.
__device__ __host__ T getLow(int i) const
get the i-coordinate of the low bound interval of the box
__device__ __host__ T getHigh(int i) const
get the high interval of the box
Point< dim, T > getP1() const
Get the point p1.
Class for FAST cell list implementation.
const grid_sm< dim, void > & getGrid()
Return the underlying grid information of the cell list.
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)
void addCell(size_t cell_id, typename Mem_type::local_index_type ele)
Add to the cell.
It is a class that work like a vector of vector.
This class implement the point shape in an N-dimensional space.
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Distributed linearized key.
size_t & getKeyRef()
Get the reference key.
void setSub(size_t sub)
Set the local grid.
Declaration grid_key_dx_iterator_sub.
grid_key_dx< dim > get() const
Return the actual grid key iterator.
bool isNext()
Check if there is the next element.
const grid_key_dx< dim > & get() const
Get the actual key.
bool isNext()
Check if there is the next element.
grid_key_dx is the key to access any element in the grid
__device__ __host__ void set_d(index_type i, index_type id)
Set the i index.
mem_id LinId(const grid_key_dx< N, ids_type > &gk, const signed char sum_id[N]) const
Linearization of the grid_key_dx with a specified shift.
Main class for interpolation Particle to mest p2m and Mesh to particle m2p.
void m2p(grid &gd, vector &vd)
Interpolate mesh to particle.
Box< vector::dims, typename vector::stype > domain
Simulation domain.
interpolate(vector &vd, grid &gd)
construct an interpolation object between a grid and a vector
openfpm::vector< agg_arr< openfpm::math::pow(kernel::np, vector::dims)> > offsets
the offset for each sub-sub-domain
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.
size_t sz[vector::dims]
kernel size
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.
void p2m(vector &vd, grid &gd, const vect_dist_key_dx &p)
Interpolate particles to mesh.
int getSub(Point< vector::dims, typename vector::stype > &p)
Return the sub-domain of the particles.
vector::stype dx[vector::dims]
grid spacing
void p2m(vector &vd, grid &gd)
Interpolate particles to mesh.
void m2p(grid &gd, vector &vd, const vect_dist_key_dx &p)
Interpolate mesh to particle.
vector::stype arr_type
Type of the calculations.
Implementation of 1-D std::vector like structure.
Grid key for a distributed grid.
It store the offsets of the interpolation points.
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(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(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.
calculate the interpolation for one point
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.
vector::stype arr_type
Type of the calculations.
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.
Class that select the operation to do differently if we are doing Mesh to particle (m2p) or particle ...
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 vol
Calculated volume.
bool operator<(const Box_vol &bv)
operator to reorder
Box< vector::dims, size_t > bv
Box.
static void value(T(&result)[N1][N2], const T &coeff, const T(&src)[N1][N2])
multiply the src by coeff for several types T
static void value(T(&result)[N1], const T &coeff, const T(&src)[N1])
multiply the src by coeff for several types T
multiply the src by coeff for several types T
static void value(T &result, const T &coeff, const T &src)
multiply the src by coeff for several types T