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; }
int sscf (basis_set_t *basis, erd_t *erd_inp, double *H, double * S, double *S_sinv, int n, int n_ele, int maxit, int diis_lim, double *D_old, double *D_new, double *F) { double *int_buffer; double *tmp; double *tmp2; double *F_tt; double *F_t; double *D_t; double *delta_D; double err; int conv = 0; int iter = 0; double trace; double s; double c; double lambda; int i; int max_funcs; int max_buffer_dim; max_funcs = 2 * basis->max_momentum + 1; max_buffer_dim = max_funcs * max_funcs * max_funcs * max_funcs; int_buffer = (double *)malloc (max_buffer_dim * sizeof(double)); tmp = (double *)malloc (n * n * sizeof(double)); F_t = (double *)malloc (n * n * sizeof(double)); D_t = (double *)malloc (n * n * sizeof(double)); delta_D = (double *)malloc (n * n * sizeof(double)); tmp2 = (double *)malloc (n * n * sizeof(double)); F_tt = (double *)malloc (n * n * sizeof(double)); memset (int_buffer, 0, max_buffer_dim * sizeof(double)); memset (tmp, 0, n * n * sizeof(double)); memset (F_t, 0, n * n * sizeof(double)); memset (D_old, 0, n * n * sizeof(double)); memset (D_new, 0, n * n * sizeof(double)); memset (D_t, 0, n * n * sizeof(double)); memset (delta_D, 0, n * n * sizeof(double)); memset (tmp2, 0, n * n * sizeof(double)); memset (F_tt, 0, n * n * sizeof(double)); memcpy (F, H, n * n * sizeof(double)); memcpy (F_t, H, n * n * sizeof(double)); do { #if ODA /*1. D <- Diagonalize(F_t) */ cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, S_sinv, n, F_t, n, 0.0, tmp, n); cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, tmp, n, S_sinv, n, 0.0, F_tt, n); /*Compute D*/ compute_D (n, n_ele, F_tt, D_new); /*Transform D*/ cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, S_sinv, n, D_new, n, 0.0, tmp, n); cblas_dgemm (CblasColMajor, CblasNoTrans, CblasTrans, n, n, n, 1.0, tmp, n, S_sinv, n, 0.0, D_new, n); /*2. conv = Check (D-D') */ /*3. F = Fock (D)*/ memcpy (F, H, n * n * sizeof(double)); build_fock (basis, erd_inp, int_buffer, D_new, F); /* delta_D = D - D_t*/ memset (delta_D, 0, n * n * sizeof(double)); cblas_daxpy (n * n, -1.0, D_t, 1, delta_D, 1); cblas_daxpy (n * n, 1.0, D_new, 1, delta_D, 1); /* s = trace(F_t * delta_D) */ cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, F_t, n, delta_D, n, 0.0, tmp, n); s = compute_trace (tmp, n); /*tmp = F - F_t*/ memset (tmp, 0, n * n * sizeof(double)); cblas_daxpy (n * n, -1.0, F_t, 1, tmp, 1); cblas_daxpy (n * n, 1.0, F, 1, tmp, 1); /* c = trace (tmp * delta_D) */ cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, tmp, n, delta_D, n, 0.0, tmp2, n); c = compute_trace (tmp2, n); /* set lambda */ if (c < -s/2.0) { lambda = 1.0; } else { lambda = -s / (2.0 * c); } memcpy (D_old, D_t, n * n * sizeof (double)); memcpy (F_tt, F_t, n * n * sizeof (double)); /* D_t = (1-lambda) * D_t + lambda * D */ memset (tmp, 0, n * n * sizeof(double)); cblas_daxpy (n * n, (1.0 - lambda), D_t, 1, tmp, 1); cblas_daxpy (n * n, lambda, D_new, 1, tmp, 1); memset (D_t, 0, n * n * sizeof(double)); cblas_daxpy (n * n, 1.0, tmp, 1, D_t, 1); /* F_t = (1-lambda) * F_t + lambda * F */ memset (tmp, 0, n * n * sizeof(double)); cblas_daxpy (n * n, (1.0 - lambda), F_t, 1, tmp, 1); cblas_daxpy (n * n, lambda, F, 1, tmp, 1); memset (F_t, 0, n * n * sizeof(double)); cblas_daxpy (n * n, 1.0, tmp, 1, F_t, 1); /* print energy at each iteration */ err = fabs (calc_hf_ene (D_new, F, H, n) - calc_hf_ene (D_old, F_tt, H, n)); /* fprintf (stderr, "\n iteration ene %d: %lf", iter, calc_hf_ene(D_new, F, H, n)); */ /* fprintf (stderr, "\n iteration %d: %10.6e", iter, err); */ /* fprintf (stderr, "\n lambda %d: %lf",iter, lambda); */ fprintf (stdout, "\n %d, %lf, %10.6e", iter, calc_hf_ene(D_new, F, H, n), err); iter++; #endif #if NORM memcpy (D_old, D_new, n * n * sizeof(double)); /*Build F*/ memcpy (F, H, n * n * sizeof(double)); build_fock (basis, erd_inp, int_buffer, D_new, F); /*Transform F*/ cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, S_sinv, n, F, n, 0.0, tmp, n); cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, tmp, n, S_sinv, n, 0.0, F_t, n); /*Compute D*/ compute_D (n, n_ele, F_t, D_new); /*Transform D*/ cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, S_sinv, n, D_new, n, 0.0, tmp, n); cblas_dgemm (CblasColMajor, CblasNoTrans, CblasTrans, n, n, n, 1.0, tmp, n, S_sinv, n, 0.0, D_new, n); iter++; /*Check energy convergence*/ err = fabs (calc_hf_ene (D_new, F, H, n) - calc_hf_ene (D_old, F, H, n)); /* fprintf (stderr, "\n iteration ene %d: %lf", iter, calc_hf_ene(D_new, F, H, n)); */ /* fprintf (stderr, "\n iteration %d: %10.6e", iter, err); */ fprintf (stdout, "\n %d, %lf, %10.6e", iter, calc_hf_ene(D_new, F, H, n), err); #endif } while ((iter < maxit)); fprintf (stderr, "\n Final Energy: %lf \n", calc_hf_ene (D_new, F, H, n)); /* printmatCM ("Final D", D_new, n, n); */ /* printmatCM ("Final F", F, n, n); */ free (D_t); free (delta_D); free (tmp2); free (tmp); free (F_t); free (F_tt); free (int_buffer); return 0; }