"""Point-backed and file-backed airfoil schema dataclasses."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Literal
from buffalo_core.schema import SchemaChoice, SchemaField
from .common import Point2DSpec
from .constants import POINT2D_TUPLE_LENGTH
[docs]
@dataclass(slots=True)
class FileAirfoilSpec:
"""Schema dataclass for a file-backed airfoil definition."""
#: Schema discriminator for a file-backed airfoil definition.
type: Literal["file"] = field(
default="file",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a file-backed airfoil.",
default="file",
choices=("file",),
).to_metadata(),
)
#: Path to the file containing the airfoil definition.
path: str = field(
default="",
metadata=SchemaField(
value_kind="string",
required=False,
label="Path",
order=20,
short_help="Path to the source file containing the airfoil.",
default="",
format_hint="relative/or/absolute/path",
notes="Validation requires a non-empty path.",
).to_metadata(),
)
#: File format used to parse the airfoil definition.
format: Literal[
"auto",
"lednicer",
"selig",
"surface_curve",
"upper_lower",
] = field(
default="auto",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Format",
order=30,
short_help="Expected file payload format or auto-detection mode.",
default="auto",
choices=(
"auto",
"lednicer",
"selig",
SchemaChoice(
value="surface_curve",
label="Surface Curve",
),
SchemaChoice(
value="upper_lower",
label="Upper/Lower",
),
),
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class PointsAirfoilSpec:
"""Airfoil schema defined directly from inline point coordinates."""
#: Schema discriminator for an inline point-defined airfoil.
type: Literal["points"] = field(
default="points",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for inline point data.",
default="points",
choices=("points",),
).to_metadata(),
)
#: Point-layout convention used by the inline coordinate payload.
format: Literal["surface_curve", "upper_lower"] = field(
default="surface_curve",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Format",
order=20,
short_help="Inline point layout convention.",
default="surface_curve",
choices=(
SchemaChoice(
value="surface_curve",
label="Surface Curve",
),
SchemaChoice(
value="upper_lower",
label="Upper/Lower",
),
),
).to_metadata(),
)
#: Leading-edge split index for ``surface_curve`` point ordering.
leading_edge: int | None = field(
default=None,
metadata=SchemaField(
value_kind="integer",
required=False,
label="Leading Edge Index",
order=30,
short_help="Leading-edge split index for surface-curve points.",
minimum=0,
notes=(
"Required when format is surface_curve and unused for "
"upper_lower payloads."
),
).to_metadata(),
)
#: Single ordered surface walk when ``format == "surface_curve"``.
points: list[Point2DSpec] = field(
default_factory=list,
metadata=SchemaField(
value_kind="list",
required=False,
label="Points",
order=40,
short_help="Single ordered surface walk around the airfoil.",
min_items=3,
item_kind="Point2DSpec",
tuple_length=POINT2D_TUPLE_LENGTH,
format_hint="[(x, y), ...]",
notes=(
"Used when format is surface_curve; points should trace one "
"continuous surface walk."
),
).to_metadata(),
)
#: Upper-surface points when ``format == "upper_lower"``.
upper: list[Point2DSpec] = field(
default_factory=list,
metadata=SchemaField(
value_kind="list",
required=False,
label="Upper Surface",
order=50,
short_help="Upper-surface points from leading to trailing edge.",
min_items=2,
item_kind="Point2DSpec",
tuple_length=POINT2D_TUPLE_LENGTH,
format_hint="[(x, y), ...]",
notes="Used when format is upper_lower.",
).to_metadata(),
)
#: Lower-surface points when ``format == "upper_lower"``.
lower: list[Point2DSpec] = field(
default_factory=list,
metadata=SchemaField(
value_kind="list",
required=False,
label="Lower Surface",
order=60,
short_help="Lower-surface points from leading to trailing edge.",
min_items=2,
item_kind="Point2DSpec",
tuple_length=POINT2D_TUPLE_LENGTH,
format_hint="[(x, y), ...]",
notes="Used when format is upper_lower.",
).to_metadata(),
)
@dataclass(slots=True)
class CstSurfaceSpec:
"""CST coefficient set for one airfoil surface."""
#: Leading-edge class-function exponent.
n1: float = 0.5
#: Trailing-edge class-function exponent.
n2: float = 1.0
#: Bernstein polynomial coefficients for the surface shape.
a: list[float] = field(default_factory=list)
@dataclass(slots=True)
class CstAirfoilSpec:
"""CST airfoil schema definition."""
#: Schema discriminator for a CST airfoil.
type: Literal["cst"] = "cst"
#: Explicit trailing-edge gap as a fraction of chord.
trailing_edge_thickness: float = 0.0
#: CST coefficients for the upper surface.
upper: CstSurfaceSpec = field(default_factory=CstSurfaceSpec)
#: CST coefficients for the lower surface.
lower: CstSurfaceSpec = field(default_factory=CstSurfaceSpec)