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