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])
201 auto key = kit.
get();
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).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++)
322 if (sub_dom.
getLow(j) > p.get(j))
323 {dx[j] = 2*(sub_dom.
getLow(j) - p.get(j));}
324 else if (sub_dom.
getHigh(j) < p.get(j))
325 {dx[j] = 2*(sub_dom.
getHigh(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++)
345 if (sub_dom.
getLow(j) > p.get(j))
346 {dx[j] = 2*(sub_dom.
getLow(j) - p.get(j));}
347 else if (sub_dom.
getHigh(j) < p.get(j))
348 {dx[j] = 2*(sub_dom.
getHigh(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];
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);