|
| 1 | +import numpy as np |
| 2 | +from numpy.linalg import solve |
| 3 | +from numpy.polynomial import polynomial as P |
| 4 | + |
| 5 | +def vanderpoly(xp,yp): |
| 6 | + """ |
| 7 | + Vandermonde Polynomial Interpolator |
| 8 | + |
| 9 | + Interpolate sets of datapoints using polynomials in the Vandermonde basis. The resulting |
| 10 | + polynomial and its derivatives and antiderivatives is efficiently evaluated using |
| 11 | + recursive horner's rule. |
| 12 | + |
| 13 | + Parameters |
| 14 | + -------- |
| 15 | + xp : array_like, shape(n,) |
| 16 | + 1-D array containing values of the independent variable. Values don't have to be |
| 17 | + in strictly increasing order since they are sorted internally along with the |
| 18 | + corresponding values of the dependent variable. However, the values must be real |
| 19 | + and finite for there to be sensible results. |
| 20 | + |
| 21 | + For numerical stability, the values of the independent variable are linearly mapped to the |
| 22 | + interval [-1,1]. The inputs to the resulting polynomial output function are also similarly |
| 23 | + transformed. The constant 2/(b-a), raised to the power of k, is multiplied to the output |
| 24 | + to obtain the correct value of interpolator in the original xp domain. a and b are the |
| 25 | + left and right endpoints of the interval, respectively, while k is the order of the |
| 26 | + desired derivative/antiderivative. |
| 27 | + |
| 28 | + yp: array_like, shape(n,) or shape(n,m) |
| 29 | + 1-D or 2-D array containing values of the independent variable. Values must be real |
| 30 | + and finite. For complex values, simply seperate into real and imaginary parts and |
| 31 | + then interpolate as usual. |
| 32 | + |
| 33 | + |
| 34 | + Returns |
| 35 | + -------- |
| 36 | + P : callable |
| 37 | + Function evaluating the polynomial interpolator and its derivatives and anti-derivatives. |
| 38 | + """ |
| 39 | + xp = np.asfarray(xp) |
| 40 | + yp = np.asfarray(yp) |
| 41 | + idx = np.argsort(xp) |
| 42 | + xp = xp[idx] |
| 43 | + yp = yp[idx] |
| 44 | + |
| 45 | + a, b = xp[[0,-1]] |
| 46 | + du_dx = 2/(b-a) |
| 47 | + up = du_dx*(xp-a)-1 |
| 48 | + |
| 49 | + p = np.arange(up.size).astype(float) |
| 50 | + UP, PP = np.meshgrid(up, p, indexing='ij') |
| 51 | + V = UP ** PP |
| 52 | + coeff = solve(V,yp) |
| 53 | + |
| 54 | + def Pfun(x,m=0, k=[], lbnd=0): |
| 55 | + u = du_dx*(x-a)-1 |
| 56 | + if m==0: |
| 57 | + val = P.polyval(u, coeff) |
| 58 | + elif m>0: |
| 59 | + val = P.polyval(u, P.polyder(coeff, m, du_dx)) |
| 60 | + else: |
| 61 | + val = P.polyval(u, P.polyint(coeff, abs(m), k, lbnd, 1/du_dx)) |
| 62 | + return val |
| 63 | + return Pfun |
0 commit comments