FVM in CFD 学习笔记_第10章_求解代数方程组系统

学习自F. Moukalled, L. Mangani, M. Darwish所著The Finite Volume Method in Computational Fluid Dynamics - An Advanced Introduction with OpenFOAM and Matlab
Chapter 10 Solving the System of Algebraic Equations

离散过程将会生成线性方程组系统, A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b,其中未知量 ϕ \boldsymbol \phi ϕ位于网格单元形心上,是待求量。该系统中,未知变量的系数构成了矩阵 A \bold A A,其由线性化过程和网格几何量导出,而向量 b \bold b b则包含了源项、常数项、边界条件和非线性分量。

求解线性方程组系统的技术通常被分为直接方法和迭代方法,每类又有很多具体方法。由于流动问题是高度非线性的,从其线性化过程得到的系数通常是依赖于解的,因此,在每步的迭代过程中并不需要得到非常精确的解,所以直接解法在CFD的应用中很少使用。最常用的还是迭代解法,因为它们更适合求解该类问题,其在每步迭代中所需内存更小,计算消耗更小。

本章首先讲解在结构和非结构网格上的一些直接解法(Gauss消元、LU分解、三对角和五对角矩阵算法),以便为在CFD应用中更加广泛使用的迭代方法提供基础。然后回顾一些基本的迭代解法(含预处理和不含预处理)的特性和局限性,包括Jacobi、Gauss-Seidel、不完全LU分解、以及共轭梯度(CG)方法。最后,简要讲讲多重网格方法,它通常是和迭代方法联合使用,以克服这些迭代方法的局限性。

1 引言

线性求解器求解的是如下形式的代数方程组
A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b
其中 A \bold A A是单元的系数矩阵 a i j a_{ij} aij ϕ \boldsymbol \phi ϕ是未知变量 ϕ \phi ϕ的向量,而 b \bold b b则是源项 b i b_i bi的矢量。使用矩阵编号,该方程的展开形式为
[ a 11 a 12 . . . a 1   N − 1 a 1   N a 21 a 22 . . . a 2   N − 1 a 2   N . . . . . . . . . . . . . . . a N 1 a N 2 . . . a N   N − 1 a N   N ] [ ϕ 1 ϕ 2 . . . ϕ N − 1 ϕ N ] = [ b 1 b 2 . . . b N − 1 b N ] \begin{bmatrix} a_{11} & a_{12} & ... & a_{1~N-1} & a_{1~N} \\ a_{21} & a_{22} & ... & a_{2~N-1} & a_{2~N} \\ ... & ... & ... & ... & ... \\ a_{N1} & a_{N2} & ... & a_{N~N-1} & a_{N~N} \end{bmatrix} \begin{bmatrix} \phi_1 \\ \phi_2 \\ ... \\ \phi_{N-1} \\ \phi_N \end{bmatrix} = \begin{bmatrix} b_1 \\ b_2 \\ ... \\ b_{N-1} \\ b_N \end{bmatrix} a11a21...aN1a12a22...aN2............a1 N1a2 N1...aN N1a1 Na2 N...aN Nϕ1ϕ2...ϕN1ϕN=b1b2...bN1bN
一般来说呢,矩阵 A \bold A A中的每一行代表计算域1个单元上定义的方程,非0系数是与该单元紧邻的邻居单元的,系数 a i j a_{ij} aij反映的是存储在 i i i单元控制体形心的 ϕ i \phi_i ϕi与其邻近单元形心的 ϕ j \phi_j ϕj的关系紧密程度。由于一个单元只和少数几个单元相邻,且其邻接关系是与离散区域上单元的剖分编码方式相关的,所以大部分的系数实际上是0,这就使得矩阵 A \bold A A总是个稀疏矩阵(即,非零元素的个数很少,在整体矩阵中占比很小,绝大多数的元素都是0)。更进一步,如果用的是结构化的网格,那么矩阵 A \bold A A将会是带状矩阵,即,其仅含几条非零的对角线元素。因此,求解该类系统时,可针对其特性选用对应的高效方法。

如上所述,求解代数方程组系统的方法可以大体上分为两大类,即直接和迭代方法。在直接方法中,矩阵 A \bold A A求逆,解 ϕ \bold\phi ϕ通过 ϕ = A − 1 b \bold\phi=\bold A^{-1}\bold b ϕ=A1b来求出。当矩阵 A \bold A A非常大的时候,应用直接线性解法来求解CFD问题是不切实际的,因为这些CFD问题通常包含非线性系统方程, 即它们的系数是与解相关联的,那么使用迭代方法是切合实际的。

另一方面,在迭代代数解法中,求解算法将重复多次直至达到预期的收敛水平,而不需要在每次迭代的过程中都获得完全收敛的解。

接下来,首先展示一些应用于结构和非结构网格的直接解法,紧接着是结构网格上带状矩阵的高效解法,该章的重点是,迭代线性代数求解器,它们已经被广为证明是在FVM中最有效的和最经济的方法,而且已经被包含进几乎所有有限体积代码的线性求解器中。

2 直接或Gauss消元方法

尽管直接方法并非求解线性代数方程组中稀疏系统的高效方法(它们的计算消耗实在是大的离谱),然而对于它们的讨论可为后续高效的迭代方法的引入铺平道路,所以还是讲一下为好。最简单的直接方法是Gauss消元方法,将被首先介绍。使用Gauss消元法时,将系统转化成等效的上三角系统,这激发了下三角上三角分解方法(LU分解方法),将随后介绍。该方法中,矩阵 A \bold A A将被分解成两个矩阵 L \bold L L U \bold U U的乘积,其中 L \bold L L是下三角矩阵,而 U \bold U U是上三角矩阵。该过程也被称为LU因子分解。此外,还将讨论应用于从结构网格所推出的带状矩阵 A \bold A A的直接方法。

2.1 Gauss消元

假设有如下2变量 ϕ 1 \phi_1 ϕ1 ϕ 2 \phi_2 ϕ2的线性方程组
a 11 ϕ 1 + a 12 ϕ 2 = b 1   a 21 ϕ 1 + a 22 ϕ 2 = b 2 a_{11}\phi_1+a_{12}\phi_2=b_1 \\ ~\\ a_{21}\phi_1+a_{22}\phi_2=b_2 a11ϕ1+a12ϕ2=b1 a21ϕ1+a22ϕ2=b2
为了消去 ϕ 1 \phi_1 ϕ1,将第1个式子乘上 a 21 / a 11 a_{21}/a_{11} a21/a11,并减去第2个式子,可得
( a 22 − a 21 a 11 a 12 ) ϕ 2 = b 2 − a 21 a 11 b 1 \left(a_{22}-\frac{a_{21}}{a_{11}}a_{12}\right)\phi_2=b_2-\frac{a_{21}}{a_{11}}b_1 (a22a11a21a12)ϕ2=b2a11a21b1
从而可以直接求得 ϕ 2 \phi_2 ϕ2
ϕ 2 = b 2 − a 21 a 11 b 1 a 22 − a 21 a 11 a 12 \phi_2=\frac {b_2-\displaystyle\frac{a_{21}}{a_{11}}b_1} {a_{22}-\displaystyle\frac{a_{21}}{a_{11}}a_{12}} ϕ2=a22a11a21a12b2a11a21b1
再把这个求得的 ϕ 2 \phi_2 ϕ2代入到方程最初的第1个式子里,可以求得 ϕ 1 \phi_1 ϕ1的值
ϕ 1 = b 1 a 11 − a 12 a 11 b 2 − a 21 a 11 b 1 a 22 − a 21 a 11 a 12 \phi_1=\frac{b_1}{a_{11}}-\frac{a_{12}}{a_{11}}\frac {b_2-\displaystyle\frac{a_{21}}{a_{11}}b_1} {a_{22}-\displaystyle\frac{a_{21}}{a_{11}}a_{12}} ϕ1=a11b1a11a12a22a11a21a12b2a11a21b1
上述过程实际上分成了2步,第1步是消去1个未知量,得到仅剩1个未知量的方程,求解该方程,可得该未知量的值;第2步是将该未知量回代到原方程中,求出剩余未知量的值。即,消元-回代,同样的思路也可用于N个变量的线性代数方程组。

2.2&2.3 前向消元Forward Elimination

直接给出算法流程

for k = 1 to N - 1
{
	for i = k + 1 to N	
	{
		Ratio = a_ik / a_ kk
		for j = k + 1 to N
		{
			a_ij = a_ij - Ratio * a_kj
		}
		b_i = b_i - Ratio * b_k
	}
}

2.4&2.5 反向回代Backward Substitution

直接给出算法流程

phi_N = b_N / a_NN
for i = N - 1 to 1
{
	Term = 0
	for j = i + 1 to N
	{
		Term = Term + a_ij * phi_j
	}
	phi_i = (b_i - Term) / a_ii
}

为防止被0除,消元的时候可选用最大行主元,并互换两行的位置。实际上,Gauss消元回代的方法计算量是非常大的,对于一个N个方程的线性系统,其计算量与 N 3 / 3 N^3/3 N3/3成正比,其中回代过程仅仅占了 N 2 / 2 N^2/2 N2/2,这样高的计算消耗迫使人们针对稀疏矩阵系统寻求更加高效的解法。

2.6 LU分解

求解线性代数方程组的另一个直接解法是LU或PLU(P即前面所讲的行主元选择过程),咱这里就讲讲LU就好了。LU实际上是Gauss方法的变种,LU方法比Gauss消元方法的优势在于,一旦LU分解执行之后,对于右端项 b \bold b b不同的线性系统就想求解多少次就求解多少次,而不需要再做消元处理了(相当于把第1次的消元处理做了LU分解),然而在Gauss消元方法中,消元是始终需要进行的。

基于前面消元处理过程,是将原本的矩阵 A \bold A A转化为上三角矩阵,即
[ u 11 u 12 u 13 . . . u 1   N − 1 u 1   N 0 u 22 u 23 . . . u 2   N − 1 u 2   N 0 0 u 33 . . . u 3   N − 1 u 3   N . . . . . . . . . . . . . . . . . . 0 0 0 . . . 0 u N   N ] [ ϕ 1 ϕ 2 ϕ 3 . . . ϕ N ] = [ c 1 c 2 c 3 . . . c N ] \begin{bmatrix} u_{11} & u_{12} & u_{13} & ... & u_{1~N-1} & u_{1~N} \\ 0 & u_{22} & u_{23} &... & u_{2~N-1} & u_{2~N} \\ 0 & 0 & u_{33} & ... & u_{3~N-1} & u_{3~N} \\ ... & ... & ... & ... & ... & ... \\ 0 & 0 & 0 & ... & 0 & u_{N~N} \end{bmatrix} \begin{bmatrix} \phi_1 \\ \phi_2 \\ \phi_3 \\ ... \\ \phi_N \end{bmatrix} = \begin{bmatrix} c_1 \\ c_2 \\ c_3 \\ ... \\ c_N \end{bmatrix} u1100...0u12u220...0u13u23u33...0...............u1 N1u2 N1u3 N1...0u1 Nu2 Nu3 N...uN Nϕ1ϕ2ϕ3...ϕN=c1c2c3...cN
使用缩写形式,即
U ϕ − c = 0 \bold U \boldsymbol \phi - \bold c = \bold 0 Uϕc=0
L \bold L L为单位下三角矩阵(对角线上的元素是1),即
L = [ 1 0 0 . . . 0 0 l 21 1 0 . . . 0 0 l 31 l 32 1 . . . 0 0 . . . . . . . . . . . . . . . . . . l N 1 l N 2 l N 3 . . . l N   N − 1 1 ] \bold L = \begin{bmatrix} 1 & 0 & 0 & ... & 0 & 0 \\ l_{21} & 1 & 0 & ... & 0 & 0 \\ l_{31} & l_{32} & 1 & ... & 0 & 0 \\ ... & ... & ... & ... & ... & ... \\ l_{N1} & l_{N2} & l_{N3} & ... & l_{N~N-1} & 1 \end{bmatrix} L=1l21l31...lN101l32...lN2001...lN3...............000...lN N1000...1
将方程 U ϕ − c = 0 \bold U \boldsymbol \phi - \bold c = \bold 0 Uϕc=0左乘以 L \bold L L,则变回了最初的方程
L ( U ϕ − c ) = L U ϕ − L c = A ϕ − b \bold L(\bold U \boldsymbol \phi - \bold c) = \bold L \bold U \boldsymbol \phi - \bold L \bold c=\bold A \boldsymbol \phi - \bold b L(Uϕc)=LUϕLc=Aϕb
这样,变得到
L U = A \bold L \bold U = \bold A LU=A

L c = b \bold L \bold c = \bold b Lc=b
即,矩阵 A \bold A A写成了下三角和上三角矩阵的乘积形式,即 L U LU LU分解。

2.7 分解步骤

L U = A \bold L \bold U = \bold A LU=A写成展开形式
[ 1 0 0 . . . 0 0 l 21 1 0 . . . 0 0 l 31 l 32 1 . . . 0 0 . . . . . . . . . . . . . . . . . . l N 1 l N 2 l N 3 . . . l N   N − 1 1 ] [ u 11 u 12 u 13 . . . u 1   N − 1 u 1   N 0 u 22 u 23 . . . u 2   N − 1 u 2   N 0 0 u 33 . . . u 3   N − 1 u 3   N . . . . . . . . . . . . . . . . . . 0 0 0 . . . 0 u N   N ] = [ a 11 a 12 a 13 . . . a 1   N − 1 a 1   N a 21 a 22 a 23 . . . a 2   N − 1 a 2   N a 31 a 32 a 33 . . . a 3   N − 1 a 3   N . . . . . . . . . . . . . . . . . . a N 1 a N 2 a N 3 . . . a N   N − 1 a N   N ] \begin{bmatrix} 1 & 0 & 0 & ... & 0 & 0 \\ l_{21} & 1 & 0 & ... & 0 & 0 \\ l_{31} & l_{32} & 1 & ... & 0 & 0 \\ ... & ... & ... & ... & ... & ... \\ l_{N1} & l_{N2} & l_{N3} & ... & l_{N~N-1} & 1 \end{bmatrix} \begin{bmatrix} u_{11} & u_{12} & u_{13} & ... & u_{1~N-1} & u_{1~N} \\ 0 & u_{22} & u_{23} &... & u_{2~N-1} & u_{2~N} \\ 0 & 0 & u_{33} & ... & u_{3~N-1} & u_{3~N} \\ ... & ... & ... & ... & ... & ... \\ 0 & 0 & 0 & ... & 0 & u_{N~N} \end{bmatrix} = \begin{bmatrix} a_{11} & a_{12} & a_{13} & ... & a_{1~N-1} & a_{1~N} \\ a_{21} & a_{22} & a_{23} &... & a_{2~N-1} & a_{2~N} \\ a_{31} & a_{32} & a_{33} &... & a_{3~N-1} & a_{3~N} \\ ... & ... & ... & ... & ... & ... \\ a_{N1} & a_{N2} & a_{N3} & ... & a_{N~N-1} & a_{N~N} \end{bmatrix} 1l21l31...lN101l32...lN2001...lN3...............000...lN N1000...1u1100...0u12u220...0u13u23u33...0...............u1 N1u2 N1u3 N1...0u1 Nu2 Nu3 N...uN N=a11a21a31...aN1a12a22a32...aN2a13a23a33...aN3...............a1 N1a2 N1a3 N1...aN N1a1 Na2 Na3 N...aN N
L \bold L L的第1行和 U \bold U U的每一列(第1到N列)相乘,得到
u 1 j = a 1 j      j = 1 , 2 , 3 , . . . , N u_{1j}=a_{1j}~~~~j=1,2,3,...,N u1j=a1j    j=1,2,3,...,N
接下来,让 L \bold L L的第2到第N行与 U \bold U U的第1列相乘,得到
l i 1 u 11 = a i 1 ⇒ l i 1 = a i 1 u 11      i = 2 , 3 , . . . , N l_{i1}u_{11}=a_{i1}\Rightarrow l_{i1}=\frac{a_{i1}}{u_{11}}~~~~i=2,3,...,N li1u11=ai1li1=u11ai1    i=2,3,...,N
重复该过程,让 L \bold L L的第2行与 U \bold U U的第2到第N列相乘,得到
l 21 u 1 j + u 2 j = a 2 j ⇒ u 2 j = a 2 j − l 21 u 1 j      j = 2 , 3 , . . . , N l_{21}u_{1j}+u_{2j}=a_{2j} \Rightarrow u_{2j}=a_{2j} - l_{21}u_{1j}~~~~j=2,3,...,N l21u1j+u2j=a2ju2j=a2jl21u1j    j=2,3,...,N
然后呢,再把 L \bold L L的第3到N行与 U \bold U U的第2列相乘,得到
l i 1 u 12 + l i 2 u 22 = a i 2 ⇒ l i 2 = a i 2 − l i 1 u 12 u 22      i = 3 , 4 , . . . , N l_{i1}u_{12}+l_{i2}u_{22}=a{i2} \Rightarrow l_{i2}=\frac{a{i2}-l_{i1}u_{12}}{u_{22}}~~~~i=3,4,...,N li1u12+li2u22=ai2li2=u22ai2li1u12    i=3,4,...,N
如此不断重复,直至解出所有 L \bold L L U \bold U U的元素值。

