pfh.glidersim.airfoil#

Models for the geometry and aerodynamic coefficients of 2D wing sections.

Geometry models are for computing mass distributions (for moments of inertia), points on reference lines (such as the quarter-chord position, frequently used by lifting line methods), and graphical purposes.

Coefficient models are for querying the section coefficients for lift, drag, and pitching moment.

Classes

AirfoilCoefficientsInterpolator(*args, **kwargs)

Interface for classes that provide airfoil coefficients.

AirfoilGeometry(profile_curve, camber_curve, ...)

A class for describing wing section profiles.

AirfoilGeometryInterpolator(airfoils)

Simple airfoil geometry interpolator.

GridCoefficients(file[, ai])

Loads a set of polars from a CSV file.

NACA(code, *[, open_TE, convention, N_points])

Generate an airfoil using a NACA4 or NACA5 parameterization.

XFLR5Coefficients(dirname, flapped)

Loads a set of XFLR5 polars (.txt) from a directory.

class pfh.glidersim.airfoil.AirfoilCoefficientsInterpolator(*args, **kwargs)#

Bases: Protocol

Interface for classes that provide airfoil coefficients.

Aerodynamic coefficients for a single airfoil are typicall calculated over a range of angle of attack and Reynolds number. For wings with control surfaces, the section profiles are variable; the control inputs choose the section profile from a set of airfoils by specifying their unique “airfoil index”. The definition of airfoil index is up to the user, but common choices are deflection angle, normalized vertical deflection distance, etc.

Coefficients interpolators calculate the aerodynamic coefficients over the range of airfoil index, angle of attack, and Reynolds number.

Methods

Cd(ai, alpha, Re[, clamp])

Compute the drag coefficient of the airfoil.

Cl(ai, alpha, Re[, clamp])

Compute the lift coefficient of the airfoil.

Cl_alpha(ai, alpha, Re[, clamp])

Compute the derivative of the lift coefficient versus angle of attack.

Cm(ai, alpha, Re[, clamp])

Compute the pitching coefficient of the airfoil.

abstract Cl(ai, alpha, Re, clamp=False)#

Compute the lift coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Clfloat
abstract Cd(ai, alpha, Re, clamp=False)#

Compute the drag coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Cdfloat
abstract Cm(ai, alpha, Re, clamp=False)#

Compute the pitching coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Cmfloat
abstract Cl_alpha(ai, alpha, Re, clamp=False)#

Compute the derivative of the lift coefficient versus angle of attack.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to return 0 if alpha exceeds the the highest non-nan value supported by the (ai, Re) pair.

Returns
Cl_alphafloat
__init__(*args, **kwargs)#
class pfh.glidersim.airfoil.GridCoefficients(file: str | pathlib.Path | TextIO, ai: str = 'delta_d')#

Bases: pfh.glidersim.airfoil.AirfoilCoefficientsInterpolator

Loads a set of polars from a CSV file.

The CSV must contain a header with the following columns:
  • delta_d

  • alpha [degrees]

  • Re

  • Cl

  • Cd

  • Cm

  • Cl_alpha

All values must lie on a grid over delta, alpha, and Re. The points must be on a grid, but the spacing in each dimension is not required to be uniform. If the grid has uniform spacing in each dimension, the GridCoefficients2 class is faster.

FIXME: requires a valid ai column name

Methods

Cd(ai, alpha, Re[, clamp])

Compute the drag coefficient of the airfoil.

Cl(ai, alpha, Re[, clamp])

Compute the lift coefficient of the airfoil.

Cl_alpha(ai, alpha, Re[, clamp])

Compute the derivative of the lift coefficient versus angle of attack.

Cm(ai, alpha, Re[, clamp])

Compute the pitching coefficient of the airfoil.

__init__(file: str | pathlib.Path | TextIO, ai: str = 'delta_d') None#
Cl(ai, alpha, Re, clamp=False)#

Compute the lift coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Clfloat
Cd(ai, alpha, Re, clamp=False)#

Compute the drag coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Cdfloat
Cm(ai, alpha, Re, clamp=False)#

