G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsTensorBSplineBasis.h
Go to the documentation of this file.
1 
15 #pragma once
16 
17 #include <gsTensor/gsTensorBasis.h>
18 #include <gsNurbs/gsBSplineBasis.h>
20 
21 namespace gismo
22 {
23 
35 template<short_t d, class T>
37 {
38 public:
39  typedef gsKnotVector<T> KnotVectorType;
40 
43 
46 
48 
51  typedef CoordinateBasis Basis_t;
52 
54  typedef T Scalar_t;
55 
58 
61 
62  typedef typename Base::iterator iterator;
63  typedef typename Base::const_iterator const_iterator;
64 
66  typedef memory::shared_ptr< Self_t > Ptr;
67 
69  typedef memory::unique_ptr< Self_t > uPtr;
70 
71 public:
72 
75  {
76  for(short_t i = 0; i!=d; ++i)
77  this->m_bases[i] = new Basis_t();
78  }
79 
80  void swap(gsTensorBSplineBasis & other)
81  {
82  this->Base::swap(static_cast<Base&>(other));
83  std::swap(m_isPeriodic, other.m_isPeriodic);
84  }
85 
86 #if !EIGEN_HAS_RVALUE_REFERENCES
88  { gsTensorBSplineBasis::swap(other); return *this;}
89 // #else // defined implicitly
90 // gsTensorBSplineBasis(gsTensorBSplineBasis && other) : Base(give(other)) { }
91 // gsTensorBSplineBasis(const gsTensorBSplineBasis & other) : Base(other) { }
92 // gsTensorBSplineBasis & operator=(gsTensorBSplineBasis&& other)
93 // { return (gsTensorBSplineBasis &)Base::operator=(give(other)); }
94 // gsTensorBSplineBasis & operator=(const gsTensorBSplineBasis& other)
95 // { return (gsTensorBSplineBasis &)Base::operator=(other); }
96 #endif
97 
105  template<typename U>
106  gsTensorBSplineBasis( KnotVectorType KV1, gsKnotVector<U> KV2,
107  typename util::enable_if<d==2,U>::type * = NULL )
108  : Base( new Basis_t(give(KV1)), new Basis_t(give(KV2)) )
109  { m_isPeriodic = -1; }
110 
119  gsTensorBSplineBasis( KnotVectorType KV1,
120  KnotVectorType KV2,
121  KnotVectorType KV3 )
122  : Base( new Basis_t(give(KV1)), new Basis_t(give(KV2)), new Basis_t(give(KV3)) )
123  { m_isPeriodic = -1; }
124 
125  gsTensorBSplineBasis( KnotVectorType KV1,
126  KnotVectorType KV2,
127  KnotVectorType KV3,
128  KnotVectorType KV4)
129  : Base( new Basis_t(give(KV1)), new Basis_t(give(KV2)),
130  new Basis_t(give(KV3)), new Basis_t(give(KV4)) )
131  { m_isPeriodic = -1; }
132 
133  explicit gsTensorBSplineBasis(std::vector<KnotVectorType> KV)
134  {
135  GISMO_ENSURE(d == KV.size(), "Invalid number of knot-vectors given." );
136  for(short_t i = 0; i!=d; ++i)
137  this->m_bases[i] = new Basis_t( give(KV[i]) );
138  m_isPeriodic = -1;
139  }
140 
141  gsTensorBSplineBasis( Basis_t* x, Basis_t* y) : Base(x,y)
142  {
143  GISMO_ENSURE(d==2,"Invalid constructor." );
144  setIsPeriodic();
145  }
146 
147  gsTensorBSplineBasis( Basis_t* x, Basis_t* y, Basis_t* z ) : Base(x,y,z)
148  {
149  GISMO_ENSURE(d==3,"Invalid constructor." );
150  setIsPeriodic();
151 
152  }
153 
154  gsTensorBSplineBasis( Basis_t* x, Basis_t* y, Basis_t* z, Basis_t* w ) : Base(x,y,z,w)
155  {
156  GISMO_ENSURE(d==4,"Invalid constructor." );
157  setIsPeriodic();
158  }
159 
160  explicit gsTensorBSplineBasis(std::vector< gsBasis<T>*> & bb );
161 
162  explicit gsTensorBSplineBasis(std::vector< Basis_t*> & bb );
163 
164 #ifdef __DOXYGEN__
165  typename gsBSplineTraits<static_cast<short_t>(d-1),T>::Basis::uPtr boundaryBasis(boxSide const & s);
167 #endif
168  GISMO_UPTR_FUNCTION_DEF(BoundaryBasisType, boundaryBasis, boxSide const &)
169  {
170  std::vector<gsBasis<T>*> rr;
171  this->getComponentsForSide(n1,rr);
172  return BoundaryBasisType::New(rr);
173  }
174 
175  GISMO_CLONE_FUNCTION(gsTensorBSplineBasis)
176 
177  static Self_t * New(std::vector<gsBasis<T>*> & bb )
178  { return new Self_t(bb); }
179 
180  static Self_t * New(std::vector<Basis_t*> & bb )
181  { return new Self_t(bb); }
182 
183  static uPtr make(std::vector<gsBasis<T>*> & bb )
184  { return uPtr( new Self_t(bb) ); }
185 
186  static uPtr make(std::vector<Basis_t*> & bb )
187  { return uPtr( new Self_t(bb) ); }
188 
189 public:
190 
191  KnotVectorType & knots (int i)
192  { return Self_t::component(i).knots(); }
193 
194  const KnotVectorType & knots (int i) const
195  { return Self_t::component(i).knots(); }
196 
197  // knot \a k of direction \a i
198  T knot(int i, int k) const
199  { return Self_t::component(i).knots()[k]; }
200 
201 
202  const Basis_t & component(short_t dir) const
203  {
204  return static_cast<const Basis_t &>(Base::component(dir));
205  }
206 
208  {
209  return static_cast<Basis_t &>(Base::component(dir));
210  }
211 
212  // Look at gsBasis class for a description
213  void active_into(const gsMatrix<T> & u, gsMatrix<index_t>& result) const;
214 
219  void active_cwise(const gsMatrix<T> & u, gsVector<index_t,d>& low,
220  gsVector<index_t,d>& upp ) const;
221 
223  std::ostream &print(std::ostream &os) const
224  {
225  os << "TensorBSplineBasis: dim=" << this->dim()<< ", size="<< this->size() <<".";
226  if( m_isPeriodic != -1 )
227  os << "Periodic in " << m_isPeriodic << "-th direction.\n";
228  for ( short_t i = 0; i!=d; ++i )
229  os << "\n Direction "<< i <<": "<< Self_t::component(i).knots() <<" ";
230  os << "\n";
231  return os;
232  }
233 
234  //
235  // param other parent/reference mesh determining the smoothness at the inner knots.
236  // param i number of k-refinement steps to perform
237 
241  void k_refine(Self_t & other, int const & i = 1)
242  {
243  for (short_t j = 0; j < d; ++j)
244  Self_t::component(j).refine_k(other.component(j), i);
245  }
246 
249  void refine_p(int const & i = 1)
250  {
251  for (short_t j = 0; j < d; ++j)
252  Self_t::component(j).refine_p(i);
253  }
254 
257  void refine_h(int const & i = 1)
258  {
259  for (short_t j = 0; j < d; ++j)
260  Self_t::component(j).refine_h(i);
261  }
262 
274  void refine_withTransfer(gsSparseMatrix<T,RowMajor> & transfer, const std::vector< std::vector<T> >& refineKnots);
275 
276 
288  void refine_withCoefs(gsMatrix<T> & coefs,const std::vector< std::vector<T> >& refineKnots);
289 
292  void insertKnot(T knot, index_t dir, int mult=1)
293  { this->knots(dir).insert( knot, mult); }
294 
297  void removeKnot(T knot, index_t dir, int mult=1)
298  { this->knots(dir).remove( knot, mult); }
299 
306  void insertKnots(const std::vector< std::vector<T> >& refineKnots)
307  {
308  GISMO_ASSERT( refineKnots.size() == d, "refineKnots vector has wrong size" );
309  for (short_t j = 0; j < d; ++j) // refine basis in each direction
310  this->knots(j).insert(refineKnots[j]);
311  }
312 
351  void refine( gsMatrix<T> const & boxes, int refExt = 0);
352 
353  GISMO_MAKE_GEOMETRY_NEW
354 
357  void reduceContinuity(int const & i = 1)
358  {
359  for (short_t j = 0; j < d; ++j)
360  Self_t::component(j).reduceContinuity(i);
361  }
362 
365  template <int _Rows>
367  {
368  //result.resize(d,2);
369  gsMatrix<index_t> tmp_vec;
370  const gsVector<index_t, d> ti = this->tensorIndex(i);
371 
372  for (short_t dim = 0; dim < d; ++dim)
373  {
374  const gsKnotVector<T> & kv = Self_t::component(dim).knots();
375  kv.supportIndex_into(ti[dim], tmp_vec);
376  result.row(dim).noalias() =
377  tmp_vec.cwiseMax(0).cwiseMin(kv.numElements());
378  }
379  }
380 
384  {
385  gsMatrix<index_t, d, 2> result(d, 2);
386  elementSupport_into(i, result);
387  return result;
388  }
389 
392  template <int _Rows>
394  gsMatrix<index_t> & result) const
395  {
396  GISMO_ASSERT( box.rows() == static_cast<index_t>(d), "Invalid input box");
398 
400  this->stride_cwise(str);
401 
402  for (short_t dm = 0; dm != d; ++dm)
403  {
404  tmp(dm,0) = Self_t::component(dm).knots().lastKnotIndex (box(dm,0)) - this->degree(dm);
405  tmp(dm,1) = Self_t::component(dm).knots().firstKnotIndex(box(dm,1)) - 1;
406  }
407 
408  const gsVector<index_t,d> sz = tmp.col(1)- tmp.col(0) + gsVector<index_t,d>::Ones();
409 
410  result = gsVector<index_t>::LinSpaced(sz[0], tmp(0,0), tmp(0,1));
411  for (short_t dm = 1; dm != d; ++dm)
412  result = result.replicate(1,sz[dm]) +
413  gsVector<index_t>::Constant(result.rows(), str[dm] )
414  * gsVector<index_t>::LinSpaced(sz[dm], tmp(dm,0), tmp(dm,1))
415  .transpose();
416  }
417 
418  template <int _Rows>
419  gsMatrix<T> elementDom(const gsMatrix<index_t,_Rows,2> & box) const
420  {
421  GISMO_ASSERT( box.rows() == static_cast<index_t>(d), "Invalid input box");
422  gsMatrix<T> rvo;
423  rvo.resize(d,2);
424  for (short_t dm = 0; dm != d; ++dm)
425  {
426  rvo(dm,0) = Self_t::component(dm).knots().uValue(box(dm,0));
427  rvo(dm,1) = Self_t::component(dm).knots().uValue(box(dm,1));
428  }
429  return rvo;
430  }
431 
433  inline bool isPeriodic() const { return m_isPeriodic != -1; }
434 
436  inline int periodicDirection() const { return m_isPeriodic; }
437 
439  inline void setPeriodic( const int dir )
440  {
441  Self_t::component(dir).setPeriodic();
442  if( Self_t::component(dir).isPeriodic() ) // Only when succeeded when converting to periodic.
443  m_isPeriodic = dir;
444  }
445 
447  gsMatrix<T> perCoefs( const gsMatrix<T>& originalCoefs, short_t dir ) const
448  {
449  // Identify which coefficients to copy and where to copy them.
450  std::vector<index_t> sourceSliceIndices;
451  std::vector<index_t> targetSliceIndices;
452  index_t numPeriodic = Self_t::component(dir).numCrossingFunctions();
453 
454  const index_t sz = this->size(dir) - numPeriodic;
455  for( index_t i = 0; i < numPeriodic; i++ )
456  {
457  gsMatrix<index_t> currentSourceSlice = this->coefSlice(dir,i);
458  gsMatrix<index_t> currentTargetSlice = this->coefSlice(dir, sz + i );
459 
460  for( index_t j = 0; j != currentSourceSlice.size(); j++ )
461  {
462  sourceSliceIndices.push_back( static_cast<index_t>( currentSourceSlice(j) ) );
463  targetSliceIndices.push_back( static_cast<index_t>( currentTargetSlice(j) ) );
464  }
465  }
466 
467  // Copy the chosen coefficients.
468  gsMatrix<T> result = originalCoefs;
469  for( size_t i = 0; i != sourceSliceIndices.size(); i++ )
470  {
471  //gsDebug << "source: " << sourceSliceIndices[i] << "\n";
472  //gsDebug << "target: " << targetSliceIndices[i] << "\n";
473  result.row( targetSliceIndices[ i ] ) = originalCoefs.row( sourceSliceIndices[ i ] );
474  }
475 
476  return result;
477  }
478 
479 private:
480 
484  {
485  m_isPeriodic = -1;
486  for( short_t i = 0; i < this->dim(); i++ )
487  {
488  if( Self_t::component(i).isPeriodic() )
489  {
490  if( m_isPeriodic == -1 )
491  m_isPeriodic = i;
492  else
493  gsWarn << "Cannot handle a basis that is periodic in more than one direction.\n";
494  }
495  }
496  }
497 
498 protected:
499 
503 
504 };
505 
506 #ifdef GISMO_WITH_PYBIND11
507 
511  void pybind11_init_gsTensorBSplineBasis2(pybind11::module &m);
512  void pybind11_init_gsTensorBSplineBasis3(pybind11::module &m);
513  void pybind11_init_gsTensorBSplineBasis4(pybind11::module &m);
514 
515 #endif // GISMO_WITH_PYBIND11
516 
517 } // namespace gismo
518 
519 
520 // *****************************************************************
521 #ifndef GISMO_BUILD_LIB
522 #include GISMO_HPP_HEADER(gsTensorBSplineBasis.hpp)
523 /*
524 #else
525 #ifdef gsTensorBSplineBasis_EXPORT
526 #include GISMO_HPP_HEADER(gsTensorBSplineBasis.hpp)
527 #undef EXTERN_CLASS_TEMPLATE
528 #define EXTERN_CLASS_TEMPLATE CLASS_TEMPLATE_INST
529 #endif
530 namespace gismo
531 {
532 EXTERN_CLASS_TEMPLATE gsTensorBSplineBasis<2,real_t>;
533 EXTERN_CLASS_TEMPLATE gsTensorBSplineBasis<3,real_t>;
534 EXTERN_CLASS_TEMPLATE gsTensorBSplineBasis<4,real_t>;
535 }
536 */
537 #endif
538 // *****************************************************************
void k_refine(Self_t &other, int const &i=1)
Perform k-refinement coordinate-wise, in all directions.
Definition: gsTensorBSplineBasis.h:241
short_t degree(short_t i) const
Returns the degree of the basis wrt variable i.
Definition: gsTensorBasis.h:465
void removeKnot(T knot, index_t dir, int mult=1)
Definition: gsTensorBSplineBasis.h:297
void insertKnot(T knot, index_t dir, int mult=1)
Definition: gsTensorBSplineBasis.h:292
void refine(gsMatrix< T > const &boxes, int refExt=0)
Refinement of the tensor basis on the area defined by boxes.
Definition: gsTensorBSplineBasis.hpp:106
Traits for BSplineBasis in more dimensions.
Definition: gsBSplineBasis.h:31
index_t size() const
Returns the number of elements in the basis.
Definition: gsTensorBasis.h:108
void active_into(const gsMatrix< T > &u, gsMatrix< index_t > &result) const
Returns the indices of active basis functions at points u, as a list of indices, in result...
Definition: gsTensorBSplineBasis.hpp:166
int periodicDirection() const
Gives the value of m_isPeriodic.
Definition: gsTensorBSplineBasis.h:436
#define short_t
Definition: gsConfig.h:35
size_t numElements() const
Number of knot intervals inside domain.
Definition: gsKnotVector.h:268
gsMatrix< index_t, d, 2 > elementSupport(const index_t &i) const
Returns span (element) indices of the beginning and end of the support of the i-th basis function...
Definition: gsTensorBSplineBasis.h:383
A tensor product of d B-spline functions, with arbitrary target dimension.
Definition: gsTensorBSpline.h:44
Basis_t ** iterator
Iterators on coordinate bases.
Definition: gsTensorBasis.h:52
void supportIndex_into(const mult_t &i, gsMatrix< index_t > &result) const
Definition: gsKnotVector.hpp:1066
Represents a tensor-product B-spline patch.
gsTensorBSplineBasis(KnotVectorType KV1, gsKnotVector< U > KV2, typename util::enable_if< d==2, U >::type *=NULL)
Constructs a 2D tensor product B-spline basis. Assumes that the tamplate parameter d is equal to 2...
Definition: gsTensorBSplineBasis.h:106
gsBSplineBasis< T > CoordinateBasis
Coordinate basis type.
Definition: gsTensorBSplineBasis.h:50
S give(S &x)
Definition: gsMemory.h:266
gsBSplineBasis< T > Family_t
Family type.
Definition: gsTensorBSplineBasis.h:45
void elementSupport_into(const index_t i, gsMatrix< index_t, _Rows, 2 > &result) const
Returns span (element) indices of the beginning and end of the support of the i-th basis function...
Definition: gsTensorBSplineBasis.h:366
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
gsTensorBSplineBasis()
Default constructor.
Definition: gsTensorBSplineBasis.h:74
std::ostream & print(std::ostream &os) const
Prints the object as a string.
Definition: gsTensorBSplineBasis.h:223
void refine_h(int const &i=1)
Uniform h-refinement (placing i new knots inside each knot-span, for all directions.
Definition: gsTensorBSplineBasis.h:257
gsBSplineTraits< d, T >::Geometry GeometryType
Associated Boundary basis type.
Definition: gsTensorBSplineBasis.h:57
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
void active_cwise(const gsMatrix< T > &u, gsVector< index_t, d > &low, gsVector< index_t, d > &upp) const
Definition: gsTensorBSplineBasis.hpp:50
GISMO_MAKE_GEOMETRY_NEW void reduceContinuity(int const &i=1)
Reduces spline continuity (in all directions) at interior knots by i.
Definition: gsTensorBSplineBasis.h:357
A univariate B-spline basis.
Definition: gsBSplineBasis.h:694
void setPeriodic(const int dir)
Converts.
Definition: gsTensorBSplineBasis.h:439
#define gsWarn
Definition: gsDebug.h:50
void refine_withCoefs(gsMatrix< T > &coefs, const std::vector< std::vector< T > > &refineKnots)
Takes a vector of coordinate wise knot values and inserts these values to the basis.
Definition: gsTensorBSplineBasis.hpp:83
void insertKnots(const std::vector< std::vector< T > > &refineKnots)
Takes a vector of coordinate wise knot values and inserts these values to the basis.
Definition: gsTensorBSplineBasis.h:306
Provides declaration of BSplineBasis class.
Basis_t & component(short_t dir)
For a tensor product basis, return the 1-d basis for the i-th parameter component.
Definition: gsTensorBasis.h:596
gsBSplineTraits< static_cast< short_t >d-1), T >::Basis BoundaryBasisType
Associated Boundary basis type.
Definition: gsTensorBSplineBasis.h:60
void setIsPeriodic()
Definition: gsTensorBSplineBasis.h:483
Interface for the set of functions defined on a domain (the total number of functions in the set equa...
Definition: gsFuncData.h:23
Abstract base class for tensor product bases.
Definition: gsTensorBasis.h:33
void refine_withTransfer(gsSparseMatrix< T, RowMajor > &transfer, const std::vector< std::vector< T > > &refineKnots)
Takes a vector of coordinate wise knot values and inserts these values to the basis.
Definition: gsTensorBSplineBasis.hpp:66
void getComponentsForSide(boxSide const &s, std::vector< Basis_t * > &rr) const
Returns the components for a basis on the face s.
Definition: gsTensorBasis.hpp:377
void refine_p(int const &i=1)
p-refinement (essentially degree elevation in all directions)
Definition: gsTensorBSplineBasis.h:249
memory::shared_ptr< Self_t > Ptr
Smart pointer for gsTensorBSplineBasis.
Definition: gsTensorBSplineBasis.h:66
T Scalar_t
Coefficient type.
Definition: gsTensorBSplineBasis.h:54
gsMatrix< T > perCoefs(const gsMatrix< T > &originalCoefs, short_t dir) const
Sets the coefficients so that the resulting TensorBSpline is periodic in direction dir...
Definition: gsTensorBSplineBasis.h:447
void stride_cwise(gsVector< index_t, d > &result) const
Returns the strides for all dimensions.
Definition: gsTensorBasis.h:512
gsTensorBasis< d, T > Base
Base type.
Definition: gsTensorBSplineBasis.h:42
memory::unique_ptr< Self_t > uPtr
Smart pointer for gsTensorBSplineBasis.
Definition: gsTensorBSplineBasis.h:69
gsMatrix< index_t > coefSlice(short_t dir, index_t k) const
Returns all the basis functions with tensor-numbering.
Definition: gsTensorBasis.hpp:250
void elementActive_into(const gsMatrix< index_t, _Rows, 2 > &box, gsMatrix< index_t > &result) const
Returns the indices of active basis functions in the given input element box.
Definition: gsTensorBSplineBasis.h:393
gsVector< index_t, d > tensorIndex(const index_t &m) const
Returns the tensor index of the basis function with global index m.
Definition: gsTensorBasis.h:527
short_t m_isPeriodic
Definition: gsTensorBSplineBasis.h:502
Class for representing a knot vector.
Definition: gsKnotVector.h:79
Basis_t & component(short_t dir)
For a tensor product basis, return the 1-d basis for the i-th parameter component.
Definition: gsTensorBSplineBasis.h:207
Provides declaration of TensorBasis class.
gsBSplineTraits< static_cast< short_t >d-1), T >::Basis::uPtr boundaryBasis(boxSide const &s)
Returns the boundary basis for side s.
const Basis_t & component(short_t dir) const
For a tensor product basis, return the (const) 1-d basis for the i-th parameter component.
Definition: gsTensorBSplineBasis.h:202
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
bool isPeriodic() const
Tells, whether there is a coordinate direction in which the basis is periodic.
Definition: gsTensorBSplineBasis.h:433
gsTensorBSplineBasis(KnotVectorType KV1, KnotVectorType KV2, KnotVectorType KV3)
Constructs a 3D tensor product B-spline basis. Assumes that the tamplate parameter d is equal to 3...
Definition: gsTensorBSplineBasis.h:119