Distribution_unit_tests.hpp 9.69 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
12
#include "config.h"

13
14
15
16
17
18
19
20
21
22
/*! \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
 *
 */
23
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)
24
25
26
27
28
{
	float radius2 = radius * radius;
	float eq;

	// Position structure for the single vertex
29
	float pos[dim];
30

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

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

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

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

56
BOOST_AUTO_TEST_SUITE (Distribution_test)
57
58
59
60
61
62

BOOST_AUTO_TEST_CASE( Metis_distribution_test)
{
	Vcluster & v_cl = *global_v_cluster;

	if (v_cl.getProcessingUnits() != 3)
63
	return;
64
65

	if (v_cl.getProcessUnitID() != 0)
66
	return;
67
68
69

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

70
	MetisDistribution<3, float> met_dist(v_cl);
71
72

	// Cartesian grid
73
	size_t sz[3] = { GS_SIZE, GS_SIZE, GS_SIZE };
74
75

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

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

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

95
	size_t b = GS_SIZE * GS_SIZE * GS_SIZE / 5;
96
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
	met_dist.initWeights();

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

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

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

		met_dist.setMigrationCost(i,1);

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

	met_dist.decompose();

	//! [Decomposition Metis with weights]

	BOOST_REQUIRE(met_dist.getUnbalance() < 0.03);

	met_dist.write("vtk_metis_distribution_red.vtk");

	// check that match

130
#ifdef HAVE_OSX
jenkins's avatar
jenkins committed
131

132
133
134
135
	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);
136

137
#else
jenkins's avatar
jenkins committed
138

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

144
#endif
145
146
147

	// Copy the Metis distribution

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

	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

Pietro Incardona's avatar
Pietro Incardona committed
164
	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),568ul);
165
166
167
168
169
170
171
}

BOOST_AUTO_TEST_CASE( Parmetis_distribution_test)
{
	Vcluster & v_cl = *global_v_cluster;

	if (v_cl.getProcessingUnits() != 3)
172
	return;
173
174
175

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

176
	ParMetisDistribution<3, float> pmet_dist(v_cl);
177
178

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

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

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

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

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

#else

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

#endif
215
216
217
218
219
220
221
	}

	//! [refine with parmetis the decomposition]

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

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

	size_t iter = 1;

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

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

				// Check
jenkins's avatar
jenkins committed
247
				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");
248
249
250
251
252
253
				BOOST_REQUIRE_EQUAL(true,test);
			}
		}
	}

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

	BOOST_REQUIRE_EQUAL(sizeof(MetisDistribution<3,float>),568ul);
256
257
}

258
BOOST_AUTO_TEST_CASE( DistParmetis_distribution_test)
259
{
260
261
262
	Vcluster & v_cl = *global_v_cluster;

	if (v_cl.getProcessingUnits() != 3)
263
		return;
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

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

	// write the first decomposition
Pietro Incardona's avatar
Pietro Incardona committed
291
	pmet_dist.write("vtk_dist_parmetis_distribution_0");
292

Pietro Incardona's avatar
Pietro Incardona committed
293
	if (v_cl.getProcessUnitID() == 0)
294
	{
jenkins's avatar
jenkins committed
295
296
297
298
299
300
301
302

#ifdef HAVE_OSX

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

#else

Pietro Incardona's avatar
Pietro Incardona committed
303
		bool test = compare("vtk_dist_parmetis_distribution_0.vtk","src/Decomposition/Distribution/test_data/vtk_dist_parmetis_distribution_0_test.vtk");
304
		BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
305
#endif
306
	}
307

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
	//! [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
333
			pmet_dist.write(str.str());
334
335
336
337

			// Check
			if (v_cl.getProcessUnitID() == 0)
			{
jenkins's avatar
jenkins committed
338
339
#ifdef HAVE_OSX
				bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_osx_test.vtk");
340
				BOOST_REQUIRE_EQUAL(true,test);
jenkins's avatar
jenkins committed
341
342
343
344
345
346
347
348

#else

                                bool test = compare(str.str() + ".vtk",std::string("src/Decomposition/Distribution/test_data/") + str.str() + "_osx_test.vtk");
                                BOOST_REQUIRE_EQUAL(true,test);

#endif

349
350
351
352
353
			}
		}
	}

	//! [refine with dist_parmetis the decomposition]
354
355
}

356
357
358
359
360
361
void print_test_v(std::string test, size_t sz)
{
	if (global_v_cluster->getProcessUnitID() == 0)
		std::cout << test << " " << sz << "\n";
}

362
363
364
BOOST_AUTO_TEST_SUITE_END()

#endif /* SRC_DECOMPOSITION_DISTRIBUTION_DISTRIBUTION_UNIT_TESTS_HPP_ */