| 1 | /* | 
| 2 |  * CellList.hpp | 
| 3 |  * | 
| 4 |  *  Created on: Mar 21, 2015 | 
| 5 |  *      Author: Pietro Incardona | 
| 6 |  */ | 
| 7 |  | 
| 8 | #ifndef CELLLIST_HPP_ | 
| 9 | #define CELLLIST_HPP_ | 
| 10 |  | 
| 11 | #include "CellList_def.hpp" | 
| 12 | #include "Vector/map_vector.hpp" | 
| 13 | #include "CellDecomposer.hpp" | 
| 14 | #include "Space/SpaceBox.hpp" | 
| 15 | #include "util/mathutil.hpp" | 
| 16 | #include "CellNNIterator.hpp" | 
| 17 | #include "Space/Shape/HyperCube.hpp" | 
| 18 | #include "CellListNNIteratorRadius.hpp" | 
| 19 | #include <unordered_map> | 
| 20 |  | 
| 21 | #include "CellListIterator.hpp" | 
| 22 | #include "ParticleIt_Cells.hpp" | 
| 23 | #include "ParticleItCRS_Cells.hpp" | 
| 24 | #include "util/common.hpp" | 
| 25 |  | 
| 26 | #include "NN/Mem_type/MemFast.hpp" | 
| 27 | #include "NN/Mem_type/MemBalanced.hpp" | 
| 28 | #include "NN/Mem_type/MemMemoryWise.hpp" | 
| 29 | #include "NN/CellList/NNc_array.hpp" | 
| 30 | #include "cuda/CellList_cpu_ker.cuh" | 
| 31 |  | 
| 32 | //! Wrapper of the unordered map | 
| 33 | template<typename key,typename val> | 
| 34 | class wrap_unordered_map: public std::unordered_map<key,val> | 
| 35 | { | 
| 36 | }; | 
| 37 |  | 
| 38 | #ifdef HAVE_LIBQUADMATH | 
| 39 |  | 
| 40 | #include <boost/multiprecision/float128.hpp> | 
| 41 |  | 
| 42 |  | 
| 43 | //! Wrapper of the unordered map | 
| 44 | template<typename val> | 
| 45 | class wrap_unordered_map<boost::multiprecision::float128,val> | 
| 46 | { | 
| 47 | }; | 
| 48 |  | 
| 49 | #endif | 
| 50 |  | 
| 51 | //! Point at witch the cell do a reallocation (it should the the maximum for all the implementations) | 
| 52 | #define CELL_REALLOC 16ul | 
| 53 |  | 
| 54 | #define STARTING_NSLOT 16 | 
| 55 |  | 
| 56 | /*! \brief Calculate the the Neighborhood for symmetric interactions CSR scheme | 
| 57 |  * | 
| 58 |  * \param cNN calculated cross neighborhood | 
| 59 |  * \param div Number of divisions in each direction | 
| 60 |  * | 
| 61 |  */ | 
| 62 | template<unsigned int dim> void NNcalc_csr(openfpm::vector<std::pair<grid_key_dx<dim>,grid_key_dx<dim>>> & cNN) | 
| 63 | { | 
| 64 | 	// Calculate the NNc_full array, it is a structure to get the neighborhood array | 
| 65 |  | 
| 66 | 	// compile-time array {0,0,0,....}  {2,2,2,...} {1,1,1,...} | 
| 67 |  | 
| 68 | 	typedef typename generate_array<size_t,dim, Fill_zero>::result NNzero; | 
| 69 | 	typedef typename generate_array<size_t,dim, Fill_two>::result NNtwo; | 
| 70 |  | 
| 71 | 	// Generate the sub-grid iterator | 
| 72 |  | 
| 73 | 	size_t div[dim]; | 
| 74 |  | 
| 75 | 	// Calculate the divisions | 
| 76 |  | 
| 77 | 	for (size_t i = 0 ; i < dim ; i++) | 
| 78 | 		div[i] = 4; | 
| 79 |  | 
| 80 | 	grid_sm<dim,void> gs(div); | 
| 81 | 	grid_key_dx_iterator_sub<dim> gr_sub3(gs,NNzero::data,NNtwo::data); | 
| 82 |  | 
| 83 | 	grid_key_dx<dim> src_; // Source cell | 
| 84 | 	for (size_t i = 0; i < dim; i++) | 
| 85 | 		src_.set_d(i,1); | 
| 86 |  | 
| 87 | 	size_t middle = gs.LinId(src_); | 
| 88 |  | 
| 89 | 	// Calculate the symmetric crs array | 
| 90 | 	while (gr_sub3.isNext()) | 
| 91 | 	{ | 
| 92 | 		auto dst = gr_sub3.get(); | 
| 93 | 		grid_key_dx<dim> src = src_; | 
| 94 |  | 
| 95 | 		if ((long int)middle > gs.LinId(dst)) | 
| 96 | 		{ | 
| 97 | 			++gr_sub3; | 
| 98 | 			continue; | 
| 99 | 		} | 
| 100 |  | 
| 101 | 		// Here we adjust src and dst to be in the positive quadrant | 
| 102 |  | 
| 103 | 		for (size_t i = 0 ; i < dim; i++) | 
| 104 | 		{ | 
| 105 | 			if (dst.get(i) == 0) | 
| 106 | 			{ | 
| 107 | 				src.set_d(i,src.get(i) + 1); | 
| 108 | 				dst.set_d(i,dst.get(i) + 1); | 
| 109 | 			} | 
| 110 | 		} | 
| 111 |  | 
| 112 | 		src -= src_; | 
| 113 | 		dst -= src_; | 
| 114 |  | 
| 115 | 		cNN.add(std::pair<grid_key_dx<dim>,grid_key_dx<dim>>(src,dst)); | 
| 116 |  | 
| 117 | 		++gr_sub3; | 
| 118 |  | 
| 119 | 	} | 
| 120 | }; | 
| 121 |  | 
| 122 | /*! \brief Calculate the the Neighborhood for symmetric interactions | 
| 123 |  * | 
| 124 |  * \param cNN calculated cross neighborhood | 
| 125 |  * \param div Number of divisions in each direction | 
| 126 |  * | 
| 127 |  */ | 
| 128 | template<unsigned int dim> void NNcalc_sym(openfpm::vector<grid_key_dx<dim>> & cNN) | 
| 129 | { | 
| 130 | 	// Calculate the NNc_full array, it is a structure to get the neighborhood array | 
| 131 |  | 
| 132 | 	// compile-time array {0,0,0,....}  {2,2,2,...} {1,1,1,...} | 
| 133 |  | 
| 134 | 	typedef typename generate_array<size_t,dim, Fill_zero>::result NNzero; | 
| 135 | 	typedef typename generate_array<size_t,dim, Fill_two>::result NNtwo; | 
| 136 |  | 
| 137 | 	// Generate the sub-grid iterator | 
| 138 |  | 
| 139 | 	size_t div[dim]; | 
| 140 |  | 
| 141 | 	// Calculate the divisions | 
| 142 |  | 
| 143 | 	for (size_t i = 0 ; i < dim ; i++) | 
| 144 | 		div[i] = 4; | 
| 145 |  | 
| 146 | 	grid_sm<dim,void> gs(div); | 
| 147 | 	grid_key_dx_iterator_sub<dim> gr_sub3(gs,NNzero::data,NNtwo::data); | 
| 148 |  | 
| 149 | 	grid_key_dx<dim> src_; // Source cell | 
| 150 | 	for (size_t i = 0; i < dim; i++) | 
| 151 | 		src_.set_d(i,1); | 
| 152 |  | 
| 153 | 	size_t middle = gs.LinId(src_); | 
| 154 |  | 
| 155 | 	// Calculate the symmetric array | 
| 156 | 	while (gr_sub3.isNext()) | 
| 157 | 	{ | 
| 158 | 		auto dst = gr_sub3.get(); | 
| 159 |  | 
| 160 | 		if ((long int)middle > gs.LinId(dst)) | 
| 161 | 		{ | 
| 162 | 			++gr_sub3; | 
| 163 | 			continue; | 
| 164 | 		} | 
| 165 |  | 
| 166 | 		cNN.add(dst - src_); | 
| 167 |  | 
| 168 | 		++gr_sub3; | 
| 169 |  | 
| 170 | 	} | 
| 171 | }; | 
| 172 |  | 
| 173 | /*! \brief Calculate the Neighborhood cells | 
| 174 |  * | 
| 175 |  * \param cNN calculated cross neighborhood | 
| 176 |  * \param div Number of divisions in each direction | 
| 177 |  * | 
| 178 |  */ | 
| 179 | template<unsigned int dim> void NNcalc_full(openfpm::vector<grid_key_dx<dim>> & cNN) | 
| 180 | { | 
| 181 | 	// Calculate the NNc_full array, it is a structure to get the neighborhood array | 
| 182 |  | 
| 183 | 	// compile-time array {0,0,0,....}  {2,2,2,...} {1,1,1,...} | 
| 184 |  | 
| 185 | 	typedef typename generate_array<size_t,dim, Fill_zero>::result NNzero; | 
| 186 | 	typedef typename generate_array<size_t,dim, Fill_two>::result NNtwo; | 
| 187 |  | 
| 188 | 	// Generate the sub-grid iterator | 
| 189 |  | 
| 190 | 	size_t div[dim]; | 
| 191 |  | 
| 192 | 	// Calculate the divisions | 
| 193 |  | 
| 194 | 	for (size_t i = 0 ; i < dim ; i++) | 
| 195 | 	{div[i] = 4;} | 
| 196 |  | 
| 197 | 	grid_sm<dim,void> gs(div); | 
| 198 | 	grid_key_dx_iterator_sub<dim> gr_sub3(gs,NNzero::data,NNtwo::data); | 
| 199 |  | 
| 200 | 	grid_key_dx<dim> src_; // Source cell | 
| 201 | 	for (size_t i = 0; i < dim; i++) | 
| 202 | 		src_.set_d(i,1); | 
| 203 |  | 
| 204 | 	// Calculate the symmetric crs array | 
| 205 | 	while (gr_sub3.isNext()) | 
| 206 | 	{ | 
| 207 | 		auto dst = gr_sub3.get(); | 
| 208 |  | 
| 209 | 		cNN.add(dst - src_); | 
| 210 |  | 
| 211 | 		++gr_sub3; | 
| 212 | 	} | 
| 213 | }; | 
| 214 |  | 
| 215 |  | 
| 216 | /*! Calculate the neighborhood cells based on the radius | 
| 217 |  * | 
| 218 |  * \note To the calculated neighborhood cell you have to add the id of the central cell | 
| 219 |  * | 
| 220 | 	\verbatim | 
| 221 |    +-----------------------+ | 
| 222 |    |p |p |p |p |p |p |p |p | | 
| 223 |    +-----------------------+ | 
| 224 |    |p |  |  |  |  |  |  |p | | 
| 225 |    +-----------------------+ | 
| 226 |    |p |  |  |7 |8 |9 |  |p | | 
| 227 |    +-----------------------+ | 
| 228 |    |p |  |  |-1|0 |1 |  |p | | 
| 229 |    +-----------------------+ | 
| 230 |    |p |9 |  |-9|-8|-7|  |p | | 
| 231 |    +-----------------------+ | 
| 232 |    |p |p |p |p |p |p |p |p | | 
| 233 |    +-----------------------+ | 
| 234 | 	\endverbatim | 
| 235 |  * | 
| 236 |  * The number indicate the cell id calculated | 
| 237 |  * | 
| 238 |  * -9,-8,-7,-1,0,1,7,8,9 | 
| 239 |  * | 
| 240 |  * The cell 0 has id = 22 in the big cell matrix, so to calculate the | 
| 241 |  * neighborhood cells you have to sum the id of the center cell | 
| 242 |  * | 
| 243 |  * 13,14,15,21,22,23,29,30,31 | 
| 244 |  * | 
| 245 |  * \param r_cut Cutoff-radius | 
| 246 |  * \param NNcell vector containing the neighborhood cells ids | 
| 247 |  * | 
| 248 |  */ | 
| 249 | template<unsigned int dim, typename T> | 
| 250 | void NNcalc_rad(T r_cut, openfpm::vector<long int> & NNcell, const Box<dim,T> & cell_box, const grid_sm<dim,void> & gs) | 
| 251 | { | 
| 252 | 	size_t n_cell[dim]; | 
| 253 | 	size_t n_cell_mid[dim]; | 
| 254 |  | 
| 255 | 	Point<dim,T> spacing = cell_box.getP2(); | 
| 256 |  | 
| 257 | 	for (size_t i = 0 ; i < dim ; i++) | 
| 258 | 	{ | 
| 259 | 		n_cell[i] = 2*(std::ceil(r_cut / spacing.get(i)))+1; | 
| 260 | 		n_cell_mid[i] = n_cell[i] / 2; | 
| 261 | 	} | 
| 262 |  | 
| 263 | 	grid_sm<dim,void> gsc(n_cell); | 
| 264 | 	grid_key_dx_iterator<dim> gkdi(gsc); | 
| 265 |  | 
| 266 | 	Box<dim,T> cell_zero; | 
| 267 |  | 
| 268 | 	for (unsigned int i = 0 ; i < dim ; i++) | 
| 269 | 	{ | 
| 270 | 		cell_zero.setLow(i,n_cell_mid[i]*spacing.get(i)); | 
| 271 | 		cell_zero.setHigh(i,(n_cell_mid[i]+1)*spacing.get(i)); | 
| 272 | 	} | 
| 273 |  | 
| 274 | 	NNcell.clear(); | 
| 275 | 	while (gkdi.isNext()) | 
| 276 | 	{ | 
| 277 | 		auto key = gkdi.get(); | 
| 278 |  | 
| 279 | 		Box<dim,T> cell; | 
| 280 |  | 
| 281 | 		for (unsigned int i = 0 ; i < dim ; i++) | 
| 282 | 		{ | 
| 283 | 			cell.setLow(i,key.get(i)*spacing.get(i)); | 
| 284 | 			cell.setHigh(i,(key.get(i)+1)*spacing.get(i)); | 
| 285 | 		} | 
| 286 |  | 
| 287 | 		// here we check if the cell is in the radius. | 
| 288 | 		T min_distance = cell.min_distance(cell_zero); | 
| 289 | 		if (min_distance > r_cut) | 
| 290 | 		{++gkdi;continue;} | 
| 291 |  | 
| 292 | 		for (size_t i = 0 ; i < dim ; i++) | 
| 293 | 		{key.set_d(i,key.get(i) - n_cell_mid[i]);} | 
| 294 |  | 
| 295 | 		NNcell.add(gs.LinId(key)); | 
| 296 |  | 
| 297 | 		++gkdi; | 
| 298 | 	} | 
| 299 | } | 
| 300 |  | 
| 301 | /* NOTE all the implementations | 
| 302 |  * | 
| 303 |  * has complexity O(1) in getting the cell id and the elements in a cell | 
| 304 |  * but with different constants | 
| 305 |  * | 
| 306 |  */ | 
| 307 |  | 
| 308 | /*! \brief Class for FAST cell list implementation | 
| 309 |  * | 
| 310 |  * This class implement the FAST cell list, fast but memory | 
| 311 |  * expensive. The memory allocation is (M * N_cell_max)*sizeof(ele) + M*8 | 
| 312 |  * | 
| 313 |  * * M = number of cells | 
| 314 |  * * N_cell_max = maximum number of elements in a cell | 
| 315 |  * * ele = element the structure is storing | 
| 316 |  * | 
| 317 |  * \note Because N_cell_max >= N/M then M * N_cell_max >= O(N) | 
| 318 |  * | 
| 319 |  * \warning Not not use for high asymmetric distribution | 
| 320 |  * | 
| 321 |  * Example of a 2D Cell list 6x6 structure with padding 1 without shift, cell indicated with p are padding cell | 
| 322 |  * the origin of the cell or point (0,0) is marked with cell number 9 | 
| 323 |  * | 
| 324 |  * \verbatim | 
| 325 |  * +-----------------------+ | 
| 326 |  * |p |p |p |p |p |p |p |p | | 
| 327 |  * +-----------------------+ | 
| 328 |  * |p |  |  |  |  |  |  |p | | 
| 329 |  * +-----------------------+ | 
| 330 |  * |p |  |  |  |  |  |  |p | | 
| 331 |  * +-----------------------+ | 
| 332 |  * |p |  |  |  |  |  |  |p | | 
| 333 |  * +-----------------------+ | 
| 334 |  * |p |9 |  |  |  |  |  |p | | 
| 335 |  * +-----------------------+ | 
| 336 |  * |p |p |p |p |p |p |p |p | | 
| 337 |  * +-----------------------+ | 
| 338 |  * \endverbatim | 
| 339 |  * | 
| 340 |  * | 
| 341 |  * \tparam dim Dimensionality of the space | 
| 342 |  * \tparam T type of the space float, double ... | 
| 343 |  * \tparam base Base structure that store the information | 
| 344 |  * | 
| 345 |  * ### Declaration of a cell list | 
| 346 |  * \snippet CellList_test.hpp Declare a cell list | 
| 347 |  * ### Usage of cell list [CellS == CellList<3,double,FAST>] | 
| 348 |  * \snippet CellList_test.hpp Usage of cell list | 
| 349 |  * ### Remove one particle from each cell | 
| 350 |  * \snippet CellList_test.hpp remove one particle from each cell | 
| 351 |  * ### Usage of the neighborhood iterator | 
| 352 |  * \snippet CellList_test.hpp Usage of the neighborhood iterator | 
| 353 |  * | 
| 354 |  */ | 
| 355 | template<unsigned int dim, typename T,  typename Mem_type, typename transform = no_transform<dim,T>, typename vector_pos_type = openfpm::vector<Point<dim,T>>> | 
| 356 | class CellList : public CellDecomposer_sm<dim,T,transform>, public Mem_type | 
| 357 | { | 
| 358 | protected: | 
| 359 | 	//! The array contain the neighborhood of the cell-id in case of asymmetric interaction | 
| 360 | 	// | 
| 361 | 	//    * * * | 
| 362 | 	//    * x * | 
| 363 | 	//    * * * | 
| 364 |  | 
| 365 |  | 
| 366 | 	NNc_array<dim,(unsigned int)openfpm::math::pow(3,dim)> NNc_full; | 
| 367 |  | 
| 368 | 	//! The array contain the neighborhood of the cell-id in case of symmetric interaction | 
| 369 | 	// | 
| 370 | 	//   * * * | 
| 371 | 	//     x * | 
| 372 | 	// | 
| 373 | //	long int NNc_sym[openfpm::math::pow(3,dim)/2+1]; | 
| 374 | 	NNc_array<dim,(unsigned int)openfpm::math::pow(3,dim)/2+1> NNc_sym; | 
| 375 |  | 
| 376 | private: | 
| 377 |  | 
| 378 | 	//! Caching of r_cutoff radius | 
| 379 | 	wrap_unordered_map<T,openfpm::vector<long int>> rcache; | 
| 380 |  | 
| 381 | 	//! True if has been initialized from CellDecomposer | 
| 382 | 	bool from_cd; | 
| 383 |  | 
| 384 | 	//! Additional information in general (used to understand if the cell-list) | 
| 385 | 	//! has been constructed from an old decomposition | 
| 386 | 	size_t n_dec; | 
| 387 |  | 
| 388 | 	//! Cells for the neighborhood radius | 
| 389 | 	openfpm::vector<long int> nnc_rad; | 
| 390 |  | 
| 391 |  | 
| 392 |  | 
| 393 | 	//! Initialize the structures of the data structure | 
| 394 | 	void InitializeStructures(const size_t (& div)[dim], size_t tot_n_cell, size_t slot=STARTING_NSLOT) | 
| 395 | 	{ | 
| 396 | 		Mem_type::init_to_zero(slot,tot_n_cell); | 
| 397 |  | 
| 398 | 		NNc_full.set_size(div); | 
| 399 | 		NNc_full.init_full(); | 
| 400 |  | 
| 401 | 		NNc_sym.set_size(div); | 
| 402 | 		NNc_sym.init_sym(); | 
| 403 | 	} | 
| 404 |  | 
| 405 | 	void setCellDecomposer(CellDecomposer_sm<dim,T,transform> & cd, const CellDecomposer_sm<dim,T,transform> & cd_sm, const Box<dim,T> & dom_box, size_t pad) const | 
| 406 | 	{ | 
| 407 | 		size_t bc[dim]; | 
| 408 |  | 
| 409 | 		for (size_t i = 0 ; i < dim ; i++) | 
| 410 | 		{bc[i] = NON_PERIODIC;} | 
| 411 |  | 
| 412 | 		Box<dim,long int> bx = cd_sm.convertDomainSpaceIntoCellUnits(dom_box,bc); | 
| 413 |  | 
| 414 | 		size_t div[dim]; | 
| 415 | 		size_t div_big[dim]; | 
| 416 |  | 
| 417 | 		for (size_t i = 0 ; i < dim ; i++) | 
| 418 | 		{ | 
| 419 | 			div[i] = bx.getHigh(i) - bx.getLow(i); | 
| 420 | 			div_big[i] = cd_sm.getDiv()[i] - 2*cd_sm.getPadding(i); | 
| 421 | 		} | 
| 422 |  | 
| 423 | 		cd.setDimensions(cd_sm.getDomain(),div_big,div, pad, bx.getP1()); | 
| 424 | 	} | 
| 425 |  | 
| 426 | public: | 
| 427 |  | 
| 428 | 	//! Type of internal memory structure | 
| 429 | 	typedef Mem_type Mem_type_type; | 
| 430 |  | 
| 431 | 	typedef CellNNIteratorSym<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,vector_pos_type,RUNTIME,NO_CHECK> SymNNIterator; | 
| 432 |  | 
| 433 | 	//! Object type that the structure store | 
| 434 | 	typedef typename Mem_type::local_index_type value_type; | 
| 435 |  | 
| 436 | 	//! Type of the coordinate space (double float) | 
| 437 | 	typedef T stype; | 
| 438 |  | 
| 439 | 	//! | 
| 440 | 	typedef vector_pos_type internal_vector_pos_type; | 
| 441 |  | 
| 442 | 	/*! \brief Return the underlying grid information of the cell list | 
| 443 | 	 * | 
| 444 | 	 * \return the grid infos | 
| 445 | 	 * | 
| 446 | 	 */ | 
| 447 | 	const grid_sm<dim,void> & getGrid() | 
| 448 | 	{ | 
| 449 | 		return CellDecomposer_sm<dim,T,transform>::getGrid(); | 
| 450 | 	} | 
| 451 |  | 
| 452 | 	/*! Initialize the cell list from a well-define Cell-decomposer | 
| 453 | 	 * | 
| 454 | 	 * In some cases is needed to have a Cell-list with Cells consistent | 
| 455 | 	 * with a well predefined CellDecomposer. In this case we use this function. | 
| 456 | 	 * Using this initialization the Cell-list maintain the Cells defined by this | 
| 457 | 	 * Cell-decomposer consistently | 
| 458 | 	 * | 
| 459 | 	 * \param cd_sm Cell-Decomposer | 
| 460 | 	 * \param dom_box domain box (carefully this is going to be adjusted) | 
| 461 | 	 * \param pad cell-list padding | 
| 462 | 	 * \param slot slots for each cell | 
| 463 | 	 * | 
| 464 | 	 */ | 
| 465 | 	void Initialize(CellDecomposer_sm<dim,T,transform> & cd_sm, const Box<dim,T> & dom_box,const size_t pad = 1, size_t slot=STARTING_NSLOT) | 
| 466 | 	{ | 
| 467 | 		size_t bc[dim]; | 
| 468 | 		for (size_t i = 0 ; i < dim ; i++)	{bc[i] = NON_PERIODIC;} | 
| 469 |  | 
| 470 | 		Box<dim,long int> bx = cd_sm.convertDomainSpaceIntoCellUnits(dom_box,bc); | 
| 471 |  | 
| 472 | 		setCellDecomposer(*this,cd_sm,dom_box,pad); | 
| 473 |  | 
| 474 | 		size_t div_w_pad[dim]; | 
| 475 | 		size_t tot_cell = 1; | 
| 476 |  | 
| 477 | 		for (size_t i = 0 ; i < dim ; i++) | 
| 478 | 		{ | 
| 479 | 			div_w_pad[i] = bx.getHigh(i) - bx.getLow(i) + 2*pad; | 
| 480 | 			tot_cell *= div_w_pad[i]; | 
| 481 | 		} | 
| 482 |  | 
| 483 | 		// here we set the cell-shift for the CellDecomposer | 
| 484 |  | 
| 485 | 		InitializeStructures(div_w_pad,tot_cell); | 
| 486 |  | 
| 487 | 		// Initialized from CellDecomposer | 
| 488 | 		from_cd = true; | 
| 489 | 	} | 
| 490 |  | 
| 491 | 	/*! Initialize the cell list | 
| 492 | 	 * | 
| 493 | 	 * \param box Domain where this cell list is living | 
| 494 | 	 * \param div grid size on each dimension | 
| 495 | 	 * \param pad padding cell | 
| 496 | 	 * \param slot maximum number of slot | 
| 497 | 	 * | 
| 498 | 	 */ | 
| 499 | 	void Initialize(const Box<dim,T> & box, const size_t (&div)[dim], const size_t pad = 1, size_t slot=STARTING_NSLOT) | 
| 500 | 	{ | 
| 501 | 		SpaceBox<dim,T> sbox(box); | 
| 502 |  | 
| 503 | 		// Initialize point transformation | 
| 504 |  | 
| 505 | 		Initialize(sbox,div,pad,slot); | 
| 506 | 	} | 
| 507 |  | 
| 508 | 	/*! Initialize the cell list constructor | 
| 509 | 	 * | 
| 510 | 	 * \param box Domain where this cell list is living | 
| 511 | 	 * \param div grid size on each dimension | 
| 512 | 	 * \param pad padding cell | 
| 513 | 	 * \param slot maximum number of slot | 
| 514 | 	 * | 
| 515 | 	 */ | 
| 516 | 	void Initialize(const SpaceBox<dim,T> & box, const size_t (&div)[dim], const size_t pad = 1, size_t slot=STARTING_NSLOT) | 
| 517 | 	{ | 
| 518 | 		Matrix<dim,T> mat; | 
| 519 |  | 
| 520 | 		CellDecomposer_sm<dim,T,transform>::setDimensions(box,div, mat, pad); | 
| 521 | 		Mem_type::set_slot(slot); | 
| 522 |  | 
| 523 | 		// create the array that store the number of particle on each cell and se it to 0 | 
| 524 | 		InitializeStructures(this->gr_cell.getSize(),this->gr_cell.size()); | 
| 525 |  | 
| 526 | 		from_cd = false; | 
| 527 | 	} | 
| 528 |  | 
| 529 | 	//! Default Constructor | 
| 530 | 	CellList() | 
| 531 |  | 
| 532 | 	:Mem_type(STARTING_NSLOT) | 
| 533 | 	{}; | 
| 534 |  | 
| 535 | 	//! Copy constructor | 
| 536 | 	CellList(const CellList<dim,T,Mem_type,transform,vector_pos_type> & cell) | 
| 537 | 	:Mem_type(STARTING_NSLOT) | 
| 538 | 	{ | 
| 539 | 		this->operator=(cell); | 
| 540 | 	} | 
| 541 |  | 
| 542 | 	//! Copy constructor | 
| 543 | 	CellList(CellList<dim,T,Mem_type,transform,vector_pos_type> && cell) | 
| 544 | 	:Mem_type(STARTING_NSLOT) | 
| 545 | 	{ | 
| 546 | 		this->operator=(cell); | 
| 547 | 	} | 
| 548 |  | 
| 549 |  | 
| 550 | 	/*! \brief Cell list constructor | 
| 551 | 	 * | 
| 552 | 	 * \param box Domain where this cell list is living | 
| 553 | 	 * \param div grid size on each dimension | 
| 554 | 	 * \param mat Matrix transformation | 
| 555 | 	 * \param pad Cell padding | 
| 556 | 	 * \param slot maximum number of slot | 
| 557 | 	 * | 
| 558 | 	 */ | 
| 559 | 	CellList(Box<dim,T> & box, const size_t (&div)[dim], Matrix<dim,T> mat, const size_t pad = 1, size_t slot=STARTING_NSLOT) | 
| 560 | 	:Mem_type(slot),CellDecomposer_sm<dim,T,transform>(box,div,mat,box.getP1(),pad) | 
| 561 | 	{ | 
| 562 | 		SpaceBox<dim,T> sbox(box); | 
| 563 | 		Initialize(sbox,div,pad,slot); | 
| 564 | 	} | 
| 565 |  | 
| 566 | 	/*! \brief Cell list constructor | 
| 567 | 	 * | 
| 568 | 	 * \param box Domain where this cell list is living | 
| 569 | 	 * \param div grid size on each dimension | 
| 570 | 	 * \param pad Cell padding | 
| 571 | 	 * \param slot maximum number of slot | 
| 572 | 	 * | 
| 573 | 	 */ | 
| 574 | 	CellList(Box<dim,T> & box, const size_t (&div)[dim], const size_t pad = 1, size_t slot=STARTING_NSLOT) | 
| 575 | 	:Mem_type(slot),n_dec(0) | 
| 576 | 	{ | 
| 577 | 		SpaceBox<dim,T> sbox(box); | 
| 578 | 		Initialize(sbox,div,pad,slot); | 
| 579 | 	} | 
| 580 |  | 
| 581 | 	/*! \brief Cell list constructor | 
| 582 | 	 * | 
| 583 | 	 * \param box Domain where this cell list is living | 
| 584 | 	 * \param div grid size on each dimension | 
| 585 | 	 * \param pad Cell padding | 
| 586 | 	 * \param slot maximum number of slot | 
| 587 | 	 * | 
| 588 | 	 */ | 
| 589 | 	CellList(SpaceBox<dim,T> & box, const size_t (&div)[dim], const size_t pad = 1, size_t slot=STARTING_NSLOT) | 
| 590 | 	:Mem_type(slot) | 
| 591 | 	{ | 
| 592 | 		Initialize(box,div,pad,slot); | 
| 593 | 	} | 
| 594 |  | 
| 595 | 	/*! \brief Cell list constructor from a cell decomposer | 
| 596 | 	 * | 
| 597 | 	 * \see Initialize | 
| 598 | 	 * | 
| 599 | 	 * \param cd_sm Cell-Decomposer | 
| 600 | 	 * \param box domain box (carefully this is going to be adjusted) | 
| 601 | 	 * \param pad Cell list padding | 
| 602 | 	 * \param slot number of slot for each cell | 
| 603 | 	 * | 
| 604 | 	 */ | 
| 605 | 	CellList(CellDecomposer_sm<dim,T,transform> & cd_sm, const Box<dim,T> & box, const size_t pad = 1, size_t slot=STARTING_NSLOT) | 
| 606 | 	:Mem_type(slot),n_dec(0) | 
| 607 | 	{ | 
| 608 | 		Initialize(cd_sm,box,pad,slot); | 
| 609 | 	} | 
| 610 |  | 
| 611 | 	/*! \brief Destructor | 
| 612 | 	 * | 
| 613 | 	 * | 
| 614 | 	 */ | 
| 615 | 	~CellList() | 
| 616 | 	{} | 
| 617 |  | 
| 618 | 	/*! \brief Constructor from a temporal object | 
| 619 | 	 * | 
| 620 | 	 * \param cell Cell list structure | 
| 621 | 	 * | 
| 622 | 	 * \return itself | 
| 623 | 	 * | 
| 624 | 	 */ | 
| 625 | 	CellList<dim,T,Mem_type,transform> & operator=(CellList<dim,T,Mem_type,transform> && cell) | 
| 626 | 	{ | 
| 627 | 		std::copy(&cell.NNc_full[0],&cell.NNc_full[openfpm::math::pow(3,dim)],&NNc_full[0]); | 
| 628 | 		std::copy(&cell.NNc_sym[0],&cell.NNc_sym[openfpm::math::pow(3,dim)/2+1],&NNc_sym[0]); | 
| 629 |  | 
| 630 | 		Mem_type::swap(static_cast<Mem_type &&>(cell)); | 
| 631 |  | 
| 632 | 		static_cast<CellDecomposer_sm<dim,T,transform> &>(*this).swap(cell); | 
| 633 |  | 
| 634 | 		n_dec = cell.n_dec; | 
| 635 | 		from_cd = cell.from_cd; | 
| 636 |  | 
| 637 | 		return *this; | 
| 638 | 	} | 
| 639 |  | 
| 640 | 	/*! \brief Constructor from a temporal object | 
| 641 | 	 * | 
| 642 | 	 * \param cell Cell list structure | 
| 643 | 	 * | 
| 644 | 	 * \return itself | 
| 645 | 	 * | 
| 646 | 	 */ | 
| 647 | 	CellList<dim,T,Mem_type,transform,vector_pos_type> & operator=(const CellList<dim,T,Mem_type,transform,vector_pos_type> & cell) | 
| 648 | 	{ | 
| 649 | 		NNc_full = cell.NNc_full; | 
| 650 | 		NNc_sym = cell.NNc_sym; | 
| 651 |  | 
| 652 | 		Mem_type::operator=(static_cast<const Mem_type &>(cell)); | 
| 653 |  | 
| 654 | 		static_cast<CellDecomposer_sm<dim,T,transform> &>(*this) = static_cast<const CellDecomposer_sm<dim,T,transform> &>(cell); | 
| 655 |  | 
| 656 | 		n_dec = cell.n_dec; | 
| 657 | 		from_cd = cell.from_cd; | 
| 658 |  | 
| 659 | 		return *this; | 
| 660 | 	} | 
| 661 |  | 
| 662 | 	/*! \brief Constructor from a temporal object | 
| 663 | 	 * | 
| 664 | 	 * \param cell Cell list structure | 
| 665 | 	 * | 
| 666 | 	 * \return itself | 
| 667 | 	 * | 
| 668 | 	 */ | 
| 669 | 	template<typename Mem_type2> | 
| 670 | 	CellList<dim,T,Mem_type,transform,vector_pos_type> & operator=(const CellList<dim,T,Mem_type2,transform,vector_pos_type> & cell) | 
| 671 | 	{ | 
| 672 | 		NNc_full = cell.private_get_NNc_full(); | 
| 673 | 		NNc_sym = cell.private_get_NNc_sym(); | 
| 674 |  | 
| 675 | 		Mem_type::copy_general(static_cast<const Mem_type2 &>(cell)); | 
| 676 |  | 
| 677 | 		static_cast<CellDecomposer_sm<dim,T,transform> &>(*this) = static_cast<const CellDecomposer_sm<dim,T,transform> &>(cell); | 
| 678 |  | 
| 679 | 		n_dec = cell.get_ndec(); | 
| 680 | 		from_cd = cell.private_get_from_cd(); | 
| 681 |  | 
| 682 | 		return *this; | 
| 683 | 	} | 
| 684 |  | 
| 685 | 	/*! \brief Set the radius for the getNNIteratorRadius | 
| 686 | 	 * | 
| 687 | 	 * \param radius | 
| 688 | 	 * | 
| 689 | 	 */ | 
| 690 | 	void setRadius(T radius) | 
| 691 | 	{ | 
| 692 | 		NNcalc_rad(radius,nnc_rad,this->getCellBox(),this->getGrid()); | 
| 693 | 	} | 
| 694 |  | 
| 695 | 	/*! \brief Get an iterator over particles following the cell structure | 
| 696 | 	 * | 
| 697 | 	 * \param dom_cells cells in the domain | 
| 698 | 	 * | 
| 699 | 	 * \return a particle iterator | 
| 700 | 	 * | 
| 701 | 	 */ | 
| 702 | 	ParticleIt_Cells<dim,CellList<dim,T,Mem_fast<>,transform>> getDomainIterator(openfpm::vector<size_t> & dom_cells) | 
| 703 | 	{ | 
| 704 | 		ParticleIt_Cells<dim,CellList<dim,T,Mem_fast<>,transform>> it(*this,dom_cells); | 
| 705 |  | 
| 706 | 		return it; | 
| 707 | 	} | 
| 708 |  | 
| 709 | 	/*! \brief Add to the cell | 
| 710 | 	 * | 
| 711 | 	 * \param cell_id Cell id where to add | 
| 712 | 	 * \param ele element to add | 
| 713 | 	 * | 
| 714 | 	 */ | 
| 715 | 	inline void addCell(size_t cell_id, typename Mem_type::local_index_type ele) | 
| 716 | 	{ | 
| 717 | 		Mem_type::addCell(cell_id,ele); | 
| 718 | 	} | 
| 719 |  | 
| 720 | 	/*! \brief Add an element in the cell list | 
| 721 | 	 * | 
| 722 | 	 * \param pos array that contain the coordinate | 
| 723 | 	 * \param ele element to store | 
| 724 | 	 * | 
| 725 | 	 */ | 
| 726 | 	inline void add(const T (& pos)[dim], typename Mem_type::local_index_type ele) | 
| 727 | 	{ | 
| 728 | 		// calculate the Cell id | 
| 729 | 		size_t cell_id = this->getCell(pos); | 
| 730 |  | 
| 731 | 		Mem_type::add(cell_id,ele); | 
| 732 | 	} | 
| 733 |  | 
| 734 | 	/*! \brief Add an element in the cell list | 
| 735 | 	 * | 
| 736 | 	 * \param pos array that contain the coordinate | 
| 737 | 	 * \param ele element to store | 
| 738 | 	 * | 
| 739 | 	 */ | 
| 740 | 	inline void add(const Point<dim,T> & pos, typename Mem_type::local_index_type ele) | 
| 741 | 	{ | 
| 742 | 		// calculate the Cell id | 
| 743 | 		size_t cell_id = this->getCell(pos); | 
| 744 |  | 
| 745 | 		Mem_type::add(cell_id,ele); | 
| 746 | 	} | 
| 747 |  | 
| 748 |  | 
| 749 | 	/*! \brief Add an element in the cell list forcing to be in the domain cells | 
| 750 | 	 * | 
| 751 | 	 * \warning careful is intended to be used ONLY to avoid round-off problems | 
| 752 | 	 * | 
| 753 | 	 * \param pos array that contain the coordinate | 
| 754 | 	 * \param ele element to store | 
| 755 | 	 * | 
| 756 | 	 */ | 
| 757 | 	inline void addDom(const T (& pos)[dim], typename Mem_type::local_index_type ele) | 
| 758 | 	{ | 
| 759 | 		// calculate the Cell id | 
| 760 |  | 
| 761 | 		size_t cell_id = this->getCellDom(pos); | 
| 762 |  | 
| 763 | 		// add the element to the cell | 
| 764 |  | 
| 765 | 		addCell(cell_id,ele); | 
| 766 | 	} | 
| 767 |  | 
| 768 | 	/*! \brief Add an element in the cell list forcing to be in the domain cells | 
| 769 | 	 * | 
| 770 | 	 * \warning careful is intended to be used ONLY to avoid round-off problems | 
| 771 | 	 * | 
| 772 | 	 * \param pos array that contain the coordinate | 
| 773 | 	 * \param ele element to store | 
| 774 | 	 * | 
| 775 | 	 */ | 
| 776 | 	inline void addDom(const Point<dim,T> & pos, typename Mem_type::local_index_type ele) | 
| 777 | 	{ | 
| 778 | 		// calculate the Cell id | 
| 779 |  | 
| 780 | 		size_t cell_id = this->getCellDom(pos); | 
| 781 |  | 
| 782 | 		// add the element to the cell | 
| 783 |  | 
| 784 | 		addCell(cell_id,ele); | 
| 785 | 	} | 
| 786 |  | 
| 787 | 	/*! \brief Add an element in the cell list forcing to be in the padding cells | 
| 788 | 	 * | 
| 789 | 	 * \warning careful is intended to be used ONLY to avoid round-off problems | 
| 790 | 	 * | 
| 791 | 	 * \param pos array that contain the coordinate | 
| 792 | 	 * \param ele element to store | 
| 793 | 	 * | 
| 794 | 	 */ | 
| 795 | 	inline void addPad(const T (& pos)[dim], typename Mem_type::local_index_type ele) | 
| 796 | 	{ | 
| 797 | 		// calculate the Cell id | 
| 798 |  | 
| 799 | 		size_t cell_id = this->getCellPad(pos); | 
| 800 |  | 
| 801 | 		// add the element to the cell | 
| 802 |  | 
| 803 | 		addCell(cell_id,ele); | 
| 804 | 	} | 
| 805 |  | 
| 806 | 	/*! \brief Add an element in the cell list forcing to be in the padding cells | 
| 807 | 	 * | 
| 808 | 	 * \warning careful is intended to be used ONLY to avoid round-off problems | 
| 809 | 	 * | 
| 810 | 	 * \param pos array that contain the coordinate | 
| 811 | 	 * \param ele element to store | 
| 812 | 	 * | 
| 813 | 	 */ | 
| 814 | 	inline void addPad(const Point<dim,T> & pos, typename Mem_type::local_index_type ele) | 
| 815 | 	{ | 
| 816 | 		// calculate the Cell id | 
| 817 |  | 
| 818 | 		size_t cell_id = this->getCell(pos); | 
| 819 |  | 
| 820 | 		// add the element to the cell | 
| 821 |  | 
| 822 | 		addCell(cell_id,ele); | 
| 823 | 	} | 
| 824 |  | 
| 825 | 	/*! \brief remove an element from the cell | 
| 826 | 	 * | 
| 827 | 	 * \param cell cell id | 
| 828 | 	 * \param ele element id | 
| 829 | 	 * | 
| 830 | 	 */ | 
| 831 | 	inline void remove(size_t cell, size_t ele) | 
| 832 | 	{ | 
| 833 | 		Mem_type::remove(cell,ele); | 
| 834 | 	} | 
| 835 |  | 
| 836 | 	/*! \brief Get the number of cells this cell-list contain | 
| 837 | 	 * | 
| 838 | 	 * \return number of cells | 
| 839 | 	 */ | 
| 840 | 	inline size_t getNCells() const | 
| 841 | 	{ | 
| 842 | 		return Mem_type::size(); | 
| 843 | 	} | 
| 844 |  | 
| 845 | 	/*! \brief Return the number of elements in the cell | 
| 846 | 	 * | 
| 847 | 	 * \param cell_id id of the cell | 
| 848 | 	 * | 
| 849 | 	 * \return number of elements in the cell | 
| 850 | 	 * | 
| 851 | 	 */ | 
| 852 | 	inline size_t getNelements(const size_t cell_id) const | 
| 853 | 	{ | 
| 854 | 		return Mem_type::getNelements(cell_id); | 
| 855 | 	} | 
| 856 |  | 
| 857 | 	/*! \brief Get an element in the cell | 
| 858 | 	 * | 
| 859 | 	 * \tparam i property to get | 
| 860 | 	 * | 
| 861 | 	 * \param cell cell id | 
| 862 | 	 * \param ele element id | 
| 863 | 	 * | 
| 864 | 	 * \return The element value | 
| 865 | 	 * | 
| 866 | 	 */ | 
| 867 | 	inline auto get(size_t cell, size_t ele) -> decltype(this->Mem_type::get(cell,ele)) | 
| 868 | 	{ | 
| 869 | 		return Mem_type::get(cell,ele); | 
| 870 | 	} | 
| 871 |  | 
| 872 | 	/*! \brief Get an element in the cell | 
| 873 | 	 * | 
| 874 | 	 * \tparam i property to get | 
| 875 | 	 * | 
| 876 | 	 * \param cell cell id | 
| 877 | 	 * \param ele element id | 
| 878 | 	 * | 
| 879 | 	 * \return The element value | 
| 880 | 	 * | 
| 881 | 	 */ | 
| 882 | 	inline auto get(size_t cell, size_t ele) const -> decltype(this->Mem_type::get(cell,ele)) | 
| 883 | 	{ | 
| 884 | 		return Mem_type::get(cell,ele); | 
| 885 | 	} | 
| 886 |  | 
| 887 | 	/*! \brief Swap the memory | 
| 888 | 	 * | 
| 889 | 	 * \param cl Cell list with witch you swap the memory | 
| 890 | 	 * | 
| 891 | 	 */ | 
| 892 | 	inline void swap(CellList<dim,T,Mem_type,transform,vector_pos_type> & cl) | 
| 893 | 	{ | 
| 894 | 		NNc_full.swap(cl.NNc_full); | 
| 895 | 		NNc_sym.swap(cl.NNc_sym); | 
| 896 |  | 
| 897 | 		Mem_type::swap(static_cast<Mem_type &>(cl)); | 
| 898 |  | 
| 899 | 		static_cast<CellDecomposer_sm<dim,T,transform> &>(*this).swap(static_cast<CellDecomposer_sm<dim,T,transform> &>(cl)); | 
| 900 |  | 
| 901 | 		n_dec = cl.n_dec; | 
| 902 | 		from_cd = cl.from_cd; | 
| 903 | 	} | 
| 904 |  | 
| 905 | 	/*! \brief Get the Cell iterator | 
| 906 | 	 * | 
| 907 | 	 * \param cell | 
| 908 | 	 * | 
| 909 | 	 * \return the iterator to the elements inside cell | 
| 910 | 	 * | 
| 911 | 	 */ | 
| 912 | 	CellIterator<CellList<dim,T,Mem_type,transform>> getCellIterator(size_t cell) | 
| 913 | 	{ | 
| 914 | 		return CellIterator<CellList<dim,T,Mem_type,transform>>(cell,*this); | 
| 915 | 	} | 
| 916 |  | 
| 917 | 	/*! \brief Get the Neighborhood iterator | 
| 918 | 	 * | 
| 919 | 	 * It iterate across all the element of the selected cell and the near cells | 
| 920 | 	 * | 
| 921 | 	 *  \verbatim | 
| 922 |  | 
| 923 | 	     * * * | 
| 924 | 	     * x * | 
| 925 | 	     * * * | 
| 926 |  | 
| 927 | 	   \endverbatim | 
| 928 | 	 * | 
| 929 | 	 * * x is the selected cell | 
| 930 | 	 * * * are the near cell | 
| 931 | 	 * | 
| 932 | 	 * \param cell cell id | 
| 933 | 	 * | 
| 934 | 	 * \return An iterator across the neighhood particles | 
| 935 | 	 * | 
| 936 | 	 */ | 
| 937 | 	template<unsigned int impl=NO_CHECK> inline CellNNIteratorRadius<dim,CellList<dim,T,Mem_type,transform>,impl> getNNIteratorRadius(size_t cell) | 
| 938 | 	{ | 
| 939 | 		CellNNIteratorRadius<dim,CellList<dim,T,Mem_type,transform>,impl> cln(cell,nnc_rad,*this); | 
| 940 | 		return cln; | 
| 941 | 	} | 
| 942 |  | 
| 943 | 	/*! \brief Get the Neighborhood iterator | 
| 944 | 	 * | 
| 945 | 	 * It iterate across all the element of the selected cell and the near cells | 
| 946 | 	 * | 
| 947 | 	 *  \verbatim | 
| 948 |  | 
| 949 | 	     * * * | 
| 950 | 	     * x * | 
| 951 | 	     * * * | 
| 952 |  | 
| 953 | 	   \endverbatim | 
| 954 | 	 * | 
| 955 | 	 * * x is the selected cell | 
| 956 | 	 * * * are the near cell | 
| 957 | 	 * | 
| 958 | 	 * \param cell cell id | 
| 959 | 	 * | 
| 960 | 	 * \return An iterator across the neighhood particles | 
| 961 | 	 * | 
| 962 | 	 */ | 
| 963 | 	template<unsigned int impl=NO_CHECK> | 
| 964 | 	__attribute__((always_inline)) inline CellNNIterator<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,(int)FULL,impl> getNNIterator(size_t cell) | 
| 965 | 	{ | 
| 966 | 		CellNNIterator<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,(int)FULL,impl> cln(cell,NNc_full,*this); | 
| 967 | 		return cln; | 
| 968 |  | 
| 969 | 	} | 
| 970 |  | 
| 971 | 	/*! \brief Get the symmetric Neighborhood iterator | 
| 972 | 	 * | 
| 973 | 	 * It iterate across all the element of the selected cell and the near cells up to some selected radius | 
| 974 | 	 * | 
| 975 | 	 * \param cell cell id | 
| 976 | 	 * \param r_cut radius | 
| 977 | 	 * | 
| 978 | 	 * \return An iterator across the neighborhood particles | 
| 979 | 	 * | 
| 980 | 	 */ | 
| 981 | 	template<unsigned int impl=NO_CHECK> | 
| 982 | 	__attribute__((always_inline)) inline CellNNIteratorRadius<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,impl> getNNIteratorRadius(size_t cell, T r_cut) | 
| 983 | 	{ | 
| 984 | 		openfpm::vector<long int> & NNc = rcache[r_cut]; | 
| 985 |  | 
| 986 | 		if (NNc.size() == 0) | 
| 987 | 		{NNcalc_rad(r_cut,NNc,this->getCellBox(),this->getGrid());} | 
| 988 |  | 
| 989 | 		CellNNIteratorRadius<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,impl> cln(cell,NNc,*this); | 
| 990 |  | 
| 991 | 		return cln; | 
| 992 | 	} | 
| 993 |  | 
| 994 |  | 
| 995 |  | 
| 996 | 	/*! \brief Get the symmetric Neighborhood iterator | 
| 997 | 	 * | 
| 998 | 	 * It iterate across all the element of the selected cell and the near cells | 
| 999 | 	 * | 
| 1000 | 	 *  \verbatim | 
| 1001 |  | 
| 1002 | 	   * * * | 
| 1003 | 	     x * | 
| 1004 |  | 
| 1005 | 	   \endverbatim | 
| 1006 | 	 * | 
| 1007 | 	 * * x is the selected cell | 
| 1008 | 	 * * * are the near cell | 
| 1009 | 	 * | 
| 1010 | 	 * \param cell cell id | 
| 1011 | 	 * \param p particle id | 
| 1012 | 	 * | 
| 1013 | 	 * \return An aiterator across the neighborhood particles | 
| 1014 | 	 * | 
| 1015 | 	 */ | 
| 1016 | 	template<unsigned int impl> | 
| 1017 | 	__attribute__((always_inline)) inline CellNNIteratorSym<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,vector_pos_type,(unsigned int)SYM,impl> | 
| 1018 | 	getNNIteratorSym(size_t cell, size_t p, const vector_pos_type & v) | 
| 1019 | 	{ | 
| 1020 | #ifdef SE_CLASS1 | 
| 1021 | 		if (from_cd == false) | 
| 1022 | 		{std::cerr << __FILE__ << ":"  << __LINE__ << " Warning when you try to get a symmetric neighborhood iterator, you must construct the Cell-list in a symmetric way"  << std::endl;} | 
| 1023 | #endif | 
| 1024 |  | 
| 1025 | 		CellNNIteratorSym<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,vector_pos_type,SYM,impl> cln(cell,p,NNc_sym,*this,v); | 
| 1026 | 		return cln; | 
| 1027 | 	} | 
| 1028 |  | 
| 1029 | 	/*! \brief Get the symmetric Neighborhood iterator | 
| 1030 | 	 * | 
| 1031 | 	 * It iterate across all the element of the selected cell and the near cells | 
| 1032 | 	 * | 
| 1033 | 	 *  \verbatim | 
| 1034 |  | 
| 1035 | 	   * * * | 
| 1036 | 	     x * | 
| 1037 |  | 
| 1038 | 	   \endverbatim | 
| 1039 | 	 * | 
| 1040 | 	 * * x is the selected cell | 
| 1041 | 	 * * * are the near cell | 
| 1042 | 	 * | 
| 1043 | 	 * \param cell cell id | 
| 1044 | 	 * \param p particle id | 
| 1045 | 	 * \param v_p1 first phase for particle p | 
| 1046 | 	 * \param v_p2 second phase for particle q | 
| 1047 | 	 * | 
| 1048 | 	 * \return An aiterator across the neighborhood particles | 
| 1049 | 	 * | 
| 1050 | 	 */ | 
| 1051 | 	template<unsigned int impl, typename vector_pos_type2> | 
| 1052 | 	__attribute__((always_inline)) inline CellNNIteratorSymMP<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,vector_pos_type2,(unsigned int)SYM,impl> | 
| 1053 | 	getNNIteratorSymMP(size_t cell, size_t p, const vector_pos_type2 & v_p1, const vector_pos_type2 & v_p2) | 
| 1054 | 	{ | 
| 1055 | #ifdef SE_CLASS1 | 
| 1056 | 		if (from_cd == false) | 
| 1057 | 			std::cerr << __FILE__ << ":"  << __LINE__ << " Warning when you try to get a symmetric neighborhood iterator, you must construct the Cell-list in a symmetric way"  << std::endl; | 
| 1058 | #endif | 
| 1059 |  | 
| 1060 | 		CellNNIteratorSymMP<dim,CellList<dim,T,Mem_type,transform,vector_pos_type>,vector_pos_type2,SYM,impl> cln(cell,p,NNc_sym,*this,v_p1,v_p2); | 
| 1061 | 		return cln; | 
| 1062 | 	} | 
| 1063 |  | 
| 1064 | 	/*! \brief Get the symmetric neighborhood | 
| 1065 | 	 * | 
| 1066 | 	 * \return the symmetric neighborhood | 
| 1067 | 	 * | 
| 1068 | 	 */ | 
| 1069 | 	const NNc_array<dim,(unsigned int)openfpm::math::pow(3,dim)/2+1> & getNNc_sym() const | 
| 1070 | 	{ | 
| 1071 | 		return NNc_sym; | 
| 1072 | 	} | 
| 1073 |  | 
| 1074 | 	/*! \brief Return the number of padding cells of the Cell decomposer | 
| 1075 | 	 * | 
| 1076 | 	 * \param i dimension | 
| 1077 | 	 * | 
| 1078 | 	 * \return the number of padding cells | 
| 1079 | 	 * | 
| 1080 | 	 */ | 
| 1081 | 	size_t getPadding(size_t i) const | 
| 1082 | 	{ | 
| 1083 | 		return CellDecomposer_sm<dim,T,transform>::getPadding(i); | 
| 1084 | 	} | 
| 1085 |  | 
| 1086 | 	/*! \brief Return the number of padding cells of the Cell decomposer as an array | 
| 1087 | 	 * | 
| 1088 | 	 * | 
| 1089 | 	 * \return the number of padding cells | 
| 1090 | 	 * | 
| 1091 | 	 */ | 
| 1092 | 	size_t (& getPadding())[dim] | 
| 1093 | 	{ | 
| 1094 | 		return CellDecomposer_sm<dim,T,transform>::getPadding(); | 
| 1095 | 	} | 
| 1096 |  | 
| 1097 | 	/*! \brief Clear the cell list | 
| 1098 | 	 * | 
| 1099 | 	 */ | 
| 1100 | 	void clear() | 
| 1101 | 	{ | 
| 1102 | 		Mem_type::clear(); | 
| 1103 | 	} | 
| 1104 |  | 
| 1105 | 	/*! \brief Litterary destroy the memory of the cell list, including the retained one | 
| 1106 | 	 * | 
| 1107 | 	 */ | 
| 1108 | 	void destroy() | 
| 1109 | 	{ | 
| 1110 | 		Mem_type::destroy(); | 
| 1111 | 	} | 
| 1112 |  | 
| 1113 | 	/*! \brief Return the starting point of the cell p | 
| 1114 | 	 * | 
| 1115 | 	 * \param cell_id cell id | 
| 1116 | 	 * | 
| 1117 | 	 * \return the index | 
| 1118 | 	 * | 
| 1119 | 	 */ | 
| 1120 | 	__attribute__((always_inline)) inline const typename Mem_type::local_index_type & getStartId(typename Mem_type::local_index_type cell_id) const | 
| 1121 | 	{ | 
| 1122 | 		return Mem_type::getStartId(cell_id); | 
| 1123 | 	} | 
| 1124 |  | 
| 1125 | 	/*! \brief Return the end point of the cell p | 
| 1126 | 	 * | 
| 1127 | 	 * \param cell_id cell id | 
| 1128 | 	 * | 
| 1129 | 	 * \return the stop index | 
| 1130 | 	 * | 
| 1131 | 	 */ | 
| 1132 | 	__attribute__((always_inline)) inline const typename Mem_type::local_index_type & getStopId(typename Mem_type::local_index_type cell_id) const | 
| 1133 | 	{ | 
| 1134 | 		return Mem_type::getStopId(cell_id); | 
| 1135 | 	} | 
| 1136 |  | 
| 1137 | 	/*! \brief Return the neighborhood id | 
| 1138 | 	 * | 
| 1139 | 	 * \param part_id particle id | 
| 1140 | 	 * | 
| 1141 | 	 * \return the neighborhood id | 
| 1142 | 	 * | 
| 1143 | 	 */ | 
| 1144 | 	__attribute__((always_inline)) inline const typename Mem_type::local_index_type & get_lin(const typename Mem_type::local_index_type * part_id) const | 
| 1145 | 	{ | 
| 1146 | 		return Mem_type::get_lin(part_id); | 
| 1147 | 	} | 
| 1148 |  | 
| 1149 | //////////////////////////////// POINTLESS BUT REQUIRED TO RESPECT THE INTERFACE ////////////////// | 
| 1150 |  | 
| 1151 | 	//! Ghost marker | 
| 1152 | 	size_t g_m = 0; | 
| 1153 |  | 
| 1154 | 	/*! \brief return the ghost marker | 
| 1155 | 	 * | 
| 1156 | 	 * \return ghost marker | 
| 1157 | 	 * | 
| 1158 | 	 */ | 
| 1159 | 	inline size_t get_gm() | 
| 1160 | 	{ | 
| 1161 | 		return g_m; | 
| 1162 | 	} | 
| 1163 |  | 
| 1164 | 	/*! \brief Set the ghost marker | 
| 1165 | 	 * | 
| 1166 | 	 * \param g_m marker | 
| 1167 | 	 * | 
| 1168 | 	 */ | 
| 1169 | 	inline void set_gm(size_t g_m) | 
| 1170 | 	{ | 
| 1171 | 		this->g_m = g_m; | 
| 1172 | 	} | 
| 1173 |  | 
| 1174 | #ifdef CUDA_GPU | 
| 1175 |  | 
| 1176 | 	CellList_cpu_ker<dim,T,typename Mem_type::toKernel_type,transform> toKernel() | 
| 1177 | 	{ | 
| 1178 | 		typedef typename Mem_type::local_index_type ids_type; | 
| 1179 | 		typedef typename Mem_type::local_index_type cnt_type; | 
| 1180 |  | 
| 1181 | 		openfpm::array<T,dim,cnt_type> spacing_c; | 
| 1182 | 		openfpm::array<ids_type,dim,cnt_type> div_c; | 
| 1183 | 		openfpm::array<ids_type,dim,cnt_type> off; | 
| 1184 |  | 
| 1185 | 		for (size_t i = 0 ; i < dim ; i++) | 
| 1186 | 		{ | 
| 1187 | 			spacing_c[i] = CellDecomposer_sm<dim,T,transform>::getCellBox().getHigh(i); | 
| 1188 | 			div_c[i] = CellDecomposer_sm<dim,T,transform>::getDiv()[i]; | 
| 1189 | 			off[i] = CellDecomposer_sm<dim,T,transform>::getPadding(i); | 
| 1190 | 		} | 
| 1191 |  | 
| 1192 | 		CellList_cpu_ker<dim,T,typename Mem_type::toKernel_type,transform> cl(Mem_type::toKernel(), | 
| 1193 | 																			  spacing_c, | 
| 1194 | 																			  div_c, | 
| 1195 | 																			  off, | 
| 1196 | 				                      	  	  	  	  	  	  	  	  	  	  CellDecomposer_sm<dim,T,transform>::getTransform()); | 
| 1197 |  | 
| 1198 | 		return cl; | 
| 1199 | 	} | 
| 1200 |  | 
| 1201 |  | 
| 1202 | 	void hostToDevice() | 
| 1203 | 	{ | 
| 1204 | 		Mem_type::hostToDevice(); | 
| 1205 | 	} | 
| 1206 |  | 
| 1207 | #endif | 
| 1208 |  | 
| 1209 | 	const NNc_array<dim,(unsigned int)openfpm::math::pow(3,dim)> & private_get_NNc_full () const | 
| 1210 | 	{ | 
| 1211 | 		return NNc_full; | 
| 1212 | 	} | 
| 1213 |  | 
| 1214 | 	const NNc_array<dim,(unsigned int)openfpm::math::pow(3,dim)/2+1> & private_get_NNc_sym () const | 
| 1215 | 	{ | 
| 1216 | 		return NNc_sym; | 
| 1217 | 	} | 
| 1218 |  | 
| 1219 | 	bool private_get_from_cd() const | 
| 1220 | 	{ | 
| 1221 | 		return from_cd; | 
| 1222 | 	} | 
| 1223 |  | 
| 1224 | ///////////////////////////////////// | 
| 1225 |  | 
| 1226 | 	void re_setBoxNN() | 
| 1227 | 	{} | 
| 1228 |  | 
| 1229 | ///////////////////////////////////// | 
| 1230 |  | 
| 1231 | 	/*! \brief Set the n_dec number | 
| 1232 | 	 * | 
| 1233 | 	 * \param n_dec | 
| 1234 | 	 * | 
| 1235 | 	 */ | 
| 1236 | 	void set_ndec(size_t n_dec) | 
| 1237 | 	{ | 
| 1238 | 		this->n_dec = n_dec; | 
| 1239 | 	} | 
| 1240 |  | 
| 1241 | 	/*! \brief Set the n_dec number | 
| 1242 | 	 * | 
| 1243 | 	 * \return n_dec | 
| 1244 | 	 * | 
| 1245 | 	 */ | 
| 1246 | 	size_t get_ndec() const | 
| 1247 | 	{ | 
| 1248 | 		return n_dec; | 
| 1249 | 	} | 
| 1250 |  | 
| 1251 | ///////////////////////////////////// | 
| 1252 | }; | 
| 1253 |  | 
| 1254 | /*! \brief Calculate parameters for the cell list | 
| 1255 |  * | 
| 1256 |  * \param div Division array | 
| 1257 |  * \param r_cut interation radius or size of each cell | 
| 1258 |  * \param enlarge In case of padding particles the cell list must be enlarged, like a ghost. This parameter says how much must be enlarged | 
| 1259 |  * | 
| 1260 |  * \return the processor bounding box | 
| 1261 |  */ | 
| 1262 | template<unsigned int dim, typename St> static inline void cl_param_calculate(Box<dim, St> & pbox, size_t (&div)[dim], St r_cut, const Ghost<dim, St> & enlarge) | 
| 1263 | { | 
| 1264 | 	// calculate the parameters of the cell list | 
| 1265 |  | 
| 1266 | 	// extend by the ghost | 
| 1267 | 	pbox.enlarge(enlarge); | 
| 1268 |  | 
| 1269 | 	// Calculate the division array and the cell box | 
| 1270 | 	for (size_t i = 0; i < dim; i++) | 
| 1271 | 	{ | 
| 1272 | 		div[i] = static_cast<size_t>((pbox.getP2().get(i) - pbox.getP1().get(i)) / r_cut); | 
| 1273 | 		div[i]++; | 
| 1274 | 		pbox.setHigh(i,pbox.getLow(i) + div[i]*r_cut); | 
| 1275 | 	} | 
| 1276 | } | 
| 1277 |  | 
| 1278 | /*! \brief Calculate parameters for the symmetric cell list | 
| 1279 |  * | 
| 1280 |  * \param[in] dom Simulation domain | 
| 1281 |  * \param[output] cd_sm This cell-decomposer is set according to the needed division | 
| 1282 |  * \param[in] g Ghost dimensions | 
| 1283 |  * \param[output] pad required padding for the cell-list | 
| 1284 |  * | 
| 1285 |  * \return the processor bounding box | 
| 1286 |  */ | 
| 1287 | template<unsigned int dim, typename St> static | 
| 1288 | inline void cl_param_calculateSym(const Box<dim,St> & dom, | 
| 1289 | 								  CellDecomposer_sm<dim,St,shift<dim,St>> & cd_sm, | 
| 1290 | 								  Ghost<dim,St> g, | 
| 1291 | 								  St r_cut, | 
| 1292 | 								  size_t & pad) | 
| 1293 | { | 
| 1294 | 	size_t div[dim]; | 
| 1295 |  | 
| 1296 | 	for (size_t i = 0 ; i < dim ; i++) | 
| 1297 | 		div[i] = (dom.getHigh(i) - dom.getLow(i)) / r_cut; | 
| 1298 |  | 
| 1299 | 	g.magnify(1.013); | 
| 1300 |  | 
| 1301 | 	// Calculate the maximum padding | 
| 1302 | 	for (size_t i = 0 ; i < dim ; i++) | 
| 1303 | 	{ | 
| 1304 | 		size_t tmp = std::ceil(fabs(g.getLow(i)) / r_cut); | 
| 1305 | 		pad = (pad > tmp)?pad:tmp; | 
| 1306 |  | 
| 1307 | 		tmp = std::ceil(fabs(g.getHigh(i)) / r_cut); | 
| 1308 | 		pad = (pad > tmp)?pad:tmp; | 
| 1309 | 	} | 
| 1310 |  | 
| 1311 | 	cd_sm.setDimensions(dom,div,pad); | 
| 1312 | } | 
| 1313 |  | 
| 1314 |  | 
| 1315 | /*! \brief Calculate parameters for the symmetric cell list | 
| 1316 |  * | 
| 1317 |  * \param[in] dom Simulation domain | 
| 1318 |  * \param[out] cd_sm This cell-decomposer is set according to the needed division | 
| 1319 |  * \param[in] g Ghost part extension | 
| 1320 |  * \param[out] pad required padding for the cell-list | 
| 1321 |  * | 
| 1322 |  * \return the processor bounding box | 
| 1323 |  */ | 
| 1324 | template<unsigned int dim, typename St> | 
| 1325 | static inline void cl_param_calculateSym(const Box<dim,St> & dom, | 
| 1326 | 										 CellDecomposer_sm<dim,St,shift<dim,St>> & cd_sm, | 
| 1327 | 										 Ghost<dim,St> g, | 
| 1328 | 										 size_t & pad) | 
| 1329 | { | 
| 1330 | 	size_t div[dim]; | 
| 1331 |  | 
| 1332 | 	for (size_t i = 0 ; i < dim ; i++) | 
| 1333 | 		div[i] = (dom.getHigh(i) - dom.getLow(i)) / g.getHigh(i); | 
| 1334 |  | 
| 1335 | 	g.magnify(1.013); | 
| 1336 |  | 
| 1337 | 	pad = 1; | 
| 1338 |  | 
| 1339 | 	cd_sm.setDimensions(dom,div,pad); | 
| 1340 | } | 
| 1341 |  | 
| 1342 |  | 
| 1343 | #endif /* CELLLIST_HPP_ */ | 
| 1344 |  |