Compute the pitching coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Cmfloat
Cl_alpha(ai, alpha, Re, clamp=False)#

Compute the derivative of the lift coefficient versus angle of attack.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to return 0 if alpha exceeds the the highest non-nan value supported by the (ai, Re) pair.

Returns
Cl_alphafloat
class pfh.glidersim.airfoil.XFLR5Coefficients(dirname: str, flapped: bool)#

Bases: pfh.glidersim.airfoil.AirfoilCoefficientsInterpolator

Loads a set of XFLR5 polars (.txt) from a directory.

Requirements:

  1. All .txt files in the directory are valid XFLR5 polar files, generated using a single test configuration over a range of Reynolds numbers.

  2. Filenames must use <…>_ReN.NNN_<…> to encode the Reynolds number in units of millions (so 920,000 is encoded as 0.920).

  3. All polars will be included.

FIXME: doesn’t support clamping

Methods

Cd(ai, alpha, Re[, clamped])

Compute the drag coefficient of the airfoil.

Cl(ai, alpha, Re[, clamped])

Compute the lift coefficient of the airfoil.

Cl_alpha(ai, alpha, Re[, clamped])

Compute the derivative of the lift coefficient versus angle of attack.

Cm(ai, alpha, Re[, clamped])

Compute the pitching coefficient of the airfoil.

__init__(dirname: str, flapped: bool) None#
Cl(ai, alpha, Re, clamped=None)#

Compute the lift coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Clfloat
Cd(ai, alpha, Re, clamped=None)#

Compute the drag coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Cdfloat
Cm(ai, alpha, Re, clamped=None)#

Compute the pitching coefficient of the airfoil.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to clamp alpha to the highest non-nan value supported by the (ai, Re) pair.

Returns
Cmfloat
Cl_alpha(ai, alpha, Re, clamped=None)#

Compute the derivative of the lift coefficient versus angle of attack.

Parameters
ai

Airfoil index

alphafloat [radians]

The angle of attack

Refloat [unitless]

The Reynolds number

clampbool

Whether to return 0 if alpha exceeds the the highest non-nan value supported by the (ai, Re) pair.

Returns
Cl_alphafloat
class pfh.glidersim.airfoil.AirfoilGeometry(profile_curve: Callable[[float], Any], camber_curve: Callable[[float], Any], thickness: Callable[[float], Any], convention: str, theta: float = 0, scale: float = 1)#

Bases: object

A class for describing wing section profiles.

Provides the surface curve, mean camber curve, thickness, and dimensionless mass properties of the airfoil.

Parameters
profile_curvecallable

Profile xy-coordinates as a curve parametrized by the normalized arc-length -1 <= r <= 1, where r = 0 is the leading edge, r = 1 is the tip of the upper surface, and r = -1 is the tip of the lower surface. Midpoints by length of the upper and lower surface curves are given by r = 0.5 and r = -0.5.

camber_curvecallable

Mean camber curve xy-coordinates as a function of normalized arc-length 0 <= r <= 1, where r = 0 is the leading edge, r = 1 is the trailing edge, and r = 0.5 is the midpoint by length.

thicknesscallable

Airfoil thickness as a function of r.

convention{“perpendicular”, “vertical”}

Whether the airfoil thickness is measured perpendicular to the mean camber line or vertically (perpendicular to the chord).

thetafloat [radians]

The angle between the chord and the x-axis that was removed during derotation. Useful for converting alpha of the derotated airfoil into alpha of the reference foil.

scalefloat [unitless]

The rescaling factor due to normalization. Useful for adjusting an existing set of coefficients for the original foil to account for the normalization.

Methods

camber_curve(r)

Compute points on the camber curve.

from_points(points, convention[, center, ...])

Construct an AirfoilGeometry from a set of airfoil xy-coordinates.

profile_curve(r)

Compute points on the profile curve.

profile_curve_normal(r)

Compute the normal unit vector at points on the profile curve.

profile_curve_tangent(r)

Compute the tangent unit vector at points on the profile curve.

thickness(r)

Compute airfoil thickness.

