线性系统经典迭代求解器的收敛由迭代矩阵的谱半径。对于一般的线性系统,由于难以确定迭代矩阵的谱半径,因此难以确定最佳(甚至良好)的SOR参数。下面,我提供了许多其他详细信息,包括一个实际问题的示例,其中已知最佳SOR权重。ρ(G)
光谱半径和会聚
光谱半径定义为最大幅度特征值的绝对值。如果,则方法将收敛,而较小的频谱半径意味着收敛速度更快。SOR通过基于加权参数的选择来更改用于导出迭代矩阵的矩阵拆分,从而希望减小所得迭代矩阵的频谱半径,从而实现工作。ρ<1ω
矩阵分割
对于下面的讨论,我将假设要解决的系统由
Ax=b,
与形式的迭代
x(k+1)=v+Gx(k),
其中是向量,迭代次数表示为。vkx(k)
SOR采用旧迭代和高斯-赛德尔迭代的加权平均值。高斯-塞德尔方法依赖于形式的矩阵分裂
A=D+L+U
其中是的对角线,是一个下三角矩阵,包含所有元素,严格位于对角线之下,而是上三角矩阵包含所有元素,严格位于对角线上方。高斯-赛德尔迭代然后由DALARA
x(k+1)=(D+L)−1b+GG−Sx(k)
迭代矩阵为
GG−S=−(D+L)−1U.
SOR可以写成
x(k+1)=ω(D+ωL)−1b+GSORx(k)
哪里
GSOR=(D+ωL)−1((1−ω)D−ωU).
确定迭代方案的收敛速度实际上归结为确定这些迭代矩阵的谱半径。通常,除非您对矩阵的结构有特定的了解,否则这是一个难题。我知道的最佳加权系数可计算的地方很少。实际上,必须根据观察到的(假定的)运行算法的收敛动态确定。这在某些情况下有效,但在其他情况下则失败。ω
最佳SOR
在求解泊松方程的情况下出现了一个已知最佳加权系数的现实示例:
∇2u=f in Ωu=g on ∂Ω
使用具有均匀网格间距的二阶有限差分在2D平方域上将此系统离散化,得到一个对称的带状矩阵,对角线上有4个,对角线上下分别为-1,另外两个带为-1,与对角线。由于边界条件而存在一些差异,但这是基本结构。给定该矩阵,SOR系数的最佳选择由下式给出
ω=21+sin(πΔx/L)
其中是网格间距,是域大小。对于这两种方法,使用已知解决方案进行简单处理会产生以下误差与迭代次数的关系:ΔxL
如您所见,SOR在大约100次迭代中达到了机器精度,此时Gauss-Seidel差了25个数量级。如果您想使用此示例,请在下面添加我使用的MATLAB代码。
clear all
close all
%number of iterations:
niter = 150;
%number of grid points in each direction
N = 16;
% [x y] = ndgrid(linspace(0,1,N),linspace(0,1,N));
[x y] = ndgrid(linspace(-pi,pi,N),linspace(-pi,pi,N));
dx = x(2,1)-x(1,1);
L = x(N,1)-x(1,1);
%desired solution:
U = sin(x/2).*cos(y);
% Right hand side for the Poisson equation (computed from U to produce the
% desired known solution)
Ix = 2:N-1;
Iy = 2:N-1;
f = zeros(size(U));
f(Ix,Iy) = (-4*U(Ix,Iy)+U(Ix-1,Iy)+U(Ix+1,Iy)+U(Ix,Iy-1)+U(Ix,Iy+1));
figure(1)
clf
contourf(x,y,U,50,'linestyle','none')
title('True solution')
%initial guess (must match boundary conditions)
U0 = U;
U0(Ix,Iy) = rand(N-2);
%Gauss-Seidel iteration:
UGS = U0; EGS = zeros(1,niter);
for iter=1:niter
for iy=2:N-1
for ix=2:N-1
UGS(ix,iy) = -1/4*(f(ix,iy)-UGS(ix-1,iy)-UGS(ix+1,iy)-UGS(ix,iy-1)-UGS(ix,iy+1));
end
end
%error:
EGS(iter) = sum(sum((U-UGS).^2))/sum(sum(U.^2));
end
figure(2)
clf
contourf(x,y,UGS,50,'linestyle','none')
title(sprintf('Gauss-Seidel approximate solution, iteration %d', iter))
drawnow
%SOR iteration:
USOR = U0; ESOR = zeros(1,niter);
w = 2/(1+sin(pi*dx/L));
for iter=1:niter
for iy=2:N-1
for ix=2:N-1
USOR(ix,iy) = (1-w)*USOR(ix,iy)-w/4*(f(ix,iy)-USOR(ix-1,iy)-USOR(ix+1,iy)-USOR(ix,iy-1)-USOR(ix,iy+1));
end
end
%error:
ESOR(iter) = sum(sum((U-USOR).^2))/sum(sum(U.^2));
end
figure(4)
clf
contourf(x,y,USOR,50,'linestyle','none')
title(sprintf('Gauss-Seidel approximate solution, iteration %d', iter))
drawnow
figure(5)
clf
semilogy(EGS,'b')
hold on
semilogy(ESOR,'r')
title('L2 relative error')
xlabel('Iteration number')
legend('Gauss-Seidel','SOR','location','southwest')