Skip to content
Snippets Groups Projects

Airfoil toolbox

A list of functions and script used for analysis of airfoils and related data with Matlab.

Disclaimer

This toolbox was mainly developed under Matlab R2018a. The various functions were not tested on older versions. A code compatibility analysis showed no errors, so in theory it should work properly with any other versions of Matlab as well. If for some reason it does not work on your version, please open an issue.

The functions in this repository are intended to be used as a Matlab package (see Matlab documentation for more details).

Documentation

Each function contains a complete description in its preamble. Type help <function> in Matlab command window to print it.

Install and use

Installation

  1. Either clone this repository or download a .zip version of the source code.
  2. Place the +af_tools/ folder somewhere on your Matlab Path such as:

Remark

Unfortunately, Matlab packages have a few limitations. Hence, you should avoid changing the package name if you do not know what you are doing.

  • The + in the folder's name is required for Matlab to treat it as a package.
  • Some functions of this package are interconnected (e.g., nacaairfoil calls nacacamber). In that situation, Matlab forces the main function to re-import explicitly all sub-functions before using them, even if they are part of the same package (people have complained about that design choice for quite some time, to no avail). If you rename the package, these links will be broken and Matlab will not find the connected functions.
  • All functions that import other functions will have an import line at the beginning. If you rename the package, you must therefore update these imports.

Use

Once the +af_tools/ folder is placed somewhere where Matlab will find it, you can start using its features.

  • If you are only interested in a single function of the package, use
import af_tools.<functionName>
functionName(args)
  • If you want to import all functions, use
import af_tools.*
xf2mat(args)
nacacamber(args)
...
  • If you want to use functions on-the-fly without importing them, call them directly
af_tools.xf2mat(args)

Functions

  • All functions can be used as standalone functions and give meaningful output on their own (they are not sub-routines used to perform intermediary tasks).
  • All functions can be called without arguments. If that is the case, they will prompt the user to manually enter or select the few mandatory arguments. The rest will be set to default values.

List of functions:

  • xf2mat: Aggregates multiple XFOIL or XFLR5 polar results into a single structure.
  • uiuccleaner: Re-formats airfoil coordinates obtained from UIUC Airfoil database.
  • Airfoil generation
    • nacacamber: Generates the coordinates of the camberline for a NACA 4 or 5 digits airfoil.
    • nacaairfoil: Generates the full coordinates of a NACA 4 or 5 digits airfoil.
  • Polar manipulation
    • extendpolar: Extends polars to the full range of \alpha ([-180, 180] deg).
    • findstall: Finds the stall point and returns the corresponding \alpha, C_l and C_d.
    • findzerolift: Finds the zero-lift angle and the associate C_d.
    • findcllinearrange: Finds the linear range of the lift coefficient and returns the range and lift slope.
    • plotpolars: Plot various polars.

xf2mat

Aggregates airfoil polars obtained using XFOIL v6.99 of XFLR5 v6.55 into a single Matlab structure.

This function can either aggregate multiple polar files into a single structure (e.g. same airfoil at different Reynolds) or simply convert a single polar data into a Matlab-ready structure.

import af_tools.xf2mat
Polar = xf2mat
Polar = xf2mat(inputDir, inputFiles, 'autosave', true)
Polar = xf2mat(inputDir, inputFiles, 'trimAoas', true)
Polar = xf2mat(inputDir, inputFiles, 'autosave', true, 'trimAoas', true)
Input Example Default
inputDir '.', 'xf_results' -
inputFiles '*', '*0012*', '{'*0012_1*', '*0012_2*'} '*'
'autosave' false, true false
'trimAoas' false, true false

The output is a structure with the following fields, where M is the number of angles of attack and N is the number of input files.

Field Data Size
origin Program from which the polars came (XFOIL/XFLR5) [1 x N]
airfoil Airfoil name (parsed from XFOIL/XFLR5 results) [1 x N]
alpha Angles of attacks [M x N]
reynolds Reynolds numbers [1 x N]
mach Mach number [1 x N]
nCrit BL transition factor [1 x N]
cl Lift coefficient [M x N]
cd Drag coefficient [M x N]
cm Moment coefficient [M x N]

uiuccleaner

The UIUC airfoil database from the University of Illinois gathers the coordinates for more than 1600 airfoils. However, there is a few discrepancies between the format and ordering of these coordinates. This scripts alleviates that by re-formatting any input file from the original database. The main use of this function is to make the coordinates files compliant with other existing tools, such as XFOIL.

