G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsHDomainBoundaryIterator.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsHSplines/gsHDomain.h>
17 #include <gsHSplines/gsKdNode.h>
19 
21 
22 namespace gismo
23 {
24 
25 // Documentation in gsDomainIterator
39 template<typename T, unsigned d>
41 {
42 public:
43 
44  typedef gsKdNode<d, index_t> node;
45 
46  typedef typename node::point point;
47 
48  typedef typename std::vector<T>::const_iterator uiter;
49 
51 
52  typedef typename hDomain::const_literator leafIterator;
53 
54 public:
55 
57  const boxSide & s )
58  : gsDomainIterator<T>(hbs)
59  {
60  // Initialize mesh data
61  m_meshStart.resize(d);
62  m_meshEnd .resize(d);
63 
64  // Initialize cell data
65  m_curElement.resize(d);
66  m_lower .resize(d);
67  m_upper .resize(d);
68 
69  // Allocate breaks
70  m_breaks = std::vector<std::vector<T> >(d, std::vector<T>());
71 
72  // Set to one quadrature point by default
73  m_quadrature.setNodes( gsVector<index_t>::Ones(d) );
74 
75  // Get the side information
76  par = s.parameter();
77  dir = s.direction();
78 
79  initLeaf(hbs.tree());
80  }
81 
82  // ---> Documentation in gsDomainIterator.h
83  bool next()
84  {
85  this->m_isGood = nextLexicographic(m_curElement, m_meshStart, m_meshEnd);
86 
87  if (this->m_isGood) // new element in m_leaf
88  updateElement();
89  else // went through all elements in m_leaf
90  this->m_isGood = nextLeaf();
91 
92  return this->m_isGood;
93  }
94 
95  // ---> Documentation in gsDomainIterator.h
96  bool next(index_t increment)
97  {
98  for (index_t i = 0; i < increment; i++)
99  this->m_isGood = nextLexicographic(m_curElement, m_meshStart, m_meshEnd);
100 
101  if (this->m_isGood) // new element in m_leaf
102  updateElement();
103  else // went through all elements in m_leaf
104  this->m_isGood = nextLeaf();
105 
106  return this->m_isGood;
107  }
108 
111  void reset()
112  {
113  const gsHTensorBasis<d, T>* hbs = dynamic_cast<const gsHTensorBasis<d, T> *>(m_basis);
114  initLeaf(hbs->tree());
115  }
116 
117  const gsVector<T>& lowerCorner() const { return m_lower; }
118 
119  const gsVector<T>& upperCorner() const { return m_upper; }
120 
121  int getLevel() const
122  {
123  return m_leaf.level();
124  }
125 
126 private:
127 
128  gsHDomainBoundaryIterator();
129 
131  void initLeaf(const hDomain & tree_domain)
132  {
133  // Get the first leaf
134  m_leaf = tree_domain.beginLeafIterator();
135 
136  for (; m_leaf.good(); m_leaf.next() )
137  {
138  // Check if this leaf is on our side
139  if ( leafOnBoundary() )
140  {
141  updateLeaf();
142  return;
143  }
144  }
145  GISMO_ERROR("No leaves.\n");
146  }
147 
148 
150  bool nextLeaf()
151  {
152  for (m_leaf.next(); m_leaf.good(); m_leaf.next() )
153  {
154  // Check if this leaf is on our side
155  if ( leafOnBoundary() )
156  {
157  updateLeaf();
158  return true;
159  }
160  }
161  return false;
162  }
163 
165  bool leafOnBoundary() const
166  {
167  if ( par )
168  {
169  // AM: a little ugly for now, to be improved
170  size_t diadicSize;
171  const gsHTensorBasis<d,T> * hbasis = dynamic_cast<const gsHTensorBasis<d,T> * >(m_basis);
172  if (basis().manualLevels() )
173  {
174  gsKnotVector<T> kv = hbasis->tensorLevel(m_leaf.level()).knots(dir);
175  index_t start = 0;
176  index_t end = kv.uSize()-1;
177  hbasis->_knotIndexToDiadicIndex(m_leaf.level(),dir,start);
178  hbasis->_knotIndexToDiadicIndex(m_leaf.level(),dir,end);
179  diadicSize = end - start;
180  }
181  else
182  diadicSize = static_cast<const gsHTensorBasis<d,T>*>(m_basis)->tensorLevel(m_leaf.level()).knots(dir).uSize() - 1;
183 
184  return static_cast<size_t>(m_leaf.upperCorner().at(dir) ) == diadicSize;// todo: more efficient
185  }
186  else
187  {
188  return m_leaf.lowerCorner().at(dir) == 0;
189  }
190  }
191 
195  void updateLeaf()
196  {
197  const point & lower = m_leaf.lowerCorner();
198  const point & upper = m_leaf.upperCorner();
199  // gsDebug<<"leaf "<< lower.transpose() <<", "
200  // << upper.transpose() <<"\n";
201 
202  const int level2 = m_leaf.level();
203 
204  // Update leaf box
205  for (unsigned dim = 0; dim < d; ++dim)
206  {
207  index_t start = lower(dim);
208  index_t end = upper(dim) ;
209 
210  if (basis().manualLevels() )
211  {
212  static_cast<const gsHTensorBasis<d,T>*>(m_basis)->
213  _diadicIndexToKnotIndex(level2,dim,start);
214  static_cast<const gsHTensorBasis<d,T>*>(m_basis)->
215  _diadicIndexToKnotIndex(level2,dim,end);
216  }
217 
218  const gsKnotVector<T> & kv =
219  static_cast<const gsHTensorBasis<d,T>*>(m_basis)
220  ->tensorLevel(level2).component(dim).knots();
221 
222  m_breaks[dim].clear();
223  if ( dim == dir )
224  {
225  if ( par )
226  {
227  m_breaks[dim].push_back( kv(end-1) );
228  m_breaks[dim].push_back( kv(end ) );
229  }
230  else
231  {
232  m_breaks[dim].push_back( kv(start) );
233  m_breaks[dim].push_back( kv(start+1) );
234  }
235  }
236  else
237  {
238  for (index_t index = start; index <= end; ++index)
239  m_breaks[dim].push_back( kv(index) );// unique index
240  }
241 
242  m_curElement(dim) =
243  m_meshStart(dim) = m_breaks[dim].begin();
244 
245 
246  // for n breaks, we have n - 1 elements (spans)
247  m_meshEnd(dim) = m_breaks[dim].end() - 1;
248  }
249 
250  // We are at a new element, so update cell data
251  updateElement();
252  }
253 
258  {
259  // Update cell data
260  for (unsigned i = 0; i < dir ; ++i)
261  {
262  m_lower[i] = *m_curElement[i];
263  m_upper[i] = *(m_curElement[i]+1);
264  center[i] = (T)(0.5) * (m_lower[i] + m_upper[i]);
265  }
266  m_lower[dir] =
267  m_upper[dir] =
268  center [dir] = (par ? *(m_curElement[dir]+1) : *m_curElement[dir] );
269  for (unsigned i = dir+1; i < d; ++i)
270  {
271  m_lower[i] = *m_curElement[i];
272  m_upper[i] = *(m_curElement[i]+1);
273  center [i] = (T)(0.5) * (m_lower[i] + m_upper[i]);
274  }
275  }
276 
277 // =============================================================================
278 // members
279 // =============================================================================
280 
281  const gsHTensorBasis<d,T> & basis() const { return *static_cast<const gsHTensorBasis<d,T>*>(m_basis); }
282 
283 public:
284 
285  using gsDomainIterator<T>::center;
286  using gsDomainIterator<T>::m_basis;
287 
288 # define Eigen gsEigen
289  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
290 # undef Eigen
291 
292 private:
293 
294  // Boundary parameters
295  unsigned dir; // direction normal to the boundary
296  bool par; // parameter value
297 
298  // The current leaf node of the tree
299  leafIterator m_leaf;
300 
301  // Coordinates of the grid cell boundaries
302  // \todo remove this member
303  std::vector< std::vector<T> > m_breaks;
304 
305  // Extent of the tensor grid
306  gsVector<uiter, d> m_meshStart, m_meshEnd;
307 
308  // Current element as pointers to it's supporting mesh-lines
309  gsVector<uiter, d> m_curElement;
310 
311  // parameter coordinates of current grid cell
312  gsVector<T> m_lower, m_upper;
313 
314  // Quadrature rule
315  gsGaussRule<T> m_quadrature;
316 
317 };
318 
319 } // end namespace gismo
void initLeaf(const hDomain &tree_domain)
Navigates to the first leaf on our side.
Definition: gsHDomainBoundaryIterator.h:131
void reset()
Definition: gsHDomainBoundaryIterator.h:111
Iterates over the leaves of an gsHDomain (tree).
Definition: gsHDomainLeafIter.h:29
short_t dim() const
Return dimension of the elements.
Definition: gsDomainIterator.h:115
bool parameter() const
Returns the parameter value (false=0=start, true=1=end) that corresponds to this side.
Definition: gsBoundary.h:128
const gsVector< T > & upperCorner() const
Returns the upper corner of the current element.
Definition: gsHDomainBoundaryIterator.h:119
Struct representing a kd-tree node.
Definition: gsKdNode.h:34
#define index_t
Definition: gsConfig.h:32
void updateLeaf()
Definition: gsHDomainBoundaryIterator.h:195
const gsHDomain< d > & tree() const
Returns a reference to m_tree.
Definition: gsHTensorBasis.h:601
Provides declaration of the HDomain class.
void _knotIndexToDiadicIndex(const index_t level, const index_t dir, index_t &knotIndex) const
Transfers the knotIndex in the knot span in direction dir on level level to diadic indices...
Definition: gsHTensorBasis.hpp:1892
virtual gsBSplineBasis< T > & component(short_t i)
The 1-d basis for the i-th parameter component at the highest level.
Definition: gsHTensorBasis.h:656
Class representing a (scalar) hierarchical tensor basis of functions .
Definition: gsHTensorBasis.h:74
Re-implements gsDomainIterator for iteration over all boundary elements of a hierarchical parameter d...
Definition: gsHDomainBoundaryIterator.h:40
Class which enables iteration over all elements of a parameter domain.
Definition: gsDomainIterator.h:67
Provides declaration of DomainIterator abstract interface.
const gsVector< T > & lowerCorner() const
Returns the lower corner of the current element.
Definition: gsHDomainBoundaryIterator.h:117
T at(index_t i) const
Returns the i-th element of the vector.
Definition: gsVector.h:177
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
bool nextLeaf()
returns true if there is a another leaf with a boundary element
Definition: gsHDomainBoundaryIterator.h:150
Class with a hierarchical domain structure represented by a box k-d-tree.
Definition: gsHDomain.h:75
bool m_isGood
Definition: gsDomainIterator.h:223
bool next()
Proceeds to the next element.
Definition: gsHDomainBoundaryIterator.h:83
bool nextLexicographic(Vec &cur, const Vec &size)
Iterates through a tensor lattice with the given size. Updates cur and returns true if another entry ...
Definition: gsCombinatorics.h:196
tensorBasis & tensorLevel(index_t i) const
Returns the tensor basis member of level i.
Definition: gsHTensorBasis.h:668
const gsBasis< T > * m_basis
The basis on which the domain iterator is defined.
Definition: gsDomainIterator.h:219
gsVector< T > center
Coordinates of a central point in the element (in the parameter domain).
Definition: gsDomainIterator.h:215
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
Class for representing a knot vector.
Definition: gsKnotVector.h:79
bool leafOnBoundary() const
returns true if the current leaf is on our side
Definition: gsHDomainBoundaryIterator.h:165
size_t uSize() const
Number of unique knots (i.e., without repetitions).
Definition: gsKnotVector.h:245
void updateElement()
Definition: gsHDomainBoundaryIterator.h:257
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition: gsBoundary.h:113
Provides declaration of the tree node.
bool good() const
Returns true iff we are still pointing at a valid leaf.
Definition: gsHDomainLeafIter.h:81
bool next(index_t increment)
Proceeds to the next element (skipping increment elements).
Definition: gsHDomainBoundaryIterator.h:96
Provides declaration of TensorBSplineBasis abstract interface.