G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsGridIterator.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 namespace gismo
17 {
18 
25 {
26  CUBE = 0,
27  BDR = 1,
28  VERTEX = 2,
29  CWISE = 3
30 };
31 
32 // note: default arguments are found in gsForwardDeclarations.h
33 template<typename Z, int mode, short_t d, bool> class gsGridIterator
34 {using Z::GISMO_ERROR_gsGridIterator_has_invalid_template_arguments;};
35 
69 template<class Z, int mode, short_t d>
70 class gsGridIterator<Z,mode,d,true>
71 {
72 public:
73  typedef gsVector<Z,d> point;
74 
75 public:
76 
81  {
82  GISMO_STATIC_ASSERT(std::numeric_limits<Z>::is_integer,"The template parameter needs to be an integer type.");
83  GISMO_STATIC_ASSERT(mode > -1 && mode < 3, "The mode of gsGridIterator needs to be 0, 1 or 2.");
84  }
85 
93  gsGridIterator(point const & a, point const & b, bool open = true)
94  { reset(a, b, open); }
95 
102  explicit gsGridIterator(point const & b, bool open = true)
103  { reset(point::Zero(b.size()), b, open); }
104 
111  explicit gsGridIterator(gsMatrix<Z,d,2> const & ab, bool open = true)
112  { reset(ab.col(0), ab.col(1), open); }
113 
121  inline void reset(point const & a, point const & b, bool open = true)
122  {
123  GISMO_ASSERT(a.rows() == b.rows(), "Invalid endpoint dimensions");
124  m_low = m_cur = a;
125  if (open) m_upp = b.array() - 1; else m_upp = b;
126  m_valid = ( (m_low.array() <= m_upp.array()).all() ? true : false );
127  }
128 
133  void reset() { reset(m_low,m_upp, false); }
134 
135  // See http://eigen.tuxfamily.org/dox-devel/group__TopicStructHavingEigenMembers.html
136  //EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF( (sizeof(point)%16)==0 );
137 
138 public:
139 
140  operator bool() const {return m_valid;}
141 
142  const point & operator*() const {return m_cur;}
143 
144  const point * operator->() const {return &m_cur;}
145 
146  inline gsGridIterator & operator++()
147  {
148  // Multiple implementations according to mode
149  switch (mode)
150  {
151  case 0: // ----------- Iteration over [m_low, m_upp]
152  case 2: // iteration over vertices of the cube [m_low, m_upp]
153  for (index_t i = 0; i != m_cur.size(); ++i)
154  if ( m_cur[i] != m_upp[i] )
155  {
156  if (0==mode) ++m_cur[i]; else m_cur[i] = m_upp[i];
157  return *this;
158  }
159  else
160  m_cur[i] = m_low[i];
161  m_valid = 0;//done
162  return *this;
163 
164  case 1: // ----------- Iteration over boundary of [m_low, m_upp]
165  default:
166  for (index_t i = 0; i != m_cur.size(); ++i)
167  {
168  if ( m_cur[i] != m_upp[i] )
169  {
170  if ( m_cur[i] == m_low[i] && (i+1!=m_cur.size() || 1==m_cur.size()) )
171  {
172  index_t c = i+1;
173  for (index_t j = c; j!=m_cur.size(); ++j)
174  if ( (m_cur[j] == m_low[j]) ||
175  (m_cur[j] == m_upp[j]) )
176  ++c;
177 
178  if ( c==1 )
179  m_cur[i] = m_upp[i];
180  else
181  ++m_cur[i];
182  }
183  else
184  m_cur[i]++;
185 
186  m_cur.head(i) = m_low.head(i);
187  return *this;
188  }
189  }
190  /*fall through to default*/
191  m_valid = 0;//done
192  return *this;
193  }
194  }
195 
199  inline bool isFloor(int i) const { return m_cur[i] == m_low[i];}
200 
204  inline bool isCeil (int i) const
205  { return mode ? m_cur[i] == m_upp[i] : m_cur[i] + 1 == m_upp[i];}
206 
210  bool isBoundary() const
211  {
212  return (m_cur.array() == m_low.array()).any() ||
213  (m_cur.array() == m_upp.array()).any() ;
214  }
215 
220  {
221  switch (mode)
222  {
223  case 0: return ((m_upp-m_low).array() + 1).prod();
224  case 1: return ((m_upp-m_low).array() + 1).prod() - ((m_upp-m_low).array()-1).prod();
225  case 2: return ( 1 << m_low.rows() );
226  default: GISMO_ERROR("gsGridIterator::numPoints");
227  }
228  }
229 
234  point numPointsCwise() const { return (m_upp-m_low).array() + 1;}
235 
239  const point & lower() const {return m_low;}
240 
244  const point & upper() const {return m_upp;}
245 
262  point strides() const
263  {
264  point res(m_low.rows());
265  res[0] = 1;
266  for (index_t i = 1; i != res.size(); ++i )
267  res[i] = res[i-1] * ( m_upp[i-1] - m_low[i-1] + 1 );
268  return res;
269  }
270 
271 private:
272 
273  point m_low, m_upp;
275  bool m_valid;
276 };
277 
278 
307 template<class T, int mode, short_t d>
308 class gsGridIterator<T,mode,d,false>
309 {
310 public:
311 
312  typedef gsVector<T,d> point;
313 
314  typedef gsGridIterator<index_t, mode, d> integer_iterator;
315 
316  typedef typename integer_iterator::point point_index;
317 public:
318 
328  gsGridIterator(point const & a,
329  point const & b,
330  point_index const & np)
331  : m_iter(np, 1)
332  {
333  reset(a, b);
334  GISMO_STATIC_ASSERT(mode > -1 && mode < 3, "The mode of gsGridIterator needs to be 0, 1 or 2.");
335  }
336 
346  point_index const & np)
347  : m_iter(np, 1)
348  {
349  reset(ab.col(0), ab.col(1));
350  }
351 
361  gsGridIterator(gsMatrix<T,d,2> const & ab, unsigned numPoints)
362  : m_low(ab.col(0)), m_upp(ab.col(1))
363  {
364  // deduce the number of points per direction for an approximately uniform grid
365  const gsVector<double,d> L = (ab.col(1) - ab.col(0)).template cast<double>();
366  const double h = std::pow(L.prod()/numPoints, 1.0 / m_low.rows());
367  const point_index npts = (L/h).unaryExpr((double(*)(double))std::ceil).template cast<index_t>();
368  m_iter = integer_iterator(npts, 1);
369  reset(ab.col(0), ab.col(1));
370  }
371 
376  void reset() { m_cur = m_low; m_iter.reset(); }
377 
384  void reset(point const & a,
385  point const & b)
386  {
387  m_cur = m_low = a;
388  m_upp = b;
389  m_step = (b-a).array() / (m_iter.numPointsCwise().array() - 1)
390  .matrix().cwiseMax(1).template cast<T>().array() ;
391  m_iter.reset();
392  }
393 
394  gsMatrix<T> toMatrix() const
395  {
396  gsMatrix<T> res(m_cur.rows(), numPoints());
397  integer_iterator iter = m_iter;
398  iter.reset();
399 
400  for(index_t c = 0; iter; ++iter, ++c)
401  update(*iter,res.col(c).data());
402 
403  return res;
404  }
405 
406  // See http://eigen.tuxfamily.org/dox-devel/group__TopicStructHavingEigenMembers.html
407  //EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF( (sizeof(point)%16)==0 );
408 
409 public:
410 
411  operator bool() const {return m_iter;}
412 
413  const gsMatrix<T> & operator*() const {return m_cur;}
414 
415  const gsMatrix<T> * operator->() const {return &m_cur;}
416 
417  inline gsGridIterator & operator++()
418  {
419  if ( ++m_iter ) update(*m_iter, m_cur.data());
420  return *this;
421  }
422 
426  inline bool isFloor(int i) const { return m_iter.isFloor(i);}
427 
431  inline bool isCeil (int i) const { return m_iter.isCeil(i);}
432 
436  inline bool isBoundary() const { return m_iter.isBoundary();}
437 
441  index_t numPoints() const {return m_iter.numPoints();}
442 
447  point_index numPointsCwise() const {return m_iter.numPointsCwise();}
448 
452  const point & lower() const {return m_low;}
453 
457  const point & upper() const {return m_upp;}
458 
462  const point_index & tensorIndex() const { return *m_iter;}
463 
467  index_t index(const index_t i) const { return m_iter->at(i);}
468 
472  const point & step() const {return m_step;}
473 
478  const integer_iterator & index_iterator() const { return m_iter;}
479 
489  inline const gsMatrix<T> operator [] (const point_index & ti) const
490  {
491  gsMatrix<T> res(m_low.rows(),1);
492  update(ti, res.data());
493  return res;
494  }
495 
496 private:
497 
498  // Update the point \a pt to the position \a ti
499  inline void update(const point_index & ti, T * pt) const
500  {
501  for (index_t i = 0; i != m_low.size(); ++i)
502  if ( ti[i] == m_iter.lower()[i] )
503  *(pt++) = m_low[i]; // avoid numerical error at first val
504  else if ( ti[i] == m_iter.upper()[i] )
505  *(pt++) = m_upp[i]; // avoid numerical error at last val
506  else
507  *(pt++) = m_low[i] + static_cast<T>(ti[i]) * m_step[i];
508  }
509 
510 private:
511 
512  point m_low, m_upp, m_step;
513 
514  integer_iterator m_iter;
516 };
517 
518 
538 template<class T, short_t d> // mode == 3 == CWISE
539 class gsGridIterator<T,CWISE,d,false>
540 {
541 public:
542 
543  typedef gsGridIterator<index_t, 0, d> integer_iterator;
544 
545  typedef typename integer_iterator::point point_index;
546 
547  typedef gsVector<const T *,d, 2> CwiseData; //non-aligned array
548 
549 public:
550 
557  template<class CwiseContainer>
558  explicit gsGridIterator(const CwiseContainer & cwise)
559  : m_cwise(cwise.size()), m_cur(m_cwise.size(),1)
560  {
561  point_index npts(m_cwise.size());
562  for (index_t i = 0; i != npts.size(); ++i)
563  {
564  m_cwise[i] = cwise[i].data();
565  npts[i] = cwise[i].size() - 1;
566  GISMO_ASSERT(cwise[i].cols()==1 || cwise[i].rows()==1, "Invalid input");
567  }
568  m_iter = integer_iterator(npts, 0);
569  //if (1==cwise.front().cols())
570  // m_cur.derived().resize(1, npts.size());
571  //else
572  //m_cur.derived().resize(npts.size(), 1);
573  update(*m_iter, m_cur.data());
574  }
575 
576  template<class Matrix_t>
577  explicit gsGridIterator(const std::vector<Matrix_t*> & cwise)
578  : m_cwise(cwise.size()), m_cur(m_cwise.size(),1)
579  {
580  point_index npts(m_cwise.size());
581  for (index_t i = 0; i != npts.size(); ++i)
582  {
583  m_cwise[i] = cwise[i]->data();
584  npts[i] = cwise[i]->size() - 1;
585  GISMO_ASSERT(cwise[i]->cols()==1 || cwise[i]->rows()==1, "Invalid input");
586  }
587  m_iter = integer_iterator(npts, 0);
588  update(*m_iter, m_cur.data());
589  }
590 
595  void reset() { m_iter.reset(); update(*m_iter, m_cur.data());}
596 
597  //void restart() { m_iter.reset(); update(*m_iter, m_cur.data());}
598 
599 public:
600 
601  operator bool() const {return m_iter;}
602 
603  const gsMatrix<T> & operator*() const {return m_cur;}
604 
605  const gsMatrix<T> * operator->() const {return &m_cur;}
606 
607  inline gsGridIterator & operator++()
608  {
609  if (++m_iter) update(*m_iter, m_cur.data());
610  return *this;
611  }
612 
616  inline bool isFloor(int i) const { return m_iter.isFloor(i);}
617 
621  inline bool isCeil (int i) const { return m_iter.isCeil(i);}
622 
626  inline bool isBoundary() const { return m_iter.isBoundary();}
627 
631  index_t numPoints() const {return m_iter.numPoints();}
632 
637  point_index numPointsCwise() const {return m_iter.numPointsCwise();}
638 
642  const point_index & tensorIndex() const { return *m_iter;}
643 
647  index_t index(const index_t i) const { return m_iter->at(i);}
648 
653  const integer_iterator & index_iterator() const { return m_iter;}
654 
664  inline const gsMatrix<T> operator [] (const point_index & ti) const
665  {
666  gsMatrix<T> res(m_cur.rows(),1);
667  update(ti, res.data());
668  return res;
669  }
670 
671 private:
672 
673  // Update the point \a pt to the position \a ti
674  inline void update(const point_index & ti, T * pt)
675  {
676  for (index_t i = 0; i != m_cur.rows(); ++i)
677  *(pt++) = m_cwise[i][ti[i]];
678  }
679 
680 private:
681 
683 
684  integer_iterator m_iter;
686 };
687 
688 
689 } // namespace gismo
Boundary mode iterates over boundary lattice points only.
Definition: gsGridIterator.h:27
gsGridIterator()
Empty constructor.
Definition: gsGridIterator.h:80
bool isCeil(int i) const
Returns true if the i-th coordinate has maximal value.
Definition: gsGridIterator.h:204
Coordinate-wise mode iterates over a grid given by coordinate vectors.
Definition: gsGridIterator.h:29
integer_iterator m_iter
Underlying integer lattice iterator.
Definition: gsGridIterator.h:514
const point_index & tensorIndex() const
Returns the tensor index of the current point.
Definition: gsGridIterator.h:462
const point & step() const
Returns the coordinate-wise stepping between the samples.
Definition: gsGridIterator.h:472
Vertex mode iterates over cube vertices only.
Definition: gsGridIterator.h:28
CwiseData m_cwise
List of coordinate-wise values.
Definition: gsGridIterator.h:682
index_t numPoints() const
Returns the total number of points that are iterated.
Definition: gsGridIterator.h:219
const point & lower() const
Returns the first point in the iteration.
Definition: gsGridIterator.h:452
void reset()
Resets the iterator, so that a new iteration over the points may start.
Definition: gsGridIterator.h:595
gsGridIterator(point const &a, point const &b, point_index const &np)
Constructor using lower and upper limits.
Definition: gsGridIterator.h:328
gsMatrix< T > m_cur
Current point pointed at by the iterator.
Definition: gsGridIterator.h:515
integer_iterator m_iter
Underlying integer lattice iterator.
Definition: gsGridIterator.h:684
#define index_t
Definition: gsConfig.h:32
gsGridIterator(gsMatrix< T, d, 2 > const &ab, point_index const &np)
Constructor using lower and upper limits.
Definition: gsGridIterator.h:345
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition: gsMatrix.h:38
bool isFloor(int i) const
Returns true if the i-th coordinate has minimal value.
Definition: gsGridIterator.h:199
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
gsGridIteratorMode
Specifies aliases describing the modes for gismo::gsGridIterator.
Definition: gsGridIterator.h:24
index_t index(const index_t i) const
Returns the i-th index of the current point.
Definition: gsGridIterator.h:647
bool isCeil(int i) const
Returns true if the i-th coordinate has maximal value.
Definition: gsGridIterator.h:621
const point & upper() const
Returns the last point in the iteration.
Definition: gsGridIterator.h:457
gsGridIterator(gsMatrix< Z, d, 2 > const &ab, bool open=true)
Constructor using lower and upper limits.
Definition: gsGridIterator.h:111
gsGridIterator(gsMatrix< T, d, 2 > const &ab, unsigned numPoints)
Constructor using lower and upper limits.
Definition: gsGridIterator.h:361
point m_upp
Iteration lower and upper limits.
Definition: gsGridIterator.h:273
index_t numPoints() const
Returns the total number of points that are iterated.
Definition: gsGridIterator.h:441
void reset()
Resets the iterator, so that a new iteration over the points may start.
Definition: gsGridIterator.h:133
void reset(point const &a, point const &b, bool open=true)
Resets the iterator using new lower and upper limits.
Definition: gsGridIterator.h:121
bool isBoundary() const
Returns true if the current point lies on a boundary.
Definition: gsGridIterator.h:210
point_index numPointsCwise() const
Returns the total number of points per coordinate which are iterated.
Definition: gsGridIterator.h:447
gsGridIterator(const CwiseContainer &cwise)
Constructor using references to the coordinate vectors.
Definition: gsGridIterator.h:558
EIGEN_STRONG_INLINE mult_expr< E1, E2 > const operator*(_expr< E1 > const &u, _expr< E2 > const &v)
Multiplication operator for expressions.
Definition: gsExpressions.h:4561
point m_step
Iteration lower and upper limits and stepsize.
Definition: gsGridIterator.h:512
void reset(point const &a, point const &b)
Resets the iterator using new lower and upper limits.
Definition: gsGridIterator.h:384
index_t index(const index_t i) const
Returns the i-th index of the current point.
Definition: gsGridIterator.h:467
bool m_valid
Indicates the state of the iterator.
Definition: gsGridIterator.h:275
gsGridIterator(point const &a, point const &b, bool open=true)
Constructor using lower and upper limits.
Definition: gsGridIterator.h:93
bool isBoundary() const
Returns true if the current point lies on a boundary.
Definition: gsGridIterator.h:436
bool isFloor(int i) const
Returns true if the i-th coordinate has minimal value.
Definition: gsGridIterator.h:616
const point_index & tensorIndex() const
Returns the tensor index of the current point.
Definition: gsGridIterator.h:642
void reset()
Resets the iterator, so that a new iteration over the points may start.
Definition: gsGridIterator.h:376
Cube mode iterates over all lattice points inside a cube.
Definition: gsGridIterator.h:26
bool isBoundary() const
Returns true if the current point lies on a boundary.
Definition: gsGridIterator.h:626
gsMatrix< T > m_cur
Current point pointed at by the iterator.
Definition: gsGridIterator.h:685
point numPointsCwise() const
Returns the total number of points per coordinate which are iterated.
Definition: gsGridIterator.h:234
point_index numPointsCwise() const
Returns the total number of points per coordinate which are iterated.
Definition: gsGridIterator.h:637
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
bool isFloor(int i) const
Returns true if the i-th coordinate has minimal value.
Definition: gsGridIterator.h:426
bool isCeil(int i) const
Returns true if the i-th coordinate has maximal value.
Definition: gsGridIterator.h:431
const point & lower() const
Returns the first point in the iteration.
Definition: gsGridIterator.h:239
index_t numPoints() const
Returns the total number of points that are iterated.
Definition: gsGridIterator.h:631
const integer_iterator & index_iterator() const
Returns a reference to the underlying integer lattice iterator.
Definition: gsGridIterator.h:478
const point & upper() const
Returns the last point in the iteration.
Definition: gsGridIterator.h:244
const integer_iterator & index_iterator() const
Returns a reference to the underlying integer lattice iterator.
Definition: gsGridIterator.h:653
point strides() const
Utility function which returns the vector of strides.
Definition: gsGridIterator.h:262
gsGridIterator(point const &b, bool open=true)
Constructor using upper limit. The iteration starts from zero.
Definition: gsGridIterator.h:102
point m_cur
Current point pointed at by the iterator.
Definition: gsGridIterator.h:274