OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
CartDecomposition_unit_test.cpp
1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
3 
4 #include "Decomposition/CartDecomposition.hpp"
5 #include "util/mathutil.hpp"
6 
7 BOOST_AUTO_TEST_SUITE (CartDecomposition_test)
8 
9 #define SUB_UNIT_FACTOR 1024
10 
11 void setComputationCosts(CartDecomposition<2, float> &dec, size_t n_v, Point<2, float> center, float radius, size_t weight_h, size_t weight_l)
12 {
13  float radius2 = pow(radius, 2);
14  float eq;
15 
16  // Position structure for the single vertex
17  float pos[2];
18 
19  for (size_t i = 0; i < n_v; i++)
20  {
21  dec.getSubSubDomainPosition(i, pos);
22 
23  eq = pow((pos[0] - center.get(0)), 2) + pow((pos[1] - center.get(1)), 2);
24 
25  if (eq <= radius2)
26  dec.setSubSubDomainComputationCost(i, weight_h);
27  else
28  dec.setSubSubDomainComputationCost(i, weight_l);
29  }
30 }
31 
32 void setComputationCosts3D(CartDecomposition<3, float> &dec, size_t n_v, Point<3, float> center, float radius, size_t weight_h, size_t weight_l)
33 {
34  float radius2 = radius * radius;
35  float eq;
36 
37  // Position structure for the single vertex
38  float pos[3];
39 
40  for (size_t i = 0; i < n_v; i++)
41  {
42  dec.getSubSubDomainPosition(i, pos);
43 
44  eq = pow((pos[0] - center.get(0)), 2) + pow((pos[1] - center.get(1)), 2) + pow((pos[2] - center.get(2)), 2);
45 
46  if (eq <= radius2)
47  dec.setSubSubDomainComputationCost(i, weight_h);
48  else
49  dec.setSubSubDomainComputationCost(i, weight_l);
50  }
51 }
52 
53 
54 
55 BOOST_AUTO_TEST_CASE( CartDecomposition_non_periodic_test)
56 {
57  // Vcluster
58  Vcluster & vcl = create_vcluster();
59 
61 
62  // Physical domain
63  Box<3, float> box( { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 });
64  size_t div[3];
65 
66  // Get the number of processor and calculate the number of sub-domain
67  // for each processor (SUB_UNIT_FACTOR=64)
68  size_t n_proc = vcl.getProcessingUnits();
69  size_t n_sub = n_proc * SUB_UNIT_FACTOR;
70 
71  // Set the number of sub-domains on each dimension (in a scalable way)
72  for (int i = 0; i < 3; i++)
73  { div[i] = openfpm::math::round_big_2(pow(n_sub,1.0/3));}
74 
75  // Define ghost
76  Ghost<3, float> g(0.01);
77 
78  // Boundary conditions
79  size_t bc[] = { NON_PERIODIC, NON_PERIODIC, NON_PERIODIC };
80 
81  // Decompose
82  dec.setParameters(div,box,bc,g);
83  dec.decompose();
84 
85  // For each calculated ghost box
86  for (size_t i = 0; i < dec.getNIGhostBox(); i++)
87  {
89  size_t proc = dec.getIGhostBoxProcessor(i);
90 
91  // sample one point inside the box
92  Point<3,float> p = b.rnd();
93 
94  // Check that ghost_processorsID return that processor number
96 
97  bool found = false;
98 
99  for (size_t j = 0; j < pr.size(); j++)
100  {
101  if (pr.get(j) == proc)
102  { found = true; break;}
103  }
104 
105  if (found == false)
106  {
108  }
109 
110  BOOST_REQUIRE_EQUAL(found,true);
111  }
112 
113  // Check the consistency
114 
115  bool val = dec.check_consistency();
116  BOOST_REQUIRE_EQUAL(val,true);
117 
118  // We duplicate the decomposition
120  dec2.check_consistency();
121 
122  // check that dec and dec2 contain the same information
123  bool ret = dec.is_equal(dec2);
124 
125  // We check if the two decomposition are equal
126  BOOST_REQUIRE_EQUAL(ret,true);
127 
128  // We duplicate the decomposition redefining the ghost
129 
130  // Define ghost
131  Ghost<3, float> g3(0.005);
132 
133  // We duplicate the decomposition redefining the ghost
134  CartDecomposition<3, float> dec3 = dec.duplicate(g3);
135 
136  ret = dec3.check_consistency();
137  BOOST_REQUIRE_EQUAL(ret,true);
138 
139  // Check that dec3 is equal to dec2 with the exception of the ghost part
140  ret = dec3.is_equal_ng(dec2);
141  BOOST_REQUIRE_EQUAL(ret,true);
142 }
143 
144 BOOST_AUTO_TEST_CASE( CartDecomposition_periodic_test)
145 {
146  // Vcluster
147  Vcluster & vcl = create_vcluster();
148 
151 
152  // Physical domain
153  Box<3, float> box( { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 });
154  size_t div[3];
155 
156  // Get the number of processor and calculate the number of sub-domain
157  // for each processor (SUB_UNIT_FACTOR=64)
158  size_t n_proc = vcl.getProcessingUnits();
159  size_t n_sub = n_proc * SUB_UNIT_FACTOR;
160 
161  // Set the number of sub-domains on each dimension (in a scalable way)
162  for (int i = 0; i < 3; i++)
163  { div[i] = openfpm::math::round_big_2(pow(n_sub,1.0/3));}
164 
165  // Define ghost
166  Ghost<3, float> g(0.01);
167 
168  // Boundary conditions
169  size_t bc[] = { PERIODIC, PERIODIC, PERIODIC };
170 
171  // Decompose
172  dec.setParameters(div,box,bc,g);
173  dec.decompose();
174 
176 
177  // For each calculated ghost box
178  for (size_t i = 0; i < dec.getNIGhostBox(); i++)
179  {
180  SpaceBox<3,float> b = dec.getIGhostBox(i);
181  size_t proc = dec.getIGhostBoxProcessor(i);
182 
183  // sample one point inside the box
184  Point<3,float> p = b.rnd();
185 
186  // Check that ghost_processorsID return that processor number
188 
189  bool found = false;
190 
191  for (size_t j = 0; j < pr.size(); j++)
192  {
193  if (pr.get(j) == proc)
194  { found = true; break;}
195  }
196 
197  if (found == false)
198  {
200  }
201 
202  BOOST_REQUIRE_EQUAL(found,true);
203  }
204 
205  // Check the consistency
206  bool val = dec.check_consistency();
207  BOOST_REQUIRE_EQUAL(val,true);
208 
209  // We duplicate the decomposition
211  dec2.check_consistency();
212 
213  bool ret = dec.is_equal(dec2);
214 
215  // We check if the two decomposition are equal
216  BOOST_REQUIRE_EQUAL(ret,true);
217 
218  // check that dec and dec2 contain the same information
219 
220  // We duplicate the decomposition redefining the ghost
221 
222  // Define ghost
223  Ghost<3, float> g3(0.005);
224 
225  // We duplicate the decomposition refefining the ghost
226  CartDecomposition<3, float> dec3 = dec.duplicate(g3);
227 
228  ret = dec3.check_consistency();
229  BOOST_REQUIRE_EQUAL(ret,true);
230 
231  // Check that g3 is equal to dec2 with the exception of the ghost part
232  ret = dec3.is_equal_ng(dec2);
233  BOOST_REQUIRE_EQUAL(ret,true);
234 }
235 
236 
238 
239 BOOST_AUTO_TEST_CASE( CartDecomposition_ext_non_periodic_test)
240 {
241  // Vcluster
242  Vcluster & vcl = create_vcluster();
243 
245 
246  // Physical domain
247  Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
248  size_t div[3];
249 
250  // Get the number of processor and calculate the number of sub-domain
251  // for each processor (SUB_UNIT_FACTOR=64)
252  size_t n_proc = vcl.getProcessingUnits();
253  size_t n_sub = n_proc * SUB_UNIT_FACTOR;
254 
255  // Set the number of sub-domains on each dimension (in a scalable way)
256  for (int i = 0 ; i < 3 ; i++)
257  {div[i] = openfpm::math::round_big_2(pow(n_sub,1.0/3));}
258 
259  // Define ghost
260  Ghost<3,float> g(0.01);
261 
262  // Boundary conditions
263  size_t bc[] = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
264 
265  // Decompose
266  dec.setParameters(div,box,bc,g);
267  dec.decompose();
268 
270 
271  Box<3,float> box_ext({-0.1,-0.1,-0.1},{1.1,1.1,1.1});
272 
273  // Use the old decomposition to extend on a bigger domain
274  CartDecomposition_ext<3,float> dec_ext(vcl);
275 
276  dec_ext.setParameters(dec,g,box_ext);
277 
279 
280  // Check the new decomposition is fully contained in the new one, and there are
281  // box not fully contained i the old box
282 
283  BOOST_REQUIRE_EQUAL(dec_ext.getNSubDomain(),dec.getNSubDomain());
284 
285  double volume = 0.0;
286  for (size_t i = 0; i < dec_ext.getNSubDomain() ; i++)
287  {
288  volume += dec_ext.getSubDomain(i).getVolume();
289  BOOST_REQUIRE_EQUAL(dec_ext.getSubDomain(i).isContained(dec.getSubDomain(i)),true);
290  }
291 
292  vcl.sum(volume);
293  vcl.execute();
294 
295  BOOST_REQUIRE_CLOSE(volume,1.728,0.0001);
296 
297  BOOST_REQUIRE_EQUAL(dec.getNNProcessors(),dec_ext.getNNProcessors());
298 
299  double volume_g = 0.0;
300  double volume_ge = 0.0;
301  for (size_t p = 0; p < dec.getNNProcessors(); p++)
302  {
303  BOOST_REQUIRE_EQUAL(dec.getProcessorNEGhost(p),dec_ext.getProcessorNEGhost(p));
304  for (size_t i = 0; i < dec.getProcessorNEGhost(p); i++)
305  {
306  volume_g += dec.getProcessorEGhostBox(p,i).getVolume();
307  volume_ge += dec_ext.getProcessorEGhostBox(p,i).getVolume();
308 
309  BOOST_REQUIRE_EQUAL(dec_ext.getProcessorEGhostBox(p,i).isContained(dec_ext.getProcessorEGhostBox(p,i)),true);
310  }
311  }
312 
313  vcl.sum(volume_g);
314  vcl.sum(volume_ge);
315  vcl.execute();
316 
317  if (vcl.getProcessingUnits() > 1)
318  {
319  BOOST_REQUIRE(volume_ge > volume_g*1.05);
320  }
321 
322  volume_g = 0.0;
323  volume_ge = 0.0;
324  for (size_t p = 0; p < dec.getNNProcessors(); p++)
325  {
326  for (size_t i = 0; i< dec.getProcessorNIGhost(p); i++)
327  {
328  volume_g += dec.getProcessorIGhostBox(p,i).getVolume();
329  volume_ge += dec_ext.getProcessorIGhostBox(p,i).getVolume();
330  BOOST_REQUIRE_EQUAL(dec_ext.getProcessorIGhostBox(p,i).isContained(dec.getProcessorIGhostBox(p,i)),true);
331  }
332  }
333 
334  vcl.sum(volume_g);
335  vcl.sum(volume_ge);
336  vcl.execute();
337 
338  if (vcl.getProcessingUnits() > 1)
339  {
340  BOOST_REQUIRE(volume_ge > volume_g*1.05);
341  }
342 }
343 
344 
345 BOOST_AUTO_TEST_CASE( CartDecomposition_non_periodic_test_dist_grid)
346 {
347  // Vcluster
348  Vcluster & vcl = create_vcluster();
349 
351 
352  // Physical domain
353  Box<3, float> box( { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 });
354  size_t div[3];
355  size_t div_sub[3];
356 
357  // Get the number of processor and calculate the number of sub-domain
358  // for each processor (SUB_UNIT_FACTOR=64)
359  size_t n_proc = vcl.getProcessingUnits();
360  size_t n_sub = n_proc * SUB_UNIT_FACTOR*4*4*4;
361 
362  // Set the number of sub-domains on each dimension (in a scalable way)
363  for (int i = 0; i < 3; i++)
364  {div[i] = openfpm::math::round_big_2(pow(n_sub,1.0/3));}
365 
366  // create a sub_distribution grid
367  for (int i = 0; i < 3; i++)
368  {div_sub[i] = div[i] / 4;}
369 
370  grid_sm<3,void> gsub(div_sub);
371 
372  // Define ghost
373  Ghost<3, float> g(0.01);
374 
375  // Boundary conditions
376  size_t bc[] = { NON_PERIODIC, NON_PERIODIC, NON_PERIODIC };
377 
378  // Decompose
379  dec.setParameters(div,box,bc,g,gsub);
380  dec.decompose();
381  dec.write("Test_sub_dist2");
382 
383  // For each calculated ghost box
384  for (size_t i = 0; i < dec.getNIGhostBox(); i++)
385  {
386  SpaceBox<3,float> b = dec.getIGhostBox(i);
387  size_t proc = dec.getIGhostBoxProcessor(i);
388 
389  // sample one point inside the box
390  Point<3,float> p = b.rnd();
391 
392  // Check that ghost_processorsID return that processor number
394 
395  bool found = false;
396 
397  for (size_t j = 0; j < pr.size(); j++)
398  {
399  if (pr.get(j) == proc)
400  { found = true; break;}
401  }
402 
403  if (found == false)
404  {
406  }
407 
408  BOOST_REQUIRE_EQUAL(found,true);
409  }
410 
411  // Check the consistency
412 
413  bool val = dec.check_consistency();
414  BOOST_REQUIRE_EQUAL(val,true);
415 }
416 
417 BOOST_AUTO_TEST_CASE( CartDecomposition_nsub_algo_functions_test)
418 {
419  size_t n_sub = 64*2;
420  size_t div[3];
421 
422  nsub_to_div2<3>(div,n_sub,3);
423 
424  BOOST_REQUIRE_EQUAL(div[0],8ul);
425  BOOST_REQUIRE_EQUAL(div[1],8ul);
426  BOOST_REQUIRE_EQUAL(div[2],8ul);
427 
428  nsub_to_div2<3>(div,n_sub,2);
429 
430  BOOST_REQUIRE_EQUAL(div[0],16ul);
431  BOOST_REQUIRE_EQUAL(div[1],16ul);
432  BOOST_REQUIRE_EQUAL(div[2],1ul);
433 
434  nsub_to_div2<3>(div,n_sub,1);
435 
436  BOOST_REQUIRE_EQUAL(div[0],128ul);
437  BOOST_REQUIRE_EQUAL(div[1],1ul);
438  BOOST_REQUIRE_EQUAL(div[2],1ul);
439 
440  n_sub = 64*3;
441  nsub_to_div<3>(div,n_sub,3);
442 
443  BOOST_REQUIRE_EQUAL(div[0],5ul);
444  BOOST_REQUIRE_EQUAL(div[1],5ul);
445  BOOST_REQUIRE_EQUAL(div[2],5ul);
446 
447  nsub_to_div<3>(div,n_sub,2);
448 
449  BOOST_REQUIRE_EQUAL(div[0],13ul);
450  BOOST_REQUIRE_EQUAL(div[1],13ul);
451  BOOST_REQUIRE_EQUAL(div[2],1ul);
452 
453  nsub_to_div<3>(div,n_sub,1);
454 
455  BOOST_REQUIRE_EQUAL(div[0],192ul);
456  BOOST_REQUIRE_EQUAL(div[1],1ul);
457  BOOST_REQUIRE_EQUAL(div[2],1ul);
458 
459  // Test high dimension cart decomposition subdivision
460 
461  Box<50,double> domain;
462  size_t bc[50];
463  Ghost<50,double> ghost(0.01);
464 
465  for(size_t i = 0 ; i < 50 ; i++)
466  {
467  domain.setLow(i,0.0);
468  domain.setHigh(i,1.0);
469  bc[i] = NON_PERIODIC;
470  }
471 
472  CartDecomposition<50,double> dec(create_vcluster());
473 
474  dec.setGoodParameters(domain,bc,ghost,64);
475 
476  size_t div2[50];
477  dec.getParameters(div2);
478 
479  auto & v_cl = create_vcluster();
480  if (v_cl.size() == 1)
481  {
482  for (size_t i = 0 ; i < 50 ; i++)
483  {
484  if (i < 6)
485  {BOOST_REQUIRE_EQUAL(div2[i],2ul);}
486  else
487  {BOOST_REQUIRE_EQUAL(div2[i],1ul);}
488  }
489  }
490 
491  if (v_cl.size() == 2)
492  {
493  for (size_t i = 0 ; i < 50 ; i++)
494  {
495  if (i < 7)
496  {BOOST_REQUIRE_EQUAL(div2[i],2ul);}
497  else
498  {BOOST_REQUIRE_EQUAL(div2[i],1ul);}
499  }
500  }
501 
502  if (v_cl.size() == 3)
503  {
504  for (size_t i = 0 ; i < 50 ; i++)
505  {
506  if (i < 2)
507  {BOOST_REQUIRE_EQUAL(div2[i],13ul);}
508  else
509  {BOOST_REQUIRE_EQUAL(div2[i],1ul);}
510  }
511  }
512 
513  if (v_cl.size() == 4)
514  {
515  for (size_t i = 0 ; i < 50 ; i++)
516  {
517  if (i < 8)
518  {BOOST_REQUIRE_EQUAL(div2[i],2ul);}
519  else
520  {BOOST_REQUIRE_EQUAL(div2[i],1ul);}
521  }
522  }
523 
524  if (v_cl.size() == 5)
525  {
526  for (size_t i = 0 ; i < 50 ; i++)
527  {
528  if (i < 8)
529  {BOOST_REQUIRE_EQUAL(div2[i],2ul);}
530  else
531  {BOOST_REQUIRE_EQUAL(div2[i],1ul);}
532  }
533  }
534 
535  if (v_cl.size() == 6)
536  {
537  for (size_t i = 0 ; i < 50 ; i++)
538  {
539  if (i < 3)
540  {BOOST_REQUIRE_EQUAL(div2[i],7ul);}
541  else
542  {BOOST_REQUIRE_EQUAL(div2[i],1ul);}
543  }
544  }
545 }
546 
547 BOOST_AUTO_TEST_SUITE_END()
548 
size_t getNIGhostBox() const
Return the total number of the calculated internal ghost boxes.
Definition: ie_ghost.hpp:673
void sum(T &num)
Sum the numbers across all processors and get the result.
void setGoodParameters(::Box< dim, T > domain_, const size_t(&bc)[dim], const Ghost< dim, T > &ghost, size_t dec_gran, const grid_sm< dim, void > &sec_dist=grid_sm< dim, void >())
Set the best parameters for the decomposition.
This class represent an N-dimensional box.
Definition: SpaceBox.hpp:26
bool is_equal(CartDecomposition< dim, T, Memory > &cart)
Check if the CartDecomposition contain the same information.
void getParameters(size_t(&div_)[dim])
return the parameters of the decomposition
This class decompose a space into sub-sub-domains and distribute them across processors.
const ::Box< dim, T > & getProcessorIGhostBox(size_t id, size_t j) const
Get the j Internal ghost box for one processor.
Definition: ie_ghost.hpp:555
void execute()
Execute all the requests.
size_t getIGhostBoxProcessor(size_t b_id) const
Given the internal ghost box id, it return the near processor at witch belong or the near processor t...
Definition: ie_ghost.hpp:698
void decompose()
Start decomposition.
void setParameters(const size_t(&div_)[dim],::Box< dim, T > domain_, const size_t(&bc)[dim], const Ghost< dim, T > &ghost, const grid_sm< dim, void > &sec_dist=grid_sm< dim, void >())
Set the parameter of the decomposition.
size_t getNNProcessors() const
Get the number of Near processors.
bool check_consistency()
function to check the consistency of the information of the decomposition
size_t getProcessorNEGhost(size_t id) const
Get the number of External ghost boxes for one processor id.
Definition: ie_ghost.hpp:543
void setHigh(int i, T val)
set the high interval of the box
Definition: Box.hpp:467
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
const ::Box< dim, T > & getProcessorEGhostBox(size_t id, size_t j) const
Get the j External ghost box.
Definition: ie_ghost.hpp:567
const openfpm::vector< size_t > ghost_processorID(const Point< dim, T > &p, const int opt=MULTIPLE)
Given a position it return if the position belong to any neighborhood processor ghost (Internal ghost...
Definition: ie_ghost.hpp:828
void getSubSubDomainPosition(size_t id, T(&pos)[dim])
function that return the position of the cell in the space
Definition: Ghost.hpp:39
Implementation of VCluster class.
Definition: VCluster.hpp:36
This class decompose a space into sub-sub-domains and distribute them across processors.
size_t getProcessorNIGhost(size_t id) const
Get the number of Internal ghost boxes for one processor.
Definition: ie_ghost.hpp:532
size_t getNSubDomain()
Get the number of local sub-domains.
SpaceBox< dim, T > getSubDomain(size_t lc)
Get the local sub-domain.
class to select the returned id by ghost_processorID
CartDecomposition< dim, T, Memory, Distribution > duplicate(const Ghost< dim, T > &g) const
It create another object that contain the same decomposition information but with different ghost box...
const T & get(size_t i) const
Get coordinate.
Definition: Point.hpp:142
void setLow(int i, T val)
set the low interval of the box
Definition: Box.hpp:456
bool write(std::string output) const
Write the decomposition as VTK file.
Declaration grid_sm.
Definition: grid_sm.hpp:71
bool is_equal_ng(CartDecomposition< dim, T, Memory > &cart)
Check if the CartDecomposition contain the same information with the exception of the ghost part It i...
void setSubSubDomainComputationCost(size_t id, size_t weight)
Function that set the computational cost for a of a sub-sub domain.
const ::Box< dim, T > & getIGhostBox(size_t b_id) const
Given the internal ghost box id, it return the internal ghost box.
Definition: ie_ghost.hpp:685
size_t getProcessingUnits()
Get the total number of processors.
Point< dim, T > rnd()
Generate a random point inside the box.
Definition: SpaceBox.hpp:209