def datcom(wing,mach): """ cL_alpha = SUAVE.Methods.Flight_Dynamics.Static_Stability.Approximations.datcom(wing,mach) This method uses the DATCOM formula to compute dCL/dalpha without correlations for downwash of lifting surfaces further ahead on the aircraft or upwash resulting from the position of the wing on the body. CAUTION: The method presented here is applicable for subsonic speeds. May be inaccurate for transonic or supersonic flight. A correction factor for supersonic flight is included, but may not be completely accurate. Inputs: wing - a data dictionary with the fields: effective_apsect_ratio - wing aspect ratio [dimensionless]. If this variable is not inlcuded in the input, the method will look for a variable named 'aspect_ratio'. sweep_le - wing leading-edge sweep angle [radians] taper - wing taper ratio [dimensionless] mach - flight Mach number [dimensionless]. Should be a numpy array with one or more elements. Outputs: cL_alpha - The derivative of 3D lift coefficient with respect to AoA Assumptions: -Mach number should not be transonic """ #Unpack inputs try: ar = wing.effective_aspect_ratio except AttributeError: ar = wing.aspect_ratio sweep = wing.sweep # Value is at the leading edge #Compute relevent parameters cL_alpha = [] half_chord_sweep = convert_sweep(wing,0.0,0.5) #Assumes original sweep is that of LE #Compute k correction factor for Mach number #First, compute corrected 2D section lift curve slope (C_la) for the given Mach number cla = 6.13 #Section C_la at M = 0; Roskam Airplane Design Part VI, Table 8.1 for M in mach: if M < 1: Beta = np.sqrt(1.0-M**2.0) cla_M = cla/Beta k = cla_M/(2.0*np.pi/Beta) cL_alpha.extend([2.0*np.pi*ar/(2.0+((ar**2.0*Beta**2.0/k**2.0)*(1.0+(np.tan(half_chord_sweep))**2.0/Beta**2.0)+4.0)**0.5)]) else: Beta = np.sqrt(M**2.0-1.0) cla_M = 4.0/Beta k = cla_M/(2.0*np.pi/Beta) cL_alpha.extend([2.0*np.pi*ar/(2.0+((ar**2.0*Beta**2.0/k**2.0)*(1.0+(np.tan(half_chord_sweep))**2.0/Beta**2.0)+4.0)**0.5)]) #Compute aerodynamic surface 3D lift curve slope using the DATCOM formula return np.array(cL_alpha)
def datcom(wing,mach): """ cL_alpha = SUAVE.Methods.Flight_Dynamics.Static_Stability.Approximations.datcom(wing,mach) This method uses the DATCOM formula to compute dCL/dalpha without correlations for downwash of lifting surfaces further ahead on the aircraft or upwash resulting from the position of the wing on the body. CAUTION: The method presented here is applicable for subsonic speeds. May be inaccurate for transonic or supersonic flight. A correction factor for supersonic flight is included, but may not be completely accurate. Inputs: wing - a data dictionary with the fields: effective_apsect_ratio - wing aspect ratio [dimensionless]. If this variable is not inlcuded in the input, the method will look for a variable named 'aspect_ratio'. sweep_le - wing leading-edge sweep angle [radians] taper - wing taper ratio [dimensionless] mach - flight Mach number [dimensionless]. Should be a numpy array with one or more elements. Outputs: cL_alpha - The derivative of 3D lift coefficient with respect to AoA Assumptions: -Mach number should not be transonic """ #Unpack inputs try: ar = wing.effective_aspect_ratio except AttributeError: ar = wing.aspect_ratio sweep = wing.sweep # Value is at the leading edge #Compute relevent parameters cL_alpha = [] half_chord_sweep = convert_sweep(wing,0.25,0.5) #Assumes original sweep is that of LE #Compute k correction factor for Mach number #First, compute corrected 2D section lift curve slope (C_la) for the given Mach number cla = 6.13 #Section C_la at M = 0; Roskam Airplane Design Part VI, Table 8.1 cL_alpha = np.ones_like(mach) Beta = np.ones_like(mach) k = np.ones_like(mach) cla_M = np.ones_like(mach) Beta[mach<1.] = np.sqrt(1.0-mach[mach<1.]**2.0) Beta[mach>1.] = np.sqrt(mach[mach>1.]**2.0-1.0) cla_M[mach<1.] = cla/Beta[mach<1.] cla_M[mach>1.] = 4.0/Beta[mach>1.] k = cla_M/(2.0*np.pi/Beta) #Compute aerodynamic surface 3D lift curve slope using the DATCOM formula cL_alpha =([2.0*np.pi*ar/(2.0+((ar**2.0*(Beta*Beta)/(k*k))*(1.0+(np.tan(half_chord_sweep))**2.0/(Beta*Beta))+4.0)**0.5)]) return np.array(cL_alpha)
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
def compute_component_centers_of_gravity(vehicle, nose_load=0.06): """ computes the CG of all of the vehicle components based on correlations from AA241 Assumptions: None Source: AA 241 Notes Inputs: vehicle Outputs: None Properties Used: N/A """ C = SUAVE.Components # Go through all wings for wing in vehicle.wings: if wing.sweeps.leading_edge == None: wing.sweeps.leading_edge = convert_sweep( wing, old_ref_chord_fraction=0.25, new_ref_chord_fraction=0.0) if isinstance(wing, C.Wings.Main_Wing): wing.mass_properties.center_of_gravity[0][ 0] = .05 * wing.chords.mean_aerodynamic + wing.aerodynamic_center[ 0] elif isinstance(wing, C.Wings.Horizontal_Tail): chord_length_h_tail_35_percent_semi_span = compute_chord_length_from_span_location( wing, .35 * wing.spans.projected * .5) h_tail_35_percent_semi_span_offset = np.tan( wing.sweeps.quarter_chord) * .35 * .5 * wing.spans.projected wing.mass_properties.center_of_gravity[0][0] = .3*chord_length_h_tail_35_percent_semi_span + \ h_tail_35_percent_semi_span_offset elif isinstance(wing, C.Wings.Vertical_Tail): chord_length_v_tail_35_percent_semi_span = compute_chord_length_from_span_location( wing, .35 * wing.spans.projected) v_tail_35_percent_semi_span_offset = np.tan( wing.sweeps.quarter_chord) * .35 * .5 * wing.spans.projected wing.mass_properties.center_of_gravity[0][0] = .3*chord_length_v_tail_35_percent_semi_span + \ v_tail_35_percent_semi_span_offset else: span_location_mac = compute_span_location_from_chord_length( wing, wing.chords.mean_aerodynamic) mac_le_offset = np.tan( wing.sweeps.leading_edge) * span_location_mac wing.mass_properties.center_of_gravity[0][ 0] = .3 * wing.chords.mean_aerodynamic + mac_le_offset # Go through all the propulsors propulsion_moment = 0. propulsion_mass = 0. for prop in vehicle.propulsors: prop.mass_properties.center_of_gravity[0][0] = prop.engine_length * .5 propulsion_mass += prop.mass_properties.mass propulsion_moment += propulsion_mass * (prop.engine_length * .5 + prop.origin[0][0]) if propulsion_mass != 0.: propulsion_cg = propulsion_moment / propulsion_mass else: propulsion_cg = 0. # Go through all the fuselages for fuse in vehicle.fuselages: fuse.mass_properties.center_of_gravity[0][0] = .45 * fuse.lengths.total #--------------------------------------------------------------------------------- # All other components #--------------------------------------------------------------------------------- # Select a length scale depending on what kind of vehicle this is length_scale = 1. nose_length = 0. # Check if there is a fuselage if len(vehicle.fuselages) == 0.: for wing in vehicle.wings: if isinstance(wing, C.Wings.Main_Wing): b = wing.chords.root if b > length_scale: length_scale = b nose_length = 0.25 * b else: for fuse in vehicle.fuselages: nose = fuse.lengths.nose length = fuse.lengths.total if length > length_scale: length_scale = length nose_length = nose # unpack all components: avionics = vehicle.systems.avionics furnishings = vehicle.systems.furnishings apu = vehicle.systems.apu passengers = vehicle.payload.passengers baggage = vehicle.payload.baggage cargo = vehicle.payload.cargo air_conditioner = vehicle.systems.air_conditioner optionals = vehicle.systems.optionals fuel = vehicle.systems.fuel control_systems = vehicle.systems.control_systems electrical_systems = vehicle.systems.electrical_systems main_gear = vehicle.landing_gear.main nose_gear = vehicle.landing_gear.nose hydraulics = vehicle.systems.hydraulics avionics.origin[0][0] = 0.4 * nose_length avionics.mass_properties.center_of_gravity[0][0] = 0.0 furnishings.origin[0][0] = 0.51 * length_scale furnishings.mass_properties.center_of_gravity[0][0] = 0.0 #assumption that it's at 90% of fuselage length (not from notes) apu.origin[0][0] = 0.9 * length_scale apu.mass_properties.center_of_gravity[0][0] = 0.0 passengers.origin[0][0] = 0.51 * length_scale passengers.mass_properties.center_of_gravity[0][0] = 0.0 baggage.origin[0][0] = 0.51 * length_scale baggage.mass_properties.center_of_gravity[0][0] = 0.0 cargo.origin[0][0] = 0.51 * length_scale cargo.mass_properties.center_of_gravity[0][0] = 0.0 air_conditioner.origin[0][0] = nose_length air_conditioner.mass_properties.center_of_gravity[0][0] = 0.0 optionals.origin[0][0] = 0.51 * length_scale optionals.mass_properties.center_of_gravity[0][0] = 0.0 fuel.origin[0][0] = vehicle.wings.main_wing.origin[0][0] fuel.mass_properties.center_of_gravity = vehicle.wings.main_wing.mass_properties.center_of_gravity control_systems.origin[0][0] = vehicle.wings.main_wing.origin[0][0] control_systems.mass_properties.center_of_gravity[0][0] = vehicle.wings.main_wing.mass_properties.center_of_gravity[0][0] + \ .1*vehicle.wings.main_wing.chords.mean_aerodynamic electrical_systems.origin[0][0] = .75 * ( .5 * length_scale) + propulsion_cg * .25 electrical_systems.mass_properties.center_of_gravity[0][0] = 0.0 hydraulics.origin[0][0] = .75*(vehicle.wings.main_wing.origin[0][0] + \ wing.mass_properties.center_of_gravity[0][0]) + 0.25* \ length_scale*.95 hydraulics.mass_properties.center_of_gravity[0][0] = 0.0 # Now the landing gear # Nose gear nose_gear.origin[0][0] = 0.25 * nose_length nose_gear.mass_properties.center_of_gravity[0][0] = 0.0 # Main gear moment_sans_main = vehicle.center_of_gravity()[0][0] * ( vehicle.sum_mass() - main_gear.mass_properties.mass) main_gear_location = moment_sans_main / ( vehicle.mass_properties.takeoff - main_gear.mass_properties.mass) / (1 - nose_load) main_gear.origin[0][0] = main_gear_location main_gear.mass_properties.center_of_gravity = 0.0 return
def taw_cnbeta(geometry, conditions, configuration): """ CnBeta = SUAVE.Methods.Flight_Dynamics.Static_Stability.Approximations.Tube_Wing.taw_cnbeta(configuration,conditions) This method computes the static directional stability derivative for a standard Tube-and-Wing aircraft configuration. CAUTION: The correlations used in this method do not account for the destabilizing moments due to propellers. This can lead to higher-than- expected values of CnBeta, particularly for smaller prop-driven aircraft Inputs: geometry - aircraft geometrical features: a data dictionary with the fields: wings['Main Wing'] - the aircraft's main wing areas.reference - wing reference area [meters**2] spans.projected - span of the wing [meters] sweep - sweep of the wing leading edge [radians] aspect_ratio - wing aspect ratio [dimensionless] origin - the position of the wing root in the aircraft body frame [meters] wings['Vertical Stabilizer'] spans.projected - projected span (height for a vertical tail) of the exposed surface [meters] areas.reference - area of the reference vertical tail [meters**2] sweep - leading edge sweep of the aerodynamic surface [radians] chords.root - chord length at the junction between the tail and the fuselage [meters] chords.tip - chord length at the tip of the aerodynamic surface [meters] symmetric - Is the wing symmetric across the fuselage centerline? origin - the position of the vertical tail root in the aircraft body frame [meters] exposed_root_chord_offset - the displacement from the fuselage centerline to the exposed area's physical root chordline [meters] fuselages.Fuselage - a data dictionary with the fields: areas.side_projected - fuselage body side area [meters**2] lengths.total - length of the fuselage [meters] heights.maximum - maximum height of the fuselage [meters] width - maximum width of the fuselage [meters] heights.at_quarter_length - fuselage height at 1/4 of the fuselage length [meters] heights.at_three_quarters_length - fuselage height at 3/4 of fuselage length [meters] heights.at_vertical_root_quarter_chord - fuselage height at the quarter chord of the vertical tail root [meters] vertical - a data dictionary with the fields below: NOTE: This vertical tail geometry will be used to define a reference vertical tail that extends to the fuselage centerline. x_ac_LE - the x-coordinate of the vertical tail aerodynamic center measured relative to the tail root leading edge (root of reference tail area - at fuselage centerline) leading edge, relative to the nose [meters] sweep_le - leading edge sweep of the vertical tail [radians] span - height of the vertical tail [meters] taper - vertical tail taper ratio [dimensionless] aspect_ratio - vertical tail AR: bv/(Sv)^2 [dimensionless] effective_aspect_ratio - effective aspect ratio considering the effects of fuselage and horizontal tail [dimensionless] symmetric - indicates whether the vertical panel is symmetric about the fuselage centerline [Boolean] other_bodies - an list of data dictionaries containing bodies such as nacelles if these are large enough to strongly influence stability. Each body data dictionary contains the same fields as the fuselage data dictionary (described above), except no value is needed for 'height_at_vroot_quarter_chord'. CAN BE EMPTY LIST x_front - This is the only new field needed: the x-coordinate of the nose of the body relative to the fuselage nose conditions - a data dictionary with the fields: v_inf - true airspeed [meters/second] M - flight Mach number rho - air density [kg/meters**3] mew - air dynamic dynamic_viscosity [kg/meter/second] configuration - a data dictionary with the fields: mass_properties - a data dictionary with the field: center_of_gravity - A vector in 3-space indicating CG position [meters] other - a dictionary of aerodynamic bodies, other than the fuselage, whose effect on directional stability is to be included in the analysis Outputs: CnBeta - a single float value: The static directional stability derivative Assumptions: -Assumes a tube-and-wing configuration with a single centered vertical tail -Uses vertical tail effective aspect ratio, currently calculated by hand, using methods from USAF Stability and Control DATCOM -The validity of correlations for KN is questionable for sqrt(h1/h2) greater than about 4 or h_max/w_max outside [0.3,2]. -This method assumes a small angle of attack, so the vertical tail AC z-position does not affect the sideslip derivative. Correlations: -Correlations are taken from Roskam's Airplane Design, Part VI. """ try: configuration.other except AttributeError: configuration.other = 0 CnBeta_other = [] # Unpack inputs S = geometry.wings['main_wing'].areas.reference b = geometry.wings['main_wing'].spans.projected sweep = geometry.wings['main_wing'].sweeps.quarter_chord AR = geometry.wings['main_wing'].aspect_ratio z_w = geometry.wings['main_wing'].origin[2] S_bs = geometry.fuselages['fuselage'].areas.side_projected l_f = geometry.fuselages['fuselage'].lengths.total h_max = geometry.fuselages['fuselage'].heights.maximum w_max = geometry.fuselages['fuselage'].width h1 = geometry.fuselages['fuselage'].heights.at_quarter_length h2 = geometry.fuselages['fuselage'].heights.at_three_quarters_length d_i = geometry.fuselages['fuselage'].heights.at_wing_root_quarter_chord other = configuration.other vert = extend_to_ref_area(geometry.wings['vertical_stabilizer']) S_v = vert.extended.areas.reference x_v = vert.extended.origin[0] b_v = vert.extended.spans.projected ac_vLE = vert.aerodynamic_center[0] x_cg = configuration.mass_properties.center_of_gravity[0] v_inf = conditions.freestream.velocity mu = conditions.freestream.dynamic_viscosity rho = conditions.freestream.density M = conditions.freestream.mach_number #Compute wing contribution to Cn_beta CnBeta_w = 0.0 #The wing contribution is assumed to be zero except at very #high angles of attack. #Compute fuselage contribution to Cn_beta Re_fuse = rho * v_inf * l_f / mu x1 = x_cg / l_f x2 = l_f * l_f / S_bs x3 = np.sqrt(h1 / h2) x4 = h_max / w_max kN_1 = 3.2413 * x1 - 0.663345 + 6.1086 * np.exp(-0.22 * x2) kN_2 = (-0.2023 + 1.3422 * x3 - 0.1454 * x3 * x3) * kN_1 kN_3 = (0.7870 + 0.1038 * x4 + 0.1834 * x4 * x4 - 2.811 * np.exp(-4.0 * x4)) K_N = (-0.47899 + kN_3 * kN_2) * 0.001 K_Rel = 1.0 + 0.8 * np.log(Re_fuse / 1.0E6) / np.log(50.) #K_Rel: Correction for fuselage Reynolds number. Roskam VI, page 400. CnBeta_f = -57.3 * K_N * K_Rel * S_bs * l_f / S / b #Compute contributions of other bodies on CnBeta if other > 0: for body in other: #Unpack inputs S_bs = body.areas.side_projected x_le = body.origin[0] l_b = body.lengths.total h_max = body.heights.maximum w_max = body.width h1 = body.heights.at_quarter_length h2 = body.heights.at_three_quarters_length #Compute body contribution to Cn_beta x_cg_on_body = (x_cg - x_le) / l_b Re_body = rho * v_inf * l_b / mew x1 = x_cg_on_body / l_b x2 = l_b * l_b / S_bs x3 = np.sqrt(h1 / h2) x4 = h_max / w_max kN_1 = 3.2413 * x1 - 0.663345 + 6.1086 * np.exp(-0.22 * x2) kN_2 = (-0.2023 + 1.3422 * x3 - 0.1454 * x3 * x3) * kN_1 kN_3 = (0.7870 + 0.1038 * x4 + 0.1834 * x4 * x4 - 2.811 * np.exp(-4.0 * x4)) K_N = (-0.47899 + kN_3 * kN_2) * 0.001 #K_Rel: Correction for fuselage Reynolds number. Roskam VI, page 400. K_Rel = 1.0 + 0.8 * np.log(Re_body / 1.0E6) / np.log(50.) CnBeta_b = -57.3 * K_N * K_Rel * S_bs * l_b / S / b CnBeta_other.append(CnBeta_b) #Compute vertical tail contribution l_v = x_v + ac_vLE - x_cg try: iter(M) except TypeError: M = [M] CLa_v = datcom(vert, M) #k_v correlated from Roskam Fig. 10.12. NOT SMOOTH. bf = b_v / d_i if bf < 2.0: k_v = 0.76 elif bf < 3.5: k_v = 0.76 + 0.24 * (bf - 2.0) / 1.5 else: k_v = 1.0 quarter_chord_sweep = convert_sweep(geometry.wings['main_wing']) k_sweep = (1.0 + np.cos(quarter_chord_sweep)) dsdb_e = 0.724 + 3.06 * ( (S_v / S) / k_sweep) + 0.4 * z_w / h_max + 0.009 * AR Cy_bv = -k_v * CLa_v * dsdb_e * (S_v / S) #ASSUMING SINGLE VERTICAL TAIL CnBeta_v = -Cy_bv * l_v / b CnBeta = CnBeta_w + CnBeta_f + CnBeta_v + sum(CnBeta_other) return CnBeta
def taw_cnbeta(geometry,conditions,configuration): """ CnBeta = SUAVE.Methods.Flight_Dynamics.Static_Stability.Approximations.Tube_Wing.taw_cnbeta(configuration,conditions) This method computes the static directional stability derivative for a standard Tube-and-Wing aircraft configuration. CAUTION: The correlations used in this method do not account for the destabilizing moments due to propellers. This can lead to higher than expected values of CnBeta, particularly for smaller prop-driven aircraft Inputs: configuration - a data dictionary with the fields: Mass_Props - a data dictionary with the field: pos_cg - A vector in 3-space indicating CG position wing - a data dictionary with the fields: area - wing reference area [meters**2] span - span of the wing [meters] sweep_le - sweep of the wing leading edge [radians] z_position - distance of wing root quarter chord point below fuselage centerline [meters] taper - wing taper ratio [dimensionless] aspect_ratio - wing aspect ratio [dimensionless] fuselage - a data dictionary with the fields: side_area - fuselage body side area [meters**2] length - length of the fuselage [meters] h_max - maximum height of the fuselage [meters] w_max - maximum width of the fuselage [meters] height_at_quarter_length - fuselage height at 1/4 of the fuselage length [meters] height_at_three_quarters_length - fuselage height at 3/4 of the fuselage length [meters] height_at_vroot_quarter_chord - fuselage height at the aerodynamic center of the vertical tail [meters] vertical - a data dictionary with the fields below: NOTE: Reference vertical tail extends to the fuselage centerline area - area of the reference vertical tail [meters**2] x_root_LE - x-position of the vertical reference root chord x_ac_LE - the x-coordinate of the vertical tail aerodynamic center measured relative to the tail root leading edge (root of reference tail area - at fuselage centerline) leading edge, relative to the nose [meters] sweep_le - leading edge sweep of the vertical tail [radians] span - height of the vertical tail [meters] taper - vertical tail taper ratio [dimensionless] aspect_ratio - vertical tail AR: bv/(Sv)^2 [dimensionless] effective_aspect_ratio - effective aspect ratio considering the effects of fuselage and horizontal tail [dimensionless] symmetric - indicates whether the vertical panel is symmetric about the fuselage centerline [Boolean] other_bodies - an list of data dictionaries containing bodies such as nacelles if these are large enough to strongly influence stability. Each body data dictionary contains the same fields as the fuselage data dictionary (described above), except no value is needed for 'height_at_vroot_quarter_chord'. CAN BE EMPTY LIST x_front - This is the only new field needed: the x-coordinate of the nose of the body relative to the fuselage nose conditions - a data dictionary with the fields: v_inf - true airspeed [meters/second] M - flight Mach number rho - air density [kg/meters**3] mew - air dynamic viscosity [kg/meter/second] Outputs: CnBeta - a single float value: The static directional stability derivative Assumptions: -Assumes a tube-and-wing configuration with a single centered vertical tail -Uses vertical tail effective aspect ratio, currently calculated by hand, using methods from USAF Stability and Control DATCOM -The validity of correlations for KN is questionable for sqrt(h1/h2) greater than about 4 or h_max/w_max outside [0.3,2]. -This method assumes a small angle of attack, so the vertical tail AC z-position does not affect the sideslip derivative. Correlations: -Correlations are taken from Roskam's Airplane Design, Part VI. """ try: configuration.other except AttributeError: configuration.other = 0 CnBeta_other = [] # Unpack inputs S = geometry.Wings['Main Wing'].sref b = geometry.Wings['Main Wing'].span sweep = geometry.Wings['Main Wing'].sweep AR = geometry.Wings['Main Wing'].ar z_w = configuration.mass_props.pos_cg[2] S_bs = geometry.Fuselages.Fuselage.side_area l_f = geometry.Fuselages.Fuselage.length_total h_max = geometry.Fuselages.Fuselage.height w_max = geometry.Fuselages.Fuselage.width h1 = geometry.Fuselages.Fuselage.height_at_quarter_length h2 = geometry.Fuselages.Fuselage.height_at_three_quarters_length d_i = geometry.Fuselages.Fuselage.height_at_vroot_quarter_chord other = configuration.other S_v = geometry.Wings['Vertical Stabilizer'].sref x_v = geometry.Wings['Vertical Stabilizer'].origin[0] b_v = geometry.Wings['Vertical Stabilizer'].span ac_vLE = geometry.Wings['Vertical Stabilizer'].aero_center[0] x_cg = configuration.mass_props.pos_cg[0] v_inf = conditions.freestream.velocity mu = conditions.freestream.viscosity rho = conditions.freestream.density M = conditions.freestream.mach_number #Compute wing contribution to Cn_beta CnBeta_w = 0.0 #The wing contribution is assumed to be zero except at very #high angles of attack. #Compute fuselage contribution to Cn_beta Re_fuse = rho*v_inf*l_f/mu x1 = x_cg/l_f x2 = l_f**2.0/S_bs x3 = np.sqrt(h1/h2) x4 = h_max/w_max kN_1 = 3.2413*x1 - 0.663345 + 6.1086*np.exp(-0.22*x2) kN_2 = (-0.2023 + 1.3422*x3 - 0.1454*x3**2)*kN_1 kN_3 = (0.7870 + 0.1038*x4 + 0.1834*x4**2 - 2.811*np.exp(-4.0*x4)) K_N = (-0.47899 + kN_3*kN_2)*0.001 K_Rel = 1.0+0.8*np.log(Re_fuse/1.0E6)/np.log(50.) #K_Rel: Correction for fuselage Reynolds number. Roskam VI, page 400. CnBeta_f = -57.3*K_N*K_Rel*S_bs*l_f/S/b #Compute contributions of other bodies on CnBeta if other > 0: for body in other: #Unpack inputs S_bs = body.side_area x_le = body.x_front l_b = body.length h_max = body.h_max w_max = body.w_max h1 = body.height_at_quarter_length h2 = body.height_at_three_quarters_length x_cg_on_body = (x_cg-x_le)/l_b #Compute body contribution to Cn_beta Re_body = rho*v_inf*l_b/mew x1 = x_cg_on_body/l_b x2 = l_b**2.0/S_bs x3 = np.sqrt(h1/h2) x4 = h_max/w_max kN_1 = 3.2413*x1 - 0.663345 + 6.1086*np.exp(-0.22*x2) kN_2 = (-0.2023 + 1.3422*x3 - 0.1454*x3**2)*kN_1 kN_3 = (0.7870 + 0.1038*x4 + 0.1834*x4**2 - 2.811*np.exp(-4.0*x4)) K_N = (-0.47899 + kN_3*kN_2)*0.001 K_Rel = 1.0+0.8*np.log(Re_body/1.0E6)/np.log(50.) #K_Rel: Correction for fuselage Reynolds number. Roskam VI, page 400. CnBeta_b = -57.3*K_N*K_Rel*S_bs*l_b/S/b CnBeta_other.append(CnBeta_b) #Compute vertical tail contribution l_v = x_v + ac_vLE - x_cg CLa_v = geometry.Wings['Vertical Stabilizer'].CL_alpha #k_v correlated from Roskam Fig. 10.12. NOT SMOOTH. bf = b_v/d_i if bf < 2.0: k_v = 0.76 elif bf < 3.5: k_v = 0.76 + 0.24*(bf-2.0)/1.5 else: k_v = 1.0 quarter_chord_sweep = convert_sweep(geometry.Wings['Main Wing']) k_sweep = (1.0+np.cos(quarter_chord_sweep)) dsdb_e = 0.724 + 3.06*((S_v/S)/k_sweep) + 0.4*z_w/h_max + 0.009*AR Cy_bv = -k_v*CLa_v*dsdb_e*(S_v/S) #ASSUMING SINGLE VERTICAL TAIL CnBeta_v = -Cy_bv*l_v/b CnBeta = CnBeta_w + CnBeta_f + CnBeta_v + sum(CnBeta_other) return CnBeta
def vortex_lift(state, settings, geometry): """Computes vortex lift according to the Polhamus Suction Analogy Assumptions: simple delta wing Source: http://aerodesign.stanford.edu/aircraftdesign/highlift/sstclmax.html Inputs: states.conditions. freestream.mach_number [-] aerodynamics.angle_of_attack [radians] aerodynamics.lift_coefficient [-] geometry.wings.*.aspect_ratio [Unitless] geometry.wings.*.sweeps.leading_edge [radians] Outputs: state.conditions.aerodynamics. lift_breakdown.vortex_lift [-] CL due to vortex lift wings_lift [-] Total CL at this point Properties Used: N/A """ Mc = state.conditions.freestream.mach_number AoA = state.conditions.aerodynamics.angle_of_attack wings_lift = np.zeros_like(state.conditions.aerodynamics.lift_coefficient) vortex_cl = np.zeros_like(wings_lift) for wing in geometry.wings: wing_lift = state.conditions.aerodynamics.lift_breakdown.inviscid_wings[ wing.tag] if wing.vortex_lift is True: # compute leading edge sweek if not given if wing.sweeps.leading_edge == None: gamma = convert_sweep(wing, old_ref_chord_fraction=0.25, new_ref_chord_fraction=0.0) else: gamma = wing.sweeps.leading_edge AR = wing.aspect_ratio a = AoA[Mc < 1.0] # Calculate vortex lift vortex_cl[Mc < 1.0] += np.pi * AR / 2 * np.sin(a) * np.cos(a) * ( np.cos(a) + np.sin(a) * np.cos(a) / np.cos(gamma) - np.sin(a) / (2 * np.cos(gamma))) # Apply to wing lift wing_lift[Mc < 1.0] = vortex_cl[Mc < 1.0] wings_lift += wing_lift state.conditions.aerodynamics.lift_coefficient = wings_lift state.conditions.aerodynamics.lift_breakdown.vortex_lift = vortex_cl return vortex_cl
def taw_cnbeta(geometry,conditions,configuration): """ CnBeta = SUAVE.Methods.Flight_Dynamics.Static_Stability.Approximations.Tube_Wing.taw_cnbeta(configuration,conditions) This method computes the static directional stability derivative for a standard Tube-and-Wing aircraft configuration. CAUTION: The correlations used in this method do not account for the destabilizing moments due to propellers. This can lead to higher-than- expected values of CnBeta, particularly for smaller prop-driven aircraft Inputs: geometry - aircraft geometrical features: a data dictionary with the fields: wings['Main Wing'] - the aircraft's main wing areas.reference - wing reference area [meters**2] spans.projected - span of the wing [meters] sweep - sweep of the wing leading edge [radians] aspect_ratio - wing aspect ratio [dimensionless] origin - the position of the wing root in the aircraft body frame [meters] wings['Vertical Stabilizer'] spans.projected - projected span (height for a vertical tail) of the exposed surface [meters] areas.reference - area of the reference vertical tail [meters**2] sweep - leading edge sweep of the aerodynamic surface [radians] chords.root - chord length at the junction between the tail and the fuselage [meters] chords.tip - chord length at the tip of the aerodynamic surface [meters] symmetric - Is the wing symmetric across the fuselage centerline? origin - the position of the vertical tail root in the aircraft body frame [meters] exposed_root_chord_offset - the displacement from the fuselage centerline to the exposed area's physical root chordline [meters] x_v = vert.origin[0] b_v = vert.spans.projected ac_vLE = vert.aerodynamic_center[0] fuselages.Fuselage - a data dictionary with the fields: areas.side_projected - fuselage body side area [meters**2] lengths.total - length of the fuselage [meters] heights.maximum - maximum height of the fuselage [meters] width - maximum width of the fuselage [meters] heights.at_quarter_length - fuselage height at 1/4 of the fuselage length [meters] heights.at_three_quarters_length - fuselage height at 3/4 of fuselage length [meters] heights.at_vertical_root_quarter_chord - fuselage height at the quarter chord of the vertical tail root [meters] vertical - a data dictionary with the fields below: NOTE: This vertical tail geometry will be used to define a reference vertical tail that extends to the fuselage centerline. x_ac_LE - the x-coordinate of the vertical tail aerodynamic center measured relative to the tail root leading edge (root of reference tail area - at fuselage centerline) leading edge, relative to the nose [meters] sweep_le - leading edge sweep of the vertical tail [radians] span - height of the vertical tail [meters] taper - vertical tail taper ratio [dimensionless] aspect_ratio - vertical tail AR: bv/(Sv)^2 [dimensionless] effective_aspect_ratio - effective aspect ratio considering the effects of fuselage and horizontal tail [dimensionless] symmetric - indicates whether the vertical panel is symmetric about the fuselage centerline [Boolean] other_bodies - an list of data dictionaries containing bodies such as nacelles if these are large enough to strongly influence stability. Each body data dictionary contains the same fields as the fuselage data dictionary (described above), except no value is needed for 'height_at_vroot_quarter_chord'. CAN BE EMPTY LIST x_front - This is the only new field needed: the x-coordinate of the nose of the body relative to the fuselage nose conditions - a data dictionary with the fields: v_inf - true airspeed [meters/second] M - flight Mach number rho - air density [kg/meters**3] mew - air dynamic dynamic_viscosity [kg/meter/second] configuration - a data dictionary with the fields: mass_properties - a data dictionary with the field: center_of_gravity - A vector in 3-space indicating CG position [meters] other - a dictionary of aerodynamic bodies, other than the fuselage, whose effect on directional stability is to be included in the analysis Outputs: CnBeta - a single float value: The static directional stability derivative Assumptions: -Assumes a tube-and-wing configuration with a single centered vertical tail -Uses vertical tail effective aspect ratio, currently calculated by hand, using methods from USAF Stability and Control DATCOM -The validity of correlations for KN is questionable for sqrt(h1/h2) greater than about 4 or h_max/w_max outside [0.3,2]. -This method assumes a small angle of attack, so the vertical tail AC z-position does not affect the sideslip derivative. Correlations: -Correlations are taken from Roskam's Airplane Design, Part VI. """ try: configuration.other except AttributeError: configuration.other = 0 CnBeta_other = [] # Unpack inputs S = geometry.wings['main_wing'].areas.reference b = geometry.wings['main_wing'].spans.projected sweep = geometry.wings['main_wing'].sweep AR = geometry.wings['main_wing'].aspect_ratio z_w = geometry.wings['main_wing'].origin[2] S_bs = geometry.fuselages['fuselage'].areas.side_projected l_f = geometry.fuselages['fuselage'].lengths.total h_max = geometry.fuselages['fuselage'].heights.maximum w_max = geometry.fuselages['fuselage'].width h1 = geometry.fuselages['fuselage'].heights.at_quarter_length h2 = geometry.fuselages['fuselage'].heights.at_three_quarters_length d_i = geometry.fuselages['fuselage'].heights.at_wing_root_quarter_chord other = configuration.other vert = extend_to_ref_area(geometry.wings['vertical_stabilizer']) S_v = vert.areas.reference x_v = vert.origin[0] b_v = vert.spans.projected ac_vLE = vert.aerodynamic_center[0] x_cg = configuration.mass_properties.center_of_gravity[0] v_inf = conditions.freestream.velocity mu = conditions.freestream.dynamic_viscosity rho = conditions.freestream.density M = conditions.freestream.mach_number #Compute wing contribution to Cn_beta CnBeta_w = 0.0 #The wing contribution is assumed to be zero except at very #high angles of attack. #Compute fuselage contribution to Cn_beta Re_fuse = rho*v_inf*l_f/mu x1 = x_cg/l_f x2 = l_f**2.0/S_bs x3 = np.sqrt(h1/h2) x4 = h_max/w_max kN_1 = 3.2413*x1 - 0.663345 + 6.1086*np.exp(-0.22*x2) kN_2 = (-0.2023 + 1.3422*x3 - 0.1454*x3**2)*kN_1 kN_3 = (0.7870 + 0.1038*x4 + 0.1834*x4**2 - 2.811*np.exp(-4.0*x4)) K_N = (-0.47899 + kN_3*kN_2)*0.001 K_Rel = 1.0+0.8*np.log(Re_fuse/1.0E6)/np.log(50.) #K_Rel: Correction for fuselage Reynolds number. Roskam VI, page 400. CnBeta_f = -57.3*K_N*K_Rel*S_bs*l_f/S/b #Compute contributions of other bodies on CnBeta if other > 0: for body in other: #Unpack inputs S_bs = body.areas.side_projected x_le = body.origin[0] l_b = body.lengths.total h_max = body.heights.maximum w_max = body.width h1 = body.heights.at_quarter_length h2 = body.heights.at_three_quarters_length #Compute body contribution to Cn_beta x_cg_on_body = (x_cg-x_le)/l_b Re_body = rho*v_inf*l_b/mew x1 = x_cg_on_body/l_b x2 = l_b**2.0/S_bs x3 = np.sqrt(h1/h2) x4 = h_max/w_max kN_1 = 3.2413*x1 - 0.663345 + 6.1086*np.exp(-0.22*x2) kN_2 = (-0.2023 + 1.3422*x3 - 0.1454*x3**2)*kN_1 kN_3 = (0.7870 + 0.1038*x4 + 0.1834*x4**2 - 2.811*np.exp(-4.0*x4)) K_N = (-0.47899 + kN_3*kN_2)*0.001 #K_Rel: Correction for fuselage Reynolds number. Roskam VI, page 400. K_Rel = 1.0+0.8*np.log(Re_body/1.0E6)/np.log(50.) CnBeta_b = -57.3*K_N*K_Rel*S_bs*l_b/S/b CnBeta_other.append(CnBeta_b) #Compute vertical tail contribution l_v = x_v + ac_vLE - x_cg #try: # CLa_v = geometry.wings['Vertical Stabilizer'].CL_alpha #except AttributeError: # CLa_v = datcom(geometry.wings['Vertical Stabilizer'], [M]) try: iter(M) except TypeError: M = [M] CLa_v = datcom(vert,M) #k_v correlated from Roskam Fig. 10.12. NOT SMOOTH. bf = b_v/d_i if bf < 2.0: k_v = 0.76 elif bf < 3.5: k_v = 0.76 + 0.24*(bf-2.0)/1.5 else: k_v = 1.0 quarter_chord_sweep = convert_sweep(geometry.wings['main_wing']) k_sweep = (1.0+np.cos(quarter_chord_sweep)) dsdb_e = 0.724 + 3.06*((S_v/S)/k_sweep) + 0.4*z_w/h_max + 0.009*AR Cy_bv = -k_v*CLa_v*dsdb_e*(S_v/S) #ASSUMING SINGLE VERTICAL TAIL CnBeta_v = -Cy_bv*l_v/b CnBeta = CnBeta_w + CnBeta_f + CnBeta_v + sum(CnBeta_other) ##print "Wing: {} Fuse: {} Vert: {} Othr: {}".format(CnBeta_w,CnBeta_f,CnBeta_v,sum(CnBeta_other)) return CnBeta
def datcom(wing,mach): """ This method uses the DATCOM formula to compute dCL/dalpha without correlations for downwash of lifting surfaces further ahead on the aircraft or upwash resulting from the position of the wing on the body. CAUTION: The method presented here is applicable for subsonic speeds. May be inaccurate for transonic or supersonic flight. A correction factor for supersonic flight is included, but may not be completely accurate. Assumptions: Mach number should not be transonic Source: None Inputs: wing - a data dictionary with the fields: effective_apsect_ratio - wing aspect ratio [dimensionless]. If this variable is not inlcuded in the input, the method will look for a variable named 'aspect_ratio'. sweep_le - wing leading-edge sweep angle [radians] taper - wing taper ratio [dimensionless] mach - flight Mach number [dimensionless]. Should be a numpy array with one or more elements. Outputs: cL_alpha - The derivative of 3D lift coefficient with respect to AoA Properties Used: N/A """ #Unpack inputs if wing.has_key('effective_aspect_ratio'): ar = wing.effective_aspect_ratio elif wing.has_key('extended'): if wing.extended.has_key('aspect_ratio'): ar = wing.extended.aspect_ratio else: ar = wing.aspect_ratio else: ar = wing.aspect_ratio #Compute relevent parameters cL_alpha = [] half_chord_sweep = convert_sweep(wing,0.25,0.5) #Assumes original sweep is that of LE #Compute k correction factor for Mach number #First, compute corrected 2D section lift curve slope (C_la) for the given Mach number cla = 6.13 #Section C_la at M = 0; Roskam Airplane Design Part VI, Table 8.1 cL_alpha = np.ones_like(mach) Beta = np.ones_like(mach) k = np.ones_like(mach) cla_M = np.ones_like(mach) Beta[mach<1.] = (1.0-mach[mach<1.]**2.0)**0.5 Beta[mach>1.] = (mach[mach>1.]**2.0-1.0)**0.5 cla_M[mach<1.] = cla/Beta[mach<1.] cla_M[mach>1.] = 4.0/Beta[mach>1.] k = cla_M/(2.0*np.pi/Beta) #Compute aerodynamic surface 3D lift curve slope using the DATCOM formula cL_alpha =(2.0*np.pi*ar/(2.0+((ar**2.0*(Beta*Beta)/(k*k))*(1.0+(np.tan(half_chord_sweep))**2.0/(Beta*Beta))+4.0)**0.5)) return cL_alpha