本文译自作者的韩语原文。 阅读原文(한국어)
[论文评述] 把对流和压力彻底拆开 — Baer–Nunziato flux 的 TV 分裂
Toro Test 4上密度L1大约比Rusanov小1.5倍,可Noh壁面第三步压力就到了−0.12。
Tokareva 和 Toro 2016 年的这篇论文,看起来三十分钟就能复现完。把 flux 一分为二,各自单独计算再相加,仅此而已。实现确实只用了 40 行。在两道强激波对撞的 Riemann 问题上,它比 Rusanov flux 精确 1.5 倍。然后换到 Noh 问题,第三步压力就变成了 −0.12。今天就用代码追一遍:这个分裂究竟做了什么,白拿到了什么,又在哪里付账。
把 a 滑块从 0.1 拉到 2.0,只有右边压力系统的扇形张开,中间对流系统的扇形角度不动。
看 |λ|max 条在哪一块面板变长,声学 CFL 就落在压力系统那一侧。把 ū 推到 ±2,下方标记会离开论文里的亚声速假定。
论文如何切开 flux#
- 作者: S. A. Tokareva, E. F. Toro
- 题目: A flux splitting method for the Baer–Nunziato equations of compressible two-phase flow
- 出处: Journal of Computational Physics 323 (2016) 45–74
- DOI: 10.1016/j.jcp.2016.07.019
一句话概括:把 Toro–Vázquez(TV) flux 分裂推广到 Baer–Nunziato(BN,给两相各自速度和压力的七方程模型)方程,只求解拆出来的廉价压力子系统,再拼出整体 flux。
BN 方程写不成守恒形式。一维 x-分裂形式把非守恒项单独带在身上。
是七个守恒量, 是守恒 flux, 是挂在体积分数梯度上的非守恒项。带横杠(¯)的是固相,不带的是气相。
论文的起手式,是把 的守恒部分切成两块。只写气相三个分量:
里一个压力项都没有。 里一个 对流项都没有。两者相加,精确还原原来的 Euler flux。对流系统(A-system)与压力系统(P-system)由此而来,非守恒项归到压力系统一侧。
切开之后,声速只留在一侧
拆分的收益,看各子系统的特征速度就清楚了。对流系统的 Jacobian 第三列为零,因此特征值是 。没有声速。压力系统对原始变量 给出
是比焓,。代入理想气体:,于是 ,即 。固相的 stiffened EOS 同样化为 。
代入 得到 。也就是说,声速整个落在压力系统里。锁住时间步长的不是对流系统。
锁住时间步的 在哪一侧,上面面板的 |λ|max 已经拆开给看了。 时 ,所以变长的那根条才是声速。
BN 只多加了一条 λ₇ = ū#
气相、固相各三个共六个,再加上第七个特征值 。论文展开特征向量得到的结论在工程上很关键:体积分数 只在穿过 场时跳变。气相密度穿过 不变,气相压力在 上为常数。
这让 Godunov 状态的采样变便宜。假定亚声速配置 ,则 恒成立,界面状态仅由 的符号决定。也不需要熵修正。这正是论文声称节省 CPU 时间之处。上面模拟底部的绿/红标记会实时检查该亚声速条件;把 ū 推到 ±2,就走出了论文覆盖的范围。
体积分数的跳跃只搭在 上,这和把非守恒项挂错波之后压力立刻乱跳的 Abgrall 准则 是同一件事。亚声速标记变红的地方,就是这条假定的边界。
两条直线搞定的 P-system Riemann solver#
压力系统非线性波上的广义 Riemann 不变量是:
第一个等号给出 。剩下的 ODE ,论文把系数冻结在特征线的脚上来线性化。固定 ,积分就塌缩成一条直线。
其中 。两条直线联立,无需迭代即得闭式解:
由于 ,恒有 。分母在结构上不可能为零。也就是说没有地方需要放除零保护,实际上也确实不必放。
不过这个线性化有多粗,得亲眼看。在下面拖动左右状态。
白色曲线是用 RK4 老老实实积分的不变量,虚线是论文真正使用的切线。把 p_L/p_R 降到 1.1,两个星状态在 2% 以内重合。默认比值 3 时已经是 12%,把 p_L 提到 40 则张开到 67%。切线到不了曲线去的地方。
代码 — 40 行结束的 TV flux#
缩到理想气体单相来实现。压力系统状态不需要 ,这点很省事:因为 ,P-flux 第三个分量整理成 。
import numpy as np
def prim(q, g):
rho = q[0]; u = q[1] / rho
return rho, u, (g - 1.0) * (q[2] - 0.5 * rho * u * u)
def pressure_wave_speed(rho, u, p, g):
"""A = sqrt(u^2 + 4h/(rho e_p)) -> sqrt(u^2 + 4a^2) [论文 eq. 9]"""
return np.sqrt(u * u + 4.0 * g * p / rho)
def advection_flux(rho, u):
"""A(Q): 一个压力项都没有 [论文 eq. 5]"""
return np.array([rho * u, rho * u * u, 0.5 * rho * u ** 3])
def p_system_star(rhoL, uL, pL, rhoR, uR, pR, g):
"""压力系统的线性化 Riemann solver [论文 eq. 15, 19]"""
CL = rhoL * (uL - pressure_wave_speed(rhoL, uL, pL, g)) # 恒 < 0
CR = rhoR * (uR + pressure_wave_speed(rhoR, uR, pR, g)) # 恒 > 0
us = (2.0 * (pR - pL) + CL * uL - CR * uR) / (CL - CR)
return us, pL + 0.5 * CL * (us - uL)
def tv_face_flux(qL, qR, g):
rhoL, uL, pL = prim(qL, g)
rhoR, uR, pR = prim(qR, g)
us, ps = p_system_star(rhoL, uL, pL, rhoR, uR, pR, g)
# 对流系统特征值是 {0, u, u} -> 一个速度符号就定完迎风
fa = advection_flux(rhoL, uL) if us >= 0.0 else advection_flux(rhoR, uR)
# 压力系统: rho e = p/(g-1),所以根本不需要 rho*
fp = np.array([0.0, ps, g / (g - 1.0) * us * ps])
return fa + fp在 Toro Test 4 上跟 Rusanov 对打#
玩具问题选了两道强激波迎面对撞的 Toro Test 4。左 ,右 ,,,CFL 0.9。没有滞止区,迎风方向不会摇摆。精确解另外实现了 Toro 的迭代解法,得到 、。
| TV 分裂 | Rusanov | TV 收敛率 | |
|---|---|---|---|
| 100 | 0.9523 | 1.4303 | — |
| 200 | 0.5936 | 0.9349 | 0.68 |
| 400 | 0.3879 | 0.6187 | 0.61 |
| 800 | 0.2695 | 0.4217 | 0.53 |
同样一阶精度、同一成本量级,TV 分裂稳定地精确 1.5 倍。有意思的是前面看到的星状态误差:此处压力比为 10,压力系统星状态偏离精确值 65%。可格式照样赢。一阶 FV 里主导误差是 抹平,而 P-flux 不需要准确,只要相容且耗散就够了。
在 Noh 问题上分道扬镳的地方#
换到 Noh 问题。,、 向壁面涌来,精确解是 、、,激波立在 。整个波后区域都是 的滞止区。
TV 分裂以两种方式死掉。若按 的符号对对流 flux 迎风, 时第 3 步、距壁第二个单元出现 。改按 的符号迎风则能活下来,但网格越细,密度锯齿越严重。
| TV 分裂 | Rusanov | |
|---|---|---|
| 100 | 12.01 | 0.445 |
| 200 | 14.18 | 0.194 |
| 400 | 31.38 | 0.104 |
| 800 | 34.45 | 0.072 |
是波后区域密度的全变差。网格加密 8 倍,Rusanov 降为六分之一,TV 分裂却涨了三倍。它不收敛。平均值本身两边都对——TV 是 ,Rusanov 是 3.99——但剖面不一样。
原因就在分裂本身。质量 flux 只有 的第一分量 这一项,而 的第一分量为零。也就是说,压力系统根本不碰密度。 滞止区里 ,质量 flux 也跟着归零,密度场上就没有数值耗散可留。无论迎风取哪一侧结果都相同,于是奇偶单元解耦。同样这个对流 flux 的选择,在 Toro Test 4 上只把 从 0.594 改成 0.568。在 处几乎无关紧要,在 处却是生死攸关。
把表里的比原样除开,分叉的位置会更清楚。 时 TV 分裂的 0.9523 是 Rusanov 1.4303 的 0.666 倍。 时 0.5936/0.9349 约为 0.635, 时 0.2695/0.4217 约为 0.639。所谓 1.5 倍,是三个网格上的比值都卡在 0.63 到 0.67 之间。收敛率顺着 0.68、0.61、0.53 往下掉,斜率不到一阶。这和压力比等于 10 时星状态偏了 65%、 却仍然赢,是对得上的。 的抹平比星状态误差更大。Noh 那边的全变差正好相反。从 12.01 到 34.45,网格放大 8 倍的过程里大约涨了 2.87 倍。Rusanov 从 0.445 降到 0.072,大约缩了 6.2 倍。平均密度 和 3.99 都靠近精确解 4。积分量是对的,长出来的只有锯齿。对流 flux 的取法一换,Toro Test 4 的 从 0.594 挪到 0.568,幅度只有 0.026。同一个选择在 Noh 上,要么第三步就打出 ,要么活下来却把锯齿养大。
论文跳过的东西
论文的六个测试问题全是 Riemann 问题,跨越初始间断的速度都不为零。没有一个会制造滞止区、壁面反射或定常流动。上面的结果表明这个盲区确实存在。论文把对流系统 flux 甩给 Toro–Vázquez 原文也很遗憾——那里只写了「straightforward」,可实际上这个选择决定了滞止区的生死。
亚声速限制也还在。 的引入理由是「许多作者认为它在物理上更合理」,但固相超过气相声速的配置,在爆燃-爆轰转变(DDT)中确实会出现。固相接触面处仍需用迭代法求解薄层(thin-layer)非线性方程组,这一点也和「无需迭代」的印象不符——尽管论文明确表示未遇到收敛问题。
效率数字很有说服力。线性化 solver 最快,最接近的竞争者慢 8 倍;而 HLLEM-TV 贵 125 倍,数值 Roe 贵 67 倍。作者的结论——一旦需要评估特征向量,TV 分裂的吸引力就荡然无存——直接体现在这组数字里。若要在 OpenFOAM 一类代码里模仿这个结构,做法是建两个独立的 surfaceScalarField 再相加,而只用专门的 Riemann solver 去填压力系统那一半,完全可行。
壁面单元的迎风交给 u*,还是交给平均速度#
用 的符号给对流做迎风, 时第三步、离壁第二个单元的压力会到 。改成平均速度的符号可以躲开负值,但网格加密 8 倍时 会从 12.01 涨到 34.45。Rusanov 则从 0.445 降到 0.072。滞止单元的质量 flux 放在哪里,就是在收敛和负压之间做选择。
复现到分裂定义(式 3–5)、压力系统特征结构(式 9–10)、线性化(式 15、19、23、26)为止,都和式子一致。 时 在机器精度上成立,切线是精确曲线的 。缺的两处,一是对流系统 flux 根本不在这篇论文里,二是薄层推导压得太紧,还得对照原文 [1] 和 [4]。界面上声波几乎全被反射回去的水–气配置,声阻抗另有一笔。这个分裂的对流 flux 最早写在 Toro & Vázquez (2012), Computers & Fluids 70, 1–12。
相关文章
如果对您有帮助,请分享。