示例#1
0
def init_guess_by_chkfile(mol, chkfile_name, project=None):
    '''Read SCF chkfile and make the density matrix for UHF initial guess.

    Kwargs:
        project : None or bool
            Whether to project chkfile's orbitals to the new basis.  Note when
            the geometry of the chkfile and the given molecule are very
            different, this projection can produce very poor initial guess.
            In PES scanning, it is recommended to swith off project.

            If project is set to None, the projection is only applied when the
            basis sets of the chkfile's molecule are different to the basis
            sets of the given molecule (regardless whether the geometry of
            the two molecules are different).  Note the basis sets are
            considered to be different if the two molecules are derived from
            the same molecule with different ordering of atoms.
    '''
    from pyscf.scf import addons
    chk_mol, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_mol, mol)

    # Check whether the two molecules are similar
    im1 = scipy.linalg.eigvalsh(mol.inertia_moment())
    im2 = scipy.linalg.eigvalsh(chk_mol.inertia_moment())
    # im1+1e-7 to avoid 'divide by zero' error
    if abs((im1 - im2) / (im1 + 1e-7)).max() > 0.01:
        logger.warn(
            mol, "Large deviations found between the input "
            "molecule and the molecule from chkfile\n"
            "Initial guess density matrix may have large error.")

    if project:
        s = hf.get_ovlp(mol)

    def fproj(mo):
        if project:
            mo = addons.project_mo_nr2nr(chk_mol, mo, mol)
            norm = numpy.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= numpy.sqrt(norm)
        return mo

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if getattr(mo[0], 'ndim', None) == 1:  # RHF
        if numpy.iscomplexobj(mo):
            raise NotImplementedError(
                'TODO: project DHF orbital to UHF orbital')
        mo_coeff = fproj(mo)
        mo_occa = (mo_occ > 1e-8).astype(numpy.double)
        mo_occb = mo_occ - mo_occa
        dm = make_rdm1([mo_coeff, mo_coeff], [mo_occa, mo_occb])
    else:  #UHF
        if getattr(mo[0][0], 'ndim', None) == 2:  # KUHF
            logger.warn(
                mol, 'k-point UHF results are found.  Density matrix '
                'at Gamma point is used for the molecular SCF initial guess')
            mo = mo[0]
        dm = make_rdm1([fproj(mo[0]), fproj(mo[1])], mo_occ)
    return dm
示例#2
0
文件: uhf.py 项目: sunqm/pyscf
def init_guess_by_chkfile(mol, chkfile_name, project=None):
    '''Read SCF chkfile and make the density matrix for UHF initial guess.

    Kwargs:
        project : None or bool
            Whether to project chkfile's orbitals to the new basis.  Note when
            the geometry of the chkfile and the given molecule are very
            different, this projection can produce very poor initial guess.
            In PES scanning, it is recommended to swith off project.

            If project is set to None, the projection is only applied when the
            basis sets of the chkfile's molecule are different to the basis
            sets of the given molecule (regardless whether the geometry of
            the two molecules are different).  Note the basis sets are
            considered to be different if the two molecules are derived from
            the same molecule with different ordering of atoms.
    '''
    from pyscf.scf import addons
    chk_mol, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_mol, mol)

    # Check whether the two molecules are similar
    im1 = scipy.linalg.eigvalsh(mol.inertia_moment())
    im2 = scipy.linalg.eigvalsh(chk_mol.inertia_moment())
    # im1+1e-7 to avoid 'divide by zero' error
    if abs((im1-im2)/(im1+1e-7)).max() > 0.01:
        logger.warn(mol, "Large deviations found between the input "
                    "molecule and the molecule from chkfile\n"
                    "Initial guess density matrix may have large error.")

    if project:
        s = hf.get_ovlp(mol)

    def fproj(mo):
        if project:
            mo = addons.project_mo_nr2nr(chk_mol, mo, mol)
            norm = numpy.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= numpy.sqrt(norm)
        return mo

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if getattr(mo[0], 'ndim', None) == 1:  # RHF
        if numpy.iscomplexobj(mo):
            raise NotImplementedError('TODO: project DHF orbital to UHF orbital')
        mo_coeff = fproj(mo)
        mo_occa = (mo_occ>1e-8).astype(numpy.double)
        mo_occb = mo_occ - mo_occa
        dm = make_rdm1([mo_coeff,mo_coeff], [mo_occa,mo_occb])
    else: #UHF
        if getattr(mo[0][0], 'ndim', None) == 2:  # KUHF
            logger.warn(mol, 'k-point UHF results are found.  Density matrix '
                        'at Gamma point is used for the molecular SCF initial guess')
            mo = mo[0]
        dm = make_rdm1([fproj(mo[0]),fproj(mo[1])], mo_occ)
    return dm
