AERO-440 · Lesson 8 of 12 · 24 min

Viscous flows and the Navier-Stokes equations

The Euler screen picked a section for the Swift 900, but the drag that matters to the airline customers is mostly viscous: on a business jet at cruise, skin friction and form drag together make up more than half of the total. The Petrel 19 is the same story at lower speed, with large wetted areas on its high wing, fuselage and nacelles. To predict that drag, the group must solve the Navier-Stokes equations, which add viscosity and heat conduction to the Euler equations. This lesson covers the equations, how their viscous terms are discretized, and a first validation: a laminar flat-plate boundary layer, for which an exact similarity solution exists.

The Navier-Stokes equations

The compressible Navier-Stokes equations keep the conservation form of the Euler equations and add a viscous flux. In compact form,

\[\frac{\partial \mathbf{U}}{\partial t} + \nabla\cdot(\mathbf{F}_c - \mathbf{F}_v) = 0\]

The convective flux \(\mathbf{F}_c\) is the Euler flux. The viscous flux \(\mathbf{F}_v\) contains the viscous stress tensor in the momentum equations and, in the energy equation, the work done by viscous stresses and the heat conducted. For a Newtonian fluid with Stokes' hypothesis, the stress tensor is

\[\tau_{ij} = \mu(\frac{\partial u_i}{\partial x_j} + \frac{\partial u_j}{\partial x_i}) - \frac{2}{3}\mu\,\frac{\partial u_k}{\partial x_k}\,\delta_{ij}, \qquad q_j = -k\,\frac{\partial T}{\partial x_j}\]

The dynamic viscosity \(\mu\) of air varies with temperature, usually through Sutherland's law, and the thermal conductivity \(k\) is linked to it through a Prandtl number of about 0.72. Making the equations dimensionless with a reference length, velocity and density brings out the governing parameters: the Reynolds number, the ratio of inertial to viscous forces, the Mach number and the Prandtl number. At the Tern Block 2 cruise condition, the Reynolds number based on mean chord is about \(10^{7}\): viscous effects are confined to thin layers next to the surfaces and in the wakes, but those layers decide the drag and, near stall, the lift.

The viscous terms change the mathematical character of the equations. The steady Navier-Stokes equations are no longer purely hyperbolic; the viscous terms are second derivatives, which are parabolic in time and elliptic in space. Every point in a viscous flow influences its neighbors by diffusion, and the boundary conditions change accordingly. At a solid wall, the no-slip condition sets all velocity components to zero, and a thermal condition fixes either the wall temperature or the heat flux; an adiabatic wall, with zero heat flux, is the usual choice for external aerodynamics.

Discretizing the viscous terms

In a finite-volume code, the viscous flux at each face needs the velocity and temperature gradients there. On a structured grid, these come from central differences across the face, which are second order and naturally stable because diffusion damps errors. On unstructured grids, the face gradient is usually built from the average of the two cell gradients, corrected with the direct difference between the two cell values along the line joining their centers. The correction matters: averaged gradients alone can let odd-even oscillations go undamped, and on stretched or skewed boundary-layer cells the uncorrected scheme loses accuracy. Viscous terms are central-differenced, never upwinded, because diffusion has no preferred direction.

The viscous terms also make the equations stiff. In a boundary-layer cell a few micrometers thick, the viscous time scale \(\Delta y^{2}/\nu\) is extremely short, as lesson 5 showed. Implicit treatment of at least the wall-normal viscous terms is therefore standard. The resolution requirement is equally severe: lesson 6 showed that \(y^{+} \approx 1\) at the wall means first cells of about 5 micrometers on the Tern Block 2, and the boundary layer needs perhaps 30 to 40 cells across its thickness to resolve the velocity profile.

A laminar check: the Blasius boundary layer

Before trusting a viscous solver with turbulence, the group checks it on laminar flow, where the physics is exact and only numerical error remains. The laminar boundary layer on a flat plate with zero pressure gradient has a similarity solution found by Heinrich Blasius in 1908. Introducing the similarity variable \(\eta = y\sqrt{U/(\nu x)}\) and a stream function \(\psi = \sqrt{\nu U x}\, f(\eta)\), the boundary-layer equations collapse to a single ordinary differential equation:

