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

134
135
136
137
	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);
138

139
#else
jenkins's avatar
jenkins committed
140

141
	bool test = compare("vtk_metis_distribution.vtk", "src/Decomposition/Distribution/test_data/vtk_metis_distribution_test.vtk");
142
143
144
145
	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);

146
#endif
147
148
149

	// Copy the Metis distribution

150
	MetisDistribution<3, float> met_dist2(v_cl);
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

	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
166
	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),472ul);
167
168
169
170
}

BOOST_AUTO_TEST_CASE( Parmetis_distribution_test)
{
171
	Vcluster & v_cl = create_vcluster();
172
173

	if (v_cl.getProcessingUnits() != 3)
174
	return;
175
176
177

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

178
	ParMetisDistribution<3, float> pmet_dist(v_cl);
179
180

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

	// Grid info
184
	grid_sm<3, void> info( { GS_SIZE, GS_SIZE, GS_SIZE });
185
186
187
188
189

	// 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
190
	Point<3, float> center( { 2.0, 2.0, 2.0 });
191
192
193
194
195
196
197
198
199
200

	// 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
201
	if (v_cl.getProcessUnitID() == 0)
202
203
	{
		// write the first decomposition
Pietro Incardona's avatar
Pietro Incardona committed
204
		pmet_dist.write("vtk_parmetis_distribution_0");
205

jenkins's avatar
jenkins committed
206
207
208
#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");
209
		BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
210
211
212

#else

incardon's avatar
incardon committed
213
214
        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
215
216

#endif
217
218
219
220
221
222
223
	}

	//! [refine with parmetis the decomposition]

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

	// Shift of the sphere at each iteration
224
	Point<3, float> shift( { tstep, tstep, tstep });
225
226
227
228
229
230

	size_t iter = 1;

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

		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
246
				pmet_dist.write(str.str());
247

Pietro Incardona's avatar
Pietro Incardona committed
248
249
#ifdef HAVE_OSX

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

#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
261
262
263
264
265
			}
		}
	}

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

incardon's avatar
incardon committed
267
	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),472ul);
268
269
}

270
BOOST_AUTO_TEST_CASE( DistParmetis_distribution_test)
271
{
272
	Vcluster & v_cl = create_vcluster();
273
274

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

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

incardon's avatar
incardon committed
305
306
307
	// Check
	if (v_cl.getProcessUnitID() == 0)
	{
jenkins's avatar
jenkins committed
308

incardon's avatar
incardon committed
309
	#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
310

incardon's avatar
incardon committed
311
312
		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
313

incardon's avatar
incardon committed
314
	#else
incardon's avatar
incardon committed
315

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

incardon's avatar
incardon committed
319
320
321
	#endif

	}
322

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

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

#else

Pietro Incardona's avatar
Pietro Incardona committed
359
360
				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
361
362
363

#endif

364
365
366
367
368
			}
		}
	}

	//! [refine with dist_parmetis the decomposition]
369
370
}

incardon's avatar
incardon committed
371
372
373
374
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
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]
}

408
409
void print_test_v(std::string test, size_t sz)
{
410
	if (create_vcluster().getProcessUnitID() == 0)
411
412
413
		std::cout << test << " " << sz << "\n";
}

414
415
416
BOOST_AUTO_TEST_SUITE_END()

#endif /* SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_ */