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_unit_test.cpp
1 /*
2  * vector_dist_unit_test.hpp
3  *
4  * Created on: Mar 6, 2015
5  * Author: Pietro Incardona
6  */
7 
8 #define BOOST_TEST_DYN_LINK
9 #include <boost/test/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_dist_util_unit_tests.hpp"
17 #include "Point_test.hpp"
18 #include "Vector/performance/vector_dist_performance_common.hpp"
19 
26 void print_test_v(std::string test, size_t sz)
27 {
28  if (create_vcluster().getProcessUnitID() == 0)
29  std::cout << test << " " << sz << "\n";
30 }
31 
40 long int decrement(long int k, long int step)
41 {
42  if (k <= 32)
43  {
44  return 1;
45  }
46  else if (k - 2*step+1 <= 0)
47  {
48  return k - 32;
49  }
50  else
51  return step;
52 }
53 
60 template<unsigned int dim, template <typename> class layout> size_t total_n_part_lc(vector_dist<dim,float, Point_test<float>,typename layout<Point_test<float>>::type, layout, CartDecomposition<dim,float> > & vd, size_t (& bc)[dim])
61 {
62  Vcluster & v_cl = vd.getVC();
63  auto it2 = vd.getDomainIterator();
64  const CartDecomposition<3,float> & ct = vd.getDecomposition();
65 
66  bool noOut = true;
67 
68  size_t cnt = 0;
69  while (it2.isNext())
70  {
71  auto key = it2.get();
72 
73  noOut &= ct.isLocal(vd.getPos(key));
74 
75  cnt++;
76 
77  ++it2;
78  }
79 
80  BOOST_REQUIRE_EQUAL(noOut,true);
81 
82  //
83  v_cl.sum(cnt);
84  v_cl.execute();
85 
86  return cnt;
87 }
88 
89 
90 BOOST_AUTO_TEST_SUITE( vector_dist_test )
91 
92 void print_test(std::string test, size_t sz)
93 {
94  if (create_vcluster().getProcessUnitID() == 0)
95  std::cout << test << " " << sz << "\n";
96 }
97 
98 template<typename vector>
99 void Test2D_ghost(Box<2,float> & box)
100 {
101  // Communication object
102  Vcluster & v_cl = create_vcluster();
103 
104  typedef Point_test<float> p;
105 
106  // Get the default minimum number of sub-sub-domain per processor (granularity of the decomposition)
107  size_t n_sub = 64 * v_cl.getProcessingUnits();
108  // Convert the request of having a minimum n_sub number of sub-sub domain into grid decompsition of the space
110 
112 
113  size_t g_div[]= {sz,sz};
114 
115  // number of particles
116  size_t np = sz * sz;
117 
118  // Calculate the number of elements this processor is going to obtain
119  size_t p_np = np / v_cl.getProcessingUnits();
120 
121  // Get non divisible part
122  size_t r = np % v_cl.getProcessingUnits();
123 
124  // Get the offset
125  size_t offset = v_cl.getProcessUnitID() * p_np + std::min(v_cl.getProcessUnitID(),r);
126 
127  // Distribute the remain elements
128  if (v_cl.getProcessUnitID() < r)
129  p_np++;
130 
131  // Create a grid info
132  grid_sm<2,void> g_info(g_div);
133 
134  // Calculate the grid spacing
135  Point<2,float> spacing = box.getP2() - box.getP1();
136  spacing = spacing / g_div;
137 
138  // middle spacing
139  Point<2,float> m_spacing = spacing / 2.0;
140 
141  // set the ghost based on the radius cut off (make just a little bit smaller than the spacing)
142  Ghost<2,float> g(spacing.get(0) - spacing .get(0) * 0.0001);
143 
144  // Boundary conditions
145  size_t bc[2]={NON_PERIODIC,NON_PERIODIC};
146 
147  // Vector of particles
148  vector vd(g_info.size(),box,bc,g);
149 
150  // size_t
151  size_t cobj = 0;
152 
153  grid_key_dx_iterator_sp<2> it(g_info,offset,offset+p_np-1);
154  auto v_it = vd.getIterator();
155 
156  while (v_it.isNext() && it.isNext())
157  {
158  auto key = it.get();
159  auto key_v = v_it.get();
160 
161  // set the particle position
162 
163  vd.getPos(key_v)[0] = key.get(0) * spacing[0] + m_spacing[0] + box.getLow(0);
164  vd.getPos(key_v)[1] = key.get(1) * spacing[1] + m_spacing[1] + box.getLow(1);
165 
166  cobj++;
167 
168  ++v_it;
169  ++it;
170  }
171 
173 
174  // Both iterators must signal the end, and the number of elements in the vector, must the equal to the
175  // predicted one
176  BOOST_REQUIRE_EQUAL(v_it.isNext(),false);
177  BOOST_REQUIRE_EQUAL(it.isNext(),false);
178  BOOST_REQUIRE_EQUAL(cobj,p_np);
179 
181 
182  // redistribute the particles according to the decomposition
183  vd.map();
184 
185  auto v_it2 = vd.getIterator();
186 
187  while (v_it2.isNext())
188  {
189  auto key = v_it2.get();
190 
191  // fill with the processor ID where these particle live
192  vd.template getProp<p::s>(key) = vd.getPos(key)[0] + vd.getPos(key)[1] * 16.0f;
193  vd.template getProp<p::v>(key)[0] = v_cl.getProcessUnitID();
194  vd.template getProp<p::v>(key)[1] = v_cl.getProcessUnitID();
195  vd.template getProp<p::v>(key)[2] = v_cl.getProcessUnitID();
196 
197  ++v_it2;
198  }
199 
200  // do a ghost get
201  vd.template ghost_get<p::s,p::v>();
202 
204 
205  // Get the decomposition
206  const auto & dec = vd.getDecomposition();
207 
208  // Get the ghost external boxes
209  openfpm::vector<size_t> vb(dec.getNEGhostBox());
210 
211  // Get the ghost iterator
212  auto g_it = vd.getGhostIterator();
213 
214  size_t n_part = 0;
215 
216  // Check if the ghost particles contain the correct information
217  while (g_it.isNext())
218  {
219  auto key = g_it.get();
220 
221  // Check the received data
222  BOOST_REQUIRE_EQUAL(vd.getPos(key)[0] + vd.getPos(key)[1] * 16.0f,vd.template getProp<p::s>(key));
223 
224  bool is_in = false;
225  size_t b = 0;
226  size_t lb = 0;
227 
228  // check if the received data are in one of the ghost boxes
229  for ( ; b < dec.getNEGhostBox() ; b++)
230  {
231  Point<2,float> xp = vd.getPos(key);
232 
233  if (dec.getEGhostBox(b).isInside(xp) == true )
234  {
235  is_in = true;
236 
237  // Add
238  vb.get(b)++;
239  lb = b;
240  }
241  }
242  BOOST_REQUIRE_EQUAL(is_in,true);
243 
244  // Check that the particle come from the correct processor
245  BOOST_REQUIRE_EQUAL(vd.template getProp<p::v>(key)[0],dec.getEGhostBoxProcessor(lb));
246 
247  n_part++;
248  ++g_it;
249  }
250 
251  if (v_cl.getProcessingUnits() > 1)
252  {
253  BOOST_REQUIRE(n_part != 0);
254  }
255 
256  CellDecomposer_sm<2,float,shift<2,float>> cd(SpaceBox<2,float>(box),g_div,0);
257 
258  for (size_t i = 0 ; i < vb.size() ; i++)
259  {
260  // Calculate how many particle should be in the box
261  size_t n_point = cd.getGridPoints(dec.getEGhostBox(i)).getVolumeKey();
262 
263  BOOST_REQUIRE_EQUAL(n_point,vb.get(i));
264  }
265 }
266 
267 BOOST_AUTO_TEST_CASE( vector_dist_ghost )
268 {
270 
271  Box<2,float> box({0.0,0.0},{1.0,1.0});
272  Test2D_ghost<vector>(box);
273 
274  Box<2,float> box2({-1.0,-1.0},{2.5,2.5});
275  Test2D_ghost<vector>(box2);
276 }
277 
278 BOOST_AUTO_TEST_CASE( vector_dist_ghost_inte )
279 {
281 
282  Box<2,float> box({0.0,0.0},{1.0,1.0});
283  Test2D_ghost<vector>(box);
284 
285  Box<2,float> box2({-1.0,-1.0},{2.5,2.5});
286  Test2D_ghost<vector>(box2);
287 }
288 
289 
290 
291 BOOST_AUTO_TEST_CASE( vector_dist_iterator_test_use_2d )
292 {
293  Vcluster & v_cl = create_vcluster();
294 
295  // set the seed
296  // create the random generator engine
297  std::srand(v_cl.getProcessUnitID());
298  std::default_random_engine eg;
299  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
300 
301 #ifdef TEST_COVERAGE_MODE
302  long int k = 24288 * v_cl.getProcessingUnits();
303 #else
304  long int k = 524288 * v_cl.getProcessingUnits();
305 #endif
306 
307  long int big_step = k / 4;
308  big_step = (big_step == 0)?1:big_step;
309 
310  print_test_v( "Testing 2D vector k<=",k);
311 
312  // 2D test
313  for ( ; k >= 2 ; k-= decrement(k,big_step) )
314  {
315  BOOST_TEST_CHECKPOINT( "Testing 2D vector k=" << k );
316 
318 
319  Box<2,float> box({0.0,0.0},{1.0,1.0});
320 
321  // Boundary conditions
322  size_t bc[2]={NON_PERIODIC,NON_PERIODIC};
323 
324  vector_dist<2,float, Point_test<float> > vd(k,box,bc,Ghost<2,float>(0.0));
325 
326  auto it = vd.getIterator();
327 
328  while (it.isNext())
329  {
330  auto key = it.get();
331 
332  vd.getPos(key)[0] = ud(eg);
333  vd.getPos(key)[1] = ud(eg);
334 
335  ++it;
336  }
337 
338  vd.map();
339 
341 
342  // Check if we have all the local particles
343  size_t cnt = 0;
344  const CartDecomposition<2,float> & ct = vd.getDecomposition();
345  auto it2 = vd.getIterator();
346 
347  while (it2.isNext())
348  {
349  auto key = it2.get();
350 
351  // Check if local
352  BOOST_REQUIRE_EQUAL(ct.isLocal(vd.getPos(key)),true);
353 
354  cnt++;
355 
356  ++it2;
357  }
358 
359  //
360  v_cl.sum(cnt);
361  v_cl.execute();
362  BOOST_REQUIRE_EQUAL((long int)cnt,k);
363  }
364 }
365 
366 BOOST_AUTO_TEST_CASE( vector_dist_iterator_test_use_3d )
367 {
368  Vcluster & v_cl = create_vcluster();
369 
370  // set the seed
371  // create the random generator engine
372  std::srand(v_cl.getProcessUnitID());
373  std::default_random_engine eg;
374  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
375 
376 #ifdef TEST_COVERAGE_MODE
377  long int k = 24288 * v_cl.getProcessingUnits();
378 #else
379  long int k = 524288 * v_cl.getProcessingUnits();
380 #endif
381 
382  long int big_step = k / 4;
383  big_step = (big_step == 0)?1:big_step;
384 
385  print_test_v( "Testing 3D vector k<=",k);
386 
387  // 3D test
388  for ( ; k >= 2 ; k-= decrement(k,big_step) )
389  {
390  BOOST_TEST_CHECKPOINT( "Testing 3D vector k=" << k );
391 
393 
394  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
395 
396  // Boundary conditions
397  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
398 
400 
401  auto it = vd.getIterator();
402 
403  while (it.isNext())
404  {
405  auto key = it.get();
406 
407  vd.getPos(key)[0] = ud(eg);
408  vd.getPos(key)[1] = ud(eg);
409  vd.getPos(key)[2] = ud(eg);
410 
411  ++it;
412  }
413 
414  vd.map();
415 
417 
418  // Check if we have all the local particles
419  size_t cnt = 0;
420  const CartDecomposition<3,float> & ct = vd.getDecomposition();
421  auto it2 = vd.getIterator();
422 
423  while (it2.isNext())
424  {
425  auto key = it2.get();
426 
427  // Check if local
428  BOOST_REQUIRE_EQUAL(ct.isLocal(vd.getPos(key)),true);
429 
430  cnt++;
431 
432  ++it2;
433  }
434 
435  //
436  v_cl.sum(cnt);
437  v_cl.execute();
438  BOOST_REQUIRE_EQUAL(cnt,(size_t)k);
439  }
440 }
441 
442 
443 BOOST_AUTO_TEST_CASE( vector_dist_iterator_fixed_dec_3d )
444 {
445  Vcluster & v_cl = create_vcluster();
446 
447  // set the seed
448  // create the random generator engine
449  std::srand(v_cl.getProcessUnitID());
450  std::default_random_engine eg;
451  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
452 
453 #ifdef TEST_COVERAGE_MODE
454  long int k = 2428 * v_cl.getProcessingUnits();
455 #else
456  long int k = 52428 * v_cl.getProcessingUnits();
457 #endif
458 
459  long int big_step = k / 4;
460  big_step = (big_step == 0)?1:big_step;
461 
462  print_test_v( "Testing 3D vector copy decomposition k<=",k);
463 
464  // 3D test
465  for ( ; k >= 2 ; k-= decrement(k,big_step) )
466  {
467  BOOST_TEST_CHECKPOINT( "Testing 3D vector copy decomposition k=" << k );
468 
469  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
470 
471  // Boundary conditions
472  size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
473 
475  vector_dist<3,float, aggregate<double,double> > vd2(vd.getDecomposition(),k);
476 
477  auto it = vd.getIterator();
478 
479  while (it.isNext())
480  {
481  auto key = it.get();
482 
483  vd.getPos(key)[0] = ud(eg);
484  vd.getPos(key)[1] = ud(eg);
485  vd.getPos(key)[2] = ud(eg);
486 
487  vd2.getPos(key)[0] = vd.getPos(key)[0];
488  vd2.getPos(key)[1] = vd.getPos(key)[1];
489  vd2.getPos(key)[2] = vd.getPos(key)[2];
490 
491  ++it;
492  }
493 
494  vd.map();
495  vd2.map();
496 
497  vd.ghost_get();
498  vd2.ghost_get();
499 
500  auto NN = vd.getCellList(0.05);
501  auto NN2 = vd2.getCellList(0.05);
502 
503  cross_calc<3,0>(NN,NN2,vd,vd2);
504  cross_calc<3,1>(NN,NN,vd,vd);
505 
506 
507  auto it3 = vd.getIterator();
508 
509  while (it3.isNext())
510  {
511  auto key = it3.get();
512 
513  BOOST_REQUIRE_EQUAL(vd.getProp<0>(key),vd.getProp<1>(key));
514 
515  ++it3;
516  }
517  }
518 }
519 
520 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_use_2d )
521 {
522  Vcluster & v_cl = create_vcluster();
523 
524  // set the seed
525  // create the random generator engine
526  std::srand(v_cl.getProcessUnitID());
527  std::default_random_engine eg;
528  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
529 
530 #ifdef TEST_COVERAGE_MODE
531  long int k = 24288 * v_cl.getProcessingUnits();
532 #else
533  long int k = 524288 * v_cl.getProcessingUnits();
534 #endif
535 
536  long int big_step = k / 4;
537  big_step = (big_step == 0)?1:big_step;
538 
539  print_test_v( "Testing 2D periodic vector k<=",k);
540 
541  // 2D test
542  for ( ; k >= 2 ; k-= decrement(k,big_step) )
543  {
544  BOOST_TEST_CHECKPOINT( "Testing 2D periodic vector k=" << k );
545 
546  Box<2,float> box({0.0,0.0},{1.0,1.0});
547 
548  // Boundary conditions
549  size_t bc[2]={PERIODIC,PERIODIC};
550 
551  // factor
552  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
553 
554  // ghost
555  Ghost<2,float> ghost(0.01 / factor);
556 
557  // ghost2 (a little bigger because of round off error)
558  Ghost<2,float> ghost2(0.05001 / factor);
559 
560  // Distributed vector
561  vector_dist<2,float, Point_test<float> > vd(k,box,bc,ghost);
562 
563  auto it = vd.getIterator();
564 
565  while (it.isNext())
566  {
567  auto key = it.get();
568 
569  vd.getPos(key)[0] = ud(eg);
570  vd.getPos(key)[1] = ud(eg);
571 
572  ++it;
573  }
574 
575  vd.map();
576 
577  // sync the ghost, only the property zero
578  vd.ghost_get<0>();
579 
580  // Domain + ghost box
581  Box<2,float> dom_ext = box;
582  dom_ext.enlarge(ghost2);
583 
584  // Iterate on all particles domain + ghost
585  size_t l_cnt = 0;
586  size_t nl_cnt = 0;
587  size_t n_out = 0;
588 
589 
590  auto it2 = vd.getIterator();
591  count_local_n_local<2,vector_dist<2,float, Point_test<float> >>(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
592 
593  // No particles should be out of domain + ghost
594  BOOST_REQUIRE_EQUAL(n_out,0ul);
595 
596  // Ghost must populated because we synchronized them
597  if (k > 524288)
598  {
599  BOOST_REQUIRE(nl_cnt != 0);
600  BOOST_REQUIRE(l_cnt > nl_cnt);
601  }
602 
603  // Sum all the particles inside the domain
604  v_cl.sum(l_cnt);
605  v_cl.execute();
606 
607  // count that they are equal to the initial total number
608  BOOST_REQUIRE_EQUAL((long int)l_cnt,k);
609 
610  l_cnt = 0;
611  nl_cnt = 0;
612 
613  // Iterate only on the ghost particles
614  auto itg = vd.getGhostIterator();
615  count_local_n_local<2,vector_dist<2,float, Point_test<float> > >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
616 
617  // No particle on the ghost must be inside the domain
618  BOOST_REQUIRE_EQUAL(l_cnt,0ul);
619 
620  // Ghost must be populated
621  if (k > 524288)
622  {
623  BOOST_REQUIRE(nl_cnt != 0);
624  }
625  }
626 }
627 
628 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_use_3d )
629 {
630  Vcluster & v_cl = create_vcluster();
631 
632  // set the seed
633  // create the random generator engine
634  std::srand(v_cl.getProcessUnitID());
635  std::default_random_engine eg;
636  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
637 
638 #ifdef TEST_COVERAGE_MODE
639  long int k = 24288 * v_cl.getProcessingUnits();
640 #else
641  long int k = 524288 * v_cl.getProcessingUnits();
642 #endif
643 
644  long int big_step = k / 4;
645  big_step = (big_step == 0)?1:big_step;
646 
647  print_test_v( "Testing 3D periodic vector k<=",k);
648 
649  // 3D test
650  for ( ; k >= 2 ; k-= decrement(k,big_step) )
651  {
652  BOOST_TEST_CHECKPOINT( "Testing 3D periodic vector k=" << k );
653 
654  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
655 
656  // Boundary conditions
657  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
658 
659  // factor
660  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
661 
662  // ghost
663  Ghost<3,float> ghost(0.05 / factor);
664 
665  // ghost2 (a little bigger because of round off error)
666  Ghost<3,float> ghost2(0.05001 / factor);
667 
668  // Distributed vector
669  vector_dist<3,float, Point_test<float> > vd(k,box,bc,ghost);
670 
671  auto it = vd.getIterator();
672 
673  while (it.isNext())
674  {
675  auto key = it.get();
676 
677  vd.getPos(key)[0] = ud(eg);
678  vd.getPos(key)[1] = ud(eg);
679  vd.getPos(key)[2] = ud(eg);
680 
681  ++it;
682  }
683 
684  vd.map();
685 
686  // sync the ghost
687  vd.ghost_get<0>();
688 
689  // Domain + ghost
690  Box<3,float> dom_ext = box;
691  dom_ext.enlarge(ghost2);
692 
693  // Iterate on all particles domain + ghost
694  size_t l_cnt = 0;
695  size_t nl_cnt = 0;
696  size_t n_out = 0;
697 
698  auto it2 = vd.getIterator();
699  count_local_n_local<3,vector_dist<3,float, Point_test<float> >>(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
700 
701  // No particles should be out of domain + ghost
702  BOOST_REQUIRE_EQUAL(n_out,0ul);
703 
704  // Ghost must populated because we synchronized them
705  if (k > 524288)
706  {
707  BOOST_REQUIRE(nl_cnt != 0);
708  BOOST_REQUIRE(l_cnt > nl_cnt);
709  }
710 
711  // Sum all the particles inside the domain
712  v_cl.sum(l_cnt);
713  v_cl.execute();
714  BOOST_REQUIRE_EQUAL(l_cnt,(size_t)k);
715 
716  l_cnt = 0;
717  nl_cnt = 0;
718 
719  // Iterate only on the ghost particles
720  auto itg = vd.getGhostIterator();
721  count_local_n_local<3,vector_dist<3,float, Point_test<float> > >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
722 
723  // No particle on the ghost must be inside the domain
724  BOOST_REQUIRE_EQUAL(l_cnt,0ul);
725 
726  // Ghost must be populated
727  if (k > 524288)
728  {
729  BOOST_REQUIRE(nl_cnt != 0);
730  }
731  }
732 }
733 
734 void test_random_walk(size_t opt)
735 {
736  Vcluster & v_cl = create_vcluster();
737 
738  // set the seed
739  // create the random generator engine
740  std::srand(v_cl.getProcessUnitID());
741  std::default_random_engine eg;
742  std::uniform_real_distribution<float> ud(0.0f, 1.0f);
743 
744  size_t nsz[] = {0,32,4};
745  nsz[0] = 65536 * v_cl.getProcessingUnits();
746 
747  print_test_v( "Testing 3D random walk vector k<=",nsz[0]);
748 
749  // 3D test
750  for (size_t i = 0 ; i < 3 ; i++ )
751  {
752  size_t k = nsz[i];
753 
754  BOOST_TEST_CHECKPOINT( "Testing 3D random walk vector k=" << k );
755 
756  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
757 
758  // Boundary conditions
759  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
760 
761  // factor
762  float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
763 
764  // ghost
765  Ghost<3,float> ghost(0.01 / factor);
766 
767  // Distributed vector
768  vector_dist<3,float, Point_test<float> > vd(k,box,bc,ghost);
769 
770  auto it = vd.getIterator();
771 
772  while (it.isNext())
773  {
774  auto key = it.get();
775 
776  vd.getPos(key)[0] = ud(eg);
777  vd.getPos(key)[1] = ud(eg);
778  vd.getPos(key)[2] = ud(eg);
779 
780  ++it;
781  }
782 
783  vd.map();
784 
785  // 10 step random walk
786 
787  for (size_t j = 0 ; j < 4 ; j++)
788  {
789  auto it = vd.getDomainIterator();
790 
791  while (it.isNext())
792  {
793  auto key = it.get();
794 
795  vd.getPos(key)[0] += 0.02 * ud(eg);
796  vd.getPos(key)[1] += 0.02 * ud(eg);
797  vd.getPos(key)[2] += 0.02 * ud(eg);
798 
799  ++it;
800  }
801 
802  vd.map(opt);
803 
804  vd.ghost_get<0>();
805 
806  // Count the local particles and check that the total number is consistent
807  size_t cnt = total_n_part_lc(vd,bc);
808 
809  BOOST_REQUIRE_EQUAL((size_t)k,cnt);
810  }
811  }
812 }
813 
814 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_random_walk )
815 {
816  test_random_walk(NONE);
817 }
818 
819 BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_random_walk_local_map )
820 {
821  test_random_walk(MAP_LOCAL);
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
838  vector_dist<3,float, Point_test<float> > vd(1,box,bc,ghost);
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
889  vector_dist<3,float, Point_test<float> > vd(1,box,bc,ghost);
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
944  vector_dist<3,float, Point_test<float> > vd(100,box,bc,ghost);
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
1028  vector_dist<3,float, Point_test<float> > vd(k,box,bc,ghost);
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
1168  vector_dist<3,float, Point_test<float> > vd(0,box,bc,ghost);
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
1242  vector_dist<3,float, Point_test<float> > vd(0,box,bc,ghost);
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,Mem_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_fixing_noposition_and_keep_prop )
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 
1840  vector_dist<3,float, aggregate<double,double>> vd(4096,box,bc,ghost);
1841 
1842  auto it = vd.getDomainIterator();
1843 
1844  while (it.isNext())
1845  {
1846  auto key = it.get();
1847 
1848  vd.getPos(key)[0] = ((double)rand())/RAND_MAX;
1849  vd.getPos(key)[1] = ((double)rand())/RAND_MAX;
1850  vd.getPos(key)[2] = ((double)rand())/RAND_MAX;
1851 
1852  ++it;
1853  }
1854 
1855  vd.map();
1856 
1857  vd.ghost_get<>();
1858  size_t local = vd.getPosVector().size();
1859 
1860  vd.ghost_get<>(KEEP_PROPERTIES | NO_POSITION);
1861 
1862  size_t local2 = vd.getPosVector().size();
1863 
1864  BOOST_REQUIRE_EQUAL(local,local2);
1865 
1866  // Check now that map reset
1867 
1868  vd.map();
1869 
1870  local = vd.getPosVector().size();
1871  BOOST_REQUIRE_EQUAL(local,vd.size_local());
1872  vd.ghost_get<>(KEEP_PROPERTIES | NO_POSITION);
1873 
1874  local2 = vd.getPosVector().size();
1875 
1876  BOOST_REQUIRE_EQUAL(local,local2);
1877 
1878  vd.ghost_get<>(KEEP_PROPERTIES);
1879  BOOST_REQUIRE_EQUAL(local,vd.getPosVector().size());
1880  BOOST_REQUIRE_EQUAL(vd.getPropVector().size(),local);
1881 
1882  vd.ghost_get<0>(KEEP_PROPERTIES);
1883  BOOST_REQUIRE_EQUAL(local,vd.getPosVector().size());
1884  BOOST_REQUIRE_EQUAL(vd.getPropVector().size(),local);
1885 }
1886 
1887 
1888 BOOST_AUTO_TEST_CASE( vector_of_vector_dist )
1889 {
1890  Vcluster & v_cl = create_vcluster();
1891 
1892  if (v_cl.getProcessingUnits() > 48)
1893  return;
1894 
1895  // Boundary conditions
1896  size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
1897 
1898  // Box
1899  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
1900 
1901  // ghost
1902  Ghost<3,float> ghost(0.1);
1903 
1905 
1906  // first phase
1907  phases.add( vector_dist<3,float, aggregate<double,double>>(4096,box,bc,ghost) );
1908 
1909  // The other 3 phases
1910  phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),4096) );
1911  phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),4096) );
1912  phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),4096) );
1913 
1914  phases.get(0).map();
1915  phases.get(0).ghost_get<>();
1916  phases.get(1).map();
1917  phases.get(1).ghost_get<>();
1918  phases.get(2).map();
1919  phases.get(2).ghost_get<>();
1920  phases.get(3).map();
1921  phases.get(3).ghost_get<>();
1922 
1923  size_t cnt = 0;
1924 
1925  for (size_t i = 0 ; i < phases.size() ; i++)
1926  cnt += phases.get(i).size_local();
1927 
1928  v_cl.sum(cnt);
1929  v_cl.execute();
1930 
1931  BOOST_REQUIRE_EQUAL(cnt,4*4096ul);
1932 }
1933 
1934 
1935 BOOST_AUTO_TEST_SUITE_END()
1936 
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
size_t get(size_t i, size_t j) const
Get the neighborhood element j for the particle i.
T getLow(int i) const
get the i-coordinate of the low bound interval of the box
Definition: Box.hpp:479
size_t getProcessUnitID()
Get the process unit id.
static size_t getDefaultGrid(size_t n_sub)
The default grid size.
void execute()
Execute all the requests.
std::string toString() const
Return the string with the point coordinate.
Definition: Point.hpp:371
Class for Verlet list implementation.
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
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
vector_dist_iterator getGhostIterator() const
Get the iterator across the position of the ghost particles.
Point< dim, T > getP1() const
Get the point p1.
Definition: Box.hpp:605
grid_dist_id_iterator_dec< Decomposition > getGridIterator(const size_t(&sz)[dim])
Definition: Ghost.hpp:39
bool isLocal(const encapc< 1, Point< dim, T >, Mem > p) const
Check if the particle is local.
Transform the boost::fusion::vector into memory specification (memory_traits)
Definition: memory_conf.hpp:52
Implementation of VCluster class.
Definition: VCluster.hpp:36
auto getLastPosWrite() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element.
This class decompose a space into sub-sub-domains and distribute them across processors.
void enlarge(const Box< dim, T > &gh)
Enlarge the box with ghost margin.
Definition: Box.hpp:700
size_t getNNPart(size_t part_id) const
Return the number of neighborhood particles for the particle id.
const T & get(size_t i) const
Get coordinate.
Definition: Point.hpp:142
void map(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor...
void ghost_get(size_t opt=WITH_POSITION)
It synchronize the properties and position of the ghost particles.
void add()
Add local particle.
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 getLastPropWrite() -> decltype(v_prp.template get< id >(0))
Get the property of the last element.
void map_list(size_t opt=NONE)
It move all the particles that does not belong to the local processor to the respective processor...
Declaration grid_sm.
Definition: grid_sm.hpp:71
vector_dist_iterator getIterator()
Get an iterator that traverse domain and ghost particles.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
Distributed vector.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:81
auto getLastPos() -> decltype(v_pos.template get< 0 >(0))
Get the position of the last element.
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:105
size_t getProcessingUnits()
Get the total number of processors.
size_t size()
Return for how many particles has been constructed this verlet list.
Point< dim, T > getP2() const
Get the point p2.
Definition: Box.hpp:619