Skip to content
cfd-lab:~/zh/posts/2026-07-26-imex-tvd-ap-l…● online

本文译自作者的韩语原文。 阅读原文(한국어)

NOTE #113DAY SUN 논문리뷰DATE 2026.07.26UPDATED 2026.10.19READ 7 min read#IMEX#Asymptotic-Preserving#Low-Mach#TVD#Compressible

马赫数趋于零,时间步长却纹丝不动 — IMEX TVD 格式复现记

把θ按在√2−1上,过冲会变成0,但ε=10^{-4}时一步就把总变差从4削到1.860。

一阶 AP 格式跑得很顺。马赫数降到 10−210^{-2} 也好,降到 10−410^{-4} 也好,时间步长纹丝不动。可是把二阶时间离散 ARS(2,2,2) 加上去的那一刻,脉冲两侧就冒出了过冲。这不是发散。幅值有界,但步数再多也不消失,直到把时间步长降到声学CFL(Courant–Friedrichs–Lewy·让信息传播速度不越过一个网格的时间步长条件)才终于消掉。这正是该格式想要避开的那个约束。

把 ε 滑块拉到 10−410^{-4},声学特征线会躺下去;Explicit 和 IMEX 按钮会换掉走到同一个 t=1t=1 所需的步数。

Acoustic CFL budget — explicit vs IMEX time step, x–t diagram (Δx = 1/40)
acoustic speed c/√ε
100.0
Δt (explicit)
2.23e-4
steps to t = 1
4489 explicit vs 89 IMEX
speed-up
×50.4
Time levels clipped: 4489 levels needed, only 400 drawn (evenly subsampled).
Drag ε down to 1e-4 and compare the two step counts — the acoustic rays flatten toward horizontal while the explicit stack collapses into a solid block, yet the IMEX spacing never moves.

这个刻度上显式是 4489 步,IMEX 是 89 步。要看的是声学线是否贴平,以及差距缩在哪一个按钮上。

今天读的论文说,这个失败不是实现上的 bug,而是一条定理(theorem)。这篇文章能带走三样东西:为什么二阶和无约束时间步长无法同时成立,作者们如何绕开这堵墙,以及用 30 行 Python 复现出来的实际数值说明了什么。先说结论:振荡确实按论文所说彻底消失,代价却比预想的大。

  • 标题: Second order Implicit-Explicit Total Variation Diminishing schemes for the Euler system in the low Mach regime
  • 作者: Giacomo Dimarco (Ferrara), Raphaël Loubère (Bordeaux), Victor Michel-Dansac, Marie-Hélène Vignal (Toulouse)
  • 来源: Elsevier 投稿预印本,2017-10-23
  • DOI: 内部摘要中没有 DOI 字段 — 原文需要按标题检索。
  • 一句话总结: 把一阶 AP 格式与二阶 IMEX 格式做凸组合,在使用与马赫数无关的时间步长的同时,不丢失 TVD(总变差不增·解的总变差不随时间增长的性质)与 L∞L^\infty 性质。

Q1. 马赫数变小后为什么时间步长会崩#

出发点是把马赫数平方记为 ε\varepsilon 后无量纲化的等熵 Euler 方程。

∂tρ+∇⋅(ρU)=0\partial_t \rho + \nabla\cdot(\rho U) = 0

ρ\rho 是密度,UU 是速度场,第一式是质量守恒。

∂t(ρU)+∇⋅(ρU⊗U)+1ε∇p(ρ)=0\partial_t (\rho U) + \nabla\cdot(\rho U \otimes U) + \frac{1}{\varepsilon}\nabla p(\rho) = 0

ρU\rho U 是动量,p(ρ)=ργp(\rho)=\rho^\gamma 是压力,γ\gamma 是比热比,1/ε1/\varepsilon 是马赫数平方的倒数。

值得注意的是,只有压力项带 1/ε1/\varepsilon。压力梯度变大,声速也跟着变大。准确地说,声速按 1/ε1/\sqrt{\varepsilon} 标度。完全显式的求解器必须跟上最快的波,因此被 Δt≤Δx/(∣u∣+c/ε)\Delta t \le \Delta x / (|u| + c/\sqrt{\varepsilon}) 束缚住。ε=10−4\varepsilon = 10^{-4} 时,步长比对流时间尺度所要求的小约 100 倍。

