1 | /* |
2 | * CellNNIteratorRuntime.hpp |
3 | * |
4 | * Created on: Nov 18, 2016 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef OPENFPM_DATA_SRC_NN_CELLLIST_CELLNNITERATORRUNTIME_HPP_ |
9 | #define OPENFPM_DATA_SRC_NN_CELLLIST_CELLNNITERATORRUNTIME_HPP_ |
10 | |
11 | #include "util/mathutil.hpp" |
12 | |
13 | #define FULL openfpm::math::pow(3,dim) |
14 | #define SYM openfpm::math::pow(3,dim)/2 + 1 |
15 | #define CRS openfpm::math::pow(2,dim) |
16 | |
17 | #define RUNTIME -1 |
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 impl implementation specific options NO_CHECK do not do check on access, SAFE do check on access |
30 | * |
31 | */ |
32 | template<unsigned int dim, typename Cell,unsigned int impl> |
33 | class CellNNIterator<dim,Cell,RUNTIME,impl> |
34 | { |
35 | protected: |
36 | |
37 | //! actual element id |
38 | const typename Cell::Mem_type_type::loc_index * start_id; |
39 | |
40 | //! stop id to read the end of the cell |
41 | const typename Cell::Mem_type_type::loc_index * stop_id; |
42 | |
43 | //! Actual NNc_id; |
44 | size_t NNc_id; |
45 | |
46 | //! Size of the neighboring cells |
47 | size_t NNc_size; |
48 | |
49 | //! Center cell, or cell for witch we are searching the NN-cell |
50 | const long int cell; |
51 | |
52 | //! actual cell id = NNc[NNc_id]+cell stored for performance reason |
53 | size_t cell_id; |
54 | |
55 | //! Cell list |
56 | Cell & cl; |
57 | |
58 | //! NN cell id |
59 | const long int * NNc; |
60 | |
61 | /*! \brief Select non-empty cell |
62 | * |
63 | */ |
64 | __attribute__((always_inline)) inline void selectValid() |
65 | { |
66 | while (start_id == stop_id) |
67 | { |
68 | NNc_id++; |
69 | |
70 | // No more Cell |
71 | if (NNc_id >= NNc_size) return; |
72 | |
73 | cell_id = NNc[NNc_id] + cell; |
74 | |
75 | start_id = &cl.getStartId(cell_id); |
76 | stop_id = &cl.getStopId(cell_id); |
77 | } |
78 | } |
79 | |
80 | private: |
81 | |
82 | |
83 | public: |
84 | |
85 | /*! \brief |
86 | * |
87 | * Cell NN iterator |
88 | * |
89 | * \param cell Cell id |
90 | * \param NNc Cell neighborhood indexes (relative) |
91 | * \param NNc_size size of the neighborhood |
92 | * \param cl Cell structure |
93 | * |
94 | */ |
95 | __attribute__((always_inline)) inline CellNNIterator(size_t cell, const long int * NNc, size_t NNc_size, Cell & cl) |
96 | :NNc_id(0),NNc_size(NNc_size),cell(cell),cell_id(NNc[NNc_id] + cell),cl(cl),NNc(NNc) |
97 | { |
98 | start_id = &cl.getStartId(cell_id); |
99 | stop_id = &cl.getStopId(cell_id); |
100 | selectValid(); |
101 | } |
102 | |
103 | /*! \brief Check if there is the next element |
104 | * |
105 | * \return true if there is the next element |
106 | * |
107 | */ |
108 | __attribute__((always_inline)) inline bool isNext() |
109 | { |
110 | if (NNc_id >= NNc_size) |
111 | return false; |
112 | return true; |
113 | } |
114 | |
115 | /*! \brief take the next element |
116 | * |
117 | * \return itself |
118 | * |
119 | */ |
120 | __attribute__((always_inline)) inline CellNNIterator & operator++() |
121 | { |
122 | start_id++; |
123 | |
124 | selectValid(); |
125 | |
126 | return *this; |
127 | } |
128 | |
129 | /*! \brief Get the value of the cell |
130 | * |
131 | * \return the next element object |
132 | * |
133 | */ |
134 | __attribute__((always_inline)) inline const typename Cell::Mem_type_type::loc_index & get() |
135 | { |
136 | return cl.get_lin(start_id); |
137 | } |
138 | }; |
139 | |
140 | |
141 | /*! \brief Symmetric iterator for the neighborhood of the cell structures |
142 | * |
143 | * In general you never create it directly but you get it from the CellList structures |
144 | * |
145 | * It iterate across all the element of the selected cell and the near cells. |
146 | * |
147 | * \note if we query the neighborhood of p and q is the neighborhood of p |
148 | * when we will query the neighborhood of q p is not present. This is |
149 | * useful to implement formula like \f$ \sum_{q = neighborhood(p) and p <= q} \f$ |
150 | * |
151 | * \tparam dim dimensionality of the space where the cell live |
152 | * \tparam Cell cell type on which the iterator is working |
153 | * \tparam NNc_size neighborhood size |
154 | * \tparam impl implementation specific options NO_CHECK do not do check on access, SAFE do check on access |
155 | * |
156 | */ |
157 | template<unsigned int dim, typename Cell,typename vector_pos_type, unsigned int impl> |
158 | class CellNNIteratorSym<dim,Cell,vector_pos_type,RUNTIME,impl> : public CellNNIterator<dim,Cell,RUNTIME,impl> |
159 | { |
160 | //! index of the particle p |
161 | size_t p; |
162 | |
163 | //! Position of the particle p |
164 | const vector_pos_type & v; |
165 | |
166 | /*! Select the next valid element |
167 | * |
168 | */ |
169 | __attribute__((always_inline)) inline void selectValid() |
170 | { |
171 | if (this->NNc[this->NNc_id] == 0) |
172 | { |
173 | while (this->start_id < this->stop_id) |
174 | { |
175 | size_t q = this->cl.get_lin(this->start_id); |
176 | for (long int i = dim-1 ; i >= 0 ; i--) |
177 | { |
178 | if (v.template get<0>(p)[i] < v.template get<0>(q)[i]) |
179 | return; |
180 | else if (v.template get<0>(p)[i] > v.template get<0>(q)[i]) |
181 | goto next; |
182 | } |
183 | if (q >= p) return; |
184 | next: |
185 | this->start_id++; |
186 | } |
187 | |
188 | CellNNIterator<dim,Cell,RUNTIME,impl>::selectValid(); |
189 | } |
190 | else |
191 | { |
192 | CellNNIterator<dim,Cell,RUNTIME,impl>::selectValid(); |
193 | } |
194 | } |
195 | |
196 | public: |
197 | |
198 | /*! \brief |
199 | * |
200 | * Cell NN iterator |
201 | * |
202 | * \param cell Cell id |
203 | * \param p index of the particle from which we are searching the neighborhood particles |
204 | * \param NNc Cell neighborhood indexes (relative) |
205 | * \param cl Cell structure |
206 | * |
207 | */ |
208 | __attribute__((always_inline)) inline CellNNIteratorSym(size_t cell, |
209 | size_t p, |
210 | const long int * NNc, |
211 | size_t NNc_size, |
212 | Cell & cl, |
213 | const vector_pos_type & v) |
214 | :CellNNIterator<dim,Cell,RUNTIME,impl>(cell,NNc,NNc_size,cl),p(p),v(v) |
215 | { |
216 | if (this->NNc_id >= this->NNc_size) |
217 | return; |
218 | |
219 | selectValid(); |
220 | } |
221 | |
222 | |
223 | /*! \brief take the next element |
224 | * |
225 | * \return itself |
226 | * |
227 | */ |
228 | __attribute__((always_inline)) inline CellNNIteratorSym<dim,Cell,vector_pos_type,RUNTIME,impl> & operator++() |
229 | { |
230 | this->start_id++; |
231 | |
232 | selectValid(); |
233 | |
234 | return *this; |
235 | } |
236 | }; |
237 | |
238 | #endif /* OPENFPM_DATA_SRC_NN_CELLLIST_CELLNNITERATORRUNTIME_HPP_ */ |
239 | |