def set_NPR(self, NPR): """ Define Nozzle Pressure Ratio (inlet Ptot over outlet Ps) for this case Define Nozzle pressure ratio and compute Mach number, Ptot and Ps according to nozzle regime :param NPR: NPR value (>1) """ self._Pt = np.ones_like(self.AxoAc) if NPR < self.NPR0: _Ms = Is.Mach_PtPs(NPR, gamma=self.gamma) self._M = mf.MachSub_Sigma(self.AxoAc / self.AsoAc * mf.Sigma_Mach(_Ms), gamma=self.gamma) self._Ps = self._Pt / Is.PtPs_Mach(self._M, gamma=self.gamma) else: self._M = np.ones_like(self.AxoAc) self._M[:self.ithroat + 1] = mf.MachSub_Sigma( self.AxoAc[:self.ithroat + 1], gamma=self.gamma) self._M[self.ithroat + 1:] = mf.MachSup_Sigma( self.AxoAc[self.ithroat + 1:], gamma=self.gamma) if NPR < self.NPRsw: # analytical solution for Ms, losses and upstream Mach number of shock wave Ms = Ms_from_AsAc_NPR(self.AsoAc, NPR) Ptloss = Is.PtPs_Mach(Ms) / NPR Msh = sw.Mn_Pi_ratio(Ptloss) # redefine curves starting from 'ish' index (closest value of Msh in supersonic flow) ish = np.abs(self._M - Msh).argmin() self._M[ish:] = mf.MachSub_Sigma( self.AxoAc[ish:] * mf.Sigma_Mach(Ms) / self.AsoAc) self._Pt[ish:] = Ptloss self._Ps = self._Pt / Is.PtPs_Mach(self._M)
def Madapt_from_AsAc_NPR(AsAc, NPR): """ Computes Mach number for pressure adapted flow of a nozzle given As/Ac and NPR This method checks the NPR to define regime and computes Mach number in jet. The switch between overexpanded jet and underexpanded jet is :param AsAc: ratio of section at exit over throat :param NPR: ratio of total pressure at inlet over 'expected' static pressure at exit :return: result Mach number at exit :Example: >>> print round(Ms_from_AsAc_NPR(2.636, 1.5), 8) # case with shock in diffuser 0.32586574 .. seealso:: .. note:: NOT available for array (numpy) computations """ NPR0, NPRsw, NPR1, Msub, Msh, Msup = _NPR_Ms_list(AsAc) if (NPR < NPR0): Ms = Is.Mach_PtPs(NPR) elif (NPR > NPR1): # under expanded flow Ms = Is.Mach_PtPs(NPR) elif (NPR > NPRsw): # shock wave in jet Ms = sw.downstreamMach_Mach_ShockPsratio(Msup, NPR1 / NPR) else: gmu = defg._gamma - 1. K = NPR / AsAc / ((defg._gamma + 1.) / 2)**( (defg._gamma + 1.) / 2 / gmu) Ms = np.sqrt((np.sqrt(1. + 2. * gmu * K * K) - 1.) / gmu) return Ms
def stage_19(self): if self.current_stage_fan == 13: self.Pt19 = self.Pt13 * self.xi_tuy self.Tt19 = self.Tt13 self.P19 = self.P0 self.M19 = Is.Mach_PtPs(self.Pt19 / self.P19, self.g.gamma) self.V19 = Is.Velocity_MachTi(self.M19, self.Tt19, self.g.r, self.g.gamma) self.F_f = self.m_f * (self.V19 - self.V0) self.current_stage_fan = 19
def update(self): gg.base.update(self) gh = self.gam_hot cph = gh * self.r_hot / (gh - 1.) self.Pt9 = np.maximum(self.Pt45 * self.xi_nozzle, self.P0) self.M9 = Is.Mach_PtPs(self.Pt9 / self.P0, gamma=self.gam_hot) self.V9 = Is.Velocity_MachTi(self.M9, self.Tt45, r=self.r_hot, gamma=self.gam_hot)
def stage_9(self): if self.current_stage_corps == 5: self.Tt9 = self.Tt5 self.Pt9 = self.Pt5 * self.xi_tuy self.P9 = self.P0 self.M9 = Is.Mach_PtPs(self.Pt9 / self.P9, self.g_fuel.gamma) self.V9 = Is.Velocity_MachTi(self.M9, self.Tt9, self.g_fuel.r, self.g_fuel.gamma) self.F_c = self.m_c * (self.V9 - self.V0) self.current_stage_corps = 9
def compute_from_pt_rtt_p(self, pt, rtt, p): """Init state from Ptot r.Ttot and Ps (velocity sign is arbitrary and positive) Args: pt ([float]): [description] rtt ([float]): [description] p ([float]): [description] """ M = Is.Mach_PtPs(pt / p, self._gamma) rts = rtt / Is.TtTs_Mach(M, self._gamma) self.__init__(rho=p / rts, u=M * np.sqrt(self._gamma * rts), p=p)
def Pt_ratio(Mn, gamma=defg._gamma): """Total pressure ration through shock wave Args: Mn: upstream relative normal Mach number to param gamma: (Default value = defg._gamma) Returns: """ return Ps_ratio(Mn, gamma) * Is.PtPs_Mach(downstream_Mn( Mn, gamma)) / Is.PtPs_Mach(Mn, gamma)
def update(self): gc = self.gam_cold cpc = gc*self.r_cold/(gc-1.) self.Tt0 = self.T0*Is.TtTs_Mach(self.M0, gamma=self.gam_cold) self.Pt0 = self.P0*Is.PtPs_Mach(self.M0, gamma=self.gam_cold) self.V0 = self.M0*np.sqrt(gc*self.r_cold*self.T0) self.Pt2 = self.Pt0*self.xi_inlet self.Tt2 = self.Tt0 self.Pt3 = self.Pt2*self.OPR self.Tt3 = self.Tt2*self.OPR**((gc-1.)/(gc*self.etapolCHP)) #self.Tt4 = Ti_4 self.Pt4 = self.Pt3*self.xi_cc gh = self.gam_hot cph = gh*self.r_hot/(gh-1.) self.far = (cph*self.Tt4 - cpc*self.Tt3)/(self.xi_cc*self.Pci - cph*self.Tt4) self.Tt45 = self.Tt4 - cpc*(self.Tt3-self.Tt2)/(self.eta_shaft*cph*(1.+self.far)) #print self.Tt3, self.Pt4, self.Tt45, self.Tt4, self.far self.Pt45 = self.Pt4*(self.Tt45/self.Tt4)**(gh/((gh-1.)*self.etapolTHP))
def primdata(self): """ computes list of rho, u, p data """ p = self._scale_ps * self._Ps rt = self._ref_rttot / Is.TiTs_Mach(self._M, gamma=self._gam) rho = p / rt u = self._M * np.sqrt(self._gam * rt) return [rho, u, p]
def NPR_choked_supersonic(AsAc): """Compute Nozzle Pressure Ratio to get a choked supersonic regime in a nozzle with As/Ac diffuser Args: AsAc ([real]): ratio of exit over throat surfaces Returns: [real]: Nozzle Pressure ratio (inlet total pressure over exit static pressure) """ return Is.PtPs_Mach(mf.MachSup_Sigma(AsAc))
def NPR_shock_at_exit(AsAc): """Compute Nozzle Pressure Ratio to get a choked, supersonic regime but shock at exit in a nozzle with As/Ac diffuser Args: AsAc ([real]): ratio of exit over throat surfaces Returns: [real]: Nozzle Pressure ratio (inlet total pressure over exit static pressure) """ Msup = mf.MachSup_Sigma(AsAc) Msh = sw.downstream_Mn(Msup) return Is.PtPs_Mach(Msh) / sw.Pi_ratio(Msup)
def update(self): tj.turbojet_opt.update(self) gh = self.gam_hot cph = gh*self.r_hot/(gh-1.) Wsp_mono = (1.-(self.Pt45/self.P0*self.xi_nozzle)**(-(gh-1.)*self.etapolTBP/gh))*self.Tt45*cph*(1.+self.far) self.Tt5 = self.Tt45 - Wsp_mono*self.fanpower_ratio/cph/(1.+self.far) self.Pt5 = self.Pt45*(self.Tt5/self.Tt45)**(gh/((gh-1.)*self.etapolTBP)) # core nozzle self.Pt9 = self.Pt5 * self.xi_nozzle self.M9 = Is.Mach_PtPs(self.Pt9/self.P0, gamma=self.gam_hot) self.V9 = Is.Velocity_MachTi(self.M9, self.Tt5, r=self.r_hot, gamma=self.gam_hot) # fan gc = self.gam_cold cpc = gc*self.r_cold/(gc-1.) #print self.bpr, cpc self.Tt17 = self.Tt2 + self.eta_shaft*Wsp_mono*self.fanpower_ratio/(self.bpr*cpc) self.Pt17 = self.Pt2*(self.Tt17/self.Tt2)**((gc*self.etapolfan)/(gc-1.)) # bypass nozzle self.Tt19 = self.Tt17 self.Pt19 = self.Pt17*self.xi_nozzle self.M19 = Is.Mach_PtPs(self.Pt19/self.P0, gamma=gc) self.V19 = Is.Velocity_MachTi(self.M19, self.Tt19, r=self.r_cold, gamma=gc)
def set_NPR(NPR): if NPR < NPR0: _Ms = Is.Mach_PiPs(NPR, gamma=self.model.gamma) self._M = mf.MachSub_Sigma(self.AsoAc * mf.Sigma_Mach(Ma_col) / self.AsoAc[-1], gamma=self.model.gamma) self._Pt = 0. * coord_x + 1. self._Ps = _Pt / Is.PiPs_Mach(self._M, gamma=self.model.gamma) elif NPR < NPRsw: _M = mf.Mach_Sigma(Noz_AoAc, Mach=_Minit) # # analytical solution for Ms, losses and upstream Mach number of shock wave Ms = nz.Ms_from_AsAc_NPR(target_AoAc, NPR) Ptloss = Is.PiPs_Mach(Ms) / NPR Msh = sw.Mn_Pi_ratio(Ptloss) # # redefine curves starting from 'ish' index (closest value of Msh in supersonic flow) ish = np.abs(_M - Msh).argmin() _M[ish:] = mf.MachSub_Sigma(Noz_AoAc[ish:] * mf.Sigma_Mach(Ms) / target_AoAc) _Pt[ish:] = Ptloss _Ps = _Pt / Is.PiPs_Mach(_M)
def set_NPR(self, NPR): """ Define Nozzle Pressure Ratio (inlet Ptot over outlet Ps) for this case :param NPR: NPR value (>1) """ self.NPR = NPR defg.set_gamma(self._gam) if NPR < self.NPR0: # flow is fully subsonic _Ms = Is.Mach_PiPs(NPR) _M = mf.MachSub_Sigma(self.section * mf.Sigma_Mach(_Ms) / self.section[-1]) _Pt = 0. * _M + NPR _Ps = _Pt / Is.PiPs_Mach(_M) else: # compute Mach, assumed to be subsonic before throat, supersonic after _Minit = 0. * self.section + .5 _Minit[self.ithroat:] = 2. _M = mf.Mach_Sigma(self.section / self.section[self.ithroat], Mach=_Minit) _Pt = NPR + 0. * _M # CHECK, there is a shock # analytical solution for Ms, losses and upstream Mach number of shock wave Ms = nz.Ms_from_AsAc_NPR(self.AsoAc, NPR) Ptloss = Is.PiPs_Mach(Ms) / NPR Msh = sw.Mn_Pi_ratio(Ptloss) # if NPR < self.NPRsw: # throat is choked, there may be a shock # redefine curves starting from 'ish' index (closest value of Msh in supersonic flow) ish = np.abs(_M - Msh).argmin() _M[ish:] = mf.MachSub_Sigma( self.section[ish:] * mf.Sigma_Mach(Ms) / self.section[-1]) _Pt[ish:] = Ptloss * NPR _Ps = _Pt / Is.PiPs_Mach(_M) # self._M = _M self._Pt = _Pt self._Ps = _Ps return
def _NPR_Ms_list(AsAc): """ Computes all NPR limits and associated exit Mach number internal function :param AsAc: ratio of section at exit over throat :return: result NPR and Mach numbers :Example: >>> import aerokit.aero.MassFlow as mf ; mf.Sigma_Mach(Is.Mach_PtPs(np.array(_NPR_Ms_list(2.)[:3:2]))) array([ 2., 2.]) .. seealso:: NPR_choked_subsonic(), NPR_choked_supersonic(), NPR_shock_at_exit() .. note:: available for scalar or array (numpy) computations """ Msub = mf.MachSub_Sigma(AsAc) NPR0 = Is.PtPs_Mach(Msub) Msup = mf.MachSup_Sigma(AsAc) Msh = sw.downstream_Mn(Msup) NPRsw = Is.PtPs_Mach(Msh) / sw.Pi_ratio(Msup) NPR1 = Is.PtPs_Mach(Msup) return NPR0, NPRsw, NPR1, Msub, Msh, Msup
def deflection_Mach_IsentropicPsratio(Mach, Pratio, gamma=defg._gamma): m2 = Is.Mach_PtPs(Is.PtPs_Mach(Mach, gamma) / Pratio, gamma) return -PrandtlMeyer_Mach(Mach, gamma) + PrandtlMeyer_Mach(m2, gamma)
def compute_from_pt_rtt_M(self, pt, rtt, M): ps = pt / Is.PtPs_Mach(M, self._gamma) rts = rtt / Is.TtTs_Mach(M, self._gamma) self.__init__(rho=ps / rts, u=M * np.sqrt(self._gamma * rts), p=ps)
def Ptot(self): """returns Total pressure""" return self.p * Is.PtPs_Mach(self.Mach(), self._gamma)
from flowdyn.integration import rk3ssp import flowdyn.modelphy.euler as euler import flowdyn.modeldisc as modeldisc import flowdyn.solution.euler_nozzle as sol gam = 1.4 bctype = "outsub_rh" ncell = 100 nit_super = 1000 nit_tot = 10000 # expected Mach number at exit when supersonic ; defines As/Ac ratio Msup = 1.8 AsAc = mf.Sigma_Mach(Msup, gam) Msub = mf.MachSub_Sigma(AsAc, gam) NPRsup = Is.PtPs_Mach(Msup, gam) NPRsub = Is.PtPs_Mach(Msub, gam) res = {} meshsim = mesh.unimesh(ncell=ncell, length=10.0) def S(x): # section law, throat is at x=5 return 1 + (AsAc - 1.0) * (1.0 - np.exp(-0.5 * (x - 2.0)**2)) model = euler.nozzle(gamma=gam, sectionlaw=S) nozz = sol.nozzle(model, S(meshsim.centers()), NPR=NPRsup) finit = nozz.fdata(meshsim) print(NPRsup, AsAc, Msup, Msub)
import numpy as np import aerokit.aero.Isentropic as Is import matplotlib.pyplot as plt import aerokit.engine.turbofan as tf #%matplotlib inline plt.rcParams['figure.figsize'] = (10, 6) M0=.5 T0=200. P0=200e2 # Ttmax = 1600. Tt0 = T0*Is.TtTs_Mach(M0) Tt3 = np.arange(1.2*Tt0, 0.5*Ttmax, 50.) Opr = (Tt3/Tt0)**3.2 Bpr = np.arange(0.2, 10., .2) AllOpr, AllBpr = np.meshgrid(Opr, Bpr) # model = tf.turbofan_adapt(AllOpr, Ttmax, AllBpr, AllBpr/(2.+AllBpr)) model.flight_conditions(T0, P0, M0) model.update() # plt_etathp = plt.contour(AllOpr, model.spec_thrust(), model.thermoprop_efficiency(), levels=np.arange(0, 1.,.05)) plt.clabel(plt_etathp, inline=True, fontsize=8) # plt_Bpr = plt.contour(AllOpr, model.spec_thrust(), AllBpr, linestyles='dashed', levels=[0., 1., 2., 4., 8., 12.]) plt.clabel(plt_Bpr, inline=True, fontsize=8) # plt.show()
def InitialValues(self): self.Pt0 = self.P0 * Is.PtPs_Mach(Mach=self.M0, gamma=self.g.gamma) self.Tt0 = self.T0 * Is.TtTs_Mach(Mach=self.M0, gamma=self.g.gamma) self.V0 = self.M0 * np.sqrt(self.g.gamma * self.g.r * self.T0) self.current_stage_corps = 1
def IsentropicPsratio_Mach_deflection(Mach, dev, gamma=defg._gamma): m2 = Mach_PrandtlMeyer(PrandtlMeyer_Mach(Mach, gamma) - dev, gamma) return Is.PtPs_Mach(Mach, gamma) / Is.PtPs_Mach(m2, gamma)
def test_stagnation_i2t(): assert Is.TtTs_Mach(2.) == Is.TiTs_Mach(2.) assert Is.PtPs_Mach(2.) == Is.PiPs_Mach(2.) assert Is.Mach_PiPs(3.) == Is.Mach_PtPs(3.) assert Is.Mach_TiTs(3.) == Is.Mach_TtTs(3.) assert Is.Velocity_MachTi(.8, 300.) == Is.Velocity_MachTt(.8, 300.)