Exemplo n.º 1
0
    def init_guess(self, mf, nstates=None, wfnsym=None):
        if nstates is None: nstates = self.nstates
        if wfnsym is None: wfnsym = self.wfnsym

        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        occidx = numpy.where(mo_occ == 2)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        e_ia = mo_energy[viridx] - mo_energy[occidx, None]
        e_ia_max = e_ia.max()

        if wfnsym is not None and mf.mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mf.mol.groupname, wfnsym)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsym = hf_symm.get_orbsym(mf.mol, mf.mo_coeff)
            orbsym_in_d2h = numpy.asarray(orbsym) % 10  # convert to D2h irreps
            e_ia[(orbsym_in_d2h[occidx, None]
                  ^ orbsym_in_d2h[viridx]) != wfnsym] = 1e99

        nov = e_ia.size
        nstates = min(nstates, nov)
        e_ia = e_ia.ravel()
        e_threshold = min(e_ia_max, e_ia[numpy.argsort(e_ia)[nstates - 1]])
        # Handle degeneracy, include all degenerated states in initial guess
        e_threshold += 1e-6

        idx = numpy.where(e_ia <= e_threshold)[0]
        x0 = numpy.zeros((idx.size, nov))
        for i, j in enumerate(idx):
            x0[i, j] = 1  # Koopmans' excitations
        return x0
Exemplo n.º 2
0
    def init_guess(self, mf, nstates=None, wfnsym=None):
        if nstates is None: nstates = self.nstates
        if wfnsym is None: wfnsym = self.wfnsym

        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        occidx = numpy.where(mo_occ == 2)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        e_ia = mo_energy[viridx] - mo_energy[occidx, None]

        if wfnsym is not None and mf.mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mf.mol.groupname, wfnsym)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsym = hf_symm.get_orbsym(mf.mol, mf.mo_coeff)
            orbsym_in_d2h = numpy.asarray(orbsym) % 10  # convert to D2h irreps
            e_ia[(orbsym_in_d2h[occidx, None]
                  ^ orbsym_in_d2h[viridx]) != wfnsym] = 1e99

        nov = e_ia.size
        nroot = min(nstates, nov)
        x0 = numpy.zeros((nroot, nov))
        idx = numpy.argsort(e_ia.ravel())
        for i in range(nroot):
            x0[i, idx[i]] = 1  # Koopmans' excitations
        return x0
Exemplo n.º 3
0
    def init_guess(self, mf, nstates=None, wfnsym=None):
        if nstates is None: nstates = self.nstates
        if wfnsym is None: wfnsym = self.wfnsym

        mol = mf.mol
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mf.mo_coeff)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsyma = orbsyma % 10
            orbsymb = orbsymb % 10
            e_ia_a[(orbsyma[occidxa, None]
                    ^ orbsyma[viridxa]) != wfnsym] = 1e99
            e_ia_b[(orbsymb[occidxb, None]
                    ^ orbsymb[viridxb]) != wfnsym] = 1e99

        e_ia = numpy.hstack((e_ia_a.ravel(), e_ia_b.ravel()))
        nov = e_ia.size
        nroot = min(nstates, nov)
        x0 = numpy.zeros((nroot, nov))
        idx = numpy.argsort(e_ia)
        for i in range(nroot):
            x0[i, idx[i]] = 1  # lowest excitations
        return x0
Exemplo n.º 4
0
def _id_wfnsym(cis, norb, nelec, orbsym, wfnsym):
    if wfnsym is None:
        neleca, nelecb = _unpack_nelec(nelec)
        wfnsym = 0  # Ag, A1 or A
        for i in orbsym[nelecb:neleca]:
            wfnsym ^= i
    elif isinstance(wfnsym, str):
        wfnsym = symm.irrep_name2id(cis.mol.groupname, wfnsym)
    return wfnsym % 10
Exemplo n.º 5
0
def _id_wfnsym(cis, norb, nelec, wfnsym):
    if wfnsym is None:
        neleca, nelecb = direct_spin1._unpack_nelec(nelec)
        wfnsym = 0  # Ag, A1 or A
        for i in cis.orbsym[nelecb:neleca]:
            wfnsym ^= i
    elif isinstance(wfnsym, str):
        wfnsym = symm.irrep_name2id(cis.mol.groupname, wfnsym) % 10
    return wfnsym
Exemplo n.º 6
0
    def gen_vind(self, mf=None):
        if mf is None:
            mf = self._scf
        wfnsym = self.wfnsym
        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert mo_coeff.dtype == numpy.double
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff.shape
        occidx = numpy.where(mo_occ == 1)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        nocc = len(occidx)
        nvir = len(viridx)
        orbv = mo_coeff[:, viridx]
        orbo = mo_coeff[:, occidx]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsym = ghf_symm.get_orbsym(mol, mo_coeff)
            orbsym_in_d2h = numpy.asarray(orbsym) % 10  # convert to D2h irreps
            sym_forbid = (orbsym_in_d2h[occidx, None]
                          ^ orbsym_in_d2h[viridx]) != wfnsym

        e_ia = (mo_energy[viridx].reshape(-1, 1) - mo_energy[occidx]).T
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia)
        ed_ia = e_ia * d_ia
        hdiag = e_ia.ravel()**2

        vresp = mf.gen_response(mo_coeff, mo_occ, hermi=1)

        def vind(zs):
            zs = numpy.asarray(zs).reshape(-1, nocc, nvir)
            if wfnsym is not None and mol.symmetry:
                zs = numpy.copy(zs)
                zs[:, sym_forbid] = 0

            dmov = lib.einsum('xov,po,qv->xpq', zs * d_ia, orbo, orbv)
            # +cc for A+B because K_{ai,jb} in A == K_{ai,bj} in B
            dmov = dmov + dmov.transpose(0, 2, 1)

            v1ao = vresp(dmov)
            v1ov = lib.einsum('xpq,po,qv->xov', v1ao, orbo, orbv)

            # numpy.sqrt(e_ia) * (e_ia*d_ia*z + v1ov)
            v1ov += numpy.einsum('xov,ov->xov', zs, ed_ia)
            v1ov *= d_ia
            if wfnsym is not None and mol.symmetry:
                v1ov[:, sym_forbid] = 0
            return v1ov.reshape(v1ov.shape[0], -1)

        return vind, hdiag
Exemplo n.º 7
0
def _id_wfnsym(cisolver, norb, nelec, orbsym, wfnsym):
    '''Guess wfnsym or convert wfnsym to symmetry ID if it's a symmetry label'''
    if wfnsym is None:
        neleca, nelecb = _unpack_nelec(nelec)
        wfnsym = 0  # Ag, A1 or A
        for i in orbsym[nelecb:neleca]:
            wfnsym ^= i
    elif isinstance(wfnsym, str):
        wfnsym = symm.irrep_name2id(cisolver.mol.groupname, wfnsym)
    return wfnsym % 10
Exemplo n.º 8
0
    def gen_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff.dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff.shape
        occidx = numpy.where(mo_occ == 2)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        nocc = len(occidx)
        nvir = len(viridx)
        orbv = mo_coeff[:, viridx]
        orbo = mo_coeff[:, occidx]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsym = hf_symm.get_orbsym(mol, mo_coeff) % 10
            sym_forbid = (orbsym[occidx, None] ^ orbsym[viridx]) != wfnsym

        e_ia = (mo_energy[viridx].reshape(-1, 1) - mo_energy[occidx]).T
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia).ravel()
        ed_ia = e_ia.ravel() * d_ia
        hdiag = e_ia.ravel()**2

        vresp = _gen_rhf_response(mf, singlet=singlet, hermi=1)

        def vind(zs):
            nz = len(zs)
            dmov = numpy.empty((nz, nao, nao))
            for i, z in enumerate(zs):
                # *2 for double occupancy
                dm = reduce(numpy.dot,
                            (orbo, (d_ia * z).reshape(nocc, nvir) * 2, orbv.T))
                dmov[
                    i] = dm + dm.T  # +cc for A+B and K_{ai,jb} in A == K_{ai,bj} in B
            v1ao = vresp(dmov)
            v1ov = _ao2mo.nr_e2(v1ao, mo_coeff,
                                (0, nocc, nocc, nmo)).reshape(-1, nocc * nvir)
            for i, z in enumerate(zs):
                # numpy.sqrt(e_ia) * (e_ia*d_ia*z + v1ov)
                v1ov[i] += ed_ia * z
                v1ov[i] *= d_ia
            return v1ov.reshape(nz, -1)

        return vind, hdiag
Exemplo n.º 9
0
def _id_wfnsym(cis, norb, nelec, wfnsym):
    if wfnsym is None:
        if isinstance(nelec, (int, numpy.number)):
            nelecb = nelec//2
            neleca = nelec - nelecb
        else:
            neleca, nelecb = nelec
        wfnsym = 0  # Ag, A1 or A
        for i in cis.orbsym[nelecb:neleca]:
            wfnsym ^= i
    elif isinstance(wfnsym, str):
        wfnsym = symm.irrep_name2id(cis.mol.groupname, wfnsym) % 10
    return wfnsym
Exemplo n.º 10
0
def _id_wfnsym(cis, norb, nelec, wfnsym):
    if wfnsym is None:
        if isinstance(nelec, (int, numpy.integer)):
            nelecb = nelec//2
            neleca = nelec - nelecb
        else:
            neleca, nelecb = nelec
        wfnsym = 0  # Ag, A1 or A
        for i in cis.orbsym[nelecb:neleca]:
            wfnsym ^= i
    elif isinstance(wfnsym, str):
        wfnsym = symm.irrep_name2id(cis.mol.groupname, wfnsym) % 10
    return wfnsym
