src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp
// compute exponential of a real, antisymmetric matrix by diagonalizing and exponentiating eigenvalues
compute exponential of a real, antisymmetric matrix by diagonalizing and exponentiating eigenvalues
compute exponential of a real antisymmetric matrix by diagonalizing and exponentiating eigenvalues
void LCAOrbitalSet::exponentiate_antisym_matrix(ValueMatrix_t& mat)
{
  const int n = mat.rows();
  std::vector<std::complex<RealType>> mat_h(n * n, 0);
  std::vector<RealType> eval(n, 0);
  std::vector<std::complex<RealType>> work(2 * n, 0);
  std::vector<RealType> rwork(3 * n, 0);
  std::vector<std::complex<RealType>> mat_d(n * n, 0);
  std::vector<std::complex<RealType>> mat_t(n * n, 0);
  for (int i = 0; i < n; ++i)
  {
    for (int j = i; j < n; ++j)
    {
      mat_h[i + n * j] = std::complex<RealType>(0, -1.0 * mat[j][i]);
      mat_h[j + n * i] = std::complex<RealType>(0, 1.0 * mat[j][i]);
    }
  }
  char JOBZ('V');
  char UPLO('U');
  int N(n);
  int LDA(n);
  int LWORK(2 * n);
  int info = 0;
  LAPACK::heev(JOBZ, UPLO, N, &mat_h.at(0), LDA, &eval.at(0), &work.at(0), LWORK, &rwork.at(0), info);
  if (info != 0)
  {
    std::ostringstream msg;
    msg << "heev failed with info = " << info << " in MultiSlaterDeterminantFast::exponentiate_antisym_matrix";
    app_log() << msg.str() << std::endl;
    APP_ABORT(msg.str());
  }
  for (int i = 0; i < n; ++i)
  {
    for (int j = 0; j < n; ++j)
    {
      mat_d[i + j * n] = (i == j) ? std::exp(std::complex<RealType>(0.0, eval[i])) : std::complex<RealType>(0.0, 0.0);
    }
  }
  BLAS::gemm('N', 'C', n, n, n, std::complex<RealType>(1.0, 0), &mat_d.at(0), n, &mat_h.at(0), n,
             std::complex<RealType>(0.0, 0.0), &mat_t.at(0), n);
  BLAS::gemm('N', 'N', n, n, n, std::complex<RealType>(1.0, 0), &mat_h.at(0), n, &mat_t.at(0), n,
             std::complex<RealType>(0.0, 0.0), &mat_d.at(0), n);
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j)
    {
      if (mat_d[i + n * j].imag() > 1e-12)
      {
        app_log() << "warning: large imaginary value in orbital rotation matrix: (i,j) = (" << i << "," << j
                  << "), im = " << mat_d[i + n * j].imag() << std::endl;
      }
      mat[j][i] = mat_d[i + n * j].real();
    }
}
void LCAOrbitalSet :: exponentiate_antisym_matrix ( ValueMatrix_t & mat ) { const int n = mat . rows ( ) ; std :: vector < std :: complex < RealType > > mat_h ( n * n , 0 ) ; std :: vector < RealType > eval ( n , 0 ) ; std :: vector < std :: complex < RealType > > work ( 2 * n , 0 ) ; std :: vector < RealType > rwork ( 3 * n , 0 ) ; std :: vector < std :: complex < RealType > > mat_d ( n * n , 0 ) ; std :: vector < std :: complex < RealType > > mat_t ( n * n , 0 ) ; for ( int i = 0 ; i < n ; ++ i ) { for ( int j = i ; j < n ; ++ j ) { mat_h [ i + n * j ] = std :: complex < RealType > ( 0 , -1.0 * mat [ j ] [ i ] ) ; mat_h [ j + n * i ] = std :: complex < RealType > ( 0 , 1.0 * mat [ j ] [ i ] ) ; } } char JOBZ ( ' ' ) ; char UPLO ( ' ' ) ; int N ( n ) ; int LDA ( n ) ; int LWORK ( 2 * n ) ; int info = 0 ; LAPACK :: heev ( JOBZ , UPLO , N , & mat_h . at ( 0 ) , LDA , & eval . at ( 0 ) , & work . at ( 0 ) , LWORK , & rwork . at ( 0 ) , info ) ; if ( info != 0 ) { std :: ostringstream msg ; msg << " " << info << " " ; app_log ( ) << msg . str ( ) << std :: endl ; APP_ABORT ( msg . str ( ) ) ; } for ( int i = 0 ; i < n ; ++ i ) { for ( int j = 0 ; j < n ; ++ j ) { mat_d [ i + j * n ] = ( i == j ) ? std :: exp ( std :: complex < RealType > ( 0.0 , eval [ i ] ) ) : std :: complex < RealType > ( 0.0 , 0.0 ) ; } } BLAS :: gemm ( ' ' , ' ' , n , n , n , std :: complex < RealType > ( 1.0 , 0 ) , & mat_d . at ( 0 ) , n , & mat_h . at ( 0 ) , n , std :: complex < RealType > ( 0.0 , 0.0 ) , & mat_t . at ( 0 ) , n ) ; BLAS :: gemm ( ' ' , ' ' , n , n , n , std :: complex < RealType > ( 1.0 , 0 ) , & mat_h . at ( 0 ) , n , & mat_t . at ( 0 ) , n , std :: complex < RealType > ( 0.0 , 0.0 ) , & mat_d . at ( 0 ) , n ) ; for ( int i = 0 ; i < n ; ++ i ) for ( int j = 0 ; j < n ; ++ j ) { if ( mat_d [ i + n * j ] . imag ( ) > 1e-12 ) { app_log ( ) << " " << i << " " << j << " " << mat_d [ i + n * j ] . imag ( ) << std :: endl ; } mat [ j ] [ i ] = mat_d [ i + n * j ] . real ( ) ; } }
compute exponential of a real, antisymmetric matrix by diagonalizing and exponentiating eigenvalues
compute exponential of a real antisymmetric matrix by diagonalizing and exponentiating eigenvalues
// exponentiating e^X = e^iY (Y hermitian) // i(-iX) = X, so -iX is hermitian // diagonalize -iX = UDU^T, exponentiate e^iD, and return U e^iD U^T // construct hermitian analogue of mat by multiplying by -i // diagonalize the matrix // iterate through diagonal matrix, exponentiate terms // perform matrix multiplication // assume row major