aerosandbox.geometry.wing#

Module Contents#

Classes#

Wing

Definition for a Wing.

WingXSec

Definition for a wing cross-section ("X-section").

ControlSurface

Definition for a control surface, which is attached to a particular WingXSec via WingXSec's control_surfaces=[] parameter.

Attributes#

class aerosandbox.geometry.wing.Wing(name=None, xsecs=None, symmetric=False, color=None, analysis_specific_options=None, **kwargs)[source]#

Bases: aerosandbox.common.AeroSandboxObject

Definition for a Wing.

Anatomy of a Wing:

A wing consists chiefly of a collection of cross-sections, or “xsecs”. A cross-section is a 2D “slice” of a wing. These can be accessed with Wing.xsecs, which gives a list of xsecs in the Wing. Each xsec is a WingXSec object, a class that is defined separately.

You may also see references to wing “sections”, which are different than cross-sections (xsecs)! Sections are the portions of the wing that are in between xsecs. In other words, a wing with N cross-sections (xsecs, WingXSec objects) will always have N-1 sections. Sections are never explicitly defined, since you can get all needed information by lofting from the adjacent cross-sections. For example, section 0 (the first one) is a loft between cross-sections 0 and 1.

Wings are lofted linearly between cross-sections.

If the wing is symmetric across the XZ plane, just define the right half and supply symmetric=True in the constructor.

If the wing is not symmetric across the XZ plane (e.g., a single vertical stabilizer), just define the wing.

Parameters:
  • name (Optional[str]) –

  • xsecs (List[WingXSec]) –

  • symmetric (bool) –

  • color (Optional[Union[str, Tuple[float]]]) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

translate(xyz)[source]#

Translates the entire Wing by a certain amount.

Parameters:

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

Return type:

Wing

Returns: The new wing object.

span(type='yz', include_centerline_distance=False, _sectional=False)[source]#

Computes the span, with options for various ways of measuring this (see type argument).

If the wing is symmetric, both left/right sides are included in order to obtain the full span. In the case where the root cross-section is not coincident with the center plane (e.g., XZ plane), this function’s behavior depends on the include_centerline_distance argument.

Parameters:
  • type (str) –

    One of the following options, as a string:

    • ”xyz”: First, computes the quarter-chord point of each WingXSec. Then, connects these with

    straight lines. Then, adds up the lengths of these lines.

    • ”xy” or “top”: Same as “xyz”, except it projects each line segment onto the XY plane before adding up the

    lengths.

    • ”yz” (default) or “front”: Same as “xyz”, except it projects each line segment onto the YZ plane (i.e., front view)

    before adding up the lengths.

    • ”xz” or “side”: Same as “xyz”, except it projects each line segment onto the XZ plane before adding up the

    lengths. Rarely needed.

    • ”x”: Same as “xyz”, except it only counts the x-components of each line segment when adding up the

    lengths.

    • ”y”: Same as “xyz”, except it only counts the y-components of each line segment when adding up the

    lengths.

    • ”z”: Same as “xyz”, except it only counts the z-components of each line segment when adding up the

    lengths.

  • include_centerline_distance – A boolean flag that tells the function what to do if a wing’s root is not

  • plane (coincident with the centerline) –

    • If True, we first figure out which WingXSec has its quarter-chord point closest to the centerline

    plane (i.e., XZ plane). Then, we compute the distance from that quarter-chord point directly to the centerline plane (along Y). We then add that distance to the span calculation. In other words, the fictitious span connecting the left and right root cross-sections is included.

    • If False, this distance is ignored. In other words, the fictitious span connecting the left and

    right root cross-sections is not included. This is the default behavior.

    Note: For computation, either the root WingXSec (i.e., index=0) or the tip WingXSec (i.e., index=-1) is used, whichever is closer to the centerline plane. This will almost-always be the root WingXSec, but some weird edge cases (e.g., a half-wing defined on the left-hand-side of the airplane, rather than the conventional right-hand side) will result in the tip WingXSec being used.

  • _sectional (bool) – A boolean. If False, returns the total span. If True, returns a list of spans for each of the n-1 lofted sections (between the n wing cross-sections in wing.xsec).

Return type:

Union[float, List[float]]

area(type='planform', include_centerline_distance=False, _sectional=False)[source]#

Computes the wing area, with options for various ways of measuring this (see type argument):

If the wing is symmetric, both left/right sides are included in order to obtain the full area. In the case where the root cross-section is not coincident with the center plane (e.g., XZ plane), this function’s behavior depends on the include_centerline_distance argument.

