vector_dist_unit_test.cpp 40.5 KB
Newer Older
incardon's avatar
incardon committed
1 2 3 4 5 6 7
/*
 * vector_dist_unit_test.hpp
 *
 *  Created on: Mar 6, 2015
 *      Author: Pietro Incardona
 */

incardon's avatar
incardon committed
8 9
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
incardon's avatar
incardon committed
10

incardon's avatar
incardon committed
11 12
#include "config.h"

incardon's avatar
incardon committed
13
#include <random>
incardon's avatar
incardon committed
14
#include "Vector/vector_dist.hpp"
Yaroslav's avatar
Yaroslav committed
15
#include "data_type/aggregate.hpp"
incardon's avatar
incardon committed
16 17
#include "vector_dist_util_unit_tests.hpp"
#include "Point_test.hpp"
incardon's avatar
incardon committed
18
#include "Vector/performance/vector_dist_performance_common.hpp"
incardon's avatar
incardon committed
19

incardon's avatar
incardon committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/*! \brief Print a string about the test
 *
 * \param test string to print
 * \param sz size
 *
 */
void print_test_v(std::string test, size_t sz)
{
	if (create_vcluster().getProcessUnitID() == 0)
		std::cout << test << " " << sz << "\n";
}

/*! \brief Get next testing step decrementing the size
 *
 * \param k actual size
 * \param step
 *
 * \return the next step
 *
 */
long int decrement(long int k, long int step)
{
	if (k <= 32)
	{
		return 1;
	}
	else if (k - 2*step+1 <= 0)
	{
		return k - 32;
	}
	else
		return step;
}

54 55 56 57 58 59
/*! \brief Count the total number of particles
 *
 * \param vd distributed vector
 * \param bc boundary conditions
 *
 */
incardon's avatar
incardon committed
60 61
template<unsigned int dim, template <typename> class layout>
size_t total_n_part_lc(vector_dist<dim,float, Point_test<float>, CartDecomposition<dim,float>, HeapMemory, layout > & vd, size_t (& bc)[dim])
62 63 64 65 66
{
	Vcluster & v_cl = vd.getVC();
	auto it2 = vd.getDomainIterator();
	const CartDecomposition<3,float> & ct = vd.getDecomposition();

67 68
	bool noOut = true;

69 70 71 72 73
	size_t cnt = 0;
	while (it2.isNext())
	{
		auto key = it2.get();

Pietro Incardona's avatar
Pietro Incardona committed
74
		noOut &= ct.isLocal(vd.getPos(key));
75 76 77 78 79 80

		cnt++;

		++it2;
	}

81 82
	BOOST_REQUIRE_EQUAL(noOut,true);

83 84 85 86 87 88 89 90
	//
	v_cl.sum(cnt);
	v_cl.execute();

	return cnt;
}


incardon's avatar
incardon committed
91 92
BOOST_AUTO_TEST_SUITE( vector_dist_test )

93 94
void print_test(std::string test, size_t sz)
{
95
	if (create_vcluster().getProcessUnitID() == 0)
96 97 98
		std::cout << test << " " << sz << "\n";
}

