home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21eb.zip / octave / SCRIPTS.ZIP / scripts.fat / la / krylov.m < prev    next >
Text File  |  1999-04-29  |  5KB  |  163 lines

  1. # Copyright (C) 1996,1998 A. Scottedward Hodel 
  2. #
  3. # This file is part of Octave. 
  4. #
  5. # Octave is free software; you can redistribute it and/or modify it 
  6. # under the terms of the GNU General Public License as published by the 
  7. # Free Software Foundation; either version 2, or (at your option) any 
  8. # later version. 
  9. # Octave is distributed in the hope that it will be useful, but WITHOUT 
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  11. # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
  12. # for more details.
  13. # You should have received a copy of the GNU General Public License 
  14. # along with Octave; see the file COPYING.  If not, write to the Free 
  15. # Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  16.  
  17. function [U,H,k1] = krylov(A,v,k,eps1,pflg);
  18.   # function [U,H,k1] = krylov(A,v,k{,eps1});
  19.   # construct orthogonal basis U of Krylov subspace;
  20.   #     span([v Av A^2*v ... A^(k+1)*v]);
  21.   # via householder reflections; reflections are multiplied to obtain U
  22.   # inputs:
  23.   #   A: square matrix
  24.   #   v: column vector
  25.   #   k: desired krylov subspace dimension (as above)
  26.   #   eps1: threshhold for 0 relative to norm of current column (default: 1e-12)
  27.   #   pflg: permutation flag (default 0): avoid using zero rows of
  28.   #      [A,v] as householder pivots; this avoids spurious non-zero entries
  29.   #      in returned orthogonal matrix U, but destroys the Householder matrix
  30.   #      structure of H.
  31.   # outputs:
  32.   #   U: (n x k+1) orthogonal basis of Krylov subspace. A*U(:,1:k) = U*H
  33.   #   H: (pflg=0): Hessenberg matrix satisfying A*U(:,1:k) = U*H
  34.   #      (pflg=1): Workspace; does not satisfy above equation.
  35.   # k1: dimension of span of krylov subspace (based on eps1)
  36.   # if k > m-1, krylov returns the Hessenberg decompostion of A.
  37.  
  38.   # Written by A. S. Hodel 1992
  39.   # $Revision: 1.2 $
  40.   # $Log$
  41.  
  42.   save_empty_list_elements_ok = empty_list_elements_ok;
  43.   empty_list_elements_ok = 1;
  44.  
  45.   if    (nargin > 5)   usage("[U,H,k1] = krylov(A,v,k{,eps1,pflg})");
  46.   elseif(nargin < 5)   pflg = 0;
  47.   elseif(nargin < 4)   eps1 = 1e-12; endif
  48.   na = is_sqr(A);
  49.   if(!na) error("krylov: A(%dx%d) must be square",na,na); endif
  50.   [m,n] = size(v);
  51.   if(!is_vec(v)) error("krylov: v(%dx%d) must be a vector",m,n);
  52.   elseif(length(v) != na)
  53.     error("krylov: A(%dx%d), v(%dx1); mismatch",na,na,length(v));
  54.   endif
  55.   v = vec(v);    # make sure it's a column vector
  56.   if(!is_scal(k))
  57.     error("krylov: k(%dx%d) must be a scalar",rows(k), columns(k));
  58.   elseif( k > m)
  59.     warning("krylov: k is too large; reducing to %d",m-1);
  60.     k = m-1;
  61.   endif
  62.  
  63.   # check for zero input vector
  64.   if(norm(v) == 0) U = []; H = []; k1 = 0; return endif
  65.  
  66.   # indices of legal pivot points (identifies trivial null space).
  67.   abm = max(abs([A,v]')); nzidx = find(abm != 0); zidx = find(abm == 0);
  68.  
  69.   # check permutation flag
  70.   if(pflg)
  71.     # permute zero rows of [A,v] to trailing rows
  72.     permvec = [vec(nzidx); vec(zidx)];
  73.     pmat = eye(na); pmat = pmat(permvec,:);
  74.     ipermvec = pmat'*vec(1:na);
  75.     A = A(permvec,permvec);
  76.     v = v(permvec);
  77.   endif
  78.  
  79.   k1 = k+1;        # Assume subspace basis has full rank
  80.   [m,n] = size(A);
  81.   [hv,alpha(1),z] = housh(v,1,0);
  82.  
  83.   # initial orthogonal vector
  84.   q = zeros(n,1);
  85.   q(1) = 1;
  86.   q = q - alpha*hv*hv'*q;
  87.   normq = norm(q);
  88.   normres = normq;
  89.  
  90.   U(:,1) = hv;
  91.   j = 1;
  92.   while(j <= k & normres > eps1*normq)
  93.     # multiply to get new vector;
  94.     q = A*q;
  95.     normq = norm(q);
  96.  
  97.     # multiply by householder reflections to obtain projected vector and the
  98.     # next column of H
  99.     for i=1:j
  100.      hv = U(i:n,i);
  101.      av = alpha(i);
  102.      q(i:n,1) = q(i:n,1)-av*hv*(hv'*q(i:n,1));
  103.     endfor
  104.  
  105.     i = j+1;
  106.     # compute and apply next householder vector;
  107.     if(i <= n)
  108.       [hv,av,z] = housh(q(i:n,1),1,0);
  109.       alpha(i) = av;
  110.       q(i:n,1) = q(i:n,1)-av*hv*(hv'*q(i:n,1));
  111.       U(i:n,i) = hv;
  112.       H(1:i,j) = q(1:i);
  113.     else
  114.       av = 0;
  115.       H(:,j) = q;    # complete Hessenberg decomposition
  116.     endif
  117.  
  118.     # see if done yet
  119.     normres = norm(q(i:n));
  120.     if(normres > eps1*normq)
  121.       j = j+1;
  122.     else   
  123.       k1 = min(k1,j);    # time to quit; norm of residual is small
  124.     endif
  125.   
  126.     # back out new q vector for next pass;
  127.     j1 = columns(U);
  128.     q = zeros(n,1);
  129.     q(j1) = 1;
  130.     for i=j1:-1:1;
  131.       hv = U(i:n,i);
  132.       av = alpha(i);
  133.       q(i:n,1) = q(i:n,1)-av*hv*(hv'*q(i:n,1));
  134.     endfor
  135.   endwhile
  136.  
  137.   # back out U matrix ;
  138.   j1 = columns(U);
  139.   for i=j1:-1:1;
  140.    hv = U(i:n,i);
  141.    av = alpha(i);
  142.    U(:,i) = zeros(n,1);
  143.    U(i,i) = 1;
  144.    U(i:n,i:j1) = U(i:n,i:j1)-av*hv*(hv'*U(i:n,i:j1));
  145.   endfor
  146.  
  147.   # check permutation flag
  148.   if(pflg)
  149.     # permute rows of U back to original coordinates
  150.     U = U(ipermvec,:);
  151.   endif
  152.  
  153.   # check for spurious nonzero entries
  154.   if( max(max( abs(U(zidx,:)) )) > eps1 )
  155.     warning("krylov: trivial null space corrupted; set pflg=1 or eps1>%e",eps1);
  156.   endif
  157.  
  158.   empty_list_elements_ok = save_empty_list_elements_ok;
  159.  
  160. endfunction
  161.