Skip to content
cfd-lab:~/es/posts/2026-07-24-euler-charact…online
NOTE #113DAY FRI CFD기법DATE 2026.07.24READ 5 min readWORDS 940#Characteristics#Compressible#Euler-Equations#Acoustics#Riemann

El flujo supersónico no sabe lo que ocurre aguas arriba — curvas características y ondas sonoras en las ecuaciones de Euler

Por qué una pequeña perturbación se separa en tres velocidades características

Un caza supersónico llega antes que el sonido de su propio motor: primero pasa por encima de la cabeza y solo después llega el estruendo. La razón de que esto ocurra ya está escrita dentro de las ecuaciones de Euler. Este artículo deriva cómo una pequeña perturbación se separa en tres señales distintas. Las curvas características que esas señales dibujan en el plano (x,t)(x,t) (la traza que deja el paso de cada señal) se examinan en una figura manipulable, y al final las tres velocidades características se extraen directamente con Python.

Las ecuaciones compresibles son propagación de señales#

El flujo compresible no viscoso en una dimensión se escribe con tres leyes de conservación.

tρ+x(ρu)=0\partial_t \rho + \partial_x(\rho u) = 0 t(ρu)+x(ρu2+P)=0\partial_t(\rho u) + \partial_x(\rho u^2 + P) = 0 t(ρetot)+x[(ρetot+P)u]=0\partial_t(\rho e_{\text{tot}}) + \partial_x\big[(\rho e_{\text{tot}} + P)\,u\big] = 0

ρ\rho es la densidad, uu la velocidad, PP la presión y etote_{\text{tot}} la energía específica total. A primera vista parecen ecuaciones de un fluido que "fluye". Pero la esencia de estas ecuaciones no es el transporte, sino la propagación de señales. Toda la dinámica del flujo se descompone en unas pocas señales que viajan a velocidades determinadas. Para ver cuáles son esas velocidades basta con linealizar la ecuación por un momento.

Una pequeña perturbación genera una ecuación de onda#

Sobre un estado de fondo (ρ0,u0,P0)(\rho_0, u_0, P_0) se superpone una perturbación muy pequeña. Tomando ρ=ρ0+ρ1\rho = \rho_0 + \rho_1, u=u0+u1u = u_0 + u_1 y usando P=KργP = K\rho^\gamma, se conservan solo los términos de primer orden. Definiendo la derivada que se mueve con el fondo Dtt+u0xD_t \equiv \partial_t + u_0\,\partial_x (derivada co-móvil), al combinar las dos ecuaciones de perturbación resulta una única ecuación de onda.

Dt2ρ1c02x2ρ1=0D_t^2\,\rho_1 - c_0^2\,\partial_x^2\,\rho_1 = 0

Aquí c0c_0 es la velocidad del sonido.

c0=γP0ρ0c_0 = \sqrt{\gamma\,\frac{P_0}{\rho_0}}

γ\gamma es la razón de calores específicos. Al insertar ρ1ei(kxωt)\rho_1 \sim e^{i(kx-\omega t)} en esta ecuación se obtiene la relación de dispersión.

ωk=u0±c0\frac{\omega}{k} = u_0 \pm c_0

ω\omega es la frecuencia angular y kk el número de onda. La perturbación se deja arrastrar por el flujo de fondo u0u_0 y se propaga hacia ambos lados a la velocidad del sonido c0c_0. Es decir, la perturbación en un punto se separa en dos velocidades: u0+c0u_0 + c_0 y u0c0u_0 - c_0.

Las curvas características que se separan en tres ramas#

Las dos ondas sonoras no son todo. La tercera señal es el propio fluido. Supongamos que se pinta el fluido con color. Si en t=0t=0 se tiñe la izquierda de azul y la derecha de rojo, la frontera de color ϕ\phi simplemente se deja arrastrar por el flujo.

tϕ+u0xϕ=0\partial_t \phi + u_0\,\partial_x \phi = 0

Esta señal se desplaza a la velocidad u0u_0. Esta es la característica de entropía (o superficie de contacto). En resumen, el flujo unidimensional tiene tres velocidades características.

λ=u0c0,λ0=u0,λ+=u0+c0\lambda_- = u_0 - c_0, \qquad \lambda_0 = u_0, \qquad \lambda_+ = u_0 + c_0

En el plano (x,t)(x,t), las líneas que satisfacen dxdt=λ\dfrac{dx}{dt} = \lambda se llaman curvas características. λ±\lambda_\pm son las ondas sonoras y λ0\lambda_0 es el transporte de materia. A lo largo de cada característica acústica se conservan constantes los invariantes de Riemann u±2cγ1u \pm \dfrac{2c}{\gamma-1}, y a lo largo de la característica material se conserva la entropía.

Se puede manipular directamente el flujo de fondo u0u_0 en la animación de abajo.

The blue tint marks the upstream region the left-going sound has reached. Push u₀ past 1 and the blue tint vanishes: the C− signal now has a positive speed, so every signal runs downstream and the source can no longer talk to what lies upstream.

Con M=u0/c0M = u_0/c_0 en 0.4, la señal azul (onda sonora izquierda) se extiende hacia la izquierda de la fuente, es decir, aguas arriba. Al subir MM por encima de 1 esa traza azul desaparece. Esto ocurre porque λ=u0c0\lambda_- = u_0 - c_0 se vuelve positivo y las tres señales viajan solo aguas abajo.

En régimen supersónico el cono de señal se vuelca#

La misma historia se ve con más claridad en un diagrama espacio-temporal. La cuña entre las tres curvas características C,C0,C+C_-,\,C_0,\,C_+ que salen de la fuente es el dominio de influencia (domain of influence). Es el conjunto de eventos espacio-temporales a los que la fuente puede enviar una señal.

