"""Cylinder implementation used as airfoil geometry."""
import numpy as np
from buffalo_wings.internal.numeric import as_float_array
from buffalo_wings.type_aliases import FloatArray, FloatInput
from .airfoil import Airfoil
[docs]
class Cylinder(Airfoil):
"""Cylindrical 2D airfoil."""
[docs]
def __init__(self, radius: float) -> None:
"""
Initialize the cylinder radius.
Parameters
----------
radius : float
Radius of the cylinder.
"""
super().__init__()
self._r = radius
@property
def radius(self) -> float:
"""
Return the cylinder radius.
Returns
-------
float
Radius of the cylinder.
"""
return self._r
@radius.setter
def radius(self, radius: float) -> None:
"""
Set the cylinder radius.
Parameters
----------
radius : float
New cylinder radius.
"""
self._r = radius
[docs]
def xy(self, t: FloatInput) -> tuple[FloatArray, FloatArray]:
"""
Calculate the coordinates of geometry at parameter location.
Notes
-----
Parameter goes from -1 (trailing edge lower surface) to +1 (trailing
edge upper surface) with 0 representing the leading edge.
Parameters
----------
t : numpy.ndarray
Parameter for desired locations.
Returns
-------
numpy.ndarray
X-coordinate of point.
numpy.ndarray
Y-coordinate of point.
"""
theta = self._convert_theta(t)
x = self.radius * (1 + np.cos(theta))
y = self.radius * np.sin(theta)
return x, y
[docs]
def xy_t(self, t: FloatInput) -> tuple[FloatArray, FloatArray]:
"""
Calculate rates of change of the coordinates at parameter location.
Notes
-----
Parameter goes from -1 (trailing edge lower surface) to +1 (trailing
edge upper surface) with 0 representing the leading edge.
Parameters
----------
t : numpy.ndarray
Parameter for desired locations.
Returns
-------
numpy.ndarray
Parametric rate of change of the x-coordinate of point.
numpy.ndarray
Parametric rate of change of the y-coordinate of point.
"""
theta = self._convert_theta(t)
x_t = np.pi * self.radius * np.sin(theta)
y_t = -np.pi * self.radius * np.cos(theta)
return x_t, y_t
[docs]
def xy_tt(self, t: FloatInput) -> tuple[FloatArray, FloatArray]:
"""
Return second derivative of the coordinates at parameter location.
Notes
-----
Parameter goes from -1 (trailing edge lower surface) to +1 (trailing
edge upper surface) with 0 representing the leading edge.
Parameters
----------
t : numpy.ndarray
Parameter for desired locations.
Returns
-------
numpy.ndarray
Parametric second derivative of the x-coordinate of point.
numpy.ndarray
Parametric second derivative of the y-coordinate of point.
"""
theta = self._convert_theta(t)
x_tt = -(np.pi**2) * self.radius * np.cos(theta)
y_tt = -(np.pi**2) * self.radius * np.sin(theta)
return x_tt, y_tt
[docs]
@staticmethod
def camber_location(
t: FloatInput,
) -> tuple[FloatArray, FloatArray]:
"""
Return the amount of camber at specified parameter location.
Parameters
----------
t : numpy.ndarray
Parameter location of interest.
Returns
-------
numpy.ndarray
X-coordinate of camber at specified point.
numpy.ndarray
Y-coordinate of camber at specified point.
"""
t_array = as_float_array(t)
return t_array, np.zeros_like(t_array)
[docs]
def thickness_value(self, t: FloatInput) -> FloatArray:
"""
Return the amount of thickness at specified parameter location.
Parameters
----------
t : numpy.ndarray
Parameter location of interest.
Returns
-------
numpy.ndarray
Thickness at specified point.
"""
return self.xy(t)[1]
[docs]
def joints(self) -> list[float]: # noqa: PLR6301
"""
Return the locations of any joints/discontinuities in the curve.
Returns
-------
List[float]
Parametric coordinates of any discontinuities.
"""
return [-1.0, 1.0]
@staticmethod
def _convert_theta(t: FloatInput) -> FloatArray:
"""
Convert the airfoil parameter to the cylinder polar angle.
Parameters
----------
t : FloatArray
Signed airfoil parameter values in ``[-1, 1]``.
Returns
-------
FloatArray
Polar angle values in radians.
"""
t_array = as_float_array(t)
return np.pi * (1 - t_array)