Skip to content
cfd-lab:~/es/posts/2026-07-11-acoustic-conv…● online

Traducción del original en coreano escrito por el autor. Leer el original (한국어)

NOTE #099DAY SAT 논문리뷰DATE 2026.07.11UPDATED 2026.10.19READ 7 min read#Lagrange-Projection#Operator-Splitting#Low-Mach#Compressible#PaperReview

Dejar que el sonido y la materia fluyan por separado — División acústico-convectiva (Lagrange–Projection)

Sin devolver R_j a la proyección convectiva, masa, momento y energía dejan de cuadrar.

Dejar que el sonido y la materia fluyan por separado — División acústico-convectiva (Lagrange–Projection)#

El sonido sigue a 340 m/s junto a quien camina a 5 km/h. Un solver compresible mete ambas velocidades en un solo paso. La razón es el problema. En un flujo lento, las ondas acústicas adelantan a la materia por cientos. Un Godunov directo queda atado a las ondas rápidas. La convección lenta se difumina.

Al bajar el control de Mach cambian a la vez la velocidad a la que se parte el pulso de presión y el sitio donde se queda el grumo de entropía.

stiffness ratio (u+c)/u = 7.7×
amber = 압력 섭동(음향파, u±c) · teal = 엔트로피 이상(대류/접촉, u). M을 0.02까지 내리면 음향파가 접촉파를 압도적으로 앞질러 달아난다.

En 0.02 el pulso ámbar se abre en dos ondas que escapan a los lados. El grumo teal casi no se mueve. Los tres triángulos quedan en u ⁣− ⁣cu\!-\!c, uu y u ⁣+ ⁣cu\!+\!c. Con menos Mach solo se detiene el del centro. La separación exterior sigue en 2c2c.

ten Eikelder et al. (2017) separan ambas. Parte acústica, parte convectiva, cada una con su esquema. Estas notas ponen esa división Lagrange–Projection sobre las ecuaciones de Euler monofásicas (single-phase) y la contrastan con un pulso acústico en un flujo lento.

Artículo: M.F.P. ten Eikelder, F. Daude, B. Koren, A.S. Tijsseling, "An acoustic-convective splitting-based approach for the Kapila two-phase flow model", Journal of Computational Physics 331 (2017) 188–208. DOI: 10.1016/j.jcp.2016.11.031

El jacobiano se parte en dos#

Al escribir las ecuaciones de Euler 1D en variables primitivas W=(ρ,u,p)T\mathbf{W}=(\rho,u,p)^T, toman forma cuasilineal.

∂tW+B(W) ∂xW=0\partial_t \mathbf{W} + \mathbf{B}(\mathbf{W})\,\partial_x \mathbf{W} = \mathbf{0}

Aquí ρ\rho es la densidad, uu la velocidad y pp la presión. La matriz de coeficientes B\mathbf{B} se parte en dos piezas.

B(W)=A(W)⏟acuˊstica+C(W)⏟convectiva,C(W)=u I\mathbf{B}(\mathbf{W}) = \underbrace{\mathbf{A}(\mathbf{W})}_{\text{acústica}} + \underbrace{\mathbf{C}(\mathbf{W})}_{\text{convectiva}}, \qquad \mathbf{C}(\mathbf{W}) = u\,\mathbf{I}

A\mathbf{A} contiene todos los términos de presión: la parte acústica (acoustic). C=uI\mathbf{C}=u\mathbf{I} simplemente arrastra la materia: la parte convectiva (convective). En realidad, la división equivale a arrancar el término u∂xu\partial_x de la derivada lagrangiana D/Dt=∂t+u∂x\mathrm{D}/\mathrm{D}t = \partial_t + u\partial_x.

La descomposición aditiva de los autovalores#

Por qué esta división es tan potente se ve al mirar los autovalores. Las velocidades de onda del sistema completo son u−c, u, u+cu-c,\ u,\ u+c. Se suman exactamente a partir de una contribución acústica y una convectiva.

λ1,2,3=(−c, 0, +c)⏟λa acuˊstica+(u, u, u)⏟λc convectiva\lambda_{1,2,3} = \underbrace{(-c,\ 0,\ +c)}_{\lambda^a\ \text{acústica}} + \underbrace{(u,\ u,\ u)}_{\lambda^c\ \text{convectiva}}

