Distribution_unit_tests.hpp 11.3 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
	met_dist.write("vtk_metis_distribution");
95

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

	//! [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
105
	for (size_t k = 0; k < met_dist.getNOwnerSubSubDomains(); k++)
106
	{
incardon's avatar
incardon committed
107
108
		size_t i = met_dist.getOwnerSubSubDomain(k);

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

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

		met_dist.setMigrationCost(i,1);

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

	met_dist.decompose();

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

129
130
	//! [Decomposition Metis with weights]

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

incardon's avatar
incardon committed
133
	met_dist.write("vtk_metis_distribution_red");
134
135
136

	// check that match

incardon's avatar
incardon committed
137
138
	bool test;

139
#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
140

incardon's avatar
incardon committed
141
	test = compare("0_vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_osx_test.vtk");
142
	BOOST_REQUIRE_EQUAL(true,test);
incardon's avatar
incardon committed
143
	test = compare("0_vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_osx_test.vtk");
144
	BOOST_REQUIRE_EQUAL(true,test);
145

incardon's avatar
incardon committed
146
#elif __GNUC__ == 6 && __GNUC_MINOR__ == 3
jenkins's avatar
jenkins committed
147

incardon's avatar
incardon committed
148
	test = compare("0_vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_test.vtk");
149
	BOOST_REQUIRE_EQUAL(true,test);
incardon's avatar
incardon committed
150
	test = compare("0_vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_test.vtk");
151
152
	BOOST_REQUIRE_EQUAL(true,test);

153
#endif
154
155
156

	// Copy the Metis distribution

157
	MetisDistribution<3, float> met_dist2(v_cl);
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

	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
173
//	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),720ul);
174
175
176
177
}

BOOST_AUTO_TEST_CASE( Parmetis_distribution_test)
{
178
	Vcluster & v_cl = create_vcluster();
179
180

	if (v_cl.getProcessingUnits() != 3)
181
	return;
182
183
184

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

185
	ParMetisDistribution<3, float> pmet_dist(v_cl);
186
187

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

	// Grid info
191
	grid_sm<3, void> info( { GS_SIZE, GS_SIZE, GS_SIZE });
192
193
194
195
196

	// 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
197
	Point<3, float> center( { 2.0, 2.0, 2.0 });
198
199
200
201
202
203
204
205

	// 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
206
207
	BOOST_REQUIRE_EQUAL(pmet_dist.get_ndec(),1ul);

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

Pietro Incardona's avatar
Pietro Incardona committed
210
	if (v_cl.getProcessUnitID() == 0)
211
212
	{
		// write the first decomposition
Pietro Incardona's avatar
Pietro Incardona committed
213
		pmet_dist.write("vtk_parmetis_distribution_0");
214

jenkins's avatar
jenkins committed
215
216
217
#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");
218
		BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
219
220
221

#else

incardon's avatar
incardon committed
222
223
        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
224
225

#endif
226
227
228
229
230
231
232
	}

	//! [refine with parmetis the decomposition]

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

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

	size_t iter = 1;
incardon's avatar
incardon committed
236
	size_t n_dec = 1;
237
238
239
240

	for(float t = stime; t < etime; t = t + tstep, iter++)
	{
		if(t < etime/2)
241
		center += shift;
242
		else
243
		center -= shift;
244
245
246
247
248
249
250

		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
251
252
			n_dec++;
			BOOST_REQUIRE_EQUAL(pmet_dist.get_ndec(),n_dec);
253
254
255
256
257

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

Pietro Incardona's avatar
Pietro Incardona committed
260
261
#ifdef HAVE_OSX

262
				// Check
jenkins's avatar
jenkins committed
263
				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");
264
				BOOST_REQUIRE_EQUAL(true,test);
Pietro Incardona's avatar
Pietro Incardona committed
265
266
267
268
269
270
271
272

#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
273
274
275
276
277
			}
		}
	}

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

incardon's avatar
incardon committed
279
//	BOOST_REQUIRE_EQUAL(sizeof(ParMetisDistribution<3,float>),872ul);
280
281
}

282
BOOST_AUTO_TEST_CASE( DistParmetis_distribution_test)
283
{
284
	Vcluster & v_cl = create_vcluster();
285
286

	if (v_cl.getProcessingUnits() != 3)
287
		return;
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

	//! [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
314
315
	// write the first decomposition
	pmet_dist.write("vtk_dist_parmetis_distribution_0");
jenkins's avatar
jenkins committed
316

incardon's avatar
incardon committed
317
318
319
	// Check
	if (v_cl.getProcessUnitID() == 0)
	{
jenkins's avatar
jenkins committed
320

incardon's avatar
incardon committed
321
	#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
322

incardon's avatar
incardon committed
323
324
		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
325

incardon's avatar
incardon committed
326
	#else
incardon's avatar
incardon 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_test.vtk");
		BOOST_REQUIRE_EQUAL(true,test);
incardon's avatar
incardon committed
330

incardon's avatar
incardon committed
331
332
333
	#endif

	}
334

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
	//! [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
360
			pmet_dist.write(str.str());
361
362
363
364

			// Check
			if (v_cl.getProcessUnitID() == 0)
			{
jenkins's avatar
jenkins committed
365
366
#ifdef HAVE_OSX
				bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_osx_test.vtk");
367
				BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
368
369
370

#else

Pietro Incardona's avatar
Pietro Incardona committed
371
372
				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
373
374
375

#endif

376
377
378
379
380
			}
		}
	}

	//! [refine with dist_parmetis the decomposition]
381
382
}

incardon's avatar
incardon committed
383
384
385
386
387
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
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]
}

420
421
void print_test_v(std::string test, size_t sz)
{
422
	if (create_vcluster().getProcessUnitID() == 0)
423
424
425
		std::cout << test << " " << sz << "\n";
}

426
427
428
BOOST_AUTO_TEST_SUITE_END()

#endif /* SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_ */