1 Introduction to Gino Moretti’s Manuscript

This chapter reports an unpublished manuscript by Gino Moretti taken from the book on the shock-fitting that Gino Moretti tried to write after his retirement but that he never completed and published. The manuscript is not complete, there are two figures missing, some of final sections and the references. We repropose in this book the manuscript as it is, without any attempt to restore the missing parts. Indeed, we think that it has a high value, not only historical but also scientific, as it represents the most complete description of the floating shock-fitting technique proposed and developed by Gino Moretti in the last years of his scientific career.

The manuscript focuses exclusively on the algorithmic description of the technique and no results and applications are shown. A number of applications of this technique can be found in these Refs. [ 1 3 ] of the late 80s. Later on, the technique was further developed and applied during the 90s by Marcello Onofri and Francesco Nasuti. The next chapter will show you these further developments and some interesting applications of the floating shock-fitting.

The analysis of the manuscript allows us to observe some interesting aspects of Moretti’s “modus operandi.” What is most evident is the extreme precision and detailed information, shown in the algorithm description. The manuscript contains also some pieces of code and the description of the data structure. At the same time it is also evident the strong link between numerical algorithm and mathematical theory or the natural evolution of the physical phenomenon (e.g., see the Sect. 7.1 concerning shocks generated by coalescence of waves). Even when Moretti deals with purely numerical problems (e.g., see Sect. 9.1 on wrinkles on a shock), he tries to provide a mathematical interpretation of the numerical phenomenon, although in the light of the differences between continuous and discrete models. For this reason the explanations and solutions that Moretti proposes are always very convincing and elegant.

We hope that the publication of this manuscript could be appreciated by the scientists interested in the shock-fitting technique and that it will be a source of inspiration and example.

Rome, Italy Marcello OnofriRome, Italy Renato PaciorriJuly 2017

2 Introduction

Simple, accurate, and fast-working codes can be written for Euler’s equations if they are formulated in characteristic terms prior to discretization. A typical code is the λ-scheme [1, 2] with its variations [3–6]. It is well-known that such codes cannot properly capture strong shocks and cannot describe evolutions where a shock has to move upstream in a supersonic environment. Therefore, the formulation of Euler’s equations in divergence form and shock-capturing codes are generally preferred. Simplicity, accuracy, and speed of shock-capturing codes, however, are not a challenge for the λ-scheme; in addition, the lack of accuracy in the regions surrounding the captured shock jeopardizes certain extensions, for example to non-equilibrium flows. The only advantage of shock-capturing codes is their robustness, that gives peace of mind to the analyst (to put it, bluntly, shock-capturing codes generally produce results, but not necessarily good results). One may be induced to compute using shock-capturing codes and to fit the captured shocks where necessary. I do not agree, for the following reasons:

  1. 1.

    The inaccuracies of shock-capturing codes, that pervade the entire flow field, are not corrected by occasional fittings.

  2. 2.

    From a practical viewpoint, the shock-capturing code (that is always more cumbersome than the λ-scheme) needs additional working to be made compatible with shock-fitting.

  3. 3.

    The λ-scheme itself is able to capture oblique isentropic shocks and to give the shock detection procedure time to initialize the fitting, if necessary. Therefore, there is no reason to fear a loss of accuracy, for having missed the fitting of a shock.

  4. 4.

    Once an oblique shock has been captured by a shock-capturing code, the transition is smeared over many cells and the fitting technique (at least, the one I am going to describe in this paper) may not find a sufficiently strong jump to start working; this is particularly evident near, shock interactions and reflections from rigid wall where even regular reflections tend to be interpreted by a shock-capturing technique as Mach reflections.

There are many theoretical and practical advantages in shock-fitting. Fitting of shocks agrees with their physical nature (in an inviscid model) as a part of strong solutions. Their evaluation is very accurate and fast if the Rankine-Hugoniot conditions are used explicitly. The automatic separation of certain domains of dependence in the vicinity of a shock prevents the formation of wiggles and makes the use of arbitrary damping factors (artificial viscosity) unnecessary. Therefore, some years ago, I started working on the problem of combining a simply, highly accurate, fast, and robust λ-scheme technique with a shock-fitting technique capable of detecting and handling as large a variety of complex shock patterns as possible. Progress reports have been published [7–9] presenting a number of applications of increasing complexity. No details have been given extensively, both because of space limitations and because I wanted first to validate the technique in a greater number of problems. Unfortunately, the time scale for each problem is measured in months, not so much for the fitting of shock as for the creation of the geometry and a suitable grid, the proper enforcement of boundary conditions, a large number of parametric studies and an analysis of the possible dependence of the solution on initial conditions, grid fineness, etc. Meanwhile, I have been reprimanded for being too cryptic and, consequently, for preventing other people from contributing to the development of the technique.

The present paper tries to correct the omission. The matter contained herein is an extended version of the Final Report submitted to NASA Lewis BC, in December 1987; it supersedes all my other papers containing partial details.

3 Basic Ideas

The following problems arise in considering shock-fitting:

  1. 1.

    Detection of formation of a shock, either by coalescence of pressure waves or by abrupt changes in rigid wall geometry,

  2. 2.

    Conversely, disappearance of increasingly weaker shocks,

  3. 3.

    Local treatment of shocks according to the Rankine-Hugoniot conditions,

  4. 4.

    Shock topology: location of shocks with respect to the computational grid and to one another,

  5. 5.

    Definition of the normal to a shock,

  6. 6.

    Shock interactions,

  7. 7.

    Stability of shocks,

  8. 8.

    Treatment of points in the vicinity of a shock.

I will consider them in detail in the following sections, limiting the analysis to problems depending on two space dimensions and time. Many of the above problems are tightly tied together; no section can be written without some knowledge of other sections. I attempted to arrange the material to avoid browsing around back and forth as much as possible. Therefore, the sequence of sections is not the same as the topics listed above, that appear instead in the following order: 8 (Sect. 5), 3 (Sect. 6), 1 (Sect. 7), 4 (Sect. 8), 2 (Sect. 9), 5 and 7 (Sect. 10), and 6 (Sect. 11). In addition, the actual sequence of subroutines and operations in any of my computational codes will be described and rediscussed in Sect. 11.

4 Grids, Shock Points, Notations