incardon's avatar
incardon committed
99
template<typename vector>
100
void Test2D_ghost(Box<2,float> & box)
101 102
{
	// Communication object
103
	Vcluster & v_cl = create_vcluster();
104 105 106

	typedef Point_test<float> p;

107
	// Get the default minimum number of sub-sub-domain per processor (granularity of the decomposition)
incardon's avatar
incardon committed
108
	size_t n_sub = 64 * v_cl.getProcessingUnits();
109 110
	// Convert the request of having a minimum n_sub number of sub-sub domain into grid decompsition of the space
	size_t sz = CartDecomposition<2,float>::getDefaultGrid(n_sub);
incardon's avatar
incardon committed
111

112 113
	//! [Create a vector of elements distributed on a grid like way]

114
	size_t g_div[]= {sz,sz};
115

116 117 118
	// number of particles
	size_t np = sz * sz;

119
	// Calculate the number of elements this processor is going to obtain
120 121 122 123 124 125 126 127
	size_t p_np = np / v_cl.getProcessingUnits();

	// Get non divisible part
	size_t r = np % v_cl.getProcessingUnits();

	// Get the offset
	size_t offset = v_cl.getProcessUnitID() * p_np + std::min(v_cl.getProcessUnitID(),r);

128
	// Distribute the remain elements
129 130
	if (v_cl.getProcessUnitID() < r)
		p_np++;
131 132 133 134 135

	// Create a grid info
	grid_sm<2,void> g_info(g_div);

	// Calculate the grid spacing
136
	Point<2,float> spacing = box.getP2() - box.getP1();
137 138 139
	spacing = spacing / g_div;

	// middle spacing
Pietro Incardona's avatar
Pietro Incardona committed
140
	Point<2,float> m_spacing = spacing / 2.0;
141

incardon's avatar
incardon committed
142 143 144
	// set the ghost based on the radius cut off (make just a little bit smaller than the spacing)
	Ghost<2,float> g(spacing.get(0) - spacing .get(0) * 0.0001);

145 146 147
	// Boundary conditions
	size_t bc[2]={NON_PERIODIC,NON_PERIODIC};

148
	// Vector of particles
incardon's avatar
incardon committed
149
	vector vd(g_info.size(),box,bc,g);
150 151 152

	// size_t
	size_t cobj = 0;
153

154 155
	grid_key_dx_iterator_sp<2> it(g_info,offset,offset+p_np-1);
	auto v_it = vd.getIterator();
156

157
	while (v_it.isNext() && it.isNext())
158
	{
159 160
		auto key = it.get();
		auto key_v = v_it.get();
161 162 163

		// set the particle position

164 165
		vd.getPos(key_v)[0] = key.get(0) * spacing[0] + m_spacing[0] + box.getLow(0);
		vd.getPos(key_v)[1] = key.get(1) * spacing[1] + m_spacing[1] + box.getLow(1);
166

167 168 169
		cobj++;

		++v_it;
170 171 172
		++it;
	}

173 174 175
	//! [Create a vector of elements distributed on a grid like way]

	// Both iterators must signal the end, and the number of elements in the vector, must the equal to the
176 177 178 179 180
	// predicted one
	BOOST_REQUIRE_EQUAL(v_it.isNext(),false);
	BOOST_REQUIRE_EQUAL(it.isNext(),false);
	BOOST_REQUIRE_EQUAL(cobj,p_np);

181 182
	//! [Redistribute the particles and sync the ghost properties]

183 184 185
	// redistribute the particles according to the decomposition
	vd.map();

186
	auto v_it2 = vd.getIterator();
187

188
	while (v_it2.isNext())
189
	{
190
		auto key = v_it2.get();
191 192

		// fill with the processor ID where these particle live
incardon's avatar
incardon committed
193 194 195 196
		vd.template getProp<p::s>(key) = vd.getPos(key)[0] + vd.getPos(key)[1] * 16.0f;
		vd.template getProp<p::v>(key)[0] = v_cl.getProcessUnitID();
		vd.template getProp<p::v>(key)[1] = v_cl.getProcessUnitID();
		vd.template getProp<p::v>(key)[2] = v_cl.getProcessUnitID();
197

198
		++v_it2;
incardon's avatar
incardon committed
199
	}
incardon's avatar
incardon committed
200 201

	// do a ghost get
incardon's avatar
incardon committed
202
	vd.template ghost_get<p::s,p::v>();
203

204
	//! [Redistribute the particles and sync the ghost properties]
incardon's avatar
incardon committed
205

206 207 208 209
	// Get the decomposition
	const auto & dec = vd.getDecomposition();

	// Get the ghost external boxes
210
	openfpm::vector<size_t> vb(dec.getNEGhostBox());
211 212 213 214

	// Get the ghost iterator
	auto g_it = vd.getGhostIterator();

215 216
	size_t n_part = 0;

217 218 219 220 221 222
	// Check if the ghost particles contain the correct information
	while (g_it.isNext())
	{
		auto key = g_it.get();

		// Check the received data
incardon's avatar
incardon committed
223
		BOOST_REQUIRE_EQUAL(vd.getPos(key)[0] + vd.getPos(key)[1] * 16.0f,vd.template getProp<p::s>(key));
224 225 226

		bool is_in = false;
		size_t b = 0;
227
		size_t lb = 0;
228

229
		// check if the received data are in one of the ghost boxes
230
		for ( ; b < dec.getNEGhostBox() ; b++)
231
		{
incardon's avatar
incardon committed
232 233 234
			Point<2,float> xp = vd.getPos(key);

			if (dec.getEGhostBox(b).isInside(xp) == true )
235 236 237 238 239 240 241
			{
				is_in = true;

				// Add
				vb.get(b)++;
				lb = b;
			}
242 243 244 245
		}
		BOOST_REQUIRE_EQUAL(is_in,true);

		// Check that the particle come from the correct processor
incardon's avatar
incardon committed
246
		BOOST_REQUIRE_EQUAL(vd.template getProp<p::v>(key)[0],dec.getEGhostBoxProcessor(lb));
247

248
		n_part++;
249 250 251
		++g_it;
	}

252 253 254 255
	if (v_cl.getProcessingUnits() > 1)
	{
		BOOST_REQUIRE(n_part != 0);
	}
256

257
    CellDecomposer_sm<2,float,shift<2,float>> cd(SpaceBox<2,float>(box),g_div,0);
258 259 260 261

	for (size_t i = 0 ; i < vb.size() ; i++)
	{
		// Calculate how many particle should be in the box
262
		size_t n_point = cd.getGridPoints(dec.getEGhostBox(i)).getVolumeKey();
263

264
		BOOST_REQUIRE_EQUAL(n_point,vb.get(i));
265
	}
incardon's avatar
incardon committed
266 267
}