Parameters:
  • type (str) –

    One of the following options, as a string:

    • ”planform” (default): First, lofts a quadrilateral mean camber surface between each WingXSec. Then,

    computes the area of each of these sectional surfaces. Then, sums up all the areas and returns it. When airplane designers refer to “wing area” (in the absence of any other qualifiers), this is typically what they mean.

    • ”wetted”: Computes the actual surface area of the wing that is in contact with the air. Will

    typically be a little more than double the “planform” area above; intuitively, this is because it adds both the “top” and “bottom” surface areas. Accounts for airfoil thickness/shape effects.

    • ”xy” or “projected” or “top”: Same as “planform”, but each sectional surface is projected onto the XY plane

    (i.e., top-down view) before computing the areas. Note that if you try to use this method with a vertically-oriented wing, like most vertical stabilizers, you will get an area near zero.

    • ”xz” or “side”: Same as “planform”, but each sectional surface is projected onto the XZ plane before

    computing the areas.

  • include_centerline_distance – A boolean flag that tells the function what to do if a wing’s root chord is

  • plane (not coincident with the centerline) –

    • If True, we first figure out which WingXSec is closest to the centerline plane (i.e., XZ plane).

    Then, we imagine that this WingXSec is extruded along the Y axis to the centerline plane (assuming a straight extrusion to produce a rectangular mid-camber surface). In doing so, we use the wing geometric chord as the extrusion width. We then add the area of this fictitious surface to the area calculation.

    • If False, this function will simply ignore this fictitious wing area. This is the default behavior.

  • _sectional (bool) – A boolean. If False, returns the total area. If True, returns a list of areas for each of the n-1 lofted sections (between the n wing cross-sections in wing.xsec).

Return type:

Union[float, List[float]]

aspect_ratio(type='geometric')[source]#

Computes the aspect ratio of the wing, with options for various ways of measuring this.

  • geometric: geometric aspect ratio, computed in the typical fashion (b^2 / S).

  • effective: Differs from the geometric aspect ratio only in the case of symmetric wings whose root

cross-section is not on the centerline. In these cases, it includes the span and area of the fictitious wing center when computing aspect ratio.

Parameters:

type (str) – One of the above options, as a string.

Return type:

float

is_entirely_symmetric()[source]#
Return type:

bool

mean_geometric_chord()[source]#

Returns the mean geometric chord of the wing (S/b). :return:

Return type:

float

mean_aerodynamic_chord()[source]#

Computes the length of the mean aerodynamic chord of the wing. Uses the generalized methodology described here:

Returns: The length of the mean aerodynamic chord.

Return type:

float

mean_twist_angle()[source]#

Returns the mean twist angle (in degrees) of the wing, weighted by area. :return: mean twist angle (in degrees)

Return type:

float

mean_sweep_angle(x_nondim=0.25)[source]#

Returns the mean sweep angle (in degrees) of the wing, relative to the x-axis. Positive sweep is backwards, negative sweep is forward.

This is purely measured from root to tip, with no consideration for the sweep of the individual cross-sections in between.

Parameters:

x_nondim

The nondimensional x-coordinate of the cross-section to use for sweep angle computation.

  • If you provide 0, it will use the leading edge of the cross-section.

  • If you provide 0.25, it will use the quarter-chord point of the cross-section.

  • If you provide 1, it will use the trailing edge of the cross-section.

Returns:

The mean sweep angle, in degrees.

Return type:

float

mean_dihedral_angle(x_nondim=0.25)[source]#

Returns the mean dihedral angle (in degrees) of the wing, relative to the XY plane. Positive dihedral is bending up, negative dihedral is bending down.

This is purely measured from root to tip, with no consideration for the dihedral of the individual cross-sections in between.

Parameters:

x_nondim

The nondimensional x-coordinate of the cross-section to use for sweep angle computation.

  • If you provide 0, it will use the leading edge of the cross-section.

  • If you provide 0.25, it will use the quarter-chord point of the cross-section.

  • If you provide 1, it will use the trailing edge of the cross-section.

Returns:

The mean dihedral angle, in degrees

Return type:

float

aerodynamic_center(chord_fraction=0.25, _sectional=False)[source]#

Computes the location of the aerodynamic center of the wing. Uses the generalized methodology described here:

Args: chord_fraction: The position of the aerodynamic center along the MAC, as a fraction of MAC length.

Typically, this value (denoted h_0 in the literature) is 0.25 for a subsonic wing. However, wing-fuselage interactions can cause a forward shift to a value more like 0.1 or less. Citing Cook, Michael V., “Flight Dynamics Principles”, 3rd Ed., Sect. 3.5.3 “Controls-fixed static stability”. PDF: https://www.sciencedirect.com/science/article/pii/B9780080982427000031

Returns: The (x, y, z) coordinates of the aerodynamic center of the wing.

Parameters:

chord_fraction (float) –

Return type:

aerosandbox.numpy.ndarray

taper_ratio()[source]#

Gives the taper ratio of the Wing. Strictly speaking, only valid for trapezoidal wings.

Returns:

Taper ratio of the Wing.

Return type:

float

volume(_sectional=False)[source]#

Computes the volume of the Wing.

Parameters:
  • _sectional (bool) – A boolean. If False, returns the total volume. If True, returns a list of volumes for each of

  • sections (the n-1 lofted) –

Returns:

The computed volume.

Return type:

Union[float, List[float]]

get_control_surface_names()[source]#

Gets the names of all control surfaces on this wing.

Returns:

A list of control surface names.

Return type:

List[str]

set_control_surface_deflections(control_surface_mappings)[source]#

Sets the deflection of all control surfaces on this wing, based on the provided mapping.

Parameters:

control_surface_mappings (Dict[str, float]) –

A dictionary mapping control surface names to their deflection angles, in degrees.

Note: control surface names are set in the asb.ControlSurface constructor.

Returns:

None. (in-place)

Return type:

None

control_surface_area(by_name=None, type='planform')[source]#

Computes the total area of all control surfaces on this wing, optionally filtered by their name.

Control surfaces are defined on a section-by-section basis, and are defined in the WingXSec constructor using its control_surfaces argument.

Note: If redundant control surfaces are defined (e.g., elevons, as defined by separate ailerons + elevator), the area will be duplicated.

If the wing is symmetric, control surfaces on both left/right sides are included in order to obtain the full area.

Parameters:
  • by_name (Optional[str]) –

    If not None, only control surfaces with this name will be included in the area calculation.

    Note: control surface names are set in the asb.ControlSurface constructor.

  • type (Optional[str]) –

    One of the following options, as a string:

    • ”planform” (default): First, lofts a quadrilateral mean camber surface between each WingXSec. Then,

    computes the area of each of these sectional surfaces. Then, computes what fraction of this area is control surface. Then, sums up all the areas and returns it. When airplane designers refer to “control surface area” (in the absence of any other qualifiers), this is typically what they mean.

    • ”wetted”: Computes the actual surface area of the control surface that is in contact with the air.

    Will typically be a little more than double the “planform” area above; intuitively, this is because it adds both the “top” and “bottom” surface areas. Accounts for airfoil thickness/shape effects.

    • ”xy” or “projected” or “top”: Same as “planform”, but each sectional surface is projected onto the XY plane

    (i.e., top-down view) before computing the areas. Note that if you try to use this method with a vertically-oriented wing, like most vertical stabilizers, you will get an area near zero.

    • ”xz” or “side”: Same as “planform”, but each sectional surface is projected onto the XZ plane before

    computing the areas.

Return type:

float

mesh_body(method='quad', chordwise_resolution=36, chordwise_spacing_function_per_side=np.cosspace, mesh_surface=True, mesh_tips=True, mesh_trailing_edge=True, mesh_symmetric=True)[source]#

Meshes the outer mold line surface of the wing.

Uses the (points, faces) standard mesh format. For reference on this format, see the documentation in aerosandbox.geometry.mesh_utilities.

Order of faces:

  • On the right wing (or, if Wing.symmetric is False, just the wing itself):

    • If mesh_surface is True:

      • First face is nearest the top-side trailing edge of the wing root.

      • Proceeds chordwise, along the upper surface of the wing from back to front. Upon reaching the

      leading edge, continues along the lower surface of the wing from front to back.

      • Then, repeats this process for the next spanwise slice of the wing, and so on.

    • If mesh_trailing_edge is True:

      • Continues by meshing the trailing edge of the wing. Meshes the inboard trailing edge first, then

      proceeds spanwise to the outboard trailing edge.

    • If mesh_tips is True:

      • Continues by meshing the wing tips. Meshes the inboard tip first, then meshes the outboard tip.

      • Within each tip, meshes from the

Parameters:
  • method

    One of the following options, as a string:

    • ”tri”: Triangular mesh.

    • ”quad”: Quadrilateral mesh.

  • chordwise_resolution (int) – Number of points to use per wing chord, per wing section.

  • chordwise_spacing_function_per_side (Callable[[float, float, float], aerosandbox.numpy.ndarray]) – A function that determines how to space points in the chordwise

  • np.cosspace (direction along the top and bottom surfaces. Common values would be np.linspace or) –

  • mesh_surface (bool) –

  • mesh_tips (bool) –

  • mesh_trailing_edge (bool) –

  • mesh_symmetric (bool) –

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

