Distribution_unit_tests.hpp 11.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/*
 * Distribution_unit_tests.hpp
 *
 *  Created on: Feb 27, 2016
 *      Author: i-bird
 */

#ifndef SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_
#define SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_

jenkins's avatar
jenkins committed
11
#include "config.h"
incardon's avatar
incardon committed
12
#include "SpaceDistribution.hpp"
incardon's avatar
incardon committed
13
#include <unistd.h>
jenkins's avatar
jenkins committed
14

15
16
17
18
19
20
21
22
23
24
/*! \brief Set a sphere as high computation cost
 *
 * \param dist Distribution structure
 * \param gr grid info
 * \param center of the sphere
 * \param radius radius of the sphere
 * \param max_l maximum load of the processor
 * \param min_l minimum load of the processor
 *
 */
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
28
29
30
{
	float radius2 = radius * radius;
	float eq;

	// Position structure for the single vertex
31
	float pos[dim];
32

33
	for (size_t i = 0; i < dist.getNSubSubDomains(); i++)
34
35
36
37
	{
		dist.getSubSubDomainPosition(i, pos);

		eq = 0;
38
		for (size_t j = 0; j < dim; j++)
39
40
41
42
43
			eq += (pos[j] - center.get(j)) * (pos[j] - center.get(j));

		if (eq <= radius2)
		{
			dist.setComputationCost(i, max_l);
44
			dist.setMigrationCost(i, max_l * 2);
45
46
47
48
		}
		else
		{
			dist.setComputationCost(i, min_l);
49
			dist.setMigrationCost(i, min_l * 2);
50
51
52
		}

		// set Migration cost and communication cost
53
54
		for (size_t j = 0; j < dist.getNSubSubDomainNeighbors(i); j++)
			dist.setCommunicationCost(i, j, 1);
55
56
57
	}
}

58
BOOST_AUTO_TEST_SUITE (Distribution_test)
59
60
61

BOOST_AUTO_TEST_CASE( Metis_distribution_test)
{
62
	Vcluster & v_cl = create_vcluster();
63
64

	if (v_cl.getProcessingUnits() != 3)
65
	return;
66
67
68

	//! [Initialize a Metis Cartesian graph and decompose]

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
81
82
83
84
85
86
87

	// Set metis on test, It fix the seed (not required if we are not testing)
	met_dist.onTest();

	// Initialize Cart graph and decompose

	met_dist.createCartGraph(info,box);
	met_dist.decompose();

incardon's avatar
incardon committed
88
89
	BOOST_REQUIRE_EQUAL(met_dist.get_ndec(),1ul);

90
91
92
93
	//! [Initialize a Metis Cartesian graph and decompose]

	BOOST_REQUIRE(met_dist.getUnbalance() < 0.03);

incardon's avatar
incardon committed
94
95
	if (v_cl.getProcessUnitID() == 0)
	{met_dist.write("vtk_metis_distribution");}
96

97
	size_t b = GS_SIZE * GS_SIZE * GS_SIZE / 5;
98
99
100
101
102
103
104
105

	//! [Decomposition Metis with weights]

	// Initialize the weights to 1.0
	// not required, if we set ALL Computation,Migration,Communication cost

	// Change set some weight on the graph and re-decompose

incardon's avatar
incardon committed
106
	for (size_t k = 0; k < met_dist.getNOwnerSubSubDomains(); k++)
107
	{
incardon's avatar
incardon committed
108
109
		size_t i = met_dist.getOwnerSubSubDomain(k);

110
		if (i == 0 || i == b || i == 2*b || i == 3*b || i == 4*b)
incardon's avatar
incardon committed
111
			met_dist.setComputationCost(i,10);
112
		else
incardon's avatar
incardon committed
113
114
			met_dist.setComputationCost(i,1);
	}
115

incardon's avatar
incardon committed
116
117
	for (size_t i = 0 ; i <  met_dist.getNSubSubDomains() ; i++)
	{
118
119
120
121
		// We also show how to set some Communication and Migration cost

		met_dist.setMigrationCost(i,1);

122
123
		for (size_t j = 0; j < met_dist.getNSubSubDomainNeighbors(i); j++)
		met_dist.setCommunicationCost(i,j,1);
124
125
126
127
	}

	met_dist.decompose();

incardon's avatar
incardon committed
128
129
	BOOST_REQUIRE_EQUAL(met_dist.get_ndec(),2ul);

130
131
	//! [Decomposition Metis with weights]

Pietro Incardona's avatar
Pietro Incardona committed
132
	BOOST_REQUIRE(met_dist.getUnbalance() < 0.06);
133

incardon's avatar
incardon committed
134
135
	if (v_cl.getProcessUnitID() == 0)
	{met_dist.write("vtk_metis_distribution_red");}
136
137
138

	// check that match

incardon's avatar
incardon committed
139
140
	bool test;

incardon's avatar
incardon committed
141
142
143
	if (v_cl.getProcessUnitID() == 0)
	{
	#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
144

incardon's avatar
incardon committed
145
146
147
148
		test = compare("0_vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_osx_test.vtk");
		BOOST_REQUIRE_EQUAL(true,test);
		test = compare("0_vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_osx_test.vtk");
		BOOST_REQUIRE_EQUAL(true,test);
149

incardon's avatar
incardon committed
150
	#elif __GNUC__ == 6 && __GNUC_MINOR__ == 3
jenkins's avatar
jenkins committed
151

incardon's avatar
incardon committed
152
153
154
155
		test = compare("0_vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_test.vtk");
		BOOST_REQUIRE_EQUAL(true,test);
		test = compare("0_vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_test.vtk");
		BOOST_REQUIRE_EQUAL(true,test);
156

incardon's avatar
incardon committed
157
158
	#endif
	}
159
160
161

	// Copy the Metis distribution

162
	MetisDistribution<3, float> met_dist2(v_cl);
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

	met_dist2 = met_dist;

	test = (met_dist2 == met_dist);

	BOOST_REQUIRE_EQUAL(test,true);

	// We fix the size of MetisDistribution if you are gointg to change this number
	// please check the following
	// duplicate functions
	// swap functions
	// Copy constructors
	// operator= functions
	// operator== functions

incardon's avatar
incardon committed
178
//	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),720ul);
179
180
181
182
}

