Beispiel #1
0
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)
Beispiel #2
0
	def _rankinehugoniot_from_ushock(self, ushock):
		"""
			returns Rankine-Hugoniot state, given a shock velocity
		
			..warning:: this function is made private because there is no test about upstream/downstream consistency
			nor the right ushock range (greater than u+a or lesser than u-a
		"""
		loc_Mn    = (self.u-ushock)/self.asound()          # this Mach number is signed
		rho_ratio = sw.Rho_ratio(loc_Mn, self._gamma)
		return unsteady_state(self.rho * rho_ratio,
		             ushock + (self.u-ushock)/rho_ratio,
		             self.p * sw.Ps_ratio(loc_Mn, self._gamma),
	 	             gamma=self._gamma)
Beispiel #3
0
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
Beispiel #4
0
    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)
Beispiel #5
0
def plot_theta_sigma(mach,
                     gamma=defg._gamma,
                     npts=100,
                     curve='both',
                     devmax=False,
                     sonic=False,
                     color='k',
                     linestyle='-',
                     **kwargs):
    """
    	Plot shock polar curve in deviation / shock angle axes

		Long comment
 
		:param mach:       upstream Mach number
        :param gamma:      specific heat ratio, default from aerokit.common.defaultgas
        :param npts:       number of computed points, curve accuracy
        :param curve:      choose which curve to plot (left, right or both)
		:return:     
 
 		:Example:

		.. seealso:: 
		.. note:: 
    """

    sig = np.linspace(deg.asin(1. / mach), 90., npts + 1)
    dev = sw.deflection_Mach_sigma(mach, sig, gamma)
    if curve in ['right', 'both']:
        plt.plot(dev, sig, color=color, linestyle=linestyle, **kwargs)
    if curve in ['left', 'both']:
        plt.plot(-dev, sig, color=color, linestyle=linestyle, **kwargs)
    if devmax:
        thet = sw.dev_Max(mach, gamma=gamma)
        sig = sw.sigma_DevMax(mach, gamma=gamma)
        if curve in ['right', 'both']: plt.plot(thet, sig, 'ro', alpha=0.9)
        if curve in ['left', 'both']: plt.plot(-thet, sig, 'ro', alpha=0.9)
    if sonic:
        thet = sw.dev_Sonic(mach, gamma=gamma)
        sig = sw.sigma_Sonic(mach, gamma=gamma)
        if curve in ['right', 'both']:
            plt.plot(thet, sig, 'ko', markerfacecolor='white')
        if curve in ['left', 'both']:
            plt.plot(-thet, sig, 'ko', markerfacecolor='white')
Beispiel #6
0
def test_shockwave_Ps():
    assert sw.Ps_ratio(1.) == 1.
    assert sw.Ps_ratio(1.1) == pytest.approx(1.245)
    assert sw.Ps_ratio(2.) == pytest.approx(4.5)
    assert sw.Ps_ratio(1., gamma=1.3) == 1.
    assert sw.Ps_ratio(1.1, gamma=1.3) == pytest.approx(1.2373913043478264)
    assert sw.Ps_ratio(2., gamma=1.3) == pytest.approx(4.391304347826088)
Beispiel #7
0
def test_shockwave_Mn1():
    assert sw.downstream_Mn(1.) == 1.
    assert sw.downstream_Mn(1.1) == pytest.approx(0.9117704213259055)
    assert sw.downstream_Mn(2.) == pytest.approx(0.5773502691896257)
    assert sw.downstream_Mn(1., gamma=1.3) == 1.
    assert sw.downstream_Mn(1.1, gamma=1.3) == pytest.approx(0.911201472607656)
    assert sw.downstream_Mn(2., gamma=1.3) == pytest.approx(0.5628780357842335)
Beispiel #8
0
def test_shockwave_Ts():
    assert sw.Ts_ratio(1.) == 1.
    assert sw.Ts_ratio(1.1) == pytest.approx(1.0649380165289257)
    assert sw.Ts_ratio(2.) == pytest.approx(1.6875)
    assert sw.Ts_ratio(1., gamma=1.3) == 1.
    assert sw.Ts_ratio(1.1, gamma=1.3) == pytest.approx(1.0506488150103892)
    assert sw.Ts_ratio(2., gamma=1.3) == pytest.approx(1.527410207939509)
