def parasite_drag_aircraft(conditions, configuration, geometry): """ SUAVE.Methods.parasite_drag_aircraft(aircraft,segment,Cl,cdi_inv,cdp,fd_ws) computes the parasite_drag_aircraft associated with an aircraft Inputs: Outputs: Assumptions: based on a set of fits """ # unpack inputs wings = geometry.wings fuselages = geometry.fuselages propulsors = geometry.propulsors vehicle_reference_area = geometry.reference_area drag_breakdown = conditions.aerodynamics.drag_breakdown # the drag to be returned total_parasite_drag = 0.0 # start conditions node drag_breakdown.parasite = Results() # from wings for wing in wings.values(): parasite_drag = parasite_drag_wing(conditions, configuration, wing) conditions.aerodynamics.drag_breakdown.parasite[ wing. tag].parasite_drag_coefficient = parasite_drag * wing.areas.reference / vehicle_reference_area total_parasite_drag += parasite_drag * wing.areas.reference / vehicle_reference_area # from fuselage for fuselage in fuselages.values(): parasite_drag = parasite_drag_fuselage(conditions, configuration, fuselage) conditions.aerodynamics.drag_breakdown.parasite[ fuselage. tag].parasite_drag_coefficient = parasite_drag * fuselage.areas.front_projected / vehicle_reference_area total_parasite_drag += parasite_drag * fuselage.areas.front_projected / vehicle_reference_area # from propulsors for propulsor in propulsors.values(): parasite_drag = parasite_drag_propulsor(conditions, configuration, propulsor) ref_area = propulsor.nacelle_diameter**2 / 4 * np.pi conditions.aerodynamics.drag_breakdown.parasite[ propulsor. tag].parasite_drag_coefficient = parasite_drag * ref_area / vehicle_reference_area * propulsor.number_of_engines total_parasite_drag += parasite_drag * ref_area / vehicle_reference_area * propulsor.number_of_engines # dump to condtitions drag_breakdown.parasite.total = total_parasite_drag return total_parasite_drag
def parasite_drag_propulsor(state, settings, geometry): """ SUAVE.Methods.parasite_drag_propulsor(conditions,configuration,propulsor) computes the parasite drag associated with a propulsor Inputs: Outputs: Assumptions: """ # unpack inputs conditions = state.conditions configuration = settings propulsor = geometry Sref = propulsor.nacelle_diameter**2. / 4. * np.pi Swet = propulsor.areas.wetted l_prop = propulsor.engine_length d_prop = propulsor.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 = 1 + 0.35 / (float(l_prop) / float(d_prop)) # find the final result propulsor_parasite_drag = k_prop * cf_prop * Swet / Sref # dump data to conditions propulsor_result = Results( wetted_area=Swet, reference_area=Sref, parasite_drag_coefficient=propulsor_parasite_drag, skin_friction_coefficient=cf_prop, compressibility_factor=k_comp, reynolds_factor=k_reyn, form_factor=k_prop, ) conditions.aerodynamics.drag_breakdown.parasite[ propulsor.tag] = propulsor_result return propulsor_parasite_drag
def fuselage_correction(state, settings, geometry): """ SUAVE.Methods.Aerodynamics.compute_aircraft_lift(conditions,configuration,geometry) computes the lift associated with an aircraft Inputs: conditions - data dictionary with fields: mach_number - float or 1D array of freestream mach numbers angle_of_attack - floar or 1D array of angle of attacks configuration - data dictionary with fields: surrogate_models.lift_coefficient - a callable function or class with inputs of angle of attack and outputs of lift coefficent fuselage_lift_correction - the correction to fuselage contribution to lift geometry - used for wing Outputs: CL - float or 1D array of lift coefficients of the total aircraft Updates: conditions.lift_breakdown - stores results here Assumptions: surrogate model returns total incompressible lift due to wings prandtl-glaurert compressibility correction on this fuselage contribution to lift correction as a factor """ # unpack fus_correction = settings.fuselage_lift_correction Mc = state.conditions.freestream.mach_number AoA = state.conditions.aerodynamics.angle_of_attack wings_lift_comp = state.conditions.aerodynamics.lift_coefficient # total lift, accounting one fuselage aircraft_lift_total = wings_lift_comp * fus_correction # store results lift_results = Results( total=aircraft_lift_total, #incompressible_wings = wings_lift , compressible_wings=wings_lift_comp, #compressibility_correction_factor = compress_corr , #fuselage_correction_factor = fus_correction , #vortex = vortex_cl , ) #conditions.aerodynamics.lift_breakdown.update( lift_results ) #update state.conditions.aerodynamics.lift_coefficient = aircraft_lift_total return aircraft_lift_total
def miscellaneous_drag_aircraft_ESDU(state,settings,geometry): #def miscellaneous_drag_aircraft_ESDU(conditions,configuration,geometry): """ SUAVE.Methods.miscellaneous_drag_aircraft_ESDU(conditions,configuration,geometry): computes the miscellaneous drag based in ESDU 94044, figure 1 Inputs: conditions - data dictionary for output dump configuration - not in use geometry - SUave type vehicle Outpus: cd_misc - returns the miscellaneous drag associated with the vehicle Assumptions: if needed """ # unpack inputs conditions = state.conditions configuration = settings Sref = geometry.reference_area ones_1col = conditions.freestream.mach_number *0.+1 # Estimating total wetted area swet_tot = 0. for wing in geometry.wings: swet_tot += wing.areas.wetted for fuselage in geometry.fuselages: swet_tot += fuselage.areas.wetted for propulsor in geometry.propulsors: swet_tot += propulsor.areas.wetted * propulsor.number_of_engines swet_tot *= 1.10 # Estimating excrescence drag, based in ESDU 94044, figure 1 D_q = 0.40* (0.0184 + 0.000469 * swet_tot - 1.13*10**-7 * swet_tot ** 2) cd_excrescence = D_q / Sref # ------------------------------------------------------------------ # The final result # ------------------------------------------------------------------ # dump to results conditions.aerodynamics.drag_breakdown.miscellaneous = Results( total_wetted_area = swet_tot, reference_area = Sref , total = cd_excrescence *ones_1col, ) return cd_excrescence *ones_1col
def wave_drag_lift(conditions, configuration, wing): """ SUAVE.Methods.wave_drag_lift(conditions,configuration,wing) computes the wave drag due to lift Based on http://adg.stanford.edu/aa241/drag/ssdragcalc.html Inputs: - SUave wing - Sref - wing reference area - Mc - mach number - CL - coefficient of lift - total_length - length of the wing root Outputs: - CD due to wave drag from the wing Assumptions: - Supersonic mach numbers - Reference area of passed wing is desired for CD """ # Unpack freestream = conditions.freestream total_length = wing.total_length Sref = wing.areas.reference # Conditions Mc = freestream.mach_number * 1.0 # Length-wise aspect ratio ARL = total_length**2 / Sref # Lift coefficient CL = conditions.aerodynamics.lift_coefficient * 1.0 # Computations x = np.pi * ARL / 4 beta = np.array([[0.0]] * len(Mc)) beta[Mc >= 1.05] = np.sqrt(Mc[Mc >= 1.05]**2 - 1) wave_drag_lift = np.array([[0.0]] * len(Mc)) wave_drag_lift[Mc >= 1.05] = CL[Mc >= 1.05]**2 * x / 4 * ( np.sqrt(1 + (beta[Mc >= 1.05] / x)**2) - 1) wave_drag_lift[0:len(Mc[Mc >= 1.05]), 0] = wave_drag_lift[Mc >= 1.05] # Dump data to conditions wave_lift_result = Results( reference_area=Sref, wave_drag_lift_coefficient=wave_drag_lift, length_AR=ARL, ) return wave_drag_lift
def induced_drag_aircraft(state,settings,geometry): """ SUAVE.Methods.induced_drag_aircraft(conditions,configuration,geometry) computes the induced drag associated with a wing Inputs: Outputs: Assumptions: based on a set of fits """ # unpack inputs conditions = state.conditions configuration = settings aircraft_lift = conditions.aerodynamics.lift_coefficient e = configuration.aircraft_span_efficiency_factor # TODO: get estimate from weissinger ar = geometry.wings[0].aspect_ratio # TODO: get estimate from weissinger Mc = conditions.freestream.mach_number #e = geometry.wings[0].span_efficiency # start the result total_induced_drag = 0.0 #print("In induced_drag_aircraft:") #print aircraft_lift #for ii in range(len(Mc)): #if Mc[ii] < 1.0: #total_induced_drag = aircraft_lift**2 / (np.pi*ar*e) #else: #total_induced_drag = aircraft_lift**2 / (np.pi*ar) ##total_induced_drag = aircraft_lift * 0.0 total_induced_drag = np.array([[0.0]]*len(Mc)) total_induced_drag[Mc < 1.0] = aircraft_lift[Mc < 1.0]**2 / (np.pi*ar*e) total_induced_drag[Mc >= 1.0] = aircraft_lift[Mc >= 1.0]**2 / (np.pi*ar*e) # store data try: conditions.aerodynamics.drag_breakdown.induced = Results( total = total_induced_drag , efficiency_factor = e , aspect_ratio = ar , ) except: print("Drag Polar Mode") # done! return total_induced_drag
def induced_drag_aircraft(state, settings, geometry): """ SUAVE.Methods.induced_drag_aircraft(conditions,configuration,geometry) computes the induced drag associated with a wing Inputs: Outputs: Assumptions: based on a set of fits """ # unpack inputs conditions = state.conditions configuration = settings aircraft_lift = conditions.aerodynamics.lift_coefficient e = configuration.oswald_efficiency_factor K = configuration.viscous_lift_dependent_drag_factor wing_e = geometry.wings[0].span_efficiency ar = geometry.wings[0].aspect_ratio # TODO: get estimate from weissinger CDp = state.conditions.aerodynamics.drag_breakdown.parasite.total if e == None: e = 1 / ((1 / wing_e) + np.pi * ar * K * CDp) # start the result total_induced_drag = 0.0 #print("In induced_drag_aircraft:") #print aircraft_lift total_induced_drag = aircraft_lift**2 / (np.pi * ar * e) #raw_input() # store data conditions.aerodynamics.drag_breakdown.induced = Results( total=total_induced_drag, efficiency_factor=e, aspect_ratio=ar, ) # done! return total_induced_drag
def fuselage_correction(state,settings,geometry): # unpack fus_correction = settings.fuselage_lift_correction Mc = state.conditions.freestream.mach_number AoA = state.conditions.aerodynamics.angle_of_attack wings_lift_comp = state.conditions.aerodynamics.lift_coefficient # total lift, accounting one fuselage aircraft_lift_total = wings_lift_comp * fus_correction # store results lift_results = Results( total = aircraft_lift_total , compressible_wings = wings_lift_comp , ) state.conditions.aerodynamics.lift_coefficient= aircraft_lift_total return aircraft_lift_total
def parasite_drag_propulsor(state,settings,geometry): #def parasite_drag_propulsor(conditions,configuration,propulsor): """ SUAVE.Methods.parasite_drag_propulsor(conditions,configuration,propulsor) computes the parasite drag associated with a propulsor Inputs: Outputs: Assumptions: """ # unpack inputs conditions = state.conditions configuration = settings propulsor = geometry # unpack inputs try: form_factor = configuration.propulsor_parasite_drag_form_factor except(AttributeError): form_factor = 2.3 freestream = conditions.freestream Sref = propulsor.nacelle_diameter**2 / 4 * np.pi Swet = propulsor.nacelle_diameter * np.pi * propulsor.engine_length l_prop = propulsor.engine_length d_prop = propulsor.nacelle_diameter # conditions Mc = freestream.mach_number roc = freestream.density muc = freestream.dynamic_viscosity Tc = freestream.temperature pc = freestream.pressure # reynolds number V = Mc * compute_speed_of_sound(Tc, pc) Re_prop = roc * V * l_prop/muc # skin friction coefficient cf_prop, k_comp, k_reyn = compressible_turbulent_flat_plate(Re_prop,Mc,Tc) # form factor for cylindrical bodies try: # Check if propulsor has an intake A_max = propulsor.nacelle_diameter A_exit = propulsor.A7 A_inflow = propulsor.Ao d_d = 1/((propulsor.engine_length + propulsor.D) / np.sqrt(4/np.pi*(A_max - (A_exit+A_inflow)/2))) except: d_d = float(d_prop)/float(l_prop) D = np.array([[0.0]] * len(Mc)) a = np.array([[0.0]] * len(Mc)) du_max_u = np.array([[0.0]] * len(Mc)) k_prop = np.array([[0.0]] * len(Mc)) D[Mc < 0.95] = np.sqrt(1 - (1-Mc[Mc < 0.95]**2) * d_d**2) a[Mc < 0.95] = 2 * (1-Mc[Mc < 0.95]**2) * (d_d**2) *(np.arctanh(D[Mc < 0.95])-D[Mc < 0.95]) / (D[Mc < 0.95]**3) du_max_u[Mc < 0.95] = a[Mc < 0.95] / ( (2-a[Mc < 0.95]) * (1-Mc[Mc < 0.95]**2)**0.5 ) D[Mc >= 0.95] = np.sqrt(1 - d_d**2) a[Mc >= 0.95] = 2 * (d_d**2) *(np.arctanh(D[Mc >= 0.95])-D[Mc >= 0.95]) / (D[Mc >= 0.95]**3) du_max_u[Mc >= 0.95] = a[Mc >= 0.95] / ( (2-a[Mc >= 0.95]) ) k_prop = (1 + form_factor*du_max_u)**2 # -------------------------------------------------------- # find the final result propulsor_parasite_drag = k_prop * cf_prop * Swet / Sref # -------------------------------------------------------- # dump data to conditions propulsor_result = Results( wetted_area = Swet , reference_area = Sref , parasite_drag_coefficient = propulsor_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[propulsor.tag] = propulsor_result return propulsor_parasite_drag
def parasite_drag_wing(state, settings, geometry): """ SUAVE.Methods.parasite_drag_wing(conditions,configuration,wing) computes the parastite drag associated with a wing Inputs: conditions -freestream mach number -freestream density -freestream dynamic_viscosity -freestream temperature -freestream pressuve configuration -wing parasite drag form factor wing -S reference -mean aerodynamic chord -thickness to chord ratio -sweep -aspect ratio -span -S exposed -S affected -transition x Outputs: wing parasite drag coefficient with refernce area as the reference area of the input wing Assumptions: """ # unpack inputs C = settings.wing_parasite_drag_form_factor freestream = state.conditions.freestream wing = geometry Sref = wing.areas.reference # wing mac_w = wing.chords.mean_aerodynamic t_c_w = wing.thickness_to_chord sweep_w = wing.sweep arw_w = wing.aspect_ratio span_w = wing.spans.projected S_exposed_w = wing.areas.exposed # TODO: calculate by fuselage diameter (in Fidelity_Zero.initialize()) S_affected_w = wing.areas.affected xtu = wing.transition_x_upper xtl = wing.transition_x_lower # compute wetted area # TODO: calcualte as preprocessing Swet = 1. * (1.0 + 0.2 * t_c_w) * S_exposed_w # conditions Mc = freestream.mach_number Tc = freestream.temperature re = freestream.reynolds_number # 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 k_w = np.array([[0.0]] * len(Mc)) k_w[Mc < 0.95] = 1. + ( 2.* C * (t_c_w * (np.cos(sweep_w))**2.) ) / ( np.sqrt(1.- Mc[Mc < 0.95]**2. * ( np.cos(sweep_w))**2.) ) \ + ( C**2. * (np.cos(sweep_w))**2. * t_c_w**2. * (1. + 5.*(np.cos(sweep_w)**2.)) ) \ / (2.*(1.-(Mc[Mc < 0.95]*np.cos(sweep_w))**2.)) k_w[Mc >= 0.95] = 1. # find the final result wing_parasite_drag = k_w * cf_w_u * Swet / Sref / 2. + k_w * cf_w_l * Swet / Sref / 2. # dump data to conditions wing_result = Results( wetted_area=Swet, reference_area=Sref, parasite_drag_coefficient=wing_parasite_drag, skin_friction_coefficient=(cf_w_u + cf_w_l) / 2., compressibility_factor=k_comp_u, reynolds_factor=k_reyn_l, form_factor=k_w, ) state.conditions.aerodynamics.drag_breakdown.parasite[ wing.tag] = wing_result return wing_parasite_drag
def parasite_drag_fuselage(state, settings, geometry): """ SUAVE.Methods.parasite_drag_fuselage(conditions,configuration,fuselage) computes the parasite drag associated with a fuselage Inputs: Outputs: Assumptions: """ # unpack inputs configuration = settings form_factor = configuration.fuselage_parasite_drag_form_factor fuselage = geometry freestream = state.conditions.freestream Sref = fuselage.areas.front_projected Swet = fuselage.areas.wetted #l_fus = fuselage.lengths.cabin l_fus = fuselage.lengths.total d_fus = fuselage.width l_nose = fuselage.lengths.nose l_tail = fuselage.lengths.tail # conditions Mc = freestream.mach_number roc = freestream.density muc = freestream.dynamic_viscosity Tc = freestream.temperature pc = freestream.pressure # reynolds number V = Mc * compute_speed_of_sound(Tc, pc) Re_fus = roc * V * l_fus / muc # 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 = np.array([[0.0]] * len(Mc)) a = np.array([[0.0]] * len(Mc)) du_max_u = np.array([[0.0]] * len(Mc)) k_fus = np.array([[0.0]] * len(Mc)) D[Mc < 0.95] = np.sqrt(1 - (1 - Mc[Mc < 0.95]**2) * d_d**2) a[Mc < 0.95] = 2 * (1 - Mc[Mc < 0.95]**2) * (d_d**2) * ( np.arctanh(D[Mc < 0.95]) - D[Mc < 0.95]) / (D[Mc < 0.95]**3) du_max_u[Mc < 0.95] = a[Mc < 0.95] / ((2 - a[Mc < 0.95]) * (1 - Mc[Mc < 0.95]**2)**0.5) D[Mc >= 0.95] = np.sqrt(1 - d_d**2) a[Mc >= 0.95] = 2 * (d_d**2) * (np.arctanh(D[Mc >= 0.95]) - D[Mc >= 0.95]) / (D[Mc >= 0.95]**3) du_max_u[Mc >= 0.95] = a[Mc >= 0.95] / ((2 - a[Mc >= 0.95])) k_fus = (1 + form_factor * du_max_u)**2 #for i in range(len(Mc)): #if Mc[i] < 0.95: #D[i] = np.sqrt(1 - (1-Mc[i]**2) * d_d**2) #a[i] = 2 * (1-Mc[i]**2) * (d_d**2) *(np.arctanh(D[i])-D[i]) / (D[i]**3) #du_max_u[i] = a[i] / ( (2-a[i]) * (1-Mc[i]**2)**0.5 ) #else: #D[i] = np.sqrt(1 - d_d**2) #a[i] = 2 * (d_d**2) *(np.arctanh(D[i])-D[i]) / (D[i]**3) #du_max_u[i] = a[i] / ( (2-a[i]) ) #k_fus[i] = (1 + cf_fus[i]*du_max_u[i])**2 # -------------------------------------------------------- # find the final result fuselage_parasite_drag = k_fus * cf_fus * Swet / Sref # -------------------------------------------------------- # dump data to conditions fuselage_result = Results( 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 windmilling_drag(geometry,state): """ SUAVE.Methods.Aerodynamics.Fidelity_Zero.Drag.windmilling_drag(geometry,state): Computes the windmilling drag of turbofan engines Inputs: geometry - data dictionary with data of vehicle and engine state - to output drag breakdown Outputs: windmilling_drag Assumptions: """ # ============================================== # Unpack # ============================================== vehicle = geometry # Defining reference area if vehicle.reference_area: reference_area = vehicle.reference_area else: n_wing = 0 for wing in vehicle.wings: if not isinstance(wing,Wings.Main_Wing): continue n_wing = n_wing + 1 reference_area = wing.sref if n_wing > 1: print ' More than one Main_Wing in the vehicle. Last one will be considered.' elif n_wing == 0: print 'No Main_Wing defined! Using the 1st wing found' for wing in vehicle.wings: if not isinstance(wing,Wings.Wing): continue reference_area = wing.sref break # getting geometric data from engine (estimating when not available) for idx,propulsor in enumerate(vehicle.propulsors): try: swet_nac = propulsor.areas.wetted except: try: D_nac = propulsor.nacelle_diameter if propulsor.engine_length <> 0.: l_nac = propulsor.engine_length else: try: MMO = vehicle.max_mach_operational except: MMO = 0.84 D_nac_in = D_nac / Units.inches l_nac = (2.36 * D_nac_in - 0.01*(D_nac_in*MMO)**2) * Units.inches except AttributeError: print 'Error calculating windmilling drag. Engine dimensions missing.' swet_nac = 5.62 * D_nac * l_nac # Compute windmilling_drag_coefficient = 0.007274 * swet_nac / reference_area # dump data to state windmilling_result = Results( wetted_area = swet_nac , windmilling_drag_coefficient = windmilling_drag_coefficient , ) state.conditions.aerodynamics.drag_breakdown.windmilling_drag = windmilling_result return windmilling_drag_coefficient
def compute_aircraft_lift(conditions, configuration, geometry): """ SUAVE.Methods.Aerodynamics.compute_aircraft_lift(conditions,configuration,geometry) computes the lift associated with an aircraft Inputs: conditions - data dictionary with fields: mach_number - float or 1D array of freestream mach numbers angle_of_attack - floar or 1D array of angle of attacks configuration - data dictionary with fields: surrogate_models.lift_coefficient - a callable function or class with inputs of angle of attack and outputs of lift coefficent fuselage_lift_correction - the correction to fuselage contribution to lift geometry - used for wing Outputs: CL - float or 1D array of lift coefficients of the total aircraft Updates: conditions.lift_breakdown - stores results here Assumptions: surrogate model returns total incompressible lift due to wings prandtl-glaurert compressibility correction on this fuselage contribution to lift correction as a factor """ # unpack fus_correction = configuration.fuselage_lift_correction Mc = conditions.freestream.mach_number AoA = conditions.aerodynamics.angle_of_attack # pack for interpolate X_interp = AoA wings_lift = np.array([[0.0]] * len(Mc)) wings_lift_comp = np.array([[0.0]] * len(Mc)) compress_corr = np.array([[0.0]] * len(Mc)) aircraft_lift_total = np.array([[0.0]] * len(Mc)) vortex_cl = np.array([[0.0]] * len(Mc)) #print aircraft_lift_total wing = geometry.wings[0] # Subsonic setup wings_lift = conditions.aerodynamics.lift_breakdown.inviscid_wings_lift compress_corr[Mc < 0.95] = 1. / (np.sqrt(1. - Mc[Mc < 0.95]**2.)) compress_corr[Mc >= 0.95] = 1. / ( np.sqrt(1. - 0.95**2) ) # Values for Mc > 1.05 are update after this assignment # wings_lift[Mc <= 1.05] = wings_lift_model(X_interp[Mc <= 1.05]) if wing.vortex_lift is True: vortex_cl[Mc < 1.0] = vortex_lift(X_interp[Mc < 1.0], configuration, wing) # This was initialized at 0.0 wings_lift[Mc <= 1.05] = wings_lift[Mc <= 1.05] + vortex_cl[Mc <= 1.05] # Supersonic setup # wings_lift_model = configuration.surrogate_models_sup.lift_coefficient compress_corr[Mc > 1.05] = 1. / (np.sqrt(Mc[Mc > 1.05]**2. - 1.)) # wings_lift[Mc > 1.05] = wings_lift_model(X_interp[Mc > 1.05]) wings_lift_comp = wings_lift * compress_corr aircraft_lift_total = wings_lift_comp * fus_correction # store results lift_results = Results( total=aircraft_lift_total, incompressible_wings=wings_lift, compressible_wings=wings_lift_comp, compressibility_correction_factor=compress_corr, fuselage_correction_factor=fus_correction, vortex=vortex_cl, ) conditions.aerodynamics.lift_breakdown.update(lift_results) #update conditions.aerodynamics.lift_coefficient = aircraft_lift_total return aircraft_lift_total
def parasite_drag_pylon(state, settings, geometry): """ SUAVE.Methods.parasite_drag_pylon(conditions,configuration,geometry): Simplified estimation, considering pylon drag a fraction of the nacelle drag Inputs: conditions - data dictionary for output dump configuration - not in use geometry - SUave type vehicle Outpus: cd_misc - returns the miscellaneous drag associated with the vehicle Assumptions: simplified estimation, considering pylon drag a fraction of the nacelle drag """ # unpack conditions = state.conditions configuration = settings pylon_factor = 0.20 # 20% of propulsor drag n_propulsors = len( geometry.propulsors ) # number of propulsive system in vehicle (NOT # of ENGINES) pylon_parasite_drag = 0.00 pylon_wetted_area = 0.00 pylon_cf = 0.00 pylon_compr_fact = 0.00 pylon_rey_fact = 0.00 pylon_FF = 0.00 # Estimating pylon drag for propulsor in geometry.propulsors: ref_area = propulsor.nacelle_diameter**2 / 4 * np.pi pylon_parasite_drag += pylon_factor * conditions.aerodynamics.drag_breakdown.parasite[ propulsor.tag].parasite_drag_coefficient * ( ref_area / geometry.reference_area * propulsor.number_of_engines) pylon_wetted_area += pylon_factor * conditions.aerodynamics.drag_breakdown.parasite[ propulsor.tag].wetted_area * propulsor.number_of_engines pylon_cf += conditions.aerodynamics.drag_breakdown.parasite[ propulsor.tag].skin_friction_coefficient pylon_compr_fact += conditions.aerodynamics.drag_breakdown.parasite[ propulsor.tag].compressibility_factor pylon_rey_fact += conditions.aerodynamics.drag_breakdown.parasite[ propulsor.tag].reynolds_factor pylon_FF += conditions.aerodynamics.drag_breakdown.parasite[ propulsor.tag].form_factor pylon_cf /= n_propulsors pylon_compr_fact /= n_propulsors pylon_rey_fact /= n_propulsors pylon_FF /= n_propulsors # dump data to conditions pylon_result = Results( wetted_area=pylon_wetted_area, reference_area=geometry.reference_area, parasite_drag_coefficient=pylon_parasite_drag, skin_friction_coefficient=pylon_cf, compressibility_factor=pylon_compr_fact, reynolds_factor=pylon_rey_fact, form_factor=pylon_FF, ) conditions.aerodynamics.drag_breakdown.parasite['pylon'] = pylon_result return pylon_parasite_drag
def compressibility_drag_wing(conditions, configuration, geometry): """ SUAVE.Methods.compressibility_drag_wing(conditions,configuration,geometry) computes the induced drag associated with a wing Inputs: Outputs: Assumptions: based on a set of fits """ # unpack wings = geometry.Wings fuselages = geometry.Fuselages wing_lifts = conditions.aerodynamics.lift_breakdown.compressible_wings # currently the total aircraft lift mach = conditions.freestream.mach_number drag_breakdown = conditions.aerodynamics.drag_breakdown # start result total_compressibility_drag = 0.0 drag_breakdown.compressible = Results() # go go go for i_wing, wing, in enumerate(wings.values()): # unpack wing t_c_w = wing.t_c sweep_w = wing.sweep Mc = copy.copy(mach) for ii in range(len(Mc)): if Mc[ii] > 0.95 and Mc[ii] < 1.05: Mc[ii] = 0.95 if Mc[ii] <= 0.95: if i_wing == 0: cl_w = wing_lifts else: cl_w = 0 # get effective Cl and sweep tc = t_c_w / (np.cos(sweep_w)) cl = cl_w / (np.cos(sweep_w))**2 # compressibility drag based on regressed fits from AA241 mcc_cos_ws = 0.922321524499352 \ - 1.153885166170620*tc \ - 0.304541067183461*cl \ + 0.332881324404729*tc**2 \ + 0.467317361111105*tc*cl \ + 0.087490431201549*cl**2 # crest-critical mach number, corrected for wing sweep mcc = mcc_cos_ws / np.cos(sweep_w) # divergence mach number MDiv = mcc * (1.02 + 0.08 * (1 - np.cos(sweep_w))) # divergence ratio mo_mc = mach / mcc # compressibility correlation, Shevell dcdc_cos3g = 0.0019 * mo_mc**14.641 # compressibility drag cd_c = dcdc_cos3g * (np.cos(sweep_w))**3 else: cd_lift_wave = wave_drag_lift(conditions, configuration, wing) cd_volume_wave = wave_drag_volume(conditions, configuration, wing) cd_c = cd_lift_wave + cd_volume_wave tc = 0 sweep_w = 0 mcc = 0 MDiv = 0 # increment #total_compressibility_drag += cd_c ## todo when there is a lift break down by wing # dump data to conditions wing_results = Results( compressibility_drag=cd_c, thickness_to_chord=tc, wing_sweep=sweep_w, crest_critical=mcc, divergence_mach=MDiv, ) #drag_breakdown.compressible[wing.tag] = wing_results #: for each wing # dump total comp drag total_compressibility_drag = drag_breakdown.compressible[ 1 + 0].compressibility_drag drag_breakdown.compressible.total = total_compressibility_drag return total_compressibility_drag, wing_results
def compressibility_drag_wing(state, settings, geometry): #def compressibility_drag_wing(conditions,configuration,geometry): """ SUAVE.Methods.compressibility_drag_wing(conditions,configuration,geometry) computes the induced drag associated with a wing Inputs: Outputs: Assumptions: based on a set of fits """ # unpack conditions = state.conditions configuration = settings wing = geometry if isinstance(wing, Wings.Main_Wing): wing_lifts = conditions.aerodynamics.lift_breakdown.compressible_wings # currently the total aircraft lift elif wing.vertical: wing_lifts = 0 else: wing_lifts = 0.15 * conditions.aerodynamics.lift_breakdown.compressible_wings mach = conditions.freestream.mach_number drag_breakdown = conditions.aerodynamics.drag_breakdown # start result total_compressibility_drag = 0.0 #drag_breakdown.compressible = Results() # unpack wing t_c_w = wing.thickness_to_chord sweep_w = wing.sweep # Currently uses vortex lattice model on all wings if wing.tag == 'main_wing': cl_w = wing_lifts else: cl_w = 0 # get effective Cl and sweep tc = t_c_w / (np.cos(sweep_w)) cl = cl_w / (np.cos(sweep_w))**2 # compressibility drag based on regressed fits from AA241 mcc_cos_ws = 0.922321524499352 \ - 1.153885166170620*tc \ - 0.304541067183461*cl \ + 0.332881324404729*tc**2 \ + 0.467317361111105*tc*cl \ + 0.087490431201549*cl**2 # crest-critical mach number, corrected for wing sweep mcc = mcc_cos_ws / np.cos(sweep_w) # divergence mach number MDiv = mcc * (1.02 + 0.08 * (1 - np.cos(sweep_w))) # divergence ratio mo_mc = mach / mcc # compressibility correlation, Shevell dcdc_cos3g = 0.0019 * mo_mc**14.641 # compressibility drag cd_c = dcdc_cos3g * (np.cos(sweep_w))**3 # increment #total_compressibility_drag += cd_c # dump data to conditions wing_results = Results( compressibility_drag=cd_c, thickness_to_chord=tc, wing_sweep=sweep_w, crest_critical=mcc, divergence_mach=MDiv, ) drag_breakdown.compressible[wing.tag] = wing_results # dump total comp drag #drag_breakdown.compressible.total = total_compressibility_drag #conditions.aerodynamics.drag_breakdown.compressible[wing.tag] = wing_results #conditions.aerodynamics.drag_breakdown.compressible.total = total_compressibility_drag return total_compressibility_drag
def parasite_drag_fuselage(state, settings, geometry): """ SUAVE.Methods.parasite_drag_fuselage(conditions,configuration,fuselage) computes the parasite drag associated with a fuselage Inputs: Outputs: Assumptions: """ # unpack inputs conditions = state.conditions configuration = settings fuselage = geometry form_factor = configuration.fuselage_parasite_drag_form_factor freestream = conditions.freestream Sref = fuselage.areas.front_projected Swet = fuselage.areas.wetted l_fus = fuselage.lengths.cabin d_fus = fuselage.effective_diameter l_nose = fuselage.lengths.nose l_tail = fuselage.lengths.tail # conditions Mc = freestream.mach_number Tc = freestream.temperature re = freestream.reynolds_number # reynolds number Re_fus = re * (l_fus + l_nose + l_tail) # 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 = np.sqrt(1 - (1 - Mc**2) * d_d**2) a = 2 * (1 - Mc**2) * (d_d**2) * (np.arctanh(D) - D) / (D**3) du_max_u = a / ((2 - a) * (1 - Mc**2)**0.5) k_fus = (1 + form_factor * du_max_u)**2 # find the final result fuselage_parasite_drag = k_fus * cf_fus * Swet / Sref # dump data to conditions fuselage_result = Results( 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, ) state.conditions.aerodynamics.drag_breakdown.parasite[ fuselage.tag] = fuselage_result return fuselage_parasite_drag
def miscellaneous_drag_aircraft(state, settings, geometry): """ SUAVE.Methods.miscellaneous_drag_aircraft(Wing,segment) computes the miscellaneous drag associated with an aircraft Inputs: aircraft- An aircraft object is passed in segment - the segment object contains information regarding the mission segment Cl - wing Cl Outpus: cd_misc - returns the miscellaneous drag assoicated with the wing >> try to minimize outputs >> pack up outputs into Data() if needed Assumptions: if needed """ # unpack inputs configuration = settings trim_correction_factor = configuration.trim_drag_correction_factor propulsors = geometry.propulsors vehicle_reference_area = geometry.reference_area ones_1col = state.conditions.freestream.mach_number * 0. + 1 conditions = state.conditions # ------------------------------------------------------------------ # Control surface gap drag # ------------------------------------------------------------------ #f_gaps_w=0.0002*(numpy.cos(sweep_w))**2*S_affected_w #f_gaps_h=0.0002*(numpy.cos(sweep_h))**2*S_affected_h #f_gaps_v=0.0002*(numpy.cos(sweep_v))**2*S_affected_v #f_gapst = f_gaps_w + f_gaps_h + f_gaps_v # TODO: do this correctly total_gap_drag = 0.0001 # ------------------------------------------------------------------ # Nacelle base drag # ------------------------------------------------------------------ total_nacelle_base_drag = 0.0 nacelle_base_drag_results = Results() for propulsor in propulsors.values(): # calculate nacelle_base_drag = 0.5 / 12. * np.pi * propulsor.nacelle_diameter * 0.2 / vehicle_reference_area # dump nacelle_base_drag_results[ propulsor.tag] = nacelle_base_drag * ones_1col # increment total_nacelle_base_drag += nacelle_base_drag # ------------------------------------------------------------------ # Fuselage upsweep drag # ------------------------------------------------------------------ fuselage_upsweep_drag = 0.006 / vehicle_reference_area # ------------------------------------------------------------------ # Fuselage base drag # ------------------------------------------------------------------ fuselage_base_drag = 0.0 # ------------------------------------------------------------------ # The final result # ------------------------------------------------------------------ total_miscellaneous_drag = total_gap_drag \ + total_nacelle_base_drag \ + fuselage_upsweep_drag \ + fuselage_base_drag # dump to results conditions.aerodynamics.drag_breakdown.miscellaneous = Results( fuselage_upsweep=fuselage_upsweep_drag * ones_1col, nacelle_base=nacelle_base_drag_results, fuselage_base=fuselage_base_drag * ones_1col, control_gaps=total_gap_drag * ones_1col, total=total_miscellaneous_drag * ones_1col, ) return total_miscellaneous_drag * ones_1col
def compressibility_drag_total(state,settings,geometry): """ SUAVE.Methods.compressibility_drag_total_supersonic(conditions,configuration,geometry) computes the compressibility drag on a full aircraft Inputs: wings fuselages propulsors freestream conditions Outputs: compressibility drag coefficient Assumptions: drag is only calculated for the wings, main fuselage, and propulsors main fuselage must have tag 'fuselage' no lift on wings other than main wing """ # Unpack conditions = state.conditions configuration = settings wings = geometry.wings fuselages = geometry.fuselages propulsor = geometry.propulsors[0] Mc = conditions.freestream.mach_number drag_breakdown = conditions.aerodynamics.drag_breakdown # Initialize result drag_breakdown.compressible = Results() # Iterate through wings for i_wing, wing, in enumerate(wings.values()): # initialize array to correct length cd_c = np.array([[0.0]] * len(Mc)) mcc = np.array([[0.0]] * len(Mc)) MDiv = np.array([[0.0]] * len(Mc)) # Use main wing reference area for drag coefficients if i_wing == 0: Sref_main = wing.areas.reference # Get main fuselage data - note that name of fuselage is important here # This should be changed to be general main_fuselage = fuselages['fuselage'] # Get number of engines data num_engines = propulsor.number_of_engines # Get the lift coefficient of the wing. # Note that this is not the total CL cl = conditions.aerodynamics.lift_breakdown.compressible_wings # Calculate compressibility drag at Mach 0.99 and 1.05 for interpolation between (drag99,a,b) = drag_div(np.array([[0.99]] * len(Mc)),wing,i_wing,cl,Sref_main) (drag105,a,b) = wave_drag(conditions, configuration, main_fuselage, propulsor, wing, num_engines,i_wing,Sref_main,True) # For subsonic mach numbers, use drag divergence correlations to find the drag (cd_c[Mc <= 0.99],mcc[Mc <= 0.99], MDiv[Mc <= 0.99]) = drag_div(Mc[Mc <= 0.99],wing,i_wing,cl[Mc <= 0.99],Sref_main) # For mach numbers close to 1, use an interpolation to avoid intensive calculations cd_c[Mc > 0.99] = drag99[Mc > 0.99] + (drag105[Mc > 0.99]-drag99[Mc > 0.99])*(Mc[Mc > 0.99]-0.99)/(1.05-0.99) # Use wave drag equations at supersonic values. The cutoff for this function is 1.05 # Only the supsonic results are returned with nonzero values (cd_c_sup,mcc_sup,MDiv_sup) = wave_drag(conditions, configuration, main_fuselage, propulsor, wing, num_engines,i_wing,Sref_main,False) # Incorporate supersonic results into total compressibility drag coefficient (cd_c[Mc >= 1.05],mcc[Mc >= 1.05], MDiv[Mc >= 1.05]) = (cd_c_sup[Mc >= 1.05],mcc_sup[Mc >= 1.05],MDiv_sup[Mc >= 1.05]) # Dump data to conditions wing_results = Results( compressibility_drag = cd_c , crest_critical = mcc , divergence_mach = MDiv , ) drag_breakdown.compressible[wing.tag] = wing_results # Initialize arrays mach = conditions.freestream.mach_number prop_drag = np.array([[0.0]] * len(mach)) fuse_drag = np.array([[0.0]] * len(mach)) # Fuselage wave drag if len(main_fuselage) > 0: fuse_drag[mach >= 1.05] = wave_drag_body_of_rev(main_fuselage.lengths.total,main_fuselage.effective_diameter/2.0,Sref_main) else: raise ValueError('Main fuselage does not have a total length') # Propulsor wave drag prop_drag[mach >= 1.05] = wave_drag_body_of_rev(propulsor.engine_length,propulsor.nacelle_diameter/2.0,Sref_main)*propulsor.number_of_engines # Pack values #cd_c[mach >= 1.05] = cd_c[mach >= 1.05] + fuse_drag[mach >= 1.05] #cd_c[mach >= 1.05] = cd_c[mach >= 1.05] + prop_drag[mach >= 1.05] drag_breakdown.compressible[main_fuselage.tag] = fuse_drag drag_breakdown.compressible[propulsor.tag] = prop_drag # Dump total comp drag total_compressibility_drag = 0.0 for jj in range(0,i_wing+1): total_compressibility_drag = drag_breakdown.compressible[jj].compressibility_drag + total_compressibility_drag total_compressibility_drag = total_compressibility_drag + fuse_drag total_compressibility_drag = total_compressibility_drag + prop_drag drag_breakdown.compressible.total = total_compressibility_drag return total_compressibility_drag