逐次超松弛迭代法SOR

时间:2022-03-04 03:12:26
%SOR:逐次超松弛迭代法
%本函数只能求解当A为n*n的矩阵
%2010-10-21
function x=SOR(A,b,w)
    tic;
    if nargin==2
        w=1.23;%默认松弛因子w=1.23
    end
   
    if w<0
        error('MATLAB:SOR:Argument w:should be larger than 0',...
            'recomanded range is 0<w<2 .See SOR.');
    end
      
    t=size(A);%获取A的行列
    n=t(1);
    D=zeros(n,n);
    L=zeros(n,n);
    U=zeros(n,n);%初始化三个矩阵
    x1=zeros(n,1);
    x2=zeros(n,1);%初始结果矩阵
   
    %获取三个矩阵D,L,U
    for i=1:n
        for j=1:n
            if i>j
                L(i,j)=A(i,j);
            elseif i<j
                U(i,j)=A(i,j);
            else
                D(i,j)=A(i,j);
            end
        end
    end
   
    G=-inv(D/w+L)*((1-1/w)*D+U);%计算迭代矩阵
   
    %计算迭代矩阵的谱半径,即绝对值最大的特征值
    rho=max(abs(eig(G)));
    %rho就是G的谱半径
    if rho>1 %谱半径大于1,迭代不收敛……
        error('MATLAB:SOR:the Iteration Matrix may not be Astringent.See SOR.');
    end
   
     fid=fopen('SOR-Output.txt','w');%用文件保存每次迭代结果
     y=1;%y代表迭代深度
   
        while 1 %matlab中没有do-while循环,可用break跳出
       for i=1:n
          
           temp1=0;
           for j=1:i-1
               temp1=temp1+A(i,j)*x2(j)/A(i,i);
           end
          
           temp2=0;
           for j=i+1:n
               temp2=temp2+A(i,j)*x1(j)/A(i,i);
           end
          
           x2(i)=w*(b(i)/A(i,i)-temp1-temp2-(1-1/w)*x1(i));
       end
      
       fprintf(fid,'%d\t',y);
        for z=1:n          %将数据写入文件
            fprintf(fid,'%2.8f\t',x2(z));
        end
        fprintf(fid,'\r\n');%输出完一次结果,换行
      
       if norm(x2-x1)<1e-10
           break;%迭代结束
       end
   
       x1=x2; %继续下一轮迭代
       y=y+1;
    end
    x=x2;%返回计算结果
    fclose(fid);%关闭文件
    toc;