I have been looking at how to interpolate a function using Chebyshev polynomials. There are several good posts such as this one by Michael E2 and this one by J. M. There is also an example in the help for FourierDCT
. By studying these posts I have assembled a module that does interpolation of a function.
ClearAll[ChebInterpolation];
ChebInterpolation::usage =
"ChebInterpolation[f,{xmin,xmax},prec,n] developes an interpolation \
of the function f in the interval [xmin, xmax] based on n Chebyshev \
functions calculated with a precision prec. f must be a pure \
function. ";
ChebInterpolation[f_, {xmin_, xmax_}, prec_, n_] :=
Module[{nodes, coeff, c},
nodes =
Rescale[N[Cos[Pi Range[0, n]/n], prec], {-1, 1}, {xmin, xmax}];
coeff = Sqrt[2/n] FourierDCT[f /@ nodes, 1];
coeff[[{1, -1}]] /= 2;
c = Compile[{x},
coeff.Table[Cos[(m - 1) ArcCos[x]], {m, Length@coeff}]];
With[{w = c}, w[Rescale[#, {xmin, xmax}, {-1, 1}]] &]
]
With this module I have to supply a precision (prec) and the number of Chebyshev polynomials (n) to use. My question is how to automate finding these two parameters.
I use the module like this. First define a function and the interval within which it will be approximated.
f = BesselJ[1, #^(3/2)] Sin[#] &;
{xmin, xmax} = {25, 35};
Plot[f[x], {x, xmin, xmax}]
Now we run the module to calculate the interpolation function and plot the result.
fint = ChebInterpolation[f, {xmin, xmax}, 25, 85];
Plot[fint[x], {x, xmin, xmax}]
The plot looks very similar and to check the accuracy we can look at the error
Plot[fint[x] - f[x], {x, xmin, xmax}, WorkingPrecision -> 100,
PlotRange -> All, PlotPoints -> 100]
As can be seen the error is small. The parameters in the interpolation were a precision of 25 and 85 Chebyshev polynomials. I used these values by looking at various alternatives. The following calculation determines the log of the RMS error between the exact function and the approximate function for a range of precisions and number of polynomials.
errs = Table[fint = ChebInterpolation[f, {xmin, xmax}, prec, n];
e = Table[fint[x] - f[x], {x, xmin, xmax, (xmax - xmin)/100}];
{prec, n, Log[10, RootMeanSquare[e]]},
{n, 65, 100}, {prec, 16, 32}];
ListPlot3D[Flatten[errs, 1], PlotRange -> All,
AxesLabel -> {"Precision", "No of Chebs.",
"\!\(\*SubscriptBox[\(Log\), \(10\)]\) RMS Error"}]
A floor is reached when the precision is about 25 and the number of polynomials is 85.
Question 1: Is my module a good approach or can it be improved?
Question 2: Is looking at the errors in the above plot a robust way of finding the required precision and number of polynomials? If yes, what would be a good way of automating this?