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