"""Analytic and coefficient-based airfoil schema dataclasses."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Literal
from buffalo_core.schema import SchemaField
from .common import Point2DSpec
from .constants import POINT2D_TUPLE_LENGTH
[docs]
@dataclass(slots=True)
class FlatPlateAirfoilSpec:
"""Schema definition for a flat-plate airfoil."""
#: Schema discriminator for a flat-plate airfoil.
type: Literal["flat_plate"] = field(
default="flat_plate",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a flat-plate airfoil.",
default="flat_plate",
choices=("flat_plate",),
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class BiconvexAirfoilParamsSpec:
"""Explicit parameter definition for a biconvex airfoil."""
#: Maximum thickness as a fraction of chord.
max_thickness: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Maximum Thickness",
order=10,
short_help="Maximum thickness as a fraction of chord.",
default=0.0,
minimum=0.0,
maximum=1.0,
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class BiconvexAirfoilSpec:
"""Schema definition for a circular-arc biconvex airfoil."""
#: Schema discriminator for a circular-arc biconvex airfoil.
type: Literal["biconvex"] = field(
default="biconvex",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a biconvex airfoil.",
default="biconvex",
choices=("biconvex",),
).to_metadata(),
)
#: Explicit parameter form for the biconvex airfoil.
params: BiconvexAirfoilParamsSpec = field(
default_factory=BiconvexAirfoilParamsSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Parameters",
order=20,
short_help="Explicit parameter block for the biconvex airfoil.",
item_kind="BiconvexAirfoilParamsSpec",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class BiconvexParabolaAirfoilParamsSpec:
"""Explicit parameter definition for a parabolic biconvex airfoil."""
#: Maximum thickness as a fraction of chord.
max_thickness: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Maximum Thickness",
order=10,
short_help="Maximum thickness as a fraction of chord.",
default=0.0,
minimum=0.0,
maximum=1.0,
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class BiconvexParabolaAirfoilSpec:
"""Schema definition for a parabolic biconvex airfoil."""
#: Schema discriminator for a parabolic biconvex airfoil.
type: Literal["biconvex_parabola"] = field(
default="biconvex_parabola",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help=(
"Schema discriminator for a parabolic biconvex airfoil."
),
default="biconvex_parabola",
choices=("biconvex_parabola",),
).to_metadata(),
)
#: Explicit parameter form for the parabolic biconvex airfoil.
params: BiconvexParabolaAirfoilParamsSpec = field(
default_factory=BiconvexParabolaAirfoilParamsSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Parameters",
order=20,
short_help="Explicit parameter block for the parabolic family.",
item_kind="BiconvexParabolaAirfoilParamsSpec",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class PolygonAirfoilParamsSpec:
"""Explicit parameter definition for a polygonal airfoil."""
#: Ordered polygon vertices connected by straight segments.
vertices: list[Point2DSpec] = field(
default_factory=list,
metadata=SchemaField(
value_kind="list",
required=False,
label="Vertices",
order=10,
short_help="Ordered polygon vertices connected by segments.",
min_items=3,
item_kind="Point2DSpec",
tuple_length=POINT2D_TUPLE_LENGTH,
format_hint="[(x, y), ...]",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class PolygonAirfoilSpec:
"""Schema definition for a polygonal airfoil."""
#: Schema discriminator for a polygonal airfoil.
type: Literal["polygon"] = field(
default="polygon",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a polygonal airfoil.",
default="polygon",
choices=("polygon",),
).to_metadata(),
)
#: Explicit parameter form for the polygonal airfoil.
params: PolygonAirfoilParamsSpec = field(
default_factory=PolygonAirfoilParamsSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Parameters",
order=20,
short_help="Polygon vertex payload.",
item_kind="PolygonAirfoilParamsSpec",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class EllipseAirfoilParamsSpec:
"""Explicit parameter definition for an elliptical airfoil."""
#: Maximum thickness as a fraction of chord.
max_thickness: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Maximum Thickness",
order=10,
short_help="Maximum thickness as a fraction of chord.",
default=0.0,
exclusive_minimum=0.0,
maximum=1.0,
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class EllipseAirfoilSpec:
"""Schema definition for an elliptical airfoil."""
#: Schema discriminator for an elliptical airfoil.
type: Literal["ellipse"] = field(
default="ellipse",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for an elliptical airfoil.",
default="ellipse",
choices=("ellipse",),
).to_metadata(),
)
#: Explicit parameter form for the elliptical airfoil.
params: EllipseAirfoilParamsSpec = field(
default_factory=EllipseAirfoilParamsSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Parameters",
order=20,
short_help="Explicit parameter block for the ellipse.",
item_kind="EllipseAirfoilParamsSpec",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class CircularArcAirfoilParamsSpec:
"""Explicit parameter definition for a circular-arc airfoil."""
#: Maximum thickness as a fraction of chord.
max_thickness: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Maximum Thickness",
order=10,
short_help="Maximum thickness as a fraction of chord.",
default=0.0,
minimum=0.0,
maximum=1.0,
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class CircularArcAirfoilSpec:
"""Schema definition for a circular-arc airfoil."""
#: Schema discriminator for a circular-arc airfoil.
type: Literal["circular_arc"] = field(
default="circular_arc",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a circular-arc airfoil.",
default="circular_arc",
choices=("circular_arc",),
).to_metadata(),
)
#: Explicit parameter form for the circular-arc airfoil.
params: CircularArcAirfoilParamsSpec = field(
default_factory=CircularArcAirfoilParamsSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Parameters",
order=20,
short_help="Explicit parameter block for the circular arc.",
item_kind="CircularArcAirfoilParamsSpec",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class JoukowskiAirfoilParamsSpec:
"""Explicit parameter definition for a Joukowski airfoil."""
#: Joukowski camber-like shape parameter.
nu: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Nu",
order=10,
short_help="Joukowski camber-like shape parameter.",
default=0.0,
).to_metadata(),
)
#: Joukowski thickness-like shape parameter.
epsilon: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Epsilon",
order=20,
short_help="Joukowski thickness-like shape parameter.",
default=0.0,
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class JoukowskiAirfoilSpec:
"""Schema definition for a Joukowski airfoil."""
#: Schema discriminator for a Joukowski airfoil.
type: Literal["joukowski"] = field(
default="joukowski",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a Joukowski airfoil.",
default="joukowski",
choices=("joukowski",),
).to_metadata(),
)
#: Explicit parameter form for the Joukowski airfoil.
params: JoukowskiAirfoilParamsSpec = field(
default_factory=JoukowskiAirfoilParamsSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Parameters",
order=20,
short_help="Explicit parameter block for the Joukowski map.",
item_kind="JoukowskiAirfoilParamsSpec",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class CstSurfaceSpec:
"""CST coefficient set for one airfoil surface."""
#: Leading-edge class-function exponent.
n1: float = field(
default=0.5,
metadata=SchemaField(
value_kind="number",
required=False,
label="N1",
order=10,
short_help="Leading-edge class-function exponent.",
default=0.5,
minimum=0.0,
).to_metadata(),
)
#: Trailing-edge class-function exponent.
n2: float = field(
default=1.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="N2",
order=20,
short_help="Trailing-edge class-function exponent.",
default=1.0,
minimum=0.0,
).to_metadata(),
)
#: Bernstein polynomial coefficients for the surface shape.
a: list[float] = field(
default_factory=list,
metadata=SchemaField(
value_kind="list",
required=False,
label="Coefficients",
order=30,
short_help="Bernstein polynomial coefficients for the surface.",
item_kind="number",
format_hint="[a0, a1, ...]",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class CstAirfoilSpec:
"""Schema definition for a CST airfoil."""
#: Schema discriminator for a CST airfoil.
type: Literal["cst"] = field(
default="cst",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a CST airfoil.",
default="cst",
choices=("cst",),
).to_metadata(),
)
#: Explicit trailing-edge gap as a fraction of chord.
trailing_edge_thickness: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Trailing Edge Thickness",
order=20,
short_help="Trailing-edge gap as a fraction of chord.",
default=0.0,
minimum=0.0,
).to_metadata(),
)
#: CST coefficients for the upper surface.
upper: CstSurfaceSpec = field(
default_factory=CstSurfaceSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Upper Surface",
order=30,
short_help="Upper-surface CST coefficient block.",
item_kind="CstSurfaceSpec",
).to_metadata(),
)
#: CST coefficients for the lower surface.
lower: CstSurfaceSpec = field(
default_factory=CstSurfaceSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Lower Surface",
order=40,
short_help="Lower-surface CST coefficient block.",
item_kind="CstSurfaceSpec",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class ParsecLeadingEdgeRadiusSpec:
"""PARSEC leading-edge radius inputs."""
#: Upper-surface leading-edge radius parameter.
upper: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Upper Radius",
order=10,
short_help="Upper-surface leading-edge radius parameter.",
default=0.0,
exclusive_minimum=0.0,
).to_metadata(),
)
#: Lower-surface leading-edge radius parameter.
lower: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Lower Radius",
order=20,
short_help="Lower-surface leading-edge radius parameter.",
default=0.0,
exclusive_minimum=0.0,
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class ParsecTrailingEdgeSpec:
"""PARSEC trailing-edge geometry inputs."""
#: Trailing-edge thickness.
thickness: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Thickness",
order=10,
short_help="Trailing-edge thickness.",
default=0.0,
minimum=0.0,
).to_metadata(),
)
#: Trailing-edge vertical offset.
location: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Offset",
order=20,
short_help="Trailing-edge vertical offset.",
default=0.0,
).to_metadata(),
)
#: Trailing-edge direction angle in degrees.
direction_angle: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Direction Angle",
order=30,
short_help="Trailing-edge direction angle in degrees.",
default=0.0,
format_hint="degrees",
).to_metadata(),
)
#: Trailing-edge wedge angle in degrees.
wedge_angle: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Wedge Angle",
order=40,
short_help="Trailing-edge wedge angle in degrees.",
default=0.0,
format_hint="degrees",
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class ParsecSurfaceExtremumSpec:
"""PARSEC surface extremum constraint."""
#: ``(x, z)`` location of the surface extremum.
location: Point2DSpec = field(
default=(0.0, 0.0),
metadata=SchemaField(
value_kind="tuple",
required=False,
label="Location",
order=10,
short_help="Extremum point stored as an (x, y) pair.",
default=(0.0, 0.0),
tuple_length=POINT2D_TUPLE_LENGTH,
item_kind="number",
format_hint="(x, y)",
).to_metadata(),
)
#: Surface curvature at the extremum location.
curvature: float = field(
default=0.0,
metadata=SchemaField(
value_kind="number",
required=False,
label="Curvature",
order=20,
short_help="Surface curvature at the extremum location.",
default=0.0,
).to_metadata(),
)
[docs]
@dataclass(slots=True)
class ParsecAirfoilSpec:
"""Schema definition for a PARSEC airfoil."""
#: Schema discriminator for a PARSEC airfoil.
type: Literal["parsec"] = field(
default="parsec",
metadata=SchemaField(
value_kind="enum",
required=False,
label="Type",
order=10,
short_help="Schema discriminator for a PARSEC airfoil.",
default="parsec",
choices=("parsec",),
).to_metadata(),
)
#: Upper and lower leading-edge radius parameters.
leading_edge_radius: ParsecLeadingEdgeRadiusSpec = field(
default_factory=ParsecLeadingEdgeRadiusSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Leading Edge Radius",
order=20,
short_help="Upper and lower leading-edge radius inputs.",
item_kind="ParsecLeadingEdgeRadiusSpec",
).to_metadata(),
)
#: Trailing-edge geometry constraints.
trailing_edge: ParsecTrailingEdgeSpec = field(
default_factory=ParsecTrailingEdgeSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Trailing Edge",
order=30,
short_help="Trailing-edge geometry constraints.",
item_kind="ParsecTrailingEdgeSpec",
).to_metadata(),
)
#: Constraint for the upper-surface maximum.
upper_surface_max: ParsecSurfaceExtremumSpec = field(
default_factory=ParsecSurfaceExtremumSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Upper Surface Maximum",
order=40,
short_help="Constraint for the upper-surface extremum.",
item_kind="ParsecSurfaceExtremumSpec",
).to_metadata(),
)
#: Constraint for the lower-surface minimum.
lower_surface_min: ParsecSurfaceExtremumSpec = field(
default_factory=ParsecSurfaceExtremumSpec,
metadata=SchemaField(
value_kind="object",
required=False,
label="Lower Surface Minimum",
order=50,
short_help="Constraint for the lower-surface extremum.",
item_kind="ParsecSurfaceExtremumSpec",
).to_metadata(),
)