问题是,没有人需要这 100 倍。低马赫数流动中关心的是对流结构,不是声波。事实上在 ε→0\varepsilon \to 0 极限下,系统收敛到不可压 Euler。密度固定为常数 ρ0\rho_0,∇⋅U=0\nabla\cdot U = 0 成立,动量方程变成 ρ0∂tU+ρ0∇⋅(U⊗U)+∇π1=0\rho_0\partial_t U + \rho_0\nabla\cdot(U\otimes U) + \nabla\pi_1 = 0 的形式。这里 π1\pi_1 是压力的一阶扰动,起到维持不可压约束的 Lagrange 乘子的作用。

此时需要的性质就是 AP(asymptotic-preserving·渐近保持)。定义很简单:格式在 ε→0\varepsilon \to 0 时退化(degenerate)为极限方程的相容离散。意思是不必把网格和时间步长按 ε\varepsilon 一起缩小,极限也能被正确捕捉。

上面把 ε\varepsilon 放在 10−410^{-4} 时读到的 4489 和 89,就是这个 1/ε1/\sqrt{\varepsilon} 标度写进步数之后的样子。4489/89 大约是 50,比 1/ε=1001/\sqrt{\varepsilon}=100 小,因为显式分母里还留着对流速度。

Q2. 把什么交给隐式才能解开 CFL#

全部做成隐式,每步求解非线性系统的开销就承受不起。论文把守恒变量 W=(ρ,ρU)W = (\rho, \rho U) 的通量劈成两块。

Wn+1−WnΔt+∇⋅Fe(Wn)+∇⋅Fi(Wn+1)=0\frac{W^{n+1}-W^n}{\Delta t} + \nabla\cdot F_e(W^n) + \nabla\cdot F_i(W^{n+1}) = 0

Fe(W)=(0, ρU⊗U)F_e(W) = (0,\ \rho U \otimes U) 是显式处理的对流通量,Fi(W)=(ρU, p(ρ)/ε⋅I)F_i(W) = (\rho U,\ p(\rho)/\varepsilon \cdot I) 是隐式处理的声学通量。

关键在于这个分裂并不随意。把压力梯度放到隐式一侧就得到 asymptotic consistency,把质量通量放到隐式一侧就得到与 ε\varepsilon 无关的一致稳定性。只挪其中一项,就会破坏另一侧的性质。

那么剩下的就是如何求解隐式系统。技巧是取散度。把隐式动量方程的散度代入质量方程,动量被消去,只剩下关于 ρn+1\rho^{n+1} 的单个非线性椭圆方程。

ρn+1−ρnΔt+(∇⋅(ρU))n−Δt (∇2:(ρU⊗U))n−Δtε(Δp(ρ))n+1=0\frac{\rho^{n+1}-\rho^n}{\Delta t} + (\nabla\cdot(\rho U))^n - \Delta t\,(\nabla^2 : (\rho U\otimes U))^n - \frac{\Delta t}{\varepsilon}(\Delta p(\rho))^{n+1} = 0

左端最后一项的 Δp(ρ)n+1\Delta p(\rho)^{n+1} 是隐式压力 Laplacian,它前面的各项全部用 nn 时刻的值计算,属于显式源项。

解出这个椭圆方程得到 ρn+1\rho^{n+1} 之后,动量只需一次显式代入即可更新。这与压力基求解器的压力修正步在结构上相同。剩下的显式部分只有 FeF_e,所以时间步长约束也只看对流速度。结果是 Δt≤Δx/max⁡j(2∣ujn∣)\Delta t \le \Delta x / \max_j(2|u_j^n|)。系数 2 来自显式通量 ρU⊗U\rho U \otimes U 的最大特征值为 2u2u。ε\varepsilon 已经不在任何地方出现。

把声学从时间轴上剥开、只留下对流,和 Lagrange–Projection 分裂 盯的是同一个位置。这边把拆开的项用关于密度的椭圆方程闭上,步长上限放在 max⁡j(2∣ujn∣)\max_j(2|u_j^n|) 上。ε\varepsilon 一次也进不了这个上限。

