很多人第一次接触非线性仿真时,会看到一堆求解器词汇:residual、Jacobian、Newton iteration、tangent stiffness、nonlinear convergence。翻译过来,就是残差、雅可比矩阵、牛顿迭代、切线刚度和非线性收敛。
这些词看起来像高深的数学术语,其实背后的核心思想就是牛顿迭代方法。牛顿迭代想解决的问题只有一个:当前这个解还不对,那我下一步应该往哪里改、改多少?
为了回答这个问题,牛顿迭代用了两个信息:残差告诉我们当前错了多少;导数 / Jacobian 描述当前附近,未知量的变化会怎样影响残差。这篇文章就从最简单的一维方程讲起,看清楚牛顿迭代到底在做什么。
假设我们要解一个方程:
R(u) = 0
这里的 u 是未知量。R(u) 可以理解成一个函数,我们的目标是找到某个 u,让这个函数值等于 0。如果画成图像,就是找这条曲线和横轴的交点,这个交点就是方程的解。
如果函数很简单,比如一条直线,那当然可以直接求交点。但很多非线性问题不是直线,而是一条弯曲的曲线。曲线不好直接求解,于是牛顿迭代的想法出现了:曲线不好直接解,那就在当前点附近,用一条切线先近似它。
假设我们现在有一个猜测值:
u_k
把它代入方程,得到:
R(u_k)
如果:
R(u_k) = 0
说明猜对了,当前点就是解。但通常不会这么幸运。大多数时候:
R(u_k) ≠ 0
这说明当前点还不是解;把它代入方程后得到的 R(u_k),就是当前残差。
那怎么办?牛顿法 会在当前点 u_k 处画一条切线。这条切线代表的是:在当前点附近,先用一条直线近似原来的曲线。
为什么要用直线?因为直线好解。曲线和 x 轴的交点不好直接找,但直线和 x 轴的交点很容易算。所以牛顿法不是一上来就直接找原曲线的真实交点,而是先做一件近似的事:
当前点 → 画切线 → 找切线和 x 轴的交点 → 把这个交点作为新的猜测点
然后再在新的点上继续重复这个过程。

比如我们要解:
u² = 2
可以改写成:
R(u) = u² - 2 = 0
如果初始猜测是:
u_0 = 1
那么当前值是:
R(1) = 1² - 2 = -1
说明当前解还没有满足方程。导数是:
R'(u) = 2u
在 u_0 = 1 处:
R'(1) = 2
令切线近似后的函数值等于 0,就得到牛顿修正方程:
R'(u_0) · Δu = -R(u_0)
也就是:
2 · Δu = 1
所以:
Δu = 0.5
新的猜测点就是:
u_1 = 1 + 0.5 = 1.5
再算一次:
R(1.5) = 1.5² - 2 = 0.25
R'(1.5) = 3
新的牛顿修正方程是:
3 · Δu = -0.25
所以:
Δu ≈ -0.0833
于是:
u_2 = 1.5 - 0.0833 = 1.4167
继续迭代,就会越来越接近:
√2 ≈ 1.4142
这个例子里,牛顿迭代并没有一下子“看穿”真实答案。它只是不断做三件事:看当前错了多少,看当前斜率是多少,再估算下一步该怎么改。
CAE 里的问题当然比 u² - 2 = 0 复杂得多。因为未知量通常不是一个数字,而是一大堆自由度。
在结构仿真里,未知量可能是每个节点的位移。在三维结构里,一个节点可能有 ux、uy、uz。如果节点很多,自由度就可能是几万、几十万,甚至更多。
在 CFD 里,未知量可能是速度、压力、温度、组分浓度、湍流变量。这些未知量之间还互相耦合。所以 CAE 里的非线性方程通常不是一个方程,而是一组方程:
R(u) = 0
这里的 u 不再是一个数,而是一个向量:
u = 所有未知自由度组成的向量
R(u) 也不再是一个数,而是残差向量:
R(u) = 每个方程、每个自由度上的不平衡量

在一维问题里,牛顿迭代用的是导数:
R'(u_k)
但在多自由度问题里,未知量很多,残差也很多。这时就不能只用一个导数了。我们需要知道:每一个未知量变化一点,会怎样影响每一个残差方程。
这就是 Jacobian 矩阵。它可以写成:
J(u_k) = ∂R / ∂u
它描述的是残差对未知量的敏感性。换句话说,残差告诉求解器当前错了多少;Jacobian 描述当前附近,未知量的变化会怎样影响残差。
于是,一维里的牛顿修正方程:
R'(u_k) · Δu = -R(u_k)
在多自由度 CAE 问题里就变成:
J(u_k) · Δu = -R(u_k)
这里,R(u_k) 是当前残差,J(u_k) 是当前解附近的 Jacobian,Δu 是这一轮要求解的修正量。求出 Δu 后,更新:
u_{k+1} = u_k + Δu
然后下一轮重新计算残差、重新计算或更新 Jacobian,再继续迭代。

