Beispiel #1
0
 def ccsd(cls, hfwavefunction, hamiltonian, maxiter=100, cutoff=1e-6):
     occ = hfwavefunction.occ
     Nelec = occ['alpha'] + occ['beta']
     C = hfwavefunction.coefficient
     dim = hamiltonian.dim * 2
     #Transfer Fock integral from spatial to spin basis
     fs = spinfock(hfwavefunction.eorbitals)
     #Transfer electron repulsion integral from atomic basis
     #to molecular basis
     hamiltonian.operators['electron_repulsion'].basis_transformation(C)
     #build double bar integral <ij||kl>
     spinints = hamiltonian.operators['electron_repulsion'].double_bar
     ts, td, Dai, Dabij = initialize(fs, spinints, Nelec, dim)
     ECCSD = 0
     DECC = 1.0
     Iter = 0
     log.hline()
     log('{0:2s} {1:3s} {2:4s}'.format('Iter', 'ECC', 'Delta'))
     log.hline()
     while DECC > cutoff or Iter > maxiter:  # arbitrary convergence criteria
         Iter += 1
         OLDCC = ECCSD
         Fae, Fmi, Fme, Wmnij, Wabef, Wmbej = updateintermediates(
             True, Nelec, dim, fs, spinints, ts, td)
         ts = makeT1(True, Nelec, dim, fs, spinints, ts, td, Dai, Fae, Fmi,
                     Fme)
         td = makeT2(True, Nelec, dim, fs, spinints, ts, td, Dabij, Fae,
                     Fmi, Fme, Wmnij, Wabef, Wmbej)
         ECCSD = ccsdenergy(Nelec, dim, fs, spinints, ts, td)
         DECC = abs(ECCSD - OLDCC)
         log('{0:2d} {1:3f} {2:4f}'.format(Iter, ECCSD, DECC))
     print('CC iterations converged')
     print("E(corr,CCSD) = ", ECCSD)
Beispiel #2
0
    def hf(cls,hamiltonian,occ,maxiter=100,cutoff=1e-6):
        Norb = hamiltonian.dim
        #Form the core Hamiltonian
        Hcore = hamiltonian.operators['kinetic'].value + hamiltonian.operators['nuclear_attraction'].value
        #Build the orthogonalization matrix
        X = orthogonalization_matrix(hamiltonian.operators['overlap'].value)
        #Initial guess of density matrix
        if occ['alpha']==occ['beta']:
            D = np.zeros((Norb,Norb))
        else:
            D = {'alpha':np.zeros((Norb,Norb)),'beta':np.zeros((Norb,Norb))}
        #iteration section
        Iter = 0
        RMS = 1.0
        log.hline()
        log('{0:2s} {1:3s} {2:4s} {3:5s}'.format('Iter', 'E(elec)', 'E(tot)','RMS'))
        log.hline()
        while RMS > cutoff and Iter < maxiter:
            Iter += 1
            G = G_matrix(D,hamiltonian.operators['electron_repulsion'].value,Norb)
            F = F_matrix(Hcore,G,Norb)
            eorbitals,C = C_matrix(F,X,Norb)
            OLDD = D
            
            D = D_matrix(C,Norb,occ)
            RMS = deltap(D,OLDD,Norb)

            Eelec = energy(D,Hcore,F,Norb)
            Etot = Eelec + hamiltonian.operators['nuclear_repulsion'].value
            log('{0:2d} {1:3f} {2:4f} {3:5f}'.format(Iter, Eelec, Etot, RMS))
        return HFWaveFunction(Norb,occ,C,D,F,eorbitals,Eelec,Etot)
