예제 #1
0
def speed_from_lift(aircraft, pamb, cz, mass):

    wing = aircraft.wing
    g = earth.gravity()
    gam = earth.heat_ratio()
    mach = numpy.sqrt((mass * g) / (0.5 * gam * pamb * wing.area * cz))
    return mach
예제 #2
0
def acceleration(aircraft, nei, altp, disa, speed_mode, speed, mass, rating):
    """
    Aircraft acceleration on level flight
    """

    wing = aircraft.wing
    gam = earth.heat_ratio()

    [pamb, tamb, tstd, dtodz] = earth.atmosphere(altp, disa)

    mach = get_mach(pamb, speed_mode, speed)

    fn, Data = propu.thrust(aircraft, pamb, tamb, mach, rating, nei)

    cz = lift_from_speed(aircraft, pamb, mach, mass)

    cx, lod = aero.drag(aircraft, pamb, tamb, mach, cz)

    if (nei > 0):
        dcx = propu.oei_drag(aircraft, pamb, mach)
        cx = cx + dcx * nei

    acc = (fn - 0.5 * gam * pamb * mach**2 * wing.area * cx) / mass

    return acc
예제 #3
0
def lift_from_speed(aircraft, pamb, mach, mass):

    wing = aircraft.wing
    g = earth.gravity()
    gam = earth.heat_ratio()
    c_z = (2 * mass * g) / (gam * pamb * mach**2 * wing.area)
    return c_z
예제 #4
0
def thrust_yaw_moment(aircraft, fn, pamb, mach, dcx_oei):
    """
    Assumed right engine inoperative
    """

    propulsion = aircraft.propulsion
    wing = aircraft.wing

    gam = earth.heat_ratio()

    if (propulsion.architecture == 1):

        nacelle = aircraft.turbofan_nacelle

    elif (propulsion.architecture == 2):

        nacelle = aircraft.turbofan_nacelle

    elif (propulsion.architecture == 3):

        nacelle = aircraft.turbofan_nacelle

    elif (propulsion.architecture == 4):

        nacelle = aircraft.turboprop_nacelle

    else:
        raise Exception("propulsion.architecture index is out of range")

    cn_prop = (nacelle.y_ext /
               wing.mac) * (fn /
                            (0.5 * gam * pamb * mach**2 * wing.area) + dcx_oei)

    return cn_prop
예제 #5
0
def thrust_pitch_moment(aircraft, fn, pamb, mach, dcx_oei):

    propulsion = aircraft.propulsion
    wing = aircraft.wing

    gam = earth.heat_ratio()

    if (propulsion.architecture == 1):

        nacelle = aircraft.turbofan_nacelle

    elif (propulsion.architecture == 2):

        nacelle = aircraft.turbofan_nacelle

    elif (propulsion.architecture == 3):

        nacelle = aircraft.turbofan_nacelle

    elif (propulsion.architecture == 4):

        nacelle = aircraft.turboprop_nacelle

    else:
        raise Exception("propulsion.architecture index is out of range")

    cm_prop = nacelle.z_ext * (dcx_oei - fn /
                               (0.5 * gam * pamb * mach**2 * wing.area))

    return cm_prop