incardon's avatar
incardon committed
268 269 270
BOOST_AUTO_TEST_CASE( vector_dist_ghost )
{
	typedef vector_dist<2,float, Point_test<float>> vector;
incardon's avatar
incardon committed
271

incardon's avatar
incardon committed
272 273 274 275 276 277 278 279
	Box<2,float> box({0.0,0.0},{1.0,1.0});
	Test2D_ghost<vector>(box);

	Box<2,float> box2({-1.0,-1.0},{2.5,2.5});
	Test2D_ghost<vector>(box2);
}

BOOST_AUTO_TEST_CASE( vector_dist_ghost_inte )
280
{
incardon's avatar
incardon committed
281
	typedef vector_dist<2,float, Point_test<float>,CartDecomposition<2,float>,HeapMemory,memory_traits_inte> vector;
incardon's avatar
incardon committed
282

283
	Box<2,float> box({0.0,0.0},{1.0,1.0});
incardon's avatar
incardon committed
284
	Test2D_ghost<vector>(box);
285 286

	Box<2,float> box2({-1.0,-1.0},{2.5,2.5});
incardon's avatar
incardon committed
287
	Test2D_ghost<vector>(box2);
288 289
}

290

incardon's avatar
incardon committed
291

292
BOOST_AUTO_TEST_CASE( vector_dist_iterator_test_use_2d )
incardon's avatar
incardon committed
293
{
294
	Vcluster & v_cl = create_vcluster();
incardon's avatar
incardon committed
295 296 297 298 299 300 301

    // set the seed
	// create the random generator engine
	std::srand(v_cl.getProcessUnitID());
    std::default_random_engine eg;
    std::uniform_real_distribution<float> ud(0.0f, 1.0f);

incardon's avatar
incardon committed
302 303 304
#ifdef TEST_COVERAGE_MODE
    long int k = 24288 * v_cl.getProcessingUnits();
#else
305
    long int k = 524288 * v_cl.getProcessingUnits();
incardon's avatar
incardon committed
306
#endif
incardon's avatar
incardon committed
307

308
	long int big_step = k / 4;
309
	big_step = (big_step == 0)?1:big_step;
incardon's avatar
incardon committed
310

incardon's avatar
incardon committed
311 312
	print_test_v( "Testing 2D vector k<=",k);

313
	// 2D test
incardon's avatar
incardon committed
314
	for ( ; k >= 2 ; k-= decrement(k,big_step) )
incardon's avatar
incardon committed
315
	{
316
		BOOST_TEST_CHECKPOINT( "Testing 2D vector k=" << k );
317 318 319

		//! [Create a vector of random elements on each processor 2D]

320
		Box<2,float> box({0.0,0.0},{1.0,1.0});
321 322 323 324

		// Boundary conditions
		size_t bc[2]={NON_PERIODIC,NON_PERIODIC};

325
		vector_dist<2,float, Point_test<float> > vd(k,box,bc,Ghost<2,float>(0.0));
incardon's avatar
incardon committed
326

327
		auto it = vd.getIterator();
incardon's avatar
incardon committed
328

329 330 331 332
		while (it.isNext())
		{
			auto key = it.get();

Pietro Incardona's avatar
Pietro Incardona committed
333 334
			vd.getPos(key)[0] = ud(eg);
			vd.getPos(key)[1] = ud(eg);
335 336 337 338 339 340

			++it;
		}

		vd.map();

341 342
		//! [Create a vector of random elements on each processor 2D]

343 344 345
		// Check if we have all the local particles
		size_t cnt = 0;
		const CartDecomposition<2,float> & ct = vd.getDecomposition();
346
		auto it2 = vd.getIterator();
347

348
		while (it2.isNext())
349
		{
350
			auto key = it2.get();
351 352

			// Check if local
Pietro Incardona's avatar
Pietro Incardona committed
353
			BOOST_REQUIRE_EQUAL(ct.isLocal(vd.getPos(key)),true);
354 355 356

			cnt++;

357
			++it2;
358 359 360 361 362
		}

		//
		v_cl.sum(cnt);
		v_cl.execute();
Pietro Incardona's avatar
Pietro Incardona committed
363
		BOOST_REQUIRE_EQUAL((long int)cnt,k);
incardon's avatar
incardon committed
364
	}
365
}
incardon's avatar
incardon committed
366

