Wing Geometry Schema
This document describes the user-facing schema for defining a wing using standard preliminary-design parameters while internally constructing NURBS patches with explicit C0/G1 join control.
Runtime Support Summary
As of 2026-03-25, WingCanonical.from_spec(...) resolves wing section airfoils through AirfoilFactory.from_spec(...).
That currently supports runtime section sampling for these airfoil types:
naca4naca4_modifiednaca5naca5_modified
Other airfoil families documented in the airfoil schema are valid schema targets but are not yet constructable through the current runtime factory.
1. Top-Level Structure
Required Keys
schema_version(int): schema version.units(object): unit declarations (used for validation and display).wing(object): the wing definition.airfoils(object): named airfoil definitions referenced by panels.
Example Skeleton
schema_version: 2
units: {length: m, angle: deg}
wing: {}
airfoils: {}
2. Units
units:
length: m # or ft (if you support it)
angle: deg # or rad
Recommend storing angles in degrees for user convenience; convert to radians internally.
3. wing
3.1 Required Fields
symmetry(enum):"mirror_y"or"none"half_span(float): half-span (length units)reference_axis(enum):"leading_edge" | "quarter_chord" | "elastic_axis"twist_axis(enum):"leading_edge" | "quarter_chord" | "elastic_axis"panels(list[panel])
3.2 Optional Fields (Recommended)
name(str)frame(object): axis meaning (documentation only, but can be validated)frame: {x: forward, y: right, z: up}
joins(list[join]): required when more than one panel, unless you allow implicit defaults.
4. panel
4.1 Required Fields
id(str): unique panel identifier.eta_range(2-tuple float):[eta0, eta1]with0 ≤ eta0 < eta1 ≤ 1.ref_line(object): definesx_ref(eta)andz_ref(eta).chord(distribution): definesc(eta).twist(distribution): definestheta(eta)inunits.angle.airfoil(airfoil_spec)
4.2 Optional Fields
nurbs(object): internal construction knobs (safe to omit; defaults apply)mesh(object): sampling preferences for exports (VLM/CFD)
5. Distribution
A distribution defines a scalar function of eta.
5.1 Piecewise Linear (Recommended Baseline)
chord:
type: piecewise_linear
data: [[eta0, value0], [eta1, value1], ...]
5.2 Validation Rules
etavalues must be increasing.Values are in the implied units for the field (meters for chord, degrees for twist, meters for x_ref/z_ref).
5.3 Future Extensions
You can later add:
type: splinetype: polynomialtype: constant
6. Reference Line
ref_line:
x_ref: {type: piecewise_linear, data: [[0.0, 0.0], [1.0, 1.8]]}
z_ref: {type: piecewise_linear, data: [[0.0, 0.0], [1.0, 0.8]]}
6.1 Interpretation
x_ref(eta)encodes sweep as the x-position of the selected reference axis.z_ref(eta)encodes dihedral as the z-position of the selected reference axis.
7. Airfoil Specification
7.1 Single Airfoil
airfoil:
type: single
name: naca0012
Fields
type:"single"name: key in the top-levelairfoilsmap
7.2 Spanwise Blended Airfoil
airfoil:
type: blend
method: cst # "pointwise" | "cst" | "camber_thickness"
stations: [[0.0, naca2412], [0.6, naca0012]]
Fields
type:"blend"method: blending methodstations: list of[eta, airfoil_name]pairs defining blend control stations
Validation Rules
etainstationsmust be increasing and cover the panel’seta_range(recommended).Implementer note: if stations don’t align with panel ends, decide whether to extrapolate or error.
8. airfoils (Top Level)
Named airfoil definitions referenced by wing panels.
This mapping is part of the wing document, so a wing YAML file is self-contained. Each value in the mapping must conform to the airfoil definition schema documented in the Airfoil Geometry Schema.
Example:
airfoils:
root: {type: naca4, designation: "2412"}
mid: {type: naca4_modified, designation: "2412-46"}
tip: {type: dat, path: "airfoils/tip.dat"}
Wing canonical currently supports naca4, naca4_modified, naca5,
and naca5_modified definitions for section sampling.
9. NURBS (Panel-Local)
These parameters affect internal NURBS construction. Users can omit them and accept defaults.
nurbs:
degrees: {u: 4, v: 3}
ctrlpts: {u: 16, v: 10}
fit:
method: skin # "skin" | "least_squares"
9.1 Validation Recommendations
degrees.u >= 2,degrees.v >= 2ctrlpts.u > degrees.u,ctrlpts.v > degrees.v
10. joins
Users explicitly specify continuity at each patch interface.
joins:
- id: "J0"
left: {panel: "P0_inboard", side: "v_max"}
right: {panel: "P1_outboard", side: "v_min"}
continuity: "G1" # "C0" | "G1"
weight: 5.0 # optional; solver weighting
tangent_scale: "auto" # "auto" or numeric lambda
10.1 Required Fields
id(str)left.panel(str): existing panel idleft.side(enum):u_min|u_max|v_min|v_maxright.panel(str)right.side(enum)continuity(enum):C0|G1
10.2 Optional Fields
weight(float): relative strength of the join constraint (for constrained solve).tangent_scale(float or “auto”): sets λ in the G1 condition.
10.3 Compatibility Requirements (Recommended)
For continuity: G1:
compatible degrees in the join-normal param direction
compatible knot vectors along the join edge direction (or automatic knot refinement)
same number of control points along the join edge
If not compatible:
Recommended behavior is to either auto-refine/elevate or raise a clear error.
11. Export Sampling Controls (Optional)
You can attach export sampling controls at the panel level or globally.
Example:
mesh:
vlm: {n_span: 24, n_chord: 12, span_spacing: cosine, chord_spacing: cosine}
cfd: {n_span: 80, n_airfoil: 240}
11.1 Validation Rules (Suggested)
positive integer counts
allow
uniform|cosine
12. Minimal Complete Example
schema_version: 2
units: {length: m, angle: deg}
wing:
name: demo
symmetry: mirror_y
half_span: 5.0
reference_axis: quarter_chord
twist_axis: quarter_chord
panels:
- id: P0
eta_range: [0.0, 1.0]
ref_line:
x_ref: {type: piecewise_linear, data: [[0.0, 0.0], [1.0, 1.0]]}
z_ref: {type: piecewise_linear, data: [[0.0, 0.0], [1.0, 0.5]]}
chord: {type: piecewise_linear, data: [[0.0, 2.0], [1.0, 1.0]]}
twist: {type: piecewise_linear, data: [[0.0, 2.0], [1.0, -2.0]]}
airfoil: {type: single, name: naca0012}
airfoils:
naca0012: {type: naca4, designation: "0012"}