1/*
2 * NNc_array.hpp
3 *
4 * Created on: Feb 6, 2018
5 * Author: i-bird
6 */
7
8#ifndef OPENFPM_DATA_SRC_NN_CELLLIST_NNC_ARRAY_HPP_
9#define OPENFPM_DATA_SRC_NN_CELLLIST_NNC_ARRAY_HPP_
10
11#include "Grid/grid_sm.hpp"
12#include <boost/mpl/bool.hpp>
13
14/*! \brief Set a dimension threshold
15 *
16 * \param dim dimension
17 *
18 */
19template<unsigned int dim>
20struct as_array_nnc
21{
22 //! true only if dimension is smaller than 10
23 typedef boost::mpl::bool_< dim < 10 > type;
24};
25
26/* \brief NNc_array
27 *
28 * \param size
29 *
30 */
31template<unsigned int dim, unsigned int size, bool thr = as_array_nnc<dim>::type::value>
32class NNc_array
33{
34 //! NNc_array
35 long int NNc_arr[size];
36
37 //! size of the cell array on each dimension
38 grid_sm<dim,void> gs;
39
40public:
41
42 /*! \brief Set the size in each
43 *
44 * \param sz size og the cell grid in each dimensions
45 *
46 */
47 void set_size(const size_t (& sz)[dim])
48 {
49 gs.setDimensions(sz);
50 }
51
52 /*! \brief return the element i
53 *
54 * \return element i
55 *
56 */
57 inline const long int & operator[](size_t i) const
58 {
59 return NNc_arr[i];
60 }
61
62 /*! \brief return the element i
63 *
64 * \return element i
65 *
66 */
67 inline long int & operator[](size_t i)
68 {
69 return NNc_arr[i];
70 }
71
72 /*! \brief Initialize the NNc array with full neighborhood cells indexes
73 *
74 *
75 */
76 void init_full()
77 {
78 typedef typename generate_array<size_t,dim, Fill_zero>::result NNzero;
79 typedef typename generate_array<size_t,dim, Fill_two>::result NNtwo;
80 typedef typename generate_array<size_t,dim, Fill_one>::result NNone;
81
82 // Generate the sub-grid iterator
83
84 grid_key_dx_iterator_sub<dim> gr_sub3(gs,NNzero::data,NNtwo::data);
85
86 // Calculate the NNc array
87
88 size_t middle = gs.LinId(NNone::data);
89 size_t i = 0;
90 while (gr_sub3.isNext())
91 {
92 NNc_arr[i] = (long int)gs.LinId(gr_sub3.get()) - middle;
93
94 ++gr_sub3;
95 i++;
96 }
97 }
98
99
100 /*! \brief Initialize the NNc array with symmetric neighborhood cells indexes
101 *
102 *
103 */
104 void init_sym()
105 {
106 // compile-time array {0,0,0,....} {2,2,2,...} {1,1,1,...}
107
108 typedef typename generate_array<size_t,dim, Fill_zero>::result NNzero;
109 typedef typename generate_array<size_t,dim, Fill_two>::result NNtwo;
110 typedef typename generate_array<size_t,dim, Fill_one>::result NNone;
111
112 size_t middle = gs.LinId(NNone::data);
113
114 // Generate the sub-grid iterator
115
116 grid_key_dx_iterator_sub<dim> gr_sub3(gs,NNzero::data,NNtwo::data);
117
118 // Calculate the NNc_sym array
119
120 size_t i = 0;
121 while (gr_sub3.isNext())
122 {
123 auto key = gr_sub3.get();
124
125 size_t lin = gs.LinId(key);
126
127 // Only the first half is considered
128 if (lin < middle)
129 {
130 ++gr_sub3;
131 continue;
132 }
133
134 NNc_arr[i] = lin - middle;
135
136 ++gr_sub3;
137 i++;
138 }
139 }
140
141 /*! \brief return the pointer to the array
142 *
143 * \return the pointer
144 *
145 */
146 const long int * getPointer() const
147 {
148 return NNc_arr;
149 }
150
151 /*! \brief Copy the NNc_array
152 *
153 * \param nnc NNc_array to copy
154 *
155 */
156 NNc_array<dim,size,thr> & operator=(const NNc_array<dim,size,thr> & nnc)
157 {
158 std::copy(&nnc.NNc_arr[0],&nnc.NNc_arr[size],&NNc_arr[0]);
159 gs = nnc.gs;
160
161 return *this;
162 }
163
164 /*! \brief swap NNc_array
165 *
166 * \param nnc NNc_array to copy
167 *
168 */
169 void swap(NNc_array<dim,size,thr> & nnc)
170 {
171 gs.swap(nnc.gs);
172
173 long int NNc_full_tmp[openfpm::math::pow(3,dim)];
174
175 std::copy(&nnc.NNc_arr[0],&nnc.NNc_arr[size],&NNc_full_tmp[0]);
176 std::copy(&NNc_arr[0],&NNc_arr[size],&nnc.NNc_arr[0]);
177 std::copy(&NNc_full_tmp[0],&NNc_full_tmp[size],&NNc_arr[0]);
178 }
179};
180
181/* \brief NNc_array
182 *
183 * It encapsulate a 3^{dim} array containing the neighborhood cells-id
184 *
185 * \tparam dim dimensionality
186 * \tparam size total number of neighborhood cells
187 *
188 */
189template<unsigned int dim, unsigned int size>
190class NNc_array<dim,size,false>
191{
192 //! NNc_array is a grid in general 3^{dim}, this object contain the information
193 //! about this grid
194 grid_sm<dim,void> gs;
195
196 //! Information about the grid in the reduced space
197 grid_sm<dim,void> gs_base;
198
199 //!
200 size_t sub_off;
201 size_t sym_mid;
202
203 bool full_or_sym;
204
205public:
206
207 /*! \brief set the size of the cell grid
208 *
209 * \param sz[dim] size of the cell grid in each dimension
210 *
211 */
212 void set_size(const size_t (& sz)[dim])
213 {
214 typedef typename generate_array<size_t,dim, Fill_three>::result NNthree;
215
216 gs.setDimensions(sz);
217 gs_base.setDimensions(NNthree::data);
218
219 typedef typename generate_array<size_t,dim, Fill_one>::result NNone;
220 sub_off = gs.LinId(NNone::data);
221 sym_mid = gs_base.LinId(NNone::data);
222 }
223
224 /*! \brief return the element i
225 *
226 * \return element i
227 *
228 */
229 long int operator[](size_t i) const
230 {
231 if (full_or_sym == true)
232 {
233 grid_key_dx<dim> key = gs_base.InvLinId(i);
234 return gs.LinId(key) - sub_off;
235 }
236
237 grid_key_dx<dim> key = gs_base.InvLinId(i + sym_mid);
238 return gs.LinId(key) - sub_off;
239 }
240
241 void init_full()
242 {
243 full_or_sym = true;
244 }
245
246 void init_sym()
247 {
248 full_or_sym = false;
249 }
250
251 /*! \brief return the pointer to the array
252 *
253 * \return the pointer
254 *
255 */
256 const long int * getPointer() const
257 {
258 std::cerr << __FILE__ << ":" << __LINE__ << " error dimension is too high to use this type of neighborhood" << std::endl;
259 return NULL;
260 }
261
262 /*! \brief Copy the NNc_array
263 *
264 * \param nnc NNc_array to copy
265 *
266 */
267 NNc_array<dim,size,false> & operator=(const NNc_array<dim,size,false> & nnc)
268 {
269 gs = nnc.gs;
270 gs_base = nnc.gs_base;
271 sub_off = nnc.sub_off;
272 sym_mid = nnc.sym_mid;
273
274 full_or_sym = nnc.full_or_sym;
275
276 return *this;
277 }
278
279 /*! \brief swap the NNc_array
280 *
281 * \param nnc NNc_array to copy
282 *
283 */
284 void swap(NNc_array<dim,size,false> & nnc)
285 {
286 gs.swap(nnc.gs);
287 gs_base.swap(nnc.gs_base);
288
289 size_t sub_off_tmp = sub_off;
290 sub_off = nnc.sub_off;
291 nnc.sub_off = sub_off_tmp;
292
293 size_t sym_mid_tmp = sym_mid;
294 sym_mid = nnc.sym_mid;
295 nnc.sym_mid = sym_mid_tmp;
296
297 bool full_or_sym_tmp = full_or_sym;
298 full_or_sym = nnc.full_or_sym;
299 nnc.full_or_sym = full_or_sym_tmp;
300 }
301};
302
303
304#endif /* OPENFPM_DATA_SRC_NN_CELLLIST_NNC_ARRAY_HPP_ */
305