一般来说, L \bold L L的第i行与 U \bold U U的第i到第N列相乘,可得
u i j = a i j − ∑ k = 1 i − 1 l i k u k j      j = i , i + 1 , . . . , N u_{ij}=a_{ij}-\sum_{k=1}^{i-1}l_{ik}u_{kj}~~~~j=i,i+1,...,N uij=aijk=1i1likukj    j=i,i+1,...,N
L \bold L L的第i+1到第N行与 U \bold U U的第i列相乘,则可得
l k i = a k i − ∑ j = 1 i − 1 l k j u j i u i i      k = i + 1 , i + 2 , . . . , N l_{ki}=\frac{a_{ki}-\sum_{j=1}^{i-1}l_{kj}u_{ji}}{u_{ii}}~~~~k=i+1,i+2,...,N lki=uiiakij=1i1lkjuji    k=i+1,i+2,...,N
对于 L \bold L L的第N行,其系数与 U \bold U U的第N列相乘后,得到
u N N = a N N − ∑ k = 1 N − 1 l N k u k N u_{NN}=a_{NN}-\sum_{k=1}^{N-1}l_{Nk}u_{kN} uNN=aNNk=1N1lNkukN
LU分解的算法汇总如下

2.8 LU分解算法

for j = 1 to N
	u_1j = a_1j
for i = 2 to N
	l_i1 = a_i1 / u_11
for i = 2 to N-1
{
	for j = i to N
	{
		sum = 0
		for k = 1 to i-1
			sum += l_ik * u_kj
		u_ij = a_ij - sum
	}
	for k = i+1 to N
	{
		sum = 0
		for j = 1 to i-1
			sum += l_kj * u_ji
		l_ki = (a_ki - sum) / u_ii
	}
}
sum = 0
for i = 1 to N-1
	sum += l_Ni * u_iN
u_NN = a_NN - sum

2.9 回代步

把原矩阵 A \bold A A分解为 L \bold L L U \bold U U之后,方程系统可分两步来求解( U ϕ = c ,   L c = b \bold U \boldsymbol \phi = \bold c,~\bold L \bold c = \bold b Uϕ=c, Lc=b),两步方法等效于求解两个线性系统方程,然而却由于 L \bold L L U \bold U U的上下三角形式而极大简化了求解过程。

第1步是求解 L c = b \bold L \bold c = \bold b Lc=b,通过前向回代,可以直接得出
c 1 = b 1 c i = b i − ∑ j = 1 i − 1 l i j c j , i = 2 , 3 , . . . , N \begin{aligned} & c_1 = b_1 \\ & c_i = b_i - \sum_{j=1}^{i-1}l_{ij}c_j,\quad\quad i=2,3,...,N \end{aligned} c1=b1ci=bij=1i1lijcj,i=2,3,...,N

第2步是求解 U ϕ = c \bold U \boldsymbol \phi = \bold c Uϕ=c,采用反向回代,可以直接得到
ϕ N = C N u N N ϕ i = c i − ∑ j = i + 1 N u i j ϕ j u i i , i = N − 1 , N − 2 , . . . , 3 , 2 , 1 \begin{aligned} & \phi_N = \frac{C_N}{u_{NN}} \\ & \phi_i = \frac{c_i - \displaystyle \sum_{j=i+1}^{N}u_{ij}\phi_j}{u_{ii}},\quad\quad i=N-1,N-2,...,3,2,1 \end{aligned} ϕN=uNNCNϕi=uiicij=i+1Nuijϕj,i=N1,N2,...,3,2,1

实际上, L \bold L L U \bold U U的元素可以直接存放在最初的矩阵 A \bold A A中,如果 A \bold A A不再需要的话(当LU分解完成后, A \bold A A的确是没啥用了,求解的时候只用 L \bold L L U \bold U U就行了)。对于 N × N N\times N N×N维矩阵执行LU分解需要的计算量是 2 N 3 / 3 2N^3/3 2N3/3,是用Gauss消元法求解线性代数方程组的两倍!然而,LU分解的优势就在于,只用做一次分解,就可以把同样的矩阵 A \bold A A应用于不同的右端项 b \bold b b来求解各种问题。然而,这里LU分解引入的另一个目的,是在于用它来引出其它更加高效的迭代解法。

2.10 LU分解和Gauss消元

也许并不明显,但是在Guass消元的过程中,悄然完成了LU分解。前向消元过程生成了上三角矩阵 U \bold U U,在此过程中,下三角矩阵 L \bold L L也悄悄算好了,因为 L \bold L L的元素实际上就是在消元过程中各行乘上的那个因子。下面的算法,将在Gauss消元的基础上,同时完成LU分解。那么用这个算法显然更方便些哈。

2.11 由Gauss消元来做LU分解的算法

如果把 L \bold L L U \bold U U放在原来的矩阵 A \bold A A中,那么直接这么做就好了,相当于在Gauss消元的算法中,把系数存放到了下三角位置上,注意,不需要对 b \bold b b做处理,因为LU分解就是为了求解不同的右端项 b \bold b b

for k = 1 to N-1
{
	for i = k+1 to N
	{
		a_ik = a_ik / a_kk
		for j = k+1 to N
			a_ij = a_ij - a_ik * a_kj
	}
}

如果 L \bold L L U \bold U U另外找地方放,还要保留矩阵 A \bold A A的话,那么直接把矩阵 A \bold A A复制一份出来,还用上面的算法就行了。


例1 用LU分解方法求解如下线性代数方程组
[ 3 − 1 0 0 − 2 6 − 1 0 0 − 2 6 − 1 0 0 − 2 7 ] [ ϕ 1 ϕ 2 ϕ 3 ϕ 4 ] = [ 3 4 5 − 3 ] \begin{bmatrix} 3 & -1 & 0 & 0 \\ -2 & 6 & -1 & 0 \\ 0 & -2 & 6 & -1 \\ 0 & 0 & -2 & 7 \\ \end{bmatrix} \begin{bmatrix} \phi_1 \\ \phi_2 \\ \phi_3 \\ \phi_4 \end{bmatrix} =\begin{bmatrix} 3 \\ 4 \\ 5 \\ -3 \end{bmatrix} 3200162001620017ϕ1ϕ2ϕ3ϕ4=3453


求解过程从略,答案直接给出
L = [ 1 0 0 0 − 2 3 1 0 0 0 − 3 8 1 0 0 0 − 16 45 1 ] , U = [ 3 − 1 0 0 0 16 3 − 1 0 0 0 45 8 − 1 0 0 0 299 45 ] \bold L=\begin{bmatrix} 1 & 0 & 0 & 0 \\ -\displaystyle\frac{2}{3} & 1 & 0 & 0 \\ 0 & -\displaystyle\frac{3}{8} & 1 & 0 \\ 0 & 0 & -\displaystyle\frac{16}{45} & 1 \\ \end{bmatrix}, \quad\quad \bold U =\begin{bmatrix} 3 & -1 & 0 & 0 \\ 0 & \displaystyle\frac{16}{3} & -1 & 0 \\ 0 & 0 & \displaystyle\frac{45}{8} & -1 \\ 0 & 0 & 0 & \displaystyle\frac{299}{45} \\ \end{bmatrix} L=132000183000145160001,U=300013160001845000145299
c = [ 3 6 29 / 4 − 19 / 45 ] , ϕ = [ 435 / 299 408 / 299 382 / 299 − 19 / 299 ] \bold c=\begin{bmatrix} 3 \\ 6 \\ 29/4\\ -19/45 \end{bmatrix},\quad\quad \boldsymbol \phi=\begin{bmatrix} 435/299 \\ 408/299 \\ 382/299 \\ -19/299 \end{bmatrix} c=3629/419/45,ϕ=435/299408/299382/29919/299


2.12 带状稀疏矩阵的直接解法

Gauss消元和LU分解适用于任何方程组系统,当然,它们可以用于求解从结构或非结构网格的守恒方程离散得出的控制方程组。当使用结构网格时,离散过程得到的系统方程的非零元素仅存在于少数几个对角线上,依据不同的离散框架,常出现三对角或五对角矩阵,对于它们的求解可以提出更加高效的方法。实际上相当于把Gauss消元法应用于这类特定的问题中而已。

2.13 三对角矩阵算法(TDMA)

在这里插入图片描述

一维问题导出的方程往往具有三对角形式,即
a i ϕ i + b i ϕ i + 1 + c i ϕ i − 1 = d i , i = 1 , 2 , 3 , . . . , N , c 1 = b N = 0 a_i \phi_i + b_i \phi_{i+1}+c_i \phi_{i-1} = d_i, \quad\quad i=1,2,3,...,N, \quad\quad c_1=b_N=0 aiϕi+biϕi+1+ciϕi1=di,i=1,2,3,...,N,c1=bN=0
对于 i = 1 i=1 i=1,可直接推得 ϕ 1 \phi_1 ϕ1 ϕ 2 \phi_2 ϕ2的关系
i = 1 ⇒ a 1 ϕ 1 = − b 1 ϕ 2 + d 1 ⇒ ϕ 1 = − b 1 a 1 ϕ 2 + d 1 a 2 i=1 \Rightarrow a_1\phi_1=-b_1\phi_2 + d_1 \Rightarrow \phi_1=-\frac{b_1}{a_1}\phi_2+\frac{d_1}{a_2} i=1a1ϕ1=b1ϕ2+d1ϕ1=a1b1ϕ2+a2d1
同样对于 i = 2 i=2 i=2,可导出 ϕ 2 \phi_2 ϕ2 ϕ 3 \phi_3 ϕ3的关系
i = 2 ⇒ a 2 ϕ 2 = − b 2 ϕ 3 − c 2 ϕ 1 + d 2 ⇒ ϕ 2 = − a 1 b 2 a 1 a 2 − c 2 b 1 ϕ 3 + d 2 a 1 − c 2 d 1 a 1 a 2 − c 2 b 1 i=2 \Rightarrow a_2\phi_2 = -b_2\phi_3 - c_2\phi_1 + d_2 \Rightarrow \phi_2=-\frac{a_1b_2}{a_1a_2-c_2b_1}\phi_3 + \frac{d_2a_1-c_2d_1}{a_1a_2-c_2b_1} i=2a2ϕ2=b2ϕ3c2ϕ1+d2ϕ2=a1a2c2b1a1b2ϕ3+a1a2c2b1d2a1c2d1
同样的操作可用于 ϕ 3 \phi_3 ϕ3 ϕ N \phi_N ϕN,假设 ϕ i \phi_i ϕi可用 ϕ i + 1 \phi_{i+1} ϕi+1表示为
ϕ i = P i ϕ i + 1 + Q i , i = 1 , 2 , 3 , . . . , N \phi_i = P_i \phi_{i+1} + Q_i,\quad\quad i=1,2,3,...,N ϕi=Piϕi+1+Qi,i=1,2,3,...,N
假设对 i − 1 i-1 i1上式已知,那么对 i i i的推导如下
ϕ i − 1 = P i − 1 ϕ i + Q i − 1 a i ϕ i + b i ϕ i + 1 + c i ϕ i − 1 = d i } ⇒ ϕ i = − b i a i + c i P i − 1 ϕ i + 1 + d i − c i Q i − 1 a i + c i P i − 1 \left. \begin{matrix} \phi_{i-1}=P_{i-1}\phi_i + Q_{i-1} \\ a_i \phi_i + b_i \phi_{i+1}+c_i \phi_{i-1} = d_i \end{matrix} \right\} \Rightarrow \phi_i=-\frac{b_i}{a_i+c_iP_{i-1}}\phi_{i+1}+\frac{d_i-c_iQ_{i-1}}{a_i+c_iP_{i-1}} ϕi1=Pi1ϕi+Qi1aiϕi+biϕi+1+ciϕi1=di}ϕi=ai+ciPi1biϕi+1+ai+ciPi1diciQi1
从而推得 P i P_i Pi Q i Q_i Qi
P i = − b i a i + c i P i − 1 Q i = d i − c i Q i − 1 a i + c i P i − 1 i = 2 , 3 , 4 , . . . , N P_i=-\frac{b_i}{a_i+c_iP_{i-1}} \quad\quad Q_i=\frac{d_i-c_iQ_{i-1}}{a_i+c_iP_{i-1}} \quad\quad i=2,3,4,...,N Pi=ai+ciPi1biQi=ai+ciPi1diciQi1i=2,3,4,...,N
对于 i = 1 i=1 i=1,可直接算得 P 1 P_1 P1 Q 1 Q_1 Q1
P 1 = − b 1 a 1 Q 1 = d 1 a 2 P_1=-\frac{b_1}{a_1}\quad\quad Q_1=\frac{d_1}{a_2} P1=a1b1Q1=a2d1
而对于 i = N i=N i=N,由于 b N = 0 b_N=0 bN=0,有
b N = 0 ⇒ P N = 0 ⇒ ϕ N = Q N b_N=0\Rightarrow P_N=0 \Rightarrow \phi_N=Q_N bN=0PN=0ϕN=QN
TDMA算法总结如下

  1. 计算 P 1 P_1 P1 Q 1 Q_1 Q1,用
    P 1 = − b 1 a 1 Q 1 = d 1 a 2 P_1=-\frac{b_1}{a_1}\quad\quad Q_1=\frac{d_1}{a_2} P1=a1b1Q1=a2d1
  2. 计算 P i P_i Pi Q i Q_i Qi i = 2 , 3 , . . . , N i=2,3,...,N i=2,3,...,N,用
    P i = − b i a i + c i P i − 1 Q i = d i − c i Q i − 1 a i + c i P i − 1 P_i=-\frac{b_i}{a_i+c_iP_{i-1}} \quad\quad Q_i=\frac{d_i-c_iQ_{i-1}}{a_i+c_iP_{i-1}} Pi=ai+ciPi1biQi=ai+ciPi1diciQi1
  3. 求出 ϕ N \phi_N ϕN,用
    ϕ N = Q N \phi_N=Q_N ϕN=QN
  4. 反向依次求出 ϕ i \phi_i ϕi i = N − 1 , N − 2 , . . . , 3 , 2 , 1 i=N-1,N-2,...,3,2,1 i=N1,N2,...,3,2,1,用
    ϕ i = P i ϕ i + 1 + Q i , i = N − 1 , N − 2 , . . . , 3 , 2 , 1 \phi_i = P_i \phi_{i+1} + Q_i,\quad\quad i=N-1,N-2,...,3,2,1 ϕi=Piϕi+1+Qi,i=N1,N2,...,3,2,1

2.14 五对角矩阵算法(PDMA)

