| 1 | /* | 
| 2 |  * vector_dist_MP_unit_tests.hpp | 
| 3 |  * | 
| 4 |  *  Created on: Oct 14, 2016 | 
| 5 |  *      Author: i-bird | 
| 6 |  */ | 
| 7 |  | 
| 8 | #define BOOST_TEST_DYN_LINK | 
| 9 | #include <boost/test/unit_test.hpp> | 
| 10 |  | 
| 11 | #include "Vector/vector_dist_multiphase_functions.hpp" | 
| 12 | #include "VCluster/VCluster.hpp" | 
| 13 | #include "Vector/vector_dist.hpp" | 
| 14 |  | 
| 15 | BOOST_AUTO_TEST_SUITE( vector_dist_multiphase_test ) | 
| 16 |  | 
| 17 | BOOST_AUTO_TEST_CASE( vector_dist_multiphase_cell_list_test ) | 
| 18 | { | 
| 19 | 	if (create_vcluster().getProcessingUnits() > 24) | 
| 20 | 		return; | 
| 21 |  | 
| 22 | 	size_t sz[3] = {60,60,40}; | 
| 23 |  | 
| 24 | 	// The domain | 
| 25 | 	Box<3,float> box({-1000.0,-1000.0,-1000.0},{2000.0,2000.0,1000.0}); | 
| 26 |  | 
| 27 | 	// Boundary conditions | 
| 28 | 	size_t bc[3]={PERIODIC,PERIODIC,PERIODIC}; | 
| 29 |  | 
| 30 | 	int rank_test = create_vcluster().rank(); | 
| 31 | 	float r_cut = 51.0; | 
| 32 |  | 
| 33 | 	// ghost, big enough to contain the interaction radius | 
| 34 | 	Ghost<3,float> ghost(r_cut); | 
| 35 |  | 
| 36 | 	openfpm::vector< vector_dist<3,float, aggregate<double,double>> > phases; | 
| 37 |  | 
| 38 | 	// first phase | 
| 39 | 	phases.add( vector_dist<3,float, aggregate<double,double>>(0,box,bc,ghost) ); | 
| 40 |  | 
| 41 | 	// The other 3 phases | 
| 42 | 	phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),0) ); | 
| 43 | 	phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),0) ); | 
| 44 | 	phases.add( vector_dist<3,float, aggregate<double,double>>(phases.get(0).getDecomposition(),0) ); | 
| 45 |  | 
| 46 | 	// Fill the phases with particles | 
| 47 |  | 
| 48 | 	auto g_it = phases.get(0).getGridIterator(sz); | 
| 49 |  | 
| 50 | 	while (g_it.isNext()) | 
| 51 | 	{ | 
| 52 | 		auto key = g_it.get(); | 
| 53 |  | 
| 54 | 		// Add a particle to all the phases | 
| 55 | 		phases.get(0).add(); | 
| 56 | 		phases.get(1).add(); | 
| 57 | 		phases.get(2).add(); | 
| 58 | 		phases.get(3).add(); | 
| 59 |  | 
| 60 | 		phases.get(0).getLastPos()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 61 | 		phases.get(0).getLastPos()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 62 | 		phases.get(0).getLastPos()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 63 |  | 
| 64 | 		phases.get(1).getLastPos()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 65 | 		phases.get(1).getLastPos()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 66 | 		phases.get(1).getLastPos()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 67 |  | 
| 68 | 		phases.get(2).getLastPos()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 69 | 		phases.get(2).getLastPos()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 70 | 		phases.get(2).getLastPos()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 71 |  | 
| 72 | 		phases.get(3).getLastPos()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 73 | 		phases.get(3).getLastPos()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 74 | 		phases.get(3).getLastPos()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 75 |  | 
| 76 | 		++g_it; | 
| 77 | 	} | 
| 78 |  | 
| 79 | 	// Sync all phases | 
| 80 | 	for (size_t i = 0 ; i < 4 ; i++) | 
| 81 | 	{ | 
| 82 | 		phases.get(i).map(); | 
| 83 | 	} | 
| 84 |  | 
| 85 | 	// randomize a little the particles | 
| 86 |  | 
| 87 | 	for (size_t p = 0 ; p < phases.size() ; p++) | 
| 88 | 	{ | 
| 89 | 		openfpm::vector<Point<3,float>> vt; | 
| 90 |  | 
| 91 | 		for (size_t j = 0 ; j < phases.get(p).size_local() ; j++) | 
| 92 | 		{ | 
| 93 | 			vt.add(phases.get(p).getPos((j + p*133) % phases.get(p).size_local())); | 
| 94 | 		} | 
| 95 | 		phases.get(p).getPosVector().swap(vt); | 
| 96 | 	} | 
| 97 |  | 
| 98 | 	// Sync all phases | 
| 99 | 	for (size_t i = 0 ; i < 4 ; i++) | 
| 100 | 	{ | 
| 101 | 		phases.get(i).ghost_get<>(); | 
| 102 | 	} | 
| 103 |  | 
| 104 | 	// Get the cell list of the phase 0 and 1 | 
| 105 | 	auto CL_phase0 = phases.get(0).getCellList(r_cut); | 
| 106 | 	auto CL_phase1 = phases.get(1).getCellList(r_cut); | 
| 107 |  | 
| 108 | 	// This function create a Verlet-list between phases 0 and 1 | 
| 109 | 	auto NN_ver01 = createVerlet(phases.get(0),phases.get(1),CL_phase1,r_cut); | 
| 110 |  | 
| 111 | 	// Check NNver0_1 | 
| 112 |  | 
| 113 | 	bool ret = true; | 
| 114 | 	auto it = phases.get(0).getDomainIterator(); | 
| 115 |  | 
| 116 | 	while (it.isNext()) | 
| 117 | 	{ | 
| 118 | 		auto p = it.get(); | 
| 119 | 		auto Np = NN_ver01.getNNIterator<NO_CHECK>(p.getKey()); | 
| 120 |  | 
| 121 | 		size_t nn_count = 0; | 
| 122 |  | 
| 123 | 		// For each neighborhood of the particle p | 
| 124 | 		while (Np.isNext()) | 
| 125 | 		{ | 
| 126 | 			// Count the number of particles | 
| 127 | 			nn_count++; | 
| 128 |  | 
| 129 | 			++Np; | 
| 130 | 		} | 
| 131 |  | 
| 132 | 		ret &= nn_count == 7ul; | 
| 133 |  | 
| 134 | 		++it; | 
| 135 | 	} | 
| 136 |  | 
| 137 | 	BOOST_REQUIRE_EQUAL(ret,true); | 
| 138 |  | 
| 139 | 	// Sync all phases | 
| 140 | 	for (size_t i = 0 ; i < 4 ; i++) | 
| 141 | 	{ | 
| 142 | 		phases.get(i).map(); | 
| 143 | 		phases.get(i).ghost_get<>(); | 
| 144 | 	} | 
| 145 |  | 
| 146 | 	// NN_ver0_all | 
| 147 |  | 
| 148 | 	// This function create an "Empty" Multiphase Cell List | 
| 149 | 	auto CL_all = createCellListM<2>(phases,r_cut); | 
| 150 |  | 
| 151 | 	// This create a Verlet-list between phase 0 and all the other phases | 
| 152 | 	auto NNver0_all = createVerletM<2>(0,phases.get(0),phases,CL_all,r_cut); | 
| 153 |  | 
| 154 | 	it = phases.get(0).getDomainIterator(); | 
| 155 |  | 
| 156 | 	while (it.isNext()) | 
| 157 | 	{ | 
| 158 | 		auto p = it.get(); | 
| 159 | 		auto Np = NNver0_all.getNNIterator<NO_CHECK>(p.getKey()); | 
| 160 |  | 
| 161 | 		size_t nn_cout[4] = {0,0,0,0}; | 
| 162 |  | 
| 163 | 		// For each neighborhood of the particle p | 
| 164 | 		while (Np.isNext()) | 
| 165 | 		{ | 
| 166 | 			// Get from which phase it come from | 
| 167 | 			auto ph_q = Np.getV(); | 
| 168 |  | 
| 169 | 			nn_cout[ph_q]++; | 
| 170 |  | 
| 171 | 			++Np; | 
| 172 | 		} | 
| 173 |  | 
| 174 | 		ret &= nn_cout[0] == 7; | 
| 175 | 		ret &= nn_cout[1] == 7; | 
| 176 | 		ret &= nn_cout[2] == 7; | 
| 177 | 		ret &= nn_cout[3] == 7; | 
| 178 |  | 
| 179 | 		++it; | 
| 180 | 	} | 
| 181 |  | 
| 182 | 	BOOST_REQUIRE_EQUAL(ret,true); | 
| 183 | } | 
| 184 |  | 
| 185 |  | 
| 186 | BOOST_AUTO_TEST_CASE( vector_dist_multiphase_cell_list_sym_test ) | 
| 187 | { | 
| 188 | 	if (create_vcluster().getProcessingUnits() > 24) | 
| 189 | 		return; | 
| 190 |  | 
| 191 | 	size_t sz[3] = {60,60,40}; | 
| 192 |  | 
| 193 | 	// The domain | 
| 194 | 	Box<3,float> box({-1000.0,-1000.0,-1000.0},{2000.0,2000.0,1000.0}); | 
| 195 |  | 
| 196 | 	// Boundary conditions | 
| 197 | 	size_t bc[3]={PERIODIC,PERIODIC,PERIODIC}; | 
| 198 |  | 
| 199 | 	float r_cut = 51.0; | 
| 200 |  | 
| 201 | 	// ghost, big enough to contain the interaction radius | 
| 202 | 	Ghost<3,float> ghost(r_cut); | 
| 203 |  | 
| 204 | 	openfpm::vector< vector_dist<3,float, aggregate<size_t>> > phases; | 
| 205 |  | 
| 206 | 	// first phase | 
| 207 | 	phases.add( vector_dist<3,float, aggregate<size_t>>(0,box,bc,ghost) ); | 
| 208 |  | 
| 209 | 	// The other 3 phases | 
| 210 | 	phases.add( vector_dist<3,float, aggregate<size_t>>(phases.get(0).getDecomposition(),0) ); | 
| 211 | 	phases.add( vector_dist<3,float, aggregate<size_t>>(phases.get(0).getDecomposition(),0) ); | 
| 212 | 	phases.add( vector_dist<3,float, aggregate<size_t>>(phases.get(0).getDecomposition(),0) ); | 
| 213 |  | 
| 214 | 	// Fill the phases with particles | 
| 215 |  | 
| 216 | 	auto g_it = phases.get(0).getGridIterator(sz); | 
| 217 |  | 
| 218 | 	while (g_it.isNext()) | 
| 219 | 	{ | 
| 220 | 		auto key = g_it.get(); | 
| 221 |  | 
| 222 | 		// Add a particle to all the phases | 
| 223 | 		phases.get(0).add(); | 
| 224 | 		phases.get(1).add(); | 
| 225 | 		phases.get(2).add(); | 
| 226 | 		phases.get(3).add(); | 
| 227 |  | 
| 228 | 		phases.get(0).getLastPosWrite()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 229 | 		phases.get(0).getLastPosWrite()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 230 | 		phases.get(0).getLastPosWrite()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 231 |  | 
| 232 | 		phases.get(1).getLastPosWrite()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 233 | 		phases.get(1).getLastPosWrite()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 234 | 		phases.get(1).getLastPosWrite()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 235 |  | 
| 236 | 		phases.get(2).getLastPosWrite()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 237 | 		phases.get(2).getLastPosWrite()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 238 | 		phases.get(2).getLastPosWrite()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 239 |  | 
| 240 | 		phases.get(3).getLastPosWrite()[0] = key.get(0) * g_it.getSpacing(0) + box.getLow(0); | 
| 241 | 		phases.get(3).getLastPosWrite()[1] = key.get(1) * g_it.getSpacing(1) + box.getLow(1); | 
| 242 | 		phases.get(3).getLastPosWrite()[2] = key.get(2) * g_it.getSpacing(2) + box.getLow(2); | 
| 243 |  | 
| 244 | 		++g_it; | 
| 245 | 	} | 
| 246 |  | 
| 247 | 	// Sync all phases | 
| 248 | 	for (size_t i = 0 ; i < 4 ; i++) | 
| 249 | 	{ | 
| 250 | 		phases.get(i).map(); | 
| 251 | 	} | 
| 252 |  | 
| 253 | 	// randomize a little the particles | 
| 254 |  | 
| 255 | 	for (size_t p = 0 ; p < phases.size() ; p++) | 
| 256 | 	{ | 
| 257 | 		openfpm::vector<Point<3,float>> vt; | 
| 258 |  | 
| 259 | 		for (size_t j = 0 ; j < phases.get(p).size_local() ; j++) | 
| 260 | 		{ | 
| 261 | 			vt.add(phases.get(p).getPos((j + p*133) % phases.get(p).size_local())); | 
| 262 | 		} | 
| 263 | 		phases.get(p).getPosVector().swap(vt); | 
| 264 | 	} | 
| 265 |  | 
| 266 | 	// Sync all phases | 
| 267 | 	for (size_t i = 0 ; i < 4 ; i++) | 
| 268 | 	{ | 
| 269 | 		phases.get(i).ghost_get<>(); | 
| 270 | 	} | 
| 271 |  | 
| 272 | 	// Get the cell list of the phase 0 and 1 | 
| 273 | 	auto CL_phase0 = phases.get(0).getCellListSym(r_cut); | 
| 274 | 	auto CL_phase1 = phases.get(1).getCellListSym(r_cut); | 
| 275 |  | 
| 276 | 	// This function create a Verlet-list between phases 0 and 1 | 
| 277 | 	auto NN_ver01 = createVerletSym(phases.get(0),phases.get(1),CL_phase1,r_cut); | 
| 278 |  | 
| 279 | 	// Check NNver0_1 | 
| 280 |  | 
| 281 | 	bool ret = true; | 
| 282 | 	auto it = phases.get(0).getDomainIterator(); | 
| 283 |  | 
| 284 | 	while (it.isNext()) | 
| 285 | 	{ | 
| 286 | 		auto p = it.get(); | 
| 287 | 		auto Np = NN_ver01.getNNIterator<NO_CHECK>(p.getKey()); | 
| 288 |  | 
| 289 | 		// For each neighborhood of the particle p | 
| 290 | 		while (Np.isNext()) | 
| 291 | 		{ | 
| 292 | 			// Neighborhood particle q | 
| 293 | 			auto q = Np.get(); | 
| 294 |  | 
| 295 | 			phases.get(0).getPropWrite<0>(p)++; | 
| 296 | 			phases.get(1).getPropWrite<0>(q)++; | 
| 297 |  | 
| 298 | 			++Np; | 
| 299 | 		} | 
| 300 |  | 
| 301 | 		++it; | 
| 302 | 	} | 
| 303 |  | 
| 304 | 	phases.get(0).ghost_put<add_,0>(); | 
| 305 | 	phases.get(1).ghost_put<add_,0>(); | 
| 306 |  | 
| 307 | #ifdef SE_CLASS3 | 
| 308 |  | 
| 309 | 	phases.get(1).getDomainIterator(); | 
| 310 |  | 
| 311 | #endif | 
| 312 |  | 
| 313 | 	it = phases.get(0).getDomainIterator(); | 
| 314 | 	while (it.isNext()) | 
| 315 | 	{ | 
| 316 | 		auto p = it.get(); | 
| 317 |  | 
| 318 | 		ret &= phases.get(0).getPropRead<0>(p) == 7; | 
| 319 | 		ret &= phases.get(1).getPropRead<0>(p) == 7; | 
| 320 |  | 
| 321 | 		++it; | 
| 322 | 	} | 
| 323 |  | 
| 324 | 	BOOST_REQUIRE_EQUAL(ret,true); | 
| 325 |  | 
| 326 | 	// Sync all phases | 
| 327 | 	for (size_t i = 0 ; i < 4 ; i++) | 
| 328 | 	{ | 
| 329 | 		phases.get(i).map(); | 
| 330 | 		phases.get(i).ghost_get<>(); | 
| 331 | 	} | 
| 332 |  | 
| 333 | 	// Reset counter on all phases | 
| 334 |  | 
| 335 | 	for (size_t i = 0 ; i < phases.size() ; i++) | 
| 336 | 	{ | 
| 337 | 		it = phases.get(i).getDomainAndGhostIterator(); | 
| 338 | 		while (it.isNext()) | 
| 339 | 		{ | 
| 340 | 			auto p = it.get(); | 
| 341 |  | 
| 342 | 			phases.get(i).getPropWrite<0>(p) = 0; | 
| 343 |  | 
| 344 | 			++it; | 
| 345 | 		} | 
| 346 | 	} | 
| 347 |  | 
| 348 | 	// NN_ver0_all | 
| 349 |  | 
| 350 | 	// This function create an "Empty" Multiphase Cell List | 
| 351 | 	auto CL_all = createCellListSymM<2>(phases,r_cut); | 
| 352 |  | 
| 353 | 	typedef decltype(createVerletSymM<2>(0,phases.get(0),phases,CL_all,r_cut)) verlet_type; | 
| 354 |  | 
| 355 | 	verlet_type NNver_all[4]; | 
| 356 |  | 
| 357 | 	// This create a Verlet-list between each phase to all the other phases | 
| 358 | 	NNver_all[0] = createVerletSymM<2>(0,phases.get(0),phases,CL_all,r_cut); | 
| 359 | 	NNver_all[1] = createVerletSymM<2>(1,phases.get(1),phases,CL_all,r_cut); | 
| 360 | 	NNver_all[2] = createVerletSymM<2>(2,phases.get(2),phases,CL_all,r_cut); | 
| 361 | 	NNver_all[3] = createVerletSymM<2>(3,phases.get(3),phases,CL_all,r_cut); | 
| 362 |  | 
| 363 | 	// all phases to all phases | 
| 364 |  | 
| 365 | 	for (size_t i = 0 ; i < phases.size() ; i++) | 
| 366 | 	{ | 
| 367 | 		it = phases.get(i).getDomainIterator(); | 
| 368 |  | 
| 369 | 		while (it.isNext()) | 
| 370 | 		{ | 
| 371 | 			auto p = it.get(); | 
| 372 | 			auto Np = NNver_all[i].getNNIterator<NO_CHECK>(p.getKey()); | 
| 373 |  | 
| 374 | 			// For each neighborhood of the particle p | 
| 375 | 			while (Np.isNext()) | 
| 376 | 			{ | 
| 377 | 				// Get the particle q near to p | 
| 378 | 				auto q = Np.getP(); | 
| 379 |  | 
| 380 | 				// Get from which phase it come from | 
| 381 | 				auto ph_q = Np.getV(); | 
| 382 |  | 
| 383 | 				phases.get(i).getPropWrite<0>(p)++; | 
| 384 | 				phases.get(ph_q).getPropWrite<0>(q)++; | 
| 385 |  | 
| 386 | 				++Np; | 
| 387 | 			} | 
| 388 |  | 
| 389 | 			++it; | 
| 390 | 		} | 
| 391 | 	} | 
| 392 |  | 
| 393 | 	phases.get(0).ghost_put<add_,0>(); | 
| 394 | 	phases.get(1).ghost_put<add_,0>(); | 
| 395 | 	phases.get(2).ghost_put<add_,0>(); | 
| 396 | 	phases.get(3).ghost_put<add_,0>(); | 
| 397 |  | 
| 398 | #ifdef SE_CLASS3 | 
| 399 |  | 
| 400 | 	it = phases.get(1).getDomainIterator(); | 
| 401 | 	it = phases.get(2).getDomainIterator(); | 
| 402 | 	it = phases.get(3).getDomainIterator(); | 
| 403 |  | 
| 404 | #endif | 
| 405 |  | 
| 406 | 	it = phases.get(0).getDomainIterator(); | 
| 407 | 	while (it.isNext()) | 
| 408 | 	{ | 
| 409 | 		auto p = it.get(); | 
| 410 |  | 
| 411 | 		ret &= phases.get(0).getPropRead<0>(p) == 32; | 
| 412 | 		ret &= phases.get(1).getPropRead<0>(p) == 32; | 
| 413 | 		ret &= phases.get(2).getPropRead<0>(p) == 32; | 
| 414 | 		ret &= phases.get(3).getPropRead<0>(p) == 32; | 
| 415 |  | 
| 416 | 		if (ret == false) | 
| 417 | 		{ | 
| 418 | 			std::cout << phases.get(0).getPropRead<0>(p) << std::endl; | 
| 419 | 			std::cout << phases.get(1).getPropRead<0>(p) << std::endl; | 
| 420 | 			std::cout << phases.get(2).getPropRead<0>(p) << std::endl; | 
| 421 | 			std::cout << phases.get(3).getPropRead<0>(p) << std::endl; | 
| 422 | 		} | 
| 423 |  | 
| 424 | 		++it; | 
| 425 | 	} | 
| 426 |  | 
| 427 | 	BOOST_REQUIRE_EQUAL(ret,true); | 
| 428 | } | 
| 429 |  | 
| 430 | BOOST_AUTO_TEST_SUITE_END() | 
| 431 |  | 
| 432 |  |