OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
Distribution_unit_tests.hpp
1 /*
2  * Distribution_unit_tests.hpp
3  *
4  * Created on: Feb 27, 2016
5  * Author: i-bird
6  */
7 
8 #ifndef SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_
9 #define SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_
10 
11 #include "config.h"
12 #include "SpaceDistribution.hpp"
13 #include <unistd.h>
14 
25 template<unsigned int dim, typename Distribution> void setSphereComputationCosts(Distribution & dist, grid_sm<dim, void> & gr, Point<3, float> center, float radius, size_t max_l, size_t min_l)
26 {
27  float radius2 = radius * radius;
28  float eq;
29 
30  // Position structure for the single vertex
31  float pos[dim];
32 
33  for (size_t i = 0; i < dist.getNSubSubDomains(); i++)
34  {
35  dist.getSubSubDomainPosition(i, pos);
36 
37  eq = 0;
38  for (size_t j = 0; j < dim; j++)
39  eq += (pos[j] - center.get(j)) * (pos[j] - center.get(j));
40 
41  if (eq <= radius2)
42  {
43  dist.setComputationCost(i, max_l);
44  dist.setMigrationCost(i, max_l * 2);
45  }
46  else
47  {
48  dist.setComputationCost(i, min_l);
49  dist.setMigrationCost(i, min_l * 2);
50  }
51 
52  // set Migration cost and communication cost
53  for (size_t j = 0; j < dist.getNSubSubDomainNeighbors(i); j++)
54  dist.setCommunicationCost(i, j, 1);
55  }
56 }
57 
58 BOOST_AUTO_TEST_SUITE (Distribution_test)
59 
60 BOOST_AUTO_TEST_CASE( Metis_distribution_test)
61 {
62  Vcluster & v_cl = create_vcluster();
63 
64  if (v_cl.getProcessingUnits() != 3)
65  return;
66 
68 
69  MetisDistribution<3, float> met_dist(v_cl);
70 
71  // Cartesian grid
72  size_t sz[3] = { GS_SIZE, GS_SIZE, GS_SIZE };
73 
74  // Box
75  Box<3, float> box( { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 });
76 
77  // Grid info
78  grid_sm<3, void> info(sz);
79 
80  // Set metis on test, It fix the seed (not required if we are not testing)
81  met_dist.onTest();
82 
83  // Initialize Cart graph and decompose
84 
85  met_dist.createCartGraph(info,box);
86  met_dist.decompose();
87 
88  BOOST_REQUIRE_EQUAL(met_dist.get_ndec(),1ul);
89 
91 
92  BOOST_REQUIRE(met_dist.getUnbalance() < 0.03);
93 
94  if (v_cl.getProcessUnitID() == 0)
95  {met_dist.write("vtk_metis_distribution");}
96 
97  size_t b = GS_SIZE * GS_SIZE * GS_SIZE / 5;
98 
100 
101  // Initialize the weights to 1.0
102  // not required, if we set ALL Computation,Migration,Communication cost
103 
104  // Change set some weight on the graph and re-decompose
105 
106  for (size_t k = 0; k < met_dist.getNOwnerSubSubDomains(); k++)
107  {
108  size_t i = met_dist.getOwnerSubSubDomain(k);
109 
110  if (i == 0 || i == b || i == 2*b || i == 3*b || i == 4*b)
111  met_dist.setComputationCost(i,10);
112  else
113  met_dist.setComputationCost(i,1);
114  }
115 
116  for (size_t i = 0 ; i < met_dist.getNSubSubDomains() ; i++)
117  {
118  // We also show how to set some Communication and Migration cost
119 
120  met_dist.setMigrationCost(i,1);
121 
122  for (size_t j = 0; j < met_dist.getNSubSubDomainNeighbors(i); j++)
123  met_dist.setCommunicationCost(i,j,1);
124  }
125 
126  met_dist.decompose();
127 
128  BOOST_REQUIRE_EQUAL(met_dist.get_ndec(),2ul);
129 
131 
132  BOOST_REQUIRE(met_dist.getUnbalance() < 0.06);
133 
134  if (v_cl.getProcessUnitID() == 0)
135  {met_dist.write("vtk_metis_distribution_red");}
136 
137  // check that match
138 
139  bool test;
140 
141  if (v_cl.getProcessUnitID() == 0)
142  {
143  #ifdef HAVE_OSX
144 
145  test = compare("0_vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_osx_test.vtk");
146  BOOST_REQUIRE_EQUAL(true,test);
147  test = compare("0_vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_osx_test.vtk");
148  BOOST_REQUIRE_EQUAL(true,test);
149 
150  #elif __GNUC__ == 6 && __GNUC_MINOR__ == 3
151 
152  test = compare("0_vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_test.vtk");
153  BOOST_REQUIRE_EQUAL(true,test);
154  test = compare("0_vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_test.vtk");
155  BOOST_REQUIRE_EQUAL(true,test);
156 
157  #endif
158  }
159 
160  // Copy the Metis distribution
161 
162  MetisDistribution<3, float> met_dist2(v_cl);
163 
164  met_dist2 = met_dist;
165 
166  test = (met_dist2 == met_dist);
167 
168  BOOST_REQUIRE_EQUAL(test,true);
169 
170  // We fix the size of MetisDistribution if you are gointg to change this number
171  // please check the following
172  // duplicate functions
173  // swap functions
174  // Copy constructors
175  // operator= functions
176  // operator== functions
177 
178 // BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),720ul);
179 }
180 
181 BOOST_AUTO_TEST_CASE( Parmetis_distribution_test)
182 {
183  Vcluster & v_cl = create_vcluster();
184 
185  if (v_cl.getProcessingUnits() != 3)
186  return;
187 
189 
190  ParMetisDistribution<3, float> pmet_dist(v_cl);
191 
192  // Physical domain
193  Box<3, float> box( { 0.0, 0.0, 0.0 }, { 10.0, 10.0, 10.0 });
194 
195  // Grid info
196  grid_sm<3, void> info( { GS_SIZE, GS_SIZE, GS_SIZE });
197 
198  // Initialize Cart graph and decompose
199  pmet_dist.createCartGraph(info,box);
200 
201  // First create the center of the weights distribution, check it is coherent to the size of the domain
202  Point<3, float> center( { 2.0, 2.0, 2.0 });
203 
204  // It produces a sphere of radius 2.0
205  // with high computation cost (5) inside the sphere and (1) outside
206  setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5ul, 1ul);
207 
208  // first decomposition
209  pmet_dist.decompose();
210 
211  BOOST_REQUIRE_EQUAL(pmet_dist.get_ndec(),1ul);
212 
214 
215  if (v_cl.getProcessUnitID() == 0)
216  {
217  // write the first decomposition
218  pmet_dist.write("vtk_parmetis_distribution_0");
219 
220 #ifdef HAVE_OSX
221 
222  bool test = compare(std::to_string(v_cl.getProcessUnitID()) + "_vtk_parmetis_distribution_0.vtk","src/Decomposition/Distribution/test_data/" + std::to_string(v_cl.getProcessUnitID()) + "_vtk_parmetis_distribution_0_osx_test.vtk");
223  BOOST_REQUIRE_EQUAL(true,test);
224 
225 #else
226 
227  bool test = compare(std::to_string(v_cl.getProcessUnitID()) + "_vtk_parmetis_distribution_0.vtk","src/Decomposition/Distribution/test_data/" + std::to_string(v_cl.getProcessUnitID()) + "_vtk_parmetis_distribution_0_test.vtk");
228  BOOST_REQUIRE_EQUAL(true,test);
229 
230 #endif
231  }
232 
234 
235  float stime = 0.0, etime = 10.0, tstep = 0.1;
236 
237  // Shift of the sphere at each iteration
238  Point<3, float> shift( { tstep, tstep, tstep });
239 
240  size_t iter = 1;
241  size_t n_dec = 1;
242 
243  for(float t = stime; t < etime; t = t + tstep, iter++)
244  {
245  if(t < etime/2)
246  center += shift;
247  else
248  center -= shift;
249 
250  setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5, 1);
251 
252  // With some regularity refine and write the parmetis distribution
253  if ((size_t)iter % 10 == 0)
254  {
255  pmet_dist.refine();
256  n_dec++;
257  BOOST_REQUIRE_EQUAL(pmet_dist.get_ndec(),n_dec);
258 
259  if (v_cl.getProcessUnitID() == 0)
260  {
261  std::stringstream str;
262  str << "vtk_parmetis_distribution_" << iter;
263  pmet_dist.write(str.str());
264 
265 #ifdef HAVE_OSX
266 
267  // Check
268  bool test = compare(std::to_string(v_cl.getProcessUnitID()) + "_" + str.str() + ".vtk", "src/Decomposition/Distribution/test_data/" + std::to_string(v_cl.getProcessUnitID()) + "_" + str.str() + "_osx_test.vtk");
269  BOOST_REQUIRE_EQUAL(true,test);
270 
271 #else
272 
273  // Check
274  bool test = compare(std::to_string(v_cl.getProcessUnitID()) + "_" + str.str() + ".vtk", "src/Decomposition/Distribution/test_data/" + std::to_string(v_cl.getProcessUnitID()) + "_" + str.str() + "_test.vtk");
275  BOOST_REQUIRE_EQUAL(true,test);
276 
277 #endif
278  }
279  }
280  }
281 
283 
284 // BOOST_REQUIRE_EQUAL(sizeof(ParMetisDistribution<3,float>),872ul);
285 }
286 
287 BOOST_AUTO_TEST_CASE( DistParmetis_distribution_test)
288 {
289  Vcluster & v_cl = create_vcluster();
290 
291  if (v_cl.getProcessingUnits() != 3)
292  return;
293 
295 
296  DistParMetisDistribution<3, float> pmet_dist(v_cl);
297 
298  // Physical domain
299  Box<3, float> box( { 0.0, 0.0, 0.0 }, { 10.0, 10.0, 10.0 });
300 
301  // Grid info
302  grid_sm<3, void> info( { GS_SIZE, GS_SIZE, GS_SIZE });
303 
304  // Initialize Cart graph and decompose
305  pmet_dist.createCartGraph(info,box);
306 
307  // First create the center of the weights distribution, check it is coherent to the size of the domain
308  Point<3, float> center( { 2.0, 2.0, 2.0 });
309 
310  // It produces a sphere of radius 2.0
311  // with high computation cost (5) inside the sphere and (1) outside
312  setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5ul, 1ul);
313 
314  // first decomposition
315  pmet_dist.decompose();
316 
318 
319  // write the first decomposition
320  pmet_dist.write("vtk_dist_parmetis_distribution_0");
321 
322  // Check
323  if (v_cl.getProcessUnitID() == 0)
324  {
325 
326  #ifdef HAVE_OSX
327 
328  bool test = compare("vtk_dist_parmetis_distribution_0.vtk","src/Decomposition/Distribution/test_data/vtk_dist_parmetis_distribution_0_osx_test.vtk");
329  BOOST_REQUIRE_EQUAL(true,test);
330 
331  #else
332 
333  bool test = compare("vtk_dist_parmetis_distribution_0.vtk","src/Decomposition/Distribution/test_data/vtk_dist_parmetis_distribution_0_test.vtk");
334  BOOST_REQUIRE_EQUAL(true,test);
335 
336  #endif
337 
338  }
339 
341 
342  float stime = 0.0, etime = 10.0, tstep = 0.1;
343 
344  // Shift of the sphere at each iteration
345  Point<3, float> shift( { tstep, tstep, tstep });
346 
347  size_t iter = 1;
348 
349  for(float t = stime; t < etime; t = t + tstep, iter++)
350  {
351  if(t < etime/2)
352  center += shift;
353  else
354  center -= shift;
355 
356  setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5, 1);
357 
358  // With some regularity refine and write the parmetis distribution
359  if ((size_t)iter % 10 == 0)
360  {
361  pmet_dist.refine();
362 
363  std::stringstream str;
364  str << "vtk_dist_parmetis_distribution_" << iter;
365  pmet_dist.write(str.str());
366 
367  // Check
368  if (v_cl.getProcessUnitID() == 0)
369  {
370 #ifdef HAVE_OSX
371  bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_osx_test.vtk");
372  BOOST_REQUIRE_EQUAL(true,test);
373 
374 #else
375 
376  bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_test.vtk");
377  BOOST_REQUIRE_EQUAL(true,test);
378 
379 #endif
380 
381  }
382  }
383  }
384 
386 }
387 
388 BOOST_AUTO_TEST_CASE( Space_distribution_test)
389 {
390  Vcluster & v_cl = create_vcluster();
391 
392  if (v_cl.getProcessingUnits() != 3)
393  return;
394 
396 
397  SpaceDistribution<3, float> space_dist(v_cl);
398 
399  // Physical domain
400  Box<3, float> box( { 0.0, 0.0, 0.0 }, { 10.0, 10.0, 10.0 });
401 
402  // Grid info
403  grid_sm<3, void> info( { 17, 17, 17 });
404 
405  // Initialize Cart graph and decompose
406  space_dist.createCartGraph(info,box);
407 
408  // first decomposition
409  space_dist.decompose();
410 
412 
413  if (v_cl.getProcessUnitID() == 0)
414  {
415  // write the first decomposition
416  space_dist.write("vtk_dist_space_distribution_0");
417 
418  bool test = compare(std::to_string(v_cl.getProcessUnitID()) + "_vtk_dist_space_distribution_0.vtk","src/Decomposition/Distribution/test_data/" + std::to_string(v_cl.getProcessUnitID()) + + "_vtk_dist_space_distribution_0_test.vtk");
419  BOOST_REQUIRE_EQUAL(true,test);
420  }
421 
423 }
424 
425 
426 BOOST_AUTO_TEST_SUITE_END()
427 
428 #endif /* SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_ */
size_t getProcessUnitID()
Get the process unit id.
Class that distribute sub-sub-domains across processors using an hilbert curve to divide the space...
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:22
Implementation of VCluster class.
Definition: VCluster.hpp:36
Class that distribute sub-sub-domains across processors using ParMetis Library.
const T & get(size_t i) const
Get coordinate.
Definition: Point.hpp:142
Class that distribute sub-sub-domains across processors using Metis Library.
size_t getProcessingUnits()
Get the total number of processors.