367 368
BOOST_AUTO_TEST_CASE( vector_dist_iterator_test_use_3d )
{
369
	Vcluster & v_cl = create_vcluster();
incardon's avatar
incardon committed
370

371 372 373 374 375 376
    // set the seed
	// create the random generator engine
	std::srand(v_cl.getProcessUnitID());
    std::default_random_engine eg;
    std::uniform_real_distribution<float> ud(0.0f, 1.0f);

incardon's avatar
incardon committed
377 378 379
#ifdef TEST_COVERAGE_MODE
    long int k = 24288 * v_cl.getProcessingUnits();
#else
380
    long int k = 524288 * v_cl.getProcessingUnits();
incardon's avatar
incardon committed
381
#endif
382

383
	long int big_step = k / 4;
384 385
	big_step = (big_step == 0)?1:big_step;

incardon's avatar
incardon committed
386 387
	print_test_v( "Testing 3D vector k<=",k);

388
	// 3D test
incardon's avatar
incardon committed
389
	for ( ; k >= 2 ; k-= decrement(k,big_step) )
incardon's avatar
incardon committed
390
	{
391
		BOOST_TEST_CHECKPOINT( "Testing 3D vector k=" << k );
392 393 394

		//! [Create a vector of random elements on each processor 3D]

395
		Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
396 397 398 399

		// Boundary conditions
		size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};

400
		vector_dist<3,float, Point_test<float> > vd(k,box,bc,Ghost<3,float>(0.0));
incardon's avatar
incardon committed
401

402
		auto it = vd.getIterator();
incardon's avatar
incardon committed
403

404 405 406
		while (it.isNext())
		{
			auto key = it.get();
incardon's avatar
incardon committed
407

Pietro Incardona's avatar
Pietro Incardona committed
408 409 410
			vd.getPos(key)[0] = ud(eg);
			vd.getPos(key)[1] = ud(eg);
			vd.getPos(key)[2] = ud(eg);
411 412 413 414 415 416

			++it;
		}

		vd.map();

417 418
		//! [Create a vector of random elements on each processor 3D]

419 420 421
		// Check if we have all the local particles
		size_t cnt = 0;
		const CartDecomposition<3,float> & ct = vd.getDecomposition();
422
		auto it2 = vd.getIterator();
423

424
		while (it2.isNext())
425
		{
426
			auto key = it2.get();
427 428

			// Check if local
Pietro Incardona's avatar
Pietro Incardona committed
429
			BOOST_REQUIRE_EQUAL(ct.isLocal(vd.getPos(key)),true);
430 431 432

			cnt++;

433
			++it2;
434 435 436 437 438
		}

		//
		v_cl.sum(cnt);
		v_cl.execute();
Pietro Incardona's avatar
Pietro Incardona committed
439
		BOOST_REQUIRE_EQUAL(cnt,(size_t)k);
440
	}
incardon's avatar
incardon committed
441 442
}

Pietro Incardona's avatar
Pietro Incardona committed
443 444 445 446 447 448 449 450 451 452 453