示例#3
0
文件: dhf.py 项目: ssthurai/pyscf
def init_guess_by_chkfile(mol, chkfile_name, project=None):
    '''Read SCF chkfile and make the density matrix for 4C-DHF initial guess.

    Kwargs:
        project : None or bool
            Whether to project chkfile's orbitals to the new basis.  Note when
            the geometry of the chkfile and the given molecule are very
            different, this projection can produce very poor initial guess.
            In PES scanning, it is recommended to swith off project.

            If project is set to None, the projection is only applied when the
            basis sets of the chkfile's molecule are different to the basis
            sets of the given molecule (regardless whether the geometry of
            the two molecules are different).  Note the basis sets are
            considered to be different if the two molecules are derived from
            the same molecule with different ordering of atoms.
    '''
    from pyscf.scf import addons
    chk_mol, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_mol, mol)

    # Check whether the two molecules are similar
    def inertia_momentum(mol):
        im = gto.inertia_momentum(mol._atom, mol.atom_charges(),
                                  mol.atom_coords())
        return scipy.linalg.eigh(im)[0]

    if abs(inertia_momentum(mol) - inertia_momentum(chk_mol)).sum() > 0.5:
        logger.warn(
            mol, "Large deviations found between the input "
            "molecule and the molecule from chkfile\n"
            "Initial guess density matrix may have large error.")

    if project:
        s = get_ovlp(mol)

    def fproj(mo):
        #TODO: check if mo is GHF orbital
        if project:
            mo = addons.project_mo_r2r(chk_mol, mo, mol)
            norm = numpy.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= numpy.sqrt(norm)
        return mo

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if numpy.iscomplexobj(mo[0]):  # DHF
        dm = make_rdm1(fproj(mo), mo_occ)
    else:
        if mo[0].ndim == 1:  # nr-RHF
            dm = reduce(numpy.dot, (mo * mo_occ, mo.T))
        else:  # nr-UHF
            dm = reduce(numpy.dot, (mo[0]*mo_occ[0], mo[0].T)) \
               + reduce(numpy.dot, (mo[1]*mo_occ[1], mo[1].T))
        dm = _proj_dmll(chk_mol, dm, mol)
    return dm
示例#4
0
def init_guess_by_chkfile(cell, chkfile_name, project=None, kpt=None):
    '''Read the HF results from checkpoint file and make the density matrix
    for UHF initial guess.

    Returns:
        Density matrix, (nao,nao) ndarray
    '''
    from pyscf import gto
    chk_cell, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_cell, cell)

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if kpt is None:
        kpt = np.zeros(3)
    if 'kpt' in scf_rec:
        chk_kpt = scf_rec['kpt']
    elif 'kpts' in scf_rec:
        kpts = scf_rec['kpts']  # the closest kpt from KRHF results
        where = np.argmin(lib.norm(kpts - kpt, axis=1))
        chk_kpt = kpts[where]
        if getattr(mo[0], 'ndim', None) == 2:  # KRHF
            mo = mo[where]
            mo_occ = mo_occ[where]
        else:  # KUHF
            mo = [mo[0][where], mo[1][where]]
            mo_occ = [mo_occ[0][where], mo_occ[1][where]]
    else:  # from molecular code
        chk_kpt = np.zeros(3)

    if project:
        s = cell.pbc_intor('int1e_ovlp', kpt=kpt)

    def fproj(mo):
        if project:
            mo = addons.project_mo_nr2nr(chk_cell, mo, cell, chk_kpt - kpt)
            norm = np.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= np.sqrt(norm)
        return mo

    if getattr(mo, 'ndim', None) == 2:
        mo = fproj(mo)
        mo_occa = (mo_occ > 1e-8).astype(np.double)
        mo_occb = mo_occ - mo_occa
        dm = mol_uhf.make_rdm1([mo, mo], [mo_occa, mo_occb])
    else:  # UHF
        dm = mol_uhf.make_rdm1([fproj(mo[0]), fproj(mo[1])], mo_occ)

    # Real DM for gamma point
    if kpt is None or np.allclose(kpt, 0):
        dm = dm.real
    return dm