还是1维问题,只不过离散格式用的精度更高,让i节点与i+1,i+2,i-1,i-2都有关系,这样子出来的离散矩阵便是5对角形式了,即
a i ϕ i + b i ϕ i + 2 + c i ϕ i + 1 + d i ϕ i − 1 + e i ϕ i − 2 = f i i = 1 , 2 , 3 , . . . , N a_i\phi_i+b_i\phi_{i+2}+c_i\phi_{i+1}+d_i\phi_{i-1}+e_i\phi_{i-2}=f_i\quad\quad i=1,2,3,...,N aiϕi+biϕi+2+ciϕi+1+diϕi1+eiϕi2=fii=1,2,3,...,N
对于边界的几个节点,有
d 1 = e 1 = e 2 = 0 b N − 1 = b N = c N = 0 d_1=e_1=e_2=0 \\ b_{N-1}=b_{N}=c_{N}=0 d1=e1=e2=0bN1=bN=cN=0
对于 i = 1 i=1 i=1,有
ϕ 1 = − b 1 a 1 ϕ 3 − c 1 a 1 ϕ 2 + f 1 a 1 \phi_1=-\frac{b_1}{a_1}\phi_3-\frac{c_1}{a_1}\phi_2+\frac{f_1}{a_1} ϕ1=a1b1ϕ3a1c1ϕ2+a1f1
对于 i = 2 i=2 i=2,有
ϕ 2 = − a 1 b 2 a 1 a 2 − d 2 c 1 ϕ 4 − a 1 c 2 − b 1 d 2 a 1 a 2 − d 2 c 1 ϕ 3 + a 1 f 2 − d 2 f 1 a 1 a 2 − d 2 c 1 \phi_2=-\frac{a_1b_2}{a_1a_2-d_2c_1}\phi_4-\frac{a_1c_2-b_1d_2}{a_1a_2-d_2c_1}\phi_3+\frac{a_1f_2-d_2f_1}{a_1a_2-d_2c_1} ϕ2=a1a2d2c1a1b2ϕ4a1a2d2c1a1c2b1d2ϕ3+a1a2d2c1a1f2d2f1
该过程可重复下去,获取第 i i i个变量 ϕ i \phi_i ϕi的通有形式
ϕ i = P i ϕ i + 2 + Q i ϕ i + 1 + R i i = 1 , 2 , 3 , . . . , N \phi_i=P_i\phi_{i+2}+Q_i\phi_{i+1}+R_i\quad\quad i=1,2,3,...,N ϕi=Piϕi+2+Qiϕi+1+Rii=1,2,3,...,N
ϕ i − 1 \phi_{i-1} ϕi1 ϕ i − 2 \phi_{i-2} ϕi2已知的情况下,可求得 ϕ i \phi_i ϕi的形式为
ϕ i = − b i a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 ϕ i + 2 − c i + ( d i + e i Q i − 2 ) P i − 1 a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 ϕ i + 1 − f i − e i R i − 2 − ( d i + e i Q i − 2 ) R i − 1 a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 \begin{aligned} \phi_i=&-\frac{b_i}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}}\phi_{i+2} \\ &-\frac{c_i+(d_i+e_iQ_{i-2})P_{i-1}}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}}\phi_{i+1} \\ &-\frac{f_i-e_iR_{i-2}-(d_i+e_iQ_{i-2})R_{i-1}}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}} \end{aligned} ϕi=ai+eiPi2+(di+eiQi2)Qi1biϕi+2ai+eiPi2+(di+eiQi2)Qi1ci+(di+eiQi2)Pi1ϕi+1ai+eiPi2+(di+eiQi2)Qi1fieiRi2(di+eiQi2)Ri1
比较可得
P i = − b i a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 Q i = − c i + ( d i + e i Q i − 2 ) P i − 1 a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 R i = − f i − e i R i − 2 − ( d i + e i Q i − 2 ) R i − 1 a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 P_i=-\frac{b_i}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}} \\ Q_i= -\frac{c_i+(d_i+e_iQ_{i-2})P_{i-1}}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}} \\ R_i= -\frac{f_i-e_iR_{i-2}-(d_i+e_iQ_{i-2})R_{i-1}}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}} Pi=ai+eiPi2+(di+eiQi2)Qi1biQi=ai+eiPi2+(di+eiQi2)Qi1ci+(di+eiQi2)Pi1Ri=ai+eiPi2+(di+eiQi2)Qi1fieiRi2(di+eiQi2)Ri1
前两个节点,即 i = 1 , 2 i=1,2 i=1,2的值为
P 1 = − b 1 a 1 , Q 1 = − c 1 a 1 , R 1 = f 1 a 1 P 2 = − b 2 a 2 + d 2 Q 1 , Q 2 = − c 2 + d 2 P 1 a 2 + d 2 Q 1 , R 2 = f 2 − d 2 R 1 a 2 + d 2 Q 1 \begin{aligned} & P_1 = -\frac{b_1}{a_1},\quad Q_1=-\frac{c_1}{a_1},\quad R_1=\frac{f_1}{a_1} \\ & P_2 = -\frac{b_2}{a_2+d_2Q_1}, \quad Q_2 = -\frac{c_2+d_2P_1}{a_2+d_2Q_1}, \quad R_2 = \frac{f_2-d_2R_1}{a_2+d_2Q_1} \end{aligned} P1=a1b1,Q1=a1c1,R1=a1f1P2=a2+d2Q1b2,Q2=a2+d2Q1c2+d2P1,R2=a2+d2Q1f2d2R1
由于 b N − 1 = b N = c N = 0 b_{N-1}=b_{N}=c_{N}=0 bN1=bN=cN=0,所以 P N − 1 = P N = Q N = 0 P_{N-1}=P_N=Q_N=0 PN1=PN=QN=0,那么 ϕ N \phi_N ϕN ϕ N − 1 \phi_{N-1} ϕN1的方程为
ϕ N = R N ϕ N − 1 = Q N − 1 ϕ N + R N − 1 \begin{aligned} & \phi_N=R_N \\ & \phi_{N-1}=Q_{N-1}\phi_N+R_{N-1} \end{aligned} ϕN=RNϕN1=QN1ϕN+RN1
将PDMA算法的流程汇总如下

  1. 计算 P 1 ,   Q 1 ,   R 1 ,   P 2 ,   Q 2 ,   R 2 P_1,~Q_1,~R_1,~P_2,~Q_2,~R_2 P1, Q1, R1, P2, Q2, R2,使用
    P 1 = − b 1 a 1 , Q 1 = − c 1 a 1 , R 1 = f 1 a 1 P 2 = − b 2 a 2 + d 2 Q 1 , Q 2 = − c 2 + d 2 P 1 a 2 + d 2 Q 1 , R 2 = f 2 − d 2 R 1 a 2 + d 2 Q 1 \begin{aligned} & P_1 = -\frac{b_1}{a_1},\quad Q_1=-\frac{c_1}{a_1},\quad R_1=\frac{f_1}{a_1} \\ & P_2 = -\frac{b_2}{a_2+d_2Q_1}, \quad Q_2 = -\frac{c_2+d_2P_1}{a_2+d_2Q_1}, \quad R_2 = \frac{f_2-d_2R_1}{a_2+d_2Q_1} \end{aligned} P1=a1b1,Q1=a1c1,R1=a1f1P2=a2+d2Q1b2,Q2=a2+d2Q1c2+d2P1,R2=a2+d2Q1f2d2R1
  2. 对于 i = 3 , 4 , 5 , . . . , N i=3,4,5,...,N i=3,4,5,...,N计算 P i ,   Q i ,   R i P_i, ~Q_i,~ R_i Pi, Qi, Ri,用
    P i = − b i a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 Q i = − c i + ( d i + e i Q i − 2 ) P i − 1 a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 R i = − f i − e i R i − 2 − ( d i + e i Q i − 2 ) R i − 1 a i + e i P i − 2 + ( d i + e i Q i − 2 ) Q i − 1 P_i=-\frac{b_i}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}} \\ Q_i= -\frac{c_i+(d_i+e_iQ_{i-2})P_{i-1}}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}} \\ R_i= -\frac{f_i-e_iR_{i-2}-(d_i+e_iQ_{i-2})R_{i-1}}{a_i+e_iP_{i-2}+(d_i+e_iQ_{i-2})Q_{i-1}} Pi=ai+eiPi2+(di+eiQi2)Qi1biQi=ai+eiPi2+(di+eiQi2)Qi1ci+(di+eiQi2)Pi1Ri=ai+eiPi2+(di+eiQi2)Qi1fieiRi2(di+eiQi2)Ri1
  3. 计算 ϕ N \phi_N ϕN ϕ N − 1 \phi_{N-1} ϕN1,用
    ϕ N = R N ϕ N − 1 = Q N − 1 ϕ N + R N − 1 \begin{aligned} & \phi_N=R_N \\ & \phi_{N-1}=Q_{N-1}\phi_N+R_{N-1} \end{aligned} ϕN=RNϕN1=QN1ϕN+RN1
  4. 对于 i = N − 2 , N − 3 , . . . , 3 , 2 , 1 i=N-2,N-3,...,3,2,1 i=N2,N3,...,3,2,1,计算 ϕ i \phi_i ϕi,用
    ϕ i = P i ϕ i + 2 + Q i ϕ i + 1 + R i \phi_i=P_i\phi_{i+2}+Q_i\phi_{i+1}+R_i ϕi=Piϕi+2+Qiϕi+1+Ri

3 迭代方法

直接解法通常并不适用于求系数疏矩阵为稀疏情况下大型的方程组,即,大多数矩阵元素是0的情况。这种情况经常会出现,比如线性化的系统方程反映的是非线性的问题(系数是依赖于解的),或是处理与时间相关的系统时。这些也正是求解流动问题时经常碰到的方程类型。

相对而言,迭代方法对于这些问题更具吸引性,因为线性化系统的解变成了迭代求解过程的一部分。而且迭代方法占用内存小、计算消耗低,这都是它比直接解法有优势的地方。

迭代方法有许多系列,对它们的详细回顾可参考相关文献书籍。本章主要介绍下基本的迭代方法,并介绍多重网格算法,其可有效克服迭代方法中的缺陷。Gauss消元和LU分解直接方法的讲解只是为了阐明数值过程中的一些基本概念,以便更加深入地理解迭代方法。

为了统一这些方法的表达形式,系数矩阵将统一写成如下形式
A = D + L + U \bold A = \bold D + \bold L + \bold U A=D+L+U
其中 D \bold D D L \bold L L U \bold U U分别是对角、严格下三角、严格上三角矩阵。即,相当于把原来系数矩阵 A \bold A A的元素剥离成对角矩阵、下三角矩阵和上三角矩阵(注意,这里的 L \bold L L U \bold U U并非是前面的LU分解出来的矩阵,而只是把原始矩阵 A \bold A A的对角线元素、下三角元素、上三角元素拿出来构成的矩阵而已)。

迭代方法在求解线性系统 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b时,计算一系列的解 ϕ ( n ) \boldsymbol \phi^{(n)} ϕ(n),这些解当满足特定的条件时,收敛到精确解 ϕ \boldsymbol \phi ϕ。这样,对于特定解法而言,需要选择一个初值 ϕ ( 0 ) \boldsymbol \phi^{(0)} ϕ(0)(选择为初始条件或初始猜测值),还需要构造一个从 ϕ ( n − 1 ) \boldsymbol \phi^{(n-1)} ϕ(n1)计算到 ϕ ( n ) \boldsymbol \phi^{(n)} ϕ(n)的迭代过程。

定点迭代可通过将矩阵 A \bold A A分解为
A = M − N \bold A = \bold M - \bold N A=MN
这样,原方程 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b转化为
( M − N ) ϕ = b (\bold M - \bold N)\boldsymbol \phi = \bold b (MN)ϕ=b
使用定点迭代过程,上式变为
M ϕ ( n ) = N ϕ ( n − 1 ) + b \bold M \boldsymbol \phi^{(n)} = \bold N \boldsymbol \phi^{(n-1)} + \bold b Mϕ(n)=Nϕ(n1)+b
可改写成如下形式
ϕ ( n ) = B ϕ ( n − 1 ) + C b n = 1 , 2 , . . . \boldsymbol \phi^{(n)} = \bold B \boldsymbol \phi^{(n-1)} + \bold C\bold b \quad\quad n=1,2,... ϕ(n)=Bϕ(n1)+Cbn=1,2,...
其中 B = M − 1 N \bold B=\bold M^{-1} \bold N B=M1N,而 C = M − 1 \bold C=\bold M^{-1} C=M1。这些矩阵的选择不同将产生不同的迭代方法。

在详细描述各种迭代方法之前,先讲下迭代方法需要满足什么样的一些特性,才能让其得到收敛的解。

A. 在收敛的时候,有 ϕ ( n ) = ϕ ( n − 1 ) = ϕ \boldsymbol \phi^{(n)} =\boldsymbol \phi^{(n-1)}=\boldsymbol \phi ϕ(n)=ϕ(n1)=ϕ,则迭代方程可以写成
ϕ = B ϕ + C b \boldsymbol \phi = \bold B \boldsymbol \phi + \bold C\bold b ϕ=Bϕ+Cb

C − 1 ( I − B ) ϕ = b \bold C^{-1}(\bold I - \bold B) \boldsymbol \phi = \bold b C1(IB)ϕ=b
与原方程 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b相比较,可得
A = C − 1 ( I − B ) \bold A=\bold C^{-1}(\bold I - \bold B) A=C1(IB)

B + C A = I \bold B + \bold C \bold A = \bold I B+CA=I
不同矩阵间的关系保证了当达到精确解的时候,再继续迭代不会更改所得值。

B. 从 ϕ 0 ≠ ϕ \boldsymbol \phi^{0} \neq \boldsymbol \phi ϕ0=ϕ开始,该方法应保证 ϕ n \boldsymbol \phi^{n} ϕn随着迭代次数 n n n的增加最终收敛到 ϕ \boldsymbol \phi ϕ。因为 ϕ n \boldsymbol \phi^{n} ϕn可以展开成 ϕ 0 \boldsymbol \phi^{0} ϕ0的如下形式
ϕ n = B n ϕ 0 + ∑ i = 0 n − 1 B i C b \boldsymbol \phi^{n} = \bold B^n \boldsymbol \phi^{0} + \sum_{i=0}^{n-1}\bold B^i \bold C \bold b ϕn=Bnϕ0+i=0n1BiCb
那么,若要收敛成立,则需要让 B \bold B B满足(即让 ϕ 0 \boldsymbol \phi^{0} ϕ0的影响完全消失掉)
lim ⁡ n → ∞ B n = lim ⁡ n → ∞ B ∗ B ∗ B ∗ . . . ∗ B ⏟ n   t i m e s = 0 \lim_{n\rightarrow\infin}\bold B^n=\lim_{n\rightarrow\infin} \underbrace{\bold B *\bold B *\bold B*... *\bold B}_{n~times}=\bold 0 nlimBn=nlimn times BBB...B=0
这意味着 B \bold B B的谱半径要小于1,即
ρ ( B ) < 1 \rho(\bold B) < 1 ρ(B)<1
该条件保证了迭代方法是有自我纠正能力的,即,其对于精确解的任何不利的错误扰动是robust(健壮的,鲁棒的)的。

关于该条件的深层理解,可以通过定义精确值与迭代值之间的错误矢量 e ( n ) \bold e^{(n)} e(n),即
e ( n ) = ϕ ( n ) − ϕ e ( n − 1 ) = ϕ ( n − 1 ) − ϕ \bold e^{(n)}=\boldsymbol \phi^{(n)}-\boldsymbol \phi \\ \bold e^{(n-1)}=\boldsymbol \phi^{(n-1)}-\boldsymbol \phi e(n)=ϕ(n)ϕe(n1)=ϕ(n1)ϕ
ϕ = B ϕ + C b \boldsymbol \phi = \bold B \boldsymbol \phi + \bold C\bold b ϕ=Bϕ+Cb ϕ ( n ) = B ϕ ( n − 1 ) + C b \boldsymbol \phi^{(n)} = \bold B \boldsymbol \phi^{(n-1)} + \bold C\bold b ϕ(n)=Bϕ(n1)+Cb两式子互减,可得
e ( n ) = B e ( n − 1 ) \bold e^{(n)} = \bold B \bold e^{(n-1)} e(n)=Be(n1)
因此,若方法是收敛的,则应满足如下式子
lim ⁡ n → ∞ e ( n ) = 0 \lim_{n\rightarrow\infin}\bold e^{(n)}=0 nlime(n)=0
为使上式更有意义,假设 B \bold B B的特征向量是完全的,且形成一个完备集,即它们是 R N \bold R^N RN的基本集。那么 e \bold e e可以用 B \bold B B N N N个特征向量 v \bold v v的线性组合表示,即
e = ∑ i = 1 N α i v i \bold e=\sum_{i=1}^{N}\alpha_i \bold v_i e=i=1Nαivi
每个特征向量满足
B v i = λ i v i \bold B \bold v_i = \lambda_i \bold v_i Bvi=λivi
其中 λ i \lambda_i λi是与特征向量 v i \bold v_i vi相关的特征值,根据 e ( n ) = B e ( n − 1 ) \bold e^{(n)} = \bold B \bold e^{(n-1)} e(n)=Be(n1),从第1个迭代步开始,有
e ( 1 ) = B e ( 0 ) = B ∑ i = 1 N α i v i = ∑ i = 1 N α i ( B v i ) = ∑ i = 1 N α i ( λ i v i ) \bold e^{(1)} = \bold B \bold e^{(0)} = \bold B \sum_{i=1}^{N}\alpha_i \bold v_i = \sum_{i=1}^{N}\alpha_i (\bold B\bold v_i) = \sum_{i=1}^{N}\alpha_i (\lambda_i \bold v_i) e(1)=Be(0)=Bi=1Nαivi=i=1Nαi(Bvi)=i=1Nαi(λivi)
对于第2次迭代,误差变为
e ( 2 ) = B e ( 1 ) = B ∑ i = 1 N α i ( λ i v i ) = ∑ i = 1 N α i λ i ( B v i ) = ∑ i = 1 N α i λ i 2 v i \bold e^{(2)} = \bold B \bold e^{(1)} = \bold B \sum_{i=1}^{N}\alpha_i (\lambda_i \bold v_i) = \sum_{i=1}^{N}\alpha_i \lambda_i (\bold B \bold v_i) = \sum_{i=1}^{N}\alpha_i \lambda_i^2 \bold v_i e(2)=Be(1)=Bi=1Nαi(λivi)=i=1Nαiλi(Bvi)=i=1Nαiλi2vi
该过程可重复执行,有
e ( n ) = ∑ i = 1 N α i λ i n v i \bold e^{(n)} = \sum_{i=1}^{N}\alpha_i \lambda_i^n \bold v_i e(n)=i=1Nαiλinvi
因此,如果随着 n n n趋近无穷大迭代过程要趋于收敛的话,那么所有的特征值必须小于1。如果特征值之中有任何大于1的,那么误差将趋于无穷大。这就很好地解释了为啥谱半径要小于1,因为谱半径实际上是最大特征值,即
ρ ( B ) = max ⁡ i = 1 N ( λ i ) < 1 \rho(\bold B) = \max_{i=1}^{N}(\lambda_i) < 1 ρ(B)=i=1maxN(λi)<1
通过减小迭代矩阵的谱半径,也可以提高迭代方法的收敛速度,这也是迭代技术的核心。

