G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsDeboor.hpp
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsCore/gsLinearAlgebra.h>
17 
18 //#include <gsNurbs/gsBSplineAlgorithms.h>
19 #include <gsNurbs/gsBoehm.h>
20 
22 
23 namespace gismo {
24 
25 
28 // to do: make local version with knot iterators as arguments
29 template<class T, class KnotVectorType> inline
30 void gsDeboor(
31  const gsMatrix<T> &u,
32  const KnotVectorType & knots,
33  int deg,
34  const gsMatrix<T> & coefs,
35  gsMatrix<T>& result
36  )
37 {
38  GISMO_ASSERT( u.rows() == 1, "Waiting for 1D values" ) ;
39  GISMO_ASSERT( coefs.rows() == (index_t)(knots.size() - deg-1) ,
40  "coefs.rows(): " << coefs.rows() << ", knots.size(): " << knots.size() << ", deg: " << deg ) ;
41 
42  result.resize( coefs.cols(), u.cols() ) ;
43  int ind, k;
44  gsMatrix<T> points;
45  T tmp;
46 
47  for ( index_t j=0; j< u.cols(); j++ ) // for all points (entries of u)
48  {
49  //De Boor's algorithm for parameter u(0,j)
50  GISMO_ASSERT( (u(0,j)>knots[deg]-(T)(1e-4) ) && (u(0,j) < *(knots.end()-deg-1)+(T)(1e-4) ),
51  "Parametric point "<< u(0,j) <<" outside knot domain ["
52  << knots[deg]<<","<<*(knots.end()-deg-1) <<"].");
53 
54  ind = (knots.iFind( u(0,j) ) - knots.begin()) - deg;
55 
56  //int s= knots.multiplicity( u(0,j) ) ; // TO DO: improve using multiplicity s
57  points = coefs.middleRows( ind, deg+1 );
58 
59  for ( int r=0; r< deg; r++ ) // triangle step
60  //for ( int r=s; r< deg; r++ ) // TO DO: improve using multiplicity s
61  for ( int i=deg; i>r; i-- ) // recursive computation
62  {
63  k= ind + i;
64  tmp= ( u(0,j) - knots[k] ) / (knots[k+deg-r]-knots[k]);
65  points.row(i) = (T(1)-tmp)*points.row(i-1) + tmp* points.row(i) ;
66  }
67  result.col(j)= points.row(deg);
68  }
69 }
70 
74 template<class T, class KnotVectorType> inline
76  const gsMatrix<T> &u,
77  const KnotVectorType & knots,
78  int deg,
79  const gsMatrix<T> & coefs,
80  gsMatrix<T>& result
81  )
82 {
83  GISMO_ASSERT( u.rows() == 1, "Waiting for 1D values" ) ;
84  GISMO_ASSERT( coefs.rows() == (index_t)(knots.size() - deg-1) ,
85  "coefs.rows(): " << coefs.rows() << ", knots.size(): " << knots.size() << ", deg: " << deg ) ;
86 
87  deg--;// Derivative has degree reduced by one
88 
89  result.resize( coefs.cols(), u.cols() ) ;
90  int ind, k;
91  gsMatrix<T> points(deg+1, coefs.cols() );
92  T tmp;
93 
94  for ( index_t j=0; j< u.cols(); j++ ) // for all points (entries of u)
95  {
96  //De Boor's algorithm for parameter u(0,j)
97  GISMO_ASSERT( (u(0,j)>knots[deg]-(T)(1e-4) ) && (u(0,j) < *(knots.end()-deg-2)+(T)(1e-4) ),
98  "Parametric point "<< u(0,j) <<" outside knot domain ["
99  << knots[deg]<<","<<*(knots.end()-deg-2) <<"].");
100 
101  ind = knots.findspan( u(0,j) ) - deg - 1;
102 
103  //int s= knots.multiplicity( u(0,j) ) ; // TO DO: improve using multiplicity s
104 
105  // Get the coefficients of the first derivative
106  for ( int r=ind; r< deg+ind+1; r++ )
107  points.row(r-ind) = ( T(deg+1) / (knots[r+deg+2]-knots[r+1]) )
108  * ( coefs.row(r+1) - coefs.row(r) );
109 
110  for ( int r=0; r< deg; r++ ) // triangle step
111  //for ( int r=s; r< deg; r++ ) // TO DO: improve using multiplicity s
112  for ( int i=deg; i>r; i-- ) // recursive computation
113  {
114  k= ind + i;
115  tmp= ( u(0,j) - knots[k] ) / (knots[k+deg+1-r]-knots[k]);
116  points.row(i) = (T(1)-tmp)*points.row(i-1) + tmp* points.row(i) ;
117  }
118  result.col(j)= points.row(deg);
119  }
120 }
121 
122 
123 // =============================================================================
124 // ===== temporal version of gsTensorDeboor
125 // =============================================================================
126 
127 
128 template<short_t d, typename T, typename KnotVectorType, typename Mat>
129 inline
130 void gsTensorDeboor( //LC
131  const gsMatrix<T>& u,
132  const gsTensorBSplineBasis<d, T>& base,
133  const Mat& coefs, // works just for 1D coefficients
134  gsMatrix<T>& result
135  )
136 {
137 
138  // Default version - linear combination of basis functions
139  result.resize( coefs.cols(), u.cols() ) ;
140  gsMatrix<T> B ;
141  gsMatrix<index_t> ind;
142 
143  // "eval" of gsTensorBasis
144  base.eval_into(u, B); // col j = nonzero basis functions at column point u(..,j)
145  base.active_into(u, ind);// col j = indices of active functions at column point u(..,j)
146 
147 // gsDebug << "u: \n" << u << std::endl;
148 // gsDebug << "B: \n" << B << std::endl;
149 // gsDebug << "ind: \n" << ind << std::endl;
150 
151  for ( index_t j=0; j< u.cols() ; j++ ) // for all points (columns of u)
152  {
153  result(0, j) = coefs(ind(0, j)) * B(0, j);
154  for ( index_t i = 1; i < ind.rows(); ++i ) // for all non-zero basis functions
155  result(0, j) += coefs(ind(i, j)) * B(i, j);
156  }
157 }
158 
159 
160 // =============================================================================
161 // ===== derivatives for BSpline
162 // =============================================================================
163 
164 template<short_t d, typename T, typename KnotVectorType, typename Mat>
165 inline //LC
166 void gsTensorDeriv_into(const gsMatrix<T>& u,
167  const gsTensorBSplineBasis<d, T>& base,
168  const Mat& coefs,
169  gsMatrix<T>& result)
170 {
171  const unsigned nPts = u.cols(); // number of points
172  const unsigned nDer = d; // number of derivatives
173 
174  result.setZero(d, nPts);
175  gsMatrix<T> deriv; // derivatives
176  gsMatrix<index_t> ind;
177 
178  base.deriv_into(u, deriv); // col j = nonzero basis functions at column point u(..,j)
179  base.active_into(u, ind);// col j = indices of active functions at column point u(..,j)
180 
181 // gsDebug << "jaka n = d: " << d << std::endl;
182 // gsDebug << "ind: " << ind.rows() << " x " << ind.cols() << std::endl;
183 // gsDebug << "B: " << B.rows() << " x " << B.cols() << std::endl;
184 
185 
186  for (unsigned j = 0; j < nPts; ++j)
187  for (unsigned k = 0; k < nDer; ++k) // for all rows of the jacobian
188  for (index_t i = 0; i < ind.rows(); i++) // for all nonzero basis functions)
189  result(k, j) += coefs(ind(i, j)) * deriv(k + i * nDer, j);
190 }
191 
192 
193 // =============================================================================
194 // ===== second derivatives for BSpline
195 // =============================================================================
196 
197 template<short_t d, typename T, typename KnotVectorType, typename Mat>
198 inline
199 void gsTensorDeriv2_into(const gsMatrix<T>& u,
200  const gsTensorBSplineBasis<d, T>& base,
201  const Mat& coefs,
202  gsMatrix<T>& result)
203 {//LC
204  const unsigned nPts = u.cols(); // number points
205  const unsigned n2der = (d * (d + 1)) / 2; // number of second derivatives
206 
207  result.setZero(n2der, nPts);
208  gsMatrix<T> deriv2; // second derivatives
209  gsMatrix<index_t> ind;
210 
211 
212  base.deriv2_into(u, deriv2);
213  base.active_into(u, ind);
214 
215  for (unsigned j = 0; j < nPts; j++)
216  for (unsigned k = 0; k < n2der; k++)
217  for (index_t i = 0; i < ind.rows(); i++)
218  result(k, j) += coefs(ind(i, j)) * deriv2(k + i * n2der, j);
219 }
220 
221 // =============================================================================
222 // other version of evaluation via knot insertion
223 // =============================================================================
224 
225 template<short_t d, typename T, typename KnotVectorType, typename Mat>
226 inline
227 void gsTensorDeboor_v2(
228  const gsMatrix<T>& u,
229  const gsTensorBSplineBasis<d, T>& base,
230  const Mat& coefs,
231  gsMatrix<T>& result
232  )
233 {
234 
235 // int log = -3;
236 
237 // if (0 < log)
238 // {
239 // gsDebug << "coefs: " << coefs.rows() << " x " << coefs.cols()
240 // << std::endl;
241 // }
242 
243  // **************************************************************
244  // ** find out how many coefficients one needs for calculation **
245 
246  result.resize(coefs.cols(), u.cols());
247  gsVector<index_t, d> size_of_tmp_coefs(d);
248 
249  unsigned nmb_of_tmp_coefs = 1;
250  for (unsigned dim = 0; dim < d; dim++)
251  {
252  const KnotVectorType& kv = base.knots(dim);
253  size_of_tmp_coefs(dim) = kv.degree() + 1;
254  nmb_of_tmp_coefs *= size_of_tmp_coefs(dim);
255  }
256 
257  Mat tmp_coefs(nmb_of_tmp_coefs, coefs.cols());
258  tmp_coefs.fill(0);
259 
260  // for all points
261  for (index_t i = 0; i < u.cols(); i++)
262  {
263 // if (0 < log)
264 // {
265 // gsDebug << "\n---------------------------------------------"
266 // << std::endl;
267 
268 // gsDebug << "u( " << i << " ): ";
269 // for (unsigned dim = 0; dim < d; dim++)
270 // gsDebug << u(dim, i) << " ";
271 // gsDebug << std::endl;
272 // }
273 
274  std::vector<bool> is_last(d, false);
275 
276  for (short_t dim = 0; dim < d; dim++)
277  {
278  const KnotVectorType& kv = base.knots(dim);
279 // if (u(dim, i) == *(--kv.end()))
280  if ( u(dim, i) == kv.last() )
281  {
282  is_last[dim] = true;
283  }
284  }
285 
286 
287 
288  gsVector<index_t, d> low, upp;
289  base.active_cwise(u.col(i), low, upp);
290 
291 // if (1 < log)
292 // {
293 // gsDebug << "low: " << low.transpose() << "\nupp: "
294 // << upp.transpose() << std::endl;
295 // }
296 // if (0 < log)
297 // {
298 // gsDebug << "size_of_coefs: " << size_of_coefs.transpose() << "\n"
299 // << "number_of_coefs: " << nmb_of_coefs
300 // << std::endl;
301 // }
302 
303 
304  //*******************************************************
305  //** copy appropriate coefficients to temporary matrix **
306 
307  // position of the coefficient
308  gsVector<index_t, d> coefs_position(low);
309 
310  gsVector<index_t, d> zero(d);
311  zero.fill(0);
312 
313  // position in tmp_coefs
314  gsVector<index_t, d> tmp_coefs_position(zero);
315 
316  // strides in tmp_coefs
317  gsVector<index_t, d> tmp_coefs_str(d);
318  bspline::buildCoeffsStrides<d>(size_of_tmp_coefs, tmp_coefs_str);
319 
320  gsVector<index_t, d> tmp_coefs_last(d);
321  bspline::getLastIndexLocal<d>(size_of_tmp_coefs, tmp_coefs_last);
322 
323  do
324  {
325 // if (10 < log)
326 // {
327 // gsDebug << "coefs_position: "
328 // << coefs_position.transpose() << "\n"
329 // << "tmp_coefs_position: "
330 // << tmp_coefs_position.transpose() << "\n"
331 // << std::endl;
332 // }
333 
334  unsigned flat_index = base.index(coefs_position);
335  unsigned tmp_coefs_index = bspline::getIndex<d>(tmp_coefs_str,
336  tmp_coefs_position);
337 
338  tmp_coefs.row(tmp_coefs_index) = coefs.row(flat_index);
339 
340 
341  nextCubePoint<gsVector<index_t, d> >(tmp_coefs_position, zero,
342  tmp_coefs_last);
343  } while(nextCubePoint<gsVector<index_t, d> >(coefs_position, low, upp));
344 
345 
346 // if (1 < log)
347 // {
348 // gsDebug << "tmp_coefs: \n" << tmp_coefs << std::endl;
349 // }
350 
351 
352  // ********************************************************
353  // ** perform knot insertion appropriate number of times **
354 
355  gsVector<index_t, d> start(d);
356  start.fill(0);
357  gsVector<index_t, d> end(size_of_tmp_coefs);
358  for (short_t dim = 0; dim < d; dim++)
359  end(dim)--;
360 
361  for (short_t dim = 0; dim < d; dim++) //in each dimension insert a knot
362  {
363  if (is_last[dim])
364  {
365  start(dim) = end(dim);
366  }
367  else
368  {
369  const KnotVectorType& kv = base.knots(dim);
370 
371  gismo::gsTensorInsertKnotDegreeTimes<d, T, KnotVectorType, Mat>
372  (kv, tmp_coefs, size_of_tmp_coefs, u(dim, i), dim,
373  start, end);
374 
375  start(dim) = 0;
376  end(dim) = 0;
377  }
378 
379  }
380 
381  // index of a point at a parameter u.col(i)
382  index_t flat_index = bspline::getIndex<d>(tmp_coefs_str,
383  start);
384 
385 // if (0 < log)
386 // {
387 // gsDebug << "Point is: \n"
388 // << tmp_coefs.row(flat_index)
389 // << std::endl;
390 // }
391 
392  result.col(i) = tmp_coefs.row(flat_index).transpose();
393 
394  } // end for each point
395 }
396 
397 
398 
399 }; //end namespace gismo
bool nextCubePoint(Vec &cur, const Vec &end)
Iterate in lexigographic order through the points of the integer lattice contained in the cube [0...
Definition: gsCombinatorics.h:327
#define short_t
Definition: gsConfig.h:35
void gsDeboorDeriv(const gsMatrix< T > &u, const KnotVectorType &knots, int deg, const gsMatrix< T > &coefs, gsMatrix< T > &result)
Definition: gsDeboor.hpp:75
Boehm&#39;s algorithm for knot insertion.
#define index_t
Definition: gsConfig.h:32
void gsDeboor(const gsMatrix< T > &u, const KnotVectorType &knots, int deg, const gsMatrix< T > &coefs, gsMatrix< T > &result)
Definition: gsDeboor.hpp:30
Provides combinatorial unitilies.
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
This is the main header file that collects wrappers of Eigen for linear algebra.
int degree() const
Returns the degree of the knot vector.
Definition: gsKnotVector.hpp:700