Beispiel #3
0
    def kernel(self):
        """Kernel of the solver.

        Returns
        -------
        results : dict
            CCSD calculation results.
        """
        log.hline()
        log('CCSD Section'.format())
        log.hline()
        ham = copy.deepcopy(self.ham)
        wfn = copy.deepcopy(self.wfn)
        hf_results = self.hf_results

        occ = wfn.occ
        Nelec = occ['alpha'] + occ['beta']
        C = wfn.coefficients
        nspin = ham.nspin
        #Transfer Fock integral from spatial to spin basis
        fs = spinfock(hf_results['orbital_energies'])
        #Transfer electron repulsion integral from atomic basis
        #to molecular basis
        ham.operators['electron_repulsion'].basis_transformation(C)
        #build double bar integral <ij||kl>
        spinints = ham.operators['electron_repulsion'].double_bar
        ts, td, Dai, Dabij = initialize(fs, spinints, Nelec, nspin)
        ECCSD = 0
        DECC = 1.0
        Iter = 0
        log.hline()
        log('{0:2s} {1:3s} {2:4s}'.format('Iter', 'ECC', 'Delta'))
        log.hline()
        while DECC > self.E_conv or Iter > self.maxiter:  # arbitrary convergence criteria
            Iter += 1
            OLDCC = ECCSD
            Fae, Fmi, Fme, Wmnij, Wabef, Wmbej = updateintermediates(
                True, Nelec, nspin, fs, spinints, ts, td)
            ts = makeT1(True, Nelec, nspin, fs, spinints, ts, td, Dai, Fae,
                        Fmi, Fme)
            td = makeT2(True, Nelec, nspin, fs, spinints, ts, td, Dabij, Fae,
                        Fmi, Fme, Wmnij, Wabef, Wmbej)
            ECCSD = ccsdenergy(Nelec, nspin, fs, spinints, ts, td)
            DECC = abs(ECCSD - OLDCC)
            log('{0:2d} {1:3f} {2:4f}'.format(Iter, ECCSD, DECC))
        log.hline()
        log('CCSD Energy = {}'.format(ECCSD))
        log('Total Energy = {}'.format(hf_results['total_energy'] + ECCSD))
        log.hline()

        results = {
            "success": True,
            "CCSD_energy": ECCSD,
            "total_energy": hf_results['total_energy'] + ECCSD
        }

        return results
Beispiel #4
0
    def kernel(self):
        """Kernel of the solver.

        Returns
        -------
        results : dict
            MP2 calculation results.    
        """
        log.hline()
        log('MP2 calculation section'.format())
        log.hline()

        ham = copy.deepcopy(self.ham)
        wfn = copy.deepcopy(self.wfn)
        hf_results = self.hf_results

        nspatial = ham.nspatial
        occ = wfn.occ
        C = wfn.coefficients
        eorbitals = hf_results['orbital_energies']

        Emp2 = 0.0
        if isinstance(ham, RestrictedChemicalHamiltonian):
            ham.operators['electron_repulsion'].basis_transformation(C)
            Eri = ham.operators['electron_repulsion'].integral
            for i in range(occ['alpha']):
                for j in range(occ['alpha']):
                    for a in range(occ['alpha'], nspatial):
                        for b in range(occ['alpha'], nspatial):
                            Emp2 += Eri[i,a,j,b]*(2*Eri[i,a,j,b]-Eri[i,b,j,a])\
                            /(eorbitals[i] + eorbitals[j] -eorbitals[a] - eorbitals[b])

        log.hline()
        log('MP2 Results'.format())
        log.hline()
        log('{0:2s} {1:3f}'.format('Escf', hf_results['total_energy']))
        log('{0:2s} {1:3f}'.format('Emp2', Emp2))
        log('{0:2s} {1:3f}'.format('Etot', hf_results['total_energy'] + Emp2))
        log.hline()

        results = {
            "success": True,
            "MP2_energy": Emp2,
            "total_energy": hf_results['total_energy'] + Emp2
        }

        return results