C. 迭代方法中需要给出停止判据,应用较多的准则是给予残差的幅值变化,残差如下
r ( n ) = A ϕ ( n ) − b \bold r^{(n)} = \bold A \boldsymbol \phi^{(n)} - \bold b r(n)=Aϕ(n)b
一个准则是找寻区域中的最大残差,让其值小于某个阈值 ϵ \epsilon ϵ定义为收敛条件,即
max ⁡ i = 1 N ∣ b i − ∑ j = 1 N a i j ϕ j ( n ) ∣ ≤ ϵ \max_{i=1}^N \left| b_i - \sum_{j=1}^N a_{ij} \phi_j^{(n)} \right| \le \epsilon i=1maxNbij=1Naijϕj(n)ϵ
或者root mean square残差(RMS均方根残差)小于 ϵ \epsilon ϵ,即
∑ i = 1 N ( b i − ∑ j = 1 N a i j ϕ j ( n ) ) 2 N ≤ ϵ \frac{\displaystyle \sum_{i=1}^{N}\left( b_i - \sum_{j=1}^N a_{ij}\phi_j^{(n)} \right)^2}{N} \le \epsilon Ni=1N(bij=1Naijϕj(n))2ϵ
还有一种准则是让两个连续迭代过程中的最大单位化差值小于 ϵ \epsilon ϵ,即
max ⁡ i = 1 N ∣ ϕ i ( n ) − ϕ i ( n − 1 ) ϕ i ( n ) ∣ × 100 ≤ ϵ \max_{i=1}^{N}\left| \frac{\phi_i^{(n)}-\phi_i^{(n-1)}}{\phi_i^{(n)}} \right| \times 100 \le \epsilon i=1maxNϕi(n)ϕi(n)ϕi(n1)×100ϵ
顺道说一句,我本人(梅冠华)最喜欢和最常用的判据,是计算两次迭代的差值向量的2范数(幅值),再用本次迭代结果向量的2范数(幅值)去单位化处理,然后让该值小于某个 ϵ ≈ 1 0 − 6 \epsilon \approx 10^{-6} ϵ106,个人感觉,这种方法兼顾了向量的各个分量,又抛掉了正负号的影响,还做了单位化处理,是比较合理的,即
∑ i = 1 N ( ϕ i ( n ) − ϕ i ( n − 1 ) ) 2 ∑ i = 1 N ( ϕ i ( n ) ) 2 + e p s ≤ ϵ \frac{\sqrt{\sum_{i=1}^{N}\left(\phi_i^{(n)}-\phi_i^{(n-1)}\right)^2}}{ \sqrt{\sum_{i=1}^{N}\left(\phi_i^{(n)}\right)^2} + eps } \le \epsilon i=1N(ϕi(n))2 +epsi=1N(ϕi(n)ϕi(n1))2 ϵ
其中的 e p s eps eps是一个非常小的数,比如 1 e − 12 1e-12 1e12,主要是为了防止分母是0,出现被0除的情况,比如你的初始速度场全是0值的情况。

3.1 Jacobi方法

这恐怕是求解线性方程组系统中最简单的迭代方法了,Jacobi方法的图示如下
在这里插入图片描述
对于原方程 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b,其迭代步骤为
ϕ i ( n ) = 1 a i i ( b i − ∑ j = 1 ,   j ≠ i N a i j ϕ j ( n − 1 ) ) i = 1 , 2 , 3 , . . . , N \phi_i^{(n)}=\frac{1}{a_{ii}}\left( b_i - \sum_{j=1,~j\ne i}^{N} a_{ij} \phi_j^{(n-1)} \right)\quad\quad i=1,2,3,...,N ϕi(n)=aii1bij=1, j=iNaijϕj(n1)i=1,2,3,...,N
即,迭代中获得的新值并不用于本次迭代后续值的计算,而是在下次迭代时再去使用。使用矩阵,将上式的展开形式写出来,即
[ a 11 0 . . . 0 0 0 a 22 . . . 0 0 . . . . . . . . . . . . . . . 0 0 . . . a N − 1 ,   N − 1 0 0 0 . . . 0 a N N ] [ ϕ 1 ϕ 2 . . . ϕ N − 1 ϕ N ] + [ 0 a 12 . . . a 1 ,   N − 1 a 1 , N a 21 0 . . . a 2 ,   N − 1 a 2 , N . . . . . . . . . . . . . . . a N − 1 ,   1 a N − 1 ,   2 . . . 0 a N − 1 ,   N a N , 1 a N , 2 . . . a N ,   N − 1 0 ] [ ϕ 1 ϕ 2 . . . ϕ N − 1 ϕ N ] = [ b 1 b 2 . . . b N − 1 b N ] \begin{bmatrix} a_{11} & 0 & ... & 0 & 0 \\ 0 & a_{22} & ... & 0 & 0 \\ ... & ... & ... & ... & ... \\ 0 & 0 & ... & a_{N-1, ~N-1} & 0 \\ 0 & 0 & ... & 0 & a_{NN} \end{bmatrix} \begin{bmatrix} \phi_1 \\ \phi_2 \\ ... \\ \phi_{N-1} \\ \phi_N \end{bmatrix} + \begin{bmatrix} 0 & a_{12} & ... & a_{1,~N-1} & a_{1, N} \\ a_{21} & 0 & ... & a_{2,~N-1} & a_{2, N} \\ ... & ... & ... & ... & ... \\ a_{N-1,~1} & a_{N-1,~2} & ... & 0 & a_{N-1,~N} \\ a_{N,1} & a_{N,2} & ... & a_{N,~N-1} & 0 \end{bmatrix} \begin{bmatrix} \phi_1 \\ \phi_2 \\ ... \\ \phi_{N-1} \\ \phi_N \end{bmatrix} = \begin{bmatrix} b_1 \\ b_2 \\ ... \\ b_{N-1} \\ b_N \end{bmatrix} a110...000a22...00...............00...aN1, N1000...0aNNϕ1ϕ2...ϕN1ϕN+0a21...aN1, 1aN,1a120...aN1, 2aN,2...............a1, N1a2, N1...0aN, N1a1,Na2,N...aN1, N0ϕ1ϕ2...ϕN1ϕN=b1b2...bN1bN
求解 ϕ ( n ) \boldsymbol \phi^{(n)} ϕ(n),上式转化为
[ ϕ 1 ( n ) ϕ 2 ( n ) . . . ϕ N − 1 ( n ) ϕ N ( n ) ] = [ a 11 0 . . . 0 0 0 a 22 . . . 0 0 . . . . . . . . . . . . . . . 0 0 . . . a N − 1 ,   N − 1 0 0 0 . . . 0 a N N ] − 1 ( [ b 1 b 2 . . . b N − 1 b N ] − [ 0 a 12 . . . a 1 ,   N − 1 a 1 , N a 21 0 . . . a 2 ,   N − 1 a 2 , N . . . . . . . . . . . . . . . a N − 1 ,   1 a N − 1 ,   2 . . . 0 a N − 1 ,   N a N , 1 a N , 2 . . . a N ,   N − 1 0 ] [ ϕ 1 ( n − 1 ) ϕ 2 ( n − 1 ) . . . ϕ N − 1 ( n − 1 ) ϕ N ( n − 1 ) ] ) \begin{bmatrix} \phi_1^{(n)} \\ \phi_2^{(n)} \\ ... \\ \phi_{N-1}^{(n)} \\ \phi_N^{(n)} \end{bmatrix}=\begin{bmatrix} a_{11} & 0 & ... & 0 & 0 \\ 0 & a_{22} & ... & 0 & 0 \\ ... & ... & ... & ... & ... \\ 0 & 0 & ... & a_{N-1, ~N-1} & 0 \\ 0 & 0 & ... & 0 & a_{NN} \end{bmatrix}^{-1} \left( \begin{bmatrix} b_1 \\ b_2 \\ ... \\ b_{N-1} \\ b_N \end{bmatrix} - \begin{bmatrix} 0 & a_{12} & ... & a_{1,~N-1} & a_{1, N} \\ a_{21} & 0 & ... & a_{2,~N-1} & a_{2, N} \\ ... & ... & ... & ... & ... \\ a_{N-1,~1} & a_{N-1,~2} & ... & 0 & a_{N-1,~N} \\ a_{N,1} & a_{N,2} & ... & a_{N,~N-1} & 0 \end{bmatrix} \begin{bmatrix} \phi_1^{(n-1)} \\ \phi_2^{(n-1)} \\ ... \\ \phi_{N-1}^{(n-1)} \\ \phi_N^{(n-1)} \end{bmatrix} \right) ϕ1(n)ϕ2(n)...ϕN1(n)ϕN(n)=a110...000a22...00...............00...aN1, N1000...0aNN1b1b2...bN1bN0a21...aN1, 1aN,1a120...aN1, 2aN,2...............a1, N1a2, N1...0aN, N1a1,Na2,N...aN1, N0ϕ1(n1)ϕ2(n1)...ϕN1(n1)ϕN(n1)
使用 A = D + L + U \bold A = \bold D + \bold L + \bold U A=D+L+U,可将上式转化为
ϕ ( n ) = − D − 1 ( L + U ) ϕ ( n − 1 ) + D − 1 b \boldsymbol \phi^{(n)}=-\bold D^{-1}(\bold L + \bold U)\boldsymbol \phi^{(n-1)} + \bold D^{-1}\bold b ϕ(n)=D1(L+U)ϕ(n1)+D1b
那么只要 ρ ( − D − 1 ( L + U ) ) < 1 \rho(-\bold D^{-1}(\bold L + \bold U))<1 ρ(D1(L+U))<1则Jacobi方法是收敛的。该条件对于很多类型的矩阵都是满足的,其中一种就是对角占优矩阵,即它们的系数满足
∑ j = 1 ,   j ≠ i N ∣ a i j ∣ ≤ ∣ a i i ∣ i = 1 , 2 , 3 , . . . , N \sum_{j=1,~j\ne i}^{N} |a_{ij}| \le |a_{ii}| \quad\quad i=1,2,3,...,N j=1, j=iNaijaiii=1,2,3,...,N

3.2 Gauss-Seidel方法

从Jacobi方法改进而来的更好的方法是Gauss-Seidel方法,其收敛特性更好,而且占用内存较少,因为其不需要再单独存储计算出来的新值了,因为它用的都是最新算出来的值。Gauss-Seidel方法的示意图为
在这里插入图片描述
Guass-Seidel方法的迭代关系式为
ϕ i ( n ) = 1 a i i ( b i − ∑ j = 1 i − 1 a i j ϕ j ( n ) − ∑ j = i + 1 N a i j ϕ j ( n − 1 ) ) i = 1 , 2 , 3 , . . . , N \phi_i^{(n)}=\frac{1}{a_{ii}}\left( b_i - \sum_{j=1}^{i-1} a_{ij} \phi_j^{(n)} - \sum_{j=i+1}^{N} a_{ij} \phi_j^{(n-1)} \right)\quad\quad i=1,2,3,...,N ϕi(n)=aii1(bij=1i1aijϕj(n)j=i+1Naijϕj(n1))i=1,2,3,...,N
如果要写成矩阵形式,即
ϕ ( n ) = − ( D + L ) − 1 U ϕ ( n − 1 ) + ( D + L ) − 1 b \boldsymbol \phi^{(n)}=-(\bold D + \bold L)^{-1}\bold U\boldsymbol \phi^{(n-1)} + (\bold D + \bold L)^{-1}\bold b ϕ(n)=(D+L)1Uϕ(n1)+(D+L)1b
Gauss-Seidel方法更为高效,因为其计算 ϕ j ( n ) \phi_j^{(n)} ϕj(n)的时候用的是最新算出的 ϕ i ( n ) ,   i = 1 , 2 , 3 , . . . , j − 1 \phi_i^{(n)},~i=1,2,3,...,j-1 ϕi(n), i=1,2,3,...,j1。该方法很节省内存,因为直接用新值覆盖旧值即可。Gauss-Seidel迭代收敛的要求是
ρ ( − ( D + L ) − 1 U ) < 1 \rho(-(\bold D + \bold L)^{-1}\bold U)<1 ρ((D+L)1U)<1
尽管在某些情况下Jacobi方法收敛更快,然而Gauss-Seidel仍然是首选方法。


例2

对于例1给出的系统方程,采用Jacobi和Gauss-Seidel方法,迭代5次,并计算每次迭代解与真实解的误差,迭代初值选为
ϕ ∗ = [ 0   0   0   0 ] T \boldsymbol \phi^*=[0~0~0~0]^T ϕ=[0 0 0 0]T

较为简单,略去不提,感兴趣的可自行计算。


3.3 预处理和迭代方法

迭代方法 ϕ ( n ) = B ϕ ( n − 1 ) + C b n = 1 , 2 , . . . \boldsymbol \phi^{(n)} = \bold B \boldsymbol \phi^{(n-1)} + \bold C\bold b \quad\quad n=1,2,... ϕ(n)=Bϕ(n1)+Cbn=1,2,...的收敛速度依赖于迭代矩阵 B \bold B B的谱半径,这与矩阵的系数相关。尽管迭代方法是把原系统方程转化为有相同解的等效系统,但是拥有更好的谱半径特性。在这些条件下,等效系统的特征值更加聚集,使得其比原系统的迭代收敛速度更快。预处理器就是这样定义的一种矩阵,即
P − 1 A ϕ = P − 1 b \bold P^{-1}\bold A\boldsymbol \phi = \bold P^{-1}\bold b P1Aϕ=P1b
其有着和原方程 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b同样的解,但是 P − 1 A \bold P^{-1}\bold A P1A的谱半径特性更好。定义预处理器 P \bold P P的时候,其难点在于找寻一个与 A − 1 \bold A^{-1} A1近似的矩阵,而且还要很容易做求逆运算(为了计算 P − 1 \bold P^{-1} P1)。

将之前的式子 A = M − N \bold A = \bold M - \bold N A=MN中的 M \bold M M替换成 P \bold P P,则 M = P \bold M = \bold P M=P A = P − N \bold A = \bold P - \bold N A=PN,那么与之相关的迭代系统变为
ϕ ( n ) = B ϕ ( n − 1 ) + C b = P − 1 N ϕ ( n − 1 ) + P − 1 b = P − 1 ( P − A ) ϕ ( n − 1 ) + P − 1 b = ( I − P − 1 A ) ϕ ( n − 1 ) + P − 1 b \begin{aligned} \boldsymbol \phi^{(n)} & = \bold B \boldsymbol \phi^{(n-1)} + \bold C \bold b \\ & = \bold P^{-1} \bold N \phi^{(n-1)} + \bold P^{-1} \bold b \\ & = \bold P^{-1}(\bold P - \bold A) \phi^{(n-1)} + \bold P^{-1} \bold b \\ & = (\bold I - \bold P^{-1} \bold A)\phi^{(n-1)} + \bold P^{-1} \bold b \end{aligned} ϕ(n)=Bϕ(n1)+Cb=P1Nϕ(n1)+P1b=P1(PA)ϕ(n1)+P1b=(IP1A)ϕ(n1)+P1b
写成残差形式,为
ϕ ( n ) = ( I − P − 1 A ) ϕ ( n − 1 ) + P − 1 b = ϕ ( n − 1 ) + P − 1 ( b − A ) ϕ ( n − 1 ) = ϕ ( n − 1 ) + P − 1 r ( n − 1 ) \begin{aligned} \boldsymbol \phi^{(n)} & = (\bold I - \bold P^{-1} \bold A)\phi^{(n-1)} + \bold P^{-1} \bold b \\ & = \phi^{(n-1)} + \bold P^{-1} ( \bold b - \bold A)\phi^{(n-1)} \\ & = \phi^{(n-1)} + \bold P^{-1} \bold r^{(n-1)} \end{aligned} ϕ(n)=(IP1A)ϕ(n1)+P1b=ϕ(n1)+P1(bA)ϕ(n1)=ϕ(n1)+P1r(n1)
从这两个方程中我们可以看出,迭代方法只不过是做了分解 A = P − N \bold A = \bold P - \bold N A=PN的预处理系统的定点迭代方法,其中的谱半径特性为
ρ ( I − P − 1 A ) < 1 \rho(\bold I - \bold P^{-1} \bold A) < 1 ρ(IP1A)<1
作为比较,对于Jacobi和Gauss-Seidel的预处理矩阵J和JS分别为
P J = D P G S = D + L \bold P_J = \bold D \\ \bold P_{GS}=\bold D + \bold L PJ=DPGS=D+L
其中 D \bold D D L \bold L L分别是矩阵 A \bold A A的对角和下三角部分。

这样,预处理是对原系统的一种提高谱半径特性的处理方式,其运用预处理矩阵 P \bold P P来提高迭代效率。下面我们将会看到,可以提出更加优越的预处理矩阵,其系数的定义更加复杂。

3.4 矩阵分解技术

