def fct_power_bli(y, PwShaft, Tamb, Pamb, rho, Mach, Vair, Vsnd, r1, d1, nozzle_area): Ttot = earth.total_temperature( Tamb, Mach) # Stagnation temperature at inlet position (q0, q1, q2, Vinlet, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y) Tstat = Ttot - 0.5 * Vinlet**2 / Cp # Static temperature at inlet position Vsnd_inlet = earth.sound_speed(Tstat) # Sound speed at inlet position MachInlet = Vinlet / Vsnd_inlet # Mean Mach number at inlet position PwInput = nacelle.efficiency_fan * PwShaft Vjet = math.sqrt(2. * PwInput / q1 + Vinlet**2) TtotJet = Ttot + PwShaft / ( q1 * Cp) # Stagnation temperature increases due to introduced work Tstat = TtotJet - 0.5 * Vjet**2 / Cp # Static temperature VsndJet = earth.sound_speed(Tstat) # Sound speed at nozzle exhaust MachJet = Vjet / VsndJet # Mach number at nozzle output PtotJet = earth.total_pressure( Pamb, MachJet) # total pressure at nozzle exhaust (P = Pamb) CQoA1 = craft_aero.corrected_air_flow( PtotJet, TtotJet, MachJet) # Corrected air flow per area at fan position q = CQoA1 * nozzle_area y = q1 - q return y
def eval_turboprop_engine_design(aircraft): """ Turboprop architecture design """ engine = aircraft.turboprop_engine engine.rating_factor = (0.800, 0.688, 0.624, 0.560, 0.100) disa = 0. altp = 0. mach = 0.25 (pamb, tamb, tstd, dtodz) = earth.atmosphere(altp, disa) Vsnd = earth.sound_speed(tamb) Vair = Vsnd * mach engine.reference_power = engine.reference_thrust * ( Vair / engine.propeller_efficiency) # assuming a fan disk load of 3000 N/m2 engine.propeller_diameter = math.sqrt( (4. / math.pi) * (engine.reference_thrust / 3000)) return
def air_path(aircraft, nei, altp, disa, speed_mode, speed, mass, rating): """ Retrieves air path in various conditions """ g = earth.gravity() [pamb, tamb, tstd, dtodz] = earth.atmosphere(altp, disa) mach = get_mach(pamb, speed_mode, speed) fn, data = propu.thrust(aircraft, pamb, tamb, mach, rating, nei) cz = lift_from_speed(aircraft, pamb, mach, mass) [cx, lod] = aero.drag(aircraft, pamb, tamb, mach, cz) if (nei > 0): dcx = propu.oei_drag(aircraft, pamb, mach) cx = cx + dcx * nei lod = cz / cx acc_factor = earth.climb_mode(speed_mode, dtodz, tstd, disa, mach) slope = (fn / (mass * g) - 1 / lod) / acc_factor vsnd = earth.sound_speed(tamb) v_z = mach * vsnd * slope return slope, v_z
def turbofan_thrust(aircraft, Pamb, Tamb, Mach, rating, nei): """ Calculation of thrust for pure turbofan airplane Warning : ALL engine thrust returned """ engine = aircraft.turbofan_engine nacelle = aircraft.turbofan_nacelle factor = engine.rating_factor # [MTO,MCN,MCL,MCR,FID] kth = 0.475*Mach**2 + 0.091*(engine.bpr/10)**2 \ - 0.283*Mach*engine.bpr/10 \ - 0.633*Mach - 0.081*engine.bpr/10 + 1.192 (rho, sig) = earth.air_density(Pamb, Tamb) fn0 = factor[rating] * kth * engine.reference_thrust * sig**0.75 fn_core = fn0 * engine.core_thrust_ratio # Core thrust fn_fan0 = fn0 * (1 - engine.core_thrust_ratio) # Fan thrust Vsnd = earth.sound_speed(Tamb) Vair = Vsnd * Mach shaft_power0 = fn_fan0 * Vair / nacelle.efficiency_prop # Available total shaft power for one engine fn = fn0 * (engine.n_engine - nei) # All turbofan thrust data = (fn_core, fn_fan0, fn0, shaft_power0 ) # Data for ONE turbofan engine return fn, data
def specific_air_range(aircraft, altp, mass, mach, disa): propulsion = aircraft.propulsion (MTO, MCN, MCL, MCR, FID) = propulsion.rating_code g = earth.gravity() pamb, tamb, tstd, dtodz = earth.atmosphere(altp, disa) vsnd = earth.sound_speed(tamb) Cz = flight.lift_from_speed(aircraft, pamb, mach, mass) [Cx, LoD] = craft_aero.drag(aircraft, pamb, tamb, mach, Cz) nei = 0. sfc = propu.sfc(aircraft, pamb, tamb, mach, MCR, nei) sar = (vsnd * mach * LoD) / (mass * g * sfc) return sar
run.mass_mission_adaptation(aircraft) #run.mass_estimation(aircraft) # Calculate all airplane performances #------------------------------------------------------------------------------------------------------ run.performance_analysis(aircraft) # Print relevant output #------------------------------------------------------------------------------------------------------ altp = unit.m_ft(35000) disa = 0 pamb, tamb, tstd, dtodz = earth.atmosphere(altp, disa) (MTO, MCN, MCL, MCR, FID) = aircraft.propulsion.rating_code nei = 0 Fn, Data = propu.thrust(aircraft, pamb, tamb, cruise_mach, MTO, nei) vsnd = earth.sound_speed(tamb) tas = vsnd * cruise_mach print("") print("True air speed in cruise", "%.1f" % tas, " m/s") print("Totalthrust in cruise", "%.0f" % Fn, " N") print("") print("Engine thrust = ", "%.1f" % (aircraft.propulsion.reference_thrust_effective / 10), " daN") print("Wing area = ", "%.1f" % aircraft.wing.area, " m2") print("MTOW = ", "%.0f" % aircraft.weights.mtow, " kg") print("OWE = ", "%.0f" % aircraft.weights.owe, " kg") print("") print("Turbofan nacelle width = ", "%.1f" % aircraft.turbofan_nacelle.width, " m")
def hybrid_body_thrust(aircraft, Pamb, Tamb, Mach, rating, nei): propulsion = aircraft.propulsion engine = aircraft.turbofan_engine nacelle = aircraft.turbofan_nacelle battery = aircraft.battery power_elec = aircraft.power_elec_chain e_engine = aircraft.electric_engine e_nacelle = aircraft.electric_nacelle power_ratio = numpy.array([ e_engine.mto_e_power_ratio, e_engine.mcn_e_power_ratio, e_engine.mcl_e_power_ratio, e_engine.mcr_e_power_ratio, e_engine.fid_e_power_ratio ]) # Battery power feed is used in temporary phases only battery_power_feed = numpy.array([1,0,1,0,0])*battery.power_feed \ *e_nacelle.controler_efficiency \ *e_nacelle.motor_efficiency fn, data = propu.turbofan_thrust(aircraft, Pamb, Tamb, Mach, rating, nei) (fn_core, fn_fan0, fn0, shaft_power0) = data Vsnd = earth.sound_speed(Tamb) Vair = Vsnd * Mach shaft_power1 = (1 - power_ratio[rating] ) * shaft_power0 # Shaft power dedicated to the fan if (propulsion.bli_effect > 0): (fn_fan1, q1, dVbli) = propu.fan_thrust_with_bli(nacelle, Pamb, Tamb, Mach, Vair, shaft_power1) else: (fn_fan1, q0) = propu.fan_thrust(nacelle, Pamb, Tamb, Mach, Vair, shaft_power1) shaft_power2 = power_ratio[rating] * shaft_power0 * ( engine.n_engine - nei) # Shaft power dedicated to electric generator # Effective eFan shaft power pw_shaft2 = power_elec.overall_efficiency*shaft_power2 \ + e_nacelle.motor_efficiency*e_nacelle.controler_efficiency*battery_power_feed[rating] if (pw_shaft2 > 0.): if (propulsion.bli_effect > 0): (fn_fan2, q1, dVbli) = propu.fan_thrust_with_bli(e_nacelle, Pamb, Tamb, Mach, Vair, pw_shaft2) dVbli_o_V = dVbli / Vair else: (fn_fan2, q0) = propu.fan_thrust(e_nacelle, Pamb, Tamb, Mach, Vair, pw_shaft2) dVbli_o_V = 0. sec = (pw_shaft2 / e_nacelle.motor_efficiency) / fn_fan2 else: dVbli_o_V = 0. fn_fan2 = 0. sec = 0 fn = (fn_core + fn_fan1) * (engine.n_engine - nei) + fn_fan2 data = (fn_core, fn_fan1, fn_fan2, dVbli_o_V, shaft_power2, fn0, shaft_power0) return (fn, sec, data)
def eval_bli_nacelle_design(this_nacelle, Pamb, Tamb, Mach, shaft_power, hub_width, body_length, body_width): """ BLI nacelle design """ gam = earth.heat_ratio() r = earth.gaz_constant() Cp = earth.heat_constant(gam, r) (rho, sig) = earth.air_density(Pamb, Tamb) Vsnd = earth.sound_speed(Tamb) Re = craft_aero.reynolds_number(Pamb, Tamb, Mach) Vair = Vsnd * Mach # Precalculation of the relation between d0 and d1 #----------------------------------------------------------------------------------------------------------- body_bnd_layer = eval_boundary_layer(body_width, hub_width) # Electrical nacelle geometry : e-nacelle diameter is size by cruise conditions #----------------------------------------------------------------------------------------------------------- r0 = 0.5 * body_width # Radius of the fuselage, supposed constant d0 = craft_aero.boundary_layer( Re, body_length ) # theoritical thickness of the boundary layer without taking account of fuselage tapering r1 = 0.5 * hub_width # Radius of the hub of the efan nacelle d1 = lin_interp_1d(d0, body_bnd_layer[:, 0], body_bnd_layer[:, 1]) # Thickness of the BL around the hub deltaV = 2. * Vair * ( this_nacelle.efficiency_fan / this_nacelle.efficiency_prop - 1. ) # speed variation produced by the fan PwInput = this_nacelle.efficiency_fan * shaft_power # kinetic energy produced by the fan #=========================================================================================================== def fct_power_1(y, PwInput, deltaV, rho, Vair, r1, d1): (q0, q1, q2, v1, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y) Vinlet = Vair - dVbli Vjet = Vinlet + deltaV Pw = 0.5 * q1 * (Vjet**2 - Vinlet**2) y = PwInput - Pw return y #----------------------------------------------------------------------------------------------------------- fct_arg = (PwInput, deltaV, rho, Vair, r1, d1) # Computation of y1 : thickness of the vein swallowed by the inlet output_dict = fsolve(fct_power_1, x0=d1, args=fct_arg, full_output=True) y1 = output_dict[0][0] (q0, q1, q2, v1, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y1) MachInlet = v1 / Vsnd # Mean Mach number at inlet position Ptot = earth.total_pressure( Pamb, MachInlet) # Stagnation pressure at inlet position Ttot = earth.total_temperature( Tamb, MachInlet) # Stagnation temperature at inlet position MachFan = 0.5 # required Mach number at fan position CQoA1 = craft_aero.corrected_air_flow( Ptot, Ttot, MachFan) # Corrected air flow per area at fan position eFanArea = q1 / CQoA1 # Fan area around the hub fan_width = math.sqrt(hub_width**2 + 4 * eFanArea / math.pi) # Fan diameter Vjet = v1 + deltaV # Jet velocity TtotJet = Ttot + shaft_power / ( q1 * Cp) # Stagnation pressure increases due to introduced work Tstat = TtotJet - 0.5 * Vjet**2 / Cp # static temperature VsndJet = math.sqrt(gam * r * Tstat) # Sound velocity at nozzle exhaust MachJet = Vjet / VsndJet # Mach number at nozzle output PtotJet = earth.total_pressure( Pamb, MachJet) # total pressure at nozzle exhaust (P = Pamb) CQoA2 = craft_aero.corrected_air_flow( PtotJet, TtotJet, MachJet) # Corrected air flow per area at nozzle output nozzle_area = q1 / CQoA2 # Fan area around the hub nozzle_width = math.sqrt(4 * nozzle_area / math.pi) # Nozzle diameter this_nacelle.hub_width = hub_width this_nacelle.fan_width = fan_width this_nacelle.nozzle_width = nozzle_width this_nacelle.nozzle_area = nozzle_area this_nacelle.width = 1.19 * fan_width # Surrounding structure this_nacelle.length = 1.68 * this_nacelle.width this_nacelle.net_wetted_area = math.pi * this_nacelle.width * this_nacelle.length # Nacelle wetted area this_nacelle.bnd_layer = body_bnd_layer this_nacelle.body_length = body_length return
def eval_hybrid_engine_design(aircraft): """ Thermal propulsive architecture design """ design_driver = aircraft.design_driver fuselage = aircraft.fuselage propulsion = aircraft.propulsion engine = aircraft.turbofan_engine nacelle = aircraft.turbofan_nacelle battery = aircraft.battery power_elec = aircraft.power_elec_chain e_engine = aircraft.electric_engine e_nacelle = aircraft.electric_nacelle low_speed = aircraft.low_speed (MTO, MCN, MCL, MCR, FID) = propulsion.rating_code # Propulsion architecture design #----------------------------------------------------------------------------------------------------------- # Initialisation crm = design_driver.cruise_mach toc = design_driver.top_of_climb_altp rca = design_driver.ref_cruise_altp roa = low_speed.req_oei_altp # MTO MCN MCL MCR FIR fd_disa = numpy.array([15., 0., 0., 0., 0.]) fd_altp = numpy.array([0., roa, toc, rca, rca]) fd_mach = numpy.array([0.25, crm / 2, crm, crm, crm]) fd_nei = numpy.array([0., 1., 0., 0., 0.]) e_engine.flight_data = { "disa": fd_disa, "altp": fd_altp, "mach": fd_mach, "nei": fd_nei } e_fan_power = numpy.array([ power_elec.mto, power_elec.mcn, power_elec.mcl, power_elec.mcr, power_elec.fid ]) # Battery power feed is used in temporary phases only battery_power_feed = numpy.array([1,0,1,0,0])*battery.power_feed \ *e_nacelle.controler_efficiency \ *e_nacelle.motor_efficiency e_power_ratio = numpy.zeros(5) e_shaft_power = numpy.zeros(5) for rating in propulsion.rating_code: (Pamb, Tamb, Tstd, dTodZ) = earth.atmosphere(fd_altp[rating], fd_disa[rating]) (fn, data) = propu.turbofan_thrust(aircraft, Pamb, Tamb, fd_mach[rating], rating, fd_nei[rating]) (fn_core, fn_fan0, fn0, shaft_power0) = data if e_fan_power[rating] > 1: # required eFan shaft power is given # Fraction of the turbofan shaft power dedicated to electric generation e_power_ratio[rating] = ( (e_fan_power[rating] - battery_power_feed[rating] \ )/ power_elec.overall_efficiency \ )/((shaft_power0)*(engine.n_engine-fd_nei[rating])) # e-fan shaft power e_shaft_power[rating] = e_fan_power[rating] else: # required turbofan shaft power ration is given # Shaft power dedicated to electric generator shaft_power2 = e_power_ratio[rating] * shaft_power0 * ( engine.n_engine - fd_nei[rating]) # Fraction of the shaft power dedicated to the electric generation e_power_ratio[rating] = e_fan_power[rating] e_shaft_power[rating] = shaft_power2*power_elec.overall_efficiency \ + battery_power_feed[rating] e_engine.mto_e_power_ratio = e_power_ratio[MTO] e_engine.mcn_e_power_ratio = e_power_ratio[MCN] e_engine.mcl_e_power_ratio = e_power_ratio[MCL] e_engine.mcr_e_power_ratio = e_power_ratio[MCR] e_engine.fid_e_power_ratio = e_power_ratio[FID] e_engine.mto_e_shaft_power = e_shaft_power[MTO] e_engine.mcn_e_shaft_power = e_shaft_power[MCN] e_engine.mcl_e_shaft_power = e_shaft_power[MCL] e_engine.mcr_e_shaft_power = e_shaft_power[MCR] e_engine.fid_e_shaft_power = e_shaft_power[FID] # Engine performance update #----------------------------------------------------------------------------------------------------------- (Pamb, Tamb, Tstd, dTodZ) = earth.atmosphere(fd_altp[MTO], fd_disa[MTO]) (fn, data) = propu.turbofan_thrust(aircraft, Pamb, Tamb, fd_mach[MTO], MTO, fd_nei[MTO]) (fn_core, fn_fan0, fn0, shaft_power0) = data shaft_power1 = (1 - e_power_ratio[MTO] ) * shaft_power0 # Shaft power dedicated to the fan Vsnd = earth.sound_speed(Tamb) Vair = Vsnd * fd_mach[MTO] fn_fan1 = nacelle.efficiency_prop * shaft_power1 / Vair # Effective fan thrust engine.kfn_off_take = ( fn_core + fn_fan1) / fn0 # Thrust reduction due to power off take for the e-fan return
def eval_hybrid_nacelle_design(aircraft): """ Hybrid propulsive architecture design """ design_driver = aircraft.design_driver fuselage = aircraft.fuselage wing = aircraft.wing propulsion = aircraft.propulsion engine = aircraft.turbofan_engine nacelle = aircraft.turbofan_nacelle e_engine = aircraft.electric_engine e_nacelle = aircraft.electric_nacelle (MTO, MCN, MCL, MCR, FID) = propulsion.rating_code # Turbofan nacelles geometry adjustment #----------------------------------------------------------------------------------------------------------- nacWidth0 = 0.49 * engine.bpr**0.67 + 4.8e-6 * engine.reference_thrust # Reference dimensions of the nacelle without power off take nacLength0 = 0.86 * nacWidth0 + engine.bpr**0.37 kSize = math.sqrt( engine.kfn_off_take) # Diameter decrease due to max thrust decrease kSize_eff = (kSize + engine.core_width_ratio * (1 - kSize) ) # Diameter decrease considering core is unchanged nacelle.width = nacWidth0 * kSize_eff # Real nacelle diameter assuming core section remains unchanged nacelle.length = nacLength0 * kSize_eff # Nacelle length is reduced according to the same factor knac = math.pi * nacelle.width * nacelle.length nacelle.net_wetted_area = knac * (1.48 - 0.0076 * knac) * engine.n_engine tan_phi0 = 0.25 * (wing.c_kink - wing.c_tip) / ( wing.y_tip - wing.y_kink) + numpy.tan(wing.sweep) if (nacelle.attachment == 1): nacelle.y_ext = 0.7 * fuselage.width + 1.4 * nacelle.width # statistical regression nacelle.x_ext = wing.x_root + ( nacelle.y_ext - wing.y_root) * tan_phi0 - 0.7 * nacelle.length nacelle.z_ext = - 0.5 * fuselage.height \ + (nacelle.y_ext - 0.5 * fuselage.width) * math.tan(wing.dihedral) \ - 0.5*nacelle.width elif (nacelle.attachment == 2): nacelle.y_ext = 0.5 * fuselage.width + 0.6 * nacelle.width # statistical regression nacelle.x_ext = wing.x_root + ( nacelle.y_ext - wing.y_root) * tan_phi0 - 0.7 * nacelle.length nacelle.z_ext = 0.5 * fuselage.height # Electric nacelle is design for cruise conditions #----------------------------------------------------------------------------------------------------------- dISA = 0. Altp = design_driver.ref_cruise_altp Mach = design_driver.cruise_mach (Pamb, Tamb, Tstd, dTodZ) = earth.atmosphere(Altp, dISA) shaft_power = e_engine.mcr_e_shaft_power hub_width = 0.5 # Diameter of the e fan hub body_length = fuselage.length body_width = fuselage.width eval_bli_nacelle_design(e_nacelle, Pamb, Tamb, Mach, shaft_power, hub_width, body_length, body_width) e_nacelle.x_ext = fuselage.length + 0.2 * e_nacelle.width e_nacelle.y_ext = 0 e_nacelle.z_ext = 0.91 * fuselage.height - 0.51 * fuselage.height # Engine performance update #----------------------------------------------------------------------------------------------------------- fd = e_engine.flight_data e_fan_thrust = numpy.zeros(5) for rating in propulsion.rating_code: altp = fd.get("altp")[rating] disa = fd.get("disa")[rating] mach = fd.get("mach")[rating] nei = fd.get("nei")[rating] (Pamb, Tamb, Tstd, dTodZ) = earth.atmosphere(altp, disa) (fn, sec, data) = propu.hybrid_thrust(aircraft, Pamb, Tamb, mach, rating, nei) (fn_core, fn_fan1, fn_fan2, dVbli_o_V, shaft_power2, fn0, shaft_power0) = data e_fan_thrust[rating] = fn_fan2 e_engine.mto_e_fan_thrust = e_fan_thrust[MTO] e_engine.mcn_e_fan_thrust = e_fan_thrust[MCN] e_engine.mcl_e_fan_thrust = e_fan_thrust[MCL] e_engine.mcr_e_fan_thrust = e_fan_thrust[MCR] e_engine.fid_e_fan_thrust = e_fan_thrust[FID] Vair = Mach * earth.sound_speed(Tamb) (eFanFnBli, q1, dVbli) = propu.fan_thrust_with_bli(e_nacelle, Pamb, Tamb, Mach, Vair, shaft_power) (eFanFn, q0) = propu.fan_thrust(e_nacelle, Pamb, Tamb, Mach, Vair, shaft_power) propulsion.bli_e_thrust_factor = eFanFnBli / eFanFn # Thrust increase due to BLI at iso shaft power propulsion.bli_thrust_factor = 1 # Thrust increase due to BLI at iso shaft power return
def fan_thrust(nacelle, Pamb, Tamb, Mach, Vair, PwShaft): """ Compute the thrust of a fan of given geometry swallowing the boundary layer (BL) of a body of given geometry The amount of swallowed BL depends on the given shaft power and flying conditions """ bnd_layer = nacelle.bnd_layer Re = craft_aero.reynolds_number(Pamb, Tamb, Mach) (rho, sig) = earth.air_density(Pamb, Tamb) Vsnd = earth.sound_speed(Tamb) d0 = craft_aero.boundary_layer( Re, nacelle.body_length ) #Theoritical thickness of the boundary layer without taking account of fuselage tapering d1 = lin_interp_1d(d0, bnd_layer[:, 0], bnd_layer[:, 1]) # Using the precomputed relation r1 = 0.5 * nacelle.hub_width # Radius of the hub of the eFan nacelle PwInput = nacelle.efficiency_fan * PwShaft #=========================================================================================================== def fct_power(q, PwInput, Vair, Vsnd, eNozzleArea): Vinlet = Vair MachInlet = Vinlet / Vsnd # Mean Mach number at inlet position Ptot = earth.total_pressure( Pamb, MachInlet) #total pressure at inlet position Ttot = earth.total_temperature( Tamb, MachInlet) # Total temperature at inlet position Vjet = math.sqrt(2. * PwInput / q + Vinlet**2) MachJet = Vjet / Vsnd CQoA1 = craft_aero.corrected_air_flow( Ptot, Ttot, MachJet) # Corrected air flow per area at fan position q0 = CQoA1 * eNozzleArea y = q - q0 return y #----------------------------------------------------------------------------------------------------------- eNozzleArea = nacelle.nozzle_area fct_arg = (PwInput, Vair, Vsnd, eNozzleArea) (q0init, q1, q2, V1, dV) = craft_aero.air_flows(rho, Vair, r1, d1, 1.00) # Computation of y1 : thikness of the vein swallowed by the inlet output_dict = fsolve(fct_power, x0=q0init, args=fct_arg, full_output=True) q0 = output_dict[0][0] Vinlet = Vair Vjet = math.sqrt(2. * PwInput / q0 + Vinlet**2) eFn = q0 * (Vjet - Vinlet) return (eFn, q0)
def fan_thrust_with_bli(nacelle, Pamb, Tamb, Mach, Vair, PwShaft): """ Compute the thrust of a fan of a given geometry swallowing the boundary layer (BL) of a body of a given geometry The amount of swallowed BL depends on the given shaft power and flying conditions. """ bnd_layer = nacelle.bnd_layer gam = earth.heat_ratio() r = earth.gaz_constant() Cp = earth.heat_constant(gam, r) Re = craft_aero.reynolds_number(Pamb, Tamb, Mach) (rho, sig) = earth.air_density(Pamb, Tamb) Vsnd = earth.sound_speed(Tamb) d0 = craft_aero.boundary_layer( Re, nacelle.body_length ) # theorical thickness of the boundary layer without taking account of fuselage tapering r1 = 0.5 * nacelle.hub_width # Radius of the hub of the eFan nacelle d1 = lin_interp_1d(d0, bnd_layer[:, 0], bnd_layer[:, 1]) # Using the precomputed relation #=========================================================================================================== def fct_power_bli(y, PwShaft, Tamb, Pamb, rho, Mach, Vair, Vsnd, r1, d1, nozzle_area): Ttot = earth.total_temperature( Tamb, Mach) # Stagnation temperature at inlet position (q0, q1, q2, Vinlet, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y) Tstat = Ttot - 0.5 * Vinlet**2 / Cp # Static temperature at inlet position Vsnd_inlet = earth.sound_speed(Tstat) # Sound speed at inlet position MachInlet = Vinlet / Vsnd_inlet # Mean Mach number at inlet position PwInput = nacelle.efficiency_fan * PwShaft Vjet = math.sqrt(2. * PwInput / q1 + Vinlet**2) TtotJet = Ttot + PwShaft / ( q1 * Cp) # Stagnation temperature increases due to introduced work Tstat = TtotJet - 0.5 * Vjet**2 / Cp # Static temperature VsndJet = earth.sound_speed(Tstat) # Sound speed at nozzle exhaust MachJet = Vjet / VsndJet # Mach number at nozzle output PtotJet = earth.total_pressure( Pamb, MachJet) # total pressure at nozzle exhaust (P = Pamb) CQoA1 = craft_aero.corrected_air_flow( PtotJet, TtotJet, MachJet) # Corrected air flow per area at fan position q = CQoA1 * nozzle_area y = q1 - q return y #----------------------------------------------------------------------------------------------------------- nozzle_area = nacelle.nozzle_area fct_arg = (PwShaft, Tamb, Pamb, rho, Mach, Vair, Vsnd, r1, d1, nozzle_area) # Computation of y1 : thikness of the vein swallowed by the inlet output_dict = fsolve(fct_power_bli, x0=0.50, args=fct_arg, full_output=True) y = output_dict[0][0] Ttot = earth.total_temperature( Tamb, Mach) # Stagnation temperature at inlet position (q0, q1, q2, Vinlet, dVbli) = craft_aero.air_flows(rho, Vair, r1, d1, y) Tstat = Ttot - 0.5 * Vinlet**2 / Cp # Static temperature at inlet position Vsnd_inlet = earth.sound_speed(Tstat) # Sound speed at inlet position MachInlet = Vinlet / Vsnd_inlet # Mean Mach number at inlet position PwInput = nacelle.efficiency_fan * PwShaft Vjet = math.sqrt(2. * PwInput / q1 + Vinlet**2) eFn = q1 * (Vjet - Vinlet) return (eFn, q1, dVbli)
def eval_hybrid_body_nacelle_design(aircraft): """ Hybrid propulsive architecture design """ design_driver = aircraft.design_driver fuselage = aircraft.fuselage wing = aircraft.wing propulsion = aircraft.propulsion engine = aircraft.turbofan_engine nacelle = aircraft.turbofan_nacelle body = aircraft.body_nacelle e_engine = aircraft.electric_engine e_nacelle = aircraft.electric_nacelle (MTO, MCN, MCL, MCR, FID) = propulsion.rating_code #----------------------------------------------------------------------------------------------------------- tan_phi0 = 0.25 * (wing.c_kink - wing.c_tip) / ( wing.y_tip - wing.y_kink) + numpy.tan(wing.sweep) body.y_ext = 0.8 * fuselage.width + 1.5 * nacelle.width # statistical regression body.x_ext = wing.x_root + (nacelle.y_ext - wing.y_root) * tan_phi0 - 0.5 * body.length body.z_ext = - 0.5 * fuselage.height \ + (nacelle.y_ext - 0.5 * fuselage.width) * math.tan(wing.dihedral) \ - 0.5*nacelle.width body.net_wetted_area = 2.7 * body.length * body.width * engine.n_engine # All bodies wetted area # Turbofan nacelles geometry is designed according to cruise conditions #----------------------------------------------------------------------------------------------------------- dISA = 0. Altp = design_driver.ref_cruise_altp Mach = design_driver.cruise_mach nei = 0 (Pamb, Tamb, Tstd, dTodZ) = earth.atmosphere(Altp, dISA) fn, data = propu.turbofan_thrust(aircraft, Pamb, Tamb, Mach, MCR, nei) (fn_core, fn_fan0, fn0, shaft_power0) = data shaft_power1 = (1 - e_engine.mcr_e_power_ratio ) * shaft_power0 # Shaft power dedicated to the fan body_hub_width = body.hub_width # Diameter of the fan hub body_length = body.length body_width = body.width eval_bli_nacelle_design(nacelle, Pamb, Tamb, Mach, shaft_power1, body_hub_width, body_length, body_width) nacelle.y_ext = body.y_ext nacelle.x_ext = body.x_ext + body.length nacelle.z_ext = body.z_ext # Electric nacelle is design for cruise conditions #----------------------------------------------------------------------------------------------------------- dISA = 0. Altp = design_driver.ref_cruise_altp Mach = design_driver.cruise_mach (Pamb, Tamb, Tstd, dTodZ) = earth.atmosphere(Altp, dISA) shaft_power = e_engine.mcr_e_shaft_power efan_hub_width = 0.5 # Diameter of the e fan hub body_length = fuselage.length body_width = fuselage.width eval_bli_nacelle_design(e_nacelle, Pamb, Tamb, Mach, shaft_power, efan_hub_width, body_length, body_width) e_nacelle.x_ext = fuselage.length + 0.2 * e_nacelle.width e_nacelle.y_ext = 0 e_nacelle.z_ext = 0.91 * fuselage.height - 0.51 * fuselage.height # Engine performance update #----------------------------------------------------------------------------------------------------------- fd = e_engine.flight_data e_fan_thrust = numpy.zeros(5) for rating in propulsion.rating_code: altp = fd.get("altp")[rating] disa = fd.get("disa")[rating] mach = fd.get("mach")[rating] nei = fd.get("nei")[rating] (Pamb, Tamb, Tstd, dTodZ) = earth.atmosphere(altp, disa) (fn, sec, data) = propu.hybrid_thrust(aircraft, Pamb, Tamb, mach, rating, nei) (fn_core, fn_fan1, fn_fan2, dVbli_o_V, shaft_power2, fn0, shaft_power0) = data e_fan_thrust[rating] = fn_fan2 e_engine.mto_e_fan_thrust = e_fan_thrust[MTO] e_engine.mcn_e_fan_thrust = e_fan_thrust[MCN] e_engine.mcl_e_fan_thrust = e_fan_thrust[MCL] e_engine.mcr_e_fan_thrust = e_fan_thrust[MCR] e_engine.fid_e_fan_thrust = e_fan_thrust[FID] Vair = Mach * earth.sound_speed(Tamb) (eFanFnBli, q1, dVbli) = propu.fan_thrust_with_bli(e_nacelle, Pamb, Tamb, Mach, Vair, shaft_power) (eFanFn, q0) = propu.fan_thrust(e_nacelle, Pamb, Tamb, Mach, Vair, shaft_power) propulsion.bli_e_thrust_factor = eFanFnBli / eFanFn # Thrust increase due to BLI at iso shaft power (FanFnBli, q1, dVbli) = propu.fan_thrust_with_bli(nacelle, Pamb, Tamb, Mach, Vair, shaft_power) (FanFn, q0) = propu.fan_thrust(nacelle, Pamb, Tamb, Mach, Vair, shaft_power) propulsion.bli_thrust_factor = FanFnBli / FanFn # Thrust increase due to BLI at iso shaft power return
def mission(aircraft, dist_range, tow, altp, mach, disa): """ Mission computation using breguet equation, fixed L/D and fixed sfc """ engine = aircraft.turbofan_engine propulsion = aircraft.propulsion battery = aircraft.battery (MTO, MCN, MCL, MCR, FID) = propulsion.rating_code g = earth.gravity() pamb, tamb, tstd, dtodz = earth.atmosphere(altp, disa) vsnd = earth.sound_speed(tamb) tas = vsnd * mach lod_max, cz_lod_max = craft_aero.lod_max(aircraft, pamb, tamb, mach) lod_cruise = 0.95 * lod_max nei = 0. sfc = propu.sfc(aircraft, pamb, tamb, mach, MCR, nei) if (propulsion.architecture == 2): fn, sec, data = propu.hybrid_thrust(aircraft, pamb, tamb, mach, MCR, nei) if (propulsion.architecture == 3): fn, sec, data = propu.hybrid_thrust(aircraft, pamb, tamb, mach, MCR, nei) # Departure ground phases #----------------------------------------------------------------------------------------------------------- fuel_taxi_out = (34 + 2.3e-4 * engine.reference_thrust) * engine.n_engine time_taxi_out = 540 fuel_take_off = 1e-4 * (2.8 + 2.3 / engine.bpr) * tow time_take_off = 220 * tow / (engine.reference_thrust * engine.n_engine) # Mission leg #----------------------------------------------------------------------------------------------------------- if (propulsion.architecture == 1): fuel_mission = tow * (1 - numpy.exp(-(sfc * g * dist_range) / (tas * lod_cruise))) elif (propulsion.architecture == 2): fuel_mission = tow*(1-numpy.exp(-(sfc*g*dist_range)/(tas*lod_cruise))) \ - (sfc/sec)*battery.energy_cruise elif (propulsion.architecture == 3): fuel_mission = tow*(1-numpy.exp(-(sfc*g*dist_range)/(tas*lod_cruise))) \ - (sfc/sec)*battery.energy_cruise elif (propulsion.architecture == 4): fuel_mission = tow * (1 - numpy.exp(-(sfc * g * dist_range) / (tas * lod_cruise))) else: raise Exception("propulsion.architecture index is out of range") time_mission = 1.09 * (dist_range / tas) l_w = tow - fuel_mission # Arrival ground phases #----------------------------------------------------------------------------------------------------------- fuel_landing = 1e-4 * (0.5 + 2.3 / engine.bpr) * l_w time_landing = 180 fuel_taxi_in = (26 + 1.8e-4 * engine.reference_thrust) * engine.n_engine time_taxi_in = 420 # Block fuel and time #----------------------------------------------------------------------------------------------------------- block_fuel = fuel_taxi_out + fuel_take_off + fuel_mission + fuel_landing + fuel_taxi_in time_block = time_taxi_out + time_take_off + time_mission + time_landing + time_taxi_in # Diversion and holding reserve fuel #----------------------------------------------------------------------------------------------------------- fuel_diversion = l_w * (1 - numpy.exp(-(sfc * g * regul.diversion_range()) / (tas * lod_cruise))) fuel_holding = sfc * (l_w * g / lod_max) * regul.holding_time() # Total #----------------------------------------------------------------------------------------------------------- fuel_total = fuel_mission * ( 1 + regul.reserve_fuel_ratio()) + fuel_diversion + fuel_holding #----------------------------------------------------------------------------------------------------------- return block_fuel, time_block, fuel_total