Beispiel #5
0
    def mp2(cls,hfwavefunction,hamiltonian):
        occ = hfwavefunction.occ
        C = hfwavefunction.coefficient
        eorbitals = hfwavefunction.eorbitals
        Emp2 = 0.0
        if occ['alpha'] == occ['beta']:
            Eri = hamiltonian.operators['electron_repulsion'].basis_transformation(C)
            for i in range(occ['alpha']):
                for j in range(occ['alpha']):
                    for a in range(occ['alpha'],hamiltonian.dim):
                        for b in range(occ['alpha'],hamiltonian.dim):
                            Emp2 += Eri[i,a,j,b]*(2*Eri[i,a,j,b]-Eri[i,b,j,a])/(eorbitals[i] + eorbitals[j] -eorbitals[a] - eorbitals[b])

        elif occ['alpha'] != occ['beta']:
            for spin in C:
                Eri = hamiltonian.operators['electron_repulsion'].basis_transformation(C[spin])
                for i in range(occ[spin]):
                    for j in range(occ[spin]):
                        for a in range(occ[spin],hamiltonian.dim):
                            for b in range(occ[spin],hamiltonian.dim):
                                Emp2 += Eri[i,a,j,b]*(Eri[i,a,j,b]-0.5*Eri[i,b,j,a])/(eorbitals[spin][i] + eorbitals[spin][j] -eorbitals[spin][a] - eorbitals[spin][b])
        log.hline()
        log('{0:2s} {1:3f}'.format('Escf', hfwavefunction.Etot))
        log('{0:2s} {1:3f}'.format('Emp2', Emp2))
        log('{0:2s} {1:3f}'.format('Etot', hfwavefunction.Etot+Emp2))
        log.hline()

        return Emp2
Beispiel #6
0
    def kernel(self):
        """Kernel of the solver.

        Returns
        -------
        results : dict
            CISD calculation results.
        """
        log.hline()
        log('CISD Section'.format())
        log.hline()
        ham = copy.deepcopy(self.ham)
        wfn = copy.deepcopy(self.wfn)
        hf_results = self.hf_results

        nelec = wfn.nelec
        nspatial = wfn.nspatial

        ci_basis = copy.deepcopy(CIBasisSet(wfn, [0, 1, 2]))
        H = RestrictedCIHamiltonian(ham, wfn, ci_basis)
        ci_matrix = H.generate_matrix(ci_basis)
        e_ci, vec_ci = np.linalg.eigh(ci_matrix)
        E_ci_elec = e_ci[0]
        E_hf_elec = hf_results['electronic_energy']
        E_corr = E_ci_elec - E_hf_elec
        E_ci_tot = E_ci_elec + ham.operators['nuclear_repulsion'].integral

        #Build the ci wavefunction.
        ci_wfn = CIWaveFunction(nelec, nspatial, {}, ci_basis, vec_ci[0])

        log.hline()
        log('CISD Results')
        log.hline()
        log('CISD Correlation energy = {}'.format(E_corr))
        log('Total energy = {}'.format(E_ci_tot))
        log.hline()

        results = {"total_energy": E_ci_tot}

        return results, ci_wfn
Beispiel #7
0
    def kernel(self):
        """Kernel of the solver.

        Returns
        -------
        results : dict
            Full CI calculation results.
        """
        log.hline()
        log('Full CI Section'.format())
        log.hline()
        ham = copy.deepcopy(self.ham)
        wfn = copy.deepcopy(self.wfn)
        hf_results = self.hf_results

        occ = wfn.occ['alpha'] + wfn.occ['beta']
        vir = wfn.nspin - occ
        excitation_level = list(range(min(occ, vir) + 1))
        ci_basis = CIBasisSet(wfn, excitation_level)
        H = RestrictedCIHamiltonian(ham, wfn, ci_basis)
        ci_matrix = H.generate_matrix(ci_basis)
        e_ci, vec_ci = np.linalg.eigh(ci_matrix)
        E_ci_elec = e_ci[0]
        E_hf_elec = hf_results['electronic_energy']
        E_corr = E_ci_elec - E_hf_elec
        E_ci_tot = E_ci_elec + ham.operators['nuclear_repulsion'].integral

        log.hline()
        log('Results'.format())
        log.hline()
        log('Full CI Correlation energy = {}'.format(E_corr))
        log('Total energy = {}'.format(E_ci_tot))
        log.hline()

        results = {"total_energy": E_ci_tot}
        return results