\[f''' + \tfrac12 f f'' = 0, \qquad f(0) = f'(0) = 0, \quad f'(\infty) = 1\]

The velocity profile is \(u/U = f'(\eta)\). The wall shear stress follows from \(f''(0)\), which gives the local skin-friction coefficient \(C_f = 0.664/\sqrt{Re_x}\). The equation is solved by shooting: guess \(f''(0)\), integrate outward, and adjust the guess until \(f'\) approaches 1 far from the wall. The code below does this with a fourth-order Runge-Kutta integrator and bisection. It then solves the same flow a second way, by marching the boundary-layer equations downstream on a finite-difference grid, implicit across the layer with the Thomas algorithm from lesson 3 and with the normal velocity found from continuity. The marching solver is a simplified relative of a full Navier-Stokes code: it keeps the dominant viscous term and convection, and it must reproduce Blasius's answer.

The Blasius boundary layer by shooting, and a marching finite-difference solution of the boundary-layer equations on four grids.
# Laminar flat-plate boundary layer two ways:
# (1) Blasius similarity ODE f''' + 0.5 f f'' = 0 solved by shooting with RK4;
# (2) a marching finite-difference solution of the boundary-layer form of the Navier-Stokes equations,
#     implicit in y (Thomas algorithm), with v from continuity. Units: U = 1, nu = 1, so Re_x = x.
import math
def blasius(s, eta_max=10.0, n=2000):
    h = eta_max / n; y = [0.0, 0.0, s]
    def F(y): return [y[1], y[2], -0.5 * y[0] * y[2]]
    for _ in range(n):
        k1 = F(y); k2 = F([y[i] + h/2*k1[i] for i in range(3)])
        k3 = F([y[i] + h/2*k2[i] for i in range(3)]); k4 = F([y[i] + h*k3[i] for i in range(3)])
        y = [y[i] + h/6*(k1[i] + 2*k2[i] + 2*k3[i] + k4[i]) for i in range(3)]
    return y[1] - 1.0                                  # want f'(inf) = 1
a, b = 0.2, 0.5
for _ in range(60):                                    # bisection on f''(0)
    m = 0.5 * (a + b)
    if blasius(a) * blasius(m) <= 0: b = m
    else: a = m
fpp = 0.5 * (a + b)
print(f"Blasius f''(0) = {fpp:.5f}  ->  Cf * sqrt(Re_x) = {2 * fpp:.4f}")
def thomas(lo, di, up, rhs):
    n = len(di); c = [0.0] * n; d = [0.0] * n
    c[0] = up[0] / di[0]; d[0] = rhs[0] / di[0]
    for i in range(1, n):
        den = di[i] - lo[i] * c[i - 1]
        c[i] = up[i] / den if i < n - 1 else 0.0
        d[i] = (rhs[i] - lo[i] * d[i - 1]) / den
    x = [0.0] * n; x[-1] = d[-1]
    for i in range(n - 2, -1, -1): x[i] = d[i] - c[i] * x[i + 1]
    return x
def march(ny, x_end=1.0, nx=400):
    Y = 12.0 * math.sqrt(x_end); dy = Y / ny
    u = [1.0] * (ny + 1); u[0] = 0.0; v = [0.0] * (ny + 1)
    x = 1e-4
    for k in range(nx):
        x_new = 1e-4 + (x_end - 1e-4) * ((k + 1) / nx) ** 2    # finer steps near the leading edge
        dx = x_new - x
        lo = [0.0]; di = [1.0]; up = [0.0]; rhs = [0.0]        # wall: u = 0
        for j in range(1, ny):
            uj = max(u[j], 1e-6)
            lo.append(-v[j] / (2 * dy) - 1 / dy**2)
            di.append(uj / dx + 2 / dy**2)
            up.append(v[j] / (2 * dy) - 1 / dy**2)
            rhs.append(uj * u[j] / dx)
        lo.append(0.0); di.append(1.0); up.append(0.0); rhs.append(1.0)   # edge: u = 1
        un = thomas(lo, di, up, rhs)
        vn = [0.0] * (ny + 1)
        for j in range(1, ny + 1):                              # continuity, trapezoidal in y
            dudx = 0.5 * ((un[j] - u[j]) + (un[j - 1] - u[j - 1])) / dx
            vn[j] = vn[j - 1] - dudx * dy
        u, v, x = un, vn, x_new
    tau = (-3 * u[0] + 4 * u[1] - u[2]) / (2 * dy)              # second-order wall gradient
    return 2 * tau * math.sqrt(x)                               # Cf * sqrt(Re_x)
print("Marching solution at Re_x = 1 (similarity makes the result independent of Re_x):")
prev = None
for ny, nx in ((25, 100), (50, 200), (100, 400), (200, 800)):
    val = march(ny, nx=nx)
    err = abs(val - 2 * fpp)
    print(f"  {ny:3d} x {nx:3d} grid: Cf*sqrt(Re_x) = {val:.4f}, error {err:.4f}" +
          ("" if prev is None else f", ratio {prev / err:.2f}"))
    prev = err
Output
Blasius f''(0) = 0.33206  ->  Cf * sqrt(Re_x) = 0.6641
Marching solution at Re_x = 1 (similarity makes the result independent of Re_x):
   25 x 100 grid: Cf*sqrt(Re_x) = 0.6585, error 0.0056
   50 x 200 grid: Cf*sqrt(Re_x) = 0.6586, error 0.0056, ratio 1.01
  100 x 400 grid: Cf*sqrt(Re_x) = 0.6612, error 0.0029, ratio 1.89
  200 x 800 grid: Cf*sqrt(Re_x) = 0.6627, error 0.0014, ratio 2.13

Shooting gives \(f''(0) = 0.33206\) and \(C_f\sqrt{Re_x} = 0.6641\), the classical values. The marching solver approaches this result as both the wall-normal and the streamwise grids are refined, reaching 0.6627 on the finest grid. On the two finest grids the error halves with each refinement, the signature of first-order accuracy in the marching direction, since the scheme uses a backward step in \(x\). On the two coarsest grids the error barely changes, because two errors of opposite sign, from the coarse wall-normal grid and from the start at the leading edge, partly cancel. This is a lesson in itself: an error that does not change between two grids does not prove the solution is converged. Only a systematic study across three or more grids, lesson 10, shows whether the results lie in the asymptotic range.

Plot of the Blasius velocity profile, with u over U on the horizontal axis rising from 0 at the wall to 1 at a similarity coordinate of about 5, and thin horizontal lines showing a stretched grid clustered near the wall.
The Blasius laminar boundary layer. The velocity reaches 99 percent of the free stream at a similarity coordinate of about 4.9; a well-built grid places a dozen or more cells across that thickness, clustered at the wall.

Separation and the pressure gradient

The flat plate has no pressure gradient. On a wing, the pressure falls from the stagnation point to the suction peak and then rises toward the trailing edge. An adverse pressure gradient, rising pressure in the flow direction, decelerates the slow fluid near the wall, and if it is strong enough, the near-wall flow reverses and the boundary layer separates. Separation is where the Navier-Stokes equations show their value and where they make the greatest demands. A separated region is thick, often unsteady, and highly sensitive to the state of the boundary layer upstream, laminar or turbulent. Predicting separation on the Tern Block 2 wing near stall and on the Petrel 19 nacelle afterbody is the central difficulty of the next two lessons.

Laminar, transitional and turbulent flow

At flight Reynolds numbers, boundary layers on aircraft are mostly turbulent. On the Tern Block 2 wing, the boundary layer begins laminar at the leading edge and undergoes transition, usually within the first 10 to 40 percent of chord depending on the pressure distribution and surface finish. Direct solution of the Navier-Stokes equations, DNS, would resolve the turbulent eddies, but lesson 1 showed that DNS of a wing at flight Reynolds number is out of reach. RANS solvers average the equations in time, so that the eddies are represented by a turbulence model. The averaged equations look like the Navier-Stokes equations with an extra stress, the Reynolds stress, and closing them is the subject of lesson 9.

Drag breakdown for the Tern Block 2 half model at the cruise lift coefficient. Values are representative group results, not certified data; one count is 0.0001.
Viscous drag contribution, Tern Block 2 at cruise (RANS, medium grid)Counts
Wing skin friction58
Fuselage skin friction41
Pressure (form) drag, wing and fuselage19
Induced drag96
Interference and other12
Total, wing-body226

The breakdown shows why a viscous solver is indispensable. Skin friction and form drag together make up more than half of the wing-body drag at cruise, and none of them appears in an Euler solution. It also shows where RANS is strong. Skin friction on attached, turbulent surfaces is predicted to within a few percent by good turbulence models on adequate grids, provided the transition location is right. Form drag and interference drag are harder, because they depend on the pressure recovery near trailing edges and junctions, where separation can begin.

Worked problem

Blasius skin friction and drag

Estimate the laminar skin-friction drag on one side of a flat plate 0.5 m long and 1 m wide in air at 30 m/s, with \(\nu = 1.5 \times 10^{-5}\ \mathrm{m^2/s}\) and \(\rho = 1.2\ \mathrm{kg/m^3}\).

Show solution
  1. \(Re_L = 30 \times 0.5/1.5 \times 10^{-5} = 10^{6}\), at the upper edge of the laminar range.
  2. Average skin friction for Blasius: \(\bar{C}_f = 1.328/\sqrt{Re_L} = 0.00133\).
  3. \(D = \tfrac12\rho V^{2} S \bar{C}_f = 0.5 \times 1.2 \times 900 \times 0.5 \times 0.00133 = 0.36\ \mathrm{N}\).

Answer: About 0.36 N. A turbulent layer at the same Reynolds number would give roughly three times as much.

Worked problem

Boundary-layer thickness

How thick is the laminar layer at the end of that plate, using \(\delta_{99} \approx 4.9\,x/\sqrt{Re_x}\)?

Show solution
  1. \(\sqrt{Re_x} = 1000\).
  2. \(\delta_{99} = 4.9 \times 0.5/1000 = 2.45\ \mathrm{mm}\).

Answer: About 2.5 mm, so a grid needs cells of a fraction of a millimeter across it to resolve the profile.

Worked problem

Reading a convergence table

The code reports errors of 0.0056 on the two coarsest grids and 0.0029 and 0.0014 on the next two. Arjun says the coarse result proves the solution was converged. Is he right?

Show solution
  1. An unchanged error between two grids can come from canceling errors, not from convergence.
  2. The finer grids show the error halving, so the result was not converged on the coarse grids.
  3. Asymptotic behavior must be shown on at least three grids.

Answer: No. The coarse grids lie outside the asymptotic range, and the agreement between them is a coincidence of canceling errors.

Common mistakes

  • MistakeThe no-slip condition only affects the first cell.

    InsteadIt controls the whole boundary layer, and the first cell must be thin enough to resolve the near-wall gradient.

  • MistakeViscous terms should be upwinded like convective ones.

    InsteadDiffusion has no preferred direction; viscous terms are central-differenced.

  • MistakeTwo grids that give the same answer prove grid independence.

    InsteadCanceling errors can make two coarse grids agree; use three or more grids and check the observed order.

  • MistakeEuler drag plus a flat-plate friction estimate gives total drag.

    InsteadForm and interference drag depend on the coupled viscous flow, especially near trailing edges and junctions.

Summary and key terms

  • The Navier-Stokes equations add a viscous stress and heat flux to the Euler equations, with the Reynolds, Mach and Prandtl numbers as governing parameters.
  • Viscous terms are central-differenced and usually treated implicitly because they are stiff on thin wall cells.
  • The no-slip condition and an adiabatic or isothermal wall condition replace the inviscid slip condition.
  • The Blasius solution, with \(C_f\sqrt{Re_x} = 0.664\), is a standard check of a viscous solver, and a systematic grid study is needed to show convergence.
  • Viscous drag makes up much of an aircraft's total, and separation in adverse pressure gradients is where viscous prediction is hardest.
Navier-Stokes equations
The conservation laws for a viscous, heat-conducting fluid.
No-slip condition
Zero fluid velocity relative to a solid wall.
Sutherland law
A formula for the temperature dependence of the viscosity of a gas.
Blasius solution
The similarity solution for the laminar boundary layer on a flat plate.
Adverse pressure gradient
Pressure rising in the flow direction, which decelerates the boundary layer.
Separation
Breakaway of the boundary layer from the surface, with reversed flow near the wall.
Drag count
One ten-thousandth of a drag coefficient.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. What is \(C_f\) for a laminar boundary layer at \(Re_x = 4 \times 10^{5}\)?

    Show answer

    \(0.664/632 = 0.00105\).

  2. Why is an adiabatic wall the usual thermal condition for external aerodynamics?

    Show answer

    Heat transfer to and from the skin is small at subsonic speeds, so zero heat flux is a good approximation.

  3. What does Stokes' hypothesis set?

    Show answer

    The bulk viscosity to zero, giving the factor \(-2/3\) in the stress tensor.

  4. Which drag components does an Euler solver omit?

    Show answer

    Skin friction and viscous form drag.

  5. What is the order of accuracy of the marching solver in the streamwise direction?

    Show answer

    First order, since it uses a backward difference in \(x\).

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz