Example #1
0
def sound_speed_grad(tamb, tamb_d):
    """
    Sound speed for ideal gaz
    """
    R = earth.gaz_constant()
    gam = earth.heat_ratio()
    vsnd = numpy.sqrt(gam * R * tamb)
    vsnd_d = 0.5 * numpy.sqrt(gam * R / tamb) * tamb_d
    return vsnd, vsnd_d
Example #2
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] = airplane_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 = airplane_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
Example #3
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 = (numpy.sqrt(gam / R) * Ptot / numpy.sqrt(Ttot)) * f_M

    return CQoA
Example #4
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

    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
Example #5
0
def state_dot(xin, state, rating, nei, aircraft):

    g = earth.gravity()
    gam = earth.heat_ratio()

    area = aircraft.wing.area

    cz, fn = xin
    t, mass, xg, zg, vgnd, path = state

    xg_d = vgnd * numpy.cos(path)
    zg_d = vgnd * numpy.sin(path)

    pamb, pamb_d, tamb, tamb_d, disa, disa_d, wx, wx_d, wz, wz_d = air(
        xg, zg, xg_d, zg_d)

    rho, rho_d, sig, sig_d = g_earth.air_density_grad(pamb, pamb_d, tamb,
                                                      tamb_d)

    vsnd, vsnd_d = g_earth.sound_speed_grad(tamb, tamb_d)

    altp, altp_d = g_earth.pressure_altitude_grad(pamb, pamb_d)

    # Compute state_dot
    #-----------------------------------------------------------------------------------------------------------
    vxair = xg_d - wx  # Local wind is introduced here
    vzair = zg_d - wz

    vair = numpy.sqrt(vxair**2 + vzair**2)
    mach = vair / vsnd

    cx, lod = airplane_aero.drag(aircraft, pamb, tamb, mach,
                                 cz)  # Aerodynamic drag model

    path_d = ((0.5 * rho * vair**2) * area * cz -
              mass * g * numpy.cos(path)) / (mass * vair)  # Lift equation
    vgnd_d = (fn - mass * g * numpy.sin(path) -
              (0.5 * rho * vair**2) * area * cx) / mass  # Drag equation

    sfc = propu.sfc(aircraft, pamb, tamb, mach, rating,
                    nei)  # Propulsion consumption model

    mass_d = -sfc * fn

    state_d = numpy.array([1., mass_d, xg_d, zg_d, vgnd_d, path_d])

    # Compute other derivatives
    #-----------------------------------------------------------------------------------------------------------
    vxgnd_d = vgnd_d * numpy.cos(path) - vgnd * numpy.sin(path) * path_d
    vzgnd_d = vgnd_d * numpy.sin(path) + vgnd * numpy.cos(path) * path_d

    vxair_d = vxgnd_d - wx_d
    vzair_d = vzgnd_d - wz_d

    vair_d = (vxair * vxair_d + vzair * vzair_d) / vair
    mach_d = vair_d / vsnd - vair * vsnd_d / vsnd**2

    vcas, vcas_d = g_earth.vcas_from_mach_grad(pamb, pamb_d, mach, mach_d)

    xout = numpy.array([
        t, mass, xg, zg, vgnd, path, 1., mass_d, xg_d, zg_d, vgnd_d, path_d,
        vxgnd_d, vzgnd_d, vair, vair_d, vxair, vxair_d, vzair, vzair_d, mach,
        mach_d, vcas, vcas_d, altp, altp_d, pamb, pamb_d, tamb, tamb_d, disa,
        disa_d, rho, rho_d, wx, wx_d, wz, wz_d, cz, cx, fn
    ])

    return xout, state_d
Example #6
0
def eval_wing_design(aircraft):
    """
    Wing predesign
    """

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

    c_g = aircraft.center_of_gravity
    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 = 0.7 * fuselage.width + 1.4 * nacelle.width  # statistical regression
    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