示例#5
0
文件: uhf.py 项目: chrinide/pyscf
def init_guess_by_chkfile(cell, chkfile_name, project=None, kpt=None):
    '''Read the HF results from checkpoint file and make the density matrix
    for UHF initial guess.

    Returns:
        Density matrix, (nao,nao) ndarray
    '''
    from pyscf import gto
    chk_cell, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_cell, cell)

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if kpt is None:
        kpt = np.zeros(3)
    if 'kpt' in scf_rec:
        chk_kpt = scf_rec['kpt']
    elif 'kpts' in scf_rec:
        kpts = scf_rec['kpts'] # the closest kpt from KRHF results
        where = np.argmin(lib.norm(kpts-kpt, axis=1))
        chk_kpt = kpts[where]
        if getattr(mo[0], 'ndim', None) == 2:  # KRHF
            mo = mo[where]
            mo_occ = mo_occ[where]
        else:  # KUHF
            mo = [mo[0][where], mo[1][where]]
            mo_occ = [mo_occ[0][where], mo_occ[1][where]]
    else:  # from molecular code
        chk_kpt = np.zeros(3)

    if project:
        s = cell.pbc_intor('int1e_ovlp', kpt=kpt)
    def fproj(mo):
        if project:
            mo = addons.project_mo_nr2nr(chk_cell, mo, cell, chk_kpt-kpt)
            norm = np.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= np.sqrt(norm)
        return mo

    if getattr(mo, 'ndim', None) == 2:
        mo = fproj(mo)
        mo_occa = (mo_occ>1e-8).astype(np.double)
        mo_occb = mo_occ - mo_occa
        dm = mol_uhf.make_rdm1([mo,mo], [mo_occa,mo_occb])
    else:  # UHF
        dm = mol_uhf.make_rdm1([fproj(mo[0]),fproj(mo[1])], mo_occ)

    # Real DM for gamma point
    if kpt is None or np.allclose(kpt, 0):
        dm = dm.real
    return dm
示例#6
0
文件: dhf.py 项目: chrinide/pyscf
def init_guess_by_chkfile(mol, chkfile_name, project=None):
    '''Read SCF chkfile and make the density matrix for 4C-DHF initial guess.

    Kwargs:
        project : None or bool
            Whether to project chkfile's orbitals to the new basis.  Note when
            the geometry of the chkfile and the given molecule are very
            different, this projection can produce very poor initial guess.
            In PES scanning, it is recommended to swith off project.

            If project is set to None, the projection is only applied when the
            basis sets of the chkfile's molecule are different to the basis
            sets of the given molecule (regardless whether the geometry of
            the two molecules are different).  Note the basis sets are
            considered to be different if the two molecules are derived from
            the same molecule with different ordering of atoms.
    '''
    from pyscf.scf import addons
    chk_mol, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_mol, mol)

    # Check whether the two molecules are similar
    if abs(mol.inertia_moment() - chk_mol.inertia_moment()).sum() > 0.5:
        logger.warn(mol, "Large deviations found between the input "
                    "molecule and the molecule from chkfile\n"
                    "Initial guess density matrix may have large error.")

    if project:
        s = get_ovlp(mol)

    def fproj(mo):
#TODO: check if mo is GHF orbital
        if project:
            mo = addons.project_mo_r2r(chk_mol, mo, mol)
            norm = numpy.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= numpy.sqrt(norm)
        return mo

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if numpy.iscomplexobj(mo[0]):  # DHF
        dm = make_rdm1(fproj(mo), mo_occ)
    else:
        if mo[0].ndim == 1: # nr-RHF
            dm = reduce(numpy.dot, (mo*mo_occ, mo.T))
        else: # nr-UHF
            dm = reduce(numpy.dot, (mo[0]*mo_occ[0], mo[0].T)) \
               + reduce(numpy.dot, (mo[1]*mo_occ[1], mo[1].T))
        dm = _proj_dmll(chk_mol, dm, mol)
    return dm
示例#7
0
    def test_remove_ovlp(self):
        test_mol_16 = helpers.concat_mols([self.mol1, self.mol6])

        corr_mol16 = gto.M()
        corr_mol16.atom = """
        H-0   -1.06  0.0   0.0
        C-0   0.0   0.0   0.0
        C-1   1.2   0.0   0.0
        H-1   2.26  0.0   0.0
        """
        corr_mol16.basis = {
            'C-0': 'sto-3g',
            'H-0': 'sto-3g',
            'C-1': '6-311g',
            'H-1': '6-311g'
        }

        with self.assertRaises(AssertionError):
            test_mol_166 = helpers.concat_mols([test_mol_16, self.mol6])

        test_mol_378 = helpers.concat_mols([self.mol3, self.mol7, self.mol8])
        corr_mol378 = gto.M()
        corr_mol378.atom = """
        O-0   -1.16   0.0   0.0
        GHOST-C-1 2.0 0.0 0.0
        O-1    0.0   1.16   0.0
        C-2    0.0   0.0   0.0
        """
        corr_mol378.basis = {
            'O-0': 'sto-3g',
            'O-1': 'cc-pVTZ',
            'GHOST-C-1': 'aug-cc-pVDZ',
            'C-2': 'cc-pVDZ'
        }
        corr_mol378.build()
        self.assertTrue(gto.same_basis_set(test_mol_378, corr_mol378))
        self.assertTrue(gto.same_mol(test_mol_378, corr_mol378))
