Source code for buffalo_wings.wing.internal.wing_canonical_core

"""Core ``WingCanonical`` orchestration and validation."""

from __future__ import annotations

from buffalo_core.typing import FloatScalar

from .wing_canonical_distribution import WingCanonicalDistributionMixin
from .wing_canonical_sections import WingCanonicalSectionMixin
from .wing_schema import PanelSpec, WingSpec

_MIN_STATION_COUNT = 2


[docs] class WingCanonical( WingCanonicalDistributionMixin, WingCanonicalSectionMixin, ): """ Canonical evaluator for wing-section placement and sampling. Parameters ---------- spec : WingSpec Parsed wing schema used for panel evaluation and section sampling. Raises ------ ValueError If the configured reference-axis and twist-axis combination is not supported by the current implementation. """ def __init__(self, spec: WingSpec) -> None: """ Store the parsed wing specification and validate axis choices. Parameters ---------- spec : WingSpec Parsed wing schema used for panel evaluation and section sampling. Raises ------ ValueError If the configured reference-axis and twist-axis combination is not supported by the current implementation. """ self._spec = spec self._panel_map = {panel.id: panel for panel in spec.wing.panels} self._validate_axes()
[docs] @classmethod def from_spec(cls, spec: WingSpec) -> WingCanonical: """ Build a canonical evaluator from a parsed ``WingSpec``. Parameters ---------- spec : WingSpec Parsed wing schema used for panel evaluation and section sampling. Returns ------- WingCanonical Canonical evaluator backed by ``spec``. Raises ------ ValueError If the configured reference-axis and twist-axis combination is not supported by the current implementation. """ return cls(spec)
@property def spec(self) -> WingSpec: """ Return the underlying wing specification. Returns ------- WingSpec Wing schema used by the evaluator. """ return self._spec def _validate_axes(self) -> None: """ Reject unsupported reference-axis and twist-axis combinations. Returns ------- None This method validates the stored wing specification in place. Raises ------ ValueError If the configured axes are unsupported by the canonical evaluator. """ reference_axis = self._spec.wing.reference_axis twist_axis = self._spec.wing.twist_axis if reference_axis == "elastic_axis" or twist_axis == "elastic_axis": msg = ( "elastic_axis is not yet supported because the schema does " "not define its chordwise location." ) raise ValueError(msg) if reference_axis != twist_axis: msg = ( "WingCanonical currently requires reference_axis and " "twist_axis to match." ) raise ValueError(msg) def _get_panel(self, panel_id: str) -> PanelSpec: """ Return the panel definition for ``panel_id``. Parameters ---------- panel_id : str Identifier of the panel to retrieve. Returns ------- PanelSpec Panel definition matching ``panel_id``. Raises ------ KeyError If ``panel_id`` does not match a known panel. """ try: return self._panel_map[panel_id] except KeyError as exc: msg = f"Unknown panel id: {panel_id}" raise KeyError(msg) from exc @staticmethod def _validate_eta(panel: PanelSpec, eta: FloatScalar) -> None: """ Ensure ``eta`` lies within the panel spanwise interval. Parameters ---------- panel : PanelSpec Panel whose spanwise interval should contain ``eta``. eta : FloatScalar Spanwise parameter to validate. Returns ------- None This method validates the inputs in place. Raises ------ ValueError If ``eta`` lies outside ``panel.eta_range``. """ eta0, eta1 = panel.eta_range if eta < eta0 or eta > eta1: msg = ( f"eta={eta} lies outside panel {panel.id!r} range " f"[{eta0}, {eta1}]." ) raise ValueError(msg)