Example #1
0
def wave_drag_volume(vehicle,mach,scaling_factor):
    """Computes the volume drag

    Assumptions:
    Basic fit

    Source:
    D. Raymer, Aircraft Design: A Conceptual Approach, Fifth Ed. pg. 448-449

    Inputs:
    vehicle.
      wings.main_wing.sweeps.leading_edge [rad]
      total_length                        [m]
      maximum_cross_sectional_area        [m^2]
      reference_area                      [m^2]
      
    Outputs:
    vehicle_wave_drag                     [Unitless]

    Properties Used:
    N/A
    """ 
    
    num_main_wings = 0
    for wing in vehicle.wings:
        if isinstance(wing,Main_Wing):
            main_wing = wing
            num_main_wings += 1
        if num_main_wings > 1:
            raise NotImplementedError('This function is not designed to handle multiple main wings.')
    
    main_wing = vehicle.wings.main_wing
    # estimation of leading edge sweep if not defined 
    if main_wing.sweeps.leading_edge == None:                           
        main_wing.sweeps.leading_edge  = convert_sweep(main_wing,old_ref_chord_fraction = 0.25 ,new_ref_chord_fraction = 0.0) 
        
    LE_sweep = main_wing.sweeps.leading_edge / Units.deg
    L        = vehicle.total_length
    Ae       = vehicle.maximum_cross_sectional_area
    S        = vehicle.reference_area
    
    # Compute sears-hack D/q
    Dq_SH = 9*np.pi/2*(Ae/L)*(Ae/L)
    
    spline = Cubic_Spline_Blender(1.2,1.3)
    h00 = lambda M:spline.compute(M)    
    
    # Compute full vehicle D/q
    Dq_vehicle           = np.zeros_like(mach)
    Dq_vehicle_simpified = np.zeros_like(mach)
    
    Dq_vehicle[mach>=1.2] = scaling_factor*(1-0.2*(mach[mach>=1.2]-1.2)**0.57*(1-np.pi*LE_sweep**.77/100))*Dq_SH
    Dq_vehicle_simpified  = scaling_factor*Dq_SH
    
    Dq_vehicle = Dq_vehicle_simpified*h00(mach) + Dq_vehicle*(1-h00(mach))
    
    CD_c_vehicle = Dq_vehicle/S
    
    return CD_c_vehicle
Example #2
0
    def evaluate_thrust(self, state):
        """ Calculate thrust given the current state of the vehicle
        
            Assumptions:
            None
            
            Source:
            N/A
            
            Inputs:
            state [state()]
            
            Outputs:
            results.thrust_force_vector [newtons]
            results.vehicle_mass_rate   [kg/s]
            
            Properties Used:
            Defaulted values
        """

        # Unpack the surrogate
        sfc_surrogate = self.sfc_surrogate
        thr_surrogate = self.thrust_surrogate

        # Unpack the conditions
        conditions = state.conditions
        # rescale altitude for proper surrogate performance
        altitude = conditions.freestream.altitude / self.altitude_input_scale
        mach = conditions.freestream.mach_number
        throttle = conditions.propulsion.throttle

        cond = np.hstack([altitude, mach, throttle])

        if self.use_extended_surrogate:
            lo_blender = Cubic_Spline_Blender(0, .01)
            hi_blender = Cubic_Spline_Blender(0.99, 1)
            sfc = self.extended_sfc_surrogate(sfc_surrogate, cond, lo_blender,
                                              hi_blender)
            thr = self.extended_thrust_surrogate(thr_surrogate, cond,
                                                 lo_blender, hi_blender)
        else:
            sfc = sfc_surrogate.predict(cond)
            thr = thr_surrogate.predict(cond)

        sfc = sfc * self.sfc_input_scale * self.sfc_anchor_scale
        thr = thr * self.thrust_input_scale * self.thrust_anchor_scale

        F = thr
        mdot = thr * sfc * self.number_of_engines

        # Save the output
        results = Data()
        results.thrust_force_vector = self.number_of_engines * F * [
            np.cos(self.thrust_angle), 0, -np.sin(self.thrust_angle)
        ]
        results.vehicle_mass_rate = mdot

        return results
