aerosandbox.geometry.airfoil#

Submodules#

Package Contents#

Classes#

Airfoil

An airfoil. See constructor docstring for usage details.

KulfanAirfoil

An airfoil. See constructor docstring for usage details.

class aerosandbox.geometry.airfoil.Airfoil(name='Untitled', coordinates=None, **deprecated_keyword_arguments)[source]#

Bases: aerosandbox.geometry.polygon.Polygon

An airfoil. See constructor docstring for usage details.

Parameters:
  • name (str) –

  • coordinates (Union[None, str, pathlib.Path, aerosandbox.numpy.ndarray]) –

__repr__()[source]#

Return repr(self).

Return type:

str

to_kulfan_airfoil(n_weights_per_side=8, N1=0.5, N2=1.0, normalize_coordinates=True, use_leading_edge_modification=True)[source]#
Parameters:
  • n_weights_per_side (int) –

  • N1 (float) –

  • N2 (float) –

  • normalize_coordinates (bool) –

  • use_leading_edge_modification (bool) –

Return type:

aerosandbox.geometry.airfoil.kulfan_airfoil.KulfanAirfoil

generate_polars(alphas=np.linspace(-13, 13, 27), Res=np.geomspace(1000.0, 100000000.0, 12), cache_filename=None, xfoil_kwargs=None, unstructured_interpolated_model_kwargs=None, include_compressibility_effects=True, transonic_buffet_lift_knockdown=0.3, make_symmetric_polars=False)[source]#

Generates airfoil polar surrogate models (CL, CD, CM functions) from XFoil data and assigns them in-place to this Airfoil’s polar functions.

In other words, when this function is run, the following functions will be added (or overwritten) to the instance:
  • Airfoil.CL_function(alpha, Re, mach)

  • Airfoil.CD_function(alpha, Re, mach)

  • Airfoil.CM_function(alpha, Re, mach)

Where alpha is in degrees.

Warning: In-place operation! Modifies this Airfoil object by setting Airfoil.CL_function, etc. to the new polars.

Parameters:
  • alphas – The range of alphas to sample from XFoil at. Given in degrees.

  • Res – The range of Reynolds numbers to sample from XFoil at. Dimensionless.

  • cache_filename (str) –

    A path-like filename (ideally a “*.json” file) that can be used to cache the XFoil results, making it much faster to regenerate the results.

    • If the file does not exist, XFoil will be run, and a cache file will be created.

    • If the file does exist, XFoil will not be run, and the cache file will be read instead.

  • xfoil_kwargs (Dict[str, Any]) – Keyword arguments to pass into the AeroSandbox XFoil module. See the aerosandbox.XFoil constructor for options.

  • unstructured_interpolated_model_kwargs (Dict[str, Any]) – Keyword arguments to pass into the UnstructuredInterpolatedModels that contain the polars themselves. See the aerosandbox.UnstructuredInterpolatedModel constructor for options.

  • include_compressibility_effects (bool) – Includes compressibility effects in the polars, such as wave drag, mach tuck, CL effects across normal shocks. Note that accuracy here is dubious in the transonic regime and above - you should really specify your own CL/CD/CM models

  • transonic_buffet_lift_knockdown (float) –

  • make_symmetric_polars (bool) –

Return type:

None

Returns: None (in-place), adds the following functions to the instance:

  • Airfoil.CL_function(alpha, Re, mach)

  • Airfoil.CD_function(alpha, Re, mach)

  • Airfoil.CM_function(alpha, Re, mach)

