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 | */ |
33 | template<unsigned int dim, typename Cell,int NNc_size, unsigned int impl> |
34 | class CellNNIterator |
35 | { |
36 | protected: |
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 | |
78 | private: |
79 | |
80 | |
81 | public: |
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 | */ |
164 | template<unsigned int dim, typename Cell, typename vector_pos_type,int NNc_size, unsigned int impl> |
165 | class 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; |
191 | next: |
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 | |
203 | public: |
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 | */ |
253 | template<unsigned int dim, typename Cell, typename vector_pos_type , int NNc_size, unsigned int impl> |
254 | class 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; |
283 | next: |
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 | |
295 | public: |
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 | */ |
341 | template<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 | |
352 | public: |
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 | |