OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
grid_dist_id_comm.hpp
1 /*
2  * grid_dist_id_comm.hpp
3  *
4  * Created on: Nov 13, 2016
5  * Author: yaroslav
6  */
7 
8 #ifndef SRC_GRID_GRID_DIST_ID_COMM_HPP_
9 #define SRC_GRID_GRID_DIST_ID_COMM_HPP_
10 
11 #include "Vector/vector_dist_ofb.hpp"
12 #include "Grid/copy_grid_fast.hpp"
13 
18 template<bool result,typename T, typename device_grid, typename Memory>
20 {
29  template<template<typename,typename> class op, int ... prp> static void call_unpack(ExtPreAlloc<Memory> & recv_buf, grid_key_dx_iterator_sub<device_grid::dims> & sub2, device_grid & gd, Unpack_stat & ps)
30  {
31  std::cerr << __FILE__ << ":" << __LINE__ << " Error: complex properties on grids are not supported yet" << std::endl;
32  }
33 };
34 
39 template<typename T, typename device_grid, typename Memory>
40 struct grid_unpack_selector_with_prp<true,T,device_grid,Memory>
41 {
42 
51  template<template<typename,typename> class op, unsigned int ... prp> static void call_unpack(ExtPreAlloc<Memory> & recv_buf, grid_key_dx_iterator_sub<device_grid::dims> & sub2, device_grid & gd, Unpack_stat & ps)
52  {
53  PtrMemory * ptr1;
54 
55  size_t sz[device_grid::dims];
56 
57  for (size_t i = 0 ; i < device_grid::dims ; i++)
58  sz[i] = sub2.getStop().get(i) - sub2.getStart().get(i) + 1;
59 
60  size_t tot = 1;
61 
62  for (size_t i = 0 ; i < device_grid::dims ; i++)
63  tot *= sz[i];
64 
65  tot *= sizeof(T);
66 
67 #ifdef SE_CLASS1
68 
69  if (ps.getOffset() + tot > recv_buf.size())
70  std::cerr << __FILE__ << ":" << __LINE__ << " Error: overflow in the receiving buffer for ghost_put" << std::endl;
71 
72 #endif
73 
74  // add the received particles to the vector
75  ptr1 = new PtrMemory(((char *)recv_buf.getPointerBase()+ps.getOffset()),tot);
76 
77  // create vector representation to a piece of memory already allocated
79 
80  gs.setMemory(*ptr1);
81 
82  // resize with the number of elements
83  gs.resize(sz);
84 
85  // Merge the information
86 
87  auto it_src = gs.getIterator();
88 
89  while (sub2.isNext())
90  {
91  object_s_di_op<op,
92  decltype(gs.get_o(it_src.get())),
93  decltype(gd.get_o(sub2.get())),
94  OBJ_ENCAP,prp...>
95  (gs.get_o(it_src.get()),
96  gd.get_o(sub2.get()));
97 
98  ++sub2;
99  ++it_src;
100  }
101 
102  ps.addOffset(tot);
103  }
104 };
105 
111 template<typename device_grid, typename Memory, typename T>
113 
119 template<typename device_grid, typename Memory , int ... prp>
120 struct grid_call_serialize_variadic<device_grid, Memory, index_tuple<prp...>>
121 {
122 
131  template<template<typename,typename> class op, typename T> inline static void call_unpack(ExtPreAlloc<Memory> & recv_buf, grid_key_dx_iterator_sub<device_grid::dims> & sub2, device_grid & dg, Unpack_stat & ps)
132  {
133  const bool result = has_pack_gen<typename T::type>::value == false;
134 
135  grid_unpack_selector_with_prp<result,T,device_grid,Memory>::template call_unpack<op,prp...>(recv_buf,sub2,dg,ps);
136  }
137 };
138 
144 template<template<typename,typename> class op, typename T, typename device_grid, typename Memory>
146 {
147 
156  template<unsigned int ... prp> static void unpacking(ExtPreAlloc<Memory> & recv_buf, grid_key_dx_iterator_sub<device_grid::dims> & sub2, device_grid & dg, Unpack_stat & ps)
157  {
158  typedef index_tuple<prp...> ind_prop_to_pack;
159  grid_call_serialize_variadic<device_grid,Memory,ind_prop_to_pack>::template call_unpack<op,T>(recv_buf, sub2, dg, ps);
160  }
161 };
162 
176 template<unsigned int dim, typename St, typename T, typename Decomposition = CartDecomposition<dim,St>,typename Memory=HeapMemory , typename device_grid=grid_cpu<dim,T> >
178 {
181 
184 
187 
190 
196 
199 
202 
203 
215  template<int... prp> void ghost_get_local(const openfpm::vector<i_lbox_grid<dim>> & loc_ig_box,
216  const openfpm::vector<e_lbox_grid<dim>> & loc_eg_box,
218  openfpm::vector<device_grid> & loc_grid,
219  std::unordered_map<size_t,size_t> & g_id_to_external_ghost_box)
220  {
221  grid_key_dx<dim> cnt[1];
222  cnt[0].zero();
223 
225  for (size_t i = 0 ; i < loc_ig_box.size() ; i++)
226  {
228  for (size_t j = 0 ; j < loc_ig_box.get(i).bid.size() ; j++)
229  {
230  Box<dim,size_t> bx_src = loc_ig_box.get(i).bid.get(j).box;
231  // convert into local
232  bx_src -= gdb_ext.get(i).origin;
233 
234  // sub domain connected with external box
235  size_t sub_id_dst = loc_ig_box.get(i).bid.get(j).sub;
236 
237  // local internal ghost box connected
238  size_t k = loc_ig_box.get(i).bid.get(j).k;
239 
240  Box<dim,size_t> bx_dst = loc_eg_box.get(sub_id_dst).bid.get(k).box;
241 
242  // convert into local
243  bx_dst -= gdb_ext.get(sub_id_dst).origin;
244 
245  // create 2 sub grid iterator
246 
247  if (bx_dst.isValid() == false)
248  continue;
249 
250  const auto & gs = loc_grid.get(i);
251  auto & gd = loc_grid.get(sub_id_dst);
252 
253 #ifdef SE_CLASS1
254 
255  if (loc_eg_box.get(sub_id_dst).bid.get(k).sub != i)
256  {std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " source and destination are not correctly linked" << "\n";}
257 
258  if (bx_src.getVolumeKey() != bx_dst.getVolumeKey())
259  {std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " source and destination does not match in size" << "\n";}
260 
261  auto bxs = gs.getGrid().getBoxKey();
262  auto bxd = gd.getGrid().getBoxKey();
263 
264  if (bxs.isContained(bx_src) == false)
265  {std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the source box is out of bound of the local grid" << "\n";}
266 
267  if (bxd.isContained(bx_dst) == false)
268  {std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " the destination box is out of bound of the local grid" << "\n";}
269 
270 #endif
271 
272  typedef typename std::remove_reference<decltype(gd)>::type grid_cp;
273  typedef typename std::remove_reference<decltype(loc_grid.get(i).getGrid())>::type grid_info_cp;
274 
276  dim,
277  grid_cp,
278  grid_info_cp>::copy(loc_grid.get(i).getGrid(),
279  loc_grid.get(sub_id_dst).getGrid(),
280  bx_src,
281  bx_dst,
282  gs,gd,cnt);
283  }
284  }
285  }
286 
298  template<template<typename,typename> class op, int... prp> void ghost_put_local(const openfpm::vector<i_lbox_grid<dim>> & loc_ig_box,
299  const openfpm::vector<e_lbox_grid<dim>> & loc_eg_box,
301  openfpm::vector<device_grid> & loc_grid,
302  openfpm::vector<std::unordered_map<size_t,size_t>> & g_id_to_external_ghost_box)
303  {
305  for (size_t i = 0 ; i < loc_eg_box.size() ; i++)
306  {
308  for (size_t j = 0 ; j < loc_eg_box.get(i).bid.size() ; j++)
309  {
310  if (loc_eg_box.get(i).bid.get(j).initialized == false)
311  continue;
312 
313  Box<dim,size_t> bx_src = loc_eg_box.get(i).bid.get(j).box;
314  // convert into local
315  bx_src -= gdb_ext.get(i).origin;
316 
317  // sub domain connected with external box
318  size_t sub_id_dst = loc_eg_box.get(i).bid.get(j).sub;
319 
320  // local external ghost box connected
321  size_t k = loc_eg_box.get(i).bid.get(j).k;
322 
323  Box<dim,size_t> bx_dst = loc_ig_box.get(sub_id_dst).bid.get(k).box;
324 
325  // convert into local
326  bx_dst -= gdb_ext.get(sub_id_dst).origin;
327 
328  // create 2 sub grid iterator
329 
330  if (bx_dst.isValid() == false)
331  continue;
332 
333  grid_key_dx_iterator_sub<dim> sub_src(loc_grid.get(i).getGrid(),bx_src.getKP1(),bx_src.getKP2());
334  grid_key_dx_iterator_sub<dim> sub_dst(loc_grid.get(sub_id_dst).getGrid(),bx_dst.getKP1(),bx_dst.getKP2());
335 
336 #ifdef SE_CLASS1
337 
338  if (loc_ig_box.get(sub_id_dst).bid.get(k).sub != i)
339  std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " source and destination are not correctly linked" << "\n";
340 
341  if (sub_src.getVolume() != sub_dst.getVolume())
342  std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " source and destination does not match in size" << "\n";
343 
344 #endif
345 
346  const auto & gs = loc_grid.get(i);
347  auto & gd = loc_grid.get(sub_id_dst);
348 
349  while (sub_src.isNext())
350  {
351  // write the object in the last element
352  object_s_di_op<op,decltype(gs.get_o(sub_src.get())),decltype(gd.get_o(sub_dst.get())),OBJ_ENCAP,prp...>(gs.get_o(sub_src.get()),gd.get_o(sub_dst.get()));
353 
354  ++sub_src;
355  ++sub_dst;
356  }
357  }
358  }
359  }
360 
367  template<int... prp>
369  ExtPreAlloc<Memory> ** prRecv_prp,
370  const openfpm::vector<ip_box_grid<dim>> & ig_box,
371  const openfpm::vector<ep_box_grid<dim>> & eg_box,
373  openfpm::vector<device_grid> & loc_grid,
374  size_t & req)
375  {
376  // Sending property object
377  typedef object<typename object_creator<typename T::type,prp...>::type> prp_object;
378 
379  // Create a packing request vector
380  for ( size_t i = 0 ; i < ig_box.size() ; i++ )
381  {
382  // for each ghost box
383  for (size_t j = 0 ; j < ig_box.get(i).bid.size() ; j++)
384  {
385  // And linked sub-domain
386  size_t sub_id = ig_box.get(i).bid.get(j).sub;
387  // Internal ghost box
388  Box<dim,long int> g_ig_box = ig_box.get(i).bid.get(j).box;
389 
390  if (g_ig_box.isValid() == false)
391  continue;
392 
393  g_ig_box -= gdb_ext.get(sub_id).origin.template convertPoint<size_t>();
394 
395  // Pack a size_t for the internal ghost id
397 
398  // Create a sub grid iterator spanning the internal ghost layer
399 
400  grid_key_dx_iterator_sub<dim> sub_it(loc_grid.get(sub_id).getGrid(),g_ig_box.getKP1(),g_ig_box.getKP2());
401  // and pack the internal ghost grid
402  Packer<device_grid,HeapMemory>::template packRequest<prp...>(loc_grid.get(sub_id),sub_it,req);
403  }
404  }
405 
406  // resize the property buffer memory
407  g_send_prp_mem.resize(req);
408 
409  // Create an object of preallocated memory for properties
410  (*prAlloc_prp) = new ExtPreAlloc<Memory>(req,g_send_prp_mem);
411  (*prAlloc_prp)->incRef();
412 
413  // Pack information
414  Pack_stat sts;
415 
416  // Pack the information for each processor and send it
417  for ( size_t i = 0 ; i < ig_box.size() ; i++ )
418  {
419 
420  sts.mark();
421  void * pointer = (*prAlloc_prp)->getPointerEnd();
422 
423  // for each ghost box
424  for (size_t j = 0 ; j < ig_box.get(i).bid.size() ; j++)
425  {
426  // we pack only if it is valid
427  if (ig_box.get(i).bid.get(j).box.isValid() == false)
428  continue;
429 
430  // And linked sub-domain
431  size_t sub_id = ig_box.get(i).bid.get(j).sub;
432  // Internal ghost box
433  Box<dim,size_t> g_ig_box = ig_box.get(i).bid.get(j).box;
434  g_ig_box -= gdb_ext.get(sub_id).origin.template convertPoint<size_t>();
435  // Ghost box global id
436  size_t g_id = ig_box.get(i).bid.get(j).g_id;
437 
438  // Pack a size_t for the internal ghost id
439  Packer<size_t,HeapMemory>::pack(**prAlloc_prp,g_id,sts);
440 
441  // Create a sub grid iterator spanning the internal ghost layer
442  grid_key_dx_iterator_sub<dim> sub_it(loc_grid.get(sub_id).getGrid(),g_ig_box.getKP1(),g_ig_box.getKP2());
443  // and pack the internal ghost grid
444  Packer<device_grid,HeapMemory>::template pack<prp...>(**prAlloc_prp,loc_grid.get(sub_id),sub_it,sts);
445  }
446  // send the request
447 
448  void * pointer2 = (*prAlloc_prp)->getPointerEnd();
449 
450  v_cl.send(ig_box.get(i).prc,0,pointer,(char *)pointer2 - (char *)pointer);
451  }
452 
453  // Calculate the total information to receive from each processors
454  std::vector<size_t> prp_recv;
455 
457  for ( size_t i = 0 ; i < eg_box.size() ; i++ )
458  {
459  prp_recv.push_back(0);
460 
461  // for each external ghost box
462  for (size_t j = 0 ; j < eg_box.get(i).bid.size() ; j++)
463  {
464  // External ghost box
465  Box<dim,size_t> g_eg_box = eg_box.get(i).bid.get(j).g_e_box;
466  prp_recv[prp_recv.size()-1] += g_eg_box.getVolumeKey() * sizeof(prp_object) + sizeof(size_t);
467  }
468  }
469 
470  size_t tot_recv = ExtPreAlloc<Memory>::calculateMem(prp_recv);
471 
473  g_recv_prp_mem.resize(tot_recv);
474 
475  // Create an object of preallocated memory for properties
476  (*prRecv_prp) = new ExtPreAlloc<Memory>(tot_recv,g_recv_prp_mem);
477  (*prRecv_prp)->incRef();
478 
479  // queue the receives
480  for ( size_t i = 0 ; i < eg_box.size() ; i++ )
481  {
482  (*prRecv_prp)->allocate(prp_recv[i]);
483  v_cl.recv(eg_box.get(i).prc,0,(*prRecv_prp)->getPointer(),prp_recv[i]);
484  }
485  }
486 
492  template<int... prp>
494  const openfpm::vector<ep_box_grid<dim>> & eg_box,
495  openfpm::vector<device_grid> & loc_grid,
496  std::unordered_map<size_t,size_t> & g_id_to_external_ghost_box)
497  {
498  Unpack_stat ps;
499 
500  // Unpack the object
501  for ( size_t i = 0 ; i < eg_box.size() ; i++ )
502  {
503  // for each external ghost box
504  for (size_t j = 0 ; j < eg_box.get(i).bid.size() ; j++)
505  {
506  // Unpack the ghost box global-id
507 
508  size_t g_id;
509  Unpacker<size_t,HeapMemory>::unpack(*prRecv_prp,g_id,ps);
510 
511  size_t l_id = 0;
512  // convert the global id into local id
513  auto key = g_id_to_external_ghost_box.find(g_id);
514  if (key != g_id_to_external_ghost_box.end()) // FOUND
515  l_id = key->second;
516  else
517  {
518  // NOT FOUND
519 
520  // It must be always found, if not it mean that the processor has no-idea of
521  // what is stored and conseguently do not know how to unpack, print a critical error
522  // and return
523 
524  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " Critical, cannot unpack object, because received data cannot be interpreted\n";
525 
526  return;
527  }
528 
529  // Get the external ghost box associated with the packed information
530  Box<dim,size_t> box = eg_box.get(i).bid.get(l_id).l_e_box;
531  size_t sub_id = eg_box.get(i).bid.get(l_id).sub;
532 
533  // sub-grid where to unpack
534  grid_key_dx_iterator_sub<dim> sub2(loc_grid.get(sub_id).getGrid(),box.getKP1(),box.getKP2());
535 
536  // Unpack
537  Unpacker<device_grid,HeapMemory>::template unpack<prp...>(*prRecv_prp,sub2,loc_grid.get(sub_id),ps);
538  }
539  }
540  }
541 
542 public:
543 
553  openfpm::vector<device_grid> & loc_grid,
555  CellDecomposer_sm<dim,St,shift<dim,St>> & cd_sm)
556  {
557  size_t count2 = 0;
558  for (size_t a = 0; a < m_oGrid_recv.size(); a++)
559  {
560  for (size_t k = 0; k < m_oGrid_recv.get(a).size(); k++)
561  {
562  device_grid g = m_oGrid_recv.get(a).template get<0>(k);
563 
564  size_t count = 0;
565 
566 
567  auto it = g.getIterator();
568 
569  while (it.isNext())
570  {
571  ++it;
572  count++;
573  }
574 
575  SpaceBox<dim,long int> b = m_oGrid_recv.get(a).template get<1>(k);
576 
577  Point<dim,St> p;
578  for (size_t n = 0; n < dim; n++)
579  {p.get(n) = g.getGrid().getBox().getHigh(n);}
580 
581  Point<dim,St> point;
582  for (size_t n = 0; n < dim; n++)
583  {point.get(n) = (b.getHigh(n) + b.getLow(n))/2;}
584 
585  for (size_t j = 0; j < gdb_ext.size(); j++)
586  {
587  // Local sub-domain
588  SpaceBox<dim,long int> sub = gdb_ext.get(j).Dbox;
589  sub += gdb_ext.get(j).origin;
590 
591  if (sub.isInside(point) == true)
592  {
593  grid_key_dx<dim> start = b.getKP1() - grid_key_dx<dim>(gdb_ext.get(j).origin.asArray());
594  grid_key_dx<dim> stop = b.getKP2() - grid_key_dx<dim>(gdb_ext.get(j).origin.asArray());
595 
596  std::string start2 = start.to_string();
597  std::string stop2 = stop.to_string();
598 
599  auto it = loc_grid.get(j).getSubIterator(start,stop);
600 
601  // Copy selected elements into a local grid
602  while (it.isNext())
603  {
604  auto key = it.get();
605  std::string str = key.to_string();
606  grid_key_dx<dim> key2 = key - start;
607 
608  loc_grid.get(j).get_o(key) = g.get_o(key2);
609  count2++;
610 
611  ++it;
612  }
613  }
614  }
615  }
616  }
617  }
618 
632  CellDecomposer_sm<dim,St,shift<dim,St>> & cd_sm,
633  openfpm::vector<device_grid> & loc_grid_old,
636  openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext_global,
638  openfpm::vector<size_t> & prc_sz)
639  {
640  // resize the label buffer
641  lbl_b.resize(v_cl.getProcessingUnits());
642 
643  size_t count2 = 0;
644 
645  // Label all the intersection grids with the processor id where they should go
646 
647  for (size_t i = 0; i < gdb_ext_old.size(); i++)
648  {
649  // Local old sub-domain in global coordinates
650  SpaceBox<dim,long int> sub_dom = gdb_ext_old.get(i).Dbox;
651  sub_dom += gdb_ext_old.get(i).origin;
652 
653  for (size_t j = 0; j < gdb_ext_global.size(); j++)
654  {
655  size_t p_id = 0;
656 
657  // Intersection box
658  SpaceBox<dim,long int> inte_box;
659 
660  // Global new sub-domain in global coordinates
661  SpaceBox<dim,long int> sub_dom_new = gdb_ext_global.get(j).Dbox;
662  sub_dom_new += gdb_ext_global.get(j).origin;
663 
664  bool intersect = false;
665 
666  if (sub_dom.isValid() == true && sub_dom_new.isValid() == true)
667  intersect = sub_dom.Intersect(sub_dom_new, inte_box);
668 
669  if (intersect == true)
670  {
671  count2++;
672  auto inte_box_cont = cd_sm.convertCellUnitsIntoDomainSpace(inte_box);
673 
674  // Get processor ID that store intersection box
675  Point<dim,St> p;
676  for (size_t n = 0; n < dim; n++)
677  p.get(n) = (inte_box_cont.getHigh(n) + inte_box_cont.getLow(n))/2;
678 
679  p_id = dec.processorID(p);
680  prc_sz.get(p_id)++;
681 
682  // Transform coordinates to local
683  auto inte_box_local = inte_box;
684 
685  inte_box_local -= gdb_ext_old.get(i).origin;
686 
687  // Grid corresponding for gdb_ext_old.get(i) box
688  device_grid & gr = loc_grid_old.get(i);
689 
690  // Size of the grid to send
691  size_t sz[dim];
692  for (size_t l = 0; l < dim; l++)
693  {
694  sz[l] = inte_box_local.getHigh(l) - inte_box_local.getLow(l) + 1;
695  //std::cout << "GR_send size on " << l << " dimension: " << sz[l] << std::endl;
696  }
697 
698  // Grid to send
699  device_grid gr_send(sz);
700  gr_send.setMemory();
701 
702  // Sub iterator across intersection box inside local grid
703  grid_key_dx<dim> start = inte_box_local.getKP1();
704  grid_key_dx<dim> stop = inte_box_local.getKP2();
705 
706  Point<dim,St> p1;
707  for (size_t n = 0; n < dim; n++)
708  p1.get(n) = gr_send.getGrid().getBox().getLow(n);
709 
710  Point<dim,St> p2;
711  for (size_t n = 0; n < dim; n++)
712  p2.get(n) = gr_send.getGrid().getBox().getHigh(n);
713 
714  std::string start2 = start.to_string();
715  std::string stop2 = stop.to_string();
716 
717  auto it = gr.getSubIterator(start,stop);
718 
719  // Copy selected elements into a new sub-grid
720  while (it.isNext())
721  {
722  auto key = it.get();
723  grid_key_dx<dim> key2 = key - start;
724  std::string str = key.to_string();
725 
726  gr_send.get_o(key2) = gr.get_o(key);
727 
728  ++it;
729  }
730 
732 
733  aggr.template get<0>() = gr_send;
734  aggr.template get<1>() = inte_box;
735 
736  // Add to the labeling vector
737  lbl_b.get(p_id).add(aggr);
738  }
739  }
740  }
741  }
742 
756  void map_(Decomposition & dec,
757  CellDecomposer_sm<dim,St,shift<dim,St>> & cd_sm,
758  openfpm::vector<device_grid> & loc_grid,
759  openfpm::vector<device_grid> & loc_grid_old,
762  openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext_global)
763  {
764  // Processor communication size
765  openfpm::vector<size_t> prc_sz(v_cl.getProcessingUnits());
766 
767  // Contains the processor id of each box (basically where they have to go)
768  labelIntersectionGridsProcessor(dec,cd_sm,loc_grid_old,gdb_ext,gdb_ext_old,gdb_ext_global,m_oGrid,prc_sz);
769 
770  // Calculate the sending buffer size for each processor, put this information in
771  // a contiguous buffer
772  p_map_req.resize(v_cl.getProcessingUnits());
773 
774  // Vector of number of sending grids for each involved processor
775  openfpm::vector<size_t> prc_sz_r;
776  // Vector of ranks of involved processors
778 
779  for (size_t i = 0; i < v_cl.getProcessingUnits(); i++)
780  {
781  if (m_oGrid.get(i).size() != 0)
782  {
783  p_map_req.get(i) = prc_r.size();
784  prc_r.add(i);
785  prc_sz_r.add(m_oGrid.get(i).size());
786  }
787  }
788 
789  decltype(m_oGrid) m_oGrid_new;
790  for (size_t i = 0; i < v_cl.getProcessingUnits(); i++)
791  {
792  if (m_oGrid.get(i).size() != 0)
793  m_oGrid_new.add(m_oGrid.get(i));
794  }
795 
796  // Vector for receiving of intersection grids
798 
799  // Send and recieve intersection grids
800  v_cl.SSendRecv(m_oGrid_new,m_oGrid_recv,prc_r,prc_recv_map,recv_sz_map);
801 
802  // Reconstruct the new local grids
803  grids_reconstruct(m_oGrid_recv,loc_grid,gdb_ext,cd_sm);
804  }
805 
817  template<int... prp> void ghost_get_(const openfpm::vector<ip_box_grid<dim>> & ig_box,
818  const openfpm::vector<ep_box_grid<dim>> & eg_box,
819  const openfpm::vector<i_lbox_grid<dim>> & loc_ig_box,
820  const openfpm::vector<e_lbox_grid<dim>> & loc_eg_box,
822  openfpm::vector<device_grid> & loc_grid,
823  std::unordered_map<size_t,size_t> & g_id_to_external_ghost_box)
824  {
825  size_t req = 0;
826 
827  ExtPreAlloc<Memory> * prRecv_prp = NULL;
828  ExtPreAlloc<Memory> * prAlloc_prp = NULL;
829 
830  if (v_cl.getProcessingUnits() != 1)
831  {send_and_receive_ghost<prp...>(&prAlloc_prp,&prRecv_prp, ig_box,eg_box,gdb_ext,loc_grid,req);}
832 
833  // Before wait for the communication to complete we sync the local ghost
834  // in order to overlap with communication
835 
836  ghost_get_local<prp...>(loc_ig_box,loc_eg_box,gdb_ext,loc_grid,g_id_to_external_ghost_box);
837 
838  // wait to receive communication
839  v_cl.execute();
840 
841  if (v_cl.getProcessingUnits() != 1)
842  {process_received<prp...>(prRecv_prp,eg_box,loc_grid,g_id_to_external_ghost_box);}
843  }
844 
859  template<template<typename,typename> class op,int... prp>
861  const openfpm::vector<ep_box_grid<dim>> & eg_box,
862  const openfpm::vector<i_lbox_grid<dim>> & loc_ig_box,
863  const openfpm::vector<e_lbox_grid<dim>> & loc_eg_box,
865  openfpm::vector<device_grid> & loc_grid,
866  openfpm::vector<std::unordered_map<size_t,size_t>> & g_id_to_internal_ghost_box)
867  {
868  // Sending property object
869  typedef object<typename object_creator<typename T::type,prp...>::type> prp_object;
870 
871  size_t req = 0;
872 
873  // Create a packing request vector
874  for ( size_t i = 0 ; i < eg_box.size() ; i++ )
875  {
876  // for each ghost box
877  for (size_t j = 0 ; j < eg_box.get(i).bid.size() ; j++)
878  {
879  // And linked sub-domain
880  size_t sub_id = eg_box.get(i).bid.get(j).sub;
881  // Internal ghost box
882  Box<dim,long int> g_eg_box = eg_box.get(i).bid.get(j).g_e_box;
883 
884  if (g_eg_box.isValid() == false)
885  continue;
886 
887  g_eg_box -= gdb_ext.get(sub_id).origin.template convertPoint<size_t>();
888 
889  // Pack a size_t for the internal ghost id
891 
892  // Create a sub grid iterator spanning the internal ghost layer
893  grid_key_dx_iterator_sub<dim> sub_it(loc_grid.get(sub_id).getGrid(),g_eg_box.getKP1(),g_eg_box.getKP2());
894  // and pack the internal ghost grid
895  Packer<device_grid,HeapMemory>::template packRequest<prp...>(loc_grid.get(sub_id),sub_it,req);
896  }
897  }
898 
899  // resize the property buffer memory
900  g_send_prp_mem.resize(req);
901 
902  // Create an object of preallocated memory for properties
903  ExtPreAlloc<Memory> & prAlloc_prp = *(new ExtPreAlloc<Memory>(req,g_send_prp_mem));
904 
905  prAlloc_prp.incRef();
906 
907  // Pack information
908  Pack_stat sts;
909 
910  // Pack the information for each processor and send it
911  for ( size_t i = 0 ; i < eg_box.size() ; i++ )
912  {
913 
914  sts.mark();
915  void * pointer = prAlloc_prp.getPointerEnd();
916 
917  // for each ghost box
918  for (size_t j = 0 ; j < eg_box.get(i).bid.size() ; j++)
919  {
920  // we pack only if it is valid
921  if (eg_box.get(i).bid.get(j).g_e_box.isValid() == false)
922  continue;
923 
924  // And linked sub-domain
925  size_t sub_id = eg_box.get(i).bid.get(j).sub;
926  // Internal ghost box
927  Box<dim,size_t> g_eg_box = eg_box.get(i).bid.get(j).g_e_box;
928  g_eg_box -= gdb_ext.get(sub_id).origin.template convertPoint<size_t>();
929  // Ghost box global id
930  size_t g_id = eg_box.get(i).bid.get(j).g_id;
931 
932  // Pack a size_t for the internal ghost id
933  Packer<size_t,HeapMemory>::pack(prAlloc_prp,g_id,sts);
934 
935  // Create a sub grid iterator spanning the internal ghost layer
936  grid_key_dx_iterator_sub<dim> sub_it(loc_grid.get(sub_id).getGrid(),g_eg_box.getKP1(),g_eg_box.getKP2());
937  // and pack the internal ghost grid
938  Packer<device_grid,HeapMemory>::template pack<prp...>(prAlloc_prp,loc_grid.get(sub_id),sub_it,sts);
939  }
940  // send the request
941 
942  void * pointer2 = prAlloc_prp.getPointerEnd();
943 
944  v_cl.send(ig_box.get(i).prc,0,pointer,(char *)pointer2 - (char *)pointer);
945  }
946 
947  // Calculate the total information to receive from each processors
948  std::vector<size_t> prp_recv;
949 
951  for ( size_t i = 0 ; i < ig_box.size() ; i++ )
952  {
953  prp_recv.push_back(0);
954 
955  // for each external ghost box
956  for (size_t j = 0 ; j < ig_box.get(i).bid.size() ; j++)
957  {
958  // External ghost box
959  Box<dim,size_t> g_ig_box = ig_box.get(i).bid.get(j).box;
960  prp_recv[prp_recv.size()-1] += g_ig_box.getVolumeKey() * sizeof(prp_object) + sizeof(size_t);
961  }
962  }
963 
964  size_t tot_recv = ExtPreAlloc<Memory>::calculateMem(prp_recv);
965 
967  g_recv_prp_mem.resize(tot_recv);
968 
969  // Create an object of preallocated memory for properties
970  ExtPreAlloc<Memory> & prRecv_prp = *(new ExtPreAlloc<Memory>(tot_recv,g_recv_prp_mem));
971  prRecv_prp.incRef();
972 
973  // queue the receives
974  for ( size_t i = 0 ; i < ig_box.size() ; i++ )
975  {
976  prRecv_prp.allocate(prp_recv[i]);
977  v_cl.recv(ig_box.get(i).prc,0,prRecv_prp.getPointer(),prp_recv[i]);
978  }
979 
980  // Before wait for the communication to complete we sync the local ghost
981  // in order to overlap with communication
982 
983  ghost_put_local<op,prp...>(loc_ig_box,loc_eg_box,gdb_ext,loc_grid,g_id_to_internal_ghost_box);
984 
985  // wait to receive communication
986  v_cl.execute();
987 
988  Unpack_stat ps;
989 
990  // Unpack the object
991  for ( size_t i = 0 ; i < ig_box.size() ; i++ )
992  {
993  // for each external ghost box
994  for (size_t j = 0 ; j < ig_box.get(i).bid.size() ; j++)
995  {
996  // Unpack the ghost box global-id
997 
998  size_t g_id;
999  Unpacker<size_t,HeapMemory>::unpack(prRecv_prp,g_id,ps);
1000 
1001  size_t l_id = 0;
1002  // convert the global id into local id
1003  auto key = g_id_to_internal_ghost_box.get(i).find(g_id);
1004  if (key != g_id_to_internal_ghost_box.get(i).end()) // FOUND
1005  l_id = key->second;
1006  else
1007  {
1008  // NOT FOUND
1009 
1010  // It must be always found, if not it mean that the processor has no-idea of
1011  // what is stored and conseguently do not know how to unpack, print a critical error
1012  // and return
1013 
1014  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " Critical, cannot unpack object, because received data cannot be interpreted\n";
1015 
1016  return;
1017  }
1018 
1019  // Get the internal ghost box associated with the packed information
1020  Box<dim,size_t> box = ig_box.get(i).bid.get(l_id).box;
1021  size_t sub_id = ig_box.get(i).bid.get(l_id).sub;
1022  box -= gdb_ext.get(sub_id).origin.template convertPoint<size_t>();
1023 
1024  // sub-grid where to unpack
1025  grid_key_dx_iterator_sub<dim> sub2(loc_grid.get(sub_id).getGrid(),box.getKP1(),box.getKP2());
1026 
1027  grid_unpack_with_prp<op,prp_object,device_grid,Memory>::template unpacking<prp...>(prRecv_prp,sub2,loc_grid.get(sub_id),ps);
1028  }
1029  }
1030  }
1031 
1037  :v_cl(create_vcluster())
1038  {
1039 
1040  }
1041 };
1042 
1043 
1044 #endif /* SRC_GRID_GRID_DIST_ID_COMM_HPP_ */
size_t getOffset()
Return the actual counter.
Definition: Pack_stat.hpp:41
This class represent an N-dimensional box.
Definition: SpaceBox.hpp:26
void mark()
Mark.
Definition: Pack_stat.hpp:90
void ghost_get_local(const openfpm::vector< i_lbox_grid< dim >> &loc_ig_box, const openfpm::vector< e_lbox_grid< dim >> &loc_eg_box, const openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, openfpm::vector< device_grid > &loc_grid, std::unordered_map< size_t, size_t > &g_id_to_external_ghost_box)
Sync the local ghost part.
void ghost_put_(const openfpm::vector< ip_box_grid< dim >> &ig_box, const openfpm::vector< ep_box_grid< dim >> &eg_box, const openfpm::vector< i_lbox_grid< dim >> &loc_ig_box, const openfpm::vector< e_lbox_grid< dim >> &loc_eg_box, const openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, openfpm::vector< device_grid > &loc_grid, openfpm::vector< std::unordered_map< size_t, size_t >> &g_id_to_internal_ghost_box)
It merge the information in the ghost with the real information.
openfpm::vector< size_t > recv_sz_map
Stores the size of the elements added for each processor that communicate with us (local processor) ...
Unpacker class.
Definition: Packer_util.hpp:20
T getLow(int i) const
get the i-coordinate of the low bound interval of the box
Definition: Box.hpp:479
This class is an helper for the communication of grid_dist_id.
bool isValid() const
Check if the Box is a valid box P2 >= P1.
Definition: Box.hpp:997
grid_key_dx is the key to access any element in the grid
Definition: grid_key.hpp:18
local Internal ghost box
Memory g_send_prp_mem
Memory for the ghost sending buffer.
bool isInside(const Point< dim, T > &p) const
Check if the point is inside the box.
Definition: Box.hpp:880
Memory g_recv_prp_mem
Memory for the ghost sending buffer.
grid_key_dx< dim > getKP2() const
Get the point p12 as grid_key_dx.
Definition: Box.hpp:592
const grid_key_dx< dim > & getStop() const
Stop point.
virtual void * getPointer()
Return the pointer of the last allocation.
T getHigh(int i) const
get the high interval of the box
Definition: Box.hpp:490
Per-processor Internal ghost box.
size_t size()
Stub size.
Definition: map_vector.hpp:70
std::string to_string()
convert the information into a string
Definition: grid_key.hpp:349
void labelIntersectionGridsProcessor(Decomposition &dec, CellDecomposer_sm< dim, St, shift< dim, St >> &cd_sm, openfpm::vector< device_grid > &loc_grid_old, openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext_old, openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext_global, openfpm::vector< openfpm::vector< aggregate< device_grid, SpaceBox< dim, long int >>>> &lbl_b, openfpm::vector< size_t > &prc_sz)
Label intersection grids for mappings.
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:22
void grids_reconstruct(openfpm::vector< openfpm::vector< aggregate< device_grid, SpaceBox< dim, long int >>>> &m_oGrid_recv, openfpm::vector< device_grid > &loc_grid, openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, CellDecomposer_sm< dim, St, shift< dim, St >> &cd_sm)
Reconstruct the local grids.
This is a way to quickly copy a grid into another grid.
grid_key_dx< dim > getKP1() const
Get the point p1 as grid_key_dx.
Definition: Box.hpp:579
static void call_unpack(ExtPreAlloc< Memory > &recv_buf, grid_key_dx_iterator_sub< device_grid::dims > &sub2, device_grid &gd, Unpack_stat &ps)
Unpack.
bool send(size_t proc, size_t tag, const void *mem, size_t sz)
Send data to a processor.
virtual bool allocate(size_t sz)
Allocate a chunk of memory.
Definition: ExtPreAlloc.hpp:92
Implementation of VCluster class.
Definition: VCluster.hpp:36
This structure store the Box that define the domain inside the Ghost + domain box.
Definition: GBoxes.hpp:39
This class define the domain decomposition interface.
bool Intersect(const Box< dim, T > &b, Box< dim, T > &b_out) const
Intersect.
Definition: Box.hpp:88
void ghost_get_(const openfpm::vector< ip_box_grid< dim >> &ig_box, const openfpm::vector< ep_box_grid< dim >> &eg_box, const openfpm::vector< i_lbox_grid< dim >> &loc_ig_box, const openfpm::vector< e_lbox_grid< dim >> &loc_eg_box, const openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, openfpm::vector< device_grid > &loc_grid, std::unordered_map< size_t, size_t > &g_id_to_external_ghost_box)
It fill the ghost part of the grids.
static void unpacking(ExtPreAlloc< Memory > &recv_buf, grid_key_dx_iterator_sub< device_grid::dims > &sub2, device_grid &dg, Unpack_stat &ps)
Unpack.
static size_t packRequest(const T &obj, size_t &req)
Error, no implementation.
Definition: Packer.hpp:59
It copy the properties from one object to another applying an operation.
static void call_unpack(ExtPreAlloc< Memory > &recv_buf, grid_key_dx_iterator_sub< device_grid::dims > &sub2, device_grid &gd, Unpack_stat &ps)
Error i do not know how to unpack.
void send_and_receive_ghost(ExtPreAlloc< Memory > **prAlloc_prp, ExtPreAlloc< Memory > **prRecv_prp, const openfpm::vector< ip_box_grid< dim >> &ig_box, const openfpm::vector< ep_box_grid< dim >> &eg_box, const openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, openfpm::vector< device_grid > &loc_grid, size_t &req)
this function create send and receive asynchronously to receive ghosts part
void zero()
Set to zero the key.
Definition: grid_key.hpp:116
bool recv(size_t proc, size_t tag, void *v, size_t sz)
Recv data from a processor.
Packing class.
Definition: Packer.hpp:44
void addOffset(size_t off)
Increment the offset pointer by off.
Definition: Pack_stat.hpp:31
virtual void incRef()
Increment the reference counter.
Definition: ExtPreAlloc.hpp:69
Unpacking status object.
Definition: Pack_stat.hpp:15
const T & get(size_t i) const
Get coordinate.
Definition: Point.hpp:142
These set of classes generate an array definition at compile-time.
Definition: ct_array.hpp:25
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. ...
Definition: memory_c.hpp:201
void * getPointerBase()
The the base pointer of the preallocate memory.
static void unpack(ExtPreAlloc< Mem >, T &obj)
Error, no implementation.
Definition: Unpacker.hpp:36
openfpm::vector< openfpm::vector< aggregate< device_grid, SpaceBox< dim, long int > > > > m_oGrid
openfpm::vector< size_t > prc_recv_map
Stores the list of processors that communicate with us (local processor)
openfpm::vector< size_t > p_map_req
Maps the processor id with the communication request into map procedure.
Per-processor external ghost box.
It return true if the object T require complex serialization.
void map_(Decomposition &dec, CellDecomposer_sm< dim, St, shift< dim, St >> &cd_sm, openfpm::vector< device_grid > &loc_grid, openfpm::vector< device_grid > &loc_grid_old, openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext_old, openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext_global)
Moves all the grids that does not belong to the local processor to the respective processor...
Per-processor external ghost box.
Declaration grid_key_dx_iterator_sub.
Definition: grid_sm.hpp:77
It create a boost::fusion vector with the selected properties.
static void call_unpack(ExtPreAlloc< Memory > &recv_buf, grid_key_dx_iterator_sub< device_grid::dims > &sub2, device_grid &dg, Unpack_stat &ps)
Unpack.
void process_received(ExtPreAlloc< Memory > *prRecv_prp, const openfpm::vector< ep_box_grid< dim >> &eg_box, openfpm::vector< device_grid > &loc_grid, std::unordered_map< size_t, size_t > &g_id_to_external_ghost_box)
Process the received data.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:81
T getVolumeKey() const
Get the volume spanned by the Box P1 and P2 interpreted as grid key.
Definition: Box.hpp:1154
Packing status object.
Definition: Pack_stat.hpp:51
bool isNext()
Check if there is the next element.
virtual size_t size() const
Get the size of the LAST allocated memory.
static void pack(ExtPreAlloc< Mem >, const T &obj)
Error, no implementation.
Definition: Packer.hpp:51
const grid_key_dx< dim > & getStart() const
Starting point.
static size_t calculateMem(std::vector< size_t > &mm)
Calculate the total memory required to pack the message.
void * getPointerEnd()
Return the end pointer of the previous allocated memory.
grid_dist_id_comm()
Constructor.
void ghost_put_local(const openfpm::vector< i_lbox_grid< dim >> &loc_ig_box, const openfpm::vector< e_lbox_grid< dim >> &loc_eg_box, const openfpm::vector< GBoxes< device_grid::dims >> &gdb_ext, openfpm::vector< device_grid > &loc_grid, openfpm::vector< std::unordered_map< size_t, size_t >> &g_id_to_external_ghost_box)
Sync the local ghost part.
This class give memory from a preallocated memory, memory destruction is not performed.
Definition: PtrMemory.hpp:42
Vcluster & v_cl
VCluster.