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: orbsym = hf_symm.get_orbsym(mol, mo_coeff) sym_forbid = (orbsym[viridx].reshape(-1, 1) ^ orbsym[occidx]) != wfnsym eai = mo_energy[viridx].reshape(-1, 1) - mo_energy[occidx] if wfnsym is not None and mol.symmetry: eai[sym_forbid] = 0 dai = numpy.sqrt(eai).ravel() edai = eai.ravel() * dai hdiag = eai.ravel()**2 vresp = _gen_rhf_response(mf, singlet=singlet, hermi=1) def vind(zs): nz = len(zs) dmvo = numpy.empty((nz, nao, nao)) for i, z in enumerate(zs): # *2 for double occupancy dm = reduce(numpy.dot, (orbv, (dai * z).reshape(nvir, nocc) * 2, orbo.T)) dmvo[ i] = dm + dm.T # +cc for A+B and K_{ai,jb} in A == K_{ai,bj} in B v1ao = vresp(dmvo) v1vo = _ao2mo.nr_e2(v1ao, mo_coeff, (nocc, nmo, 0, nocc)).reshape(-1, nvir * nocc) for i, z in enumerate(zs): # numpy.sqrt(eai) * (eai*dai*z + v1vo) v1vo[i] += edai * z v1vo[i] *= dai return v1vo.reshape(nz, -1) return vind, hdiag
def gen_vind(self, mf): '''Induced potential''' vresp = _gen_rhf_response(mf, hermi=2) mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ occidx = mo_occ > 0 orbo = mo_coeff[:,occidx] nocc = orbo.shape[1] nao, nmo = mo_coeff.shape def vind(mo1): #direct_scf_bak, mf.direct_scf = mf.direct_scf, False dm1 = [reduce(numpy.dot, (mo_coeff, x*2, orbo.T.conj())) for x in mo1.reshape(3,nmo,nocc)] dm1 = numpy.asarray([d1-d1.conj().T for d1 in dm1]) v1mo = numpy.asarray([reduce(numpy.dot, (mo_coeff.T.conj(), x, orbo)) for x in vresp(dm1)]) #mf.direct_scf = direct_scf_bak return v1mo.ravel() return vind
def gen_vind(self, mf, mo_coeff, mo_occ): '''Induced potential associated with h1_PSO''' vresp = _gen_rhf_response(mf, hermi=2) occidx = mo_occ > 0 orbo = mo_coeff[:, occidx] orbv = mo_coeff[:, ~occidx] nocc = orbo.shape[1] nao, nmo = mo_coeff.shape nvir = nmo - nocc def vind(mo1): #direct_scf_bak, mf.direct_scf = mf.direct_scf, False dm1 = [ reduce(numpy.dot, (orbv, x * 2, orbo.T.conj())) for x in mo1.reshape(-1, nvir, nocc) ] dm1 = numpy.asarray([d1 - d1.conj().T for d1 in dm1]) v1mo = numpy.asarray([ reduce(numpy.dot, (orbv.T.conj(), x, orbo)) for x in vresp(dm1) ]) #mf.direct_scf = direct_scf_bak return v1mo.ravel() return vind
def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mo_energy = sscobj._scf.mo_energy mo_coeff = sscobj._scf.mo_coeff mo_occ = sscobj._scf.mo_occ nset = len(h1) eai = 1. / lib.direct_sum('a-i->ai', mo_energy[mo_occ == 0], mo_energy[mo_occ > 0]) mo1 = numpy.asarray(h1) * -eai if not sscobj.cphf: return mo1 orbo = mo_coeff[:, mo_occ > 0] orbv = mo_coeff[:, mo_occ == 0] nocc = orbo.shape[1] nvir = orbv.shape[1] nmo = nocc + nvir vresp = _gen_rhf_response(mf, singlet=False, hermi=1) mo_v_o = numpy.asarray(numpy.hstack((orbv, orbo)), order='F') def vind(mo1): dm1 = _dm1_mo2ao(mo1.reshape(nset, nvir, nocc), orbv, orbo * 2) # *2 for double occupancy dm1 = dm1 + dm1.transpose(0, 2, 1) v1 = vresp(dm1) v1 = _ao2mo.nr_e2(v1, mo_v_o, (0, nvir, nvir, nmo)).reshape(nset, nvir, nocc) v1 *= eai return v1.ravel() mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log) log.timer('solving FC CPHF eqn', *cput1) return mo1.reshape(nset, nvir, nocc)
def _gen_hop_rhf_external(mf, with_symmetry=True, verbose=None): mol = mf.mol mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ 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 with_symmetry and mol.symmetry: orbsym = hf_symm.get_orbsym(mol, mo_coeff) sym_forbid = orbsym[viridx].reshape(-1,1) != orbsym[occidx] 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, fock_ao, mo_coeff)) foo = fock[occidx[:,None],occidx] fvv = fock[viridx[:,None],viridx] hdiag = fvv.diagonal().reshape(-1,1) - foo.diagonal() if with_symmetry and mol.symmetry: hdiag[sym_forbid] = 0 hdiag = hdiag.ravel() vrespz = _gen_rhf_response(mf, singlet=None, hermi=2) def hop_real2complex(x1): x1 = x1.reshape(nvir,nocc) if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid] = 0 x2 = numpy.einsum('ps,sq->pq', fvv, x1) x2-= numpy.einsum('ps,rp->rs', foo, x1) d1 = reduce(numpy.dot, (orbv, x1*2, orbo.T.conj())) dm1 = d1 - d1.T.conj() # No Coulomb and fxc contribution for anti-hermitian DM v1 = vrespz(dm1) x2 += reduce(numpy.dot, (orbv.T.conj(), v1, orbo)) if with_symmetry and mol.symmetry: x2[sym_forbid] = 0 return x2.ravel() vresp1 = _gen_rhf_response(mf, singlet=False, hermi=1) def hop_rhf2uhf(x1): from pyscf.dft import numint # See also rhf.TDA triplet excitation x1 = x1.reshape(nvir,nocc) if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid] = 0 x2 = numpy.einsum('ps,sq->pq', fvv, x1) x2-= numpy.einsum('ps,rp->rs', foo, x1) d1 = reduce(numpy.dot, (orbv, x1*2, orbo.T.conj())) dm1 = d1 + d1.T.conj() v1ao = vresp1(dm1) x2 += reduce(numpy.dot, (orbv.T.conj(), v1ao, orbo)) if with_symmetry and mol.symmetry: x2[sym_forbid] = 0 return x2.ravel() return hop_real2complex, hdiag, hop_rhf2uhf, hdiag
def gen_vind(self, mf): ''' [ A B][X] [-B -A][Y] ''' 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: orbsym = hf_symm.get_orbsym(mol, mo_coeff) sym_forbid = (orbsym[viridx].reshape(-1, 1) ^ orbsym[occidx]) != 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]) e_ai = hdiag = fvv.diagonal().reshape(-1, 1) - foo.diagonal() 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,nvir,nocc): 2 ~ X,Y xys = numpy.copy(zs).reshape(nz, 2, nvir, nocc) xys[:, :, sym_forbid] = 0 dms = numpy.empty((nz, nao, nao)) for i in range(nz): x, y = xys[i].reshape(2, nvir, nocc) # *2 for double occupancy dmx = reduce(numpy.dot, (orbv, x * 2, orbo.T)) dmy = reduce(numpy.dot, (orbo, y.T * 2, orbv.T)) dms[i] = dmx + dmy # AX + BY v1ao = vresp(dms) v1vo = _ao2mo.nr_e2(v1ao, mo_coeff, (nocc, nmo, 0, nocc)).reshape(-1, nvir, nocc) v1ov = _ao2mo.nr_e2(v1ao, mo_coeff, (0, nocc, nocc, nmo)) v1ov = v1ov.reshape(-1, nocc, nvir).transpose(0, 2, 1) hx = numpy.empty((nz, 2, nvir, nocc), dtype=v1vo.dtype) for i in range(nz): x, y = xys[i].reshape(2, nvir, nocc) hx[i, 0] = v1vo[i] hx[i, 0] += numpy.einsum('ps,sq->pq', fvv, x) # AX hx[i, 0] -= numpy.einsum('ps,rp->rs', foo, x) # AX hx[i, 1] = -v1ov[i] hx[i, 1] -= numpy.einsum('ps,sq->pq', fvv, y) #-AY hx[i, 1] += numpy.einsum('ps,rp->rs', foo, y) #-AY if wfnsym is not None and mol.symmetry: hx[:, :, sym_forbid] = 0 return hx.reshape(nz, -1) return vind, hdiag
def gen_tda_hop(mf, fock_ao=None, singlet=True, wfnsym=None, max_memory=2000): '''(A+B)x Kwargs: wfnsym : int Point group symmetry 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: orbsym = hf_symm.get_orbsym(mol, mo_coeff) sym_forbid = (orbsym[viridx].reshape(-1, 1) ^ orbsym[occidx]) != 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.T, fock_ao, mo_coeff)) foo = fock[occidx[:, None], occidx] fvv = fock[viridx[:, None], viridx] hdiag = fvv.diagonal().reshape(-1, 1) - foo.diagonal() 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, nvir, nocc) zs[:, sym_forbid] = 0 dmvo = numpy.empty((nz, nao, nao)) for i, z in enumerate(zs): # *2 for double occupancy dmvo[i] = reduce(numpy.dot, (orbv, z.reshape(nvir, nocc) * 2, orbo.T)) v1ao = vresp(dmvo) #v1vo = numpy.asarray([reduce(numpy.dot, (orbv.T, v, orbo)) for v in v1ao]) v1vo = _ao2mo.nr_e2(v1ao, mo_coeff, (nocc, nmo, 0, nocc)).reshape(-1, nvir, nocc) for i, z in enumerate(zs): v1vo[i] += numpy.einsum('ps,sq->pq', fvv, z.reshape(nvir, nocc)) v1vo[i] -= numpy.einsum('ps,rp->rs', foo, z.reshape(nvir, nocc)) if wfnsym is not None and mol.symmetry: v1vo[:, sym_forbid] = 0 return v1vo.reshape(nz, -1) return vind, hdiag