Gauss-Seidel和Jacobi方法的低收敛速度,激发人们寻求更加快速的迭代方法。一种加速迭代收敛速度的方法是通过使用更好的预处理器来开发迭代方法,一个简单和行之有效的方法是对原矩阵 A \bold A A执行不完全分解,之所以是不完全分解,因为完全分解的话,把矩阵 A \bold A A分解成下三角矩阵 L \bold L L和上三角矩阵 U \bold U U的工作量跟直接求解方程是相当的,而且计算耗费很大,内存消耗很大(丧失了稀疏特性)。

3.5 不完全LU分解(ILU)

如同在例1中看到的那样, L \bold L L U \bold U U矩阵会出现原矩阵 A \bold A A 0 0 0元素地方的非 0 0 0元素(这是所谓的fill-in填补)。所以呢,如果是要做不完全LU(ILU)分解的话,那么得到的下三角 L \bold L L和上三角 U \bold U U矩阵应该和原矩阵 A \bold A A中下三角和上三角的非零元素排布完全一致才好,即
A = L U + R \bold A = \bold L \bold U +\bold R A=LU+R
其中 R \bold R R是分解过程产生的残差,矩阵 L \bold L L U \bold U U是稀疏矩阵(与矩阵 A \bold A A的排布一样),这样处理起来非常方便,相比而言,如果是做完全分解的话,处理起来就麻烦多了。然而, L U \bold L \bold U LU只是矩阵 A \bold A A的近似,就需要采用迭代求解过程来求解方程组系统了。求解过程得第1步是把方程组 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b重写成
A ϕ = b ⇒ 0 = b − A ϕ ⇒ ( A − R ) ϕ = ( A − R ) ϕ + ( b − A ϕ ) \bold A \boldsymbol \phi=\bold b \Rightarrow \bold 0 = \bold b - \bold A \boldsymbol \phi \Rightarrow (\bold A -\bold R)\boldsymbol \phi = (\bold A -\bold R)\boldsymbol \phi + (\bold b - \bold A \boldsymbol \phi) Aϕ=b0=bAϕ(AR)ϕ=(AR)ϕ+(bAϕ)
迭代形式可以写成
( A − R ) ϕ ( n ) = ( A − R ) ϕ ( n − 1 ) + ( b − A ϕ ( n − 1 ) ) (\bold A -\bold R)\boldsymbol \phi^{(n)} = (\bold A -\bold R)\boldsymbol \phi ^{(n-1)} + (\bold b - \bold A \boldsymbol \phi ^{(n-1)}) (AR)ϕ(n)=(AR)ϕ(n1)+(bAϕ(n1))
上式常写成修正形式,即定义
ϕ ( n ) = ϕ ( n − 1 ) + ϕ ′ ( n ) \boldsymbol \phi^{(n)} = \boldsymbol \phi^{(n-1)} + \boldsymbol \phi'^{(n)} ϕ(n)=ϕ(n1)+ϕ(n)
这样迭代过程变为
( A − R ) ϕ ′ ( n ) = ( b − A ϕ ( n − 1 ) ) (\bold A -\bold R) \boldsymbol \phi'^{(n)} = (\bold b - \bold A \boldsymbol \phi ^{(n-1)}) (AR)ϕ(n)=(bAϕ(n1))
即每步迭代中,用上式算得 ϕ ′ ( n ) \boldsymbol \phi'^{(n)} ϕ(n),然后用 ϕ ( n ) = ϕ ( n − 1 ) + ϕ ′ ( n ) \boldsymbol \phi^{(n)} = \boldsymbol \phi^{(n-1)} + \boldsymbol \phi'^{(n)} ϕ(n)=ϕ(n1)+ϕ(n)算得 ϕ ( n ) \boldsymbol \phi^{(n)} ϕ(n)

ILU分解可以通过Gauss消元法,并去掉一些在预设位置的非对角元素来实现,那么舍弃元素所处的位置不同便催生了不同的ILU近似。

3.6 不完全LU分解不含填补(ILU(0))

有许多ILU分解技术的变种,然而最简单的莫过于ILU(0)了,在ILU(0)中,0元素在矩阵 L \bold L L U \bold U U中的位置是和原矩阵 A \bold A A中的0元素位置严格对应的。使用Gauss消元,计算过程和完全LU分解是一样的,只是如果在原矩阵 A \bold A A的0元素位置处出现了新的非0元素( l i j l_{ij} lij u i j u_{ij} uij),那么直接把它们刨掉就是了。因此,矩阵 L \bold L L U \bold U U联合起来,所反映的就是原始矩阵 A \bold A A中非0元素的位置,如此一来,在分解稀疏矩阵时经常出现的填补现象就被消除了。然而,精度却有所丧失导致达到收敛的迭代次数有所增加。为克服该缺陷,人们发展了更加精确的ILU分解方法,它们更加高效更加可靠。这些方法依据允许填补层次的不同,用 I L U ( p ) ILU(p) ILU(p)来定义填补的阶数。填补的阶数越高,ILU分解步骤代价越大。此外,当使用多重网格方法的时候(后面会讲到),ILU(0)方法作为光滑器(smoother)是绰绰有余的。正因为如此,这里就不展示高阶方法了。

ILU(0)分解算法假设 L \bold L L是个单位下三角矩阵,因此,可以把矩阵 L \bold L L U \bold U U还是存在矩阵 A \bold A A原本的位置上,该算法如下

3.7 ILU(0)分解算法

for k = 1 to N-1
{
	for i = k+1 to N and a_ik != 0
	{
		a_ik = a_ik / a_kk	// 这个是l矩阵的元素
		for j = k+1 to N and a_ij != 0
			a_ij = a_ij - a_ik * a_kj	// 这个是u矩阵的元素
	}
}

其实跟Gauss消元推出的LU分解一样,不过是判断了原矩阵的原始元素是否为0,如果是0就不处理了,仅此而已。

值的注意的是,对于对称正定矩阵的ILU分解被定义成了不完全Cholesky分解,此时,分解只需做下三角(或上三角)部分,对原矩阵的近似可以写为
L ‾   L ‾ T ≈ A \overline \bold L ~ \overline \bold L ^\text T \approx \bold A L LTA
其中 L ‾ \overline \bold L L是分解出来的稀疏下三角矩阵(矩阵 L \bold L L的近似),预处理矩阵 P \bold P P
P = L ‾   L ‾ T ≈ A \bold P = \overline \bold L ~ \overline \bold L ^\text T \approx \bold A P=L LTA

3.8 ILU分解预处理器

基于ILU分解有很多好用的预处理器,前面提到直接解法中把稀疏矩阵 A \bold A A分解成下三角和上三角矩阵乘积的时候会出现填补现象。由于预处理器仅需要是矩阵 A − 1 \bold A^{-1} A1的近似,因此,寻找矩阵 A \bold A A的近似分解就足够了,比如 A = L ‾   U ‾ \bold A = \overline \bold L ~ \overline \bold U A=L U。选择 P = L ‾   U ‾ \bold P = \overline \bold L ~ \overline \bold U P=L U将会使得 P − 1 \bold P^{-1} P1的计算非常高效,因为该求逆可以用前向和后向回代来求出,如前所述,而此时精确的 L \bold L L U \bold U U已经分别被近似的 L ‾ \overline \bold L L U ‾ \overline \bold U U替代了。

对于ILU(0)方法,不完全分解减少了非零元素的稀疏度,预处理器与原矩阵的大小完全一样。为了减少存储量,Pommerell引入了ILU的简化版叫做对角ILU(DILU),在DILU中非对角元的填补都被消去了(矩阵中的上下三角部分的元素保持不变),只有对角元素才被修改。

那么,预处理器可写成如下形式
P = ( D ∗ + L ) D ∗ − 1 ( D ∗ + U ) \bold P = (\bold D^* + \bold L)\bold D^{*-1}(\bold D^* + \bold U) P=(D+L)D1(D+U)
其中 L \bold L L U \bold U U为矩阵 A \bold A A的上下三角分量(注意,不是LU分解,这里的L和U就是A中原本的上下三角部分的元素值),而 D ∗ \bold D^* D为规则的对角矩阵,但是与 A \bold A A的对角元素不同,矩阵 D ∗ \bold D^* D的定义是,让上式 ( D ∗ + L ) D ∗ − 1 ( D ∗ + U ) (\bold D^* + \bold L)\bold D^{*-1}(\bold D^* + \bold U) (D+L)D1(D+U)的对角元等于 A \bold A A的对角元素。

3.9 计算DILU方法中D*的算法

for i = 1 to N
	d_ii = a_ii
for i = 1 to N
	for j = i+1 to N 且 a_ij != 0 且 a_ji != 0
		d_jj = d_jj - a_ji * a_ij / d_ii

为了求预处理器的逆,定义
P = ( D ∗ + L ) D ∗ − 1 ( D ∗ + U ) = L ‾   U ‾ , L ‾ = ( D ∗ + L ) D ∗ − 1 , U ‾ = ( D ∗ + U ) \bold P = (\bold D^* + \bold L)\bold D^{*-1}(\bold D^* + \bold U)=\overline\bold L~\overline\bold U,\quad \overline\bold L=(\bold D^* + \bold L)\bold D^{*-1},\quad \overline\bold U=(\bold D^* + \bold U) P=(D+L)D1(D+U)=L U,L=(D+L)D1,U=(D+U)

P = ( D ∗ + L ) ( I + D ∗ − 1 U ) = L ‾   U ‾ , L ‾ = ( D ∗ + L ) , U ‾ = ( I + D ∗ − 1 U ) \bold P = (\bold D^* + \bold L)(\bold I + \bold D^{*-1}\bold U)=\overline\bold L~\overline\bold U,\quad \overline\bold L=(\bold D^* + \bold L),\quad \overline\bold U=(\bold I + \bold D^{*-1}\bold U) P=(D+L)(I+D1U)=L U,L=(D+L),U=(I+D1U)
这样在求解 P ϕ ′ ( n + 1 ) = r ( n ) \bold P \boldsymbol \phi'^{(n+1)} = \bold r^{(n)} Pϕ(n+1)=r(n)时,需要用到修正场 ϕ ′ ( n + 1 ) = P − 1 r ( n ) \boldsymbol \phi'^{(n+1)} = \bold P^{-1}\bold r^{(n)} ϕ(n+1)=P1r(n),就可以很方便地用前向和后向回代算法求出了。

3.10 DILU方法中的前向和后向回代算法

for i = 1 to N
	for j = 1 to i-1
		t_i = d_ii^-1 (r_i - l_ij * t_j)
for i = N to 1
	for j = i+1 to N
		phi'_i = t_i - d_ii^-1 (u_ij * t_j)

DILU的显著优势是,其仅需要存储一个额外的对角矩阵就行了。

3.11 求解代数系统的梯度方法

另一组求解线性代数方程组系统的迭代方法是梯度方法(Gradient Method),包含最速下降法(Steepest Descent)和共轭梯度方法(Conjugate Gradient)。它们最初是用于求解对称正定(SPD)矩阵 A \bold A A为系数的二次矢量函数的最小值问题,即
Q ( ϕ ) = 1 2 ϕ T A ϕ − b T ϕ + c \bold Q(\boldsymbol \phi) = \frac{1}{2}\boldsymbol \phi^T\bold A \boldsymbol \phi - \bold b^T \boldsymbol \phi + \bold c Q(ϕ)=21ϕTAϕbTϕ+c
其中 c \bold c c为标量矢量, Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ)的最小值对应的是其对 ϕ \boldsymbol \phi ϕ的梯度值是零。而矢量场 Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ) ϕ \boldsymbol \phi ϕ处的梯度 Q ′ ( ϕ ) \bold Q'(\boldsymbol \phi) Q(ϕ),指向的正是 Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ)的最大增长方向。梯度可算得
Q ′ ( ϕ ) = 1 2 A T ϕ + 1 2 A ϕ − b \bold Q'(\boldsymbol \phi)=\frac{1}{2}\bold A^T \boldsymbol \phi +\frac{1}{2}\bold A \boldsymbol \phi - \bold b Q(ϕ)=21ATϕ+21Aϕb
如果 A \bold A A是对称的( A = A T \bold A=\bold A^T A=AT),则
Q ′ ( ϕ ) = A ϕ − b \bold Q'(\boldsymbol \phi)=\bold A \boldsymbol \phi - \bold b Q(ϕ)=Aϕb
最小值是在 Q ′ ( ϕ ) = 0 \bold Q'(\boldsymbol \phi)=\bold 0 Q(ϕ)=0处获得的,有
Q ′ ( ϕ ) = 0 ⇒ A ϕ = b \bold Q'(\boldsymbol \phi)=\bold 0 \Rightarrow \bold A \boldsymbol \phi = \bold b Q(ϕ)=0Aϕ=b
因此, Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ)的最小值问题对应的就是求解 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b的问题,即该最小值问题的解和线性代数方程组的解是一样的。

还有个问题,要保证函数 Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ)的最小值是全局最小值,需要系数矩阵 A \bold A A是正定的(positive definite),即,其应该对所有的 ϕ ≠ 0 \boldsymbol \phi \neq \bold 0 ϕ=0满足 ϕ T A ϕ > 0 \boldsymbol \phi^T\bold A \boldsymbol \phi>0 ϕTAϕ>0。这一要求可通过考察精确解 ϕ \boldsymbol \phi ϕ与其当前预估值 ϕ ( n ) \boldsymbol \phi^{(n)} ϕ(n)的关系来阐明,令 e = ϕ ( n ) − ϕ \bold e=\boldsymbol \phi^{(n)}-\boldsymbol \phi e=ϕ(n)ϕ代表精确值和当前值的差别,则
Q ( ϕ + e ) = 1 2 ( ϕ + e ) T A ( ϕ + e ) − b T ( ϕ + e ) + c = 1 2 ϕ T A ϕ + 1 2 e T A ϕ + 1 2 ϕ T A e + 1 2 e T A e − b T ϕ − b T e + c = 1 2 ϕ T A ϕ − b T ϕ + c ⏟ Q ( ϕ ) + 1 2 ( e T A ϕ + ϕ T A e ) − b T e + 1 2 e T A e = Q ( ϕ ) + 1 2 e T A e \begin{aligned} \bold Q(\boldsymbol \phi + \bold e) & = \frac{1}{2}(\boldsymbol \phi + \bold e)^T\bold A (\boldsymbol \phi + \bold e) - \bold b^T (\boldsymbol \phi + \bold e) + \bold c \\ & = \frac{1}{2}\boldsymbol \phi^T\bold A \boldsymbol \phi + \frac{1}{2}\boldsymbol e^T\bold A \boldsymbol \phi + \frac{1}{2}\boldsymbol \phi^T\bold A \boldsymbol e + \frac{1}{2}\boldsymbol e^T\bold A \boldsymbol e - \bold b^T \boldsymbol \phi - \bold b^T \boldsymbol e + \bold c \\ & = \underbrace{\frac{1}{2}\boldsymbol \phi^T\bold A \boldsymbol \phi - \bold b^T \boldsymbol \phi + \bold c}_{\bold Q(\boldsymbol \phi)} + \frac{1}{2}(\boldsymbol e^T\bold A \boldsymbol \phi + \boldsymbol \phi^T\bold A \boldsymbol e) - \bold b^T \boldsymbol e + \frac{1}{2}\boldsymbol e^T\bold A \boldsymbol e \\ & = \bold Q(\boldsymbol \phi) + \frac{1}{2}\boldsymbol e^T\bold A \boldsymbol e \end{aligned} Q(ϕ+e)=21(ϕ+e)TA(ϕ+e)bT(ϕ+e)+c=21ϕTAϕ+21eTAϕ+21ϕTAe+21eTAebTϕbTe+c=Q(ϕ) 21ϕTAϕbTϕ+c+21(eTAϕ+ϕTAe)bTe+21eTAe=Q(ϕ)+21eTAe
之所以消去了一些项,是因为
1 2 ( e T A ϕ + ϕ T A e ) − b T e = 1 2 ( ( A ϕ ) T e + ϕ T A e ) − b T e = 1 2 ( ϕ T A T e + ϕ T A e ) − b T e = 1 2 ( ϕ T A e + ϕ T A e ) − b T e = ϕ T A e − b T e = ϕ T A T e − b T e = ( ϕ T A T − b T ) e = ( A ϕ − b ) T e = 0 \begin{aligned} \frac{1}{2}(\boldsymbol e^T\bold A \boldsymbol \phi + \boldsymbol \phi^T\bold A \boldsymbol e) - \bold b^T \boldsymbol e & = \frac{1}{2}((\bold A \boldsymbol \phi)^T \boldsymbol e + \boldsymbol \phi^T\bold A \boldsymbol e) - \bold b^T \boldsymbol e \\ & = \frac{1}{2}(\boldsymbol \phi^T \bold A^T \boldsymbol e + \boldsymbol \phi^T\bold A \boldsymbol e) - \bold b^T \boldsymbol e \\ & = \frac{1}{2}(\boldsymbol \phi^T \bold A \boldsymbol e + \boldsymbol \phi^T\bold A \boldsymbol e) - \bold b^T \boldsymbol e \\ & = \boldsymbol \phi^T\bold A \boldsymbol e - \bold b^T \boldsymbol e \\ & = \boldsymbol \phi^T\bold A^T \boldsymbol e - \bold b^T \boldsymbol e \\ & = (\boldsymbol \phi^T\bold A^T - \bold b^T) \boldsymbol e \\ & = (\bold A \boldsymbol \phi - \bold b)^T \boldsymbol e \\ & = \bold 0 \end{aligned} 21(eTAϕ+ϕTAe)bTe=21((Aϕ)Te+ϕTAe)bTe=21(ϕTATe+ϕTAe)bTe=21(ϕTAe+ϕTAe)bTe=ϕTAebTe=ϕTATebTe=(ϕTATbT)e=(Aϕb)Te=0
Q ( ϕ + e ) = Q ( ϕ ) + 1 2 e T A e \bold Q(\boldsymbol \phi + \bold e) = \bold Q(\boldsymbol \phi) + \frac{1}{2}\boldsymbol e^T\bold A \boldsymbol e Q(ϕ+e)=Q(ϕ)+21eTAe可见,如果 A \bold A A是正定的,那么第2项将永远是正值,除非 e = 0 \bold e=\bold 0 e=0,即获得了所要的全局最小值。此外,如果 A \bold A A是正定的,它的所有特征值都是正的,且函数 Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ)有唯一的最小值。