Q3. 升到二阶后为什么会出现振荡#

时间二阶用 ARS(2,2,2) IMEX(implicit-explicit·按项混用隐式与显式的时间积分) Runge–Kutta 来实现。系数 β=1−2/2≈0.2929\beta = 1 - \sqrt{2}/2 \approx 0.2929 支配整个格式。半离散形式分两个阶段。

W(1)=Wn−β Δt ∇⋅Fe(Wn)−β Δt ∇⋅Fi(W(1))W^{(1)} = W^n - \beta\,\Delta t\,\nabla\cdot F_e(W^n) - \beta\,\Delta t\,\nabla\cdot F_i(W^{(1)})

W(1)W^{(1)} 是中间阶段的解,显式和隐式都只前进 β\beta 那么多。

Wn+1=Wn−Δt[δ ∇⋅Fe(Wn)+(1−δ) ∇⋅Fe(W(1))]−Δt[(1−β) ∇⋅Fi(W(1))+β ∇⋅Fi(Wn+1)]W^{n+1} = W^n - \Delta t\Big[\delta\,\nabla\cdot F_e(W^n) + (1-\delta)\,\nabla\cdot F_e(W^{(1)})\Big] - \Delta t\Big[(1-\beta)\,\nabla\cdot F_i(W^{(1)}) + \beta\,\nabla\cdot F_i(W^{n+1})\Big]

δ=1−1/(2β)≈−0.7071\delta = 1 - 1/(2\beta) \approx -0.7071 来自显式表的二阶条件,它是负数,这一点后面会成为问题。

论文在这里正面抛出一个否定性结果。

阶数高于一阶的隐式 Runge–Kutta 格式中,不存在无时间步长约束即为 TVD 的格式。(Gottlieb 一系的否定性结果,论文 Theorem 1)

这不是靠实现能凿穿的墙。二阶 AP 格式在显式 CFL 数 σe=ceΔt/Δx≤1\sigma_e = c_e\Delta t/\Delta x \le 1 之下是 L2L^2 稳定的。但 Δt\Delta t 一旦越过声学CFL Δx/(ce+ci/ε)\Delta x/(c_e + c_i/\sqrt{\varepsilon}),L∞L^\infty 稳定性和 TVD 就同时丢掉。我看到的过冲正是这个。因为有界所以不发散,因为是结构性的所以多跑几步也不会消失。

为便于分析,论文把系统约化成一个标量模型问题(论文式 12)。可以想象一道声脉冲搭在缓慢流动之上被带着走。

∂tw+ce∂xw+ciε∂xw=0\partial_t w + c_e \partial_x w + \frac{c_i}{\sqrt{\varepsilon}} \partial_x w = 0

ww 是标量未知量,cec_e 是缓慢的对流速度,ci/εc_i/\sqrt{\varepsilon} 是快速的声速。这个结构原样搬来了 Euler 压力波的 1/ε1/\sqrt{\varepsilon} 标度。

Q4. 一阶与二阶混合真的能得到 TVD 吗#

作者们的解法很简单。同一步分别用一阶 AP 格式和二阶格式各算一次,然后做凸组合。

wjn+1=θ wjn+1,O2+(1−θ) wjn+1,O1w_j^{n+1} = \theta\, w_j^{n+1,\mathrm{O2}} + (1-\theta)\, w_j^{n+1,\mathrm{O1}}

θ\theta 是压在二阶格式上的权重,θ=0\theta = 0 是纯一阶,θ=1\theta = 1 是纯二阶。

这与空间中使用的通量限制器思路相同。不同之处在于,这个混合被施加到时间离散而不是空间离散上。论文 Theorem 3 给出了条件:若 θ=αβ/(1−β)\theta = \alpha\beta/(1-\beta) 且 α∈[0,1]\alpha \in [0,1],则混合格式一致 TVD 且 L∞L^\infty 稳定。而且是在与马赫数无关的 CFL σe≤2\sigma_e \le \sqrt{2} 之下(α=1\alpha = 1 的情形)。因此能压在二阶格式上的最大权重就这样定下来。