在结构非线性里,很多软件不会总说 Jacobian,而会说 tangent stiffness,也就是切线刚度。这其实和牛顿法里的“切线”是同一个思想。
线性结构静力学里,我们熟悉的是:
K u = F
这里 K 是刚度矩阵。但在非线性结构问题里,结构刚度可能会随着当前状态改变。比如材料进入塑性,橡胶发生大变形,结构几何发生明显变化,接触状态发生开闭或滑移,边界条件或载荷随变形变化。
这时,内力和位移之间不再是简单线性关系。整体平衡更适合写成:
R(u) = F_internal(u) - F_external = 0
当前位移 u_k 如果还不平衡,就有残差。为了修正它,牛顿法 会在当前状态附近做线性化:
K_t · Δu = -R(u_k)
这里的 K_t 就是切线刚度矩阵。它可以理解为:当前这个状态附近,结构力—位移关系的局部线性近似。
所以结构里的“切线刚度 × 位移修正量 = 负残差”,本质上就是数学里的“Jacobian × 修正量 = 负残差”,只是工程语境换了说法。
牛顿迭代不是把非线性问题一次性变成线性问题。它做的是:在每一个迭代步,把当前点附近的非线性问题临时近似成一个线性修正问题。
原始目标是:
R(u) = 0
但当前这一轮实际求解的是:
J(u_k) · Δu = -R(u_k)
或者在结构里写成:
K_t · Δu = -R(u_k)
这就是一个线性代数方程组。所以求解器每一轮都在做:
当前解 u_k → 计算残差 R(u_k) → 计算或更新 Jacobian / 切线刚度 → 解线性修正方程 → 得到修正量 Δu → 更新解 u_{k+1} → 再判断残差是否足够小
如果残差足够小,就认为这一非线性步收敛。如果残差降不下来,或者震荡、变大,就说明当前迭代过程遇到了困难。
理解了牛顿迭代的过程,就能理解为什么非线性仿真会不收敛。牛顿法依赖的是当前点附近的局部线性近似。如果当前点离真实解比较近,问题也比较平滑,那么这条“切线”通常很可靠,迭代会很快收敛。
但如果当前点离真实解太远,或者问题非线性太强,那么当前这条切线可能就不再代表后面的真实曲线。这时求出来的修正量可能方向不对、步子太大,导致下一步残差更大;也可能在几个状态之间来回震荡,或者让矩阵变得病态、接近奇异。
在 CAE 软件里,就可能表现为 residual 不下降、residual 震荡、Newton iteration 失败、cutback、time step / load step 被减小、Jacobian 或 stiffness matrix 接近奇异、nonlinear solver did not converge。
所以不收敛不是一个单独的“软件报错”。它背后通常是在说:当前这个局部线性化,已经不足以可靠地把解带到正确方向。这可能和很多因素有关:
牛顿迭代可以用一句话概括:它用当前点的残差和 Jacobian,把非线性问题临时变成一个线性修正问题,然后不断更新解,直到残差足够小。
如果用更短的链条表示,就是:
非线性问题 → 当前猜测解 → 计算残差 → 计算 Jacobian / 切线刚度 → 求解线性修正方程 → 更新解 → 再判断残差
放到 CAE 里,牛顿迭代也没有脱离这个基本思想。它只是从一个变量的方程,变成了多自由度、多方程耦合的非线性系统。
一维里的导数,变成了 Jacobian。结构里的 Jacobian,常常表现为切线刚度矩阵。而每一次非线性迭代,本质上都是求解器在问:根据当前残差和当前局部线性关系,我下一步应该怎么修正这个解?
理解了这一点,再看 residual、Jacobian、切线刚度、非线性收敛、矩阵奇异,就不再是孤立的软件术语,而是同一条求解逻辑上的不同部分。

参考资料
ANSYS Mechanical APDL Theory Reference, Newton-Raphson Procedure.
https://www.mm.bme.hu/~gyebro/files/ans_help_v182/ans_thry/thy_tool10.html
ETH Zürich, The Finite Element Method for the Analysis of Non-Linear and Dynamic Systems. https://public.fangzhenxiu.com/fixComment/commentContent/imgs/1784605188276_9b14bm.pdf
COMSOL Blog, Solving Nonlinear Static Finite Element Problems. https://www.comsol.com/blogs/solving-nonlinear-static-finite-element-problems/