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
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
88
89
90
91
92
93

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

94
	size_t b = GS_SIZE * GS_SIZE * GS_SIZE / 5;
95
96
97
98
99
100
101
102

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

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

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

		met_dist.setMigrationCost(i,1);

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

	met_dist.decompose();

	//! [Decomposition Metis with weights]

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

	met_dist.write("vtk_metis_distribution_red.vtk");

	// check that match

133
#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
134

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

140
#else
jenkins's avatar
jenkins committed
141

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

147
#endif
148
149
150

	// Copy the Metis distribution

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

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

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

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

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

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

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

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

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

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

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

#else

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

#endif
218
219
220
221
222
223
224
	}

	//! [refine with parmetis the decomposition]

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

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

	size_t iter = 1;

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

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

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

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

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

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

incardon's avatar
incardon committed
268
	BOOST_REQUIRE_EQUAL(sizeof(ParMetisDistribution<3,float>),872ul);
269
270
}

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

	if (v_cl.getProcessingUnits() != 3)
276
		return;
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
302

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

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

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

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

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

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

incardon's avatar
incardon committed
320
321
322
	#endif

	}
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
348
	//! [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
349
			pmet_dist.write(str.str());
350
351
352
353

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

#else

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

#endif

365
366
367
368
369
			}
		}
	}

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

incardon's avatar
incardon committed
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
408
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]
}

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

415
416
417
BOOST_AUTO_TEST_SUITE_END()

#endif /* SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_ */