Search code examples
matlabnumerical-methods

Interpolation using chebyshev points


Interpolate the Runge function of Example 10.6 at Chebyshev points for n from 10 to 170 in increments of 10. Calculate the maximum interpolation error on the uniform evaluation mesh x = -1:.001:1 and plot the error vs. polynomial degree as in Figure 10.8 using semilogy. Observe spectral accuracy.

The runge function is given by: f(x) = 1 / (1 + 25x^2)

My code so far:

x = -1:0.001:1;
n = 170;
i = 10:10:170;
cx = cos(((2*i + 1)/(2*(n+1)))*pi); %chebyshev pts

y = 1 ./ (1 + 25*x.^2); %true fct
%chebyshev polynomial, don't know how to construct using matlab

yc = polyval(c, x); %graph of approx polynomial fct
plot(x, yc);
mErr =  (1 / ((2.^n).*(n+1)!))*%n+1 derivative of f evaluated at max x in [-1,1], not sure how to do this
%plotting stuff

I know very little matlab, so I am struggling on creating the interpolating polynomial. I did some google work, but I was confused with the current functions as I didn't find one that just simply took in points and the polynomial to be interpolated. I am also a bit confused in this case of whether I should be doing i = 0:1:n and n=10:10:170 or if n is fixed here. Any help is appreciated, thank you


Solution

  • Since you know very little about MATLAB, I will try explain everything step by step:

    First, to visualize the Runge function, you can type:

    f = @(x) 1./(1+25*x.^2); % Runge function
    
    % plot Runge function over [-1,1];
    x = -1:1e-3:1;
    y = f(x);
    figure;
    plot(x,y); title('Runge function)'); xlabel('x');ylabel('y');
    

    enter image description here

    The @(x) part of the code is a function handle, a very useful feature of MATLAB. Notice the function is properly vecotrized, so it can receive as an argument a variable or an array. The plot function is straightforward.

    To understand the Runge phenomenon, consider a linearly spaced vector of [-1,1] of 10 elements and use these points to obtain the interpolating (Lagrange) polynomial. You get the following:

    % 10 linearly spaced points
    xc = linspace(-1,1,10);
    yc = f(xc);
    p = polyfit(xc,yc,9); % gives the coefficients of the polynomial of degree 10
    hold on; plot(xc,yc,'o',x,polyval(p,x)); 
    

    enter image description here

    The polyfit function does a polynomial curve fitting - it obtains the coefficients of the interpolating polynomial, given the poins x,y and the degree of the polynomial n. You can easily evaluate the polynomial at other points with the polyval function.

    Obseve that, close to the end domains, you get an oscilatting polynomial and the interpolation is not a good approximation of the function. As a matter of fact, you can plot the absolute error, comparing the value of the function f(x) and the interpolating polynomial p(x):

    plot(x,abs(y-polyval(p,x))); xlabel('x');ylabel('|f(x)-p(x)|');title('Error');
    

    enter image description here

    This error can be reduced if, instead of using a linearly space vector, you use other points to do the interpolation. A good choice is to use the Chebyshev nodes, which should reduce the error. As a matter of fact, notice that:

    % find 10 Chebyshev nodes and mark them on the plot
    n = 10;
    k = 1:10; % iterator
    xc = cos((2*k-1)/2/n*pi); % Chebyshev nodes
    yc = f(xc); % function evaluated at Chebyshev nodes
    hold on;
    plot(xc,yc,'o')
    
    % find polynomial to interpolate data using the Chebyshev nodes
    p = polyfit(xc,yc,n-1); % gives the coefficients of the polynomial of degree 10
    plot(x,polyval(p,x),'--'); % plot polynomial
    legend('Runge function','Chebyshev nodes','interpolating polynomial','location','best')
    

    enter image description here

    Notice how the error is reduced close to the end domains. You don't get now that high oscillatory behaviour of the interpolating polynomial. If you plot the error, you will observe:

    plot(x,abs(y-polyval(p,x))); xlabel('x');ylabel('|f(x)-p(x)|');title('Error');
    

    enter image description here

    If, now, you change the number of Chebyshev nodes, you will get an even better approximation. A little modification on the code lets you run it again for different numbers of nodes. You can store the maximum error and plot it as a function of the number of nodes:

    n=1:20; % number of nodes
    
    % pre-allocation for speed
    e_ln = zeros(1,length(n)); % error for the linearly spaced interpolation
    e_cn = zeros(1,length(n)); % error for the chebyshev nodes interpolation
    
    for ii=1:length(n)
        % linearly spaced vector
        x_ln = linspace(-1,1,n(ii)); y_ln = f(x_ln);
        p_ln = polyfit(x_ln,y_ln,n(ii)-1);
        e_ln(ii) = max( abs( y-polyval(p_ln,x) ) );
    
        % Chebyshev nodes
        k = 1:n(ii); x_cn = cos((2*k-1)/2/n(ii)*pi); y_cn = f(x_cn);
        p_cn = polyfit(x_cn,y_cn,n(ii)-1);
        e_cn(ii) = max( abs( y-polyval(p_cn,x) ) );
    end
    figure
    plot(n,e_ln,n,e_cn);
    xlabel('no of points'); ylabel('maximum absolute error');
    legend('linearly space','chebyshev nodes','location','best')
    

    enter image description here