G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsDeboor.hpp
Go to the documentation of this file.
1
14#pragma once
15
17
18//#include <gsNurbs/gsBSplineAlgorithms.h>
19#include <gsNurbs/gsBoehm.h>
20
22
23namespace gismo {
24
25
28// to do: make local version with knot iterators as arguments
29template<class T, class KnotVectorType> inline
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
74template<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
128template<short_t d, typename T, typename KnotVectorType, typename Mat>
129inline
130void 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
164template<short_t d, typename T, typename KnotVectorType, typename Mat>
165inline //LC
166void 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
197template<short_t d, typename T, typename KnotVectorType, typename Mat>
198inline
199void 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
225template<short_t d, typename T, typename KnotVectorType, typename Mat>
226inline
227void 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
int degree() const
Returns the degree of the knot vector.
Definition gsKnotVector.hpp:700
T last() const
Get the last knot.
Definition gsKnotVector.h:728
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
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
Boehm's algorithm for knot insertion.
Provides combinatorial unitilies.
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
This is the main header file that collects wrappers of Eigen for linear algebra.
The G+Smo namespace, containing all definitions for the library.
void gsDeboorDeriv(const gsMatrix< T > &u, const KnotVectorType &knots, int deg, const gsMatrix< T > &coefs, gsMatrix< T > &result)
Definition gsDeboor.hpp:75
void gsDeboor(const gsMatrix< T > &u, const KnotVectorType &knots, int deg, const gsMatrix< T > &coefs, gsMatrix< T > &result)
Definition gsDeboor.hpp:30