Beispiel #9
0
def test_shockwave_Rho():
    assert sw.Rho_ratio(1.) == 1.
    assert sw.Rho_ratio(1.1) == pytest.approx(1.1690821256038648)
    assert sw.Rho_ratio(2.) == pytest.approx(2.666666666666667)
    assert sw.Rho_ratio(1., gamma=1.3) == 1.
    assert sw.Rho_ratio(1.1, gamma=1.3) == pytest.approx(1.1777401608125266)
    assert sw.Rho_ratio(2., gamma=1.3) == pytest.approx(2.875)
Beispiel #10
0
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
Beispiel #11
0
    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
Beispiel #12
0
 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)
Beispiel #13
0
def test_Mn_Ps():
    assert sw.Ps_ratio(2.) == pytest.approx(4.5)
    assert sw.Mn_Ps_ratio(sw.Ps_ratio(3.)) == pytest.approx(3.)
Beispiel #14
0
fsol = solver.solve(finit, cfl, stop={"maxit": nit_super}, monitors=monitors)

fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(14, 4))
monitors["residual"]["output"].semilogplot_it(ax=ax1)
fsol[-1].plot('mach', style='-', axes=ax2)
fsol[-1].plot('ptot', style='-', axes=ax3)
finit.plot('mach', style='--', axes=ax2)
finit.plot('ptot', style='--', axes=ax3)
fig.show()

# if verbose: solver.show_perf()
res["init_residual"] = monitors["residual"]["output"]._value[-1]
res["init_M9"] = fsol[-1].phydata("mach")[-1]

# RESTART
bcR = {"type": bctype, "p": 1.1 * sw.Ps_ratio(Msup, gam)}
rhs = modeldisc.fvm(model, meshsim, muscl(vanleer), bcL=bcL, bcR=bcR)
solver = rk3ssp(meshsim, rhs)
try:
    fsol = solver.solve(fsol[-1],
                        cfl,
                        stop={"maxit": nit_tot},
                        monitors=monitors)
    solver.show_perf()
    res["simu_residual"] = monitors["residual"]["output"]._value[-1]
    res["simu_M9"] = fsol[-1].phydata("mach")[-1]
    # if verbose: print(res)
except Exception:
    res["simu_residual"] = 1.0e9
    res["simu_M9"] = 0.0
Beispiel #15
0
def plot_theta_pressure(mach,
                        gamma=defg._gamma,
                        npts=100,
                        thet_init=0.,
                        p_init=1.,
                        curve='both',
                        devmax=False,
                        sonic=False,
                        color='k',
                        linestyle='-',
                        ax=plt,
                        **kwargs):
    """
    	Plot shock polar curve in deviation / pressure ratio axes

		Long comment
 
		:param mach:       upstream Mach number
        :param gamma:      specific heat ratio, default from aerokit.common.defaultgas
        :param npts:       number of computed points, curve accuracy
        :param thet_init:  upstream angle (shift the curve by this angle), default 0.
        :param p_init:     reference pressure (shift the curve by this ratio), default 1.
        :param curve:      choose which curve to plot (left, right or both)
		:return:     
 
 		:Example:

		.. seealso:: 
		.. note:: 
    """

    sig = np.linspace(deg.asin(1. / mach), 90., npts + 1)
    dev = sw.deflection_Mach_sigma(mach, sig, gamma)
    ps = p_init * sw.Ps_ratio(
        mach * deg.sin(sig),
        gamma)  # pressure ratio only depends on normal Mach number
    if curve in ['right', 'both']:
        ax.plot(thet_init + dev,
                ps,
                color=color,
                linestyle=linestyle,
                **kwargs)
    if curve in ['left', 'both']:
        ax.plot(thet_init - dev,
                ps,
                color=color,
                linestyle=linestyle,
                **kwargs)
    if devmax:
        thet = sw.dev_Max(mach, gamma=gamma)
        sig = sw.sigma_DevMax(mach, gamma=gamma)
        ps = sw.Ps_ratio(mach * deg.sin(sig), gamma=gamma)
        if curve in ['right', 'both']:
            ax.plot(thet_init + thet, p_init * ps, 'ro', alpha=0.9)
        if curve in ['left', 'both']:
            ax.plot(thet_init - thet, p_init * ps, 'ro', alpha=0.9)
    if sonic:
        thet = sw.dev_Sonic(mach, gamma=gamma)
        sig = sw.sigma_Sonic(mach, gamma=gamma)
        ps = sw.Ps_ratio(mach * deg.sin(sig), gamma=gamma)
        if curve in ['right', 'both']:
            ax.plot(thet_init + thet,
                    p_init * ps,
                    'ko',
                    markerfacecolor='white')
        if curve in ['left', 'both']:
            ax.plot(thet_init - thet,
                    p_init * ps,
                    'ko',
                    markerfacecolor='white')