Si M<1M<1, esta cuña se abre hacia ambos lados de la línea vertical. La señal va tanto aguas arriba como aguas abajo. Si M>1M>1, la cuña entera se vuelca hacia la derecha. Incluso la característica CC_- se inclina hacia la derecha, y ningún evento aguas arriba queda dentro del dominio de influencia. Esta es la razón de que en el flujo supersónico "aguas arriba no sepa lo que ocurre aguas abajo". También es el fundamento numérico de por qué no se deben imponer condiciones de contorno en una salida supersónica.

Se puede arrastrar la sonda redonda en el diagrama de abajo.

Drag the probe across the plane. At M = 0.4 the wedge straddles the vertical, so events both upstream and downstream are reachable. Slide u₀ above 1 and the whole wedge leans right — drop the probe anywhere to the left of the source and it stays red.

Si la sonda se coloca dentro de la cuña se vuelve verde (alcanzable) y, si se coloca fuera, roja (inalcanzable). Al subir u0u_0 por encima de 1 y colocar la sonda en cualquier punto a la izquierda de la fuente, permanece roja. Aguas arriba queda completamente desconectado de la señal.

Verificación de las velocidades características con Python#

Comprobemos si las velocidades características son realmente u±cu \pm c y uu. Al escribir el Euler unidimensional con las variables primitivas W=(ρ,u,P)W=(\rho,u,P) se obtiene la forma cuasilineal tW+A(W)xW=0\partial_t W + A(W)\,\partial_x W = 0, y los autovalores de la matriz de coeficientes AA son precisamente las velocidades características.

import numpy as np
 
def characteristic_speeds(rho, u, p, gamma=1.4):
    """Jacobiano de variables primitivas del Euler 1D A(W), W=(rho,u,p).
    Autovalores de A = las tres velocidades características."""
    c = np.sqrt(gamma * p / rho)              # velocidad del sonido
    A = np.array([[u,      rho,        0.0  ],
                  [0.0,    u,          1/rho],
                  [0.0,    rho*c**2,   u    ]])
    lam = np.sort(np.linalg.eigvals(A).real)
    return c, lam
 
rho, u, p = 1.225, 220.0, 1.0e5               # aire, u = 220 m/s
c, lam = characteristic_speeds(rho, u, p)
print(f"c0         = {c:8.2f} m/s")
print(f"eig(A)     = {np.round(lam, 2)}")
print(f"u-c,u,u+c  = {np.round([u-c, u, u+c], 2)}")
print(f"Mach       = {u/c:5.3f}  -> {'supersonic' if u > c else 'subsonic'}")

La salida es la siguiente.

c0         =   338.06 m/s
eig(A)     = [-118.06  220.    558.06]
u-c,u,u+c  = [-118.06  220.    558.06]
Mach       =  0.651  -> subsonic

Los autovalores coinciden exactamente con uc,u,u+cu-c,\,u,\,u+c. Ahora avancemos realmente la perturbación en el tiempo y midamos la velocidad del frente de la señal. Los invariantes de Riemann acústicos w±=u1±(c0/ρ0)ρ1w_\pm = u_1 \pm (c_0/\rho_0)\,\rho_1 son escalares que se dejan arrastrar respectivamente a u0±c0u_0 \pm c_0, así que basta con transportarlos por separado con esquema upwind.

N, L = 400, 1.0
x = np.linspace(0, L, N, endpoint=False)
dx = L / N
rho0, c0 = 1.0, 1.0
u0 = 0.6 * c0                                  # Mach de fondo 0.6
 
bump = np.exp(-((x - 0.5) ** 2) / (2 * 0.01 ** 2))
wp = bump.copy()                              # invariante derecho (u0 + c0)
wm = bump.copy()                              # invariante izquierdo (u0 - c0)
 
def upwind_step(w, a, dt):
    if a > 0:
        dwdx = (w - np.roll(w, 1)) / dx
    else:
        dwdx = (np.roll(w, -1) - w) / dx
    return w - a * dt * dwdx
 
CFL = 0.4
dt = CFL * dx / (abs(u0) + c0)
steps = int(0.25 / dt)
for _ in range(steps):                        # bucle de avance temporal
    wp = upwind_step(wp, u0 + c0, dt)
    wm = upwind_step(wm, u0 - c0, dt)
 
T = steps * dt
def front_speed(w):
    return (x[np.argmax(w)] - 0.5) / T
print(f"u0+c0: target {u0 + c0:+.3f}, measured {front_speed(wp):+.3f}")
print(f"u0-c0: target {u0 - c0:+.3f}, measured {front_speed(wm):+.3f}")
u0+c0: target +1.600, measured +1.600
u0-c0: target -0.400, measured -0.400

Cada uno de los dos frentes se mueve a u0+c0u_0+c_0 y u0c0u_0-c_0. El invariante derecho va aguas abajo y el izquierdo aguas arriba. Al subir u0u_0 por encima de c0c_0, el valor medido de la segunda línea también se vuelve positivo.

Lo que dejan las curvas características#

  • La dinámica del flujo compresible es la propagación de señales que viajan a tres velocidades características uc, u, u+cu-c,\ u,\ u+c. Dos son ondas sonoras y una es el transporte de materia.
  • El instante en que la cuña del dominio de influencia cruza la línea vertical es M=1M=1. Por encima de ese punto no hay ninguna señal que vaya aguas arriba.
  • Si en un contorno supersónico todas las características apuntan en una sola dirección, queda determinado también el número de condiciones de contorno que se pueden imponer. El hábito de contar el signo de las características evita errores en las condiciones de contorno.

Comparte si te resultó útil.