FEEG1001 Applied Computing
FEEG1001 Applied Computing
Mechanical Engineering
Alexander I J Forrester
Contents
1 Computational Definition of Curves
1.1 Lecture 1: Conics and Bezier curves . . . . . . . . .
1.1.1 Parametric Bernstein Conic . . . . . . . . . .
1.2 Lecture 2: rational conics, Bezier curves and splines
1.2.1 Properties of Bezier curves . . . . . . . . . .
1.2.2 Splines . . . . . . . . . . . . . . . . . . . . . .
1.3 Lab 1: create a Bezier spline using Python . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
2
2
8
9
10
10
. . . . .
. . . . .
. . . . .
. . . . .
Python
. . . . .
. . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
19
19
20
21
22
23
25
26
27
29
29
30
a (0 )
a (1 )
a (2 )
1
1.1
The classical, and initially intuitive, definition of conics is that of a plane intersecting a cone, with the angle of intersection determining the shape. Here we
hope to give more insight and intuition, particularly when considering parametric conics and then on to NURBS, by using the projective geometry definition.
We will only cover the essentials of projective geometry
Figure 1 shows a conic as the intersection of lines. The conic is defined by two
tangent lines, here through a(0) , a(1) and a(2) , a(1) (but could easily be any two of
the lines shown), and a third shoulder tangent (shown in bold). Described in this
way, the conic is a mapping or projectivity between the two tangent lines, with
this projectivity defining the shoulder tangent. The following sections cover this
projective geometry construction of conics, before moving on to Bezier cures,
splines, B-splines and NURBS. We will skip some of the intricacies of projective
geometry and the reader wanting more on in this area may wish to refer to
[Farin, 1999].
Studies on conics date back to Menaechmus (380-320 BC) [Thomas, 1939].
Conics are found in astronomy, palaeontology, aerodynamic design (see figure
2) where P-51 designer Edgar Schmued called second degree conics the shape
the air likes to touch and, indeed, many areas of everyday life (see figure 3).
1.1.1
Figure 2: a conic-based jet nozzle design for an unmanned air vehicle (provided
by Andr
as S
obester).
Figure 3: a BMX ramp with a conic profile marked-out by hand using the same
construction by projectivities as in figure 1.
a (0 )
t (1 )
s (1 )
t
(3 )
s (3 )
a (1 )
s (2 )
a (2 )
t (2 )
1 (0) 1 (1)
a + a
2
2
(1)
s(2) =
1 (1) 1 (2)
a + a .
2
2
(2)
and
A point on the conic, which we will call C, in figure 4 shall be found as the
intersection of a tangent, T(t), with the conic (t is a parameter that we vary so
that t(3) (the intersection of T with the conic) traces out, i.e. moves along the
along the conic). The intersection of T with A is
t(1) = (1
t)a(0) + ta(1) ,
(3)
t(2) = (1
t)a(1) + ta(2) .
(4)
and with B is
This intuitive result is derived in Farin [1999] using the four tangent theorem
(which is also employed below). Thus as t varies from 0 to 1, the intersection
t(3) traces out the conic from a(0) to a(2) (the whole conic is traced out by
1 < t < 1).
Looking at figure 4, by bringing t(1) to a(1) , i.e. setting t = 0, we see that
the intersection of S and T,
s(3) =
1 (1) 1 (2)
t + t .
2
2
4
(5)
We now have enough information to find any point on the conic t(3) (t), but
will need to invoke the four tangent theorem. Four tangents to a conic (e.g.
A, B, S and T in figure 4) each have an intersection with the conic and three
intersections with the other three tangents. The four tangent theorem states
that the cross ratio of these four intersections equals the same constant for all
four tangents.
In general, given four points on a line, such that
a(3) = 1 a(1) +
1a
(2)
a(4) = 2 a(1) +
(2)
,
2a
and
(6)
1/2 t
t
=
1/2 1 t
1 t
(7)
(8)
Using 6 and 8,
cr(t(1) , t(3) , s(3) , t(2) ) =
1/2 t
.
1/2 1 t
(9)
And so:
t(3) (t) = (1
(10)
Substituting 3 and 4 into 10 , we find that the point on the conic, C(t) is a
quadratic with coefficients based on our original points in figure 4:
C(t) = t(3) (t) = (1
t)a(1) + t2 a(2) .
2
bi,2 (t) =
ti (1 t)2 i , i = 0, 1, 2,
i
where the binomial coefficient
2
i
2!
,
i!(2 i)!
(11)
(12)
0.9
0.8
b 0 ,2( t)
0.7
b 2 ,2( t)
b i , 2( t)
0.6
b 1 ,2( t)
0.5
0.4
0.3
0.2
0.1
0
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
2
X
(13)
i=0
We see that the Bezier curve is a weighted sum of the control points, a(i) . The
influence of these control points, which is determined by their weighting bi,2 (t),
should be greatest when the curve passes closest to them and this influence
should diminish as the curve moves away. For example, bi,2 (t) should reach
a maximum when t = 0.5 and bi,2 (t) ! 0 as t ! 1. Figure 5 shows the
Bernstein polyniomial weightings (equation 12) used by the Bezier curve.
It is possible to add further control points to the sum in equation 13, weighted
using higher degree Bernstein polynomials:
n!
n
n
i
n i
bi,n (t) =
t (1 t) , where
=
,
(14)
i
i
i!(n i)!
which are shown in figure 6. Figure 7 demonstrates this by inserting a control
point in to the definition of the quadratic Bezier curve in figure 4 to produce a
cubic Bezier curve:
B(t)
3
X
i=0
3
X
i=0
(1
a(i)
3
i
ti (1
t)3
t)a(2) + t3 a(3) .
(15)
0.9
0.8
b 0 , 3( t)
0.7
b 3 , 3( t)
b i , 2( t)
0.6
b 1 ,3( t)
0.5
b 2 , 3( t)
0.4
0.3
0.2
0.1
0
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
This is a rather nave implementation, which only works with four control
points. A generic Bezier curve could be produce by using the function for the
binomial coefficient in listing 2.
Listing 2: Python code to calculate the binomial coefficient
def binom ( n , i ) :
i f 0 <= i <= n :
a (0 )
a (1 )
a (2 )
a (3 )
1.2
While the use of projective geometry to define conics is elegant and intuitive,
it is unsuitable for design purposes. We can project onto the the plane z = 1
(an affine plane), simply by dividing the projective points through by the zcomponent (the figures in the previous sections are in this plane):
0 IP IP 1
ax /az
aIP
ax
a=
= IP = @ aIyP /aIzP A ,
ay
az
aIzP /aIzP
where here we use IP to denote a point in projective space. Equation 11 can
now be written as a rational form as
C(t) =
(1
(16)
a (0 )
z (1 ) = 0
0.25
0.5
1
2
5
z (1 ) = 100
a (1 )
a (2 )
where wi are the weights. Figure 4 has all weights set at unity. Figure 8 shows
the eect of varying z (1) , with z (0) , z (2) = 1. The eect is intuitive; for z (1) = 0,
C becomes a straight line from a(0) to a(2) and as z (1) ! 1, C(t) tends to the
line a(0) , a(1) , a(2) .
For the remainder of this chapter we will consider rational curves defined by
x, y coordinates of points and weightings.
1.2.1
Properties of B
ezier curves
The above derivation of a conic and so Bezier curve has lead to an intuitive form
of curve, which can be pushed and pulled around by control points. Salomon
[2006] lists a number of properties of Bezier curves (and discusses them in more
detail than we shall do here), which help in understanding their usefulness in
geometry definition and manipulation:
the weights, bi,n (t) add up to 1 (they are barycentric),
the curve passes through the two endpoints a(0) and a(n) ,
the curve is symmetric with respect to the numbering of control points, i.e.
the same result will be obtained by setting a(0) = a(n) , a(1) = a(n 1) , ..., a(n) =
a(0) ,
a(t)
=n
n
X1
a(i) bi,n
1 (t),
where
a(i) = a(i+1)
a(i) ,
(18)
the weight functions bi,n have a maximum at t = i/n, that is the influence
of the control points is spaced evenly with respect to t,
a(1)
= n(a
a
), are easily controlled by moving a and a(n 1)
respectively,
the Bezier curve is controlled globally by editing control point(s) and
weighting(s), that is changing one control point will aect the entire curve
(note how in figures 5 and 6 the weighting of each point has an influence
over all values of t), with the aect greatest close to the control point,
the curve is contained within the control polygon (within its convex hull ),
as seen in figure 7, where the curve lies within the triangle formed by
a(0) , a(1) , a(2) and then that formed by a(1) , a(2) , a(3) , and
the curve is invariant to affine transformations, e.g. can be shifted up/down, left/right, rotated, reflected (but is not invariant under projections).
1.2.2
Splines
1.3
Lab 1: create a B
ezier spline using Python
q (2 )
p (1 )
p (2 ) = q (0 )
q (1 )
p (0 )
q (2 )
q
p
(3 )
=q
(1 )
(0 )
p (1 )
p (0 ), q (3 )
p (2 )
11
1.5]])
[ [ 0 . 0. ] [ 0.03910797 0.02000198]
...
[ 0.01970397 1.51910798] [ 0 . 1.5 ] ]
You can tackle this code writing problem by modifying the code in listing
1, which implements the last line of equation 15. Instead of explicitly
coding this cubic Bezier equation, you first need to code it as a sum of
four terms using the binom function, i.e. as in the second line of equation
15. Use a for loop followed by sum to do this. Next make you code handle
any number of control points by using n+1 instead of four terms. Finally,
make points an input to the function, rather than have the control points
hard-coded as in listing1 (where the array a is the control points).
A function rational bezier(points, weights) that creates a rational
cubic Bezier, with n control points with n weights in the input arrays
points and weights, returns a 1012 array of x, y points on the curve for
t[0, 1] and plots the curve, control points and control polygon. Example:
>>> p o i n t s = a r r a y ( [ [ 0 , 0 ] , [ 1 , 0 . 5 ] , [ 0 . 5 , 1 ] , [ 0 . 5 , 2 ] , [ 0 ,
>>> w e i g h t s = a r r a y ( [ 1 , 1 0 , 5 , 1 5 , 1 ] )
>>> p r i n t r a t i o n a l b e z i e r ( p o i n t s , w e i g h t s )
12
1.5]])
0.
0.28824076
0.
]
0.14582872]
0.18929222
0.
1.68733879]
1.5
]]
2.1
XFOIL is an interactive program for the design and analysis of subsonic isolated
airfoils [Drela, 1989]. It combines the speed and accuracy of high-order panel
methods with a fully-coupled viscous boundary layer method [Drela and Giles,
1987]. Here we will consider XFOIL as a black-box analysis method and use it to
understand geometry manipulation, linking computer codes, and optimisation,
i.e. we will use it, but not try to understand it (that would be part of a
aerodynamics and computational fluid dynamics module).
XFOIL can be found under Your School Software. Selecting XfoilP4
opens the DOS command prompt and the program can be run interactively
using a set of commands detailed in the user guide. A sample XFOIL session can
be found at http://web.mit.edu/drela/Public/web/xfoil/. Listing 3 is a sample
session that runs a viscous analysis of an aerofoil defined in aerofoil.dat. The
inputs work, line-by-line as follows:
load aerofoil coordinates form the aerofoil.dat file,
name this aerofoil CubicBez,
13
quit
14
quit
Listing 5 is an example of the polar.dat output file. The format of this file
is always the same, which is useful to know if you are going to interrogate it for
data. If the output file entered in XFOIL already exists, the pacc command in
listing 3 will fail. It is therefore best to use a new output file name or delete the
existing output file before XFOIL is run again.
Listing 5: sample Xfoil output file.
XFOIL
Version 6.97
C a l c u l a t e d p o l a r f o r : CubicBez
1 1 Reynolds number f i x e d
xtrf =
Mach =
alpha
3.699
2.1.1
1 . 0 0 0 ( top )
0.100
Re =
CL
1.2000
CD
0.00745
Mach number f i x e d
1 . 0 0 0 ( bottom )
1.398 e 6
Ncrit =
CDp
0.00290
CM
9.000
Top Xtr
Bot Xtr
0.4208
1.0000
0.1629
The aerofoil.dat file contains the x,y coordinates of the aerofoil in two columns
(x and y), with the coordinates starting at the trailing edge, running along the
lower surface to the leading edge, and back along the upper surface to the trailing edge. Assuming the coordinates are stored in the (1011) arrays lower and
upper, we can write these aerofoil coordinates in two ways: line-by-line using
the write function (listing 6) or, more succinctly, using the savetxt function
(listing 7). Note that in both cases the last element of the lower array is omitted
so that the leading edge point is not duplicated.
Listing 6: line-by-line writing of aerofoil coordinates.
d a t a f i l e = open ( f i l e p a t h + a e r o f o i l . dat , w )
15
f o r i in r a n g e ( 0 , 1 0 0 ) :
d a t a f i l e . w r i t e ( %f %f \ r %( l o w e r [ i , 0 ] , l o w e r [ i ,
#LINUX/OSX: d a t a f i l e . w r i t e (% f \ t%f \n %( l o w e r [ i , 0 ] ,
f o r i in r a n g e ( 0 , 1 0 1 ) :
d a t a f i l e . w r i t e ( %f %f \ r %(upper [ i , 0 ] , upper [ i ,
#LINUX/OSX: d a t a f i l e . w r i t e (% f \ t%f \n %(upper [ i , 0 ] ,
data file . close ()
1]))
lower [ i , 1 ] ) )
1]))
upper [ i , 1 ] ) )
1 ] , upper ] ) )
While with the aerofoil.dat file we are writing columns of numbers from
which the shape of the aerofoil is not immediately apparent, the input file is
readable (at least to the trained eye) and we wish to preserve this in the Python
code via which we write it. In listing 8 the write function is used in a format
where the structure of the resulting file is apparent and the variable names, e.g.
Re for Reynolds number, are logical. Writing code in this way is not particularly
succinct, but is often preferable from a development perspective.
Listing 8: writing the commands.in file in Python in an easily identifiable format.
c o m m a n d f i l e=open ( f i l e p a t h + commands . i n , w )
c o m m a n d f i l e . w r i t e ( l o a d + f i l e p a t h + a e r o f o i l . dat \n\
CubicBez \n\
p a n e l \n\
o p e r \n\
v i s c + s t r ( Re ) + \n\
M + s t r (M) + \n\
t y p e 1\n\
pacc \n \
+ f i l e p a t h + p o l a r . dat \n\
\n\
i t e r \n 1000\ n\
c l 1 . 2 \ n\
\n\
\n\
q u i t \n )
command file . c l o s e ( )
2.1.2
System calls can be made from Python after importing os using os.system().
For example, assuming XfoilP4 is in C:\apps\XFOIL\ and commands.in and
aerofoil.dat are in C:\Users\aijf197\Documents\, an output similar to listing 5 could be produced with the code in listing 9. Note the use of double
backslashes in the file paths. This is because \ is a special character in Python
and needs to be escaped by adding the extra backslash. XFOIL needs to be able
to write to the directory defined by your file path. This might not be possible
for remote/shared drives, so it may be necessary to work in a local directory,
e.g. use the Documents folder and not My Documents. However,
16
make sure you copy your work across to My Documents or backup in some other way before you logout. Note that to run XFOIL using
os.system() on one of the University workstations, you need to first open and
close XFOIL from the start menu (you only need to do this once each time you
login to a new machine).
Listing 9: sample Python code to run XFOIL
import o s
f i l e p a t h = C: \ \ U s e r s \\ a i j f 1 9 7 \\ Documents \\
x f o i l p a t h = C: \ \ apps \\XFOIL\\
r u n x f o i l c o m m a n d = x f o i l p a t h + XFOIL < + f i l e p a t h + \
commands . i n
o s . system ( r u n x f o i l c o m m a n d )
Now we need to retrieve the results from polar.dat (listing 5), which can be
read using, for example, the Python readlines() function as shown in listing
11. Here we read all the lines of the file and then assign specific elements of the
last line to cl and cd. A command to delete the polar.dat file is included to
allow XFOIL to be run again in the same way if needed.
Listing 11: sample Python code to read results from polar.dat
a e r o d a t a f i l e = open ( f i l e p a t h + p o l a r . dat , r )
lines = aero data file . readlines ()
aero data file . close ()
#d e l e t e X f o i l o u t p u t f i l e r e a d y f o r n e x t X f o i l run
o s . system ( d e l + f i l e p a t h + p o l a r . dat )
#Linux /OSX: os . s yst e m ( rm f + f i l e p a t h + p o l a r . d a t )
cl = float ( lines [ 1][11: 17])
cd = f l o a t ( l i n e s [ 1 ] [ 2 0 : 2 7 ] )
2.2
17
(1.0, 0.0)
l(1)
l(2)
=
=
(0.5, 0.08)
(0.0, 0.05),
(20)
(0.0, 0.1)
u(2)
(0.4, 0.2)
u(3)
(1.0, 0.0).
(0,1,2,3)
(21)
(0,1,2,3)
0.000000
0.002337
0.022811
0.025000
0.027257
0.005910
0.000000
You already have the function rational bezier from aclab1.py to create
the upper and lower Bezier curves, but you need to find the leading edge
control point l(3) = u(0) by coding equation 19. With this point calculated,
rational bezier can be called to calculate the points on the upper and
lower curves and then these can be written to aerofoil.dat using, e.g.
listing 6.
A function run xfoil(file path, xfoil path) that runs XFOIL, reading in aerofoil.dat created by bezier spline aerofoil() and running
the viscous analysis using the commands in listing 3, reads and returns
CD and CL from polar.dat.
Example:
>>> p r i n t r u n x f o i l ( f i l e p a t h , x f o i l p a t h )
(0.00802 , 1.2)
18
Listings 8, 10 and 11, which will form the basis of your code, are provided
in a text file on Blackboard for your convenience.
If your function is not working, first try opening XFOIL from the start
menu and copy and paste the contents of commands.in (opened in notepad)
into the XFOIL command prompt line-by-line to check that your input
file is formatted correctly. Next check that polar.dat has been created
and contains Cl and CD values.
3
3.1
Optimization
Lecture 4: shape optimization
All areas of design are concerned with producing the best product in terms of
physical performance, cost, aesthetics, etc. Engineering design is, more formally,
the optimisation of performance criteria based on analyses. The performance
criteria will include profit margin and various fitness criteria such as weight,
stiness, cost to consumer, etc. The analyses could include cost modelling,
finite element analysis, wind-tunnel testing, consumer trials, etc. Indeed, a
major part of engineering design is identifying appropriate criteria and analyses
on which to base decisions.
We are going to design an aerofoil section for SUHPA (Southampton University Human Powered Aircraft, figure 13). We will conisider the section for the
six metre station (six metres out from the wing root). Here the chord is 0.698
m and the design speed for this aerofoil will be 12.5 m/s. Thus the constants
defined at the top of our functions that run XFOIL will look like:
a=340.3 #speed of sound
v=12.5 #velocity
M=v/a #Mach number
nu=0.00001461 #kinematic viscosity
L=0.698 #chord length of aircraft wing
Re=v*L/nu #Reynolds number
We will also need to define the lift coefficient, which at this location along
the wing is 0.843.
We will minimise the drag (known as the cost function, or objective function)
of an aerofoil for a fixed lift (our constraint function). We have one form of analysis: XFOIL. The optimum aerofoil is found through methodical changes to its
geometry based results from XFOIL according to some optimisation algorithm.
There are many optimisation algorithms. Indeed whole scientific communities
are devoted to their development. Algorithms include local methods such as
the Newton-Raphson method (which steps towards a local minimum, or saddle point, based on first and second derivatives of the objective function) and
quasi-Newton methods (e.g. Broyden-Fletcher-Goldfarb-Shanno, BFGS, where
second derivatives are not required). Global methods include those inspired by
nature like genetic algorithms and particle swarm. Each of these algorithms is
19
Figure 13: SUHPA in flight during the 2013 Icarus Cup at Sywell Aerodrome
(piloted by Guy Martin, photo by Fred To).
suited to dierent types of problems. We will examine the use of the Python
implementations of BFGS.
3.1.1
BFGS
SciPys scipy.optimize.fmin bfgs minimises a function using the BFGS algorithm. Information from the SciPy reference guide on the required input
parameters and outputs is given below.
The algorithm is called with:
scipy.optimize.fmin bfgs(f, x0, fprime=None, args=(), gtol=1e-05, norm=inf,
epsilon=1.4901161193847656e-08, maxiter=None, full output=0, disp=1,
retall=0, callback=None),
where the input parameters are:
f : callable f(x,*args). Objective function to be minimized.
x0 : ndarray. Initial guess.
fprime : callable f(x,*args), optional. Gradient of f.
args : tuple, optional. Extra arguments passed to f and fprime.
gtol : float, optional. Gradient norm must be less than gtol before successful termination.
norm : float, optional. Order of norm (Inf is max, -Inf is min)
epsilon : int or ndarray, optional. If fprime is approximated, use this value
for the step size.
20
L-BFGS-B
Here the L stands for limited memory, which means that this algorithm is
more efficient for large numbers of design variables and, more important to us,
21
the B stands for bounded, which means that bounds can be set on the design
variables. This is important as often geometry becomes physically unrealisable
or unsolvable outside of certain bounds on the design variables, resulting in simulation failures and so optimiser failure. SciPys scipy.optimize.fmin l bfgs b
is called in a similar way to scipy.optimize.fmin bfgs (or a maddeningly
slightly dierent way, depending on how you see things):
scipy.optimize.fmin l bfgs b(f, x0, fprime=None, args=(), approx grad=0,
bounds=None, m=10, factr=10000000.0, gtol=1e-05, epsilon=1e-08, iprint=-1,
maxfun=15000, disp=None)
The new parameters that concern us are:
approx grad : bool. Whether to approximate the gradient numerically (in
which case func returns only the function value).
bounds : list. (min, max) pairs for each element in x, defining the bounds
on that parameter. Use None for one of min or max when there is no bound in
that direction.
3.1.3
Further considerations
22
1]) ,\
file path = . . .
xfoil path = . . .
w array = l i n s p a c e ( 0 . 6 , 1 . 2 , 11)
figure (1)
cd = p a r a m e t e r s w e e p ( w array , 0 . 8 4 3 , f i l e p a t h , x f o i l p a t h )
s a v e f i g ( a e r o f o i l s . pdf )
# f i t moving l e a s t s q u a r e s
s i g m a b e s t = f s o l v e ( m l s e r r o r , 0 . 2 , a r g s = ( w array , cd ) )
w f i n e = l i n s p a c e ( 1 . 1 5 , 1 . 8 5 , 101)
y pred = zeros (101)
f o r i in r a n g e ( 0 , 1 0 1 ) :
y p r e d [ i ] = mls ( w f i n e [ i ] , w array , cd , s i g m a b e s t )
figure (2)
p y l a b . p l o t ( w array , cd , o , l a b e l = XFOIL data )
p l o t ( w f i n e , y p r e d , l a b e l = MLS f i t )
legend ()
x l a b e l ( w )
ylabel ( c d )
s a v e f i g ( parameter sweep . pdf )
3.2
Figure 14: aerofoil shapes (note scales are not equal) and a moving least squares
for to the XFOIL data, calculated in listing 12.
24
returns CD and CL from polar.dat. Use the SUHPA velocity and aerofoil
chord values.
Example:
>>> p r i n t r u n x f o i l w c l ( 1 . 1 , 0 . 8 4 3 3 , f i l e p a t h , x f o i l p a t h )
(0.00738 , 0.843)
0.00697
0.00669
0.00746
0.00759]
0.00655
0.0065
0.00681
0.00706
Add the code in lising 12 to plot a moving least squares fit to your XFOIL
data:
3.3
(1.0, 0.0)
(1)
(0.5, 0.08)
l(2)
(0.0, 0.05),
(22)
(0.0, 0.1)
u(2)
(0.4, 0.2)
u(3)
(1.0, 0.0).
Example:
>>> p r i n t o n e d i m o p t ( x0 , c l , f i l e p a t h , x f o i l p a t h )
Optimization terminated s u c c e s s f u l l y .
25
(23)
where x0 is the starting point for the optimiser, i.e. your best guess at
(2)
the optimum zu .
A function four dim opt(x0,weight limits,cl,file path,xfoil path)
(2) (3,) (2) (3)
which optimises the Bezier spline aerofoil weights zu , zu , zl , zl for
SUHPA using the scipy.optimize.fmin l bfgs b optimiser. Use the
above control points.
Example:
>>> p r i n t f o u r d i m o p t ( x0 , w e i g h t l i m i t s , c l , f i l e p a t h , x f o i l p a t h )
( array ( [ 1.3 ,
0.5 ,
0.5 ,
0 . 5 ] ) , 10 , 0)
The material in this section will not be assessed, but is included here to show
how your Python implemented geometry sits in context with the NURBS based
geometry of modern CAD engines.
1 If no upper and lower bounds are set, the optimiser may try to evaluate geometries that
cannot be solved in XFOIL. Wide bounds increase the search-space and so better designs
could be found, but failures are more likely. If XFOIL fails, shrink your bounds. Look at the
optimised values (stored in opt) to see if upper or lower bounds are being hit and expand your
bounds accordingly
26
a (0 )
a (1 )
a (3 )
a (4 )
a (2 )
Figure 15: a quadratic rational B-spline showing the vicinity of local control as
control point a(0) is shifted.
4.1
B-splines, where the B stands for basis, have a number of key characteristics
which may make them preferable to Bezier splines in many applications.
The degree of a B-spline is not determined by the number of control points.
Local control of the spline is possible (unlike Bezier splines where moving
one control point aects the whole spline).
The degree of continuity between segments can be specified.
Local control of the spline means that moving or changing the weight of a
control point will only aect the spline in the vicinity of this point. The extent
of this vicinity is determined by the degree of the B-spline. In figure 15 we
see that moving control point a(0) only aects the a degree two spline up until
midway between a(1) and a(3) (up until the end of the first segment).
A B-spline is made of n d segments, which we shall call B0 , B1 , ..., B(n d) ,
where n + 1 is the number of control points (remember these are numbered
from zero) and d is the degree of each segment (the degree of the B-spline).
The segments start and end at joints k(0) , k(1) , ..., k(n d+1) . Note that, unlike
a Bezier spline, the ends of the B-spline k(0) and k(n d+1) do not coincide with
the first and last control points. The exception to this is if there are multiple
control points: a degree d B-spline passes through a control point repeated d
times. For example if a(0) = a(1) , a degree 2 B-spline will start at the first
control point (the first segment will be a straight line towards a(2) ).
We will start by defining a uniform B-spline using control points and then
go on to interpolating B-splines, i.e. defined by the joint points, which may be
more practical in some situations.
27
Expressed in the same way as (??), the ith segment of a d-degree uniform
B-spline can be calculated as
0
1
a(i 1)
B
C
a(i)
B
C
Bi (t) = (td , td 1 , ..., t, 1)M(d) B
(24)
C
..
@
A
.
a(i+d 1)
where elements of the basis matrix M are given by
(d)
mi,j =
1
d!
n
i
X
d
(d
k)i ( 1)d
1
1
1
0
k=j
d+1
k j
(25)
M(d=1)
M(d=2)
M(d=3)
M(d=4)
=
=
1
1!
1
1 @
2
2!
1
0
1
1 B
B 3
3! @ 3
1
0
1
B 4
B
1 B
6
4! B
@ 4
1
2
20
1
,
1
0
A,
3
6
0
4
3
3
3
1
4
12
6
12
11
6
12
6
12
11
1
1
0 C
C,
0 A
0
1
4 1
4 0 C
C
6 0 C
C.
4 0 A
1 0
Varying t from zero to one, equation 24 traces out the ith segment of the
B-spline between joints k(i) and k(i+1) . These joints can be calculated as
0 (d) 1
c0
B (d) C
c1 C
B
1
k(i) = (a(i) a(1) . . . a(i+d 1) ) B
(26)
. C
B
C
d!
@ .. A
(d)
cd
where
(d)
cj
d
X
(d
k)d ( 1)k
k=j
(d)
d+1
k j
(c0,1,...,d is also the first d elements of the last row of the M(d) matrix).
28
(27)
4.1.1
interpolating B-spline
Having found the joint points, given the control points, we can now find the
control points (and so the B-spline) given the joint points. We actually need
a little more information. A B-spline with n + 1 control points has n d + 1
joints and so along the n d + 1 equations for these joints, we need d 1
further equations. Specifying tangents gives us the remaining expressions. For
a quadratic B-spline we only need to specify one tangent, e.g. the start tangent,
resulting the the following system of equations:
0
B c(2)
B 0
1 B
B 0
2! B
B ..
@ .
0
2
(2)
c1
(2)
c0
..
.
0
0
0
(2)
c1
..
.
0
...
...
...
..
.
0
0
0
..
.
0
0
0
..
.
...
c0
(2)
c1
(2)
10
a(0)
C B (1)
CB a
C B (2)
CB a
CB .
C@ .
.
A
a(n)
C B
C B
C B
C=B
C B
A @
t(0)
k(0)
k(1)
..
.
k(n
d+1)
C
C
C
C,
C
A
(28)
Knots
29
2/3
1/6
0
1
k not value s
NURBS
By varying the knot vector in a non-uniform manner, we can achieve an increased level of versatility and recoup some of the attractive features of B/ezier
curves. The first feature to note is that repeating a knot value d+1 times results
in the NURBS passing through a control points. The knot vector is n + d + 1
long so for a degree three NURBS with four control points there are eight knots.
Repeating the first and last knot values four times will create a NURBS with
one cubic segment that starts and ends at the first and last control point. The
basis functions for this NURBS are shown in figure 17. We see that they are the
same as those for a Bezier curve (figure 6). A Bezier curve is indeed a special
case of a NURBS from which, using the knot vector and the ability to specify
the degree of the NURBS, we can add more and more complexity.
We can take advantage of NURBS local control to, for example, refine the
shape of the B/ezier curve aerofoil definition in figure 10. With the influence of
a control point extending over d + 1 knot values, adding an extra control point
will not give local control in our degree three definition. Reducing to degree
two and adding a control point gives local control, as shown in figure 18 where
moving a control point on the lower surface gives control over the aft portion of
the aerofoil without aecting the leading edge region.
The knot vector for the lower surface NURBS is k = [0, 0, 0, 1, 2, 3, 3, 3] and
the resulting basis functions are shown in figure 19. Note how the second basis
function is non-zero only for the first and second segment, i.e. it has no influence
on the last segment (the leading edge region of the aerofoil in figure 18.
30
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0
0000
1111
k not value s
Figure 17: Repeated knot values in a third degree NUBRS yield the cubic
Bernstein polynomials in figure 6 (i.e. the NURBS is equivalent to a B/ezier
curve).
k (3) = 1
k ( 5 , 6 , 7 )= 3
k ( 0 , 1 , 2 )= 0
k
(4)
=2
Figure 18: Reducing the degree of the lower surface NURBS to three and adding
a control point gives local control towards the trailing edge, potentially giving
more design capability than the B/ezier curve definition in figure 10 (shown
here by moving the additional control point). Note that the plot has been
stretched to highlight the geometry changes.
31
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0
000
333
k not value s
Figure 19: Degree two NURBS basis functions for knot vector k =
[0, 0, 0, 1, 2, 3, 3, 3], resulting in a curve starting and ending at the first and last
control points. The central segment is uniform, but the first and last segments
have basis functions distorted by the repeated knot values.
A further level of detail can be obtained by varying the spacing of the knot
vector. Bringing knots together pulls the NURBS towards the control polygon:
for a degree three NURBS two repeated knot values matches the gradient of
the NURBS at the knot to the control polygon (i.e. alligns it with a line drawn
between the knots either side), three repeated knot values causes the NURBS
to pass through a control point (with a gradient discontinuity), four repeated
knots causes a break in the NURBS between two control points.
Figure 20 shows the range of manoeuvres possible with a degree three
NURBS (omitting the cause of changing control point weights, which is similar
to changin rational B/ezier spline weights, as shown in figure 12). Figure 20(a)
is a uniform degree threevB-spline and the uniform weightings from the uniform
knot-vector are shown in the right hand plot. Figure 20(b) has the degree
increased to seven and the first and last knot values repeated to yield a Bezier
spline equivalent. In figure 20(c) the degree is reduced back to three and the
first and last knots repeated such that the NURBS starts and ends at the first
and last control points. Figure 20(c) to (f) show the eect of repeated knot
values: causing tangent matching, control point interpolation, and breaks in
the NURBS.
As a weighted sum of control points, the equation for a NURBS can be
expressed in a similar way as a Bezier curve:
N (t) = sumni=0 a(i) Bi,d (t).
(29)
However, since the basis functions Bi,d (t) depend on the knot vector, the calculation of Bi,d (t) is rather tedious and usually performed recursively. That
32
(a)
k
( 3)
= 3
( 4)
= 4
( 7)
= 7k
( 5)
= 5
( 8)
= 8
( 6)
= 6
10
11
( b)
( 0, . . . , 7)
= 0
( 8, . . . , 15)
= 1
00000000
11111111
( c)
k
( 4)
= 1
k
k
( 5)
= 2
( 07)
= 4
( 6)
= 3
( 0, 1, 2, 3)
= 0
( 8, , 9, 10, 11)
0000
( 8, , 9, 10, 11)
0000
( 8, , 9, 10, 11)
0000
= 5
5555
( d)
k
( 4)
= 1
( 0, 1, 2, 3)
= 0
( 7)
= 3
( 5, 6)
= 2
= 4
22
4444
( e)
k
( 0, 1, 2, 3)
= 0
( 4, 5, 6)
= 2
( 7)
= 1
= 3
111
3333
(f )
0.5
( 0, 1, 2, 3)
= 0
( 4, 5, 6, 7)
= 1k
0
0000
( 8, , 9, 10, 11)
= 2
1111
k n ot v al u e s
Figure 20: Various NURBS defined by eight control points (left) and knot vectors (right): (a) degree three with uniform knot vector; (b) degree seven; (c-f)
degree three. The control point locations are chosen to be similar to Figure 7.19
in Salomon [2006].
33
2222
is, we start by calculating B0,1 (t) and B1,1 (t) from which B0,2 (t) can be calculated, and so on through to Bn,d (t). The implementation of NURBS in Python
is beyond the scope of this module, but the necessary equations are included
below.
The basis functions for d = 1 are defined as:
1, if t 2 [i, i + 1]
Bi,1 (t) =
(30)
0, otherwise
and the remaining basis functions can be calculated recursively from
Bi,d (t) =
k (i)
k (i+d 1)
k (i)
Bi,d
1 (t)
k (i+d)
k (i+d)
t
Bi+1,d
k (i+1)
1 (t),
(31)
noting that where a zero denominator occurs, the term should be evaluated as
zero.
References
M. Drela. XFOIL: An analysis and design system for low reynolds number airfoils. Conference on Low Reynolds Number Airfoil Aerodynamics, University
of Notre Dame, 1989.
M. Drela and M.B. Giles. Viscous-inviscid analysis of transonic and low reynolds
number airfoils. AIAA Journal, 25(10):13471355, October 1987.
G. Farin. NURBS: from projective geometry to practical use. Aerospace Science
Series. A K Peters, Natick, Massachusetts, second edition edition, 1999.
D. Salomon. Curves and Surfaces for Computer Graphics. Springer, New York,
2006.
I. Thomas. Selections Illustrating the History of Greek Mathematics (with English translation). Harvard University Press, Cambridge, Massachusetts, 1939.
34