def gen_vind(mf, mo_coeff, mo_occ): nao, nmoa = mo_coeff[0].shape nmob = mo_coeff[1].shape[1] mocca = mo_coeff[0][:,mo_occ[0]>0] moccb = mo_coeff[1][:,mo_occ[1]>0] nocca = mocca.shape[1] noccb = moccb.shape[1] vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def fx(mo1): mo1 = mo1.reshape(-1,nmoa*nocca+nmob*noccb) nset = len(mo1) dm1 = numpy.empty((2,nset,nao,nao)) for i, x in enumerate(mo1): xa = x[:nmoa*nocca].reshape(nmoa,nocca) xb = x[nmoa*nocca:].reshape(nmob,noccb) dma = reduce(numpy.dot, (mo_coeff[0], xa, mocca.T)) dmb = reduce(numpy.dot, (mo_coeff[1], xb, moccb.T)) dm1[0,i] = dma + dma.T dm1[1,i] = dmb + dmb.T v1 = vresp(dm1) v1vo = numpy.empty_like(mo1) for i in range(nset): v1vo[i,:nmoa*nocca] = reduce(numpy.dot, (mo_coeff[0].T, v1[0,i], mocca)).ravel() v1vo[i,nmoa*nocca:] = reduce(numpy.dot, (mo_coeff[1].T, v1[1,i], moccb)).ravel() return v1vo return fx
def gen_vind(mf, mo_coeff, mo_occ): '''Induced potential''' vresp = _gen_uhf_response(mf, with_j=False, hermi=0) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 orboa = mo_coeff[0][:, occidxa] orbva = mo_coeff[0][:,~occidxa] orbob = mo_coeff[1][:, occidxb] orbvb = mo_coeff[1][:,~occidxb] nocca = orboa.shape[1] noccb = orbob.shape[1] nvira = orbva.shape[1] nvirb = orbvb.shape[1] nova = nocca * nvira novb = noccb * nvirb mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F') def vind(mo1): mo1a = mo1.reshape(-1,nova+novb)[:,:nova].reshape(-1,nvira,nocca) mo1b = mo1.reshape(-1,nova+novb)[:,nova:].reshape(-1,nvirb,noccb) nset = mo1a.shape[0] dm1a = _dm1_mo2ao(mo1a, orbva, orboa) dm1b = _dm1_mo2ao(mo1b, orbvb, orbob) dm1 = numpy.vstack([dm1a-dm1a.transpose(0,2,1), dm1b-dm1b.transpose(0,2,1)]) v1 = vresp(dm1) v1a = _ao2mo.nr_e2(v1[ :nset], mo_va_oa, (0,nvira,nvira,nvira+nocca)) v1b = _ao2mo.nr_e2(v1[nset: ], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb)) v1mo = numpy.hstack((v1a.reshape(nset,-1), v1b.reshape(nset,-1))) return v1mo.ravel() return vind
def gen_vind(self, mf, mo_coeff, mo_occ): '''Induced potential''' vresp = _gen_uhf_response(mf, hermi=1) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 mo0a, mo0b = mo_coeff orboa = mo0a[:, occidxa] orbob = mo0b[:, occidxb] nocca = orboa.shape[1] noccb = orbob.shape[1] nmoa = mo0a.shape[1] nmob = mo0b.shape[1] def vind(mo1): mo1 = mo1.reshape(-1,nmoa*nocca+nmob*noccb) mo1a = mo1[:,:nmoa*nocca].reshape(-1,nmoa,nocca) mo1b = mo1[:,nmoa*nocca:].reshape(-1,nmob,noccb) dm1a = lib.einsum('xai,pa,qi->xpq', mo1a, mo0a, orboa.conj()) dm1b = lib.einsum('xai,pa,qi->xpq', mo1b, mo0b, orbob.conj()) dm1a = dm1a + dm1a.transpose(0,2,1).conj() dm1b = dm1b + dm1b.transpose(0,2,1).conj() v1ao = vresp(numpy.stack((dm1a,dm1b))) v1a = lib.einsum('xpq,pi,qj->xij', v1ao[0], mo0a.conj(), orboa) v1b = lib.einsum('xpq,pi,qj->xij', v1ao[1], mo0b.conj(), orbob) v1mo = numpy.hstack((v1a.reshape(-1,nmoa*nocca), v1b.reshape(-1,nmob*noccb))) return v1mo.ravel() return vind
def gen_vind(self, mf, mo_coeff, mo_occ): '''Induced potential''' vresp = _gen_uhf_response(mf, hermi=1) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 mo0a, mo0b = mo_coeff orboa = mo0a[:, occidxa] orbob = mo0b[:, occidxb] nocca = orboa.shape[1] noccb = orbob.shape[1] nmoa = mo0a.shape[1] nmob = mo0b.shape[1] def vind(mo1): mo1 = mo1.reshape(-1, nmoa * nocca + nmob * noccb) mo1a = mo1[:, :nmoa * nocca].reshape(-1, nmoa, nocca) mo1b = mo1[:, nmoa * nocca:].reshape(-1, nmob, noccb) dm1a = lib.einsum('xai,pa,qi->xpq', mo1a, mo0a, orboa.conj()) dm1b = lib.einsum('xai,pa,qi->xpq', mo1b, mo0b, orbob.conj()) dm1a = dm1a + dm1a.transpose(0, 2, 1).conj() dm1b = dm1b + dm1b.transpose(0, 2, 1).conj() v1ao = vresp(numpy.stack((dm1a, dm1b))) v1a = lib.einsum('xpq,pi,qj->xij', v1ao[0], mo0a.conj(), orboa) v1b = lib.einsum('xpq,pi,qj->xij', v1ao[1], mo0b.conj(), orbob) v1mo = numpy.hstack( (v1a.reshape(-1, nmoa * nocca), v1b.reshape(-1, nmob * noccb))) return v1mo.ravel() return vind
def gen_vind(mf, mo_coeff, mo_occ): '''Induced potential associated with h1_PSO''' vresp = _gen_uhf_response(mf, with_j=False, hermi=0) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 orboa = mo_coeff[0][:, occidxa] orbva = mo_coeff[0][:, ~occidxa] orbob = mo_coeff[1][:, occidxb] orbvb = mo_coeff[1][:, ~occidxb] nocca = orboa.shape[1] noccb = orbob.shape[1] nvira = orbva.shape[1] nvirb = orbvb.shape[1] nova = nocca * nvira novb = noccb * nvirb mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1a = mo1.reshape(-1, nova + novb)[:, :nova].reshape(-1, nvira, nocca) mo1b = mo1.reshape(-1, nova + novb)[:, nova:].reshape(-1, nvirb, noccb) nset = mo1a.shape[0] dm1a = _dm1_mo2ao(mo1a, orbva, orboa) dm1b = _dm1_mo2ao(mo1b, orbvb, orbob) dm1 = numpy.asarray( [dm1a - dm1a.transpose(0, 2, 1), dm1b - dm1b.transpose(0, 2, 1)]) v1 = vresp(dm1) v1a = _ao2mo.nr_e2(v1[0], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1b = _ao2mo.nr_e2(v1[1], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1mo = numpy.hstack((v1a.reshape(nset, -1), v1b.reshape(nset, -1))) return v1mo.ravel() return vind
def gen_vind(self, mf, mo_coeff, mo_occ): '''Induced potential''' vresp = _gen_uhf_response(self._scf, hermi=2) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] nocca = orboa.shape[1] noccb = orbob.shape[1] nao, nmo = mo_coeff[0].shape nvira = nmo - nocca def vind(mo1): mo1a = mo1.reshape(3,-1)[:,:nocca*nmo].reshape(3,nmo,nocca) mo1b = mo1.reshape(3,-1)[:,nocca*nmo:].reshape(3,nmo,noccb) dm1a = [reduce(numpy.dot, (mo_coeff[0], x, orboa.T.conj())) for x in mo1a] dm1b = [reduce(numpy.dot, (mo_coeff[1], x, orbob.T.conj())) for x in mo1b] dm1 = numpy.asarray(([d1-d1.conj().T for d1 in dm1a], [d1-d1.conj().T for d1 in dm1b])) v1ao = vresp(dm1) v1a = [reduce(numpy.dot, (mo_coeff[0].T.conj(), x, orboa)) for x in v1ao[0]] v1b = [reduce(numpy.dot, (mo_coeff[1].T.conj(), x, orbob)) for x in v1ao[1]] v1mo = numpy.hstack((numpy.asarray(v1a).reshape(3,-1), numpy.asarray(v1b).reshape(3,-1))) return v1mo.ravel() return vind
def gen_vind(mf, mo_coeff, mo_occ): nao, nmoa = mo_coeff[0].shape nmob = mo_coeff[1].shape[1] mocca = mo_coeff[0][:, mo_occ[0] > 0] moccb = mo_coeff[1][:, mo_occ[1] > 0] nocca = mocca.shape[1] noccb = moccb.shape[1] vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def fx(mo1): mo1 = mo1.reshape(-1, nmoa * nocca + nmob * noccb) nset = len(mo1) dm1 = numpy.empty((2, nset, nao, nao)) for i, x in enumerate(mo1): xa = x[:nmoa * nocca].reshape(nmoa, nocca) xb = x[nmoa * nocca:].reshape(nmob, noccb) dma = reduce(numpy.dot, (mo_coeff[0], xa, mocca.T)) dmb = reduce(numpy.dot, (mo_coeff[1], xb, moccb.T)) dm1[0, i] = dma + dma.T dm1[1, i] = dmb + dmb.T v1 = vresp(dm1) v1vo = numpy.empty_like(mo1) for i in range(nset): v1vo[i, :nmoa * nocca] = reduce( numpy.dot, (mo_coeff[0].T, v1[0, i], mocca)).ravel() v1vo[i, nmoa * nocca:] = reduce( numpy.dot, (mo_coeff[1].T, v1[1, i], moccb)).ravel() return v1vo return fx
def gen_vind(mf, mo_coeff, mo_occ): '''Induced potential''' vresp = _gen_uhf_response(mf, hermi=2) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] nocca = orboa.shape[1] noccb = orbob.shape[1] nao, nmo = mo_coeff[0].shape nvira = nmo - nocca def vind(mo1): mo1a = mo1.reshape(3,-1)[:,:nocca*nmo].reshape(3,nmo,nocca) mo1b = mo1.reshape(3,-1)[:,nocca*nmo:].reshape(3,nmo,noccb) dm1a = [reduce(numpy.dot, (mo_coeff[0], x, orboa.T.conj())) for x in mo1a] dm1b = [reduce(numpy.dot, (mo_coeff[1], x, orbob.T.conj())) for x in mo1b] dm1 = numpy.asarray(([d1-d1.conj().T for d1 in dm1a], [d1-d1.conj().T for d1 in dm1b])) v1ao = vresp(dm1) v1a = [reduce(numpy.dot, (mo_coeff[0].T.conj(), x, orboa)) for x in v1ao[0]] v1b = [reduce(numpy.dot, (mo_coeff[1].T.conj(), x, orbob)) for x in v1ao[1]] v1mo = numpy.hstack((numpy.asarray(v1a).reshape(3,-1), numpy.asarray(v1b).reshape(3,-1))) return v1mo.ravel() return vind
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 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 ucphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb mo_ea, mo_eb = mo_energy # e_ai - freq may produce very small elements which can cause numerical # issue in krylov solver LEVEL_SHIF = 0.1 e_ai_a = lib.direct_sum('a-i->ai', mo_ea[viridxa], mo_ea[occidxa]).ravel() e_ai_b = lib.direct_sum('a-i->ai', mo_eb[viridxb], mo_eb[occidxb]).ravel() diag = (e_ai_a - freq, e_ai_b - freq, e_ai_a + freq, e_ai_b + freq) diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF diag[2][diag[2] < LEVEL_SHIF] += LEVEL_SHIF diag[3][diag[3] < LEVEL_SHIF] += LEVEL_SHIF mo0a, mo0b = mf.mo_coeff nao, nmoa = mo0a.shape nmob = mo0b.shape orbva = mo0a[:, viridxa] orbvb = mo0b[:, viridxb] orboa = mo0a[:, occidxa] orbob = mo0b[:, occidxb] nvira = orbva.shape[1] nvirb = orbvb.shape[1] nocca = orboa.shape[1] noccb = orbob.shape[1] h1a = h1[0].reshape(-1, nvira * nocca) h1b = h1[1].reshape(-1, nvirb * noccb) ncomp = h1a.shape[0] mo1base = numpy.hstack( (-h1a / diag[0], -h1b / diag[1], -h1a / diag[2], -h1b / diag[3])) offsets = numpy.cumsum((nocca * nvira, noccb * nvirb, nocca * nvira)) vresp = _gen_uhf_response(mf, hermi=0) def vind(xys): nz = len(xys) dm1a = numpy.empty((nz, nao, nao)) dm1b = numpy.empty((nz, nao, nao)) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca), orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira, nocca).T, orbva.T)) dm1a[i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb), orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb, noccb).T, orbvb.T)) dm1b[i] = dmx + dmy # AX + BY v1ao = vresp(numpy.stack((dm1a, dm1b))) v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva, orboa).reshape(nz, -1) v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb, orbob).reshape(nz, -1) v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa, orbva).reshape(nz, -1) v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob, orbvb).reshape(nz, -1) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) v1voa[i] += (e_ai_a - freq - diag[0]) * xa v1voa[i] /= diag[0] v1vob[i] += (e_ai_b - freq - diag[1]) * xb v1vob[i] /= diag[1] v1ova[i] += (e_ai_a + freq - diag[2]) * ya v1ova[i] /= diag[2] v1ovb[i] += (e_ai_b + freq - diag[3]) * yb v1ovb[i] /= diag[3] v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb)) return v # FIXME: krylov solver is not accurate enough for many freqs. Using tight # tol and lindep could offer small help. A better linear equation solver # is needed. mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, lindep=1e-18, verbose=log) log.timer('krylov solver in CPHF', *t0) dm1a = numpy.empty((ncomp, nao, nao)) dm1b = numpy.empty((ncomp, nao, nao)) for i in range(ncomp): xa, xb, ya, yb = numpy.split(mo1[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca) * 2, orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira, nocca).T * 2, orbva.T)) dm1a[i] = dmx + dmy dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb) * 2, orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb, noccb).T * 2, orbvb.T)) dm1b[i] = dmx + dmy v1ao = vresp(numpy.stack((dm1a, dm1b))) mo_e1_a = lib.einsum('xpq,pi,qj->xij', v1ao[0], orboa, orboa) mo_e1_b = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbob, orbob) mo_e1 = (mo_e1_a, mo_e1_b) xa, xb, ya, yb = numpy.split(mo1, offsets, axis=1) mo1 = (xa.reshape(ncomp, nvira, nocca), xb.reshape(ncomp, nvirb, noccb), ya.reshape(ncomp, nvira, nocca), yb.reshape(ncomp, nvirb, noccb)) return mo1, mo_e1
def solve_mo1(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 h1aa, h1ab, h1ba, h1bb = h1 nset = len(h1aa) eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[0][mo_occ[0] > 0]) eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[1][mo_occ[1] > 0]) eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[0][mo_occ[0] > 0]) eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[1][mo_occ[1] > 0]) mo1 = (numpy.asarray(h1aa) * -eai_aa, numpy.asarray(h1ab) * -eai_ab, numpy.asarray(h1ba) * -eai_ba, numpy.asarray(h1bb) * -eai_bb) h1aa = h1ab = h1ba = h1bb = None if not sscobj.cphf: return mo1 orboa = mo_coeff[0][:, mo_occ[0] > 0] orbva = mo_coeff[0][:, mo_occ[0] == 0] orbob = mo_coeff[1][:, mo_occ[1] > 0] orbvb = mo_coeff[1][:, mo_occ[1] == 0] nocca = orboa.shape[1] nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] p1 = nvira * nocca p2 = p1 + nvira * noccb p3 = p2 + nvirb * nocca def _split_mo1(mo1): mo1 = mo1.reshape(nset, -1) mo1aa = mo1[:, :p1].reshape(nset, nvira, nocca) mo1ab = mo1[:, p1:p2].reshape(nset, nvira, noccb) mo1ba = mo1[:, p2:p3].reshape(nset, nvirb, nocca) mo1bb = mo1[:, p3:].reshape(nset, nvirb, noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1 = numpy.hstack((mo1[0].reshape(nset, -1), mo1[1].reshape(nset, -1), mo1[2].reshape(nset, -1), mo1[3].reshape(nset, -1))) vresp = _gen_uhf_response(mf, with_j=False, hermi=0) mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_va_ob = numpy.asarray(numpy.hstack((orbva, orbob)), order='F') mo_vb_oa = numpy.asarray(numpy.hstack((orbvb, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob) dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) # imaginary Hermitian dm1 = numpy.vstack([ dm1aa - dm1aa.transpose(0, 2, 1), dm1ab - dm1ba.transpose(0, 2, 1), dm1ba - dm1ab.transpose(0, 2, 1), dm1bb - dm1bb.transpose(0, 2, 1) ]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[:nset], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1ab = _ao2mo.nr_e2(v1[nset * 1:nset * 2], mo_va_ob, (0, nvira, nvira, nvira + noccb)) v1ba = _ao2mo.nr_e2(v1[nset * 2:nset * 3], mo_vb_oa, (0, nvirb, nvirb, nvirb + nocca)) v1bb = _ao2mo.nr_e2(v1[nset * 3:], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1aa = v1aa.reshape(nset, nvira, nocca) v1ab = v1ab.reshape(nset, nvira, noccb) v1ba = v1ba.reshape(nset, nvirb, nocca) v1bb = v1bb.reshape(nset, nvirb, noccb) v1aa *= eai_aa v1ab *= eai_ab v1ba *= eai_ba v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset, -1), v1ab.reshape(nset, -1), v1ba.reshape(nset, -1), v1bb.reshape(nset, -1))) return v1mo.ravel() mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log) log.timer('solving FC CPHF eqn', *cput1) mo1 = _split_mo1(mo1) return mo1
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None): '''Generate function to compute [ A B][X] [-B -A][Y] ''' mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape occidxa = numpy.where(mo_occ[0] > 0)[0] occidxb = numpy.where(mo_occ[1] > 0)[0] viridxa = numpy.where(mo_occ[0] == 0)[0] viridxb = numpy.where(mo_occ[1] == 0)[0] nocca = len(occidxa) noccb = len(occidxb) nvira = len(viridxa) nvirb = len(viridxb) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel())) mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F') mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F') mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory) def vind(xys): nz = len(xys) if wfnsym is not None and mol.symmetry: # shape(nz,2,-1): 2 ~ X,Y xys = numpy.copy(xys).reshape(nz, 2, -1) xys[:, :, sym_forbid] = 0 dms = numpy.empty((2, nz, nao, nao)) # 2 ~ alpha,beta for i in range(nz): x, y = xys[i].reshape(2, -1) xa = x[:nocca * nvira].reshape(nocca, nvira) xb = x[nocca * nvira:].reshape(noccb, nvirb) ya = y[:nocca * nvira].reshape(nocca, nvira) yb = y[nocca * nvira:].reshape(noccb, nvirb) dmx = reduce(numpy.dot, (orboa, xa, orbva.T)) dmy = reduce(numpy.dot, (orbva, ya.T, orboa.T)) dms[0, i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbob, xb, orbvb.T)) dmy = reduce(numpy.dot, (orbvb, yb.T, orbob.T)) dms[1, i] = dmx + dmy # AX + BY v1ao = vresp(dms) v1avo = _ao2mo.nr_e2(v1ao[0], mo_a, (nocca, nmo, 0, nocca)) v1bvo = _ao2mo.nr_e2(v1ao[1], mo_b, (noccb, nmo, 0, noccb)) v1aov = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo)) v1bov = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo)) hx = numpy.empty((nz, 2, nvira * nocca + nvirb * noccb), dtype=v1avo.dtype) for i in range(nz): x, y = xys[i].reshape(2, -1) hx[i, 0, :nvira * nocca] = v1aov[i].ravel() hx[i, 0, nvira * nocca:] = v1bov[i].ravel() hx[i, 0] += e_ia * x # AX hx[i, 1, :nvira * nocca] = -v1avo[i].reshape(nvira, nocca).T.ravel() hx[i, 1, nvira * nocca:] = -v1bvo[i].reshape(nvirb, noccb).T.ravel() hx[i, 1] -= e_ia * y #-AY if wfnsym is not None and mol.symmetry: hx[:, :, sym_forbid] = 0 return hx.reshape(nz, -1) return vind, hdiag
def gen_tda_operation(mf, fock_ao=None, wfnsym=None): '''(A+B)x Kwargs: wfnsym : int or str Point group symmetry irrep symbol or ID for excited CIS wavefunction. ''' mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape occidxa = numpy.where(mo_occ[0] > 0)[0] occidxb = numpy.where(mo_occ[1] > 0)[0] viridxa = numpy.where(mo_occ[0] == 0)[0] viridxb = numpy.where(mo_occ[1] == 0)[0] nocca = len(occidxa) noccb = len(occidxb) nvira = len(viridxa) nvirb = len(viridxb) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F') mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F') mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:, sym_forbid] = 0 dmov = numpy.empty((2, nz, nao, nao)) for i, z in enumerate(zs): za = z[:nocca * nvira].reshape(nocca, nvira) zb = z[nocca * nvira:].reshape(noccb, nvirb) dmov[0, i] = reduce(numpy.dot, (orboa, za, orbva.conj().T)) dmov[1, i] = reduce(numpy.dot, (orbob, zb, orbvb.conj().T)) v1ao = vresp(dmov) v1a = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo)).reshape(-1, nocca, nvira) v1b = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo)).reshape(-1, noccb, nvirb) for i, z in enumerate(zs): za = z[:nocca * nvira].reshape(nocca, nvira) zb = z[nocca * nvira:].reshape(noccb, nvirb) v1a[i] += numpy.einsum('ia,ia->ia', e_ia_a, za) v1b[i] += numpy.einsum('ia,ia->ia', e_ia_b, zb) hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1))) if wfnsym is not None and mol.symmetry: hx[:, sym_forbid] = 0 return hx return vind, hdiag
def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mf = sscobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ h1aa, h1ab, h1ba, h1bb = h1 eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[0][mo_occ[0] > 0]) eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[1][mo_occ[1] > 0]) eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[0][mo_occ[0] > 0]) eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[1][mo_occ[1] > 0]) mo1aa = numpy.asarray(h1aa) * -eai_aa mo1ab = numpy.asarray(h1ab) * -eai_ab mo1ba = numpy.asarray(h1ba) * -eai_ba mo1bb = numpy.asarray(h1bb) * -eai_bb mo1_fc = (mo1aa, mo1ab, mo1ba, mo1bb) if not sscobj.cphf: return mo1_fc orboa = mo_coeff[0][:, mo_occ[0] > 0] orbva = mo_coeff[0][:, mo_occ[0] == 0] orbob = mo_coeff[1][:, mo_occ[1] > 0] orbvb = mo_coeff[1][:, mo_occ[1] == 0] nocca = orboa.shape[1] nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] nao = mol.nao vresp = _gen_uhf_response(mf, with_j=False, hermi=1) if ZZ_ONLY: # To make UHF/UKS and RHF/RKS code consistent, only z-component is # considered. nvars = nvira * nocca + nvirb * noccb nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = mo1.reshape(nset, nvars) mo1aa = mo1[:, :nvira * nocca].reshape(nset, nvira, nocca) mo1bb = mo1[:, nvira * nocca:].reshape(nset, nvirb, noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack( (mo1_fc[0].reshape(nset, -1), mo1_fc[3].reshape(nset, -1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([ dm1aa + dm1aa.transpose(0, 2, 1), dm1bb + dm1bb.transpose(0, 2, 1) ]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1bb = _ao2mo.nr_e2(v1[1], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1aa = v1aa.reshape(nset, nvira, nocca) v1bb = v1bb.reshape(nset, nvirb, noccb) v1aa *= eai_aa v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset, -1), v1bb.reshape(nset, -1))) return v1mo.ravel() else: segs = (nvira * nocca, nvira * noccb, nvirb * nocca, nvirb * noccb) sections = numpy.cumsum(segs[:3]) nvars = numpy.sum(segs) nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = numpy.split(mo1.reshape(nset, nvars), sections, axis=1) mo1aa = mo1[0].reshape(nset, nvira, nocca) mo1ab = mo1[1].reshape(nset, nvira, noccb) mo1ba = mo1[2].reshape(nset, nvirb, nocca) mo1bb = mo1[3].reshape(nset, nvirb, noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack( (mo1_fc[0].reshape(nset, -1), mo1_fc[1].reshape(nset, -1), mo1_fc[2].reshape(nset, -1), mo1_fc[3].reshape(nset, -1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_va_ob = numpy.asarray(numpy.hstack((orbva, orbob)), order='F') mo_vb_oa = numpy.asarray(numpy.hstack((orbvb, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob) dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([ dm1aa + dm1aa.transpose(0, 2, 1), dm1ab + dm1ba.transpose(0, 2, 1), dm1ba + dm1ab.transpose(0, 2, 1), dm1bb + dm1bb.transpose(0, 2, 1) ]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1ab = _ao2mo.nr_e2(v1[1], mo_va_ob, (0, nvira, nvira, nvira + noccb)) v1ba = _ao2mo.nr_e2(v1[2], mo_vb_oa, (0, nvirb, nvirb, nvirb + nocca)) v1bb = _ao2mo.nr_e2(v1[3], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1aa = v1aa.reshape(nset, nvira, nocca) v1ab = v1ab.reshape(nset, nvira, noccb) v1ba = v1ba.reshape(nset, nvirb, nocca) v1bb = v1bb.reshape(nset, nvirb, noccb) v1aa *= eai_aa v1ab *= eai_ab v1ba *= eai_ba v1bb *= eai_bb v1mo = numpy.hstack( (v1aa.reshape(nset, -1), v1ab.reshape(nset, -1), v1ba.reshape(nset, -1), v1bb.reshape(nset, -1))) return v1mo.ravel() mo1 = lib.krylov(vind, mo1_fc.ravel(), tol=sscobj.conv_tol, max_cycle=sscobj.max_cycle_cphf, verbose=log) log.timer('solving FC CPHF eqn', *cput1) mo1_fc = _split_mo1(mo1) return mo1_fc
def _gen_hop_uhf_external(mf, with_symmetry=True, verbose=None): mol = mf.mol 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] if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = orbsyma[viridxa].reshape(-1,1) != orbsyma[occidxa] sym_forbidb = orbsymb[viridxb].reshape(-1,1) != orbsymb[occidxb] sym_forbid1 = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(mol, dm0) focka = reduce(numpy.dot, (mo_coeff[0].conj().T, fock_ao[0], mo_coeff[0])) fockb = reduce(numpy.dot, (mo_coeff[1].conj().T, fock_ao[1], mo_coeff[1])) fooa = focka[occidxa[:,None],occidxa] fvva = focka[viridxa[:,None],viridxa] foob = fockb[occidxb[:,None],occidxb] fvvb = fockb[viridxb[:,None],viridxb] h_diaga =(focka[viridxa,viridxa].reshape(-1,1) - focka[occidxa,occidxa]) h_diagb =(fockb[viridxb,viridxb].reshape(-1,1) - fockb[occidxb,occidxb]) hdiag1 = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1))) if with_symmetry and mol.symmetry: hdiag1[sym_forbid1] = 0 mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory*.8-mem_now) vrespz = _gen_uhf_response(mf, with_j=False, hermi=2) def hop_real2complex(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid1] = 0 x1a = x1[:nvira*nocca].reshape(nvira,nocca) x1b = x1[nvira*nocca:].reshape(nvirb,noccb) x2a = numpy.einsum('pr,rq->pq', fvva, x1a) x2a-= numpy.einsum('sq,ps->pq', fooa, x1a) x2b = numpy.einsum('pr,rq->pq', fvvb, x1b) x2b-= numpy.einsum('qs,ps->pq', foob, x1b) d1a = reduce(numpy.dot, (orbva, x1a, orboa.conj().T)) d1b = reduce(numpy.dot, (orbvb, x1b, orbob.conj().T)) dm1 = numpy.array((d1a-d1a.conj().T, d1b-d1b.conj().T)) v1 = vrespz(dm1) x2a += reduce(numpy.dot, (orbva.conj().T, v1[0], orboa)) x2b += reduce(numpy.dot, (orbvb.conj().T, v1[1], orbob)) x2 = numpy.hstack((x2a.ravel(), x2b.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid1] = 0 return x2 if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbidab = orbsyma[viridxa].reshape(-1,1) != orbsymb[occidxb] sym_forbidba = orbsymb[viridxb].reshape(-1,1) != orbsyma[occidxa] sym_forbid2 = numpy.hstack((sym_forbidab.ravel(), sym_forbidba.ravel())) hdiagab = fvva.diagonal().reshape(-1,1) - foob.diagonal() hdiagba = fvvb.diagonal().reshape(-1,1) - fooa.diagonal() hdiag2 = numpy.hstack((hdiagab.ravel(), hdiagba.ravel())) if with_symmetry and mol.symmetry: hdiag2[sym_forbid2] = 0 vresp1 = _gen_uhf_response(mf, with_j=False, hermi=0) # Spin flip GHF solution is not considered def hop_uhf2ghf(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid2] = 0 x1ab = x1[:nvira*noccb].reshape(nvira,noccb) x1ba = x1[nvira*noccb:].reshape(nvirb,nocca) x2ab = numpy.einsum('pr,rq->pq', fvva, x1ab) x2ab-= numpy.einsum('sq,ps->pq', foob, x1ab) x2ba = numpy.einsum('pr,rq->pq', fvvb, x1ba) x2ba-= numpy.einsum('qs,ps->pq', fooa, x1ba) d1ab = reduce(numpy.dot, (orbva, x1ab, orbob.conj().T)) d1ba = reduce(numpy.dot, (orbvb, x1ba, orboa.conj().T)) dm1 = numpy.array((d1ab+d1ba.conj().T, d1ba+d1ab.conj().T)) v1 = vresp1(dm1) x2ab += reduce(numpy.dot, (orbva.conj().T, v1[0], orbob)) x2ba += reduce(numpy.dot, (orbvb.conj().T, v1[1], orboa)) x2 = numpy.hstack((x2ab.real.ravel(), x2ba.real.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid2] = 0 return x2 return hop_real2complex, hdiag1, hop_uhf2ghf, hdiag2
def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mf = sscobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ h1aa, h1ab, h1ba, h1bb = h1 eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0]==0], mo_energy[0][mo_occ[0]>0]) eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0]==0], mo_energy[1][mo_occ[1]>0]) eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1]==0], mo_energy[0][mo_occ[0]>0]) eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1]==0], mo_energy[1][mo_occ[1]>0]) mo1aa = numpy.asarray(h1aa) * -eai_aa mo1ab = numpy.asarray(h1ab) * -eai_ab mo1ba = numpy.asarray(h1ba) * -eai_ba mo1bb = numpy.asarray(h1bb) * -eai_bb mo1_fc = (mo1aa, mo1ab, mo1ba, mo1bb) if not sscobj.cphf: return mo1_fc orboa = mo_coeff[0][:,mo_occ[0]> 0] orbva = mo_coeff[0][:,mo_occ[0]==0] orbob = mo_coeff[1][:,mo_occ[1]> 0] orbvb = mo_coeff[1][:,mo_occ[1]==0] nocca = orboa.shape[1] nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] nao = mol.nao vresp = _gen_uhf_response(mf, with_j=False, hermi=1) if ZZ_ONLY: # To make UHF/UKS and RHF/RKS code consistent, only z-component is # considered. nvars = nvira*nocca + nvirb*noccb nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = mo1.reshape(nset,nvars) mo1aa = mo1[:,:nvira*nocca].reshape(nset,nvira,nocca) mo1bb = mo1[:,nvira*nocca:].reshape(nset,nvirb,noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack((mo1_fc[0].reshape(nset,-1), mo1_fc[3].reshape(nset,-1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([dm1aa+dm1aa.transpose(0,2,1), dm1bb+dm1bb.transpose(0,2,1)]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0,nvira,nvira,nvira+nocca)) v1bb = _ao2mo.nr_e2(v1[1], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb)) v1aa = v1aa.reshape(nset,nvira,nocca) v1bb = v1bb.reshape(nset,nvirb,noccb) v1aa *= eai_aa v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset,-1), v1bb.reshape(nset,-1))) return v1mo.ravel() else: segs = (nvira*nocca, nvira*noccb, nvirb*nocca, nvirb*noccb) sections = numpy.cumsum(segs[:3]) nvars = numpy.sum(segs) nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = numpy.split(mo1.reshape(nset,nvars), sections, axis=1) mo1aa = mo1[0].reshape(nset,nvira,nocca) mo1ab = mo1[1].reshape(nset,nvira,noccb) mo1ba = mo1[2].reshape(nset,nvirb,nocca) mo1bb = mo1[3].reshape(nset,nvirb,noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack((mo1_fc[0].reshape(nset,-1), mo1_fc[1].reshape(nset,-1), mo1_fc[2].reshape(nset,-1), mo1_fc[3].reshape(nset,-1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F') mo_va_ob = numpy.asarray(numpy.hstack((orbva,orbob)), order='F') mo_vb_oa = numpy.asarray(numpy.hstack((orbvb,orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob) dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([dm1aa+dm1aa.transpose(0,2,1), dm1ab+dm1ba.transpose(0,2,1), dm1ba+dm1ab.transpose(0,2,1), dm1bb+dm1bb.transpose(0,2,1)]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0,nvira,nvira,nvira+nocca)) v1ab = _ao2mo.nr_e2(v1[1], mo_va_ob, (0,nvira,nvira,nvira+noccb)) v1ba = _ao2mo.nr_e2(v1[2], mo_vb_oa, (0,nvirb,nvirb,nvirb+nocca)) v1bb = _ao2mo.nr_e2(v1[3], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb)) v1aa = v1aa.reshape(nset,nvira,nocca) v1ab = v1ab.reshape(nset,nvira,noccb) v1ba = v1ba.reshape(nset,nvirb,nocca) v1bb = v1bb.reshape(nset,nvirb,noccb) v1aa *= eai_aa v1ab *= eai_ab v1ba *= eai_ba v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset,-1), v1ab.reshape(nset,-1), v1ba.reshape(nset,-1), v1bb.reshape(nset,-1))) return v1mo.ravel() mo1 = lib.krylov(vind, mo1_fc.ravel(), tol=sscobj.conv_tol, max_cycle=sscobj.max_cycle_cphf, verbose=log) log.timer('solving FC CPHF eqn', *cput1) mo1_fc = _split_mo1(mo1) return mo1_fc
def _gen_hop_uhf_external(mf, with_symmetry=True, verbose=None): mol = mf.mol 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] if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = orbsyma[viridxa].reshape(-1, 1) != orbsyma[occidxa] sym_forbidb = orbsymb[viridxb].reshape(-1, 1) != orbsymb[occidxb] sym_forbid1 = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(mol, dm0) focka = reduce(numpy.dot, (mo_coeff[0].T, fock_ao[0], mo_coeff[0])) fockb = reduce(numpy.dot, (mo_coeff[1].T, fock_ao[1], mo_coeff[1])) fooa = focka[occidxa[:, None], occidxa] fvva = focka[viridxa[:, None], viridxa] foob = fockb[occidxb[:, None], occidxb] fvvb = fockb[viridxb[:, None], viridxb] h_diaga = (focka[viridxa, viridxa].reshape(-1, 1) - focka[occidxa, occidxa]) h_diagb = (fockb[viridxb, viridxb].reshape(-1, 1) - fockb[occidxb, occidxb]) hdiag1 = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1))) if with_symmetry and mol.symmetry: hdiag1[sym_forbid1] = 0 mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) vrespz = _gen_uhf_response(mf, with_j=False, hermi=2) def hop_real2complex(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid1] = 0 x1a = x1[:nvira * nocca].reshape(nvira, nocca) x1b = x1[nvira * nocca:].reshape(nvirb, noccb) x2a = numpy.einsum('pr,rq->pq', fvva, x1a) x2a -= numpy.einsum('sq,ps->pq', fooa, x1a) x2b = numpy.einsum('pr,rq->pq', fvvb, x1b) x2b -= numpy.einsum('qs,ps->pq', foob, x1b) d1a = reduce(numpy.dot, (orbva, x1a, orboa.T.conj())) d1b = reduce(numpy.dot, (orbvb, x1b, orbob.T.conj())) dm1 = numpy.array((d1a - d1a.T.conj(), d1b - d1b.T.conj())) v1 = vrespz(dm1) x2a += reduce(numpy.dot, (orbva.T.conj(), v1[0], orboa)) x2b += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orbob)) x2 = numpy.hstack((x2a.ravel(), x2b.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid1] = 0 return x2 if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbidab = orbsyma[viridxa].reshape(-1, 1) != orbsymb[occidxb] sym_forbidba = orbsymb[viridxb].reshape(-1, 1) != orbsyma[occidxa] sym_forbid2 = numpy.hstack( (sym_forbidab.ravel(), sym_forbidba.ravel())) hdiagab = fvva.diagonal().reshape(-1, 1) - foob.diagonal() hdiagba = fvvb.diagonal().reshape(-1, 1) - fooa.diagonal() hdiag2 = numpy.hstack((hdiagab.ravel(), hdiagba.ravel())) if with_symmetry and mol.symmetry: hdiag2[sym_forbid2] = 0 vresp1 = _gen_uhf_response(mf, with_j=False, hermi=0) # Spin flip GHF solution is not considered def hop_uhf2ghf(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid2] = 0 x1ab = x1[:nvira * noccb].reshape(nvira, noccb) x1ba = x1[nvira * noccb:].reshape(nvirb, nocca) x2ab = numpy.einsum('pr,rq->pq', fvva, x1ab) x2ab -= numpy.einsum('sq,ps->pq', foob, x1ab) x2ba = numpy.einsum('pr,rq->pq', fvvb, x1ba) x2ba -= numpy.einsum('qs,ps->pq', fooa, x1ba) d1ab = reduce(numpy.dot, (orbva, x1ab, orbob.T.conj())) d1ba = reduce(numpy.dot, (orbvb, x1ba, orboa.T.conj())) dm1 = numpy.array((d1ab + d1ba.T.conj(), d1ba + d1ab.T.conj())) v1 = vresp1(dm1) x2ab += reduce(numpy.dot, (orbva.T.conj(), v1[0], orbob)) x2ba += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orboa)) x2 = numpy.hstack((x2ab.ravel(), x2ba.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid2] = 0 return x2 return hop_real2complex, hdiag1, hop_uhf2ghf, hdiag2
def get_vind(self, mf): wfnsym = self.wfnsym singlet = self.singlet mol = mf.mol mo_coeff = mf.mo_coeff assert(mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape occidxa = numpy.where(mo_occ[0]>0)[0] occidxb = numpy.where(mo_occ[1]>0)[0] viridxa = numpy.where(mo_occ[0]==0)[0] viridxb = numpy.where(mo_occ[1]==0)[0] nocca = len(occidxa) noccb = len(occidxb) nvira = len(viridxa) nvirb = len(viridxb) orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] orbva = mo_coeff[0][:,viridxa] orbvb = mo_coeff[1][:,viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa,None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb,None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) e_ia_a = (mo_energy[0][viridxa,None] - mo_energy[0][occidxa]).T e_ia_b = (mo_energy[1][viridxb,None] - mo_energy[1][occidxb]).T e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) if wfnsym is not None and mol.symmetry: e_ia[sym_forbid] = 0 d_ia = numpy.sqrt(e_ia).ravel() ed_ia = e_ia.ravel() * d_ia hdiag = e_ia.ravel() ** 2 vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:,sym_forbid] = 0 dmov = numpy.empty((2,nz,nao,nao)) for i in range(nz): z = d_ia * zs[i] za = z[:nocca*nvira].reshape(nocca,nvira) zb = z[nocca*nvira:].reshape(noccb,nvirb) dm = reduce(numpy.dot, (orboa, za, orbva.T)) dmov[0,i] = dm + dm.T dm = reduce(numpy.dot, (orbob, zb, orbvb.T)) dmov[1,i] = dm + dm.T v1ao = vresp(dmov) v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0,nocca,nocca,nmo)) v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0,noccb,noccb,nmo)) hx = numpy.hstack((v1a.reshape(nz,-1), v1b.reshape(nz,-1))) for i, z in enumerate(zs): hx[i] += ed_ia * z hx[i] *= d_ia return hx return vind, hdiag
def ucphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb mo_ea, mo_eb = mo_energy # e_ai - freq may produce very small elements which can cause numerical # issue in krylov solver LEVEL_SHIF = 0.1 e_ai_a = lib.direct_sum('a-i->ai', mo_ea[viridxa], mo_ea[occidxa]).ravel() e_ai_b = lib.direct_sum('a-i->ai', mo_eb[viridxb], mo_eb[occidxb]).ravel() diag = (e_ai_a - freq, e_ai_b - freq, e_ai_a + freq, e_ai_b + freq) diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF diag[2][diag[2] < LEVEL_SHIF] += LEVEL_SHIF diag[3][diag[3] < LEVEL_SHIF] += LEVEL_SHIF mo0a, mo0b = mf.mo_coeff nao, nmoa = mo0a.shape nmob = mo0b.shape orbva = mo0a[:,viridxa] orbvb = mo0b[:,viridxb] orboa = mo0a[:,occidxa] orbob = mo0b[:,occidxb] nvira = orbva.shape[1] nvirb = orbvb.shape[1] nocca = orboa.shape[1] noccb = orbob.shape[1] h1a = h1[0].reshape(-1,nvira*nocca) h1b = h1[1].reshape(-1,nvirb*noccb) ncomp = h1a.shape[0] mo1base = numpy.hstack((-h1a/diag[0], -h1b/diag[1], -h1a/diag[2], -h1b/diag[3])) offsets = numpy.cumsum((nocca*nvira, noccb*nvirb, nocca*nvira)) vresp = _gen_uhf_response(mf, hermi=0) def vind(xys): nz = len(xys) dm1a = numpy.empty((nz,nao,nao)) dm1b = numpy.empty((nz,nao,nao)) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira,nocca) , orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira,nocca).T, orbva.T)) dm1a[i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb,noccb) , orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb,noccb).T, orbvb.T)) dm1b[i] = dmx + dmy # AX + BY v1ao = vresp(numpy.stack((dm1a,dm1b))) v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva, orboa).reshape(nz,-1) v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb, orbob).reshape(nz,-1) v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa, orbva).reshape(nz,-1) v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob, orbvb).reshape(nz,-1) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) v1voa[i] += (e_ai_a - freq - diag[0]) * xa v1voa[i] /= diag[0] v1vob[i] += (e_ai_b - freq - diag[1]) * xb v1vob[i] /= diag[1] v1ova[i] += (e_ai_a + freq - diag[2]) * ya v1ova[i] /= diag[2] v1ovb[i] += (e_ai_b + freq - diag[3]) * yb v1ovb[i] /= diag[3] v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb)) return v # FIXME: krylov solver is not accurate enough for many freqs. Using tight # tol and lindep could offer small help. A better linear equation solver # is needed. mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, lindep=1e-18, verbose=log) log.timer('krylov solver in CPHF', *t0) dm1a = numpy.empty((ncomp,nao,nao)) dm1b = numpy.empty((ncomp,nao,nao)) for i in range(ncomp): xa, xb, ya, yb = numpy.split(mo1[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira,nocca) *2, orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira,nocca).T*2, orbva.T)) dm1a[i] = dmx + dmy dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb,noccb) *2, orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb,noccb).T*2, orbvb.T)) dm1b[i] = dmx + dmy v1ao = vresp(numpy.stack((dm1a,dm1b))) mo_e1_a = lib.einsum('xpq,pi,qj->xij', v1ao[0], orboa, orboa) mo_e1_b = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbob, orbob) mo_e1 = (mo_e1_a, mo_e1_b) xa, xb, ya, yb = numpy.split(mo1, offsets, axis=1) mo1 = (xa.reshape(ncomp,nvira,nocca), xb.reshape(ncomp,nvirb,noccb), ya.reshape(ncomp,nvira,nocca), yb.reshape(ncomp,nvirb,noccb)) return mo1, mo_e1
def get_vind(self, mf): wfnsym = self.wfnsym singlet = self.singlet mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape occidxa = numpy.where(mo_occ[0] > 0)[0] occidxb = numpy.where(mo_occ[1] > 0)[0] viridxa = numpy.where(mo_occ[0] == 0)[0] viridxb = numpy.where(mo_occ[1] == 0)[0] nocca = len(occidxa) noccb = len(occidxb) nvira = len(viridxa) nvirb = len(viridxb) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack( (sym_forbida.ravel(), sym_forbidb.ravel())) e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) if wfnsym is not None and mol.symmetry: e_ia[sym_forbid] = 0 d_ia = numpy.sqrt(e_ia).ravel() ed_ia = e_ia.ravel() * d_ia hdiag = e_ia.ravel()**2 vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:, sym_forbid] = 0 dmov = numpy.empty((2, nz, nao, nao)) for i in range(nz): z = d_ia * zs[i] za = z[:nocca * nvira].reshape(nocca, nvira) zb = z[nocca * nvira:].reshape(noccb, nvirb) dm = reduce(numpy.dot, (orboa, za, orbva.T)) dmov[0, i] = dm + dm.T dm = reduce(numpy.dot, (orbob, zb, orbvb.T)) dmov[1, i] = dm + dm.T v1ao = vresp(dmov) v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0, nocca, nocca, nmo)) v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0, noccb, noccb, nmo)) hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1))) for i, z in enumerate(zs): hx[i] += ed_ia * z hx[i] *= d_ia return hx return vind, hdiag