def pyq2_dft(atomtuples=[(2,0,0,0)],basis = '6-31G**',maxit=10,xcname='svwn'): import pyquante2 as pyq2 print ("pyq2 DFT run") geo = pyq2.molecule(atomtuples) bfs = pyq2.basisset(geo,name=basis) i1 = pyq2.onee_integrals(bfs,geo) i2 = pyq2.twoe_integrals(bfs) grid = pyq2.grid(geo) h = i1.T + i1.V orbe,orbs = pyq2.geigh(h,i1.S) eold = 0 grid.setbfamps(bfs) E0 = geo.nuclear_repulsion() for i in range(maxit): D = pyq2.dmat(orbs,geo.nocc()) E1 = 2*pyq2.trace2(h,D) J = i2.get_j(D) Ej = 2*pyq2.trace2(J,D) Exc,Vxc = pyq2.get_xc(grid,0.5*D,xcname=xcname) energy = E0+E1+Ej+Exc F = h+2*J+Vxc orbe,orbs = pyq2.geigh(F,i1.S) print (i,energy,E1,Ej,Exc,E0) if np.isclose(energy,eold): break eold = energy return energy
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 pyq2_rohf(atomtuples=[(2, 0, 0, 0)], basis='6-31G**', maxit=10, xcname='svwn', mult=3): import pyquante2 as pyq2 print("pyq2 ROHF run") geo = pyq2.molecule(atomtuples, multiplicity=mult) bfs = pyq2.basisset(geo, name=basis) i1 = pyq2.onee_integrals(bfs, geo) i2 = pyq2.twoe_integrals(bfs) h = i1.T + i1.V orbe, orbs = pyq2.geigh(h, i1.S) eold = 0 E0 = geo.nuclear_repulsion() nalpha, nbeta = geo.nup(), geo.ndown() norbs = len(bfs) for i in range(maxit): Da = pyq2.dmat(orbs, nalpha) Db = pyq2.dmat(orbs, nbeta) E1 = 0.5 * pyq2.trace2(Da + Db, h) 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 E2 = 0.5 * (pyq2.trace2(Fa, Da) + pyq2.trace2(Fb, Db)) energy = E0 + E1 + E2 print(energy, E1, E2, E0) Fa = pyq2.utils.simx(Fa, orbs) Fb = pyq2.utils.simx(Fb, orbs) F = 0.5 * (Fa + Fb) K = Fb - Fa # Make explicit slice objects to simplify this do = slice(0, nbeta) so = slice(nbeta, nalpha) uo = slice(nalpha, norbs) F[do, do] -= K[do, do] F[uo, uo] += K[uo, uo] F[do, so] += 0.5 * K[do, so] F[so, do] += 0.5 * K[so, do] F[so, uo] -= 0.5 * K[so, uo] F[uo, so] -= 0.5 * K[uo, so] E, cmo = np.linalg.eigh(F) orbs = np.dot(orbs, cmo) return
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 pyq2_rohf(atomtuples=[(2,0,0,0)],basis = '6-31G**',maxit=10,xcname='svwn', mult=3): import pyquante2 as pyq2 print ("pyq2 ROHF run") geo = pyq2.molecule(atomtuples,multiplicity=mult) bfs = pyq2.basisset(geo,name=basis) i1 = pyq2.onee_integrals(bfs,geo) i2 = pyq2.twoe_integrals(bfs) h = i1.T + i1.V orbe,orbs = pyq2.geigh(h,i1.S) eold = 0 E0 = geo.nuclear_repulsion() nalpha,nbeta = geo.nup(),geo.ndown() norbs = len(bfs) for i in range(maxit): Da = pyq2.dmat(orbs,nalpha) Db = pyq2.dmat(orbs,nbeta) E1 = 0.5*pyq2.trace2(Da+Db,h) 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 E2 = 0.5*(pyq2.trace2(Fa,Da)+pyq2.trace2(Fb,Db)) energy = E0+E1+E2 print (energy,E1,E2,E0) Fa = pyq2.utils.simx(Fa,orbs) Fb = pyq2.utils.simx(Fb,orbs) F = 0.5*(Fa+Fb) K = Fb-Fa # Make explicit slice objects to simplify this do = slice(0,nbeta) so = slice(nbeta,nalpha) uo = slice(nalpha,norbs) F[do,do] -= K[do,do] F[uo,uo] += K[uo,uo] F[do,so] += 0.5*K[do,so] F[so,do] += 0.5*K[so,do] F[so,uo] -= 0.5*K[so,uo] F[uo,so] -= 0.5*K[uo,so] E,cmo = np.linalg.eigh(F) orbs = np.dot(orbs,cmo) return
def pyq2_dft(atomtuples=[(2, 0, 0, 0)], basis='6-31G**', maxit=10, xcname='svwn'): import pyquante2 as pyq2 print("pyq2 DFT run") geo = pyq2.molecule(atomtuples) bfs = pyq2.basisset(geo, name=basis) i1 = pyq2.onee_integrals(bfs, geo) i2 = pyq2.twoe_integrals(bfs) grid = pyq2.grid(geo) h = i1.T + i1.V orbe, orbs = pyq2.geigh(h, i1.S) eold = 0 grid.setbfamps(bfs) E0 = geo.nuclear_repulsion() for i in range(maxit): D = pyq2.dmat(orbs, geo.nocc()) E1 = 2 * pyq2.trace2(h, D) J = i2.get_j(D) Ej = 2 * pyq2.trace2(J, D) Exc, Vxc = pyq2.get_xc(grid, 0.5 * D, xcname=xcname) energy = E0 + E1 + Ej + Exc F = h + 2 * J + Vxc orbe, orbs = pyq2.geigh(F, i1.S) print(i, energy, E1, Ej, Exc, E0) if np.isclose(energy, eold): break eold = energy return 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_