Oblique Shock Relation

An oblique shock results from a sudden change of direction of supersonic flow. The relations of density (\(\rho\)), pressure (\(p\)), and temprature (\(T\)) across the shock can be obtained analytically [Anderson03]. In addition, two angles are defined:

  1. The angle of the oblique shock wave deflected from the upstream is \(\beta\); the shock angle.
  2. The angle of the flow behind the shock wave deflected from the upstream is \(\theta\); the flow angle.

See Figure 1 for the illustration of the two angles.

Figure 1: Oblique shock wave by a wedge

\(M\) is Mach number. \(\theta\) is the flow deflection angle. \(\beta\) is the oblique shock angle.

Methods of calculating the shock relations are organized in the class ObliqueShockRelation. To obtain the relations of density (\(\rho\)), pressure (\(p\)), and temprature (\(T\)), the control volume across the shock is emplyed, as shown in Figure 2. In the figure and in ObliqueShockRelation, subscript 1 denotes upstream properties and subscript 2 denotes downstream properties. Derivation of the relation uses a rotated coordinate system \((n, t)\) defined by the oblique shock, where \(\hat{n}\) is the unit vector normal to the shock, and \(\hat{t}\) is the unit vector tangential to the shock. But in this document we won’t go into the detail.

Figure 2: Properties across an oblique shock

The flow properties in the upstream zone of the oblique shock are \(v_1, M_1, \rho_1, p_1, T_1\). Those in the downstream zone of the shock are \(v_2, M_2, \rho_2, p_2, T_2\).
class solvcon.parcel.gas.oblique_shock.ObliqueShockRelation(gamma)

Calculators of oblique shock relations.

The constructor must take the ratio of specific heat:

>>> ObliqueShockRelation() 
Traceback (most recent call last):
    ...
TypeError: __init__() ...
>>> ob = ObliqueShockRelation(gamma=1.4)

The ratio of specific heat can be accessed through the gamma attribute:

>>> ob.gamma
1.4

The object can be used to calculate shock relations. For example, calc_density_ratio() returns the \(\rho_2/\rho_1\):

>>> np.around(ob.calc_density_ratio(mach1=3, beta=37.8/180*np.pi),
...           10).tolist()
2.4204302545

The solution changes as gamma changes:

>>> ob.gamma = 1.2
>>> np.around(ob.calc_density_ratio(mach1=3, beta=37.8/180*np.pi),
...           10).tolist()
2.7793244902
gamma

Ratio of specific heat \(\gamma\), dimensionless.

ObliqueShockRelation provides three methods to calculate the ratio of flow properties across the shock. \(M_1\) and \(\beta\) are required arguments:

\(\rho\)
calc_density_ratio()
\(p\)
calc_pressure_ratio()
\(T\)
calc_temperature_ratio()

With \(M_1\) available, the shock angle \(\beta\) can be calculated from the flow angle \(\theta\), or vice versa, by using the following two methods:

\(\beta\)
ObliqueShockRelation.calc_shock_angle()
\(\theta\)
ObliqueShockRelation.calc_flow_angle()

The following method calculates the downstream Mach number, with the upstream Mach number \(M_1\) and either of \(\beta\) or \(\theta\) supplied:

\(M_2\)
calc_dmach()

Listing of all methods:

ObliqueShockRelation.calc_density_ratio(mach1, beta)

Calculate the ratio of density \(\rho\) across an oblique shock wave of which the angle deflected from the upstream flow is \(\beta\) and the upstream Mach number is \(M_1\):

\[\frac{\rho_2}{\rho_1} = \frac{(\gamma + 1) M_{n1}^2} {(\gamma - 1) M_{n1}^2 + 2}\]

where \(M_{n1} = M_1\sin\beta\).

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> np.around(ob.calc_density_ratio(mach1=3, beta=37.8/180*np.pi),
...           10).tolist()
2.4204302545

as well as numpy.ndarray:

>>> angle = 37.8/180*np.pi; angle = np.array([angle, angle])
>>> np.around(ob.calc_density_ratio(mach1=3, beta=angle), 10).tolist()
[2.4204302545, 2.4204302545]
Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • beta – Oblique shock angle \(\beta\) deflected from the upstream flow, in radian.
ObliqueShockRelation.calc_pressure_ratio(mach1, beta)

Calculate the ratio of pressure \(p\) across an oblique shock wave of which the angle deflected from the upstream flow is \(\beta\) and the upstream Mach number is \(M_1\):

\[\frac{p_2}{p_1} = 1 + \frac{2\gamma}{\gamma+1}(M_{n1}^2 - 1)\]

where \(M_{n1} = M_1\sin\beta\).

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> np.around(ob.calc_pressure_ratio(mach1=3, beta=37.8/180*np.pi), 10).tolist()
3.7777114257

as well as numpy.ndarray:

>>> angle = 37.8/180*np.pi; angle = np.array([angle, angle])
>>> np.around(ob.calc_pressure_ratio(mach1=3, beta=angle), 10).tolist()
[3.7777114257, 3.7777114257]
Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • beta – Oblique shock angle \(\beta\) deflected from the upstream flow, in radian.
ObliqueShockRelation.calc_temperature_ratio(mach1, beta)

Calculate the ratio of temperature \(T\) across an oblique shock wave of which the angle deflected from the upstream flow is \(\beta\) and the upstream Mach number is \(M_1\):

\[\frac{T_2}{T_1} = \frac{p_2}{p_1} \frac{\rho_1}{\rho_2}\]

where both \(p_2/p_1\) and \(\rho_1/\rho_2\) are functions of \(\gamma\), \(M_1\), and \(\beta\). See also calc_pressure_ratio() and calc_density_ratio().

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> np.around(ob.calc_temperature_ratio(mach1=3, beta=37.8/180*np.pi), 10).tolist()
1.5607602899

as well as numpy.ndarray:

>>> angle = 37.8/180*np.pi; angle = np.array([angle, angle])
>>> np.around(ob.calc_temperature_ratio(mach1=3, beta=angle), 10).tolist()
[1.5607602899, 1.5607602899]
Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • beta – Oblique shock angle \(\beta\) deflected from the upstream flow, in radian.
ObliqueShockRelation.calc_dmach(mach1, beta=None, theta=None, delta=1)

Calculate the downstream Mach number from the upstream Mach number \(M_1\) and either of the shock or flow deflection angles:

\[M_2 = \frac{M_{n2}}{\sin(\beta-\theta)}\]

where \(M_{n2}\) is calculated from calc_normal_dmach() with \(M_{n1} = M_1\sin\beta\).

The method can be invoked with only either \(\beta\) or \(\theta\):

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> ob.calc_dmach(3, beta=0.2, theta=0.1)
Traceback (most recent call last):
    ...
ValueError: got (beta=0.2, theta=0.1), but I need to take either beta or theta
>>> ob.calc_dmach(3)
Traceback (most recent call last):
    ...
ValueError: got (beta=None, theta=None), but I need to take either beta or theta

This method accepts scalar:

>>> np.around(ob.calc_dmach(3, beta=37.8/180*np.pi), 10).tolist()
1.9924827009
>>> np.around(ob.calc_dmach(3, theta=20./180*np.pi), 10).tolist()
1.9941316656

as well as numpy.ndarray:

>>> angle = 37.8/180*np.pi; angle = np.array([angle, angle])
>>> np.around(ob.calc_dmach(3, beta=angle), 10).tolist()
[1.9924827009, 1.9924827009]
>>> angle = 20./180*np.pi; angle = np.array([angle, angle])
>>> np.around(ob.calc_dmach(3, theta=angle), 10).tolist()
[1.9941316656, 1.9941316656]
Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • beta – Oblique shock angle \(\beta\) deflected from the upstream flow, in radian.
  • theta – Downstream flow angle \(\theta\) deflected from the upstream flow, in radian.
  • delta – A switching integer \(\delta\). For \(\delta = 0\), the function gives the solution of strong shock, while for \(\delta = 1\), it gives the solution of weak shock. This keyword argument is only valid when theta is given. The default value is 1.
ObliqueShockRelation.calc_normal_dmach(mach_n1)

Calculate the downstream Mach number from the given upstream Mach number \(M_{n1}\), in the direction normal to the shock:

\[M_{n2} = \sqrt{\frac{(\gamma-1)M_{n1}^2 + 2} {2\gamma M_{n1}^2 - (\gamma-1)}}\]

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> np.around(ob.calc_normal_dmach(mach_n1=3), 10).tolist()
0.4751909633

as well as numpy.ndarray:

>>> np.around(ob.calc_normal_dmach(mach_n1=np.array([3, 3])), 10).tolist()
[0.4751909633, 0.4751909633]
Parameters:mach_n1 – Upstream Mach number \(M_{n1}\) normal to the shock wave, dimensionless.
ObliqueShockRelation.calc_flow_angle(mach1, beta)

Calculate the downstream flow angle \(\theta\) deflected from the upstream flow by using calc_flow_tangent(), in radian.

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> angle = 48.25848/180*np.pi
>>> np.around(
...     ob.calc_flow_angle(mach1=4, beta=angle)/np.pi*180, 10).tolist()
32.0000000807

as well as numpy.ndarray:

>>> angle = 48.25848/180*np.pi; angle = np.array([angle, angle])
>>> np.around((ob.calc_flow_angle(mach1=4, beta=angle)/np.pi*180),
...           10).tolist()
[32.0000000807, 32.0000000807]

See Example 4.6 in [Anderson03] for the forward analysis. The above is the inverse analysis.

Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • beta – Oblique shock angle \(\beta\) deflected from the upstream flow, in radian.
ObliqueShockRelation.calc_flow_tangent(mach1, beta)