:param : :param but it can be any function with the call signature f: :type but it can be any function with the call signature `f: a, b, n :param between `a and b. [function]: :param mesh_surface: If True, includes the actual wing surface in the mesh. :param mesh_tips: If True, includes the wing tips (both on the inboard-most section and on the outboard-most :param section) in the mesh.: :param mesh_trailing_edge: If True, includes the wing trailing edge in the mesh, if the trailing-edge thickness :param is nonzero.: :param mesh_symmetric: Has no effect if the wing is not symmetric. If the wing is symmetric this determines whether :param the generated mesh is also symmetric: :type the generated mesh is also symmetric: right side :param or if if only one side of the wing: :type or if if only one side of the wing: right side

Returns: Standard unstructured mesh format: A tuple of points and faces, where:

  • points is a n x 3 array of points, where n is the number of points in the mesh.

  • faces is a m x 3 array of faces if method is “tri”, or a m x 4 array of faces if method is “quad”.

    • Each row of faces is a list of indices into points, which specifies a face.

mesh_thin_surface(method='tri', chordwise_resolution=36, chordwise_spacing_function=np.cosspace, add_camber=True)[source]#

Meshes the mean camber line of the wing as a thin-sheet body.

Uses the (points, faces) standard mesh format. For reference on this format, see the documentation in aerosandbox.geometry.mesh_utilities.

Order of faces:
  • On the right wing (or, if Wing.symmetric is False, just the wing itself):
    • First face is the face nearest the leading edge of the wing root.

    • Proceeds along a chordwise strip to the trailing edge.

    • Then, goes to the subsequent spanwise location and does another chordwise strip, et cetera until we get to the wing tip.

  • On the left wing (applicable only if Wing.symmetric is True):
    • Same order: Starts at the root leading edge, goes in chordwise strips.

Order of vertices within each face:
  • On the right wing (or, if Wing.symmetric is False, just the wing itself):
    • Front-left

    • Back-left

    • Back-right

    • Front-right

  • On the left wing (applicable only if Wing.symmetric is True):
    • Front-left

    • Back-left

    • Back-right

    • Front-right

