Translated from the author's Korean original. Read the original (한국어)
How to Make an Outflow Stop Reflecting Sound — Navier–Stokes Characteristic Boundary Conditions
Zero incoming amplitude lets sound out and lets the mean wander. Relaxation near σ=0.25 pulls the mean back without turning the outlet into a wall.
A compressible LES blew up after six hours. There was no NaN in the log, no shock anywhere. The mean pressure had drifted up by 0.3 bar, and acoustic waves were ricocheting back into the domain from the outlet. The culprit was a zero-gradient extrapolation at the outflow. Today we walk all the way through Poinsot–Lele's NSCBC (1992) using one single 1D acoustic pulse — the cleanest way to see why an outflow has to listen to incoming waves, not extrapolate them.
The Mach slider runs from 0 to 1.6. Raising it drops the count of arrows that point back into the domain.
Below Mach 1 one bold red arrow still points inward. Past Mach 1 that arrow leaves with the flow. The number of signals the outlet must set is on that screen.
The Domain Diverged After Six Hours#
External boundaries kill compressible solvers more often than shocks do. A zero-gradient outflow copies momentum and energy into the ghost cells, but that copy creates an acoustic impedance mismatch. Any acoustic wave that should leave the domain instead hits a jump in impedance, and part of it bounces back. How much of that jump is transmitted, and how much comes back, is written out on the acoustic side of an interface.
In LES, DNS, or combustion runs this reflection accumulates in the mean field. Before Reynolds averaging even settles, the outlet starts acting like a resonator and the pressure drifts slowly upward. NSCBC fixes the whole class of problems with a single principle — specify the amplitude of incoming characteristic waves directly.
Five Signals Coming Out of the Boundary#
For the 1D Euler equations in conservative form we have
where is the flux Jacobian. Its right-eigendecomposition gives five eigenvalues (for a planar boundary in 3D), , where is the velocity and the speed of sound.
Each eigenvalue corresponds to one characteristic wave. is a left-going acoustic, carries entropy and transverse velocity (transported with the fluid), and is a right-going acoustic.
The bold arrow on the Mach slider above is . A subsonic outflow lets only that one wave back in. Exactly one boundary value is required. Pinning velocity, pressure, and temperature together over-specifies the row, and the solver dies.
LODI — The Plane-Wave Approximation#
The brain of NSCBC is the Local One-Dimensional Inviscid (LODI) relations. Drop viscous and transverse derivatives for one time step at the boundary and the conservation equations become ODEs in the characteristic amplitudes .
where , , and is the entropy wave.
The point: the outgoing waves and are computed by upwind finite differences from the interior. Only the incoming wave has to be supplied by the BC. That one line is NSCBC in its entirety.
The Trap of Perfect Non-Reflection — Drifting Mean Pressure#
The simplest nonreflecting condition sets the incoming wave to zero.
Acoustics leave cleanly. But integrate LODI: . If the time average of has any small positive bias, drifts without bound. The code never crashes — it just lifts past 1 atm six hours later.
Rudy & Strikwerda (1980) and Poinsot & Lele (1992) added a first-order relaxation term to kill the drift.
is the target pressure, a characteristic domain length, the maximum expected Mach at the boundary. is the relaxation strength, typically .
Poinsot–Lele Relaxation — One Knob Called σ#
has two faces:
- too small (): nearly perfectly nonreflecting. Mean drift is uncontrolled.
- too large (): the boundary stiffens again and starts reflecting acoustics.
The acoustic reflection coefficient scales as to leading order, where is the wave transit time. In LES practice, once domain length and mean Mach are fixed, is tuned in the range 0.1–0.5.
Set the transit time to a domain crossing, . Then and the estimate collapses to . The usual is a 0.25 amplitude bounce under that reading. Moving from 0.1 to 0.5 drags across the same interval. is linear in , so doubling 0.25 to 0.5 doubles . The factor is the Mach correction. It is 1 at and at , a 25% cut in . As approaches 1, shuts off, the same direction as an incoming arrow disappearing on the slider.
Switch the mode between Zero-gradient and NSCBC. The slider is the factor multiplying the incoming wave.
On Zero-gradient the Gaussian pulse bounces off the right edge almost intact. The reflection coefficient sits near 1. NSCBC lets the pulse leave, until climbs past 0.5 and the echo piles up again. The lower curve is at the boundary.
Python — A Sound Pulse Meets an Outflow#
A 1D linearized Euler model written in the two Riemann invariants and . Toy problem: throw a rightward Gaussian pulse into a quiescent medium and compare the two BCs.
import numpy as np
def linearized_acoustic_pulse(bc='nscbc', sigma=0.05, N=240, n_steps=400):
"""1D linearized Euler with right-side acoustic outflow.
Returns p'(x) at final time for each BC mode."""
# grid / sound speed / CFL
c, cfl = 1.0, 0.5
dx = 1.0 / N
Ap = np.exp(-((np.linspace(0, 1, N) - 0.22) ** 2) / 0.003) # right-moving pulse
Am = np.zeros(N) # left-moving = 0
for _ in range(n_steps):
Ap_new = Ap.copy()
Am_new = Am.copy()
# Ap travels at +c → left-upwind
Ap_new[1:] = Ap[1:] - cfl * (Ap[1:] - Ap[:-1])
Ap_new[0] = 0.0 # quiescent inflow
# Am travels at -c → right-upwind
Am_new[:-1] = Am[:-1] - cfl * (Am[:-1] - Am[1:])
# right boundary — the heart of NSCBC
if bc == 'wall':
# zero-gradient: incoming Am equals Ap → full reflection
Am_new[-1] = Ap_new[-1]
else:
# NSCBC: incoming Am pinned via reflectivity sigma
Am_new[-1] = sigma * Ap_new[-1]
Ap, Am = Ap_new, Am_new
p_prime = 0.5 * (Ap - Am) # p' in normalized units
return p_prime
p_reflect = linearized_acoustic_pulse(bc='wall')
p_nscbc = linearized_acoustic_pulse(bc='nscbc', sigma=0.05)
print(f"max |p'| (reflect): {np.max(np.abs(p_reflect)):.3e}")
print(f"max |p'| (nscbc): {np.max(np.abs(p_nscbc)):.3e}")
# reflect: 0.998 / nscbc: 0.025 → two orders of magnitudeFor the same pulse, zero-gradient keeps almost all of it (reflection), while NSCBC suppresses it by two orders of magnitude. Sweeping traces an almost linear reflection coefficient.
The comment records peaks of 0.998 and 0.025. Their ratio is about 40. The code multiplies the outgoing wave by , yet the peak ratio sits closer to 0.025 than to 0.05, because the pulse also leaves and spreads. Divide the logged 0.3 bar by six hours and the mean slope is 0.05 bar/h. With , sets the sign of that slope.
Checklist Before You Ship It#
- Count the boundary type first. Subsonic outflow → 1 BC, supersonic outflow → 0 BCs, subsonic inflow → 4 BCs, supersonic inflow → 5 BCs. Use the figure above to double-check.
- σ tuning is tied to domain length. Double the domain and shifts. Never hard-code an absolute number.
- Do not drop transverse terms blindly. In 3D LES, Yoo & Im (2007) relaxed transverse formulation is more stable.
- NSCBC alone is not enough when shocks hit the outlet. Pair it with a buffer zone (sponge layer) to kill nonlinear reflection.
- Viscous fluxes need separate handling. NSCBC does not address them on its own.
Pinning σ at Zero Lets the Mean Walk Off#
sends acoustics out cleanly and leaves . Any small positive bias in the time average of means pressure has no ceiling. The 0.3 bar after six hours is that integral, sitting in the log. Putting into pulls the drift back, and under it also returns about a quarter of the amplitude.
Push toward 5 and the boundary stiffens until the pulse bounces. Between 0 and 5, the code's 0.05 and the usual 0.25 are two points on the same line. This page stops at "one incoming wave." The tighter account of that single coefficient is how σ at an outlet fixes the reflection.
Related
Share if you found it helpful.