def test_nozzle_class(): target_AoAc = 6. length = 8. Noz_x = np.linspace(0., length, 200, endpoint=True) ma_max = mf.Mach_Sigma(target_AoAc, Mach=2.) ma = 1. + (ma_max-1.)*np.sin(.5*(Noz_x-1.)*np.pi/(length-1.)) Noz_AoAc = mf.Sigma_Mach(ma) convdiv = noz.nozzle(Noz_x, Noz_AoAc, AsoAc=target_AoAc) assert convdiv.AsoAc == target_AoAc assert convdiv.ithroat == 25
def test_nozzle(): target_AoAc = 6. length = 8. Noz_x = np.linspace(0., length, 200, endpoint=True) ma_max = mf.Mach_Sigma(target_AoAc, Mach=2.) ma = 1. + (ma_max-1.)*np.sin(.5*(Noz_x-1.)*np.pi/(length-1.)) Noz_AoAc = mf.Sigma_Mach(ma) convdiv = noz.nozzle(Noz_x, Noz_AoAc, AsoAc=target_AoAc, NPR=4.) assert not np.any(np.isnan(convdiv.Mach())) assert not np.any(np.isnan(convdiv.Ps())) assert not np.any(np.isnan(convdiv.Ptot()))
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 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 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 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 _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
- 8 is the throat of the nozzle - 9 is the nozzle exit """ import numpy as np import matplotlib.pyplot as plt #import aerokit.aero.Isentropic as isent import aerokit.aero.MassFlow as mf import aerokit.aero.ShockWave as sw import aerokit.aero.Rayleigh as ray gam = 1.4 # assumed constant npts = 50 M0 = 2.8 M2 = 1.5 A2A0 = mf.Sigma_Mach(M2, gam) / mf.Sigma_Mach(M0, gam) print("A0/A2 for isentropic compression from Mach %4.2f to %4.2f : %6.3f" % (M0, M2, 1. / A2A0)) A3A2 = 1. / A2A0 * 0.9 A8A2 = .8 * A3A2 fig, ax = plt.subplots(3, 1, figsize=(10, 16)) fig.suptitle( 'Flow features on RAMJET, $M_0=%.2f$, $M_2=%.2f$, $A_8/A_2=%.2f$, $\gamma = %.1f$' % (M0, M2, A8A2, gam), fontsize=12, y=0.93) ax[0].set_ylabel('$p_{i3}/p_{i0}$', fontsize=10) ax[0].grid(which='major', linestyle=':', alpha=0.5)
import numpy as np import aerokit.aero.MassFlow as mf import matplotlib.pyplot as plt # g = 1.4 mmax = 5. n = 1000 Mach = np.linspace(.05, mmax, n) Sigma = mf.Sigma_Mach(Mach) Mres = mf.Mach_Sigma(Sigma, Mach) fig, ax = plt.subplots(1, 2) ax[0].plot(Mach, Mres, Mach, mf.__MachSub_sigma(Sigma, g), Mach, mf.__MachSup_sigma(Sigma, g)) ax[0].set_xlim(0, mmax) ax[0].set_ylim(0, mmax) # Taylor expansions m = np.linspace(0.05, 5, 1000) gpuogmu = (g + 1.) / (g - 1.) sig1 = 1. / m / ((g + 1) / 2.)**(gpuogmu / 2.) sig2 = (1. + (3 - g) / 4. / (g - 1.) * (m - 1.)**2) sig3 = (m**2 / gpuogmu)**(gpuogmu / 2.) / m ax[1].plot(m, sig1, m, sig2, m, sig3, m, mf.Sigma_Mach(m)) plt.show()
import flowdyn.mesh as mesh from flowdyn.xnum import * 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)
def test_sigma_scalar(): assert mf.Sigma_Mach(.5) == pytest.approx(1.33984375) assert mf.Sigma_Mach(1.) == 1. assert mf.Sigma_Mach(2.) == pytest.approx(1.687500)
def test_MachSup_Sigma(AsAc): mach = mf.MachSup_Sigma(AsAc) assert (mach > 1) assert mf.Sigma_Mach(mach) == pytest.approx(AsAc, rel=1.e-6)
def test_sigma_reverse_numpy(): m = np.linspace(.01, 2., 30) np.testing.assert_allclose(m, mf.Mach_Sigma(mf.Sigma_Mach(m), m))
def test_sigma_def_massflow(m): assert mf.Sigma_Mach(m, gamma=1.3) == pytest.approx( mf.WeightMassFlow(1., gamma=1.3) / mf.WeightMassFlow(m, gamma=1.3))
import aerokit.aero.MassFlow as mf plt.rcParams['font.size'] = 14 plt.rcParams['lines.linewidth'] = 1.5 # for slides #plt.rcParams['font.size'] = 24 ; plt.rcParams['grid.linewidth'] = 2 ; plt.rcParams['lines.linewidth'] = 4 npoints = 100 gam = 1.4 Mmin = 0.1 Mmax = 4. Mach = np.log10(np.logspace(Mmin, Mmax, npoints + 1)) debr = mf.WeightMassFlow(Mach, gam) sig = mf.Sigma_Mach(Mach, gam) fig = plt.figure(1, figsize=(10, 8)) #fig.suptitle('Ratio to critical state, $\gamma = %.1f$'%gam, y=0.93) plt.plot(Mach, debr, 'k-') #plt.axis([Mmin, Mmax, 0., 4.]) plt.xlabel('Mach number') plt.ylabel('weighted mass flow') #plt.minorticks_on() plt.grid(which='major', linestyle=':', alpha=0.8) #plt.grid(which='minor', linestyle=':', alpha=0.5) fig.savefig('fct-weightedmf.pdf', bbox_inches='tight') plt.show() fig = plt.figure(2, figsize=(10, 8))