Example #3
0
def induced_drag_aircraft(state, settings, geometry):
    """Determines induced drag for the full aircraft

    Assumptions:
    Based on fits

    Source:
    http://aerodesign.stanford.edu/aircraftdesign/aircraftdesign.html (Stanford AA241 A/B Course Notes)

    Inputs:
    state.conditions.aerodynamics.lift_coefficient               [Unitless]
    state.conditions.aerodynamics.drag_breakdown.parasite.total  [Unitless]
    configuration.oswald_efficiency_factor                       [Unitless]
    configuration.viscous_lift_dependent_drag_factor             [Unitless]
    geometry.wings['main_wing'].span_efficiency                  [Unitless]
    geometry.wings['main_wing'].aspect_ratio                     [Unitless]

    Outputs:
    total_induced_drag                                           [Unitless]

    Properties Used:
    N/A
    """

    # unpack inputs
    conditions = state.conditions
    configuration = settings

    aircraft_lift = conditions.aerodynamics.lift_coefficient
    mach = conditions.freestream.mach_number

    e = configuration.oswald_efficiency_factor
    wing_e = configuration.span_efficiency
    K = configuration.viscous_lift_dependent_drag_factor
    ar = geometry.wings['main_wing'].aspect_ratio
    CDp = state.conditions.aerodynamics.drag_breakdown.parasite.total

    if e == None:
        e = 1 / ((1 / wing_e) + np.pi * ar * K * CDp)

    spline = Cubic_Spline_Blender(.91, .99)
    h00 = lambda M: spline.compute(M)

    total_induced_drag_low = aircraft_lift**2 / (np.pi * ar * e)
    total_induced_drag_high = aircraft_lift**2 / (
        np.pi * ar * wing_e
    )  # oswald factor would include wave drag due to lift
    # which is not computed here

    total_induced_drag = total_induced_drag_low * h00(
        mach) + total_induced_drag_high * (1 - h00(mach))

    # store data
    try:
        conditions.aerodynamics.drag_breakdown.induced = Data(
            total=total_induced_drag,
            efficiency_factor=e,
            aspect_ratio=ar,
        )
    except:
        print("Drag Polar Mode")

    return total_induced_drag
Example #4
0
def parasite_drag_nacelle(state, settings, nacelle):
    """Computes the parasite drag due to the nacelle

    Assumptions:
    Basic fit

    Source:
    Raymer equation (pg 283 of Aircraft Design: A Conceptual Approach) (subsonic)
    http://aerodesign.stanford.edu/aircraftdesign/drag/BODYFORMFACTOR.HTML (supersonic)

    Inputs:
    state.conditions.freestream.
      mach_number                                [Unitless]
      temperature                                [K]
      reynolds_number                            [Unitless]
    geometry.      
      nacelle.diameter                           [m^2]
             areas.wetted                        [m^2]
             length                              [m]
 
    Outputs:
    nacelle_parasite_drag                      [Unitless]

    Properties Used:
    N/A
    """

    # unpack inputs
    conditions = state.conditions

    low_mach_cutoff = settings.begin_drag_rise_mach_number
    high_mach_cutoff = settings.end_drag_rise_mach_number

    freestream = conditions.freestream

    Sref = nacelle.diameter**2 / 4 * np.pi
    Swet = nacelle.areas.wetted

    l_prop = nacelle.length
    d_prop = nacelle.diameter

    # conditions
    freestream = conditions.freestream
    Mc = freestream.mach_number
    Tc = freestream.temperature
    re = freestream.reynolds_number

    # reynolds number
    Re_prop = re * l_prop

    # skin friction coefficient
    cf_prop, k_comp, k_reyn = compressible_turbulent_flat_plate(
        Re_prop, Mc, Tc)

    # form factor according to Raymer equation (pg 283 of Aircraft Design: A Conceptual Approach)
    k_prop_sub = 1. + 0.35 / (float(l_prop) / float(d_prop))

    # for supersonic flow (http://adg.stanford.edu/aa241/drag/BODYFORMFACTOR.HTML)
    k_prop_sup = 1.

    trans_spline = Cubic_Spline_Blender(low_mach_cutoff, high_mach_cutoff)
    h00 = lambda M: trans_spline.compute(M)

    k_prop = k_prop_sub * (h00(Mc)) + k_prop_sup * (1 - h00(Mc))

    # --------------------------------------------------------
    # find the final result
    nacelle_parasite_drag = k_prop * cf_prop * Swet / Sref
    # --------------------------------------------------------

    # dump data to conditions
    nacelle_result = Data(
        wetted_area=Swet,
        reference_area=Sref,
        parasite_drag_coefficient=nacelle_parasite_drag,
        skin_friction_coefficient=cf_prop,
        compressibility_factor=k_comp,
        reynolds_factor=k_reyn,
        form_factor=k_prop,
    )
    state.conditions.aerodynamics.drag_breakdown.parasite[
        nacelle.tag] = nacelle_result

    return nacelle_parasite_drag