예제 #6
0
def forward_cg_stall(aircraft, altp, disa, nei, hld_conf, speed_mode, mass):
    """
    Computes max forward trimmable CG position at stall speed
    """

    wing = aircraft.wing
    htp = aircraft.horizontal_tail

    gam = earth.heat_ratio()

    [pamb, tamb, tstd, dtodz] = earth.atmosphere(altp, disa)

    [cz_max_wing, cz0] = craft_aero.high_lift(
        wing, hld_conf)  # Wing maximum lift coefficient without margin

    [cza_htp, xlc_htp, aoa_max_htp,
     ki_htp] = frame_aero.htp_aero_data(aircraft)

    cz_max_htp = cza_htp * aoa_max_htp

    c_z = cz_max_wing - cz_max_htp  # Max forward Cg assumed, HTP has down lift

    mach = flight.speed_from_lift(aircraft, pamb, c_z, mass)

    [cza_wo_htp, xlc_wo_htp,
     ki_wing] = frame_aero.wing_aero_data(aircraft, mach, hld_conf)

    if (nei > 0):
        dcx_oei = nei * propu.oei_drag(pamb, mach)
    else:
        dcx_oei = 0

    dw_angle = frame_aero.wing_downwash(
        aircraft, cz_max_wing)  # Downwash angle due to the wing
    cx_basic, lod_trash = craft_aero.drag(
        aircraft, pamb, tamb, mach,
        cz_max_wing)  # By definition of the drag_ function
    cxi_htp = (ki_htp * cz_max_htp**2) * (htp.area / wing.area
                                          )  # Induced drag generated by HTP
    cx_inter = cz_max_htp * dw_angle  # Interaction drag (due to downwash)
    cx_trimmed = cx_basic + cxi_htp + cx_inter + dcx_oei

    fn = 0.5 * gam * pamb * mach**2 * wing.area * cx_trimmed

    cm_prop = propu.thrust_pitch_moment(aircraft, fn, pamb, mach, dcx_oei)

    cg_max_fwd_stall = (cm_prop + xlc_wo_htp * cz_max_wing -
                        xlc_htp * cz_max_htp) / (cz_max_wing - cz_max_htp)

    aoa_wing = (cz_max_wing - cz0) / cza_wo_htp  # Wing angle of attack
    aoa = aoa_wing - wing.setting  # Reference angle of attack (fuselage axis versus air speed)
    ih = -aoa + dw_angle - aoa_max_htp  # HTP trim setting

    speed = flight.get_speed(pamb, speed_mode, mach)

    return cg_max_fwd_stall, speed, fn, aoa, ih, c_z, cx_trimmed
예제 #7
0
def corrected_air_flow(Ptot, Ttot, Mach):
    """
    Computes the corrected air flow per square meter
    """

    R = earth.gaz_constant()
    gam = earth.heat_ratio()

    f_M = Mach * (1. + 0.5 * (gam - 1) * Mach**2)**(-(gam + 1.) / (2. *
                                                                   (gam - 1.)))

    CQoA = (math.sqrt(gam / R) * Ptot / math.sqrt(Ttot)) * f_M

    return CQoA