θM=β1−β=2−1≈0.4142\theta_M = \frac{\beta}{1-\beta} = \sqrt{2}-1 \approx 0.4142

θM\theta_M 是保持 TVD 的前提下所允许的二阶占比上限。

老实读下来是这样:二阶格式的占比最多只能烧到 41%。而且这个上限不是普适常数,而是绑在所选 IMEX 时间离散——也就是 ARS(2,2,2)——上的数值。换一张 IMEX 表,θM\theta_M 也随之改变。

41% 的精度让人不满足。于是论文又加上了 MOOD(Multi-dimensional Optimal Order Detection·算完之后检查解,只把出问题的单元用低阶重算的事后限制器)方案。步骤分三步。先算出候选的二阶解,再找出违反 L∞L^\infty 界或 TVD 条件的单元,最后只把违规单元退回到 TVD-AP 解。光滑区域保留完整的二阶,只有间断附近才落到安全的混合上。

θ=1\theta=1 时带子被冲破、θM\theta_M 时过冲贴在 0 上的那条曲线,会在下面输出块之后用同一个滑块再走一遍。

Q5. 用 Python 复现 — 振荡消失了,失去的是什么#

只要有模型问题(式 12)和混合格式(式 17),复现就很短。以方波脉冲作初始条件,把 θ\theta 换成三种,测量总变差与最大过冲。

import numpy as np
 
BETA = 1.0 - np.sqrt(2.0) / 2.0        # ARS(2,2,2)
THETA_M = BETA / (1.0 - BETA)          # = sqrt(2) - 1
 
def solve_backward(rhs, s):
    """在周期边界上求解 (1+s)w_j - s*w_{j-1} = rhs_j(隐式迎风)。"""
    n = rhs.size
    A = (1.0 + s) * np.eye(n)
    A[np.arange(n), np.arange(n) - 1] -= s
    return np.linalg.solve(A, rhs)
 
def dminus(v):
    return v - np.roll(v, 1)
 
def blended_step(w, se, si, theta):
    """论文式 (17):theta 是二阶格式的占比。"""
    b = BETA
    star = solve_backward(w - b * se * dminus(w), b * si)          # (17a)
    rhs = (w - theta * (b - 1.0) * se * dminus(w)
             - theta * (1.0 - b) * si * dminus(star)
             - theta * (2.0 - b) * se * dminus(star)
             - (1.0 - theta) * se * dminus(w))                     # (17b)
    return solve_backward(rhs, (1.0 - theta + theta * b) * si)
 
def pulse_run(eps, theta, steps=60, n=200, cfl=0.9, ce=1.0, ci=1.0):
    dx = 1.0 / n
    x = (np.arange(n) + 0.5) * dx
    w = np.where((x > 0.25) & (x <= 0.75), 1.0, -1.0)   # 方波脉冲, TV = 4
    se, si = ce * cfl, (ci / np.sqrt(eps)) * cfl        # dt = cfl*dx/ce
    over = 0.0
    for _ in range(steps):
        w = blended_step(w, se, si, theta)
        over = max(over, w.max() - 1.0, -1.0 - w.min())
    tv = np.abs(np.roll(w, -1) - w).sum()
    return tv, over
 
for eps in (1e-2, 1e-4):
    for theta, tag in ((0.0, "一阶AP "), (THETA_M, "TVD-AP "), (1.0, "二阶AP ")):
        tv, over = pulse_run(eps, theta)
        print(f"eps={eps:<7g} {tag} TV={tv:6.3f}  最大过冲={over:+.4f}")

输出如下。

eps=0.01    一阶AP  TV= 0.395  最大过冲=+0.0000
eps=0.01    TVD-AP  TV= 0.977  最大过冲=+0.0000
eps=0.01    二阶AP  TV= 3.784  最大过冲=+0.4226
eps=0.0001  一阶AP  TV= 0.000  最大过冲=+0.0000
eps=0.0001  TVD-AP  TV= 0.000  最大过冲=+0.0000
eps=0.0001  二阶AP  TV= 0.006  最大过冲=+0.3776