BOOST_AUTO_TEST_CASE( vector_dist_iterator_fixed_dec_3d )
{
	Vcluster & v_cl = create_vcluster();

    // set the seed
	// create the random generator engine
	std::srand(v_cl.getProcessUnitID());
    std::default_random_engine eg;
    std::uniform_real_distribution<float> ud(0.0f, 1.0f);

incardon's avatar
incardon committed
454 455 456
#ifdef TEST_COVERAGE_MODE
    long int k = 2428 * v_cl.getProcessingUnits();
#else
Pietro Incardona's avatar
Pietro Incardona committed
457
    long int k = 52428 * v_cl.getProcessingUnits();
incardon's avatar
incardon committed
458
#endif
Pietro Incardona's avatar
Pietro Incardona committed
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

	long int big_step = k / 4;
	big_step = (big_step == 0)?1:big_step;

	print_test_v( "Testing 3D vector copy decomposition k<=",k);

	// 3D test
	for ( ; k >= 2 ; k-= decrement(k,big_step) )
	{
		BOOST_TEST_CHECKPOINT( "Testing 3D vector copy decomposition k=" << k );

		Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});

		// Boundary conditions
		size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};

		vector_dist<3,float, aggregate<double,double> > vd(k,box,bc,Ghost<3,float>(0.05));
		vector_dist<3,float, aggregate<double,double> > vd2(vd.getDecomposition(),k);

		auto it = vd.getIterator();

		while (it.isNext())
		{
			auto key = it.get();

			vd.getPos(key)[0] = ud(eg);
			vd.getPos(key)[1] = ud(eg);
			vd.getPos(key)[2] = ud(eg);

			vd2.getPos(key)[0] = vd.getPos(key)[0];
			vd2.getPos(key)[1] = vd.getPos(key)[1];
			vd2.getPos(key)[2] = vd.getPos(key)[2];

			++it;
		}

		vd.map();
		vd2.map();

		vd.ghost_get();
		vd2.ghost_get();

		auto NN = vd.getCellList(0.05);
		auto NN2 = vd2.getCellList(0.05);

		cross_calc<3,0>(NN,NN2,vd,vd2);
		cross_calc<3,1>(NN,NN,vd,vd);


		auto it3 = vd.getIterator();

		while (it3.isNext())
		{
			auto key = it3.get();

			BOOST_REQUIRE_EQUAL(vd.getProp<0>(key),vd.getProp<1>(key));

			++it3;
		}
	}
}

521 522
BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_use_2d )
{
523
	Vcluster & v_cl = create_vcluster();
524 525 526 527 528 529 530

    // set the seed
	// create the random generator engine
	std::srand(v_cl.getProcessUnitID());
    std::default_random_engine eg;
    std::uniform_real_distribution<float> ud(0.0f, 1.0f);

incardon's avatar
incardon committed
531 532 533
#ifdef TEST_COVERAGE_MODE
    long int k = 24288 * v_cl.getProcessingUnits();
#else
534
    long int k = 524288 * v_cl.getProcessingUnits();
incardon's avatar
incardon committed
535
#endif
536

537
	long int big_step = k / 4;
538 539 540 541 542 543 544 545 546 547 548 549 550 551
	big_step = (big_step == 0)?1:big_step;

	print_test_v( "Testing 2D periodic vector k<=",k);

	// 2D test
	for ( ; k >= 2 ; k-= decrement(k,big_step) )
	{
		BOOST_TEST_CHECKPOINT( "Testing 2D periodic vector k=" << k );

		Box<2,float> box({0.0,0.0},{1.0,1.0});

		// Boundary conditions
		size_t bc[2]={PERIODIC,PERIODIC};

552
		// factor
553
		float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
554

555
		// ghost
556
		Ghost<2,float> ghost(0.01 / factor);
557

558
		// ghost2 (a little bigger because of round off error)
559
		Ghost<2,float> ghost2(0.05001 / factor);
560 561

		// Distributed vector
Pietro Incardona's avatar
Pietro Incardona committed
562
		vector_dist<2,float, Point_test<float> > vd(k,box,bc,ghost);
563 564 565 566 567 568 569

		auto it = vd.getIterator();

		while (it.isNext())
		{
			auto key = it.get();

Pietro Incardona's avatar
Pietro Incardona committed
570 571
			vd.getPos(key)[0] = ud(eg);
			vd.getPos(key)[1] = ud(eg);
572 573 574 575 576 577

			++it;
		}

		vd.map();

578
		// sync the ghost, only the property zero
579 580
		vd.ghost_get<0>();

581
		// Domain + ghost box
582
		Box<2,float> dom_ext = box;
583
		dom_ext.enlarge(ghost2);
584

585 586 587 588
		// Iterate on all particles domain + ghost
		size_t l_cnt = 0;
		size_t nl_cnt = 0;
		size_t n_out = 0;
589 590


591
		auto it2 = vd.getIterator();
592
		count_local_n_local<2,vector_dist<2,float, Point_test<float> >>(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
593

594 595
		// No particles should be out of domain + ghost
		BOOST_REQUIRE_EQUAL(n_out,0ul);
596

597
		// Ghost must populated because we synchronized them
598
		if (k > 524288)
599
		{
600
			BOOST_REQUIRE(nl_cnt != 0);
601 602
			BOOST_REQUIRE(l_cnt > nl_cnt);
		}
603

604
		// Sum all the particles inside the domain
605 606
		v_cl.sum(l_cnt);
		v_cl.execute();
607 608

		// count that they are equal to the initial total number
609
		BOOST_REQUIRE_EQUAL((long int)l_cnt,k);
610 611 612 613 614 615

		l_cnt = 0;
		nl_cnt = 0;

		// Iterate only on the ghost particles
		auto itg = vd.getGhostIterator();
Pietro Incardona's avatar
Pietro Incardona committed
616
		count_local_n_local<2,vector_dist<2,float, Point_test<float> > >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
617 618 619 620 621 622

		// No particle on the ghost must be inside the domain
		BOOST_REQUIRE_EQUAL(l_cnt,0ul);

		// Ghost must be populated
		if (k > 524288)
623
		{
624
			BOOST_REQUIRE(nl_cnt != 0);
625
		}
626 627 628 629 630
	}
}

BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_use_3d )
{
631
	Vcluster & v_cl = create_vcluster();
632 633 634 635 636 637 638

    // set the seed
	// create the random generator engine
	std::srand(v_cl.getProcessUnitID());
    std::default_random_engine eg;
    std::uniform_real_distribution<float> ud(0.0f, 1.0f);

incardon's avatar
incardon committed
639 640 641
#ifdef TEST_COVERAGE_MODE
    long int k = 24288 * v_cl.getProcessingUnits();
#else
642
    long int k = 524288 * v_cl.getProcessingUnits();
incardon's avatar
incardon committed
643
#endif
644

645
	long int big_step = k / 4;
646 647 648 649 650 651 652 653 654 655 656 657 658 659
	big_step = (big_step == 0)?1:big_step;

	print_test_v( "Testing 3D periodic vector k<=",k);

	// 3D test
	for ( ; k >= 2 ; k-= decrement(k,big_step) )
	{
		BOOST_TEST_CHECKPOINT( "Testing 3D periodic vector k=" << k );

		Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});

		// Boundary conditions
		size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};