Parameters:
  • method

    A string, which determines whether to mesh the fuselage as a series of quadrilaterals or triangles.

    • ”quad” meshes the fuselage as a series of quadrilaterals.

    • ”tri” meshes the fuselage as a series of triangles.

  • chordwise_resolution (int) – Determines the number of chordwise panels to use in the meshing. [int]

  • chordwise_spacing_function (Callable[[float, float, float], aerosandbox.numpy.ndarray]) – Determines how to space the chordwise panels. Can be np.linspace or

  • np.cosspace (a, b, n) –

  • `f (or any other function of the call signature) –

  • [function] (n points between a and b.) –

  • add_camber (bool) – Controls whether to mesh the thin surface with camber (i.e., mean camber line), or to just

  • [bool] (mesh the flat planform.) –

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

Returns: Standard unstructured mesh format: A tuple of points and faces, where:

  • points is a n x 3 array of points, where n is the number of points in the mesh.

  • faces is a m x 3 array of faces if method is “tri”, or a m x 4 array of faces if method is “quad”.

    • Each row of faces is a list of indices into points, which specifies a face.

mesh_line(x_nondim=0.25, z_nondim=0, add_camber=True)[source]#

Meshes a line that goes through each of the WingXSec objects in this wing.

Parameters:
  • x_nondim (Union[float, List[float]]) – The nondimensional (chord-normalized) x-coordinate that the line should go through. Can either

  • cross-sections (value used at all) –

  • the (or can be an iterable of values to be used at) –

  • cross-sections. (respective) –

  • z_nondim (Union[float, List[float]]) – The nondimensional (chord-normalized) y-coordinate that the line should go through. Here,

  • component (y-coordinate means the "vertical") –

  • cross-sections

  • cross (or can be an iterable of values to be used at the respective) –

  • sections.

  • add_camber (bool) – Controls whether the camber of each cross-section’s airfoil should be added to the line or

  • camber. (not. Essentially modifies z_nondim to be z_nondim +) –

Return type:

List[aerosandbox.numpy.ndarray]

Returns: A list of points, where each point is a 3-element array of the form [x, y, z]. Goes from the root to the tip. Ignores any wing symmetry (e.g., only gives one side).

draw(*args, **kwargs)[source]#

An alias to the more general Airplane.draw() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw()

  • **kwargs – Keyword arguments to pass through to Airplane.draw()

Returns: Same return as Airplane.draw()

draw_wireframe(*args, **kwargs)[source]#

An alias to the more general Airplane.draw_wireframe() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw_wireframe()

  • **kwargs – Keyword arguments to pass through to Airplane.draw_wireframe()

Returns: Same return as Airplane.draw_wireframe()

draw_three_view(*args, **kwargs)[source]#

An alias to the more general Airplane.draw_three_view() method. See there for documentation.

Parameters:
  • *args – Arguments to pass through to Airplane.draw_three_view()

  • **kwargs – Keyword arguments to pass through to Airplane.draw_three_view()

Returns: Same return as Airplane.draw_three_view()

subdivide_sections(ratio, spacing_function=np.linspace)[source]#

Generates a new Wing that subdivides the existing sections of this Wing into several smaller ones. Splits each section into N=`ratio` smaller sub-sections by inserting new cross-sections (xsecs) as needed.

This can allow for finer aerodynamic resolution of sectional properties in certain analyses.

Parameters:
  • ratio (int) – The number of new sections to split each old section into.

  • spacing_function (Callable[[float, float, float], aerosandbox.numpy.ndarray]) –

    A function that takes in three arguments: the start, end, and number of points to generate.

    The default is np.linspace, which generates a linearly-spaced array of points.

    Other options include np.cosspace, which generates a cosine-spaced array of points.

Return type:

Wing

Returns: A new Wing object with subdivided sections.

_compute_xyz_le_of_WingXSec(index)[source]#
Parameters:

index (int) –

_compute_xyz_te_of_WingXSec(index)[source]#
Parameters:

index (int) –

_compute_xyz_of_WingXSec(index, x_nondim, z_nondim)[source]#
_compute_frame_of_WingXSec(index)[source]#

Computes the local reference frame associated with a particular cross-section (XSec) of this wing.

Parameters:

index (int) – Which cross-section (as indexed in Wing.xsecs) should we get the frame of?

Returns:

A tuple of (xg_local, yg_local, zg_local), where each entry refers to the respective (normalized) axis of the local reference frame of the WingXSec. Given in geometry axes.

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

_compute_frame_of_section(index)[source]#

Computes the local reference frame associated with a particular section. (Note that sections and cross sections are different! cross-sections, or xsecs, are the vertices, and sections are the parts in between. In other words, a wing with N cross-sections (xsecs) will always have N-1 sections.

Parameters:
  • index (int) – Which section should we get the frame of? If given i, this retrieves the frame of the section

  • i+1. (between xsecs i and) –

Returns:

A tuple of (xg_local, yg_local, zg_local), where each entry refers to the respective (normalized) axis of the local reference frame of the section. Given in geometry axes.

Return type:

Tuple[aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray, aerosandbox.numpy.ndarray]

class aerosandbox.geometry.wing.WingXSec(xyz_le=None, chord=1.0, twist=0.0, airfoil=None, control_surfaces=None, analysis_specific_options=None, **deprecated_kwargs)[source]#

Bases: aerosandbox.common.AeroSandboxObject

Definition for a wing cross-section (“X-section”).

Parameters:
  • xyz_le (Union[aerosandbox.numpy.ndarray, List]) –

  • chord (float) –

  • twist (float) –

  • airfoil (aerosandbox.geometry.airfoil.Airfoil) –

  • control_surfaces (Optional[List[ControlSurface]]) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

translate(xyz)[source]#

Returns a copy of this WingXSec that has been translated by xyz.

Parameters:

xyz (Union[aerosandbox.numpy.ndarray, List]) – The amount to translate the WingXSec. Given as a 3-element NumPy vector.

Return type:

WingXSec

Returns: A new WingXSec object.

xsec_area()[source]#

Computes the WingXSec’s cross-sectional (xsec) area.

Returns: The (dimensional) cross-sectional area of the WingXSec.

class aerosandbox.geometry.wing.ControlSurface(name='Untitled', symmetric=True, deflection=0.0, hinge_point=0.75, trailing_edge=True, analysis_specific_options=None)[source]#

Bases: aerosandbox.common.AeroSandboxObject

Definition for a control surface, which is attached to a particular WingXSec via WingXSec’s control_surfaces=[] parameter.

Parameters:
  • name (str) –

  • symmetric (bool) –

  • deflection (float) –

  • hinge_point (float) –

  • trailing_edge (bool) –

  • analysis_specific_options (Optional[Dict[type, Dict[str, Any]]]) –

__repr__()[source]#

Return repr(self).

Return type:

str

aerosandbox.geometry.wing.wing[source]#