这样对于一个对称正定矩阵,可获得其收敛序列 ϕ ( n ) \boldsymbol \phi^{(n)} ϕ(n)如下
ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) ( δ ϕ ( n ) ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)}(\delta \boldsymbol \phi^{(n)}) ϕ(n+1)=ϕ(n)+α(n)(δϕ(n))
其中 α ( n ) \alpha^{(n)} α(n)是松弛因子,而 δ ϕ ( n ) \delta \boldsymbol \phi^{(n)} δϕ(n)是与每步迭代过程中最小化函数 Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ)的相关修正,当然这个式子的实现可以有很多方式,从而产生了不同的方法。

3.12 最速下降方法(The Method of Steepest Descent)

求解线性方程组系统的最速下降方法,是基于最小化式子 Q ( ϕ ) = 1 2 ϕ T A ϕ − b T ϕ + c \bold Q(\boldsymbol \phi) = \frac{1}{2}\boldsymbol \phi^T\bold A \boldsymbol \phi - \bold b^T \boldsymbol \phi + \bold c Q(ϕ)=21ϕTAϕbTϕ+c中平方项的考虑。如果 ϕ \boldsymbol \phi ϕ是一维矢量,其分量为标量 ϕ \phi ϕ,那么函数 Q ( ϕ ) \bold Q(\phi) Q(ϕ)代表了一个抛物线,那么从某个初始点 ϕ 0 \phi_0 ϕ0开始,找到该抛物线函数的最小值的方法,可以沿着该抛物线向下运动,直到碰到其底部最小值。

同样的思想可以应用于 N N N维系统,此时函数 Q ( ϕ ( n ) ) \bold Q( \boldsymbol \phi^{(n)}) Q(ϕ(n))描述的可能是一个抛物面,而从一个初始位置 ϕ ( 0 ) \boldsymbol \phi^{(0)} ϕ(0)开始的迭代求解过程,就可以是沿着该抛物面不断向下运动直到达到底部的最小值。为了获取更快的收敛序列, ϕ ( 0 ) , ϕ ( 1 ) , ϕ ( 2 ) , . . . \boldsymbol \phi^{(0)}, \boldsymbol \phi^{(1)}, \boldsymbol \phi^{(2)},... ϕ(0),ϕ(1),ϕ(2),...应该选择最快速的下降方向,即,- Q ′ ( ϕ ) \bold Q'(\boldsymbol \phi) Q(ϕ)。这个方向就是
− Q ′ ( ϕ ) = b − A ϕ -\bold Q'(\boldsymbol \phi)= \bold b - \bold A \boldsymbol \phi Q(ϕ)=bAϕ
精确解是 ϕ \boldsymbol \phi ϕ,则在第 n n n步的误差 e ( n ) \bold e^{(n)} e(n)和残差 r ( n ) \bold r^{(n)} r(n),为
e ( n ) = ϕ ( n ) − ϕ r ( n ) = b − A ϕ ( n ) = − Q ′ ( ϕ ( n ) ) } ⇒ r ( n ) = A ϕ − A ϕ ( n ) = − A e ( n ) \left. \begin{matrix} \bold e^{(n)} = \boldsymbol \phi^{(n)} - \boldsymbol \phi \\ \bold r^{(n)} = \bold b - \bold A \boldsymbol \phi^{(n)}=-\bold Q'(\boldsymbol \phi^{(n)}) \end{matrix} \right\} \Rightarrow \bold r^{(n)} = \bold A \boldsymbol \phi- \bold A \boldsymbol \phi^{(n)} = - \bold A \boldsymbol e^{(n)} e(n)=ϕ(n)ϕr(n)=bAϕ(n)=Q(ϕ(n))}r(n)=AϕAϕ(n)=Ae(n)
那么,沿着最速下降方向, ϕ ( n + 1 ) \boldsymbol \phi^{(n+1)} ϕ(n+1)的值可由 ϕ ( n ) \boldsymbol \phi^{(n)} ϕ(n)的值写作
ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) r ( n ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold r^{(n)} ϕ(n+1)=ϕ(n)+α(n)r(n)
α ( n ) \alpha^{(n)} α(n)的值是要让 Q ( ϕ ) \bold Q(\boldsymbol \phi) Q(ϕ)最小,所以
d ( Q ( ϕ ( n + 1 ) ) ) d α ( n ) = 0 \frac{d\left(\bold Q(\boldsymbol \phi^{(n+1)})\right) }{d\alpha^{(n)}} = 0 dα(n)d(Q(ϕ(n+1)))=0

d ( Q ( ϕ ( n + 1 ) ) ) d α ( n ) = 0 ⇒ [ d ( Q ( ϕ ( n + 1 ) ) ) d ϕ ( n + 1 ) ] T d ϕ ( n + 1 ) d α ( n ) ⇒ ( r ( n + 1 ) ) T r ( n ) = 0 \frac{d\left(\bold Q(\boldsymbol \phi^{(n+1)})\right) }{d\alpha^{(n)}} = 0 \Rightarrow \left[ \frac{d\left(\bold Q(\boldsymbol \phi^{(n+1)})\right) }{d\boldsymbol \phi^{(n+1)}} \right]^T \frac{d\boldsymbol \phi^{(n+1)}}{d\alpha^{(n)}} \Rightarrow (\bold r^{(n+1)})^T\bold r^{(n)} = 0 dα(n)d(Q(ϕ(n+1)))=0dϕ(n+1)d(Q(ϕ(n+1)))Tdα(n)dϕ(n+1)(r(n+1))Tr(n)=0
表明新迭代步的方向应该与老迭代步的方向相互垂直, α ( n ) \alpha^{(n)} α(n)的值可由上式计算
( r ( n + 1 ) ) T r ( n ) = 0 ⇒ ( b − A ϕ ( n + 1 ) ) T r ( n ) = 0 ⇒ [ b − A ( ϕ ( n ) + α ( n ) r ( n ) ) ] T r ( n ) = 0 ⇒ ( b − A ϕ ( n ) ) T r ( n ) = α ( n ) ( A r ( n ) ) T r ( n ) ⇒ ( r ( n ) ) T r ( n ) = α ( n ) ( r ( n ) ) T A r ( n ) ⇒ α ( n ) = ( r ( n ) ) T r ( n ) ( r ( n ) ) T A r ( n ) \begin{aligned} (\bold r^{(n+1)})^T\bold r^{(n)} = 0 & \Rightarrow ( \bold b - \bold A \boldsymbol \phi ^{(n+1)})^T\bold r^{(n)} = 0 \\ & \Rightarrow [ \bold b - \bold A ( \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold r^{(n)})]^T\bold r^{(n)} = 0 \\ & \Rightarrow (\bold b - \bold A \boldsymbol \phi^{(n)})^T\bold r^{(n)} = \alpha^{(n)} ( \bold A \bold r^{(n)})^T \bold r^{(n)} \\ & \Rightarrow (\bold r^{(n)})^T\bold r^{(n)} = \alpha^{(n)} (\bold r^{(n)})^T\bold A\bold r^{(n)} \\ & \Rightarrow \alpha^{(n)} = \frac{(\bold r^{(n)})^T\bold r^{(n)}}{(\bold r^{(n)})^T\bold A\bold r^{(n)}} \\ \end{aligned} (r(n+1))Tr(n)=0(bAϕ(n+1))Tr(n)=0[bA(ϕ(n)+α(n)r(n))]Tr(n)=0(bAϕ(n))Tr(n)=α(n)(Ar(n))Tr(n)(r(n))Tr(n)=α(n)(r(n))TAr(n)α(n)=(r(n))TAr(n)(r(n))Tr(n)
将最速下降算法的流程总结如下

  1. 选择残差作为起始方向 r ( 0 ) = b − A ϕ ( 0 ) \bold r^{(0)} = \bold b - \bold A \boldsymbol \phi^{(0)} r(0)=bAϕ(0)
  2. 第n步的迭代过程如下
    2.1. 计算残差矢量 r ( n ) = b − A ϕ ( n ) \bold r^{(n)} = \bold b - \bold A \boldsymbol \phi^{(n)} r(n)=bAϕ(n)
    2.2. 计算正交方向的比率 α ( n ) = ( r ( n ) ) T r ( n ) ( r ( n ) ) T A r ( n ) \displaystyle \alpha^{(n)} = \frac{(\bold r^{(n)})^T\bold r^{(n)}}{(\bold r^{(n)})^T\bold A\bold r^{(n)}} α(n)=(r(n))TAr(n)(r(n))Tr(n)
    2.3. 获取新值 ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) r ( n ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold r^{(n)} ϕ(n+1)=ϕ(n)+α(n)r(n)

算法中的每个迭代步需要执行两次矩阵-矢量相乘,其中一个可以消去,即
ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) r ( n ) ⇒ b − A ϕ ( n + 1 ) = b − A ( ϕ ( n ) + α ( n ) r ( n ) ) ⇒ r ( n + 1 ) = r ( n ) − α ( n ) A r ( n ) \begin{aligned} \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold r^{(n)} & \Rightarrow \bold b - \bold A \boldsymbol \phi^{(n+1)} = \bold b - \bold A (\boldsymbol \phi^{(n)} + \alpha^{(n)} \bold r^{(n)}) \\ &\Rightarrow \boldsymbol r^{(n+1)}=\boldsymbol r{(n)}-\alpha^{(n)} \bold A \bold r^{(n)} \end{aligned} ϕ(n+1)=ϕ(n)+α(n)r(n)bAϕ(n+1)=bA(ϕ(n)+α(n)r(n))r(n+1)=r(n)α(n)Ar(n)
也就是说, r ( n ) \bold r^{(n)} r(n)只需要计算第1步的 r ( 0 ) \bold r^{(0)} r(0),用 r ( n + 1 ) = r ( n ) − α ( n ) A r ( n ) \boldsymbol r^{(n+1)}=\boldsymbol r{(n)}-\alpha^{(n)} \bold A \bold r^{(n)} r(n+1)=r(n)α(n)Ar(n)就可以把后面的算出来了,这样子就不需要再计算 A ϕ ( n ) \bold A \boldsymbol \phi^{(n)} Aϕ(n),因为算 A r ( n ) \bold A \bold r^{(n)} Ar(n)就好了(残差矢量和正交方向比率都用这个来算,只用算一次就行了)。然而这样做的缺点在于缺乏从 ϕ ( n ) \boldsymbol\phi^{(n)} ϕ(n)向残差的反馈,有可能会因为圆整误差导致解收敛到一个不同于精确解的值,该缺陷可通过使用最初的方程定期计算残差来修复。

3.13 共轭梯度方法(The Conjugate Gradient Method)

虽然最速下降方法保证了收敛性,然而其收敛速度非常低。之所以会这样,是由于局部最小值附近的震荡导致该方法不断地在同一个方向搜索引起的,为避免这类问题,需要让每一次搜索的方向都跟前一次不一样才好。这可以通过选择一系列搜索方向 d ( 0 ) , d ( 1 ) , d ( 2 ) , . . . , d ( N − 1 ) \bold d^{(0)},\bold d^{(1)},\bold d^{(2)},...,\bold d^{(N-1)} d(0),d(1),d(2),...,d(N1),让其是 A \bold A A正交的,两个矢量 d ( m ) \bold d^{(m)} d(m) d ( n ) \bold d^{(n)} d(n)如果满足如下关系则说它们是 A \bold A A正交的
( d ( n ) ) T A d ( m ) = 0 (\bold d^{(n)})^T \bold A \bold d^{(m)}=0 (d(n))TAd(m)=0
如果在每次搜索方向都采用了正确的步长,那么解将会在第 N N N步收敛。

