1/*
2 * grid_dist_id_iterator_sub.hpp
3 *
4 * Created on: Oct 14, 2015
5 * Author: i-bird
6 */
7
8#ifndef SRC_GRID_GRID_DIST_ID_ITERATOR_SUB_HPP_
9#define SRC_GRID_GRID_DIST_ID_ITERATOR_SUB_HPP_
10
11
12/*! \brief Distributed grid iterator
13 *
14 * Iterator across the local elements of the distributed grid
15 *
16 * \tparam dim dimensionality of the grid
17 * \tparam device_grid type of basic grid
18 * \tparam impl implementation
19 *
20 */
21template<unsigned int dim, typename device_grid>
22class grid_dist_iterator_sub
23{
24 // sub_set of the grid where to iterate
25 struct sub_set
26 {
27 //! start point where iterate
28 grid_key_dx<dim> start;
29 //! stop point where iterate
30 grid_key_dx<dim> stop;
31 };
32
33 //! grid list counter
34 size_t g_c;
35
36 //! List of the grids we are going to iterate
37 const openfpm::vector<device_grid> & gList;
38
39 //! Extension of each grid: domain and ghost + domain
40 const openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext;
41
42 //! Actual iterator
43 decltype(device_grid::type_of_subiterator()) a_it;
44
45 //! start key
46 grid_key_dx<dim> start;
47
48 //! stop key
49 grid_key_dx<dim> stop;
50
51 /*! \brief compute the subset where it has to iterate
52 *
53 * \param gc Actual grid
54 * \param start_c adjusted start point for the grid g_c
55 * \param stop_c adjusted stop point for the grid g_c
56 *
57 * \return false if the sub-set does not contain points
58 *
59 */
60 bool compute_subset(size_t gc, grid_key_dx<dim> & start_c, grid_key_dx<dim> & stop_c)
61 {
62 // Intersect the grid keys
63
64 for (size_t i = 0 ; i < dim ; i++)
65 {
66 long int start_p = gdb_ext.get(g_c).Dbox.getP1().get(i) + gdb_ext.get(g_c).origin.get(i);
67 long int stop_p = gdb_ext.get(g_c).Dbox.getP2().get(i) + gdb_ext.get(g_c).origin.get(i);
68 if (start.get(i) <= start_p)
69 start_c.set_d(i,gdb_ext.get(g_c).Dbox.getP1().get(i));
70 else if (start.get(i) <= stop_p)
71 start_c.set_d(i,start.get(i) - gdb_ext.get(g_c).origin.get(i));
72 else
73 return false;
74
75 if (stop.get(i) >= stop_p)
76 stop_c.set_d(i,gdb_ext.get(g_c).Dbox.getP2().get(i));
77 else if (stop.get(i) >= start_p)
78 stop_c.set_d(i,stop.get(i) - gdb_ext.get(g_c).origin.get(i));
79 else
80 return false;
81 }
82
83 return true;
84 }
85
86 /*! \brief from g_c increment g_c until you find a valid grid
87 *
88 */
89 void selectValidGrid()
90 {
91 // start and stop for the subset grid
92 grid_key_dx<dim> start_c;
93 grid_key_dx<dim> stop_c;
94
95 do
96 {
97 // When the grid has size 0 potentially all the other informations are garbage
98 while (g_c < gList.size() &&
99 (gList.get(g_c).size() == 0 || gdb_ext.get(g_c).Dbox.isValid() == false || compute_subset(g_c,start_c,stop_c) == false ))
100 {g_c++;}
101
102 // get the next grid iterator
103 if (g_c < gList.size())
104 {
105 a_it.reinitialize(gList.get(g_c).getIterator(start_c,stop_c));
106 if (a_it.isNext() == false) {g_c++;}
107 }
108 } while (g_c < gList.size() && a_it.isNext() == false);
109 }
110
111 public:
112
113 /*! \brief Copy operator=
114 *
115 * \param tmp iterator to copy
116 *
117 */
118 grid_dist_iterator_sub<dim,device_grid> &
119 operator=(const grid_dist_iterator_sub<dim,device_grid> & tmp)
120 {
121 g_c = tmp.g_c;
122 gList = tmp.gList;
123 gdb_ext = tmp.gdb_ext;
124 start = tmp.start;
125 stop = tmp.stop;
126 a_it.reinitialize(tmp.a_it);
127
128 return *this;
129 }
130
131 /*! \brief Copy constructor
132 *
133 * \param tmp iterator to copy
134 *
135 */
136 grid_dist_iterator_sub(const grid_dist_iterator_sub<dim,device_grid> & tmp)
137 :g_c(tmp.g_c),gList(tmp.gList),gdb_ext(tmp.gdb_ext),start(tmp.start),stop(tmp.stop)
138 {
139 // get the next grid iterator
140 if (g_c < gList.size())
141 {
142 a_it.reinitialize(tmp.a_it);
143 }
144 }
145
146 /*! \brief Constructor of the distributed grid iterator
147 *
148 * \param start position
149 * \param stop position
150 * \param gk std::vector of the local grid
151 * \param gdb_ext information about the local grids
152 *
153 */
154 grid_dist_iterator_sub(const grid_key_dx<dim> & start, const grid_key_dx<dim> & stop ,const openfpm::vector<device_grid> & gk, const openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext)
155 :g_c(0),gList(gk),gdb_ext(gdb_ext),start(start),stop(stop)
156 {
157 // Initialize the current iterator
158 // with the first grid
159 selectValidGrid();
160 }
161
162 // Destructor
163 ~grid_dist_iterator_sub()
164 {
165 }
166
167 /*! \brief Get the next element
168 *
169 * \return the next grid_key
170 *
171 */
172
173 inline grid_dist_iterator_sub<dim,device_grid> & operator++()
174 {
175 ++a_it;
176
177 // check if a_it is at the end
178
179 if (a_it.isNext() == true)
180 return *this;
181 else
182 {
183 // switch to the new grid
184 g_c++;
185
186 selectValidGrid();
187 }
188
189 return *this;
190 }
191
192 /*! \brief Check if there is the next element
193 *
194 * \return true if there is the next, false otherwise
195 *
196 */
197 inline bool isNext()
198 {
199 // If there are no other grid stop
200
201 if (g_c >= gList.size())
202 return false;
203
204 return true;
205 }
206
207 /*! \brief Get the actual key
208 *
209 * \return the actual key
210 *
211 */
212 inline grid_dist_key_dx<dim,typename device_grid::base_key> get()
213 {
214 return grid_dist_key_dx<dim,typename device_grid::base_key>(g_c,a_it.get());
215 }
216
217 /*! \brief Convert a g_dist_key_dx into a global key
218 *
219 * \see grid_dist_key_dx
220 * \see grid_dist_iterator
221 *
222 * \return the global position in the grid
223 *
224 */
225 inline grid_key_dx<dim> getGKey(const grid_dist_key_dx<dim> & k)
226 {
227 // Get the sub-domain id
228 size_t sub_id = k.getSub();
229
230 grid_key_dx<dim> k_glob = k.getKey();
231
232 // shift
233 k_glob = k_glob + gdb_ext.get(sub_id).origin;
234
235 return k_glob;
236 }
237
238 /* \brief Get the starting point of the grid iterator
239 *
240 * \return the starting point
241 *
242 */
243 inline grid_key_dx<dim> getStart() const
244 {
245 return start;
246 }
247
248 /* \brief Get the stop point of the grid iterator
249 *
250 * \return the stop point
251 *
252 */
253 inline grid_key_dx<dim> getStop() const
254 {
255 return stop;
256 }
257
258 /*! \brief Return the number of local grids
259 *
260 *
261 */
262 inline size_t N_loc_grid()
263 {
264 return gList.size();
265 }
266
267 /*! \brief Return the component j of the starting point (P1) of the domain part
268 * for the local grid i
269 *
270 * \param i local grid
271 * \param j dimension
272 *
273 *
274 */
275 inline size_t loc_grid_info_start(size_t i,size_t j)
276 {
277 return gdb_ext.get(i).DBox.getLow(i);
278 }
279
280 /*! \brief Return the component j of the stop point (P2) of the domain part
281 * for the local grid i
282 *
283 * \param i local grid
284 * \param j dimension
285 *
286 *
287 */
288 inline size_t loc_grid_info_size(size_t i,size_t j)
289 {
290 return gdb_ext.get(i).GDBox.getHigh(i);
291 }
292};
293
294
295//////// MACRO in 3D
296
297#define WHILE_M(grid,stencil) auto & ginfo = grid.getLocalGridsInfo();\
298 for (size_t s = 0 ; s < grid.getN_loc_grid() ; s++)\
299 {\
300 auto it = grid.get_loc_grid_iterator_stencil(s,stencil);\
301\
302 int lo[3] = {(int)ginfo.get(s).Dbox.getLow(0),(int)ginfo.get(s).Dbox.getLow(1),(int)ginfo.get(s).Dbox.getLow(2)};\
303 int hi[3] = {(int)ginfo.get(s).Dbox.getHigh(0),(int)ginfo.get(s).Dbox.getHigh(1),(int)ginfo.get(s).Dbox.getHigh(2)};\
304\
305 int uhi[3] = {(int)ginfo.get(s).GDbox.getHigh(0),(int)ginfo.get(s).GDbox.getHigh(1),(int)ginfo.get(s).GDbox.getHigh(2)};\
306\
307 int sx = uhi[0]+1;\
308 int sxsy = (uhi[0]+1)*(uhi[1]+1);
309
310#define ITERATE_3D_M(n_pt) int i = lo[2];\
311 for ( ; i <= hi[2] ; i+=1)\
312 {\
313 int j = lo[1];\
314 for ( ; j <= hi[1] ; j+=1)\
315 {\
316 int k = lo[0];\
317 for ( ; k <= hi[0] ; k+=n_pt)\
318 {
319
320
321#define GET_GRID_M(grid) grid.get_loc_grid(s);
322
323
324#define END_LOOP_M(n_pt) it.private_sum<n_pt>();\
325 }\
326 it.private_adjust( - k + sx + lo[0]);\
327 }\
328 it.private_adjust(- j*sx + sxsy + lo[1]*sx);\
329 }\
330 }
331
332#endif /* SRC_GRID_GRID_DIST_ID_ITERATOR_SUB_HPP_ */
333