Example #7
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 = earth.reynolds_number(Pamb,Tamb,Mach)
    Vair = Vsnd*Mach

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

    body_bnd_layer = resize_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 = jet.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) = jet.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) = jet.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 = jet.corrected_air_flow(Ptot,Ttot,MachFan)        # Corrected air flow per area at fan position

    eFanArea = q1/CQoA1     # Fan area around the hub

    fan_width = numpy.sqrt(hub_width**2 + 4*eFanArea/numpy.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 = numpy.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 = jet.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 = numpy.sqrt(4*nozzle_area/numpy.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.20*fan_width      # Surrounding structure

    this_nacelle.length = 1.50*this_nacelle.width

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

    this_nacelle.bnd_layer = body_bnd_layer

    this_nacelle.body_length = body_length

    return
Example #8
0
def fan_thrust(nacelle, Pamb, Tamb, Mach, PwShaft):
    """
    Compute the thrust of a fan of given geometry swallowing free air stream
    """

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

    #===========================================================================================================
    def fct_power(q, PwShaft, Pamb, Ttot, Vair, NozzleArea):

        Vinlet = Vair
        PwInput = nacelle.efficiency_fan * PwShaft
        Vjet = numpy.sqrt(2. * PwInput / q +
                          Vinlet**2)  # Supposing isentropic compression
        TtotJet = Ttot + PwShaft / (
            q * Cp)  # Stagnation temperature increases due to introduced work
        TstatJet = TtotJet - 0.5 * Vjet**2 / Cp  # Static temperature
        VsndJet = earth.sound_speed(TstatJet)  # 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 = corrected_air_flow(
            PtotJet, TtotJet,
            MachJet)  # Corrected air flow per area at fan position
        q0 = CQoA1 * NozzleArea

        y = q0 - q

        return y

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

    NozzleArea = nacelle.nozzle_area
    FanWidth = nacelle.fan_width

    Ptot = earth.total_pressure(Pamb, Mach)  # Total pressure at inlet position
    Ttot = earth.total_temperature(Tamb,
                                   Mach)  # Total temperature at inlet position

    Vsnd = earth.sound_speed(Tamb)
    Vair = Vsnd * Mach

    fct_arg = (PwShaft, Pamb, Ttot, Vair, NozzleArea)

    CQoA0 = corrected_air_flow(
        Ptot, Ttot, Mach)  # Corrected air flow per area at fan position
    q0init = CQoA0 * (0.25 * numpy.pi * FanWidth**2)

    # Computation of the air flow swallowed by the inlet
    output_dict = fsolve(fct_power, x0=q0init, args=fct_arg, full_output=True)

    q0 = output_dict[0][0]
    if (output_dict[2] != 1):
        raise Exception("Convergence problem")

    Vinlet = Vair
    PwInput = nacelle.efficiency_fan * PwShaft
    Vjet = numpy.sqrt(2. * PwInput / q0 + Vinlet**2)

    eFn = q0 * (Vjet - Vinlet)

    return (eFn, q0)
Example #9
0
def fan_thrust_with_bli(nacelle, Pamb, Tamb, Mach, 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.
    """

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

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

        (q0, q1, q2, Vinlet, dVbli) = air_flows(rho, Vair, r1, d1, y)
        PwInput = nacelle.efficiency_fan * PwShaft
        Vjet = numpy.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) supposing adapted nozzle
        CQoA1 = corrected_air_flow(
            PtotJet, TtotJet,
            MachJet)  # Corrected air flow per area at nozzle position
        q = CQoA1 * nozzle_area

        y = q1 - q

        return y

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

    nozzle_area = nacelle.nozzle_area
    bnd_layer = nacelle.bnd_layer

    Re = earth.reynolds_number(Pamb, Tamb, Mach)

    d0 = 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

    Ttot = earth.total_temperature(
        Tamb, Mach)  # Stagnation temperature at inlet position
    rho, sig = earth.air_density(Pamb, Tamb)
    Vsnd = earth.sound_speed(Tamb)
    Vair = Vsnd * Mach

    fct_arg = (PwShaft, Pamb, rho, Ttot, Vair, 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]
    if (output_dict[2] != 1):
        raise Exception("Convergence problem")

    (q0, q1, q2, Vinlet, dVbli) = air_flows(rho, Vair, r1, d1, y)
    PwInput = nacelle.efficiency_fan * PwShaft
    Vjet = numpy.sqrt(2. * PwInput / q1 + Vinlet**2)

    eFn = q1 * (Vjet - Vinlet)

    return (eFn, q1, dVbli)