Beispiel #8
0
    def kernel(self):
        """Kernel of the solver.

        Returns
        -------
        results : dict
            MP3 calculation results.
        """
        log.hline()
        log('MP3 Calculation Section'.format())
        log.hline()

        ham = copy.deepcopy(self.ham)
        wfn = copy.deepcopy(self.wfn)
        hf_results = self.hf_results

        nspatial = ham.nspatial
        occ = wfn.occ
        C = wfn.coefficients
        eorbitals = hf_results['orbital_energies']

        Emp2 = 0.0
        ham.operators['electron_repulsion'].basis_transformation(C)
        Eri = ham.operators['electron_repulsion'].integral
        for i in range(occ['alpha']):
            for j in range(occ['alpha']):
                for a in range(occ['alpha'], nspatial):
                    for b in range(occ['alpha'], nspatial):
                        Emp2 += Eri[i,a,j,b]*(2*Eri[i,a,j,b]-Eri[i,b,j,a])\
                        /(eorbitals[i] + eorbitals[j] -eorbitals[a] - eorbitals[b])

        Emp3 = 0.0
        Eri = ham.operators['electron_repulsion'].double_bar
        for i in range(occ['alpha']):
            for j in range(occ['alpha']):
                for k in range(occ['alpha']):
                    for l in range(occ['alpha']):
                        for a in range(occ['alpha'], nspatial):
                            for b in range(occ['alpha'], nspatial):
                                Emp3 += (1/8.0)*Eri[i,j,a,b]*Eri[k,l,i,j]*Eri[a,b,k,l]\
                                /((eorbitals[i] + eorbitals[j] -eorbitals[a] - eorbitals[b])\
                                *(eorbitals[k] + eorbitals[l] -eorbitals[a] - eorbitals[b]))
        for i in range(occ['alpha']):
            for j in range(occ['alpha']):
                for a in range(occ['alpha'], nspatial):
                    for b in range(occ['alpha'], nspatial):
                        for c in range(occ['alpha'], nspatial):
                            for d in range(occ['alpha'], nspatial):
                                Emp3 += (1/8.0)*Eri[i,j,a,b]*Eri[a,b,c,d]*Eri[c,d,i,j]\
                                /((eorbitals[i] + eorbitals[j] -eorbitals[a] - eorbitals[b])\
                                *(eorbitals[i] + eorbitals[j] -eorbitals[c] - eorbitals[d]))
        for i in range(occ['alpha']):
            for j in range(occ['alpha']):
                for k in range(occ['alpha']):
                    for a in range(occ['alpha'], nspatial):
                        for b in range(occ['alpha'], nspatial):
                            for c in range(occ['alpha'], nspatial):
                                Emp3 += Eri[i,j,a,b]*Eri[k,b,c,j]*Eri[a,c,i,k]\
                                /((eorbitals[i] + eorbitals[j] -eorbitals[a] - eorbitals[b])\
                                *(eorbitals[i] + eorbitals[k] -eorbitals[c] - eorbitals[c]))

        log.hline()
        log('MP3 Results'.format())
        log.hline()
        log('{0:2s} {1:3f}'.format('Escf', hf_results['total_energy']))
        log('{0:2s} {1:3f}'.format('Emp2', Emp2))
        log('{0:2s} {1:3f}'.format('Emp3', Emp3))
        log('{0:2s} {1:3f}'.format('Etot',
                                   hf_results['total_energy'] + Emp2 + Emp3))
        log.hline()

        results = {
            "success": True,
            "MP2_energy": Emp2,
            "MP3_energy": Emp3,
            "total_energy": hf_results['total_energy'] + Emp2 + Emp3
        }

        return results
