1/*
2 * CellNNIterator.hpp
3 *
4 * Created on: Mar 26, 2015
5 * Author: i-bird
6 */
7
8#ifndef CELLNNITERATOR_FULL_HPP_
9#define CELLNNITERATOR_FULL_HPP_
10
11#include "util/mathutil.hpp"
12#include "NN/CellList/NNc_array.hpp"
13
14#define FULL openfpm::math::pow(3,dim)
15#define SYM openfpm::math::pow(3,dim)/2 + 1
16#define CRS openfpm::math::pow(2,dim)
17
18
19/*! \brief Iterator for the neighborhood of the cell structures
20 *
21 * In general you never create it directly but you get it from the CellList structures
22 *
23 * It iterate across all the element of the selected cell and the near cells
24 *
25 * \note to calculate quantities that involve a total reduction (like energies) use the CellIteratorSymRed
26 *
27 * \tparam dim dimensionality of the space where the cell live
28 * \tparam Cell cell type on which the iterator is working
29 * \tparam NNc_size neighborhood size
30 * \tparam impl implementation specific options NO_CHECK do not do check on access, SAFE do check on access
31 *
32 */
33template<unsigned int dim, typename Cell,int NNc_size, unsigned int impl>
34class CellNNIterator
35{
36protected:
37
38 //! actual element id
39 const typename Cell::Mem_type_type::local_index_type * start_id;
40
41 //! stop id to read the end of the cell
42 const typename Cell::Mem_type_type::local_index_type * stop_id;
43
44 //! Actual NNc_id;
45 size_t NNc_id;
46
47 //! Center cell, or cell for witch we are searching the NN-cell
48 const long int cell;
49
50 //! actual cell id = NNc[NNc_id]+cell stored for performance reason
51 size_t cell_id;
52
53 //! Cell list
54 Cell & cl;
55
56 //! NN cell id
57 const NNc_array<dim,NNc_size> & NNc;
58
59 /*! \brief Select non-empty cell
60 *
61 */
62 __attribute__((always_inline)) inline void selectValid()
63 {
64 while (start_id == stop_id)
65 {
66 NNc_id++;
67
68 // No more Cell
69 if (NNc_id >= NNc_size) return;
70
71 cell_id = NNc[NNc_id] + cell;
72
73 start_id = &cl.getStartId(cell_id);
74 stop_id = &cl.getStopId(cell_id);
75 }
76 }
77
78private:
79
80
81public:
82
83 /*! \brief
84 *
85 * Cell NN iterator
86 *
87 * \param cell Cell id
88 * \param NNc Cell neighborhood indexes (relative)
89 * \param cl Cell structure
90 *
91 */
92 __attribute__((always_inline)) inline CellNNIterator(size_t cell, const NNc_array<dim,NNc_size> &NNc, Cell & cl)
93 :NNc_id(0),cell(cell),cell_id(NNc[NNc_id] + cell),cl(cl),NNc(NNc)
94 {
95 start_id = &cl.getStartId(cell_id);
96 stop_id = &cl.getStopId(cell_id);
97 selectValid();
98 }
99
100 /*! \brief Check if there is the next element
101 *
102 * \return true if there is the next element
103 *
104 */
105 __attribute__((always_inline)) inline bool isNext()
106 {
107 if (NNc_id >= NNc_size)
108 return false;
109 return true;
110 }
111
112 /*! \brief take the next element
113 *
114 * \return itself
115 *
116 */
117 __attribute__((always_inline)) inline CellNNIterator & operator++()
118 {
119 start_id++;
120
121 selectValid();
122
123 return *this;
124 }
125
126 /*! \brief Get the value of the cell
127 *
128 * \return the next element object
129 *
130 */
131 __attribute__((always_inline)) inline const typename Cell::Mem_type_type::local_index_type & get()
132 {
133 return cl.get_lin(start_id);
134 }
135
136 /*! \brief Get the value of the cell
137 *
138 * \return the next element object
139 *
140 */
141 __attribute__((always_inline)) inline const typename Cell::Mem_type_type::local_index_type & get() const
142 {
143 return cl.get_lin(start_id);
144 }
145};
146
147
148/*! \brief Symmetric iterator for the neighborhood of the cell structures
149 *
150 * In general you never create it directly but you get it from the CellList structures
151 *
152 * It iterate across all the element of the selected cell and the near cells.
153 *
154 * \note if we query the neighborhood of p and q is the neighborhood of p
155 * when we will query the neighborhood of q p is not present. This is
156 * useful to implement formula like \f$ \sum_{q = neighborhood(p) and p <= q} \f$
157 *
158 * \tparam dim dimensionality of the space where the cell live
159 * \tparam Cell cell type on which the iterator is working
160 * \tparam NNc_size neighborhood size
161 * \tparam impl implementation specific options NO_CHECK do not do check on access, SAFE do check on access
162 *
163 */
164template<unsigned int dim, typename Cell, typename vector_pos_type,int NNc_size, unsigned int impl>
165class CellNNIteratorSym : public CellNNIterator<dim,Cell,NNc_size,impl>
166{
167 //! index of the particle p
168 size_t p;
169
170 //! Position of the particle p
171 const vector_pos_type & v;
172
173 /*! Select the next valid element
174 *
175 */
176 __attribute__((always_inline)) inline void selectValid()
177 {
178 if (this->NNc[this->NNc_id] == 0)
179 {
180 while (this->start_id < this->stop_id)
181 {
182 size_t q = this->cl.get_lin(this->start_id);
183 for (long int i = dim-1 ; i >= 0 ; i--)
184 {
185 if (v.template get<0>(p)[i] < v.template get<0>(q)[i])
186 return;
187 else if (v.template get<0>(p)[i] > v.template get<0>(q)[i])
188 goto next;
189 }
190 if (q >= p) return;
191next:
192 this->start_id++;
193 }
194
195 CellNNIterator<dim,Cell,NNc_size,impl>::selectValid();
196 }
197 else
198 {
199 CellNNIterator<dim,Cell,NNc_size,impl>::selectValid();
200 }
201 }
202
203public:
204
205 /*! \brief
206 *
207 * Cell NN iterator
208 *
209 * \param cell Cell id
210 * \param p index of the particle from which we are searching the neighborhood particles
211 * \param NNc Cell neighborhood indexes (relative)
212 * \param cl Cell structure
213 *
214 */
215 __attribute__((always_inline)) inline CellNNIteratorSym(size_t cell, size_t p, const NNc_array<dim,NNc_size> &NNc, Cell & cl, const vector_pos_type & v)
216 :CellNNIterator<dim,Cell,NNc_size,impl>(cell,NNc,cl),p(p),v(v)
217 {
218 selectValid();
219 }
220
221
222 /*! \brief take the next element
223 *
224 * \return itself
225 *
226 */
227 __attribute__((always_inline)) inline CellNNIteratorSym<dim,Cell,vector_pos_type,NNc_size,impl> & operator++()
228 {
229 this->start_id++;
230
231 selectValid();
232
233 return *this;
234 }
235};
236
237/*! \brief Symmetric iterator for the neighborhood of the cell structures
238 *
239 * In general you never create it directly but you get it from the CellList structures
240 *
241 * It iterate across all the element of the selected cell and the near cells.
242 *
243 * \note if we query the neighborhood of p and q is the neighborhood of p
244 * when we will query the neighborhood of q p is not present. This is
245 * useful to implement formula like \f$ \sum_{q = neighborhood(p) and p <= q} \f$
246 *
247 * \tparam dim dimensionality of the space where the cell live
248 * \tparam Cell cell type on which the iterator is working
249 * \tparam NNc_size neighborhood size
250 * \tparam impl implementation specific options NO_CHECK do not do check on access, SAFE do check on access
251 *
252 */
253template<unsigned int dim, typename Cell, typename vector_pos_type , int NNc_size, unsigned int impl>
254class CellNNIteratorSymMP : public CellNNIterator<dim,Cell,NNc_size,impl>
255{
256 //! index of the particle p
257 size_t p;
258
259 //! Phase vector for particle p
260 const vector_pos_type & v_p1;
261
262 //! Phase vector for particle q
263 const vector_pos_type & v_p2;
264
265 /*! Select the next valid element
266 *
267 */
268 __attribute__((always_inline)) inline void selectValid()
269 {
270 if (this->NNc[this->NNc_id] == 0)
271 {
272 while (this->start_id < this->stop_id)
273 {
274 size_t q = this->cl.get_lin(this->start_id);
275 for (long int i = dim-1 ; i >= 0 ; i--)
276 {
277 if (v_p1.template get<0>(p)[i] < v_p2.template get<0>(q)[i])
278 return;
279 else if (v_p1.template get<0>(p)[i] > v_p2.template get<0>(q)[i])
280 goto next;
281 }
282 if (q >= p) return;
283next:
284 this->start_id++;
285 }
286
287 CellNNIterator<dim,Cell,NNc_size,impl>::selectValid();
288 }
289 else
290 {
291 CellNNIterator<dim,Cell,NNc_size,impl>::selectValid();
292 }
293 }
294
295public:
296
297 /*! \brief
298 *
299 * Cell NN iterator
300 *
301 * \param cell Cell id
302 * \param p index of the particle from which we are searching the neighborhood particles
303 * \param NNc Cell neighborhood indexes (relative)
304 * \param cl Cell structure
305 *
306 */
307 __attribute__((always_inline)) inline CellNNIteratorSymMP(size_t cell,
308 size_t p,
309 const NNc_array<dim,NNc_size> &NNc,
310 Cell & cl,
311 const vector_pos_type & v_p1,
312 const vector_pos_type & v_p2)
313 :CellNNIterator<dim,Cell,NNc_size,impl>(cell,NNc,cl),p(p),v_p1(v_p1),v_p2(v_p2)
314 {
315 selectValid();
316 }
317
318
319 /*! \brief take the next element
320 *
321 * \return itself
322 *
323 */
324 __attribute__((always_inline)) inline CellNNIteratorSymMP<dim,Cell,vector_pos_type,NNc_size,impl> & operator++()
325 {
326 this->start_id++;
327
328 selectValid();
329
330 return *this;
331 }
332};
333
334/*! \brief it iterate through the elements of a cell
335 *
336 * In general you do not create this object you get it from the CellList structures
337 *
338 * \tparam Cell cell type
339 *
340 */
341template<typename Cell> class CellIterator
342{
343 //! Cell list
344 Cell & cl;
345
346 //! actual element id inside the cell
347 size_t ele_id;
348
349 //! selected cell
350 const long int cell;
351
352public:
353
354 /*! \brief Cell iterator
355 *
356 * \param cell Cell id
357 * \param cl Cell on which iterate
358 *
359 */
360 __attribute__((always_inline)) inline CellIterator(const size_t cell, Cell & cl)
361 :cl(cl),ele_id(0),cell(cell)
362 {
363 }
364
365 /*! \brief Check if there is the next element
366 *
367 * \return true if there are still neighborhood particles
368 *
369 */
370 __attribute__((always_inline)) inline bool isNext()
371 {
372 return cl.getNelements(cell) > ele_id;
373 }
374
375 /*! \brief take the next neoghborhood particle
376 *
377 * \return itself
378 *
379 */
380 __attribute__((always_inline)) inline CellIterator & operator++()
381 {
382 ele_id++;
383
384 return *this;
385 }
386
387 /*! \brief Get the value of the cell
388 *
389 * \return the next element object
390 *
391 */
392 __attribute__((always_inline)) inline typename Cell::value_type & get()
393 {
394 return cl.get(cell,ele_id);
395 }
396
397 /*! \brief Get the value of the cell
398 *
399 * \return the next element object
400 *
401 */
402 __attribute__((always_inline)) inline const typename Cell::value_type & get() const
403 {
404 return cl.get(cell,ele_id);
405 }
406};
407
408#include "CellNNIteratorRuntime.hpp"
409
410#endif /* CELLNNITERATOR_FULL_HPP_ */
411