BOOST_AUTO_TEST_CASE( Parmetis_distribution_test)
{
183
	Vcluster & v_cl = create_vcluster();
184
185

	if (v_cl.getProcessingUnits() != 3)
186
	return;
187
188
189

	//! [Initialize a ParMetis Cartesian graph and decompose]

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
199
200
201

	// Initialize Cart graph and decompose
	pmet_dist.createCartGraph(info,box);

	// 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
205
206
207
208
209
210

	// It produces a sphere of radius 2.0
	// with high computation cost (5) inside the sphere and (1) outside
	setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5ul, 1ul);

	// first decomposition
	pmet_dist.decompose();

incardon's avatar
incardon committed
211
212
	BOOST_REQUIRE_EQUAL(pmet_dist.get_ndec(),1ul);

213
214
	//! [Initialize a ParMetis Cartesian graph and decompose]

Pietro Incardona's avatar
Pietro Incardona committed
215
	if (v_cl.getProcessUnitID() == 0)
216
217
	{
		// write the first decomposition
Pietro Incardona's avatar
Pietro Incardona committed
218
		pmet_dist.write("vtk_parmetis_distribution_0");
219

jenkins's avatar
jenkins committed
220
221
222
#ifdef HAVE_OSX

		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);
jenkins's avatar
jenkins committed
224
225
226

#else

incardon's avatar
incardon committed
227
228
        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");
        BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
229
230

#endif
231
232
233
234
235
236
237
	}

	//! [refine with parmetis the decomposition]

	float stime = 0.0, etime = 10.0, tstep = 0.1;

	// Shift of the sphere at each iteration
238
	Point<3, float> shift( { tstep, tstep, tstep });
239
240

	size_t iter = 1;
incardon's avatar
incardon committed
241
	size_t n_dec = 1;
242
243
244
245

	for(float t = stime; t < etime; t = t + tstep, iter++)
	{
		if(t < etime/2)
246
		center += shift;
247
		else
248
		center -= shift;
249
250
251
252
253
254
255

		setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5, 1);

		// With some regularity refine and write the parmetis distribution
		if ((size_t)iter % 10 == 0)
		{
			pmet_dist.refine();
incardon's avatar
incardon committed
256
257
			n_dec++;
			BOOST_REQUIRE_EQUAL(pmet_dist.get_ndec(),n_dec);
258
259
260
261
262

			if (v_cl.getProcessUnitID() == 0)
			{
				std::stringstream str;
				str << "vtk_parmetis_distribution_" << iter;
Pietro Incardona's avatar
Pietro Incardona committed
263
				pmet_dist.write(str.str());
264

Pietro Incardona's avatar
Pietro Incardona committed
265
266
#ifdef HAVE_OSX

267
				// Check
jenkins's avatar
jenkins committed
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);
Pietro Incardona's avatar
Pietro Incardona committed
270
271
272
273
274
275
276
277

#else

				// Check
				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");
				BOOST_REQUIRE_EQUAL(true,test);

#endif
278
279
280
281
282
			}
		}
	}

	//! [refine with parmetis the decomposition]