def compressibility_drag_total(state,settings,geometry):
    """Computes compressibility drag for full aircraft including volume drag

    Assumptions:
    None

    Source:
    N/A

    Inputs:   
    settings.
      begin_drag_rise_mach_number                                    [Unitless]
      end_drag_rise_mach_number                                      [Unitless]
      peak_mach_number                                               [Unitless]
      transonic_drag_multiplier                                      [Unitless]
      volume_wave_drag_scaling                                       [Unitless]
    state.conditions.aerodynamics.lift_breakdown.compressible_wings  [Unitless]
    state.conditions.freestream.mach_number                          [Unitless]
    geometry.maximum_cross_sectional_area                            [m^2] (used in subfunctions)
    geometry.total_length                                            [m]   (used in subfunctions)
    geometry.reference_area                                          [m^2]
    geometry.wings                             

    Outputs:
    total_compressibility_drag                                       [Unitless]

    Properties Used:
    N/A
    """     

    # Unpack
    conditions       = state.conditions
    configuration    = settings
    low_mach_cutoff  = settings.begin_drag_rise_mach_number
    high_mach_cutoff = settings.end_drag_rise_mach_number
    peak_mach        = settings.peak_mach_number
    peak_factor      = settings.transonic_drag_multiplier
    scaling_factor   = settings.volume_wave_drag_scaling
    
    if settings.cross_sectional_area_calculation_type != 'Fixed':
        raise NotImplementedError
    
    wings          = geometry.wings
    Mc             = conditions.freestream.mach_number
    drag_breakdown = conditions.aerodynamics.drag_breakdown

    # Initialize result
    drag_breakdown.compressible = Data()
    
    # Use vehicle reference area for drag coefficients
    Sref_main = geometry.reference_area
    

    low_cutoff_volume_total  = 0.
    high_cutoff_volume_total = 0.
    
    # Get the lift coefficient
    cl = conditions.aerodynamics.lift_breakdown.compressible_wings    
    
    for wing in geometry.wings:
        low_cutoff_volume_total += drag_div(low_mach_cutoff*np.ones([1]), wing, cl, Sref_main)[0]
    high_cutoff_volume_total = wave_drag_volume(geometry,low_mach_cutoff*np.ones([1]),scaling_factor)
    
    peak_volume_total = high_cutoff_volume_total*peak_factor
    
    # fit the drag rise using piecewise parabolas y = a*(x-x_peak)**2+y_peak
    
    # subsonic side
    a1 = (low_cutoff_volume_total-peak_volume_total)/(low_mach_cutoff-peak_mach)/(low_mach_cutoff-peak_mach)
    
    # supersonic side
    a2 = (high_cutoff_volume_total-peak_volume_total)/(high_mach_cutoff-peak_mach)/(high_mach_cutoff-peak_mach) 
    
    def CD_v_para(M,a_vertex): # parabolic approximation of drag rise in the transonic region
        ret = a_vertex*(M-peak_mach)*(M-peak_mach)+peak_volume_total
        ret = ret.reshape(np.shape(M))
        return ret
    
    # Shorten cubic Hermite spline
    sub_spline = Cubic_Spline_Blender(low_mach_cutoff, peak_mach-(peak_mach-low_mach_cutoff)*3/4)
    sup_spline = Cubic_Spline_Blender(peak_mach,high_mach_cutoff)
    sub_h00 = lambda M:sub_spline.compute(M)
    sup_h00 = lambda M:sup_spline.compute(M)
    
    cd_c_v_base = np.zeros_like(Mc)
    
    low_inds = Mc[:,0]<peak_mach
    hi_inds  = Mc[:,0]>=peak_mach
    
    for wing in geometry.wings:
        cd_c_v_base[low_inds] += drag_div(Mc[low_inds], wing, cl, Sref_main)[0]
    cd_c_v_base[Mc>=peak_mach] = wave_drag_volume(geometry, Mc[Mc>=peak_mach], scaling_factor)
    
    cd_c_l_base = lift_wave_drag(conditions, configuration, geometry.wings.main_wing, Sref_main)
    
    cd_c_v = np.zeros_like(Mc)
    
    cd_c_v[low_inds] = cd_c_v_base[low_inds]*(sub_h00(Mc[low_inds])) + CD_v_para(Mc[low_inds],a1)*(1-sub_h00(Mc[low_inds]))
    cd_c_v[hi_inds]  = CD_v_para(Mc[hi_inds],a2)*(sup_h00(Mc[hi_inds])) + cd_c_v_base[hi_inds]*(1-sup_h00(Mc[hi_inds]))

    if peak_mach<1.01:
        print('Warning: a peak mach number of less than 1.01 will cause a small discontinuity in lift wave drag')
    cd_c_l           = cd_c_l_base*(1-sup_h00(Mc))
    
    cd_c = cd_c_v + cd_c_l

    
    # Save drag breakdown

    drag_breakdown.compressible.total        = cd_c
    drag_breakdown.compressible.total_volume = cd_c_v
    drag_breakdown.compressible.total_lift   = cd_c_l
    

    return cd_c