示例#8
0
    def test_basic(self):
        test_mol_12 = helpers.concat_mols([self.mol1, self.mol2])

        corr_mol12 = gto.M()
        corr_mol12.atom = """
        H-0   -1.06  0.0   0.0
        C-0   0.0   0.0   0.0
        C-1   1.2   0.0   0.0
        H-1   2.26  0.0   0.0
        """
        corr_mol12.spin = 0
        corr_mol12.basis = {
            'C-0': 'sto-3g',
            'H-0': 'sto-3g',
            'C-1': '6-311g',
            'H-1': '6-311g'
        }
        corr_mol12.build()

        self.assertEqual(test_mol_12.spin, corr_mol12.spin)
        self.assertTrue(gto.same_mol(test_mol_12, corr_mol12))
        self.assertTrue(gto.same_mol(test_mol_12, corr_mol12))

        test_mol_345 = helpers.concat_mols([self.mol3, self.mol4, self.mol5])

        corr_mol345 = gto.M()
        corr_mol345.atom = """
        O-0   -1.16   0.0   0.0
        C-1   0.0   0.0   0.0
        O-2   1.16   0.0   0.0
        """
        corr_mol345.basis = {'O-0': 'sto-3g', 'C-1': '6-311g', 'O-2': 'sto-3g'}
        corr_mol345.build()

        self.assertTrue(gto.same_basis_set(test_mol_345, corr_mol345))
        self.assertTrue(gto.same_mol(test_mol_345, corr_mol345))
示例#9
0
文件: addons.py 项目: zzy2014/pyscf
def project_init_guess(casscf, init_mo, prev_mol=None):
    '''Project the given initial guess to the current CASSCF problem.  The
    projected initial guess has two parts.  The core orbitals are directly
    taken from the Hartree-Fock orbitals, and the active orbitals are
    projected from the given initial guess.

    Args:
        casscf : an :class:`CASSCF` or :class:`CASCI` object

        init_mo : ndarray or list of ndarray
            Initial guess orbitals which are not orth-normal for the current
            molecule.  When the casscf is UHF-CASSCF, the init_mo needs to be
            a list of two ndarrays, for alpha and beta orbitals

    Kwargs:
        prev_mol : an instance of :class:`Mole`
            If given, the inital guess orbitals are associated to the geometry
            and basis of prev_mol.  Otherwise, the orbitals are based of
            the geometry and basis of casscf.mol

    Returns:
        New orthogonal initial guess orbitals with the core taken from
        Hartree-Fock orbitals and projected active space from original initial
        guess orbitals

    Examples:

    .. code:: python

        import numpy
        from pyscf import gto, scf, mcscf
        mol = gto.Mole()
        mol.build(atom='H 0 0 0; F 0 0 0.8', basis='ccpvdz', verbose=0)
        mf = scf.RHF(mol)
        mf.scf()
        mc = mcscf.CASSCF(mf, 6, 6)
        mo = mcscf.sort_mo(mc, mf.mo_coeff, [3,4,5,6,8,9])
        print('E(0.8) = %.12f' % mc.kernel(mo)[0])
        init_mo = mc.mo_coeff
        for b in numpy.arange(1.0, 3., .2):
            mol.atom = [['H', (0, 0, 0)], ['F', (0, 0, b)]]
            mol.build(0, 0)
            mf = scf.RHF(mol)
            mf.scf()
            mc = mcscf.CASSCF(mf, 6, 6)
            mo = mcscf.project_init_guess(mc, init_mo)
            print('E(%2.1f) = %.12f' % (b, mc.kernel(mo)[0]))
            init_mo = mc.mo_coeff
    '''
    from pyscf import lo

    def project(mfmo, init_mo, ncore, s):
        s_init_mo = numpy.einsum('pi,pi->i', init_mo.conj(), s.dot(init_mo))
        if abs(s_init_mo -
               1).max() < 1e-7 and mfmo.shape[1] == init_mo.shape[1]:
            # Initial guess orbitals are orthonormal
            return init_mo