We consider only structured grids that may or may not be orthogonal. Portions of such grids will be represented here as in Fig. 1 because we are only concerned with the topology of the shocks. In other words, our considerations apply to any type of structured grids, not only to Cartesian grids as shown in the figure. Let grid lines of one family (the horizontal ones in Fig. 1 be called x-lines, and the others y-lines; x-lines are numbered using the index m, y-lines using the index n (M and N in FORTRAN codes, respectively). Thus, grid points on a given x-line are ordered in increasing sequences of values of N; grid points on a given y-line are ordered in increasing sequences of values of M. Every grid point can be identified by its coordinates (x, y) or by its indices (N, M).

Fig. 1
figure 1

Computational grid

A shock front is described by its intersections with grid lines. The intersection of a shock with an x-line is called an x-point and its intersection with a y-line is called a y-point. We will stipulate not to consider x-points where the normal to the shock forms an angle of more than 45 with the x-line, and not to consider y-points where the normal to the shock forms an angle of more than 45 with the y-line.

All information pertinent to shock points is stored in single arrays, depending on a counter, J. No attempt is made to organize the arrays; the shock points are stored at random, regardless of their relative position in the physical plane. Cross-referencing between the grid points and the shock points is necessary. To this effect, we use the following indices:

  • NS(J) is the value of N to the left of an x-point or the value of N itself for a y-point (Fig. 2),

    Fig. 2
    figure 2

    Shock points in a grid

  • MS(J) is the value of M for an x-point or the value of M below a y-point,

  • JSX(N,M) is the value of J for the x-point lying on the m-th x-line to the left of the n-th y-line, and it is zero elsewhere,

  • JSY(N,M) is the value of J for the y-point lying on the n-th y-line below the m-th x-line, and it is zero elsewhere,

  • INDX(N,M) equals zero where JSX(N,M) equals zero, and 1 where JSX is not zero,

  • INDY(N,M) equals zero where JSY(N,M) equals zero, and 1 where JSY is not zero,

  • JI(J) equals zero for an x-point with the high pressure on the left, 1 for an x-point with the high pressure on the right, 2 for a y-point with the high pressure below, and 3 for a y-point with the high pressure above.

In addition, the following arrays are defined:

  • XS(J), YS(J) are the x- and y-coordinates of any shock point,

  • ANGLE(J), for an x-shock, is the angle, α, between the normal N to the shock at any shock point, and the x-line ( − π/2 ≤ α ≤ π/2),

  • ANGLE(J), for a y-shock, is the angle, α, between the normal N to the shock at any shock point, and the y-line ( − π/2 ≤ α ≤ π/2),

  • W(J) is the normal shock velocity at any shock point,

  • TMA(J) is the absolute value of the normal relative Mach number at any shock point.

5 Brief Recall of λ-Scheme Procedures and Notation

Obviously, the shock-fitting technique to be explained in what follows can be used in connection with any integration scheme for ordinary points. The most natural scheme, though, is the λ-scheme because it propagates signals along bi-characteristics in a way that easily satisfies the basic requirements for the environment of a shock. Therefore, I will consider the λ-scheme as the updating technique for all ordinary points and briefly recall the pertinent notation, as needed in the application to shock-fitting. If anyone wants to attempt shock-fitting on top of other integration schemes, these should be properly modified in the vicinity of the shock to mimic the λ-scheme features. Here we consider only the simplest formulation of the λ-scheme, that is, the one based on Cartesian grids. This is done for simplicity and clarity, in an attempt to focus the attention on the treatment of the shock itself.

As explained in [2], the λ-formulation of Euler’s equations in a Cartesian grid leads to the following equations:

$$\displaystyle \begin{aligned} \begin{array}{rcl} S_t & = & f_4^x+f_4^y \\ a_t & = & 0.5 \delta \left[f_1^x+f_2^x+f_1^y + f_2^y -aS_t \right] \\ u_t & = & 0.5 \left[f_1^x-f_2^x+f_3^y \right] \\ v_t & = & 0.5 \left[f_1^y-f_2^y+f_3^x \right] \end{array} \end{aligned} $$
(1)

with δ = (γ − 1)/2,

$$\displaystyle \begin{aligned} \begin{array}{rcl} && \lambda_i^x=u \pm a, \ \ \lambda_i^y=v \pm a, \ \ R_i^x= a/\delta \pm u, \ \ R_i^y= a/\delta \pm v. \\ && f_i^x= - \lambda_i^x\left[(R_i^x)_x-aS_x\right],\ \ f_i^y= - \lambda_i^y\left[(R_i^y)_y-aS_y\right] \\ && f_3^x=-uv_x,\ \ f_3^y=-vu_y, \ \ f_4^x=-uS_x, f_4^y=-vS_y \end{array} \end{aligned} $$

where the symbol () x means a left or right derivative according to the corresponding coefficient, \(\lambda _i^x\) or u being positive or negative and the symbol () y means a derivative from below or from above according to the corresponding coefficient, \(\lambda _i^y\) or v being positive or negative. I generally use a second-order (predictor-corrector) integration scheme. At any level, the derivatives are approximated by two-point differences. The coefficients of each f-term are expressed by their two-point averages overt the same interval on which the pertinent difference is taken. In principle, this procedure maintains second-order accuracy in a nonlinear problem.

At the predictor level, each f-term is divided by 2 and multiplied by Δt to integrate (1) over half a step. Each f-term is also stored in f 0-arrays. At the corrector step, each f-term is recomputed and then corrected by subtracting the stored f 0 previously computed at the grid point next to the point to be updated, once more on the left (or from below) if the coefficient is positive, on the right (or from above) if it is negative.

6 The NEIGHBOR Subroutine

Grid points in the vicinity of shocks must be given a special treatment, essentially to avoid differentiating across a discontinuity. Such points are detected by examining the neighborhood of each shock point. By so doing, only all values of J are scanned, not the doubly-dimensioned set of grid points. First, we describe the procedure to detect all points where one or more derivatives must be approximated in a special way (Sect. 5.1), then we detail the special approximations being used (Sect. 5.2) and, finally, in Sect. 5.3, we justify the approximations by interpreting them physically.

6.1 Detection of Grid Points Neighboring Shocks

To describe the procedure we follow the computational code step by step. First, the two-dimensional index NMOUT(N,M) is set to zero at all grid points. We will see that NMOUT is set equal to 1 every time a grid point has been treated by the subroutine; this avoids going twice over the same point.

Then, a loop over all values of J begins:

   D0 11 J=1,JA      N=NS(J)      M=MS(J)

The grid point next to the shock point is thus detected; it is the one marked with a P in Fig. 2.

We choose now to consider x-shocks first:

     IF(JI(J).LT.2) THEN

Point P is taken into consideration, unless already treated:

     IF(NMOUT(N,M).EQ.1) GO TO 2

(2 is the statement number for the next analysis). Eight indices are defined:

     IL=INDY(N,M+1)+(INDY(N-1,M)      IR=INDY(N,M)+INDY(N-1,M+1)      ILU=INDY(N-1,M+1)+INDX(N,M+1)+1      IL1U=INDX(N,M)+INDX(N+1,M+1)      IL2U=INDX(N,M)+INDY(N+1,M+1)      ILL=INDY(N-1,M)+INDX(N,M-1)+1      IL1L=INDX(N,M)+INDX(N+1,M-1)      IL2L=INDX(N,M)+INDY(N+1,M)

A patient study of Fig. 3 reveals that IL=2 or IR=2 if two y-shocks define a shock line a or b, respectively; ILU=2 or 3, or ILL=2 or 3 if an additional x- or y-shock, together with shock J, define possible shock lines c, d, or h, i, respectively; IL1U=2 or IL2U=2 if an x-shock to the left of P and an x-shock or y-shock define possible shock lines f or g; and, finally, a similar consideration can be made for IL1L=2 or IL2L=2.

Fig. 3
figure 3

Neighborhood of an x-shock point (left region)

6.2 Special Computations at Points Neighboring Shocks

The above indices, used in a calling sequence as the CALL FXM below, allow us to call some of the four subroutines:

  FXM(N,M,L,IA,IB,IC)   FXP(N,M,L,IA,IB,IC)   FYM(N,M,L,IA,IB,IC)   FYP(N,M,L,IA,IB,IC)

for redefining some of the f-terms at point P properly. Let us consider FXM in detail. In it, all f x-terms are set equal to zero if L or IC are different from zero, or if IA or IB are greater than 1. Otherwise, all \(f^x_i\) affected by negative \(\lambda _i^x\) or negative u are computed using left-differences. The same can be said for FXP, provided that positive is substituted to negative and right to left.

Similarly, in FYM all f y-terms are set equal to zero if L or IC are not zero, or if IA or IB are greater than 1. Otherwise, all \(f_i^y\) affected by negative \(\lambda _i^y\) or negative v are computed using downward differences. The same can be said for FYP, substituting positive for negative and upward for downward.

Thus, the following statement:

  CALL FXM(N,M,JSX(N,M),IL,IR,0)

takes care of the f x-terms at P, setting all of them to zero if either S or a or b of Fig. 3 (left) are present. The next statements:

  IF(JSY(N,M+1).NE.0.OR.ILU.GT.1.0R.IL1U.EQ.2.0R.IL2U      .EQ.2) 1   CALL FYM(N,M,ILL-1,IL1L,IL2L,JSY(N,M))   IF(JSY(N,M).NE.0.OR.ILL.GT.1.OR.IL1L.EQ.2.OR.IL2L.      EQ.2) 1   CALL FYP(N,M,ILU-1,ILIU,IL2U,JSY(N,M+1))

take care of the f y-terms at P. The first asks the question: Does any obstacle exist above P? If the answer is no, upward differences can be used and we proceed to the next question. Otherwise, we must take all differences from below, except if there are obstacles as well, as in the last sketch of Fig. 3, in which case all f y-terms are set to zero (this is done by calling FYN). The second statement reverses the issues between above and below.

At this point, all f-terms have been taken care of at P and NMOUT(N,M) is set equal to 1. Then we proceed to point Q, on the other side of J (Fig. 4) where V , e, and p play the roles played before by S, a, and b. The index N is bumped to N+1 and NMOUT is tested:

Fig. 4
figure 4

Neighborhood of an x-shock point (right region)

2 N=N+1   IF(NMOUT(N,M).EQ.1) GO TO 11

(11 is the end of the loop). Again, we define 8 indices:

  IL=INDY(N,M)+INDY(N+1,M+1)   IR=INDY(N,M+1)+INDY(N+1,M)   ILU=INDY(N+1,M+1)+INDX(N+1,M+1)+1   IL1U=INDX(N+1,M)+INDX(N,M)   IL2U=INDX(N+1,M)+INDY(N-1,M+1)   ILL=INDY(N+1,M)+INDX(N+1,M-1)+1   IL1L=INDX(N+1,M)+INDX(N,M-1)   IL2L=INDX(N+1,M)+INDY(N-1,M)

that are explained in Fig. 4. Similarly to what we did before, we use the following statements:

  CALL FXP(N,M,JSX(N+1,M),IL,IR,0)   IF(JSY(M,M+1).NE.0.OR.ILU.GT.1.OR.IL1U.EQ.2.OR.      IL2U.EQ.2) 1 CALL FYM(N,M,ILL-1,IL1L,IL2L,JSY(N,M))   IF(JSY(N,M).NE.0.OR.ILL.GT.1.OR.IL1L.EQ.2.OR.      IL2L.EQ.2) 1 CALL FYP(N,M,ILU-1,IL1U,IL2U,JSY(N,M+1))

Then NMOUT(N,M) is set equal to 1 and the x-shock analysis is closed by an ELSE statement.

The same analysis, with obvious changes, is repeated for the y-shocks (the entire procedure is easily modified by interchanging x and y, and N and M).

6.3 Physical Relevance of the Technique

Let us discuss the legitimacy of the redefinition of f-terms introduced in the NEIGHBOR subroutine. First, let us consider an x-shock, as in Fig. 5, and the two points, A and B, that are affected by the subroutine. In Fig. 5a the low-pressure region is to the left of the shock. The opposite happens in Fig. 5b. The flow may be supersonic at A. In the case of Fig. 5a, the flow must run from left to right; in the case of Fig. 5b, from right to left. In either case, the values in A would be computed correctly (both characteristics and the velocity vector would point toward the shock from the same direction (Fig. 6). If the flow is subsonic at B, the (u − a)-characteristic points towards the shock in Fig. 6a and the (u + a)-characteristic points toward the shock in Fig. 6b. Therefore \(R^x_2\) and \(R^x_1\) are computed correctly, the former in case (a) and the latter in case (b). These are the elements needed to evaluate the shock through the function Σ, to be defined in Sect. 6.

Fig. 5
figure 5

Low- and high-pressure sides of an x-shock

Fig. 6
figure 6

Characteristics relative to a shock

If the flow is subsonic at A, that means that the shock moves very rapidly into the region containing A (that is, to the left in Fig. 5a and to the right in Fig. 5b). Relatively to the moving shock, the flow is still supersonic at A. Therefore, in such a frame all the f x-terms must be approximated using up-wind differences, as the NEIGHBOR subroutine prescribes. On the other hand, if all differences are taken from the same side, certain simplifications occur and the following chains of identities result:

$$\displaystyle \begin{aligned} \begin{array}{rcl} a_t & = & 0.5 \delta (f_1^x+f_2^x + \ldots ) \\ & = & -0.5 \delta \left[ \lambda_1^x(R_1^x)_x + \lambda_2^x(R_2^x)_x+ \ldots \right] \\ & = & -0.5 \delta \left[ (\lambda_1+W)(R_1^x)_x + (\lambda_2^x+W)(R_2^x)_x+ \ldots -2W a_x/\delta \right] \\ & = & a_T-W a_x \\ \\ u_t & = & 0.5 \delta (f_1^x-f_2^x + \ldots ) \\ & = & -0.5 \delta \left[ \lambda_1^x(R_1^x)_x - \lambda_2^x(R_2^x)_x+ \ldots \right] \\ & = & -0.5 \delta \left[ (\lambda_1+W)(R_1^x)_x - (\lambda_2^x+W)(R_2^x)_x+ \ldots -2W u_x \right] \\ & = & u_T-W u_x \end{array} \end{aligned} $$

where W is the shock velocity, a t u t and a T , u T are the derivatives of a and u in the fixed frame, and the moving frame respectively. Since a t  = a T  − Wa x and u t  = u T  − Wu x , formally, the above results show that a t and u t are evaluated correctly if the f-terms are approximated as prescribed in the NEIGHBOR subroutine. A similar argument legitimizes the use of the subroutine to compute the grid values at B with the only objective, here, of getting a value for \(R_2^x\) (in case a) or \(R_1^x\) (in case b). The whole discussion can be repeated for points A and B in the case of y-shocks (Fig. 7).

Fig. 7
figure 7

Low and high pressure sides of a y-shock

7 Calculation at Shock Points

We stipulate to update all grid points, both in predictor and corrector, using the λ-scheme (or any other scheme) and the NEIGHBOR subroutine. In so doing, all points are updated correctly, except the points on the high-pressure side of a shock. At such points, however, if the grid point is next to an x-shock, we assume that one of the combinations \(R_i^x = a/\delta \pm u\) is correct (the one with i=1 if JI=0, and the one with i=2 if JI=1; note also that the point has INDX(N,M)=1 if JI=1 and INDX(N+1,M)=1 if JI=0).

Let A and B be the low-pressure and high-pressure sides of the shock, respectively. At this stage, we do not make any distinction between the two points located exactly on what we called the shock point J, and the grid nodes bracketing the shock (on the same x-line for an x-shock, on the same y-line for a y-shock). We will also assume that the direction of the normal N to the shock is known, and we will denote by \(\tilde {u}\) and \(\tilde {v}\) the two components of the velocity vector, q, in the direction of the normal and along the shock, respectively; therefore, if i and j are the unit vectors of the x- and y-lines at the shock point, and N = N 1 i + N 2 j, it is also q = u i + v j and \(\tilde {u}= u N_1 + vN_2\), \(\tilde {v}= -u N_2 +v N_1\).

We define the following three parameters:

$$\displaystyle \begin{aligned} \varSigma^x = (a_B+\delta\left| u_B-u_A\right|)/a_A \end{aligned} $$
(2)
$$\displaystyle \begin{aligned} \varSigma^y= (a_B+\delta\left| v_B-v_A\right|)/a_A \end{aligned} $$
(3)
$$\displaystyle \begin{aligned} \varSigma= (a_B+\delta\left| \tilde{u}_B-\tilde{u}_A\right|)/a_A \end{aligned} $$
(4)

If an x-shock is normal to the x-line, Σ x is computed without errors (note that the absolute value takes care of switching \(R_1^x\) and \(R_2^x\) consistently with the relative position of A and B); this is because the contributions of the “wrong” f-terms cancel with each other, and v vanishes identically. The same can be said of Σ y for a y-shock normal to the y-line. If an x-shock is not normal to the x-line but the shock does not cross the y-line in the immediate vicinity of the shock point, or if a y-shock is not normal to the y-line but the shock does not cross the x-line in the immediate vicinity of the shock point, Σ x or, respectively, Σ y are still correct. Minor errors appear in Σ x or Σ y if the shocks cross the line of opposite name, because \(f_3^y\) or \(f_3^x\) may be computed from the wrong side. Such errors are negligible when compared with the relevant contributions to Σ x and Σ y.

For these reason, one is prompted to use Σ x or Σ y in dealing with x-shocks or y-shocks, respectively. The application is easy. Beginning again with an x-shock, note that, if [ ] denotes a jump across a shock,

$$\displaystyle \begin{aligned} \left[u \right] = \left[ \tilde{u} \right] N_1 \end{aligned}$$

since \([u] = [\tilde {u} N_1 - \tilde {v} N_2]\) but \([\tilde {v}] = 0\). The normal relative Mach number of the shock is

$$\displaystyle \begin{aligned} M=(\tilde{u}_A-W)/a_A \end{aligned} $$
(5)

The Rankine-Hugoniot conditions are:

$$\displaystyle \begin{aligned} \begin{array}{rcl} a_B & = & a_A \frac{[(\gamma M^2-\delta)(1+\delta M^2)]^{1/2}}{(1+\delta)M} \\ \tilde{u}_B &=& \tilde{u}_A+a_A\frac{1-M^2}{(1+\delta)M} \\ \tilde{v}_B &=& \tilde{v}_A \\ S_B &=& S_A+\frac{1}{2\delta \gamma} \ln {\frac{\gamma M^2-\delta}{1+\delta}}- \gamma \ln{\frac{(1+\delta)M^2}{1+\delta M^2}} \end{array} \end{aligned} $$
(6)

From these equations and (2) we obtain

$$\displaystyle \begin{aligned} \varSigma^x=\frac{1}{(1+\delta)M} [\sqrt{(\gamma M^2 -\delta)(1+\delta M^2)}+\delta N_1(M^2-1)] \end{aligned} $$
(7)

which yields the basic relationship between Σ x and M; consequently, if Σ x is known, M can be computed from (7). Similarly, for a y-shock, (3) and (6) can be used to get M from Σ x.

When M is close to 1, the inversion of (7) by iterations may present some difficulty (during the process, M may occasionally become less than \(\sqrt {\delta /\gamma }\), causing the radicand in (7) to become negative). It is safer to store the values of Σ x and Σ y at the end of the previous step into an array, SIGMA(J), and then to recompute (2) and (3) and store them into another array, SIG(J), as we start the calculation of the shock. Meanwhile, also the old values of N 1 must have been stored in one array, EN1O(J), and the new values (see Sect. 8) must be stored in another array, EN1(J). It is then possible for each shock point, to calculate the increment ΔΣ x or ΔΣ y, and ΔN 1.

Then, from (7) we obtain

$$\displaystyle \begin{aligned} \varDelta M= \frac{(1+\delta) M \ \varDelta \varSigma^x - \delta (M^2-1) \ \varDelta N_1} {\rho M - (1+\delta) \varSigma^x+ 2\delta M N_1} \end{aligned} $$
(8)

where

$$\displaystyle \begin{aligned} \rho= \frac{\gamma -\delta^2+2\gamma \delta M^2} {\sqrt{(\gamma M^2-\delta)(1+\delta M^2)}} \end{aligned}$$

If we stipulate that the variation of the shock slope in a single step is not as important as the variation of Σ x and M, the following, simpler formula can be used:

$$\displaystyle \begin{aligned} \varDelta M = \frac{(1+\delta)} {\rho - (1+\delta)\varSigma^x/M+2\delta N_1} \varDelta \varSigma^x \end{aligned} $$
(9)

In this way, M at the end of the step is obtained. A parallel procedure allows M to be updated at all y-shocks.

The displacement of a shock point is obtained as follows. First, the normal shock velocity, W is computed from (8):

$$\displaystyle \begin{aligned} W=\tilde{u}_A-\tilde{a}_A M \end{aligned} $$
(10)

For an x-shock (J in Fig. 8a), its new position on the x-line, J′, is obtained from

$$\displaystyle \begin{aligned} \begin{array}{rcl} x_{J'} & = & x_J+\varDelta s \\ & = & x_J +W\varDelta t \ N_1 \end{array} \end{aligned} $$
(11)

(note that Δs is the hypotenuse, not the cathetus of a right triangle). For a y-shock, Fig. 8b holds.

Fig. 8
figure 8

Displacement of a shock point

The shock calculation is now completed by a correct updating of the values at point B, obtained using the Rankine-Hugoniot conditions (6).

Comments and further refinements of this subroutine [including the use of Σ as defined in (4)] will be found in Sect. 10.

8 Shock Detection

The detection of a shock as a rapid transition in some significant parameter ( for example, pressure) in a compressive mode (that is, with pressure increasing in the direction of the flow) seems to be a major concern for most numerical analysts. Having applied the procedure described below to a large number of problems, however, I never found any difficulty.

8.1 Shocks Generated by Coalescence of Waves

As mentioned in Sect. 2, shocks are generated either by a gradual coalescence of compression waves or by an abrupt variation in the slope of a rigid wall. Considering the first case first. We see from Fig. 9 how coalescence of characteristics preludes to a possible formation of a shock. The upper part of the figure shows some (u − a)-characteristics in the process of coalescing in time; the lower graphs represent \(\lambda ^x_2\) and its first and second derivatives as functions of x; at the initial time. Clearly, the inflexion point of \(\lambda _2^x(x)\) is the point to be monitored because it will eventually become the origin of a shock. Working on a smooth distribution of data, it is easy to evaluate an approximation to \(d \lambda ^x_2 /dx\) by two-point differences and then again an approximation to \(d^2 \lambda ^x_2/dx^2\) by two-point differences. The possible location of a shock point can be found by interpolation over the interval having a negative second derivative on the left and a positive second derivatives on the right. Note that coalescence will occur anyhow, regardless of the flow being subsonic or supersonic on either side; in other words, the shape of the curve, not its vertical position with respect to the horizontal axis is our subject of concern.

Fig. 9
figure 9

Coalescence of characteristics

In the numerical handling of complicated flows, minor oscillations may occur that, although irrelevant for all practical purposes, may confuse the issues in the search for the origin of a shock. The situation, almost paradoxically, is most critical in the simplest cases. Think of a theoretically constant distribution, represented numerically by data with alternate positive and negative errors of the order of 0.00001. Obviously, a second derivative approximated as said above is also alternatively positive and negative, so that possible loci of incipient shocks would be detected at every second node. The additional testing on the shock strength, to be described below, would definitively eliminate all such accidental guesses; nevertheless, some precaution can be taken in defining the approximations to the first and second derivatives of \(\lambda _2^x\). Let us simplify the notation by eliminating the subscript and the superscript in \(\lambda _2^x\) and using instead a subscript to denote the nodal point where λ is defined. Imagine having replaced λ n with its mean-square value obtained by a linear approximation over five points; the first difference, Δλ is thus the slope of the approximating straight line, given by:

$$\displaystyle \begin{aligned} \varDelta \lambda= \lambda_{n+1}-\lambda_{n-1}+2(\lambda_{n+2}-\lambda_{n-2}) \end{aligned}$$

and the second difference, Δ 2 λ can be obtained by subtracting Δλ n−1 from Δλ n :

$$\displaystyle \begin{aligned} \left. \varDelta_2 \lambda \right|{}_{n-1/2}= -\lambda_{n+1}- \lambda_{n-2}- \lambda_{n-1}- \lambda_{n}+ 2(\lambda_{n+2}+\lambda_{n-3}) \end{aligned}$$

Naturally, the test can only begin at a value of n that leaves n − 3 still at the boundary. If the boundary is denoted by N = 2, the first point we can test is N = 5. Similarly, the test must end at point N = NC − 3 if the last point on the axis is denoted by NC. Testing for shocks near the boundaries, however, is not necessary. If any shock crosses such lines, most likely it is a shock of the other family (Fig. 10).

Fig. 10
figure 10

Shock near a wall

The cells where the inflection points are located are found, as said above, where Δ 2 λ n  < 0 and Δ 2 λ n+1 ≥ 0. We should also make sure that the pressure (or, equivalently in this as yet isentropic environment, the speed of sound) increases in the right direction. To this effect, it is convenient to determine Δa using the same mean-square linear approximation mentioned above for Δλ. A cell containing an inflexion point is temporarily marked, and a tentative location for the incipient shock is defined:

$$\displaystyle \begin{aligned} x_s= x_n - \frac{\varDelta_2 \lambda_n} {\varDelta_2\lambda_{n+1}-\varDelta_2 \lambda_n} \varDelta x \end{aligned}$$

The point is not accepted as a shock point under three circumstances:

  1. (1)

    Σ x, as defined by (2), is less than a prescribed tolerance, or

  2. (2)

    the pressure jump is too low, or

  3. (3)

    there is a shock point already in the cell or in any of the two adjoining cells.

The first criterion is used to discard “shocks” with too low a relative Mach number; Σ x > 1.02 is a reasonable criterion, eliminating shocks with M < 1.03. The second criterion is necessary to discriminate between shocks and contact discontinuities (as in the breaking of a diaphragm in a cylindrical pipe). For a shock generated by coalescence of characteristics in a still isentropic environment, a test on a is equivalent to a test on p since p is proportional to a power of a; therefore, the second criterion, if applied with the proper tolerance, is a redundant repeat of the first. In the case of an original contact discontinuity, instead, the speed of sound may change strongly in one cell, with pressure and velocity remaining practically the same. Thus, the value of Σ may largely exceed the prescribed tolerance and make a contact discontinuity be accepted as a shock and computed accordingly. The third criterion is simply meant to avoid overcrowding of shock points. It is interesting to note that it can be easily written in the form:

IF(JSX(N,M)+JSX(N+1,M)+JSX(N+2,M).NE.0) GO TO 2

where 2 is a statement outside and beyond the introduction of a new shock point.

If the new shock point is accepted, JI is set equal to 0 or 1 according to the rule mentioned in Sect. 3. Then, a preliminary estimate of the shock slope at that point is made. With reference to Fig. 11a, we define two neighborhoods of the new shock, J; the upper neighborhood, formed by the segments AB, CD, and EF, and the lower neighborhood, formed by the segments FG, DH, and KM. We search for other shock points on the upper neighborhood. The index, INDP, defined by

INDP=INDX(N,M+1)+INDX(N+1,M+1)         +INDX(N+2,M+1)+INDY(N,M+1)+INDY(N+1,M+1)

Fig. 11
figure 11

Neighborhood of a shock point

equals the number of such shocks. If INDP differs from zero, the averages of the x- and y-coordinates of the shocks are evaluated and define a single point. U, as the upper neighbor of J. The same procedure generates a lower neighbor, L, if any shock point exists in the lower neighborhood of J. If neither U nor L are found, the new shock point, J, is still isolated and it is dropped from consideration.

There is a possibility (particularly when the grid is very fine) to have no shocks in the region explored as shown in Fig. 11, but still a significant shock located, for example, as U in Fig. 12. In such a case, it is convenient to extend the search to a line above m + 1 and a line below m − 1 (for an x-shock), limitedly to shocks of the same family.

Fig. 12
figure 12

Neighborhood of a shock point

If both U and L exist, the abscissa of J is corrected to be a weighted average between the abscissas of U and L. If only L exists, U is made to coincide with J; if only U exists, L is made to coincide with J. If at least one neighbor exists, the angle α is defined using the coordinates of U and L, as the angle between UL and the x-line:

$$\displaystyle \begin{aligned} \alpha= \arctan[(x_U-x_L)/(y_U-y_L)] \end{aligned} $$
(12)

Please take account of some additional comment on the definition of α in Sect. 10.

The same procedure is repeated for y-shocks, working along y-lines. The above outline can be used, replacing u ± a with v ± a, x with y, JSX with JSY, increments and decrements of N with increments and decrements of M, and switching INDX and INDY with one another. The “upper” and “lower” points are now points to the right and to the left of the y-line, respectively. The index, JI, has to be set equal to 2 or 3 according to Δa being negative or positive. Figure 11a is replaced by Fig. 11b and Fig. 12a by Fig. 12b. Equation (12) is replaced by

$$\displaystyle \begin{aligned} \alpha= \arctan[(y_U-y_L)/(x_U-x_L)] \end{aligned} $$
(13)

8.2 Shocks Produced by Abrupt Changes in Geometry

If, somewhere in a supersonic flow, the slope of a rigid wall changes abruptly, locally producing a sudden, non-isentropic jump in the flow parameters, two possibilities must be considered:

  1. 1.

    The perturbation is large; a local subsonic region is formed, preceded by a normal shock, or

  2. 2.

    The perturbation is sufficiently small; the flow is deflected abruptly across an oblique shock, attached to the corner in the wall.

Both situations may occur under different circumstances:

  1. (a)

    in a fixed geometry, by an impulsive start of the calculation with supersonic flow prescribed.

  2. (b)

    in a variable geometry, when a wedge or a bump develops above a previously straight wall.

In any event, the same procedure can be followed, that consists of freezing the environment of the corner during the calculation and looking at the possible existence of a steady, attached shock. The scale of the flow-field in the immediate vicinity of the corner is indeed very small and an unsteady flow may be treated as a succession of quasi-steady fields.

The input data are: the velocity vector at the wall node immediately ahead of the corner, and the deflection angle produced by the wall, 𝜖. The angle θ between an attached shock and the impinging flow is defined by:

$$\displaystyle \begin{aligned} \zeta^3+b\zeta^2+c\zeta+d=0 \end{aligned} $$
(14)

where

$$\displaystyle \begin{aligned} \begin{array}{rcl} && \zeta = \sin^2 \theta,\ \ b=-2M_1^2 - 1 - \gamma \sin^2 \epsilon, \\ && c = (2M_1^2+1)/M_1^4+[(1+\delta)^2 + 2 \delta / M^2_1]\sin^2 \epsilon, \ \ d=-(\cos^2 \epsilon)/ M_1^4 \end{array} \end{aligned} $$

and M 1 = q/a at the node on front of the corner.

A subroutine to solve (14) is needed. We can make it as a function defining θ by the code name SHANG, as follows:

FUNCTION SHANG(SM,SDO,GAMMA,PI,KUT)     SHANG=0.     GD=.5∗(GAMMA-1.)     KUT=1     B=-1.-2./SM-GAMMA∗SDO     C=2./SM+1./SM∗∗2+((1.+GD)∗∗2+2.∗GD/SM)∗SDO     D=-1./SM∗∗2∗(1.-SDO)     P=(3.∗C-B∗∗2)/9.     Q=(2.∗B∗∗3-9.∗B∗C+27.∗D)/54.     IF(Q∗∗2+P∗∗3.GT.0.)RETURN     KUT=0     SQRP=SQRT(-P)     ANG=ASIN(-Q/(P∗SQRP))     SIG1=SIN(ANG/3.)     SIG2=SIN((2.∗PI+ANG)/3.)     SIG3=SIN((4.∗PI+ANG)/3.)     SIGMAX=AMAX1(SIG1,SIG2,SIG3)     SIGMIN=AMIN1(SIG1,SIG2,SIG3)     IF(SIG1.EQ.SIGMIM.OR.SIG1.EQ.SIGMAX)GO T0 1     SHANG=ASIN(SQRT(2.∗SQRP∗SIG1-B/3.))     RETURN 1   IF(SIG2.EQ.SIGMIN.OR.SIG2.EQ.SIGMAX)GO T0 2     SHANG=ASIN(SQRT(2.∗SQRP∗SIG2-B/3.))     RETURN 2   SHANG=ASIN(SQRT(2.∗SQRP∗SIG3-B/3.))     RETURN END

In the calling sequence, SM is the square of q/a in front of the corner, SDO is the square of sin 𝜖, GAMMA is the ratio of specific heats, PI is π, and KUT its a flag defined by the function itself. We recall that, if (14) has a single real root, the shock cannot be attached; in such a case, the functions return with KUT=1 to let the code proceed without attempting to force an attached shock at the corner (the detached shock will then be detected as explained above in (A) and it will be forced to be normal to the wall). If (14) has three real roots, the one of interest is the middle one (the other two define a strong attached shock and an expansion shock, respectively). The function is thus defined, and KUT set equal to 0.

9 Shock Tracking; Elimination of Redundant Shocks

When the detection of new shocks is completed, the arrays providing the shock information may contain data pertaining to shock points already existing at the previous computational step, as well as data pertaining to newly detected points.

9.1 Elimination of Shocks

The first question to be answered is. “Does any mesh interval contain more than one shock?” To answer the question, the entire array of shock points is checked. For each value of J, we test, in the case of an x-shock, whether JSX(NS(J)+1,MS(J)) equals J or not. If it does not, that means that there are two shocks, one defined by the index J and another by the index JSX(NS(J)+1,MS(J)), in the same interval. The shock that has the smaller Mach number (TMA) is dropped. We proceed similarly if J denotes a y-shock and JSY(NS(J),MS(J)+1) is not equal to J. Another reason for eliminating a shock is its progressive weakening produced by interactions with expansion waves; this is accomplished by testing whether Σ x (or Σ y) are below the prescribed tolerance and dropping the corresponding shock accordingly.

A shock point cannot be eliminated within a DO-loop ranging over the total number of shock points (JA), because JA itself decreases by 1 any time a shock is dropped. Keeping this in mind, we build an explicit loop in the form:

   J=O 1  J=J+1 2  IF(J.GT.JA) GO TO 3

Here we test for possible causes of shock elimination. If any of them is found, the code is sent to statement 4. Otherwise, it continues as follows:

   GO TO 1 4  CALL MOVE(J)    GO TO 2 3  CONTINUE

The subroutine MOVE restores JSX to zero at NS(J)+1, MS(J) or JSY to zero at NS(J), MS(J)+1, according to J being an x-shock or a y-shock, for all the shock points. Then, it moves the last point in the shock array (JA) to the position J, decreases JA by 1, and redefines all JSX and JSY for all the shock points.

9.2 Shocks Crossing Mesh Lines

Next, the question to be answered is: “Did any point, in its motion along an x-line or a y-line, cross over a line of the opposite family?” To answer the question in the case of x-shocks, a new value of NS, called NSN, is computed from the new value of XS for each point. If NSN and NS differ, not only NS is updated but some field values must be changed. Using Fig. 13, assume that the shock point, P has moved to a new position, Q. The flow values at A, that originally pertained to one side of the shock, now pertain to the opposite side; consequently, the code replaces them with the new values at B. Opposite action has to be taken if the shock point moves from Q to P; the values at A must be replaced with the new values at C. One proceeds in a similar way for y-shocks. Obviously, after checking the crossings, the distributions of JSX, JSY and INDX, INDY are updated. Note: if the shock moves from P to Q, point C must acquire the values of JSX and INDX previously attributed to point A, and JSX, INDX at A must be made equal to zero. Similarly, if the shock moves from Q to P, the values of JSX, INDX formerly at C must be moved to A, and they must be set equal to zero at C.

Fig. 13
figure 13

Shock point moving across mesh lines

9.3 Second Process of Elimination

After analyzing the crossings, the entire procedure described in Sect. 8.1 is repeated. The apparent redundancy can be justified with the help of Fig. 14. In Fig. 14a, we see two shocks, J and K, in the same cell, prior to the analysis of crossings. After the analysis, J remained in the same cell but K went to the next. One of these two shocks should have been eliminated before letting K cross over. In fact, to all practical effects, J should have been equal to K; their velocities should have been the same and they should have crossed over together. If this did not happen, most probably it is because J is a newly found shock point, having a poorly defined velocity. If we do not kill J before K crosses over to the next cell, a test for two shocks in one cell made after the crossing fails and J is kept alive in the next computational step. In principle, this should not be a cause of concern; one of the two shocks should have a vanishing strength and be dropped at the end of the step. Unfortunately, according to the sequence of events in the calculation, the “good” shock could be dropped, leaving the “bad” one in a wrong position with a wrong strength; this may trigger a series of catastrophic events or, at least, produce a perturbation that may require many computational steps to be ironed out. Figure 14b shows the opposite case, where two shocks in two different cells fall into the same cell after crossing; this requires the test for two shocks in one cell to be taken after the crossing.

Fig. 14
figure 14

Illustrating a need for elimination of shocks

Then, a search for neighbors of all shock points is performed again, as described in Sect. 7. All isolated shocks are dropped. For the remaining shocks, the values of α are defined by (12) or (13). Shock points whose \(\left | \alpha \right | \) is larger than 50 are dropped (a shock of the opposite family should appear in their immediate neighborhood as more representative). See also, in Sect. 10, how to drop points that may have been detected as belonging to oblique shocks but are, instead, on an oblique contact discontinuity.

At this stage, we have all the ingredients needed to define Σ x or Σ y, according to (2) or (3), at all shock points. All points where Σ x or Σ y is less than 1.02 are dropped. The normal, relative Mach number, M is evaluated according to (7) for x-shocks or its counterpart for y-shocks. The iterations needed to get M are, at this stage, quite safe. The values of Σ x or Σ y, N 1 and M will be used at the next computational step as initial values for the shock computation.

Here is the function TMD that I use to define M(Σ, N 1):

   FUNCTION TMD(SIG,EN1,GI,GL,GAMMA)    GD=.5∗(GAMMA-1.)    GE=1.+GD    G1=3./(GI+GL∗EN1-1.)    TMD=1.+G1∗(SIG-1.)    KIP=1 1  SM=TM∗∗2    DSIG=(SQRT((GAMMA∗SM-GD)∗(1+GD∗SM))+GD∗(SM-1)∗EN1)          /(GE∗TM)    SIG1=SIG-DSIG    TMD=TMD+G1∗SIG1    KIP=KIP+1    IF(ABS(SIG1).LT.1.E-8)RETURN    IF(KIP.LT.30)GO T0 1    WRITE(6,∗) FAILURE AT TMD    RETURN    END

10 Finding a Robust Normal to a Shock

In Sect. 6, we saw that two parameters are necessary to determine the shock normal relative Mach number, Σ x (or Σ y, or Σ, as the case may be) and N 1. The former is easily and safely computed using information from the nodes (see also Sect. 11 for more details). The second, instead, requires a knowledge of the shock geometry and it is the most difficult parameter to determine for shock-fitting. There are several sources of difficulties. Firstly, the geometric pattern of all shocks as a whole is not a basic information of the code. We should keep in mind that the shock pattern is two-dimensional, but the computer (at least, so far) works essentially in a one-dimensional mode. The shock information is stored at random, without any reference to the structure of the shocks in the computational plane; this makes creation, manipulation, and suppression of shock points very easy and the related subroutines independent of the physical problem under scrutiny. To determine the normal to the shock at any of its points, however, we must know which points lie on each side of it along the same shock line. We have seen in Sect. 7 how such points can be detected; here we want to examine a few typical cases, to evaluate the efficiency and correctness of the technique.

If complex shock patterns develop, care must be taken not to let the orientation of the normal at any given point change abruptly from step to step or, even worse, oscillate back and forth between two widely different values. This is, most probably, a non-physical behavior; the flow downstream is forced to undergo violent changes; the instability may not remain confined to the immediate vicinity of the shock point and catastrophic instabilities may even be triggered. Situations of this kind are likely to appear at triple points. See, for example, in Fig. 15 a possible evolution of shocks at a typical Mach reflection. Point A, the triple point, is not detected as a shock point. During the evolution, shock points appear and disappear, as shown in the figure.

Fig. 15
figure 15

Moving triple point

In this case, all shock points are x-points. From the figure, the slope of the shocks at each point is clear, but we must assure that our technique for detecting “upper” and “lower” points provides a reasonable approximation to such slopes, and that changes occur progressively and with a reasonable smoothness (taking into account that the advances in time are themselves discretized). The three crucial points in this figure are B, D, and E. Figures 16, 17, 18 show what the “upper” and “lower” points are, for B, D and E, respectively; such points are marked by black dots. In the first two diagrams of Fig. 16 the slope, as determined by the black dots, is very close to reality; in the third, it seems to depart substantially. Later, we will come back to this pattern and discuss a possible variant. Now, we limit ourselves to observe that the apparently abnormal definition of the slope at B is simply an anticipation of the fact that B itself is about to be swallowed by the vertical stem of the shock.

Fig. 16
figure 16

Definition of slopes at B

Fig. 17
figure 17

Definition of slope at D

Fig. 18
figure 18

Definition of slope at E

The numerical definition of the slope at D does not create any problem in the present case; D is, indeed, always considered as belonging to the vertical stem. For point E, considerations similar to the ones exposed above for B are in order. As the vertical stem lengthens and swallows more and more of the left oblique shock, the slope at E tends to become vertical, as it should be since at the next time step (not shown in the graphs) point E becomes itself a part of the vertical stem.

Many other patterns, involving y-shocks as well as x-shocks, can appear in the course of a calculation but, as far as we know, the substantial facts remain the same. I would like to conclude the presentation of examples by showing another typical shock interaction pattern (Fig. 19) in which three shock points (in this case, two of the x-type and one of the y-type) appear on three sides of the same cell. The shock points are labeled A, B, and C; the black dots, labeled a, b, and c, are the points to be used to determine the slopes at A, B, and C, respectively, according to the technique described above. Again, we may see that the slope thus determined is quite acceptable.

Fig. 19
figure 19

Definition of slopes at a triple point

10.1 Eliminating Wrinkles on a Shock

Another problem in shock-fitting is the stability of a shock line itself, regardless of interactions. We must consider two cases.

The first is the occasional wrinkling of a shock line. A real shock is a taut surface. Consider, indeed, a wrinkled shock (ABCDE), as shown in Fig. 20. Assuming that the impinging flow is supersonic, uniform and its velocity vector, q, is horizontal, the flow downstream of BC would be tilted downwards, and the flow downstream of CD upwards. Such a pattern would be physically impossible; at B a Mach reflection would appear producing a local strengthening of the shock and, consequently, pushing it to the left; at C an expansion would be produced, weakening the original shock and pulling it to the right. Numerically, wrinkles may appear if the slope of the shock is computed as the slope of the straight line joining the “lower” and “upper” points. Another glance at Fig. 20 explains why. Suppose that the solution to the problem were a vertical, steady shock, separating a supersonic flow on the left from a subsonic flow on the right; and suppose that, for any numerical accident (even a different round-off in the calculation of two adjacent shock points), a minor wrinkle appeared (grossly amplified in Fig. 20). In evaluating the slope at B as the slope of the line between A and C, and the slope at C as the slope of the line between B and D, both lines would still be vertical; no correction would be made to the shock Mach numbers and the original error in their velocities W, that had produced the original wrinkle, would not be corrected. The wrinkle would not be ironed out and it could worsen, if the original error persisted. If the shock is oblique and the flow is supersonic on both sides of it, the remedy is very simple: it suffices to evaluate the slope of the shock using one-sided differences (that is, using the coordinates of the point itself and of either the “upper” or the “lower” point). By so doing, the actual slope between two adjacent shock points will be used. How should one choose between one side or another? For oblique shocks embedded in supersonic flows, the slope should be computed from the side opposite to the deflection of the flow (Fig. 21). In practice, we will use the “lower” point for x-shocks having u > 0, N 2 < 0 or u < 0, N 2 > 0 and for y-shocks having N 2 < 0.

Fig. 20
figure 20

Wrinkled shock

Fig. 21
figure 21

One-sided differences on shocks

For shocks followed by a subsonic flow it is more convenient to use two-sided differences to give equal weight to all points in the subsonic environment. In this case a slight correction on the value of Σ defining the shock Mach number should be used. Without attempting a sophisticated but complicated evaluation of the correction factor, we can argue as follows: The correction, as Fig. 20 shows, is related to the local curvature of the shock curve. For an x-shock, if the second difference of the x-coordinates is negative (as at point B in Fig. 20) and u > 0, Σ must be increased to make the shock stronger; if u < 0, Σ must be decreased. The same can be said for a y-shock, provided that y and v are used in lieu of x and u. The opposite should be done when the second differences are positive. If we write the correction to E in the form:

$$\displaystyle \begin{aligned} \varSigma(1\pm \epsilon \varDelta_2 x ) \end{aligned}$$

the value of 𝜖 should be of the order of 0.0001.

11 Missing Section

.....

12 Missing Section

.....

13 Missing References

.....