예제 #8
0
def eval_pre_design_wing(aircraft):
    """
    Wing predesign
    """

    design_driver = aircraft.design_driver
    fuselage = aircraft.fuselage
    vtp = aircraft.vertical_tail
    nacelle = aircraft.turbofan_nacelle
    weights = aircraft.weights

    wing = aircraft.wing

    wing.t_o_c_t = 0.10
    wing.t_o_c_k = wing.t_o_c_t + 0.01
    wing.t_o_c_r = wing.t_o_c_k + 0.03

    wing.sweep = 1.6 * max(0,
                           (design_driver.cruise_mach - 0.5))  # Empirical law

    wing.dihedral = unit.rad_deg(5)

    if (wing.morphing == 1):  # Aspect ratio is driving parameter
        wing.span = numpy.sqrt(wing.aspect_ratio * wing.area)
    elif (wing.morphing == 2):  # Span is driving parameter
        wing.aspect_ratio = wing.span**2 / wing.area
    else:
        print("geometry_predesign_, wing_morphing index is unkown")

    # Correlation between span loading and tapper ratio
    wing.taper_ratio = 0.3 - 0.025 * (1e-3 * weights.mtow / wing.span)

    # Factor 1.64 accounts for the part of HTP ref area hidden in the fuselage
    wing.net_wetted_area = 1.64 * wing.area

    wing.y_kink = nacelle.y_ext
    wing.y_root = 0.5 * fuselage.width
    wing.y_tip = 0.5 * wing.span

    if (15 < unit.deg_rad(wing.sweep)):  # With kink
        Phi100intTE = max(0, 2 * (wing.sweep - unit.rad_deg(32)))
        tan_phi100 = numpy.tan(Phi100intTE)
        A = ((1 - 0.25 * wing.taper_ratio) * wing.y_kink +
             0.25 * wing.taper_ratio * wing.y_root - wing.y_tip) / (
                 0.75 * wing.y_kink + 0.25 * wing.y_root - wing.y_tip)
        B = (numpy.tan(wing.sweep) - tan_phi100) * (
            (wing.y_tip - wing.y_kink) *
            (wing.y_kink - wing.y_root)) / (0.25 * wing.y_root +
                                            0.75 * wing.y_kink - wing.y_tip)
        wing.c_root = (wing.area - B * (wing.y_tip - wing.y_root)) / (
            wing.y_root + wing.y_kink + A *
            (wing.y_tip - wing.y_root) + wing.taper_ratio *
            (wing.y_tip - wing.y_kink))
        wing.c_kink = A * wing.c_root + B
        wing.c_tip = wing.taper_ratio * wing.c_root

    else:  # Without kink
        wing.c_root = 2 * wing.area / (
            2 * wing.y_root * (1 - wing.taper_ratio) +
            (1 + wing.taper_ratio) * numpy.sqrt(wing.aspect_ratio * wing.area))
        wing.c_tip = wing.taper_ratio * wing.c_root
        wing.c_kink = ((wing.y_tip - wing.y_kink) * wing.c_root +
                       (wing.y_kink - wing.y_root) * wing.c_tip) / (
                           wing.y_tip - wing.y_root)

    tan_phi0 = 0.25 * (wing.c_kink - wing.c_tip) / (
        wing.y_tip - wing.y_kink) + numpy.tan(wing.sweep)

    wing.mac = 2.*(3*wing.y_root*wing.c_root**2 \
            +(wing.y_kink-wing.y_root)*(wing.c_root**2+wing.c_kink**2+wing.c_root*wing.c_kink) \
            +(wing.y_tip-wing.y_kink)*(wing.c_kink**2+wing.c_tip**2+wing.c_kink*wing.c_tip) \
            )/(3*wing.area)

    wing.y_mac = ( 3*wing.c_root*wing.y_root**2 \
              +(wing.y_kink-wing.y_root)*(wing.c_kink*(wing.y_root+wing.y_kink*2.)+wing.c_root*(wing.y_kink+wing.y_root*2.)) \
              +(wing.y_tip-wing.y_kink)*(wing.c_tip*(wing.y_kink+wing.y_tip*2.)+wing.c_kink*(wing.y_tip+wing.y_kink*2.)) \
              )/(3*wing.area)

    x_mac_local = ( (wing.y_kink-wing.y_root)*tan_phi0*((wing.y_kink-wing.y_root)*(wing.c_kink*2.+wing.c_root) \
                   +(wing.y_tip-wing.y_kink)*(wing.c_kink*2.+wing.c_tip))+(wing.y_tip-wing.y_root)*tan_phi0*(wing.y_tip-wing.y_kink)*(wing.c_tip*2.+wing.c_kink) \
                  )/(3*wing.area)

    wing.x_root = vtp.x_mac + 0.25 * vtp.mac - vtp.lever_arm - 0.25 * wing.mac - x_mac_local

    wing.x_kink = wing.x_root + (wing.y_kink - wing.y_root) * tan_phi0
    wing.x_tip = wing.x_root + (wing.y_tip - wing.y_root) * tan_phi0

    wing.x_mac = wing.x_root+( (wing.x_kink-wing.x_root)*((wing.y_kink-wing.y_root)*(wing.c_kink*2.+wing.c_root) \
                        +(wing.y_tip-wing.y_kink)*(wing.c_kink*2.+wing.c_tip))+(wing.x_tip-wing.x_root)*(wing.y_tip-wing.y_kink)*(wing.c_tip*2.+wing.c_kink) \
                       )/(wing.area*3.)
    if (wing.attachment == 1):
        wing.z_root = 0
    else:
        wing.z_root = fuselage.height - 0.5 * wing.t_o_c_r * wing.c_root

    wing.z_kink = wing.z_root + (wing.y_kink - wing.y_root) * numpy.tan(
        wing.dihedral)
    wing.z_tip = wing.z_root + (wing.y_tip - wing.y_root) * numpy.tan(
        wing.dihedral)

    # Wing setting
    #-----------------------------------------------------------------------------------------------------------
    g = earth.gravity()
    gam = earth.heat_ratio()

    disa = 0
    rca = design_driver.ref_cruise_altp
    mach = design_driver.cruise_mach
    mass = 0.95 * weights.mtow

    pamb, tamb, tstd, dtodz = earth.atmosphere(rca, disa)

    cza_wo_htp = frame_aero.cza_wo_htp(mach, fuselage.width, wing.aspect_ratio,
                                       wing.span, wing.sweep)

    # AoA = 2.5° at cruise start
    wing.setting = (0.97 * mass * g) / (0.5 * gam * pamb * mach**2 * wing.area
                                        * cza_wo_htp) - unit.rad_deg(2.5)

    return
