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 == 1)[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 = ghf_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
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
def gen_g_hop_ghf(mf, mo_coeff, mo_occ, fock_ao=None, h1e=None, with_symmetry=True): mol = mf.mol occidx = numpy.where(mo_occ == 1)[0] viridx = numpy.where(mo_occ == 0)[0] nocc = len(occidx) nvir = len(viridx) orbo = mo_coeff[:, occidx] orbv = mo_coeff[:, viridx] if with_symmetry and mol.symmetry: orbsym = ghf_symm.get_orbsym(mol, mo_coeff) sym_forbid = orbsym[viridx, None] != orbsym[occidx] if fock_ao is None: if h1e is None: h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(mol, dm0) fock = reduce(numpy.dot, (mo_coeff.T.conj(), fock_ao, mo_coeff)) g = fock[viridx[:, None], occidx] foo = fock[occidx[:, None], occidx] fvv = fock[viridx[:, None], viridx] h_diag = fvv.diagonal()[:, None] - foo.diagonal() if with_symmetry and mol.symmetry: g[sym_forbid] = 0 h_diag[sym_forbid] = 0 vind = _gen_ghf_response(mf, mo_coeff, mo_occ, hermi=1) def h_op(x): x = x.reshape(nvir, nocc) if with_symmetry and mol.symmetry: x = x.copy() x[sym_forbid] = 0 x2 = numpy.einsum('ps,sq->pq', fvv, x) x2 -= numpy.einsum('ps,rp->rs', foo, x) d1 = reduce(numpy.dot, (orbv, x, orbo.T.conj())) dm1 = d1 + d1.T.conj() v1 = vind(dm1) x2 += reduce(numpy.dot, (orbv.T.conj(), v1, orbo)) if with_symmetry and mol.symmetry: x2[sym_forbid] = 0 return x2.ravel() return g.reshape(-1), h_op, h_diag.reshape(-1)
def gen_g_hop_ghf(mf, mo_coeff, mo_occ, fock_ao=None, h1e=None, with_symmetry=True): mol = mf.mol occidx = numpy.where(mo_occ==1)[0] viridx = numpy.where(mo_occ==0)[0] nocc = len(occidx) nvir = len(viridx) orbo = mo_coeff[:,occidx] orbv = mo_coeff[:,viridx] if with_symmetry and mol.symmetry: orbsym = ghf_symm.get_orbsym(mol, mo_coeff) sym_forbid = orbsym[viridx,None] != orbsym[occidx] if fock_ao is None: dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = mf.get_fock(h1e, dm=dm0) fock = reduce(numpy.dot, (mo_coeff.conj().T, fock_ao, mo_coeff)) g = fock[viridx[:,None],occidx] foo = fock[occidx[:,None],occidx] fvv = fock[viridx[:,None],viridx] h_diag = fvv.diagonal().real[:,None] - foo.diagonal().real if with_symmetry and mol.symmetry: g[sym_forbid] = 0 h_diag[sym_forbid] = 0 vind = _gen_ghf_response(mf, mo_coeff, mo_occ, hermi=1) def h_op(x): x = x.reshape(nvir,nocc) if with_symmetry and mol.symmetry: x = x.copy() x[sym_forbid] = 0 x2 = numpy.einsum('ps,sq->pq', fvv, x) x2-= numpy.einsum('ps,rp->rs', foo, x) d1 = reduce(numpy.dot, (orbv, x, orbo.conj().T)) dm1 = d1 + d1.conj().T v1 = vind(dm1) x2 += reduce(numpy.dot, (orbv.conj().T, v1, orbo)) if with_symmetry and mol.symmetry: x2[sym_forbid] = 0 return x2.ravel() return g.reshape(-1), h_op, h_diag.reshape(-1)
def gen_tdhf_operation(mf, fock_ao=None, wfnsym=None): '''Generate function to compute [ A B ][X] [-B* -A*][Y] ''' mol = mf.mol mo_coeff = mf.mo_coeff 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 #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())).real mo_coeff = numpy.asarray(numpy.hstack((orbo, orbv)), order='F') vresp = mf.gen_response(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 dms = lib.einsum('xov,qv,po->xpq', xs, orbv.conj(), orbo) dms += lib.einsum('xov,pv,qo->xpq', ys, orbv, orbo.conj()) v1ao = vresp(dms) v1ov = lib.einsum('xpq,po,qv->xov', v1ao, orbo.conj(), orbv) v1vo = lib.einsum('xpq,qo,pv->xov', v1ao, orbo, orbv.conj()) 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.conj()) # (A*)Y v1vo -= lib.einsum('xpr,sp->xsr', ys, foo.conj()) # (A*)Y if wfnsym is not None and mol.symmetry: v1ov[:, sym_forbid] = 0 v1vo[:, sym_forbid] = 0 # (AX, (-A*)Y) nz = xys.shape[0] hx = numpy.hstack((v1ov.reshape(nz, -1), -v1vo.reshape(nz, -1))) return hx return vind, hdiag
def gen_tda_operation(mf, fock_ao=None, wfnsym=None): '''A 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 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 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().real mo_coeff = numpy.asarray(numpy.hstack((orbo, orbv)), order='F') vresp = mf.gen_response(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 dmov = lib.einsum('xov,qv,po->xpq', zs, orbv.conj(), orbo) 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