Beispiel #9
0
    def kernel(self):
        """Kernel of the solver.

        Returns
        -------
        results : dict
            Hartree Fock calculation results.
        """
        log.hline()
        log('SCF Calculation Section'.format())
        log.hline()

        # Set defaults
        ham = self.ham
        occ = self.wfn.occ
        Norb = ham.nspatial

        maxiter = self.maxiter
        E_conv = self.E_conv
        D_conv = self.D_conv

        #Form the core Hamiltonian
        Hcore = ham.operators['kinetic'].integral + ham.operators[
            'nuclear_attraction'].integral
        #Build the orthogonalization matrix
        X = orthogonalization_matrix(ham.operators['overlap'].integral)
        #Initial guess of density matrix
        D = np.zeros((Norb, Norb))

        #iteration section
        Enuc = ham.operators['nuclear_repulsion'].integral
        RMS = 1.0
        Eold = 0.0
        log.hline()
        log('{0:2s}\t {1:3s}\t {2:4s}\t\t {3:5s}'.format(
            'Iter', 'E(elec)', 'dE', 'dRMS'))
        log.hline()
        for Iter in range(1, maxiter + 1):
            Iter += 1
            G = G_matrix(D, ham.operators['electron_repulsion'].integral, Norb)
            F = F_matrix(Hcore, G, Norb)
            Eorbs, C = C_matrix(F, X, Norb)
            OLDD = D

            D = D_matrix(C, Norb, occ)
            dRMS = deltap(D, OLDD, Norb)

            Eelec = energy(D, Hcore, F, Norb)
            log('{0:2d}\t {1:3f}\t {2:4f}\t {3:5f}'.format(
                Iter, Eelec, Eelec - Eold, dRMS))
            if (abs(Eelec - Eold) < E_conv) and (dRMS < D_conv):
                break
            Eold = Eelec
            if Iter == maxiter:
                raise Exception("Maximum number of SCF cycles exceeded.")

        log.hline()
        log('SCF Results'.format())
        log.hline()
        log('Electronic Energy = {}'.format(Eelec))
        log('Nuclear Energy = {}'.format(Enuc))
        log('Total Energy = {}'.format(Eelec + Enuc))
        log.hline()

        self.wfn.assign_coefficients(C)

        results = {
            "success": True,
            "electronic_energy": Eelec,
            "nuclear_energy": Enuc,
            "total_energy": Eelec + Enuc,
            "orbital_energies": Eorbs
        }
        return results
