4、时间步长与CFL条件:显式与隐式时间推进、CFL数选取原则、自适应时间步长、瞬态仿真的时间分辨率

时间步长怎么选?这个问题我几乎每次培训都会被问到。

说实话,我刚入行那会儿也踩过坑。有一次算一个高超声速进气道,时间步长设得太大,结果激波直接穿过了壁面——嗯,算出来的结果我自己都不敢信。后来才明白,时间步长不是拍脑袋定的,背后有个硬约束叫CFL条件。

4.1 显式时间推进:简单但“短腿”

显式格式,说白了就是“用当前时刻的值,直接算出下一时刻”。

它的优点是实现简单,每步计算量小。但缺点也很明显——稳定性受CFL条件严格限制。

显式格式的CFL条件:

CFL = u · Δt / Δx ≤ CFL_max

对于大多数显式格式,CFL_max ≈ 1.0

什么意思呢?就是你的时间步长不能太大,否则数值上就“炸”了。我见过一个新手做LES,网格加密后忘了调时间步长,结果残差直接飞到10^10——那画面,啧啧。

注意:显式格式的CFL上限因空间离散格式而异。中心差分通常CFL_max ≈ 1.0,迎风格式可能到0.8,高阶格式甚至只有0.3~0.5。别拿一个值到处套。

4.2 隐式时间推进:稳,但代价高

隐式格式就不一样了。它用“未来时刻”的值来算,每步都要解一个大型线性方程组。

代价是每步计算量大,但好处是——理论上无条件稳定。你想想看,这意味着你可以用大时间步长,快速算到稳态。

我的经验:做稳态计算时,我习惯用隐式格式配合大CFL数(比如5~100)。但做瞬态计算时,千万别为了省时间把CFL设太大——时间精度会丢,涡结构都给你抹平了。

我曾经帮一个团队调试涡轮叶栅的算例。他们用隐式格式,CFL设到200,结果算出来的总压损失比实验值低了30%。后来我把CFL降到10,结果就对上了。为什么?因为时间离散误差把流动的细节给“平均”掉了。

4.3 CFL数选取原则:不是越大越好

CFL数到底怎么选?我总结了一个“三步法”:

  1. 看问题类型:稳态还是瞬态?稳态可以大CFL(隐式),瞬态必须小CFL。
  2. 看网格质量:网格长宽比大、扭曲严重的地方,CFL要打折。我一般打五折起步。
  3. 看物理特征:有激波、火焰面、相界面这些强间断,CFL要小。我通常从0.5开始试。
应用场景 推荐CFL(显式) 推荐CFL(隐式)
稳态不可压 0.5~1.0 5~50
稳态可压缩(无激波) 0.3~0.8 10~100
稳态可压缩(有激波) 0.1~0.5 1~10
瞬态LES/DES 0.3~0.8 0.5~2
瞬态DNS 0.1~0.3 0.2~0.5

核心原则:CFL数不是越大越好,也不是越小越好。它是在“计算效率”和“时间精度”之间找平衡。

4.4 自适应时间步长:让求解器自己“踩油门”

手动调时间步长?太累了。尤其是非定常流动,流场变化剧烈的时候,一个固定步长要么浪费计算资源,要么算不准。

自适应时间步长就是让求解器根据当前流场状态,自动调整Δt。

常见的策略有:

  • 基于CFL数:设定目标CFL,每步根据最大速度/声速反算Δt。
  • 基于残差变化:残差下降快就增大Δt,下降慢就减小。
  • 基于物理时间尺度:比如涡脱落周期、火焰传播时间等。
// 伪代码示例:基于CFL的自适应步长
double compute_dt(mesh, fields, target_cfl) {
    double dt_min = 1e10;
    for (each cell) {
        double u = |velocity| + speed_of_sound;
        double dx = cell_characteristic_length;
        double dt_local = target_cfl * dx / u;
        dt_min = min(dt_min, dt_local);
    }
    return dt_min;
}

我的习惯:做LES时,我通常设目标CFL=0.5~0.8,然后让求解器自动调。但我会加一个上限和下限,防止它“抽风”。比如Δt_max = 1e-4,Δt_min = 1e-8。

4.5 瞬态仿真的时间分辨率:别让时间步长毁了你的涡

瞬态仿真最怕什么?时间分辨率不够。

你想想看,一个涡脱落周期是0.01秒,你时间步长设了0.005秒——一个周期才两个点,能看出什么?

我一般遵循“20步原则”:

  • 一个物理周期内,至少要有20个时间步。
  • 对于湍流统计量,至少需要50~100步/周期。
  • 对于声学计算,需要100~200步/周期。

避坑指南:我曾经算一个圆柱绕流,Strouhal数约0.2,来流速度1m/s,圆柱直径0.1m。我一开始用Δt=0.01s,结果涡脱落频率算出来差了15%。后来把Δt降到0.002s,结果才收敛。记住:时间步长收敛性验证,和网格无关性验证一样重要。

4.6 知识体系:一张图说清楚

下面这张图是我自己整理的,把时间步长和CFL条件的核心逻辑串起来了。你看一遍,应该能有个整体印象。

时间步长与CFL条件 · 知识体系 显式时间推进 隐式时间推进 CFL ≤ CFL_max(通常≈1) 理论上无条件稳定 CFL数选取原则 稳态→大CFL(隐式) | 瞬态→小CFL | 有激波→更小CFL | 网格差→打折 自适应时间步长 基于CFL/残差/物理尺度 时间分辨率 20步/周期(最低)→ 100步/周期(推荐) 核心:效率与精度的平衡 · 收敛性验证不可少

这张图从左到右、从上到下,把显式/隐式、CFL约束、选取原则、自适应和分辨率串在了一起。你保存下来,以后调时间步长的时候拿出来对照一下,应该能少走不少弯路。

最后说一句:时间步长这东西,理论是基础,经验是升华。我建议你每做一个新算例,都做一次时间步长无关性验证——哪怕只算三个步长(粗、中、细),也比拍脑袋强十倍。


公众号:蓝海资料掘金营,微信deep3321