def uhf_simple(geo,basisname='sto3g',maxiter=25,verbose=False): if geo.nopen() == 0: return scf_simple(geo,basisname,maxiter,verbose) bfs = basisset(geo,basisname) i1 = onee_integrals(bfs,geo) i2 = twoe_integrals(bfs) h = i1.T + i1.V E,U = geigh(h,i1.S) Enuke = geo.nuclear_repulsion() Eold = Energy = 0 ca = cb = U na,nb = geo.nup(),geo.ndown() for i in xrange(maxiter): Energy = Enuke Da = dmat(ca,na) Db = dmat(cb,nb) h = i1.T + i1.V Energy += trace2(Da+Db,h)/2 Ja,Ka = i2.get_j(Da),i2.get_k(Da) Jb,Kb = i2.get_j(Db),i2.get_k(Db) Fa = h + Ja + Jb - Ka Fb = h + Ja + Jb - Kb orbea,ca = geigh(Fa,i1.S) orbeb,cb = geigh(Fb,i1.S) Energy += trace2(Fa,Da)/2 + trace2(Fb,Db)/2 print ("UHF: %d %10.4f : %10.4f" % ((i+1),Energy,Enuke)) if np.isclose(Energy,Eold): break Eold = Energy else: print ("Warning: Maxiter %d hit in scf_simple" % maxiter) return Energy,E,U
def scf_simple(geo,basisname='sto-3g',maxiter=25,verbose=False): bfs = basisset(geo,basisname) i1 = onee_integrals(bfs,geo) i2 = twoe_integrals(bfs) if verbose: print ("S=\n%s" % i1.S) h = i1.T + i1.V if verbose: print ("h=\n%s" % h) if verbose: print ("T=\n%s" % i1.T) if verbose: print ("V=\n%s" % i1.V) E,U = geigh(h,i1.S) if verbose: print ("E=\n%s" % E) if verbose: print ("U=\n%s" % U) Enuke = geo.nuclear_repulsion() nocc = geo.nocc() Eold = Energy = 0 if verbose: print ("2e ints\n%s" % i2) for i in xrange(maxiter): D = dmat(U,nocc) if verbose: print ("D=\n%s" % D) Eone = trace2(h,D) G = i2.get_2jk(D) H = h+G Etwo = trace2(H,D) E,U = geigh(H,i1.S) Energy = Enuke+Eone+Etwo print ("HF: %d %10.4f : %10.4f %10.4f %10.4f" % ((i+1),Energy,Enuke,Eone,Etwo)) if np.isclose(Energy,Eold): break Eold = Energy else: print ("Warning: Maxiter %d hit in scf_simple" % maxiter) return Energy,E,U
def rhf_simple(geo,basisname='sto3g',maxiter=25,verbose=False): bfs = basisset(geo,basisname) i1 = onee_integrals(bfs,geo) i2 = twoe_integrals(bfs) if verbose: print ("S=\n%s" % i1.S) h = i1.T + i1.V if verbose: print ("h=\n%s" % h) if verbose: print ("T=\n%s" % i1.T) if verbose: print ("V=\n%s" % i1.V) E,U = geigh(h,i1.S) if verbose: print ("E=\n%s" % E) if verbose: print ("U=\n%s" % U) Enuke = geo.nuclear_repulsion() nocc = geo.nocc() Eold = Energy = 0 if verbose: print ("2e ints\n%s" % i2) for i in xrange(maxiter): D = dmat(U,nocc) if verbose: print ("D=\n%s" % D) Eone = trace2(h,D) G = i2.get_2jk(D) H = h+G Etwo = trace2(H,D) E,U = geigh(H,i1.S) Energy = Enuke+Eone+Etwo print ("HF: %d %10.4f : %10.4f %10.4f %10.4f" % ((i+1),Energy,Enuke,Eone,Etwo)) if np.isclose(Energy,Eold): break Eold = Energy else: print ("Warning: Maxiter %d hit in scf_simple" % maxiter) return Energy,E,U
def __init__(self,geo,bfs): self.geo = geo self.bfs = bfs self.i1 = onee_integrals(bfs,geo) self.i2 = twoe_integrals(bfs) self.energies = [] self.energy = 0 self.converged = False
def _calculate_integrals(molecule, basis='sto3g', calc_type='rhf'): """Function to calculate the one and two electron terms. Perform a Hartree-Fock calculation in the given basis. Args: molecule : A pyquante2 molecular object. basis : The basis set for the electronic structure computation calc_type: rhf, uhf, rohf Returns: ehf : Hartree-Fock energy enuke: Nuclear repulsion energy norbs : Number of orbitals mohij : One electron terms of the Hamiltonian. mohijkl : Two electron terms of the Hamiltonian. orbs: Molecular orbital coefficients orbs_energy: Orbital energies """ bfs = basisset(molecule, basis) integrals = onee_integrals(bfs, molecule) hij = integrals.T + integrals.V hijkl_compressed = twoe_integrals(bfs) # convert overlap integrals to molecular basis # calculate the Hartree-Fock solution of the molecule if calc_type == 'rhf': solver = rhf(molecule, bfs) elif calc_type == 'rohf': solver = rohf(molecule, bfs) elif calc_type == 'uhf': solver = uhf(molecule, bfs) else: raise QiskitChemistryError('Invalid calc_type: {}'.format(calc_type)) logger.debug('Solver name {}'.format(solver.name)) ehf = solver.converge() if hasattr(solver, 'orbs'): orbs = solver.orbs else: orbs = solver.orbsa norbs = len(orbs) if hasattr(solver, 'orbe'): orbs_energy = solver.orbe else: orbs_energy = solver.orbea enuke = molecule.nuclear_repulsion() # Get ints in molecular orbital basis mohij = simx(hij, orbs) mohijkl_compressed = transformintegrals(hijkl_compressed, orbs) mohijkl = np.zeros((norbs, norbs, norbs, norbs)) for i in range(norbs): for j in range(norbs): for k in range(norbs): for l in range(norbs): mohijkl[i, j, k, l] = mohijkl_compressed[ijkl2intindex(i, j, k, l)] return ehf[0], enuke, norbs, mohij, mohijkl, orbs, orbs_energy
def _populate_driver_result_electronic_energy( self, driver_result: ElectronicStructureDriverResult) -> None: # pylint: disable=import-error from pyquante2 import onee_integrals from pyquante2.ints.integrals import twoe_integrals basis_transform = driver_result.get_property(ElectronicBasisTransform) integrals = onee_integrals(self._bfs, self._mol) hij = integrals.T + integrals.V hijkl = twoe_integrals(self._bfs) one_body_ao = OneBodyElectronicIntegrals(ElectronicBasis.AO, (hij, None)) two_body_ao = TwoBodyElectronicIntegrals( ElectronicBasis.AO, (hijkl.transform(np.identity(self._nmo)), None, None, None), ) one_body_mo = one_body_ao.transform_basis(basis_transform) two_body_mo = two_body_ao.transform_basis(basis_transform) electronic_energy = ElectronicEnergy( [one_body_ao, two_body_ao, one_body_mo, two_body_mo], nuclear_repulsion_energy=self._mol.nuclear_repulsion(), reference_energy=self._calc.energy, ) if hasattr(self._calc, "orbe"): orbs_energy = self._calc.orbe orbs_energy_b = None else: orbs_energy = self._calc.orbea orbs_energy_b = self._calc.orbeb orbital_energies = ((orbs_energy, orbs_energy_b) if orbs_energy_b is not None else orbs_energy) electronic_energy.orbital_energies = np.asarray(orbital_energies) electronic_energy.kinetic = OneBodyElectronicIntegrals( ElectronicBasis.AO, (integrals.T, None)) electronic_energy.overlap = OneBodyElectronicIntegrals( ElectronicBasis.AO, (integrals.S, None)) driver_result.add_property(electronic_energy)
def _calculate_integrals(molecule, basis="sto3g", hf_method="rhf", tol=1e-8, maxiters=100): """Function to calculate the one and two electron terms. Perform a Hartree-Fock calculation in the given basis. Args: molecule (pyQuante2.molecule): A pyquante2 molecular object. basis (str) : The basis set for the electronic structure computation hf_method (str): rhf, uhf, rohf tol (float): tolerance maxiters (int): max. iterations Returns: QMolecule: QMolecule populated with driver integrals etc Raises: QiskitNatureError: Invalid hf methods type """ bfs = basisset(molecule, basis) integrals = onee_integrals(bfs, molecule) hij = integrals.T + integrals.V hijkl = twoe_integrals(bfs) # convert overlap integrals to molecular basis # calculate the Hartree-Fock solution of the molecule if hf_method == "rhf": solver = rhf(molecule, bfs) elif hf_method == "rohf": solver = rohf(molecule, bfs) elif hf_method == "uhf": solver = uhf(molecule, bfs) else: raise QiskitNatureError("Invalid hf_method type: {}".format(hf_method)) ehf = solver.converge(tol=tol, maxiters=maxiters) logger.debug("PyQuante2 processing information:\n%s", solver) if hasattr(solver, "orbs"): orbs = solver.orbs orbs_b = None else: orbs = solver.orbsa orbs_b = solver.orbsb norbs = len(orbs) if hasattr(solver, "orbe"): orbs_energy = solver.orbe orbs_energy_b = None else: orbs_energy = solver.orbea orbs_energy_b = solver.orbeb enuke = molecule.nuclear_repulsion() # Get ints in molecular orbital basis mohij = simx(hij, orbs) mohij_b = None if orbs_b is not None: mohij_b = simx(hij, orbs_b) eri = hijkl.transform(np.identity(norbs)) mohijkl = hijkl.transform(orbs) mohijkl_bb = None mohijkl_ba = None if orbs_b is not None: mohijkl_bb = hijkl.transform(orbs_b) mohijkl_ba = np.einsum("aI,bJ,cK,dL,abcd->IJKL", orbs_b, orbs_b, orbs, orbs, hijkl[...]) # Create driver level molecule object and populate _q_ = QMolecule() _q_.origin_driver_version = "?" # No version info seems available to access # Energies and orbits _q_.hf_energy = ehf[0] _q_.nuclear_repulsion_energy = enuke _q_.num_molecular_orbitals = norbs _q_.num_alpha = molecule.nup() _q_.num_beta = molecule.ndown() _q_.mo_coeff = orbs _q_.mo_coeff_b = orbs_b _q_.orbital_energies = orbs_energy _q_.orbital_energies_b = orbs_energy_b # Molecule geometry _q_.molecular_charge = molecule.charge _q_.multiplicity = molecule.multiplicity _q_.num_atoms = len(molecule) _q_.atom_symbol = [] _q_.atom_xyz = np.empty([len(molecule), 3]) atoms = molecule.atoms for n_i in range(0, _q_.num_atoms): atuple = atoms[n_i].atuple() _q_.atom_symbol.append(QMolecule.symbols[atuple[0]]) _q_.atom_xyz[n_i][0] = atuple[1] _q_.atom_xyz[n_i][1] = atuple[2] _q_.atom_xyz[n_i][2] = atuple[3] # 1 and 2 electron integrals _q_.hcore = hij _q_.hcore_b = None _q_.kinetic = integrals.T _q_.overlap = integrals.S _q_.eri = eri _q_.mo_onee_ints = mohij _q_.mo_onee_ints_b = mohij_b _q_.mo_eri_ints = mohijkl _q_.mo_eri_ints_bb = mohijkl_bb _q_.mo_eri_ints_ba = mohijkl_ba return _q_
def _calculate_integrals(molecule, basis='sto3g', hf_method='rhf', tol=1e-8, maxiters=100): """Function to calculate the one and two electron terms. Perform a Hartree-Fock calculation in the given basis. Args: molecule : A pyquante2 molecular object. basis : The basis set for the electronic structure computation hf_method: rhf, uhf, rohf Returns: QMolecule: QMolecule populated with driver integrals etc """ bfs = basisset(molecule, basis) integrals = onee_integrals(bfs, molecule) hij = integrals.T + integrals.V hijkl = twoe_integrals(bfs) # convert overlap integrals to molecular basis # calculate the Hartree-Fock solution of the molecule if hf_method == 'rhf': solver = rhf(molecule, bfs) elif hf_method == 'rohf': solver = rohf(molecule, bfs) elif hf_method == 'uhf': solver = uhf(molecule, bfs) else: raise QiskitChemistryError('Invalid hf_method type: {}'.format(hf_method)) ehf = solver.converge(tol=tol, maxiters=maxiters) logger.debug('PyQuante2 processing information:\n{}'.format(solver)) if hasattr(solver, 'orbs'): orbs = solver.orbs orbs_B = None else: orbs = solver.orbsa orbs_B = solver.orbsb norbs = len(orbs) if hasattr(solver, 'orbe'): orbs_energy = solver.orbe orbs_energy_B = None else: orbs_energy = solver.orbea orbs_energy_B = solver.orbeb enuke = molecule.nuclear_repulsion() # Get ints in molecular orbital basis mohij = simx(hij, orbs) mohij_B = None if orbs_B is not None: mohij_B = simx(hij, orbs_B) eri = hijkl.transform(np.identity(norbs)) mohijkl = hijkl.transform(orbs) mohijkl_BB = None mohijkl_BA = None if orbs_B is not None: mohijkl_BB = hijkl.transform(orbs_B) mohijkl_BA = np.einsum('aI,bJ,cK,dL,abcd->IJKL', orbs_B, orbs_B, orbs, orbs, hijkl[...]) # Create driver level molecule object and populate _q_ = QMolecule() _q_.origin_driver_version = '?' # No version info seems available to access # Energies and orbits _q_.hf_energy = ehf[0] _q_.nuclear_repulsion_energy = enuke _q_.num_orbitals = norbs _q_.num_alpha = molecule.nup() _q_.num_beta = molecule.ndown() _q_.mo_coeff = orbs _q_.mo_coeff_B = orbs_B _q_.orbital_energies = orbs_energy _q_.orbital_energies_B = orbs_energy_B # Molecule geometry _q_.molecular_charge = molecule.charge _q_.multiplicity = molecule.multiplicity _q_.num_atoms = len(molecule) _q_.atom_symbol = [] _q_.atom_xyz = np.empty([len(molecule), 3]) atoms = molecule.atoms for _n in range(0, _q_.num_atoms): atuple = atoms[_n].atuple() _q_.atom_symbol.append(QMolecule.symbols[atuple[0]]) _q_.atom_xyz[_n][0] = atuple[1] _q_.atom_xyz[_n][1] = atuple[2] _q_.atom_xyz[_n][2] = atuple[3] # 1 and 2 electron integrals _q_.hcore = hij _q_.hcore_B = None _q_.kinetic = integrals.T _q_.overlap = integrals.S _q_.eri = eri _q_.mo_onee_ints = mohij _q_.mo_onee_ints_B = mohij_B _q_.mo_eri_ints = mohijkl _q_.mo_eri_ints_BB = mohijkl_BB _q_.mo_eri_ints_BA = mohijkl_BA return _q_
def gvb(geo,npair=0,basisname='sto3g',maxiter=25,verbose=False, return_orbs=False, input_orbs=None): """\ This is a trivial test for the gvb module, because other pyquante modules are simpler if you're doing closed shell rhf, and should give the same results. # -0.46658184546856041 from uhf/sto3g >>> gvb(h) # doctest: +ELLIPSIS -0.4665818... # -1.117099582955609 from rhf/sto3g >>> gvb(h2) # doctest: +ELLIPSIS -1.117099... >>> gvb(lih,maxiter=5) # doctest: +ELLIPSIS -7.86073... >>> gvb(li,maxiter=5) # doctest: +ELLIPSIS -7.31552... >>> gvb(h2,npair=1) # doctest: +ELLIPSIS -1.13730... """ # Get the basis set and the integrals bfs = basisset(geo,basisname) i1 = onee_integrals(bfs,geo) i2 = twoe_integrals(bfs) h = i1.T + i1.V # Get a guess for the orbitals if input_orbs is not None: U = input_orbs else: E,U = geigh(h,i1.S) # Set the parameters based on the molecule nopen = geo.nopen() ncore = geo.nclosed() - npair nocc = ncore + nopen + 2*npair norb = len(bfs) virt = range(nocc,norb) orbs_per_shell = get_orbs_per_shell(ncore,nopen,npair) nsh = len(orbs_per_shell) shell = orbital_to_shell_mapping(ncore,nopen,npair) Enuke = geo.nuclear_repulsion() f,a,b = fab(ncore,nopen,npair) if verbose: np.set_printoptions(precision=4) print("**** PyQuante GVB ****") print(geo) print("Nuclear repulsion energy: %.3f" % Enuke) print("Basis set: %s" % basisname) print(" ncore/open/pair: %d,%d,%d" % (ncore,nopen,npair)) print(" occ/bf/orb: %d,%d,%d" % (nocc,len(bfs),norb)) for i in range(nsh): print("Shell %d" % i) print(" occupation = %.2f" % f[i]) print(" orbitals in shell %s" % orbs_per_shell[i]) print(" couplings to other shells %s" % zip(a[i,:],b[i,:])) print("Starting guess at orbitals:\n%s"%U) print("Shell array: %s" % shell) print("****") Eold = 0 for it in range(maxiter): # Make all of the density matrices: Ds = [dmat_gen(U,orbs) for orbs in orbs_per_shell] # Compute the required Hamiltonian matrices: Js = [i2.get_j(D) for D in Ds] Ks = [i2.get_k(D) for D in Ds] # Perform the ROTION step and compute the energy Eel,Eone,Uocc = ROTION(U[:,:nocc],h,Js,Ks,f,a,b,nocc,shell, verbose=verbose) if nsh > 1: U[:,:nocc] = Uocc # Perform the OCBSE step U = OCBSE(U,h,Js,Ks,f,a,b,orbs_per_shell,virt) #E = Enuke+Eone+Etwo E = Enuke+Eel Etwo = Eel-2*Eone # Update CI coefs coeffs = update_gvb_ci_coeffs(Uocc,h,Js,Ks,f,a,b,ncore,nopen,npair, orbs_per_shell,verbose) f,a,b = fab(ncore,nopen,npair,coeffs) if verbose: print ("---- %d : %10.4f %10.4f %10.4f %10.4f" % ((it+1),E,Enuke,Eone,Etwo)) if np.isclose(E,Eold): if verbose: print("Energy converged") break Eold = E else: print("Maximum iterations (%d) reached without convergence" % (maxiter)) if return_orbs: return E,U return E
def gvb(geo, npair=0, basisname='sto3g', maxiter=25, verbose=False, return_orbs=False, input_orbs=None): """\ This is a trivial test for the gvb module, because other pyquante modules are simpler if you're doing closed shell rhf, and should give the same results. # -0.46658184546856041 from uhf/sto3g >>> gvb(h) # doctest: +ELLIPSIS -0.4665818... # -1.117099582955609 from rhf/sto3g >>> gvb(h2) # doctest: +ELLIPSIS -1.117099... >>> gvb(lih,maxiter=5) # doctest: +ELLIPSIS -7.86073... >>> gvb(li,maxiter=5) # doctest: +ELLIPSIS -7.31552... >>> gvb(h2,npair=1) # doctest: +ELLIPSIS -1.13730... """ # Get the basis set and the integrals bfs = basisset(geo, basisname) i1 = onee_integrals(bfs, geo) i2 = twoe_integrals(bfs) h = i1.T + i1.V # Get a guess for the orbitals if input_orbs is not None: U = input_orbs else: E, U = geigh(h, i1.S) # Set the parameters based on the molecule nopen = geo.nopen() ncore = geo.nclosed() - npair nocc = ncore + nopen + 2 * npair norb = len(bfs) virt = range(nocc, norb) orbs_per_shell = get_orbs_per_shell(ncore, nopen, npair) nsh = len(orbs_per_shell) shell = orbital_to_shell_mapping(ncore, nopen, npair) Enuke = geo.nuclear_repulsion() f, a, b = fab(ncore, nopen, npair) if verbose: np.set_printoptions(precision=4) print("**** PyQuante GVB ****") print(geo) print("Nuclear repulsion energy: %.3f" % Enuke) print("Basis set: %s" % basisname) print(" ncore/open/pair: %d,%d,%d" % (ncore, nopen, npair)) print(" occ/bf/orb: %d,%d,%d" % (nocc, len(bfs), norb)) for i in range(nsh): print("Shell %d" % i) print(" occupation = %.2f" % f[i]) print(" orbitals in shell %s" % orbs_per_shell[i]) print(" couplings to other shells %s" % zip(a[i, :], b[i, :])) print("Starting guess at orbitals:\n%s" % U) print("Shell array: %s" % shell) print("****") Eold = 0 for it in range(maxiter): # Make all of the density matrices: Ds = [dmat_gen(U, orbs) for orbs in orbs_per_shell] # Compute the required Hamiltonian matrices: Js = [i2.get_j(D) for D in Ds] Ks = [i2.get_k(D) for D in Ds] # Perform the ROTION step and compute the energy Eel, Eone, Uocc = ROTION(U[:, :nocc], h, Js, Ks, f, a, b, nocc, shell, verbose=verbose) if nsh > 1: U[:, :nocc] = Uocc # Perform the OCBSE step U = OCBSE(U, h, Js, Ks, f, a, b, orbs_per_shell, virt) #E = Enuke+Eone+Etwo E = Enuke + Eel Etwo = Eel - 2 * Eone # Update CI coefs coeffs = update_gvb_ci_coeffs(Uocc, h, Js, Ks, f, a, b, ncore, nopen, npair, orbs_per_shell, verbose) f, a, b = fab(ncore, nopen, npair, coeffs) if verbose: print("---- %d : %10.4f %10.4f %10.4f %10.4f" % ((it + 1), E, Enuke, Eone, Etwo)) if np.isclose(E, Eold): if verbose: print("Energy converged") break Eold = E else: print("Maximum iterations (%d) reached without convergence" % (maxiter)) if return_orbs: return E, U return E