G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsTensorBSplineBasis.hpp
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsCore/gsTemplateTools.h>
17 #include <gsTensor/gsTensorTools.h>
19 #include <gsNurbs/gsKnotVector.h>
20 #include <gsNurbs/gsBoehm.h>
21 
22 #include <gsIO/gsXml.h>
24 
25 
26 namespace gismo
27 {
28 
29 template<short_t d, class T>
30 gsTensorBSplineBasis<d,T>::gsTensorBSplineBasis(std::vector<typename gsTensorBSplineBasis<d,T>::Basis_t*> & bb )
31 : Base( castVectorPtr<gsBasis<T> >(bb).data() )
32 {
33  GISMO_ASSERT( checkVectorPtrCast<Basis_t>(bb), "Invalid vector of basis pointers.");
34  GISMO_ENSURE( d == bb.size(), "Wrong d in the constructor of gsTensorBSplineBasis." );
35  bb.clear();
36  setIsPeriodic();
37 }
38 
39 template<short_t d, class T>
40 gsTensorBSplineBasis<d,T>::gsTensorBSplineBasis(std::vector<gsBasis<T>*> & bb )
41 : Base(bb.data())
42 {
43  GISMO_ENSURE( d == bb.size(), "Wrong d in the constructor of gsTensorBSplineBasis." );
44  bb.clear();
45  setIsPeriodic();
46 }
47 
48 template<short_t d, class T>
49 void gsTensorBSplineBasis<d,T>::
50 active_cwise(const gsMatrix<T> & u,
52  gsVector<index_t,d>& upp ) const
53 {
54  for (index_t j = 0; j < u.cols(); ++j)
55  {
56  for (short_t i = 0; i < d; ++i)
57  {
58  low[i] = component(i).firstActive( u(i,j) );
59  upp[i] = low[i] + component(i).degree();
60  }
61  }
62 }
63 
64 template<short_t d, class T>
67  const std::vector< std::vector<T> >& refineKnots)
68 {
69  GISMO_ASSERT( refineKnots.size() == d, "refineKnots vector has wrong size" );
71 
72  // refine component bases and obtain their transfer matrices
73  for (unsigned i = 0; i < d; ++i)
74  {
75  this->component(i).refine_withTransfer( B[i], refineKnots[i] );
76  }
77 
78  tensorCombineTransferMatrices<d, T>( B, transfer );
79 }
80 
81 template<short_t d, class T>
83 refine_withCoefs(gsMatrix<T> & coefs,const std::vector< std::vector<T> >& refineKnots)
84 {
85  GISMO_ASSERT( refineKnots.size() == d, "refineKnots vector has wrong size" );
86  gsVector<unsigned> strides(d);
87  for (unsigned j = 0; j < d; ++j) //calculate the strides for each direction
88  {
89  strides[j]=this->stride(j);
90  }
91  for (unsigned i = 0; i < d; ++i)
92  {
93  if(refineKnots[i].size()>0)
94  {
95  gsTensorBoehmRefine(this->component(i).knots(), coefs, i, strides,
96  refineKnots[i].begin(), refineKnots[i].end(), true);
97 
98  for (index_t j = i+1; j<strides.rows(); ++j)
99  strides[j]=this->stride(j); //new stride for this direction
100  }
101  }
102 }
103 
104 
105 template<short_t d, class T>
107 {
108  // Note: refExt parameter is ignored
109  GISMO_ASSERT( boxes.rows() == this->dim() ,
110  "Number of rows of refinement boxes must equal dimension of parameter space.");
111  GISMO_ASSERT( boxes.cols() % 2 == 0,
112  "Refinement boxes must have even number of columns.");
113 
114  const T tol = 0.000000001;
115 
116  // for each coordinate direction of the parameter domain:
117  for( int di = 0; di < this->dim(); di++)
118  {
119 
120  // for simplicity, get the corresponding knot vector.
121  KnotVectorType kold_di = Self_t::component(di).knots();
122 
123  // vector of flags for refining knotspans
124  std::vector<bool> flagInsertKt( kold_di.size(), false);
125 
126  // This is a very crude and unelegant test, but
127  // conveniently straightforward to implement (and maybe to):
128  // For each knot span, check if its midpoint is
129  // contained in any of the refinement boxes.
130  // If yes, set the corresponding flag to 1.
131  for( size_t i=1; i < kold_di.size(); i++ ) // loop over spans
132  if( kold_di[i]-kold_di[i-1] > tol) // check for empty spans
133  {
134  const T midpt = (kold_di[i] + kold_di[i-1])/(T)(2); // midpoint of knot span
135  for( index_t j=0; j < boxes.cols(); j+=2 ) // loop over all boxes
136  {
137  // if the box contains the midpoint, mark it
138  flagInsertKt[i] = boxes(di,j) < midpt && midpt < boxes(di,j+1);
139  }
140  }
141 
142  // now, with the flags set, loop over all knots spans and
143  // insert midpoint in each knot span which is marked for refinement.
144  for( size_t i=1; i < kold_di.size(); i++ )
145  if( flagInsertKt[i] )
146  {
147  T midpt = (kold_di[i] + kold_di[i-1])/(T)(2);
148  Self_t::component(di).insertKnot( midpt );
149  }
150 
151  } // for( int di )
152 
153 
154 } // refine()
155 
156 
157 /*
158  * NB:
159  * This implementation assumes that the component bases implement the firstActive() / numActive() protocol.
160  * In particular, their active basis functions must always be continuous intervals.
161  * This is the case for all current component bases, so we only keep this version for now.
162  * Above, commented out, is the generic version which is quite a bit slower.
163  */
164 template<short_t d, class T>
166 active_into(const gsMatrix<T> & u, gsMatrix<index_t>& result) const
167 {
168  GISMO_ASSERT( u.rows() == static_cast<index_t>(d), "Invalid point dimension: "<<u.rows()<<", expected "<< d);
169 
170  unsigned firstAct[d];
171  gsVector<unsigned, d> v, size;
172 
173  // count active functions in each tensor direction
174  unsigned numAct = 1;
175  for (unsigned i = 0; i < d; ++i)
176  {
177  size[i] = component(i).numActive();
178  numAct *= size[i];
179  }
180 
181  result.resize( numAct, u.cols() );
182 
183  // Fill with active bases indices
184  for (index_t j = 0; j < u.cols(); ++j)
185  {
186  // get the active basis indices for the component bases at u(:,j)
187  for (short_t i = 0; i < d; ++i)
188  {
189  firstAct[i] = component(i).firstActive( u(i,j) );
190  }
191 
192  // iterate over all tensor product active functions
193  unsigned r = 0;
194  v.setZero();
195  do
196  {
197  index_t gidx = firstAct[d-1] + v(d-1); //compute global index in the tensor product
198  for ( short_t i=d-2; i>=0; --i )
199  gidx = gidx * this->size(i) + firstAct[i] + v(i);
200 
201  result(r, j) = gidx;
202  ++r ;
203  } while (nextLexicographic(v, size));
204  }
205 }
206 
207 
208 namespace internal
209 {
210 
212 template<short_t d, class T>
213 class gsXml< gsTensorBSplineBasis<d,T> >
214 {
215 private:
216  gsXml() { }
217  typedef gsTensorBSplineBasis<d,T> Object;
218 public:
219  GSXML_COMMON_FUNCTIONS(Object);
220  static std::string tag () { return "Basis"; }
221  static std::string type () { return "TensorBSplineBasis"+to_string(d); }
222 
223  static Object * get (gsXmlNode * node)
224  {
225  if (d>1)
226  {
227  GISMO_ASSERT( ( !strcmp( node->name(),"Basis") )
228  && ( !strcmp(node->first_attribute("type")->value(),
229  internal::gsXml<Object>::type().c_str() ) ),
230  "Something is wrong with the XML data: There should be a node with a "
231  <<internal::gsXml<Object>::type().c_str()<<" Basis.");
232  }
233  else
234  {
235  GISMO_ASSERT( ( !strcmp( node->name(),"Basis") )
236  && ( !strcmp(node->first_attribute("type")->value(),
237  internal::gsXml<Object>::type().c_str())
238  || !strcmp(node->first_attribute("type")->value(), "BSplineBasis") ),
239  "Something is wrong with the XML data: There should be a node with a "
240  <<internal::gsXml<Object>::type().c_str()<<" Basis.");
241  }
242 
243  return getTensorBasisFromXml<Object >( node );
244  }
245 
246  static gsXmlNode * put (const Object & obj,
247  gsXmlTree & data )
248  {
249  return putTensorBasisToXml<Object >(obj,data);
250  }
251 };
252 
253 } // internal
254 
255 } // gismo
256 
Knot vector for B-splines.
std::vector< Base * > castVectorPtr(std::vector< Derived * > pVec)
Casts a vector of pointers.
Definition: gsMemory.h:344
#define short_t
Definition: gsConfig.h:35
Boehm&#39;s algorithm for knot insertion.
Utility functions related to tensor-structured objects.
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
gsTensorBSplineBasis()
Default constructor.
Definition: gsTensorBSplineBasis.h:74
void gsTensorBoehmRefine(KnotVectorType &knots, Mat &coefs, int direction, gsVector< unsigned > str, ValIt valBegin, ValIt valEnd, bool update_knots=true)
Definition: gsBoehm.hpp:372
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Provides implementation of generic XML functions.
std::string to_string(const unsigned &i)
Helper to convert small unsigned to string.
Definition: gsXml.cpp:74
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
Utilities related to template programming.
Provides declaration of input/output XML utilities struct.
Provides declaration of TensorBSplineBasis abstract interface.