def fuselage_base_drag_coefficient(mach: float) -> float:
    """
    A fit for the fuselage base drag coefficient of a cylindrical fuselage, as described in:

    MIL-HDBK-762: DESIGN OF AERODYNAMICALLY STABILIZED FREE ROCKETS:
        * Section 5-5.3.1 Body-of-Revolution Base Drag, Rocket Jet Plume-Off
        * Figure 5-140: Effects of Mach Number and Reynolds Number on Base Pressure

    Fits in /studies/FuselageBaseDragCoefficient

    Args:
        mach: Mach number [-]

    Returns: Fuselage base drag coefficient

    """

    m = mach
    p = {
        'a': 0.18024110740341143,
        'center_sup': -0.21737019935624047,
        'm_trans': 0.9985447737532848,
        'pc_sub': 0.15922582283573747,
        'pc_sup': 0.04698820458826384,
        'scale_sup': 0.34978926411193456,
        'trans_str': 9.999987483414937
    }

    return np.blend(
        p["trans_str"] * (m - p["m_trans"]), p["pc_sup"] +
        p["a"] * np.exp(-(p["scale_sup"] * (m - p["center_sup"]))**2),
        p["pc_sub"])
Example #2
0
 def CM_function(alpha, Re, mach=0, deflection=0):
     alpha = np.mod(alpha + 180,
                    360) - 180  # Keep alpha in the valid range.
     CM_attached = CM_attached_interpolator({
         "alpha": alpha,
         "ln_Re": np.log(Re),
     })
     CM_separated = CM_separated_interpolator(alpha)
     return np.blend(separation_parameter(alpha, Re), CM_separated,
                     CM_attached)
Example #3
0
 def CD_function(alpha, Re, mach=0, deflection=0):
     alpha = np.mod(alpha + 180,
                    360) - 180  # Keep alpha in the valid range.
     log10_CD_attached = log10_CD_attached_interpolator({
         "alpha":
         alpha,
         "ln_Re":
         np.log(Re),
     })
     log10_CD_separated = log10_CD_separated_interpolator(alpha)
     return 10**np.blend(
         separation_parameter(alpha, Re),
         log10_CD_separated,
         log10_CD_attached,
     )
Example #4
0
def approximate_CD_wave(
    mach,
    mach_crit,
    CD_wave_at_fully_supersonic,
):
    """
    An approximate relation for computing transonic wave drag, based on an object's Mach number.

    Considered reasonably valid from Mach 0 up to around Mach 2 or 3-ish.

    Methodology is a combination of:

        * The methodology described in Raymer, "Aircraft Design: A Conceptual Approach", Section 12.5.10 Transonic Parasite Drag (pg. 449 in Ed. 2)

        and

        * The methodology described in W.H. Mason's Configuration Aerodynamics, Chapter 7. Transonic Aerodynamics of Airfoils and Wings.

    Args:

        mach: Mach number at the operating point to be evaluated

        mach_crit: Critical mach number, a function of the body geometry

        CD_wave_at_fully_supersonic: The wave drag coefficient of the body at the speed that it first goes (
        effectively) fully supersonic.

            Here, that is taken to mean at the Mach 1.2 case.

            This value should probably be derived using something similar to a Sears-Haack relation for the body in
            question, with a markup depending on geometry smoothness.

            The CD_wave predicted by this function will match this value exactly at M=1.2 and M=1.05.

            The peak CD_wave that is predicted is ~1.23 * this value, which occurs at M=1.10.

            In the high-Mach limit, this function asymptotes at 0.80 * this value, as empirically stated by Raymer.
            However, this model is only approximate and is likely not valid for high-supersonic flows.

    Returns: The approximate wave drag coefficient at the specified Mach number.

        The reference area is whatever the reference area used in the `CD_wave_at_fully_supersonic` parameter is.

    """
    mach_crit_max = 1 - (0.1 / 80)**(1 / 3)

    mach_crit = -np.softmax(-mach_crit, -mach_crit_max, hardness=50)

    ### The following approximate relation is derived in W.H. Mason, "Configuration Aerodynamics", Chapter 7. Transonic Aerodynamics of Airfoils and Wings.
    ### Equation 7-8 on Page 7-19.
    ### This is in turn based on Lock's proposed empirically-derived shape of the drag rise, from Hilton, W.F., High Speed Aerodynamics, Longmans, Green & Co., London, 1952, pp. 47-49
    mach_dd = mach_crit + (0.1 / 80)**(1 / 3)

    ### Model drag sections and cutoffs:
    return CD_wave_at_fully_supersonic * np.where(
        mach < mach_crit,
        0,
        np.where(
            mach < mach_dd,
            20 * (mach - mach_crit)**4,
            np.where(
                mach < 1.05,
                cubic_hermite_patch(mach,
                                    x_a=mach_dd,
                                    x_b=1.05,
                                    f_a=20 * (0.1 / 80)**(4 / 3),
                                    f_b=1,
                                    dfdx_a=0.1,
                                    dfdx_b=10),
                np.where(mach < 1.2,
                         cubic_hermite_patch(mach,
                                             x_a=1.05,
                                             x_b=1.2,
                                             f_a=1,
                                             f_b=1,
                                             dfdx_a=10,
                                             dfdx_b=-4),
                         np.blend(
                             switch=4 * 2 * (mach - 1.2) / (1.2 - 0.8),
                             value_switch_high=0.8,
                             value_switch_low=1.2,
                         )
                         # 0.8 + 0.2 * np.exp(20 * (1.2 - mach))
                         ))))
