1/*
2 * grid_key_dx_iterator_sub.hpp
3 *
4 * Created on: Dec 15, 2015
5 * Author: i-bird
6 */
7
8#ifndef OPENFPM_DATA_SRC_GRID_ITERATORS_GRID_KEY_DX_ITERATOR_SUB_HPP_
9#define OPENFPM_DATA_SRC_GRID_ITERATORS_GRID_KEY_DX_ITERATOR_SUB_HPP_
10
11#include "grid_key_dx_iterator.hpp"
12#include "Grid/grid_key.hpp"
13
14/* \brief grid_key_dx_iterator_sub can adjust the domain if the border go out-of-side
15 * in this case a warning is produced
16 *
17 * \tparam dim dimensionality
18 *
19 */
20template <unsigned int dim, typename linearizer>
21class print_warning_on_adjustment
22{
23public:
24
25 /*! \brief print warning type1
26 *
27 * \param gk_start start point
28 *
29 */
30 inline static void pw1(size_t i, const grid_key_dx<dim> & gk_start) {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " start with index smaller than zero x[" << i << "]=" << gk_start.get(i) << "\n";}
31
32 /*! \brief print warning type2
33 *
34 * \param i component
35 * \param gk_start start point
36 *
37 */
38 inline static void pw2(size_t i, const grid_key_dx<dim> & gk_start) {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " Cropping start point x[" << i << "]=" << gk_start.get(i) << " to x[" << i << "]=0 \n" ;}
39
40
41 /*! \brief print warning type3
42 *
43 *
44 */
45 inline static void pw3() {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " stop with smaller index than start \n";}
46
47
48 /*! \brief print warning type4
49 *
50 * \param i component
51 * \param gk_stop stop point
52 * \param grid_base grid information
53 *
54 */
55 inline static void pw4(size_t i, const grid_key_dx<dim> & gk_stop, const linearizer & grid_base) {std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " stop index bigger than cell domain x[" << i << "]=" << gk_stop.get(i) << " > " << grid_base.size(i) << "\n";}
56
57 /*! \brief print warning type5
58 *
59 *
60 */
61 inline static void pw5() {std::cerr << "Warning grid_key_dx_iterator_sub: " << __FILE__ << ":" << __LINE__ << " the starting point is not smaller or equal than than the stop point in all the coordinates" << "\n";}
62};
63
64/* \brief grid_key_dx_iterator_sub can adjust the domain if the border go out-of-side
65 * in this case a warning is produced
66 *
67 * \tparam dim dimensionality
68 * \tparam gb type of grid
69 *
70 */
71template <unsigned int dim, typename linearizer>
72class do_not_print_warning_on_adjustment
73{
74public:
75
76 /*! \brief print warning type1
77 *
78 * \param i component
79 * \param gk_start start point
80 *
81 */
82 inline static void pw1(size_t i, const grid_key_dx<dim> & gk_start) {}
83
84 /*! \brief print warning type2
85 *
86 * \param i component
87 * \param gk_start start point
88 *
89 */
90 inline static void pw2(size_t i, const grid_key_dx<dim> & gk_start) {}
91
92 /*! \brief print warning type3
93 *
94 *
95 */
96 inline static void pw3() {}
97
98 /*! \brief print warning type4
99 *
100 * \param i component
101 * \param gk_stop stop point
102 * \param grid_base grid information
103 *
104 */
105 inline static void pw4(size_t i, const grid_key_dx<dim> & gk_stop, const linearizer & grid_base) {}
106
107 /*! \brief print warning type5
108 *
109 *
110 */
111 inline static void pw5() {}
112};
113
114template<unsigned int dim, typename stl_type, typename linearizer>
115struct post_increment_sub_impl
116{
117 static inline void inc(grid_key_dx<dim> & gk,
118 grid_key_dx<dim> & gk_start,
119 grid_key_dx<dim> & gk_stop,
120 stl_type & stl_code,
121 linearizer & grid_base)
122 {
123 long int i = 0;
124 for ( ; i < dim-1 ; i++)
125 {
126 /* coverity[dead_error_begin] */
127 size_t id = gk.get(i);
128 if ((long int)id > gk_stop.get(i))
129 {
130 // ! overflow, increment the next index
131
132 size_t idr = gk.get(i) - gk_start.get(i);
133 gk.set_d(i,gk_start.get(i));
134 id = gk.get(i+1);
135 gk.set_d(i+1,id+1);
136
137 stl_code.adjust_offset(i,idr,grid_base);
138 }
139 else
140 {
141 break;
142 }
143 }
144 }
145};
146
147
148/**
149 *
150 * Grid key class iterator, iterate through a sub-grid defined by an hyper-cube
151 *
152 * \param dim dimensionality of the grid
153 *
154 * \note if you have a grid you can get this object from getIteratorSub()
155 *
156 * ### Sub grid iterator declaration and usage
157 * \snippet grid_unit_tests.hpp Sub-grid iterator test usage
158 *
159 */
160
161template<unsigned int dim, typename stencil, typename linearizer, typename warn>
162class grid_key_dx_iterator_sub : public grid_key_dx_iterator<dim,stencil,linearizer>
163{
164#ifdef SE_CLASS1
165 bool initialized = false;
166#endif
167
168 //! grid base where we are iterating
169 linearizer grid_base;
170
171 //! start point
172 grid_key_dx<dim> gk_start;
173
174 //! stop point
175 grid_key_dx<dim> gk_stop;
176
177 /*! \brief Initialize gk
178 *
179 */
180 void Initialize()
181 {
182 // Check that start and stop are inside the domain otherwise crop them
183
184 for (size_t i = 0 ; i < dim ; i++)
185 {
186 // if start smaller than 0
187 if (gk_start.get(i) < 0)
188 {
189#ifdef SE_CLASS1
190 warn::pw1(i,gk_start);
191#endif
192 if (gk_start.get(i) < gk_stop.get(i))
193 {
194#ifdef SE_CLASS1
195 warn::pw2(i,gk_start);
196#endif
197 gk_start.set_d(i,0);
198 }
199 else
200 {
201#ifdef SE_CLASS1
202 warn::pw3();
203#endif
204 // No points are available
205 gk_start.set_d(dim-1,gk_stop.get(dim-1)+1);
206 break;
207 }
208 }
209
210 // if stop bigger than the domain
211 if (gk_stop.get(i) >= (long int)grid_base.size(i))
212 {
213#ifdef SE_CLASS1
214 warn::pw4(i,gk_stop,grid_base);
215#endif
216
217 if (gk_start.get(i) < (long int)grid_base.size(i))
218 gk_stop.set_d(i,grid_base.size(i)-1);
219 else
220 {
221 // No point are available
222 gk_start.set_d(dim-1,gk_stop.get(dim-1)+1);
223 break;
224 }
225 }
226 }
227
228 //! Initialize gk
229 for (unsigned int i = 0 ; i < dim ; i++)
230 {
231 this->gk.set_d(i,gk_start.get(i));
232 }
233
234#ifdef SE_CLASS1
235 initialized = true;
236#endif
237 }
238
239 /*! \brief After incremented we have to check we did not overflo
240 * any dimension and in case adjust the dimensions
241 *
242 */
243 void post_increment()
244 {
245 //! check the overflow of all the index with exception of the last dimensionality
246
247// post_increment_sub_impl<dim,stencil>::inc(this->gk,gk_start,gk_stop,this->stl_code,grid_base);
248
249 long int i = 0;
250 for ( ; i < dim-1 ; i++)
251 {
252 /* coverity[dead_error_begin] */
253 size_t id = this->gk.get(i);
254 if ((long int)id > gk_stop.get(i))
255 {
256 // ! overflow, increment the next index
257
258 size_t idr = this->gk.get(i) - gk_start.get(i);
259 this->gk.set_d(i,gk_start.get(i));
260 id = this->gk.get(i+1);
261 this->gk.set_d(i+1,id+1);
262
263 this->stl_code.adjust_offset(i,idr,grid_base);
264 }
265 else
266 {
267 break;
268 }
269 }
270 }
271
272public:
273
274 /*! \brief Default constructor
275 *
276 * \warning extremely unsafe
277 * If you use this constructor before use the iterator you should call reinitialize first
278 *
279 */
280 grid_key_dx_iterator_sub()
281 {}
282
283 /*! \brief Constructor from another grid_key_dx_iterator_sub
284 *
285 *
286 * \param g_s_it grid_key_dx_iterator_sub
287 *
288 */
289 grid_key_dx_iterator_sub(const grid_key_dx_iterator_sub<dim,stencil,linearizer> & g_s_it)
290 :grid_key_dx_iterator<dim,stencil>(g_s_it),grid_base(g_s_it.grid_base),gk_start(g_s_it.gk_start), gk_stop(g_s_it.gk_stop)
291 {
292#ifdef SE_CLASS1
293 //! If we are on debug check that the stop grid_key id bigger than the start
294 //! grid_key
295
296 for (unsigned int i = 0 ; i < dim ; i++)
297 {
298 if (gk_start.get(i) > gk_stop.get(i))
299 {
300 warn::pw5();
301 }
302 }
303#endif
304
305 Initialize();
306 }
307
308
309 /*! \brief Constructor require a grid grid<dim,T>
310 *
311 * It construct an iterator over an hyper-cube defined by start and stop,
312 * \warning if start and stop are outside the domain defined by g the intersection
313 * will be considered
314 *
315 * \tparam T type of object that the grid store
316 *
317 * \param g Grid on which iterate
318 * \param start starting point
319 * \param stop end point
320 *
321 */
322 grid_key_dx_iterator_sub(const linearizer & g,
323 const grid_key_dx<dim> & start,
324 const grid_key_dx<dim> & stop)
325 : grid_key_dx_iterator<dim,stencil,linearizer>(g),grid_base(g),gk_start(start), gk_stop(stop)
326 {
327#ifdef SE_CLASS1
328 //! If we are on debug check that the stop grid_key id bigger than the start
329 //! grid_key
330
331 for (unsigned int i = 0 ; i < dim ; i++)
332 {
333 if (gk_start.get(i) > gk_stop.get(i))
334 {
335 warn::pw5();
336 }
337 }
338#endif
339
340 Initialize();
341 }
342
343
344 /*! \brief Constructor require a grid grid<dim,T>
345 *
346 * It construct an iterator over an hyper-cube defined by start and stop,
347 * \warning if start and stop are outside the domain defined by g the intersection
348 * will be considered
349 *
350 * \tparam T type of object that the grid store
351 *
352 * \param g Grid on which iterate
353 * \param start starting point
354 * \param stop end point
355 * \param stencil_pnt stencil points
356 *
357 */
358 grid_key_dx_iterator_sub(const linearizer & g,
359 const grid_key_dx<dim> & start,
360 const grid_key_dx<dim> & stop,
361 const grid_key_dx<dim> (& stencil_pnt)[stencil::nsp])
362 :grid_key_dx_iterator<dim,stencil,linearizer>(g,stencil_pnt),grid_base(g),gk_start(start), gk_stop(stop)
363 {
364#ifdef SE_CLASS1
365 //! If we are on debug check that the stop grid_key id bigger than the start
366 //! grid_key
367
368 for (unsigned int i = 0 ; i < dim ; i++)
369 {
370 if (gk_start.get(i) > gk_stop.get(i))
371 {
372 warn::pw5();
373 }
374 }
375#endif
376
377 Initialize();
378 grid_key_dx_iterator<dim,stencil>::calc_stencil_offset(this->gk);
379 }
380
381 /*! \brief Constructor
382 *
383 * It construct an iterator setting only the stencil point.
384 * Require reinitialize to make it work
385 *
386 *
387 * \param stencil_pnt stencil points
388 *
389 */
390 grid_key_dx_iterator_sub(const grid_key_dx<dim> (& stencil_pnt)[stencil::nsp])
391 :grid_key_dx_iterator<dim,stencil>(stencil_pnt)
392 {
393 }
394
395 /*! \brief Constructor require a grid grid<dim,T>
396 *
397 * It construct an iterator over an hyper-cube defined by start and stop,
398 * \warning if start and stop are outside the domain defined by g the intersection
399 * will be considered
400 *
401 * \tparam T type of object that the grid store
402 *
403 * \param g info of the grid where we are iterating
404 * \param m Margin of the domain
405 *
406 */
407 grid_key_dx_iterator_sub(const linearizer & g, const size_t m)
408 :grid_key_dx_iterator<dim>(g),grid_base(g)
409 {
410 // Initialize the start and stop point
411 for (unsigned int i = 0 ; i < dim ; i++)
412 {
413 gk_start.set_d(i,m);
414 gk_stop.set_d(i,g.size(i)-m-1);
415 }
416
417 //
418 Initialize();
419 }
420
421 /*! \brief Constructor require a grid grid<dim,T>
422 *
423 * It construct an iterator over an hyper-cube defined by start and stop,
424 *
425 *
426 * \param g Grid on which iterate
427 * \param start starting point
428 * \param stop end point
429 *
430 */
431 grid_key_dx_iterator_sub(const linearizer & g,
432 const size_t (& start)[dim],
433 const size_t (& stop)[dim])
434 :grid_key_dx_iterator<dim>(g),grid_base(g),gk_start(start), gk_stop(stop)
435 {
436#ifdef SE_CLASS1
437 //! If we are on debug check that the stop grid_key id bigger than the start
438 //! grid_key
439
440 for (unsigned int i = 0 ; i < dim ; i++)
441 {
442 if (start[i] > stop[i])
443 {
444 warn::pw5();
445 }
446 }
447#endif
448
449 Initialize();
450 }
451
452 /*! \brief Get the next element
453 *
454 * Get the next element
455 *
456 * \return the next grid_key
457 *
458 */
459 grid_key_dx_iterator_sub<dim,stencil,linearizer,warn> & operator++()
460 {
461#ifdef SE_CLASS1
462 if (initialized == false)
463 {std::cerr << "Error: " << __FILE__ << __LINE__ << " using unitialized iterator" << "\n";}
464#endif
465
466 //! increment the first index
467
468 size_t id = this->gk.get(0);
469 this->gk.set_d(0,id+1);
470
471 this->stl_code.increment();
472
473 //! check the overflow of all the index with exception of the last dimensionality
474
475 post_increment();
476
477 return *this;
478 }
479
480 /*! \brief increment the operator by more than one
481 *
482 * \return the next grid_key
483 *
484 */
485 grid_key_dx_iterator_sub<dim,stencil,warn> & operator+=(int nsteps)
486 {
487#ifdef SE_CLASS1
488 if (initialized == false)
489 {std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " using unitialized iterator" << "\n";}
490#endif
491
492 for (size_t i = 0 ; i < nsteps ; i++)
493 {
494 this->operator ++();
495 }
496
497 return *this;
498 }
499
500 /*! \brief Check if there is the next element
501 *
502 * Check if there is the next element
503 *
504 * \return true if there is the next, false otherwise
505 *
506 */
507 inline bool isNext()
508 {
509#ifdef SE_CLASS1
510 if (initialized == false)
511 {std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " using unitialized iterator" << "\n";}
512#endif
513
514 if (this->gk.get(dim-1) <= gk_stop.get(dim-1))
515 {
516 //! we did not reach the end of the grid
517
518 return true;
519 }
520
521 //! we reach the end of the grid
522 return false;
523 }
524
525 /*! \brief Return the actual grid key iterator
526 *
527 * \return the actual key
528 *
529 */
530 inline grid_key_dx<dim> get() const
531 {
532#ifdef SE_CLASS1
533 if (initialized == false)
534 {std::cerr << "Error: " << __FILE__ << __LINE__ << " using unitialized iterator" << "\n";}
535#endif
536
537 return grid_key_dx_iterator<dim,stencil,linearizer>::get();
538 }
539
540 /*! \brief Reinitialize the iterator
541 *
542 * it re-initialize the iterator with the passed grid_key_dx_iterator_sub
543 * the actual position of the grid_key_dx_iterator_sub is ignored
544 *
545 * \param g_s_it grid_key_dx_iterator_sub
546 *
547 */
548 inline void reinitialize(const grid_key_dx_iterator_sub<dim> & g_s_it)
549 {
550 // Reinitialize the iterator
551
552 grid_key_dx_iterator<dim,stencil>::reinitialize(g_s_it);
553 grid_base = g_s_it.getGridInfo();
554 gk_start = g_s_it.getStart();
555 gk_stop = g_s_it.getStop();
556
557
558#ifdef SE_CLASS1
559 //! If we are on debug check that the stop grid_key id bigger than the start
560 //! grid_key
561
562 for (unsigned int i = 0 ; i < dim ; i++)
563 {
564 if (gk_start.get(i) > gk_stop.get(i))
565 {
566 warn::pw5();
567 }
568 }
569
570 initialized = true;
571#endif
572
573 Initialize();
574 grid_key_dx_iterator<dim,stencil>::calc_stencil_offset(this->gk);
575 }
576
577 /*! \brief Get the volume spanned by this sub-grid iterator
578 *
579 * \return the volume
580 *
581 */
582 inline size_t getVolume()
583 {
584 return Box<dim,long int>::getVolumeKey(gk_start.get_k(), gk_stop.get_k());
585 }
586
587 /*! \brief Reset the iterator (it restart from the beginning)
588 *
589 */
590 inline void reset()
591 {
592 //! Initialize to 0 the index
593
594 for (size_t i = 0 ; i < dim ; i++)
595 {this->gk.set_d(i,gk_start.get(i));}
596 }
597
598 /*! \brief Return the grid information related to this grid
599 *
600 *
601 *
602 */
603 inline const linearizer & getGridInfo() const
604 {
605 return grid_base;
606 }
607
608 /*! \brief Starting point
609 *
610 * \return starting point
611 *
612 */
613 const grid_key_dx<dim> & getStart() const
614 {
615 return gk_start;
616 }
617
618 /*! \brief Stop point
619 *
620 * \return stop point
621 *
622 */
623 const grid_key_dx<dim> & getStop() const
624 {
625 return gk_stop;
626 }
627
628 /*! \brief Sum a template constant
629 *
630 * \tparam compile-time offset
631 *
632 */
633 template<unsigned int tot_add>
634 inline void private_sum()
635 {
636 this->stl_code.template private_sum<tot_add>();
637 }
638
639 /*! \brief Sum a template constant
640 *
641 * \param tot_add Add an offset to all the pointer
642 *
643 */
644 inline void private_adjust(size_t tot_add)
645 {
646 this->stl_code.private_adjust(tot_add);
647 }
648
649 /* \brief Set the iterator in a way that isNext return false
650 *
651 */
652 void invalidate()
653 {
654 this->gk.set_d(dim-1,1);
655 this->gk_stop.set_d(dim-1,0);
656
657#ifdef SE_CLASS1
658 this->initialized = true;
659#endif
660 }
661};
662
663
664//// Specialization for dimension 0
665
666/**
667 *
668 * Grid key class iterator, iterate through a sub-grid defined by an hyper-cube
669 *
670 * \param dim dimensionality of the grid
671 *
672 * \note if you have a grid you can get this object from getIteratorSub()
673 *
674 * ### Sub grid iterator declaration and usage
675 * \snippet grid_unit_tests.hpp Sub-grid iterator test usage
676 *
677 */
678
679template<typename warn>
680class grid_key_dx_iterator_sub<0,warn>
681{
682
683public:
684
685 grid_key_dx_iterator_sub()
686 {}
687
688 /*! \brief Next point
689 *
690 * stub version do nothing
691 *
692 * \return itself
693 *
694 */
695 grid_key_dx_iterator<0> & operator++()
696 {return *this;}
697
698 /*! \brief Is there a next point
699 *
700 * stub version
701 *
702 * \return always false
703 *
704 */
705 inline bool isNext()
706 {return false;}
707
708 /*! \brief return the volume
709 *
710 * stub version
711 *
712 * \return always 0
713 *
714 */
715 inline size_t getVolume()
716 {return 0;}
717
718 /*! \brief Reset the iterator
719 *
720 * stub version, do nothing
721 *
722 *
723 */
724 inline void reset()
725 {}
726};
727
728#endif /* OPENFPM_DATA_SRC_GRID_ITERATORS_GRID_KEY_DX_ITERATOR_SUB_HPP_ */
729