Example #1
0
def air_path(aircraft, nei, altp, disa, speed_mode, speed, mass, rating):
    """
    Retrieves air path in various conditions
    """

    g = earth.gravity()

    [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
        lod = cz / cx

    acc_factor = earth.climb_mode(speed_mode, dtodz, tstd, disa, mach)

    slope = (fn / (mass * g) - 1 / lod) / acc_factor

    vsnd = earth.sound_speed(tamb)

    v_z = mach * vsnd * slope

    return slope, v_z
Example #2
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
Example #3
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
Example #4
0
def pressure_altitude_grad(pamb, pamb_d):
    """
    Pressure altitude from ground to 50 km
    """
    g = earth.gravity()
    R = earth.gaz_constant()

    Z = numpy.array([0., 10999., 19999., 31999., 46999., 49999.])
    dtodz = numpy.array([-0.0065, 0., 0.0010, 0.0028, 0.])

    P = numpy.array([earth.sea_level_pressure(), 0., 0., 0., 0., 0.])
    T = numpy.array([earth.sea_level_temperature(), 0., 0., 0., 0., 0.])

    j = 0
    n = len(P) - 1
    P[1] = P[0] * (1 + (dtodz[0] / T[0]) * (Z[1] - Z[0]))**(-g /
                                                            (R * dtodz[0]))
    T[1] = T[0] + dtodz[0] * (Z[1] - Z[0])

    while (j < n and pamb < P[j + 1]):
        j = j + 1
        T[j + 1] = T[j] + dtodz[j] * (Z[j + 1] - Z[j])
        if (0. < numpy.abs(dtodz[j])):
            P[j + 1] = P[j] * (1 + (dtodz[j] / T[j]) *
                               (Z[j + 1] - Z[j]))**(-g / (R * dtodz[j]))
        else:
            P[j + 1] = P[j] * numpy.exp(-(g / R) * ((Z[j + 1] - Z[j]) / T[j]))

    if (pamb < P[n]):
        raise Exception("pressure_altitude_grad, altitude cannot exceed 50km")

    if (0. < numpy.abs(dtodz[j])):
        altp = Z[j] + (
            (pamb / P[j])**(-(R * dtodz[j]) / g) - 1) * (T[j] / dtodz[j])
        altp_d = (T[j] / dtodz[j]) * (-(R * dtodz[j]) /
                                      (g * P[j])) * pamb_d * (pamb / P[j])**(
                                          -(R * dtodz[j]) / g - 1)
    else:
        altp = Z[j] - (T[j] / (g / R)) * numpy.log(pamb / P[j])
        altp_d = -((T[j] * R) / g) * (pamb_d / pamb)

    return altp, altp_d
Example #5
0
def approach_speed(aircraft, altp, disa, mass, hld_conf):
    """
    Minimum approach speed (VLS)
    """

    wing = aircraft.wing

    g = earth.gravity()

    czmax, trash = airplane_aero.high_lift(wing, hld_conf)

    stall_margin = regul.kvs1g_min_landing()

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

    [rho, sig] = earth.air_density(pamb, tamb)

    vapp = numpy.sqrt(
        (mass * g) / (0.5 * rho * wing.area * (czmax / stall_margin**2)))

    return vapp
Example #6
0
def specific_air_range(aircraft, altp, mass, mach, disa):

    propulsion = aircraft.propulsion

    (MTO, MCN, MCL, MCR, FID) = propulsion.rating_code

    g = earth.gravity()

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

    vsnd = earth.sound_speed(tamb)

    Cz = flight.lift_from_speed(aircraft, pamb, mach, mass)

    [Cx, LoD] = airplane_aero.drag(aircraft, pamb, tamb, mach, Cz)

    nei = 0.

    sfc = propu.sfc(aircraft, pamb, tamb, mach, MCR, nei)

    sar = (vsnd * mach * LoD) / (mass * g * sfc)

    return sar
Example #7
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 #8
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 #9
0
def mission(aircraft, dist_range, tow, altp, mach, disa):
    """
    Mission computation using breguet equation, fixed L/D and fixed sfc
    """

    engine = aircraft.turbofan_engine
    propulsion = aircraft.propulsion
    battery = aircraft.battery

    (MTO, MCN, MCL, MCR, FID) = propulsion.rating_code

    g = earth.gravity()

    pamb, tamb, tstd, dtodz = earth.atmosphere(altp, disa)
    vsnd = earth.sound_speed(tamb)
    tas = vsnd * mach

    lod_max, cz_lod_max = airplane_aero.lod_max(aircraft, pamb, tamb, mach)

    lod_cruise = 0.95 * lod_max

    nei = 0.

    sfc = propu.sfc(aircraft, pamb, tamb, mach, MCR, nei)

    if (propulsion.architecture == 2):
        fn, sec, data = propu.hybrid_thrust(aircraft, pamb, tamb, mach, MCR,
                                            nei)
    if (propulsion.architecture == 3):
        fn, sec, data = propu.hybrid_thrust(aircraft, pamb, tamb, mach, MCR,
                                            nei)

    # Departure ground phases
    #-----------------------------------------------------------------------------------------------------------
    fuel_taxi_out = (34 + 2.3e-4 * engine.reference_thrust) * engine.n_engine
    time_taxi_out = 540

    fuel_take_off = 1e-4 * (2.8 + 2.3 / engine.bpr) * tow
    time_take_off = 220 * tow / (engine.reference_thrust * engine.n_engine)

    # Mission leg
    #-----------------------------------------------------------------------------------------------------------
    if (propulsion.architecture == 1):
        fuel_mission = tow * (1 - numpy.exp(-(sfc * g * dist_range) /
                                            (tas * lod_cruise)))
    elif (propulsion.architecture == 2):
        fuel_mission = tow*(1-numpy.exp(-(sfc*g*dist_range)/(tas*lod_cruise))) \
                        - (sfc/sec)*battery.energy_cruise
    elif (propulsion.architecture == 3):
        fuel_mission = tow*(1-numpy.exp(-(sfc*g*dist_range)/(tas*lod_cruise))) \
                        - (sfc/sec)*battery.energy_cruise
    elif (propulsion.architecture == 4):
        fuel_mission = tow * (1 - numpy.exp(-(sfc * g * dist_range) /
                                            (tas * lod_cruise)))
    else:
        raise Exception("propulsion.architecture index is out of range")

    time_mission = 1.09 * (dist_range / tas)

    l_w = tow - fuel_mission

    # Arrival ground phases
    #-----------------------------------------------------------------------------------------------------------
    fuel_landing = 1e-4 * (0.5 + 2.3 / engine.bpr) * l_w
    time_landing = 180

    fuel_taxi_in = (26 + 1.8e-4 * engine.reference_thrust) * engine.n_engine
    time_taxi_in = 420

    # Block fuel and time
    #-----------------------------------------------------------------------------------------------------------
    block_fuel = fuel_taxi_out + fuel_take_off + fuel_mission + fuel_landing + fuel_taxi_in
    time_block = time_taxi_out + time_take_off + time_mission + time_landing + time_taxi_in

    # Diversion and holding reserve fuel
    #-----------------------------------------------------------------------------------------------------------
    fuel_diversion = l_w * (1 -
                            numpy.exp(-(sfc * g * regul.diversion_range()) /
                                      (tas * lod_cruise)))

    fuel_holding = sfc * (l_w * g / lod_max) * regul.holding_time()

    # Total
    #-----------------------------------------------------------------------------------------------------------
    design_range = aircraft.design_driver.design_range

    fuel_total = fuel_mission * (1 + regul.reserve_fuel_ratio(design_range)
                                 ) + fuel_diversion + fuel_holding

    #-----------------------------------------------------------------------------------------------------------
    return block_fuel, time_block, fuel_total
Example #10
0
def atmosphere_grad(altp, altp_d, disa, disa_d):
    """
    Pressure from pressure altitude from ground to 50 km
    """
    g = earth.gravity()
    R = earth.gaz_constant()

    Z = numpy.array([0., 10999., 19999., 31999., 46999., 49999.])
    Z_d = numpy.array([0., 0., 0., 0., 0., 0.])

    dtodz = numpy.array([-0.0065, 0., 0.0010, 0.0028, 0.])
    dtodz_d = numpy.array([0., 0., 0., 0., 0.])

    P = numpy.array([earth.sea_level_pressure(), 0., 0., 0., 0., 0.])
    P_d = numpy.array([0., 0., 0., 0., 0., 0.])

    T = numpy.array([earth.sea_level_temperature(), 0., 0., 0., 0., 0.])
    T_d = numpy.array([0., 0., 0., 0., 0., 0.])

    if (Z[-1] < altp):
        raise Exception("atmosphere_grad, altitude cannot exceed 50km")

    j = 0

    while (Z[1 + j] <= altp):
        T[j + 1] = T[j] + dtodz[j] * (Z[j + 1] - Z[j])
        T_d[j + 1] = T_d[j] + dtodz_d[j] * (Z[j + 1] - Z[j]) + dtodz[j] * (
            Z_d[j + 1] - Z_d[j])
        if (0. < numpy.abs(dtodz[j])):
            B1 = 1 + (dtodz[j] * (Z[1 + j] - Z[j])) / (T[j] + disa)
            B1_dz = (dtodz[j] * (Z_d[1 + j] - Z_d[j])) / (T[j] + disa)
            B1_dt = (dtodz_d[j] * (Z[1 + j] - Z[j])) / (T[j] + disa) - (
                dtodz[j] * (Z[1 + j] - Z[j]) * disa_d) / (T[j] + disa)**2
            B2 = -g / (R * dtodz[j])
            B2_dt = (g * dtodz_d[j]) / (R * dtodz[j]**2)
            P[1 + j] = P[j] * B1**B2
            P_d[1 + j] = P[j] * (
                B2 * B1_dz * B1**(B2 - 1) + (B1**B2) *
                (B2_dt * numpy.log(B1) + B2 * B1_dt / B1)) + P_d[j] * B1**B2
        else:
            B3 = -(g / R) * ((Z[1 + j] - Z[j]) / (T[j] + disa))
            B3_d = -(g / R) * ((Z_d[1 + j] - Z_d[j]) /
                               (T[j] + disa)) + (g / R) * ((Z[1 + j] - Z[j]) *
                                                           (T_d[j] + disa_d) /
                                                           (T[j] + disa)**2)
            P[j + 1] = P[j] * numpy.exp(B3)
            P_d[j + 1] = P_d[j] * numpy.exp(B3) + P[j] * B3_d * numpy.exp(B3)
        j = j + 1

    if (0. < numpy.abs(dtodz[j])):
        B1 = 1 + (dtodz[j] * (altp - Z[j])) / (T[j] + disa)
        B1_dz = (dtodz[j] * (altp_d - Z_d[j])) / (T[j] + disa)
        B1_dt = (dtodz_d[j] *
                 (altp - Z[j])) / (T[j] + disa) - (dtodz[j] * (altp - Z[j]) *
                                                   disa_d) / (T[j] + disa)**2
        B2 = -g / (R * dtodz[j])
        B2_dt = (g * dtodz_d[j]) / (R * dtodz[j]**2)
        pamb = P[j] * B1**B2
        pamb_d = P[j] * (
            B2 * B1_dz * B1**(B2 - 1) + (B1**B2) *
            (B2_dt * numpy.log(B1) + B2 * B1_dt / B1)) + P_d[j] * B1**B2
    else:
        B3 = -(g / R) * ((altp - Z[j]) / (T[j] + disa))
        B3_d = -(g / R) * ((altp_d - Z_d[j]) /
                           (T[j] + disa)) + (g / R) * ((altp - Z[j]) *
                                                       (T_d[j] + disa_d) /
                                                       (T[j] + disa)**2)
        pamb = P[j] * numpy.exp(B3)
        pamb_d = P_d[j] * numpy.exp(B3) + P[j] * B3_d * numpy.exp(B3)

    tamb = T[j] + dtodz[j] * (altp - Z[j]) + disa
    tamb_d = T_d[j] + dtodz_d[j] * (altp - Z[j]) + dtodz[j] * (altp_d -
                                                               Z_d[j]) + disa_d

    return pamb, pamb_d, tamb, tamb_d, dtodz[j]