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; }
/***************************************************************************** * 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(); }