c=γp/ρc=\sqrt{\gamma p/\rho} es la velocidad del sonido. Las velocidades acústicas son ±c\pm c, independientes de la velocidad del flujo. La velocidad convectiva es uu en todos los casos. En el límite de bajo Mach M=u/c→0M=u/c\to 0, la banda acústica conserva su ancho 2c2c mientras la velocidad convectiva se encoge a cero. Esa brecha es la rigidez (stiffness). La separación de los triángulos de la figura de arriba es esta misma suma. Cuando M→0M\to 0 solo desaparece λc\lambda^c. λa=±c\lambda^a=\pm c se queda.

Paso acústico — HLLC en coordenadas lagrangianas#

La parte acústica es la expansión y compresión que impulsa la presión. El artículo la lleva a coordenadas de masa (lagrangianas) y la resuelve con un solver de Riemann tipo HLLC. El estado con asterisco en la cara j+1/2j+1/2 se reduce a dos fórmulas.

uj+1/2∗=uj+uj+12+pj−pj+12 aj+1/2,pj+1/2∗=pj+pj+12+aj+1/22 (uj−uj+1)u^*_{j+1/2} = \frac{u_j+u_{j+1}}{2} + \frac{p_j-p_{j+1}}{2\,a_{j+1/2}}, \qquad p^*_{j+1/2} = \frac{p_j+p_{j+1}}{2} + \frac{a_{j+1/2}}{2}\,(u_j-u_{j+1})

aj+1/2=max⁡(ρjcj, ρj+1cj+1)a_{j+1/2}=\max(\rho_j c_j,\ \rho_{j+1}c_{j+1}) es la impedancia acústica (densidad por velocidad del sonido). Solo con esas velocidades y presiones con asterisco se realiza la actualización de las variables eulerianas. La tasa de expansión de cada celda se comprime en un único coeficiente.

Rj=1+ΔtΔx(uj+1/2∗−uj−1/2∗)R_j = 1 + \frac{\Delta t}{\Delta x}\big(u^*_{j+1/2}-u^*_{j-1/2}\big)

RjR_j indica cuánto estiró o comprimió el paso acústico el volumen de la celda. La densidad sale de inmediato como ρjn+1−=ρjn/Rj\rho^{n+1-}_j = \rho^n_j / R_j.

El fondo del cálculo es c0=1c_0=1, ρ0=1\rho_0=1, γ=1.4\gamma=1.4, de modo que p0=ρ0c02/γ=1/1.4p_0=\rho_0 c_0^2/\gamma=1/1.4. El pulso de presión tiene amplitud 10−310^{-3}. La anomalía de densidad tiene amplitud 5×10−25\times 10^{-2}. Los centros están en x=0.5x=0.5 y x=0.25x=0.25, así que al inicio no se solapan. El máximo de densidad arranca en el grumo de entropía, cerca de 1.051.05. Si RjR_j supera 1, la celda se expande y la densidad baja. Si queda por debajo de 1, comprime. Como Δt/Δx\Delta t/\Delta x multiplica el salto de u∗u^* en las caras, un CFL de 0.8 mantiene RjR_j cerca de 1. Con 400 celdas en un dominio de longitud 1, Δx=1/400\Delta x=1/400.

Paso convectivo — proyección upwind#

Ahora la velocidad con asterisco u∗u^* del paso acústico arrastra la materia. Se actualizan las cantidades conservadas φ∈{ρ,ρu,ρE}\varphi\in\{\rho,\rho u,\rho E\} con un simple esquema upwind.

φjn+1=Rj φjn+1−−ΔtΔx(uj+1/2∗φj+1/2up−uj−1/2∗φj−1/2up)\varphi^{n+1}_j = R_j\,\varphi^{n+1-}_j - \frac{\Delta t}{\Delta x}\big(u^*_{j+1/2}\varphi^{\text{up}}_{j+1/2} - u^*_{j-1/2}\varphi^{\text{up}}_{j-1/2}\big)

φj+1/2up\varphi^{\text{up}}_{j+1/2} es φj\varphi_j cuando u∗ ⁣≥ ⁣0u^*\!\ge\!0, y φj+1\varphi_{j+1} en caso contrario. El RjR_j del paso anterior regresa aquí, y la masa, el momento y la energía se conservan de forma exacta. Al recorrer los dos pasos en orden, un paso de tiempo queda completo.