# TODO: test whether the canonicalized orbitals are better than the projected orbitals
# Be careful that the ordering of the canonicalized orbitals may be very different
# to the CASSCF orbitals.
#        else:
#            fock = casscf.get_fock(mc, init_mo, casscf.ci)
#            return casscf._scf.eig(fock, s)[1]

        nocc = ncore + casscf.ncas
        if ncore > 0:
            mo0core = init_mo[:, :ncore]
            s1 = reduce(numpy.dot, (mfmo.T, s, mo0core))
            s1core = reduce(numpy.dot, (mo0core.T, s, mo0core))
            coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T))
            coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore])
            logger.debug(casscf, 'Core indices %s', coreidx)
            logger.debug(casscf, 'Core components %s', coreocc[coreidx])
            # take HF core
            mocore = mfmo[:, coreidx]

            # take projected CAS space
            mocas = init_mo[:,ncore:nocc] \
                  - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc]))
            mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s)
        else:
            mocc = lo.orth.vec_lowdin(init_mo[:, :nocc], s)

        # remove core and active space from rest
        if mocc.shape[1] < mfmo.shape[1]:
            if casscf.mol.symmetry:
                restorb = []
                orbsym = scf.hf_symm.get_orbsym(casscf.mol, mfmo, s)
                for ir in set(orbsym):
                    mo_ir = mfmo[:, orbsym == ir]
                    rest = mo_ir - reduce(numpy.dot, (mocc, mocc.T, s, mo_ir))
                    e, u = numpy.linalg.eigh(
                        reduce(numpy.dot, (rest.T, s, rest)))
                    restorb.append(numpy.dot(rest, u[:, e > 1e-7]))
                restorb = numpy.hstack(restorb)
            else:
                rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo))
                e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest)))
                restorb = numpy.dot(rest, u[:, e > 1e-7])
            mo = numpy.hstack((mocc, restorb))
        else:
            mo = mocc

        if casscf.verbose >= logger.DEBUG:
            s1 = reduce(numpy.dot, (mo[:, ncore:nocc].T, s, mfmo))
            idx = numpy.argwhere(abs(s1) > 0.4)
            for i, j in idx:
                logger.debug(casscf,
                             'Init guess <mo-CAS|mo-hf>  %d  %d  %12.8f',
                             ncore + i + 1, j + 1, s1[i, j])
        return mo

    ncore = casscf.ncore
    mfmo = casscf._scf.mo_coeff
    s = casscf._scf.get_ovlp()
    if prev_mol is None:
        if init_mo.shape[0] != mfmo.shape[0]:
            raise RuntimeError('Initial guess orbitals has wrong dimension')
    elif gto.same_mol(prev_mol, casscf.mol, cmp_basis=False):
        if isinstance(ncore, (int, numpy.integer)):  # RHF
            init_mo = scf.addons.project_mo_nr2nr(prev_mol, init_mo,
                                                  casscf.mol)
        else:
            init_mo = (scf.addons.project_mo_nr2nr(prev_mol, init_mo[0],
                                                   casscf.mol),
                       scf.addons.project_mo_nr2nr(prev_mol, init_mo[1],
                                                   casscf.mol))
    elif gto.same_basis_set(prev_mol, casscf.mol):
        if isinstance(ncore, (int, numpy.integer)):  # RHF
            fock = casscf.get_fock(init_mo, casscf.ci)
            return casscf._scf.eig(fock, s)[1]
        else:
            raise NotImplementedError('Project initial for UHF orbitals.')
    else:
        raise NotImplementedError(
            'Project initial guess from different system.')

# Be careful with the orbital projection. The projection may lead to bad
# initial guess orbitals if the geometry is dramatically changed.
    if isinstance(ncore, (int, numpy.integer)):
        mo = project(mfmo, init_mo, ncore, s)
    else:  # UHF-based CASSCF
        mo = (project(mfmo[0], init_mo[0], ncore[0],
                      s), project(mfmo[1], init_mo[1], ncore[1], s))
    return mo
