La convergence des solveurs itératifs classiques pour les systèmes linéaires est déterminée par le rayon spectral de la matrice d'itération, .ρ ( G )Pour un système linéaire général, il est difficile de déterminer un paramètre SOR optimal (ou même bon) en raison de la difficulté à déterminer le rayon spectral de la matrice d'itération. Ci-dessous, j'ai inclus de nombreux détails supplémentaires, y compris un exemple d'un problème réel où le poids SOR optimal est connu.
Rayon spectral et convergence
Le rayon spectral est défini comme la valeur absolue de la valeur propre de plus grande amplitude. Une méthode convergera si et un rayon spectral plus petit signifie une convergence plus rapide. SOR fonctionne en modifiant le fractionnement de la matrice utilisé pour dériver la matrice d'itération en fonction du choix d'un paramètre de pondération ωρ < 1ω , ce qui, espérons-le, diminue le rayon spectral de la matrice d'itération résultante.
Fractionnement de matrice
Pour la discussion ci-dessous, je suppose que le système à résoudre est donné par
A x = b ,
avec une itération du formulaire
X( k + 1 )= v + G x( k ),
où est un vecteur et le numéro d'itération k est noté x ( k ) .vkX( k )
SOR prend une moyenne pondérée de l'ancienne itération et une itération de Gauss-Seidel. La méthode de Gauss-Seidel repose sur un découpage matriciel de la forme
A = D + L + U
où est la diagonale de A , L est une matrice triangulaire inférieure contenant tous les éléments de A strictement en dessous de la diagonale et R est une matrice triangulaire supérieure contenant tous les éléments de A strictement au-dessus de la diagonale. L'itération de Gauss-Seidel est alors donnée parréUNELUNERUNE
X( k + 1 )= ( D + L )- 1b + GG - SX( k )
et la matrice d'itération est
gG - S= - ( D + L )- 1U .
Le SOR peut alors s'écrire
X( k + 1 )= ω ( D + ω L )- 1b + GS O RX( k )
où
gS O R= ( D + ω L )- 1( ( 1 - ω ) D - ω U ) .
ω
SOR optimal
Un exemple réaliste où le coefficient de pondération optimal est connu se présente dans le contexte de la résolution d'une équation de Poisson:
∇2u = f i n Ω u = g o n ∂ Ω
La discrétisation de ce système sur un domaine carré en 2D en utilisant des différences finies de second ordre avec un espacement de grille uniforme donne une matrice à bandes symétriques avec 4 sur la diagonale, -1 immédiatement au-dessus et en dessous de la diagonale, et deux autres bandes de -1 à une certaine distance du diagonale. Il y a quelques différences en raison des conditions aux limites, mais c'est la structure de base. Étant donné cette matrice, le choix prouvablement optimal pour le coefficient SOR est donné par
ω = 21 + péché( πΔ x / L )
où Δ xL
Comme vous pouvez le voir, le SOR atteint la précision de la machine en environ 100 itérations, moment auquel Gauss-Seidel est environ 25 ordres de grandeur pire. Si vous voulez jouer avec cet exemple, j'ai inclus le code MATLAB que j'ai utilisé ci-dessous.
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')
Ce côté des choses n'est pas vraiment ma spécialité, mais je ne pense pas que ce soit un test super juste pour de nombreuses applications réalistes.
Je ne sais pas pour quelles valeurs vous utilisiez c et r , mais je soupçonne que vous travailliez avec des matrices extrêmement mal conditionnées. (Ci-dessous, un code Python montrant que ce ne sont peut-être pas les matrices les plus inversibles.)
Si vous aviez réellement besoin d'inverser des matrices aussi mal conditionnées, vous auriez a) utiliser une méthode spécialisée, et b) devrait probablement simplement trouver un nouveau champ 😉
Pour les matrices bien conditionnées de toute taille, le SOR est susceptible d'être plus rapide. Pour de vrais problèmes où la vitesse est importante, il serait rare d'utiliser SOR - du côté sophistiqué, il y a beaucoup mieux de nos jours; Du côté lent mais fiable, le SOR n'est pas le meilleur que vous puissiez faire.
la source
OK, donc pour les matrices symétriques de ce roi:
Sit s varient beaucoup et sont centrés autour de 0 ( c = 0 , r = 0,1 ) que Gauss-Seidel est plus rapide. Gauss-Seidel est également plus rapide si chaque ligne est remplie à plus de la moitié part s. Cela signifie également que le SOR est meilleur pour les matrices très grandes et très clairsemées.
(Ce n'est qu'une observation emperique, rien de rigoureux)
la source