#ifndef BFM_DEFLATE_H #define BFM_DEFLATE_H /********************************************** * * TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * This is a massive lag point. Figure out how to make it * exponentially faster or don't do it. * ************************************************/ #include "Matrix.h" #include "Francis.h" #include #include #include #include #include #include #include #include #include namespace BFM_Krylov{ /** Return smallest number number such that 1 + epsilon > 1. stolen from Tony Kennedy*/ static double findUlp() { double epsilon = 1., ope; do { epsilon *= 1./2.; ope = 1. + epsilon; } while (ope > 1.); return 2. * epsilon; } /** Unit of least precision (ULP), smallest number such that 1 + ulp > 1*/ const double ulp = findUlp(); /** Tolerance for floating point computations*/ const double eps = ulp * (double) 3.; /**Deflation functions live here. Locking and (one day) purging**/ template class Deflate{ public: /** There is some matrix Q such that for any vector y Q.e_1 = y and Q is unitary. **/ static T orthQ(Matrix &Q, std::vector y){ int N = y.size(); //Matrix Size Q.Fill(0.0); T tau; for(int i=0;i 0.0){ T gam = conj( (y[j]/tau)/tau0 ); for(int k=0;k<=j-1;k++){ Q(-gam*y[k],k,j); } Q(tau0/tau,j,j); } else{ Q(1.0,j-1,j); } tau0 = tau; } return tau; } /** There is some matrix Q such that for any vector y Q.e_1 = y and Q is unitary. **/ static double orthQM(Matrix &Q, Matrix &H, std::vector y){ int N = y.size(); //Matrix Size Q.Fill(0.0); T tau; int ii=0; while(real(y[ii]) == 0 && ii < N){y[ii] = eps/(double)N; ii++;} T sig = conj(y[0])*y[0]; T tau0 = abs(y[0]); for(int j=1;j 0.0){ T gam = -1.0*conj( ( y[j]/tau)/tau0 ); T rho = tau0/tau; for(int k=0;k<=j-1;k++){ Q(gam*y[k],k,j); } Q(rho,j,j); if(j < (N-1) && abs(tau) < 0.05){ T taup = sqrt(sig + conj(y[j+1])*y[j+1]); T alpha = 0.0; std::vector tmp(j+1); for(int k=0;k Hj(j+1); Hj = H.GetSubMtx(0, j+1, 0, j+1); std::vector tmp2(j+1); tmp2 = Hj*tmp; for(int k=0;k eps*abs(taup) ){ if(abs(rho) < sqrt(eps)/100.0){ T qjj = Q(j,j); Q(qjj*sig0*(eps*taup + abs(alpha))/abs(delta),j,j); } else{ if(abs(alpha) > abs(delta)){ T phi = sig0*(eps*taup + abs(delta))/abs(alpha); for(int k=0;k &y){ T front = y[0]; for(int i=0;i &H){ int N = H.dim; for(int r=0;r &Q, std::vector y){ T tau = orthQ(Q,y); SL(Q); return tau; } /** Wind up with a matrix with the first con rows untouched say con = 2 Q is such that Qdag H Q has {x, x, val, 0, 0, 0, 0, ...} as 1st colum and the matrix is upper hessenberg and with f and Q appropriately modidied with Q is the arnoldi factorization **/ #if 1 static void Lock(Matrix &H, ///Hess mtx Matrix &Q, ///Lock Transform T val, ///value to be locked int con, ///number already locked double small, int dfg, bool herm){ //ForceTridiagonal(H); int M = H.dim; std::vector vec(M-con); Matrix AH(M-con); AH = H.GetSubMtx(con, M, con, M); Matrix QQ(M-con); Q.Unity(); QQ.Unity(); std::vector evals(M-con); std::vector > evecs(M-con); if(herm){Wilkinson(AH, evals, evecs, small);} else{QReigensystem(AH, evals, evecs, small);} int k=0; double cold = abs( val - evals[k]); for(int i=1;i tau; orthQ(QQ,vec); //orthQM(QQ,AH,vec); AH = QQ.Hermitian()*AH; AH = AH*QQ; for(int i=con;icon+2; j--){ Matrix U(j-1-con); std::vector z(j-1-con); T nm = norm(z); for(int k = con+0;k > Hb(j-1-con); for(int k=con+1;k > Qb(j-1-con); for(int k=con+1;k > Hc(M); for(int k=0;k &H, ///Hess mtx Matrix &Q, ///Lock Transform T val, ///value to be locked int con, ///number already locked double small, int dfg, bool herm){ using namespace std; int M = H.dim; vector vec(M-con); Matrix AH(M-con); for(int i=0;i evals(M-con); vector > evecs(M-con); if(herm){Wilkinson(AH, evals, evecs, small);} else{Eigensystem(AH, evals, evecs, small);} int k=0; double cold = abs( val - evals[k]); for(int i=1;i QQ(M-con); Q.Unity(); QQ.Unity(); complex tau = orthQ(QQ,vec); for(int i=con;icon+2; j--){ Matrix U(j-1-con); vector z(j-1-con); for(int k = con+0;k > Hb(j-1-con); for(int k=con+1;k > Qb(j-1-con); for(int k=con+1;k > Hc(M); for(int k=0;k