Beispiel #16
0
FSalpha = np.log10(np.logspace(1., alphamax, npts + 1))
FSm4 = ray.SupMach_TiTicri(FSalpha / alphamax * ray.Ti_Ticri(M4max, gam), gam)
FSpi4 = ray.Pi_Picri(FSm4, gam) / ray.Pi_Picri(M3sup, gam)
FSpi3 = np.ones(npts + 1)
FSm3 = M3sup * np.ones(npts + 1)

ax[0].plot(FSalpha, FSpi3, '-', color='#ff0000')
ax[1].plot(FSalpha, FSpi4, '-', color='#ff0000')
ax[2].plot(FSalpha, FSm3, '-', color='#ff0000')

# --- (CW) conventional working state

# M8 is sonic so M4 is known
CWm4 = mf.Mach_Sigma(A3A2 / A8A2, .1, gam)  # look for subsonic value

CWm3low = sw.downstream_Mn(M3sup, gam)
alphamin = ray.Ti_Ticri(CWm4, gam) / ray.Ti_Ticri(CWm3low, gam)
CWm3high = mf.Mach_Sigma(A3A2 * mf.Sigma_Mach(sw.downstream_Mn(M2, gam), gam),
                         .1, gam)
alphamax = ray.Ti_Ticri(CWm4, gam) / ray.Ti_Ticri(CWm3high, gam)
print("           unstart of inlet throat for Ti4/Ti0 = %6.3f" % (alphamax))
print("             fully supersonic flow for Ti4/Ti0 = %6.3f" % (alphamin))

CWalpha = np.log10(np.logspace(alphamin, alphamax, npts + 1))
CWm3 = ray.SubMach_TiTicri(ray.Ti_Ticri(CWm4, gam) / CWalpha, gam)
CWpi3 = mf.Sigma_Mach(CWm3, gam) / mf.Sigma_Mach(M2, gam) / A3A2
CWpi4 = CWpi3 * ray.Pi_Picri(CWm4, gam) / ray.Pi_Picri(CWm3, gam)
CWm4 = np.ones(npts + 1) * CWm4

ax[0].plot(CWalpha, CWpi3, '-', color='#bb0000')
ax[1].plot(CWalpha, CWpi4, '-', color='#bb0000')
Beispiel #17
0
def test_conical_shock_mach():
    mach = sw.conical_Mach_walldeflection_sigma(30., 45.)
    assert mach == pytest.approx(2.2376,
                                 rel=1.e-4)  # solution of iterative process
Beispiel #18
0
def test_conical_shock_sigma():
    sig = sw.conical_sigma_Mach_walldeflection(2., 30.)
    assert sig == pytest.approx(48.079078,
                                rel=1.e-4)  # solution of iterative process
Beispiel #19
0
def test_conical_shock_deflection():
    dev = sw.conical_deflection_Mach_sigma(2., 35.)
    assert dev == pytest.approx(16.5322,
                                rel=1.e-4)  # solution of iterative process
Beispiel #20
0
def test_polar_iterative_vs_cubic_strong(M0, dev):
    sig_it = sw.sigma_Mach_deflection(M0, dev, init=80.)
    sig_cub = sw.strongsigma_Mach_deflection(M0, dev)
    assert sig_it == pytest.approx(sig_cub)
Beispiel #21
0
def test_shockwave_Mn1_involutive_numpy():
    m = np.linspace(1., 10., 30)
    np.testing.assert_allclose(m, sw.downstream_Mn(sw.downstream_Mn(m)))
Beispiel #22
0
def test_polar_iterative_vs_cubic_weak(M0, dev):
    sig_it = sw.sigma_Mach_deflection(M0, dev)  # default is weak shock
    sig_cub = sw.weaksigma_Mach_deflection(M0, dev)
    assert sig_it == pytest.approx(sig_cub)
Beispiel #23
0
def test_Ptshock():
    assert sw.Pt_ratio(2.) == sw.Pi_ratio(2.)