def sound_speed_grad(tamb, tamb_d): """ Sound speed for ideal gaz """ R = earth.gaz_constant() gam = earth.heat_ratio() vsnd = numpy.sqrt(gam * R * tamb) vsnd_d = 0.5 * numpy.sqrt(gam * R / tamb) * tamb_d return vsnd, vsnd_d
def air_density_grad(pamb, pamb_d, tamb, tamb_d): """ Ideal gaz density """ R = earth.gaz_constant() rho0 = earth.sea_level_density() rho = pamb / (R * tamb) rho_d = pamb_d / (R * tamb) - tamb_d * pamb / (R * tamb**2) sig = rho / rho0 sig_d = rho_d / rho0 return rho, rho_d, sig, sig_d
def corrected_air_flow(Ptot, Ttot, Mach): """ Computes the corrected air flow per square meter """ R = earth.gaz_constant() gam = earth.heat_ratio() f_M = Mach * (1. + 0.5 * (gam - 1) * Mach**2)**(-(gam + 1.) / (2. * (gam - 1.))) CQoA = (numpy.sqrt(gam / R) * Ptot / numpy.sqrt(Ttot)) * f_M return CQoA
def pressure_altitude_grad(pamb, pamb_d): """ Pressure altitude from ground to 50 km """ g = earth.gravity() R = earth.gaz_constant() Z = numpy.array([0., 10999., 19999., 31999., 46999., 49999.]) dtodz = numpy.array([-0.0065, 0., 0.0010, 0.0028, 0.]) P = numpy.array([earth.sea_level_pressure(), 0., 0., 0., 0., 0.]) T = numpy.array([earth.sea_level_temperature(), 0., 0., 0., 0., 0.]) j = 0 n = len(P) - 1 P[1] = P[0] * (1 + (dtodz[0] / T[0]) * (Z[1] - Z[0]))**(-g / (R * dtodz[0])) T[1] = T[0] + dtodz[0] * (Z[1] - Z[0]) while (j < n and pamb < P[j + 1]): j = j + 1 T[j + 1] = T[j] + dtodz[j] * (Z[j + 1] - Z[j]) if (0. < numpy.abs(dtodz[j])): P[j + 1] = P[j] * (1 + (dtodz[j] / T[j]) * (Z[j + 1] - Z[j]))**(-g / (R * dtodz[j])) else: P[j + 1] = P[j] * numpy.exp(-(g / R) * ((Z[j + 1] - Z[j]) / T[j])) if (pamb < P[n]): raise Exception("pressure_altitude_grad, altitude cannot exceed 50km") if (0. < numpy.abs(dtodz[j])): altp = Z[j] + ( (pamb / P[j])**(-(R * dtodz[j]) / g) - 1) * (T[j] / dtodz[j]) altp_d = (T[j] / dtodz[j]) * (-(R * dtodz[j]) / (g * P[j])) * pamb_d * (pamb / P[j])**( -(R * dtodz[j]) / g - 1) else: altp = Z[j] - (T[j] / (g / R)) * numpy.log(pamb / P[j]) altp_d = -((T[j] * R) / g) * (pamb_d / pamb) return altp, altp_d
def atmosphere_grad(altp, altp_d, disa, disa_d): """ Pressure from pressure altitude from ground to 50 km """ g = earth.gravity() R = earth.gaz_constant() Z = numpy.array([0., 10999., 19999., 31999., 46999., 49999.]) Z_d = numpy.array([0., 0., 0., 0., 0., 0.]) dtodz = numpy.array([-0.0065, 0., 0.0010, 0.0028, 0.]) dtodz_d = numpy.array([0., 0., 0., 0., 0.]) P = numpy.array([earth.sea_level_pressure(), 0., 0., 0., 0., 0.]) P_d = numpy.array([0., 0., 0., 0., 0., 0.]) T = numpy.array([earth.sea_level_temperature(), 0., 0., 0., 0., 0.]) T_d = numpy.array([0., 0., 0., 0., 0., 0.]) if (Z[-1] < altp): raise Exception("atmosphere_grad, altitude cannot exceed 50km") j = 0 while (Z[1 + j] <= altp): T[j + 1] = T[j] + dtodz[j] * (Z[j + 1] - Z[j]) T_d[j + 1] = T_d[j] + dtodz_d[j] * (Z[j + 1] - Z[j]) + dtodz[j] * ( Z_d[j + 1] - Z_d[j]) if (0. < numpy.abs(dtodz[j])): B1 = 1 + (dtodz[j] * (Z[1 + j] - Z[j])) / (T[j] + disa) B1_dz = (dtodz[j] * (Z_d[1 + j] - Z_d[j])) / (T[j] + disa) B1_dt = (dtodz_d[j] * (Z[1 + j] - Z[j])) / (T[j] + disa) - ( dtodz[j] * (Z[1 + j] - Z[j]) * disa_d) / (T[j] + disa)**2 B2 = -g / (R * dtodz[j]) B2_dt = (g * dtodz_d[j]) / (R * dtodz[j]**2) P[1 + j] = P[j] * B1**B2 P_d[1 + j] = P[j] * ( B2 * B1_dz * B1**(B2 - 1) + (B1**B2) * (B2_dt * numpy.log(B1) + B2 * B1_dt / B1)) + P_d[j] * B1**B2 else: B3 = -(g / R) * ((Z[1 + j] - Z[j]) / (T[j] + disa)) B3_d = -(g / R) * ((Z_d[1 + j] - Z_d[j]) / (T[j] + disa)) + (g / R) * ((Z[1 + j] - Z[j]) * (T_d[j] + disa_d) / (T[j] + disa)**2) P[j + 1] = P[j] * numpy.exp(B3) P_d[j + 1] = P_d[j] * numpy.exp(B3) + P[j] * B3_d * numpy.exp(B3) j = j + 1 if (0. < numpy.abs(dtodz[j])): B1 = 1 + (dtodz[j] * (altp - Z[j])) / (T[j] + disa) B1_dz = (dtodz[j] * (altp_d - Z_d[j])) / (T[j] + disa) B1_dt = (dtodz_d[j] * (altp - Z[j])) / (T[j] + disa) - (dtodz[j] * (altp - Z[j]) * disa_d) / (T[j] + disa)**2 B2 = -g / (R * dtodz[j]) B2_dt = (g * dtodz_d[j]) / (R * dtodz[j]**2) pamb = P[j] * B1**B2 pamb_d = P[j] * ( B2 * B1_dz * B1**(B2 - 1) + (B1**B2) * (B2_dt * numpy.log(B1) + B2 * B1_dt / B1)) + P_d[j] * B1**B2 else: B3 = -(g / R) * ((altp - Z[j]) / (T[j] + disa)) B3_d = -(g / R) * ((altp_d - Z_d[j]) / (T[j] + disa)) + (g / R) * ((altp - Z[j]) * (T_d[j] + disa_d) / (T[j] + disa)**2) pamb = P[j] * numpy.exp(B3) pamb_d = P_d[j] * numpy.exp(B3) + P[j] * B3_d * numpy.exp(B3) tamb = T[j] + dtodz[j] * (altp - Z[j]) + disa tamb_d = T_d[j] + dtodz_d[j] * (altp - Z[j]) + dtodz[j] * (altp_d - Z_d[j]) + disa_d return pamb, pamb_d, tamb, tamb_d, dtodz[j]
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 = earth.reynolds_number(Pamb,Tamb,Mach) Vair = Vsnd*Mach # Precalculation of the relation between d0 and d1 #----------------------------------------------------------------------------------------------------------- body_bnd_layer = resize_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 = jet.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) = jet.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) = jet.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 = jet.corrected_air_flow(Ptot,Ttot,MachFan) # Corrected air flow per area at fan position eFanArea = q1/CQoA1 # Fan area around the hub fan_width = numpy.sqrt(hub_width**2 + 4*eFanArea/numpy.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 = numpy.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 = jet.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 = numpy.sqrt(4*nozzle_area/numpy.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.20*fan_width # Surrounding structure this_nacelle.length = 1.50*this_nacelle.width this_nacelle.net_wetted_area = numpy.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 fan_thrust(nacelle, Pamb, Tamb, Mach, PwShaft): """ Compute the thrust of a fan of given geometry swallowing free air stream """ gam = earth.heat_ratio() r = earth.gaz_constant() Cp = earth.heat_constant(gam, r) #=========================================================================================================== def fct_power(q, PwShaft, Pamb, Ttot, Vair, NozzleArea): Vinlet = Vair PwInput = nacelle.efficiency_fan * PwShaft Vjet = numpy.sqrt(2. * PwInput / q + Vinlet**2) # Supposing isentropic compression TtotJet = Ttot + PwShaft / ( q * Cp) # Stagnation temperature increases due to introduced work TstatJet = TtotJet - 0.5 * Vjet**2 / Cp # Static temperature VsndJet = earth.sound_speed(TstatJet) # 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 = corrected_air_flow( PtotJet, TtotJet, MachJet) # Corrected air flow per area at fan position q0 = CQoA1 * NozzleArea y = q0 - q return y #----------------------------------------------------------------------------------------------------------- NozzleArea = nacelle.nozzle_area FanWidth = nacelle.fan_width Ptot = earth.total_pressure(Pamb, Mach) # Total pressure at inlet position Ttot = earth.total_temperature(Tamb, Mach) # Total temperature at inlet position Vsnd = earth.sound_speed(Tamb) Vair = Vsnd * Mach fct_arg = (PwShaft, Pamb, Ttot, Vair, NozzleArea) CQoA0 = corrected_air_flow( Ptot, Ttot, Mach) # Corrected air flow per area at fan position q0init = CQoA0 * (0.25 * numpy.pi * FanWidth**2) # Computation of the air flow swallowed by the inlet output_dict = fsolve(fct_power, x0=q0init, args=fct_arg, full_output=True) q0 = output_dict[0][0] if (output_dict[2] != 1): raise Exception("Convergence problem") Vinlet = Vair PwInput = nacelle.efficiency_fan * PwShaft Vjet = numpy.sqrt(2. * PwInput / q0 + Vinlet**2) eFn = q0 * (Vjet - Vinlet) return (eFn, q0)
def fan_thrust_with_bli(nacelle, Pamb, Tamb, Mach, 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. """ gam = earth.heat_ratio() r = earth.gaz_constant() Cp = earth.heat_constant(gam, r) #=========================================================================================================== def fct_power_bli(y, PwShaft, Pamb, rho, Ttot, Vair, r1, d1, nozzle_area): (q0, q1, q2, Vinlet, dVbli) = air_flows(rho, Vair, r1, d1, y) PwInput = nacelle.efficiency_fan * PwShaft Vjet = numpy.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) supposing adapted nozzle CQoA1 = corrected_air_flow( PtotJet, TtotJet, MachJet) # Corrected air flow per area at nozzle position q = CQoA1 * nozzle_area y = q1 - q return y #----------------------------------------------------------------------------------------------------------- nozzle_area = nacelle.nozzle_area bnd_layer = nacelle.bnd_layer Re = earth.reynolds_number(Pamb, Tamb, Mach) d0 = 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 Ttot = earth.total_temperature( Tamb, Mach) # Stagnation temperature at inlet position rho, sig = earth.air_density(Pamb, Tamb) Vsnd = earth.sound_speed(Tamb) Vair = Vsnd * Mach fct_arg = (PwShaft, Pamb, rho, Ttot, Vair, 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] if (output_dict[2] != 1): raise Exception("Convergence problem") (q0, q1, q2, Vinlet, dVbli) = air_flows(rho, Vair, r1, d1, y) PwInput = nacelle.efficiency_fan * PwShaft Vjet = numpy.sqrt(2. * PwInput / q1 + Vinlet**2) eFn = q1 * (Vjet - Vinlet) return (eFn, q1, dVbli)