G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsQuasiInterpolate.hpp
Go to the documentation of this file.
1
15#pragma once
16
17namespace gismo {
18
19template<typename T>
20gsMatrix<T> gsQuasiInterpolate<T>::localIntpl(const gsBasis<T> &bb,
21 const gsFunction<T> &fun,
22 index_t i,
23 const gsMatrix<T> &ab)
24{
25 gsMatrix<T> bev, fev, pts, tmp;
26 gsVector<index_t> nNodes = gsQuadrature::numNodes(bb,(T)1.0,1);
27 gsQuadRule<T> qRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,nNodes);
28
29 qRule.mapTo(ab, pts);//map points on element
30 bb .eval_into(pts, bev);//evaluate basis
31 fun.eval_into(pts, fev);//evaluate function
32 bev.transposeInPlace();
33 fev.transposeInPlace();
34 tmp = bev.partialPivLu().solve(fev);//solve on element
35
36 // find the i-th BS:
37 gsMatrix<index_t> act = bb.active(pts.col(0));
38 index_t c = std::lower_bound(act.data(), act.data()+act.size(), i) - act.data();
39 GISMO_ASSERT(c<act.size(), "Problem with basis function index");
40 return tmp.row(c);
41}
42
43/*
44gsMatrix<T> gsQuasiInterpolate<T>::localIntpl(const gsTensorBasis<d,T> &bb,
45 const gsFunction<T> &fun,
46 index_t i,
47 const gsMatrix<T> &ab)
48{
49 gsMatrix<T> bev, fev, pts, tmp;
50 gsVector<index_t> nNodes = gsQuadrature::numNodes(bb,(T)1.0,1);
51 gsQuadRule<T> qRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,nNodes); //gsTPQuadRule ..
52
53 // for(pt..)
54 //{
55 qRule.mapTo(ab, pt);//map point on element
56 fun.eval_into(pts, fev);//evaluate function
57 //}
58 fev.transposeInPlace();
59
60 //solve
61 bev.transposeInPlace();// must be cwise
62 tmp = bev.partialPivLu().solve(fev);//solve on element
63
64 // find the i-th BS:
65 gsMatrix<index_t> act = bb.active(pts.col(0)); //cwise..?
66 index_t c = std::lower_bound(act.data(), act.data()+act.size(), i) - act.data();
67 GISMO_ASSERT(c<act.size(), "Problem with basis function index");
68 return tmp.row(c);
69}
70*/
71
72template<typename T>
73template<short_t d>
74gsMatrix<T> gsQuasiInterpolate<T>::localIntpl(const gsHTensorBasis<d,T> &bb,
75 const gsFunction<T> &fun,
76 index_t i)
77{
78 index_t lvl = bb.levelOf(i);
79 index_t j = bb.flatTensorIndexOf(i);
80 return localIntpl(bb.tensorLevel(lvl),fun,j, bb.elementInSupportOf(i)); // uses the H-grid element implementation
81 //return localIntpl(bb.tensorLevel(lvl),fun,j); // uses the central element implementation
82}
83
84template<typename T>
85gsMatrix<T> gsQuasiInterpolate<T>::localIntpl(const gsBasis<T> &bb,
86 const gsFunction<T> &fun,
87 index_t i)
88{
89 if (const gsHTensorBasis<1,T>* b = dynamic_cast<const gsHTensorBasis<1,T>* >(&bb))
90 return localIntpl(*b,fun,i);
91 if (const gsHTensorBasis<2,T>* b = dynamic_cast<const gsHTensorBasis<2,T>* >(&bb))
92 return localIntpl(*b,fun,i);
93 if (const gsHTensorBasis<3,T>* b = dynamic_cast<const gsHTensorBasis<3,T>* >(&bb))
94 return localIntpl(*b,fun,i);
95 if (const gsHTensorBasis<4,T>* b = dynamic_cast<const gsHTensorBasis<4,T>* >(&bb))
96 return localIntpl(*b,fun,i);
97 else
98 return localIntpl(bb,fun,i,bb.elementInSupportOf(i));
99}
100
101
102template<typename T>
103void gsQuasiInterpolate<T>::Taylor(const gsBasis<T> &bb, const gsFunction<T> &fun, const int &r, gsMatrix<T> & coefs)
104{
105 const gsBSplineBasis<T> & b = dynamic_cast<const gsBSplineBasis<T> &>(bb);
106 // ONLY 1D
107
108 const gsKnotVector<T> & kv = b.knots();
109 int deg = b.degree();
110 gsMatrix<T> xj = b.anchors();
111
112 int n = xj.size();
113 int dim = fun.targetDim();
114 coefs.resize(n,dim);
115
116 std::vector<gsMatrix<T> > derivs;
117 fun.evalAllDers_into(xj, r, derivs);
118
119
120 gsMatrix<T> val;
121 std::vector<T> knots;
122 for(int j=0; j<n; j++)
123 {
124 val.setZero(1,dim);
125 knots.clear();
126 for(int i=j+1; i<=j+deg; i++)
127 knots.push_back(kv[i]);
128
129 for(int k=0; k<=r; k++) // (r+1) nodes
130 {
131 const T factor1 = derivProd(knots, deg-k, xj(j)); //coeff
132 for(int i=0; i<dim; i++)
133 {
134 const T factor2 = derivs[k](i,j); //node
135 val(i) += std::pow(-1.0,k) * factor1 * factor2;
136 }
137 }
138 val /= factorial(deg);
139 coefs.row(j) = val;
140 }
141}
142
143template<typename T> gsMatrix<T>
145 const gsFunction<T> &fun,
146 index_t i)
147{
148 gsMatrix<T> res;
149 fun.eval_into(b.anchor(i), res);
150 res.transposeInPlace();
151 return res;
152}
153
154
155template<typename T>
156void gsQuasiInterpolate<T>::EvalBased(const gsBasis<T> &bb, const gsFunction<T> &fun, const bool specialCase, gsMatrix<T> &coefs)
157{
158 const gsBSplineBasis<T> & b = dynamic_cast<const gsBSplineBasis<T> &>(bb);
159 // ONLY 1D
160
161 const gsKnotVector<T> & kv = b.knots();
162 const int n = b.size();
163 //gsDebugVar(kv);
164
165 coefs.resize(n, fun.targetDim());
166
167 gsMatrix<T> knots(1,kv.size());
168 for(unsigned int i=0; i<kv.size(); i++)
169 knots(i) = kv[i];
170
171 gsMatrix<T> TmpCoefs;
172
173 int type = 0;
174 if(specialCase)
175 {
176 type = b.degree();
177 GISMO_ASSERT( (type == 1 || type == 2 || type == 3),
178 "quasiInterpolateEvalBased is implemented for special cases of deg 1, 2 or 3!");
179 }
180
181 switch(type)
182 {
183 case 1: //piecewise linear (section 8.2.1 of "Spline methods (Lyche Morken)")
184 {
185 fun.eval_into(knots, TmpCoefs);
186 for(int i=0; i<n; i++)
187 coefs.row(i) = TmpCoefs.col(i+1).transpose();
188 break;
189 }
190 case 2: //3-point quadratic (section 8.2.2 of "Spline methods (Lyche Morken)")
191 {
192 fun.eval_into(knots, TmpCoefs);
193 gsMatrix<T> knotsAvg(1, kv.size()-1);
194 for(unsigned int i=0; i<kv.size()-1; i++)
195 knotsAvg(i) = (kv[i]+kv[i+1]) / (T)(2);
196 gsMatrix<T> TmpCoefsAvg;
197 fun.eval_into(knotsAvg, TmpCoefsAvg);
198
199 coefs.row(0) = TmpCoefs.col(0);
200 for(int i=1; i<n-1; i++)
201 {
202 // formula: (-a + 4b - c)/2;
203 coefs.row(i).noalias() =
204 ( - TmpCoefs.col(i+1)
205 + 4 * TmpCoefsAvg.col(i+1)
206 - TmpCoefs.col(i+2) ) / (T)(2);
207 }
208 coefs.row(n-1) = TmpCoefs.col(n);
209 break;
210 }
211 case 3: //5-point cubic (section 8.2.3 of "Spline methods (Lyche Morken)")
212 {
213 fun.eval_into(knots, TmpCoefs);
214 gsMatrix<T> knotsAvg(1, kv.size()-1);
215 for(unsigned int i=0; i<kv.size()-1; i++)
216 knotsAvg(i) = (kv[i]+kv[i+1]) / (T)(2);
217 gsMatrix<T> TmpCoefsAvg;
218 fun.eval_into(knotsAvg, TmpCoefsAvg);
219
220 coefs.row(0) = TmpCoefs.col(3).transpose();
221
222 // formula: (- 5a + 40b - 24c + 8d - e)/18
223 coefs.row(1).noalias() =
224 ( - 5 * TmpCoefs.col(3)
225 + 40 * TmpCoefsAvg.col(3)
226 - 24 * TmpCoefs.col(4)
227 + 8 * TmpCoefsAvg.col(4)
228 - TmpCoefs.col(5) ) / (T)(18);
229
230 for(int i=2; i<n-2; i++)
231 {
232 // formula: (a - 8b + 20c - 8d + e)/6
233 coefs.row(i).noalias() =
234 ( TmpCoefs.col(i+1)
235 - 8 * TmpCoefsAvg.col(i+1)
236 + 20 * TmpCoefs.col(i+2)
237 - 8 * TmpCoefsAvg.col(i+2)
238 + TmpCoefs.col(i+3) ) / (T)(6);
239 }
240
241 // formula: (- a + 8b - 24c + 40d - 5e)/18
242 coefs.row(n-2).noalias() =
243 ( - TmpCoefs.col(n-2)
244 + 8 * TmpCoefsAvg.col(n-2)
245 - 24 * TmpCoefs.col(n-1)
246 + 40 * TmpCoefsAvg.col(n-1)
247 - 5 * TmpCoefs.col(n) ) / (T)(18);
248
249 coefs.row(n-1) = TmpCoefs.col(n);
250
251 break;
252 }
253 default: //if none of the special cases, (Theorem 8.7 and Lemma 9.7 of "Spline methods (Lyche Morken)")
254 gsMatrix<T> xik, weights;
255 for(int i=0; i<n; i++)
256 {
257 //look for the greatest subinterval to chose the interpolation points from
258 int gsi = greatestSubInterval(kv, i, i+kv.degree());
259
260 //compute equally distributed points in greatest subinterval
261 distributePoints(kv[gsi], kv[gsi+1], kv.degree()+1, xik);
262 //gsDebugVar(xik);
263
264 //compute the factors omega_{ik}
265 computeWeights(xik, kv, i+1, weights);
266
267 //compute the coefficients lambda_i of the quasi-interpolant
268 coefs.row(i) = computeControlPoints(weights, fun, xik);
269 }
270 break;
271 }
272}
273
274
275template<typename T>
276T gsQuasiInterpolate<T>::derivProd(const std::vector<T> &zeros, const int &order, const T &x)
277{
278 if(order == 0) // value
279 return (x - gsAsConstMatrix<T,1>(zeros).array()).prod();
280
281 std::vector<T> tmpZeros;
282
283 if(order == 1) // first derivative
284 {
285 const index_t n1 = zeros.size() - 1;
286 tmpZeros = zeros;
287 T val = 0;
288 for(typename std::vector<T>::iterator it = tmpZeros.begin(); it!=tmpZeros.end(); ++it)
289 {
290 std::iter_swap(it, tmpZeros.end()-1);
291 val += (x - gsAsConstMatrix<T,1>(tmpZeros,1,n1).array()).prod(); // eval product
292 std::iter_swap(it, tmpZeros.end()-1);
293 }
294 return val;
295 }
296
297 // Reccursion for higher order derivatives
298 const int n = zeros.size();
299 T val = 0;
300 for(int i=0; i!=n; i++)
301 {
302 tmpZeros = zeros;
303 tmpZeros.erase(tmpZeros.begin() + i);
304 val += derivProd(tmpZeros, order-1, x);
305 }
306 return val;
307}
308
309
310template<typename T>
312{
313 points.resize(1,n);
314 for(int k=0; k<n; k++)
315 points.at(k) = a + (T)k/(T)(n-1) * (b-a);
316}
317
318
319template<typename T>
320void gsQuasiInterpolate<T>::computeWeights(const gsMatrix<T> &points, const gsKnotVector<T> &knots, const int &pos, gsMatrix<T> &weights)
321{
322 const int deg = knots.degree();
323 weights.resize(1,deg+1);
324
325 gsMatrix<T> pointsReduced(1,deg);
326 gsVector<int> indices(deg);
327 for(int k=0; k<deg+1; k++)
328 {
329 T constant = (T)factorial(deg);
330
331 //get the list of points without 'points(k)' and
332 //multiply the values of the numerator together, to get the total constant
333 for(int i=0; i<k; i++)
334 {
335 pointsReduced(i) = points(i);
336 constant *= points(k) - points(i);
337 }
338 for(int i=k+1; i<deg+1; i++)
339 {
340 pointsReduced(i-1) = points(i);
341 constant *= points(k) - points(i);
342 }
343
344 //get all permutations of the list
345 for(int i=0; i<deg; i++)
346 indices[i]=i;
347
348 T sum = 0;
349 do
350 {
351 //compute the product of values for this permutation
352 T factor = 1;
353 for(int i=0; i<deg; i++)
354 {
355 factor *= (knots[pos+indices[i]] - pointsReduced(i));
356 }
357 sum += factor; //sum up the products for each permutation
358 }
359 while(std::next_permutation(indices.data(), indices.data()+deg));
360
361 weights(k) = sum / constant;
362 }
363}
364
365
366template<typename T>
368{
369 gsMatrix<T> funValues;
370 fun.eval_into(xik, funValues);
371 return (weights.asDiagonal() * funValues.transpose()).colwise().sum();
372}
373
374
375template<typename T>
376int gsQuasiInterpolate<T>::greatestSubInterval(const gsKnotVector<T> &knots, const int &posStart, const int &posEnd) //ToDo: move to gsKnotVector
377{
378 const int diff = posEnd-posStart;
379 T maxDist=0.0;
380 int maxInd = posStart;
381 for(int i=1; i<diff+1; i++)
382 {
383 const T dist = knots[posStart+i+1] - knots[posStart+i];
384 if(dist > maxDist)
385 {
386 maxDist = dist;
387 maxInd = posStart+i;
388 }
389 }
390 return maxInd;
391}
392
393
394template<typename T>
396 const gsFunction<T> &fun,
397 gsMatrix<T> & result)
398{
399 GISMO_ASSERT(b.domainDim()==fun.domainDim(),"Domain dimensions should be equal");
400 //assert b.domainDim()==fun.domainDim()
401 gsMatrix<T> cf;
402 index_t n = b.size();
403 index_t dim = fun.targetDim();
404 result.resize(n,dim);
405
406 for (index_t i = 0; i!=n; ++i)
407 {
408 cf = localIntpl(b,fun,i);
409 result.row(i) = cf;
410 }
411}
412
413template<typename T>
415 const gsFunction<T> &fun,
416 gsMatrix<T> & result)
417{
418 //assert b.domainDim()==fun.domainDim()
419 gsMatrix<T> cf;
420 index_t n = b.size();
421 index_t dim = fun.targetDim();
422 result.resize(n,dim);
423
424 for (index_t i = 0; i!=n; ++i)
425 {
426 cf = Schoenberg(b,fun,i);
427 result.row(i) = cf;
428 }
429}
430
431
432} // gismo
Creates a mapped object or data pointer to a const matrix without copying data.
Definition gsAsMatrix.h:141
A univariate B-spline basis.
Definition gsBSplineBasis.h:700
A basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
gsMatrix< T > anchors() const
Returns the anchor points that represent the members of the basis. There is exactly one anchor point ...
Definition gsBasis.h:437
virtual short_t domainDim() const =0
Dimension of the (source) domain.
virtual index_t size() const
size
Definition gsFunctionSet.h:613
virtual void evalAllDers_into(const gsMatrix< T > &u, int n, std::vector< gsMatrix< T > > &result, bool sameElement=false) const
Evaluate the nonzero functions and their derivatives up to order n at points u into result.
Definition gsFunctionSet.hpp:81
A function from a n-dimensional domain to an m-dimensional image.
Definition gsFunction.h:60
virtual short_t domainDim() const=0
Dimension of the (source) domain.
virtual short_t targetDim() const
Dimension of the target space.
Definition gsFunctionSet.h:595
virtual void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const =0
Evaluate the function at points u into result.
Class for representing a knot vector.
Definition gsKnotVector.h:80
size_t size() const
Number of knots (including repetitions).
Definition gsKnotVector.h:242
int degree() const
Returns the degree of the knot vector.
Definition gsKnotVector.hpp:700
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition gsMatrix.h:211
const KnotVectorType & knots(int i=0) const
Returns the knot vector of the basis.
Definition gsBSplineBasis.h:371
short_t degree(short_t i) const
Returns the degree of the basis wrt variable i.
Definition gsBSplineBasis.h:324
index_t size() const
Returns the number of elements in the basis.
Definition gsBSplineBasis.h:165
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
unsigned factorial(unsigned n)
Returns the factorial of n i.e. n! Remember that factorial grow too fast and only n!...
Definition gsCombinatorics.h:29
#define index_t
Definition gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
The G+Smo namespace, containing all definitions for the library.
gsVector< unsigned > distributePoints(const gsGeometry< T > &geo, unsigned numPoints)
distributes sampling points according to the length of the patch in each parametric direction
Definition gsGeoUtils.hpp:536
@ GaussLegendre
Gauss-Legendre quadrature.
Definition gsQuadrature.h:37
static gsVector< index_t > numNodes(const gsBasis< T > &basis, const Real quA, const index_t quB, short_t fixDir=-1)
Definition gsQuadrature.h:155
Quasi-interpolation operators.
Definition gsQuasiInterpolate.h:37
static void EvalBased(const gsBasis< T > &bb, const gsFunction< T > &fun, const bool specialCase, gsMatrix< T > &result)
A quasi-interpolation scheme based on the evaluation of the function at certain points....
Definition gsQuasiInterpolate.hpp:156
static gsMatrix< T > computeControlPoints(const gsMatrix< T > &weights, const gsFunction< T > &fun, const gsMatrix< T > &xik)
The quasi-interpolant is a spline function, in particular a linear combination of some controlpoints ...
Definition gsQuasiInterpolate.hpp:367
static void Schoenberg(const gsBasis< T > &b, const gsFunction< T > &fun, gsMatrix< T > &result)
A quasi-interpolation scheme based on Schoenberg Variation Diminishing Spline Approximation....
Definition gsQuasiInterpolate.hpp:414
static T derivProd(const std::vector< T > &zeros, const int &order, const T &x)
Compute the derivative of a certain order of a normalized polynomial (leading coefficient is 1) defin...
Definition gsQuasiInterpolate.hpp:276
static void distributePoints(T a, T b, int n, gsMatrix< T > &points)
Compute a number of equally distributed points in a given interval . You get a list of points .
Definition gsQuasiInterpolate.hpp:311
static void computeWeights(const gsMatrix< T > &points, const gsKnotVector< T > &knots, const int &pos, gsMatrix< T > &weights)
To compute the control points of the quasi-interpolant one uses the function computeControlPoints....
Definition gsQuasiInterpolate.hpp:320
static void Taylor(const gsBasis< T > &bb, const gsFunction< T > &fun, const int &r, gsMatrix< T > &result)
A quasi-interpolation scheme based on the tayor expansion of the function to approximate....
Definition gsQuasiInterpolate.hpp:103
static int greatestSubInterval(const gsKnotVector< T > &knots, const int &posStart, const int &posEnd)
This function finds the greatest knot interval in a given range in a knot vector.
Definition gsQuasiInterpolate.hpp:376