示例#10
0
def init_guess_by_chkfile(cell, chkfile_name, project=None, kpts=None):
    '''Read the KHF results from checkpoint file, then project it to the
    basis defined by ``cell``

    Returns:
        Density matrix, 3D ndarray
    '''
    from pyscf import gto
    chk_cell, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_cell, cell)

    if kpts is None:
        kpts = scf_rec['kpts']

    if 'kpt' in scf_rec:
        chk_kpts = scf_rec['kpt'].reshape(-1, 3)
    elif 'kpts' in scf_rec:
        chk_kpts = scf_rec['kpts']
    else:
        chk_kpts = np.zeros((1, 3))

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if 'kpts' not in scf_rec:  # gamma point or single k-point
        if mo.ndim == 2:
            mo = np.expand_dims(mo, axis=0)
            mo_occ = np.expand_dims(mo_occ, axis=0)
        else:  # UHF
            mo = [np.expand_dims(mo[0], axis=0), np.expand_dims(mo[1], axis=0)]
            mo_occ = [
                np.expand_dims(mo_occ[0], axis=0),
                np.expand_dims(mo_occ[1], axis=0)
            ]

    if project:
        s = cell.pbc_intor('int1e_ovlp', kpts=kpts)

    def fproj(mo, kpts):
        if project:
            mo = addons.project_mo_nr2nr(chk_cell, mo, cell, kpts)
            for k, c in enumerate(mo):
                norm = np.einsum('pi,pi->i', c.conj(), s[k].dot(c))
                mo[k] /= np.sqrt(norm)
        return mo

    if kpts.shape == chk_kpts.shape and np.allclose(kpts, chk_kpts):

        def makedm(mos, occs):
            moa, mob = mos
            mos = ([fproj(mo, None)
                    for mo in moa], [fproj(mo, None) for mo in mob])
            return make_rdm1(mos, occs)
    else:

        def makedm(mos, occs):
            where = [
                np.argmin(lib.norm(chk_kpts - kpt, axis=1)) for kpt in kpts
            ]
            moa, mob = mos
            occa, occb = occs
            dkpts = [chk_kpts[w] - kpts[i] for i, w in enumerate(where)]
            mos = (fproj([moa[w] for w in where],
                         dkpts), fproj([mob[w] for w in where], dkpts))
            occs = ([occa[i] for i in where], [occb[i] for i in where])
            return make_rdm1(mos, occs)

    if getattr(mo[0], 'ndim', None) == 2:  # KRHF
        mo_occa = [(occ > 1e-8).astype(np.double) for occ in mo_occ]
        mo_occb = [occ - mo_occa[k] for k, occ in enumerate(mo_occ)]
        dm = makedm((mo, mo), (mo_occa, mo_occb))
    else:  # KUHF
        dm = makedm(mo, mo_occ)

    # Real DM for gamma point
    if np.allclose(kpts, 0):
        dm = dm.real
    return dm
示例#11
0
文件: ghf.py 项目: zwang123/pyscf
def init_guess_by_chkfile(mol, chkfile_name, project=None):
    '''Read SCF chkfile and make the density matrix for GHF initial guess.

    Kwargs:
        project : None or bool
            Whether to project chkfile's orbitals to the new basis.  Note when
            the geometry of the chkfile and the given molecule are very
            different, this projection can produce very poor initial guess.
            In PES scanning, it is recommended to swith off project.

            If project is set to None, the projection is only applied when the
            basis sets of the chkfile's molecule are different to the basis
            sets of the given molecule (regardless whether the geometry of
            the two molecules are different).  Note the basis sets are
            considered to be different if the two molecules are derived from
            the same molecule with different ordering of atoms.
    '''
    from pyscf.scf import addons
    chk_mol, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_mol, mol)

    # Check whether the two molecules are similar enough
    def inertia_momentum(mol):
        im = gto.inertia_momentum(mol._atom, mol.atom_charges(),
                                  mol.atom_coords())
        return scipy.linalg.eigh(im)[0]

    if abs(inertia_momentum(mol) - inertia_momentum(chk_mol)).sum() > 0.5:
        logger.warn(
            mol, "Large deviations found between the input "
            "molecule and the molecule from chkfile\n"
            "Initial guess density matrix may have large error.")

    if project:
        s = hf.get_ovlp(mol)

    def fproj(mo):
        if project:
            mo = addons.project_mo_nr2nr(chk_mol, mo, mol)
            norm = numpy.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= numpy.sqrt(norm)
        return mo

    nao = chk_mol.nao_nr()
    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if hasattr(mo[0], 'ndim') and mo[0].ndim == 1:  # RHF/GHF/DHF
        if nao * 2 == mo.shape[0]:  # GHF or DHF
            if project:
                raise NotImplementedError('Project initial guess from '
                                          'different geometry')
            else:
                dm = hf.make_rdm1(mo, mo_occ)
        else:  # RHF
            mo_coeff = fproj(mo)
            mo_occa = (mo_occ > 1e-8).astype(numpy.double)
            mo_occb = mo_occ - mo_occa
            dma, dmb = uhf.make_rdm1([mo_coeff] * 2, (mo_occa, mo_occb))
            dm = scipy.linalg.block_diag(dma, dmb)
    else:  #UHF
        if hasattr(mo[0][0], 'ndim') and mo[0][0].ndim == 2:  # KUHF
            logger.warn(
                mol, 'k-point UHF results are found.  Density matrix '
                'at Gamma point is used for the molecular SCF initial guess')
            mo = mo[0]
        dma, dmb = uhf.make_rdm1([fproj(mo[0]), fproj(mo[1])], mo_occ)
        dm = scipy.linalg.block_diag(dma, dmb)
    return dm