The output format of this script follows the "labeled coordinates" file, used originally by Selig on the UIUC Airfoil Database. The first line contains the name of the airfoil, and each line after that is a set of coordinates. The coordinates are ordered from the trailing edge, along the upper surface to the leading edge and back around the lower surface to trailing edge.

import af_tools.xf2mat
Polar = uiuccleaner
Polar = uiuccleaner(inputDir, inputFiles, 'autosave', true)
Polar = uiuccleaner(inputDir, inputFiles, 'overwrite', true)
Input Example Default
inputDir '.', 'xf_results' -
inputFiles '*', '*0012*', '{'*0012_1*', '*0012_2*'} '*'
'autosave' false, true false
'overwrite' false, true false
'refine' false, true false

Airfoil generation

The following functions use the same two main input arguments.

Input Example Default
digits '0012', '24012' -
nPoints 100, 130 100

nacacamber

Determines the camber line of a NACA 4 or 5 digits airfoil. The output is ordered from the leading edge to the trailing edge.

import af_tools.nacacamber
[xc, yc, gradY] = nacacamber
[xc, yc, gradY] = nacacamber(digits)
[xc, yc, gradY] = nacacamber(digits, nPoints)
[xc, yc, gradY] = nacacamber(digits, nPoints, 'spacing', 'halfcosine')
Options Example Default
'spacing' halfcosine, cosine, linear 'halfcosine'

nacaairfoil

Generates the full coordinates of a NACA 4 or 5 digits airfoil. The output coordinates follow the most usual order. They start at the trailing edge, along the upper surface to the leading edge and back around the lower surface to trailing edge.

import af_tools.nacaairfoil
[x, y] = nacaairfoil
[x, y] = nacaairfoil(digits)
[x, y] = nacaairfoil(digits, nPoints)
[x, y] = nacaairfoil(digits, nPoints, 'spacing', spacing, 'zerote', true)
[x, y] = nacaairfoil(digits, nPoints, 'savedat', true)
Options Example Default
'spacing' halfcosine, cosine, linear 'halfcosine'
'zerote' true, false true
'savedat' true, false true

Polar manipulation

The following functions all share the same main inputs arguments in the exact same order. These arguments can be of two types:

  1. Polar: A Polar structure, as the one given by [xf2mat][xf2mat];
  2. alpha, cl, cd, cm: Arrays representing the different polars. Some functions only allow the first two or three arrays.

Some functions then extend these inputs by using various optional arguments.

extendpolar

This function extends known C_l and C_d polars to the full range of angle of attacks [-180; 180]. This is especially useful when studying rotors and propellers in off-design configuration (with the Blade Element Momentum Theory for instance).

import af_tools.extendpolar
[alphaExt, clExt, cdExt] = extendpolar
[alphaExt, clExt, cdExt] = extendpolar(Polar)
[alphaExt, clExt, cdExt] = extendpolar(Polar, 'method', 'Viterna')
[alphaExt, clExt, cdExt] = extendpolar(Polar, 'limit', 'stall')
[alphaExt, clExt, cdExt] = extendpolar(alpha, cl, cd, 'method', 'Viterna')
Options Example Default
'method' 'Viterna' 'Viterna'
'limit' 'stall','limit' 'last'

plotpolars

Plots the following polars: C_l-\alpha  ,   C_d-\alpha  ,   C_m-\alpha  ,   C_l/C_d-\alpha  ,   C_l-C_d.

import af_tools.plotpolars
plotpolars
plotpolars(Polar)
plotpolars(alpha, cl, cd, cm)

findstall

Finds the stall angle of attack and the associated C_l and C_d.

import af_tools.findstall
[alpha_s, cl_s, cd_s] = findstall
[alpha_s, cl_s, cd_s] = findstall(Polar)
[alpha_s, cl_s, cd_s] = findstall(alpha, cl, cd)

findzerolift

Finds the zero-lift angle of attack and the associated C_d.

import af_tools.findzerolift
[alpha_zeroL, cd_zeroL] = findzerolift
[alpha_zeroL, cd_zeroL] = findzerolift(Polar)
[alpha_zeroL, cd_zeroL] = findzerolift(alpha, cl, cd)

findcllinearrange

Finds the range of angles of attack for which the C_l can be considered linear.

import af_tools.findcllinearrange
[alphaRange, clRange, clSlope] = findcllinearrange
[alphaRange, clRange, clSlope] = findcllinearrange(Polar)
[alphaRange, clRange, clSlope] = findcllinearrange(alpha,cl)

Licence

Copyright (c) 2022 Thomas Lambert, University of Liège.

All functions and scripts of the af_tools code are licensed under the Apache 2.0 Licence.