get_aero_from_neuralfoil(alpha, Re, mach=0.0, n_crit=9.0, xtr_upper=1.0, xtr_lower=1.0, model_size='large', control_surfaces=None, include_360_deg_effects=True)[source]#
Parameters:
  • alpha (Union[float, aerosandbox.numpy.ndarray]) –

  • Re (Union[float, aerosandbox.numpy.ndarray]) –

  • mach (Union[float, aerosandbox.numpy.ndarray]) –

  • n_crit (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_upper (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_lower (Union[float, aerosandbox.numpy.ndarray]) –

  • model_size (str) –

  • control_surfaces (List[ControlSurface]) –

  • include_360_deg_effects (bool) –

Return type:

Dict[str, Union[float, aerosandbox.numpy.ndarray]]

plot_polars(alphas=np.linspace(-20, 20, 500), Res=10**np.arange(3, 9), mach=0.0, show=True, Re_colors=None)[source]#
Parameters:
  • alphas (Union[aerosandbox.numpy.ndarray, List[float]]) –

  • Res (Union[aerosandbox.numpy.ndarray, List[float]]) –

  • mach (float) –

  • show (bool) –

Return type:

None

local_camber(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local camber of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the camber at [1D array, more generally, an iterable of floats]

Returns:

Local camber of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

local_thickness(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local thickness of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the thickness at [1D array, more generally, an iterable of floats]

Returns:

Local thickness of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

max_camber(x_over_c_sample=np.linspace(0, 1, 101))[source]#

Returns the maximum camber of the airfoil.

Parameters:

x_over_c_sample (aerosandbox.numpy.ndarray) – Where should the airfoil be sampled to determine the max camber?

Return type:

float

Returns: The maximum thickness, as a fraction of chord.

max_thickness(x_over_c_sample=np.linspace(0, 1, 101))[source]#

Returns the maximum thickness of the airfoil.

Parameters:

x_over_c_sample (aerosandbox.numpy.ndarray) – Where should the airfoil be sampled to determine the max thickness?

Return type:

float

Returns: The maximum thickness, as a fraction of chord.

draw(draw_mcl=False, draw_markers=True, backend='matplotlib', show=True)[source]#

Draw the airfoil object.

Parameters:
  • draw_mcl – Should we draw the mean camber line (MCL)? [boolean]

  • backend – Which backend should we use? “plotly” or “matplotlib”

  • show – Should we show the plot? [boolean]

Return type:

None

Returns: None

LE_index()[source]#

Returns the index of the leading edge point in the airfoil coordinates.

Return type:

int

lower_coordinates()[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the lower surface of the airfoil.

Order is from the leading edge to the trailing edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.upper_coordinates().

Return type:

aerosandbox.numpy.ndarray

upper_coordinates()[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the upper surface of the airfoil.

Order is from the trailing edge to the leading edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.lower_coordinates().

Return type:

aerosandbox.numpy.ndarray

LE_radius(softness=1e-06)[source]#
Parameters:

softness (float) –

TE_thickness()[source]#

Returns the thickness of the trailing edge of the airfoil.

Return type:

float

TE_angle()[source]#

Returns the trailing edge angle of the airfoil, in degrees.

Return type:

float

repanel(n_points_per_side=100, spacing_function_per_side=np.cosspace)[source]#

Returns a repaneled copy of the airfoil with cosine-spaced coordinates on the upper and lower surfaces.

Parameters:
  • n_points_per_side (int) –

    Number of points per side (upper and lower) of the airfoil [int]

    Notes: The number of points defining the final airfoil will be n_points_per_side * 2 - 1, since one point (the leading edge point) is shared by both the upper and lower surfaces.

  • spacing_function_per_side – Determines how to space the points on each side of the airfoil. Can be np.linspace or np.cosspace, or any other function of the call signature f(a, b, n) that returns a spaced array of n points between a and b. [function]

Return type:

Airfoil

Returns: A copy of the airfoil with the new coordinates.

normalize(return_dict=False)[source]#
Returns a copy of the Airfoil with a new set of coordinates, such that:
  • The leading edge (LE) is at (0, 0)

  • The trailing edge (TE) is at (1, 0)

  • The chord length is equal to 1

The trailing-edge (TE) point is defined as the midpoint of the line segment connecting the first and last coordinate points (upper and lower surface TE points, respectively). The TE point is not necessarily one of the original points in the airfoil coordinates (Airfoil.coordinates); in general, it will not be one of the points if the TE thickness is nonzero.

The leading-edge (LE) point is defined as the coordinate point with the largest Euclidian distance from the trailing edge. (In other words, if you were to center a circle on the trailing edge and progressively grow it, what’s the last coordinate point that it would intersect?) The LE point is always one of the original points in the airfoil coordinates.

The chord is defined as the Euclidian distance between the LE and TE points.

Coordinate modifications to achieve the constraints described above (LE @ origin, TE at (1, 0), and chord of 1) are done by means of a translation and rotation.

Parameters:

return_dict (bool) –

Determines the output type of the function. - If False (default), returns a copy of the Airfoil with the new coordinates. - If True, returns a dictionary with keys:

  • ”airfoil”: a copy of the Airfoil with the new coordinates

  • ”x_translation”: the amount by which the airfoil’s LE was translated in the x-direction

  • ”y_translation”: the amount by which the airfoil’s LE was translated in the y-direction

  • ”scale_factor”: the amount by which the airfoil was scaled (if >1, the airfoil had to get

    bigger)

  • ”rotation_angle”: the angle (in degrees) by which the airfoil was rotated about the LE.

    Sign convention is that positive angles rotate the airfoil counter-clockwise.

All of thes values represent the “required change”, e.g.:

  • ”x_translation” is the amount by which the airfoil’s LE had to be translated in the

    x-direction to get it to the origin.

  • ”rotation_angle” is the angle (in degrees) by which the airfoil had to be rotated (CCW).

Return type:

Union[Airfoil, Dict[str, Union[Airfoil, float]]]

Returns: Depending on the value of return_dict, either:

  • A copy of the airfoil with the new coordinates (default), or

  • A dictionary with keys “airfoil”, “x_translation”, “y_translation”, “scale_factor”, and “rotation_angle”.

    documentation for return_tuple for more information.

add_control_surface(deflection=0.0, hinge_point_x=0.75, modify_coordinates=True, modify_polars=True)[source]#

Returns a version of the airfoil with a trailing-edge control surface added at a given point. Implicitly repanels the airfoil as part of this operation.

Parameters:
  • deflection (float) – Deflection angle [degrees]. Downwards-positive.

  • hinge_point_x (float) – Chordwise location of the hinge, as a fraction of chord (x/c) [float]

  • modify_coordinates (bool) –

  • modify_polars (bool) –

Return type:

Airfoil

Returns: an Airfoil object with the new control deflection.

set_TE_thickness(thickness=0.0)[source]#

Creates a modified copy of the Airfoil that has a specified trailing-edge thickness.

Note that the trailing-edge thickness is given nondimensionally (e.g., as a fraction of chord).

Parameters:

thickness (float) – The target trailing-edge thickness, given nondimensionally (e.g., as a fraction of chord).

Return type:

Airfoil

Returns: The modified airfoil.

scale(scale_x=1.0, scale_y=1.0)[source]#

Scales an Airfoil about the origin.

Parameters:
  • scale_x (float) – Amount to scale in the x-direction.

  • scale_y (float) – Amount to scale in the y-direction. Scaling by a negative y-value will result in coordinates being re-ordered such that the order of the coordinates is still correct (i.e., starts from the upper-surface trailing edge, continues along the upper surface to the nose, then continues along the lower surface to the trailing edge).

Return type:

Airfoil

Returns: A copy of the Airfoil with appropriate scaling applied.

translate(translate_x=0.0, translate_y=0.0)[source]#

Translates an Airfoil by a given amount. :param translate_x: Amount to translate in the x-direction :param translate_y: Amount to translate in the y-direction

Returns: The translated Airfoil.

Parameters:
  • translate_x (float) –

  • translate_y (float) –

Return type:

Airfoil

rotate(angle, x_center=0.0, y_center=0.0)[source]#

Rotates the airfoil clockwise by the specified amount, in radians.

Rotates about the point (x_center, y_center), which is (0, 0) by default.

Parameters:
  • angle (float) – Angle to rotate, counterclockwise, in radians.

  • x_center (float) – The x-coordinate of the center of rotation.

  • y_center (float) – The y-coordinate of the center of rotation.

Return type:

Airfoil

Returns: The rotated Airfoil.

blend_with_another_airfoil(airfoil, blend_fraction=0.5, n_points_per_side=100)[source]#

Blends this airfoil with another airfoil. Merges both the coordinates and the aerodynamic functions.

Parameters:
  • airfoil (Airfoil) – The other airfoil to blend with.

  • blend_fraction (float) –

    The fraction of the other airfoil to use when blending. Defaults to 0.5 (50%).

    • A blend fraction of 0 will return an identical airfoil to this one (self).

    • A blend fraction of 1 will return an identical airfoil to the other one (airfoil parameter).

  • n_points_per_side (int) – The number of points per side to use when blending the coordinates of the two airfoils.

Return type:

Airfoil

Returns: A new airfoil that is a blend of this airfoil and another one.

write_dat(filepath=None, include_name=True)[source]#

Writes a .dat file corresponding to this airfoil to a filepath.

Parameters:
  • filepath (Union[str, pathlib.Path]) – filepath (including the filename and .dat extension) [string] If None, this function returns the .dat file as a string.

  • include_name (bool) – Should the name be included in the .dat file? (In a standard *.dat file, it usually is.)

Return type:

str

Returns: None

class aerosandbox.geometry.airfoil.KulfanAirfoil(name='Untitled', lower_weights=None, upper_weights=None, leading_edge_weight=0.0, TE_thickness=0.0, N1=0.5, N2=1.0)[source]#

Bases: aerosandbox.geometry.airfoil.airfoil.Airfoil

An airfoil. See constructor docstring for usage details.

Parameters:
  • name (str) –

  • lower_weights (aerosandbox.numpy.ndarray) –

  • upper_weights (aerosandbox.numpy.ndarray) –

  • leading_edge_weight (float) –

  • TE_thickness (float) –

  • N1 (float) –

  • N2 (float) –

property kulfan_parameters#
property coordinates: aerosandbox.numpy.ndarray#
Return type:

aerosandbox.numpy.ndarray

__repr__()[source]#

Return repr(self).

Return type:

str

to_airfoil(n_coordinates_per_side=200, spacing_function_per_side=np.cosspace)[source]#
Return type:

aerosandbox.geometry.airfoil.airfoil.Airfoil

repanel(n_points_per_side=100, spacing_function_per_side=np.cosspace)[source]#

Returns a repaneled copy of the airfoil with cosine-spaced coordinates on the upper and lower surfaces.

Parameters:
  • n_points_per_side (int) –

    Number of points per side (upper and lower) of the airfoil [int]

    Notes: The number of points defining the final airfoil will be n_points_per_side * 2 - 1, since one point (the leading edge point) is shared by both the upper and lower surfaces.

  • spacing_function_per_side – Determines how to space the points on each side of the airfoil. Can be np.linspace or np.cosspace, or any other function of the call signature f(a, b, n) that returns a spaced array of n points between a and b. [function]

Return type:

aerosandbox.geometry.airfoil.airfoil.Airfoil

Returns: A copy of the airfoil with the new coordinates.

normalize(return_dict=False)[source]#
Returns a copy of the Airfoil with a new set of coordinates, such that:
  • The leading edge (LE) is at (0, 0)

  • The trailing edge (TE) is at (1, 0)

  • The chord length is equal to 1

The trailing-edge (TE) point is defined as the midpoint of the line segment connecting the first and last coordinate points (upper and lower surface TE points, respectively). The TE point is not necessarily one of the original points in the airfoil coordinates (Airfoil.coordinates); in general, it will not be one of the points if the TE thickness is nonzero.

The leading-edge (LE) point is defined as the coordinate point with the largest Euclidian distance from the trailing edge. (In other words, if you were to center a circle on the trailing edge and progressively grow it, what’s the last coordinate point that it would intersect?) The LE point is always one of the original points in the airfoil coordinates.

The chord is defined as the Euclidian distance between the LE and TE points.

Coordinate modifications to achieve the constraints described above (LE @ origin, TE at (1, 0), and chord of 1) are done by means of a translation and rotation.

Parameters:

return_dict (bool) –

Determines the output type of the function. - If False (default), returns a copy of the Airfoil with the new coordinates. - If True, returns a dictionary with keys:

  • ”airfoil”: a copy of the Airfoil with the new coordinates

  • ”x_translation”: the amount by which the airfoil’s LE was translated in the x-direction

  • ”y_translation”: the amount by which the airfoil’s LE was translated in the y-direction

  • ”scale_factor”: the amount by which the airfoil was scaled (if >1, the airfoil had to get

    bigger)

  • ”rotation_angle”: the angle (in degrees) by which the airfoil was rotated about the LE.

    Sign convention is that positive angles rotate the airfoil counter-clockwise.

All of thes values represent the “required change”, e.g.:

  • ”x_translation” is the amount by which the airfoil’s LE had to be translated in the

    x-direction to get it to the origin.

  • ”rotation_angle” is the angle (in degrees) by which the airfoil had to be rotated (CCW).

Return type:

Union[KulfanAirfoil, Dict[str, Union[KulfanAirfoil, float]]]

Returns: Depending on the value of return_dict, either:

  • A copy of the airfoil with the new coordinates (default), or

  • A dictionary with keys “airfoil”, “x_translation”, “y_translation”, “scale_factor”, and “rotation_angle”.

    documentation for return_tuple for more information.

draw(*args, draw_markers=False, **kwargs)[source]#

Draw the airfoil object.

Parameters:
  • draw_mcl – Should we draw the mean camber line (MCL)? [boolean]

  • backend – Which backend should we use? “plotly” or “matplotlib”

  • show – Should we show the plot? [boolean]

Returns: None

get_aero_from_neuralfoil(alpha, Re, mach=0.0, n_crit=9.0, xtr_upper=1.0, xtr_lower=1.0, model_size='large', control_surfaces=None, include_360_deg_effects=True)[source]#
Parameters:
  • alpha (Union[float, aerosandbox.numpy.ndarray]) –

  • Re (Union[float, aerosandbox.numpy.ndarray]) –

  • mach (Union[float, aerosandbox.numpy.ndarray]) –

  • n_crit (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_upper (Union[float, aerosandbox.numpy.ndarray]) –

  • xtr_lower (Union[float, aerosandbox.numpy.ndarray]) –

  • model_size (str) –

  • control_surfaces (List[ControlSurface]) –

  • include_360_deg_effects (bool) –

Return type:

Dict[str, Union[float, aerosandbox.numpy.ndarray]]

upper_coordinates(x_over_c=np.linspace(1, 0, 101))[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the upper surface of the airfoil.

Order is from the trailing edge to the leading edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.lower_coordinates().

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) –

Return type:

aerosandbox.numpy.ndarray

lower_coordinates(x_over_c=np.linspace(0, 1, 101))[source]#

Returns an Nx2 ndarray of [x, y] coordinates that describe the lower surface of the airfoil.

Order is from the leading edge to the trailing edge.

Includes the leading edge point; be careful about duplicates if using this method in conjunction with Airfoil.upper_coordinates().

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) –

Return type:

aerosandbox.numpy.ndarray

local_camber(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local camber of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the camber at [1D array, more generally, an iterable of floats]

Returns:

Local camber of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

local_thickness(x_over_c=np.linspace(0, 1, 101))[source]#

Returns the local thickness of the airfoil at a given point or points.

Parameters:

x_over_c (Union[float, aerosandbox.numpy.ndarray]) – The x/c locations to calculate the thickness at [1D array, more generally, an iterable of floats]

Returns:

Local thickness of the airfoil (y/c) [1D array].

Return type:

Union[float, aerosandbox.numpy.ndarray]

LE_radius(relative_softness=0.03)[source]#
Parameters:

relative_softness (float) –

TE_angle()[source]#

Returns the trailing edge angle of the airfoil, in degrees.

area()[source]#

Returns the area of the polygon.

set_TE_thickness(thickness=0.0)[source]#

Creates a modified copy of the KulfanAirfoil that has a specified trailing-edge thickness.

Note that the trailing-edge thickness is given nondimensionally (e.g., as a fraction of chord).

Parameters:

thickness (float) – The target trailing-edge thickness, given nondimensionally (e.g., as a fraction of chord).

Return type:

KulfanAirfoil

Returns: The modified KulfanAirfoil.

scale(scale_x=1.0, scale_y=1.0)[source]#

Scales a KulfanAirfoil about the origin.

Parameters:
  • scale_x (float) – Amount to scale in the x-direction. Note: not supported by KulfanAirfoil due to inherent limitations of parameterization; only given here so that argument symmetry to Airfoil.scale() is retained. Raises a ValueError if modified, along with instructions to use Airfoil if needed.

  • scale_y (float) – Amount to scale in the y-direction. Scaling by a negative y-value will result in lower_weights and upper_weights being flipped as appropriate.

Return type:

KulfanAirfoil

Returns: A copy of the KulfanAirfoil with appropriate scaling applied.

blend_with_another_airfoil(airfoil, blend_fraction=0.5)[source]#

Blends this airfoil with another airfoil. Merges both the coordinates and the aerodynamic functions.

Parameters:
  • airfoil (Union[KulfanAirfoil, aerosandbox.geometry.airfoil.airfoil.Airfoil]) – The other airfoil to blend with.

  • blend_fraction (float) –

    The fraction of the other airfoil to use when blending. Defaults to 0.5 (50%).

    • A blend fraction of 0 will return an identical airfoil to this one (self).

    • A blend fraction of 1 will return an identical airfoil to the other one (airfoil parameter).

  • n_points_per_side – The number of points per side to use when blending the coordinates of the two airfoils.

Return type:

KulfanAirfoil

Returns: A new airfoil that is a blend of this airfoil and another one.