Exemplo n.º 11
0
Arquivo: rks.py Projeto: y1xiaoc/pyscf
    def gen_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff.dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff.shape
        occidx = numpy.where(mo_occ == 2)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        nocc = len(occidx)
        nvir = len(viridx)
        orbv = mo_coeff[:, viridx]
        orbo = mo_coeff[:, occidx]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsym = hf_symm.get_orbsym(mol, mo_coeff) % 10
            sym_forbid = (orbsym[occidx, None] ^ orbsym[viridx]) != wfnsym

        e_ia = (mo_energy[viridx].reshape(-1, 1) - mo_energy[occidx]).T
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia)
        ed_ia = e_ia * d_ia
        hdiag = e_ia.ravel()**2

        vresp = mf.gen_response(singlet=singlet, hermi=1)

        def vind(zs):
            zs = numpy.asarray(zs).reshape(-1, nocc, nvir)
            # *2 for double occupancy
            dmov = lib.einsum('xov,ov,po,qv->xpq', zs, d_ia * 2, orbo,
                              orbv.conj())
            # +cc for A+B and K_{ai,jb} in A == K_{ai,bj} in B
            dmov = dmov + dmov.conj().transpose(0, 2, 1)

            v1ao = vresp(dmov)
            v1ov = lib.einsum('xpq,po,qv->xov', v1ao, orbo.conj(), orbv)

            # numpy.sqrt(e_ia) * (e_ia*d_ia*z + v1ov)
            v1ov += numpy.einsum('xov,ov->xov', zs, ed_ia)
            v1ov *= d_ia
            return v1ov.reshape(v1ov.shape[0], -1)

        return vind, hdiag
Exemplo n.º 12
0
    def gen_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert(mo_coeff.dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff.shape
        occidx = numpy.where(mo_occ==2)[0]
        viridx = numpy.where(mo_occ==0)[0]
        nocc = len(occidx)
        nvir = len(viridx)
        orbv = mo_coeff[:,viridx]
        orbo = mo_coeff[:,occidx]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsym = hf_symm.get_orbsym(mol, mo_coeff) % 10
            sym_forbid = (orbsym[occidx,None] ^ orbsym[viridx]) != wfnsym

        e_ia = (mo_energy[viridx].reshape(-1,1) - mo_energy[occidx]).T
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia).ravel()
        ed_ia = e_ia.ravel() * d_ia
        hdiag = e_ia.ravel() ** 2

        vresp = _gen_rhf_response(mf, singlet=singlet, hermi=1)

        def vind(zs):
            nz = len(zs)
            dmov = numpy.empty((nz,nao,nao))
            for i, z in enumerate(zs):
                # *2 for double occupancy
                dm = reduce(numpy.dot, (orbo, (d_ia*z).reshape(nocc,nvir)*2, orbv.T))
                dmov[i] = dm + dm.T # +cc for A+B and K_{ai,jb} in A == K_{ai,bj} in B
            v1ao = vresp(dmov)
            v1ov = _ao2mo.nr_e2(v1ao, mo_coeff, (0,nocc,nocc,nmo)).reshape(-1,nocc*nvir)
            for i, z in enumerate(zs):
                # numpy.sqrt(e_ia) * (e_ia*d_ia*z + v1ov)
                v1ov[i] += ed_ia*z
                v1ov[i] *= d_ia
            return v1ov.reshape(nz,-1)

        return vind, hdiag
Exemplo n.º 13
0
 def check_transformer_cache(self):
     assert (isinstance(self.smult, (int, np.number)))
     neleca, nelecb = _unpack_nelec(self.nelec)
     if isinstance(self.wfnsym, str):
         wfnsym = symm.irrep_name2id(self.mol.groupname, self.wfnsym)
     else:
         wfnsym = self.wfnsym
     if self.transformer is None:
         self.transformer = CSFTransformer(self.norb,
                                           neleca,
                                           nelecb,
                                           self.smult,
                                           orbsym=self.orbsym,
                                           wfnsym=wfnsym)
     else:
         self.transformer._update_spin_cache(self.norb, neleca, nelecb,
                                             self.smult)
         self.transformer._update_symm_cache(self.orbsym)
         self.transformer.wfnsym = wfnsym
Exemplo n.º 14
0
def las_symm_tuple(las):
    # This really should be much more modular
    # Symmetry tuple: neleca, nelecb, irrep
    statesym = []
    s2_states = []
    for iroot in range(las.nroots):
        neleca = 0
        nelecb = 0
        wfnsym = 0
        s = 0
        m = []
        for fcibox, nelec in zip(las.fciboxes, las.nelecas_sub):
            solver = fcibox.fcisolvers[iroot]
            na, nb = _unpack_nelec(fcibox._get_nelec(solver, nelec))
            neleca += na
            nelecb += nb
            s_frag = (solver.smult - 1) // 2
            s += s_frag * (s_frag + 1)
            m.append((na - nb) // 2)
            fragsym = getattr(solver, 'wfnsym',
                              0) or 0  # in case getattr returns "None"
            if isinstance(fragsym, str):
                fragsym = symm.irrep_name2id(solver.mol.groupname, fragsym)
            assert isinstance(fragsym, (int, np.integer)), '{} {}'.format(
                type(fragsym), fragsym)
            wfnsym ^= fragsym
        s += sum([2 * m1 * m2 for m1, m2 in combinations(m, 2)])
        s2_states.append(s)
        statesym.append((neleca, nelecb, wfnsym))
    lib.logger.info(las, 'Symmetry analysis of LAS states:')
    lib.logger.info(
        las, ' {:2s}  {:>16s}  {:6s}  {:6s}  {:6s}  {:6s}'.format(
            'ix', 'Energy', 'Neleca', 'Nelecb', '<S**2>', 'Wfnsym'))
    for ix, (e, sy, s2) in enumerate(zip(las.e_states, statesym, s2_states)):
        neleca, nelecb, wfnsym = sy
        wfnsym = symm.irrep_id2name(las.mol.groupname, wfnsym)
        lib.logger.info(
            las, ' {:2d}  {:16.10f}  {:6d}  {:6d}  {:6.3f}  {:>6s}'.format(
                ix, e, neleca, nelecb, s2, wfnsym))

    return statesym, np.asarray(s2_states)
Exemplo n.º 15
0
    def init_guess(self, mf, nstates=None, wfnsym=None):
        if nstates is None: nstates = self.nstates
        if wfnsym is None: wfnsym = self.wfnsym

        mol = mf.mol
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
        e_ia_max = max(e_ia_a.max(), e_ia_b.max())

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mf.mo_coeff)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsyma_in_d2h = numpy.asarray(orbsyma) % 10
            orbsymb_in_d2h = numpy.asarray(orbsymb) % 10
            e_ia_a[(orbsyma_in_d2h[occidxa, None]
                    ^ orbsyma_in_d2h[viridxa]) != wfnsym] = 1e99
            e_ia_b[(orbsymb_in_d2h[occidxb, None]
                    ^ orbsymb_in_d2h[viridxb]) != wfnsym] = 1e99

        e_ia = numpy.hstack((e_ia_a.ravel(), e_ia_b.ravel()))
        e_ia_max = e_ia.max()
        nov = e_ia.size
        nstates = min(nstates, nov)
        e_threshold = min(e_ia_max, e_ia[numpy.argsort(e_ia)[nstates - 1]])
        # Handle degeneracy
        e_threshold += 1e-6

        idx = numpy.where(e_ia <= e_threshold)[0]
        x0 = numpy.zeros((idx.size, nov))
        for i, j in enumerate(idx):
            x0[i, j] = 1  # Koopmans' excitations
        return x0
Exemplo n.º 16
0
    def init_guess(self, mf, nstates=None, wfnsym=None):
        if nstates is None: nstates = self.nstates
        if wfnsym is None: wfnsym = self.wfnsym

        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        occidx = numpy.where(mo_occ==2)[0]
        viridx = numpy.where(mo_occ==0)[0]
        e_ia = mo_energy[viridx] - mo_energy[occidx,None]

        if wfnsym is not None and mf.mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mf.mol.groupname, wfnsym)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsym = hf_symm.get_orbsym(mf.mol, mf.mo_coeff) % 10
            e_ia[(orbsym[occidx,None] ^ orbsym[viridx]) != wfnsym] = 1e99

        nov = e_ia.size
        nroot = min(nstates, nov)
        x0 = numpy.zeros((nroot, nov))
        idx = numpy.argsort(e_ia.ravel())
        for i in range(nroot):
            x0[i,idx[i]] = 1  # Koopmans' excitations
        return x0
