線形システムの従来の反復ソルバーの収束は、反復行列のスペクトル半径によって決定されます。一般的な線形システムでは、反復行列のスペクトル半径を決定するのが難しいため、最適な(または良い)SORパラメーターを決定することは困難です。以下に、最適なSOR重みがわかっている実際の問題の例を含む、多くの詳細を追加しました。ρ(G)
スペクトル半径と収束
スペクトル半径は、最大振幅固有値の絶対値として定義されます。で、スペクトル半径が小さいほど収束が速い場合、メソッドは収束します。SORは、重み付けパラメーター選択に基づいて反復行列を導出するために使用される行列分割を変更することで機能し、できれば結果の反復行列のスペクトル半径を小さくします。ωρ<1ω
マトリックス分割
以下の議論では、解くシステムは
Ax=b,
フォームの反復あり
x(k+1)=v+Gx(k),
ここで、はベクトルであり、反復番号はます。k x (k )vkx(k)
SORは、古い反復とGauss-Seidel反復の加重平均を取ります。ガウスザイデル法は、フォームの行列分割に依存しています
A=D+L+U
ここで、は対角、は対角の真下にあるすべての要素を含む下三角行列、は上三角行列です対角線の真上にあるすべての要素を含みます。ガウスザイデルの反復は、A L A R ADALARA
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
最適な重み係数がわかっている現実的な例の1つは、ポアソン方程式を解くコンテキストで発生します。
∇2u=f in Ωu=g on ∂Ω
均一なグリッド間隔の2次有限差分を使用して、2Dの正方形領域でこのシステムを離散化すると、対角線上に4、対角線の真上と真下に-1、および-1から少し離れた2つのバンドをもつ対称バンドマトリックスが生成されます。対角線。境界条件による違いはありますが、それが基本的な構造です。この行列が与えられた場合、SOR係数の証明可能な最適な選択は、
ω=21+sin(πΔx/L)
ここで、はグリッド間隔、はドメインサイズです。既知のソリューションを使用した単純なケースでこれを行うと、これらの2つの方法について次のエラーと反復数が得られます。Δの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')