G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsHTensorBasis.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsCore/gsBasis.h>
17 
18 #include <gsHSplines/gsHDomain.h>
21 
22 #include <gsCore/gsBoundary.h>
23 
25 #include <gsNurbs/gsBSplineBasis.h> // for gsBasis::component(short_t)
26 
27 #include <gsUtils/gsSortedVector.h>
28 
29 namespace gismo
30 {
31 
32 struct lvl_coef
33 {
34  int pos; // flat index at grid of level \a lvl
35  int unsigned lvl; // level
36  real_t coef; // value of the coefficient (lvl,pos)
37 };
38 
73 template<short_t d, class T>
74 class GISMO_DEFAULT_VIS gsHTensorBasis: public gsBasis<T>
75 {
76 public:
78  typedef memory::shared_ptr< gsHTensorBasis > Ptr;
79 
81  typedef memory::unique_ptr< gsHTensorBasis > uPtr;
82 
84 
85  typedef T Scalar_t;
86 
87  typedef gsHDomain<d> hdomain_type;
88 
89  typedef typename hdomain_type::point point;
90 
91  typedef typename hdomain_type::box box;
92 
93  typedef std::vector< box > boxHistory;
94 
95  typedef gsSortedVector< index_t > CMatrix; // charMatrix_
96 
97  typedef typename CMatrix::const_iterator cmatIterator;
98 
99  typedef gsKnotVector<T> KnotVectorType;
100 
101  typedef typename gsBSplineTraits<static_cast<short_t>(d-1),T>::Basis BoundaryBasisType;
102 
103  typedef typename gsBSplineTraits<d,T>::Basis tensorBasis;
104 
106  static const short_t Dim = d;
107 
108  friend class gsHDomainIterator<T,d>;
109  friend class gsHDomainBoundaryIterator<T,d>;
110 public:
111 
114  :
115  m_manualLevels(false)
116  {
117  initialize_class(tensorBasis());
118  update_structure();
119  }
120 
121  gsHTensorBasis( gsBasis<T> const& tbasis, bool manualLevels)
122  :
123  m_manualLevels(manualLevels)
124  {
125  if (!m_manualLevels)
126  {
127  initialize_class(tbasis);
128  // Build the characteristic matrices
129  }
130  else
131  {
132  // Degrees
133  m_deg.resize(d);
134  for( index_t i = 0; i < d; i++)
135  m_deg[i] = tbasis.degree(i);
136 
137  // Construct the initial basis
138  m_bases.reserve(3);
139  if ( const tensorBasis * tb2 = dynamic_cast<const tensorBasis*>(&tbasis) )
140  {
141  m_bases.push_back(tb2->clone().release());
142  // For the tbasis, count the unique knot values
143  std::vector<std::vector<index_t>> lvlIndices(d);
144  std::vector<index_t> dirIndices;
145  for (short_t dim=0; dim!=d; dim++)
146  {
147  dirIndices.resize(tb2->knots(dim).uSize());
148  std::iota(dirIndices.begin(),dirIndices.end(),0);
149  lvlIndices[dim] = dirIndices;
150  }
151  m_uIndices.push_back(lvlIndices);
152  }
153  else
154  {
155  GISMO_ERROR("Cannot construct a Hierarchical basis from "<< tbasis );
156  }
157 
158  // Initialize the binary tree
159  point upp;
160  for ( index_t i = 0; i!=d; ++i )
161  upp[i] = m_bases[0]->knots(i).numElements();
162 
163  m_tree.init(upp);
164  }
165  update_structure();
166  }
167 
168  gsHTensorBasis( gsTensorBSplineBasis<d,T> const& tbasis,
169  const std::vector<index_t> & boxes)
170  :
171  m_manualLevels(false)
172  {
173  initialize_class(tbasis);
174  point i1;
175  point i2;
176  //i1.resize(d);
177  //i2.resize(d);
178  // Set all functions to active
179  GISMO_ASSERT( (boxes.size()%(2*d+1))==0,
180  "The points did not define boxes properly. The basis was created without any domain structure.");
181 
182  for( size_t i = 0; i < (boxes.size()/(2*d+1)); i++)
183  {
184  for( short_t j = 0; j < d; j++)
185  {
186  i1[j] = boxes[(2*d+1)*i+j+1];
187  i2[j] = boxes[(2*d+1)*i+j+d+1];
188  }
189  insert_box(i1,i2,boxes[i*(2*d+1)]);
190  }
191 
192  // Build the characteristic matrices (note: call is non-vritual)
193  update_structure();
194  }
195 
206  gsMatrix<T> const & boxes)
207  :
208  m_manualLevels(false)
209  {
210  //assert(boxes.rows() == 2); //can accept only 2D coordinates- Delete during the generalization of the lac to nD
211  GISMO_ASSERT(boxes.rows() == d, "Points in boxes need to be of dimension d.");
212  GISMO_ASSERT(boxes.cols()%2 == 0, "Each box needs two corners but you don't provied gsHTensorBasis constructor with them.");
213  initialize_class(tbasis);
214 
215  point k1;
216  point k2;
217 
218  for(index_t i = 0; i < boxes.cols()/2; i++)
219  {
220  for(short_t j = 0; j < d; j++)
221  {
222  k1[j] = this->m_bases.back()->knots(j).uFind(boxes(j,2*i)).uIndex();
223  k2[j] = this->m_bases.back()->knots(j).uFind(boxes(j,2*i+1)).uIndex()+1;
224  }
225  int level = m_tree.query3(k1,k2,m_bases.size()-1);
226  for(short_t j = 0; j < d; j++)
227  {
228  k1[j] = this->m_bases[level+1]->knots(j).uFind(boxes(j,2*i)).uIndex();
229  k2[j] = this->m_bases[level+1]->knots(j).uFind(boxes(j,2*i+1)).uIndex()+1;
230  }
231 
232  insert_box(k1,k2,level+1);
233 
234  // Build the characteristic matrices (note: call is non-vritual)
235  update_structure();
236 
237  }
238  }
239 
248  gsMatrix<T> const & boxes,
249  const std::vector<index_t> & levels)
250  :
251  m_manualLevels(false)
252  {
253  GISMO_ASSERT(boxes.rows() == d, "Points in boxes need to be of dimension d.");
254  GISMO_ASSERT(boxes.cols()%2 == 0, "Each box needs two corners but you don't provied gsHTensorBasis constructor with them.");
255  GISMO_ASSERT(unsigned (boxes.cols()/2) <= levels.size(), "We don't have enough levels for the boxes.");
256 
257  initialize_class(tbasis);
258 
261 
262  const size_t mLevel = *std::max_element(levels.begin(), levels.end() );
263  needLevel( mLevel );
264 
265  for(index_t i = 0; i < boxes.cols()/2; i++)
266  {
267  for(short_t j = 0; j < d; j++)
268  {
269  k1[j] = m_bases[levels[i]]->knots(j).uFind(boxes(j,2*i)).uIndex();
270  k2[j] = m_bases[levels[i]]->knots(j).uFind(boxes(j,2*i+1)).uIndex()+1;
271  }
272 
273  /* m_boxHistory.push_back( box(k1,k2,levels[i]) ); */
274  this->m_tree.insertBox(k1,k2, levels[i]);
275 
276  // Build the characteristic matrices (note: call is non-vritual)
277  update_structure();
278  }
279  }
280 
283  {
284  this->operator=(o);
285  }
286 
287  gsHTensorBasis& operator=(const gsHTensorBasis & o)
288  {
289  if ( this != &o )
290  {
291  m_xmatrix_offset = o.m_xmatrix_offset;
292  m_deg = o.m_deg;
293  m_tree = o.m_tree;
294  m_xmatrix = o.m_xmatrix;
295  m_manualLevels = o.m_manualLevels;
296  m_uIndices = o.m_uIndices;
297 
298  freeAll( m_bases );
299  m_bases.resize( o.m_bases.size() );
300  cloneAll(o.m_bases.begin(), o.m_bases.end(), m_bases.begin());
301  }
302  return *this;
303  }
304 
305 #if EIGEN_HAS_RVALUE_REFERENCES
306  gsHTensorBasis(gsHTensorBasis&& other)
307  {
308  this->operator=(other);
309  }
310 
311  gsHTensorBasis & operator=(gsHTensorBasis&& other)
312  {
313  m_deg = std::move(other.m_deg);
314  freeAll( m_bases );
315  m_bases = std::move(other.m_bases);
316  m_xmatrix = std::move(other.m_xmatrix);
317  m_tree = std::move(other.m_tree);
318  m_xmatrix_offset = std::move(other.m_xmatrix_offset);
319  m_manualLevels = std::move(other.m_manualLevels);
320  m_uIndices = std::move(other.m_uIndices);
321  return *this;
322  }
323 #endif
324 
326  virtual ~gsHTensorBasis()
327  {
328  freeAll( m_bases );
329  }
330 
332  bool manualLevels() const { return m_manualLevels; }
333 
335  index_t numLevels() const { return m_bases.size(); }
336 
338  void addLevel( const gsTensorBSplineBasis<d, T>& next_basis);
339 
341  void only_insert_box(point const & k1, point const & k2, int lvl);
342 
343 protected:
344 
345  // TO DO: remove these members after they are not used anymore
346  std::vector<int> m_deg;
347 
348 protected:
349 
361  mutable std::vector<tensorBasis*> m_bases;
362 
377  std::vector< CMatrix > m_xmatrix;
378 
381 
382  // // Stores the coordinates of all inserted boxes
383  // (for debugging purposes)
384  // boxHistory m_boxHistory;
385 
386  bool m_manualLevels;
387 
389  std::vector<std::vector<std::vector<index_t>>> m_uIndices;
390 
391 
392 
393 public:
394  // Needed since m_tree is 16B aligned
395 # define Eigen gsEigen
396  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
397 # undef Eigen
398  protected:
399 
411  std::vector<index_t> m_xmatrix_offset;
412 
413  //------------------------------------
414 
415 public:
416 
417  const std::vector< CMatrix >& getXmatrix() const
418  {
419  return m_xmatrix;
420  }
421 
425  const std::vector<tensorBasis*>& getBases() const
426  {
427  return m_bases;
428  }
429 
431  virtual short_t dim() const
432  { return d; }
433 
436  int numBreaks(int lvl, int k) const
437  {
438  return m_tree.numBreaks(lvl,k);
439  }
440 
442  int numKnots(int lvl, int k) const
443  {
444  needLevel(lvl);
445 
446  return m_bases[lvl]->knots(k).size();
447  }
448 
450  T knot(int lvl, int k, int i) const
451  {
452  needLevel(lvl);
453 
454  return m_bases[lvl]->component(k).knot(i);
455  //return m_bases[lvl]->knot(k,i);
456  }
457 
460  virtual void anchors_into(gsMatrix<T> & result) const
461  {
462  result.resize( d, this->size()) ;
463  unsigned k(0);
464 
466  for(size_t i = 0; i < m_xmatrix.size(); i++)
467  {
468  for( CMatrix::const_iterator it =
469  m_xmatrix[i].begin(); it != m_xmatrix[i].end(); it++)
470  {
471  ind = m_bases[i]->tensorIndex(*it);
472  for ( short_t r = 0; r!=d; ++r )
473  result(r,k) = m_bases[i]->knots(r).greville( ind[r] );
474  k++;
475  }
476  }
477  }
478 
479  virtual void anchor_into(index_t i, gsMatrix<T> & result) const
480  {
481  index_t lvl = levelOf(i);
482  index_t ind = flatTensorIndexOf(i);
483 
484  m_bases[lvl]->anchor_into(ind,result);
485  }
486 
487  virtual void connectivity(const gsMatrix<T> & nodes, gsMesh<T> & mesh) const;
488  void connectivity(const gsMatrix<T> & nodes, int level, gsMesh<T> & mesh) const;
489 
490  // Prints the characteristic matrices (ie. the indices of all basis
491  // functions in the basis)
492  void printCharMatrix(std::ostream &os = gsInfo) const
493  {
494  os<<"Characteristic matrix:\n";
495  for(size_t i = 0; i!= m_xmatrix.size(); i++)
496  {
497  if ( m_xmatrix[i].size() )
498  {
499  os<<"- level="<<i<<
500  ", size="<<m_xmatrix[i].size() << ":\n";
501  os << "("<< m_bases[i]->tensorIndex(*m_xmatrix[i].begin()).transpose() <<")";
502  for( CMatrix::const_iterator it =
503  m_xmatrix[i].begin()+1; it != m_xmatrix[i].end(); it++)
504  {
505  os << ", ("<< m_bases[i]->tensorIndex(*it).transpose() <<")";
506  }
507  os <<"\n";
508  }
509  else
510  {
511  os<<"- level="<<i<<" is empty.\n";
512  }
513  }
514  }
515 
517  void printSpaces(std::ostream &os = gsInfo) const
518  {
519  os<<"Spline-space hierarchy:\n";
520  for(size_t i = 0; i!= m_xmatrix.size(); i++)
521  {
522  if ( m_xmatrix[i].size() )
523  {
524  os<<"- level="<<i<<
525  ", size="<<m_xmatrix[i].size() << ":\n";
526  os << "Space: "<< * m_bases[i] <<")\n";
527  if (m_manualLevels)
528  {
529  os << "Indices:\n";
530  for (size_t dim=0; dim!=d; dim++)
531  os << "Dir "<<dim<<": "<<gsAsConstVector<index_t>(m_uIndices[i][dim]).transpose()<<"\n";
532  }
533  }
534  else
535  {
536  os<<"- level="<<i<<" is empty.\n";
537  }
538  }
539  }
540 
542  void printBases(std::ostream &os = gsInfo) const
543  {
544  os<<"Spline-space hierarchy:\n";
545  for(unsigned i = 0; i< m_bases.size(); i++)
546  {
547  os<<"- level="<<i<<
548  ", size="<<m_bases[i]->size() << ":\n";
549  os << "Space: "<< * m_bases[i] <<")\n";
550  if (m_manualLevels)
551  {
552  os << "Indices:\n";
553  for (size_t dim=0; dim!=d; dim++)
554  os << "Dir "<<dim<<": "<<gsAsConstVector<index_t>(m_uIndices[i][dim]).transpose()<<"\n";
555  }
556  }
557  }
558 
560  void printBasic(std::ostream &os = gsInfo) const
561  {
562  os << "basis of dimension " <<this->dim()<<
563  ",\nlevels="<< this->m_tree.getMaxInsLevel()+1 <<", size="
564  << this->size()<<", tree_nodes="<< this->m_tree.size()
565  // << ", leaf_nodes="<< this->m_tree.leafSize();
566  //const std::pair<int,int> paths = this->m_tree.minMaxPath();
567  //os << ", path lengths=("<<paths.first<<", "<<paths.second
568  << ").\n";
569  const gsMatrix<T> supp = this->support();
570  os << "Domain: ["<< supp.col(0).transpose()<< "]..["<<
571  supp.col(1).transpose()<< "].\n";
572  os <<"Size per level: ";
573  for(size_t i = 0; i!= m_xmatrix.size(); i++)
574  os << this->m_xmatrix[i].size()<< " ";
575  os<<"\n";
576  }
577 
578  // Look at gsBasis.h for the documentation of this function
579  virtual void active_into(const gsMatrix<T> & u, gsMatrix<index_t>& result) const;
580 
581 
582  // Look at gsBasis.h for the documentation of this function
583  gsMatrix<index_t> allBoundary( ) const;
584 
585  // Look at gsBasis.h for the documentation of this function
586  virtual gsMatrix<index_t> boundaryOffset(boxSide const & s, index_t offset ) const;
587 
588  virtual gsMatrix<index_t> boundaryOffsetLevel(boxSide const & s, index_t offset , index_t level) const;
589 
590  virtual index_t levelAtCorner(boxCorner const & c) const;
591 
592  virtual index_t functionAtCorner(boxCorner const & c) const;
593  virtual index_t functionAtCorner(boxCorner const & c, index_t level) const;//..
594 
595 
596  // Look at gsBasis.h for the documentation of this function
597  //void evalAllDers_into(const gsMatrix<T> & u, int n,
598  // std::vector<gsMatrix<T> >& result, bool sameElement) const;
599 
601  const gsHDomain<d> & tree() const { return m_tree; }
602 
604  gsHDomain<d> & tree() { return m_tree; }
605 
607  void makeCompressed();
608 
609 
611  // GISMO_UPTR_FUNCTION_DEC(gsHTensorBasis<d,T>, boundaryBasis, boxSide const &)
612 
614  gsMatrix<T> support() const;
615 
616  gsMatrix<T> support(const index_t & i) const;
617 
618  void elementSupport_into(const index_t i, gsMatrix<index_t, d, 2>& result) const
619  {
620  index_t lvl = levelOf(i);
621  m_bases[lvl]->elementSupport_into(m_xmatrix[lvl][ i - m_xmatrix_offset[lvl] ],
622  result);
623  }
624 
626  {
627  index_t lvl = levelOf(j);
629  m_bases[lvl]->elementSupport_into(m_xmatrix[lvl][j-m_xmatrix_offset[lvl]], sup);
630  std::pair<point,point> box = m_tree.queryLevelCell(sup.col(0),sup.col(1),lvl);
631  for ( short_t i = 0; i!=d; ++i) //get intersection
632  {
633  box.first[i] = ( sup(i,0) >= box.first[i] ? sup(i,0) : box.first[i] );
634  box.second[i] = ( sup(i,1) <= box.second[i] ? sup(i,1) : box.second[i]);
635  }
636  sup.col(0) = (box.first+box.second)/2;
637  sup.col(1) = sup.col(0).array() + 1;
638  return m_bases[lvl]->elementDom(sup);
639  }
640 
641  GISMO_UPTR_FUNCTION_PURE(gsHTensorBasis, clone)
642 
643 
644  index_t size() const;
645 
647  int treeSize() const
648  {
649  return m_tree.size();
650  }
651 
653  void numActive_into(const gsMatrix<T> & u, gsVector<index_t>& result) const;
654 
657  {
658  return m_bases[ this->maxLevel() ]->component(i);
659  }
660 
662  virtual const gsBSplineBasis<T> & component(short_t i) const
663  {
664  return m_bases[ this->maxLevel() ]->component(i);
665  }
666 
669  {
670  needLevel( i );
671  return *this->m_bases[i];
672  }
673 
674  // Refine the basis uniformly by inserting \a numKnots new knots on each knot span
675  virtual void uniformRefine(int numKnots = 1, int mul=1, int dir=-1);
676 
677  // Refine the basis uniformly and adjust the given matrix of coefficients accordingly
678  //virtual void uniformRefine_withCoefs(gsMatrix<T>& coefs, int numKnots = 1, int mul = 1)
679 
680  // Refine the basis uniformly and produce a sparse matrix which
681  // maps coarse coefficient vectors to refined ones
682  //virtual void uniformRefine_withTransfer(gsSparseMatrix<T,RowMajor> & transfer, int numKnots = 1, int mul = 1)
683 
684  // Refine the basis uniformly and adjust the given matrix of coefficients accordingly
685  void uniformRefine_withCoefs(gsMatrix<T>& coefs, int numKnots = 1, int mul = 1, int dir = -1);
686 
687  // Refine the basis and adjust the given matrix of coefficients accordingly
688  void refine_withCoefs(gsMatrix<T> & coefs, gsMatrix<T> const & boxes);
689  // void unrefine_withCoefs(gsMatrix<T> & coefs, gsMatrix<T> const & boxes);
690 
697  void refineElements_withCoefs (gsMatrix<T> & coefs,std::vector<index_t> const & boxes);
698  void refineElements_withTransfer(std::vector<index_t> const & boxes, gsSparseMatrix<T> &transfer);
699  void refineElements_withTransfer2(std::vector<index_t> const & boxes, gsSparseMatrix<T> &transfer);
700 
701  void refineElements_withCoefs2(gsMatrix<T> & coefs,std::vector<index_t> const & boxes);
702 
703  void unrefineElements_withCoefs (gsMatrix<T> & coefs,std::vector<index_t> const & boxes);
704  void unrefineElements_withTransfer(std::vector<index_t> const & boxes, gsSparseMatrix<T> &transfer);
705 
706  // Coarsens the basis uniformly by removing \a numKnots knots on each knot span
707  virtual void uniformCoarsen(int numKnots = 1);
708 
709  // Coarsen the basis uniformly and adjust the given matrix of coefficients accordingly
710  void uniformCoarsen_withCoefs(gsMatrix<T>& coefs, int numKnots = 1);
711 
712  // see gsBasis for documentation
713  void matchWith(const boundaryInterface & bi, const gsBasis<T> & other,
714  gsMatrix<index_t> & bndThis, gsMatrix<index_t> & bndOther) const;
715 
716  // see gsBasis for documentation
717  void matchWith(const boundaryInterface & bi, const gsBasis<T> & other,
718  gsMatrix<index_t> & bndThis, gsMatrix<index_t> & bndOther, index_t offset) const;
719 
721  {
722  short_t td = m_bases[0]->degree(0);
723  // take maximum of coordinate bases degrees
724  for (short_t k=1; k!=d; ++k)
725  td = math::max(td, m_bases[0]->degree(k));
726  return td;
727  }
728 
730  {
731  short_t td = m_bases[0]->degree(0);
732  // take maximum of coordinate bases degrees
733  for (short_t k=1; k!=d; ++k)
734  td = math::min(td, m_bases[0]->degree(k));
735  return td;
736  }
737 
739  void reduceContinuity(int const & i = 1)
740  {
741  for (unsigned int lvl = 0; lvl <= maxLevel(); lvl++)
742  {
743  for (unsigned int dir = 0; dir < d; dir++)
744  {
745  // TODO check: max interior mult + i <= m_p+1
746 
747  // We iterate through unique knots, skipping the first and last knot
748  // At level 0 we iterate through all unique knots,
749  // At level >0 we iterate through all knots that are new, i.e. every other knot starting from 1
750  for (typename gsKnotVector<T>::uiterator it =
751  m_bases[lvl]->knots(dir).ubegin() + 1;
752  it < m_bases[lvl]->knots(dir).uend() - 1;
753  it += (lvl == 0? 1 : 2))
754  {
755  for(unsigned int j =lvl;j < m_bases.size();j++)
756  m_bases[j]->component(dir).insertKnot(*it,i);
757 
758  }
759  }
760  }
761  update_structure();
762  }
763 
767  virtual inline short_t degree(short_t i) const
768  { return m_bases[0]->degree(i);}
769 
770 
771 
772  // S.K.
781  index_t getLevelAtPoint(const gsMatrix<T> & Pt ) const;
782 
783  // S.K.
792  index_t getLevelAtIndex(const point & Pt ) const;
793 
794  // S.K.
806  void getLevelUniqueSpanAtPoints(const gsMatrix<T> & Pt,
807  gsVector<index_t> & lvl,
808  gsMatrix<index_t> & loIdx ) const;
809 
811  unsigned maxLevel() const
812  {
813  return m_tree.getMaxInsLevel();
814  }
815 
817  inline index_t levelOf(index_t i) const
818  {
819  return std::upper_bound(m_xmatrix_offset.begin(),
820  m_xmatrix_offset.end(), i)
821  - m_xmatrix_offset.begin() - 1;
822  }
823 
824 /*
825  const boxHistory & get_inserted_boxes() const
826  {
827  return m_boxHistory;
828  }
829 */
830 
831  void degreeElevate(int const & i = 1, int const dir = -1);
832  void degreeReduce(int const & i = 1, int const dir = -1);
833 
834  void degreeIncrease(int const & i= 1, int const dir = -1);
835  void degreeDecrease(int const & i = 1, int const dir = -1);
836 
848  virtual void refine(gsMatrix<T> const & boxes, int refExt);
849  virtual void unrefine(gsMatrix<T> const & boxes, int refExt);
850 
851  std::vector<index_t> asElements(gsMatrix<T> const & boxes, int refExt = 0) const;
852  std::vector<index_t> asElementsUnrefine(gsMatrix<T> const & boxes, int refExt = 0) const;
853 
854  // std::vector<index_t> asElements(gsMatrix<T> const & boxes, int refExt = 0) const;
855 
863  virtual void refine(gsMatrix<T> const & boxes);
864  // virtual void unrefine(gsMatrix<T> const & boxes);
865 
891  virtual void refineElements(std::vector<index_t> const & boxes);
892 
899  virtual void unrefineElements(std::vector<index_t> const & boxes);
900 
902  void refineSide(const boxSide side, index_t lvl);
903 
905  void refineBasisFunction(const index_t i);
906 
907  // Look at gsBasis.h for the documentation of this function
908  //virtual void uniformRefine(int numKnots = 1);
909 
910  typename gsBasis<T>::domainIter makeDomainIterator() const
911  {
912  return typename gsBasis<T>::domainIter(new gsHDomainIterator<T, d>(*this));
913  }
914 
915  typename gsBasis<T>::domainIter makeDomainIterator(const boxSide & s) const
916  {
917  return ( s == boundary::none ?
918  typename gsBasis<T>::domainIter(new gsHDomainIterator<T, d>(*this)) :
919  typename gsBasis<T>::domainIter(new gsHDomainBoundaryIterator<T, d>(*this,s) )
920  );
921  }
922 
931  inline
933  {
934  return flatTensorIndexOf(i, this->levelOf(i) );
935  }
936 
946  inline
947  index_t flatTensorIndexOf(const index_t i, const index_t level) const
948  {
949  const index_t offset = this->m_xmatrix_offset[level];
950  const index_t ind_in_level = this->m_xmatrix[level][i - offset];
951  return ind_in_level;
952  }
953 
961  std::vector< std::vector< std::vector<index_t > > > domainBoundariesParams( std::vector< std::vector< std::vector< std::vector< T > > > >& result) const;
962 
970  std::vector< std::vector< std::vector<index_t > > > domainBoundariesIndices( std::vector< std::vector< std::vector< std::vector<index_t > > > >& result) const;
971  // TO DO: use gsHDomainLeafIterator for a better implementation
972  size_t numElements(boxSide const & s = 0) const
973  {
974  typename gsBasis<T>::domainIter domIter =
975  s == boundary::none ?
976  typename gsBasis<T>::domainIter(new gsHDomainIterator<T, d>(*this)) :
977  typename gsBasis<T>::domainIter(new gsHDomainBoundaryIterator<T, d>(*this,s) );
978 
979  size_t numEl = 0;
980  for (; domIter->good(); domIter->next())
981  {
982  numEl++;
983  }
984 
985  return numEl;
986  }
987 
994  void flatTensorIndexesToHierachicalIndexes(gsSortedVector< int > & indexes,const int level) const;
995 
1003  int flatTensorIndexToHierachicalIndex(index_t index,const int level) const;
1004 
1012  void activeBoundaryFunctionsOfLevel(const unsigned level,const boxSide & s,std::vector<bool>& actives) const;
1013 
1022 
1023  virtual void increaseMultiplicity(index_t lvl, int dir, T knotValue, int mult = 1);
1024 
1033  virtual void increaseMultiplicity(index_t lvl, int dir, const std::vector<T> & knotValue, int mult = 1);
1034 
1035 protected:
1036 
1039  virtual void update_structure(); // to do: rename as updateCharMatrices
1040 
1043  void needLevel(int maxLevel) const;
1044 
1046  void createMoreLevels(int numLevels) const;
1047 
1051  void getBoxesAlongSlice( int dir, T par,std::vector<index_t>& boxes ) const;
1052 
1053 protected:
1054 
1062  void _knotIndexToDiadicIndex(const index_t level, const index_t dir, index_t & knotIndex) const;
1063  void _knotIndexToDiadicIndex(const index_t level, gsVector<index_t,d> & diadicIndex) const;
1064 
1071  void _diadicIndexToKnotIndex(const index_t level, gsVector<index_t,d> & diadicIndex) const;
1072  void _diadicIndexToKnotIndex(const index_t level, const index_t dir, index_t & diadicIndex) const;
1073 
1074 private:
1075 
1077  void insert_box(point const & k1, point const & k2, int lvl);
1078 
1079  void initialize_class(gsBasis<T> const& tbasis);
1080 
1083  void functionOverlap(const point & boxLow, const point & boxUpp,
1084  const int level, point & actLow, point & actUpp);
1085 
1086  // \brief Sets all functions of \a level to active or passive- one by one
1087  void set_activ1(int level);
1088 
1089  // \brief Computes the set of active basis functions in the basis
1090  void setActive();
1091 
1092  // \brief Computes the connectivity for a level on a mesh that has all vertices
1093  void addConnectivity(int level, gsMesh<T> & mesh) const;
1094 
1096  virtual gsSparseMatrix<T> coarsening(const std::vector<CMatrix>& old,
1097  const std::vector<CMatrix>& n,
1098  const gsSparseMatrix<T,RowMajor> & transfer) const = 0;
1099 
1100  virtual gsSparseMatrix<T> coarsening_direct(const std::vector<gsSortedVector<index_t> >& old,
1101  const std::vector<gsSortedVector<index_t> >& n,
1102  const std::vector<gsSparseMatrix<T,RowMajor> >& transfer) const = 0;
1103 
1104  virtual gsSparseMatrix<T> coarsening_direct2(const std::vector<gsSortedVector<index_t> >& old,
1105  const std::vector<gsSortedVector<index_t> >& n,
1106  const std::vector<gsSparseMatrix<T,RowMajor> >& transfer) const = 0;
1107 
1110  std::vector< std::vector< std::vector<index_t > > > domainBoundariesGeneric(std::vector< std::vector< std::vector< std::vector<index_t > > > >& indices,
1111  std::vector< std::vector< std::vector< std::vector< T > > > >& params,
1112  bool indicesFlag ) const;
1113 
1114 public:
1117  void transfer (const std::vector<gsSortedVector<index_t> > &old, gsSparseMatrix<T>& result);
1118 
1119  void transfer2 (const std::vector<gsSortedVector<index_t> > &old, gsSparseMatrix<T>& result);
1120 
1123  void setActiveToLvl(int level, std::vector<CMatrix>& x_matrix_lvl) const;
1124 
1125 public:
1133  bool testPartitionOfUnity(const index_t npts = 100, const T tol = 1e-12) const;
1134 
1135 // void local2globalIndex( gsVector<index_t,d> const & index,
1136 // index_t lvl,
1137 // gsVector<index_t,d> & result
1138 // ) const;
1139 
1140 // void global2localIndex( gsVector<index_t,d> const & index,
1141 // index_t lvl,
1142 // gsVector<index_t,d> & result
1143 // ) const;
1144 
1145 }; // class gsHTensorBasis
1146 
1147 // Next line disallows instantization of gsTensorBasis<0,T>
1148 template<typename T> class gsHTensorBasis<0,T>
1149 {using T::GISMO_ERROR_gsHTensorBasis_cannot_have_dimension_zero;};
1150 
1151 
1152 #ifdef GISMO_WITH_PYBIND11
1153 
1157  void pybind11_init_gsHTensorBasis2(pybind11::module &m);
1158  void pybind11_init_gsHTensorBasis3(pybind11::module &m);
1159  void pybind11_init_gsHTensorBasis4(pybind11::module &m);
1160 
1161 #endif // GISMO_WITH_PYBIND11
1162 
1163 
1164 } // namespace gismo
1165 
1166 // ************************************************
1167 // ************************************************
1168 
1169 #ifndef GISMO_BUILD_LIB
1170 #include GISMO_HPP_HEADER(gsHTensorBasis.hpp)
1171 #endif
Re-implements gsDomainIterator for iteration over all boundary elements of a hierarchical parameter d...
Definition: gsHDomain.h:24
bool manualLevels() const
Returns true if levels are assigned manually.
Definition: gsHTensorBasis.h:332
internal::gsUKnotIterator< T > uiterator
Definition: gsKnotVector.h:102
index_t flatTensorIndexOf(const index_t i) const
Returns the tensor index of the function indexed i (in continued indices).
Definition: gsHTensorBasis.h:932
size_t numElements(boxSide const &s=0) const
The number of elements on side s.
Definition: gsHTensorBasis.h:972
Provides declaration of iterator of hierarchical domain.
Traits for BSplineBasis in more dimensions.
Definition: gsBSplineBasis.h:31
virtual void anchors_into(gsMatrix< T > &result) const
Definition: gsHTensorBasis.h:460
virtual const gsBSplineBasis< T > & component(short_t i) const
The 1-d basis for the i-th parameter component at the highest level.
Definition: gsHTensorBasis.h:662
memory::unique_ptr< gsHTensorBasis > uPtr
Unique pointer for gsHTensorBasis.
Definition: gsHTensorBasis.h:81
#define short_t
Definition: gsConfig.h:35
Provides structs and classes related to interfaces and boundaries.
short_t minDegree() const
If the basis is of polynomial or piecewise polynomial type, then this function returns the minimum po...
Definition: gsHTensorBasis.h:729
virtual ~gsHTensorBasis()
Destructor.
Definition: gsHTensorBasis.h:326
virtual short_t degree(short_t i) const
Degree with respect to the i-th variable. If the basis is a tensor product of (piecewise) polynomial ...
Definition: gsBasis.hpp:650
index_t flatTensorIndexOf(const index_t i, const index_t level) const
Returns the tensor index of the function indexed i (in continued indices).
Definition: gsHTensorBasis.h:947
std::vector< tensorBasis * > m_bases
The list of nested spaces.
Definition: gsHTensorBasis.h:361
Provides declaration of Basis abstract interface.
gsHTensorBasis()
Default empty constructor.
Definition: gsHTensorBasis.h:113
gsHDomain< d > & tree()
Returns a reference to m_tree.
Definition: gsHTensorBasis.h:604
#define index_t
Definition: gsConfig.h:32
void reduceContinuity(int const &i=1)
Reduces spline continuity at interior knots by i.
Definition: gsHTensorBasis.h:739
void printBasic(std::ostream &os=gsInfo) const
Prints the spline-space hierarchy.
Definition: gsHTensorBasis.h:560
This class is derived from std::vector, and adds sort tracking.
Definition: gsSortedVector.h:109
const std::vector< tensorBasis * > & getBases() const
Returns the tensor B-spline space of all levels.
Definition: gsHTensorBasis.h:425
const gsHDomain< d > & tree() const
Returns a reference to m_tree.
Definition: gsHTensorBasis.h:601
short_t maxDegree() const
If the basis is of polynomial or piecewise polynomial type, then this function returns the maximum po...
Definition: gsHTensorBasis.h:720
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
void cloneAll(It start, It end, ItOut out)
Clones all pointers in the range [start end) and stores new raw pointers in iterator out...
Definition: gsMemory.h:295
Provides declaration of the HDomain class.
gsHTensorBasis(const gsHTensorBasis &o)
Copy constructor.
Definition: gsHTensorBasis.h:282
T knot(int lvl, int k, int i) const
Returns the i-th knot in direction k at level lvl.
Definition: gsHTensorBasis.h:450
index_t numLevels() const
Returns the number of levels.
Definition: gsHTensorBasis.h:335
A univariate B-spline basis.
Definition: gsBSplineBasis.h:694
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
gsHTensorBasis(gsTensorBSplineBasis< d, T > const &tbasis, gsMatrix< T > const &boxes, const std::vector< index_t > &levels)
gsHTensorBasis
Definition: gsHTensorBasis.h:247
Class Representing a triangle mesh with 3D vertices.
Definition: gsMesh.h:31
std::vector< CMatrix > m_xmatrix
The characteristic matrices for each level.
Definition: gsHTensorBasis.h:377
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
Provides declaration of BSplineBasis class.
gsBasis< T >::domainIter makeDomainIterator(const boxSide &s) const
Create a boundary domain iterator for the computational mesh this basis, that points to the first ele...
Definition: gsHTensorBasis.h:915
gsMatrix< T > elementInSupportOf(index_t j) const
Returns (the coordinates of) an element in the support of basis function j.
Definition: gsHTensorBasis.h:625
#define gsInfo
Definition: gsDebug.h:43
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition: gsMemory.h:312
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
std::vector< index_t > m_xmatrix_offset
Stores the offsets of active functions for all levels.
Definition: gsHTensorBasis.h:411
virtual short_t dim() const
Returns the dimension of the parameter space.
Definition: gsHTensorBasis.h:431
gsBasis< T >::domainIter makeDomainIterator() const
Create a domain iterator for the computational mesh of this basis, that points to the first element o...
Definition: gsHTensorBasis.h:910
virtual void anchor_into(index_t i, gsMatrix< T > &result) const
Returns the anchor point for member i of the basis.
Definition: gsHTensorBasis.h:479
hdomain_type m_tree
The tree structure of the index space.
Definition: gsHTensorBasis.h:380
int numKnots(int lvl, int k) const
Returns the number of knots in direction k of level lvl.
Definition: gsHTensorBasis.h:442
index_t levelOf(index_t i) const
Returns the level of the function indexed i (in continued indices)
Definition: gsHTensorBasis.h:817
unsigned maxLevel() const
Returns the level in which the indices are stored internally.
Definition: gsHTensorBasis.h:811
tensorBasis & tensorLevel(index_t i) const
Returns the tensor basis member of level i.
Definition: gsHTensorBasis.h:668
An std::vector with sorting capabilities.
void printBases(std::ostream &os=gsInfo) const
Prints the spline-space hierarchy.
Definition: gsHTensorBasis.h:542
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
Struct of for an Axis-aligned bounding box.
Definition: gsAABB.h:30
Class for representing a knot vector.
Definition: gsKnotVector.h:79
Creates a mapped object or data pointer to a const vector without copying data.
Definition: gsLinearAlgebra.h:130
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
Provides declaration of iterator on boundary of hierarchical basis.
std::vector< std::vector< std::vector< index_t > > > m_uIndices
Store the indices of the element boundaries for each level (only if m_manualLevels==true) ...
Definition: gsHTensorBasis.h:389
virtual short_t degree(short_t i) const
If the basis is a tensor product of (piecewise) polynomial bases, then this function returns the poly...
Definition: gsHTensorBasis.h:767
Struct which represents a certain corner of a hyper-cube.
Definition: gsBoundary.h:291
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
gsHTensorBasis(gsTensorBSplineBasis< d, T > const &tbasis, gsMatrix< T > const &boxes)
gsHTensorBasis
Definition: gsHTensorBasis.h:205
int numBreaks(int lvl, int k) const
Definition: gsHTensorBasis.h:436
memory::shared_ptr< gsHTensorBasis > Ptr
Shared pointer for gsHTensorBasis.
Definition: gsHTensorBasis.h:78
Provides declaration of TensorBSplineBasis abstract interface.
void printSpaces(std::ostream &os=gsInfo) const
Prints the spline-space hierarchy.
Definition: gsHTensorBasis.h:517