Exemplo n.º 17
0
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute

    [ A  B][X]
    [-B -A][Y]
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert(mo_coeff.dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ==2)[0]
    viridx = numpy.where(mo_occ==0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsym = hf_symm.get_orbsym(mol, mo_coeff) % 10
        sym_forbid = (orbsym[occidx,None] ^ orbsym[viridx]) != wfnsym

    #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
    #fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff))
    #foo = fock[occidx[:,None],occidx]
    #fvv = fock[viridx[:,None],viridx]
    foo = numpy.diag(mo_energy[occidx])
    fvv = numpy.diag(mo_energy[viridx])

    hdiag = (fvv.diagonal().reshape(-1,1) - foo.diagonal()).T
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel()))

    mo_coeff = numpy.asarray(numpy.hstack((orbo,orbv)), order='F')
    vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0)

    def vind(xys):
        nz = len(xys)
        if wfnsym is not None and mol.symmetry:
            # shape(nz,2,nocc,nvir): 2 ~ X,Y
            xys = numpy.copy(xys).reshape(nz,2,nocc,nvir)
            xys[:,:,sym_forbid] = 0
        dms = numpy.empty((nz,nao,nao))
        for i in range(nz):
            x, y = xys[i].reshape(2,nocc,nvir)
            # *2 for double occupancy
            dmx = reduce(numpy.dot, (orbo, x*2, orbv.T))
            dmy = reduce(numpy.dot, (orbv, y.T*2, orbo.T))
            dms[i] = dmx + dmy  # AX + BY

        v1ao = vresp(dms)
        v1ov = _ao2mo.nr_e2(v1ao, mo_coeff, (0,nocc,nocc,nmo)).reshape(-1,nocc,nvir)
        v1vo = _ao2mo.nr_e2(v1ao, mo_coeff, (nocc,nmo,0,nocc)).reshape(-1,nvir,nocc)
        hx = numpy.empty((nz,2,nocc,nvir), dtype=v1ov.dtype)
        for i in range(nz):
            x, y = xys[i].reshape(2,nocc,nvir)
            hx[i,0] = v1ov[i]
            hx[i,0]+= numpy.einsum('sp,qs->qp', fvv, x)  # AX
            hx[i,0]-= numpy.einsum('sp,pr->sr', foo, x)  # AX
            hx[i,1] =-v1vo[i].T
            hx[i,1]-= numpy.einsum('sp,qs->qp', fvv, y)  #-AY
            hx[i,1]+= numpy.einsum('sp,pr->sr', foo, y)  #-AY

        if wfnsym is not None and mol.symmetry:
            hx[:,:,sym_forbid] = 0
        return hx.reshape(nz,-1)

    return vind, hdiag
Exemplo n.º 18
0
def gen_tda_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute (A+B)x
    
    Kwargs:
        wfnsym : int or str
            Point group symmetry irrep symbol or ID for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert(mo_coeff.dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ==2)[0]
    viridx = numpy.where(mo_occ==0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsym = hf_symm.get_orbsym(mol, mo_coeff) % 10
        sym_forbid = (orbsym[occidx,None] ^ orbsym[viridx]) != wfnsym

    if fock_ao is None:
        #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
        foo = numpy.diag(mo_energy[occidx])
        fvv = numpy.diag(mo_energy[viridx])
    else:
        fock = reduce(numpy.dot, (mo_coeff.conj().T, fock_ao, mo_coeff))
        foo = fock[occidx[:,None],occidx]
        fvv = fock[viridx[:,None],viridx]

    hdiag = (fvv.diagonal().reshape(-1,1) - foo.diagonal()).T
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = hdiag.ravel()

    mo_coeff = numpy.asarray(numpy.hstack((orbo,orbv)), order='F')
    vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0)

    def vind(zs):
        nz = len(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs).reshape(-1,nocc,nvir)
            zs[:,sym_forbid] = 0
        dmov = numpy.empty((nz,nao,nao))
        for i, z in enumerate(zs):
            # *2 for double occupancy
            dmov[i] = reduce(numpy.dot, (orbo, z.reshape(nocc,nvir)*2, orbv.conj().T))
        v1ao = vresp(dmov)
        #v1ov = numpy.asarray([reduce(numpy.dot, (orbo.T, v, orbv)) for v in v1ao])
        v1ov = _ao2mo.nr_e2(v1ao, mo_coeff, (0,nocc,nocc,nmo)).reshape(-1,nocc,nvir)
        for i, z in enumerate(zs):
            v1ov[i]+= numpy.einsum('sp,qs->qp', fvv, z.reshape(nocc,nvir))
            v1ov[i]-= numpy.einsum('sp,pr->sr', foo, z.reshape(nocc,nvir))
        if wfnsym is not None and mol.symmetry:
            v1ov[:,sym_forbid] = 0
        return v1ov.reshape(nz,-1)

    return vind, hdiag
Exemplo n.º 19
0
    def get_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert(mo_coeff[0].dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff[0].shape
        occidxa = numpy.where(mo_occ[0]>0)[0]
        occidxb = numpy.where(mo_occ[1]>0)[0]
        viridxa = numpy.where(mo_occ[0]==0)[0]
        viridxb = numpy.where(mo_occ[1]==0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        orboa = mo_coeff[0][:,occidxa]
        orbob = mo_coeff[1][:,occidxb]
        orbva = mo_coeff[0][:,viridxa]
        orbvb = mo_coeff[1][:,viridxb]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsyma = orbsyma % 10
            orbsymb = orbsymb % 10
            sym_forbida = (orbsyma[occidxa,None] ^ orbsyma[viridxa]) != wfnsym
            sym_forbidb = (orbsymb[occidxb,None] ^ orbsymb[viridxb]) != wfnsym
            sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

        e_ia_a = (mo_energy[0][viridxa,None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb,None] - mo_energy[1][occidxb]).T
        e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia).ravel()
        ed_ia = e_ia.ravel() * d_ia
        hdiag = e_ia.ravel() ** 2

        vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1)

        def vind(zs):
            nz = len(zs)
            if wfnsym is not None and mol.symmetry:
                zs = numpy.copy(zs)
                zs[:,sym_forbid] = 0
            dmov = numpy.empty((2,nz,nao,nao))
            for i in range(nz):
                z = d_ia * zs[i]
                za = z[:nocca*nvira].reshape(nocca,nvira)
                zb = z[nocca*nvira:].reshape(noccb,nvirb)
                dm = reduce(numpy.dot, (orboa, za, orbva.T))
                dmov[0,i] = dm + dm.T
                dm = reduce(numpy.dot, (orbob, zb, orbvb.T))
                dmov[1,i] = dm + dm.T

            v1ao = vresp(dmov)
            v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0,nocca,nocca,nmo))
            v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0,noccb,noccb,nmo))
            hx = numpy.hstack((v1a.reshape(nz,-1), v1b.reshape(nz,-1)))
            for i, z in enumerate(zs):
                hx[i] += ed_ia * z
                hx[i] *= d_ia
            return hx

        return vind, hdiag
Exemplo n.º 20
0
def gen_tda_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute (A+B)x
    
    Kwargs:
        wfnsym : int or str
            Point group symmetry irrep symbol or ID for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert(mo_coeff.dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ==2)[0]
    viridx = numpy.where(mo_occ==0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsym = hf_symm.get_orbsym(mol, mo_coeff) % 10
        sym_forbid = (orbsym[occidx,None] ^ orbsym[viridx]) != wfnsym

    if fock_ao is None:
        #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
        foo = numpy.diag(mo_energy[occidx])
        fvv = numpy.diag(mo_energy[viridx])
    else:
        fock = reduce(numpy.dot, (mo_coeff.conj().T, fock_ao, mo_coeff))
        foo = fock[occidx[:,None],occidx]
        fvv = fock[viridx[:,None],viridx]

    hdiag = (fvv.diagonal().reshape(-1,1) - foo.diagonal()).T
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = hdiag.ravel()

    mo_coeff = numpy.asarray(numpy.hstack((orbo,orbv)), order='F')
    vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0)

    def vind(zs):
        nz = len(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs).reshape(-1,nocc,nvir)
            zs[:,sym_forbid] = 0
        dmov = numpy.empty((nz,nao,nao))
        for i, z in enumerate(zs):
            # *2 for double occupancy
            dmov[i] = reduce(numpy.dot, (orbo, z.reshape(nocc,nvir)*2, orbv.conj().T))
        v1ao = vresp(dmov)
        #v1ov = numpy.asarray([reduce(numpy.dot, (orbo.T, v, orbv)) for v in v1ao])
        v1ov = _ao2mo.nr_e2(v1ao, mo_coeff, (0,nocc,nocc,nmo)).reshape(-1,nocc,nvir)
        for i, z in enumerate(zs):
            v1ov[i]+= numpy.einsum('sp,qs->qp', fvv, z.reshape(nocc,nvir))
            v1ov[i]-= numpy.einsum('sp,pr->sr', foo, z.reshape(nocc,nvir))
        if wfnsym is not None and mol.symmetry:
            v1ov[:,sym_forbid] = 0
        return v1ov.reshape(nz,-1)

    return vind, hdiag
Exemplo n.º 21
0
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute

    [ A  B][X]
    [-B -A][Y]
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma = orbsyma % 10
        orbsymb = orbsymb % 10
        sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym
        sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
    e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
    e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel()))
    mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F')
    mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F')

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory)

    def vind(xys):
        nz = len(xys)
        if wfnsym is not None and mol.symmetry:
            # shape(nz,2,-1): 2 ~ X,Y
            xys = numpy.copy(xys).reshape(nz, 2, -1)
            xys[:, :, sym_forbid] = 0
        dms = numpy.empty((2, nz, nao, nao))  # 2 ~ alpha,beta
        for i in range(nz):
            x, y = xys[i].reshape(2, -1)
            xa = x[:nocca * nvira].reshape(nocca, nvira)
            xb = x[nocca * nvira:].reshape(noccb, nvirb)
            ya = y[:nocca * nvira].reshape(nocca, nvira)
            yb = y[nocca * nvira:].reshape(noccb, nvirb)
            dmx = reduce(numpy.dot, (orboa, xa, orbva.T))
            dmy = reduce(numpy.dot, (orbva, ya.T, orboa.T))
            dms[0, i] = dmx + dmy  # AX + BY
            dmx = reduce(numpy.dot, (orbob, xb, orbvb.T))
            dmy = reduce(numpy.dot, (orbvb, yb.T, orbob.T))
            dms[1, i] = dmx + dmy  # AX + BY

        v1ao = vresp(dms)
        v1avo = _ao2mo.nr_e2(v1ao[0], mo_a, (nocca, nmo, 0, nocca))
        v1bvo = _ao2mo.nr_e2(v1ao[1], mo_b, (noccb, nmo, 0, noccb))
        v1aov = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo))
        v1bov = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo))
        hx = numpy.empty((nz, 2, nvira * nocca + nvirb * noccb),
                         dtype=v1avo.dtype)
        for i in range(nz):
            x, y = xys[i].reshape(2, -1)
            hx[i, 0, :nvira * nocca] = v1aov[i].ravel()
            hx[i, 0, nvira * nocca:] = v1bov[i].ravel()
            hx[i, 0] += e_ia * x  # AX
            hx[i,
               1, :nvira * nocca] = -v1avo[i].reshape(nvira, nocca).T.ravel()
            hx[i, 1,
               nvira * nocca:] = -v1bvo[i].reshape(nvirb, noccb).T.ravel()
            hx[i, 1] -= e_ia * y  #-AY

        if wfnsym is not None and mol.symmetry:
            hx[:, :, sym_forbid] = 0
        return hx.reshape(nz, -1)

    return vind, hdiag
