跳到正文
格致开物MATHWIKI

柯朗—弗里德里希斯—列维条件

柯朗—弗里德里希斯—列维条件(Courant–Friedrichs–Lewy condition,简称CFL条件)比较微分方程的信息传播速度与离散格式在网格上传递信息的速度。对显式双曲问题格式,要在网格细化时得到正确解,数值依赖域必须能够覆盖相应的物理依赖域。由此导出的时间步长限制是必要条件;它是否也足以保证稳定,还取决于具体方程和格式。

考虑一维线性输运方程 ut+cux=0,速度 c>0 为常数。解沿特征线平移,即 u(x,t)=u0(x−ct)。设空间步长为 Δx、时间步长为 Δt,无量纲Courant数为 ν=cΔt/Δx。它表示一步内物理信号跨过多少个网格间距。

迎风格式的信息来源

在网格 xj=jΔx,tn=nΔt 上,以 Ujn 近似真解。对正速度使用左侧差分,得到显式迎风格式 Ujn+1−UjnΔt+cUjn−Uj−1nΔx=0,Ujn+1=(1−ν)Ujn+νUj−1n. 一步只读取当前位置和左邻居;两步至多读取 j,j−1,j−2,归纳可知,经过 n 步只可能使用初始网格点 j−n,…,j 的数据。数值信息最远每步向右传播一个网格间距。

真解在 (xj,tn) 却读取初始位置 xj−ctn=xj−nνΔx。要让它位于数值依赖范围 [xj−nΔx,xj] 内,必须有 0≤ν≤1. 对这里的正速度,左侧非负自动成立,所以常写为 cΔt≤Δx。[1]

四步数值依赖域底边从零到四,Courant数为0.5时物理特征线起点为二,位于范围内
取空间、时间步长均为一、当前点横坐标四。物理传播脚点落在数值依赖范围内。
同一四步数值依赖域底边从零到四,Courant数1.25的物理脚点为负一,在范围外
时间步过大时,真解需要的初始信息来自数值格式无法读取的位置。

这个必要性的含义可用两组初值说明。若在细化过程中物理脚点始终位于数值依赖域之外,就可选两组初值,使它们在数值依赖区间上完全相同,在物理脚点附近却不同。格式因读取相同数据给出相同输出,两个真解在目标点却不同,因此不可能对两组初值都收敛到正确解。这是依赖域条件的理由,不是把某张图上看见的一个脚点当作全体格式的稳定性证明。

对迎风格式成立的稳定性证明

当 0≤ν≤1 时,更新是两个旧值的凸组合,所以 minjUjn≤Ujn+1≤maxjUjn. 对两个数值解之差 Ejn 使用同一更新式,三角不等式给出 |Ejn+1|≤(1−ν)|Ejn|+ν|Ej−1n|≤maxk|Ekn|. 对 j 取最大值,再逐步迭代,得到 ‖En‖∞≤‖E0‖∞。这证明在无限网格或周期边界下,初始扰动的最大幅度不增长;一般边界还要正确控制边界输入。

取傅里叶模式 Ujn=Gneijθ,可求得放大因子 G(θ)=1−ν+νe−iθ,|G(θ)|2=1−4ν(1−ν)sin2(θ/2). 所以在本格式中,0≤ν≤1 也恰好保证所有模式不放大。若 ν=1.25,交替正负模式 θ=π 每步乘 1−2ν=−1.5,幅度逐步乘 1.5,直接显示失稳。ν=1 时更新为 Ujn+1=Uj−1n,恰好每步平移一格。

六个网格值的手算与程序

在周期网格上取初值 (0,1,2,1,0,0),末端左邻居按周期回到数组末项。取 ν=1/2,第一步为 (0,1/2,3/2,3/2,1/2,0), 第二步为 (0,1/4,1,3/2,1,1/4)。每步数值和仍为四,最大值未超过初始的二。和守恒来自将更新式对全部周期索引求和:两个旧值之和都等于同一个旧数组总和。

下面输入周期网格值、Courant数和步数,返回新的数组;不改写输入,只接受有限实数值以及稳定范围内的 ν。它求解的是已说明的正速度迎风更新,不是通用偏微分方程求解器。

Python 3
from math import isfinite

def periodic_upwind(values, nu, steps):
    state = [float(x) for x in values]
    nu = float(nu)
    if len(state) < 2 or not all(isfinite(x) for x in state):
        raise ValueError("need at least two finite grid values")
    if not isfinite(nu) or not 0 <= nu <= 1:
        raise ValueError("Courant number outside [0,1]")
    if type(steps) is not int or steps < 0:
        raise ValueError("steps must be a nonnegative integer")
    for _ in range(steps):
        old = state
        state = [(1 - nu) * old[j] + nu * old[j - 1]
                 for j in range(len(old))]
    return state

initial = [0, 1, 2, 1, 0, 0]
assert periodic_upwind(initial, 0.5, 1) == [0, 0.5, 1.5, 1.5, 0.5, 0]
assert periodic_upwind(initial, 0.5, 2) == [0, 0.25, 1, 1.5, 1, 0.25]
assert periodic_upwind(initial, 1, 1) == [0, 0, 1, 2, 1, 0]
assert periodic_upwind(initial, 0, 3) == initial
assert initial == [0, 1, 2, 1, 0, 0]
print(periodic_upwind(initial, 0.5, 2))

每步对 m 个网格值各计算一次凸组合,N 步时间为 O(mN),仅保存新旧数组,空间为 O(m)。若 c<0,应改用右侧邻居;只把负速度代进上述左迎风式会使权重超出凸组合范围。

CFL条件不等于通用稳定性条件

变式。 将空间差分改为中心差分,得到前向时间中心空间格式 Ujn+1=Ujn−ν2(Uj+1n−Uj−1n). 它的数值依赖范围每步向两侧各扩一格,因此同样可以满足 |ν|≤1 的几何条件。取保持固定非零 ν 的双曲细化路径,其放大因子为 G=1−iνsin⁡θ;选择 sin⁡θ=1 的网格模式,单步幅度乘 1+ν2>1。在固定正时间 T 内,步数 n=T/Δt 随细化趋于无穷,累计放大 (1+ν2)n/2 无界,所以沿这条满足几何CFL的细化路径仍不稳定。必要的依赖域覆盖没有保证该格式控制扰动。这里用到了固定非零Courant数;仅有某一步的放大大于一并不足以排除所有细化路径,例如让 Δt/Δx2 有界时,累计放大可有固定时间上的有界增长。

扩散方程也有显式时间步限制,典型尺度为 Δt=O(Δx2),其传播机制和放大因子与输运不同;不能只把波速公式机械换一个符号就涵盖全部方程。

参考文献

  1. ↑ Tobin A. Driscoll、Richard J. Braun:Fundamentals of Numerical Computation: Upwinding and stability,数值与精确依赖域、CFL条件及迎风方向。访问日期:2026-10-22。