__init__(profile_curve: Callable[[float], Any], camber_curve: Callable[[float], Any], thickness: Callable[[float], Any], convention: str, theta: float = 0, scale: float = 1) None#
classmethod from_points(points, convention: str, center: bool = False, derotate: bool = False, normalize: bool = False) pfh.glidersim.airfoil.AirfoilGeometry#

Construct an AirfoilGeometry from a set of airfoil xy-coordinates.

By default, the input coordinates will be centered, normalized, and derotated so the leading edge is at the origin and the chord lies on the x-axis between 0 and 1.

The input coordinates are treated as the “reference” airfoil. If the user provides coefficient data to FoilSections, then it will be assumed that those coefficients were computed for the reference airfoil. If the reference coordinates are rotated and/or normalized by this function, the theta and scale properties allow those reference coefficients to be used with the modified airfoil. For example, if the lift coefficient for the reference airfoil was given by Cl(alpha), then the lift coefficient for the modified airfoil can be computed as scale * Cl(alpha + theta). (Centering has no effect on the coefficients.)

Parameters
pointsarray of float, shape (N,2)

The xy-coordinates of the airfoil in counter-clockwise order.

convention{“perpendicular”, “vertical”}

Whether the airfoil thickness is measured perpendicular to the mean camber line or vertically (the y-axis distance).

centerbool

Translate the curve leading edge to the origin. Default: False

derotatebool

Rotate the the chord parallel to the x-axis. Default: False

normalizebool

Scale the curve so the chord is unit length. Default: False

Returns
AirfoilGeometry
profile_curve(r)#

Compute points on the profile curve.

Parameters
rarray_like of float, shape (N,)

The curve parameter from -1..1, with -1 the lower surface trailing edge, 0 is the leading edge, and +1 is the upper surface trailing edge

Returns
pointsarray of float, shape (N, 2)

The (x, y) coordinates of points on the airfoil at r.

profile_curve_tangent(r)#

Compute the tangent unit vector at points on the profile curve.

Parameters
rarray_like of float

The profile curve parameter.

Returns
dxdyarray, shape (N, 2)

The unit tangent lines at the specified points, oriented with increasing r, so the tangents trace from the lower surface to the upper surface.

profile_curve_normal(r)#

Compute the normal unit vector at points on the profile curve.

Parameters
rarray_like of float

The profile curve parameter.

Returns
dxdyarray, shape (N, 2)

The unit normal vectors at the specified points, oriented with increasing r, so the normals point “out” of the airfoil.

camber_curve(r)#

Compute points on the camber curve.

Parameters
rarray_like of float [percentage]

Fractional position on the camber line, where 0 <= r <= 1

Returns
array of float, shape (N, 2)

The xy coordinate pairs of the camber line.

thickness(r)#

Compute airfoil thickness.

Parameters
rarray_like of float [percentage]

Fractional position on the camber line, where 0 <= r <= 1

Returns
thicknessarray_like of float
class pfh.glidersim.airfoil.AirfoilGeometryInterpolator(airfoils: dict[float, pfh.glidersim.airfoil.AirfoilGeometry])#

Bases: object

Simple airfoil geometry interpolator.

Attributes
index_bounds

Methods

camber_curve

profile_curve

thickness

__init__(airfoils: dict[float, pfh.glidersim.airfoil.AirfoilGeometry]) None#
property index_bounds: tuple[float, float]#
profile_curve(ai, r)#
camber_curve(ai, r)#
thickness(ai, r)#
class pfh.glidersim.airfoil.NACA(code: int | str, *, open_TE: bool = False, convention: str = 'perpendicular', N_points: int = 300)#

Bases: pfh.glidersim.airfoil.AirfoilGeometry

Generate an airfoil using a NACA4 or NACA5 parameterization.

Parameters
codeinteger or string

A 4- or 5-digit NACA code. If the code is an integer less than 1000, leading zeros are implicitly added; for example, 12 becomes the NACA4 code 0012.

Only a subset of NACA5 codes are supported. A NACA5 code can be expressed as LPSTT; valid codes for this implementation are restricted to L = 2, 1 <= P <= 5, and S = 0.

open_TEbool, optional

Generate airfoils with an open trailing edge. Default: False.

