def compute_CCD(Settings, silent=False, compare=True): t0 = time.time() printif = print if not silent else lambda *k, **w: None Escf, Ca, Cb, epsa, epsb, _, g, Vnuc = compute_uhf(Settings, return_C=True, return_integrals=True, silent=silent) printif(""" ======================================================= Spin-Orbital Coupled Cluster Doubles {} ======================================================= """.format('\U0001F9D9')) tsave = [] show_progress(tsave, printif) t = time.time() # Create Spin-Orbital arrays C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]]) eps = np.concatenate((epsa, epsb)) g = np.kron(np.eye(2), g) g = np.kron(np.eye(2), g.T) # re-Sorting orbitals s = np.argsort(eps) eps = eps[s] C = C[:, s] tsave.append(time.time() - t) show_progress(tsave, printif) t = time.time() # Get the MO integral nelec = Settings['nalpha'] + Settings['nbeta'] # Converto to Physicists notation g = g.transpose(0, 2, 1, 3) # Antisymmetrize g = g - g.transpose(0, 1, 3, 2) # Save Slices ERI = lambda a, b, c, d: np.einsum('ap,bq,cr,ds,abcd->pqrs', C[:, a], C[:, b], C[:, c], C[:, d], g, optimize='optimal') o = slice(0, nelec) v = slice(nelec, len(g)) Voovv = ERI(o, o, v, v) Voooo = ERI(o, o, o, o) Vvvvv = ERI(v, v, v, v) Vvoov = ERI(v, o, o, v) g = None tsave.append(time.time() - t) show_progress(tsave, printif) t = time.time() # Get eigenvalues Matrix D new = np.newaxis eo = eps[:nelec] ev = eps[nelec:] D = 1.0 / (eo[:, new, new, new] + eo[new, :, new, new] - ev[new, new, :, new] - ev[new, new, new, :]) tsave.append(time.time() - t) show_progress(tsave, printif) t = time.time() # Initial guess for amplitudes T = Voovv * D # Get MP2 energy E = CCD_Energy(T, Voovv) printif('\nMP2 Energy: {:<15.10f}\n'.format(E + Escf)) # Setup iteration options rms = 0.0 dE = 1 ite = 1 rms_LIM = 10**(-8) E_LIM = 10**(-12) t0 = time.time() printif('\U00003030' * 20) # Start CC iterations while abs(dE) > E_LIM or rms > rms_LIM: t = time.time() if ite > Settings["cc_max_iter"]: raise NameError('CCD equations did not converge') T, rms = CCD_Amplitude(T, D, Voovv, Voooo, Vvvvv, Vvoov) dE = -E E = CCD_Energy(T, Voovv) dE += E printif("Iteration {}".format(numoji(ite))) printif("\U000027B0 Correlation energy: {:< 15.10f}".format(E)) printif("\U0001F53A Energy change: {:< 15.10f}".format(dE)) printif("\U00002622 Max RMS residue: {:< 15.10f}".format(rms)) printif("\U0001F570 Time required: {:< 15.10f}".format( time.time() - t)) printif('\U00003030' * 20) ite += 1 printif('\U0001F3C1 CCD Energy: {:<15.10f}'.format(E + Escf)) printif('\U000023F3 CCD iterations took %.2f seconds.\n' % (time.time() - t0)) return (E + Escf)
from input import Settings if 'active_space' in Settings: print('TEST') from CI import compute_CI compute_CI(Settings) else: from uhf import compute_uhf compute_uhf(Settings)
def compute_SOMP2(Settings, silent=False, psi4compare=True): printif = print if not silent else lambda *k, **w: None Escf, Ca, Cb, epsa, epsb, _, g, Vnuc = compute_uhf(Settings, return_C=True, return_integrals=True, psi4compare=psi4compare, silent=silent) printif(""" =================================================== Spin-Orbital Møller-Plesset Perturbation Theory {} =================================================== """.format(emoji('wine'))) tasks = """ Building: \U0001F426 Spin-Orbital arrays {} \U0001F986 MO integral <OO|VV> {} \U0001F9A2 Eigenvalues auxiliar array Dijab {}""" printif(tasks.format('', '', '')) if not silent: sys.stdout.write("\033[F" * 5) time.sleep(0.1) # Create Spin-Orbital arrays C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]]) eps = np.concatenate((epsa, epsb)) g = np.kron(np.eye(2), g) g = np.kron(np.eye(2), g.T) # re-Sorting orbitals s = np.argsort(eps) eps = eps[s] C = C[:, s] printif(tasks.format(emoji('check'), '', '')) if not silent: sys.stdout.write("\033[F" * 5) time.sleep(0.1) # Get the MO integral OOVV nelec = Settings['nalpha'] + Settings['nbeta'] # Converto to Physicists notation g = g.transpose(0, 2, 1, 3) ERI = np.einsum('ap,bq,cr,ds,abcd->pqrs', C[:, :nelec], C[:, :nelec], C[:, nelec:], C[:, nelec:], g, optimize='optimal') # Antisymmetrize ERI = ERI - ERI.transpose(0, 1, 3, 2) printif(tasks.format(emoji('check'), emoji('check'), '')) if not silent: sys.stdout.write("\033[F" * 5) time.sleep(0.1) # Get eigenvalues Matrix D new = np.newaxis eo = eps[:nelec] ev = eps[nelec:] D = 1.0 / (eo[:, new, new, new] + eo[new, :, new, new] - ev[new, new, :, new] - ev[new, new, new, :]) printif(tasks.format(emoji('check'), emoji('check'), emoji('check'))) time.sleep(0.1) # Get MP2 energy printif('\n{} Computing MP2 energy'.format('\U0001F9ED'), end=' ') Emp2 = (1.0 / 4.0) * np.einsum('ijab,ijab,ijab->', ERI, ERI, D) printif(emoji('check')) printif('\n{} MP2 Correlation Energy: {:>16.10f}'.format( emoji('bolt'), Emp2)) printif('\U0001F308 Final Electronic Energy: {:>16.10f}'.format(Emp2 + Escf)) if psi4compare: psi4.set_options({ 'basis': Settings['basis'], 'scf_type': 'pk', 'mp2_type': 'conv', 'puream': False, 'reference': 'uhf' }) psi4_mp2 = psi4.energy('mp2') printif('\n\n{} Psi4 MP2 Energy: {:>16.10f}'.format( emoji('eyes'), psi4_mp2)) if abs(psi4_mp2 - Emp2 - Escf) < 1.e-8: printif('\n ' + emoji('books'), end=' ') printif('My grade:') printif(\ """ AAA A:::A A:::::A A:::::::A A:::::::::A A:::::A:::::A A:::::A A:::::A A:::::A A:::::A A:::::A A:::::A A:::::AAAAAAAAA:::::A A:::::::::::::::::::::A A:::::AAAAAAAAAAAAA:::::A A:::::A A:::::A A:::::A A:::::A A:::::A A:::::A AAAAAAA AAAAAAA""") return Emp2
def compute_DFMP2(Settings, silent=False): t0 = time.time() printif = print if not silent else lambda *k, **w: None Escf, Ca, Cb, epsa, epsb, = compute_uhf(Settings, return_C=True, return_integrals=False) printif(""" =================================================== Density-Fitting Spin-Orbital Møller-Plesset Perturbation Theory {} =================================================== """.format('\U0001F347' + '\U000027A1' + emoji('wine'))) tasks = """ Building: \U0001F426 Spin-Orbital arrays {} \U0001F986 J^(-1/2) (P|Q) {} \U0001F989 (uv|P) {} \U0001F9A2 b(ia|Q) {}""" printif(tasks.format('', '', '', '')) # Create Spin-Orbital arrays tsave = [] t = time.time() C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]]) eps = np.concatenate((epsa, epsb)) nmo = len(eps) ## Sorting orbitals s = np.argsort(eps) eps = eps[s] C = C[:, s] tsave.append(time.time() - t) show_progress(tsave, printif) # Create slices nelec = Settings['nalpha'] + Settings['nbeta'] o = slice(0, nelec) v = slice(nelec, nmo) # Build J^(-1/2) using Psi4 t = time.time() molecule = psi4.geometry(Settings['molecule']) basis = psi4.core.BasisSet.build(molecule, 'BASIS', Settings['basis'], puream=0) dfbasis = psi4.core.BasisSet.build(molecule, 'DF_BASIS_MP2', Settings['df_basis'], puream=0) mints = psi4.core.MintsHelper(basis) zero = psi4.core.BasisSet.zero_ao_basis_set() Jinvs = np.squeeze(mints.ao_eri(dfbasis, zero, dfbasis, zero).np) Jinvs = psi4.core.Matrix.from_array(Jinvs) Jinvs.power(-0.5, 1.e-14) Jinvs = Jinvs.np tsave.append(time.time() - t) show_progress(tsave, printif) # Get integrals uvP t = time.time() ao_uvP = np.squeeze(mints.ao_eri(basis, basis, dfbasis, zero).np) fh = slice(0, int(nmo / 2)) sh = slice(int(nmo / 2), nmo) ## Build spin-blocks uvP = np.zeros((nmo, nmo, ao_uvP.shape[2])) uvP[fh, fh, :] = ao_uvP uvP[sh, sh, :] = ao_uvP tsave.append(time.time() - t) show_progress(tsave, printif) # Get b(iaP) t = time.time() biaQ = np.einsum('ui, va, uvP, PQ -> iaQ', C[:, o], C[:, v], uvP, Jinvs, optimize='optimal') print(biaQ) tsave.append(time.time() - t) show_progress(tsave, printif) # Get MP2 energy printif('\n{} Computing DF-MP2 energy'.format('\U0001F9ED'), end=' ') t = time.time() Emp2 = 0 new = np.newaxis eo = eps[o] ev = eps[v] for i in range(nelec): for j in range(nelec): D = -ev[:, new] - ev[new, :] D = D + eo[i] + eo[j] D = 1.0 / D bAB = np.einsum('aQ, bQ-> ab', biaQ[i, :, :], biaQ[j, :, :]) bBA = np.einsum('bQ, aQ-> ab', biaQ[i, :, :], biaQ[j, :, :]) Emp2 += np.einsum('ab, ab->', np.square(bAB - bBA), D, optimize='optimal') Emp2 = Emp2 / 4.0 tsave.append(time.time() - t) printif('\n{} DF-MP2 Correlation Energy: {:>16.10f}'.format( emoji('bolt'), Emp2)) printif('\U0001F308 Final Electronic Energy: {:>16.10f}'.format(Emp2 + Escf)) printif('\n{} Total Computation time: {:10.5f} seconds'.format( '\U0000231B', time.time() - t0)) # Compare results with SO-MP2 printif('\n \U0001F4C8 Comparing results with regular MP2:') t0 = time.time() E0mp2 = compute_SOMP2(Settings, psi4compare=False, silent=True) printif('\n{} MP2 Correlation Energy: {:>16.10f}'.format( emoji('bolt'), E0mp2)) printif('{} DF error: {:>16.10f}'.format( '\U0000274C', E0mp2 - Emp2)) printif('\n{} Total Computation time: {:10.5f} seconds'.format( '\U0000231B', time.time() - t0)) # Compare with Psi4 psi4.set_options({ 'basis': Settings['basis'], 'df_basis_mp2': Settings['df_basis'], 'e_convergence': 1e-12, 'scf_type': 'pk', 'puream': False, 'reference': 'uhf' }) psi4_mp2 = psi4.energy('mp2') printif('\n\n{} Psi4 DF-MP2 Energy: {:>16.10f}'.format( emoji('eyes'), psi4_mp2))
def compute_DFMP2(Settings): Escf, Ca, Cb, epsa, epsb, = compute_uhf(Settings, return_C=True, return_integrals=False) print(""" =================================================== Density-Fitting Møller-Plesset Perturbation Theory {} =================================================== """.format(emoji('wine'))) tasks = """ Building: \U0001F426 Spin-Orbital arrays {} \U0001F986 MO integral <OO|VV> {} \U0001F9A2 Eigenvalues auxiliar array Dijab {}""" print(tasks.format('', '', '')) sys.stdout.write("\033[F" * 5) time.sleep(0.1) # Create Spin-Orbital arrays #C = np.block([ # [Ca, np.zeros(Ca.shape)], # [np.zeros(Cb.shape), Cb] # ]) #eps = np.concatenate((epsa, epsb)) eps = epsa nmo = len(eps) # re-Sorting orbitals #s = np.argsort(eps) #eps = eps[s] #C = C[:,s] print(tasks.format(emoji('check'), '', '')) # Create slices nelec = Settings['nalpha'] + Settings['nbeta'] ndocc = int(nelec / 2) nmo = len(eps) nvir = nmo - ndocc o = slice(0, ndocc) v = slice(ndocc, nmo) # Build J^(-1/2) using Psi4 molecule = psi4.geometry(Settings['molecule']) basis = psi4.core.BasisSet.build(molecule, 'BASIS', Settings['basis'], puream=0) dfbasis = psi4.core.BasisSet.build(molecule, 'DF_BASIS_MP2', Settings['df_basis'], puream=0) mints = psi4.core.MintsHelper(basis) zero = psi4.core.BasisSet.zero_ao_basis_set() Jinvs = np.squeeze(mints.ao_eri(dfbasis, zero, dfbasis, zero).np) Jinvs = psi4.core.Matrix.from_array(Jinvs) Jinvs.power(-0.5, 1.e-14) Jinvs = Jinvs.np # Get integrals uvP uvP = np.squeeze(mints.ao_eri(basis, basis, dfbasis, zero).np) #fh = slice(0, int(nmo/2)) #sh = slice(int(nmo/2), nmo) #uvP = np.zeros((nmo, nmo, ao_uvP.shape[2])) #uvP[fh, fh, :] = ao_uvP #uvP[sh, sh, :] = ao_uvP #uvP = uvP[s,:,:] #uvP = uvP[:,s,:] #print(uvP.shape) # Get b(iaP) # b(uvQ) biaQ = np.einsum('uvP, PQ-> uvQ', uvP, Jinvs) # b(ivQ) biaQ = np.einsum('ui, uvQ-> ivQ', Ca[:, o], biaQ) # b(iaQ) biaQ = np.einsum('va, ivQ-> iaQ', Ca[:, v], biaQ) # Get eigenvalues Matrix D new = np.newaxis eo = eps[o] ev = eps[v] D = 1.0 / (eo[:, new, new, new] - ev[new, :, new, new] + eo[new, new, :, new] - ev[new, new, new, :]) # Get MP2 energy print('\n{} Computing MP2 energy'.format('\U0001F9ED'), end=' ') Emp2 = 0 for i in range(ndocc): for j in range(ndocc): bAB = np.einsum('aQ, bQ-> ab', biaQ[i, :, :], biaQ[j, :, :]) bBA = np.einsum('bQ, aQ-> ab', biaQ[i, :, :], biaQ[j, :, :]) Emp2 += np.einsum('ab, ab, ab->', bAB, (2 * bAB - bBA), D[i, :, j, :], optimize='optimal') print('\n{} MP2 Correlation Energy: {:>16.10f}'.format( emoji('bolt'), Emp2)) print('\U0001F308 Final Electronic Energy: {:>16.10f}'.format(Emp2 + Escf)) psi4.set_options({ 'basis': Settings['basis'], 'df_basis_mp2': Settings['df_basis'], 'e_convergence': 1e-12, 'scf_type': 'pk', 'puream': False, 'reference': 'uhf' }) psi4_mp2 = psi4.energy('mp2') print('\n\n{} Psi4 MP2 Energy: {:>16.10f}'.format( emoji('eyes'), psi4_mp2))
def compute_CI(Settings): Escf, C, _, _, _, h, g, Vnuc = compute_uhf(Settings, return_C=True, return_integrals=True) print(""" ========================================= Configuration Interaction Starting {} ========================================= """.format(emoji('brinde'))) # Initial workup nmo = len(C) nelec = Settings['nalpha'] + Settings['nbeta'] if nelec % 2 != 0: raise NameError('This code works only for closed-shell molecules') ndocc = int(nelec / 2) nvir = nmo - ndocc # Read in excitation level if type(Settings["excitation_level"]) == int: exlv = int(Settings["excitation_level"]) elif type(Settings["excitation_level"]) == str: if Settings["excitation_level"].lower() == 'full': exlv = nelec elif Settings["excitation_level"].lower() == 'cis': exlv = 1 elif Settings["excitation_level"].lower() == 'cisd': exlv = 2 elif Settings["excitation_level"].lower() == 'cisdt': exlv = 3 elif Settings["excitation_level"].lower() == 'cisdtq': exlv = 4 elif Settings["excitation_level"].lower() == 'cisdtqp': exlv = 5 else: raise TypeError('Invalid excitation level: {}'.format( Settings["excitation_level"])) else: raise TypeError('Invalid excitation level: {}'.format( Settings["excitation_level"])) # Convert AO integrals to Molecular integrals h = np.einsum('up,vq,uv->pq', C, C, h, optimize='optimal') ERI = np.einsum('ap,bq,cr,ds,abcd->pqrs', C, C, C, C, g, optimize='optimal') ############### STEP 1 ############### ######## Read Active Space ######### ## The active_space must be a string containing the letters 'o', 'a' and 'u': ## 'o' represents frozen doubly occupied orbitals; ## 'a' represents active orbitals; ## 'u' represents frozen unoccupied orbitals. ## However, the active_space can also be given in three alternative ways: ## active_space = 'full': for a full CI computation; ## active_space = 'none': for a emputy active space (output energy is SCF energy); ## If the active_space string is shorter than expected, remaining orbitals will be ## considered 'u' (unoccupied) ## Note that, the first orbital has index 0 active_space = Settings['active_space'] if active_space == 'full': active_space = 'a' * nmo elif active_space == 'none': active_space = 'o' * ndocc + 'u' * nvir # If the active space string is smaller than the number of orbitals, # append 'u' (unoccupied) at the end while len(active_space) < nmo: active_space += 'u' # Check if active space size is consistem with given integrals if len(active_space) != nmo: raise NameError( 'Active Space size is {} than the number of molecular orbitals'. format('greater' if len(active_space) > nmo else 'smaller')) nfrozen = active_space.count('o') nactive = active_space.count('a') active_elec = nelec - 2 * nfrozen # Check if number of frozen orbitals is valid (must be less than the number of electron pairs) if active_elec < 0: raise NameError( 'Invalid number of frozen orbitals ({}), for {} electrons'.format( nfrozen, nelec)) # Check if there are enough active orbitals for the active electrons if 2 * nactive < active_elec: raise NameError( '{} active orbitals not enough for {} active electrons'.format( nactive, active_elec)) print("Active Space:") out = '' for x in active_space: if x == 'o': out += emoji('Obold') elif x == 'a': out += emoji('O') elif x == 'u': out += emoji('X') else: raise TypeError('Invalid active space key: {}'.format(x)) print(out + '\n') print("Number of active spatial orbitals: {}".format(numoji(nactive))) print("Number of active electrons: {}".format(numoji(active_elec))) print("Number of frozen orbitals: {}\n".format(numoji(nfrozen))) ############### STEP 2 ############### ###### Generate Determinants ####### # Creating a template string. Active orbitals are represented by {} # Occupied orbitals are 1, and unnocupied 0. # For example: 11{}{}{}000 represents a system with 8 orbitals where the two lowest ones are frozen (doubly occupied) # and the three highest ones are frozen (unnocupied). Thus, there are 3 active orbitals. template_space = active_space.replace('o', '1') template_space = template_space.replace('u', '0') template_space = template_space.replace('a', '{}') # Produce a reference determinant ref = Determinant(a = ('1'*ndocc + '0'*nvir), \ b = ('1'*ndocc + '0'*nvir)) # Produces a list of active electrons in active orbitals and get all permutations of it. # For example. Say we have a template 11{}{}{}000 as in the example above. If the system contains 6 electrons # we have one pair of active electrons. The list of active electrons will look like '100' and the permutations # will be generated (as lists): ['1', '0', '0'], ['0', '1', '0'], and ['0', '0', '1']. # Each permutation is then merged with the template above to generate a string used ot create a Determinant object # For example. 11{}{}{}000 is combine with ['0','1', '0'] to produce an alpha/beta string 11010000. # These strings are then combined to form various determinants print("Generating excitations", end=' ') perms = set( permutations('1' * int(active_elec / 2) + '0' * int(nactive - active_elec / 2))) print(emoji('check')) determinants = [] for p1 in perms: for p2 in perms: newdet = Determinant(a=template_space.format(*p1), b=template_space.format(*p2)) if ref - newdet > 2 * exlv: continue else: determinants.append(newdet) ndets = len(determinants) nelements = int((ndets * (ndets + 1)) / 2) print("Number of determinants: {}".format(numoji(ndets))) print("Number of unique matrix elements: {}\n".format( numoji(nelements))) # Build Hamiltonian matrix print("Building Hamiltonian Matrix", end=' ') H = get_Hamiltonian(determinants, h, ERI) print(emoji('check')) # Diagonalize Hamiltonian print("Diagonalizing Hamiltonian Matrix", end=' ') Eci, Cci = np.linalg.eigh(H) print(emoji('check')) E0 = Eci[0] + Vnuc C0 = Cci[:, 0] print('\nFinal CASCI Energy: {:<14.10f}'.format(E0)) if exlv == nelec: psi4.set_options({ 'basis': Settings['basis'], 'scf_type': 'pk', 'puream': False, 'FROZEN_DOCC': [nfrozen], 'ACTIVE': [nactive], 'FCI': True, 'reference': 'rhf' }) print('Final DETCI Energy: {:<14.10f}'.format(psi4.energy('detci'))) # Print wavefunction analysis ndet = 10 args = np.argsort(C0 * C0) sortedC = C0[args] sortedC = sortedC[::-1] sortedC = sortedC[:ndet] sortedD = np.array(determinants)[args] sortedD = sortedD[::-1] sortedD = sortedD[:ndet] print('\n\n' + emoji('bchart') + ' Wave function analysis') print('=' * 25) print('\n') print(' ' * 10 + emoji('top') + ' Top {} determinants as voted by the public\n'.format(ndet)) # Header l = len(ref.short_info()) header = ' {:^7s} {:^8s} {:^' + str(l) + 's} {:^9s}' print(header.format('%', 'Coef', 'Determinant', 'Exc lv')) print(' ' * 4 + '=' * 7 + ' ' + '=' * 8 + ' ' + '=' * l + ' ' + '=' * 9) # Actual info f = True for c, d in zip(sortedC, sortedD): sq = c * c ex = int((ref - d) / 2) if f: print(' ' * 2 + emoji('trophy') + '{:7.5f} {: 8.5f} {} {:^9s}'.format( sq, c, d.short_info(), numoji(ex))) f = False else: print(' ' * 4 + '{:7.5f} {: 8.5f} {} {:^9s}'.format( sq, c, d.short_info(), numoji(ex)))
def compute_dfCEPA(Settings, silent=False, compare=False): t0 = time.time() printif = print if not silent else lambda *k, **w: None Escf, Ca, Cb, epsa, epsb, _, g, Vnuc = compute_uhf(Settings, return_C=True, return_integrals=True) printif(""" ======================================================= Density-Fitting CEPA0 (For those who havent heard Coupled Cluster exists) {} ======================================================= """.format('\U0001F474')) tsave = [] show_progress(tsave, printif) # Create Spin-Orbital arrays t = time.time() C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]]) eps = np.concatenate((epsa, epsb)) g = np.kron(np.eye(2), g) g = np.kron(np.eye(2), g.T) # re-Sorting orbitals s = np.argsort(eps) eps = eps[s] C = C[:, s] tsave.append(time.time() - t) show_progress(tsave, printif) # Get the MO integral t = time.time() nelec = Settings['nalpha'] + Settings['nbeta'] # Converto to Physicists notation g = g.transpose(0, 2, 1, 3) # Antisymmetrize g = g - g.transpose(0, 1, 3, 2) # Save Slices ERI = lambda ax, bx, cx, dx: np.einsum('ap,bq,cr,ds,abcd->pqrs', C[:, ax], C[:, bx], C[:, cx], C[:, dx], g, optimize='optimal') nmo = len(g) o = slice(0, nelec) v = slice(nelec, nmo) Voovv = ERI(o, o, v, v) Voooo = ERI(o, o, o, o) Vvoov = ERI(v, o, o, v) tsave.append(time.time() - t) show_progress(tsave, printif) # Use Density-Fitting for the Vvvvv case # Build J^(-1/2) using Psi4 t = time.time() molecule = psi4.geometry(Settings['molecule']) basis = psi4.core.BasisSet.build(molecule, 'BASIS', Settings['basis'], puream=0) dfbasis = psi4.core.BasisSet.build(molecule, 'DF_BASIS_MP2', Settings['df_basis'], puream=0) mints = psi4.core.MintsHelper(basis) zero = psi4.core.BasisSet.zero_ao_basis_set() Jinvs = np.squeeze(mints.ao_eri(dfbasis, zero, dfbasis, zero).np) Jinvs = psi4.core.Matrix.from_array(Jinvs) Jinvs.power(-0.5, 1.e-14) Jinvs = Jinvs.np tsave.append(time.time() - t) show_progress(tsave, printif) # Get integrals uvP t = time.time() ao_uvP = np.squeeze(mints.ao_eri(basis, basis, dfbasis, zero).np) fh = slice(0, int(nmo / 2)) sh = slice(int(nmo / 2), nmo) ## Build spin-blocks uvP = np.zeros((nmo, nmo, ao_uvP.shape[2])) uvP[fh, fh, :] = ao_uvP uvP[sh, sh, :] = ao_uvP tsave.append(time.time() - t) show_progress(tsave, printif) # Get b(abP) t = time.time() babQ = np.einsum('ua, vb, uvP, PQ -> abQ', C[:, v], C[:, v], uvP, Jinvs, optimize='optimal') tsave.append(time.time() - t) show_progress(tsave, printif) # Get eigenvalues Matrix D t = time.time() new = np.newaxis eo = eps[:nelec] ev = eps[nelec:] D = 1.0 / (eo[:, new, new, new] + eo[new, :, new, new] - ev[new, new, :, new] - ev[new, new, new, :]) tsave.append(time.time() - t) show_progress(tsave, printif) t = time.time() # Initial guess for amplitudes T = Voovv * D # Get MP2 energy E = CEPA_Energy(T, Voovv) print('\nMP2 Energy: {:<15.10f}\n'.format(E + Escf)) # Setup iteration options rms = 0.0 dE = 1 ite = 1 rms_LIM = 10**(-8) E_LIM = 10**(-12) t0 = time.time() printif('\U00003030' * 20) # Start CC iterations while abs(dE) > E_LIM or rms > rms_LIM: t = time.time() if ite > Settings["cc_max_iter"]: raise NameError('CEPA0 equations did not converge') T, rms = CEPA_Amplitude(T, D, Voovv, Voooo, babQ, Vvoov) dE = -E E = CEPA_Energy(T, Voovv) dE += E printif("Iteration {}".format(numoji(ite))) printif("\U000027B0 Correlation energy: {:< 15.10f}".format(E)) printif("\U0001F53A Energy change: {:< 15.10f}".format(dE)) printif("\U00002622 Max RMS residue: {:< 15.10f}".format(rms)) printif("\U0001F570 Time required: {:< 15.10f}".format( time.time() - t)) printif('\U00003030' * 20) ite += 1 printif('\U0001F3C1 DF-CEPA0 Energy: {:<15.10f}'.format(E + Escf)) printif('\U000023F3 CEPA0 iterations took %.2f seconds.\n' % (time.time() - t0)) if compare: from CEPA import compute_CEPA printif('\n Running regular CEPA...\n') t0 = time.time() Efull = compute_CEPA(Settings, silent=True, compare=False) printif('\U0001F3C1 CEPA0 Energy: {:<15.10f}'.format(Efull)) printif('\U000023F3 CEPA0 iterations took %.2f seconds.\n' % (time.time() - t0)) printif( '\n\U0000274C Density Fitting Error: {:<15.10f}'.format(E + Escf - Efull)) return (E + Escf)