Пример #1
0
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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
    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)
Пример #5
0
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
Пример #6
0
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
Пример #7
0
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_