Con u∗u^* positivo, el valor de cara sale de la celda izquierda. Con u∗u^* negativo, de la derecha. Rj φn+1−R_j\,\varphi^{n+1-} deshace primero el cambio de volumen. El flujo de cara mueve la materia después. Si el orden se invierte, las sumas de masa, ρu\rho u y ρE\rho E se separan. Las caras periódicas no dejan escapar nada. Con la realimentación de RjR_j en su sitio, la suma de momento conserva solo el redondeo. Cuánto se esparce un Roe directo a bajo Mach lo mide aparte las tres escalas de difusión artificial de Hope–Collins.

Python — pulso acústico en un flujo lento#

Aquí está toda la tubería en numpy: fronteras periódicas, un gas ideal, tres cantidades conservadas por celda. La condición inicial coloca un pequeño pulso de presión y una anomalía de densidad sobre un flujo de fondo u0=Mc0u_0=Mc_0.

import numpy as np
 
GAMMA = 1.4  # razon de calores especificos del gas ideal
 
def primitives(rho, mom, Ene):
    """Conservadas -> variables primitivas (velocidad, presion, velocidad del sonido)."""
    u = mom / rho
    e = Ene / rho - 0.5 * u * u            # energia interna especifica
    p = (GAMMA - 1.0) * rho * e
    c = np.sqrt(GAMMA * p / rho)
    return u, p, c
 
def acoustic_faces(rho, u, p, c):
    """Estado acustico HLLC u*, p* en la cara j+1/2 (ec. 34 del articulo)."""
    rp, up, pp, cp = (np.roll(a, -1) for a in (rho, u, p, c))
    a = np.maximum(rho * c, rp * cp)       # impedancia acustica a = max(rho*c) (ec. 32)
    ustar = 0.5 * (u + up) + (p - pp) / (2 * a)
    pstar = 0.5 * (p + pp) + 0.5 * a * (u - up)
    return ustar, pstar
 
def lagrange_projection_step(rho, mom, Ene, dx, dt):
    """Paso acustico -> paso convectivo (ec. 38, 40 del articulo)."""
    u, p, c = primitives(rho, mom, Ene)
    uf, pf = acoustic_faces(rho, u, p, c)          # j+1/2
    uf_m, pf_m = np.roll(uf, 1), np.roll(pf, 1)    # j-1/2
    lam = dt / dx
    # 1) paso acustico: expansion/compresion impulsada por la presion
    R = 1.0 + lam * (uf - uf_m)                     # ec. (39)
    rho1 = rho / R
    mom1 = (mom - lam * (pf - pf_m)) / R
    Ene1 = (Ene - lam * (pf * uf - pf_m * uf_m)) / R
    # 2) paso convectivo: arrastrar la materia a u* (proyeccion upwind)
    def project(phi1):
        phi_f = np.where(uf >= 0, phi1, np.roll(phi1, -1))
        phi_f_m = np.roll(phi_f, 1)
        return R * phi1 - lam * (uf * phi_f - uf_m * phi_f_m)
    return project(rho1), project(mom1), project(Ene1)
 
def run_acoustic_pulse(mach, n=400, cfl=0.8, tmax=0.25):
    x = (np.arange(n) + 0.5) / n
    dx = 1.0 / n
    c0, rho0 = 1.0, 1.0
    p0 = rho0 * c0**2 / GAMMA
    u0 = mach * c0
    dp = 1e-3 * np.exp(-((x - 0.5) / 0.03)**2)     # pulso de presion acustico
    ds = 5e-2 * np.exp(-((x - 0.25) / 0.03)**2)    # anomalia de entropia (densidad) -> onda de contacto
    rho = rho0 + dp / c0**2 + ds
    u = np.full(n, u0)
    p = p0 + dp
    mom = rho * u
    Ene = p / (GAMMA - 1) + 0.5 * rho * u * u
    t, m0 = 0.0, mom.sum()
    while t < tmax:
        _, _, c = primitives(rho, mom, Ene)
        dt = min(cfl * dx / np.max(np.abs(mom / rho) + c), tmax - t)
        rho, mom, Ene = lagrange_projection_step(rho, mom, Ene, dx, dt)
        t += dt
    return rho, mom, m0, mom.sum()
 
for M in (0.02, 0.2):
    rho, mom, m0, m1 = run_acoustic_pulse(M)
    print(f"M={M}: error de momento={abs(m1-m0)/abs(m0):.1e}, rho_max={rho.max():.4f}")