Example #6
0
def parasite_drag_fuselage(state, settings, geometry):
    """Computes the parasite drag due to the fuselage

    Assumptions:
    Basic fit

    Source:
    http://aerodesign.stanford.edu/aircraftdesign/aircraftdesign.html (Stanford AA241 A/B Course Notes)

    Inputs:
    state.conditions.freestream.
      mach_number                                [Unitless]
      temperature                                [K]
      reynolds_number                            [Unitless]
    settings.fuselage_parasite_drag_form_factor  [Unitless]
    geometry.fuselage.       
      areas.front_projected                      [m^2]
      areas.wetted                               [m^2]
      lengths.total                              [m]
      effective_diameter                         [m]

    Outputs:
    fuselage_parasite_drag                       [Unitless]

    Properties Used:
    N/A
    """

    # unpack inputs
    configuration = settings
    form_factor = configuration.fuselage_parasite_drag_form_factor
    low_cutoff = configuration.fuselage_parasite_drag_begin_blend_mach
    high_cutoff = configuration.fuselage_parasite_drag_end_blend_mach
    fuselage = geometry

    freestream = state.conditions.freestream
    Sref = fuselage.areas.front_projected
    Swet = fuselage.areas.wetted

    l_fus = fuselage.lengths.total
    d_fus = fuselage.effective_diameter

    # conditions
    Mc = freestream.mach_number
    Tc = freestream.temperature
    re = freestream.reynolds_number

    # reynolds number
    Re_fus = re * (l_fus)

    # skin friction coefficient
    cf_fus, k_comp, k_reyn = compressible_turbulent_flat_plate(Re_fus, Mc, Tc)

    # form factor for cylindrical bodies
    d_d = float(d_fus) / float(l_fus)

    D_low = np.array([[0.0]] * len(Mc))
    a_low = np.array([[0.0]] * len(Mc))
    du_max_u_low = np.array([[0.0]] * len(Mc))

    D_high = np.array([[0.0]] * len(Mc))
    a_high = np.array([[0.0]] * len(Mc))
    du_max_u_high = np.array([[0.0]] * len(Mc))

    k_fus = np.array([[0.0]] * len(Mc))

    low_inds = Mc < high_cutoff
    high_inds = Mc > low_cutoff

    D_low[low_inds] = np.sqrt(1 - (1 - Mc[low_inds]**2) * d_d**2)
    a_low[low_inds] = 2 * (1 - Mc[low_inds]**2) * (d_d**2) * (
        np.arctanh(D_low[low_inds]) - D_low[low_inds]) / (D_low[low_inds]**3)
    du_max_u_low[low_inds] = a_low[low_inds] / ((2 - a_low[low_inds]) *
                                                (1 - Mc[low_inds]**2)**0.5)

    D_high[high_inds] = np.sqrt(1 - d_d**2)
    a_high[high_inds] = 2 * (d_d**2) * (np.arctanh(
        D_high[high_inds]) - D_high[high_inds]) / (D_high[high_inds]**3)
    du_max_u_high[high_inds] = a_high[high_inds] / ((2 - a_high[high_inds]))

    spline = Cubic_Spline_Blender(low_cutoff, high_cutoff)
    h00 = lambda M: spline.compute(M)

    du_max_u = du_max_u_low * (h00(Mc)) + du_max_u_high * (1 - h00(Mc))

    k_fus = (1 + form_factor * du_max_u)**2

    fuselage_parasite_drag = k_fus * cf_fus * Swet / Sref

    # dump data to conditions
    fuselage_result = Data(
        wetted_area=Swet,
        reference_area=Sref,
        parasite_drag_coefficient=fuselage_parasite_drag,
        skin_friction_coefficient=cf_fus,
        compressibility_factor=k_comp,
        reynolds_factor=k_reyn,
        form_factor=k_fus,
    )
    try:
        state.conditions.aerodynamics.drag_breakdown.parasite[
            fuselage.tag] = fuselage_result
    except:
        print("Drag Polar Mode fuse parasite")

    return fuselage_parasite_drag
