3. 迭代求解器不收敛

在计算物理中,绝大多数偏微分方程离散后都会得到一个大型线性或非线性方程组,最终交给迭代求解器处理。迭代法不收敛是排障中最常见、也最容易被误判的一类问题:有人看到残差曲线不动就加大迭代步数,有人看到残差上下跳动就换求解器,结果往往徒劳。要高效定位,先要分清两种截然不同的失败形态——残差停滞与发散振荡,它们的成因和处置手段差别很大。

先读懂残差曲线:三种典型形态

迭代求解器的核心观测量是残差范数,通常取相对残差 r_k = ||b - A x_k|| / ||b||。健康收敛时,残差在半对数坐标下近似直线下降;而故障形态主要有三类:

  • 停滞:残差快速下降一段后进入平台,几乎不再变化,例如卡在 1e-4 附近。常见于预条件子与矩阵不匹配、边界条件欠约束、存在零空间(如纯 Neumann 问题的常数零模态)。
  • 发散振荡:残差在若干量级间来回跳动甚至持续上升。常见于松弛因子过大、矩阵非对角占优、对流项离散导致中心差分失稳、时间步长超过稳定性限制。
  • 缓慢收敛:残差单调下降但斜率极缓,迭代上千步仍达不到容差。多与条件数过大、网格长宽比过高、预条件子质量差有关。

下图给出三类残差形态的判读逻辑与对应的首要排查方向,可作为现场诊断的对照参考。

迭代残差形态判读与排查方向 残差停滞 迭代步 log r 平台 ≈1e-4 发散振荡 迭代步 log r 振幅增大 / 量级跳动 缓慢收敛 迭代步 log r 斜率平缓,步数超限 首要排查 · 预条件子与矩阵不匹配 · 边界条件欠约束 / 零空间 · 容差低于舍入误差下限 · 检查 A 是否奇异 首要排查 · 松弛因子 ω 过大 · 对流项中心差分失稳 · 时间步长超稳定限 · 矩阵非对角占优 首要排查 · 条件数过大 · 网格长宽比过高 · 预条件子质量差 · 改用 GMRES / 多重网格

停滞的典型成因与验证手段

停滞最容易被误认为“算得慢”,其实它往往意味着迭代方向已经无法再降低残差。一个高频原因是预条件子与矩阵不匹配:例如对非对称矩阵误用了对称 Gauss-Seidel 预条件,或 ILU 分解的填充级别过低,导致预条件后的系统仍严重病态。验证方法是关闭预条件(P = I)跑几十步,若残差下降趋势明显改善,说明预条件子本身在拖后腿。

第二个高频原因是零空间未被处理。以纯 Neumann 边界的热传导问题为例,解只在相差一个常数的意义下唯一,系数矩阵奇异,残差会稳定停在某个非零水平。此时应固定一个参考点(如令 x[0] = 0)或改用能处理奇异系统的求解器。第三个原因是容差设置不合理:把相对容差设到 1e-14,而双精度舍入误差本身就在 1e-16 量级,残差自然无法继续下降。经验上,相对容差取 1e-8~1e-10 已能满足多数工程精度。

发散振荡的典型成因与稳定化

振荡发散通常指向迭代格式本身不稳定。以 SOR 方法为例,松弛因子 ω 必须满足 0 < ω < 2,且最优值依赖谱半径;ω 取 1.9 对某些矩阵会直接振荡。调试时先把 ω 降到 1.0(退化为 Gauss-Seidel)观察是否恢复单调下降,再逐步上调。

对流占优问题中,若对流项采用中心差分且网格 Péclet 数 Pe = u·h/α > 2,离散矩阵失去对角占优,迭代必然振荡。此时应改用迎风格式或加人工粘性。瞬态问题则要检查时间步长是否超过显式格式的 CFL 限制。下面是一段可复用的诊断代码骨架,用于在迭代循环中自动识别形态:

r_hist = []
for k in range(max_iter):
    r = np.linalg.norm(b - A @ x) / norm_b
    r_hist.append(r)
    if r < tol:
        print("收敛于第", k, "步"); break
    if k > 20:
        recent = r_hist[-10:]
        if max(recent) / min(recent) < 1.05:
            print("残差停滞,检查预条件子/零空间"); break
        if recent[-1] > 10 * recent[0]:
            print("发散振荡,检查松弛因子/离散格式"); break
    x = x + omega * (solve_precond(b - A @ x))

系统化调试顺序

面对不收敛,建议按“先小后大、先简后繁”的顺序排查:先用一个已知解析解的小规模算例(如 2D Poisson 方程在 16×16 网格上)验证求解器链路是否正常;再逐步放大到真实规模,观察残差形态在哪一步发生质变;然后单独测试预条件子、松弛因子、边界条件三个变量,每次只改一个。若条件数过大导致缓慢收敛,可考虑改用 GMRES 配合 ILU,或引入几何多重网格作为预条件。记录每次调整后的残差曲线与迭代步数,是判断是否真正改善的唯一可靠依据,切勿仅凭“感觉变快了”下结论。

调试时把残差历史完整保存并画在半对数坐标上,比只看最终是否收敛更有价值——曲线的拐点、平台和振荡周期往往直接指向根因。