本文译自作者的韩语原文。 阅读原文(한국어)
液滴模拟为何被 Δt 绊住 — 把表面张力隐式求解的论文
1.5倍步长下显式峰值是3.6e+07,隐式峰值停在1.000。解开枷锁的是后向欧拉。
网格加密一倍,时间步长就缩到约2.8倍。物理并没有变快。带表面张力的界面上,毛细时间步长约束(capillary time-step constraint)几乎总是最紧的那条。
把 滑块推过0.9,只有橙色(显式)的振幅炸开。青色(隐式)还按着同一条驻波。
虚线是解析衰减。mesh Oh 一抬,阻尼变强,两条都更快平息。Janodet、van Wachem 与 Denner 在2025年的耦合,是把这块橙色炸开的地方放进一个矩阵。
评述对象是 R. Janodet, B. van Wachem, F. Denner, "A fully-coupled algorithm with implicit surface tension treatment for interfacial flows with large density ratios", arXiv:2410.17757 (2024)。
毛细时间步长这道枷锁
不可压界面流动求解器通常把扩散项隐式处理,抹去粘性时间约束。于是作为最强约束剩下的,就是表面张力。以 Brackbill 在 1992 年最早写下的形式,
是两种流体的密度, 是表面张力系数, 是网格间距。指数 才是问题所在。为了把界面看得更清而把 减半,时间步长就缩小 倍。液滴越小、流动越接近毛细尺度,步数就越爆炸。用显式表面张力,无路可逃。
为什么是 Δx^1.5 — 毛细波的色散关系#
这道约束其实是 CFL 条件。界面上的小正弦扰动以毛细波(capillary wave,以表面张力为恢复力的波)的形式振荡。在无粘深水极限下,色散关系为
是角频率, 是波数。网格能分辨的最短波是 。若 超过该波的振荡周期,显式积分跟不上振荡而发散。计算 得到 。也就是说, 正是套在最快毛细波上的 CFL。
把表面张力隐式化 — 用一行振子看清核心
不必搬出整个求解器。一个毛细波模态可归约为阻尼谐振子。
是界面振幅, 是粘性阻尼。显式表面张力等同于用辛欧拉法积分这个振子,在 处发散 —— 正是上面的毛细 CFL。把表面张力项取在新时刻的值(后向欧拉),就变成无条件稳定。
上面的橙色在0.9附近炸开,是因为辛欧拉的极限 除以输出里的 。。再往上,显式一侧就把振幅放大。青色到3倍仍沿着虚线衰减。mesh Oh(粘性尺度)一大,阻尼变强,两条都更快平息。
静止界面上留下来的假流动,是这股恢复力的离散失去平衡时出现的。那个位置是 力平衡被打破的寄生电流。
透过放大因子看稳定边界
用振子的放大因子(amplification factor,每步振幅被乘的倍率),边界就清晰了。numpy 三十行即可复现。玩具问题不是激波管,而是驻立毛细波的衰减。
import numpy as np
def capillary_omega(sigma, k, rho_hat):
# 色散关系: 无粘深水毛细波 omega^2 = sigma k^3 / (rhoA+rhoB)
return np.sqrt(sigma * k**3 / rho_hat)
def dt_capillary(sigma, dx, rho_hat):
# 式(4): Brackbill 毛细时间步长 ~ dx^{3/2}
return np.sqrt(rho_hat * dx**3 / (2*np.pi*sigma))
def run_standing_wave(omega, gamma, dt, steps, implicit):
eta, v = 1.0, 0.0
peak = 0.0
for _ in range(steps):
if implicit: # 后向欧拉: 表面张力取新时刻值 (无条件稳定)
v = (v - dt*omega**2*eta) / (1 + dt**2*omega**2 + 2*gamma*dt)
eta = eta + dt*v
else: # 辛欧拉: 显式表面张力 (omega*dt<2 约束)
v = v - dt*omega**2*eta - dt*2*gamma*v
eta = eta + dt*v
peak = max(peak, abs(eta))
return peak
sigma, rho_hat, L = 0.07, 1001.2, 1.0 # 水/空气
for N in (64, 128, 256):
dx = L/N; k = np.pi/dx # 最短可分辨毛细波
om = capillary_omega(sigma, k, rho_hat)
dts = dt_capillary(sigma, dx, rho_hat)
print(f"N={N:4d} dt_sigma={dts:.2e} omega*dt_sigma={om*dts:.3f}")
# 输出: 所有 N 下 omega*dt_sigma = 2.221 (= pi/sqrt(2)),CFL 即毛细约束本身
N = 128; dx = L/N; k = np.pi/dx
om = capillary_omega(sigma, k, rho_hat); dts = dt_capillary(sigma, dx, rho_hat)
dt = 1.5*dts; gamma = 0.1*om # 强制取毛细约束的 1.5 倍
pe = run_standing_wave(om, gamma, dt, 200, implicit=False)
pi_ = run_standing_wave(om, gamma, dt, 200, implicit=True)
print(f"dt=1.5*dt_sigma 显式峰值={pe:.1e} 隐式峰值={pi_:.3f}")
# 输出示例: 显式峰值=3.6e+07 隐式峰值=1.000代码放进去的是 、密度和 、长度 。 是水加空气, 是表面张力。 时 ,同一公式给出的 约 。 再除以 ,约 。 再除一次,约 。从64到256,间距只变成四分之一,同一物理时间的步数却变成8倍,因为 。omega*dt_sigma 与分辨率无关,总是2.221。注释里的例子取 、200步、,显式峰值 ,隐式 。那时 ,越过辛欧拉的2。
曲线的横轴是 。mesh 和 滑块移动的是 本身。
显式(橙色)把 守到 ,再往上就越过1。隐式(青色)在任何步长下都 。把 提高4倍, 变成 。这道枷锁的斜率并不只来自网格。
全耦合才是关键 — 把色函数、压力、速度装进一个矩阵
隐式化的难点在于,表面张力 与色函数(colour function,用 0~1 标记流体种类的 VOF 变量) 非线性纠缠。曲率 也由 的导数决定。论文对该项关于新时刻的 做 Newton 线性化,并把界面输运方程与连续、动量方程一起作为单一线性系统 求解,其中 被整体隐式耦合。Denner 等人此前的算法被锁死在密度比 1。Janodet 的贡献是把连续与动量写成守恒形式,并在瞬态项中把密度关于 隐式处理,从而在水/空气 1000:1 这样的大密度比下仍保持耦合。界面输运用 THINC/QQ 而非 CICSAM 离散,在大 CFL 下也保持界面锐利。与 OpenFOAM 的分离式 PIMPLE 不同,这要在块耦合(block-coupled)求解器里才有意义。
复现时撞上的问题
“无条件稳定”是有附注的。即便隐式表面张力突破了毛细约束,可稳定的最大 仍然有限。Galusinski–Vigneaux 的粘性-毛细上限给出了它。在密度比 1000 下,这个上限比密度比 1 时严苛一个数量级,论文自己也报告在无粘极限下只稳定到约 。上面的振子模型简化了这种粘性-毛细耦合,因而让隐式一侧显得比现实更宽容。此外后向欧拉虽稳定,却会人为地衰减快毛细波。在需要能量守恒的问题里,这种数值衰减可能被误认为物理衰减,所以论文单独验证了力平衡与能量守恒。
停在 1.5 Δt_σ,还是丢掉密度比 1000#
隐式跨过毛细 CFL 之后,上限还在。无粘极限里论文说的稳定窗口大约是 。注释里 1.5 倍、200 步的例子,显式峰值冲到 ,隐式停在 1.000,那是振子,不是求解器。密度比 1000 时,Galusinski–Vigneaux 上限比密度比 1 紧一个数量级。振子给的宽限,到求解器里留不下来。
后向欧拉用数值把快毛细波杀掉,换来稳定。能量必须守住的问题里,这种衰减很容易被当成物理。把 再往前推之后的窗口,记在 五倍处打开、十倍处关上的记录 里。
相关文章
如果对您有帮助,请分享。