def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, s1=None, with_cphf=None): cput1 = (time.clock(), time.time()) log = logger.Logger(self.stdout, self.verbose) if mo_energy is None: mo_energy = self._scf.mo_energy if mo_occ is None: mo_occ = self._scf.mo_occ if with_cphf is None: with_cphf = self.cphf mol = self.mol mo_coeff = self._scf.mo_coeff orboa = mo_coeff[0][:,mo_occ[0]>0] orbob = mo_coeff[1][:,mo_occ[1]>0] if h1 is None: dm0 = self._scf.make_rdm1(mo_coeff, mo_occ) h1 = self.make_h10(mol, dm0) h1a = [reduce(numpy.dot, (mo_coeff[0].T.conj(), x, orboa)) for x in h1[0]] h1b = [reduce(numpy.dot, (mo_coeff[1].T.conj(), x, orbob)) for x in h1[1]] h1 = (numpy.asarray(h1a), numpy.asarray(h1b)) if s1 is None: s1 = self.make_s10(mol) s1a = [reduce(numpy.dot, (mo_coeff[0].T.conj(), x, orboa)) for x in s1] s1b = [reduce(numpy.dot, (mo_coeff[1].T.conj(), x, orbob)) for x in s1] s1 = (numpy.asarray(s1a), numpy.asarray(s1b)) cput1 = log.timer('first order Fock matrix', *cput1) if self.cphf: vind = self.gen_vind(self._scf, mo_coeff, mo_occ) mo10, mo_e10 = ucphf.solve(vind, mo_energy, mo_occ, h1, s1, self.max_cycle_cphf, self.conv_tol, verbose=log) else: mo10, mo_e10 = solve_mo1(mo_energy, mo_occ, h1, s1) logger.timer(self, 'solving mo1 eqn', *cput1) return mo10, mo_e10
def solve_mo1(sscobj, mo_energy=None, mo_coeff=None, mo_occ=None, h1=None, s1=None, with_cphf=None): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) if mo_energy is None: mo_energy = sscobj._scf.mo_energy if mo_coeff is None: mo_coeff = sscobj._scf.mo_coeff if mo_occ is None: mo_occ = sscobj._scf.mo_occ if with_cphf is None: with_cphf = sscobj.cphf mol = sscobj.mol if h1 is None: atmlst = sorted(set([j for i,j in sscobj.nuc_pair])) h1a, h1b = make_h1_pso(mol, sscobj._scf.mo_coeff, mo_occ, atmlst) else: h1a, h1b = h1 h1a = numpy.asarray(h1a) h1b = numpy.asarray(h1b) if with_cphf: if callable(with_cphf): vind = with_cphf else: vind = gen_vind(sscobj._scf, mo_coeff, mo_occ) mo1, mo_e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), None, sscobj.max_cycle_cphf, sscobj.conv_tol, verbose=log) else: eai_aa = lib.direct_sum('i-a->ai', mo_energy[0][mo_occ[0]>0], mo_energy[0][mo_occ[0]==0]) eai_bb = lib.direct_sum('i-a->ai', mo_energy[1][mo_occ[1]>0], mo_energy[1][mo_occ[1]==0]) mo1 = (h1a * (1/eai_aa), h1b * (1/eai_bb)) mo_e1 = None logger.timer(sscobj, 'solving mo1 eqn', *cput1) return mo1, mo_e1
def _response_dm1(mp, Xvo): Xvo, XVO = Xvo nvira, nocca = Xvo.shape nvirb, noccb = XVO.shape nmoa = nocca + nvira nmob = noccb + nvirb nova = nocca * nvira mo_energy = mp._scf.mo_energy mo_occ = mp.mo_occ mo_a, mo_b = mp.mo_coeff def fvind(x): x1a = x[0,:nova].reshape(Xvo.shape) x1b = x[0,nova:].reshape(XVO.shape) dm1a = reduce(numpy.dot, (mo_a[:,nocca:], x1a, mo_a[:,:nocca].T)) dm1b = reduce(numpy.dot, (mo_b[:,noccb:], x1b, mo_b[:,:noccb].T)) va, vb = mp._scf.get_veff(mp.mol, (dm1a+dm1a.T, dm1b+dm1b.T)) va = reduce(numpy.dot, (mo_a[:,nocca:].T, va, mo_a[:,:nocca])) vb = reduce(numpy.dot, (mo_b[:,noccb:].T, vb, mo_b[:,:noccb])) return numpy.hstack((va.ravel(), vb.ravel())) dvo = ucphf.solve(fvind, mo_energy, mo_occ, (Xvo,XVO), max_cycle=30)[0] dm1a = numpy.zeros((nmoa,nmoa)) dm1a[nocca:,:nocca] = dvo[0] dm1a[:nocca,nocca:] = dvo[0].T dm1b = numpy.zeros((nmob,nmob)) dm1b[noccb:,:noccb] = dvo[1] dm1b[:noccb,noccb:] = dvo[1].T return dm1a, dm1b
def Z(self): so, sv = self.so, self.sv nocc, nvir = self.nocc, self.nvir Ax0_Core = self.Ax0_Core e, mo_occ = self.e, self.mo_occ F_0_mo = self.nc_deriv.F_0_mo def fx(X): X_ = (X[:, :nocc[0] * nvir[0]].reshape( (nvir[0], nocc[0])), X[:, nocc[0] * nvir[0]:].reshape( (nvir[1], nocc[1]))) return np.concatenate([ v.ravel() for v in Ax0_Core(sv, so, sv, so, in_cphf=True)(X_) ]) Z = ucphf.solve( fx, e, mo_occ, (F_0_mo[0, None, sv[0], so[0]], F_0_mo[1, None, sv[1], so[1]]), max_cycle=100, tol=self.cphf_tol)[0] # output Z shape is (1, nvir, nocc), we remove the first dimension Z = (Z[0][0], Z[1][0]) return Z
def D_r(self) -> np.ndarray: L = self.L D_r = np.copy(self.D_r_oovv) so, sv = self.so, self.sv Ax0_Core = self.Ax0_Core e, mo_occ = self.e, self.mo_occ nvir, nocc, nmo = self.nvir, self.nocc, self.nmo def fx(X): X_alpha = X[:, :nocc[0] * nvir[0]].reshape((nvir[0], nocc[0])) X_beta = X[:, nocc[0] * nvir[0]:].reshape((nvir[1], nocc[1])) Ax = Ax0_Core(sv, so, sv, so, in_cphf=True)((X_alpha, X_beta)) result = np.concatenate([Ax[0].reshape(-1), Ax[1].reshape(-1)]) return result D_r_vo = ucphf.solve(fx, e, mo_occ, L, max_cycle=100, tol=self.cphf_tol)[0] D_r[0][sv[0], so[0]] = D_r_vo[0] D_r[1][sv[1], so[1]] = D_r_vo[1] return D_r
def _response_dm1(mp, Xvo): Xvo, XVO = Xvo nvira, nocca = Xvo.shape nvirb, noccb = XVO.shape nmoa = nocca + nvira nmob = noccb + nvirb nova = nocca * nvira mo_energy = mp._scf.mo_energy mo_occ = mp.mo_occ mo_a, mo_b = mp.mo_coeff def fvind(x): x1a = x[0,:nova].reshape(Xvo.shape) x1b = x[0,nova:].reshape(XVO.shape) dm1a = reduce(numpy.dot, (mo_a[:,nocca:], x1a, mo_a[:,:nocca].T)) dm1b = reduce(numpy.dot, (mo_b[:,noccb:], x1b, mo_b[:,:noccb].T)) va, vb = mp._scf.get_veff(mp.mol, (dm1a+dm1a.T, dm1b+dm1b.T)) va = reduce(numpy.dot, (mo_a[:,nocca:].T, va, mo_a[:,:nocca])) vb = reduce(numpy.dot, (mo_b[:,noccb:].T, vb, mo_b[:,:noccb])) return numpy.hstack((va.ravel(), vb.ravel())) dvo = ucphf.solve(fvind, mo_energy, mo_occ, (Xvo,XVO), max_cycle=30)[0] dm1a = numpy.zeros((nmoa,nmoa)) dm1a[nocca:,:nocca] = dvo[0] dm1a[:nocca,nocca:] = dvo[0].T dm1b = numpy.zeros((nmob,nmob)) dm1b[noccb:,:noccb] = dvo[1] dm1b[:noccb,noccb:] = dvo[1].T return dm1a, dm1b
def _response_dm1(mycc, Xvo, eris=None): Xvo, XVO = Xvo nvira, nocca = Xvo.shape nvirb, noccb = XVO.shape nmoa = nocca + nvira nmob = noccb + nvirb nova = nocca * nvira with_frozen = not ((mycc.frozen is None) or (isinstance(mycc.frozen, (int, numpy.integer)) and mycc.frozen == 0) or (len(mycc.frozen) == 0)) if eris is None or with_frozen: mo_energy = mycc._scf.mo_energy mo_occ = mycc.mo_occ mo_a, mo_b = mycc.mo_coeff def fvind(x): x1a = x[0, :nova].reshape(Xvo.shape) x1b = x[0, nova:].reshape(XVO.shape) dm1a = reduce(numpy.dot, (mo_a[:, nocca:], x1a, mo_a[:, :nocca].T)) dm1b = reduce(numpy.dot, (mo_b[:, noccb:], x1b, mo_b[:, :noccb].T)) va, vb = mycc._scf.get_veff(mycc.mol, (dm1a + dm1a.T, dm1b + dm1b.T)) va = reduce(numpy.dot, (mo_a[:, nocca:].T, va, mo_a[:, :nocca])) vb = reduce(numpy.dot, (mo_b[:, noccb:].T, vb, mo_b[:, :noccb])) return numpy.hstack((va.ravel(), vb.ravel())) else: moidx = mycc.get_frozen_mask() mo_energy = eris.mo_energy mo_occ = (mycc.mo_occ[0][moidx[0]], mycc.mo_occ[1][moidx[1]]) ovvo = numpy.empty((nocca, nvira, nvira, nocca)) ovVO = numpy.empty((nocca, nvira, nvirb, noccb)) OVVO = numpy.empty((noccb, nvirb, nvirb, noccb)) for i in range(nocca): ovvo[i] = eris.ovvo[i] ovvo[i] = ovvo[i] * 2 - ovvo[i].transpose(1, 0, 2) ovvo[i] -= eris.oovv[i].transpose(2, 1, 0) ovVO[i] = eris.ovVO[i] * 2 for i in range(noccb): OVVO[i] = eris.OVVO[i] OVVO[i] = OVVO[i] * 2 - OVVO[i].transpose(1, 0, 2) OVVO[i] -= eris.OOVV[i].transpose(2, 1, 0) def fvind(x): x1a = x[0, :nova].reshape(Xvo.shape) x1b = x[0, nova:].reshape(XVO.shape) va = numpy.einsum('iabj,bj->ai', ovvo, x1a) va += numpy.einsum('iabj,bj->ai', ovVO, x1b) vb = numpy.einsum('iabj,bj->ai', OVVO, x1b) vb += numpy.einsum('jbai,bj->ai', ovVO, x1a) return numpy.hstack((va.ravel(), vb.ravel())) dvo = ucphf.solve(fvind, mo_energy, mo_occ, (Xvo, XVO), max_cycle=30)[0] dm1a = numpy.zeros((nmoa, nmoa)) dm1a[nocca:, :nocca] = dvo[0] dm1a[:nocca, nocca:] = dvo[0].T dm1b = numpy.zeros((nmob, nmob)) dm1b[noccb:, :noccb] = dvo[1] dm1b[:noccb, noccb:] = dvo[1].T return dm1a, dm1b
def solve_mo1(sscobj, mo_energy=None, mo_coeff=None, mo_occ=None, h1=None, s1=None, with_cphf=None): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) if mo_energy is None: mo_energy = sscobj._scf.mo_energy if mo_coeff is None: mo_coeff = sscobj._scf.mo_coeff if mo_occ is None: mo_occ = sscobj._scf.mo_occ if with_cphf is None: with_cphf = sscobj.cphf mol = sscobj.mol if h1 is None: atmlst = sorted(set([j for i,j in sscobj.nuc_pair])) h1a, h1b = make_h1_pso(mol, sscobj._scf.mo_coeff, mo_occ, atmlst) else: h1a, h1b = h1 h1a = numpy.asarray(h1a) h1b = numpy.asarray(h1b) if with_cphf: if callable(with_cphf): vind = with_cphf else: vind = gen_vind(sscobj._scf, mo_coeff, mo_occ) mo1, mo_e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), None, sscobj.max_cycle_cphf, sscobj.conv_tol, verbose=log) else: eai_aa = lib.direct_sum('i-a->ai', mo_energy[0][mo_occ[0]>0], mo_energy[0][mo_occ[0]==0]) eai_bb = lib.direct_sum('i-a->ai', mo_energy[1][mo_occ[1]>0], mo_energy[1][mo_occ[1]==0]) mo1 = (h1a * (1/eai_aa), h1b * (1/eai_bb)) mo_e1 = None logger.timer(sscobj, 'solving mo1 eqn', *cput1) return mo1, mo_e1
def hyper_polarizability(polobj, with_cphf=True): from pyscf.prop.nmr import uhf as uhf_nmr log = logger.new_logger(polobj) mf = polobj._scf mol = mf.mol mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 mo0a, mo0b = mo_coeff orboa = mo0a[:, occidxa] orbva = mo0a[:, ~occidxa] orbob = mo0b[:, occidxb] orbvb = mo0b[:, ~occidxb] charges = mol.atom_charges() coords = mol.atom_coords() charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum() with mol.with_common_orig(charge_center): int_r = mol.intor_symmetric('int1e_r', comp=3) h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa) h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob) s1a = numpy.zeros_like(h1a) s1b = numpy.zeros_like(h1b) vind = polobj.gen_vind(mf, mo_coeff, mo_occ) if with_cphf: mo1, e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a, h1b), (s1a, s1b), polobj.max_cycle_cphf, polobj.conv_tol, verbose=log) else: mo1, e1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a, h1b), (s1a, s1b)) mo1a = lib.einsum('xqi,pq->xpi', mo1[0], mo0a) mo1b = lib.einsum('xqi,pq->xpi', mo1[1], mo0b) dm1a = lib.einsum('xpi,qi->xpq', mo1a, orboa) dm1b = lib.einsum('xpi,qi->xpq', mo1b, orbob) dm1a = dm1a + dm1a.transpose(0, 2, 1) dm1b = dm1b + dm1b.transpose(0, 2, 1) vresp = _gen_uhf_response(mf, hermi=1) h1ao = int_r + vresp(numpy.stack((dm1a, dm1b))) s0 = mf.get_ovlp() e3 = lib.einsum('xpq,ypi,zqi->xyz', h1ao[0], mo1a, mo1a) e3 += lib.einsum('xpq,ypi,zqi->xyz', h1ao[1], mo1b, mo1b) e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1a, mo1a, e1[0]) e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1b, mo1b, e1[1]) e3 = (e3 + e3.transpose(1, 2, 0) + e3.transpose(2, 0, 1) + e3.transpose(0, 2, 1) + e3.transpose(1, 0, 2) + e3.transpose(2, 1, 0)) e3 = -e3 log.debug('Static hyper polarizability tensor\n%s', e3) return e3
def solve_mo1(nmrobj, mo_energy=None, mo_coeff=None, mo_occ=None, h1=None, s1=None, with_cphf=None): '''Solve the first order equation Kwargs: with_cphf : boolean or function(dm_mo) => v1_mo If a boolean value is given, the value determines whether CPHF equation will be solved or not. The induced potential will be generated by the function gen_vind. If a function is given, CPHF equation will be solved, and the given function is used to compute induced potential ''' cput1 = (time.clock(), time.time()) log = logger.Logger(nmrobj.stdout, nmrobj.verbose) if mo_energy is None: mo_energy = nmrobj._scf.mo_energy if mo_coeff is None: mo_coeff = nmrobj._scf.mo_coeff if mo_occ is None: mo_occ = nmrobj._scf.mo_occ if with_cphf is None: with_cphf = nmrobj.cphf mol = nmrobj.mol orboa = mo_coeff[0][:, mo_occ[0] > 0] orbob = mo_coeff[1][:, mo_occ[1] > 0] if h1 is None: dm0 = nmrobj._scf.make_rdm1(mo_coeff, mo_occ) h1 = nmrobj.get_fock(dm0) h1 = (lib.einsum('xpq,pi,qj->xij', h1[0], mo_coeff[0].conj(), orboa), lib.einsum('xpq,pi,qj->xij', h1[1], mo_coeff[1].conj(), orbob)) cput1 = log.timer('first order Fock matrix', *cput1) if s1 is None: s1 = nmrobj.get_ovlp(mol) s1 = (lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[0].conj(), orboa), lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[1].conj(), orbob)) if with_cphf: if callable(with_cphf): vind = with_cphf else: vind = gen_vind(nmrobj._scf, mo_coeff, mo_occ) mo10, mo_e10 = ucphf.solve(vind, mo_energy, mo_occ, h1, s1, nmrobj.max_cycle_cphf, nmrobj.conv_tol, verbose=log) else: mo10, mo_e10 = _solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1) logger.timer(nmrobj, 'solving mo1 eqn', *cput1) return mo10, mo_e10
def _response_dm1(mycc, Xvo, eris=None): Xvo, XVO = Xvo nvira, nocca = Xvo.shape nvirb, noccb = XVO.shape nmoa = nocca + nvira nmob = noccb + nvirb nova = nocca * nvira with_frozen = not (mycc.frozen is None or mycc.frozen is 0) if eris is None or with_frozen: mo_energy = mycc._scf.mo_energy mo_occ = mycc.mo_occ mo_a, mo_b = mycc.mo_coeff def fvind(x): x1a = x[0,:nova].reshape(Xvo.shape) x1b = x[0,nova:].reshape(XVO.shape) dm1a = reduce(numpy.dot, (mo_a[:,nocca:], x1a, mo_a[:,:nocca].T)) dm1b = reduce(numpy.dot, (mo_b[:,noccb:], x1b, mo_b[:,:noccb].T)) va, vb = mycc._scf.get_veff(mycc.mol, (dm1a+dm1a.T, dm1b+dm1b.T)) va = reduce(numpy.dot, (mo_a[:,nocca:].T, va, mo_a[:,:nocca])) vb = reduce(numpy.dot, (mo_b[:,noccb:].T, vb, mo_b[:,:noccb])) return numpy.hstack((va.ravel(), vb.ravel())) else: moidx = mycc.get_frozen_mask() mo_energy = eris.mo_energy mo_occ = (mycc.mo_occ[0][moidx[0]], mycc.mo_occ[1][moidx[1]]) ovvo = numpy.empty((nocca,nvira,nvira,nocca)) ovVO = numpy.empty((nocca,nvira,nvirb,noccb)) OVVO = numpy.empty((noccb,nvirb,nvirb,noccb)) for i in range(nocca): ovvo[i] = eris.ovvo[i] ovvo[i] = ovvo[i] * 2 - ovvo[i].transpose(1,0,2) ovvo[i]-= eris.oovv[i].transpose(2,1,0) ovVO[i] = eris.ovVO[i] * 2 for i in range(noccb): OVVO[i] = eris.OVVO[i] OVVO[i] = OVVO[i] * 2 - OVVO[i].transpose(1,0,2) OVVO[i]-= eris.OOVV[i].transpose(2,1,0) def fvind(x): x1a = x[0,:nova].reshape(Xvo.shape) x1b = x[0,nova:].reshape(XVO.shape) va = numpy.einsum('iabj,bj->ai', ovvo, x1a) va+= numpy.einsum('iabj,bj->ai', ovVO, x1b) vb = numpy.einsum('iabj,bj->ai', OVVO, x1b) vb+= numpy.einsum('jbai,bj->ai', ovVO, x1a) return numpy.hstack((va.ravel(), vb.ravel())) dvo = ucphf.solve(fvind, mo_energy, mo_occ, (Xvo,XVO), max_cycle=30)[0] dm1a = numpy.zeros((nmoa,nmoa)) dm1a[nocca:,:nocca] = dvo[0] dm1a[:nocca,nocca:] = dvo[0].T dm1b = numpy.zeros((nmob,nmob)) dm1b[noccb:,:noccb] = dvo[1] dm1b[:noccb,noccb:] = dvo[1].T return dm1a, dm1b
def hyper_polarizability(polobj, with_cphf=True): from pyscf.prop.nmr import uhf as uhf_nmr log = logger.new_logger(polobj) mf = polobj._scf mol = mf.mol mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 mo0a, mo0b = mo_coeff orboa = mo0a[:, occidxa] orbva = mo0a[:,~occidxa] orbob = mo0b[:, occidxb] orbvb = mo0b[:,~occidxb] charges = mol.atom_charges() coords = mol.atom_coords() charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum() with mol.with_common_orig(charge_center): int_r = mol.intor_symmetric('int1e_r', comp=3) h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa) h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob) s1a = numpy.zeros_like(h1a) s1b = numpy.zeros_like(h1b) vind = polobj.gen_vind(mf, mo_coeff, mo_occ) if with_cphf: mo1, e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), (s1a,s1b), polobj.max_cycle_cphf, polobj.conv_tol, verbose=log) else: mo1, e1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a,h1b), (s1a,s1b)) mo1a = lib.einsum('xqi,pq->xpi', mo1[0], mo0a) mo1b = lib.einsum('xqi,pq->xpi', mo1[1], mo0b) dm1a = lib.einsum('xpi,qi->xpq', mo1a, orboa) dm1b = lib.einsum('xpi,qi->xpq', mo1b, orbob) dm1a = dm1a + dm1a.transpose(0,2,1) dm1b = dm1b + dm1b.transpose(0,2,1) vresp = _gen_uhf_response(mf, hermi=1) h1ao = int_r + vresp(numpy.stack((dm1a, dm1b))) s0 = mf.get_ovlp() e3 = lib.einsum('xpq,ypi,zqi->xyz', h1ao[0], mo1a, mo1a) e3 += lib.einsum('xpq,ypi,zqi->xyz', h1ao[1], mo1b, mo1b) e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1a, mo1a, e1[0]) e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1b, mo1b, e1[1]) e3 = (e3 + e3.transpose(1,2,0) + e3.transpose(2,0,1) + e3.transpose(0,2,1) + e3.transpose(1,0,2) + e3.transpose(2,1,0)) e3 = -e3 log.debug('Static hyper polarizability tensor\n%s', e3) return e3
def polarizability(polobj, with_cphf=True): from pyscf.prop.nmr import uhf as uhf_nmr log = logger.new_logger(polobj) mf = polobj._scf mol = mf.mol mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 mo0a, mo0b = mo_coeff orboa = mo0a[:, occidxa] orbva = mo0a[:, ~occidxa] orbob = mo0b[:, occidxb] orbvb = mo0b[:, ~occidxb] charges = mol.atom_charges() coords = mol.atom_coords() charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum() with mol.with_common_orig(charge_center): int_r = mol.intor_symmetric('int1e_r', comp=3) h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa) h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob) s1a = numpy.zeros_like(h1a) s1b = numpy.zeros_like(h1b) vind = polobj.gen_vind(mf, mo_coeff, mo_occ) if with_cphf: mo1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a, h1b), (s1a, s1b), polobj.max_cycle_cphf, polobj.conv_tol, verbose=log)[0] else: mo1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a, h1b), (s1a, s1b))[0] e2 = numpy.einsum('xpi,ypi->xy', h1a, mo1[0]) e2 += numpy.einsum('xpi,ypi->xy', h1b, mo1[1]) e2 = -(e2 + e2.T) if mf.verbose >= logger.INFO: xx, yy, zz = e2.diagonal() log.note('Isotropic polarizability %.12g', (xx + yy + zz) / 3) log.note('Polarizability anisotropy %.12g', (.5 * ((xx - yy)**2 + (yy - zz)**2 + (zz - xx)**2))**.5) log.debug('Static polarizability tensor\n%s', e2) return e2
def solve_mo1(nmrobj, mo_energy=None, mo_coeff=None, mo_occ=None, h1=None, s1=None, with_cphf=None): '''Solve the first order equation Kwargs: with_cphf : boolean or function(dm_mo) => v1_mo If a boolean value is given, the value determines whether CPHF equation will be solved or not. The induced potential will be generated by the function gen_vind. If a function is given, CPHF equation will be solved, and the given function is used to compute induced potential ''' cput1 = (time.clock(), time.time()) log = logger.Logger(nmrobj.stdout, nmrobj.verbose) if mo_energy is None: mo_energy = nmrobj._scf.mo_energy if mo_coeff is None: mo_coeff = nmrobj._scf.mo_coeff if mo_occ is None: mo_occ = nmrobj._scf.mo_occ if with_cphf is None: with_cphf = nmrobj.cphf mol = nmrobj.mol orboa = mo_coeff[0][:,mo_occ[0]>0] orbob = mo_coeff[1][:,mo_occ[1]>0] if h1 is None: dm0 = nmrobj._scf.make_rdm1(mo_coeff, mo_occ) h1 = nmrobj.get_fock(dm0) h1 = (lib.einsum('xpq,pi,qj->xij', h1[0], mo_coeff[0].conj(), orboa), lib.einsum('xpq,pi,qj->xij', h1[1], mo_coeff[1].conj(), orbob)) cput1 = log.timer('first order Fock matrix', *cput1) if s1 is None: s1 = nmrobj.get_ovlp(mol) s1 = (lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[0].conj(), orboa), lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[1].conj(), orbob)) if with_cphf: if callable(with_cphf): vind = with_cphf else: vind = gen_vind(nmrobj._scf, mo_coeff, mo_occ) mo10, mo_e10 = ucphf.solve(vind, mo_energy, mo_occ, h1, s1, nmrobj.max_cycle_cphf, nmrobj.conv_tol, verbose=log) else: mo10, mo_e10 = _solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1) logger.timer(nmrobj, 'solving mo1 eqn', *cput1) return mo10, mo_e10
def polarizability(polobj, with_cphf=True): from pyscf.prop.nmr import uhf as uhf_nmr log = logger.new_logger(polobj) mf = polobj._scf mol = mf.mol mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 mo0a, mo0b = mo_coeff orboa = mo0a[:, occidxa] orbva = mo0a[:,~occidxa] orbob = mo0b[:, occidxb] orbvb = mo0b[:,~occidxb] charges = mol.atom_charges() coords = mol.atom_coords() charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum() with mol.with_common_orig(charge_center): int_r = mol.intor_symmetric('int1e_r', comp=3) h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa) h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob) s1a = numpy.zeros_like(h1a) s1b = numpy.zeros_like(h1b) vind = polobj.gen_vind(mf, mo_coeff, mo_occ) if with_cphf: mo1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), (s1a,s1b), polobj.max_cycle_cphf, polobj.conv_tol, verbose=log)[0] else: mo1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a,h1b), (s1a,s1b))[0] e2 = numpy.einsum('xpi,ypi->xy', h1a, mo1[0]) e2+= numpy.einsum('xpi,ypi->xy', h1b, mo1[1]) e2 = -(e2 + e2.T) if mf.verbose >= logger.INFO: xx, yy, zz = e2.diagonal() log.note('Isotropic polarizability %.12g', (xx+yy+zz)/3) log.note('Polarizability anisotropy %.12g', (.5 * ((xx-yy)**2 + (yy-zz)**2 + (zz-xx)**2))**.5) log.debug('Static polarizability tensor\n%s', e2) return e2
def h_op(x): x = x.reshape(natm,3) hx = numpy.einsum('abxy,ax->by', de2, x) h1aoa = 0 h1aob = 0 s1ao = 0 for ia in range(natm): shl0, shl1, p0, p1 = aoslices[ia] h1ao_i = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/0/%d' % ia) h1aoa += numpy.einsum('x,xij->ij', x[ia], h1ao_i) h1ao_i = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/1/%d' % ia) h1aob += numpy.einsum('x,xij->ij', x[ia], h1ao_i) s1ao_i = numpy.zeros((3,nao,nao)) s1ao_i[:,p0:p1] += s1a[:,p0:p1] s1ao_i[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1) s1ao += numpy.einsum('x,xij->ij', x[ia], s1ao_i) s1voa = reduce(numpy.dot, (mo_coeff[0].T, s1ao, mocca)) s1vob = reduce(numpy.dot, (mo_coeff[1].T, s1ao, moccb)) h1voa = reduce(numpy.dot, (mo_coeff[0].T, h1aoa, mocca)) h1vob = reduce(numpy.dot, (mo_coeff[1].T, h1aob, moccb)) mo1, mo_e1 = ucphf.solve(fvind, mo_energy, mo_occ, (h1voa,h1vob), (s1voa,s1vob)) mo1a = numpy.dot(mo_coeff[0], mo1[0]) mo1b = numpy.dot(mo_coeff[1], mo1[1]) mo_e1a = mo_e1[0].reshape(nocca,nocca) mo_e1b = mo_e1[1].reshape(noccb,noccb) dm1a = numpy.einsum('pi,qi->pq', mo1a, mocca) dm1b = numpy.einsum('pi,qi->pq', mo1b, moccb) dme1a = numpy.einsum('pi,qi,i->pq', mo1a, mocca, mo_ea) dme1a = dme1a + dme1a.T + reduce(numpy.dot, (mocca, mo_e1a, mocca.T)) dme1b = numpy.einsum('pi,qi,i->pq', mo1b, moccb, mo_eb) dme1b = dme1b + dme1b.T + reduce(numpy.dot, (moccb, mo_e1b, moccb.T)) dme1 = dme1a + dme1b for ja in range(natm): q0, q1 = aoslices[ja][2:] h1aoa = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/0/%d' % ja) h1aob = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/1/%d' % ja) hx[ja] += numpy.einsum('xpq,pq->x', h1aoa, dm1a) * 2 hx[ja] += numpy.einsum('xpq,pq->x', h1aob, dm1b) * 2 hx[ja] -= numpy.einsum('xpq,pq->x', s1a[:,q0:q1], dme1[q0:q1]) hx[ja] -= numpy.einsum('xpq,qp->x', s1a[:,q0:q1], dme1[:,q0:q1]) return hx.ravel()
def h_op(x): x = x.reshape(natm, 3) hx = numpy.einsum('abxy,ax->by', de2, x) h1aoa = 0 h1aob = 0 s1ao = 0 for ia in range(natm): shl0, shl1, p0, p1 = aoslices[ia] h1ao_i = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/0/%d' % ia) h1aoa += numpy.einsum('x,xij->ij', x[ia], h1ao_i) h1ao_i = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/1/%d' % ia) h1aob += numpy.einsum('x,xij->ij', x[ia], h1ao_i) s1ao_i = numpy.zeros((3, nao, nao)) s1ao_i[:, p0:p1] += s1a[:, p0:p1] s1ao_i[:, :, p0:p1] += s1a[:, p0:p1].transpose(0, 2, 1) s1ao += numpy.einsum('x,xij->ij', x[ia], s1ao_i) s1voa = reduce(numpy.dot, (mo_coeff[0].T, s1ao, mocca)) s1vob = reduce(numpy.dot, (mo_coeff[1].T, s1ao, moccb)) h1voa = reduce(numpy.dot, (mo_coeff[0].T, h1aoa, mocca)) h1vob = reduce(numpy.dot, (mo_coeff[1].T, h1aob, moccb)) mo1, mo_e1 = ucphf.solve(fvind, mo_energy, mo_occ, (h1voa, h1vob), (s1voa, s1vob)) mo1a = numpy.dot(mo_coeff[0], mo1[0]) mo1b = numpy.dot(mo_coeff[1], mo1[1]) mo_e1a = mo_e1[0].reshape(nocca, nocca) mo_e1b = mo_e1[1].reshape(noccb, noccb) dm1a = numpy.einsum('pi,qi->pq', mo1a, mocca) dm1b = numpy.einsum('pi,qi->pq', mo1b, moccb) dme1a = numpy.einsum('pi,qi,i->pq', mo1a, mocca, mo_ea) dme1a = dme1a + dme1a.T + reduce(numpy.dot, (mocca, mo_e1a, mocca.T)) dme1b = numpy.einsum('pi,qi,i->pq', mo1b, moccb, mo_eb) dme1b = dme1b + dme1b.T + reduce(numpy.dot, (moccb, mo_e1b, moccb.T)) dme1 = dme1a + dme1b for ja in range(natm): q0, q1 = aoslices[ja][2:] h1aoa = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/0/%d' % ja) h1aob = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/1/%d' % ja) hx[ja] += numpy.einsum('xpq,pq->x', h1aoa, dm1a) * 2 hx[ja] += numpy.einsum('xpq,pq->x', h1aob, dm1b) * 2 hx[ja] -= numpy.einsum('xpq,pq->x', s1a[:, q0:q1], dme1[q0:q1]) hx[ja] -= numpy.einsum('xpq,qp->x', s1a[:, q0:q1], dme1[:, q0:q1]) return hx.ravel()
def solve_cphf_uhf(mf, Lvo, max_cycle, tol, logger): ''' Solve the CPHF equations. Args: mf : a UHF object Lvo : right-hand side the the response equation max_cycle : number of iterations for the CPHF solver tol : convergence tolerance for the CPHF solver logger : Logger object ''' logger.info('Solving the CPHF response equations') logger.info('Max. iterations: {0:d}'.format(max_cycle)) logger.info('Convergence tolerance: {0:.3g}'.format(tol)) # Currently we need to make the CPHF solver somewhat more talkative to see anything at all. cphf_verbose = logger.verbose if logger.verbose == lib.logger.INFO: cphf_verbose = lib.logger.DEBUG nva, noa = Lvo[0].shape nvb, nob = Lvo[1].shape def fvind(zflat): za = zflat[0, :noa * nva].reshape(nva, noa) zb = zflat[0, -nob * nvb:].reshape(nvb, nob) ra, rb = fock_response_uhf(mf, [za, zb], full=False) rflat = np.hstack( [ra.reshape((1, noa * nva)), rb.reshape((1, nob * nvb))]) return rflat zvo = ucphf.solve(fvind, mf.mo_energy, mf.mo_occ, Lvo, max_cycle=max_cycle, tol=tol, verbose=cphf_verbose)[0] logger.info('CPHF iterations finished') return zvo
def solve_mo1_pso(hfcobj, hfc_nuc=None, with_cphf=None): if hfc_nuc is None: hfc_nuc = hfcobj.hfc_nuc if with_cphf is None: with_cphf = hfcobj.cphf mf = hfcobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ mol = hfcobj.mol h1a, h1b = uhf_ssc.make_h1_pso(mol, mo_coeff, mo_occ, hfc_nuc) h1a = numpy.asarray(h1a) h1b = numpy.asarray(h1b) if with_cphf: vind = gen_vind(mf, mo_coeff, mo_occ) mo1, mo_e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), None, hfcobj.max_cycle_cphf, hfcobj.conv_tol) else: eai_aa = lib.direct_sum('i-a->ai', mo_energy[0][mo_occ[0]>0], mo_energy[0][mo_occ[0]==0]) eai_bb = lib.direct_sum('i-a->ai', mo_energy[1][mo_occ[1]>0], mo_energy[1][mo_occ[1]==0]) mo1 = (h1a * (1/eai_aa), h1b * (1/eai_bb)) return mo1
def solve_mo1_pso(hfcobj, hfc_nuc=None, with_cphf=None): if hfc_nuc is None: hfc_nuc = hfcobj.hfc_nuc if with_cphf is None: with_cphf = hfcobj.cphf mf = hfcobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ mol = hfcobj.mol h1a, h1b = uhf_ssc.make_h1_pso(mol, mo_coeff, mo_occ, hfc_nuc) h1a = numpy.asarray(h1a) h1b = numpy.asarray(h1b) if with_cphf: vind = gen_vind(mf, mo_coeff, mo_occ) mo1, mo_e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a, h1b), None, hfcobj.max_cycle_cphf, hfcobj.conv_tol) else: eai_aa = lib.direct_sum('i-a->ai', mo_energy[0][mo_occ[0] > 0], mo_energy[0][mo_occ[0] == 0]) eai_bb = lib.direct_sum('i-a->ai', mo_energy[1][mo_occ[1] > 0], mo_energy[1][mo_occ[1] == 0]) mo1 = (h1a * (1 / eai_aa), h1b * (1 / eai_bb)) return mo1
def kernel(td_grad, x_y, atmlst=None, max_memory=2000, verbose=logger.INFO): log = logger.new_logger(td_grad, verbose) time0 = time.clock(), time.time() mol = td_grad.mol mf = td_grad.base._scf mo_coeff = mf.mo_coeff 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] 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] nao = mo_coeff[0].shape[0] nmoa = nocca + nvira nmob = noccb + nvirb (xa, xb), (ya, yb) = x_y xpya = (xa+ya).reshape(nocca,nvira).T xpyb = (xb+yb).reshape(noccb,nvirb).T xmya = (xa-ya).reshape(nocca,nvira).T xmyb = (xb-yb).reshape(noccb,nvirb).T dvva = numpy.einsum('ai,bi->ab', xpya, xpya) + numpy.einsum('ai,bi->ab', xmya, xmya) dvvb = numpy.einsum('ai,bi->ab', xpyb, xpyb) + numpy.einsum('ai,bi->ab', xmyb, xmyb) dooa =-numpy.einsum('ai,aj->ij', xpya, xpya) - numpy.einsum('ai,aj->ij', xmya, xmya) doob =-numpy.einsum('ai,aj->ij', xpyb, xpyb) - numpy.einsum('ai,aj->ij', xmyb, xmyb) dmzvopa = reduce(numpy.dot, (orbva, xpya, orboa.T)) dmzvopb = reduce(numpy.dot, (orbvb, xpyb, orbob.T)) dmzvoma = reduce(numpy.dot, (orbva, xmya, orboa.T)) dmzvomb = reduce(numpy.dot, (orbvb, xmyb, orbob.T)) dmzooa = reduce(numpy.dot, (orboa, dooa, orboa.T)) dmzoob = reduce(numpy.dot, (orbob, doob, orbob.T)) dmzooa+= reduce(numpy.dot, (orbva, dvva, orbva.T)) dmzoob+= reduce(numpy.dot, (orbvb, dvvb, orbvb.T)) vj, vk = mf.get_jk(mol, (dmzooa, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T, dmzoob, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T), hermi=0) vj = vj.reshape(2,3,nao,nao) vk = vk.reshape(2,3,nao,nao) veff0doo = vj[0,0]+vj[1,0] - vk[:,0] wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2 wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2 veff = vj[0,1]+vj[1,1] - vk[:,1] veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:,nocca:], xpya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:,noccb:], xpyb) * 2 veff = -vk[:,2] veff0moma = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0momb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0moma[nocca:,nocca:], xmya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0momb[noccb:,noccb:], xmyb) * 2 def fvind(x): dm1 = numpy.empty((2,nao,nao)) xa = x[0,:nvira*nocca].reshape(nvira,nocca) xb = x[0,nvira*nocca:].reshape(nvirb,noccb) dma = reduce(numpy.dot, (orbva, xa, orboa.T)) dmb = reduce(numpy.dot, (orbvb, xb, orbob.T)) dm1[0] = dma + dma.T dm1[1] = dmb + dmb.T vj, vk = mf.get_jk(mol, dm1) v1 = vj[0] + vj[1] - vk v1a = reduce(numpy.dot, (orbva.T, v1[0], orboa)) v1b = reduce(numpy.dot, (orbvb.T, v1[1], orbob)) return numpy.hstack((v1a.ravel(), v1b.ravel())) z1a, z1b = ucphf.solve(fvind, mo_energy, mo_occ, (wvoa,wvob), max_cycle=td_grad.cphf_max_cycle, tol=td_grad.cphf_conv_tol)[0] time1 = log.timer('Z-vector using UCPHF solver', *time0) z1ao = numpy.empty((2,nao,nao)) z1ao[0] = reduce(numpy.dot, (orbva, z1a, orboa.T)) z1ao[1] = reduce(numpy.dot, (orbvb, z1b, orbob.T)) vj, vk = mf.get_jk(mol, z1ao, hermi=0) veff = vj[0]+vj[1] - vk im0a = numpy.zeros((nmoa,nmoa)) im0b = numpy.zeros((nmob,nmob)) im0a[:nocca,:nocca] = reduce(numpy.dot, (orboa.T, veff0doo[0]+veff[0], orboa)) * .5 im0b[:noccb,:noccb] = reduce(numpy.dot, (orbob.T, veff0doo[1]+veff[1], orbob)) * .5 im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0mopa[nocca:,:nocca], xpya) * .5 im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0mopb[noccb:,:noccb], xpyb) * .5 im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0moma[nocca:,:nocca], xmya) * .5 im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0momb[noccb:,:noccb], xmyb) * .5 im0a[nocca:,nocca:] = numpy.einsum('ci,ai->ac', veff0mopa[nocca:,:nocca], xpya) * .5 im0b[noccb:,noccb:] = numpy.einsum('ci,ai->ac', veff0mopb[noccb:,:noccb], xpyb) * .5 im0a[nocca:,nocca:]+= numpy.einsum('ci,ai->ac', veff0moma[nocca:,:nocca], xmya) * .5 im0b[noccb:,noccb:]+= numpy.einsum('ci,ai->ac', veff0momb[noccb:,:noccb], xmyb) * .5 im0a[nocca:,:nocca] = numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) im0b[noccb:,:noccb] = numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) im0a[nocca:,:nocca]+= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya) im0b[noccb:,:noccb]+= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb) zeta_a = (mo_energy[0][:,None] + mo_energy[0]) * .5 zeta_b = (mo_energy[1][:,None] + mo_energy[1]) * .5 zeta_a[nocca:,:nocca] = mo_energy[0][:nocca] zeta_b[noccb:,:noccb] = mo_energy[1][:noccb] zeta_a[:nocca,nocca:] = mo_energy[0][nocca:] zeta_b[:noccb,noccb:] = mo_energy[1][noccb:] dm1a = numpy.zeros((nmoa,nmoa)) dm1b = numpy.zeros((nmob,nmob)) dm1a[:nocca,:nocca] = dooa * .5 dm1b[:noccb,:noccb] = doob * .5 dm1a[nocca:,nocca:] = dvva * .5 dm1b[noccb:,noccb:] = dvvb * .5 dm1a[nocca:,:nocca] = z1a * .5 dm1b[noccb:,:noccb] = z1b * .5 dm1a[:nocca,:nocca] += numpy.eye(nocca) # for ground state dm1b[:noccb,:noccb] += numpy.eye(noccb) im0a = reduce(numpy.dot, (mo_coeff[0], im0a+zeta_a*dm1a, mo_coeff[0].T)) im0b = reduce(numpy.dot, (mo_coeff[1], im0b+zeta_b*dm1b, mo_coeff[1].T)) im0 = im0a + im0b hcore_deriv = td_grad.hcore_generator(mol) s1 = td_grad.get_ovlp(mol) dmz1dooa = z1ao[0] + dmzooa dmz1doob = z1ao[1] + dmzoob oo0a = reduce(numpy.dot, (orboa, orboa.T)) oo0b = reduce(numpy.dot, (orbob, orbob.T)) as_dm1 = oo0a + oo0b + (dmz1dooa + dmz1doob) * .5 vj, vk = td_grad.get_jk(mol, (oo0a, dmz1dooa+dmz1dooa.T, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T, oo0b, dmz1doob+dmz1doob.T, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T)) vj = vj.reshape(2,4,3,nao,nao) vk = vk.reshape(2,4,3,nao,nao) vhf1a, vhf1b = vj[0] + vj[1] - vk time1 = log.timer('2e AO integral derivatives', *time1) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst),3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # Ground state gradients h1ao = hcore_deriv(ia) de[k] = numpy.einsum('xpq,pq->x', h1ao, as_dm1) de[k] += numpy.einsum('xpq,pq->x', vhf1a[0,:,p0:p1], oo0a[p0:p1]) de[k] += numpy.einsum('xpq,pq->x', vhf1b[0,:,p0:p1], oo0b[p0:p1]) de[k] += numpy.einsum('xpq,qp->x', vhf1a[0,:,p0:p1], oo0a[:,p0:p1]) de[k] += numpy.einsum('xpq,qp->x', vhf1b[0,:,p0:p1], oo0b[:,p0:p1]) de[k] += numpy.einsum('xpq,pq->x', vhf1a[0,:,p0:p1], dmz1dooa[p0:p1]) * .5 de[k] += numpy.einsum('xpq,pq->x', vhf1b[0,:,p0:p1], dmz1doob[p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', vhf1a[0,:,p0:p1], dmz1dooa[:,p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', vhf1b[0,:,p0:p1], dmz1doob[:,p0:p1]) * .5 de[k] -= numpy.einsum('xpq,pq->x', s1[:,p0:p1], im0[p0:p1]) de[k] -= numpy.einsum('xqp,pq->x', s1[:,p0:p1], im0[:,p0:p1]) de[k] += numpy.einsum('xij,ij->x', vhf1a[1,:,p0:p1], oo0a[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', vhf1b[1,:,p0:p1], oo0b[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', vhf1a[2,:,p0:p1], dmzvopa[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', vhf1b[2,:,p0:p1], dmzvopb[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', vhf1a[3,:,p0:p1], dmzvoma[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', vhf1b[3,:,p0:p1], dmzvomb[p0:p1,:]) de[k] += numpy.einsum('xji,ij->x', vhf1a[2,:,p0:p1], dmzvopa[:,p0:p1]) de[k] += numpy.einsum('xji,ij->x', vhf1b[2,:,p0:p1], dmzvopb[:,p0:p1]) de[k] -= numpy.einsum('xji,ij->x', vhf1a[3,:,p0:p1], dmzvoma[:,p0:p1]) de[k] -= numpy.einsum('xji,ij->x', vhf1b[3,:,p0:p1], dmzvomb[:,p0:p1]) log.timer('TDUHF nuclear gradients', *time0) return de
def kernel(td_grad, x_y, atmlst=None, max_memory=2000, verbose=logger.INFO): log = logger.new_logger(td_grad, verbose) time0 = time.clock(), time.time() mol = td_grad.mol mf = td_grad.base._scf mo_coeff = mf.mo_coeff 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] 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] nao = mo_coeff[0].shape[0] nmoa = nocca + nvira nmob = noccb + nvirb (xa, xb), (ya, yb) = x_y xpya = (xa+ya).reshape(nocca,nvira).T xpyb = (xb+yb).reshape(noccb,nvirb).T xmya = (xa-ya).reshape(nocca,nvira).T xmyb = (xb-yb).reshape(noccb,nvirb).T dvva = numpy.einsum('ai,bi->ab', xpya, xpya) + numpy.einsum('ai,bi->ab', xmya, xmya) dvvb = numpy.einsum('ai,bi->ab', xpyb, xpyb) + numpy.einsum('ai,bi->ab', xmyb, xmyb) dooa =-numpy.einsum('ai,aj->ij', xpya, xpya) - numpy.einsum('ai,aj->ij', xmya, xmya) doob =-numpy.einsum('ai,aj->ij', xpyb, xpyb) - numpy.einsum('ai,aj->ij', xmyb, xmyb) dmzvopa = reduce(numpy.dot, (orbva, xpya, orboa.T)) dmzvopb = reduce(numpy.dot, (orbvb, xpyb, orbob.T)) dmzvoma = reduce(numpy.dot, (orbva, xmya, orboa.T)) dmzvomb = reduce(numpy.dot, (orbvb, xmyb, orbob.T)) dmzooa = reduce(numpy.dot, (orboa, dooa, orboa.T)) dmzoob = reduce(numpy.dot, (orbob, doob, orbob.T)) dmzooa+= reduce(numpy.dot, (orbva, dvva, orbva.T)) dmzoob+= reduce(numpy.dot, (orbvb, dvvb, orbvb.T)) ni = mf._numint ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True) omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin) # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing # fxc since rho0 is passed to fxc function. dm0 = None rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol, mf.grids, mf.xc, mo_coeff, mo_occ, spin=1) f1vo, f1oo, vxc1, k1ao = \ _contract_xc_kernel(td_grad, mf.xc, (dmzvopa,dmzvopb), (dmzooa,dmzoob), True, True, max_memory) if abs(hyb) > 1e-10: dm = (dmzooa, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T, dmzoob, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T) vj, vk = mf.get_jk(mol, dm, hermi=0) vj = vj.reshape(2,3,nao,nao) vk = vk.reshape(2,3,nao,nao) * hyb if abs(omega) > 1e-10: vk += rks._get_k_lr(mol, dm, omega).reshape(2,3,nao,nao) * (alpha-hyb) veff0doo = vj[0,0]+vj[1,0] - vk[:,0] + f1oo[:,0] + k1ao[:,0] * 2 wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2 wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2 veff = vj[0,1]+vj[1,1] - vk[:,1] + f1vo[:,0] * 2 veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:,nocca:], xpya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:,noccb:], xpyb) * 2 veff = -vk[:,2] veff0moma = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0momb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0moma[nocca:,nocca:], xmya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0momb[noccb:,noccb:], xmyb) * 2 else: dm = (dmzooa, dmzvopa+dmzvopa.T, dmzoob, dmzvopb+dmzvopb.T) vj = mf.get_j(mol, dm, hermi=1).reshape(2,2,nao,nao) veff0doo = vj[0,0]+vj[1,0] + f1oo[:,0] + k1ao[:,0] * 2 wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2 wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2 veff = vj[0,1]+vj[1,1] + f1vo[:,0] * 2 veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:,nocca:], xpya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:,noccb:], xpyb) * 2 veff0moma = numpy.zeros((nmoa,nmoa)) veff0momb = numpy.zeros((nmob,nmob)) def fvind(x): dm1 = numpy.empty((2,nao,nao)) xa = x[0,:nvira*nocca].reshape(nvira,nocca) xb = x[0,nvira*nocca:].reshape(nvirb,noccb) dma = reduce(numpy.dot, (orbva, xa, orboa.T)) dmb = reduce(numpy.dot, (orbvb, xb, orbob.T)) dm1[0] = dma + dma.T dm1[1] = dmb + dmb.T relativity = 0 hermi = 1 vindxc = numint.nr_uks_fxc(ni, mol, mf.grids, mf.xc, dm0, dm1, relativity, hermi, rho0, vxc, fxc, max_memory) if abs(hyb) > 1e-10: vj, vk = mf.get_jk(mol, dm1) veff = vj[0] + vj[1] - hyb * vk + vindxc if abs(omega) > 1e-10: veff -= rks._get_k_lr(mol, dm1, omega, hermi=1) * (alpha-hyb) else: vj = mf.get_j(mol, dm1) veff = vj[0] + vj[1] + vindxc v1a = reduce(numpy.dot, (orbva.T, veff[0], orboa)) v1b = reduce(numpy.dot, (orbvb.T, veff[1], orbob)) return numpy.hstack((v1a.ravel(), v1b.ravel())) z1a, z1b = ucphf.solve(fvind, mo_energy, mo_occ, (wvoa,wvob), max_cycle=td_grad.cphf_max_cycle, tol=td_grad.cphf_conv_tol)[0] time1 = log.timer('Z-vector using UCPHF solver', *time0) z1ao = numpy.empty((2,nao,nao)) z1ao[0] = reduce(numpy.dot, (orbva, z1a, orboa.T)) z1ao[1] = reduce(numpy.dot, (orbvb, z1b, orbob.T)) fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None, False, False, max_memory)[0] if abs(hyb) > 1e-10: vj, vk = mf.get_jk(mol, z1ao, hermi=0) veff = vj[0]+vj[1] - hyb * vk + fxcz1[:,0] if abs(omega) > 1e-10: veff -= rks._get_k_lr(mol, z1ao, omega) * (alpha-hyb) else: vj = mf.get_j(mol, z1ao, hermi=1) veff = vj[0]+vj[1] + fxcz1[:,0] im0a = numpy.zeros((nmoa,nmoa)) im0b = numpy.zeros((nmob,nmob)) im0a[:nocca,:nocca] = reduce(numpy.dot, (orboa.T, veff0doo[0]+veff[0], orboa)) * .5 im0b[:noccb,:noccb] = reduce(numpy.dot, (orbob.T, veff0doo[1]+veff[1], orbob)) * .5 im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0mopa[nocca:,:nocca], xpya) * .5 im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0mopb[noccb:,:noccb], xpyb) * .5 im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0moma[nocca:,:nocca], xmya) * .5 im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0momb[noccb:,:noccb], xmyb) * .5 im0a[nocca:,nocca:] = numpy.einsum('ci,ai->ac', veff0mopa[nocca:,:nocca], xpya) * .5 im0b[noccb:,noccb:] = numpy.einsum('ci,ai->ac', veff0mopb[noccb:,:noccb], xpyb) * .5 im0a[nocca:,nocca:]+= numpy.einsum('ci,ai->ac', veff0moma[nocca:,:nocca], xmya) * .5 im0b[noccb:,noccb:]+= numpy.einsum('ci,ai->ac', veff0momb[noccb:,:noccb], xmyb) * .5 im0a[nocca:,:nocca] = numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) im0b[noccb:,:noccb] = numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) im0a[nocca:,:nocca]+= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya) im0b[noccb:,:noccb]+= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb) zeta_a = (mo_energy[0][:,None] + mo_energy[0]) * .5 zeta_b = (mo_energy[1][:,None] + mo_energy[1]) * .5 zeta_a[nocca:,:nocca] = mo_energy[0][:nocca] zeta_b[noccb:,:noccb] = mo_energy[1][:noccb] zeta_a[:nocca,nocca:] = mo_energy[0][nocca:] zeta_b[:noccb,noccb:] = mo_energy[1][noccb:] dm1a = numpy.zeros((nmoa,nmoa)) dm1b = numpy.zeros((nmob,nmob)) dm1a[:nocca,:nocca] = dooa * .5 dm1b[:noccb,:noccb] = doob * .5 dm1a[nocca:,nocca:] = dvva * .5 dm1b[noccb:,noccb:] = dvvb * .5 dm1a[nocca:,:nocca] = z1a * .5 dm1b[noccb:,:noccb] = z1b * .5 dm1a[:nocca,:nocca] += numpy.eye(nocca) # for ground state dm1b[:noccb,:noccb] += numpy.eye(noccb) im0a = reduce(numpy.dot, (mo_coeff[0], im0a+zeta_a*dm1a, mo_coeff[0].T)) im0b = reduce(numpy.dot, (mo_coeff[1], im0b+zeta_b*dm1b, mo_coeff[1].T)) im0 = im0a + im0b hcore_deriv = td_grad.hcore_generator(mol) s1 = td_grad.get_ovlp(mol) dmz1dooa = z1ao[0] + dmzooa dmz1doob = z1ao[1] + dmzoob oo0a = reduce(numpy.dot, (orboa, orboa.T)) oo0b = reduce(numpy.dot, (orbob, orbob.T)) as_dm1 = oo0a + oo0b + (dmz1dooa + dmz1doob) * .5 if abs(hyb) > 1e-10: dm = (oo0a, dmz1dooa+dmz1dooa.T, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T, oo0b, dmz1doob+dmz1doob.T, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T) vj, vk = td_grad.get_jk(mol, dm) vj = vj.reshape(2,4,3,nao,nao) vk = vk.reshape(2,4,3,nao,nao) * hyb if abs(omega) > 1e-10: with mol.with_range_coulomb(omega): vk += td_grad.get_k(mol, dm).reshape(2,4,3,nao,nao) * (alpha-hyb) veff1 = vj[0] + vj[1] - vk else: dm = (oo0a, dmz1dooa+dmz1dooa.T, dmzvopa+dmzvopa.T, oo0b, dmz1doob+dmz1doob.T, dmzvopb+dmzvopb.T) vj = td_grad.get_j(mol, dm).reshape(2,3,3,nao,nao) veff1 = numpy.zeros((2,4,3,nao,nao)) veff1[:,:3] = vj[0] + vj[1] veff1[:,0] += vxc1[:,1:] veff1[:,1] +=(f1oo[:,1:] + fxcz1[:,1:] + k1ao[:,1:]*2)*2 # *2 for dmz1doo+dmz1oo.T veff1[:,2] += f1vo[:,1:] * 2 veff1a, veff1b = veff1 time1 = log.timer('2e AO integral derivatives', *time1) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst),3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # Ground state gradients h1ao = hcore_deriv(ia) de[k] = numpy.einsum('xpq,pq->x', h1ao, as_dm1) de[k] += numpy.einsum('xpq,pq->x', veff1a[0,:,p0:p1], oo0a[p0:p1]) de[k] += numpy.einsum('xpq,pq->x', veff1b[0,:,p0:p1], oo0b[p0:p1]) de[k] += numpy.einsum('xpq,qp->x', veff1a[0,:,p0:p1], oo0a[:,p0:p1]) de[k] += numpy.einsum('xpq,qp->x', veff1b[0,:,p0:p1], oo0b[:,p0:p1]) de[k] += numpy.einsum('xpq,pq->x', veff1a[0,:,p0:p1], dmz1dooa[p0:p1]) * .5 de[k] += numpy.einsum('xpq,pq->x', veff1b[0,:,p0:p1], dmz1doob[p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', veff1a[0,:,p0:p1], dmz1dooa[:,p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', veff1b[0,:,p0:p1], dmz1doob[:,p0:p1]) * .5 de[k] -= numpy.einsum('xpq,pq->x', s1[:,p0:p1], im0[p0:p1]) de[k] -= numpy.einsum('xqp,pq->x', s1[:,p0:p1], im0[:,p0:p1]) de[k] += numpy.einsum('xij,ij->x', veff1a[1,:,p0:p1], oo0a[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', veff1b[1,:,p0:p1], oo0b[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', veff1a[2,:,p0:p1], dmzvopa[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', veff1b[2,:,p0:p1], dmzvopb[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', veff1a[3,:,p0:p1], dmzvoma[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', veff1b[3,:,p0:p1], dmzvomb[p0:p1,:]) de[k] += numpy.einsum('xji,ij->x', veff1a[2,:,p0:p1], dmzvopa[:,p0:p1]) de[k] += numpy.einsum('xji,ij->x', veff1b[2,:,p0:p1], dmzvopb[:,p0:p1]) de[k] -= numpy.einsum('xji,ij->x', veff1a[3,:,p0:p1], dmzvoma[:,p0:p1]) de[k] -= numpy.einsum('xji,ij->x', veff1b[3,:,p0:p1], dmzvomb[:,p0:p1]) log.timer('TDUHF nuclear gradients', *time0) return de
def grad_elec(td_grad, x_y, atmlst=None, max_memory=2000, verbose=logger.INFO): log = logger.new_logger(td_grad, verbose) time0 = time.clock(), time.time() mol = td_grad.mol mf = td_grad.base._scf mo_coeff = mf.mo_coeff 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] 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] nao = mo_coeff[0].shape[0] nmoa = nocca + nvira nmob = noccb + nvirb (xa, xb), (ya, yb) = x_y xpya = (xa + ya).reshape(nocca, nvira).T xpyb = (xb + yb).reshape(noccb, nvirb).T xmya = (xa - ya).reshape(nocca, nvira).T xmyb = (xb - yb).reshape(noccb, nvirb).T dvva = numpy.einsum('ai,bi->ab', xpya, xpya) + numpy.einsum( 'ai,bi->ab', xmya, xmya) dvvb = numpy.einsum('ai,bi->ab', xpyb, xpyb) + numpy.einsum( 'ai,bi->ab', xmyb, xmyb) dooa = -numpy.einsum('ai,aj->ij', xpya, xpya) - numpy.einsum( 'ai,aj->ij', xmya, xmya) doob = -numpy.einsum('ai,aj->ij', xpyb, xpyb) - numpy.einsum( 'ai,aj->ij', xmyb, xmyb) dmzvopa = reduce(numpy.dot, (orbva, xpya, orboa.T)) dmzvopb = reduce(numpy.dot, (orbvb, xpyb, orbob.T)) dmzvoma = reduce(numpy.dot, (orbva, xmya, orboa.T)) dmzvomb = reduce(numpy.dot, (orbvb, xmyb, orbob.T)) dmzooa = reduce(numpy.dot, (orboa, dooa, orboa.T)) dmzoob = reduce(numpy.dot, (orbob, doob, orbob.T)) dmzooa += reduce(numpy.dot, (orbva, dvva, orbva.T)) dmzoob += reduce(numpy.dot, (orbvb, dvvb, orbvb.T)) ni = mf._numint ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True) omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin) # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing # fxc since rho0 is passed to fxc function. dm0 = None rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol, mf.grids, mf.xc, mo_coeff, mo_occ, spin=1) f1vo, f1oo, vxc1, k1ao = \ _contract_xc_kernel(td_grad, mf.xc, (dmzvopa,dmzvopb), (dmzooa,dmzoob), True, True, max_memory) if abs(hyb) > 1e-10: dm = (dmzooa, dmzvopa + dmzvopa.T, dmzvoma - dmzvoma.T, dmzoob, dmzvopb + dmzvopb.T, dmzvomb - dmzvomb.T) vj, vk = mf.get_jk(mol, dm, hermi=0) vk *= hyb if abs(omega) > 1e-10: vk += mf.get_k(mol, dm, hermi=0, omega=omega) * (alpha - hyb) vj = vj.reshape(2, 3, nao, nao) vk = vk.reshape(2, 3, nao, nao) veff0doo = vj[0, 0] + vj[1, 0] - vk[:, 0] + f1oo[:, 0] + k1ao[:, 0] * 2 wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2 wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2 veff = vj[0, 1] + vj[1, 1] - vk[:, 1] + f1vo[:, 0] * 2 veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca], xpya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb], xpyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:, nocca:], xpya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:, noccb:], xpyb) * 2 veff = -vk[:, 2] veff0moma = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0momb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0moma[:nocca, :nocca], xmya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0momb[:noccb, :noccb], xmyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0moma[nocca:, nocca:], xmya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0momb[noccb:, noccb:], xmyb) * 2 else: dm = (dmzooa, dmzvopa + dmzvopa.T, dmzoob, dmzvopb + dmzvopb.T) vj = mf.get_j(mol, dm, hermi=1).reshape(2, 2, nao, nao) veff0doo = vj[0, 0] + vj[1, 0] + f1oo[:, 0] + k1ao[:, 0] * 2 wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2 wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2 veff = vj[0, 1] + vj[1, 1] + f1vo[:, 0] * 2 veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca], xpya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb], xpyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:, nocca:], xpya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:, noccb:], xpyb) * 2 veff0moma = numpy.zeros((nmoa, nmoa)) veff0momb = numpy.zeros((nmob, nmob)) def fvind(x): dm1 = numpy.empty((2, nao, nao)) xa = x[0, :nvira * nocca].reshape(nvira, nocca) xb = x[0, nvira * nocca:].reshape(nvirb, noccb) dma = reduce(numpy.dot, (orbva, xa, orboa.T)) dmb = reduce(numpy.dot, (orbvb, xb, orbob.T)) dm1[0] = dma + dma.T dm1[1] = dmb + dmb.T relativity = 0 hermi = 1 vindxc = numint.nr_uks_fxc(ni, mol, mf.grids, mf.xc, dm0, dm1, relativity, hermi, rho0, vxc, fxc, max_memory) if abs(hyb) > 1e-10: vj, vk = mf.get_jk(mol, dm1) veff = vj[0] + vj[1] - hyb * vk + vindxc if abs(omega) > 1e-10: veff -= mf.get_k(mol, dm1, hermi=1, omega=omega) * (alpha - hyb) else: vj = mf.get_j(mol, dm1) veff = vj[0] + vj[1] + vindxc v1a = reduce(numpy.dot, (orbva.T, veff[0], orboa)) v1b = reduce(numpy.dot, (orbvb.T, veff[1], orbob)) return numpy.hstack((v1a.ravel(), v1b.ravel())) z1a, z1b = ucphf.solve(fvind, mo_energy, mo_occ, (wvoa, wvob), max_cycle=td_grad.cphf_max_cycle, tol=td_grad.cphf_conv_tol)[0] time1 = log.timer('Z-vector using UCPHF solver', *time0) z1ao = numpy.empty((2, nao, nao)) z1ao[0] = reduce(numpy.dot, (orbva, z1a, orboa.T)) z1ao[1] = reduce(numpy.dot, (orbvb, z1b, orbob.T)) fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None, False, False, max_memory)[0] if abs(hyb) > 1e-10: vj, vk = mf.get_jk(mol, z1ao, hermi=0) veff = vj[0] + vj[1] - hyb * vk + fxcz1[:, 0] if abs(omega) > 1e-10: veff -= mf.get_k(mol, z1ao, hermi=0, omega=omega) * (alpha - hyb) else: vj = mf.get_j(mol, z1ao, hermi=1) veff = vj[0] + vj[1] + fxcz1[:, 0] im0a = numpy.zeros((nmoa, nmoa)) im0b = numpy.zeros((nmob, nmob)) im0a[:nocca, :nocca] = reduce(numpy.dot, (orboa.T, veff0doo[0] + veff[0], orboa)) * .5 im0b[:noccb, :noccb] = reduce(numpy.dot, (orbob.T, veff0doo[1] + veff[1], orbob)) * .5 im0a[:nocca, :nocca] += numpy.einsum('ak,ai->ki', veff0mopa[nocca:, :nocca], xpya) * .5 im0b[:noccb, :noccb] += numpy.einsum('ak,ai->ki', veff0mopb[noccb:, :noccb], xpyb) * .5 im0a[:nocca, :nocca] += numpy.einsum('ak,ai->ki', veff0moma[nocca:, :nocca], xmya) * .5 im0b[:noccb, :noccb] += numpy.einsum('ak,ai->ki', veff0momb[noccb:, :noccb], xmyb) * .5 im0a[nocca:, nocca:] = numpy.einsum('ci,ai->ac', veff0mopa[nocca:, :nocca], xpya) * .5 im0b[noccb:, noccb:] = numpy.einsum('ci,ai->ac', veff0mopb[noccb:, :noccb], xpyb) * .5 im0a[nocca:, nocca:] += numpy.einsum('ci,ai->ac', veff0moma[nocca:, :nocca], xmya) * .5 im0b[noccb:, noccb:] += numpy.einsum('ci,ai->ac', veff0momb[noccb:, :noccb], xmyb) * .5 im0a[nocca:, :nocca] = numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca], xpya) im0b[noccb:, :noccb] = numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb], xpyb) im0a[nocca:, :nocca] += numpy.einsum('ki,ai->ak', veff0moma[:nocca, :nocca], xmya) im0b[noccb:, :noccb] += numpy.einsum('ki,ai->ak', veff0momb[:noccb, :noccb], xmyb) zeta_a = (mo_energy[0][:, None] + mo_energy[0]) * .5 zeta_b = (mo_energy[1][:, None] + mo_energy[1]) * .5 zeta_a[nocca:, :nocca] = mo_energy[0][:nocca] zeta_b[noccb:, :noccb] = mo_energy[1][:noccb] zeta_a[:nocca, nocca:] = mo_energy[0][nocca:] zeta_b[:noccb, noccb:] = mo_energy[1][noccb:] dm1a = numpy.zeros((nmoa, nmoa)) dm1b = numpy.zeros((nmob, nmob)) dm1a[:nocca, :nocca] = dooa * .5 dm1b[:noccb, :noccb] = doob * .5 dm1a[nocca:, nocca:] = dvva * .5 dm1b[noccb:, noccb:] = dvvb * .5 dm1a[nocca:, :nocca] = z1a * .5 dm1b[noccb:, :noccb] = z1b * .5 dm1a[:nocca, :nocca] += numpy.eye(nocca) # for ground state dm1b[:noccb, :noccb] += numpy.eye(noccb) im0a = reduce(numpy.dot, (mo_coeff[0], im0a + zeta_a * dm1a, mo_coeff[0].T)) im0b = reduce(numpy.dot, (mo_coeff[1], im0b + zeta_b * dm1b, mo_coeff[1].T)) im0 = im0a + im0b # Initialize hcore_deriv with the underlying SCF object because some # extensions (e.g. QM/MM, solvent) modifies the SCF object only. mf_grad = td_grad.base._scf.nuc_grad_method() hcore_deriv = mf_grad.hcore_generator(mol) s1 = mf_grad.get_ovlp(mol) dmz1dooa = z1ao[0] + dmzooa dmz1doob = z1ao[1] + dmzoob oo0a = reduce(numpy.dot, (orboa, orboa.T)) oo0b = reduce(numpy.dot, (orbob, orbob.T)) as_dm1 = oo0a + oo0b + (dmz1dooa + dmz1doob) * .5 if abs(hyb) > 1e-10: dm = (oo0a, dmz1dooa + dmz1dooa.T, dmzvopa + dmzvopa.T, dmzvoma - dmzvoma.T, oo0b, dmz1doob + dmz1doob.T, dmzvopb + dmzvopb.T, dmzvomb - dmzvomb.T) vj, vk = td_grad.get_jk(mol, dm) vj = vj.reshape(2, 4, 3, nao, nao) vk = vk.reshape(2, 4, 3, nao, nao) * hyb if abs(omega) > 1e-10: with mol.with_range_coulomb(omega): vk += td_grad.get_k(mol, dm).reshape(2, 4, 3, nao, nao) * (alpha - hyb) veff1 = vj[0] + vj[1] - vk else: dm = (oo0a, dmz1dooa + dmz1dooa.T, dmzvopa + dmzvopa.T, oo0b, dmz1doob + dmz1doob.T, dmzvopb + dmzvopb.T) vj = td_grad.get_j(mol, dm).reshape(2, 3, 3, nao, nao) veff1 = numpy.zeros((2, 4, 3, nao, nao)) veff1[:, :3] = vj[0] + vj[1] veff1[:, 0] += vxc1[:, 1:] veff1[:, 1] += (f1oo[:, 1:] + fxcz1[:, 1:] + k1ao[:, 1:] * 2) * 2 # *2 for dmz1doo+dmz1oo.T veff1[:, 2] += f1vo[:, 1:] * 2 veff1a, veff1b = veff1 time1 = log.timer('2e AO integral derivatives', *time1) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst), 3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # Ground state gradients h1ao = hcore_deriv(ia) de[k] = numpy.einsum('xpq,pq->x', h1ao, as_dm1) de[k] += numpy.einsum('xpq,pq->x', veff1a[0, :, p0:p1], oo0a[p0:p1]) de[k] += numpy.einsum('xpq,pq->x', veff1b[0, :, p0:p1], oo0b[p0:p1]) de[k] += numpy.einsum('xpq,qp->x', veff1a[0, :, p0:p1], oo0a[:, p0:p1]) de[k] += numpy.einsum('xpq,qp->x', veff1b[0, :, p0:p1], oo0b[:, p0:p1]) de[k] += numpy.einsum('xpq,pq->x', veff1a[0, :, p0:p1], dmz1dooa[p0:p1]) * .5 de[k] += numpy.einsum('xpq,pq->x', veff1b[0, :, p0:p1], dmz1doob[p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', veff1a[0, :, p0:p1], dmz1dooa[:, p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', veff1b[0, :, p0:p1], dmz1doob[:, p0:p1]) * .5 de[k] -= numpy.einsum('xpq,pq->x', s1[:, p0:p1], im0[p0:p1]) de[k] -= numpy.einsum('xqp,pq->x', s1[:, p0:p1], im0[:, p0:p1]) de[k] += numpy.einsum('xij,ij->x', veff1a[1, :, p0:p1], oo0a[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', veff1b[1, :, p0:p1], oo0b[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', veff1a[2, :, p0:p1], dmzvopa[p0:p1, :]) de[k] += numpy.einsum('xij,ij->x', veff1b[2, :, p0:p1], dmzvopb[p0:p1, :]) de[k] += numpy.einsum('xij,ij->x', veff1a[3, :, p0:p1], dmzvoma[p0:p1, :]) de[k] += numpy.einsum('xij,ij->x', veff1b[3, :, p0:p1], dmzvomb[p0:p1, :]) de[k] += numpy.einsum('xji,ij->x', veff1a[2, :, p0:p1], dmzvopa[:, p0:p1]) de[k] += numpy.einsum('xji,ij->x', veff1b[2, :, p0:p1], dmzvopb[:, p0:p1]) de[k] -= numpy.einsum('xji,ij->x', veff1a[3, :, p0:p1], dmzvoma[:, p0:p1]) de[k] -= numpy.einsum('xji,ij->x', veff1b[3, :, p0:p1], dmzvomb[:, p0:p1]) log.timer('TDUHF nuclear gradients', *time0) return de
def U_1(self): B_1 = self.B_1 S_1_mo = self.S_1_mo if not isinstance(S_1_mo, np.ndarray): S_1_mo = np.zeros_like(B_1) Ax0_Core = self.Ax0_Core sv, so = self.sv, self.so nocc, nvir, nmo = self.nocc, self.nvir, self.nmo e, eo, ev, mo_occ = self.e, self.eo, self.ev, self.mo_occ prop_dim = B_1.shape[1] # Calculate U_1_vo def fx(X): prop_dim = X.shape[0] X_alpha = X[:, :nocc[0] * nvir[0]].reshape( (prop_dim, nvir[0], nocc[0])) X_beta = X[:, nocc[0] * nvir[0]:].reshape( (prop_dim, nvir[1], nocc[1])) Ax = Ax0_Core(sv, so, sv, so, in_cphf=True)((X_alpha, X_beta)) result = np.concatenate( [Ax[0].reshape(prop_dim, -1), Ax[1].reshape(prop_dim, -1)], axis=1) return result U_1_vo = ucphf.solve( fx, e, mo_occ, (B_1[0, :, sv[0], so[0]], B_1[1, :, sv[1], so[1]]), max_cycle=100, tol=self.cphf_tol)[0] # Additional Iteration by newton_krylov def get_conv(U_1_vo): Ax_U = Ax0_Core(sv, so, sv, so, in_cphf=True)(U_1_vo) return ( (ev[0][:, None] - eo[0][None, :]) * U_1_vo[0] + Ax_U[0] + B_1[0][:, sv[0], so[0]], (ev[1][:, None] - eo[1][None, :]) * U_1_vo[1] + Ax_U[1] + B_1[1][:, sv[1], so[1]], ) # def vind(guess): # U_1_vo_inner = ( # guess[:3 * nocc[0] * nvir[0]].reshape(3, nvir[0], nocc[0]), # guess[3 * nocc[0] * nvir[0]:].reshape(3, nvir[1], nocc[1])) # conv = get_conv(U_1_vo_inner) # return np.concatenate([conv[0].ravel(), conv[1].ravel()]) # # guess = ( # B_1[0, :, sv[0], so[0]] / (ev[0][:, None] - eo[0][None, :]), # B_1[1, :, sv[1], so[1]] / (ev[1][:, None] - eo[1][None, :])) # guess = np.concatenate([guess[0].ravel(), guess[1].ravel()]) # res = newton_krylov(vind, guess, f_tol=1e-10) # U_1_vo = ( # res[:3 * nocc[0] * nvir[0]].reshape(3, nvir[0], nocc[0]), # res[3 * nocc[0] * nvir[0]:].reshape(3, nvir[1], nocc[1])) # Check sanity conv = get_conv(U_1_vo) if np.abs(conv[0]).max() > 1e-8 or np.abs(conv[1]).max() > 1e-8: msg = "\nget_U_1: CP-HF not converged well!\nMaximum deviation: " + str( np.abs(conv[0]).max()) + ", " + str(np.abs(conv[1]).max()) warnings.warn(msg) # Build rest of U_1 U_1 = np.zeros((2, prop_dim, nmo, nmo)) if self.rotation: U_1 = -0.5 * S_1_mo U_1[0, :, sv[0], so[0]] = U_1_vo[0] U_1[1, :, sv[1], so[1]] = U_1_vo[1] U_1[0, :, so[0], sv[0]] = -S_1_mo[0, :, so[0], sv[0]] - U_1_vo[0].swapaxes( -1, -2) U_1[1, :, so[1], sv[1]] = -S_1_mo[1, :, so[1], sv[1]] - U_1_vo[1].swapaxes( -1, -2) else: U_1[0, :, sv[0], so[0]] = U_1_vo[0] U_1[1, :, sv[1], so[1]] = U_1_vo[1] U_1[0, :, so[0], sv[0]] = -S_1_mo[0, :, so[0], sv[0]] - U_1_vo[0].swapaxes( -1, -2) U_1[1, :, so[1], sv[1]] = -S_1_mo[1, :, so[1], sv[1]] - U_1_vo[1].swapaxes( -1, -2) Ax_oo = Ax0_Core(so, so, sv, so)(U_1_vo) Ax_vv = Ax0_Core(sv, sv, sv, so)(U_1_vo) U_1[0, :, so[0], so[0]] = -(Ax_oo[0] + B_1[0, :, so[0], so[0]]) / ( eo[0][:, None] - eo[0][None, :]) U_1[1, :, so[1], so[1]] = -(Ax_oo[1] + B_1[1, :, so[1], so[1]]) / ( eo[1][:, None] - eo[1][None, :]) U_1[0, :, sv[0], sv[0]] = -(Ax_vv[0] + B_1[0, :, sv[0], sv[0]]) / ( ev[0][:, None] - ev[0][None, :]) U_1[1, :, sv[1], sv[1]] = -(Ax_vv[1] + B_1[1, :, sv[1], sv[1]]) / ( ev[1][:, None] - ev[1][None, :]) for p in range(nmo): U_1[:, :, p, p] = -S_1_mo[:, :, p, p] / 2 U_1 -= (U_1 + U_1.swapaxes(-1, -2) + S_1_mo) / 2 U_1 -= (U_1 + U_1.swapaxes(-1, -2) + S_1_mo) / 2 return U_1
def solve_mo1(mf, mo_energy, mo_coeff, mo_occ, h1ao_or_chkfile, fx=None, atmlst=None, max_memory=4000, verbose=None): mol = mf.mol if atmlst is None: atmlst = range(mol.natm) nao, nmo = mo_coeff[0].shape mocca = mo_coeff[0][:, mo_occ[0] > 0] moccb = mo_coeff[1][:, mo_occ[1] > 0] nocca = mocca.shape[1] noccb = moccb.shape[1] if fx is None: fx = gen_vind(mf, mo_coeff, mo_occ) s1a = -mol.intor('int1e_ipovlp', comp=3) def _ao2mo(mat, mo_coeff, mocc): return numpy.asarray( [reduce(numpy.dot, (mo_coeff.T, x, mocc)) for x in mat]) mem_now = lib.current_memory()[0] max_memory = max(2000, max_memory * .9 - mem_now) blksize = max(2, int(max_memory * 1e6 / 8 / (nao * (nocca + noccb) * 3 * 6))) mo1sa = [None] * mol.natm mo1sb = [None] * mol.natm e1sa = [None] * mol.natm e1sb = [None] * mol.natm aoslices = mol.aoslice_by_atom() for ia0, ia1 in lib.prange(0, len(atmlst), blksize): s1voa = [] s1vob = [] h1voa = [] h1vob = [] for i0 in range(ia0, ia1): ia = atmlst[i0] shl0, shl1, p0, p1 = aoslices[ia] s1ao = numpy.zeros((3, nao, nao)) s1ao[:, p0:p1] += s1a[:, p0:p1] s1ao[:, :, p0:p1] += s1a[:, p0:p1].transpose(0, 2, 1) s1voa.append(_ao2mo(s1ao, mo_coeff[0], mocca)) s1vob.append(_ao2mo(s1ao, mo_coeff[1], moccb)) if isinstance(h1ao_or_chkfile, str): h1aoa = lib.chkfile.load(h1ao_or_chkfile, 'scf_f1ao/0/%d' % ia) h1aob = lib.chkfile.load(h1ao_or_chkfile, 'scf_f1ao/1/%d' % ia) else: h1aoa = h1ao_or_chkfile[0][ia] h1aob = h1ao_or_chkfile[1][ia] h1voa.append(_ao2mo(h1aoa, mo_coeff[0], mocca)) h1vob.append(_ao2mo(h1aob, mo_coeff[1], moccb)) h1vo = (numpy.vstack(h1voa), numpy.vstack(h1vob)) s1vo = (numpy.vstack(s1voa), numpy.vstack(s1vob)) mo1, e1 = ucphf.solve(fx, mo_energy, mo_occ, h1vo, s1vo) mo1a = numpy.einsum('pq,xqi->xpi', mo_coeff[0], mo1[0]).reshape(-1, 3, nao, nocca) mo1b = numpy.einsum('pq,xqi->xpi', mo_coeff[1], mo1[1]).reshape(-1, 3, nao, noccb) e1a = e1[0].reshape(-1, 3, nocca, nocca) e1b = e1[1].reshape(-1, 3, noccb, noccb) for k in range(ia1 - ia0): ia = atmlst[k + ia0] if isinstance(h1ao_or_chkfile, str): lib.chkfile.save(h1ao_or_chkfile, 'scf_mo1/0/%d' % ia, mo1a[k]) lib.chkfile.save(h1ao_or_chkfile, 'scf_mo1/1/%d' % ia, mo1b[k]) else: mo1sa[ia] = mo1a[k] mo1sb[ia] = mo1b[k] e1sa[ia] = e1a[k].reshape(3, nocca, nocca) e1sb[ia] = e1b[k].reshape(3, noccb, noccb) mo1 = e1 = mo1a = mo1b = e1a = e1b = None if isinstance(h1ao_or_chkfile, str): return h1ao_or_chkfile, (e1sa, e1sb) else: return (mo1sa, mo1sb), (e1sa, e1sb)
def grad_elec(td_grad, x_y, atmlst=None, max_memory=2000, verbose=logger.INFO): ''' Electronic part of TDA, TDHF nuclear gradients Args: td_grad : grad.tduhf.Gradients or grad.tduks.Gradients object. x_y : a two-element list of numpy arrays TDDFT X and Y amplitudes. If Y is set to 0, this function computes TDA energy gradients. ''' log = logger.new_logger(td_grad, verbose) time0 = time.clock(), time.time() mol = td_grad.mol mf = td_grad.base._scf mo_coeff = mf.mo_coeff 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] 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] nao = mo_coeff[0].shape[0] nmoa = nocca + nvira nmob = noccb + nvirb (xa, xb), (ya, yb) = x_y xpya = (xa + ya).reshape(nocca, nvira).T xpyb = (xb + yb).reshape(noccb, nvirb).T xmya = (xa - ya).reshape(nocca, nvira).T xmyb = (xb - yb).reshape(noccb, nvirb).T dvva = numpy.einsum('ai,bi->ab', xpya, xpya) + numpy.einsum( 'ai,bi->ab', xmya, xmya) dvvb = numpy.einsum('ai,bi->ab', xpyb, xpyb) + numpy.einsum( 'ai,bi->ab', xmyb, xmyb) dooa = -numpy.einsum('ai,aj->ij', xpya, xpya) - numpy.einsum( 'ai,aj->ij', xmya, xmya) doob = -numpy.einsum('ai,aj->ij', xpyb, xpyb) - numpy.einsum( 'ai,aj->ij', xmyb, xmyb) dmxpya = reduce(numpy.dot, (orbva, xpya, orboa.T)) dmxpyb = reduce(numpy.dot, (orbvb, xpyb, orbob.T)) dmxmya = reduce(numpy.dot, (orbva, xmya, orboa.T)) dmxmyb = reduce(numpy.dot, (orbvb, xmyb, orbob.T)) dmzooa = reduce(numpy.dot, (orboa, dooa, orboa.T)) dmzoob = reduce(numpy.dot, (orbob, doob, orbob.T)) dmzooa += reduce(numpy.dot, (orbva, dvva, orbva.T)) dmzoob += reduce(numpy.dot, (orbvb, dvvb, orbvb.T)) vj, vk = mf.get_jk(mol, (dmzooa, dmxpya + dmxpya.T, dmxmya - dmxmya.T, dmzoob, dmxpyb + dmxpyb.T, dmxmyb - dmxmyb.T), hermi=0) vj = vj.reshape(2, 3, nao, nao) vk = vk.reshape(2, 3, nao, nao) veff0doo = vj[0, 0] + vj[1, 0] - vk[:, 0] wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2 wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2 veff = vj[0, 1] + vj[1, 1] - vk[:, 1] veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca], xpya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb], xpyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:, nocca:], xpya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:, noccb:], xpyb) * 2 veff = -vk[:, 2] veff0moma = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0momb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0moma[:nocca, :nocca], xmya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0momb[:noccb, :noccb], xmyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0moma[nocca:, nocca:], xmya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0momb[noccb:, noccb:], xmyb) * 2 vresp = mf.gen_response(hermi=1) def fvind(x): dm1 = numpy.empty((2, nao, nao)) xa = x[0, :nvira * nocca].reshape(nvira, nocca) xb = x[0, nvira * nocca:].reshape(nvirb, noccb) dma = reduce(numpy.dot, (orbva, xa, orboa.T)) dmb = reduce(numpy.dot, (orbvb, xb, orbob.T)) dm1[0] = dma + dma.T dm1[1] = dmb + dmb.T v1 = vresp(dm1) v1a = reduce(numpy.dot, (orbva.T, v1[0], orboa)) v1b = reduce(numpy.dot, (orbvb.T, v1[1], orbob)) return numpy.hstack((v1a.ravel(), v1b.ravel())) z1a, z1b = ucphf.solve(fvind, mo_energy, mo_occ, (wvoa, wvob), max_cycle=td_grad.cphf_max_cycle, tol=td_grad.cphf_conv_tol)[0] time1 = log.timer('Z-vector using UCPHF solver', *time0) z1ao = numpy.empty((2, nao, nao)) z1ao[0] = reduce(numpy.dot, (orbva, z1a, orboa.T)) z1ao[1] = reduce(numpy.dot, (orbvb, z1b, orbob.T)) veff = vresp((z1ao + z1ao.transpose(0, 2, 1)) * .5) im0a = numpy.zeros((nmoa, nmoa)) im0b = numpy.zeros((nmob, nmob)) im0a[:nocca, :nocca] = reduce(numpy.dot, (orboa.T, veff0doo[0] + veff[0], orboa)) * .5 im0b[:noccb, :noccb] = reduce(numpy.dot, (orbob.T, veff0doo[1] + veff[1], orbob)) * .5 im0a[:nocca, :nocca] += numpy.einsum('ak,ai->ki', veff0mopa[nocca:, :nocca], xpya) * .5 im0b[:noccb, :noccb] += numpy.einsum('ak,ai->ki', veff0mopb[noccb:, :noccb], xpyb) * .5 im0a[:nocca, :nocca] += numpy.einsum('ak,ai->ki', veff0moma[nocca:, :nocca], xmya) * .5 im0b[:noccb, :noccb] += numpy.einsum('ak,ai->ki', veff0momb[noccb:, :noccb], xmyb) * .5 im0a[nocca:, nocca:] = numpy.einsum('ci,ai->ac', veff0mopa[nocca:, :nocca], xpya) * .5 im0b[noccb:, noccb:] = numpy.einsum('ci,ai->ac', veff0mopb[noccb:, :noccb], xpyb) * .5 im0a[nocca:, nocca:] += numpy.einsum('ci,ai->ac', veff0moma[nocca:, :nocca], xmya) * .5 im0b[noccb:, noccb:] += numpy.einsum('ci,ai->ac', veff0momb[noccb:, :noccb], xmyb) * .5 im0a[nocca:, :nocca] = numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca], xpya) im0b[noccb:, :noccb] = numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb], xpyb) im0a[nocca:, :nocca] += numpy.einsum('ki,ai->ak', veff0moma[:nocca, :nocca], xmya) im0b[noccb:, :noccb] += numpy.einsum('ki,ai->ak', veff0momb[:noccb, :noccb], xmyb) zeta_a = (mo_energy[0][:, None] + mo_energy[0]) * .5 zeta_b = (mo_energy[1][:, None] + mo_energy[1]) * .5 zeta_a[nocca:, :nocca] = mo_energy[0][:nocca] zeta_b[noccb:, :noccb] = mo_energy[1][:noccb] zeta_a[:nocca, nocca:] = mo_energy[0][nocca:] zeta_b[:noccb, noccb:] = mo_energy[1][noccb:] dm1a = numpy.zeros((nmoa, nmoa)) dm1b = numpy.zeros((nmob, nmob)) dm1a[:nocca, :nocca] = dooa * .5 dm1b[:noccb, :noccb] = doob * .5 dm1a[nocca:, nocca:] = dvva * .5 dm1b[noccb:, noccb:] = dvvb * .5 dm1a[nocca:, :nocca] = z1a * .5 dm1b[noccb:, :noccb] = z1b * .5 dm1a[:nocca, :nocca] += numpy.eye(nocca) # for ground state dm1b[:noccb, :noccb] += numpy.eye(noccb) im0a = reduce(numpy.dot, (mo_coeff[0], im0a + zeta_a * dm1a, mo_coeff[0].T)) im0b = reduce(numpy.dot, (mo_coeff[1], im0b + zeta_b * dm1b, mo_coeff[1].T)) im0 = im0a + im0b # Initialize hcore_deriv with the underlying SCF object because some # extensions (e.g. QM/MM, solvent) modifies the SCF object only. mf_grad = td_grad.base._scf.nuc_grad_method() hcore_deriv = mf_grad.hcore_generator(mol) s1 = mf_grad.get_ovlp(mol) dmz1dooa = z1ao[0] + dmzooa dmz1doob = z1ao[1] + dmzoob oo0a = reduce(numpy.dot, (orboa, orboa.T)) oo0b = reduce(numpy.dot, (orbob, orbob.T)) as_dm1 = oo0a + oo0b + (dmz1dooa + dmz1doob) * .5 vj, vk = td_grad.get_jk( mol, (oo0a, dmz1dooa + dmz1dooa.T, dmxpya + dmxpya.T, dmxmya - dmxmya.T, oo0b, dmz1doob + dmz1doob.T, dmxpyb + dmxpyb.T, dmxmyb - dmxmyb.T)) vj = vj.reshape(2, 4, 3, nao, nao) vk = vk.reshape(2, 4, 3, nao, nao) vhf1a, vhf1b = vj[0] + vj[1] - vk time1 = log.timer('2e AO integral derivatives', *time1) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst), 3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # Ground state gradients h1ao = hcore_deriv(ia) de[k] = numpy.einsum('xpq,pq->x', h1ao, as_dm1) de[k] += numpy.einsum('xpq,pq->x', vhf1a[0, :, p0:p1], oo0a[p0:p1]) de[k] += numpy.einsum('xpq,pq->x', vhf1b[0, :, p0:p1], oo0b[p0:p1]) de[k] += numpy.einsum('xpq,qp->x', vhf1a[0, :, p0:p1], oo0a[:, p0:p1]) de[k] += numpy.einsum('xpq,qp->x', vhf1b[0, :, p0:p1], oo0b[:, p0:p1]) de[k] += numpy.einsum('xpq,pq->x', vhf1a[0, :, p0:p1], dmz1dooa[p0:p1]) * .5 de[k] += numpy.einsum('xpq,pq->x', vhf1b[0, :, p0:p1], dmz1doob[p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', vhf1a[0, :, p0:p1], dmz1dooa[:, p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', vhf1b[0, :, p0:p1], dmz1doob[:, p0:p1]) * .5 de[k] -= numpy.einsum('xpq,pq->x', s1[:, p0:p1], im0[p0:p1]) de[k] -= numpy.einsum('xqp,pq->x', s1[:, p0:p1], im0[:, p0:p1]) de[k] += numpy.einsum('xij,ij->x', vhf1a[1, :, p0:p1], oo0a[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', vhf1b[1, :, p0:p1], oo0b[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', vhf1a[2, :, p0:p1], dmxpya[p0:p1, :]) de[k] += numpy.einsum('xij,ij->x', vhf1b[2, :, p0:p1], dmxpyb[p0:p1, :]) de[k] += numpy.einsum('xij,ij->x', vhf1a[3, :, p0:p1], dmxmya[p0:p1, :]) de[k] += numpy.einsum('xij,ij->x', vhf1b[3, :, p0:p1], dmxmyb[p0:p1, :]) de[k] += numpy.einsum('xji,ij->x', vhf1a[2, :, p0:p1], dmxpya[:, p0:p1]) de[k] += numpy.einsum('xji,ij->x', vhf1b[2, :, p0:p1], dmxpyb[:, p0:p1]) de[k] -= numpy.einsum('xji,ij->x', vhf1a[3, :, p0:p1], dmxmya[:, p0:p1]) de[k] -= numpy.einsum('xji,ij->x', vhf1b[3, :, p0:p1], dmxmyb[:, p0:p1]) log.timer('TDUHF nuclear gradients', *time0) return de
def solve_mo1(mf, mo_energy, mo_coeff, mo_occ, h1ao_or_chkfile, fx=None, atmlst=None, max_memory=4000, verbose=None): mol = mf.mol if atmlst is None: atmlst = range(mol.natm) nao, nmo = mo_coeff[0].shape mocca = mo_coeff[0][:,mo_occ[0]>0] moccb = mo_coeff[1][:,mo_occ[1]>0] nocca = mocca.shape[1] noccb = moccb.shape[1] if fx is None: fx = gen_vind(mf, mo_coeff, mo_occ) s1a = -mol.intor('int1e_ipovlp', comp=3) def _ao2mo(mat, mo_coeff, mocc): return numpy.asarray([reduce(numpy.dot, (mo_coeff.T, x, mocc)) for x in mat]) mem_now = lib.current_memory()[0] max_memory = max(2000, max_memory*.9-mem_now) blksize = max(2, int(max_memory*1e6/8 / (nao*(nocca+noccb)*3*6))) mo1sa = [None] * mol.natm mo1sb = [None] * mol.natm e1sa = [None] * mol.natm e1sb = [None] * mol.natm aoslices = mol.aoslice_by_atom() for ia0, ia1 in lib.prange(0, len(atmlst), blksize): s1voa = [] s1vob = [] h1voa = [] h1vob = [] for i0 in range(ia0, ia1): ia = atmlst[i0] shl0, shl1, p0, p1 = aoslices[ia] s1ao = numpy.zeros((3,nao,nao)) s1ao[:,p0:p1] += s1a[:,p0:p1] s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1) s1voa.append(_ao2mo(s1ao, mo_coeff[0], mocca)) s1vob.append(_ao2mo(s1ao, mo_coeff[1], moccb)) if isinstance(h1ao_or_chkfile, str): h1aoa = lib.chkfile.load(h1ao_or_chkfile, 'scf_f1ao/0/%d'%ia) h1aob = lib.chkfile.load(h1ao_or_chkfile, 'scf_f1ao/1/%d'%ia) else: h1aoa = h1ao_or_chkfile[0][ia] h1aob = h1ao_or_chkfile[1][ia] h1voa.append(_ao2mo(h1aoa, mo_coeff[0], mocca)) h1vob.append(_ao2mo(h1aob, mo_coeff[1], moccb)) h1vo = (numpy.vstack(h1voa), numpy.vstack(h1vob)) s1vo = (numpy.vstack(s1voa), numpy.vstack(s1vob)) mo1, e1 = ucphf.solve(fx, mo_energy, mo_occ, h1vo, s1vo) mo1a = numpy.einsum('pq,xqi->xpi', mo_coeff[0], mo1[0]).reshape(-1,3,nao,nocca) mo1b = numpy.einsum('pq,xqi->xpi', mo_coeff[1], mo1[1]).reshape(-1,3,nao,noccb) e1a = e1[0].reshape(-1,3,nocca,nocca) e1b = e1[1].reshape(-1,3,noccb,noccb) for k in range(ia1-ia0): ia = atmlst[k+ia0] if isinstance(h1ao_or_chkfile, str): lib.chkfile.save(h1ao_or_chkfile, 'scf_mo1/0/%d'%ia, mo1a[k]) lib.chkfile.save(h1ao_or_chkfile, 'scf_mo1/1/%d'%ia, mo1b[k]) else: mo1sa[ia] = mo1a[k] mo1sb[ia] = mo1b[k] e1sa[ia] = e1a[k].reshape(3,nocca,nocca) e1sb[ia] = e1b[k].reshape(3,noccb,noccb) mo1 = e1 = mo1a = mo1b = e1a = e1b = None if isinstance(h1ao_or_chkfile, str): return h1ao_or_chkfile, (e1sa,e1sb) else: return (mo1sa,mo1sb), (e1sa,e1sb)
def kernel(td_grad, x_y, atmlst=None, max_memory=2000, verbose=logger.INFO): log = logger.new_logger(td_grad, verbose) time0 = time.clock(), time.time() mol = td_grad.mol mf = td_grad.base._scf mo_coeff = mf.mo_coeff 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] 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] nao = mo_coeff[0].shape[0] nmoa = nocca + nvira nmob = noccb + nvirb (xa, xb), (ya, yb) = x_y xpya = (xa+ya).reshape(nocca,nvira).T xpyb = (xb+yb).reshape(noccb,nvirb).T xmya = (xa-ya).reshape(nocca,nvira).T xmyb = (xb-yb).reshape(noccb,nvirb).T dvva = numpy.einsum('ai,bi->ab', xpya, xpya) + numpy.einsum('ai,bi->ab', xmya, xmya) dvvb = numpy.einsum('ai,bi->ab', xpyb, xpyb) + numpy.einsum('ai,bi->ab', xmyb, xmyb) dooa =-numpy.einsum('ai,aj->ij', xpya, xpya) - numpy.einsum('ai,aj->ij', xmya, xmya) doob =-numpy.einsum('ai,aj->ij', xpyb, xpyb) - numpy.einsum('ai,aj->ij', xmyb, xmyb) dmzvopa = reduce(numpy.dot, (orbva, xpya, orboa.T)) dmzvopb = reduce(numpy.dot, (orbvb, xpyb, orbob.T)) dmzvoma = reduce(numpy.dot, (orbva, xmya, orboa.T)) dmzvomb = reduce(numpy.dot, (orbvb, xmyb, orbob.T)) dmzooa = reduce(numpy.dot, (orboa, dooa, orboa.T)) dmzoob = reduce(numpy.dot, (orbob, doob, orbob.T)) dmzooa+= reduce(numpy.dot, (orbva, dvva, orbva.T)) dmzoob+= reduce(numpy.dot, (orbvb, dvvb, orbvb.T)) vj, vk = mf.get_jk(mol, (dmzooa, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T, dmzoob, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T), hermi=0) vj = vj.reshape(2,3,nao,nao) vk = vk.reshape(2,3,nao,nao) veff0doo = vj[0,0]+vj[1,0] - vk[:,0] wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2 wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2 veff = vj[0,1]+vj[1,1] - vk[:,1] veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:,nocca:], xpya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:,noccb:], xpyb) * 2 veff = -vk[:,2] veff0moma = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0])) veff0momb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1])) wvoa -= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya) * 2 wvob -= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb) * 2 wvoa += numpy.einsum('ac,ai->ci', veff0moma[nocca:,nocca:], xmya) * 2 wvob += numpy.einsum('ac,ai->ci', veff0momb[noccb:,noccb:], xmyb) * 2 def fvind(x): dm1 = numpy.empty((2,nao,nao)) xa = x[0,:nvira*nocca].reshape(nvira,nocca) xb = x[0,nvira*nocca:].reshape(nvirb,noccb) dma = reduce(numpy.dot, (orbva, xa, orboa.T)) dmb = reduce(numpy.dot, (orbvb, xb, orbob.T)) dm1[0] = dma + dma.T dm1[1] = dmb + dmb.T vj, vk = mf.get_jk(mol, dm1) v1 = vj[0] + vj[1] - vk v1a = reduce(numpy.dot, (orbva.T, v1[0], orboa)) v1b = reduce(numpy.dot, (orbvb.T, v1[1], orbob)) return numpy.hstack((v1a.ravel(), v1b.ravel())) z1a, z1b = ucphf.solve(fvind, mo_energy, mo_occ, (wvoa,wvob), max_cycle=td_grad.cphf_max_cycle, tol=td_grad.cphf_conv_tol)[0] time1 = log.timer('Z-vector using UCPHF solver', *time0) z1ao = numpy.empty((2,nao,nao)) z1ao[0] = reduce(numpy.dot, (orbva, z1a, orboa.T)) z1ao[1] = reduce(numpy.dot, (orbvb, z1b, orbob.T)) vj, vk = mf.get_jk(mol, z1ao, hermi=0) veff = vj[0]+vj[1] - vk im0a = numpy.zeros((nmoa,nmoa)) im0b = numpy.zeros((nmob,nmob)) im0a[:nocca,:nocca] = reduce(numpy.dot, (orboa.T, veff0doo[0]+veff[0], orboa)) * .5 im0b[:noccb,:noccb] = reduce(numpy.dot, (orbob.T, veff0doo[1]+veff[1], orbob)) * .5 im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0mopa[nocca:,:nocca], xpya) * .5 im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0mopb[noccb:,:noccb], xpyb) * .5 im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0moma[nocca:,:nocca], xmya) * .5 im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0momb[noccb:,:noccb], xmyb) * .5 im0a[nocca:,nocca:] = numpy.einsum('ci,ai->ac', veff0mopa[nocca:,:nocca], xpya) * .5 im0b[noccb:,noccb:] = numpy.einsum('ci,ai->ac', veff0mopb[noccb:,:noccb], xpyb) * .5 im0a[nocca:,nocca:]+= numpy.einsum('ci,ai->ac', veff0moma[nocca:,:nocca], xmya) * .5 im0b[noccb:,noccb:]+= numpy.einsum('ci,ai->ac', veff0momb[noccb:,:noccb], xmyb) * .5 im0a[nocca:,:nocca] = numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) im0b[noccb:,:noccb] = numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) im0a[nocca:,:nocca]+= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya) im0b[noccb:,:noccb]+= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb) zeta_a = (mo_energy[0][:,None] + mo_energy[0]) * .5 zeta_b = (mo_energy[1][:,None] + mo_energy[1]) * .5 zeta_a[nocca:,:nocca] = mo_energy[0][:nocca] zeta_b[noccb:,:noccb] = mo_energy[1][:noccb] zeta_a[:nocca,nocca:] = mo_energy[0][nocca:] zeta_b[:noccb,noccb:] = mo_energy[1][noccb:] dm1a = numpy.zeros((nmoa,nmoa)) dm1b = numpy.zeros((nmob,nmob)) dm1a[:nocca,:nocca] = dooa * .5 dm1b[:noccb,:noccb] = doob * .5 dm1a[nocca:,nocca:] = dvva * .5 dm1b[noccb:,noccb:] = dvvb * .5 dm1a[nocca:,:nocca] = z1a * .5 dm1b[noccb:,:noccb] = z1b * .5 dm1a[:nocca,:nocca] += numpy.eye(nocca) # for ground state dm1b[:noccb,:noccb] += numpy.eye(noccb) im0a = reduce(numpy.dot, (mo_coeff[0], im0a+zeta_a*dm1a, mo_coeff[0].T)) im0b = reduce(numpy.dot, (mo_coeff[1], im0b+zeta_b*dm1b, mo_coeff[1].T)) im0 = im0a + im0b hcore_deriv = td_grad.hcore_generator(mol) s1 = td_grad.get_ovlp(mol) dmz1dooa = z1ao[0] + dmzooa dmz1doob = z1ao[1] + dmzoob oo0a = reduce(numpy.dot, (orboa, orboa.T)) oo0b = reduce(numpy.dot, (orbob, orbob.T)) as_dm1 = oo0a + oo0b + (dmz1dooa + dmz1doob) * .5 vj, vk = td_grad.get_jk(mol, (oo0a, dmz1dooa+dmz1dooa.T, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T, oo0b, dmz1doob+dmz1doob.T, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T)) vj = vj.reshape(2,4,3,nao,nao) vk = vk.reshape(2,4,3,nao,nao) vhf1a, vhf1b = vj[0] + vj[1] - vk time1 = log.timer('2e AO integral derivatives', *time1) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst),3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # Ground state gradients h1ao = hcore_deriv(ia) de[k] = numpy.einsum('xpq,pq->x', h1ao, as_dm1) de[k] += numpy.einsum('xpq,pq->x', vhf1a[0,:,p0:p1], oo0a[p0:p1]) de[k] += numpy.einsum('xpq,pq->x', vhf1b[0,:,p0:p1], oo0b[p0:p1]) de[k] += numpy.einsum('xpq,qp->x', vhf1a[0,:,p0:p1], oo0a[:,p0:p1]) de[k] += numpy.einsum('xpq,qp->x', vhf1b[0,:,p0:p1], oo0b[:,p0:p1]) de[k] += numpy.einsum('xpq,pq->x', vhf1a[0,:,p0:p1], dmz1dooa[p0:p1]) * .5 de[k] += numpy.einsum('xpq,pq->x', vhf1b[0,:,p0:p1], dmz1doob[p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', vhf1a[0,:,p0:p1], dmz1dooa[:,p0:p1]) * .5 de[k] += numpy.einsum('xpq,qp->x', vhf1b[0,:,p0:p1], dmz1doob[:,p0:p1]) * .5 de[k] -= numpy.einsum('xpq,pq->x', s1[:,p0:p1], im0[p0:p1]) de[k] -= numpy.einsum('xqp,pq->x', s1[:,p0:p1], im0[:,p0:p1]) de[k] += numpy.einsum('xij,ij->x', vhf1a[1,:,p0:p1], oo0a[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', vhf1b[1,:,p0:p1], oo0b[p0:p1]) * .5 de[k] += numpy.einsum('xij,ij->x', vhf1a[2,:,p0:p1], dmzvopa[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', vhf1b[2,:,p0:p1], dmzvopb[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', vhf1a[3,:,p0:p1], dmzvoma[p0:p1,:]) de[k] += numpy.einsum('xij,ij->x', vhf1b[3,:,p0:p1], dmzvomb[p0:p1,:]) de[k] += numpy.einsum('xji,ij->x', vhf1a[2,:,p0:p1], dmzvopa[:,p0:p1]) de[k] += numpy.einsum('xji,ij->x', vhf1b[2,:,p0:p1], dmzvopb[:,p0:p1]) de[k] -= numpy.einsum('xji,ij->x', vhf1a[3,:,p0:p1], dmzvoma[:,p0:p1]) de[k] -= numpy.einsum('xji,ij->x', vhf1b[3,:,p0:p1], dmzvomb[:,p0:p1]) log.timer('TDUHF nuclear gradients', *time0) return de