#!../src/tops -i -s ../sys  -u ../usr
/*
Program Tops - a stack-based computing environment
Copyright (C) 1999-2006  Dale R. Williamson

Author: Dale R. Williamson <dale.williamson@prodigy.net>

File test/cmplx_chk June 2006
Check the left and right eigenvectors of a complex modal model
*/

#-----------------------------------------------------------------------

# Making a complex modal model:
   N = 200;

   seedset((R=seedget()), seed0);
   A = random(N, N);
   seedset(R);

   size = intstr(rows(A)) + "-by-" + intstr(cols(A));
   dot(" Computing complex modes of unsymmetric matrix A, " 
      + size + " ...");

   (Wr, Wi, Lr, Li, Rr, Ri) = dgeev2(A);

   VR = complex(Rr, Ri); # right hand eigenvectors
   VL = complex(Lr, Li); # left hand eigenvectors

   W  = complex(Wr, Wi); # eigenvalues, W

   Wr = Wi = Lr = Li = Rr = Ri = purged;

   nl(dot(" done"));

# Normalizing VL and VR so conj(VL)' * A * VR = W:

   dot(" Normalizing left and right eigenvectors ...");

   fac = (W ./ mpydg(conj(VL)', A * VR)).^0.5;

   PSI = VR *\ fac;          # right eigenvectors, PSI
   GAM = (conj(VL) *\ fac)'; # left eigenvectors, GAM

   (VR, VL, fac) = (purged, dup, dup);

   nl(dot(" done"));

# Checking normalized eigenvectors.
   nl(dot(" Checking the normalized left and right eigenvectors, "
      + "GAM and PSI:"));

# Check 1.  Inverse:
   (E1, r, c) = maxfetch(abs(GAM * PSI - identity(rows(GAM))));
   dot("   Inverse check, GAM * PSI - Identity:"); dot(E1); nl();
      
# Check 2.  Inverse:
   (E2, r, c) = maxfetch(abs(PSI * GAM - identity(rows(GAM))));
   dot("   Inverse check, PSI * GAM - Identity:"); dot(E2); nl();

# Check 3.  Self orthogonality of PSI with A and W:
   (E3, r, c) = maxfetch(abs(A * PSI - PSI *\ W));
   dot("   Self ortho of PSI against A and eigenvalues W:"); 
   dot(E3); nl();
      
# Check 4.  Self orthogonality of GAM with A and W:
   (E4, r, c) = maxfetch(abs(GAM * A - W \* GAM));
   dot("   Self ortho of GAM against A and W:"); dot(E4); nl();
      
# Check 5.  Cross orthogonality of PSI and GAM with A and W:
   (E5, r, c) = maxfetch(abs(GAM * A * PSI - sq(W)));
   dot("   Cross ortho of PSI and GAM against A and W:"); dot(E5); nl();

#-----------------------------------------------------------------------

   eps = 1E-8;

   if(E1>eps || E2>eps || E3>eps || E4>eps || E5>eps) 
      nl(dot(" Errors in eigenvector check"));
   else 
      nl(dot(" Eigenvector check ok"));

   << 2 idle "*" 72 cats . nl
