OpenFPM_pdata  1.0.0
Project that contain the implementation of distributed structures
 All Data Structures Functions Variables Typedefs Enumerations Friends Pages
vector_dist_unit_test.hpp
1 /*
2  * vector_dist_unit_test.hpp
3  *
4  * Created on: Mar 6, 2015
5  * Author: Pietro Incardona
6  */
7 
8 #ifndef VECTOR_DIST_UNIT_TEST_HPP_
9 #define VECTOR_DIST_UNIT_TEST_HPP_
10 
11 #include "config.h"
12 
13 #include <random>
14 #include "Vector/vector_dist.hpp"
15 #include "data_type/aggregate.hpp"
16 #include "Vector/performance/vector_dist_performance_common.hpp"
17 
24 template<unsigned int dim> size_t total_n_part_lc(vector_dist<dim,float, Point_test<float>, CartDecomposition<dim,float> > & vd, size_t (& bc)[dim])
25 {
26  Vcluster & v_cl = vd.getVC();
27  auto it2 = vd.getDomainIterator();
28  const CartDecomposition<3,float> & ct = vd.getDecomposition();
29 
30  bool noOut = true;
31 
32  size_t cnt = 0;
33  while (it2.isNext())
34  {
35  auto key = it2.get();
36 
37  noOut &= ct.isLocal(vd.getPos(key));
38 
39  cnt++;
40 
41  ++it2;
42  }
43 
44  BOOST_REQUIRE_EQUAL(noOut,true);
45 
46  //
47  v_cl.sum(cnt);
48  v_cl.execute();
49 
50  return cnt;
51 }
52 
65 template<unsigned int dim,typename vector_dist> inline void count_local_n_local(vector_dist & vd, vector_dist_iterator & it, size_t (& bc)[dim] , Box<dim,float> & box, Box<dim,float> & dom_ext, size_t & l_cnt, size_t & nl_cnt, size_t & n_out)
66 {
68 
69  while (it.isNext())
70  {
71  auto key = it.get();
72  // Check if it is in the domain
73  if (box.isInsideNP(vd.getPos(key)) == true)
74  {
75  // Check if local
76  if (ct.isLocalBC(vd.getPos(key),bc) == true)
77  l_cnt++;
78  else
79  nl_cnt++;
80  }
81  else
82  {
83  nl_cnt++;
84  }
85 
86  Point<dim,float> xp = vd.getPos(key);
87 
88  // Check that all particles are inside the Domain + Ghost part
89  if (dom_ext.isInside(xp) == false)
90  n_out++;
91 
92  ++it;
93  }
94 }
95 
96 BOOST_AUTO_TEST_SUITE( vector_dist_test )
97 
98 void print_test(std::string test, size_t sz)
99 {
100  if (create_vcluster().getProcessUnitID() == 0)
101  std::cout << test << " " << sz << "\n";
102 }
103 
104 void Test2D_ghost(Box<2,float> & box)
105 {
106  // Communication object
107  Vcluster & v_cl = create_vcluster();
108 
109  typedef Point_test<float> p;
110 
111  // Get the default minimum number of sub-sub-domain per processor (granularity of the decomposition)
112  size_t n_sub = 64 * v_cl.getProcessingUnits();
113  // Convert the request of having a minimum n_sub number of sub-sub domain into grid decompsition of the space
115 
117 
118  size_t g_div[]= {sz,sz};
119 
120  // number of particles
121  size_t np = sz * sz;
122 
123  // Calculate the number of elements this processor is going to obtain
124  size_t p_np = np / v_cl.getProcessingUnits();
125 
126  // Get non divisible part
127  size_t r = np % v_cl.getProcessingUnits();
128 
129  // Get the offset
130  size_t offset = v_cl.getProcessUnitID() * p_np + std::min(v_cl.getProcessUnitID(),r);
131 
132  // Distribute the remain elements
133  if (v_cl.getProcessUnitID() < r)
134  p_np++;
135 
136  // Create a grid info
137  grid_sm<2,void> g_info(g_div);
138 
139  // Calculate the grid spacing
140  Point<2,float> spacing = box.getP2() - box.getP1();
141  spacing = spacing / g_div;
142 
143  // middle spacing
144  Point<2,float> m_spacing = spacing / 2.0;
145 
146  // set the ghost based on the radius cut off (make just a little bit smaller than the spacing)
147  Ghost<2,float> g(spacing.get(0) - spacing .get(0) * 0.0001);
148 
149  // Boundary conditions
150  size_t bc[2]={NON_PERIODIC,NON_PERIODIC};
151 
152  // Vector of particles
153  vector_dist<2,float, Point_test<float> > vd(g_info.size(),box,bc,g);
154 
155  // size_t
156  size_t cobj = 0;
157 
158  grid_key_dx_iterator_sp<2> it(g_info,offset,offset+p_np-1);
159  auto v_it = vd.getIterator();
160 
161  while (v_it.isNext() && it.isNext())
162  {
163  auto key = it.get();
164  auto key_v = v_it.get();
165 
166  // set the particle position
167 
168  vd.getPos(key_v)[0] = key.get(0) * spacing[0] + m_spacing[0] + box.getLow(0);
169  vd.getPos(key_v)[1] = key.get(1) * spacing[1] + m_spacing[1] + box.getLow(1);
170 
171  cobj++;
172 
173  ++v_it;
174  ++it;
175  }
176 
178 
179  // Both iterators must signal the end, and the number of elements in the vector, must the equal to the
180  // predicted one
181  BOOST_REQUIRE_EQUAL(v_it.isNext(),false);
182  BOOST_REQUIRE_EQUAL(it.isNext(),false);
183  BOOST_REQUIRE_EQUAL(cobj,p_np);
184 
186 
187  // redistribute the particles according to the decomposition
188  vd.map();
189 
190  auto v_it2 = vd.getIterator();
191 
192  while (v_it2.isNext())
193  {
194  auto key = v_it2.get();
195 
196  // fill with the processor ID where these particle live
197  vd.getProp<p::s>(key) = vd.getPos(key)[0] + vd.getPos(key)[1] * 16.0f;
198  vd.getProp<p::v>(key)[0] = v_cl.getProcessUnitID();
199  vd.getProp<p::v>(key)[1] = v_cl.getProcessUnitID();
200  vd.getProp<p::v>(key)[2] = v_cl.getProcessUnitID();
201 
202  ++v_it2;
203  }
204 
205  // do a ghost get
206  vd.ghost_get<p::s,p::v>();
207 
209 
210  // Get the decomposition
211  const auto & dec = vd.getDecomposition();
212 
213  // Get the ghost external boxes
214  openfpm::vector<size_t> vb(dec.getNEGhostBox());
215 
216  // Get the ghost iterator
217  auto g_it = vd.getGhostIterator();
218 
219  size_t n_part = 0;
220 
221  // Check if the ghost particles contain the correct information
222  while (g_it.isNext())
223  {
224  auto key = g_it.get();
225 
226  // Check the received data
227  BOOST_REQUIRE_EQUAL(vd.getPos(key)[0] + vd.getPos(key)[1] * 16.0f,vd.getProp<p::s>(key));
228 
229  bool is_in = false;
230  size_t b = 0;
231  size_t lb = 0;
232 
233  // check if the received data are in one of the ghost boxes
234  for ( ; b < dec.getNEGhostBox() ; b++)
235  {
236  Point<2,float> xp = vd.getPos(key);
237 
238  if (dec.getEGhostBox(b).isInside(xp) == true )
239  {
240  is_in = true;
241 
242  // Add
243  vb.get(b)++;
244  lb = b;
245  }
246  }
247  BOOST_REQUIRE_EQUAL(is_in,true);
248 
249  // Check that the particle come from the correct processor
250  BOOST_REQUIRE_EQUAL(vd.getProp<p::v>(key)[0],dec.getEGhostBoxProcessor(lb));
251 
252  n_part++;
253  ++g_it;
254  }
255 
256  if (v_cl.getProcessingUnits() > 1)
257  {
258  BOOST_REQUIRE(n_part != 0);
259  }
260 
261  CellDecomposer_sm<2,float,shift<2,float>> cd(SpaceBox<2,float>(box),g_div,0);
262 
263  for (size_t i = 0 ; i < vb.size() ; i++)
264  {
265  // Calculate how many particle should be in the box
266  size_t n_point = cd.getGridPoints(dec.getEGhostBox(i)).getVolumeKey();
267 
268  BOOST_REQUIRE_EQUAL(n_point,vb.get(i));
269  }
270 }
271 
272 BOOST_AUTO_TEST_CASE( vector_dist_ghost )
273 {
274  Box<2,float> box({0.0,0.0},{1.0,1.0});
275  Test2D_ghost(box);
276 
277  Box<2,float> box2({-1.0,-1.0},{2.5,2.5});
278  Test2D_ghost(box2);
279 }
280 
281 void print_test_v(std::string test, size_t sz)
282 {
283  if (create_vcluster().getProcessUnitID() == 0)
284  std::cout << test << " " << sz << "\n";
285 }
286 
287 long int decrement(long int k, long int step)
288 {
289  if (k <= 32)
290  {
291  return 1;
292  }
293  else if (k - 2*step+1 <= 0)
294  {
295  return k - 32;
296  }
297  else
298  return step;
299 }
300 
301 BOOST_AUTO_TEST_CASE( vector_dist_iterator_test_use_2d )
302 {
303  Vcluster & v_cl = create_vcluster();
304 
305  // set the seed
306  // create the random generator engine
307  std::srand(v_cl.getProcessUnitID());
308  std::default_random_engine eg;
309  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
310 
311 #ifdef TEST_COVERAGE_MODE
312  long int k = 24288 * v_cl.getProcessingUnits();
313 #else
314  long int k = 524288 * v_cl.getProcessingUnits();
315 #endif
316 
317  long int big_step = k / 4;
318  big_step = (big_step == 0)?1:big_step;
319 
320  print_test_v( "Testing 2D vector k<=",k);
321 
322  // 2D test
323  for ( ; k >= 2 ; k-= decrement(k,big_step) )
324  {
325  BOOST_TEST_CHECKPOINT( "Testing 2D vector k=" << k );
326 
328 
329  Box<2,float> box({0.0,0.0},{1.0,1.0});
330 
331  // Boundary conditions
332  size_t bc[2]={NON_PERIODIC,NON_PERIODIC};
333 
335 
336  auto it = vd.getIterator();
337 
338  while (it.isNext())
339  {
340  auto key = it.get();
341 
342  vd.getPos(key)[0] = ud(eg);
343  vd.getPos(key)[1] = ud(eg);
344 
345  ++it;
346  }
347 
348  vd.map();
349 
351 
352  // Check if we have all the local particles
353  size_t cnt = 0;
355  auto it2 = vd.getIterator();
356 
357  while (it2.isNext())
358  {
359  auto key = it2.get();
360 
361  // Check if local
362  BOOST_REQUIRE_EQUAL(ct.isLocal(vd.getPos(key)),true);
363 
364  cnt++;
365 
366  ++it2;
367  }
368 
369  //
370  v_cl.sum(cnt);
371  v_cl.execute();
372  BOOST_REQUIRE_EQUAL((long int)cnt,k);
373  }
374 }
375 
376 BOOST_AUTO_TEST_CASE( vector_dist_iterator_test_use_3d )
377 {
378  Vcluster & v_cl = create_vcluster();
379 
380  // set the seed
381  // create the random generator engine
382  std::srand(v_cl.getProcessUnitID());
383  std::default_random_engine eg;
384  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
385 
386 #ifdef TEST_COVERAGE_MODE
387  long int k = 24288 * v_cl.getProcessingUnits();
388 #else
389  long int k = 524288 * v_cl.getProcessingUnits();
390 #endif
391 
392  long int big_step = k / 4;
393  big_step = (big_step == 0)?1:big_step;
394 
395  print_test_v( "Testing 3D vector k<=",k);
396 
397  // 3D test
398  for ( ; k >= 2 ; k-= decrement(k,big_step) )
399  {
400  BOOST_TEST_CHECKPOINT( "Testing 3D vector k=" << k );
401 
403 
404  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
405 
406  // Boundary conditions
407  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
408 
410 
411  auto it = vd.getIterator();
412 
413  while (it.isNext())
414  {
415  auto key = it.get();
416 
417  vd.getPos(key)[0] = ud(eg);
418  vd.getPos(key)[1] = ud(eg);
419  vd.getPos(key)[2] = ud(eg);
420 
421  ++it;
422  }
423 
424  vd.map();
425 
427 
428  // Check if we have all the local particles
429  size_t cnt = 0;
431  auto it2 = vd.getIterator();
432 
433  while (it2.isNext())
434  {
435  auto key = it2.get();
436 
437  // Check if local
438  BOOST_REQUIRE_EQUAL(ct.isLocal(vd.getPos(key)),true);
439 
440  cnt++;
441 
442  ++it2;
443  }
444 
445  //
446  v_cl.sum(cnt);
447  v_cl.execute();
448  BOOST_REQUIRE_EQUAL(cnt,(size_t)k);
449  }
450 }
451 
452 
453 BOOST_AUTO_TEST_CASE( vector_dist_iterator_fixed_dec_3d )
454 {
455  Vcluster & v_cl = create_vcluster();
456 
457  // set the seed
458  // create the random generator engine
459  std::srand(v_cl.getProcessUnitID());
460  std::default_random_engine eg;
461  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
462 
463 #ifdef TEST_COVERAGE_MODE
464  long int k = 2428 * v_cl.getProcessingUnits();
465 #else
466  long int k = 52428 * v_cl.getProcessingUnits();
467 #endif
468 
469  long int big_step = k / 4;
470  big_step = (big_step == 0)?1:big_step;
471 
472  print_test_v( "Testing 3D vector copy decomposition k<=",k);
473 
474  // 3D test
475  for ( ; k >= 2 ; k-= decrement(k,big_step) )
476  {
477  BOOST_TEST_CHECKPOINT( "Testing 3D vector copy decomposition k=" << k );
478 
479  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
480 
481  // Boundary conditions
482  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
483 
486 
487  auto it = vd.getIterator();
488 
489  while (it.isNext())
490  {
491  auto key = it.get();
492 
493  vd.getPos(key)[0] = ud(eg);
494  vd.getPos(key)[1] = ud(eg);
495  vd.getPos(key)[2] = ud(eg);
496 
497  vd2.getPos(key)[0] = vd.getPos(key)[0];
498  vd2.getPos(key)[1] = vd.getPos(key)[1];
499  vd2.getPos(key)[2] = vd.getPos(key)[2];
500 
501  ++it;
502  }
503 
504  vd.map();
505  vd2.map();
506 
507  vd.ghost_get();
508  vd2.ghost_get();
509 
510  auto NN = vd.getCellList(0.05);
511  auto NN2 = vd2.getCellList(0.05);
512 
513  cross_calc<3,0>(NN,NN2,vd,vd2);
514  cross_calc<3,1>(NN,NN,vd,vd);
515 
516 
517  auto it3 = vd.getIterator();
518 
519  while (it3.isNext())
520  {
521  auto key = it3.get();
522 
523  BOOST_REQUIRE_EQUAL(vd.getProp<0>(key),vd.getProp<1>(key));
524 
525  ++it3;
526  }
527  }
528 }
529 
530 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_use_2d )
531 {
532  Vcluster & v_cl = create_vcluster();
533 
534  // set the seed
535  // create the random generator engine
536  std::srand(v_cl.getProcessUnitID());
537  std::default_random_engine eg;
538  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
539 
540 #ifdef TEST_COVERAGE_MODE
541  long int k = 24288 * v_cl.getProcessingUnits();
542 #else
543  long int k = 524288 * v_cl.getProcessingUnits();
544 #endif
545 
546  long int big_step = k / 4;
547  big_step = (big_step == 0)?1:big_step;
548 
549  print_test_v( "Testing 2D periodic vector k<=",k);
550 
551  // 2D test
552  for ( ; k >= 2 ; k-= decrement(k,big_step) )
553  {
554  BOOST_TEST_CHECKPOINT( "Testing 2D periodic vector k=" << k );
555 
556  Box<2,float> box({0.0,0.0},{1.0,1.0});
557 
558  // Boundary conditions
559  size_t bc[2]={PERIODIC,PERIODIC};
560 
561  // factor
562  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
563 
564  // ghost
565  Ghost<2,float> ghost(0.01 / factor);
566 
567  // ghost2 (a little bigger because of round off error)
568  Ghost<2,float> ghost2(0.05001 / factor);
569 
570  // Distributed vector
571  vector_dist<2,float, Point_test<float> > vd(k,box,bc,ghost);
572 
573  auto it = vd.getIterator();
574 
575  while (it.isNext())
576  {
577  auto key = it.get();
578 
579  vd.getPos(key)[0] = ud(eg);
580  vd.getPos(key)[1] = ud(eg);
581 
582  ++it;
583  }
584 
585  vd.map();
586 
587  // sync the ghost, only the property zero
588  vd.ghost_get<0>();
589 
590  // Domain + ghost box
591  Box<2,float> dom_ext = box;
592  dom_ext.enlarge(ghost2);
593 
594  // Iterate on all particles domain + ghost
595  size_t l_cnt = 0;
596  size_t nl_cnt = 0;
597  size_t n_out = 0;
598 
599 
600  auto it2 = vd.getIterator();
601  count_local_n_local<2,vector_dist<2,float, Point_test<float> >>(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
602 
603  // No particles should be out of domain + ghost
604  BOOST_REQUIRE_EQUAL(n_out,0ul);
605 
606  // Ghost must populated because we synchronized them
607  if (k > 524288)
608  {
609  BOOST_REQUIRE(nl_cnt != 0);
610  BOOST_REQUIRE(l_cnt > nl_cnt);
611  }
612 
613  // Sum all the particles inside the domain
614  v_cl.sum(l_cnt);
615  v_cl.execute();
616 
617  // count that they are equal to the initial total number
618  BOOST_REQUIRE_EQUAL((long int)l_cnt,k);
619 
620  l_cnt = 0;
621  nl_cnt = 0;
622 
623  // Iterate only on the ghost particles
624  auto itg = vd.getGhostIterator();
625  count_local_n_local<2,vector_dist<2,float, Point_test<float> > >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
626 
627  // No particle on the ghost must be inside the domain
628  BOOST_REQUIRE_EQUAL(l_cnt,0ul);
629 
630  // Ghost must be populated
631  if (k > 524288)
632  {
633  BOOST_REQUIRE(nl_cnt != 0);
634  }
635  }
636 }
637 
638 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_use_3d )
639 {
640  Vcluster & v_cl = create_vcluster();
641 
642  // set the seed
643  // create the random generator engine
644  std::srand(v_cl.getProcessUnitID());
645  std::default_random_engine eg;
646  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
647 
648 #ifdef TEST_COVERAGE_MODE
649  long int k = 24288 * v_cl.getProcessingUnits();
650 #else
651  long int k = 524288 * v_cl.getProcessingUnits();
652 #endif
653 
654  long int big_step = k / 4;
655  big_step = (big_step == 0)?1:big_step;
656 
657  print_test_v( "Testing 3D periodic vector k<=",k);
658 
659  // 3D test
660  for ( ; k >= 2 ; k-= decrement(k,big_step) )
661  {
662  BOOST_TEST_CHECKPOINT( "Testing 3D periodic vector k=" << k );
663 
664  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
665 
666  // Boundary conditions
667  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
668 
669  // factor
670  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
671 
672  // ghost
673  Ghost<3,float> ghost(0.05 / factor);
674 
675  // ghost2 (a little bigger because of round off error)
676  Ghost<3,float> ghost2(0.05001 / factor);
677 
678  // Distributed vector
679  vector_dist<3,float, Point_test<float> > vd(k,box,bc,ghost);
680 
681  auto it = vd.getIterator();
682 
683  while (it.isNext())
684  {
685  auto key = it.get();
686 
687  vd.getPos(key)[0] = ud(eg);
688  vd.getPos(key)[1] = ud(eg);
689  vd.getPos(key)[2] = ud(eg);
690 
691  ++it;
692  }
693 
694  vd.map();
695 
696  // sync the ghost
697  vd.ghost_get<0>();
698 
699  // Domain + ghost
700  Box<3,float> dom_ext = box;
701  dom_ext.enlarge(ghost2);
702 
703  // Iterate on all particles domain + ghost
704  size_t l_cnt = 0;
705  size_t nl_cnt = 0;
706  size_t n_out = 0;
707 
708  auto it2 = vd.getIterator();
709  count_local_n_local<3,vector_dist<3,float, Point_test<float> >>(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
710 
711  // No particles should be out of domain + ghost
712  BOOST_REQUIRE_EQUAL(n_out,0ul);
713 
714  // Ghost must populated because we synchronized them
715  if (k > 524288)
716  {
717  BOOST_REQUIRE(nl_cnt != 0);
718  BOOST_REQUIRE(l_cnt > nl_cnt);
719  }
720 
721  // Sum all the particles inside the domain
722  v_cl.sum(l_cnt);
723  v_cl.execute();
724  BOOST_REQUIRE_EQUAL(l_cnt,(size_t)k);
725 
726  l_cnt = 0;
727  nl_cnt = 0;
728 
729  // Iterate only on the ghost particles
730  auto itg = vd.getGhostIterator();
731  count_local_n_local<3,vector_dist<3,float, Point_test<float> > >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
732 
733  // No particle on the ghost must be inside the domain
734  BOOST_REQUIRE_EQUAL(l_cnt,0ul);
735 
736  // Ghost must be populated
737  if (k > 524288)
738  {
739  BOOST_REQUIRE(nl_cnt != 0);
740  }
741  }
742 }
743 
744 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_random_walk )
745 {
746  Vcluster & v_cl = create_vcluster();
747 
748  // set the seed
749  // create the random generator engine
750  std::srand(v_cl.getProcessUnitID());
751  std::default_random_engine eg;
752  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
753 
754  size_t nsz[] = {0,32,4};
755  nsz[0] = 65536 * v_cl.getProcessingUnits();
756 
757  print_test_v( "Testing 3D random walk vector k<=",nsz[0]);
758 
759  // 3D test
760  for (size_t i = 0 ; i < 3 ; i++ )
761  {
762  size_t k = nsz[i];
763 
764  BOOST_TEST_CHECKPOINT( "Testing 3D random walk vector k=" << k );
765 
766  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
767 
768  // Boundary conditions
769  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
770 
771  // factor
772  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
773 
774  // ghost
775  Ghost<3,float> ghost(0.01 / factor);
776 
777  // Distributed vector
779 
780  auto it = vd.getIterator();
781 
782  while (it.isNext())
783  {
784  auto key = it.get();
785 
786  vd.getPos(key)[0] = ud(eg);
787  vd.getPos(key)[1] = ud(eg);
788  vd.getPos(key)[2] = ud(eg);
789 
790  ++it;
791  }
792 
793  vd.map();
794 
795  // 10 step random walk
796 
797  for (size_t j = 0 ; j < 4 ; j++)
798  {
799  auto it = vd.getDomainIterator();
800 
801  while (it.isNext())
802  {
803  auto key = it.get();
804 
805  vd.getPos(key)[0] += 0.02 * ud(eg);
806  vd.getPos(key)[1] += 0.02 * ud(eg);
807  vd.getPos(key)[2] += 0.02 * ud(eg);
808 
809  ++it;
810  }
811 
812  vd.map();
813 
814  vd.ghost_get<0>();
815 
816  // Count the local particles and check that the total number is consistent
817  size_t cnt = total_n_part_lc(vd,bc);
818 
819  BOOST_REQUIRE_EQUAL((size_t)k,cnt);
820  }
821  }
822 }
823 
824 BOOST_AUTO_TEST_CASE( vector_dist_periodic_map )
825 {
826  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
827 
828  // Boundary conditions
829  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
830 
831  // factor
832  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
833 
834  // ghost
835  Ghost<3,float> ghost(0.05 / factor);
836 
837  // Distributed vector
839 
840  // put particles al 1.0, check that they go to 0.0
841 
842  auto it = vd.getIterator();
843 
844  while (it.isNext())
845  {
846  auto key = it.get();
847 
848  vd.getPos(key)[0] = 1.0;
849  vd.getPos(key)[1] = 1.0;
850  vd.getPos(key)[2] = 1.0;
851 
852  ++it;
853  }
854 
855  vd.map();
856 
857  auto it2 = vd.getIterator();
858 
859  while (it2.isNext())
860  {
861  auto key = it2.get();
862 
863  float f = vd.getPos(key)[0];
864  BOOST_REQUIRE_EQUAL(f, 0.0);
865  f = vd.getPos(key)[1];
866  BOOST_REQUIRE_EQUAL(f, 0.0);
867  f = vd.getPos(key)[2];
868  BOOST_REQUIRE_EQUAL(f, 0.0);
869 
870  ++it2;
871  }
872 }
873 
874 
875 BOOST_AUTO_TEST_CASE( vector_dist_not_periodic_map )
876 {
877  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
878 
879  // Boundary conditions
880  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
881 
882  // factor
883  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
884 
885  // ghost
886  Ghost<3,float> ghost(0.05 / factor);
887 
888  // Distributed vector
890 
891  // put particles al 1.0, check that they go to 0.0
892 
893  auto it = vd.getIterator();
894 
895  while (it.isNext())
896  {
897  auto key = it.get();
898 
899  vd.getPos(key)[0] = 1.0;
900  vd.getPos(key)[1] = 1.0;
901  vd.getPos(key)[2] = 1.0;
902 
903  ++it;
904  }
905 
906  vd.map();
907 
908  auto it2 = vd.getIterator();
909 
910  while (it2.isNext())
911  {
912  auto key = it2.get();
913 
914  float f = vd.getPos(key)[0];
915  BOOST_REQUIRE_EQUAL(f, 1.0);
916  f = vd.getPos(key)[1];
917  BOOST_REQUIRE_EQUAL(f, 1.0);
918  f = vd.getPos(key)[2];
919  BOOST_REQUIRE_EQUAL(f, 1.0);
920 
921  ++it2;
922  }
923 }
924 
925 BOOST_AUTO_TEST_CASE( vector_dist_out_of_bound_policy )
926 {
927  Vcluster & v_cl = create_vcluster();
928 
929  if (v_cl.getProcessingUnits() > 8)
930  return;
931 
932  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
933 
934  // Boundary conditions
935  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
936 
937  // factor
938  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
939 
940  // ghost
941  Ghost<3,float> ghost(0.05 / factor);
942 
943  // Distributed vector
945 
946  // put particles at out of the boundary, they must be detected and and killed
947 
948  auto it = vd.getIterator();
949 
950  size_t cnt = 0;
951 
952  while (it.isNext())
953  {
954  auto key = it.get();
955 
956  if (cnt < 1)
957  {
958  vd.getPos(key)[0] = -0.06;
959  vd.getPos(key)[1] = -0.06;
960  vd.getPos(key)[2] = -0.06;
961  }
962  else
963  {
964  vd.getPos(key)[0] = 0.06;
965  vd.getPos(key)[1] = 0.06;
966  vd.getPos(key)[2] = 0.06;
967  }
968 
969  cnt++;
970  ++it;
971  }
972 
973  vd.map();
974 
975  // Particles out of the boundary are killed
976 
977  size_t cnt_l = vd.size_local();
978 
979  v_cl.sum(cnt_l);
980  v_cl.execute();
981 
982  BOOST_REQUIRE_EQUAL(cnt_l,100-v_cl.getProcessingUnits());
983 }
984 
985 void Test_interacting(Box<3,float> & box)
986 {
987  Vcluster & v_cl = create_vcluster();
988 
989  if (v_cl.getProcessingUnits() > 8)
990  return;
991 
992  // set the seed
993  // create the random generator engine
994  std::srand(v_cl.getProcessUnitID());
995  std::default_random_engine eg;
996  std::uniform_real_distribution<float> ud(-0.5f, 0.5f);
997 
998  size_t nsz[] = {0,32,4};
999 
1000 #ifdef TEST_COVERAGE_MODE
1001  nsz[0] = 5536 * v_cl.getProcessingUnits();
1002 #else
1003  nsz[0] = 65536 * v_cl.getProcessingUnits();
1004 #endif
1005 
1006  print_test_v("Testing 3D random walk interacting particles vector k=", nsz[0]);
1007 
1008  // 3D test
1009  for (size_t i = 0 ; i < 3 ; i++ )
1010  {
1011  size_t k = nsz[i];
1012 
1013  BOOST_TEST_CHECKPOINT( "Testing 3D random walk interacting particles vector k=" << k );
1014 
1015  // Boundary conditions
1016  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
1017 
1018  // factor
1019  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
1020 
1021  // interaction radius
1022  float r_cut = 0.01 / factor;
1023 
1024  // ghost
1025  Ghost<3,float> ghost(r_cut);
1026 
1027  // Distributed vector
1029 
1030  auto it = vd.getIterator();
1031 
1032  while (it.isNext())
1033  {
1034  auto key = it.get();
1035 
1036  vd.getPos(key)[0] = ud(eg);
1037  vd.getPos(key)[1] = ud(eg);
1038  vd.getPos(key)[2] = ud(eg);
1039 
1040  ++it;
1041  }
1042 
1043  vd.map();
1044 
1045  // 4 step random walk
1046 
1047  for (size_t j = 0 ; j < 4 ; j++)
1048  {
1049  auto it = vd.getDomainIterator();
1050 
1051  // Move the particles
1052 
1053  while (it.isNext())
1054  {
1055  auto key = it.get();
1056 
1057  vd.getPos(key)[0] += 0.02 * ud(eg);
1058  vd.getPos(key)[1] += 0.02 * ud(eg);
1059  vd.getPos(key)[2] += 0.02 * ud(eg);
1060 
1061  ++it;
1062  }
1063 
1064  vd.map();
1065 
1066  vd.write("Without_ghost");
1067 
1068  vd.ghost_get<0>();
1069 
1070  vd.write("With_ghost");
1071  vd.getDecomposition().write("With_dec_ghost");
1072 
1073  // get the cell list with a cutoff radius
1074 
1075  bool error = false;
1076 
1077  auto NN = vd.getCellList(0.01 / factor);
1078 
1079  // iterate across the domain particle
1080 
1081  auto it2 = vd.getDomainIterator();
1082 
1083  while (it2.isNext())
1084  {
1085  auto p = it2.get();
1086 
1087  Point<3,float> xp = vd.getPos(p);
1088 
1089  auto Np = NN.getCellIterator(NN.getCell(xp));
1090 
1091  while (Np.isNext())
1092  {
1093  auto q = Np.get();
1094 
1095  // repulsive
1096 
1097  Point<3,float> xq = vd.getPos(q);
1098  Point<3,float> f = (xp - xq);
1099 
1100  float distance = f.norm();
1101 
1102  // Particle should be inside 2 * r_cut range
1103 
1104  if (distance > 2*r_cut*sqrt(2))
1105  error = true;
1106 
1107  ++Np;
1108  }
1109 
1110  ++it2;
1111  }
1112 
1113  // Error
1114 
1115  BOOST_REQUIRE_EQUAL(error,false);
1116 
1117  // Count the local particles and check that the total number is consistent
1118  size_t cnt = total_n_part_lc(vd,bc);
1119 
1120  BOOST_REQUIRE_EQUAL((size_t)k,cnt);
1121  }
1122  }
1123 }
1124 
1125 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_interacting_particles )
1126 {
1127  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1128  Test_interacting(box);
1129 
1130  Box<3,float> box2({-0.5,-0.5,-0.5},{0.5,0.5,0.5});
1131  Test_interacting(box2);
1132 }
1133 
1134 BOOST_AUTO_TEST_CASE( vector_dist_grid_iterator )
1135 {
1136 #ifdef TEST_COVERAGE_MODE
1137  long int k = 32*32*32*create_vcluster().getProcessingUnits();
1138 #else
1139  long int k = 64*64*64*create_vcluster().getProcessingUnits();
1140 #endif
1141  k = std::pow(k, 1/3.);
1142 
1143  long int big_step = k / 30;
1144  big_step = (big_step == 0)?1:big_step;
1145  long int small_step = 21;
1146 
1147  print_test( "Testing vector grid iterator list k<=",k);
1148 
1149  // 3D test
1150  for ( ; k > 8*big_step ; k-= (k > 2*big_step)?big_step:small_step )
1151  {
1152  Vcluster & v_cl = create_vcluster();
1153 
1154  const size_t Ng = k;
1155 
1156  // we create a 128x128x128 Grid iterator
1157  size_t sz[3] = {Ng,Ng,Ng};
1158 
1159  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1160 
1161  // Boundary conditions
1162  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
1163 
1164  // ghost
1165  Ghost<3,float> ghost(1.0/(Ng-2));
1166 
1167  // Distributed vector
1169 
1170  // Put particles on a grid creating a Grid iterator
1171  auto it = vd.getGridIterator(sz);
1172 
1173  while (it.isNext())
1174  {
1175  vd.add();
1176 
1177  auto key = it.get();
1178 
1179  vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
1180  vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
1181  vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
1182 
1183  ++it;
1184  }
1185 
1186  BOOST_REQUIRE_EQUAL(it.getSpacing(0),1.0f/(Ng-1));
1187  BOOST_REQUIRE_EQUAL(it.getSpacing(1),1.0f/(Ng-1));
1188  BOOST_REQUIRE_EQUAL(it.getSpacing(2),1.0f/(Ng-1));
1189 
1190  // distribute particles and sync ghost
1191  vd.map();
1192 
1193 
1194  // Check that the sum of all the particles is the grid size
1195  size_t total = vd.size_local();
1196  v_cl.sum(total);
1197  v_cl.execute();
1198 
1199  BOOST_REQUIRE_EQUAL(total,(Ng) * (Ng) * (Ng));
1200  }
1201 }
1202 
1203 BOOST_AUTO_TEST_CASE( vector_dist_cell_verlet_test )
1204 {
1205 #ifdef TEST_COVERAGE_MODE
1206  long int k = 16*16*16*create_vcluster().getProcessingUnits();
1207 #else
1208  long int k = 64*64*64*create_vcluster().getProcessingUnits();
1209 #endif
1210  k = std::pow(k, 1/3.);
1211 
1212  long int big_step = k / 30;
1213  big_step = (big_step == 0)?1:big_step;
1214  long int small_step = 21;
1215 
1216  print_test( "Testing cell and verlet list k<=",k);
1217 
1218  // 3D test
1219  for ( ; k > 8*big_step ; k-= (k > 2*big_step)?big_step:small_step )
1220  {
1221  Vcluster & v_cl = create_vcluster();
1222 
1223  const size_t Ng = k;
1224 
1225  // we create a 128x128x128 Grid iterator
1226  size_t sz[3] = {Ng,Ng,Ng};
1227 
1228  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1229 
1230  // Boundary conditions
1231  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
1232 
1233  float spacing = 1.0/Ng;
1234  float first_dist = spacing;
1235  float second_dist = sqrt(2.0*spacing*spacing);
1236  float third_dist = sqrt(3.0 * spacing*spacing);
1237 
1238  // ghost
1239  Ghost<3,float> ghost(third_dist*1.1);
1240 
1241  // Distributed vector
1243 
1244  // Put particles on a grid creating a Grid iterator
1245  auto it = vd.getGridIterator(sz);
1246 
1247  while (it.isNext())
1248  {
1249  vd.add();
1250 
1251  auto key = it.get();
1252 
1253  vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
1254  vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
1255  vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
1256 
1257  ++it;
1258  }
1259 
1260  BOOST_REQUIRE_EQUAL(it.getSpacing(0),1.0f/Ng);
1261  BOOST_REQUIRE_EQUAL(it.getSpacing(1),1.0f/Ng);
1262  BOOST_REQUIRE_EQUAL(it.getSpacing(2),1.0f/Ng);
1263 
1264  // distribute particles and sync ghost
1265  vd.map();
1266 
1267  // Check that the sum of all the particles is the grid size
1268  size_t total = vd.size_local();
1269  v_cl.sum(total);
1270  v_cl.execute();
1271 
1272  BOOST_REQUIRE_EQUAL(total,(Ng) * (Ng) * (Ng));
1273 
1274  vd.ghost_get<0>();
1275 
1276  // calculate the distance of the first, second and third neighborhood particle
1277  // Consider that they are on a regular grid
1278 
1279  // add a 5% to dist
1280 
1281  first_dist += first_dist * 0.05;
1282  second_dist += second_dist * 0.05;
1283  third_dist += third_dist * 0.05;
1284 
1285  // Create a verlet list for each particle
1286 
1287  VerletList<3,float,FAST,shift<3,float>> verlet = vd.getVerlet(third_dist);
1288 
1289  bool correct = true;
1290 
1291  BOOST_REQUIRE_EQUAL(vd.size_local(),verlet.size());
1292 
1293  // for each particle
1294  for (size_t i = 0 ; i < verlet.size() ; i++)
1295  {
1296  // first NN
1297  size_t first_NN = 0;
1298  size_t second_NN = 0;
1299  size_t third_NN = 0;
1300 
1301  Point<3,float> p = vd.getPos(i);
1302 
1303  // for each neighborhood particle
1304  for (size_t j = 0 ; j < verlet.getNNPart(i) ; j++)
1305  {
1306  Point<3,float> q = vd.getPos(verlet.get(i,j));
1307 
1308  float dist = p.distance(q);
1309 
1310  if (dist <= first_dist)
1311  first_NN++;
1312  else if (dist <= second_dist)
1313  second_NN++;
1314  else
1315  third_NN++;
1316  }
1317 
1318  correct &= (first_NN == 7);
1319  correct &= (second_NN == 12);
1320  correct &= (third_NN == 8);
1321  }
1322 
1323  BOOST_REQUIRE_EQUAL(correct,true);
1324  }
1325 }
1326 
1327 
1328 BOOST_AUTO_TEST_CASE( vector_dist_periodic_map_list )
1329 {
1330  Vcluster & v_cl = create_vcluster();
1331 
1332  if (v_cl.getProcessingUnits() > 3)
1333  return;
1334 
1335  // set the seed
1336  // create the random generator engine
1337  std::srand(v_cl.getProcessUnitID());
1338  std::default_random_engine eg;
1339  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
1340 
1341 #ifdef TEST_COVERAGE_MODE
1342  long int k = 24288 * v_cl.getProcessingUnits();
1343 #else
1344  long int k = 524288 * v_cl.getProcessingUnits();
1345 #endif
1346 
1347  long int big_step = k / 4;
1348  big_step = (big_step == 0)?1:big_step;
1349 
1350  print_test("Testing 3D periodic vector with map_list k=",k);
1351  BOOST_TEST_CHECKPOINT( "Testing 3D periodic vector with map_list k=" << k );
1352 
1353  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1354 
1355  // Boundary conditions
1356  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
1357 
1358  // factor
1359  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
1360 
1361  // ghost
1362  Ghost<3,float> ghost(0.05 / factor);
1363 
1364  // ghost2 (a little bigger because of round off error)
1365  Ghost<3,float> ghost2(0.05001 / factor);
1366 
1368 
1369  // Distributed vector
1370  vector_dist<3,float, part_prop > vd(k,box,bc,ghost);
1371 
1372  auto it = vd.getIterator();
1373 
1374  while (it.isNext())
1375  {
1376  auto key = it.get();
1377 
1378  vd.getPos(key)[0] = ud(eg);
1379  vd.getPos(key)[1] = ud(eg);
1380  vd.getPos(key)[2] = ud(eg);
1381 
1382  // Fill some properties randomly
1383 
1384  vd.getProp<2>(key).push_back(1);
1385  vd.getProp<2>(key).push_back(2);
1386  vd.getProp<2>(key).push_back(3);
1387  vd.getProp<2>(key).push_back(4);
1388 
1389  vd.getProp<3>(key).add(1);
1390  vd.getProp<3>(key).add(2);
1391  vd.getProp<3>(key).add(3);
1392  vd.getProp<3>(key).add(4);
1393 
1394  vd.getProp<4>(key).add();
1395  vd.getProp<4>(key).add();
1396  vd.getProp<4>(key).add();
1397  vd.getProp<4>(key).add();
1398 
1399  ++it;
1400  }
1401 
1402  vd.map_list<0,1>();
1403 
1404  // sync the ghost
1405  vd.ghost_get<0>();
1406 
1407  // Domain + ghost
1408  Box<3,float> dom_ext = box;
1409  dom_ext.enlarge(ghost2);
1410 
1411  // Iterate on all particles domain + ghost
1412  size_t l_cnt = 0;
1413  size_t nl_cnt = 0;
1414  size_t n_out = 0;
1415 
1416  auto it2 = vd.getIterator();
1417  count_local_n_local<3,vector_dist<3,float, part_prop>>(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
1418 
1419  // No particles should be out of domain + ghost
1420  BOOST_REQUIRE_EQUAL(n_out,0ul);
1421 
1422  // Ghost must populated because we synchronized them
1423  if (k > 524288)
1424  {
1425  BOOST_REQUIRE(nl_cnt != 0);
1426  BOOST_REQUIRE(l_cnt > nl_cnt);
1427  }
1428 
1429  // Sum all the particles inside the domain
1430  v_cl.sum(l_cnt);
1431  v_cl.execute();
1432  BOOST_REQUIRE_EQUAL(l_cnt,(size_t)k);
1433 
1434  l_cnt = 0;
1435  nl_cnt = 0;
1436 
1437  // Iterate only on the ghost particles
1438  auto itg = vd.getGhostIterator();
1439  count_local_n_local<3, vector_dist<3,float,part_prop> >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
1440 
1441  // No particle on the ghost must be inside the domain
1442  BOOST_REQUIRE_EQUAL(l_cnt,0ul);
1443 
1444  // Ghost must be populated
1445  if (k > 524288)
1446  {
1447  BOOST_REQUIRE(nl_cnt != 0);
1448  }
1449 }
1450 
1451 
1452 BOOST_AUTO_TEST_CASE( vector_dist_ghost_with_ghost_buffering )
1453 {
1454  Vcluster & v_cl = create_vcluster();
1455 
1456  if (v_cl.getProcessingUnits() > 3)
1457  return;
1458 
1459  // set the seed
1460  // create the random generator engine
1461  std::srand(v_cl.getProcessUnitID());
1462  std::default_random_engine eg;
1463  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
1464 
1465 #ifdef TEST_COVERAGE_MODE
1466  long int k = 24288 * v_cl.getProcessingUnits();
1467 #else
1468  long int k = 524288 * v_cl.getProcessingUnits();
1469 #endif
1470 
1471  long int big_step = k / 4;
1472  big_step = (big_step == 0)?1:big_step;
1473 
1474  print_test("Testing 3D periodic vector with ghost buffering k=",k);
1475  BOOST_TEST_CHECKPOINT( "Testing 3D periodic with ghost buffering k=" << k );
1476 
1477  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1478 
1479  // Boundary conditions
1480  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
1481 
1482  // ghost
1483  Ghost<3,float> ghost(0.1);
1484 
1485  typedef aggregate<float,float,float> part_prop;
1486 
1487  // Distributed vector
1488  vector_dist<3,float, part_prop > vd(k,box,bc,ghost);
1489 
1490  auto it = vd.getIterator();
1491 
1492  while (it.isNext())
1493  {
1494  auto key = it.get();
1495 
1496  vd.getPos(key)[0] = ud(eg);
1497  vd.getPos(key)[1] = ud(eg);
1498  vd.getPos(key)[2] = ud(eg);
1499 
1500  // Fill some properties randomly
1501 
1502  vd.getProp<0>(key) = 0.0;
1503  vd.getProp<1>(key) = vd.getPos(key)[0];
1504  vd.getProp<2>(key) = vd.getPos(key)[0]*vd.getPos(key)[0];
1505 
1506  ++it;
1507  }
1508 
1509  vd.map();
1510 
1511  // sync the ghost
1512  vd.ghost_get<0,1,2>();
1513 
1514  bool ret = true;
1515  auto it2 = vd.getGhostIterator();
1516  while (it2.isNext())
1517  {
1518  auto key = it2.get();
1519 
1520  ret &= vd.getProp<1>(key) == vd.getPos(key)[0];
1521  ret &= vd.getProp<2>(key) == vd.getPos(key)[0] * vd.getPos(key)[0];
1522 
1523  ++it2;
1524  }
1525 
1526  BOOST_REQUIRE_EQUAL(ret,true);
1527 
1528  for (size_t i = 0 ; i < 10 ; i++)
1529  {
1530  auto it = vd.getDomainIterator();
1531 
1532  while (it.isNext())
1533  {
1534  auto key = it.get();
1535 
1536  vd.getPos(key)[1] = ud(eg);
1537  vd.getPos(key)[2] = ud(eg);
1538 
1539  // Fill some properties randomly
1540 
1541  vd.getProp<0>(key) = i;
1542 
1543  ++it;
1544  }
1545 
1546  if (i % 2 == 0)
1547  vd.ghost_get<0>(SKIP_LABELLING);
1548  else
1549  vd.ghost_get<0>(SKIP_LABELLING | NO_CHANGE_ELEMENTS );
1550 
1551  auto it2 = vd.getGhostIterator();
1552  bool ret = true;
1553 
1554  while (it2.isNext())
1555  {
1556  auto key = it2.get();
1557 
1558  ret &= vd.getProp<0>(key) == i;
1559  ret &= vd.getProp<1>(key) == vd.getPos(key)[0];
1560  ret &= vd.getProp<2>(key) == vd.getPos(key)[0] * vd.getPos(key)[0];
1561 
1562  ++it2;
1563  }
1564 
1565  BOOST_REQUIRE_EQUAL(ret,true);
1566  }
1567 
1568  vd.map();
1569  vd.ghost_get<0,1,2>();
1570 
1571  // shift the particle position by 1.0
1572 
1573  it = vd.getGhostIterator();
1574  while (it.isNext())
1575  {
1576  // Particle p
1577  auto p = it.get();
1578 
1579  // we shift down he particles
1580  vd.getPos(p)[0] = 10.0;
1581 
1582  // we shift
1583  vd.getPos(p)[1] = 17.0;
1584 
1585  // next particle
1586  ++it;
1587  }
1588 
1589  for (size_t i = 0 ; i < 10 ; i++)
1590  {
1591  auto it = vd.getDomainIterator();
1592 
1593  while (it.isNext())
1594  {
1595  auto key = it.get();
1596 
1597  vd.getPos(key)[1] = ud(eg);
1598  vd.getPos(key)[2] = ud(eg);
1599 
1600  // Fill some properties randomly
1601 
1602  vd.getProp<0>(key) = i;
1603  vd.getProp<1>(key) = vd.getPos(key)[0];
1604  vd.getProp<2>(key) = vd.getPos(key)[0]*vd.getPos(key)[0];
1605 
1606  ++it;
1607  }
1608 
1609  vd.ghost_get<0>(SKIP_LABELLING | NO_POSITION);
1610 
1611  auto it2 = vd.getGhostIterator();
1612  bool ret = true;
1613 
1614  while (it2.isNext())
1615  {
1616  // Particle p
1617  auto p = it.get();
1618 
1619  ret &= vd.getPos(p)[0] == 10.0;
1620 
1621  // we shift
1622  ret &= vd.getPos(p)[1] == 17.0;
1623 
1624  // next particle
1625  ++it2;
1626  }
1627 
1628  BOOST_REQUIRE_EQUAL(ret,true);
1629  }
1630 }
1631 
1632 
1633 
1634 BOOST_AUTO_TEST_CASE( vector_dist_ghost_put )
1635 {
1636  Vcluster & v_cl = create_vcluster();
1637 
1638  long int k = 25*25*25*create_vcluster().getProcessingUnits();
1639  k = std::pow(k, 1/3.);
1640 
1641  if (v_cl.getProcessingUnits() > 48)
1642  return;
1643 
1644  print_test("Testing 3D periodic ghost put k=",k);
1645  BOOST_TEST_CHECKPOINT( "Testing 3D periodic ghost put k=" << k );
1646 
1647  long int big_step = k / 30;
1648  big_step = (big_step == 0)?1:big_step;
1649  long int small_step = 21;
1650 
1651  // 3D test
1652  for ( ; k >= 2 ; k-= (k > 2*big_step)?big_step:small_step )
1653  {
1654  float r_cut = 1.3 / k;
1655  float r_g = 1.5 / k;
1656 
1657  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1658 
1659  // Boundary conditions
1660  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
1661 
1662  // ghost
1663  Ghost<3,float> ghost(r_g);
1664 
1665  typedef aggregate<float> part_prop;
1666 
1667  // Distributed vector
1668  vector_dist<3,float, part_prop > vd(0,box,bc,ghost);
1669 
1670  auto it = vd.getGridIterator({(size_t)k,(size_t)k,(size_t)k});
1671 
1672  while (it.isNext())
1673  {
1674  auto key = it.get();
1675 
1676  vd.add();
1677 
1678  vd.getLastPosWrite()[0] = key.get(0)*it.getSpacing(0);
1679  vd.getLastPosWrite()[1] = key.get(1)*it.getSpacing(1);
1680  vd.getLastPosWrite()[2] = key.get(2)*it.getSpacing(2);
1681 
1682  // Fill some properties randomly
1683 
1684  vd.getLastPropWrite<0>() = 0.0;
1685 
1686  ++it;
1687  }
1688 
1689  vd.map();
1690 
1691  // sync the ghost
1692  vd.ghost_get<0>();
1693 
1694  {
1695  auto NN = vd.getCellList(r_cut);
1696  float a = 1.0f*k*k;
1697 
1698  // run trough all the particles + ghost
1699 
1700  auto it2 = vd.getDomainIterator();
1701 
1702  while (it2.isNext())
1703  {
1704  // particle p
1705  auto p = it2.get();
1706  Point<3,float> xp = vd.getPos(p);
1707 
1708  // Get an iterator over the neighborhood particles of p
1709  auto Np = NN.getNNIterator<NO_CHECK>(NN.getCell(xp));
1710 
1711  // For each neighborhood particle ...
1712  while (Np.isNext())
1713  {
1714  auto q = Np.get();
1715  Point<3,float> xq = vd.getPosRead(q);
1716 
1717  float dist = xp.distance(xq);
1718 
1719  if (dist < r_cut)
1720  vd.getPropWrite<0>(q) += a*(-dist*dist+r_cut*r_cut);
1721 
1722  ++Np;
1723  }
1724 
1725  ++it2;
1726  }
1727 
1728  vd.ghost_put<add_,0>();
1729 
1730  bool ret = true;
1731  auto it3 = vd.getDomainIterator();
1732 
1733  float constant = vd.getProp<0>(it3.get());
1734  float eps = 0.001;
1735 
1736  while (it3.isNext())
1737  {
1738  float constant2 = vd.getProp<0>(it3.get());
1739  if (fabs(constant - constant2)/constant > eps)
1740  {
1741  Point<3,float> p = vd.getPosRead(it3.get());
1742 
1743  std::cout << p.toString() << " " << constant2 << "/" << constant << " " << v_cl.getProcessUnitID() << std::endl;
1744  ret = false;
1745  break;
1746  }
1747 
1748  ++it3;
1749  }
1750  BOOST_REQUIRE_EQUAL(ret,true);
1751  }
1752 
1753  auto itp = vd.getDomainAndGhostIterator();
1754  while (itp.isNext())
1755  {
1756  auto key = itp.get();
1757 
1758  vd.getPropWrite<0>(key) = 0.0;
1759 
1760  ++itp;
1761  }
1762 
1763  {
1764  auto NN = vd.getCellList(r_cut);
1765  float a = 1.0f*k*k;
1766 
1767  // run trough all the particles + ghost
1768 
1769  auto it2 = vd.getDomainIterator();
1770 
1771  while (it2.isNext())
1772  {
1773  // particle p
1774  auto p = it2.get();
1775  Point<3,float> xp = vd.getPosRead(p);
1776 
1777  // Get an iterator over the neighborhood particles of p
1778  auto Np = NN.getNNIterator<NO_CHECK>(NN.getCell(xp));
1779 
1780  // For each neighborhood particle ...
1781  while (Np.isNext())
1782  {
1783  auto q = Np.get();
1784  Point<3,float> xq = vd.getPosRead(q);
1785 
1786  float dist = xp.distance(xq);
1787 
1788  if (dist < r_cut)
1789  vd.getPropWrite<0>(q) += a*(-dist*dist+r_cut*r_cut);
1790 
1791  ++Np;
1792  }
1793 
1794  ++it2;
1795  }
1796 
1797  vd.ghost_put<add_,0>();
1798 
1799  bool ret = true;
1800  auto it3 = vd.getDomainIterator();
1801 
1802  float constant = vd.getPropRead<0>(it3.get());
1803  float eps = 0.001;
1804 
1805  while (it3.isNext())
1806  {
1807  float constant2 = vd.getPropRead<0>(it3.get());
1808  if (fabs(constant - constant2)/constant > eps)
1809  {
1810  Point<3,float> p = vd.getPosRead(it3.get());
1811 
1812  std::cout << p.toString() << " " << constant2 << "/" << constant << " " << v_cl.getProcessUnitID() << std::endl;
1813  ret = false;
1814  break;
1815  }
1816 
1817  ++it3;
1818  }
1819  BOOST_REQUIRE_EQUAL(ret,true);
1820  }
1821  }
1822 }
1823 
1824 BOOST_AUTO_TEST_CASE( vector_of_vector_dist )
1825 {
1826  Vcluster & v_cl = create_vcluster();
1827 
1828  if (v_cl.getProcessingUnits() > 48)
1829  return;
1830 
1831  // Boundary conditions
1832  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
1833 
1834  // Box
1835  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1836 
1837  // ghost
1838  Ghost<3,float> ghost(0.1);
1839 
1841 
1842  // first phase
1843  phases.add( vector_dist<3,float, aggregate<double,double>>(4096,box,bc,ghost) );
1844 
1845  // The other 3 phases
1846  phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),4096) );
1847  phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),4096) );
1848  phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),4096) );
1849 
1850  phases.get(0).map();
1851  phases.get(0).ghost_get<>();
1852  phases.get(1).map();
1853  phases.get(1).ghost_get<>();
1854  phases.get(2).map();
1855  phases.get(2).ghost_get<>();
1856  phases.get(3).map();
1857  phases.get(3).ghost_get<>();
1858 
1859  size_t cnt = 0;
1860 
1861  for (size_t i = 0 ; i < phases.size() ; i++)
1862  cnt += phases.get(i).size_local();
1863 
1864  v_cl.sum(cnt);
1865  v_cl.execute();
1866 
1867  BOOST_REQUIRE_EQUAL(cnt,4*4096ul);
1868 }
1869 
1870 
1871 #include "vector_dist_cell_list_tests.hpp"
1872 #include "vector_dist_NN_tests.hpp"
1873 #include "vector_dist_complex_prp_unit_test.hpp"
1874 
1875 BOOST_AUTO_TEST_SUITE_END()
1876 
1877 #endif /* VECTOR_DIST_UNIT_TEST_HPP_ */
void sum(T &num)
Sum the numbers across all processors and get the result.
This class represent an N-dimensional box.
Definition: SpaceBox.hpp:26
bool isInsideNP(const Point< dim, T > &p) const
Check if the point is inside the region excluding the positive part.
Definition: Box.hpp:910
T getLow(int i) const
get the i-coordinate of the low bound interval of the box
Definition: Box.hpp:479
void map_list()
It move all the particles that does not belong to the local processor to the respective processor...
size_t getProcessUnitID()
Get the process unit id.
static size_t getDefaultGrid(size_t n_sub)
The default grid size.
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
void execute()
Execute all the requests.
bool isInside(const Point< dim, T > &p) const
Check if the point is inside the box.
Definition: Box.hpp:880
std::string toString() const
Return the string with the point coordinate.
Definition: Point.hpp:361
Cell list structure.
Definition: VerletList.hpp:36
auto getLastPos() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element.
Iterator that Iterate across particle indexes.
This structure define the operation add to use with copy general.
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
auto getLastPropWrite() -> decltype(v_prp.template get< id >(0))
Get the property of the last element.
vector_dist_iterator getIterator()
Get an iterator that traverse domain and ghost particles.
bool isLocalBC(const encapc< 1, Point< dim, T >, Mem > p, const size_t(&bc)[dim]) const
Check if the particle is local considering boundary conditions.
Point< dim, T > getP1() const
Get the point p1.
Definition: Box.hpp:605
CellL getCellList(St r_cut, bool no_se3=false)
Construct a cell list starting from the stored particles.
Definition: Ghost.hpp:37
bool isLocal(const encapc< 1, Point< dim, T >, Mem > p) const
Check if the particle is local.
Implementation of VCluster class.
Definition: VCluster.hpp:36
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
bool isNext()
Check if there is the next element.
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
This class decompose a space into sub-sub-domains and distribute them across processors.
vector_dist_iterator getGhostIterator() const
Get the iterator across the position of the ghost particles.
void enlarge(const Box< dim, T > &gh)
Enlarge the box with ghost margin.
Definition: Box.hpp:700
const T & get(int i) const
Get coordinate.
Definition: Point.hpp:142
void add()
Add local particle.
void map()
It move all the particles that does not belong to the local processor to the respective processor...
This class represent an N-dimensional box.
Definition: Box.hpp:56
T norm()
norm of the vector
Definition: Point.hpp:202
This class is a trick to indicate the compiler a specific specialization pattern. ...
Definition: memory_c.hpp:201
auto getLastPosWrite() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element.
Declaration grid_sm.
Definition: grid_sm.hpp:71
Distributed vector.
vect_dist_key_dx get()
Get the actual key.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:71
T distance(const Point< dim, T > &q)
It calculate the distance between 2 points.
Definition: Point.hpp:221
Test structure used for several test.
Definition: Point_test.hpp:95
size_t getProcessingUnits()
Get the total number of processors.
Point< dim, T > getP2() const
Get the point p2.
Definition: Box.hpp:619
Decomposition & getDecomposition()
Get the decomposition.
void ghost_get(size_t opt=WITH_POSITION)
It synchronize the properties and position of the ghost particles.
grid_dist_id_iterator_dec< Decomposition > getGridIterator(const size_t(&sz)[dim])