void build_fock(arma::mat& F, arma::mat& P, arma::mat& H, arma::vec& ERI) {
  for (size_t mu = 0; mu < H.n_rows; mu++) {
    for (size_t nu = 0; nu < H.n_cols; nu++) {
      F(mu, nu) = H(mu, nu);
      for (size_t lm = 0; lm < P.n_rows; lm++) {
        for (size_t sg = 0; sg < P.n_cols; sg++) {
          F(mu, nu) += P(lm, sg) * (2*ERI(idx4(mu, nu, lm, sg)) - ERI(idx4(mu, lm, nu, sg)));
        }
      }
    }
  }
}
int main()
{

  size_t NElec = 10;
  size_t NOcc = NElec / 2;
  size_t NBasis = 26;
  size_t M = idx4(NBasis, NBasis, NBasis, NBasis);

  size_t i, j, k, l;
  double val;
  size_t mu, nu, lam, sig;

  FILE *enuc_file;
  enuc_file = fopen("h2o_dzp_enuc.dat", "r");
  double Vnn;
  fscanf(enuc_file, "%lf", &Vnn);
  fclose(enuc_file);

  printf("Nuclear repulsion energy =  %12f\n", Vnn);

  arma::mat S(NBasis, NBasis);
  arma::mat T(NBasis, NBasis);
  arma::mat V(NBasis, NBasis);
  arma::mat H(NBasis, NBasis);
  arma::mat F(NBasis, NBasis, arma::fill::zeros);
  arma::mat F_prime(NBasis, NBasis, arma::fill::zeros);
  arma::mat D(NBasis, NBasis, arma::fill::zeros);
  arma::mat D_old(NBasis, NBasis, arma::fill::zeros);
  arma::mat C(NBasis, NBasis);

  arma::vec eps_vec(NBasis);
  arma::mat C_prime(NBasis, NBasis);

  arma::vec Lam_S_vec(NBasis);
  arma::mat Lam_S_mat(NBasis, NBasis);
  arma::mat L_S(NBasis, NBasis);

  FILE *S_file, *T_file, *V_file;
  S_file = fopen("h2o_dzp_s.dat", "r");
  T_file = fopen("h2o_dzp_t.dat", "r");
  V_file = fopen("h2o_dzp_v.dat", "r");

  while (fscanf(S_file, "%d %d %lf", &i, &j, &val) != EOF)
    S(i-1, j-1) = S(j-1, i-1) = val;
  while (fscanf(T_file, "%d %d %lf", &i, &j, &val) != EOF)
    T(i-1, j-1) = T(j-1, i-1) = val;
  while (fscanf(V_file, "%d %d %lf", &i, &j, &val) != EOF)
    V(i-1, j-1) = V(j-1, i-1) = val;

  fclose(S_file);
  fclose(T_file);
  fclose(V_file);

  arma::vec ERI = arma::vec(M, arma::fill::zeros);

  FILE *ERI_file;
  ERI_file = fopen("h2o_dzp_eri.dat", "r");

  while (fscanf(ERI_file, "%d %d %d %d %lf", &i, &j, &k, &l, &val) != EOF) {
    mu = i-1; nu = j-1; lam = k-1; sig = l-1;
    ERI(idx4(mu,nu,lam,sig)) = val;
  }

  fclose(ERI_file);

  double thresh_E = 1.0e-15;
  double thresh_D = 1.0e-10;
  size_t iteration = 0;
  size_t max_iterations = 1024;
  double E_total, E_elec_old, E_elec_new, delta_E, rmsd_D;

  printf("Overlap Integrals:\n");
  print_arma_mat(S);
  printf("Kinetic-Energy Integrals:\n");
  print_arma_mat(T);
  printf("Nuclear Attraction Integrals\n");
  print_arma_mat(V);

  H = T + V;

  printf("Core Hamiltonian:\n");
  print_arma_mat(H);

  arma::eig_sym(Lam_S_vec, L_S, S);
  // What's wrong with this?
  // Lam_S_mat = Lam_S_vec * arma::eye<arma::mat>(Lam_S_vec.n_elem, Lam_S_vec.n_elem);
  Lam_S_mat = arma::diagmat(Lam_S_vec);
  arma::mat Lam_sqrt_inv = arma::sqrt(arma::inv(Lam_S_mat));
  arma::mat symm_orthog = L_S * Lam_sqrt_inv * L_S.t();
  F_prime = symm_orthog.t() * H * symm_orthog;
  arma::eig_sym(eps_vec, C_prime, F_prime);
  C = symm_orthog * C_prime;
  build_density(D, C, NOcc);

  printf("S^-1/2 Matrix:\n");
  print_arma_mat(symm_orthog);
  printf("Initial F' Matrix:\n");
  print_arma_mat(F_prime);
  printf("Initial C Matrix:\n");
  print_arma_mat(C);
  printf("Initial Density Matrix:\n");
  print_arma_mat(D);

  E_elec_new = calc_elec_energy(D, H, H);
  E_total = E_elec_new + Vnn;
  delta_E = E_total;
  printf(" Iter        E(elec)              E(tot)               Delta(E)             RMS(D)\n");
  printf("%4d %20.12f %20.12f %20.12f\n",
         iteration, E_elec_new, E_total, delta_E);
  iteration++;

  while (iteration < max_iterations) {
    build_fock(F, D, H, ERI);
    F_prime = symm_orthog.t() * F * symm_orthog;
    arma::eig_sym(eps_vec, C_prime, F_prime);
    C = symm_orthog * C_prime;
    D_old = D;
    build_density(D, C, NOcc);
    E_elec_old = E_elec_new;
    E_elec_new = calc_elec_energy(D, H, F);
    E_total = E_elec_new + Vnn;
    if (iteration == 1) {
      printf("Fock Matrix:\n");
      print_arma_mat(F);
      printf("%4d %20.12f %20.12f %20.12f\n",
             iteration, E_elec_new, E_total, delta_E);
    } else {
      printf("%4d %20.12f %20.12f %20.12f %20.12f\n",
             iteration, E_elec_new, E_total, delta_E, rmsd_D);
    }
    delta_E = E_elec_new - E_elec_old;
    rmsd_D = rmsd_density(D, D_old);
    if (delta_E < thresh_E && rmsd_D < thresh_D) {
      printf("Convergence achieved.\n");
      break;
    }
    F = F_prime;
    iteration++;
  }

  arma::mat F_MO = C.t() * F * C;

  // Save the TEIs and MO coefficients/energies to disk
  // for use in other routines.
  H.save("H.mat", arma::arma_ascii);
  ERI.save("TEI_AO.mat", arma::arma_ascii);
  C.save("C.mat", arma::arma_ascii);
  F_MO.save("F_MO.mat", arma::arma_ascii);

  return 0;

}
Beispiel #3
0
/*****************************************************************************
* First character of command id should be second char of line
* Lexer returns a full line of data, needs to be parsed if .ce
* In version 1.0, valid commands are:
* .* (comment) followed by text to '\n'
* .br (new line), nothing else allowed on line
* .im (include file) 'filename'
* .nameit (define text macro) symbol=[a-zA-Z0-9]+ (10 max) text='text string'
*     text may contain entity references, nameit references and tags
* .ce (center) no tags, but text and both entity types
* Version 2.0 only supports .*, .br, .im
*/
Lexer::Token Document::processCommand( Lexer* lexer, Tag* parent )
{
    if( lexer->cmdId() == Lexer::COMMENT )
        ;//do nothing
    else if( lexer->cmdId() == Lexer::BREAK )
        parent->appendChild( new BrCmd( this, parent, dataName(), dataLine(), dataCol() ) );
    else if( lexer->cmdId() == Lexer::CENTER ) {
        CeCmd* cecmd( new CeCmd( this, parent, dataName(), dataLine(), dataCol() ) );
        parent->appendChild( cecmd );
        return cecmd->parse( lexer );
    }
    else if( lexer->cmdId() == Lexer::IMBED ) {
        std::string env( Environment.value( "IPFCIMBED" ) );
        std::vector< std::wstring > paths;
        std::wstring cwd;   //empty string for current directory
        paths.push_back( cwd );
#ifdef __UNIX__
        std::string separators( ":;" );
        char slash( '/' );
#else
        std::string separators( ";" );
        char slash( '\\' );
#endif
        std::string::size_type idx1( 0 );
        std::string::size_type idx2( env.find_first_of( separators, idx1 ) );
        std::wstring fbuffer;
        mbtowstring( env.substr( idx1, idx2 - idx1 ), fbuffer );
        paths.push_back( fbuffer );
        while( idx2 != std::string::npos ) {
            idx1 = idx2 + 1;
            idx2 = env.find_first_of( separators, idx1 );
            fbuffer.clear();
            mbtowstring( env.substr( idx1, idx2 - idx1 ), fbuffer );
            paths.push_back( fbuffer );
        }
        for( size_t count = 0; count < paths.size(); ++count ) {
            std::wstring* fname( new std::wstring( paths[ count ] ) );
            if( !fname->empty() )
                *fname += slash;
            *fname += lexer->text();
#ifndef __UNIX__
            if( fname->size() > PATH_MAX ) {
                throw FatalError( ERR_PATH_MAX );
            }
#endif
            try {
                IpfFile* ipff( new IpfFile( fname ) );
                fname = addFileName( fname );
                pushInput( ipff );
                break;
            }
            catch( FatalError& e ) {
                delete fname;
                if( count == paths.size() - 1 )
                    throw e;
            }
            catch( FatalIOError& e ) {
                delete fname;
                if( count == paths.size() - 1 )
                    throw e;
            }
        }
    }
    else if( lexer->cmdId() == Lexer::NAMEIT ) {
        std::wstring::size_type idx1( lexer->text().find( L"symbol=" ) );
        std::wstring::size_type idx2( lexer->text().find( L' ', idx1 ) );
        std::wstring sym( lexer->text().substr( idx1 + 7, idx2 - idx1 - 7 ) );
        killQuotes( sym );
        sym.insert( sym.begin(), L'&' );
        sym += L'.';
        std::wstring::size_type idx3( lexer->text().find( L"text=" ) );
        //check for single quotes
        std::wstring::size_type idx4( lexer->text()[ idx3 + 5 ] == L'\'' ? \
            lexer->text().find( L'\'', idx3  + 6 ) : \
            lexer->text().find( L' ', idx3 + 5 ) );
        std::wstring txt( lexer->text().substr( idx3 + 5, idx4 - idx3 - 5 ) );
        killQuotes( txt );
        if( !nls->isEntity( sym ) && nameIts.find( sym ) == nameIts.end() ) //add it to the list
            nameIts.insert( std::map< std::wstring, std::wstring >::value_type( sym, txt ) );
        else
            printError( ERR3_DUPSYMBOL );
    }
    else
        printError( ERR1_CMDNOTDEF );
    return getNextToken();
}