Source code for buffalo_wings.wing.internal.wing_schema

"""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.""" #: Length unit used throughout the serialized schema. length: LengthUnit = "m" #: Angle unit used throughout the serialized schema. angle: AngleUnit = "deg"
[docs] @dataclass(slots=True) class FrameSpec: """Human-readable axis labels for the wing coordinate frame.""" #: Label describing the positive ``x`` direction. x: str = "forward" #: Label describing the positive ``y`` direction. y: str = "right" #: Label describing the positive ``z`` direction. z: str = "up"
[docs] @dataclass(slots=True) class PiecewiseLinearDistribution: """Piecewise-linear scalar distribution over ``eta``.""" #: Schema discriminator for a piecewise-linear distribution. type: Literal["piecewise_linear"] = "piecewise_linear" #: Ordered ``(eta, value)`` pairs defining the distribution. 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.""" #: Spanwise distribution of the reference-line ``x`` position. x_ref: DistributionSpec #: Spanwise distribution of the reference-line ``z`` position. z_ref: DistributionSpec
[docs] @dataclass(slots=True) class SingleAirfoilRef: """Reference to a single named airfoil.""" #: Schema discriminator for a single-airfoil reference. type: Literal["single"] = "single" #: Name of the referenced airfoil in the top-level ``airfoils`` map. name: str = ""
[docs] @dataclass(slots=True) class BlendAirfoilRef: """Spanwise airfoil blend definition for a panel.""" #: Schema discriminator for a blended-airfoil reference. type: Literal["blend"] = "blend" #: Blend method used to transition between named stations. method: BlendMethod = "cst" #: Ordered list of ``(eta, airfoil_name)`` blend stations. stations: list[tuple[float, str]] = field(default_factory=list)
type AirfoilRefSpec = SingleAirfoilRef | BlendAirfoilRef
[docs] @dataclass(slots=True) class DegreesSpec: """Requested NURBS polynomial degrees.""" #: Polynomial degree in the chordwise ``u`` direction. u: int = 4 #: Polynomial degree in the spanwise ``v`` direction. v: int = 3
[docs] @dataclass(slots=True) class ControlPointSpec: """Requested NURBS control-point counts.""" #: Control-point count in the chordwise ``u`` direction. u: int = 16 #: Control-point count in the spanwise ``v`` direction. v: int = 10
[docs] @dataclass(slots=True) class FitSpec: """Surface fitting method for internal NURBS construction.""" #: Surface fitting algorithm used during NURBS construction. method: FitMethod = "skin"
[docs] @dataclass(slots=True) class NurbsSpec: """Panel-local NURBS construction controls.""" #: Requested polynomial degrees for the fitted surface. degrees: DegreesSpec = field(default_factory=DegreesSpec) #: Requested control-point counts for the fitted surface. ctrlpts: ControlPointSpec = field(default_factory=ControlPointSpec) #: Fitting method used to construct the panel surface. fit: FitSpec = field(default_factory=FitSpec)
[docs] @dataclass(slots=True) class VlmMeshSpec: """VLM sampling controls.""" #: Number of spanwise VLM panels. n_span: int #: Number of chordwise VLM panels. n_chord: int #: Spanwise spacing rule for the VLM mesh. span_spacing: SpacingMethod = "cosine" #: Chordwise spacing rule for the VLM mesh. chord_spacing: SpacingMethod = "cosine"
[docs] @dataclass(slots=True) class CfdMeshSpec: """CFD surface sampling controls.""" #: Number of spanwise CFD samples. n_span: int #: Number of airfoil-surface samples per section. n_airfoil: int
[docs] @dataclass(slots=True) class MeshSpec: """Optional export sampling settings.""" #: Optional VLM mesh sampling settings. vlm: VlmMeshSpec | None = None #: Optional CFD surface sampling settings. cfd: CfdMeshSpec | None = None
[docs] @dataclass(slots=True) class PanelSpec: """Parametric definition of a single spanwise wing panel.""" #: Unique panel identifier. id: str #: Closed spanwise ``eta`` interval covered by the panel. eta_range: tuple[float, float] #: Reference-line position distributions for the panel. ref_line: RefLineSpec #: Chord distribution over the panel span. chord: DistributionSpec #: Twist distribution over the panel span. twist: DistributionSpec #: Airfoil reference or blend assigned to the panel. airfoil: AirfoilRefSpec #: Optional NURBS construction controls. nurbs: NurbsSpec | None = None #: Optional mesh export controls. mesh: MeshSpec | None = None
[docs] @dataclass(slots=True) class JoinSideSpec: """One side of a panel-to-panel join constraint.""" #: Panel identifier participating in the join. panel: str #: Boundary side of that panel used in the join. side: PanelSide
[docs] @dataclass(slots=True) class JoinSpec: """Continuity constraint across a panel interface.""" #: Unique join identifier. id: str #: Left-hand side of the join relationship. left: JoinSideSpec #: Right-hand side of the join relationship. right: JoinSideSpec #: Requested continuity level across the join. continuity: JoinContinuity #: Optional enforcement weight for the join. weight: float | None = None #: Tangent scaling used for ``G1`` joins. tangent_scale: float | Literal["auto"] = "auto"
[docs] @dataclass(slots=True) class WingDefinitionSpec: """The ``wing`` object from the documented schema.""" #: Symmetry mode for the wing definition. symmetry: SymmetryMode #: Half-span of the modeled wing. half_span: float #: Reference axis used to position sections along the span. reference_axis: ReferenceAxis #: Axis about which section twist is applied. twist_axis: ReferenceAxis #: Ordered list of spanwise wing panels. panels: list[PanelSpec] #: Optional human-readable wing name. name: str | None = None #: Optional human-readable frame labels. frame: FrameSpec | None = None #: Optional continuity constraints between adjacent panels. joins: list[JoinSpec] = field(default_factory=list)
[docs] @dataclass(slots=True) class WingSpec: """Top-level wing geometry schema.""" #: Schema version number for the serialized wing definition. schema_version: int #: Units block used by the serialized schema. units: UnitsSpec #: Wing definition payload. wing: WingDefinitionSpec #: Named airfoils referenced by the wing definition. airfoils: dict[str, AirfoilDefinitionSpec] = field(default_factory=dict)