第n+1步的值为
ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) d ( n ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold d^{(n)} ϕ(n+1)=ϕ(n)+α(n)d(n)
ϕ \boldsymbol \phi ϕ从上式两端减去,可得误差方程
e ( n + 1 ) = e ( n ) + α ( n ) d ( n ) \boldsymbol e^{(n+1)} = \boldsymbol e^{(n)} + \alpha^{(n)} \bold d^{(n)} e(n+1)=e(n)+α(n)d(n)
由于在前面最速下降算法中提到 r ( n ) = − A e ( n ) \bold r^{(n)} =- \bold A \boldsymbol e^{(n)} r(n)=Ae(n),故
r ( n + 1 ) = − A e ( n + 1 ) = − A ( e ( n ) + α ( n ) d ( n ) ) = r ( n ) − α ( n ) A d ( n ) \begin{aligned} \bold r^{(n+1)} &= - \bold A \boldsymbol e^{(n+1)} \\ &= - \bold A (\boldsymbol e^{(n)} + \alpha^{(n)} \bold d^{(n)}) \\ &= \bold r^{(n)} - \alpha^{(n)} \bold A \bold d^{(n)} \end{aligned} r(n+1)=Ae(n+1)=A(e(n)+α(n)d(n))=r(n)α(n)Ad(n)
上式表明,新残差 r ( n + 1 ) \bold r^{(n+1)} r(n+1)只是之前残差 r ( n ) \bold r^{(n)} r(n) A d ( n ) \bold A \bold d^{(n)} Ad(n)的线性组合。

接下来需要让 e ( n + 1 ) \boldsymbol e^{(n+1)} e(n+1) d ( n ) \bold d^{(n)} d(n) A \bold A A正交的,这等效于沿着 d ( n ) \bold d^{(n)} d(n)方向搜索找到最小点,可推出 α ( n ) \alpha^{(n)} α(n)
( d ( n ) ) T A e ( n + 1 ) = 0 ⇒ ( d ( n ) ) T A ( e ( n ) + α ( n ) d ( n ) ) = 0 ⇒ α ( n ) = ( d ( n ) ) T r ( n ) ( d ( n ) ) T A d ( n ) \begin{aligned} (\bold d^{(n)})^T \bold A \bold e^{(n+1)}=0 & \Rightarrow (\bold d^{(n)})^T \bold A (\boldsymbol e^{(n)} + \alpha^{(n)} \bold d^{(n)})=0 \\ & \Rightarrow \alpha^{(n)} = \frac{(\bold d^{(n)})^T\bold r^{(n)}}{(\bold d^{(n)})^T \bold A \bold d^{(n)}} \end{aligned} (d(n))TAe(n+1)=0(d(n))TA(e(n)+α(n)d(n))=0α(n)=(d(n))TAd(n)(d(n))Tr(n)
上式也意味着
( d ( n ) ) T A e ( n + 1 ) = 0 ⇒ ( d ( n ) ) T r ( n + 1 ) = 0 (\bold d^{(n)})^T \bold A \bold e^{(n+1)}=0 \Rightarrow (\bold d^{(n)})^T \bold r^{(n+1)}= 0 (d(n))TAe(n+1)=0(d(n))Tr(n+1)=0
即,如果知道了搜索方向,那么可以算出 α ( n ) \alpha^{(n)} α(n)

为了推导出搜索方向,假设其控制方程的形式为
d ( n + 1 ) = r ( n + 1 ) + β ( n ) d ( n ) \bold d^{(n+1)} = \bold r^{(n+1)} + \beta^{(n)}\bold d^{(n)} d(n+1)=r(n+1)+β(n)d(n)
d \bold d d矢量的 A \bold A A正交需要其满足
( d ( n + 1 ) ) T A d ( n ) = 0 (\bold d^{(n+1)})^T \bold A \bold d^{(n)}= 0 (d(n+1))TAd(n)=0
结合上上式子,可得
β ( n ) = − ( r ( n + 1 ) ) T A d ( n ) ( d ( n ) ) T A d ( n ) \beta^{(n)} =- \frac{(\bold r^{(n+1)})^T\bold A \bold d^{(n)}}{(\bold d^{(n)})^T \bold A \bold d^{(n)}} β(n)=(d(n))TAd(n)(r(n+1))TAd(n)
由于 r ( n + 1 ) = r ( n ) − α ( n ) A d ( n ) \bold r^{(n+1)} = \bold r^{(n)} - \alpha^{(n)} \bold A \bold d^{(n)} r(n+1)=r(n)α(n)Ad(n),得到
A d ( n ) = − 1 α ( n ) ( r ( n + 1 ) − r ( n ) ) \bold A \bold d^{(n)} = - \frac{1}{\alpha^{(n)} }(\bold r^{(n+1)} - \bold r^{(n)} ) Ad(n)=α(n)1(r(n+1)r(n))
结合上式、上上式,以及 α ( n ) = ( d ( n ) ) T r ( n ) ( d ( n ) ) T A d ( n ) \displaystyle \alpha^{(n)} = \frac{(\bold d^{(n)})^T\bold r^{(n)}}{(\bold d^{(n)})^T \bold A \bold d^{(n)}} α(n)=(d(n))TAd(n)(d(n))Tr(n),可推得
β ( n ) = ( r ( n + 1 ) ) T ( r ( n + 1 ) − r ( n ) ) ( d ( n ) ) T A d ( n ) α ( n ) = ( r ( n + 1 ) ) T ( r ( n + 1 ) − r ( n ) ) ( d ( n ) ) T r ( n ) = ( r ( n + 1 ) ) T r ( n + 1 ) − r ( n + 1 ) ) T r ( n ) ⏟ = 0 ( d ( n ) ) T r ( n ) = ( r ( n + 1 ) ) T r ( n + 1 ) ( d ( n ) ) T r ( n ) \begin{aligned} \beta^{(n)} &= \frac{(\bold r^{(n+1)})^T(\bold r^{(n+1)} - \bold r^{(n)} )}{(\bold d^{(n)})^T \bold A \bold d^{(n)}\alpha^{(n)}} \\ &= \frac{(\bold r^{(n+1)})^T(\bold r^{(n+1)} - \bold r^{(n)} )}{(\bold d^{(n)})^T \bold r^{(n)}} \\ & = \frac{(\bold r^{(n+1)})^T \bold r^{(n+1)} - \underbrace{\bold r^{(n+1))^T}\bold r^{(n)}}_{=0} }{(\bold d^{(n)})^T \bold r^{(n)}} \\ &= \frac{(\bold r^{(n+1)})^T \bold r^{(n+1)} }{(\bold d^{(n)})^T \bold r^{(n)}} \end{aligned} β(n)=(d(n))TAd(n)α(n)(r(n+1))T(r(n+1)r(n))=(d(n))Tr(n)(r(n+1))T(r(n+1)r(n))=(d(n))Tr(n)(r(n+1))Tr(n+1)=0 r(n+1))Tr(n)=d(n))Tr(n)(r(n+1))Tr(n+1)
上式中的分母可进一步展开为
( d ( n ) ) T r ( n ) = ( r ( n ) + β ( n − 1 ) d ( n − 1 ) ) T r ( n ) = ( r ( n ) ) T r ( n ) + β ( n − 1 ) ( d ( n − 1 ) ) T r ( n ) ⏟ = 0 = ( r ( n ) ) T r ( n ) \begin{aligned} (\bold d^{(n)})^T \bold r^{(n)} &= (\bold r^{(n)} + \beta^{(n-1)} \bold d^{(n-1)})^T \bold r^{(n)} \\ &= (\bold r^{(n)})^T \bold r^{(n)} + \beta^{(n-1)} \underbrace{(\bold d^{(n-1)})^T \bold r^{(n)}}_{=0} \\ &= (\bold r^{(n)})^T \bold r^{(n)} \end{aligned} (d(n))Tr(n)=(r(n)+β(n1)d(n1))Tr(n)=(r(n))Tr(n)+β(n1)=0 (d(n1))Tr(n)=(r(n))Tr(n)
因此,有
β ( n ) = ( r ( n + 1 ) ) T r ( n + 1 ) ( r ( n ) ) T r ( n ) \beta^{(n)} = \frac{(\bold r^{(n+1)})^T \bold r^{(n+1)} }{ (\bold r^{(n)})^T \bold r^{(n)} } β(n)=(r(n))Tr(n)(r(n+1))Tr(n+1)
共轭梯度(CG)算法流程为

  1. 选择残差作为初始方向 d ( 0 ) = r ( 0 ) = b − A ϕ ( 0 ) \bold d^{(0)} = \bold r^{(0)} = \bold b - \bold A \boldsymbol \phi^{(0)} d(0)=r(0)=bAϕ(0)
  2. 第n步的迭代过程如下
    2.1. 选择 d \bold d d方向的比率因子 α ( n ) = ( d ( n ) ) T r ( n ) ( d ( n ) ) T A d ( n ) \displaystyle \alpha^{(n)} = \frac{(\bold d^{(n)})^T\bold r^{(n)}}{(\bold d^{(n)})^T \bold A \bold d^{(n)}} α(n)=(d(n))TAd(n)(d(n))Tr(n)
    2.2. 获得新的 ϕ \boldsymbol \phi ϕ,用 ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) d ( n ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold d^{(n)} ϕ(n+1)=ϕ(n)+α(n)d(n)
    2.3. 计算新残差 r ( n + 1 ) = r ( n ) − α ( n ) A d ( n ) \bold r^{(n+1)} = \bold r^{(n)} - \alpha^{(n)} \bold A \bold d^{(n)} r(n+1)=r(n)α(n)Ad(n)
    2.4. 计算共轭残差系数 β ( n ) = ( r ( n + 1 ) ) T r ( n + 1 ) ( r ( n ) ) T r ( n ) \displaystyle \beta^{(n)} = \frac{(\bold r^{(n+1)})^T \bold r^{(n+1)} }{ (\bold r^{(n)})^T \bold r^{(n)} } β(n)=(r(n))Tr(n)(r(n+1))Tr(n+1)
    2.5. 获取新的共轭搜索方向 d ( n + 1 ) = r ( n + 1 ) + β ( n ) d ( n ) \bold d^{(n+1)} = \bold r^{(n+1)} + \beta^{(n)}\bold d^{(n)} d(n+1)=r(n+1)+β(n)d(n)

共轭梯度(CG)方法的收敛速度可以通过预处理来提高,这可以通过将原系统方程乘上一个预处理矩阵的逆矩阵 P − 1 \bold P^{-1} P1来实现,其中 P \bold P P是对称正定矩阵,以便做预处理 P − 1 A ϕ = P − 1 b \bold P^{-1}\bold A\boldsymbol \phi = \bold P^{-1}\bold b P1Aϕ=P1b。问题在于,即便 P \bold P P A \bold A A都是对称的, P − 1 A \bold P^{-1}\bold A P1A也未必是对称的,为了克服该问题,把 P \bold P P采用Cholesky分解成
P = L L T \bold P = \bold L \bold L ^T P=LLT
为了保证对称性,将系统方程写为
L − 1 A L − T L T ϕ = L − 1 b \bold L ^{-1}\bold A\bold L ^{-T} \bold L ^{T}\boldsymbol \phi = \bold L ^{-1}\bold b L1ALTLTϕ=L1b
其中 L − 1 A L − T \bold L ^{-1}\bold A\bold L ^{-T} L1ALT是对称和正定的。CG方法可用于求解 L T ϕ \bold L ^{T}\boldsymbol \phi LTϕ,从而解出 ϕ \boldsymbol \phi ϕ。然而,通过替换,可以把 L \bold L L从方程中消去,而且不会影响到对称性和该方法的可靠性。通过对CG方法做一定的处理,便可获得预处理CG方法。

预处理CG方法(PCG)算法流程如下

  1. 选择初始方向 r ( 0 ) = b − A ϕ ( 0 ) \bold r^{(0)} = \bold b - \bold A \boldsymbol \phi^{(0)} r(0)=bAϕ(0) d ( 0 ) = P − 1 r ( 0 ) \bold d^{(0)} =\bold P^{-1}\bold r^{(0)} d(0)=P1r(0)
  2. 第n步的迭代过程如下
    2.1. 选择 d \bold d d方向的比率因子 α ( n ) = ( r ( n ) ) T P − 1 r ( n ) ( d ( n ) ) T A d ( n ) \displaystyle \alpha^{(n)} = \frac{(\bold r^{(n)})^T\bold P^{-1}\bold r^{(n)}}{(\bold d^{(n)})^T \bold A \bold d^{(n)}} α(n)=(d(n))TAd(n)(r(n))TP1r(n)
    2.2. 获得新的 ϕ \boldsymbol \phi ϕ,用 ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) d ( n ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold d^{(n)} ϕ(n+1)=ϕ(n)+α(n)d(n)
    2.3. 计算新残差 r ( n + 1 ) = r ( n ) − α ( n ) A d ( n ) \bold r^{(n+1)} = \bold r^{(n)} - \alpha^{(n)} \bold A \bold d^{(n)} r(n+1)=r(n)α(n)Ad(n)
    2.4. 计算共轭残差系数 β ( n + 1 ) = ( r ( n + 1 ) ) T P − 1 r ( n + 1 ) ( r ( n ) ) T P − 1 r ( n ) \displaystyle \beta^{(n+1)} = \frac{(\bold r^{(n+1)})^T \bold P^{-1} \bold r^{(n+1)} }{ (\bold r^{(n)})^T \bold P^{-1}\bold r^{(n)} } β(n+1)=(r(n))TP1r(n)(r(n+1))TP1r(n+1)
    2.5. 获取新的共轭搜索方向 d ( n + 1 ) = P − 1 r ( n + 1 ) + β ( n + 1 ) d ( n ) \bold d^{(n+1)} = \bold P^{-1}\bold r^{(n+1)} + \beta^{(n+1)}\bold d^{(n)} d(n+1)=P1r(n+1)+β(n+1)d(n)

实际上,有很多预处理的方法,较为简单的方法是选用原矩阵 A \bold A A的对角元素构建一个对角元矩阵(Jacobi pre-conditioner),较为复杂的方法是使用不完全Cholesky分解。无论如何,当CG方法用于大型矩阵求解时一定要采用预处理,毕竟能提高收敛效率不是。

3.14 双共轭梯度(BiCG)算法及其预处理器

一般来说,扩散方程、不可压缩的压力方程离散后的格式是对称的,可以用CG方法来求解,可是CFD的更加普遍的其它方程则不是对称的,就没法直接用CG方法了。但是CG方法的收敛实在是太快了,不用又怪可惜的。所以,要是能把不对称的矩阵转化成对称的矩阵,就能用CG方法了,有一种法子是这样的
[ 0 A A T 0 ] [ ϕ ^ ϕ ] = [ b 0 ] \begin{bmatrix} \bold 0 & \bold A \\ \bold A^T & \bold 0 \end{bmatrix} \begin{bmatrix} \hat{\boldsymbol \phi} \\ \boldsymbol \phi \end{bmatrix} = \begin{bmatrix} \bold b \\ \bold 0 \end{bmatrix} [0ATA0][ϕ^ϕ]=[b0]
其中 ϕ ^ \hat{\boldsymbol \phi} ϕ^是虚假/伪变量,其添加只是为了让原本不对称的系统转化成对称系统,从而可以用CG方法求解。那么,CG方法现在求解了两个矢量,其中一个就是原方程 A ϕ = b \bold A \boldsymbol \phi = \bold b Aϕ=b要求解的矢量 ϕ \boldsymbol \phi ϕ,另一个则是不需要的伪矢量 ϕ ^ \hat{\boldsymbol \phi} ϕ^(如果想算就把它算出来,如果不想算就不算它了)。因为要求解两个序列的矢量,所以这个方法便称之为双共轭梯度(BiCG)。

实际上基于这个思路提了很多BiCG方法,Lanczos提出的BiCG方法流程如下

  1. 选择初始方向 d ( 0 ) = r ( 0 ) = d ^ ( 0 ) = r ^ ( 0 ) = b − A ϕ ( 0 ) \bold d^{(0)} = \bold r^{(0)} = \hat \bold d^{(0)} = \hat \bold r^{(0)} = \bold b - \bold A \boldsymbol \phi^{(0)} d(0)=r(0)=d^(0)=r^(0)=bAϕ(0)
  2. 第n步的迭代过程如下
    2.1. 选择 d \bold d d方向的比率因子 α ( n ) = ( r ^ ( n ) ) T r ( n ) ( d ^ ( n ) ) T A d ( n ) \displaystyle \alpha^{(n)} = \frac{(\hat \bold r^{(n)})^T\bold r^{(n)}}{(\hat \bold d^{(n)})^T \bold A \bold d^{(n)}} α(n)=(d^(n))TAd(n)(r^(n))Tr(n)
    2.2. 获得新的 ϕ \boldsymbol \phi ϕ,用 ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) d ( n ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold d^{(n)} ϕ(n+1)=ϕ(n)+α(n)d(n)
    2.3. 计算新残差 r ( n + 1 ) = r ( n ) − α ( n ) A d ( n ) \bold r^{(n+1)} = \bold r^{(n)} - \alpha^{(n)} \bold A \bold d^{(n)} r(n+1)=r(n)α(n)Ad(n)
    2.4. 计算新伪残差 r ^ ( n + 1 ) = r ^ ( n ) − α ( n ) A T d ^ ( n ) \hat \bold r^{(n+1)} = \hat \bold r^{(n)} - \alpha^{(n)} \bold A^T \hat\bold d^{(n)} r^(n+1)=r^(n)α(n)ATd^(n)
    2.5. 计算共轭残差系数 β ( n + 1 ) = ( r ^ ( n + 1 ) ) T r ( n + 1 ) ( r ^ ( n ) ) T r ( n ) \displaystyle \beta^{(n+1)} = \frac{(\hat \bold r^{(n+1)})^T \bold r^{(n+1)} }{ (\hat\bold r^{(n)})^T \bold r^{(n)} } β(n+1)=(r^(n))Tr(n)(r^(n+1))Tr(n+1)
    2.6. 获取新的搜索方向 d ( n + 1 ) = r ( n + 1 ) + β ( n + 1 ) d ( n ) \bold d^{(n+1)} = \bold r^{(n+1)} + \beta^{(n+1)}\bold d^{(n)} d(n+1)=r(n+1)+β(n+1)d(n)
    2.7. 获取新的伪搜索方向 d ^ ( n + 1 ) = r ^ ( n + 1 ) + β ( n + 1 ) d ^ ( n ) \hat\bold d^{(n+1)} = \hat\bold r^{(n+1)} + \beta^{(n+1)}\hat\bold d^{(n)} d^(n+1)=r^(n+1)+β(n+1)d^(n)

BiCG方法在每步迭代中需要对矩阵和矩阵的转置做两次相乘运算,这使得其计算量是CG方法的两倍。

BiCG方法当然也可以做预处理,跟预处理CG方法一样,Fletcher的方法流程如下( P \bold P P代表预处理矩阵):

  1. 选择初始方向 r ( 0 ) = r ^ ( 0 ) = b − A ϕ ( 0 ) \bold r^{(0)} = \hat \bold r^{(0)} = \bold b - \bold A \boldsymbol \phi^{(0)} r(0)=r^(0)=bAϕ(0) d ( 0 ) = P − 1 r ( 0 ) \bold d^{(0)} = \bold P^{-1}\bold r^{(0)} d(0)=P1r(0) d ^ ( 0 ) = P − T r ^ ( 0 ) \hat \bold d^{(0)} = \bold P^{-T}\hat \bold r^{(0)} d^(0)=PTr^(0)
  2. 第n步的迭代过程如下
    2.1. 选择 d \bold d d方向的比率因子 α ( n ) = ( r ^ ( n ) ) T P − 1 r ( n ) ( d ^ ( n ) ) T A d ( n ) \displaystyle \alpha^{(n)} = \frac{(\hat \bold r^{(n)})^T\bold P^{-1}\bold r^{(n)}}{(\hat \bold d^{(n)})^T \bold A \bold d^{(n)}} α(n)=(d^(n))TAd(n)(r^(n))TP1r(n)
    2.2. 获得新的 ϕ \boldsymbol \phi ϕ,用 ϕ ( n + 1 ) = ϕ ( n ) + α ( n ) d ( n ) \boldsymbol \phi^{(n+1)} = \boldsymbol \phi^{(n)} + \alpha^{(n)} \bold d^{(n)} ϕ(n+1)=ϕ(n)+α(n)d(n)
    2.3. 计算新残差 r ( n + 1 ) = r ( n ) − α ( n ) A d ( n ) \bold r^{(n+1)} = \bold r^{(n)} - \alpha^{(n)} \bold A \bold d^{(n)} r(n+1)=r(n)α(n)Ad(n)
    2.4. 计算新伪残差 r ^ ( n + 1 ) = r ^ ( n ) − α ( n ) A T d ^ ( n ) \hat \bold r^{(n+1)} = \hat \bold r^{(n)} - \alpha^{(n)} \bold A^T \hat\bold d^{(n)} r^(n+1)=r^(n)α(n)ATd^(n)
    2.5. 计算共轭残差系数 β ( n + 1 ) = ( r ^ ( n + 1 ) ) T P − 1 r ( n + 1 ) ( r ^ ( n ) ) T P − 1 r ( n ) \displaystyle \beta^{(n+1)} = \frac{(\hat \bold r^{(n+1)})^T\bold P^{-1} \bold r^{(n+1)} }{ (\hat\bold r^{(n)})^T \bold P^{-1} \bold r^{(n)} } β(n+1)=(r^(n))TP1r(n)(r^(n+1))TP1r(n+1)
    2.6. 获取新的搜索方向 d ( n + 1 ) = P − 1 r ( n + 1 ) + β ( n + 1 ) d ( n ) \bold d^{(n+1)} = \bold P^{-1}\bold r^{(n+1)} + \beta^{(n+1)}\bold d^{(n)} d(n+1)=P1r(n+1)+β(n+1)d(n)
    2.7. 获取新的伪搜索方向 d ^ ( n + 1 ) = P − 1 r ^ ( n + 1 ) + β ( n + 1 ) d ^ ( n ) \hat\bold d^{(n+1)} = \bold P^{-1}\hat\bold r^{(n+1)} + \beta^{(n+1)}\hat\bold d^{(n)} d^(n+1)=P1r^(n+1)+β(n+1)d^(n)

BiCG方法的其它变种,更具稳定性和可靠性的,有Sonneveld的共轭梯度平方(CGS)、Van Der Vorst的双共轭梯度稳定(Bi-CGSTAB)、通用最小残差方法(GMRES),等。这些方法对于求解CFD当中出现的大型系统矩阵非常有用,可应用于结构和非结构网格所产生的非对称矩阵。

4 多重网格方法

迭代方法的收敛速度随着代数方程系统维数的增大而急剧恶化,这一情况即便是对于中等程度维数的系统也是存在的。这使得迭代方法的应用很受限制,幸运的是,人们很快发现把多重网格算法和迭代方法联合起来使用可以很好地克服该缺陷。

多重网格方法的提出源自于这些学者的贡献:Fedorenko(几何多重网格Geometric Multigrid)、Poussin(代数多重网格Algebraic Multigrid)、以及Settari和Azziz、还有Brandt在理论上的工作。尽管高频或振荡误差可以很容易地通过标准迭代方法(Jacobi、Gauss-Seidel、ILU)消除,然而这些求解方法无法轻易地去除光滑或低频误差分量。正因为如此,这些解法在多重网格方法中被定义成光滑器,下图展示了一维问题的误差频率模态的变化情况。

在这里插入图片描述
从上向下看,图中展示的误差模态从高频到低频,波长也从短 λ 1 \lambda_1 λ1到长 λ 5 \lambda_5 λ5,一维计算域采用一维网格离散,不同的模态分别绘制在同样的网格上。可见,高频误差的振荡发生在一个单元内部,其可以轻易地被迭代方法感受到。但是伴随着误差频率的降低,即,波长的增大,误差在网格上变得越来越光滑,在一个单元内部仅可感受到误差波长的一小部分,网格越是加密该问题反而越是严重,使得系统维数的增大导致方程数目的增多和收敛速率的恶化。

多重网格方法提高迭代求解器效率的法子是,确保在一个网格层级(level)上由于光滑器的应用所产生的低频误差,可以转化到,较粗糙网格层级上的高频误差。如图,通过使用多层次的粗细网格,多重网格方法能够克服收敛恶化的现象。

在这里插入图片描述

一般而言,粗网格可以用细网格的拓扑和几何关系来生成,这相当于在细网格的上面重新生成了一层粗网格;粗网格也可以直接通过细网格单元的聚合来生成,这样就是所谓的代数多重网格(Algebraic MutiGrid Method (AMG))。在AMG中,并不直接用到几何信息,聚合过程只是纯粹的代数处理,即通过聚合过程从细网格上的方程直接构建粗网格上的方程(并不需要重画网格啥的)。该方法可用于构造高效可靠的线性求解器,适用于高度各向异性网格或方程中系数变化很大的问题。

不管哪种方法,多重网格循环过程将用于遍历不同的网格层级。每次从细网格到粗网格的遍历包含:(i)限制(restriction)过程,(ii)设置或更新系统方程到粗网格,(iii)应用几次光滑迭代。每个从粗网格到细网格的遍历包含:(i)扩展(prolongation)过程,(ii)在细网格层级上的流场值修正,(iii)在限制过程中构造的方程上应用几次光滑迭代。下面将详细讲讲不同的步骤。

4.1 单元聚合/粗化(Element Agglomeration/Coarsening)

求解过程的首要任务是通过单元聚合/粗化来生成粗糙/细腻网格层级,有三种方法可以用来达成此目的。一,首先生成粗网格,然后再加密生成细网格,优点是粗-细网格关系非常好获取,缺点是细网格的分布要依赖于粗网格。二,使用非嵌套网格使得网格层级间的信息传递变得耗费较大(这个我确实没看明白,只好直译了)。这两种方法都不允许复杂区域有很好的分辨率。在第三种方法(推荐使用)中,由最精细的网格开始求解,然后通过把细网格单元做聚合处理来生成粗网格,如图所示,聚合的过程或者由单元的几何拓扑关系给出,或者是由与邻近单元的系数满足一定的判据来给出。以下的讨论都针对第三种方法。

在这里插入图片描述

粗网格是通过聚合算法把细网格单元汇聚起来生成的。对每个粗网格层级,该算法不断进行直到细网格层级的所有单元都与粗网格层级的单元相互关联为止。在该聚合过程中,细网格点被逐一访问,若某个单元被选中为种子(seed)单元,则其周围满足设定判据的邻居单元将会与该种子单元聚合形成一个粗单元。提前需要设定好融合成一个粗单元的细单元的最大数目。如果所选的种子单元没办法生成一个粗单元,那么把它加到其邻居单元中的最小粗单元中即可。

一个高效的聚合算法是直接聚合(DA)算法,由Mavriplis提出。在DA中,聚合由种子单元开始,将其与邻近的细单元,基于它们之间的几何关联强度做聚合。该过程仅需在求解开始前执行一次就好。

4.2 限制步和粗层次系数(The Restriction Step and Coarse Level Coefficients)

先在细网格上求解,执行几次迭代后,将误差转化或者说是限制到粗网格层级上,然后在粗网格上迭代几次,再往更高层级的网格上限制和求解,如此重复,直至达到最高或者说是最粗糙的网格层级。用(k)代表不同层级,则通过求解如下的系统方程可获得该层级的解
A ( k ) e ( k ) = r ( k ) \bold A^{(k)}\bold e^{(k)}=\bold r^{(k)} A(k)e(k)=r(k)
下一个粗糙层级是(k+1),误差要限制到(k+1)层。令 G I G_I GI代表聚合成粗网格层级(k+1)上的I单元的细网格层级(k)上的i单元的集合,那么,在(k+1)层级要求解的系统是
A ( k + 1 ) e ( k + 1 ) = r ( k + 1 ) \bold A^{(k+1)}\bold e^{(k+1)}=\bold r^{(k+1)} A(k+1)e(k+1)=r(k+1)
上式右端项的残差为
r ( k + 1 ) = I k k + 1 r ( k ) \bold r^{(k+1)}=\bold I_k^{k+1}\bold r^{(k)} r(k+1)=Ikk+1r(k)
其中 I k k + 1 \bold I_k^{k+1} Ikk+1为限制算子(即,插值矩阵),其反映的是细网格到粗网格的聚合过程中残差的传递或者说转化特性。在AMG中,限制算子直接用线性形式定义,即等于细网格残差的加和
r I ( k + 1 ) = ∑ i ∈ G I r i ( k ) \bold r^{(k+1)}_I=\sum_{i\in G_I}\bold r^{(k)}_i rI(k+1)=iGIri(k)
此外,粗网格单元的系数是由细网格单元的系数相加来构造的,再回顾下离散后所得的线性方程形式
a C ϕ C + ∑ F ∼ N B ( C ) a F ϕ F = b C a_C\phi_C + \sum_{F\sim NB(C)}a_F\phi_F=b_C aCϕC+FNB(C)aFϕF=bC
对于(k)层级,写成
a i ( k ) ϕ i ( k ) + ∑ j ∼ N B ( i ) a i j ( k ) ϕ j ( k ) = b i ( k ) a_i^{(k)}\phi_i^{(k)} + \sum_{j\sim NB(i)}a_{ij}^{(k)}\phi_{j}^{(k)}=b_{i}^{(k)} ai(k)ϕi(k)+jNB(i)aij(k)ϕj(k)=bi(k)
其中 N B ( i ) NB(i) NB(i)代表单元 i i i的邻近单元。当然一开始上式是不会满足的,会有如下的残差存在
r i ( k ) = b i ( k ) − ( a i ( k ) ϕ i ( k ) + ∑ j ∼ N B ( i ) a i j ( k ) ϕ j ( k ) ) r_i^{(k)}=b_{i}^{(k)}-\left( a_i^{(k)}\phi_i^{(k)} + \sum_{j\sim NB(i)}a_{ij}^{(k)}\phi_{j}^{(k)} \right) ri(k)=bi(k)ai(k)ϕi(k)+jNB(i)aij(k)ϕj(k)
定义 ϕ I ( k + 1 ) \phi_I^{(k+1)} ϕI(k+1)代表粗网格单元 I I I的解,且是要传递到细网格上去的,那么由粗网格给予细网格的修正可以写成
ϕ i ′ ( k ) = ϕ I ( k + 1 ) − ϕ i ( k ) \phi_i'^{(k)}=\phi_I^{(k+1)}-\phi_i^{(k)} ϕi(k)=ϕI(k+1)ϕi(k)
当然我们希望修正能使得在粗网格的单元 I I I上的残差是0。将新残差用 r ~ i ( k ) \tilde r_i^{(k)} r~i(k)表示,其等于
r ~ i ( k ) = b i ( k ) − ( a i ( k ) ( ϕ i ( k ) + ϕ i ′ ( k ) ) + ∑ j ∼ N B ( i ) a i j ( k ) ( ϕ j ( k ) + ϕ j ′ ( k ) ) ) \tilde r_i^{(k)}=b_{i}^{(k)}-\left( a_i^{(k)}\left(\phi_i^{(k)}+\phi_i'^{(k)}\right) + \sum_{j\sim NB(i)}a_{ij}^{(k)}\left(\phi_j^{(k)}+\phi_j'^{(k)}\right)\right) r~i(k)=bi(k)ai(k)(ϕi(k)+ϕi(k))+jNB(i)aij(k)(ϕj(k)+ϕj(k))
等效于
r ~ i ( k ) = b i ( k ) − ( a i ( k ) ϕ i ( k ) + ∑ j ∼ N B ( i ) a i j ( k ) ϕ j ( k ) ) ⏟ r i ( k ) − ( a i ( k ) ϕ i ′ ( k ) + ∑ j ∼ N B ( i ) a i j ( k ) ϕ j ′ ( k ) ) = r i ( k ) − ( a i ( k ) ϕ i ′ ( k ) + ∑ j ∼ N B ( i ) a i j ( k ) ϕ j ′ ( k ) ) \begin{aligned} \tilde r_i^{(k)}&=\underbrace{b_{i}^{(k)}- \left(a_i^{(k)}\phi_i^{(k)}+\sum_{j\sim NB(i)}a_{ij}^{(k)}\phi_j^{(k)}\right)}_{r_i^{(k)}} - \left(a_i^{(k)}\phi_i'^{(k)}+\sum_{j\sim NB(i)}a_{ij}^{(k)}\phi_j'^{(k)}\right) \\ &=r_i^{(k)}-\left(a_i^{(k)}\phi_i'^{(k)}+\sum_{j\sim NB(i)}a_{ij}^{(k)}\phi_j'^{(k)}\right) \end{aligned} r~i(k)=ri(k) bi(k)ai(k)ϕi(k)+jNB(i)aij(k)ϕj(k)ai(k)ϕi(k)+jNB(i)aij(k)ϕj(k)=ri(k)ai(k)ϕi(k)+jNB(i)aij(k)ϕj(k)
强迫 I I I的残差加和为0,即
∑ i ∈ G I r ~ i ( k ) = 0 \sum_{i\in G_I}\tilde \bold r^{(k)}_i=0 iGIr~i(k)=0
得到
0 = ∑ i ∈ G I r ~ i ( k ) − ( ∑ i ∈ G I a i ( k ) ϕ i ′ ( k ) + ∑ i ∈ G I ∑ j ∼ N B ( i ) a i j ( k ) ϕ j ′ ( k ) ) 0=\sum_{i\in G_I}\tilde \bold r_i^{(k)}-\left(\sum_{i\in G_I}a_i^{(k)}\phi_i'^{(k)}+\sum_{i\in G_I}\sum_{j\sim NB(i)}a_{ij}^{(k)}\phi_j'^{(k)}\right) 0=iGIr~i(k)iGIai(k)ϕi(k)+iGIjNB(i)aij(k)ϕj(k)
将上式重写成粗网格形式,即,粗网格的修正方程
a I ( k + 1 ) ϕ I ′ ( k + 1 ) + ∑ J ∼ N B ( I ) a I J ( k + 1 ) ϕ J ′ ( k + 1 ) = r I ( k + 1 ) a_I^{(k+1)}\phi_I'^{(k+1)} + \sum_{J\sim NB(I)}a_{IJ}^{(k+1)}\phi_{J}'^{(k+1)}=r_{I}^{(k+1)} aI(k+1)ϕI(k+1)+JNB(I)aIJ(k+1)ϕJ(k+1)=rI(k+1)
其中 a I ( k + 1 ) a_I^{(k+1)} aI(k+1) a I J ( k + 1 ) a_{IJ}^{(k+1)} aIJ(k+1) r I ( k + 1 ) r_{I}^{(k+1)} rI(k+1)是直接从细网格系数推导出来的,即
a I ( k + 1 ) = ∑ i ∈ G I a i ( k ) + ∑ i ∈ G I ∑ j ∈ G I a i j ( k ) a I J ( k + 1 ) = ∑ i ∈ G I ∑ j ∉ G I ,   j ∈ N B ( I ) a i j ( k ) r I ( k + 1 ) = ∑ i ∈ G I r i ( k ) \begin{aligned} & a_I^{(k+1)}=\sum_{i\in G_I}a_i^{(k)} + \sum_{i\in G_I}\sum_{j\in G_I}a_{ij}^{(k)} \\ & a_{IJ}^{(k+1)}=\sum_{i\in G_I}\sum_{j\notin G_I,~ j\in NB(I)}a_{ij}^{(k)} \\ & r_{I}^{(k+1)}=\sum_{i\in G_I}r_i^{(k)} \end{aligned} aI(k+1)=iGIai(k)+iGIjGIaij(k)aIJ(k+1)=iGIj/GI, jNB(I)aij(k)rI(k+1)=iGIri(k)

在这里插入图片描述

4.3 扩展步和细网格层级修正(The Prolongation Step and Fine Grid Level Corrections)

扩展算子用于把修正从粗网格转化到细网格层级上,有许多可用的算子,其中一个如图所示,为0阶扩展算子,其在细网格上产生同样的误差值,即,粗网格单元的误差将会被其在细网格层级上该单元的子单元所继承。

在这里插入图片描述

修正是从粗网格上的系统方程获取的,然后再插值到细网格层级上的
e ( k ) = I k + 1 k e ( k + 1 ) \bold e^{(k)} = \bold I_{k+1}^{k} \bold e^{(k+1)} e(k)=Ik+1ke(k+1)
其中 I k + 1 k \bold I_{k+1}^{k} Ik+1k为从粗网格到细网格的插值矩阵,最终,细网格上的解得以修正
ϕ ( k ) ← ϕ ( k ) + e ( k ) \bold \phi^{(k)} \leftarrow \bold \phi^{(k)} + \bold e^{(k)} ϕ(k)ϕ(k)+e(k)
网格层级的层数取决于网格的多寡,即便是多层的网格系统,其流程也和图中所展示的差不太多。

4.4 遍历策略和代数多重网格循环(Traversal Strategies and Algebraic Multigrid Cycles)

遍历策略指的是在求解过程中粗网格的访问方式,也被称之为多重网格循环。通常在AMG方法中用的循环是V循环、W循环、F循环,如图

在这里插入图片描述

AMG循环中最简单的是V循环,其对每层次的网格访问一次,对于刚性特别大的系统,V循环可能无法加速求解过程。因此,需要在粗网格上做较多求解,W循环实际上是在粗网格层级上做了些小的V循环,这样一来,W循环由嵌套的粗细网格层级扫描构成,随着AMG层数的增加其复杂性也有所增加。F循环是W循环的变种,其可视为把W循环劈开一半,F循环的粗网格扫描没W循环多,但是比V循环要多,因此,其介于V和W循环之间。

感觉书中对多重网格算法的讲解不是很透彻,看完也没能理解该如何应用,如何求解具体问题,所以准备找些材料弄明白后再单独讲讲这部分内容。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值