660
		// factor
661
		float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
662

663
		// ghost
664
		Ghost<3,float> ghost(0.05 / factor);
665

666
		// ghost2 (a little bigger because of round off error)
667
		Ghost<3,float> ghost2(0.05001 / factor);
668 669

		// Distributed vector
Pietro Incardona's avatar
Pietro Incardona committed
670
		vector_dist<3,float, Point_test<float> > vd(k,box,bc,ghost);
671 672 673 674 675 676 677

		auto it = vd.getIterator();

		while (it.isNext())
		{
			auto key = it.get();

Pietro Incardona's avatar
Pietro Incardona committed
678 679 680
			vd.getPos(key)[0] = ud(eg);
			vd.getPos(key)[1] = ud(eg);
			vd.getPos(key)[2] = ud(eg);
681 682 683 684 685 686 687 688 689

			++it;
		}

		vd.map();

		// sync the ghost
		vd.ghost_get<0>();

690 691 692 693 694
		// Domain + ghost
		Box<3,float> dom_ext = box;
		dom_ext.enlarge(ghost2);

		// Iterate on all particles domain + ghost
695 696 697
		size_t l_cnt = 0;
		size_t nl_cnt = 0;
		size_t n_out = 0;
698 699

		auto it2 = vd.getIterator();
Pietro Incardona's avatar
Pietro Incardona committed
700
		count_local_n_local<3,vector_dist<3,float, Point_test<float> >>(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
701 702 703 704 705 706

		// No particles should be out of domain + ghost
		BOOST_REQUIRE_EQUAL(n_out,0ul);

		// Ghost must populated because we synchronized them
		if (k > 524288)
707
		{
708
			BOOST_REQUIRE(nl_cnt != 0);
709 710
			BOOST_REQUIRE(l_cnt > nl_cnt);
		}
711 712 713 714 715 716 717 718 719 720 721

		// Sum all the particles inside the domain
		v_cl.sum(l_cnt);
		v_cl.execute();
		BOOST_REQUIRE_EQUAL(l_cnt,(size_t)k);

		l_cnt = 0;
		nl_cnt = 0;

		// Iterate only on the ghost particles
		auto itg = vd.getGhostIterator();
Pietro Incardona's avatar
Pietro Incardona committed
722
		count_local_n_local<3,vector_dist<3,float, Point_test<float> > >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
723 724 725 726 727 728

		// No particle on the ghost must be inside the domain
		BOOST_REQUIRE_EQUAL(l_cnt,0ul);

		// Ghost must be populated
		if (k > 524288)
729
		{
730
			BOOST_REQUIRE(nl_cnt != 0);
731
		}
732 733 734
	}
}