示例#12
0
文件: addons.py 项目: chrinide/pyscf
def project_init_guess(casscf, init_mo, prev_mol=None):
    '''Project the given initial guess to the current CASSCF problem.  The
    projected initial guess has two parts.  The core orbitals are directly
    taken from the Hartree-Fock orbitals, and the active orbitals are
    projected from the given initial guess.

    Args:
        casscf : an :class:`CASSCF` or :class:`CASCI` object

        init_mo : ndarray or list of ndarray
            Initial guess orbitals which are not orth-normal for the current
            molecule.  When the casscf is UHF-CASSCF, the init_mo needs to be
            a list of two ndarrays, for alpha and beta orbitals

    Kwargs:
        prev_mol : an instance of :class:`Mole`
            If given, the inital guess orbitals are associated to the geometry
            and basis of prev_mol.  Otherwise, the orbitals are based of
            the geometry and basis of casscf.mol

    Returns:
        New orthogonal initial guess orbitals with the core taken from
        Hartree-Fock orbitals and projected active space from original initial
        guess orbitals

    Examples:

    .. code:: python

        import numpy
        from pyscf import gto, scf, mcscf
        mol = gto.Mole()
        mol.build(atom='H 0 0 0; F 0 0 0.8', basis='ccpvdz', verbose=0)
        mf = scf.RHF(mol)
        mf.scf()
        mc = mcscf.CASSCF(mf, 6, 6)
        mo = mcscf.sort_mo(mc, mf.mo_coeff, [3,4,5,6,8,9])
        print('E(0.8) = %.12f' % mc.kernel(mo)[0])
        init_mo = mc.mo_coeff
        for b in numpy.arange(1.0, 3., .2):
            mol.atom = [['H', (0, 0, 0)], ['F', (0, 0, b)]]
            mol.build(0, 0)
            mf = scf.RHF(mol)
            mf.scf()
            mc = mcscf.CASSCF(mf, 6, 6)
            mo = mcscf.project_init_guess(mc, init_mo)
            print('E(%2.1f) = %.12f' % (b, mc.kernel(mo)[0]))
            init_mo = mc.mo_coeff
    '''
    from pyscf import lo

    def project(mfmo, init_mo, ncore, s):
        s_init_mo = numpy.einsum('pi,pi->i', init_mo.conj(), s.dot(init_mo))
        if abs(s_init_mo - 1).max() < 1e-7 and mfmo.shape[1] == init_mo.shape[1]:
            # Initial guess orbitals are orthonormal
            return init_mo
# TODO: test whether the canonicalized orbitals are better than the projected orbitals
# Be careful that the ordering of the canonicalized orbitals may be very different
# to the CASSCF orbitals.
#        else:
#            fock = casscf.get_fock(mc, init_mo, casscf.ci)
#            return casscf._scf.eig(fock, s)[1]

        nocc = ncore + casscf.ncas
        if ncore > 0:
            mo0core = init_mo[:,:ncore]
            s1 = reduce(numpy.dot, (mfmo.T, s, mo0core))
            s1core = reduce(numpy.dot, (mo0core.T, s, mo0core))
            coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T))
            coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore])
            logger.debug(casscf, 'Core indices %s', coreidx)
            logger.debug(casscf, 'Core components %s', coreocc[coreidx])
            # take HF core
            mocore = mfmo[:,coreidx]

            # take projected CAS space
            mocas = init_mo[:,ncore:nocc] \
                  - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc]))
            mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s)
        else:
            mocc = lo.orth.vec_lowdin(init_mo[:,:nocc], s)

        # remove core and active space from rest
        if mocc.shape[1] < mfmo.shape[1]:
            if casscf.mol.symmetry:
                restorb = []
                orbsym = scf.hf_symm.get_orbsym(casscf.mol, mfmo, s)
                for ir in set(orbsym):
                    mo_ir = mfmo[:,orbsym==ir]
                    rest = mo_ir - reduce(numpy.dot, (mocc, mocc.T, s, mo_ir))
                    e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest)))
                    restorb.append(numpy.dot(rest, u[:,e>1e-7]))
                restorb = numpy.hstack(restorb)
            else:
                rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo))
                e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest)))
                restorb = numpy.dot(rest, u[:,e>1e-7])
            mo = numpy.hstack((mocc, restorb))
        else:
            mo = mocc

        if casscf.verbose >= logger.DEBUG:
            s1 = reduce(numpy.dot, (mo[:,ncore:nocc].T, s, mfmo))
            idx = numpy.argwhere(abs(s1) > 0.4)
            for i,j in idx:
                logger.debug(casscf, 'Init guess <mo-CAS|mo-hf>  %d  %d  %12.8f',
                             ncore+i+1, j+1, s1[i,j])
        return mo

    ncore = casscf.ncore
    mfmo = casscf._scf.mo_coeff
    s = casscf._scf.get_ovlp()
    if prev_mol is None:
        if init_mo.shape[0] != mfmo.shape[0]:
            raise RuntimeError('Initial guess orbitals has wrong dimension')
    elif gto.same_mol(prev_mol, casscf.mol, cmp_basis=False):
        if isinstance(ncore, (int, numpy.integer)):  # RHF
            init_mo = scf.addons.project_mo_nr2nr(prev_mol, init_mo, casscf.mol)
        else:
            init_mo = (scf.addons.project_mo_nr2nr(prev_mol, init_mo[0], casscf.mol),
                       scf.addons.project_mo_nr2nr(prev_mol, init_mo[1], casscf.mol))
    elif gto.same_basis_set(prev_mol, casscf.mol):
        if isinstance(ncore, (int, numpy.integer)):  # RHF
            fock = casscf.get_fock(init_mo, casscf.ci)
            return casscf._scf.eig(fock, s)[1]
        else:
            raise NotImplementedError('Project initial for UHF orbitals.')
    else:
        raise NotImplementedError('Project initial guess from different system.')

