Piecewise linear interpolation has many good properties. In
particular, if the data come from a continuously differentiable
function
and if the data points are suitably spread throughout
the closed interval, then the interpolant converges to the function.
The resulting interpolant consists of straight line segments and so
has flats and kinks in it, making it inappropriate for many applications.
In this lab we will look at one example of piecewise polynomial interpolation that has curved pieces with continuous derivatives from patch to patch. You have seen spline interpolation, but we will be looking at piecewise Hermite cubic interpolation. We will apply this method first to parametric curves and then to two-dimensional patches. The two-dimensional case is useful because of applications to mesh generation for solving partial differential equations.
This lab will take three sessions. If you print this lab, you may prefer to use the pdf version.
You are familiar with a parameterized
curve, in which a special variable, typically called
, is
used to draw objects for which the relationship between
and
is not functional. One good definition of a circle is:
Suppose we wanted to do interpolation of some complicated curve? If we have a drawing of the curve, we could simply mark points along the curve that are roughly evenly spaced, and make tables of tdata, xdata and ydata, where the values of tdata could be 1, 2, 3, ....
Now if we want to compute intermediate points on the curve, that's really saying, for a given value of tdata, what would the corresponding values of xdata and ydata be? This means doing two interpolation problems, one for xdata as a function of tdata and the second for ydata as a function of tdata.
You may recall that
a cardiod is a roughly heart-shaped closed curve, but it has no sharp point
at the bottom. You can find a nice description of cardioid curves
with various ways of defining them at
http://mathworld.wolfram.com/Cardioid.html
One cardiod can be given by the equations
% generate the data points for a cardioid ndata = 21; tdata = linspace ( 0, 2*pi, ndata ); r = 0.5 + cos ( tdata ); % equation for a cardioid xdata = r .* cos ( tdata ); ydata = r .* sin ( tdata ); % interpolate them tval = linspace ( 0, 2*pi, 10*ndata ); xval = eval_plin ( tdata, xdata, tval ); yval = eval_plin ( tdata, ydata, tval ); % plot them with correct aspect ratio plot ( xval, yval ) axis equalYou do not need to send me this plot.
You can see that the plot of the cardioid in Exercise 1 is not very smooth. This is because the line segments are straiaght lines that meet at corners. In the following section you will see one way of interpolating curves using curved sections whose derivatives are continuous so that there are no corners.
Hermite interpolation is discussed in Atkinson, Section 3.6.
If we were trying to design, say, the shape of the sheet metal pattern for a car door, kinks and corners would not be acceptable. If that's a problem, then perhaps we could try to make sure that our interpolant is smoother and simpler by matching both the function value and the derivative at each point. (This assumes you can get the derivative value.)
Suppose we have points
,
and a differentiable
function
, so that the values
and
can be regarded as data points.
Now consider the situation in the
interval,
. There is just one cubic
polynomial on this interval that has the
appropriate function and derivative values at the two endpoints.
You may recall the Lagrange interpolation polynomials from Lab 6. Their
claim to fame is that on the interval
there are two special
linear polynomials: one that is 1 at
and zero at
, and the other
is 1 at
and zero at
. This feature makes it easy to
construct an arbitrary linear polynomial that matches given values
at the endpoints. We want to match both the function and
derivative values at the endpoints, so we will need cubic Hermite polynomials.
Consder the four Hermite polynomials
![]() |
|||
![]() |
|||
![]() |
|||
![]() |
Given these four polynomials, the unique polynomial with the values
We are now in a position to write a piecewise Hermite interpolation
routine. This routine will be similar to eval_plin.m.
eval_herm.m with the
signature
function yval = eval_herm ( xdata, ydata, ypdata, xval )and insert comments. the values in
ypdata are the derivative values at the points xdata.
bracket function to find the interval
in which xval lies. As in eval_plin.m, this can be done
in a single line.
Now, we will use eval_herm.m to see how piecewise Hermite converges.
runge.m so that it returns
both the Runge function
function [y,yprime]= runge ( x ) % commentsand it should have appropriate comments. Do not forget to use componentwise syntax.
test_piece_interpolate.m function from last lab,
or download my version. Rename
it to test_piece_hermite.m and modify it to use eval_herm.m.
Runge function, Piecewise Hermite Cubic ndata = 5 Err( 5) = ________ ndata = 11 Err( 11) = ________ Err( 5)/Err( 11) = ________ ndata = 21 Err( 21) = ________ Err( 11)/Err( 21) = ________ ndata = 41 Err( 41) = ________ Err( 21)/Err( 41) = ________ ndata = 81 Err( 81) = ________ Err( 41)/Err( 81) = ________ ndata =161 Err(161) = ________ Err( 81)/Err(161) = ________ ndata =321 Err(321) = ________ Err(161)/Err(321) = ________ ndata =641 Err(641) = ________ Err(321)/Err(641) = ________
Err(41)/Err(81), etc., and estimating
the nearest power of two. You should observe the theoretical convergence
rate, which is larger than 2.
Now, you are in a position to apply Hermite interpolation to generate a very smooth cardioid.
In order to solve a partial differential equation, the region over which it is to be solved must be broken into small pieces. These pieces are often called ``mesh elements,'' and the process of generating them for arbitrary regions is called ``mesh generation.'' You can see some examples of complicated meshes at http://www.geuz.org/gmsh/gallery/spirale.gif The process of building the outline of a complicated assembly and then using it to generate a mesh is very labor-intensive and can take weeks. The discussion in this lab is most relevant to generation of quadrilateral and hexahedral meshes, not triangular or tetrahedral meshes.
The lowest-level activity in generating meshes in many commercial packages is defining ``Coons Patches.'' These are two- or three-dimensional geometrical entities that can, on the one hand, be combined together smoothly, and, on the other hand, easily divided into mesh elements. These Coons Patches are generally built using bicubic Hermite polynomials in two dimensions, and tricubic Hermite polynomials in three dimensions. We will be focussing on two dimensions in this lab.
Coons patches are also used in computer graphics, but I am not familiar enough with this application to discuss it.
One approach to generating two-dimensional meshes is to take a drawing of the object and cover it with reasonably large patches with four curved sides. These patches generally are chosen to match up (to a reasonable approximation) with the boundaries of the object and fit against each other and are no smaller than necessary for these tasks. Once all the object in the drawing is completely covered with patches, the patches themselves are broken into smaller mesh pieces. It is important that the mesh lines do not undergo abrupt changes across patch boundaries and it is also important that the user be able to modify the density of mesh lines and to concentrate them near, for example, one boundary. Commercial programs such as Patran and Ansys use this approach.
A two-dimensional bicubic Hermite patch is a smooth map from
the unit square
to a region
.
This mapping is a cubic polynomial in
for each fixed
and
a cubic polynomial in
for each fixed
. A similar definition
holds for a two-dimensional patch on a surface in
, with an
additional function
.
Consider the following sketch.
Among these sixteen data, there is enough information to construct the
boundary curve AB parametrically using Hermite polynomials for
and
, where
is the indepentent variable
increasing from point A to point B. This interpolation can be done
using the eval_herm.m function you wrote earlier. Similarly,
the curve DC can be constructed using Hermite polynomials to give
and
. Lines of constant
, such as the line EF,
can be constructed using the curves AB and DC. The result will be the
parametric coordinate functions
and
for all
. This is the approach taken in the
following exercise.
In the next exercise you will write a script m-file that fills a square with smaller squares. This is a special case of mesh generateion. In doing this exercise, we will not use any special facts about squares, but will be writing as if the lines were curved. In subsequent exercises, we will see what meshes with curved lines look like.
The four corners, A, B, C, and D, each require data for
and
regarded as functions of
and
. The data are
|
|
|
|
|
|
|
|
|
Hints:
% Generate a mesh based on Hermite bicubic interpolation
% values for point A
xA = 0; yA = 0;
dxdsA = 1; dydsA = 0;
dxdtA = 0; dydtA = 1;
d2xdsdtA = 0; d2ydsdtA = 0;
% values for point B
xB = 1; yB = 0;
dxdsB = ??? dydsB = ???
dxdtB = 0; dydtB = 1;
d2xdsdtB = 0; d2ydsdtB = 0;
% values for point C
xC = 1; yC = 1;
dxdsC = 1; dydsC = 0;
dxdtC = ??? dydtC = ???
d2xdsdtC = 0; d2ydsdtC = 0;
% values for point D
xD = 0; yD = 1;
dxdsD = 1; dydsD = 0;
dxdtD = 0; dydtD = 1;
d2xdsdtD = ??? d2ydsdtD = ???
% Start off with 5 points horizontally,
% and 3 points vertically
s=linspace(0,1,5);
t=linspace(0,1,3);
% interpolate x along bottom and top, function of s
xAB =eval_herm([0,1],[xA,xB] ,[dxdsA,dxdsB], s);
dxdtAB=eval_herm([0,1],[dxdtA,dxdtB],[d2xdsdtA,d2xdsdtB],s);
xDC =???
dxdtDC=???
% interpolate y along bottom and top, function of s
yAB =???
dydtAB=???
yDC =???
dydtDC=eval_herm([0,1],[dydtD,dydtC],[d2ydsdtD,d2ydsdtC],s);
% interpolate s-interpolations in t-direction
% if variables x and y already exist, they might have
% the wrong dimensions. Get rid of them before reusing them.
clear x y
for k=1:length(s)
x(k,:)=eval_herm([0,1],[xAB(k),xDC(k)],[dxdtAB(k),dxdtDC(k)],t);
y(k,:)=???
end
% plot all lines
axis('square');
plot(x(:,1),y(:,1),'b')
hold on
for k=2:length(t)
plot(x(:,k),y(:,k),'b')
end
for k=1:length(s)
plot(x(k,:),y(k,:),'b')
end
hold off
Just because you can correctly generate a straight-line mesh does not mean your code is correct. In the next exercise, you are going to continue debugging your Matlab programming by testing with two more difficult shapes.
Why should we have used parametric interpolation?
Once you have the outline of a patch specified, it is possible
to change the distribution of the internal mesh lines by
changing the parameters (
and
). So long as they
vary smoothly and map onto the square
, they
are essentially arbitrary.
So far, you have not seen any good reason for using Hermite cubic interpolation over any other method. There really is a good reason for this choice, namely, that two patches can be placed adjacent to each other and, if the derivatives at the endpoints of the common side are given the same values, the mesh will be smooth across the boundary. In the following exercise, there are two patches that touch along one edge. Consider the following sketch.
| Point | Coordinates |
| A | |
| B |
|
| C | |
| D | |
| a | |
| b | |
| c | |
| d |
|
% Generate a mesh for the patch ABCD sqrt2on2=sqrt(2)/2; % values for point A xA = 0; yA = 1; dxdsA = 1; dydsA = 0; dxdtA = 0; dydtA = 1; d2xdsdtA = 0; d2ydsdtA = 0; % values for point B xB = sqrt2on2; yB = sqrt2on2; dxdsB = sqrt2on2; dydsB = -sqrt2on2; dxdtB = sqrt2on2; dydtB = sqrt2on2; d2xdsdtB = 0; d2ydsdtB = 0; % values for point C xC = 2; yC = 2; dxdsC = 2; dydsC = 0; dxdtC = sqrt2on2; dydtC = sqrt2on2; d2xdsdtC = 0; d2ydsdtC = 0; % values for point D xD = 0; yD = 2; dxdsD = 2; dydsD = 0; dxdtD = 0; dydtD = 1; d2xdsdtD = 0; d2ydsdtD = 0;
Back to MATH2070 page.