123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- function [x,tnorm,flag]=CMRH(A,b,tol,maxiter,x0,iprint)
- %
- % function [x,tnorm,flag] = (A,b,tol,maxiter,x0,iprint)
- %
- % This function solves the linear system Ax=b using the CMRH method
- %
- % Input :
- % A : the n times n matrix
- % b : the right hand side vector
- % tol : the stopping criterion
- % maxiter : the maximum number of iterations
- % x0 : the initial approximation
- % iprint : iprint = 1 to print some components of the
- % approximated solution and the norm of the residual
- % in the Matlab Command Window.
- % : iprint = 0 if we do not want to print the components
- % and the norm of the residuals in the matlab Command
- % Window.
- %
- % Output :
- % x : the solution
- % tnorm : the pseudo residual norm array
- % flag : the stopping criterion uses
- % if flag = 0 : we use tol
- % if flag = 1 : we use maxiter
- %
- n=length(A(:,1));
- if (nargin < 5)
- x = x0;
- else
- x = zeros(n,1);
- end
- if (nargin < 4)
- maxiter = n;
- end
- if (nargin < 3)
- tol = 1.d-7;
- end
- rs = zeros(n,1); s = zeros(n,1); c = zeros(n,1);
- p = 1:n; b = b-A*x;
- [~,indice] = max(abs(b(1:n)));
- beta = b(indice); D_inv = 1/beta; rs(1) = beta;
- dnorm = abs(beta); tnorm = dnorm;
- if ((indice < 1)||(indice > 1))
- temp = p(1); p(1) = p(indice); p(indice) = temp;
- temp = b(1); b(1) = b(indice); b(indice) = temp;
- Ai = A(:,indice);
- A(:,indice) = A(:,1); A(:,1) = Ai;
- Aip = A(indice,:); A(indice,:)=A(1,:); A(1,:) = Aip;
- end
- b = D_inv.*b;
- k = 0;
- while((dnorm > tol)&&(k < maxiter))
- k = k+1;
- n_k = n-k;
- k1 = k+1;
- if (iprint==1)
- fprintf(' %3.0f %6.4e \n',k-1,dnorm);
- end
- work = A(:,k);
- work = A(:,k1:n)*b(k1:n)+work;
- A(k1:n,k) = b(k1:n);
- for j = 1:k
- A(j,k) = work(j);
- work(j) = 0.d0;
- j1 = j+1;
- work(j1:n) = -A(j,k).*A(j1:n,j)+work(j1:n);
- end
- if (k < n)
- [~,indice] = max(abs(work(k1:n)));
- indice = k+indice;
- H_k1 = work(indice);
- if ((indice < k1)||(indice > k1))
- temp = p(k1); p(k1) = p(indice); p(indice) = temp;
- temp = work(k1); work(k1) = work(indice); work(indice) = temp;
- Ai = A(:,indice); A(:,indice) = A(:,k1);
- A(:,k1) = Ai; Aip = A(indice,:); A(indice,:) = A(k1,:);
- A(k1,:) = Aip;
- end
- if ((H_k1 < 0)||(H_k1 > 0))
- D_inv = 1/H_k1; b = work; b = D_inv.*b;
- end
- else
- H_k1 = 0;
- b = zeros(n,1);
- end
-
- % solving the least squares problem
- if (k > 1)
- for i = 2:k
- i_1 = i-1;
- dtemp = A(i_1,k);
- A(i_1,k) = c(i_1)*dtemp+s(i_1)*A(i,k);
- A(i,k) = -s(i_1)*dtemp+c(i_1)*A(i,k);
- end
- end
- if (k <= n)
- dgam = sqrt(A(k,k)^2+H_k1^2);
- c(k) = abs(A(k,k))/dgam;
- s(k) = (H_k1*abs(A(k,k)))/(A(k,k)*dgam);
- rs(k1) = -s(k)*rs(k);
- rs(k) = c(k)*rs(k);
- A(k,k) = c(k)*A(k,k)+s(k)*H_k1;
- dnorm = abs(rs(k1));
- end
- tnorm = [tnorm dnorm];
- end
- if (k==maxiter)
- flag=1;
- else
- flag=0;
- end
- if (iprint==1)
- fprintf(' %3.0f %6.4e \n',k,dnorm);
- end
- % computing d the solution of the least square problem
- for j = k:-1:1
- rs(j) = rs(j)/A(j,j);
- rs(1:j-1) = rs(1:j-1)-rs(j).*A(1:j-1,j);
- end
- work(1:k) = rs(1:k);
- for j = k:-1:1
- rs(j+1:k) = rs(j+1:k)+rs(j).*A(j+1:k,j);
- end
- c = A(k1:n,1:k)*work(1:k);
- x(1:k) = rs(1:k)+x(1:k);
- x(k1:n) = c(1:n_k)+x(k1:n);
- % Reorder the components of x to get the solution
- xx(p(1:n)) = x(1:n);
- x = xx';
|