Example #5
0
def model(m, p):
    return np.blend(
        p["trans_str"] * (m - p["m_trans"]), p["pc_sup"] +
        p["a"] * np.exp(-(p["scale_sup"] * (m - p["center_sup"]))**2),
        p["pc_sub"])
Example #6
0
def model(m, p):
    return np.blend(
        p["trans_str"] * (m - p["trans"]),
        p["cd_sup"] + np.exp(p["a_sup"] + p["s_sup"] * (m - p["trans"])),
        p["cd_sub"] + np.exp(p["a_sub"] + p["s_sub"] * (m - p["trans"])))
Example #7
0
def Cd_cylinder(Re_D: float,
                mach: float = 0.,
                include_mach_effects=True,
                subcritical_only=False) -> float:
    """
    Returns the drag coefficient of a cylinder in crossflow as a function of its Reynolds number and Mach.

    Args:
        Re_D: Reynolds number, referenced to diameter
        mach: Mach number
        include_mach_effects: If this is set False, it assumes Mach = 0, which simplifies the computation.
        subcritical_only: Determines whether the model models purely subcritical (Re < 300k) cylinder flows. Useful, since
    this model is now convex and can be more well-behaved.

    Returns:

    # TODO rework this function to use tanh blending, which will mitigate overflows

    """

    ##### Do the viscous part of the computation
    csigc = 5.5766722118597247
    csigh = 23.7460859935990563
    csub0 = -0.6989492360435040
    csub1 = 1.0465189382830078
    csub2 = 0.7044228755898569
    csub3 = 0.0846501115443938
    csup0 = -0.0823564417206403
    csupc = 6.8020230357616764
    csuph = 9.9999999999999787
    csupscl = -0.4570690347113859

    x = np.log10(np.abs(Re_D) + 1e-16)

    if subcritical_only:
        Cd_mach_0 = 10**(csub0 * x + csub1) + csub2 + csub3 * x
    else:
        log10_Cd = (
            (np.log10(10**(csub0 * x + csub1) + csub2 + csub3 * x)) *
            (1 - 1 / (1 + np.exp(-csigh * (x - csigc)))) +
            (csup0 + csupscl / csuph * np.log(np.exp(csuph *
                                                     (csupc - x)) + 1)) *
            (1 / (1 + np.exp(-csigh * (x - csigc)))))
        Cd_mach_0 = 10**log10_Cd

    ##### Do the compressible part of the computation
    if include_mach_effects:
        m = mach
        p = {
            'a_sub': 0.03458900259594298,
            'a_sup': -0.7129528087049688,
            'cd_sub': 1.163206940186374,
            'cd_sup': 1.2899213533122527,
            's_sub': 3.436601777569716,
            's_sup': -1.37123096976983,
            'trans': 1.022819211244295,
            'trans_str': 19.017600596069848
        }

        Cd_over_Cd_mach_0 = np.blend(
            p["trans_str"] *
            (m - p["trans"]), p["cd_sup"] + np.exp(p["a_sup"] + p["s_sup"] *
                                                   (m - p["trans"])),
            p["cd_sub"] + np.exp(p["a_sub"] + p["s_sub"] *
                                 (m - p["trans"]))) / 1.1940010047391572

        Cd = Cd_mach_0 * Cd_over_Cd_mach_0

    else:
        Cd = Cd_mach_0

    return Cd