"""Internal implementation of the wing geometry schema dataclasses."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Literal
from buffalo_wings.airfoil import AirfoilDefinitionSpec
type LengthUnit = Literal["m", "ft"]
type AngleUnit = Literal["deg", "rad"]
type SymmetryMode = Literal["mirror_y", "none"]
type ReferenceAxis = Literal["leading_edge", "quarter_chord", "elastic_axis"]
type JoinContinuity = Literal["C0", "G1"]
type PanelSide = Literal["u_min", "u_max", "v_min", "v_max"]
type BlendMethod = Literal["pointwise", "cst", "camber_thickness"]
type FitMethod = Literal["skin", "least_squares"]
type SpacingMethod = Literal["uniform", "cosine"]
[docs]
@dataclass(slots=True)
class UnitsSpec:
"""
Unit declarations used by the serialized schema.
Attributes
----------
length : {"m", "ft"}, default="m"
Length unit used for dimensional wing quantities.
angle : {"deg", "rad"}, default="deg"
Angle unit used for twist and other angular quantities.
"""
length: LengthUnit = "m"
angle: AngleUnit = "deg"
[docs]
@dataclass(slots=True)
class FrameSpec:
"""
Human-readable axis labels for the wing coordinate frame.
Attributes
----------
x : str, default="forward"
Human-readable label for the positive x-axis.
y : str, default="right"
Human-readable label for the positive y-axis.
z : str, default="up"
Human-readable label for the positive z-axis.
"""
x: str = "forward"
y: str = "right"
z: str = "up"
[docs]
@dataclass(slots=True)
class PiecewiseLinearDistribution:
"""
Piecewise-linear scalar distribution over ``eta``.
Attributes
----------
type : Literal["piecewise_linear"], default="piecewise_linear"
Schema discriminator for the distribution type.
data : list[tuple[float, float]], optional
Ordered ``(eta, value)`` control points used for linear interpolation.
"""
type: Literal["piecewise_linear"] = "piecewise_linear"
data: list[tuple[float, float]] = field(default_factory=list)
type DistributionSpec = PiecewiseLinearDistribution
[docs]
@dataclass(slots=True)
class RefLineSpec:
"""
Reference-axis position distributions used for sweep and dihedral.
Attributes
----------
x_ref : DistributionSpec
Spanwise distribution of the reference-axis x-position.
z_ref : DistributionSpec
Spanwise distribution of the reference-axis z-position.
"""
x_ref: DistributionSpec
z_ref: DistributionSpec
[docs]
@dataclass(slots=True)
class SingleAirfoilRef:
"""
Reference to a single named airfoil.
Attributes
----------
type : Literal["single"], default="single"
Schema discriminator for a single airfoil reference.
name : str, default=""
Name of the airfoil in ``WingSpec.airfoils``.
"""
type: Literal["single"] = "single"
name: str = ""
[docs]
@dataclass(slots=True)
class BlendAirfoilRef:
"""
Spanwise airfoil blend definition for a panel.
Attributes
----------
type : Literal["blend"], default="blend"
Schema discriminator for a blended airfoil reference.
method : {"pointwise", "cst", "camber_thickness"}, default="cst"
Blend strategy used between the listed stations.
stations : list[tuple[float, str]], optional
Ordered ``(eta_local, airfoil_name)`` blend stations within the panel.
"""
type: Literal["blend"] = "blend"
method: BlendMethod = "cst"
stations: list[tuple[float, str]] = field(default_factory=list)
type AirfoilRefSpec = SingleAirfoilRef | BlendAirfoilRef
[docs]
@dataclass(slots=True)
class DegreesSpec:
"""
Requested NURBS polynomial degrees.
Attributes
----------
u : int, default=4
Polynomial degree in the chordwise surface direction.
v : int, default=3
Polynomial degree in the spanwise surface direction.
"""
u: int = 4
v: int = 3
[docs]
@dataclass(slots=True)
class ControlPointSpec:
"""
Requested NURBS control-point counts.
Attributes
----------
u : int, default=16
Number of control points in the chordwise surface direction.
v : int, default=10
Number of control points in the spanwise surface direction.
"""
u: int = 16
v: int = 10
[docs]
@dataclass(slots=True)
class FitSpec:
"""
Surface fitting method for internal NURBS construction.
Attributes
----------
method : {"skin", "least_squares"}, default="skin"
Surface fitting strategy used to build the panel NURBS patch.
"""
method: FitMethod = "skin"
[docs]
@dataclass(slots=True)
class NurbsSpec:
"""
Panel-local NURBS construction controls.
Attributes
----------
degrees : DegreesSpec, optional
Requested polynomial degrees for the panel patch.
ctrlpts : ControlPointSpec, optional
Requested control-point counts for the panel patch.
fit : FitSpec, optional
Fitting strategy used during patch construction.
"""
degrees: DegreesSpec = field(default_factory=DegreesSpec)
ctrlpts: ControlPointSpec = field(default_factory=ControlPointSpec)
fit: FitSpec = field(default_factory=FitSpec)
[docs]
@dataclass(slots=True)
class VlmMeshSpec:
"""
VLM sampling controls.
Attributes
----------
n_span : int
Number of spanwise samples used for the exported VLM mesh.
n_chord : int
Number of chordwise samples used for the exported VLM mesh.
span_spacing : {"uniform", "cosine"}, default="cosine"
Spanwise spacing rule for mesh sampling.
chord_spacing : {"uniform", "cosine"}, default="cosine"
Chordwise spacing rule for mesh sampling.
"""
n_span: int
n_chord: int
span_spacing: SpacingMethod = "cosine"
chord_spacing: SpacingMethod = "cosine"
[docs]
@dataclass(slots=True)
class CfdMeshSpec:
"""
CFD surface sampling controls.
Attributes
----------
n_span : int
Number of spanwise samples used for the exported CFD surface mesh.
n_airfoil : int
Number of chordwise airfoil samples per section.
"""
n_span: int
n_airfoil: int
[docs]
@dataclass(slots=True)
class MeshSpec:
"""
Optional export sampling settings.
Attributes
----------
vlm : VlmMeshSpec or None, optional
VLM mesh export settings.
cfd : CfdMeshSpec or None, optional
CFD surface mesh export settings.
"""
vlm: VlmMeshSpec | None = None
cfd: CfdMeshSpec | None = None
[docs]
@dataclass(slots=True)
class PanelSpec:
"""
Parametric definition of a single spanwise wing panel.
Attributes
----------
id : str
Unique panel identifier within the wing definition.
eta_range : tuple[float, float]
Inclusive spanwise parameter range covered by the panel.
ref_line : RefLineSpec
Reference-axis position distributions for the panel.
chord : DistributionSpec
Spanwise chord distribution over ``eta_range``.
twist : DistributionSpec
Spanwise twist distribution over ``eta_range``.
airfoil : AirfoilRefSpec
Airfoil definition or blend applied across the panel.
nurbs : NurbsSpec or None, optional
Optional panel-local NURBS construction overrides.
mesh : MeshSpec or None, optional
Optional export mesh sampling overrides for the panel.
"""
id: str
eta_range: tuple[float, float]
ref_line: RefLineSpec
chord: DistributionSpec
twist: DistributionSpec
airfoil: AirfoilRefSpec
nurbs: NurbsSpec | None = None
mesh: MeshSpec | None = None
[docs]
@dataclass(slots=True)
class JoinSideSpec:
"""
One side of a panel-to-panel join constraint.
Attributes
----------
panel : str
Identifier of the panel participating in the join.
side : {"u_min", "u_max", "v_min", "v_max"}
Parametric side of the panel constrained by the join.
"""
panel: str
side: PanelSide
[docs]
@dataclass(slots=True)
class JoinSpec:
"""
Continuity constraint across a panel interface.
Attributes
----------
id : str
Unique identifier for the join definition.
left : JoinSideSpec
Left-hand side of the join relation.
right : JoinSideSpec
Right-hand side of the join relation.
continuity : {"C0", "G1"}
Continuity target enforced across the interface.
weight : float or None, optional
Optional relative weighting for the join constraint.
tangent_scale : float or {"auto"}, default="auto"
Tangent scaling factor used for directional continuity constraints.
"""
id: str
left: JoinSideSpec
right: JoinSideSpec
continuity: JoinContinuity
weight: float | None = None
tangent_scale: float | Literal["auto"] = "auto"
[docs]
@dataclass(slots=True)
class WingDefinitionSpec:
"""
The ``wing`` object from the documented schema.
Attributes
----------
symmetry : {"mirror_y", "none"}
Symmetry mode applied to the wing definition.
half_span : float
Half-span of the wing in the declared length units.
reference_axis : {"leading_edge", "quarter_chord", "elastic_axis"}
Reference axis used for panel placement.
twist_axis : {"leading_edge", "quarter_chord", "elastic_axis"}
Axis about which twist values are applied.
panels : list[PanelSpec]
Ordered spanwise panel definitions for the wing.
name : str or None, optional
Optional human-readable name for the wing definition.
frame : FrameSpec or None, optional
Optional axis-label metadata for documentation.
joins : list[JoinSpec], optional
Join constraints applied between neighboring panels.
"""
symmetry: SymmetryMode
half_span: float
reference_axis: ReferenceAxis
twist_axis: ReferenceAxis
panels: list[PanelSpec]
name: str | None = None
frame: FrameSpec | None = None
joins: list[JoinSpec] = field(default_factory=list)
[docs]
@dataclass(slots=True)
class WingSpec:
"""
Top-level wing geometry schema.
Attributes
----------
schema_version : int
Version number of the serialized schema format.
units : UnitsSpec
Unit declarations for dimensional and angular values.
wing : WingDefinitionSpec
Wing geometry definition.
airfoils : dict[str, AirfoilDefinitionSpec], optional
Named airfoil library referenced by the wing panels.
"""
schema_version: int
units: UnitsSpec
wing: WingDefinitionSpec
airfoils: dict[str, AirfoilDefinitionSpec] = field(default_factory=dict)
__all__ = [
"AirfoilRefSpec",
"BlendAirfoilRef",
"BlendMethod",
"CfdMeshSpec",
"ControlPointSpec",
"DegreesSpec",
"DistributionSpec",
"FitMethod",
"FitSpec",
"FrameSpec",
"JoinContinuity",
"JoinSideSpec",
"JoinSpec",
"MeshSpec",
"NurbsSpec",
"PanelSide",
"PanelSpec",
"PiecewiseLinearDistribution",
"RefLineSpec",
"ReferenceAxis",
"SingleAirfoilRef",
"SpacingMethod",
"SymmetryMode",
"UnitsSpec",
"VlmMeshSpec",
"WingDefinitionSpec",
"WingSpec",
]