Beispiel #10
0
    def kernel(self):
        """Kernel of the solver.
        
        Returns
        -------
        results : dict
            Hartree Fock calculation results.
        """
        log.hline()
        log('SCF DIIS Calculation Section'.format())
        log.hline()
        # Set defaults
        ham = self.ham
        wfn = self.wfn
        maxiter = self.maxiter
        E_conv = self.E_conv
        D_conv = self.D_conv
        # Overlap Integral
        S = ham.operators['overlap'].integral

        # Get occ nbf and ndocc for closed shell molecules
        occ = wfn.occ
        nspatial = ham.nspatial
        ndocc = wfn.occ['alpha']

        # Compute required quantities for SCF
        V = ham.operators['nuclear_attraction'].integral
        T = ham.operators['kinetic'].integral
        I = ham.operators['electron_repulsion'].integral
        # Build H_core
        H = T + V

        # Orthogonalizer A = S^(-1/2)
        A = np.array(ham.operators['overlap'].integral)
        A = orthogonalization_matrix(A, type='symmetric')

        # Calculate initial core guess: [Szabo:1996] pp. 145
        Hp = A.dot(H).dot(A)  # Eqn. 3.177
        e, C2 = np.linalg.eigh(Hp)  # Solving Eqn. 1.178
        C = A.dot(C2)  # Back transform, Eqn. 3.174
        Cocc = C[:, :ndocc]

        D = D_matrix(C, nspatial, occ)
        E = 0.0
        Enuc = ham.operators['nuclear_repulsion'].integral
        Eold = 0.0

        Fock_list = []
        DIIS_error = []
        log.hline()
        log('{0:2s}\t {1:3s}\t {2:4s}\t\t {3:5s}'.format(
            'Iter', 'E(elec)', 'dE', 'dRMS'))
        log.hline()
        for Iter in range(1, maxiter + 1):

            # Build fock matrix
            J = np.einsum('pqrs,rs->pq', I, D)
            K = np.einsum('prqs,rs->pq', I, D)
            F = H + J * 2 - K

            # DIIS error build w/ HF analytic gradient ([Pulay:1969:197])
            diis_e = np.einsum('ij,jk,kl->il', F, D, S) - np.einsum(
                'ij,jk,kl->il', S, D, F)
            diis_e = A.dot(diis_e).dot(A)
            Fock_list.append(F)
            DIIS_error.append(diis_e)
            dRMS = np.mean(diis_e**2)**0.5

            # SCF energy and update: [Szabo:1996], Eqn. 3.184, pp. 150
            Eelec = np.einsum('pq,pq->', F + H, D)
            log('{0:2d}\t {1:3f}\t {2:4f}\t {3:5f}'.format(
                Iter, Eelec, Eelec - Eold, dRMS))
            if (abs(Eelec - Eold) < E_conv) and (dRMS < D_conv):
                break

            Eold = Eelec

            if Iter >= 2:

                # Limit size of DIIS vector
                diis_count = len(Fock_list)
                if diis_count > 6:
                    # Remove oldest vector
                    del Fock_list[0]
                    del DIIS_error[0]
                    diis_count -= 1

                # Build error matrix B, [Pulay:1980:393], Eqn. 6, LHS
                B = np.empty((diis_count + 1, diis_count + 1))
                B[-1, :] = -1
                B[:, -1] = -1
                B[-1, -1] = 0
                for num1, e1 in enumerate(DIIS_error):
                    for num2, e2 in enumerate(DIIS_error):
                        if num2 > num1: continue
                        val = np.einsum('ij,ij->', e1, e2)
                        B[num1, num2] = val
                        B[num2, num1] = val

                # normalize
                B[:-1, :-1] /= np.abs(B[:-1, :-1]).max()

                # Build residual vector, [Pulay:1980:393], Eqn. 6, RHS
                resid = np.zeros(diis_count + 1)
                resid[-1] = -1

                # Solve Pulay equations, [Pulay:1980:393], Eqn. 6
                ci = np.linalg.solve(B, resid)

                # Calculate new fock matrix as linear
                # combination of previous fock matrices
                F = np.zeros_like(F)
                for num, c in enumerate(ci[:-1]):
                    F += c * Fock_list[num]

            # Diagonalize Fock matrix
            Fp = A.dot(F).dot(A)
            Eorbs, C2 = np.linalg.eigh(Fp)
            C = A.dot(C2)
            Cocc = C[:, :ndocc]
            D = np.einsum('pi,qi->pq', Cocc, Cocc)
            if Iter == maxiter:
                raise Exception("Maximum number of SCF cycles exceeded.")

        log.hline()
        log('SCF Results'.format())
        log.hline()
        log('Electronic Energy = {}'.format(Eelec))
        log('Nuclear Energy = {}'.format(Enuc))
        log('Total Energy = {}'.format(Eelec + Enuc))
        log.hline()

        self.wfn.assign_coefficients(C)

        results = {
            "success": True,
            "electronic_energy": Eelec,
            "nuclear_energy": Enuc,
            "total_energy": Eelec + Enuc,
            "orbital_energies": Eorbs
        }
        return results