convention{“perpendicular”, “vertical”}, optional

The convention to use for defining the airfoil thickness. Default: “perpendicular”.

The “perpendicular” convention (sometimes called the “American” convention) measures airfoil thickness perpendicular to the mean camber line. The “vertical” convention (sometimes called the “British” convention) measures airfoil thickness in vertical strips (the y-axis distance between points on the upper and lower surfaces).

The “American” convention is used here since it was the original definition (see [0]), but the “British” convention is available in case the output needs to match the popular tool “XFOIL”.

N_pointsinteger

The number of sample points from each surface. Default: 300

References

0

Jacobs, Eastman N., Ward, Kenneth E., Pinkerton, Robert M. “The characteristics of 78 related airfoil sections from tests in the variable-density wind tunnel”. NACA Technical Report 460. 1933.

Methods

camber_curve(r)

Compute points on the camber curve.

from_points(points, convention[, center, ...])

Construct an AirfoilGeometry from a set of airfoil xy-coordinates.

profile_curve(r)

Compute points on the profile curve.

profile_curve_normal(r)

Compute the normal unit vector at points on the profile curve.

profile_curve_tangent(r)

Compute the tangent unit vector at points on the profile curve.

thickness(r)

Compute airfoil thickness.

__init__(code: int | str, *, open_TE: bool = False, convention: str = 'perpendicular', N_points: int = 300) None#
camber_curve(r)#

Compute points on the camber curve.

Parameters
rarray_like of float [percentage]

Fractional position on the camber line, where 0 <= r <= 1

Returns
array of float, shape (N, 2)

The xy coordinate pairs of the camber line.

classmethod from_points(points, convention: str, center: bool = False, derotate: bool = False, normalize: bool = False) pfh.glidersim.airfoil.AirfoilGeometry#

Construct an AirfoilGeometry from a set of airfoil xy-coordinates.

By default, the input coordinates will be centered, normalized, and derotated so the leading edge is at the origin and the chord lies on the x-axis between 0 and 1.

The input coordinates are treated as the “reference” airfoil. If the user provides coefficient data to FoilSections, then it will be assumed that those coefficients were computed for the reference airfoil. If the reference coordinates are rotated and/or normalized by this function, the theta and scale properties allow those reference coefficients to be used with the modified airfoil. For example, if the lift coefficient for the reference airfoil was given by Cl(alpha), then the lift coefficient for the modified airfoil can be computed as scale * Cl(alpha + theta). (Centering has no effect on the coefficients.)

Parameters
pointsarray of float, shape (N,2)

The xy-coordinates of the airfoil in counter-clockwise order.

convention{“perpendicular”, “vertical”}

Whether the airfoil thickness is measured perpendicular to the mean camber line or vertically (the y-axis distance).

centerbool

Translate the curve leading edge to the origin. Default: False

derotatebool

Rotate the the chord parallel to the x-axis. Default: False

normalizebool

Scale the curve so the chord is unit length. Default: False

Returns
AirfoilGeometry
profile_curve(r)#

Compute points on the profile curve.

Parameters
rarray_like of float, shape (N,)

The curve parameter from -1..1, with -1 the lower surface trailing edge, 0 is the leading edge, and +1 is the upper surface trailing edge

Returns
pointsarray of float, shape (N, 2)

The (x, y) coordinates of points on the airfoil at r.

profile_curve_normal(r)#

Compute the normal unit vector at points on the profile curve.

Parameters
rarray_like of float

The profile curve parameter.

Returns
dxdyarray, shape (N, 2)

The unit normal vectors at the specified points, oriented with increasing r, so the normals point “out” of the airfoil.

profile_curve_tangent(r)#

Compute the tangent unit vector at points on the profile curve.

Parameters
rarray_like of float

The profile curve parameter.

Returns
dxdyarray, shape (N, 2)

The unit tangent lines at the specified points, oriented with increasing r, so the tangents trace from the lower surface to the upper surface.

thickness(r)#

Compute airfoil thickness.

Parameters
rarray_like of float [percentage]

Fractional position on the camber line, where 0 <= r <= 1

Returns
thicknessarray_like of float