Esempio n. 1
0
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;

}
Esempio n. 2
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;
}