G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsQuasiInterpolate.hpp
Go to the documentation of this file.
1 
15 #pragma once
16 
17 namespace gismo {
18 
19 template<typename T>
20 gsMatrix<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 /*
44 gsMatrix<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 
72 template<typename T>
73 template<short_t d>
74 gsMatrix<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 
84 template<typename T>
85 gsMatrix<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 
102 template<typename T>
103 void 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 
143 template<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 
155 template<typename T>
156 void 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 
275 template<typename T>
276 T 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 
310 template<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 
319 template<typename T>
320 void 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 
366 template<typename T>
368 {
369  gsMatrix<T> funValues;
370  fun.eval_into(xik, funValues);
371  return (weights.asDiagonal() * funValues.transpose()).colwise().sum();
372 }
373 
374 
375 template<typename T>
376 int 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 
394 template<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 
413 template<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
index_t size() const
size
Definition: gsBSplineBasis.h:165
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
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. See Theorem 8.5 of &quot;Spline methods (Lyche Morken)&quot; Theorem: (Lyche, Morken: Thm 8.5, page 178) Let and be the degree and knotvector of the quasi-interpolant, respectively. Futhermore let be an integer with and let be a number in for . Consider the quasi-interpolant and . Then reproduces all polynomials of degree and reproduces all splines in .
Definition: gsQuasiInterpolate.hpp:103
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
short_t degree(short_t i) const
Degree with respect to the i-th variable. If the basis is a tensor product of (piecewise) polynomial ...
Definition: gsBSplineBasis.h:322
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. The weights can be computed as , for , where for a polynomial , where is the set of all permutations of the intergers .
Definition: gsQuasiInterpolate.hpp:320
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
virtual index_t size() const
size
Definition: gsFunctionSet.h:578
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
#define index_t
Definition: gsConfig.h:32
A function from a n-dimensional domain to an m-dimensional image.
Definition: gsFunction.h:59
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. See sections 8.2.1, 8.2.2, 8.2.3 and Theorem 8.7 or Lemma 9.7 of &quot;Spline methods (Lyche Morken)&quot;. The formulas for the special cases (degrees 1, 2 and 3) look like this: where the coefficients for are given as: for degree 1, where .
Definition: gsQuasiInterpolate.hpp:156
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
virtual short_t targetDim() const
Dimension of the target space.
Definition: gsFunctionSet.h:560
A univariate B-spline basis.
Definition: gsBSplineBasis.h:694
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition: gsMatrix.h:211
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
const KnotVectorType & knots(int i=0) const
Returns the knot vector of the basis.
Definition: gsBSplineBasis.h:369
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. See Exercise 9.1 of &quot;Spline methods (Lyche Morken)&quot;.
Definition: gsQuasiInterpolate.hpp:414
Quasi-interpolation operators.
Definition: gsQuasiInterpolate.h:36
Gauss-Legendre quadrature.
Definition: gsQuadrature.h:34
virtual short_t domainDim() const =0
Dimension of the (source) domain.
Creates a mapped object or data pointer to a const matrix without copying data.
Definition: gsLinearAlgebra.h:127
static gsVector< index_t > numNodes(const gsBasis< T > &basis, const Real quA, const index_t quB, short_t fixDir=-1)
Definition: gsQuadrature.h:152
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
virtual void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const =0
Evaluate the function at points u into result.
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
Class for representing a knot vector.
Definition: gsKnotVector.h:79
int degree() const
Returns the degree of the knot vector.
Definition: gsKnotVector.hpp:700
unsigned factorial(unsigned n)
Returns the factorial of n i.e. n! Remember that factorial grow too fast and only n! with n&lt;=13 can b...
Definition: gsCombinatorics.h:29
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78