Calculate the trigonometric tangent function \(\tan\beta\) of the downstream flow angle \(\theta\) deflected from the upstream flow by using the \(\theta\)-\(\beta\)-\(M\) relation:

\[\tan\theta = 2\cot\beta \frac{M_1^2\sin^2\beta - 1} {M_1^2(\gamma+\cos2\beta) + 2}\]

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> angle = 48.25848/180*np.pi
>>> np.around(ob.calc_flow_tangent(mach1=4, beta=angle), 10).tolist()
0.6248693539

as well as numpy.ndarray:

>>> angle = 48.25848/180*np.pi; angle = np.array([angle, angle])
>>> np.around(ob.calc_flow_tangent(mach1=4, beta=angle), 10).tolist()
[0.6248693539, 0.6248693539]

See Example 4.6 in [Anderson03] for the forward analysis. The above is the inverse analysis.

Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • beta – Oblique shock angle \(\beta\) deflected from the upstream flow, in radian.
ObliqueShockRelation.calc_shock_angle(mach1, theta, delta=1)

Calculate the downstream shock angle \(\beta\) deflected from the upstream flow by using calc_shock_tangent(), in radian.

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> angle = 32./180*np.pi
>>> np.around(ob.calc_shock_angle(mach1=4, theta=angle, delta=1)/np.pi*180, 10).tolist()
48.2584798722

as well as numpy.ndarray:

>>> angle = np.array([angle, angle])
>>> np.around(
...     ob.calc_shock_angle(mach1=4, theta=angle, delta=1)/np.pi*180,
...                         10).tolist()
[48.2584798722, 48.2584798722]

See Example 4.6 in [Anderson03] for the analysis.

Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • theta – Downstream flow angle \(\theta\) deflected from the upstream flow, in radian.
  • delta – A switching integer \(\delta\). For \(\delta = 0\), the function gives the solution of strong shock, while for \(\delta = 1\), it gives the solution of weak shock. The default value is 1.
ObliqueShockRelation.calc_shock_tangent(mach1, theta, delta)

Calculate the downstream shock angle \(\beta\) deflected from the upstream flow by using the alternative \(\beta\)-\(\theta\)-\(M\) relation:

\[\tan\beta = \frac{M_1^2 - 1 + 2\lambda\cos\left(\frac{4\pi\delta + \cos^{-1}\chi}{3}\right)} {3\left(1 + \frac{\gamma-1}{2}M_1^2\right)\tan\theta}\]

where \(\lambda\) and \(\chi\) are obtained internally by calling calc_shock_tangent_aux().

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> angle = 32./180*np.pi
>>> np.around(ob.calc_shock_tangent(mach1=4, theta=angle, delta=1),
...           10).tolist()
1.1207391858

as well as numpy.ndarray:

>>> angle = np.array([angle, angle])
>>> np.around(ob.calc_shock_tangent(mach1=4, theta=angle, delta=1),
...           10).tolist()
[1.1207391858, 1.1207391858]

See Example 4.6 in [Anderson03] for the analysis.

Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • theta – Downstream flow angle \(\theta\) deflected from the upstream flow, in radian.
  • delta – A switching integer \(\delta\). For \(\delta = 0\), the function gives the solution of strong shock, while for \(\delta = 1\), it gives the solution of weak shock.
ObliqueShockRelation.calc_shock_tangent_aux(mach1, theta)

Calculate the \(\lambda\) and \(\chi\) functions used by calc_shock_tangent():

\[\lambda = \sqrt{(M_1^2-1)^2 - 3\left(1+\frac{\gamma-1}{2}M_1^2\right) \left(1+\frac{\gamma+1}{2}M_1^2\right)\tan^2\theta}\]
\[\chi = \frac{(M_1^2-1)^3 - 9\left(1+\frac{\gamma-1}{2}M_1^2\right) \left(1+\frac{\gamma-1}{2}M_1^2+\frac{\gamma+1}{4}M_1^4\right) \tan^2\theta} {\lambda^3}\]

This method accepts scalar:

>>> ob = ObliqueShockRelation(gamma=1.4)
>>> lmbd, chi = ob.calc_shock_tangent_aux(mach1=4, theta=32./180*np.pi)
>>> np.around([lmbd, chi], 10).tolist()
[11.2080188412, 0.7428957121]

as well as numpy.ndarray:

>>> angle = 32./180*np.pi; angle = np.array([angle, angle])
>>> lmbd, chi = ob.calc_shock_tangent_aux(mach1=4, theta=angle)
>>> np.around(lmbd, 10).tolist()
[11.2080188412, 11.2080188412]
>>> np.around(chi, 10).tolist()
[0.7428957121, 0.7428957121]

See Example 4.6 in [Anderson03] for the analysis.

Parameters:
  • mach1 – Upstream Mach number \(M_1\), dimensionless.
  • theta – Downstream flow angle \(\theta\) deflected from the upstream flow, in radian.