# Be careful with the orbital projection. The projection may lead to bad
# initial guess orbitals if the geometry is dramatically changed.
    if isinstance(ncore, (int, numpy.integer)):
        mo = project(mfmo, init_mo, ncore, s)
    else: # UHF-based CASSCF
        mo = (project(mfmo[0], init_mo[0], ncore[0], s),
              project(mfmo[1], init_mo[1], ncore[1], s))
    return mo
示例#13
0
文件: kuhf.py 项目: chrinide/pyscf
def init_guess_by_chkfile(cell, chkfile_name, project=None, kpts=None):
    '''Read the KHF results from checkpoint file, then project it to the
    basis defined by ``cell``

    Returns:
        Density matrix, 3D ndarray
    '''
    from pyscf import gto
    chk_cell, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_cell, cell)

    if kpts is None:
        kpts = scf_rec['kpts']

    if 'kpt' in scf_rec:
        chk_kpts = scf_rec['kpt'].reshape(-1,3)
    elif 'kpts' in scf_rec:
        chk_kpts = scf_rec['kpts']
    else:
        chk_kpts = np.zeros((1,3))

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if 'kpts' not in scf_rec:  # gamma point or single k-point
        if mo.ndim == 2:
            mo = np.expand_dims(mo, axis=0)
            mo_occ = np.expand_dims(mo_occ, axis=0)
        else:  # UHF
            mo = [np.expand_dims(mo[0], axis=0),
                  np.expand_dims(mo[1], axis=0)]
            mo_occ = [np.expand_dims(mo_occ[0], axis=0),
                      np.expand_dims(mo_occ[1], axis=0)]

    if project:
        s = cell.pbc_intor('int1e_ovlp', kpts=kpts)
    def fproj(mo, kpts):
        if project:
            mo = addons.project_mo_nr2nr(chk_cell, mo, cell, kpts)
            for k, c in enumerate(mo):
                norm = np.einsum('pi,pi->i', c.conj(), s[k].dot(c))
                mo[k] /= np.sqrt(norm)
        return mo

    if kpts.shape == chk_kpts.shape and np.allclose(kpts, chk_kpts):
        def makedm(mos, occs):
            moa, mob = mos
            mos =([fproj(mo, None) for mo in moa],
                  [fproj(mo, None) for mo in mob])
            return make_rdm1(mos, occs)
    else:
        def makedm(mos, occs):
            where = [np.argmin(lib.norm(chk_kpts-kpt, axis=1)) for kpt in kpts]
            moa, mob = mos
            occa, occb = occs
            dkpts = [chk_kpts[w]-kpts[i] for i,w in enumerate(where)]
            mos = (fproj([moa[w] for w in where], dkpts),
                   fproj([mob[w] for w in where], dkpts))
            occs = ([occa[i] for i in where], [occb[i] for i in where])
            return make_rdm1(mos, occs)

    if getattr(mo[0], 'ndim', None) == 2:  # KRHF
        mo_occa = [(occ>1e-8).astype(np.double) for occ in mo_occ]
        mo_occb = [occ-mo_occa[k] for k,occ in enumerate(mo_occ)]
        dm = makedm((mo, mo), (mo_occa, mo_occb))
    else:  # KUHF
        dm = makedm(mo, mo_occ)

    # Real DM for gamma point
    if np.allclose(kpts, 0):
        dm = dm.real
    return dm