Airfoil Geometry Schema
This document defines the user-facing schema for airfoil geometry definitions. Field definitions and validation rules are normative. Examples are illustrative.
1. Top-Level Structure
Required Keys
schema_version(int): schema version; current version is1airfoils(object): named airfoil definitions.
Example Skeleton
schema_version: 1
airfoils: {}
2. Common Conventions
Unless otherwise noted, airfoil geometry is defined in a local nondimensional section frame:
chordwise coordinate:
xthickness/camber coordinate:
yleading edge at
x = 0trailing edge at
x = 1angular quantities are specified in degrees unless otherwise noted
Positive y corresponds to the upper surface side of the airfoil.
Unless otherwise specified, airfoil definitions are normalized to unit chord.
Unless otherwise specified by a particular airfoil type, all coordinates are interpreted in this normalized local frame.
3. airfoils
airfoils is a mapping from unique airfoil names to airfoil definitions.
Example:
airfoils:
root: {type: naca4, designation: "2412"}
tip: {type: dat, path: "airfoils/tip.dat"}
Keys must be unique and are case-sensitive.
4. Airfoil Definition Types
Airfoils may be defined using analytic parameterizations or point-based representations.
Analytic representations define the airfoil geometry through a parameterized model. Point-based representations define the airfoil geometry through discrete coordinates on the surface.
This schema supports standard NACA designations, externally stored coordinate files, inline coordinate definitions, and parameterized coefficient-based representations.
As of 2026-03-25, AirfoilFactory.from_spec(...) constructs runtime airfoils for naca4, naca4_modified, naca5, and naca5_modified.
Other families documented in this schema are planned schema targets, but they are not yet constructable through the current runtime factory and are tracked as roadmap work rather than migration-completion work.
4.0 Construction Status
The current migration-complete construction surface is:
naca4naca4_modifiednaca5naca5_modified
The following schema families are planned but not yet constructable through AirfoilFactory.from_spec(...):
datpointscstparsecnaca4btnaca4rnaca4fnaca16naca6naca6anaca7naca8
4.1 NACA Airfoils
These airfoils are all based on the canonical NACA airfoil specifications.
4.1.a NACA 4-digit
NACA 4-digit airfoils may be specified in either of two ways.
Code
airfoils:
naca2412:
type: naca4
designation: "2412"
Explicit Parameters
airfoils:
naca2412_explicit:
type: naca4
params:
m: 0.02
p: 0.4
t: 0.12
trailing_edge: sharp
leading_edge_radius: exact
Fields
type:"naca4"Exactly one of:
designation: 4-digit NACA designation stringparams: explicit parameter definition
If params is present, it contains:
m: maximum camber as a fraction of chordp: location of maximum camber as a fraction of chordt: maximum thickness as a fraction of chordtrailing_edge:"standard"or"sharp"; default"standard"leading_edge_radius:"standard"or"exact"; default"standard"
Designation Syntax
The designation must use the form
####.The first digit represents 100 times the maximum camber.
The second digit represents 10 times the location of maximum camber.
The last two digits combine to represent 100 times the maximum thickness.
For example, a
2312means:maximum thickness
0.12cmaximum camber is
0.02clocation of maximum camber is at
0.30c
Validation Rules
Exactly one of
designationandparamsmust be present.If
designationis present:must match
^[0-9]{4}$
If
paramsis present:0 <= m < 0.10 <= p <= 0.90 <= t <= 0.4if
m == 0, requirep == 0if
m > 0, requirep > 0trailing_edgemust be one ofstandard|sharpleading_edge_radiusmust be one ofstandard|exact
Notes
t = 0is permitted to support idealized zero-thickness analyses.Airfoil definitions are normalized to unit chord.
When
designationis used, the airfoil is interpreted as the classical NACA 4-digit designation.When
paramsis used, the airfoil remains within the NACA 4-digit family but allows higher-precision specification of the defining parameters and explicit control over trailing-edge closure and leading-edge radius treatment.In the runtime API,
AirfoilFactory.from_spec(...)maps designation-based NACA 4-digit specs tobuffalo_wings.airfoil.Naca4AirfoilClassic.In the runtime API,
AirfoilFactory.from_spec(...)maps explicit-parameter NACA 4-digit specs tobuffalo_wings.airfoil.Naca4AirfoilParams.
4.1.b NACA Modified 4-digit
Modified NACA 4-digit airfoils may be specified in either of two ways.
Designation
airfoils:
naca2412_46:
type: naca4_modified
designation: "2412-46"
Explicit Parameters
airfoils:
naca2412_46_explicit:
type: naca4_modified
params:
m: 0.02
p: 0.4
t: 0.12
leading_edge_index: 4.0
max_thickness_location: 0.6
trailing_edge: sharp
Fields
type:"naca4_modified"Exactly one of:
designation: modified NACA 4-digit designation stringparams: explicit parameter definition
If params is present, it contains:
m: maximum camber as a fraction of chordp: location of maximum camber as a fraction of chordt: maximum thickness as a fraction of chordleading_edge_index: modified-thickness leading-edge radius indexmax_thickness_location: location of maximum thickness as a fraction of chordtrailing_edge:"standard"or"sharp"; default"standard"
Designation Syntax
The designation must use the form
####-##.The first four digits are the standard NACA 4-digit designation.
The first digit after the dash is the leading-edge radius index.
The second digit after the dash is 10 times the chordwise location of maximum thickness.
For example,
2412-46means:NACA 4-digit camber line
2412leading-edge radius index
4maximum thickness at
0.6c
Validation Rules
Exactly one of
designationandparamsmust be present.If
designationis present:must match
^[0-9]{4}-[1-9][1-9]$
If
paramsis present:0 <= m < 0.10 <= p <= 0.90 <= t <= 0.41 <= leading_edge_index < 100.1 <= max_thickness_location < 1.0if
m == 0, requirep == 0if
m > 0, requirep > 0trailing_edgemust be one ofstandard|sharp
Notes
The modified NACA 4-digit family reuses the standard NACA 4-digit camber definition.
The modified designation selects the modified thickness law through the dash suffix.
In the runtime API,
AirfoilFactory.from_spec(...)maps designation-based modified NACA 4-digit specs tobuffalo_wings.airfoil.Naca4ModifiedAirfoilClassic.In the runtime API,
AirfoilFactory.from_spec(...)maps explicit-parameter modified NACA 4-digit specs tobuffalo_wings.airfoil.Naca4ModifiedAirfoilParams.
4.1.c NACA 4-digit B/T
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.1.d NACA 4-digit R
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.1.e NACA 4-digit F
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.1.f NACA 5-digit
NACA 5-digit airfoils may be specified in either of two ways.
Designation
airfoils:
naca23015:
type: naca5
designation: "23015"
Explicit Parameters
airfoils:
naca23015_explicit:
type: naca5
params:
ideal_lift_coefficient: 0.3
max_camber_location: 0.15
reflexed: false
t: 0.15
trailing_edge: sharp
leading_edge_radius: exact
Fields
type:"naca5"Exactly one of:
designation: 5-digit NACA designation stringparams: explicit parameter definition
If params is present, it contains:
ideal_lift_coefficient: theoretical lift coefficientmax_camber_location: location of maximum camber as a fraction of chordreflexed: whether the camber line has a reflexed trailing edget: maximum thickness as a fraction of chordtrailing_edge:"standard"or"sharp"; default"standard"leading_edge_radius:"standard"or"exact"; default"standard"
Designation Syntax
The designation must use the form
#####.The first digit represents 10 times two thirds of the ideal lift coefficient.
The second digit represents 10 times twice the location of maximum camber.
The third digit selects the camber-line family:
0: standard camber1: reflexed camber
The last two digits combine to represent 100 times the maximum thickness.
For example,
23015means:ideal lift coefficient
0.3maximum camber location
0.15cstandard non-reflexed camber
maximum thickness
0.15c
Validation Rules
Exactly one of
designationandparamsmust be present.If
designationis present:must match
^[0-9]{5}$the third digit must be
0or1
If
paramsis present:0.15 <= ideal_lift_coefficient < 0.60.05 <= max_camber_location < 0.30 <= t <= 0.4trailing_edgemust be one ofstandard|sharpleading_edge_radiusmust be one ofstandard|exact
Notes
designationrepresents the traditional encoded NACA 5-digit form.paramsis more general thandesignation.The
paramsform may describe airfoils that do not correspond to a historical published NACA 5-digit designation.The
designationdigits are encoded indices, not the physical values stored inparams.For the first digit,
digit = 10 * (2 / 3) * ideal_lift_coefficient. Equivalently,ideal_lift_coefficient = 0.15 * first_digit.For the second digit,
digit = 10 * 2 * max_camber_location. Equivalently,max_camber_location = 0.05 * second_digit.For example,
23015maps to:ideal_lift_coefficient = 0.3max_camber_location = 0.15reflexed = falset = 0.15
The reflex behavior selects which camber implementation is used.
The explicit-parameter thickness path exposes the same trailing-edge and leading-edge-radius controls as the NACA 4-digit params schema.
In the runtime API,
AirfoilFactory.from_spec(...)maps designation-based NACA 5-digit specs tobuffalo_wings.airfoil.Naca5AirfoilClassic.In the runtime API,
AirfoilFactory.from_spec(...)maps explicit-parameter NACA 5-digit specs tobuffalo_wings.airfoil.Naca5AirfoilParams.
4.1.g NACA Modified 5-digit
Modified NACA 5-digit airfoils may be specified in either of two ways.
Designation
airfoils:
naca23015_46:
type: naca5_modified
designation: "23015-46"
Explicit Parameters
airfoils:
naca23015_46_explicit:
type: naca5_modified
params:
ideal_lift_coefficient: 0.3
max_camber_location: 0.15
reflexed: false
t: 0.15
leading_edge_index: 4.0
max_thickness_location: 0.6
trailing_edge: sharp
Fields
type:"naca5_modified"Exactly one of:
designation: modified NACA 5-digit designation stringparams: explicit parameter definition
If params is present, it contains:
ideal_lift_coefficient: theoretical lift coefficientmax_camber_location: location of maximum camber as a fraction of chordreflexed: whether the camber line has a reflexed trailing edget: maximum thickness as a fraction of chordleading_edge_index: modified-thickness leading-edge radius indexmax_thickness_location: location of maximum thickness as a fraction of chordtrailing_edge:"standard"or"sharp"; default"standard"
Designation Syntax
The designation must use the form
#####-##.The first five digits are the standard NACA 5-digit designation.
The first digit after the dash is the modified-thickness leading-edge radius index.
The second digit after the dash is 10 times the chordwise location of maximum thickness.
For example,
23015-46means:ideal lift coefficient
0.3maximum camber location
0.15cstandard non-reflexed 5-digit camber
maximum thickness
0.15cleading-edge radius index
4maximum thickness at
0.6c
Validation Rules
Exactly one of
designationandparamsmust be present.If
designationis present:must match
^[0-9]{5}-[1-9][1-9]$the third digit of the 5-digit designation must be
0or1
If
paramsis present:0.15 <= ideal_lift_coefficient < 0.60.05 <= max_camber_location < 0.30 <= t <= 0.41 <= leading_edge_index < 100.1 <= max_thickness_location < 1.0trailing_edgemust be one ofstandard|sharp
Notes
The modified NACA 5-digit family reuses the NACA 5-digit camber definition.
The camber implementation is selected by reflex behavior:
designation third digit
0orparams.reflexed = false: standard 5-digit camberdesignation third digit
1orparams.reflexed = true: reflexed 5-digit camber
The designation digits are encoded indices, not the physical values stored in
params.For the first digit of the 5-digit designation:
digit = 10 * (2 / 3) * ideal_lift_coefficient. Equivalently,ideal_lift_coefficient = 0.15 * first_digit.For the second digit of the 5-digit designation:
digit = 10 * 2 * max_camber_location. Equivalently,max_camber_location = 0.05 * second_digit.designationrepresents the traditional encoded modified NACA 5-digit form.paramsis more general thandesignation.The
paramsform may describe airfoils that do not correspond to a historical published modified NACA 5-digit designation.In the runtime API,
AirfoilFactory.from_spec(...)maps designation-based modified NACA 5-digit specs tobuffalo_wings.airfoil.Naca5ModifiedAirfoilClassic.In the runtime API,
AirfoilFactory.from_spec(...)maps explicit-parameter modified NACA 5-digit specs tobuffalo_wings.airfoil.Naca5ModifiedAirfoilParams.
4.1.h NACA 16-Series
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.1.i NACA 6-Series
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.1.j NACA 6A-Series
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.1.k NACA 7-Series
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.1.l NACA 8-Series
TODO: Define supported designation syntax, explicit parameter form, and validation rules.
This family is planned, but it is not yet constructable through AirfoilFactory.from_spec(...).
4.2 Coordinate Files
TODO: Expand on this. There are different types of file formats that need to be read.
airfoils:
myfoil: {type: dat, path: "airfoils/myfoil.dat"}
Notes
Coordinate files define the airfoil through discrete surface points rather than an analytic parameterization.
Imported coordinates are interpreted in the local airfoil frame unless otherwise specified by the file format.
Unless otherwise specified, imported airfoils are normalized internally to unit chord.
File parsing rules, supported formats, and normalization behavior should be defined explicitly once this section is expanded.
Coordinate-file airfoils are planned, but they are not yet constructable through
AirfoilFactory.from_spec(...).
4.3 Point Coordinates
Coordinate-defined airfoils may be specified directly in the YAML file.
4.3.a Surface curve format
airfoils:
flat_plate:
type: points
format: surface_curve
orientation: clockwise
leading_edge: 3
normalize: false
points:
- [1.0, 0.0]
- [0.7, -0.02]
- [0.3, -0.03]
- [0.0, 0.0]
- [0.3, 0.03]
- [0.7, 0.02]
- [1.0, 0.0]
This format specifies a single ordered list of points that traces the airfoil surface starting and ending at the trailing edge.
4.3.b Upper/Lower surface format
airfoils:
example_foil:
type: points
format: upper_lower
normalize: false
upper:
- [0.0, 0.0]
- [0.3, 0.06]
- [0.7, 0.03]
- [1.0, 0.0]
lower:
- [0.0, 0.0]
- [0.3, -0.02]
- [0.7, -0.01]
- [1.0, 0.0]
This format specifies the upper and lower surfaces separately.
Fields
type:"points"format:"surface_curve"or"upper_lower"normalize: optional boolean; defaulttrue
If format: "surface_curve":
orientation:"clockwise"or"counterclockwise"leading_edge: 0-based index of the point that represents the leading edgepoints: ordered list of[x, y]coordinate pairs
If format: "upper_lower":
upper: ordered list of[x, y]coordinate pairslower: ordered list of[x, y]coordinate pairs
Supported Format Values
"surface_curve": points proceed around the airfoil surface starting and ending at the trailing edge"upper_lower": points are given as separate upper and lower surfaces, each starting from the leading edge and going to the trailing edge
Validation Rules
If
format: "surface_curve":pointsrequiredmust contain at least 3 points
each point must be a numeric pair
[x, y]
orientationrequiredleading_edgeis required and must be a valid index into thepointslistupperandlowernot allowed
If
format: "upper_lower":upperandlowerrequiredeach must contain at least 2 points
each point must be a numeric pair
[x, y]the first point of both lists (the leading edge) must be coincident
the last point of each list defines the trailing-edge point for that surface
these may be coincident for a sharp trailing edge
points,orientation, andleading_edgenot allowed
If
normalize: true, the geometry is normalized to unit chord internallyIf
normalize: false, the input must already define a valid nonzero chord extent
Notes
Point-based airfoils define the geometry directly through discrete coordinates on the surface.
Airfoil definitions are normalized to unit chord when
normalize: true.In
surface_curveformat, the trailing-edge point must be represented for both surfaces, even if the two points are coincident.In
upper_lowerformat, the upper and lower surfaces are specified independently and must share the same leading-edge point.The
leading_edgeindex is required insurface_curveformat to avoid ambiguity in point sets with multiple candidate leading-edge points or nonuniform sampling.Point-defined airfoils are planned, but they are not yet constructable through
AirfoilFactory.from_spec(...).
4.4 CST coefficients
TODO: Expand on this. Look at Chris’s code and CodeEli.
airfoils:
cst_foil:
type: cst
upper: {n1: 0.5, n2: 1.0, a: [ ... ]}
lower: {n1: 0.5, n2: 1.0, a: [ ... ]}
Notes
CST defines the airfoil geometry through separate coefficient sets for the upper and lower surfaces.
The class function exponents and coefficient arrays determine the surface shape in the normalized local airfoil frame.
Airfoil definitions are normalized to unit chord.
The exact coefficient conventions, required fields, and validation rules should be defined explicitly once this section is expanded.
CST airfoils are planned, but they are not yet constructable through
AirfoilFactory.from_spec(...).
4.5 PARSEC Coefficients
This uses a 12-parameter PARSEC specification with independently specified upper and lower leading-edge radii.
airfoils:
parsec_foil:
type: parsec
leading_edge_radius:
upper: 0.005
lower: 0.005
trailing_edge:
thickness: 0.0025
location: -0.006
direction_angle: 7.0
wedge_angle: 10.0
upper_surface_max:
location: [0.41, 0.11]
curvature: -0.9
lower_surface_min:
location: [0.20, -0.023]
curvature: 0.05
Fields
type:"parsec"leading_edge_radius.upper: upper-surface leading-edge radiusleading_edge_radius.lower: lower-surface leading-edge radiustrailing_edge.thickness: trailing-edge thicknesstrailing_edge.location: vertical coordinate of the midpoint between the upper and lower trailing-edge endpointstrailing_edge.direction_angle: angle of the bisector of the upper and lower trailing-edge surface directionstrailing_edge.wedge_angle: included angle between the upper and lower surface directions at the trailing edgeupper_surface_max.location:[x, y]location of the upper-surface maximumupper_surface_max.curvature: curvature of the upper surface at the upper-surface maximumlower_surface_min.location:[x, y]location of the lower-surface minimumlower_surface_min.curvature: curvature of the lower surface at the lower-surface minimum
Validation Rules
leading_edge_radiusmust contain bothupperandlowerleading_edge_radius.upper > 0leading_edge_radius.lower > 0trailing_edge.thickness >= 0upper_surface_max.locationmust be a numeric 2-tuple[x, y]lower_surface_min.locationmust be a numeric 2-tuple[x, y]0 < upper_surface_max.location[0] < 10 < lower_surface_min.location[0] < 1upper_surface_max.location[1] > 0lower_surface_min.location[1] < 0
Notes
All length quantities are nondimensionalized by the chord.
Angular quantities are specified in degrees.
Airfoil definitions are normalized to unit chord.
This representation defines the airfoil through geometric constraints rather than directly through surface points.
Upper and lower leading-edge radii are specified independently.
PARSEC airfoils are planned, but they are not yet constructable through
AirfoilFactory.from_spec(...).
5. Normalization
Normalization defines how coordinate-based airfoil definitions are transformed into the canonical local airfoil frame used by this schema.
This section applies to imported coordinate files and inline point-coordinate airfoils when normalization is enabled. Analytic airfoil definitions, such as NACA, CST, and PARSEC, are already defined in the normalized local frame unless otherwise specified.
5.1 Canonical Normalized Frame
A normalized airfoil is represented in the local airfoil frame with the following properties:
leading-edge reference at
[0.0, 0.0]trailing-edge reference at
[1.0, 0.0]chord line aligned with the positive
xaxispositive
ydirected toward the upper surface side of the airfoilchord length equal to
1
5.2 Reference Definitions
Normalization is based on a leading-edge reference and a trailing-edge reference.
The leading-edge reference is the geometric leading-edge point used to define the start of the chord line.
The trailing-edge reference is the point used to define the end of the chord line.
For airfoils with distinct upper and lower trailing-edge endpoints, the trailing-edge reference is the midpoint of those two endpoints.
This definition avoids ambiguity for blunt trailing edges, where the upper and lower trailing-edge points may not coincide.
5.3 Reference Extraction by Representation
Coordinate Files
For file-based coordinate definitions, the leading-edge and trailing-edge references are determined from the parsed file format and the file topology.
For formats that explicitly separate upper and lower surfaces, the leading-edge reference is the shared leading-edge endpoint of the two surfaces.
For formats that represent the airfoil as a single surface curve, the trailing-edge reference is determined from the first and last surface points, and the leading-edge reference is determined from the format-specific interpretation of the curve or from explicitly supplied metadata if required by the format.
Point Coordinates
For type: "points" airfoils:
If
format: "surface_curve":the first and last points define the two trailing-edge endpoints
the trailing-edge reference is the midpoint of those two endpoints
the
leading_edgeindex identifies the leading-edge reference point
If
format: "upper_lower":the first point of both
upperandlowerdefines the shared leading-edge referencethe last points of
upperandlowerdefine the upper and lower trailing-edge endpointsthe trailing-edge reference is the midpoint of the two trailing-edge endpoints
5.4 Normalization Transform
When normalization is enabled, the following transform is applied:
Translate the airfoil so that the leading-edge reference is at the origin.
Rotate the airfoil so that the line from the leading-edge reference to the trailing-edge reference lies on the positive
xaxis.Scale the airfoil so that the distance from the leading-edge reference to the trailing-edge reference is
1.
After normalization, the leading-edge reference is at [0.0, 0.0] and the trailing-edge reference is at [1.0, 0.0].
5.5 Orientation
If the input geometry is oriented such that the upper surface lies at negative y after normalization, the implementation must either:
reject the geometry as invalid, or
apply a reflection about the
xaxis if such behavior is explicitly supported by the implementation
Recommended behavior: reject the geometry unless automatic reflection is explicitly documented.
5.6 Validation Rules
normalization requires a valid leading-edge reference
normalization requires a valid trailing-edge reference
the distance between the leading-edge reference and trailing-edge reference must be greater than zero
for airfoils with separate upper and lower trailing-edge endpoints, both endpoints must be valid before the trailing-edge midpoint is computed
if normalization is disabled for a coordinate-based airfoil, the geometry is preserved as provided, but it must still define a valid nonzero chord extent
5.7 Notes
Normalization must not define the leading edge purely as the point with minimum
x, because valid airfoil definitions may contain points withx < 0relative to the normalized leading-edge reference.Normalization must not define the trailing edge purely as the point with maximum
x, because blunt trailing edges may have distinct upper and lower endpoints.For blunt trailing edges, the trailing-edge midpoint is the canonical chord endpoint used for normalization.
This normalization procedure is intended to make coordinate-defined airfoils consistent with analytic airfoil definitions in this schema.