Exemplo n.º 22
0
def gen_tda_operation(mf, fock_ao=None, wfnsym=None):
    '''(A+B)x

    Kwargs:
        wfnsym : int or str
            Point group symmetry irrep symbol or ID for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma = orbsyma % 10
        orbsymb = orbsymb % 10
        sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym
        sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
    e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
    e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F')
    mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F')

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory)

    def vind(zs):
        nz = len(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs)
            zs[:, sym_forbid] = 0
        dmov = numpy.empty((2, nz, nao, nao))
        for i, z in enumerate(zs):
            za = z[:nocca * nvira].reshape(nocca, nvira)
            zb = z[nocca * nvira:].reshape(noccb, nvirb)
            dmov[0, i] = reduce(numpy.dot, (orboa, za, orbva.conj().T))
            dmov[1, i] = reduce(numpy.dot, (orbob, zb, orbvb.conj().T))

        v1ao = vresp(dmov)
        v1a = _ao2mo.nr_e2(v1ao[0], mo_a,
                           (0, nocca, nocca, nmo)).reshape(-1, nocca, nvira)
        v1b = _ao2mo.nr_e2(v1ao[1], mo_b,
                           (0, noccb, noccb, nmo)).reshape(-1, noccb, nvirb)
        for i, z in enumerate(zs):
            za = z[:nocca * nvira].reshape(nocca, nvira)
            zb = z[nocca * nvira:].reshape(noccb, nvirb)
            v1a[i] += numpy.einsum('ia,ia->ia', e_ia_a, za)
            v1b[i] += numpy.einsum('ia,ia->ia', e_ia_b, zb)
        hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
        if wfnsym is not None and mol.symmetry:
            hx[:, sym_forbid] = 0
        return hx

    return vind, hdiag
Exemplo n.º 23
0
    def get_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff[0].dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff[0].shape
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        orboa = mo_coeff[0][:, occidxa]
        orbob = mo_coeff[1][:, occidxb]
        orbva = mo_coeff[0][:, viridxa]
        orbvb = mo_coeff[1][:, viridxb]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsyma = orbsyma % 10
            orbsymb = orbsymb % 10
            sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym
            sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym
            sym_forbid = numpy.hstack(
                (sym_forbida.ravel(), sym_forbidb.ravel()))

        e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
        e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia).ravel()
        ed_ia = e_ia.ravel() * d_ia
        hdiag = e_ia.ravel()**2

        vresp = mf.gen_response(mo_coeff, mo_occ, hermi=1)

        def vind(zs):
            nz = len(zs)
            zs = numpy.asarray(zs).reshape(nz, -1)
            if wfnsym is not None and mol.symmetry:
                zs = numpy.copy(zs)
                zs[:, sym_forbid] = 0

            dmsa = (zs[:, :nocca * nvira] * d_ia[:nocca * nvira]).reshape(
                nz, nocca, nvira)
            dmsb = (zs[:, nocca * nvira:] * d_ia[nocca * nvira:]).reshape(
                nz, noccb, nvirb)
            dmsa = lib.einsum('xov,po,qv->xpq', dmsa, orboa, orbva.conj())
            dmsb = lib.einsum('xov,po,qv->xpq', dmsb, orbob, orbvb.conj())
            dmsa = dmsa + dmsa.conj().transpose(0, 2, 1)
            dmsb = dmsb + dmsb.conj().transpose(0, 2, 1)

            v1ao = vresp(numpy.asarray((dmsa, dmsb)))

            v1a = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva)
            v1b = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb)

            hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
            hx += ed_ia * zs
            hx *= d_ia
            return hx

        return vind, hdiag
Exemplo n.º 24
0
def caslst_by_irrep(casscf, mo_coeff, cas_irrep_nocc,
                    cas_irrep_ncore=None, s=None, base=1):
    '''Given number of active orbitals for each irrep, return the orbital
    indices of active space

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

        cas_irrep_nocc : list or dict
            Number of active orbitals for each irrep.  It can be a dict, eg
            {'A1': 2, 'B2': 4} to indicate the active space size based on
            irrep names, or {0: 2, 3: 4} for irrep Id,  or a list [2, 0, 0, 4]
            (identical to {0: 2, 3: 4}) in which the list index is served as
            the irrep Id.

    Kwargs:
        cas_irrep_ncore : list or dict
            Number of closed shells for each irrep.  It can be a dict, eg
            {'A1': 6, 'B2': 4} to indicate the closed shells based on
            irrep names, or {0: 6, 3: 4} for irrep Id,  or a list [6, 0, 0, 4]
            (identical to {0: 6, 3: 4}) in which the list index is served as
            the irrep Id.  If cas_irrep_ncore is not given, the program
            will generate a guess based on the lowest :attr:`CASCI.ncore`
            orbitals.
        s : ndarray
            overlap matrix
        base : int
            0-based (C-like) or 1-based (Fortran-like) caslst

    Returns:
        A list of orbital indices

    Examples:

    >>> from pyscf import gto, scf, mcscf
    >>> mol = gto.M(atom='N 0 0 0; N 0 0 1', basis='ccpvtz', symmetry=True, verbose=0)
    >>> mf = scf.RHF(mol)
    >>> mf.kernel()
    >>> mc = mcscf.CASSCF(mf, 12, 4)
    >>> mcscf.caslst_by_irrep(mc, mf.mo_coeff, {'E1gx':4, 'E1gy':4, 'E1ux':2, 'E1uy':2})
    [5, 7, 8, 10, 11, 14, 15, 20, 25, 26, 31, 32]
    '''
    mol = casscf.mol
    log = logger.Logger(casscf.stdout, casscf.verbose)
    if s is None:
        s = casscf._scf.get_ovlp()
    orbsym = symm.label_orb_symm(mol, mol.irrep_id,
                                 mol.symm_orb, mo_coeff, s)
    orbsym = numpy.asarray(orbsym)
    ncore = casscf.ncore

    irreps = set(orbsym)

    if cas_irrep_ncore is not None:
        irrep_ncore = {}
        for k, v in cas_irrep_ncore.items():
            if isinstance(k, str):
                irrep_ncore[symm.irrep_name2id(mol.groupname, k)] = v
            else:
                irrep_ncore[k] = v

        ncore_rest = casscf.ncore - sum(irrep_ncore.values())
        if ncore_rest > 0:  # guess core configuration
            mask = numpy.ones(len(orbsym), dtype=bool)
            for ir in irrep_ncore:
                mask[orbsym == ir] = False
            core_rest = orbsym[mask][:ncore_rest]
            core_rest = dict([(ir, numpy.count_nonzero(core_rest==ir))
                              for ir in set(core_rest)])
            log.info('Given core space %s < casscf core size %d',
                     cas_irrep_ncore, casscf.ncore)
            log.info('Add %s to core configuration', core_rest)
            irrep_ncore.update(core_rest)
        elif ncore_rest < 0:
            raise ValueError('Given core space %s > casscf core size %d'
                             % (cas_irrep_ncore, casscf.ncore))
    else:
        irrep_ncore = dict([(ir, sum(orbsym[:ncore]==ir)) for ir in irreps])

    if not isinstance(cas_irrep_nocc, dict):
        # list => dict
        cas_irrep_nocc = dict([(ir, n) for ir,n in enumerate(cas_irrep_nocc)
                               if n > 0])

    irrep_ncas = {}
    for k, v in cas_irrep_nocc.items():
        if isinstance(k, str):
            irrep_ncas[symm.irrep_name2id(mol.groupname, k)] = v
        else:
            irrep_ncas[k] = v

    ncas_rest = casscf.ncas - sum(irrep_ncas.values())
    if ncas_rest > 0:
        mask = numpy.ones(len(orbsym), dtype=bool)
# remove core and specified active space
        for ir in irrep_ncas:
            mask[orbsym == ir] = False
        for ir, ncore in irrep_ncore.items():
            idx = numpy.where(orbsym == ir)[0]
            mask[idx[:ncore]] = False

        cas_rest = orbsym[mask][:ncas_rest]
        cas_rest = dict([(ir, numpy.count_nonzero(cas_rest==ir))
                         for ir in set(cas_rest)])
        log.info('Given active space %s < casscf active space size %d',
                 cas_irrep_nocc, casscf.ncas)
        log.info('Add %s to active space', cas_rest)
        irrep_ncas.update(cas_rest)
    elif ncas_rest < 0:
        raise ValueError('Given active space %s > casscf active space size %d'
                         % (cas_irrep_nocc, casscf.ncas))

    caslst = []
    for ir, ncas in irrep_ncas.items():
        if ncas > 0:
            if ir in irrep_ncore:
                nc = irrep_ncore[ir]
            else:
                nc = 0
            no = nc + ncas
            idx = numpy.where(orbsym == ir)[0]
            caslst.extend(idx[nc:no])
    caslst = numpy.sort(numpy.asarray(caslst)) + base
    if len(caslst) < casscf.ncas:
        raise ValueError('Not enough orbitals found for core %s, cas %s' %
                         (cas_irrep_ncore, cas_irrep_nocc))

    if log.verbose >= logger.INFO:
        log.info('ncore for each irreps %s',
                 dict([(symm.irrep_id2name(mol.groupname, k), v)
                       for k,v in irrep_ncore.items()]))
        log.info('ncas for each irreps %s',
                 dict([(symm.irrep_id2name(mol.groupname, k), v)
                       for k,v in irrep_ncas.items()]))
        log.info('(%d-based) caslst = %s', base, caslst)
    return caslst
Exemplo n.º 25
0
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute

    [ A  B][X]
    [-B -A][Y]
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert(mo_coeff.dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ==2)[0]
    viridx = numpy.where(mo_occ==0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsym = hf_symm.get_orbsym(mol, mo_coeff) % 10
        sym_forbid = (orbsym[occidx,None] ^ orbsym[viridx]) != wfnsym

    #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
    #fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff))
    #foo = fock[occidx[:,None],occidx]
    #fvv = fock[viridx[:,None],viridx]
    foo = numpy.diag(mo_energy[occidx])
    fvv = numpy.diag(mo_energy[viridx])

    hdiag = (fvv.diagonal().reshape(-1,1) - foo.diagonal()).T
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel()))

    mo_coeff = numpy.asarray(numpy.hstack((orbo,orbv)), order='F')
    vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0)

    def vind(xys):
        nz = len(xys)
        if wfnsym is not None and mol.symmetry:
            # shape(nz,2,nocc,nvir): 2 ~ X,Y
            xys = numpy.copy(xys).reshape(nz,2,nocc,nvir)
            xys[:,:,sym_forbid] = 0
        dms = numpy.empty((nz,nao,nao))
        for i in range(nz):
            x, y = xys[i].reshape(2,nocc,nvir)
            # *2 for double occupancy
            dmx = reduce(numpy.dot, (orbo, x*2, orbv.T))
            dmy = reduce(numpy.dot, (orbv, y.T*2, orbo.T))
            dms[i] = dmx + dmy  # AX + BY

        v1ao = vresp(dms)
        v1ov = _ao2mo.nr_e2(v1ao, mo_coeff, (0,nocc,nocc,nmo)).reshape(-1,nocc,nvir)
        v1vo = _ao2mo.nr_e2(v1ao, mo_coeff, (nocc,nmo,0,nocc)).reshape(-1,nvir,nocc)
        hx = numpy.empty((nz,2,nocc,nvir), dtype=v1ov.dtype)
        for i in range(nz):
            x, y = xys[i].reshape(2,nocc,nvir)
            hx[i,0] = v1ov[i]
            hx[i,0]+= numpy.einsum('sp,qs->qp', fvv, x)  # AX
            hx[i,0]-= numpy.einsum('sp,pr->sr', foo, x)  # AX
            hx[i,1] =-v1vo[i].T
            hx[i,1]-= numpy.einsum('sp,qs->qp', fvv, y)  #-AY
            hx[i,1]+= numpy.einsum('sp,pr->sr', foo, y)  #-AY

        if wfnsym is not None and mol.symmetry:
            hx[:,:,sym_forbid] = 0
        return hx.reshape(nz,-1)

    return vind, hdiag
Exemplo n.º 26
0
Arquivo: uks.py Projeto: sarminh/pyscf
    def get_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff[0].dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff[0].shape
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        orboa = mo_coeff[0][:, occidxa]
        orbob = mo_coeff[1][:, occidxb]
        orbva = mo_coeff[0][:, viridxa]
        orbvb = mo_coeff[1][:, viridxb]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsyma = orbsyma % 10
            orbsymb = orbsymb % 10
            sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym
            sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym
            sym_forbid = numpy.hstack(
                (sym_forbida.ravel(), sym_forbidb.ravel()))

        e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
        e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia).ravel()
        ed_ia = e_ia.ravel() * d_ia
        hdiag = e_ia.ravel()**2

        vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1)

        def vind(zs):
            nz = len(zs)
            if wfnsym is not None and mol.symmetry:
                zs = numpy.copy(zs)
                zs[:, sym_forbid] = 0
            dmov = numpy.empty((2, nz, nao, nao))
            for i in range(nz):
                z = d_ia * zs[i]
                za = z[:nocca * nvira].reshape(nocca, nvira)
                zb = z[nocca * nvira:].reshape(noccb, nvirb)
                dm = reduce(numpy.dot, (orboa, za, orbva.T))
                dmov[0, i] = dm + dm.T
                dm = reduce(numpy.dot, (orbob, zb, orbvb.T))
                dmov[1, i] = dm + dm.T

            v1ao = vresp(dmov)
            v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0, nocca, nocca, nmo))
            v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0, noccb, noccb, nmo))
            hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
            for i, z in enumerate(zs):
                hx[i] += ed_ia * z
                hx[i] *= d_ia
            return hx

        return vind, hdiag
Exemplo n.º 27
0
def cylindrical_init_guess(mol,
                           norb,
                           nelec,
                           orbsym,
                           wfnsym=0,
                           singlet=True,
                           nroots=1):
    '''
    FCI initial guess for system of cylindrical symmetry.
    (In testing)

    Examples:

    >>> mol = gto.M(atom='O; O 1 1.2', spin=2, symmetry=True)
    >>> orbsym = [6,7,2,3]
    >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10)[0]
    >>> print(ci0.reshape(4,4))
    >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10, singlet=False)[0]
    >>> print(ci0.reshape(4,4))
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    if isinstance(orbsym[0], str):
        orbsym = [symm.irrep_name2id(mol.groupname, x) for x in orbsym]
    orbsym = numpy.asarray(orbsym)
    if isinstance(wfnsym, str):
        wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)

    if mol.groupname in ('Dooh', 'Coov'):

        def irrep_id2lz(irrep_id):
            # See also symm.basis.DOOH_IRREP_ID_TABLE
            level = irrep_id // 10
            d2h_id = irrep_id % 10
            # irrep_id 0,1,4,5 corresponds to lz = 0,2,4,...
            # irrep_id 2,3,6,7 corresponds to lz = 1,3,5,...
            lz = level * 2 + ((d2h_id == 2) | (d2h_id == 3) | (d2h_id == 6) |
                              (d2h_id == 7))

            if isinstance(irrep_id, (int, numpy.number)):
                # irrep_id 1,3,4,6 corresponds to E_y (E_{(-)})
                # irrep_id 0,2,5,7 corresponds to E_x (E_{(+)})
                if (d2h_id == 1) | (d2h_id == 3) | (d2h_id == 4) | (d2h_id
                                                                    == 6):
                    lz = -lz
            else:
                lz[(d2h_id == 1) | (d2h_id == 3) | (d2h_id == 4) |
                   (d2h_id == 6)] *= -1
            return lz

        orb_lz = irrep_id2lz(orbsym)
        wfn_lz = irrep_id2lz(wfnsym)
        d2h_wfnsym_id = wfnsym % 10
    else:
        raise NotImplementedError
        orb_lz = wfn_lz = d2h_wfnsym_id = None

    occslsta = occslstb = cistring._gen_occslst(range(norb), neleca)
    if neleca != nelecb:
        occslstb = cistring._gen_occslst(range(norb), nelecb)
    na = len(occslsta)
    nb = len(occslsta)

    gx_mask = orbsym == 2
    gy_mask = orbsym == 3
    ux_mask = orbsym == 7
    uy_mask = orbsym == 6
    all_lz = set(abs(orb_lz))

    def search_open_shell_det(occ_lst):
        occ_mask = numpy.zeros(norb, dtype=bool)
        occ_mask[occ_lst] = True

        # First search Lz of the open-shell orbital
        for lz_open in all_lz:
            if numpy.count_nonzero(orb_lz == lz_open) % 2 == 1:
                break

        n_gx = numpy.count_nonzero(gx_mask & occ_mask & (orb_lz == lz_open))
        n_gy = numpy.count_nonzero(gy_mask & occ_mask & (orb_lz == -lz_open))
        n_ux = numpy.count_nonzero(ux_mask & occ_mask & (orb_lz == lz_open))
        n_uy = numpy.count_nonzero(uy_mask & occ_mask & (orb_lz == -lz_open))
        if n_gx > n_gy:
            idx = numpy.where(occ_mask & (orb_lz == lz_open) & gx_mask)[0][0]
            idy = numpy.where((~occ_mask) & (orb_lz == -lz_open)
                              & gy_mask)[0][0]
        elif n_gx < n_gy:
            idx = numpy.where((~occ_mask) & (orb_lz == lz_open)
                              & gx_mask)[0][0]
            idy = numpy.where(occ_mask & (orb_lz == -lz_open) & gy_mask)[0][0]
        elif n_ux > n_uy:
            idx = numpy.where(occ_mask & (orb_lz == lz_open) & ux_mask)[0][0]
            idy = numpy.where((~occ_mask) & (orb_lz == -lz_open)
                              & uy_mask)[0][0]
        elif n_ux < n_uy:
            idx = numpy.where((~occ_mask) & (orb_lz == lz_open)
                              & ux_mask)[0][0]
            idy = numpy.where(occ_mask & (orb_lz == -lz_open) & uy_mask)[0][0]
        else:
            raise RuntimeError

        nelec = len(occ_lst)
        det_x = occ_mask.copy()
        det_x[idx] = True
        det_x[idy] = False
        str_x = ''.join(['1' if i else '0' for i in det_x[::-1]])
        addr_x = cistring.str2addr(norb, nelec, str_x)
        det_y = occ_mask.copy()
        det_y[idx] = False
        det_y[idy] = True
        str_y = ''.join(['1' if i else '0' for i in det_y[::-1]])
        addr_y = cistring.str2addr(norb, nelec, str_y)
        return addr_x, addr_y

    ci0 = []
    iroot = 0
    for addr in range(na * nb):
        ci_1 = numpy.zeros((na, nb))
        addra = addr // nb
        addrb = addr % nb
        occa = occslsta[addra]
        occb = occslstb[addrb]
        tot_sym = 0
        for i in occa:
            tot_sym ^= orbsym[i]
        for i in occb:
            tot_sym ^= orbsym[i]
        if tot_sym == d2h_wfnsym_id:
            n_Ex_a = (gx_mask[occa]).sum() + (ux_mask[occa]).sum()
            n_Ey_a = (gy_mask[occa]).sum() + (uy_mask[occa]).sum()
            n_Ex_b = (gx_mask[occb]).sum() + (ux_mask[occb]).sum()
            n_Ey_b = (gy_mask[occb]).sum() + (uy_mask[occb]).sum()
            if abs(n_Ex_a - n_Ey_a) == 1 and abs(n_Ex_b - n_Ey_b) == 1:
                # open-shell for both alpha det and beta det e.g. the
                # valence part of O2 molecule

                addr_x_a, addr_y_a = search_open_shell_det(occa)
                addr_x_b, addr_y_b = search_open_shell_det(occb)
                if singlet:
                    if wfn_lz == 0:
                        ci_1[addr_x_a,addr_x_b] = \
                        ci_1[addr_y_a,addr_y_b] = numpy.sqrt(.5)
                    else:
                        ci_1[addr_x_a, addr_x_b] = numpy.sqrt(.5)
                        ci_1[addr_y_a, addr_y_b] = -numpy.sqrt(.5)
                else:
                    ci_1[addr_x_a, addr_y_b] = numpy.sqrt(.5)
                    ci_1[addr_y_a, addr_x_b] = -numpy.sqrt(.5)
            else:
                # TODO: Other direct-product to direct-sum transofromation
                # which involves CG coefficients.
                ci_1[addra, addrb] = 1
            ci0.append(ci_1.ravel())
            iroot += 1
            if iroot >= nroots:
                break

    return ci0
