Distribution_unit_tests.hpp 11 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

	if (v_cl.getProcessUnitID() != 0)
68
	return;
69
70
71

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

72
	MetisDistribution<3, float> met_dist(v_cl);
73
74

	// Cartesian grid
75
	size_t sz[3] = { GS_SIZE, GS_SIZE, GS_SIZE };
76
77

	// Box
78
	Box<3, float> box( { 0.0, 0.0, 0.0 }, { 1.0, 1.0, 1.0 });
79
80

	// Grid info
81
	grid_sm<3, void> info(sz);
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

	// 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();

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

	BOOST_REQUIRE(met_dist.getUnbalance() < 0.03);

	met_dist.write("vtk_metis_distribution.vtk");

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

	//! [Decomposition Metis with weights]

	// Initialize the weights to 1.0
	// not required, if we set ALL Computation,Migration,Communication cost
	met_dist.initWeights();

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

107
	for (size_t i = 0; i < met_dist.getNSubSubDomains(); i++)
108
109
	{
		if (i == 0 || i == b || i == 2*b || i == 3*b || i == 4*b)
110
		met_dist.setComputationCost(i,10);
111
		else
112
		met_dist.setComputationCost(i,1);
113
114
115
116
117

		// We also show how to set some Communication and Migration cost

		met_dist.setMigrationCost(i,1);

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

	met_dist.decompose();

	//! [Decomposition Metis with weights]

Pietro Incardona's avatar
Pietro Incardona committed
126
	BOOST_REQUIRE(met_dist.getUnbalance() < 0.06);
127
128
129
130
131

	met_dist.write("vtk_metis_distribution_red.vtk");

	// check that match

132
#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
133

incardon's avatar
incardon committed
134
135
	bool test = true;

incardon's avatar
incardon committed
136
137
138
139
140
141
	// If we change compiler we have to change files (no thanks)

//	bool test = compare("vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_osx_test.vtk");
//	BOOST_REQUIRE_EQUAL(true,test);
//	test = compare("vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_osx_test.vtk");
//	BOOST_REQUIRE_EQUAL(true,test);
142

143
#else
jenkins's avatar
jenkins committed
144

145
	bool test = compare("vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_test.vtk");
146
147
148
149
	BOOST_REQUIRE_EQUAL(true,test);
	test = compare("vtk_metis_distribution_red.vtk","src/Decomposition/Distribution/test_data/vtk_metis_distribution_red_test.vtk");
	BOOST_REQUIRE_EQUAL(true,test);

150
#endif
151
152
153

	// Copy the Metis distribution

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

	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
170
	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),472ul);
171
172
173
174
}

BOOST_AUTO_TEST_CASE( Parmetis_distribution_test)
{
175
	Vcluster & v_cl = create_vcluster();
176
177

	if (v_cl.getProcessingUnits() != 3)
178
	return;
179
180
181

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

182
	ParMetisDistribution<3, float> pmet_dist(v_cl);
183
184

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

	// Grid info
188
	grid_sm<3, void> info( { GS_SIZE, GS_SIZE, GS_SIZE });
189
190
191
192
193

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

	// 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]

Pietro Incardona's avatar
Pietro Incardona committed
205
	if (v_cl.getProcessUnitID() == 0)
206
207
	{
		// write the first decomposition
Pietro Incardona's avatar
Pietro Incardona committed
208
		pmet_dist.write("vtk_parmetis_distribution_0");
209

jenkins's avatar
jenkins committed
210
211
212
#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");
213
		BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
214
215
216

#else

incardon's avatar
incardon committed
217
218
        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
219
220

#endif
221
222
223
224
225
226
227
	}

	//! [refine with parmetis the decomposition]

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

	// Shift of the sphere at each iteration
228
	Point<3, float> shift( { tstep, tstep, tstep });
229
230
231
232
233
234

	size_t iter = 1;

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

		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();

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

Pietro Incardona's avatar
Pietro Incardona committed
252
253
#ifdef HAVE_OSX

254
				// Check
jenkins's avatar
jenkins committed
255
				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");
256
				BOOST_REQUIRE_EQUAL(true,test);
Pietro Incardona's avatar
Pietro Incardona committed
257
258
259
260
261
262
263
264

#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
265
266
267
268
269
			}
		}
	}

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

incardon's avatar
incardon committed
271
	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),472ul);
272
273
}

274
BOOST_AUTO_TEST_CASE( DistParmetis_distribution_test)
275
{
276
	Vcluster & v_cl = create_vcluster();
277
278

	if (v_cl.getProcessingUnits() != 3)
279
		return;
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

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

incardon's avatar
incardon committed
309
310
311
	// Check
	if (v_cl.getProcessUnitID() == 0)
	{
jenkins's avatar
jenkins committed
312

incardon's avatar
incardon committed
313
	#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
314

incardon's avatar
incardon committed
315
316
		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
317

incardon's avatar
incardon committed
318
	#else
incardon's avatar
incardon committed
319

incardon's avatar
incardon committed
320
321
		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
322

incardon's avatar
incardon committed
323
324
325
	#endif

	}
326

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
	//! [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
352
			pmet_dist.write(str.str());
353
354
355
356

			// Check
			if (v_cl.getProcessUnitID() == 0)
			{
jenkins's avatar
jenkins committed
357
358
#ifdef HAVE_OSX
				bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_osx_test.vtk");
359
				BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
360
361
362

#else

Pietro Incardona's avatar
Pietro Incardona committed
363
364
				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
365
366
367

#endif

368
369
370
371
372
			}
		}
	}

	//! [refine with dist_parmetis the decomposition]
373
374
}

incardon's avatar
incardon committed
375
376
377
378
379
380
381
382
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
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]
}

412
413
void print_test_v(std::string test, size_t sz)
{
414
	if (create_vcluster().getProcessUnitID() == 0)
415
416
417
		std::cout << test << " " << sz << "\n";
}

418
419
420
BOOST_AUTO_TEST_SUITE_END()

#endif /* SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_ */