OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
vector_dist_comm.hpp
1 /*
2  * vector_dist_comm.hpp
3  *
4  * Created on: Aug 18, 2016
5  * Author: i-bird
6  */
7 
8 #ifndef SRC_VECTOR_VECTOR_DIST_COMM_HPP_
9 #define SRC_VECTOR_VECTOR_DIST_COMM_HPP_
10 
11 #define SKIP_LABELLING 512
12 #define KEEP_PROPERTIES 512
13 
14 #define NO_POSITION 1
15 #define WITH_POSITION 2
16 #define NO_CHANGE_ELEMENTS 4
17 
18 #define BIND_DEC_TO_GHOST 1
19 
20 #define MAP_LOCAL 2
21 
26 inline static size_t compute_options(size_t opt)
27 {
28  size_t opt_ = NONE;
29  if (opt & NO_CHANGE_ELEMENTS)
30  opt_ = RECEIVE_KNOWN | KNOWN_ELEMENT_OR_BYTE;
31 
32  return opt_;
33 }
34 
47 template<unsigned int dim,
48  typename St,
49  typename prop,
50  typename layout,
51  template <typename> class layout_base,
53  typename Memory = HeapMemory>
55 {
57  size_t v_sub_unit_factor = 64;
58 
61 
64 
66  Decomposition dec;
67 
70 
77 
82 
85 
88 
92 
95 
98 
104 
105 
108 
111 
114  size_t lg_m;
115 
118 
121 
124  {
126  template<typename T1, typename T2> inline static void proc(size_t lbl, size_t cnt, size_t id, T1 & v_prp, T2 & m_prp)
127  {
128  m_prp.get(lbl).set(cnt, v_prp.get(id));
129  }
130  };
131 
133  template<typename prp_object, int ... prp>
135  {
137  template<typename T1, typename T2> inline static void proc(size_t lbl, size_t cnt, size_t id, T1 & v_prp, T2 & m_prp)
138  {
139  // source object type
141  // destination object type
143 
144  // Copy only the selected properties
145  object_si_d<encap_src, encap_dst, OBJ_ENCAP, prp...>(v_prp.get(id), m_prp.get(lbl).get(cnt));
146  }
147  };
148 
150  template<typename proc_class, typename T1, typename T2, typename T3, typename T4> inline void process_map_particle(size_t i, long int & end, long int & id_end, T1 & m_pos, T2 & m_prp, T3 & v_pos, T4 & v_prp, openfpm::vector<size_t> & cnt)
151  {
152  long int prc_id = m_opart.template get<2>(i);
153  size_t id = m_opart.template get<0>(i);
154 
155  if (prc_id >= 0)
156  {
157  size_t lbl = p_map_req.get(prc_id);
158 
159  m_pos.get(lbl).set(cnt.get(lbl), v_pos.get(id));
160  proc_class::proc(lbl,cnt.get(lbl),id,v_prp,m_prp);
161 
162  cnt.get(lbl)++;
163 
164  // swap the particle
165  long int id_valid = get_end_valid(end,id_end);
166 
167  if (id_valid > 0 && (long int)id < id_valid)
168  {
169  v_pos.set(id,v_pos.get(id_valid));
170  v_prp.set(id,v_prp.get(id_valid));
171  }
172  }
173  else
174  {
175  // swap the particle
176  long int id_valid = get_end_valid(end,id_end);
177 
178  if (id_valid > 0 && (long int)id < id_valid)
179  {
180  v_pos.set(id,v_pos.get(id_valid));
181  v_prp.set(id,v_prp.get(id_valid));
182  }
183  }
184  }
185 
194  inline size_t get_end_valid(long int & end, long int & end_id)
195  {
196  end_id--;
197 
198  while (end >= 0 && end_id >= 0 && (long int)m_opart.template get<0>(end) == end_id)
199  {
200  end_id--;
201  end--;
202  }
203 
204  return end_id;
205  }
206 
208  bool is_shift_box_created = false;
209 
211  std::unordered_map<size_t, size_t> map_cmb;
212 
216 
219 
222 
228  {
229  if (is_shift_box_created == true)
230  return;
231 
232  // Add local particles coming from periodic boundary, the only boxes that count are the one
233  // touching the border, filter them
234  for (size_t i = 0; i < dec.getNLocalSub(); i++)
235  {
236  size_t Nl = dec.getLocalNIGhost(i);
237 
238  for (size_t j = 0; j < Nl; j++)
239  {
240  // If the ghost does not come from the intersection with an out of
241  // border sub-domain the combination is all zero and n_zero return dim
242  if (dec.getLocalIGhostPos(i, j).n_zero() == dim)
243  continue;
244 
245  // Check if we already have boxes with such combination
246  auto it = map_cmb.find(dec.getLocalIGhostPos(i, j).lin());
247  if (it == map_cmb.end())
248  {
249  // we do not have it
250  box_f.add();
251  box_f.last().add(dec.getLocalIGhostBox(i, j));
252  box_cmb.add(dec.getLocalIGhostPos(i, j));
253  map_cmb[dec.getLocalIGhostPos(i, j).lin()] = box_f.size() - 1;
254  }
255  else
256  {
257  // we have it
258  box_f.get(it->second).add(dec.getLocalIGhostBox(i, j));
259  }
260 
261  }
262  }
263 
264  is_shift_box_created = true;
265  }
266 
275  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
276  size_t opt)
277  {
278  // get the shift vectors
279  const openfpm::vector<Point<dim, St>> & shifts = dec.getShiftVectors();
280 
281  if (!(opt & NO_POSITION))
282  {
283  for (size_t i = 0 ; i < o_part_loc.size() ; i++)
284  {
285  size_t lin_id = o_part_loc.get<1>(i);
286  size_t key = o_part_loc.template get<0>(i);
287 
288  Point<dim, St> p = v_pos.get(key);
289  // shift
290  p -= shifts.get(lin_id);
291 
292  // add this particle shifting its position
293  v_pos.add(p);
294  v_prp.get(lg_m+i) = v_prp.get(key);
295  }
296  }
297  else
298  {
299  for (size_t i = 0 ; i < o_part_loc.size() ; i++)
300  {
301  size_t key = o_part_loc.template get<0>(i);
302 
303  v_prp.get(lg_m+i) = v_prp.get(key);
304  }
305  }
306  }
307 
316  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
317  size_t g_m)
318  {
319  o_part_loc.clear();
320 
321  // get the shift vectors
322  const openfpm::vector<Point<dim, St>> & shifts = dec.getShiftVectors();
323 
324  // Label the internal (assigned) particles
325  auto it = v_pos.getIteratorTo(g_m);
326 
327  while (it.isNext())
328  {
329  auto key = it.get();
330 
331  // If particles are inside these boxes
332  for (size_t i = 0; i < box_f.size(); i++)
333  {
334  for (size_t j = 0; j < box_f.get(i).size(); j++)
335  {
336  if (box_f.get(i).get(j).isInside(v_pos.get(key)) == true)
337  {
338  size_t lin_id = dec.convertShift(box_cmb.get(i));
339 
340  o_part_loc.add();
341  o_part_loc.template get<0>(o_part_loc.size()-1) = key;
342  o_part_loc.template get<1>(o_part_loc.size()-1) = lin_id;
343 
344  Point<dim, St> p = v_pos.get(key);
345  // shift
346  p -= shifts.get(lin_id);
347 
348  // add this particle shifting its position
349  v_pos.add(p);
350  v_prp.add();
351  v_prp.last() = v_prp.get(key);
352 
353  // boxes in one group can be overlapping
354  // we do not have to search for the other
355  // boxes otherwise we will have duplicate particles
356  //
357  // A small note overlap of boxes across groups is fine
358  // (and needed) because each group has different shift
359  // producing non overlapping particles
360  //
361  break;
362  }
363  }
364  }
365 
366  ++it;
367  }
368  }
369 
419  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp ,
420  size_t & g_m,
421  size_t opt)
422  {
423  // Create the shift boxes
424  createShiftBox();
425 
426  if (!(opt & SKIP_LABELLING))
427  lg_m = v_prp.size();
428 
429  if (box_f.size() == 0)
430  return;
431  else
432  {
433  if (opt & SKIP_LABELLING)
434  {local_ghost_from_opart(v_pos,v_prp,opt);}
435  else
436  {local_ghost_from_dec(v_pos,v_prp,g_m);}
437  }
438  }
439 
447  {
448  // get the shift vectors
449  const openfpm::vector<Point<dim, St>> & shifts = dec.getShiftVectors();
450 
451  // create a number of send buffers equal to the near processors
452  g_pos_send.resize(g_opart.size());
453 
454  resize_retained_buffer(hsmem,g_pos_send.size());
455 
456  for (size_t i = 0; i < g_pos_send.size(); i++)
457  {
458  // Buffer must retained and survive the destruction of the
459  // vector
460  if (hsmem.get(i).ref() == 0)
461  {hsmem.get(i).incRef();}
462 
463  // Set the memory for retain the send buffer
464  g_pos_send.get(i).setMemory(hsmem.get(i));
465 
466  // resize the sending vector (No allocation is produced)
467  g_pos_send.get(i).resize(g_opart.get(i).size());
468  }
469 
470  // Fill the send buffer
471  for (size_t i = 0; i < g_opart.size(); i++)
472  {
473  for (size_t j = 0; j < g_opart.get(i).size(); j++)
474  {
475  Point<dim, St> s = v_pos.get(g_opart.get(i).template get<0>(j));
476  s -= shifts.get(g_opart.get(i).template get<1>(j));
477  g_pos_send.get(i).set(j, s);
478  }
479  }
480  }
481 
493  template<typename send_vector, typename prp_object, int ... prp> void fill_send_ghost_put_prp_buf(openfpm::vector<prop> & v_prp, openfpm::vector<send_vector> & g_send_prp, size_t & g_m)
494  {
495  // create a number of send buffers equal to the near processors
496  // from which we received
497  g_send_prp.resize(prc_recv_get.size());
498 
499  resize_retained_buffer(hsmem,g_send_prp.size());
500 
501  for (size_t i = 0; i < g_send_prp.size(); i++)
502  {
503  // Buffer must retained and survive the destruction of the
504  // vector
505  if (hsmem.get(i).ref() == 0)
506  hsmem.get(i).incRef();
507 
508  // Set the memory for retain the send buffer
509  g_send_prp.get(i).setMemory(hsmem.get(i));
510 
511  // resize the sending vector (No allocation is produced)
512  g_send_prp.get(i).resize(recv_sz_get.get(i));
513  }
514 
515  size_t accum = g_m;
516 
517  // Fill the send buffer
518  for (size_t i = 0; i < prc_recv_get.size(); i++)
519  {
520  size_t j2 = 0;
521  for (size_t j = accum; j < accum + recv_sz_get.get(i); j++)
522  {
523  // source object type
525  // destination object type
527 
528  // Copy only the selected properties
529  object_si_d<encap_src, encap_dst, OBJ_ENCAP, prp...>(v_prp.get(j), g_send_prp.get(i).get(j2));
530 
531  j2++;
532  }
533 
534  accum = accum + recv_sz_get.get(i);
535  }
536  }
537 
543  {
544  // Release all the buffer that are going to be deleted
545  for (size_t i = nbf ; i < rt_buf.size() ; i++)
546  {
547  rt_buf.get(i).decRef();
548  }
549 
550  hsmem.resize(nbf);
551  }
552 
563  template<typename send_vector, typename prp_object, int ... prp>
564  void fill_send_ghost_prp_buf(openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
565  openfpm::vector<send_vector> & g_send_prp)
566  {
567  // create a number of send buffers equal to the near processors
568  g_send_prp.resize(g_opart.size());
569 
570  resize_retained_buffer(hsmem,g_send_prp.size());
571 
572  for (size_t i = 0; i < g_send_prp.size(); i++)
573  {
574  // Buffer must retained and survive the destruction of the
575  // vector
576  if (hsmem.get(i).ref() == 0)
577  hsmem.get(i).incRef();
578 
579  // Set the memory for retain the send buffer
580  g_send_prp.get(i).setMemory(hsmem.get(i));
581 
582  // resize the sending vector (No allocation is produced)
583  g_send_prp.get(i).resize(g_opart.get(i).size());
584  }
585 
586  // Fill the send buffer
587  for (size_t i = 0; i < g_opart.size(); i++)
588  {
589  for (size_t j = 0; j < g_opart.get(i).size(); j++)
590  {
591  // source object type
593  // destination object type
595 
596  // Copy only the selected properties
597  object_si_d<encap_src, encap_dst, OBJ_ENCAP, prp...>(v_prp.get(g_opart.get(i).template get<0>(j)), g_send_prp.get(i).get(j));
598  }
599  }
600  }
601 
612  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
613  openfpm::vector<size_t> & prc_sz_r,
616  {
617  m_prp.resize(prc_sz_r.size());
618  m_pos.resize(prc_sz_r.size());
619  openfpm::vector<size_t> cnt(prc_sz_r.size());
620 
621  for (size_t i = 0; i < prc_sz_r.size() ; i++)
622  {
623  // set the size and allocate, using mem warant that pos and prp is contiguous
624  m_pos.get(i).resize(prc_sz_r.get(i));
625  m_prp.get(i).resize(prc_sz_r.get(i));
626  cnt.get(i) = 0;
627  }
628 
629  // end vector point
630  long int id_end = v_pos.size();
631 
632  // end opart point
633  long int end = m_opart.size()-1;
634 
635  // Run through all the particles and fill the sending buffer
636  for (size_t i = 0; i < m_opart.size(); i++)
637  {
638  process_map_particle<proc_without_prp>(i,end,id_end,m_pos,m_prp,v_pos,v_prp,cnt);
639  }
640 
641  v_pos.resize(v_pos.size() - m_opart.size());
642  v_prp.resize(v_prp.size() - m_opart.size());
643  }
644 
645 
658  template<typename prp_object,int ... prp>
660  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
661  openfpm::vector<size_t> & prc_sz_r,
664  {
665  m_prp.resize(prc_sz_r.size());
666  m_pos.resize(prc_sz_r.size());
667  openfpm::vector<size_t> cnt(prc_sz_r.size());
668 
669  for (size_t i = 0; i < prc_sz_r.size(); i++)
670  {
671  // set the size and allocate, using mem warant that pos and prp is contiguous
672  m_pos.get(i).resize(prc_sz_r.get(i));
673  m_prp.get(i).resize(prc_sz_r.get(i));
674  cnt.get(i) = 0;
675  }
676 
677  // end vector point
678  long int id_end = v_pos.size();
679 
680  // end opart point
681  long int end = m_opart.size()-1;
682 
683  // Run through all the particles and fill the sending buffer
684  for (size_t i = 0; i < m_opart.size(); i++)
685  {
686  process_map_particle<proc_with_prp<prp_object,prp...>>(i,end,id_end,m_pos,m_prp,v_pos,v_prp,cnt);
687  }
688 
689  v_pos.resize(v_pos.size() - m_opart.size());
690  v_prp.resize(v_prp.size() - m_opart.size());
691  }
692 
700  template<typename obp>
703  openfpm::vector<size_t> & prc_sz)
704  {
705  // reset lbl_p
706  lbl_p.clear();
707  o_part_loc.clear();
708  g_opart.clear();
709  g_opart.resize(dec.getNNProcessors());
710 
711  // resize the label buffer
712  prc_sz.resize(v_cl.getProcessingUnits());
713 
714  auto it = v_pos.getIterator();
715 
716  // Label all the particles with the processor id where they should go
717  while (it.isNext())
718  {
719  auto key = it.get();
720 
721  // Apply the boundary conditions
722  dec.applyPointBC(v_pos.get(key));
723 
724  size_t p_id = 0;
725 
726  // Check if the particle is inside the domain
727  if (dec.getDomain().isInside(v_pos.get(key)) == true)
728  {p_id = dec.processorIDBC(v_pos.get(key));}
729  else
730  {p_id = obp::out(key, v_cl.getProcessUnitID());}
731 
732  // Particle to move
733  if (p_id != v_cl.getProcessUnitID())
734  {
735  if ((long int) p_id != -1)
736  {
737  prc_sz.get(p_id)++;
738  lbl_p.add();
739  lbl_p.last().template get<0>() = key;
740  lbl_p.last().template get<2>() = p_id;
741  }
742  else
743  {
744  lbl_p.add();
745  lbl_p.last().template get<0>() = key;
746  lbl_p.last().template get<2>() = p_id;
747  }
748  }
749 
750  // Add processors and add size
751 
752  ++it;
753  }
754  }
755 
769  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
771  size_t & g_m)
772  {
773  // Buffer that contain for each processor the id of the particle to send
774  g_opart.clear();
775  g_opart.resize(dec.getNNProcessors());
776  prc_g_opart.clear();
777 
778  // Iterate over all particles
779  auto it = v_pos.getIteratorTo(g_m);
780  while (it.isNext())
781  {
782  auto key = it.get();
783 
784  // Given a particle, it return which processor require it (first id) and shift id, second id
785  // For an explanation about shifts vectors please consult getShiftVector in ie_ghost
786  const openfpm::vector<std::pair<size_t, size_t>> & vp_id = dec.template ghost_processorID_pair<typename Decomposition::lc_processor_id, typename Decomposition::shift_id>(v_pos.get(key), UNIQUE);
787 
788  for (size_t i = 0; i < vp_id.size(); i++)
789  {
790  // processor id
791  size_t p_id = vp_id.get(i).first;
792 
793  // add particle to communicate
794  g_opart.get(p_id).add();
795  g_opart.get(p_id).last().template get<0>() = key;
796  g_opart.get(p_id).last().template get<1>() = vp_id.get(i).second;
797  }
798 
799  ++it;
800  }
801 
802  // remove all zero entry and construct prc (the list of the sending processors)
804 
805  // count the non zero element
806  for (size_t i = 0 ; i < g_opart.size() ; i++)
807  {
808  if (g_opart.get(i).size() != 0)
809  {
810  g_opart_f.add();
811  g_opart.get(i).swap(g_opart_f.last());
812  prc.add(dec.IDtoProc(i));
813  }
814  }
815 
816  g_opart.swap(g_opart_f);
817  }
818 
832  static void * message_alloc_map(size_t msg_i, size_t total_msg, size_t total_p, size_t i, size_t ri, void * ptr)
833  {
834  // cast the pointer
836 
837  vd->recv_mem_gm.resize(vd->v_cl.getProcessingUnits());
838  vd->recv_mem_gm.get(i).resize(msg_i);
839 
840  return vd->recv_mem_gm.get(i).getPointer();
841  }
842 
843 public:
844 
851  :v_cl(create_vcluster()),dec(create_vcluster()),lg_m(0)
852  {
853  this->operator=(v);
854  }
855 
856 
862  vector_dist_comm(const Decomposition & dec)
863  :v_cl(create_vcluster()),dec(dec),lg_m(0)
864  {
865 
866  }
867 
873  vector_dist_comm(Decomposition && dec)
874  :v_cl(create_vcluster()),dec(dec),lg_m(0)
875  {
876 
877  }
878 
883  :v_cl(create_vcluster()),dec(create_vcluster()),lg_m(0)
884  {
885  }
886 
893  {
894  for (size_t i = 0 ; i < hsmem.size() ; i++)
895  {
896  if (hsmem.get(i).ref() == 1)
897  hsmem.get(i).decRef();
898  else
899  std::cout << __FILE__ << ":" << __LINE__ << " internal error memory is in an invalid state " << std::endl;
900  }
901 
902  }
903 
910  {
911  return v_sub_unit_factor;
912  }
913 
919  void setDecompositionGranularity(size_t n_sub)
920  {
921  this->v_sub_unit_factor = n_sub;
922  }
923 
933  const size_t (& bc)[dim],
934  const Ghost<dim,St> & g,
935  size_t opt,
936  const grid_sm<dim,void> & gdist)
937  {
938  size_t div[dim];
939 
940  if (opt & BIND_DEC_TO_GHOST)
941  {
942  // padding
943  size_t pad = 0;
944 
945  // CellDecomposer
946  CellDecomposer_sm<dim,St,shift<dim,St>> cd_sm;
947 
948  // Calculate the divisions for the symmetric Cell-lists
949  cl_param_calculateSym<dim,St>(box,cd_sm,g,pad);
950 
951  for (size_t i = 0 ; i < dim ; i++)
952  {div[i] = cd_sm.getDiv()[i] - 2*pad;}
953 
954  // Create the sub-domains
955  dec.setParameters(div, box, bc, g, gdist);
956  }
957  else
958  {
959  dec.setGoodParameters(box, bc, g, getDecompositionGranularity(), gdist);
960  }
961  dec.decompose();
962  }
963 
974  template<int ... prp> inline
976  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
977  size_t & g_m,
978  size_t opt = WITH_POSITION)
979  {
980  // Sending property object
981  typedef object<typename object_creator<typename prop::type, prp...>::type> prp_object;
982 
983  // send vector for each processor
984  typedef openfpm::vector<prp_object> send_vector;
985 
986  if (!(opt & NO_POSITION))
987  v_pos.resize(g_m);
988 
989  // reset the ghost part
990 
991  if (!(opt & SKIP_LABELLING))
992  v_prp.resize(g_m);
993 
994  // Label all the particles
995  if ((opt & SKIP_LABELLING) == false)
996  {labelParticlesGhost(v_pos,v_prp,prc_g_opart,g_m);}
997 
998  // Send and receive ghost particle information
999  {
1000  openfpm::vector<send_vector> g_send_prp;
1001  fill_send_ghost_prp_buf<send_vector, prp_object, prp...>(v_prp,g_send_prp);
1002 
1003  // if there are no properties skip
1004  // SSendRecvP send everything when we do not give properties
1005 
1006  if (sizeof...(prp) != 0)
1007  {
1008  if (opt & SKIP_LABELLING)
1009  {
1010  size_t opt_ = compute_options(opt);
1011  op_ssend_gg_recv_merge opm(g_m);
1012  v_cl.SSendRecvP_op<op_ssend_gg_recv_merge,send_vector,decltype(v_prp),layout_base,prp...>(g_send_prp,v_prp,prc_g_opart,opm,prc_recv_get,recv_sz_get,opt_);
1013  }
1014  else
1015  {v_cl.SSendRecvP<send_vector,decltype(v_prp),layout_base,prp...>(g_send_prp,v_prp,prc_g_opart,prc_recv_get,recv_sz_get,recv_sz_get_byte);}
1016 
1017  // fill g_opart_sz
1018  g_opart_sz.resize(prc_g_opart.size());
1019 
1020  for (size_t i = 0 ; i < prc_g_opart.size() ; i++)
1021  g_opart_sz.get(i) = g_send_prp.get(i).size();
1022  }
1023  }
1024 
1025  if (!(opt & NO_POSITION))
1026  {
1027  // Sending buffer for the ghost particles position
1029 
1030  fill_send_ghost_pos_buf(v_pos,g_pos_send);
1031 
1032  if (opt & SKIP_LABELLING)
1033  {
1034  size_t opt_ = compute_options(opt);
1035  v_cl.SSendRecv(g_pos_send,v_pos,prc_g_opart,prc_recv_get,recv_sz_get,opt_);
1036  }
1037  else
1038  {
1039  prc_recv_get.clear();
1040  recv_sz_get.clear();
1042  }
1043 
1044  // fill g_opart_sz
1045  g_opart_sz.resize(prc_g_opart.size());
1046 
1047  for (size_t i = 0 ; i < prc_g_opart.size() ; i++)
1048  g_opart_sz.get(i) = g_pos_send.get(i).size();
1049  }
1050 
1051  // Important to ensure that the number of particles in v_prp must be equal to v_pos
1052  // Note that if we do not give properties sizeof...(prp) == 0 in general at this point
1053  // v_prp.size() != v_pos.size()
1054  if (!(opt & SKIP_LABELLING))
1055  {
1056  v_prp.resize(v_pos.size());
1057  }
1058 
1059  add_loc_particles_bc(v_pos,v_prp,g_m,opt);
1060  }
1061 
1062 
1079  template<unsigned int ... prp>
1081  openfpm::vector<prop> & v_prp, size_t & g_m, size_t opt = NONE)
1082  {
1083  typedef KillParticle obp;
1084 
1085  // Processor communication size
1087 
1088  // map completely reset the ghost part
1089  v_pos.resize(g_m);
1090  v_prp.resize(g_m);
1091 
1092  // Contain the processor id of each particle (basically where they have to go)
1093  labelParticleProcessor<obp>(v_pos,m_opart, prc_sz);
1094 
1095  // Calculate the sending buffer size for each processor, put this information in
1096  // a contiguous buffer
1097  p_map_req.resize(v_cl.getProcessingUnits());
1098  openfpm::vector<size_t> prc_sz_r;
1100 
1101  for (size_t i = 0; i < v_cl.getProcessingUnits(); i++)
1102  {
1103  if (prc_sz.get(i) != 0)
1104  {
1105  p_map_req.get(i) = prc_r.size();
1106  prc_r.add(i);
1107  prc_sz_r.add(prc_sz.get(i));
1108  }
1109  }
1110 
1111  // In case we have receive option
1112 
1113  if (opt & MAP_LOCAL)
1114  {
1115  // if the map is local we indicate that we receive only from the neighborhood processors
1116 
1117  prc_recv_map.clear();
1118  for (size_t i = 0 ; i < dec.getNNProcessors() ; i++)
1119  {prc_recv_map.add(dec.IDtoProc(i));}
1120  }
1121 
1122  // Sending property object
1123  typedef object<typename object_creator<typename prop::type, prp...>::type> prp_object;
1124 
1129 
1130  fill_send_map_buf_list<prp_object,prp...>(v_pos,v_prp,prc_sz_r, m_pos, m_prp);
1131 
1132  v_cl.SSendRecv(m_pos,v_pos,prc_r,prc_recv_map,recv_sz_map,opt);
1133  v_cl.SSendRecvP<openfpm::vector<prp_object>,decltype(v_prp),layout_base,prp...>(m_prp,v_prp,prc_r,prc_recv_map,recv_sz_map,opt);
1134 
1135  // mark the ghost part
1136 
1137  g_m = v_pos.size();
1138  }
1139 
1153  template<typename obp = KillParticle>
1155  openfpm::vector<prop,Memory,typename layout_base<prop>::type,layout_base> & v_prp,
1156  size_t & g_m, size_t opt = NONE)
1157  {
1158  // Processor communication size
1160 
1161  // map completely reset the ghost part
1162  v_pos.resize(g_m);
1163  v_prp.resize(g_m);
1164 
1165  // Contain the processor id of each particle (basically where they have to go)
1166  labelParticleProcessor<obp>(v_pos,m_opart, prc_sz);
1167 
1168  // Calculate the sending buffer size for each processor, put this information in
1169  // a contiguous buffer
1170  p_map_req.resize(v_cl.getProcessingUnits());
1171  openfpm::vector<size_t> prc_sz_r;
1173 
1174  for (size_t i = 0; i < v_cl.getProcessingUnits(); i++)
1175  {
1176  if (prc_sz.get(i) != 0)
1177  {
1178  p_map_req.get(i) = prc_r.size();
1179  prc_r.add(i);
1180  prc_sz_r.add(prc_sz.get(i));
1181  }
1182  }
1183 
1188 
1189  fill_send_map_buf(v_pos,v_prp, prc_sz_r, m_pos, m_prp);
1190 
1191  v_cl.SSendRecv(m_pos,v_pos,prc_r,prc_recv_map,recv_sz_map,opt);
1192  v_cl.SSendRecv(m_prp,v_prp,prc_r,prc_recv_map,recv_sz_map,opt);
1193 
1194  // mark the ghost part
1195 
1196  g_m = v_pos.size();
1197  }
1198 
1204  inline Decomposition & getDecomposition()
1205  {
1206  return dec;
1207  }
1208 
1214  inline const Decomposition & getDecomposition() const
1215  {
1216  return dec;
1217  }
1218 
1227  {
1228  dec = vc.dec;
1229 
1230  return *this;
1231  }
1232 
1241  {
1242  dec = vc.dec;
1243 
1244  return *this;
1245  }
1246 
1258  template<template<typename,typename> class op, int ... prp>
1260  openfpm::vector<prop> & v_prp,
1261  size_t & g_m,
1262  size_t opt)
1263  {
1264  // Sending property object
1265  typedef object<typename object_creator<typename prop::type, prp...>::type> prp_object;
1266 
1267  // send vector for each processor
1268  typedef openfpm::vector<prp_object> send_vector;
1269 
1270  openfpm::vector<send_vector> g_send_prp;
1271  fill_send_ghost_put_prp_buf<send_vector, prp_object, prp...>(v_prp,g_send_prp,g_m);
1272 
1273  // Send and receive ghost particle information
1274  if (opt & NO_CHANGE_ELEMENTS)
1275  {
1276  size_t opt_ = compute_options(opt);
1277 
1279  v_cl.SSendRecvP_op<op_ssend_recv_merge<op>,send_vector,decltype(v_prp),layout_base,prp...>(g_send_prp,v_prp,prc_recv_get,opm,prc_g_opart,g_opart_sz,opt_);
1280  }
1281  else
1282  {
1284  v_cl.SSendRecvP_op<op_ssend_recv_merge<op>,send_vector,decltype(v_prp),layout_base,prp...>(g_send_prp,v_prp,prc_recv_get,opm,prc_recv_put,recv_sz_put);
1285  }
1286 
1287  // process also the local replicated particles
1288 
1289  size_t i2 = 0;
1290 
1291 
1292  if (lg_m < v_prp.size() && v_prp.size() - lg_m != o_part_loc.size())
1293  {
1294  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " Local ghost particles = " << v_prp.size() - lg_m << " != " << o_part_loc.size() << std::endl;
1295  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " Check that you did a ghost_get before a ghost_put" << std::endl;
1296  }
1297 
1298 
1299  for (size_t i = lg_m ; i < v_prp.size() ; i++)
1300  {
1301  auto dst = v_prp.get(o_part_loc.template get<0>(i2));
1302  auto src = v_prp.get(i);
1303  copy_cpu_encap_encap_op_prp<op,decltype(v_prp.get(0)),decltype(v_prp.get(0)),prp...> cp(src,dst);
1304 
1305  boost::mpl::for_each_ref< boost::mpl::range_c<int,0,sizeof...(prp)> >(cp);
1306  i2++;
1307  }
1308  }
1309 };
1310 
1311 
1312 #endif /* SRC_VECTOR_VECTOR_DIST_COMM_HPP_ */
void map_(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, size_t &g_m, size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor...
process the particle with properties
~vector_dist_comm()
Destructor.
void labelParticlesGhost(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, openfpm::vector< size_t > &prc, size_t &g_m)
Label the particles.
void fill_send_map_buf_list(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, openfpm::vector< size_t > &prc_sz_r, openfpm::vector< openfpm::vector< Point< dim, St >>> &m_pos, openfpm::vector< openfpm::vector< prp_object >> &m_prp)
allocate and fill the send buffer for the map function
Helper class to merge data.
openfpm::vector< openfpm::vector< aggregate< size_t, size_t > > > g_opart
size_t getProcessUnitID()
Get the process unit id.
void fill_send_ghost_prp_buf(openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, openfpm::vector< send_vector > &g_send_prp)
This function fill the send buffer for properties after the particles has been label with labelPartic...
openfpm::vector< size_t > prc_recv_get
openfpm::vector< size_t > g_opart_sz
Per processor number of particle g_opart_sz.get(i) = g_opart.get(i).size()
Vcluster & v_cl
VCluster.
bool SSendRecvP_op(openfpm::vector< T > &send, S &recv, openfpm::vector< size_t > &prc_send, op &op_param, openfpm::vector< size_t > &prc_recv, openfpm::vector< size_t > &recv_sz, size_t opt=NONE)
Semantic Send and receive, send the data to processors and receive from the other processors...
Definition: VCluster.hpp:794
openfpm::vector_std< comb< dim > > box_cmb
Store the sector for each group (previous vector)
vector_dist_comm< dim, St, prop, layout, layout_base, Decomposition, Memory > & operator=(const vector_dist_comm< dim, St, prop, layout, layout_base, Decomposition, Memory > &vc)
Copy a vector.
openfpm::vector< size_t > p_map_req
It map the processor id with the communication request into map procedure.
openfpm::vector< HeapMemory > hrmem
Receiving buffer.
void init_decomposition(Box< dim, St > &box, const size_t(&bc)[dim], const Ghost< dim, St > &g, size_t opt, const grid_sm< dim, void > &gdist)
Initialize the decomposition.
openfpm::vector< size_t > prc_recv_map
the same as prc_recv_get but for map
static void proc(size_t lbl, size_t cnt, size_t id, T1 &v_prp, T2 &m_prp)
process the particle
void setDecompositionGranularity(size_t n_sub)
Set the minimum number of sub-domain per processor.
static void * message_alloc_map(size_t msg_i, size_t total_msg, size_t total_p, size_t i, size_t ri, void *ptr)
Call-back to allocate buffer to receive incoming elements (particles)
size_t size()
Stub size.
Definition: map_vector.hpp:70
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:22
void resize_retained_buffer(openfpm::vector< HeapMemory > &rt_buf, size_t nbf)
resize the retained buffer by nbf
size_t get_end_valid(long int &end, long int &end_id)
Return a valid particle starting from end and tracing back.
Decomposition dec
Domain decomposition.
This class allocate, and destroy CPU memory.
Definition: HeapMemory.hpp:39
bool SSendRecvP(openfpm::vector< T > &send, S &recv, openfpm::vector< size_t > &prc_send, openfpm::vector< size_t > &prc_recv, openfpm::vector< size_t > &sz_recv, openfpm::vector< size_t > &sz_recv_byte, size_t opt=NONE)
Semantic Send and receive, send the data to processors and receive from the other processors...
Definition: VCluster.hpp:687
Implementation of VCluster class.
Definition: VCluster.hpp:36
openfpm::vector< size_t > prc_recv_put
the same as prc_recv_get but for put
This class define the domain decomposition interface.
bool SSendRecv(openfpm::vector< T > &send, S &recv, openfpm::vector< size_t > &prc_send, openfpm::vector< size_t > &prc_recv, openfpm::vector< size_t > &sz_recv, size_t opt=NONE)
Semantic Send and receive, send the data to processors and receive from the other processors...
Definition: VCluster.hpp:639
void add_loc_particles_bc(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, size_t &g_m, size_t opt)
Add local particles based on the boundary conditions.
This class decompose a space into sub-sub-domains and distribute them across processors.
vector_dist_comm(const vector_dist_comm< dim, St, prop, layout, layout_base, Decomposition, Memory > &v)
Copy Constructor.
openfpm::vector< size_t > recv_sz_get
openfpm::vector< Point< dim, St >, Memory > send_pos_vector
definition of the send vector for position
Decomposition & getDecomposition()
Get the decomposition.
void createShiftBox()
For every internal ghost box we create a structure that order such internal local ghost box in shift ...
process the particle without properties
vector_dist_comm(Decomposition &&dec)
Constructor.
openfpm::vector< size_t > prc_g_opart
processor rank list of g_opart
openfpm::vector_std< openfpm::vector_std< Box< dim, St > > > box_f
Helper class to merge data.
openfpm::vector< size_t > recv_sz_get_byte
Conversion to byte of recv_sz_get.
This class is an helper for the communication of vector_dist.
const T & get(size_t i) const
Get coordinate.
Definition: Point.hpp:142
void fill_send_map_buf(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, openfpm::vector< size_t > &prc_sz_r, openfpm::vector< openfpm::vector< Point< dim, St >>> &m_pos, openfpm::vector< openfpm::vector< prop >> &m_prp)
allocate and fill the send buffer for the map function
size_t v_sub_unit_factor
Number of units for each sub-domain.
openfpm::vector< size_t > recv_sz_put
The same as recv_sz_get but for put.
Out of bound policy it detect out of bound particles and decide what to do.
static void proc(size_t lbl, size_t cnt, size_t id, T1 &v_prp, T2 &m_prp)
process the particle
This class is a trick to indicate the compiler a specific specialization pattern. ...
Definition: memory_c.hpp:201
void map_list_(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop > &v_prp, size_t &g_m, size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor...
vector_dist_comm< dim, St, prop, layout, layout_base, Decomposition, Memory > & operator=(vector_dist_comm< dim, St, prop, layout, layout_base, Decomposition, Memory > &&vc)
Copy a vector.
size_t getDecompositionGranularity()
Get the number of minimum sub-domain per processor.
It copy two encap object.
Definition: Encap.hpp:88
openfpm::vector< HeapMemory > hsmem
Sending buffer.
void fill_send_ghost_put_prp_buf(openfpm::vector< prop > &v_prp, openfpm::vector< send_vector > &g_send_prp, size_t &g_m)
This function fill the send buffer for ghost_put.
bool is_shift_box_created
Flags that indicate that the function createShiftBox() has been called.
std::unordered_map< size_t, size_t > map_cmb
this map is used to check if a combination is already present
vector_dist_comm()
Constructor.
void labelParticleProcessor(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< aggregate< size_t, size_t, size_t >> &lbl_p, openfpm::vector< size_t > &prc_sz)
Label particles for mappings.
void local_ghost_from_dec(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, size_t g_m)
Local ghost from decomposition.
It create a boost::fusion vector with the selected properties.
const Decomposition & getDecomposition() const
Get the decomposition.
void local_ghost_from_opart(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, size_t opt)
Local ghost from labeled particles.
void process_map_particle(size_t i, long int &end, long int &id_end, T1 &m_pos, T2 &m_prp, T3 &v_pos, T4 &v_prp, openfpm::vector< size_t > &cnt)
It process one particle.
void ghost_get_(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop, Memory, typename layout_base< prop >::type, layout_base > &v_prp, size_t &g_m, size_t opt=WITH_POSITION)
It synchronize the properties and position of the ghost particles.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:81
void ghost_put_(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< prop > &v_prp, size_t &g_m, size_t opt)
Ghost put.
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:61
vector_dist_comm(const Decomposition &dec)
Constructor.
size_t getProcessingUnits()
Get the total number of processors.
It copy the properties from one object to another.
openfpm::vector< size_t > recv_sz_map
The same as recv_sz_get but for map.
openfpm::vector< aggregate< size_t, size_t, size_t > > m_opart
openfpm::vector< aggregate< size_t, size_t > > o_part_loc
Id of the local particle to replicate for ghost_get.
void fill_send_ghost_pos_buf(openfpm::vector< Point< dim, St >> &v_pos, openfpm::vector< send_pos_vector > &g_pos_send)
This function fill the send buffer for the particle position after the particles has been label with ...