def test_oh(self): bfs = basisset(oh,'sto-3g') hamiltonian = uhf(bfs) iterator = USCFIterator(hamiltonian) iterator.converge() self.assertTrue(iterator.converged) self.assertAlmostEqual(iterator.energy, -74.360233544941, 4)
def test_li(self): bfs = basisset(li,'sto-3g') hamiltonian = uhf(bfs) iterator = USCFIterator(hamiltonian) iterator.converge() self.assertTrue(iterator.converged) self.assertAlmostEqual(iterator.energy, -7.315525981280, 6)
def make_test_integrals_pyquante(args, mol, mol_basis): """A driver for making integrals for test comparisons using PyQuante 1 and 2. """ solver = pyquante2.uhf(mol, mol_basis) solver.converge(tol=1e-10, maxiters=1000) i1 = solver.i1 C = solver.orbsa D = np.dot(C[:, :mol.nocc()], C[:, :mol.nocc()].transpose()) # Save the one-electron integral matrices to disk. np.savetxt('pyquante2.S.txt', i1.S) np.savetxt('pyquante2.T.txt', i1.T) np.savetxt('pyquante2.V.txt', i1.V) np.savetxt('pyquante2.D.txt', D) # Save the energies to disk. np.savetxt('pyquante2.total_energy.txt', np.array([solver.energy])) np.savetxt('pyquante2.nuclear_repulsion_energy.txt', np.array([mol.nuclear_repulsion()])) # That was all pyquante2 stuff. Now for PyQuante! mol1 = pyquante_2_to_1_molecule(mol) bfs1 = pyquante_2_to_1_basis(mol_basis.bfs) from PyQuante.Ints import getFC for iat, at in enumerate(mol1.atoms, 1): FC_atom = getFC(bfs1, at.r) np.savetxt('PyQuante.FC{}.txt'.format(iat), FC_atom)
def run_pyquante(self): """Runs the PyQuante calculation. This method is part of the public interface to allow the user to easily overwrite it in a subclass to further tailor the behavior to some specific use case. Raises: QiskitNatureError: If an invalid HF method type was supplied. """ # pylint: disable=import-error from pyquante2 import rhf, uhf, rohf, basisset self._bfs = basisset(self._mol, self.basis.value) if self.method == MethodType.RHF: self._calc = rhf(self._mol, self._bfs) elif self.method == MethodType.ROHF: self._calc = rohf(self._mol, self._bfs) elif self.method == MethodType.UHF: self._calc = uhf(self._mol, self._bfs) else: raise QiskitNatureError(f"Invalid method type: {self.method}") self._calc.converge(tol=self.tol, maxiters=self.maxiters) logger.debug("PyQuante2 processing information:\n%s", self._calc)
def test_CF3(self): """CF3 radical""" CF3 = read_xyz('./molfiles/CF3.xyz') bfs = basisset(CF3,'sto-3g') hamiltonian = uhf(bfs, twoe_factory=libint_twoe_integrals) iterator = USCFIterator(hamiltonian) iterator.converge() self.assertTrue(iterator.converged) self.assertAlmostEqual(iterator.energy, -331.480688906400, 5)
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 _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 test_li_uhf(self): from pyquante2 import li bfs = basisset(li, 'sto3g') solver = uhf(li, bfs) Es = solver.converge() self.assertAlmostEqual(solver.energy, -7.31552585354, match_digits)
def test_oh_uhf(self): from pyquante2 import oh bfs = basisset(oh, 'sto3g') solver = uhf(oh, bfs) Es = solver.converge() self.assertAlmostEqual(solver.energy, -74.3602416207, match_digits)
def test_li(self): from pyquante2 import li bfs = basisset(li,'sto3g') solver = uhf(li,bfs) Es = solver.converge() self.assertAlmostEqual(solver.energy,-7.2301642412807379)
def test_oh(self): from pyquante2 import oh bfs = basisset(oh,'sto3g') solver = uhf(oh,bfs) Es = solver.converge() self.assertAlmostEqual(solver.energy,-74.14666861386641,6)
def main(args): mol = molecule([(1, 0.000, 0.000, 0.000), (8, 0.000, 0.000, 0.9697)], units='Angstrom', charge=0, multiplicity=2, name='hydroxyl_radical') mol_basis = pyquante2.basisset(mol, 'STO-3G'.lower()) solver = pyquante2.uhf(mol, mol_basis) solver.converge(tol=1e-11, maxiters=1000) print(solver) C_alph = solver.orbsa C_beta = solver.orbsb NOa = mol.nup() NOb = mol.ndown() D_alph = np.dot(C_alph[:, :NOa], C_alph[:, :NOa].transpose()) D_beta = np.dot(C_beta[:, :NOb], C_beta[:, :NOb].transpose()) D = D_alph + D_beta if args.debug: print(D_alph) print(D_beta) # This is origin used for the multipole analysis. # origin = np.array([0.0, 0.0, 0.0]) origin = calc_center_of_mass(mol) print('Origin used: ({}, {}, {})'.format(*origin)) M100_AO = makeM(mol_basis.bfs, origin, [1, 0, 0]) M010_AO = makeM(mol_basis.bfs, origin, [0, 1, 0]) M001_AO = makeM(mol_basis.bfs, origin, [0, 0, 1]) M100_MO = D * M100_AO M010_MO = D * M010_AO M001_MO = D * M001_AO if args.debug: print('M100_AO') print(M100_AO) print('M010_AO') print(M010_AO) print('M001_AO') print(M001_AO) print('M100_MO') print(M100_MO) print('M010_MO') print(M010_MO) print('M001_MO') print(M001_MO) dipole_electronic_atomic_units = -np.array([np.sum(M100_MO), np.sum(M010_MO), np.sum(M001_MO)]) convfac_au_to_debye = 2.541746230211 dipole_nuclear_atomic_units = nuclear_dipole_contribution(mol, origin) dipole_total_atomic_units = dipole_nuclear_atomic_units + dipole_electronic_atomic_units dipole_magnitude_atomic_units = npl.norm(dipole_total_atomic_units) dipole_magnitude_debye = convfac_au_to_debye * dipole_magnitude_atomic_units print('=============') print('Dipole') print('=============') print('electronic (a.u.) {:8.5f} {:8.5f} {:8.5f}'.format(*dipole_electronic_atomic_units)) print(' nuclear (a.u.) {:8.5f} {:8.5f} {:8.5f}'.format(*dipole_nuclear_atomic_units)) print(' total (a.u.) {:8.5f} {:8.5f} {:8.5f}'.format(*dipole_total_atomic_units)) print('Dipole moment magnitude') print(' {:8.5f} a.u'.format(dipole_magnitude_atomic_units)) print(' {:8.5f} D'.format(dipole_magnitude_debye)) print('=============') print('Origins') print('=============') print(' center of mass: {:f} {:f} {:f}'.format(*calc_center_of_mass(mol)))
def test_dipole_hydroxyl_radical_HF_STO_3G(): """Example: OH^{.}, neutral doublet, UHF/STO-3G """ qchem_final_energy = -74.3626375184 # Dipole Moment (Debye) # X 0.0000 Y -0.0000 Z -1.2788 # Tot 1.2788 qchem_total_components_debye = np.array([0.0000, 0.0000, -1.2788]) qchem_total_norm_debye = 1.2788 dalton_final_energy = -74.361530725817 # Dipole moment # ------------- # au Debye C m (/(10**-30) # 0.502283 1.276676 4.258534 # Dipole moment components # ------------------------ # au Debye C m (/(10**-30) # x -0.00000000 -0.00000000 -0.00000000 # y -0.00000000 -0.00000000 -0.00000000 # z -0.50228316 -1.27667636 -4.25853394 # Units: 1 a.u. = 2.54175 Debye # 1 a.u. = 8.47835 (10**-30) C m (SI) dalton_total_components_debye = np.array([0.0, 0.0, -1.27667636]) dalton_total_norm_debye = 1.276676 dalton_total_components_au = np.array([0.0, 0.0, -0.50228316]) dalton_total_norm_au = 0.502283 dalton_center_of_mass_au = np.array([0.0, 0.0, 1.723849254747]) # ORCA uses the center of mass by default. orca_final_energy = -74.362637379044 # Electronic contribution: 0.00000 -0.00000 0.35185 # Nuclear contribution : 0.00000 0.00000 -0.85498 # ----------------------------------------- # Total Dipole Moment : 0.00000 -0.00000 -0.50312 # ----------------------------------------- # Magnitude (a.u.) : 0.50312 # Magnitude (Debye) : 1.27884 orca_electronic_components_au = np.array([0.0, 0.0, 0.35185]) orca_nuclear_components_au = np.array([0.0, 0.0, -0.85498]) orca_total_components_au = np.array([0.0, 0.0, -0.50312]) assert np.all( ((orca_nuclear_components_au + orca_electronic_components_au) - orca_total_components_au) < 1.0e-14) orca_total_norm_au = 0.50312 assert abs(orca_total_norm_au - npl.norm(orca_total_components_au)) < 1.0e-5 orca_total_norm_debye = 1.27884 # prop_orca_coe.out # 505:Coordinates of the origin ... 0.00000000 -0.00000000 1.68476265 (bohrs) # prop_orca_com.out # 505:Coordinates of the origin ... 0.00000000 0.00000000 1.72385761 (bohrs) # prop_orca_con.out # 505:Coordinates of the origin ... 0.00000000 0.00000000 1.62885994 (bohrs) orca_center_of_electronic_charge_au = np.array( [0.00000000, 0.00000000, 1.68476265]) orca_center_of_mass_au = np.array([0.00000000, 0.00000000, 1.72385761]) orca_center_of_nuclear_charge_au = np.array( [0.00000000, 0.00000000, 1.62885994]) psi4_final_energy = -74.3626375190713986 # Origin is the Cartesian origin # Nuclear Dipole Moment: (a.u.) # X: 0.0000 Y: 0.0000 Z: 14.6597 # Electronic Dipole Moment: (a.u.) # X: -0.0000 Y: 0.0000 Z: -15.1629 # Dipole Moment: (a.u.) # X: -0.0000 Y: 0.0000 Z: -0.5031 Total: 0.5031 # Dipole Moment: (Debye) # X: -0.0000 Y: 0.0000 Z: -1.2788 Total: 1.2788 psi4_nuclear_components_au = np.array([0.0, 0.0, 14.6597]) psi4_electronic_components_au = np.array([0.0, 0.0, -15.1629]) psi4_total_components_au = np.array([0.0, 0.0, -0.5031]) assert np.all( ((psi4_nuclear_components_au + psi4_electronic_components_au) - psi4_total_components_au) < 1.0e-14) psi4_total_norm_au = 0.5031 assert abs(psi4_total_norm_au - npl.norm(psi4_total_components_au)) < 1.0e-4 psi4_total_components_debye = np.array([0.0, 0.0, -1.2788]) psi4_total_norm_debye = 1.2788 assert abs(psi4_total_norm_debye - npl.norm(psi4_total_components_debye)) < 1.0e-4 mol = molecule([(1, 0.000, 0.000, 0.000), (8, 0.000, 0.000, 0.9697)], units='Angstrom', charge=0, multiplicity=2, name='hydroxyl_radical') mol_basis = pyquante2.basisset(mol, 'STO-3G'.lower()) solver = pyquante2.uhf(mol, mol_basis) solver.converge(tol=1e-11, maxiters=1000) C_alph = solver.orbsa C_beta = solver.orbsb NOa = mol.nup() NOb = mol.ndown() D_alph = np.dot(C_alph[:, :NOa], C_alph[:, :NOa].T) D_beta = np.dot(C_beta[:, :NOb], C_beta[:, :NOb].T) D = D_alph + D_beta nuccoords = np.array([atom.r for atom in mol.atoms]) nuccharges = np.array([atom.Z for atom in mol.atoms])[..., np.newaxis] masses = get_isotopic_masses(nuccharges[:, 0]) origin_zero = np.array([0.0, 0.0, 0.0]) ref = psi4_nuclear_components_au res = nuclear_dipole_contribution(nuccoords, nuccharges, origin_zero) abs_diff = np.absolute(ref - res) assert np.all(abs_diff < 1.0e-4) ref = psi4_electronic_components_au res = electronic_dipole_contribution_pyquante(D, mol_basis, origin_zero) abs_diff = np.absolute(ref - res) assert np.all(abs_diff < 1.0e-4) res1 = nuclear_dipole_contribution(nuccoords, nuccharges, origin_zero) res2 = nuclear_dipole_contribution_pyquante(mol, origin_zero) assert np.all((res1 - res2) < 1.0e-15) ref = dalton_center_of_mass_au res = calc_center_of_mass_pyquante(mol) abs_diff = np.absolute(ref - res) assert np.all(abs_diff < 1.0e-6) com = res assert np.all(np.equal(np.sign(com), np.sign(orca_center_of_mass_au))) assert np.all(np.equal(np.sign(com), np.sign(ref))) res1 = calc_center_of_mass_pyquante(mol) res2 = calc_center_of_mass(nuccoords, masses) assert np.all((res1 - res2) < 1.0e-15) ncc = calc_center_of_nuclear_charge(nuccoords, nuccharges) assert np.all( np.equal(np.sign(ncc), np.sign(orca_center_of_nuclear_charge_au))) assert np.all((ncc - orca_center_of_nuclear_charge_au) < 1.0e-8) ecc = screen(calc_center_of_electronic_charge_pyquante(D, mol_basis)) assert np.all( np.equal(np.sign(ecc), np.sign(orca_center_of_electronic_charge_au))) assert np.all((ecc - orca_center_of_electronic_charge_au) < 1.0e-8) origin_zero = calculate_origin_pyquante('zero', nuccoords, nuccharges, D, mol_basis, do_print=True) dipole_zero = calculate_dipole_pyquante(nuccoords, nuccharges, origin_zero, D, mol_basis, do_print=True) origin_com = calculate_origin_pyquante('com', nuccoords, nuccharges, D, mol_basis, do_print=True) dipole_com = calculate_dipole_pyquante(nuccoords, nuccharges, origin_com, D, mol_basis, do_print=True) origin_ncc = calculate_origin_pyquante('ncc', nuccoords, nuccharges, D, mol_basis, do_print=True) dipole_ncc = calculate_dipole_pyquante(nuccoords, nuccharges, origin_ncc, D, mol_basis, do_print=True) origin_ecc = calculate_origin_pyquante('ecc', nuccoords, nuccharges, D, mol_basis, do_print=True) dipole_ecc = calculate_dipole_pyquante(nuccoords, nuccharges, origin_ecc, D, mol_basis, do_print=True) # For an uncharged system, these should all be identical. my_ref = np.array([0.0, 0.0, -0.5031245309396919]) for res in (dipole_zero, dipole_com, dipole_ncc, dipole_ecc): assert (np.absolute(my_ref - res) < 1.0e-8).all() return