def compute_parasite_drag(re, mac_w, Mc, Tc, xtu, xtl, sweep_w, t_c_w, Sref,
                          Swet, C):
    """Computes the parasite drag due to wings

    Assumptions:
    Basic fit

    Source:
    adg.stanford.edu (Stanford AA241 A/B Course Notes)

    Inputs:
    re (Reynolds Number)    [Unitless]
    mac_w (Wing MAC)        [m]
    Mc (Mach Number)        [Unitless]
    Tc (Temperature)        [K]
    xtu (Upper Transition)  [Unitless] (percent of chord)
    xtl (Lower Transition)  [Unitless] (percent of chord)
    sweep_w (Wing Sweep)    [rad]
    t_c_w (Wing t/c)        [Unitless]
    Sref (Wing Ref Area)    [m^2]
    Swet (Wing Wetted Area) [m^2]
    C (Form Factor)         [Unitless]
      
    Outputs:
    (u is upper, l is lower)
    wing_parasite_drag                 [Unitless]
    k_w    (Form Factor)               [Unitless]
    cf_w_u (Skin Friction Coefficient) [Unitless]
    cf_w_l                             [Unitless]
    k_comp_u (Compressibility Factor)  [Unitless]
    k_comp_l                           [Unitless]
    k_reyn_u (Reynolds Factor)         [Unitless]
    k_reyn_l                           [Unitless]

    Properties Used:
    N/A
    """

    # reynolds number
    Re_w = re * mac_w

    # skin friction  coefficient, upper
    cf_w_u, k_comp_u, k_reyn_u = compressible_mixed_flat_plate(
        Re_w, Mc, Tc, xtu)

    # skin friction  coefficient, lower
    cf_w_l, k_comp_l, k_reyn_l = compressible_mixed_flat_plate(
        Re_w, Mc, Tc, xtl)

    # correction for airfoils
    cos_sweep = np.cos(sweep_w)
    cos2 = cos_sweep * cos_sweep

    ind = Mc <= 1.

    k_w = np.ones_like(Mc)
    k_w[ind] = 1. + ( 2.* C * (t_c_w * cos2) ) / ( np.sqrt(1.- Mc[ind]*Mc[ind] * cos2) )  \
            + ( C*C * cos2 * t_c_w*t_c_w * (1. + 5.*(cos2)) ) \
            / (2.*(1.-(Mc[ind]*cos_sweep)**2.))

    spline = Cubic_Spline_Blender(.95, 1.0)
    h00 = lambda M: spline.compute(M)

    k_w = k_w * (h00(Mc)) + 1 * (1 - h00(Mc))

    # find the final result
    wing_parasite_drag = k_w * cf_w_u * Swet / Sref / 2. + k_w * cf_w_l * Swet / Sref / 2.

    return wing_parasite_drag, k_w, cf_w_u, cf_w_l, k_comp_u, k_comp_l, k_reyn_u, k_reyn_l