OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
grid_dist_id_iterator.hpp
1 /*
2  * grid_dist_id_iterator_sub.hpp
3  *
4  * Created on: Feb 4, 2015
5  * Author: Pietro Incardona
6  */
7 
8 #ifndef GRID_DIST_ID_ITERATOR_HPP_
9 #define GRID_DIST_ID_ITERATOR_HPP_
10 
11 #define FREE 1
12 #define FIXED 2
13 #define ITERATION_ISOLATION 4
14 
15 #include "Grid/grid_dist_key.hpp"
16 #include "VCluster/VCluster.hpp"
17 #include "util/GBoxes.hpp"
18 
19 #ifdef __NVCC__
20 #include "SparseGridGpu/encap_num.hpp"
21 #endif
22 
23 #include "Grid/cuda/grid_dist_id_kernels.cuh"
24 
25 template<unsigned int dim>
27 {
28  template<typename ec_type, typename lambda_t,typename coord_type>
29  __device__ inline static void call(ec_type & ec,lambda_t f, coord_type coord)
30  {
31  printf("Not implemented in this direction \n");
32  }
33 
34  template<typename ite_type>
35  __device__ inline static bool set_keys(grid_key_dx<3,int> & key, grid_key_dx<3,int> & keyg, ite_type & itg)
36  {
37  return false;
38  }
39 };
40 
41 template<>
43 {
44  template<typename grid_type, typename lambda_t1, typename lambda_t2,typename itd_type, typename coord_type>
45  __device__ inline static void call(grid_type & grid,
46  lambda_t1 f1, lambda_t2 f2,
47  unsigned int blockId,
48  itd_type itd,
49  coord_type & key,
50  coord_type & keyg,unsigned int offset, bool & is_block_empty,
51  bool is_in)
52  {
53 #ifdef __NVCC__
54 
55  bool is_active = false;
56  if (is_in == true)
57  {is_active = f1(keyg.get(0),keyg.get(1),keyg.get(2));}
58 
59  if (is_active == true)
60  {is_block_empty = false;}
61 
62  __syncthreads();
63 
64  if (is_block_empty == false)
65  {
66  auto ec = grid.insertBlock(blockId);
67  enc_num<decltype(grid.insertBlock(blockId))> ecn(ec,offset);
68 
69  if ( is_active == true)
70  {
71  f2(ecn,keyg.get(0),keyg.get(1),keyg.get(2));
72  ec.template get<grid_type::pMask>()[offset] = 1;
73  }
74  }
75 
76 #endif
77  }
78 
79  template<typename ite_type>
80  __device__ inline static bool set_keys(grid_key_dx<3,int> & key, grid_key_dx<3,int> & keyg, ite_type & itg)
81  {
82 #ifdef __NVCC__
83 
84  key.set_d(0,threadIdx.x + blockIdx.x * blockDim.x + itg.start.get(0));
85  key.set_d(1,threadIdx.y + blockIdx.y * blockDim.y + itg.start.get(1));
86  key.set_d(2,threadIdx.z + blockIdx.z * blockDim.z + itg.start.get(2));
87 
88  keyg.set_d(0,key.get(0) + itg.origin.get(0));
89  keyg.set_d(1,key.get(1) + itg.origin.get(1));
90  keyg.set_d(2,key.get(2) + itg.origin.get(2));
91 
92  if (key.get(0) > itg.stop.get(0) || key.get(1) > itg.stop.get(1) || key.get(2) > itg.stop.get(2) ||
93  key.get(0) < itg.start_base.get(0) || key.get(1) < itg.start_base.get(1) || key.get(2) < itg.start_base.get(2))
94  {return true;}
95 #endif
96  return false;
97  }
98 };
99 
100 template<>
102 {
103  template<typename grid_type, typename lambda_t1, typename lambda_t2,typename itd_type, typename coord_type>
104  __device__ inline static void call(grid_type & grid,
105  lambda_t1 f1, lambda_t2 f2,
106  unsigned int blockId,
107  itd_type itd,
108  coord_type & key,
109  coord_type & keyg,unsigned int offset, bool & is_block_empty,
110  bool is_in)
111  {
112 #ifdef __NVCC__
113 
114  bool is_active = false;
115  if (is_in == true)
116  {is_active = f1(keyg.get(0),keyg.get(1));}
117 
118  if (is_active == true)
119  {is_block_empty = false;}
120 
121  __syncthreads();
122 
123  if (is_block_empty == false)
124  {
125  auto ec = grid.insertBlock(blockId);
126  enc_num<decltype(grid.insertBlock(blockId))> ecn(ec,offset);
127 
128  if ( is_active == true)
129  {
130  f2(ecn,keyg.get(0),keyg.get(1));
131  ec.template get<grid_type::pMask>()[offset] = 1;
132  }
133  }
134 
135 #endif
136  }
137 
138  template<typename ite_type>
139  __device__ inline static bool set_keys(grid_key_dx<2,int> & key, grid_key_dx<2,int> & keyg, ite_type & itg)
140  {
141 #ifdef __NVCC__
142  key.set_d(0,threadIdx.x + blockIdx.x * blockDim.x + itg.start.get(0));
143  key.set_d(1,threadIdx.y + blockIdx.y * blockDim.y + itg.start.get(1));
144 
145  keyg.set_d(0,key.get(0) + itg.origin.get(0));
146  keyg.set_d(1,key.get(1) + itg.origin.get(1));
147 
148  if (key.get(0) > itg.stop.get(0) || key.get(1) > itg.stop.get(1) ||
149  key.get(0) < itg.start_base.get(0) || key.get(1) < itg.start_base.get(1))
150  {return true;}
151 #endif
152  return false;
153  }
154 };
155 
157 {
158  template<typename grid_type, typename ite_type, typename lambda_f1, typename lambda_f2>
159  __device__ void operator()(grid_type & grid, ite_type itg, bool & is_block_empty, lambda_f1 f1, lambda_f2 f2)
160  {
161 #ifdef __NVCC__
162 
165 
166  bool not_active = launch_insert_sparse_lambda_call<grid_type::dims>::set_keys(key,keyg,itg);
167 
168  if (threadIdx.x == 0 && threadIdx.y == 0 && threadIdx.z == 0)
169  {is_block_empty = true;}
170 
171  grid.init();
172 
173  int offset = 0;
175  bool out = grid.template getInsertBlockOffset<ite_type>(itg,key,blk,offset);
176 
177  auto blockId = grid.getBlockLinId(blk);
178 
179  launch_insert_sparse_lambda_call<grid_type::dims>::call(grid,f1,f2,blockId,itg,key,keyg,offset,is_block_empty,!not_active);
180 
181  __syncthreads();
182 
183  grid.flush_block_insert();
184 #endif
185  }
186 };
187 
188 template<unsigned int dim>
190 {
191  template<typename grid_type, typename ite_type, typename lambda_f2>
192  __device__ void operator()(grid_type & grid, ite_type itg, lambda_f2 f2)
193  {
194 #ifdef __NVCC__
195 
196  printf("grid on GPU Dimension %d not implemented, yet\n",(int)dim);
197 
198 #endif
199  }
200 };
201 
202 template<>
204 {
205  template<typename grid_type, typename ite_type, typename lambda_f2>
206  __device__ void operator()(grid_type & grid, ite_type itg, lambda_f2 f2)
207  {
208 #ifdef __NVCC__
209 
210  GRID_ID_2_GLOBAL(itg);
211 
212  auto obj = grid.get_o(key);
213 
214  f2(obj,keyg.get(0),keyg.get(1));
215 
216 #endif
217  }
218 };
219 
220 template<>
222 {
223  template<typename grid_type, typename ite_type, typename lambda_f2>
224  __device__ void operator()(grid_type & grid, ite_type itg, lambda_f2 f2)
225  {
226 #ifdef __NVCC__
227 
228  GRID_ID_3_GLOBAL(itg);
229 
230  auto obj = grid.get_o(key);
231 
232  f2(obj,keyg.get(0),keyg.get(1),keyg.get(2));
233 
234 #endif
235  }
236 };
237 
238 template<bool is_free>
239 struct selvg
240 {
241  template<typename a_it_type, typename gdb_ext_type, typename gList_type>
242  static inline void call(a_it_type & a_it, gdb_ext_type & gdb_ext, gList_type & gList, size_t & g_c)
243  {
244  if (gdb_ext.get(g_c).Dbox.isValid() == false)
245  {g_c++;}
246  else
247  {
248  a_it.reinitialize(gList.get(g_c).getIterator(gdb_ext.get(g_c).Dbox.getKP1(),gdb_ext.get(g_c).Dbox.getKP2()));
249  if (a_it.isNext() == false) {g_c++;}
250  }
251  }
252 };
253 
254 template<>
255 struct selvg<false>
256 {
257  template<typename a_it_type, typename gdb_ext_type, typename gList_type>
258  static inline void call(a_it_type & a_it, gdb_ext_type & gdb_ext, gList_type & gList, size_t & g_c)
259  {
260  // Full iterator (no subset)
261  a_it.reinitialize(gList.get(g_c).getIterator());
262  if (a_it.isNext() == false) {g_c++;}
263  }
264 };
265 
276 template<unsigned int dim, typename device_grid, typename device_sub_it, int impl, typename stencil = no_stencil >
278 {
280  size_t g_c;
281 
284 
287 
289  device_sub_it a_it;
290 
293 
298  {
299  do
300  {
301  if (impl == FREE)
302  {
303  // When the grid has size 0 potentially all the other informations are garbage
304  while (g_c < gList.size() && (gList.get(g_c).size() == 0 || gdb_ext.get(g_c).Dbox.isValid() == false ) ) g_c++;
305  }
306  else
307  {
308  // When the grid has size 0 potentially all the other informations are garbage
309  while (g_c < gList.size() && (gList.get(g_c).size() == 0 || gdb_ext.get(g_c).GDbox.isValid() == false) ) g_c++;
310  }
311 
312  // get the next grid iterator
313  if (g_c < gList.size())
314  {
316  }
317  } while (g_c < gList.size() && a_it.isNext() == false);
318 
319  }
320 
321  public:
322 
332  const grid_key_dx<dim> & stop)
333  :g_c(0),gList(gk),gdb_ext(gdb_ext),stop(stop)
334  {
335  // Initialize the current iterator
336  // with the first grid
337  selectValidGrid();
338  }
339 
340 
352  const grid_key_dx<dim> & stop,
353  const grid_key_dx<dim> (& stencil_pnt)[stencil::nsp])
354  :g_c(0),gList(gk),gdb_ext(gdb_ext),a_it(stencil_pnt),stop(stop)
355  {
356  // Initialize the current iterator
357  // with the first grid
358  selectValidGrid();
359  }
360 
363  :g_c(g.g_c),gList(g.gList),gdb_ext(g.gdb_ext),a_it(g.a_it),stop(g.stop)
364  {}
365 
368  :g_c(g.g_c),gList(g.gList),gdb_ext(g.gdb_ext),a_it(g.a_it),stop(g.stop)
369  {}
370 
373  {
374  }
375 
382  {
383  ++a_it;
384 
385  // check if a_it is at the end
386 
387  if (a_it.isNext() == true)
388  return *this;
389  else
390  {
391  // switch to the new grid
392  g_c++;
393 
394  selectValidGrid();
395  }
396 
397  return *this;
398  }
399 
405  inline bool isNext() const
406  {
407  // If there are no other grid stop
408 
409  if (g_c >= gList.size())
410  {return false;}
411 
412  return true;
413  }
414 
421  {
423  }
424 
432  inline grid_key_dx<dim> getStop() const
433  {
434  return stop;
435  }
436 
444  inline grid_key_dx<dim> getStart() const
445  {
446  grid_key_dx<dim> start;
447 
448  start.zero();
449 
450  return start;
451  }
452 
461  {
462  return gdb_ext;
463  }
464 
476  {
477  // Get the sub-domain id
478  size_t sub_id = k.getSub();
479 
480  auto k_glob = k.getKey();
481 
482  // shift
483  auto k_glob2 = k_glob + gdb_ext.get(sub_id).origin;
484 
485  return k_glob2;
486  }
487 
495  template<unsigned int id> inline grid_dist_lin_dx getStencil()
496  {
497  return grid_dist_lin_dx(g_c,a_it.template getStencil<id>());
498  }
499 };
500 
501 
502 
503 #endif /* GRID_DIST_ID_ITERATOR_SUB_HPP_ */
grid_dist_iterator(openfpm::vector< device_grid > &gk, const openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, const grid_key_dx< dim > &stop, const grid_key_dx< dim >(&stencil_pnt)[stencil::nsp])
Constructor of the distributed grid iterator with stencil support.
grid_key_dx< dim > getGKey(const grid_dist_key_dx< dim, typename device_grid::base_key > &k)
Convert a g_dist_key_dx into a global key.
grid_key_dx is the key to access any element in the grid
Definition: grid_key.hpp:18
size_t g_c
grid list counter
grid_dist_iterator< dim, device_grid, device_sub_it, impl, stencil > & operator++()
Get the next element.
grid_dist_lin_dx getStencil()
Return the stencil point offset.
grid_key_dx< dim > getStart() const
it return the start point of the iterator
__device__ __host__ index_type get(index_type i) const
Get the i index.
Definition: grid_key.hpp:503
Grid key for a distributed grid.
size_t size()
Stub size.
Definition: map_vector.hpp:211
grid_key_dx< dim > stop
stop point (is the grid size)
This structure store the Box that define the domain inside the Ghost + domain box.
Definition: GBoxes.hpp:39
grid_dist_iterator(const grid_dist_iterator< dim, device_grid, device_sub_it, impl, stencil > &g)
Copy constructor.
const openfpm::vector< device_grid > & gList
List of the grids we are going to iterate.
void selectValidGrid()
from g_c increment g_c until you find a valid grid
This is a distributed grid.
device_sub_it a_it
Actual iterator.
grid_dist_key_dx< dim, typename device_grid::base_key > get() const
Get the actual key.
grid_key_dx< dim > getStop() const
it return the stop point of the iterator
const openfpm::vector< GBoxes< device_grid::dims > > & getGBoxes()
Get the boxes.
bool isNext() const
Check if there is the next element.
grid_dist_iterator(grid_dist_iterator< dim, device_grid, device_sub_it, impl, stencil > &&g)
Copy constructor.
void zero()
Set to zero the key.
Definition: grid_key.hpp:170
const openfpm::vector< GBoxes< device_grid::dims > > & gdb_ext
Extension of each grid: domain and ghost + domain.
grid_dist_iterator(const openfpm::vector< device_grid > &gk, const openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, const grid_key_dx< dim > &stop)
Constructor of the distributed grid iterator.
Distributed grid iterator.
__device__ __host__ void set_d(index_type i, index_type id)
Set the i index.
Definition: grid_key.hpp:516
Distributed linearized key.