예제 #9
0
def eval_bli_nacelle_design(this_nacelle, Pamb, Tamb, Mach, shaft_power,
                            hub_width, body_length, body_width):
    """
    BLI nacelle design
    """

    gam = earth.heat_ratio()
    r = earth.gaz_constant()
    Cp = earth.heat_constant(gam, r)

    (rho, sig) = earth.air_density(Pamb, Tamb)
    Vsnd = earth.sound_speed(Tamb)
    Re = craft_aero.reynolds_number(Pamb, Tamb, Mach)
    Vair = Vsnd * Mach

    # Precalculation of the relation between d0 and d1
    #-----------------------------------------------------------------------------------------------------------

    body_bnd_layer = eval_boundary_layer(body_width, hub_width)

    # Electrical nacelle geometry : e-nacelle diameter is size by cruise conditions
    #-----------------------------------------------------------------------------------------------------------
    r0 = 0.5 * body_width  # Radius of the fuselage, supposed constant
    d0 = craft_aero.boundary_layer(
        Re, body_length
    )  # theoritical thickness of the boundary layer without taking account of fuselage tapering
    r1 = 0.5 * hub_width  # Radius of the hub of the efan nacelle
    d1 = lin_interp_1d(d0, body_bnd_layer[:, 0],
                       body_bnd_layer[:,
                                      1])  # Thickness of the BL around the hub

    deltaV = 2. * Vair * (
        this_nacelle.efficiency_fan / this_nacelle.efficiency_prop - 1.
    )  # speed variation produced by the fan

    PwInput = this_nacelle.efficiency_fan * shaft_power  # kinetic energy produced by the fan

    #===========================================================================================================
    def fct_power_1(y, PwInput, deltaV, rho, Vair, r1, d1):
        (q0, q1, q2, v1, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y)
        Vinlet = Vair - dVbli
        Vjet = Vinlet + deltaV
        Pw = 0.5 * q1 * (Vjet**2 - Vinlet**2)
        y = PwInput - Pw
        return y

    #-----------------------------------------------------------------------------------------------------------

    fct_arg = (PwInput, deltaV, rho, Vair, r1, d1)

    # Computation of y1 : thickness of the vein swallowed by the inlet
    output_dict = fsolve(fct_power_1, x0=d1, args=fct_arg, full_output=True)

    y1 = output_dict[0][0]

    (q0, q1, q2, v1, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y1)

    MachInlet = v1 / Vsnd  # Mean Mach number at inlet position

    Ptot = earth.total_pressure(
        Pamb, MachInlet)  # Stagnation pressure at inlet position

    Ttot = earth.total_temperature(
        Tamb, MachInlet)  # Stagnation temperature at inlet position

    MachFan = 0.5  # required Mach number at fan position

    CQoA1 = craft_aero.corrected_air_flow(
        Ptot, Ttot, MachFan)  # Corrected air flow per area at fan position

    eFanArea = q1 / CQoA1  # Fan area around the hub

    fan_width = math.sqrt(hub_width**2 +
                          4 * eFanArea / math.pi)  # Fan diameter

    Vjet = v1 + deltaV  # Jet velocity

    TtotJet = Ttot + shaft_power / (
        q1 * Cp)  # Stagnation pressure increases due to introduced work

    Tstat = TtotJet - 0.5 * Vjet**2 / Cp  # static temperature

    VsndJet = math.sqrt(gam * r * Tstat)  # Sound velocity at nozzle exhaust

    MachJet = Vjet / VsndJet  # Mach number at nozzle output

    PtotJet = earth.total_pressure(
        Pamb, MachJet)  # total pressure at nozzle exhaust (P = Pamb)

    CQoA2 = craft_aero.corrected_air_flow(
        PtotJet, TtotJet,
        MachJet)  # Corrected air flow per area at nozzle output

    nozzle_area = q1 / CQoA2  # Fan area around the hub

    nozzle_width = math.sqrt(4 * nozzle_area / math.pi)  # Nozzle diameter

    this_nacelle.hub_width = hub_width

    this_nacelle.fan_width = fan_width

    this_nacelle.nozzle_width = nozzle_width

    this_nacelle.nozzle_area = nozzle_area

    this_nacelle.width = 1.19 * fan_width  # Surrounding structure

    this_nacelle.length = 1.68 * this_nacelle.width

    this_nacelle.net_wetted_area = math.pi * this_nacelle.width * this_nacelle.length  # Nacelle wetted area

    this_nacelle.bnd_layer = body_bnd_layer

    this_nacelle.body_length = body_length

    return