# M=0.02: error de momento=2.2e-16, rho_max=1.0497
# M=0.2:  error de momento=0.0e+00, rho_max=1.0452

El momento se conserva a precisión de máquina. La presión se mantiene acotada y la densidad permanece positiva. La división no rompe la conservación porque el paso convectivo reintroduce el RjR_j.

El ρmax⁡\rho_{\max} impreso es 1.0497 con M=0.02M=0.02 y 1.0452 con M=0.2M=0.2. La cresta inicial, cerca de 1.05, apenas se erosiona. El pulso de presión solo suma dp/c02=10−3dp/c_0^2=10^{-3} a la densidad, así que el máximo lo pone el contacto. Errores de momento de 2.2×10−162.2\times 10^{-16} y 0 indican que la división en sí no es lo que rompe la conservación. El paso sigue limitado por ∣u∣+c|u|+c, de modo que subir MM de 0.02 a 0.2 casi no cambia el número de pasos. Con c0=1c_0=1, ∣u∣+c|u|+c vale 1.02 frente a 1.2. La convección puede acelerarse por diez y la acústica sigue ocupando la mayor parte del paso.

Lo que de verdad se separa a bajo Mach#

La división rinde a bajo Mach. El paso estable de un método directo sigue encadenado a ∣u∣+c|u|+c, aunque la física de interés viva sobre uu.

Al mover el control de Mach, la banda ámbar queda fija en un ancho 2c2c y solo se encoge la velocidad teal uu.

-101200.250.50.751Mach M = u / cu+cuu−c
(u+c)/u = 6.0× ← 직접법 시간전진이 견디는 속도비
음향 밴드(amber) 폭은 M과 무관하게 항상 2c. 대류 속도 u(teal)만 0으로 줄어든다. 이 격차가 저마하 강성의 정체.

El ancho acústico no depende de MM. Solo uu converge a cero. Con c=1c=1 y M=0.05M=0.05, u=0.05u=0.05 y u+c=1.05u+c=1.05, así que (u+c)/u=21(u+c)/u=21. El esquema dividido puede avanzar la convección con un paso distinto del acústico. La física lenta deja de ir a rastras de las ondas rápidas. La misma división evita la difusión numérica de más que un Godunov directo acumula a bajo Mach.

Una mirada crítica#

Hay tres tropiezos. La división usada aquí es de primer orden en el tiempo. El segundo orden pide un envoltorio de Strang —acústico, convectivo, acústico— y otra pasada en el costo. El escenario real del artículo es el modelo bifásico de cinco ecuaciones de Kapila. El término no conservativo K∂xuK\partial_x u de la fracción volumétrica y la garantía de positividad son el obstáculo de verdad. Este recorte monofásico los salta. La impedancia a=max⁡(ρc)a=\max(\rho c) es robusta y también disipativa. En un choque fuerte esa disipación puede difuminar el contacto. Por eso el artículo compara aparte precisión y costo frente al enfoque directo.

En un código, la bifurcación no es exótica. El rhoPimpleFoam basado en presión de OpenFOAM y la familia all-Mach ya tratan acústica y convección de forma implícita y explícita desde la misma raíz. Lagrange–Projection es la versión escrita en el lenguaje de los solvers de Riemann.

Sin R_j la conservación muere primero#

Si el RjR_j acústico no vuelve a la proyección convectiva, las actualizaciones de masa, momento y energía dejan de coincidir. La ejecución de arriba llega a 2.2×10−162.2\times 10^{-16} solo con esa realimentación puesta. Un envoltorio de Strang puede subir el orden. La secuencia crece a acústico–convectivo–acústico y aparece una pasada más.

Al pasar al modelo de cinco ecuaciones de Kapila, K∂xuK\partial_x u en la fracción volumétrica sigue ahí. El recorte monofásico no toca ese término no conservativo. Con a=max⁡(ρc)a=\max(\rho c) el choque aguanta y el contacto se engrosa. Otra forma de sacar la acústica del integrador temporal es el IMEX acústico-transporte de Peluchon. En M=0.05M=0.05, (u+c)/u=21(u+c)/u=21. Si ese factor 21 se deja en el solver acústico o se queda en el CFL convectivo es la bifurcación de la implementación.

Comparte si te resultó útil.