把 θ 滑块在 2−1\sqrt{2}-1 和 1 之间挪动,刚才输出的过冲和总变差会在曲线上重算一遍。

Low-Mach IMEX pulse lab — blended scheme of Dimarco et al. (2017), eq. (17)
step
0
TV / 4.000
4.000 / 4.000
max overshoot
0.00e+0
Δt / Δt_explicit
11.0 ×11 cheaper
Watch the θ=1 curve punch through the ±1 lines while TV climbs above 4 — that is the TVD violation. Snap to θ=√2−1 and the overshoot vanishes.

过冲确实按论文所说消失了。只有二阶 AP 冲出带外 ±0.38∼0.42\pm 0.38 \sim 0.42,一阶 AP 与 TVD-AP 在两个 ε\varepsilon 下都是 0。到这里为止,理论与实现吻合得很干净。

代价是扩散。在 ε=10−2\varepsilon = 10^{-2} 下跑 60 步后,总变差从一阶 AP 的 0.395 回升到 TVD-AP 的 0.977。改善超过两倍,但离初始总变差 4.0 还差得远。也就是说,TVD-AP 卖的是"比一阶少抹一些",而不是保住二阶的锐利。

在 ε=10−4\varepsilon = 10^{-4} 下,仅仅一步就能看出差别。二阶 AP 的总变差达到 5.510,超过初值 4.0,并制造出 +0.378+0.378 的过冲。TVD-AP 的过冲恰好为 0,但总变差掉到 1.860。声学 Courant 数是 90,隐式迎风的扩散一步就吃掉了这么多。跑到 4 步,一阶 AP 降到 0.062、TVD-AP 降到 0.068;跑到 60 步,三种格式的脉冲实际上都已消亡。

这个扩散正是论文要加上 MOOD 限制器的理由。仅靠混合守不住精度,作者们自己也清楚。

把输出的数字再除一遍,扩散的单价就出来了。ε=10−2\varepsilon=10^{-2} 下跑 60 步,TVD-AP 的总变差 0.977 大约是一阶 0.395 的 2.47 倍,却仍然只有初始总变差 4 的 0.24。ε=10−4\varepsilon=10^{-4} 的一步更陡。二阶 AP 从 4.0 升到 5.510,增量 1.51,过冲 +0.378+0.378 和 60 步输出的 +0.3776+0.3776 几乎一样。过冲生在第一步,之后不再长。TVD-AP 在同一步把总变差从 4 削到 1.860,减少 2.14。声学 Courant 数等于 90 时,隐式迎风一步就能吃掉脉冲宽度的一大块。4 步时的 0.062 和 0.068 大约是初值 4 的 1.6%。因为 θM=β/(1−β)\theta_M=\beta/(1-\beta),而 β=1−2/2≈0.2929\beta=1-\sqrt{2}/2\approx 0.2929,所以 θM≈0.4142\theta_M\approx 0.4142 是 ARS 表定下的上限,不是在网格上拟合出来的数。

二阶占比停在41%,还是只把坏单元退回去#

就算叫做二阶,能烧掉的份额也只到 θM=2−1\theta_M=\sqrt{2}-1。论文写了按单元改 θ\theta 会更好,那种情形的 TVD 证明却留着没做。第 6 节实验的 CFL,只有一阶是 C=0.9C=0.9,其余三个都是 C=0.45C=0.45,文中写明是因为空间二阶重构。把它和"时间步长已从马赫数里解放出来"并排放,实际收益只剩一半。

模型问题(式 12·17)用 30 行就能复现。完整 Euler 每一步都是关于 ρn+1\rho^{n+1} 的非线性椭圆,收敛准则和迭代次数论文里都没有。挂上限制器仍会留下小振荡,这一点论文结论自己承认。和已经把压力项做隐式的 PISO/SIMPLE 并排看,这篇论文的位置是密度基守恒型里 L∞L^\infty 会裂开的地方。那张账单和半隐式压力的 L∞L^\infty是同一个形状。喷管和滞止区贴在同一个计算域里时,先怀疑那一半的时间步长。

如果对您有帮助,请分享。