incardon's avatar
incardon committed
735
void test_random_walk(size_t opt)
736
{
737
	Vcluster & v_cl = create_vcluster();
738 739 740 741 742 743

    // set the seed
	// create the random generator engine
	std::srand(v_cl.getProcessUnitID());
    std::default_random_engine eg;
    std::uniform_real_distribution<float> ud(0.0f, 1.0f);
Pietro Incardona's avatar
Pietro Incardona committed
744
	
Pietro Incardona's avatar
Pietro Incardona committed
745 746
	size_t nsz[] = {0,32,4};
	nsz[0] = 65536 * v_cl.getProcessingUnits();
747

Pietro Incardona's avatar
Pietro Incardona committed
748
	print_test_v( "Testing 3D random walk vector k<=",nsz[0]);
749 750

	// 3D test
Pietro Incardona's avatar
Pietro Incardona committed
751
	for (size_t i = 0 ; i < 3 ; i++ )
752
	{
Pietro Incardona's avatar
Pietro Incardona committed
753
		size_t k = nsz[i];
Pietro Incardona's avatar
Pietro Incardona committed
754

755 756 757 758 759 760 761
		BOOST_TEST_CHECKPOINT( "Testing 3D random walk vector k=" << k );

		Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});

		// Boundary conditions
		size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};

762
		// factor
763
		float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
764

765
		// ghost
766
		Ghost<3,float> ghost(0.01 / factor);
767 768

		// Distributed vector
incardon's avatar
incardon committed
769
		vector_dist<3,float, Point_test<float> > vd(k,box,bc,ghost);
770 771

		auto it = vd.getIterator();
772 773 774 775 776

		while (it.isNext())
		{
			auto key = it.get();

Pietro Incardona's avatar
Pietro Incardona committed
777 778 779
			vd.getPos(key)[0] = ud(eg);
			vd.getPos(key)[1] = ud(eg);
			vd.getPos(key)[2] = ud(eg);
780 781 782 783

			++it;
		}

784
		vd.map();
785

786
		// 10 step random walk
787

788
		for (size_t j = 0 ; j < 4 ; j++)
789 790 791 792 793 794 795
		{
			auto it = vd.getDomainIterator();

			while (it.isNext())
			{
				auto key = it.get();

Pietro Incardona's avatar
Pietro Incardona committed
796 797 798
				vd.getPos(key)[0] += 0.02 * ud(eg);
				vd.getPos(key)[1] += 0.02 * ud(eg);
				vd.getPos(key)[2] += 0.02 * ud(eg);
799 800 801 802

				++it;
			}

incardon's avatar
incardon committed
803
			vd.map(opt);
804

805
			vd.ghost_get<0>();
806 807 808 809 810 811

			// Count the local particles and check that the total number is consistent
			size_t cnt = total_n_part_lc(vd,bc);

			BOOST_REQUIRE_EQUAL((size_t)k,cnt);
		}
812 813 814
	}
}

incardon's avatar
incardon committed
815 816 817 818 819 820 821 822 823 824
BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_random_walk )
{
	test_random_walk(NONE);
}

BOOST_AUTO_TEST_CASE( vector_dist_periodic_test_random_walk_local_map )
{
	test_random_walk(MAP_LOCAL);
}

825 826 827 828 829 830 831
BOOST_AUTO_TEST_CASE( vector_dist_periodic_map )
{
	Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});

	// Boundary conditions
	size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};

832
	// factor
833
	float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
834

835
	// ghost
836
	Ghost<3,float> ghost(0.05 / factor);
837 838

	// Distributed vector
incardon's avatar
incardon committed
839
	vector_dist<3,float, Point_test<float> > vd(1,box,bc,ghost);
840 841 842 843 844 845 846 847 848

	// put particles al 1.0, check that they go to 0.0

	auto it = vd.getIterator();

	while (it.isNext())
	{
		auto key = it.get();

Pietro Incardona's avatar
Pietro Incardona committed
849 850 851
		vd.getPos(key)[0] = 1.0;
		vd.getPos(key)[1] = 1.0;
		vd.getPos(key)[2] = 1.0;
852 853 854 855 856 857 858 859 860 861 862 863

		++it;
	}

	vd.map();

	auto it2 = vd.getIterator();

	while (it2.isNext())
	{
		auto key = it2.get();

Pietro Incardona's avatar
Pietro Incardona committed
864
		float f = vd.getPos(key)[0];
865
		BOOST_REQUIRE_EQUAL(f, 0.0);
Pietro Incardona's avatar
Pietro Incardona committed
866
		f = vd.getPos(key)[1];
867
		BOOST_REQUIRE_EQUAL(f, 0.0);
Pietro Incardona's avatar
Pietro Incardona committed
868
		f = vd.getPos(key)[2];
869 870 871 872 873 874
		BOOST_REQUIRE_EQUAL(f, 0.0);

		++it2;
	}
}