Exemplo n.º 28
0
def gen_tda_operation(mf, fock_ao=None, wfnsym=None):
    '''(A+B)x

    Kwargs:
        wfnsym : int or str
            Point group symmetry irrep symbol or ID for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma_in_d2h = numpy.asarray(orbsyma) % 10
        orbsymb_in_d2h = numpy.asarray(orbsymb) % 10
        sym_forbida = (orbsyma_in_d2h[occidxa, None]
                       ^ orbsyma_in_d2h[viridxa]) != wfnsym
        sym_forbidb = (orbsymb_in_d2h[occidxb, None]
                       ^ orbsymb_in_d2h[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = mo_energy[0][viridxa] - mo_energy[0][occidxa, None]
    e_ia_b = mo_energy[1][viridxb] - mo_energy[1][occidxb, None]
    e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
    hdiag = e_ia
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = mf.gen_response(hermi=0, max_memory=max_memory)

    def vind(zs):
        zs = numpy.asarray(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs)
            zs[:, sym_forbid] = 0

        za = zs[:, :nocca * nvira].reshape(-1, nocca, nvira)
        zb = zs[:, nocca * nvira:].reshape(-1, noccb, nvirb)
        dmova = lib.einsum('xov,po,qv->xpq', za, orboa, orbva.conj())
        dmovb = lib.einsum('xov,po,qv->xpq', zb, orbob, orbvb.conj())

        v1ao = vresp(numpy.asarray((dmova, dmovb)))

        v1a = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva)
        v1b = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb)
        v1a += numpy.einsum('xia,ia->xia', za, e_ia_a)
        v1b += numpy.einsum('xia,ia->xia', zb, e_ia_b)

        nz = zs.shape[0]
        hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
        if wfnsym is not None and mol.symmetry:
            hx[:, sym_forbid] = 0
        return hx

    return vind, hdiag
Exemplo n.º 29
0
def cylindrical_init_guess(mol, norb, nelec, orbsym, wfnsym=0, singlet=True,
                           nroots=1):
    '''
    FCI initial guess for system of cylindrical symmetry.
    (In testing)

    Examples:

    >>> mol = gto.M(atom='O; O 1 1.2', spin=2, symmetry=True)
    >>> orbsym = [6,7,2,3]
    >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10)[0]
    >>> print(ci0.reshape(4,4))
    >>> ci0 = fci.addons.cylindrical_init_guess(mol, 4, (3,3), orbsym, wfnsym=10, singlet=False)[0]
    >>> print(ci0.reshape(4,4))
    '''
    neleca, nelecb = _unpack_nelec(nelec)
    if isinstance(orbsym[0], str):
        orbsym = [symm.irrep_name2id(mol.groupname, x) for x in orbsym]
    orbsym = numpy.asarray(orbsym)
    if isinstance(wfnsym, str):
        wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)

    if mol.groupname in ('Dooh', 'Coov'):
        def irrep_id2lz(irrep_id):
            # See also symm.basis.DOOH_IRREP_ID_TABLE
            level = irrep_id // 10
            d2h_id = irrep_id % 10
            # irrep_id 0,1,4,5 corresponds to lz = 0,2,4,...
            # irrep_id 2,3,6,7 corresponds to lz = 1,3,5,...
            lz = level * 2 + ((d2h_id==2) | (d2h_id==3) | (d2h_id==6) | (d2h_id==7))

            if isinstance(irrep_id, (int, numpy.number)):
                # irrep_id 1,3,4,6 corresponds to E_y (E_{(-)})
                # irrep_id 0,2,5,7 corresponds to E_x (E_{(+)})
                if (d2h_id==1) | (d2h_id==3) | (d2h_id==4) | (d2h_id==6):
                    lz = -lz
            else:
                lz[(d2h_id==1) | (d2h_id==3) | (d2h_id==4) | (d2h_id==6)] *= -1
            return lz

        orb_lz = irrep_id2lz(orbsym)
        wfn_lz = irrep_id2lz(wfnsym)
        d2h_wfnsym_id = wfnsym % 10
    else:
        raise NotImplementedError
        orb_lz = wfn_lz = d2h_wfnsym_id = None

    occslsta = occslstb = cistring._gen_occslst(range(norb), neleca)
    if neleca != nelecb:
        occslstb = cistring._gen_occslst(range(norb), nelecb)
    na = len(occslsta)
    nb = len(occslsta)

    gx_mask = orbsym == 2
    gy_mask = orbsym == 3
    ux_mask = orbsym == 7
    uy_mask = orbsym == 6
    all_lz = set(abs(orb_lz))
    def search_open_shell_det(occ_lst):
        occ_mask = numpy.zeros(norb, dtype=bool)
        occ_mask[occ_lst] = True

        # First search Lz of the open-shell orbital
        for lz_open in all_lz:
            if numpy.count_nonzero(orb_lz == lz_open) % 2 == 1:
                break

        n_gx = numpy.count_nonzero(gx_mask & occ_mask & (orb_lz == lz_open))
        n_gy = numpy.count_nonzero(gy_mask & occ_mask & (orb_lz ==-lz_open))
        n_ux = numpy.count_nonzero(ux_mask & occ_mask & (orb_lz == lz_open))
        n_uy = numpy.count_nonzero(uy_mask & occ_mask & (orb_lz ==-lz_open))
        if n_gx > n_gy:
            idx = numpy.where(occ_mask    & (orb_lz == lz_open) & gx_mask)[0][0]
            idy = numpy.where((~occ_mask) & (orb_lz ==-lz_open) & gy_mask)[0][0]
        elif n_gx < n_gy:
            idx = numpy.where((~occ_mask) & (orb_lz == lz_open) & gx_mask)[0][0]
            idy = numpy.where(occ_mask    & (orb_lz ==-lz_open) & gy_mask)[0][0]
        elif n_ux > n_uy:
            idx = numpy.where(occ_mask    & (orb_lz == lz_open) & ux_mask)[0][0]
            idy = numpy.where((~occ_mask) & (orb_lz ==-lz_open) & uy_mask)[0][0]
        elif n_ux < n_uy:
            idx = numpy.where((~occ_mask) & (orb_lz == lz_open) & ux_mask)[0][0]
            idy = numpy.where(occ_mask    & (orb_lz ==-lz_open) & uy_mask)[0][0]
        else:
            raise RuntimeError

        nelec = len(occ_lst)
        det_x = occ_mask.copy()
        det_x[idx] = True
        det_x[idy] = False
        str_x = ''.join(['1' if i else '0' for i in det_x[::-1]])
        addr_x = cistring.str2addr(norb, nelec, str_x)
        det_y = occ_mask.copy()
        det_y[idx] = False
        det_y[idy] = True
        str_y = ''.join(['1' if i else '0' for i in det_y[::-1]])
        addr_y = cistring.str2addr(norb, nelec, str_y)
        return addr_x, addr_y

    ci0 = []
    iroot = 0
    for addr in range(na*nb):
        ci_1 = numpy.zeros((na,nb))
        addra = addr // nb
        addrb = addr % nb
        occa = occslsta[addra]
        occb = occslstb[addrb]
        tot_sym = 0
        for i in occa:
            tot_sym ^= orbsym[i]
        for i in occb:
            tot_sym ^= orbsym[i]
        if tot_sym == d2h_wfnsym_id:
            n_Ex_a = (gx_mask[occa]).sum() + (ux_mask[occa]).sum()
            n_Ey_a = (gy_mask[occa]).sum() + (uy_mask[occa]).sum()
            n_Ex_b = (gx_mask[occb]).sum() + (ux_mask[occb]).sum()
            n_Ey_b = (gy_mask[occb]).sum() + (uy_mask[occb]).sum()
            if abs(n_Ex_a - n_Ey_a) == 1 and abs(n_Ex_b - n_Ey_b) == 1:
                # open-shell for both alpha det and beta det e.g. the
                # valence part of O2 molecule

                addr_x_a, addr_y_a = search_open_shell_det(occa)
                addr_x_b, addr_y_b = search_open_shell_det(occb)
                if singlet:
                    if wfn_lz == 0:
                        ci_1[addr_x_a,addr_x_b] = \
                        ci_1[addr_y_a,addr_y_b] = numpy.sqrt(.5)
                    else:
                        ci_1[addr_x_a,addr_x_b] = numpy.sqrt(.5)
                        ci_1[addr_y_a,addr_y_b] =-numpy.sqrt(.5)
                else:
                    ci_1[addr_x_a,addr_y_b] = numpy.sqrt(.5)
                    ci_1[addr_y_a,addr_x_b] =-numpy.sqrt(.5)
            else:
                # TODO: Other direct-product to direct-sum transofromation
                # which involves CG coefficients.
                ci_1[addra,addrb] = 1
            ci0.append(ci_1.ravel())
            iroot += 1
            if iroot >= nroots:
                break

    return ci0
Exemplo n.º 30
0
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute

    [ A  B][X]
    [-B -A][Y]
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma_in_d2h = numpy.asarray(orbsyma) % 10
        orbsymb_in_d2h = numpy.asarray(orbsymb) % 10
        sym_forbida = (orbsyma_in_d2h[occidxa, None]
                       ^ orbsyma_in_d2h[viridxa]) != wfnsym
        sym_forbidb = (orbsymb_in_d2h[occidxb, None]
                       ^ orbsymb_in_d2h[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = mo_energy[0][viridxa] - mo_energy[0][occidxa, None]
    e_ia_b = mo_energy[1][viridxb] - mo_energy[1][occidxb, None]
    e_ia = hdiag = numpy.hstack((e_ia_a.ravel(), e_ia_b.ravel()))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = numpy.hstack((hdiag, -hdiag))

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = mf.gen_response(hermi=0, max_memory=max_memory)

    def vind(xys):
        nz = len(xys)
        xys = numpy.asarray(xys).reshape(nz, 2, -1)
        if wfnsym is not None and mol.symmetry:
            # shape(nz,2,-1): 2 ~ X,Y
            xys = numpy.copy(xys)
            xys[:, :, sym_forbid] = 0

        xs, ys = xys.transpose(1, 0, 2)
        xa = xs[:, :nocca * nvira].reshape(nz, nocca, nvira)
        xb = xs[:, nocca * nvira:].reshape(nz, noccb, nvirb)
        ya = ys[:, :nocca * nvira].reshape(nz, nocca, nvira)
        yb = ys[:, nocca * nvira:].reshape(nz, noccb, nvirb)
        # dms = AX + BY
        dmsa = lib.einsum('xov,po,qv->xpq', xa, orboa, orbva.conj())
        dmsa += lib.einsum('xov,pv,qo->xpq', ya, orbva, orboa.conj())
        dmsb = lib.einsum('xov,po,qv->xpq', xb, orbob, orbvb.conj())
        dmsb += lib.einsum('xov,pv,qo->xpq', yb, orbvb, orbob.conj())

        v1ao = vresp(numpy.asarray((dmsa, dmsb)))

        v1aov = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva)
        v1bov = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb)
        v1avo = lib.einsum('xpq,pv,qo->xov', v1ao[0], orbva.conj(), orboa)
        v1bvo = lib.einsum('xpq,pv,qo->xov', v1ao[1], orbvb.conj(), orbob)

        v1ov = xs * e_ia  # AX
        v1vo = ys * e_ia  # AY
        v1ov[:, :nocca * nvira] += v1aov.reshape(nz, -1)
        v1vo[:, :nocca * nvira] += v1avo.reshape(nz, -1)
        v1ov[:, nocca * nvira:] += v1bov.reshape(nz, -1)
        v1vo[:, nocca * nvira:] += v1bvo.reshape(nz, -1)
        if wfnsym is not None and mol.symmetry:
            v1ov[:, sym_forbid] = 0
            v1vo[:, sym_forbid] = 0
        hx = numpy.hstack((v1ov, -v1vo))
        return hx

    return vind, hdiag
Exemplo n.º 31
0
def caslst_by_irrep(casscf,
                    mo_coeff,
                    cas_irrep_nocc,
                    cas_irrep_ncore=None,
                    s=None,
                    base=BASE):
    '''Given number of active orbitals for each irrep, return the orbital
    indices of active space

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

        cas_irrep_nocc : list or dict
            Number of active orbitals for each irrep.  It can be a dict, eg
            {'A1': 2, 'B2': 4} to indicate the active space size based on
            irrep names, or {0: 2, 3: 4} for irrep Id,  or a list [2, 0, 0, 4]
            (identical to {0: 2, 3: 4}) in which the list index is served as
            the irrep Id.

    Kwargs:
        cas_irrep_ncore : list or dict
            Number of closed shells for each irrep.  It can be a dict, eg
            {'A1': 6, 'B2': 4} to indicate the closed shells based on
            irrep names, or {0: 6, 3: 4} for irrep Id,  or a list [6, 0, 0, 4]
            (identical to {0: 6, 3: 4}) in which the list index is served as
            the irrep Id.  If cas_irrep_ncore is not given, the program
            will generate a guess based on the lowest :attr:`CASCI.ncore`
            orbitals.
        s : ndarray
            overlap matrix
        base : int
            0-based (C-like) or 1-based (Fortran-like) caslst

    Returns:
        A list of orbital indices

    Examples:

    >>> from pyscf import gto, scf, mcscf
    >>> mol = gto.M(atom='N 0 0 0; N 0 0 1', basis='ccpvtz', symmetry=True, verbose=0)
    >>> mf = scf.RHF(mol)
    >>> mf.kernel()
    >>> mc = mcscf.CASSCF(mf, 12, 4)
    >>> mcscf.caslst_by_irrep(mc, mf.mo_coeff, {'E1gx':4, 'E1gy':4, 'E1ux':2, 'E1uy':2})
    [5, 7, 8, 10, 11, 14, 15, 20, 25, 26, 31, 32]
    '''
    mol = casscf.mol
    log = logger.Logger(casscf.stdout, casscf.verbose)
    orbsym = numpy.asarray(scf.hf_symm.get_orbsym(mol, mo_coeff))
    ncore = casscf.ncore

    irreps = set(orbsym)

    if cas_irrep_ncore is not None:
        irrep_ncore = {}
        for k, v in cas_irrep_ncore.items():
            if isinstance(k, str):
                irrep_ncore[symm.irrep_name2id(mol.groupname, k)] = v
            else:
                irrep_ncore[k] = v

        ncore_rest = ncore - sum(irrep_ncore.values())
        if ncore_rest > 0:  # guess core configuration
            mask = numpy.ones(len(orbsym), dtype=bool)
            for ir in irrep_ncore:
                mask[orbsym == ir] = False
            core_rest = orbsym[mask][:ncore_rest]
            core_rest = dict([(ir, numpy.count_nonzero(core_rest == ir))
                              for ir in set(core_rest)])
            log.info('Given core space %s < casscf core size %d',
                     cas_irrep_ncore, ncore)
            log.info('Add %s to core configuration', core_rest)
            irrep_ncore.update(core_rest)
        elif ncore_rest < 0:
            raise ValueError('Given core space %s > casscf core size %d' %
                             (cas_irrep_ncore, ncore))
    else:
        irrep_ncore = dict([(ir, sum(orbsym[:ncore] == ir)) for ir in irreps])

    if not isinstance(cas_irrep_nocc, dict):
        # list => dict
        cas_irrep_nocc = dict([(ir, n) for ir, n in enumerate(cas_irrep_nocc)
                               if n > 0])

    irrep_ncas = {}
    for k, v in cas_irrep_nocc.items():
        if isinstance(k, str):
            irrep_ncas[symm.irrep_name2id(mol.groupname, k)] = v
        else:
            irrep_ncas[k] = v

    ncas_rest = casscf.ncas - sum(irrep_ncas.values())
    if ncas_rest > 0:
        mask = numpy.ones(len(orbsym), dtype=bool)
        # remove core and specified active space
        for ir in irrep_ncas:
            mask[orbsym == ir] = False
        for ir, ncore in irrep_ncore.items():
            idx = numpy.where(orbsym == ir)[0]
            mask[idx[:ncore]] = False

        cas_rest = orbsym[mask][:ncas_rest]
        cas_rest = dict([(ir, numpy.count_nonzero(cas_rest == ir))
                         for ir in set(cas_rest)])
        log.info('Given active space %s < casscf active space size %d',
                 cas_irrep_nocc, casscf.ncas)
        log.info('Add %s to active space', cas_rest)
        irrep_ncas.update(cas_rest)
    elif ncas_rest < 0:
        raise ValueError(
            'Given active space %s > casscf active space size %d' %
            (cas_irrep_nocc, casscf.ncas))

    caslst = []
    for ir, ncas in irrep_ncas.items():
        if ncas > 0:
            if ir in irrep_ncore:
                nc = irrep_ncore[ir]
            else:
                nc = 0
            no = nc + ncas
            idx = numpy.where(orbsym == ir)[0]
            caslst.extend(idx[nc:no])
    caslst = numpy.sort(numpy.asarray(caslst)) + base
    if len(caslst) < casscf.ncas:
        raise ValueError('Not enough orbitals found for core %s, cas %s' %
                         (cas_irrep_ncore, cas_irrep_nocc))

    if log.verbose >= logger.INFO:
        log.info(
            'ncore for each irreps %s',
            dict([(symm.irrep_id2name(mol.groupname, k), v)
                  for k, v in irrep_ncore.items()]))
        log.info(
            'ncas for each irreps %s',
            dict([(symm.irrep_id2name(mol.groupname, k), v)
                  for k, v in irrep_ncas.items()]))
        log.info('(%d-based) caslst = %s', base, caslst)
    return caslst
Exemplo n.º 32
0
def gen_tda_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute (A+B)x

    Kwargs:
        wfnsym : int or str
            Point group symmetry irrep symbol or ID for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff.dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ == 2)[0]
    viridx = numpy.where(mo_occ == 0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:, viridx]
    orbo = mo_coeff[:, occidx]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsym = hf_symm.get_orbsym(mol, mo_coeff)
        orbsym_in_d2h = numpy.asarray(orbsym) % 10  # convert to D2h irreps
        sym_forbid = (orbsym_in_d2h[occidx, None]
                      ^ orbsym_in_d2h[viridx]) != wfnsym

    if fock_ao is None:
        #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
        foo = numpy.diag(mo_energy[occidx])
        fvv = numpy.diag(mo_energy[viridx])
    else:
        fock = reduce(numpy.dot, (mo_coeff.conj().T, fock_ao, mo_coeff))
        foo = fock[occidx[:, None], occidx]
        fvv = fock[viridx[:, None], viridx]

    hdiag = fvv.diagonal() - foo.diagonal()[:, None]
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = hdiag.ravel()

    mo_coeff = numpy.asarray(numpy.hstack((orbo, orbv)), order='F')
    vresp = mf.gen_response(singlet=singlet, hermi=0)

    def vind(zs):
        zs = numpy.asarray(zs).reshape(-1, nocc, nvir)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs)
            zs[:, sym_forbid] = 0

        # *2 for double occupancy
        dmov = lib.einsum('xov,po,qv->xpq', zs * 2, orbo, orbv.conj())
        v1ao = vresp(dmov)
        v1ov = lib.einsum('xpq,po,qv->xov', v1ao, orbo.conj(), orbv)
        v1ov += lib.einsum('xqs,sp->xqp', zs, fvv)
        v1ov -= lib.einsum('xpr,sp->xsr', zs, foo)
        if wfnsym is not None and mol.symmetry:
            v1ov[:, sym_forbid] = 0
        return v1ov.reshape(v1ov.shape[0], -1)

    return vind, hdiag
Exemplo n.º 33
0
def select_mo_by_irrep(casscf,  cas_occ_num, mo = None, base=1):
    if mo is None:
        mo = casscf.mo_coeff
    orbsym = pyscf.symm.label_orb_symm(casscf.mol, casscf.mol.irrep_id,
                                                casscf.mol.symm_orb,
                                                mo, s=casscf._scf.get_ovlp())
    orbsym = orbsym[casscf.ncore:]
    caslst = []
    for k, v in cas_occ_num.iteritems():
        orb_irrep = [ casscf.ncore + base + i for i in range(len(orbsym)) if orbsym[i]== symm.irrep_name2id(casscf.mol.groupname,k) ]
        caslst.extend(orb_irrep[:v])
    return caslst
Exemplo n.º 34
0
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute

    [ A  B][X]
    [-B -A][Y]
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff.dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ == 2)[0]
    viridx = numpy.where(mo_occ == 0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:, viridx]
    orbo = mo_coeff[:, occidx]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsym = hf_symm.get_orbsym(mol, mo_coeff)
        orbsym_in_d2h = numpy.asarray(orbsym) % 10  # convert to D2h irreps
        sym_forbid = (orbsym_in_d2h[occidx, None]
                      ^ orbsym_in_d2h[viridx]) != wfnsym

    #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
    #fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff))
    #foo = fock[occidx[:,None],occidx]
    #fvv = fock[viridx[:,None],viridx]
    foo = numpy.diag(mo_energy[occidx])
    fvv = numpy.diag(mo_energy[viridx])

    hdiag = fvv.diagonal() - foo.diagonal()[:, None]
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = numpy.hstack((hdiag.ravel(), -hdiag.ravel()))

    mo_coeff = numpy.asarray(numpy.hstack((orbo, orbv)), order='F')
    vresp = mf.gen_response(singlet=singlet, hermi=0)

    def vind(xys):
        xys = numpy.asarray(xys).reshape(-1, 2, nocc, nvir)
        if wfnsym is not None and mol.symmetry:
            # shape(nz,2,nocc,nvir): 2 ~ X,Y
            xys = numpy.copy(xys)
            xys[:, :, sym_forbid] = 0

        xs, ys = xys.transpose(1, 0, 2, 3)
        # dms = AX + BY
        # *2 for double occupancy
        dms = lib.einsum('xov,po,qv->xpq', xs * 2, orbo, orbv.conj())
        dms += lib.einsum('xov,pv,qo->xpq', ys * 2, orbv, orbo.conj())

        v1ao = vresp(dms)
        v1ov = lib.einsum('xpq,po,qv->xov', v1ao, orbo.conj(), orbv)
        v1vo = lib.einsum('xpq,pv,qo->xov', v1ao, orbv.conj(), orbo)
        v1ov += lib.einsum('xqs,sp->xqp', xs, fvv)  # AX
        v1ov -= lib.einsum('xpr,sp->xsr', xs, foo)  # AX
        v1vo += lib.einsum('xqs,sp->xqp', ys, fvv)  # AY
        v1vo -= lib.einsum('xpr,sp->xsr', ys, foo)  # AY

        if wfnsym is not None and mol.symmetry:
            v1ov[:, sym_forbid] = 0
            v1vo[:, sym_forbid] = 0

        # (AX, -AY)
        nz = xys.shape[0]
        hx = numpy.hstack((v1ov.reshape(nz, -1), -v1vo.reshape(nz, -1)))
        return hx

    return vind, hdiag
Exemplo n.º 35
0
def sort_mo_by_irrep(casscf, mo_coeff, cas_irrep_nocc,
                     cas_irrep_ncore=None, s=None):
    '''Given number of active orbitals for each irrep, form the active space
    wrt the indices of MOs

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

        cas_irrep_nocc : list or dict
            Number of active orbitals for each irrep.  It can be a dict, eg
            {'A1': 2, 'B2': 4} to indicate the active space size based on
            irrep names, or {0: 2, 3: 4} for irrep Id,  or a list [2, 0, 0, 4]
            (identical to {0: 2, 3: 4}) in which the list index is served as
            the irrep Id.

    Kwargs:
        cas_irrep_ncore : list or dict
            Number of closed shells for each irrep.  It can be a dict, eg
            {'A1': 6, 'B2': 4} to indicate the closed shells based on
            irrep names, or {0: 6, 3: 4} for irrep Id,  or a list [6, 0, 0, 4]
            (identical to {0: 6, 3: 4}) in which the list index is served as
            the irrep Id.  If cas_irrep_ncore is not given, the program
            will generate a guess based on the lowest :attr:`CASCI.ncore`
            orbitals.
        s : ndarray
            overlap matrix

    Returns:
        sorted orbitals, ordered as [c,..,c,a,..,a,v,..,v]

    Examples:

    >>> from pyscf import gto, scf, mcscf
    >>> mol = gto.M(atom='N 0 0 0; N 0 0 1', basis='ccpvtz', verbose=0)
    >>> mf = scf.RHF(mol)
    >>> mf.kernel()
    >>> mc = mcscf.CASSCF(mf, 12, 4)
    >>> mo = mcscf.sort_mo_by_irrep(mc, mf.mo_coeff, {'E1gx':4, 'E1gy':4, 'E1ux':2, 'E1uy':2})
    >>> mc.kernel(mo)[0]
    -109.058040031
    '''
    if s is None:
        s = casscf._scf.get_ovlp()
    orbsym = pyscf.symm.label_orb_symm(casscf.mol, casscf.mol.irrep_id,
                                       casscf.mol.symm_orb, mo_coeff, s)
    if cas_irrep_ncore is None:
        ncore = casscf.ncore
        nocc = ncore + casscf.ncas
        cas_irrep_ncore = {}
        for x in orbsym[:ncore]:
            if x in cas_irrep_ncore:
                cas_irrep_ncore[x] += 1
            else:
                cas_irrep_ncore[x] = 0

    orbidx_by_irrep = {}
    for i,x in enumerate(orbsym):
        if x in orbidx_by_irrep:
            orbidx_by_irrep[x].append(i)
        else:
            orbidx_by_irrep[x] = [i]

    # list => dict
    if not isinstance(cas_irrep_nocc, dict):
        cas_irrep_nocc = dict([(ir, n) for ir,n in enumerate(cas_irrep_nocc)
                               if n > 0])

    caslst = []
    for k, ncas in cas_irrep_nocc.iteritems():
        if isinstance(k, str):
            irid = symm.irrep_name2id(casscf.mol.groupname, k)
        else:
            irid = k
        idx = orbidx_by_irrep[irid]
        if irid in cas_irrep_ncore:
            ncore = cas_irrep_ncore[irid]
        else:
            ncore = 0
        caslst.extend(idx[ncore:ncore+ncas])

    return sort_mo(casscf, mo_coeff, sorted(caslst), 0)