Pietro Incardona's avatar
Pietro Incardona committed
283

incardon's avatar
incardon committed
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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

	//! [Initialize a ParMetis Cartesian graph and decompose]

	DistParMetisDistribution<3, float> pmet_dist(v_cl);

	// Physical domain
	Box<3, float> box( { 0.0, 0.0, 0.0 }, { 10.0, 10.0, 10.0 });

	// Grid info
	grid_sm<3, void> info( { GS_SIZE, GS_SIZE, GS_SIZE });

	// Initialize Cart graph and decompose
	pmet_dist.createCartGraph(info,box);

	// First create the center of the weights distribution, check it is coherent to the size of the domain
	Point<3, float> center( { 2.0, 2.0, 2.0 });

	// It produces a sphere of radius 2.0
	// with high computation cost (5) inside the sphere and (1) outside
	setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5ul, 1ul);

	// first decomposition
	pmet_dist.decompose();

	//! [Initialize a ParMetis Cartesian graph and decompose]

incardon's avatar
incardon committed
319
320
	// write the first decomposition
	pmet_dist.write("vtk_dist_parmetis_distribution_0");
jenkins's avatar
jenkins committed
321

incardon's avatar
incardon committed
322
323
324
	// Check
	if (v_cl.getProcessUnitID() == 0)
	{
jenkins's avatar
jenkins committed
325

incardon's avatar
incardon committed
326
	#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
327

incardon's avatar
incardon committed
328
329
		bool test = compare("vtk_dist_parmetis_distribution_0.vtk","src/Decomposition/Distribution/test_data/vtk_dist_parmetis_distribution_0_osx_test.vtk");
		BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
330

incardon's avatar
incardon committed
331
	#else
incardon's avatar
incardon committed
332

incardon's avatar
incardon committed
333
334
		bool test = compare("vtk_dist_parmetis_distribution_0.vtk","src/Decomposition/Distribution/test_data/vtk_dist_parmetis_distribution_0_test.vtk");
		BOOST_REQUIRE_EQUAL(true,test);
incardon's avatar
incardon committed
335

incardon's avatar
incardon committed
336
337
338
	#endif

	}
339

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
	//! [refine with dist_parmetis the decomposition]

	float stime = 0.0, etime = 10.0, tstep = 0.1;

	// Shift of the sphere at each iteration
	Point<3, float> shift( { tstep, tstep, tstep });

	size_t iter = 1;

	for(float t = stime; t < etime; t = t + tstep, iter++)
	{
		if(t < etime/2)
		center += shift;
		else
		center -= shift;

		setSphereComputationCosts(pmet_dist, info, center, 2.0f, 5, 1);

		// With some regularity refine and write the parmetis distribution
		if ((size_t)iter % 10 == 0)
		{
			pmet_dist.refine();

			std::stringstream str;
			str << "vtk_dist_parmetis_distribution_" << iter;
Pietro Incardona's avatar
Pietro Incardona committed
365
			pmet_dist.write(str.str());
366
367
368
369

			// Check
			if (v_cl.getProcessUnitID() == 0)
			{
jenkins's avatar
jenkins committed
370
371
#ifdef HAVE_OSX
				bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_osx_test.vtk");
372
				BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
373
374
375

#else

Pietro Incardona's avatar
Pietro Incardona committed
376
377
				bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_test.vtk");
				BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
378
379
380

#endif

381
382
383
384
385
			}
		}
	}

	//! [refine with dist_parmetis the decomposition]
386
387
}

incardon's avatar
incardon committed
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
BOOST_AUTO_TEST_CASE( Space_distribution_test)
{
	Vcluster & v_cl = create_vcluster();

	if (v_cl.getProcessingUnits() != 3)
		return;

	//! [Initialize a Space Cartesian graph and decompose]

	SpaceDistribution<3, float> space_dist(v_cl);

	// Physical domain
	Box<3, float> box( { 0.0, 0.0, 0.0 }, { 10.0, 10.0, 10.0 });

	// Grid info
	grid_sm<3, void> info( { 17, 17, 17 });

	// Initialize Cart graph and decompose
	space_dist.createCartGraph(info,box);

	// first decomposition
	space_dist.decompose();

	//! [Initialize a Space Cartesian graph and decompose]

	if (v_cl.getProcessUnitID() == 0)
	{
		// write the first decomposition
		space_dist.write("vtk_dist_space_distribution_0");

		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");
		BOOST_REQUIRE_EQUAL(true,test);
	}

	//! [refine with dist_parmetis the decomposition]
}

425

426
427
428
BOOST_AUTO_TEST_SUITE_END()

#endif /* SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_ */