Pietro Incardona's avatar
Pietro Incardona committed
875

876 877 878 879 880 881 882
BOOST_AUTO_TEST_CASE( vector_dist_not_periodic_map )
{
	Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});

	// Boundary conditions
	size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};

883
	// factor
884
	float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
885

886
	// ghost
887
	Ghost<3,float> ghost(0.05 / factor);
888 889

	// Distributed vector
incardon's avatar
incardon committed
890
	vector_dist<3,float, Point_test<float> > vd(1,box,bc,ghost);
891 892 893 894 895 896 897 898 899

	// put particles al 1.0, check that they go to 0.0

	auto it = vd.getIterator();

	while (it.isNext())
	{
		auto key = it.get();

Pietro Incardona's avatar
Pietro Incardona committed
900 901 902
		vd.getPos(key)[0] = 1.0;
		vd.getPos(key)[1] = 1.0;
		vd.getPos(key)[2] = 1.0;
903 904 905 906 907 908 909 910 911 912 913 914

		++it;
	}

	vd.map();

	auto it2 = vd.getIterator();

	while (it2.isNext())
	{
		auto key = it2.get();

Pietro Incardona's avatar
Pietro Incardona committed
915
		float f = vd.getPos(key)[0];
916
		BOOST_REQUIRE_EQUAL(f, 1.0);
Pietro Incardona's avatar
Pietro Incardona committed
917
		f = vd.getPos(key)[1];
918
		BOOST_REQUIRE_EQUAL(f, 1.0);
Pietro Incardona's avatar
Pietro Incardona committed
919
		f = vd.getPos(key)[2];
920 921 922 923 924 925
		BOOST_REQUIRE_EQUAL(f, 1.0);

		++it2;
	}
}

Pietro Incardona's avatar
Pietro Incardona committed
926 927
BOOST_AUTO_TEST_CASE( vector_dist_out_of_bound_policy )
{
928
	Vcluster & v_cl = create_vcluster();
Pietro Incardona's avatar
Pietro Incardona committed
929 930 931 932

	if (v_cl.getProcessingUnits() > 8)
		return;

Pietro Incardona's avatar
Pietro Incardona committed
933 934 935
	Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});

	// Boundary conditions
Pietro Incardona's avatar
Pietro Incardona committed
936 937
	size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};

Pietro Incardona's avatar
Pietro Incardona committed
938
	// factor
939
	float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
Pietro Incardona's avatar
Pietro Incardona committed
940 941 942 943 944

	// ghost
	Ghost<3,float> ghost(0.05 / factor);

	// Distributed vector
incardon's avatar
incardon committed
945
	vector_dist<3,float, Point_test<float> > vd(100,box,bc,ghost);
Pietro Incardona's avatar
Pietro Incardona committed
946 947 948 949 950

	// put particles at out of the boundary, they must be detected and and killed

	auto it = vd.getIterator();

951 952
	size_t cnt = 0;

Pietro Incardona's avatar
Pietro Incardona committed
953 954 955 956
	while (it.isNext())
	{
		auto key = it.get();

957 958
		if (cnt < 1)
		{
Pietro Incardona's avatar
Pietro Incardona committed
959 960 961
			vd.getPos(key)[0] = -0.06;
			vd.getPos(key)[1] = -0.06;
			vd.getPos(key)[2] = -0.06;
962 963 964
		}
		else
		{
Pietro Incardona's avatar
Pietro Incardona committed
965 966 967
			vd.getPos(key)[0] = 0.06;
			vd.getPos(key)[1] = 0.06;
			vd.getPos(key)[2] = 0.06;
968
		}
Pietro Incardona's avatar
Pietro Incardona committed
969

970
		cnt++;
Pietro Incardona's avatar
Pietro Incardona committed
971 972 973
		++it;
	}

Pietro Incardona's avatar
Pietro Incardona committed
974 975
	vd.map();

Pietro Incardona's avatar
Pietro Incardona committed
976 977
	// Particles out of the boundary are killed

978
	size_t cnt_l = vd.size_local();
Pietro Incardona's avatar
Pietro Incardona committed
979

980
	v_cl.sum(cnt_l);