def get_vind(self, mf): ''' [ A B ][X] [-B* -A*][Y] ''' singlet = self.singlet cell = mf.cell kpts = mf.kpts mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nkpts = len(mo_occ) nao, nmo = mo_coeff[0].shape occidx = [numpy.where(mo_occ[k]==2)[0] for k in range(nkpts)] viridx = [numpy.where(mo_occ[k]==0)[0] for k in range(nkpts)] orbo = [mo_coeff[k][:,occidx[k]] for k in range(nkpts)] orbv = [mo_coeff[k][:,viridx[k]] for k in range(nkpts)] e_ia = _get_e_ia(mo_energy, mo_occ) hdiag = numpy.hstack([x.ravel() for x in e_ia]) tot_x = hdiag.size hdiag = numpy.hstack((hdiag, hdiag)) mem_now = lib.current_memory()[0] max_memory = max(2000, self.max_memory*.8-mem_now) vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0, max_memory=max_memory) def vind(xys): nz = len(xys) z1xs = [_unpack(xy[:tot_x], mo_occ) for xy in xys] z1ys = [_unpack(xy[tot_x:], mo_occ) for xy in xys] dmov = numpy.empty((nz,nkpts,nao,nao), dtype=numpy.complex128) for i in range(nz): for k in range(nkpts): # *2 for double occupancy dmx = z1xs[i][k] * 2 dmy = z1ys[i][k] * 2 dmov[i,k] = reduce(numpy.dot, (orbo[k], dmx, orbv[k].T.conj())) dmov[i,k]+= reduce(numpy.dot, (orbv[k], dmy.T, orbo[k].T.conj())) with lib.temporary_env(mf, exxdiv=None): v1ao = vresp(dmov) v1s = [] for i in range(nz): dmx = z1xs[i] dmy = z1ys[i] v1xs = [] v1ys = [] for k in range(nkpts): v1x = reduce(numpy.dot, (orbo[k].T.conj(), v1ao[i,k], orbv[k])) v1y = reduce(numpy.dot, (orbv[k].T.conj(), v1ao[i,k], orbo[k])).T v1x+= e_ia[k] * dmx[k] v1y+= e_ia[k] * dmy[k] v1xs.append(v1x.ravel()) v1ys.append(-v1y.ravel()) v1s += v1xs + v1ys return lib.asarray(v1s).reshape(nz,-1) return vind, hdiag
def _gen_hop_rhf_external(mf, verbose=None): #FIXME: numerically unstable with small mesh? #TODO: Add a warning message for small mesh. from pyscf.pbc.dft import numint from pyscf.pbc.scf.newton_ah import _unpack cell = mf.cell kpts = mf.kpts mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ nkpts = len(mo_occ) occidx = [numpy.where(mo_occ[k] == 2)[0] for k in range(nkpts)] viridx = [numpy.where(mo_occ[k] == 0)[0] for k in range(nkpts)] orbo = [mo_coeff[k][:, occidx[k]] for k in range(nkpts)] orbv = [mo_coeff[k][:, viridx[k]] for k in range(nkpts)] h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(cell, dm0) fock = [ reduce(numpy.dot, (mo_coeff[k].T.conj(), fock_ao[k], mo_coeff[k])) for k in range(nkpts) ] foo = [fock[k][occidx[k][:, None], occidx[k]] for k in range(nkpts)] fvv = [fock[k][viridx[k][:, None], viridx[k]] for k in range(nkpts)] hdiag = [(fvv[k].diagonal().real[:, None] - foo[k].diagonal().real) * 2 for k in range(nkpts)] hdiag = numpy.hstack([x.ravel() for x in hdiag]) vresp1 = _gen_rhf_response(mf, singlet=False, hermi=1) def hop_rhf2uhf(x1): x1 = _unpack(x1, mo_occ) dmvo = [] for k in range(nkpts): # *2 for double occupancy dm1 = reduce(numpy.dot, (orbv[k], x1[k] * 2, orbo[k].T.conj())) dmvo.append(dm1 + dm1.T.conj()) dmvo = lib.asarray(dmvo) v1ao = vresp1(dmvo) x2 = [0] * nkpts for k in range(nkpts): x2[k] = numpy.einsum('ps,sq->pq', fvv[k], x1[k]) x2[k] -= numpy.einsum('ps,rp->rs', foo[k], x1[k]) x2[k] += reduce(numpy.dot, (orbv[k].T.conj(), v1ao[k], orbo[k])) # The displacement x2 corresponds to the response of rotation for bra. # Hessian*x also provides the rotation for ket which equals to # x2.T.conj(). The overall displacement is x2 + x2.T.conj(). This is # the reason of x2.real below return numpy.hstack([x.real.ravel() for x in x2]) return hop_rhf2uhf, hdiag
def _gen_hop_rhf_external(mf, verbose=None): #FIXME: numerically unstable with small mesh? #TODO: Add a warning message for small mesh. from pyscf.pbc.dft import numint from pyscf.pbc.scf.newton_ah import _unpack cell = mf.cell kpts = mf.kpts mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ nkpts = len(mo_occ) occidx = [numpy.where(mo_occ[k]==2)[0] for k in range(nkpts)] viridx = [numpy.where(mo_occ[k]==0)[0] for k in range(nkpts)] orbo = [mo_coeff[k][:,occidx[k]] for k in range(nkpts)] orbv = [mo_coeff[k][:,viridx[k]] for k in range(nkpts)] h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(cell, dm0) fock = [reduce(numpy.dot, (mo_coeff[k].T.conj(), fock_ao[k], mo_coeff[k])) for k in range(nkpts)] foo = [fock[k][occidx[k][:,None],occidx[k]] for k in range(nkpts)] fvv = [fock[k][viridx[k][:,None],viridx[k]] for k in range(nkpts)] hdiag = [(fvv[k].diagonal().real[:,None]-foo[k].diagonal().real) * 2 for k in range(nkpts)] hdiag = numpy.hstack([x.ravel() for x in hdiag]) vresp1 = _gen_rhf_response(mf, singlet=False, hermi=1) def hop_rhf2uhf(x1): x1 = _unpack(x1, mo_occ) dmvo = [] for k in range(nkpts): # *2 for double occupancy dm1 = reduce(numpy.dot, (orbv[k], x1[k]*2, orbo[k].T.conj())) dmvo.append(dm1 + dm1.T.conj()) dmvo = lib.asarray(dmvo) v1ao = vresp1(dmvo) x2 = [0] * nkpts for k in range(nkpts): x2[k] = numpy.einsum('ps,sq->pq', fvv[k], x1[k]) x2[k]-= numpy.einsum('ps,rp->rs', foo[k], x1[k]) x2[k]+= reduce(numpy.dot, (orbv[k].T.conj(), v1ao[k], orbo[k])) # The displacement x2 corresponds to the response of rotation for bra. # Hessian*x also provides the rotation for ket which equals to # x2.T.conj(). The overall displacement is x2 + x2.T.conj(). This is # the reason of x2.real below return numpy.hstack([x.real.ravel() for x in x2]) return hop_rhf2uhf, hdiag
def gen_vind(self, mf): singlet = self.singlet cell = mf.cell kpts = mf.kpts mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nkpts = len(mo_occ) nao, nmo = mo_coeff[0].shape occidx = [numpy.where(mo_occ[k] == 2)[0] for k in range(nkpts)] viridx = [numpy.where(mo_occ[k] == 0)[0] for k in range(nkpts)] orbo = [mo_coeff[k][:, occidx[k]] for k in range(nkpts)] orbv = [mo_coeff[k][:, viridx[k]] for k in range(nkpts)] e_ia = _get_e_ia(mo_energy, mo_occ) # FIXME: hdiag corresponds to the orbital energy with the exxdiv # correction. The integrals in A, B matrices do not have the # contribution from the exxdiv. Should the exchange correction be # removed from hdiag? hdiag = numpy.hstack([x.ravel() for x in e_ia]) mem_now = lib.current_memory()[0] max_memory = max(2000, self.max_memory * .8 - mem_now) vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0, max_memory=max_memory) def vind(zs): nz = len(zs) z1s = [_unpack(z, mo_occ) for z in zs] dmov = numpy.empty((nz, nkpts, nao, nao), dtype=numpy.complex128) for i in range(nz): for k in range(nkpts): # *2 for double occupancy dm1 = z1s[i][k] * 2 dmov[i, k] = reduce(numpy.dot, (orbo[k], dm1, orbv[k].conj().T)) with lib.temporary_env(mf, exxdiv=None): v1ao = vresp(dmov) v1s = [] for i in range(nz): dm1 = z1s[i] for k in range(nkpts): v1vo = reduce(numpy.dot, (orbo[k].conj().T, v1ao[i, k], orbv[k])) v1vo += e_ia[k] * dm1[k] v1s.append(v1vo.ravel()) return lib.asarray(v1s).reshape(nz, -1) return vind, hdiag
def _gen_hop_rhf_external(mf, verbose=None): #FIXME: numerically unstable with small gs? #TODO: Add a warning message for small gs. from pyscf.pbc.dft import numint from pyscf.pbc.tddft.rhf import _unpack cell = mf.cell kpts = mf.kpts mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nkpts = len(mo_occ) occidx = [numpy.where(mo_occ[k] == 2)[0] for k in range(nkpts)] viridx = [numpy.where(mo_occ[k] == 0)[0] for k in range(nkpts)] orbo = [mo_coeff[k][:, occidx[k]] for k in range(nkpts)] orbv = [mo_coeff[k][:, viridx[k]] for k in range(nkpts)] h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(cell, dm0) fock = [ reduce(numpy.dot, (mo_coeff[k].T.conj(), fock_ao[k], mo_coeff[k])) for k in range(nkpts) ] foo = [fock[k][occidx[k][:, None], occidx[k]] for k in range(nkpts)] fvv = [fock[k][viridx[k][:, None], viridx[k]] for k in range(nkpts)] hdiag = [(fvv[k].diagonal().reshape(-1, 1) - foo[k].diagonal()) * 2 for k in range(nkpts)] hdiag = numpy.hstack([x.ravel() for x in hdiag]) vresp1 = _gen_rhf_response(mf, singlet=False, hermi=1) def hop_rhf2uhf(x1): x1 = _unpack(x1, mo_occ) dmvo = [] for k in range(nkpts): # *2 for double occupancy dm1 = reduce(numpy.dot, (orbv[k], x1[k] * 2, orbo[k].T.conj())) dmvo.append(dm1 + dm1.T.conj()) dmvo = lib.asarray(dmvo) v1ao = vresp1(dmvo) x2 = [0] * nkpts for k in range(nkpts): x2[k] = numpy.einsum('ps,sq->pq', fvv[k], x1[k]) x2[k] -= numpy.einsum('ps,rp->rs', foo[k], x1[k]) x2[k] += reduce(numpy.dot, (orbv[k].T.conj(), v1ao[k], orbo[k])) return numpy.hstack([x.ravel() for x in x2]) return hop_rhf2uhf, hdiag
def get_vind(self, mf): singlet = self.singlet cell = mf.cell kpts = mf.kpts mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nkpts = len(mo_occ) nao, nmo = mo_coeff[0].shape occidx = [numpy.where(mo_occ[k] == 2)[0] for k in range(nkpts)] viridx = [numpy.where(mo_occ[k] == 0)[0] for k in range(nkpts)] orbo = [mo_coeff[k][:, occidx[k]] for k in range(nkpts)] orbv = [mo_coeff[k][:, viridx[k]] for k in range(nkpts)] eai = _get_eai(mo_energy, mo_occ) hdiag = numpy.hstack([x.ravel() for x in eai]) mem_now = lib.current_memory()[0] max_memory = max(2000, self.max_memory * .8 - mem_now) vresp = _gen_rhf_response(mf, singlet, hermi=0, max_memory=max_memory) def vind(zs): nz = len(zs) z1s = [_unpack(z, mo_occ) for z in zs] dmvo = numpy.empty((nz, nkpts, nao, nao), dtype=numpy.complex128) for i in range(nz): # *2 for double occupancy dm1 = z1s[i] * 2 for k in range(nkpts): dmvo[i, k] = reduce(numpy.dot, (orbv[k], dm1[k], orbo[k].T.conj())) v1ao = vresp(dmvo) v1s = [] for i in range(nz): dm1 = z1s[i] for k in range(nkpts): v1vo = reduce(numpy.dot, (orbv[k].T.conj(), v1ao[i, k], orbo[k])) v1vo += eai[k] * dm1[k] v1s.append(v1vo.ravel()) return lib.asarray(v1s).reshape(nz, -1) return vind, hdiag