Search code examples
matlabcurve-fittingextrapolationcubic-spline

Clampled cubic splines with flat extrapolation


I am trying to implement a clamped cubic spline with a zero slope (flat extrapolation) at the boundary knots, but I am unable to obtain the desired results.

For instance setting:

x = [3 4 7 9];
y = [2 1 2 0.5];

I can use the CSAPE function to obtain the piecewise polynomial

pp = csape(x,y,'variational');

Next, evaluating the pp in the range [0-10] yields,

xx = 0:0.1:10;
yy =ppval(pp,xx);
plot(xx,yy) 

enter image description here

However, this method do not achieve a flat extrapolation outside the [3-9] range (i.e for x<3 all values for y should be 2, and for x>9 all values for y should be 0.5)

Is there any way to achieve the desired result?

Edit: Continuity at the boundary knot should be preserved


Solution

  • I don't think there's any need to use csape, you can just use spline. From the documentation for spline:

    If Y is a vector that contains two more values than x has entries, the first and last value in Y are used as the endslopes for the cubic spline.

    Also, spline allows you to obtain the interpolated yy values directly, so:

    x = [3 4 7 9];
    y = [2 1 2 0.5];
    xx = 0:0.1:10;
    yy = spline(x,[0 y 0], xx);
    plot(xx,yy)
    

    This gives me the plot below.

    Spline Plot

    Looking at this, the slope is zero at the boundaries (x=3 and x=9), which is what we are asking of a 'clamped' spline with zero gradient at the boundaries. If you wish to have zero gradient beyond the boundaries, I would recommend just doing the following:

    yy(xx<x(1)) = y(1);
    yy(xx>x(length(x))) = y(length(y));
    

    Giving:

    enter image description here

    Edit

    This gives a continuous y function at the end-knots, but y' is not smooth at the end-knots. If you would like y' to be smooth you could pad your input arrays and use this as the input to your spline function. This would give you some oscillations as shown below, though, which may or may not be what you want.

    % Spline on padded input arrays
    x = [0 1 2 3 4 7 9 10 11 12];
    y = [2 2 2 2 1 2 0.5 0.5 0.5 0.5];
    yy = spline(x,y, xx);
    

    enter image description here