예제 #10
0
def fan_thrust_with_bli(nacelle, Pamb, Tamb, Mach, Vair, PwShaft):
    """
    Compute the thrust of a fan of a given geometry swallowing
    the boundary layer (BL) of a body of a given geometry
    The amount of swallowed BL depends on the given shaft power and flying
    conditions.
    """

    bnd_layer = nacelle.bnd_layer

    gam = earth.heat_ratio()
    r = earth.gaz_constant()
    Cp = earth.heat_constant(gam, r)

    Re = craft_aero.reynolds_number(Pamb, Tamb, Mach)
    (rho, sig) = earth.air_density(Pamb, Tamb)
    Vsnd = earth.sound_speed(Tamb)

    d0 = craft_aero.boundary_layer(
        Re, nacelle.body_length
    )  # theorical thickness of the boundary layer without taking account of fuselage tapering
    r1 = 0.5 * nacelle.hub_width  # Radius of the hub of the eFan nacelle
    d1 = lin_interp_1d(d0, bnd_layer[:, 0],
                       bnd_layer[:, 1])  # Using the precomputed relation

    #===========================================================================================================
    def fct_power_bli(y, PwShaft, Tamb, Pamb, rho, Mach, Vair, Vsnd, r1, d1,
                      nozzle_area):

        Ttot = earth.total_temperature(
            Tamb, Mach)  # Stagnation temperature at inlet position
        (q0, q1, q2, Vinlet,
         dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y)
        Tstat = Ttot - 0.5 * Vinlet**2 / Cp  # Static temperature at inlet position
        Vsnd_inlet = earth.sound_speed(Tstat)  # Sound speed at inlet position
        MachInlet = Vinlet / Vsnd_inlet  # Mean Mach number at inlet position
        PwInput = nacelle.efficiency_fan * PwShaft
        Vjet = math.sqrt(2. * PwInput / q1 + Vinlet**2)
        TtotJet = Ttot + PwShaft / (
            q1 * Cp)  # Stagnation temperature increases due to introduced work
        Tstat = TtotJet - 0.5 * Vjet**2 / Cp  # Static temperature
        VsndJet = earth.sound_speed(Tstat)  # Sound speed at nozzle exhaust
        MachJet = Vjet / VsndJet  # Mach number at nozzle output
        PtotJet = earth.total_pressure(
            Pamb, MachJet)  # total pressure at nozzle exhaust (P = Pamb)
        CQoA1 = craft_aero.corrected_air_flow(
            PtotJet, TtotJet,
            MachJet)  # Corrected air flow per area at fan position
        q = CQoA1 * nozzle_area

        y = q1 - q

        return y

    #-----------------------------------------------------------------------------------------------------------

    nozzle_area = nacelle.nozzle_area

    fct_arg = (PwShaft, Tamb, Pamb, rho, Mach, Vair, Vsnd, r1, d1, nozzle_area)

    # Computation of y1 : thikness of the vein swallowed by the inlet
    output_dict = fsolve(fct_power_bli,
                         x0=0.50,
                         args=fct_arg,
                         full_output=True)

    y = output_dict[0][0]

    Ttot = earth.total_temperature(
        Tamb, Mach)  # Stagnation temperature at inlet position
    (q0, q1, q2, Vinlet, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y)
    Tstat = Ttot - 0.5 * Vinlet**2 / Cp  # Static temperature at inlet position
    Vsnd_inlet = earth.sound_speed(Tstat)  # Sound speed at inlet position
    MachInlet = Vinlet / Vsnd_inlet  # Mean Mach number at inlet position
    PwInput = nacelle.efficiency_fan * PwShaft
    Vjet = math.sqrt(2. * PwInput / q1 + Vinlet**2)

    eFn = q1 * (Vjet - Vinlet)

    return (eFn, q1, dVbli)