Mercurial > hg > octave-nkf
diff scripts/linear-algebra/krylov.m @ 3225:7aae2c3636a7
[project @ 1998-12-04 23:20:12 by jwe]
author | jwe |
---|---|
date | Fri, 04 Dec 1998 23:20:26 +0000 |
parents | 440b2b28e74a |
children | 98d0ee053ba4 |
line wrap: on
line diff
--- a/scripts/linear-algebra/krylov.m +++ b/scripts/linear-algebra/krylov.m @@ -16,47 +16,63 @@ # along with Octave; see the file COPYING. If not, write to the Free # Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -function [U,H,k1] = krylov(A,v,k,eps1); +function [U,H,k1] = krylov(A,v,k,eps1,pflg); # function [U,H,k1] = krylov(A,v,k{,eps1}); # construct orthogonal basis U of Krylov subspace; - # span([v Av A^2*v ... A^(k+1)*v]); + # span([v Av A^2*v ... A^(k+1)*v]); # via householder reflections; reflections are multiplied to obtain U - # eps1: threshhold for 0 relative to norm of current column (default: 1e-12) - # method used: householder reflections to guard against loss of - # orthogonality - # + # inputs: + # A: square matrix + # v: column vector + # k: desired krylov subspace dimension (as above) + # eps1: threshhold for 0 relative to norm of current column (default: 1e-12) + # pflg: permutation flag (default 0): avoid using zero rows of + # [A,v] as householder pivots; this avoids spurious non-zero entries + # in returned orthogonal matrix U, but destroys the Householder matrix + # structure of H. # outputs: - # returned basis U is n x k+1; A*U(:,1:k) = U*H + # U: (n x k+1) orthogonal basis of Krylov subspace. A*U(:,1:k) = U*H + # H: (pflg=0): Hessenberg matrix satisfying A*U(:,1:k) = U*H + # (pflg=1): Workspace; does not satisfy above equation. # k1: dimension of span of krylov subspace (based on eps1) # if k > m-1, krylov returns the Hessenberg decompostion of A. - + # Written by A. S. Hodel 1992 # $Revision: 1.2 $ # $Log$ - if(nargin == 3) - eps1 = 1e-12; + if (nargin > 5) usage("[U,H,k1] = krylov(A,v,k{,eps1,pflg})"); + elseif(nargin < 5) pflg = 0; + elseif(nargin < 4) eps1 = 1e-12; endif + na = is_square(A); + if(!na) error("krylov: A(%dx%d) must be square",na,na); endif + [m,n] = size(v); + if(!is_vector(v)) error("krylov: v(%dx%d) must be a vector",m,n); + elseif(length(v) != na) + error("krylov: A(%dx%d), v(%dx1); mismatch",na,na,length(v)); + endif + v = vec(v); # make sure it's a column vector + if(!is_scalar(k)) + error("krylov: k(%dx%d) must be a scalar",rows(k), columns(k)); + elseif( k > m) + warning("krylov: k is too large; reducing to %d",m-1); + k = m-1; endif - if( !is_square(A) ) - error("first argument must be a square matrix") - else - [m,n] = size(v); - if(m != is_square(A)) - error("krylov: argument dimensions do not match") - elseif( !is_sample(k) ) - error("krylov: third argument must be a scalar integer") - elseif( k > m) - warning(["krylov: k is too large; reducing to ",num2str(m)]); - k = m-1; - endif - endif + # check for zero input vector + if(norm(v) == 0) U = []; H = []; k1 = 0; return endif + + # indices of legal pivot points (identifies trivial null space). + abm = max(abs([A,v]')); nzidx = find(abm != 0); zidx = find(abm == 0); - if(norm(v) == 0) - U = []; - H = []; - k1 = 0; - return + # check permutation flag + if(pflg) + # permute zero rows of [A,v] to trailing rows + permvec = [vec(nzidx); vec(zidx)]; + pmat = eye(na); pmat = pmat(permvec,:); + ipermvec = pmat'*vec(1:na); + A = A(permvec,permvec); + v = v(permvec); endif k1 = k+1; # Assume subspace basis has full rank @@ -127,4 +143,15 @@ U(i:n,i:j1) = U(i:n,i:j1)-av*hv*(hv'*U(i:n,i:j1)); endfor + # check permutation flag + if(pflg) + # permute rows of U back to original coordinates + U = U(ipermvec,:); + endif + + # check for spurious nonzero entries + if( max(max( abs(U(zidx,:)) )) > eps1 ) + warning("krylov: trivial null space corrupted; set pflg=1 or eps1>%e",eps1); + endif + endfunction