aerosandbox.geometry.fuselage ============================= .. py:module:: aerosandbox.geometry.fuselage Attributes ---------- .. autoapisummary:: aerosandbox.geometry.fuselage.fuse Classes ------- .. autoapisummary:: aerosandbox.geometry.fuselage.Fuselage aerosandbox.geometry.fuselage.FuselageXSec Module Contents --------------- .. py:class:: Fuselage(name = 'Untitled', xsecs = None, color = None, analysis_specific_options = None, **kwargs) Bases: :py:obj:`aerosandbox.AeroSandboxObject` Definition for a Fuselage or other slender body (pod, fuel tank, etc.). Anatomy of a Fuselage: A fuselage consists chiefly of a collection of cross-sections, or "xsecs". A cross-section is a 2D "slice" of a fuselage. These can be accessed with `Fuselage.xsecs`, which gives a list of xsecs in the Fuselage. Each xsec is a FuselageXSec object, a class that is defined separately. You may also see references to fuselage "sections", which are different from cross-sections (xsecs)! Sections are the portions of the fuselage that are in between xsecs. In other words, a fuselage with N cross-sections (xsecs, FuselageXSec 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. Fuselages are lofted linearly between cross-sections. .. py:attribute:: name :value: 'Untitled' .. py:attribute:: xsecs :value: None .. py:attribute:: color :value: None .. py:attribute:: analysis_specific_options :value: None .. py:method:: __repr__() .. py:method:: add_loft(kind, to_xsec, from_xsec = None, n_points = 5, spacing = np.cosspace) :abstractmethod: .. py:method:: translate(xyz) Translates the entire Fuselage by a certain amount. :param xyz: Returns: self .. py:method:: area_wetted() Returns the wetted area of the fuselage. :return: .. py:method:: area_projected(type = 'XY') Returns the area of the fuselage as projected onto one of the principal planes. :param type: A string, which determines which principal plane to use for projection. One of: * "XY", in which case the projected area is onto the XY plane (i.e., top-down) * "XZ", in which case the projected area is onto the XZ plane (i.e., side-view) Returns: The projected area. .. py:method:: area_base() Returns the area of the base (i.e. "trailing edge") of the fuselage. Useful for certain types of drag calculation. Returns: .. py:method:: fineness_ratio(assumed_shape='cylinder') Approximates the fineness ratio using the volume and length. The fineness ratio of a fuselage is defined as: FR = length / max_diameter :param assumed_shape: A string, which determines the assumed shape of the fuselage for the approximation. One of: * "cylinder", in which case the fuselage is assumed to have a cylindrical shape. * "sears-haack", in which case the fuselage is assumed to have Sears-Haack fuselage shape. Returns: An approximate value of the fuselage's fineness ratio. .. py:method:: length() Returns the total front-to-back length of the fuselage. Measured as the difference between the x-coordinates of the leading and trailing cross-sections. :return: .. py:method:: volume(_sectional = False) Computes the volume of the Fuselage. :param _sectional: A boolean. If False, returns the total volume. If True, returns a list of volumes for each of :param the `n-1` lofted sections: :type the `n-1` lofted sections: between the `n` fuselage cross-sections in fuselage.xsec :returns: The computed volume. .. py:method:: x_centroid_projected(type = 'XY') Returns the x_g coordinate of the centroid of the planform area. :param type: A string, which determines which principal plane to use for projection. One of: * "XY", in which case the projected area is onto the XY plane (i.e., top-down) * "XZ", in which case the projected area is onto the XZ plane (i.e., side-view) Returns: The x_g coordinate of the centroid. .. py:method:: mesh_body(method='quad', tangential_resolution = 36) Meshes the fuselage as a solid (thickened) body. Uses the `(points, faces)` standard mesh format. For reference on this format, see the documentation in `aerosandbox.geometry.mesh_utilities`. :param 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. :param tangential_resolution: An integer, which determines the number of points to use to mesh each cross-section. 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. .. py:method:: mesh_line(y_nondim = 0.0, z_nondim = 0.0) Returns points along a line that goes through each of the FuselageXSec objects in this Fuselage. :param y_nondim: The nondimensional (width-normalized) y-coordinate that the line should go through. Can either :param be a single value used at all cross-sections: :param or can be an iterable of values to be used at the: :param respective cross-sections.: :param z_nondim: The nondimensional (height-normalized) z-coordinate that the line should go through. Can either :param be a single value used at all cross-sections: :param or can be an iterable of values to be used at the: :param respective cross-sections.: Returns: A list of points, where each point is a 3-element array of the form `[x, y, z]`. Goes from the nose to the tail. .. py:method:: draw(*args, **kwargs) An alias to the more general Airplane.draw() method. See there for documentation. :param \*args: Arguments to pass through to Airplane.draw() :param \*\*kwargs: Keyword arguments to pass through to Airplane.draw() Returns: Same return as Airplane.draw() .. py:method:: draw_wireframe(*args, **kwargs) An alias to the more general Airplane.draw_wireframe() method. See there for documentation. :param \*args: Arguments to pass through to Airplane.draw_wireframe() :param \*\*kwargs: Keyword arguments to pass through to Airplane.draw_wireframe() Returns: Same return as Airplane.draw_wireframe() .. py:method:: draw_three_view(*args, **kwargs) An alias to the more general Airplane.draw_three_view() method. See there for documentation. :param \*args: Arguments to pass through to Airplane.draw_three_view() :param \*\*kwargs: Keyword arguments to pass through to Airplane.draw_three_view() Returns: Same return as Airplane.draw_three_view() .. py:method:: subdivide_sections(ratio, spacing_function = np.linspace) Generates a new Fuselage that subdivides the existing sections of this Fuselage into several smaller ones. Splits each section into N=`ratio` smaller subsections by inserting new cross-sections (xsecs) as needed. This can allow for finer aerodynamic resolution of sectional properties in certain analyses. :param ratio: The number of new sections to split each old section into. :param spacing_function: 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. Returns: A new Fuselage object with subdivided sections. .. py:method:: _compute_frame_of_FuselageXSec(index) Computes the local frame of a FuselageXSec, given the index of the FuselageXSec in the Fuselage.xsecs list. :param index: The index of the FuselageXSec in the Fuselage.xsecs list. Returns: A tuple: xg_local: The x-axis of the local coordinate frame, in aircraft geometry axes. yg_local: The y-axis of the local coordinate frame, in aircraft geometry axes. zg_local: The z-axis of the local coordinate frame, in aircraft geometry axes. .. py:class:: FuselageXSec(xyz_c = None, xyz_normal = None, radius = None, width = None, height = None, shape = 2.0, analysis_specific_options = None) Bases: :py:obj:`aerosandbox.AeroSandboxObject` Definition for a fuselage cross-section ("X-section"). .. py:attribute:: xyz_c .. py:attribute:: xyz_normal .. py:attribute:: shape :value: 2.0 .. py:attribute:: analysis_specific_options :value: None .. py:method:: __repr__() .. py:method:: xsec_area() Computes the FuselageXSec's cross-sectional (xsec) area. The computation method is a closed-form approximation for the area of a superellipse. The exact equation for the area of a superellipse with shape parameter `s` is: area = width * height * (gamma(1 + 1/n))^2 / gamma(1 + 2/n) where gamma() is the gamma function. The gamma function is (relatively) computationally expensive to evaluate and differentiate, so we replace this area calculation with a closed-form approximation (with essentially no loss in accuracy): area = width * height / (s^-1.8717618013591173 + 1) This approximation has the following properties: * It is numerically exact for the case of s = 1 (a diamond) * It is numerically exact for the case of s = 2 (a circle) * It is correct in the asymptotic limit where s -> infinity (a square) * In the range of sensible s values (1 < s < infinity), its error is less than 0.6%. * It always produces a positive area for any physically-meaningful value of s (s > 0). In the range of s values where s is physically-meaningful but not in a sensible range (0 < s < 1), this equation will over-predict area. The value of the constant seen in this expression (1.872...) is given by log(4/pi - 1) / log(2), and it is chosen as such so that the expression is exactly correct in the s=2 (circle) case. Returns: .. py:method:: xsec_perimeter() Computes the FuselageXSec's perimeter. ("Circumference" in the case of a circular cross-section.) The computation method is a closed-form approximation for the perimeter of a superellipse. The exact equation for the perimeter of a superellipse is quite long and is not repeated here for brevity; a Google search will bring it up. More importantly, this exact equation can only be represented as an infinite sum - not particularly useful for fast computation. We replace this exact equation with the following closed-form approximation obtained from symbolic regression: Imagine a superellipse centered on the origin of a 2D plane. Now, imagine that the superellipse is stretched such that the first quadrant (e.g., x>0, y>0) goes from (1, 0) to (0, h). Assume it has shape parameter s (where, as a reminder, s=1 is a diamond, s=2 is a circle, s=Inf is a square). Then, the perimeter of that single quadrant is: h + (((((s-0.88487077) * h + 0.2588574 / h) ^ exp(s / -0.90069205)) + h) + 0.09919785) ^ (-1.4812293 / s) See `AeroSandbox/studies/SuperellipseProperties` for details about how this was obtained. We can extrapolate from here to the general case of a superellipse, as shown in the code below. This approximation has the following properties: * For the s=1 case (diamond), the error is +0.2%. * For the s=2 case (circle), the error is -0.1%. * In the s -> infinity limit (square), the error is +0.1%. Returns: .. py:method:: compute_frame() Computes the local coordinate frame of the FuselageXSec, in aircraft geometry axes. xg_local is aligned with the FuselageXSec's normal vector. zg_local is roughly aligned with the z-axis of the aircraft geometry axes, but projected onto the FuselageXSec's plane. yg_local is the cross product of zg_local and xg_local. Returns: A tuple: xg_local: The x-axis of the local coordinate frame, in aircraft geometry axes. yg_local: The y-axis of the local coordinate frame, in aircraft geometry axes. zg_local: The z-axis of the local coordinate frame, in aircraft geometry axes. .. py:method:: get_3D_coordinates(theta = None) Samples points from the perimeter of this FuselageXSec. :param theta: Coordinate in the tangential-ish direction to sample points at. Given in the 2D FuselageXSec :param coordinate system: * y_2D points along the (global) y_g * z_2D points along the (global) z_g In other words, a value of: * theta=0 -> samples points from the right side of the FuselageXSec * theta=pi/2 -> samples points from the top of the FuselageXSec * theta=pi -> samples points from the left side of the FuselageXSec * theta=3pi/2 -> samples points from the bottom of the FuselageXSec :param where: * y_2D points along the (global) y_g * z_2D points along the (global) z_g In other words, a value of: * theta=0 -> samples points from the right side of the FuselageXSec * theta=pi/2 -> samples points from the top of the FuselageXSec * theta=pi -> samples points from the left side of the FuselageXSec * theta=3pi/2 -> samples points from the bottom of the FuselageXSec Returns: Points sampled from the perimeter of the FuselageXSec, as a [x, y, z] tuple. If theta is a float, then each of x, y, and z will be floats. If theta is an array, then x, y, and z will also be arrays of the same size. .. py:method:: equivalent_radius(preserve='area') Computes an equivalent radius for non-circular cross-sections. This may be necessary when doing analysis that uses axisymmetric assumptions. Can either hold area or perimeter fixed, depending on whether cross-sectional area or wetted area is more important. :param preserve: One of: * "area": holds the cross-sectional area constant * "perimeter": holds the cross-sectional perimeter (i.e., the wetted area of the Fuselage) constant Returns: An equivalent radius value. .. py:method:: translate(xyz) Returns a copy of this FuselageXSec that has been translated by `xyz`. :param xyz: The amount to translate the FuselageXSec. Given as a 3-element NumPy vector. Returns: A copy of this FuselageXSec, translated by `xyz`. .. py:data:: fuse