OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
CellList_test.hpp
1 /*
2  * CellList_test.hpp
3  *
4  * Created on: Mar 23, 2015
5  * Author: Pietro Incardona
6  */
7 
8 #include "CellList.hpp"
9 #include "CellListM.hpp"
10 #include "Grid/grid_sm.hpp"
11 
12 #ifndef CELLLIST_TEST_HPP_
13 #define CELLLIST_TEST_HPP_
14 
15 
21 template<unsigned int dim, typename T, typename CellS> void Test_cell_s(SpaceBox<dim,T> & box)
22 {
24  //Space where is living the Cell list
25  //SpaceBox<dim,T> box({0.0f,0.0f,0.0f},{1.0f,1.0f,1.0f});
26 
27  // Subdivisions
28  size_t div[dim] = {16,16,16};
29 
30  // Origin
31  Point<dim,T> org({0.0,0.0,0.0});
32 
33  // id Cell list
34  CellS cl2(box,div);
36 
37  // grid info
38  grid_sm<dim,void> g_info(div);
39 
40  // Test force reallocation in case of Cell list fast
41  for (size_t i = 0 ; i < CELL_REALLOC * 3 ; i++)
42  {
43  cl2.add(org,i);
44  }
45 
46  // Check the elements
47  BOOST_REQUIRE_EQUAL(cl2.getNelements(cl2.getCell(org)),CELL_REALLOC * 3ul);
48  for (size_t i = 0 ; i < CELL_REALLOC * 3 ; i++)
49  {
50  BOOST_REQUIRE_EQUAL(cl2.get(cl2.getCell(org),i),i);
51  }
52 
54 
55  // id Cell list
56  CellS cl1(box,div);
57 
58  // Create a grid iterator
59  grid_key_dx_iterator<dim> g_it(g_info);
60 
61  // Iterate through each element
62  // Add 1 element for each cell
63 
64  // Usefull definition of points
65  Point<dim,T> end = box.getP2() - box.getP1();
66  Point<dim,T> middle = end / div / 2.0;
67  Point<dim,T> spacing = end / div;
68 
69  Point<dim,T> offset[dim] = {middle,middle,middle};
70 
71  // Create offset shift vectors
72  for (size_t i = 0 ; i < dim ; i++)
73  {
74  offset[i].get(i) += (1.0 / div[i]) / 8.0;
75  }
76 
78  size_t id = 0;
79 
80  while (g_it.isNext())
81  {
82  // Add 2 particles on each cell
83 
84  Point<dim,T> key = Point<dim,T>(g_it.get().toPoint());
85  key = pmul(key,spacing) + offset[0] + box.getP1();
86  pos.add(key);
87 
88  cl1.add(key,id);
89  ++id;
90 
91  key = Point<dim,T>(g_it.get().toPoint());
92  key = pmul(key,spacing) + offset[1] + box.getP1();
93  pos.add(key);
94 
95  cl1.add(key,id);
96  ++id;
97 
98  ++g_it;
99  }
100 
102 
103  // check the cell are correctly filled
104 
105  // reset iterator
106  g_it.reset();
107 
108  while (g_it.isNext())
109  {
110  // Check that there are 2 particles on each cell
111 
112  Point<dim,T> key = Point<dim,T>(g_it.get().toPoint());
113  key = pmul(key,spacing) + offset[2] + box.getP1();
114 
115  size_t cell = cl1.getCell(key);
116  size_t n_ele = cl1.getNelements(cell);
117 
118  BOOST_REQUIRE_EQUAL(n_ele,2ul);
119  BOOST_REQUIRE_EQUAL((long int)(cl1.get(cell,1) - cl1.get(cell,0)),1);
120 
121  ++g_it;
122  }
123 
124  // reset itarator
125  g_it.reset();
126 
128 
129  while (g_it.isNext())
130  {
131  // remove 1 particle on each cell
132 
133  Point<dim,T> key = Point<dim,T>(g_it.get().toPoint());
134  key = pmul(key,spacing) + offset[0] + box.getP1();
135 
136  auto cell = cl1.getCell(key);
137 
138  // Remove the first particle in the cell
139  cl1.remove(cell,0);
140  ++g_it;
141  }
142 
144 
145  // Check we have 1 object per cell
146  g_it.reset();
147 
148  while (g_it.isNext())
149  {
150  // remove 1 particle on each cell
151 
152  Point<dim,T> key = Point<dim,T>(g_it.get().toPoint());
153  key = pmul(key,spacing) + offset[0] + box.getP1();
154 
155  auto cell = cl1.getCell(key);
156  size_t n_ele = cl1.getNelements(cell);
157 
158  BOOST_REQUIRE_EQUAL(n_ele,1ul);
159  ++g_it;
160  }
161 
162 
163  // Check we have 1 object per cell
164 
165  // Create a grid iterator
166  grid_key_dx<dim> p1(1,1,1);
167  grid_key_dx<dim> p2(div[0]-2,div[1]-2,div[2]-2);
168  grid_key_dx_iterator_sub<dim> g_it_s(g_info,p1,p2);
169  id = 0;
170 
171  while (g_it_s.isNext())
172  {
174 
175  Point<dim,T> key = Point<dim,T>(g_it_s.get().toPoint());
176  key = pmul(key,spacing) + offset[0] + box.getP1();
177 
178  auto NN = cl1.template getNNIterator<NO_CHECK>(cl1.getCell(key));
179  size_t total = 0;
180 
181  while(NN.isNext())
182  {
183  // total
184 
185  total++;
186 
187  ++NN;
188  }
189 
191 
192  BOOST_REQUIRE_EQUAL(total,(size_t)openfpm::math::pow(3,dim));
193 
194  // in SE1_CLASS the cell list consider this construction as an hack
195  // disable the test
196 
197 #ifndef SE_CLASS1
198 
199  id = cl1.get(cl1.getCell(key),0);
200  auto NNSym = cl1.template getNNIteratorSym<NO_CHECK>(cl1.getCell(key),id,pos);
201  total = 0;
202 
203  while(NNSym.isNext())
204  {
205  // total
206 
207  total++;
208 
209  ++NNSym;
210  }
211 
212  BOOST_REQUIRE_EQUAL(total,(size_t)openfpm::math::pow(3,dim) / 2 + 1);
213 
214 #endif
215 
216  ++g_it_s;
217  }
218 
219 }
220 
221 
227 template<unsigned int dim, typename T, typename CellS> void Test_cell_sM(SpaceBox<dim,T> & box)
228 {
229  //Space where is living the Cell list
230  //SpaceBox<dim,T> box({0.0f,0.0f,0.0f},{1.0f,1.0f,1.0f});
231 
232  // Subdivisions
233  size_t div[dim] = {16,16,16};
234 
235  // Origin
236  Point<dim,T> org({0.0,0.0,0.0});
237 
238  // grid info
239  grid_sm<dim,void> g_info(div);
240 
242 
243  // CellS = CellListM<dim,T,8>
244  CellS cl1(box,div);
245 
246  // Create a grid iterator
247  grid_key_dx_iterator<dim> g_it(g_info);
248 
249  // Iterate through each element
250  // Add 1 element for each cell
251 
252  // Usefull definition of points
253  Point<dim,T> end = box.getP2() - box.getP1();
254  Point<dim,T> middle = end / div / 2.0;
255  Point<dim,T> spacing = end / div;
256 
257  Point<dim,T> offset[dim] = {middle,middle,middle};
258 
259  // Create offset shift vectors
260  for (size_t i = 0 ; i < dim ; i++)
261  {
262  offset[i].get(i) += (1.0 / div[i]) / 8.0;
263  }
264 
267 
269  phases.add(pos_v<openfpm::vector<Point<dim,T>>>(phase1));
270  phases.add(pos_v<openfpm::vector<Point<dim,T>>>(phase2));
271 
272  size_t id = 0;
273 
274  while (g_it.isNext())
275  {
276  // Add 2 particles on each cell
277 
278  Point<dim,T> key = Point<dim,T>(g_it.get().toPoint());
279  key = pmul(key,spacing) + offset[0] + box.getP1();
280 
281  phase1.add(key);
282 
283  cl1.add(key,id,0);
284 
285  key = Point<dim,T>(g_it.get().toPoint());
286  key = pmul(key,spacing) + offset[1] + box.getP1();
287 
288  phase2.add(key);
289  cl1.add(key,id,1);
290  ++id;
291 
292  ++g_it;
293  }
294 
295  // check the cell are correctly filled
296 
297  // reset iterator
298  g_it.reset();
299 
300  while (g_it.isNext())
301  {
302  // Add 2 particles on each cell
303 
304  Point<dim,T> key = Point<dim,T>(g_it.get().toPoint());
305  key = pmul(key,spacing) + offset[2] + box.getP1();
306 
307  size_t cell = cl1.getCell(key);
308  size_t n_ele = cl1.getNelements(cell);
309 
310  size_t p1 = cl1.getP(cell,1);
311  size_t p2 = cl1.getP(cell,0);
312 
313  size_t v1 = cl1.getV(cell,1);
314  size_t v2 = cl1.getV(cell,0);
315 
316  BOOST_REQUIRE_EQUAL(n_ele,2ul);
317  BOOST_REQUIRE_EQUAL((long int)(p1 - p2),0);
318  BOOST_REQUIRE_EQUAL((long int)(v1 - v2),1);
319  ++g_it;
320  }
321 }
322 
323 
324 
325 template<typename CellList> void Test_CellDecomposer_consistent()
326 {
327  Box<2,float> bx({-1.0/3.0,-1.0/3.0},{1.0/3.0,1.0/3.0});
328 
329  size_t div[2] = {36,36};
330 
331  CellDecomposer_sm<2,float,shift<2,float>> cd(bx,div,1);
332 
333  Box<2,float> bx_sub({-1.0/5.0,-1.0/5.0},{1.0/5.0,1.0/5.0});
334 
335  size_t bc[2] = {NON_PERIODIC,NON_PERIODIC};
336  CellList cl(cd,bx_sub);
337  Box<2,long int> bx_int = cd.convertDomainSpaceIntoGridUnits(bx_sub,bc);
338 
339  BOOST_REQUIRE_EQUAL(bx_int.getLow(0),8);
340  BOOST_REQUIRE_EQUAL(bx_int.getLow(1),8);
341 
342  BOOST_REQUIRE_EQUAL(bx_int.getHigh(0),28);
343  BOOST_REQUIRE_EQUAL(bx_int.getHigh(1),28);
344 
345  cd.convertCellUnitsIntoDomainSpace(bx_sub);
346 
347  BOOST_REQUIRE_EQUAL(bx_sub.getLow(0),-1.0f/5.0f);
348  BOOST_REQUIRE_EQUAL(bx_sub.getLow(1),-1.0f/5.0f);
349 
350  BOOST_REQUIRE_EQUAL(bx_sub.getHigh(0),1.0f/5.0f);
351  BOOST_REQUIRE_EQUAL(bx_sub.getHigh(1),1.0f/5.0f);
352 }
353 
359 template<unsigned int dim, typename T, typename CellS> void Test_NN_iterator_radius(SpaceBox<dim,T> & box)
360 {
361  //Space where is living the Cell list
362  //SpaceBox<dim,T> box({0.0f,0.0f,0.0f},{1.0f,1.0f,1.0f});
363 
364  // Subdivisions
365  size_t div[dim];
366  size_t div2[dim];
367 
368  for (size_t i = 0 ; i < dim ; i++)
369  {
370  div[i] = 17;
371  div2[i] = 34;
372  }
373 
374  // grid info
375  grid_sm<dim,void> g_info(div);
376  grid_sm<dim,void> g_info2(div2);
377 
379 
380  // CellS = CellListM<dim,T,8>
381  CellS cl1(box,div,2);
382  CellS cl2(box,div2,3);
383 
384  T radius = (box.getHigh(0) - box.getLow(0))/div[0];
385 
386  cl2.setRadius( radius );
387 
388  // create a vector of random point
389 
391 
392  for (size_t j = 0 ; j < 10000 ; j++)
393  {
394  vrp.add();
395 
396  for (size_t i = 0 ; i < dim ; i++)
397  {
398  vrp.template get<0>(j)[i] = ((float)rand() / (float)RAND_MAX)*(box.getHigh(i) - box.getLow(i)) + box.getLow(i);
399  }
400  }
401 
402  auto g_it = vrp.getIterator();
403 
404  while (g_it.isNext())
405  {
406  Point<dim,T> xp = vrp.get(g_it.get());
407 
408  size_t debug = cl1.getCell(xp);
409 
410  cl1.add(xp,g_it.get());
411  cl2.add(xp,g_it.get());
412 
413  ++g_it;
414  }
415 
416  // Get the neighborhood of each particle and compare the numbers of cell
417 
418  bool match = true;
419  auto g_it2 = vrp.getIterator();
420 
421  size_t number_of_nn = 0;
422  size_t number_of_nn2 = 0;
423 
424  while (g_it2.isNext())
425  {
426  Point<dim,T> xp = vrp.get(g_it2.get());
427 
430 
431  size_t local1 = 0;
432  size_t local2 = 0;
433 
434  auto NNit = cl1.getNNIterator(cl1.getCell(xp));
435 
436  while (NNit.isNext())
437  {
438  auto q = NNit.get();
439 
440  // calculate distance
441 
442  Point<dim,T> xq = vrp.get(q);
443  Point<dim,T> r = xq - xp;
444 
445  if (r.norm() <= radius)
446  {ids1.add(q);}
447 
448  number_of_nn++;
449  local1++;
450 
451  ++NNit;
452  }
453 
454  auto NN2it = cl2.getNNIteratorRadius(cl2.getCell(xp));
455 
456  while (NN2it.isNext())
457  {
458  auto q = NN2it.get();
459 
460  Point<dim,T> xq = vrp.get(q);
461  Point<dim,T> r = xq - xp;
462 
463  if (r.norm() <= radius)
464  {ids2.add(q);}
465 
466  number_of_nn2++;
467  local2++;
468 
469  ++NN2it;
470  }
471 
472  // Sort ids1
473  ids1.sort();
474  ids2.sort();
475 
476  match &= ids1.size() == ids2.size();
477 
478  for (size_t i = 0 ; i < ids1.size() ; i++)
479  {match &= ids1.get(i) == ids2.get(i);}
480 
481  if (match == false)
482  {break;}
483 
484  ++g_it2;
485  }
486 
487  BOOST_REQUIRE_EQUAL(match,true);
488  BOOST_REQUIRE(number_of_nn2 < number_of_nn);
489 }
490 
491 BOOST_AUTO_TEST_SUITE( CellList_test )
492 
493 BOOST_AUTO_TEST_CASE ( NN_radius_check )
494 {
495  SpaceBox<2,float> box1({0.1,0.1},{0.3,0.5});
496  SpaceBox<3,float> box2({0.0,0.1,0.2},{0.3,0.7,0.5});
497  SpaceBox<3,float> box3({0.0,0.0,0.0},{1.0,1.0,1.0});
498 
499  std::cout << "Test cell list radius" << "\n";
500 
501  Test_NN_iterator_radius<2,float,CellList<2,float,Mem_fast<>,shift<2,float>>>(box1);
502  Test_NN_iterator_radius<3,float,CellList<3,float,Mem_fast<>,shift<3,float>>>(box2);
503  Test_NN_iterator_radius<3,float,CellList<3,float,Mem_fast<>,shift<3,float>>>(box3);
504 
505  std::cout << "End cell list" << "\n";
506 }
507 
508 BOOST_AUTO_TEST_CASE( CellList_use)
509 {
510  std::cout << "Test cell list" << "\n";
511 
512  SpaceBox<3,double> box({0.0f,0.0f,0.0f},{1.0f,1.0f,1.0f});
513  SpaceBox<3,double> box2({-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f});
514  Test_cell_s<3,double,CellList<3,double,Mem_fast<>>>(box);
515  Test_cell_s<3,double,CellList<3,double,Mem_fast<>,shift<3,double>> >(box2);
516  Test_cell_sM<3,double,CellListM<3,double,8>>(box);
517  Test_cell_sM<3,double,CellListM<3,double,8>>(box2);
518 
519 
520  Test_cell_s<3,double,CellList<3,double,Mem_bal<>>>(box);
521  Test_cell_s<3,double,CellList<3,double,Mem_mw<>>>(box);
522 
523  std::cout << "End cell list" << "\n";
524 
525  // Test the cell list
526 }
527 
528 BOOST_AUTO_TEST_CASE( CellList_consistent )
529 {
530  Test_CellDecomposer_consistent<CellList<2,float,Mem_fast<>,shift<2,float>>>();
531 }
532 
533 BOOST_AUTO_TEST_CASE( CellList_NNc_csr_calc )
534 {
536 
537  NNcalc_csr(cNN);
538 
539  BOOST_REQUIRE_EQUAL(cNN.size(),14ul);
540 
541  BOOST_REQUIRE(cNN.get(0).first == grid_key_dx<3>(0,0,0));
542  BOOST_REQUIRE(cNN.get(0).second == grid_key_dx<3>(0,0,0));
543 
544  BOOST_REQUIRE(cNN.get(1).first == grid_key_dx<3>(0,0,0));
545  BOOST_REQUIRE(cNN.get(1).second == grid_key_dx<3>(0,0,1));
546 
547  BOOST_REQUIRE(cNN.get(2).first == grid_key_dx<3>(0,0,1));
548  BOOST_REQUIRE(cNN.get(2).second == grid_key_dx<3>(0,1,0));
549 
550  BOOST_REQUIRE(cNN.get(3).first == grid_key_dx<3>(0,0,0));
551  BOOST_REQUIRE(cNN.get(3).second == grid_key_dx<3>(0,1,0));
552 
553  BOOST_REQUIRE(cNN.get(4).first == grid_key_dx<3>(0,0,0));
554  BOOST_REQUIRE(cNN.get(4).second == grid_key_dx<3>(0,1,1));
555 
556  BOOST_REQUIRE(cNN.get(5).first == grid_key_dx<3>(0,1,1));
557  BOOST_REQUIRE(cNN.get(5).second == grid_key_dx<3>(1,0,0));
558 
559  BOOST_REQUIRE(cNN.get(6).first == grid_key_dx<3>(0,1,0));
560  BOOST_REQUIRE(cNN.get(6).second == grid_key_dx<3>(1,0,0));
561 
562  BOOST_REQUIRE(cNN.get(7).first == grid_key_dx<3>(0,1,0));
563  BOOST_REQUIRE(cNN.get(7).second == grid_key_dx<3>(1,0,1));
564 
565  BOOST_REQUIRE(cNN.get(8).first == grid_key_dx<3>(0,0,1));
566  BOOST_REQUIRE(cNN.get(8).second == grid_key_dx<3>(1,0,0));
567 
568  BOOST_REQUIRE(cNN.get(9).first == grid_key_dx<3>(0,0,0));
569  BOOST_REQUIRE(cNN.get(9).second == grid_key_dx<3>(1,0,0));
570 
571  BOOST_REQUIRE(cNN.get(10).first == grid_key_dx<3>(0,0,0));
572  BOOST_REQUIRE(cNN.get(10).second == grid_key_dx<3>(1,0,1));
573 
574  BOOST_REQUIRE(cNN.get(11).first == grid_key_dx<3>(0,0,1));
575  BOOST_REQUIRE(cNN.get(11).second == grid_key_dx<3>(1,1,0));
576 
577  BOOST_REQUIRE(cNN.get(12).first == grid_key_dx<3>(0,0,0));
578  BOOST_REQUIRE(cNN.get(12).second == grid_key_dx<3>(1,1,0));
579 
580  BOOST_REQUIRE(cNN.get(13).first == grid_key_dx<3>(0,0,0));
581  BOOST_REQUIRE(cNN.get(13).second == grid_key_dx<3>(1,1,1));
582 
583 }
584 
585 
586 
587 BOOST_AUTO_TEST_SUITE_END()
588 
589 #endif /* CELLLIST_TEST_HPP_ */
This class represent an N-dimensional box.
Definition: SpaceBox.hpp:26
__device__ __host__ T getLow(int i) const
get the i-coordinate of the low bound interval of the box
Definition: Box.hpp:556
Point< dim, T > getP2() const
Get the point p2.
Definition: Box.hpp:722
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
Structure that contain a reference to a vector of particles.
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition: Point.hpp:172
This class represent an N-dimensional box.
Definition: Box.hpp:60
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:202
Class for FAST cell list implementation.
Definition: CellList.hpp:356
__device__ __host__ T getHigh(int i) const
get the high interval of the box
Definition: Box.hpp:567
Point< dim, T > getP1() const
Get the point p1.
Definition: Box.hpp:708