def test_ccsd_t_complex(self): mol = gto.M() numpy.random.seed(12) nocc, nvir = 3, 4 nmo = nocc + nvir eris = cc.rccsd._ChemistsERIs() eri1 = (numpy.random.random( (nmo, nmo, nmo, nmo)) + numpy.random.random( (nmo, nmo, nmo, nmo)) * .8j - .5 - .4j) eri1 = eri1 + eri1.transpose(1, 0, 2, 3) eri1 = eri1 + eri1.transpose(0, 1, 3, 2) eri1 = eri1 + eri1.transpose(2, 3, 0, 1) eri1 *= .1 eris.ovvv = eri1[:nocc, nocc:, nocc:, nocc:] eris.ovoo = eri1[:nocc, nocc:, :nocc, :nocc] eris.ovov = eri1[:nocc, nocc:, :nocc, nocc:] t1 = (numpy.random.random((nocc, nvir)) * .1 + numpy.random.random( (nocc, nvir)) * .1j) t2 = (numpy.random.random( (nocc, nocc, nvir, nvir)) * .1 + numpy.random.random( (nocc, nocc, nvir, nvir)) * .1j) t2 = t2 + t2.transpose(1, 0, 3, 2) mf = scf.RHF(mol) mcc = cc.CCSD(mf) f = (numpy.random.random((nmo, nmo)) * .1 + numpy.random.random( (nmo, nmo)) * .1j) eris.fock = f + f.T.conj() + numpy.diag(numpy.arange(nmo)) eris.mo_energy = eris.fock.diagonal().real e0 = ccsd_t.kernel(mcc, eris, t1, t2) eri2 = numpy.zeros((nmo * 2, nmo * 2, nmo * 2, nmo * 2), dtype=numpy.complex128) orbspin = numpy.zeros(nmo * 2, dtype=int) orbspin[1::2] = 1 eri2[0::2, 0::2, 0::2, 0::2] = eri1 eri2[1::2, 1::2, 0::2, 0::2] = eri1 eri2[0::2, 0::2, 1::2, 1::2] = eri1 eri2[1::2, 1::2, 1::2, 1::2] = eri1 eri2 = eri2.transpose(0, 2, 1, 3) - eri2.transpose(0, 2, 3, 1) fock = numpy.zeros((nmo * 2, nmo * 2), dtype=numpy.complex128) fock[0::2, 0::2] = eris.fock fock[1::2, 1::2] = eris.fock eris1 = gccsd._PhysicistsERIs() eris1.ovvv = eri2[:nocc * 2, nocc * 2:, nocc * 2:, nocc * 2:] eris1.oovv = eri2[:nocc * 2, :nocc * 2, nocc * 2:, nocc * 2:] eris1.ooov = eri2[:nocc * 2, :nocc * 2, :nocc * 2, nocc * 2:] eris1.fock = fock eris1.mo_energy = fock.diagonal().real t1 = gccsd.spatial2spin(t1, orbspin) t2 = gccsd.spatial2spin(t2, orbspin) gcc = gccsd.GCCSD(scf.GHF(gto.M())) e1 = gccsd_t.kernel(gcc, eris1, t1, t2) self.assertAlmostEqual(e0, e1.real, 9) self.assertAlmostEqual(e1, -0.98756910139720788 - 0.0019567929592079489j, 9)
def test_ccsd_t_complex(self): mol = gto.M() numpy.random.seed(12) nocc, nvir = 3, 4 nmo = nocc + nvir eris = cc.rccsd._ChemistsERIs() eri1 = (numpy.random.random((nmo,nmo,nmo,nmo)) + numpy.random.random((nmo,nmo,nmo,nmo)) * .8j - .5-.4j) eri1 = eri1 + eri1.transpose(1,0,2,3) eri1 = eri1 + eri1.transpose(0,1,3,2) eri1 = eri1 + eri1.transpose(2,3,0,1) eri1 *= .1 eris.ovvv = eri1[:nocc,nocc:,nocc:,nocc:] eris.ovoo = eri1[:nocc,nocc:,:nocc,:nocc] eris.ovov = eri1[:nocc,nocc:,:nocc,nocc:] t1 = (numpy.random.random((nocc,nvir)) * .1 + numpy.random.random((nocc,nvir)) * .1j) t2 = (numpy.random.random((nocc,nocc,nvir,nvir)) * .1 + numpy.random.random((nocc,nocc,nvir,nvir)) * .1j) t2 = t2 + t2.transpose(1,0,3,2) mf = scf.RHF(mol) mcc = cc.CCSD(mf) f = (numpy.random.random((nmo,nmo)) * .1 + numpy.random.random((nmo,nmo)) * .1j) eris.fock = f+f.T.conj() + numpy.diag(numpy.arange(nmo)) eris.mo_energy = eris.fock.diagonal().real e0 = ccsd_t.kernel(mcc, eris, t1, t2) eri2 = numpy.zeros((nmo*2,nmo*2,nmo*2,nmo*2), dtype=numpy.complex) orbspin = numpy.zeros(nmo*2,dtype=int) orbspin[1::2] = 1 eri2[0::2,0::2,0::2,0::2] = eri1 eri2[1::2,1::2,0::2,0::2] = eri1 eri2[0::2,0::2,1::2,1::2] = eri1 eri2[1::2,1::2,1::2,1::2] = eri1 eri2 = eri2.transpose(0,2,1,3) - eri2.transpose(0,2,3,1) fock = numpy.zeros((nmo*2,nmo*2), dtype=numpy.complex) fock[0::2,0::2] = eris.fock fock[1::2,1::2] = eris.fock eris1 = gccsd._PhysicistsERIs() eris1.ovvv = eri2[:nocc*2,nocc*2:,nocc*2:,nocc*2:] eris1.oovv = eri2[:nocc*2,:nocc*2,nocc*2:,nocc*2:] eris1.ooov = eri2[:nocc*2,:nocc*2,:nocc*2,nocc*2:] eris1.fock = fock eris1.mo_energy = fock.diagonal().real t1 = gccsd.spatial2spin(t1, orbspin) t2 = gccsd.spatial2spin(t2, orbspin) gcc = gccsd.GCCSD(scf.GHF(gto.M())) e1 = gccsd_t.kernel(gcc, eris1, t1, t2) self.assertAlmostEqual(e0, e1.real, 9) self.assertAlmostEqual(e1, -0.98756910139720788-0.0019567929592079489j, 9)
t2 = np.random.random((nocc, nocc, nvir, nvir)) - .5 t2 = t2 + np.sin(t2) * .1j t2 = t2 + t2.transpose(1, 0, 3, 2) mycc = RCCSD(mf) t1new_ref, t2new_ref = update_amps(mycc, t1, t2, eris) orbspin = np.zeros(nao * 2, dtype=int) orbspin[1::2] = 1 eri1 = np.zeros([nao * 2] * 4, dtype=np.complex) eri1[0::2,0::2,0::2,0::2] = \ eri1[0::2,0::2,1::2,1::2] = \ eri1[1::2,1::2,0::2,0::2] = \ eri1[1::2,1::2,1::2,1::2] = eri0 eri1 = eri1.transpose(0, 2, 1, 3) - eri1.transpose(0, 2, 3, 1) erig = gccsd._PhysicistsERIs(mol) nocc *= 2 nvir *= 2 erig.oooo = eri1[:nocc, :nocc, :nocc, :nocc].copy() erig.ooov = eri1[:nocc, :nocc, :nocc, nocc:].copy() erig.ovov = eri1[:nocc, nocc:, :nocc, nocc:].copy() erig.ovvo = eri1[:nocc, nocc:, nocc:, :nocc].copy() erig.oovv = eri1[:nocc, :nocc, nocc:, nocc:].copy() erig.ovvv = eri1[:nocc, nocc:, nocc:, nocc:].copy() erig.vvvv = eri1[nocc:, nocc:, nocc:, nocc:].copy() mo_e = np.array([mf.mo_energy] * 2) erig.fock = np.diag(mo_e.T.ravel()) myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1, t2 = myccg.amplitudes_from_ccsd(t1, t2) t1new, t2new = gccsd.update_amps(myccg, t1, t2, erig)
def test_update_amps2(self): # compare to gccsd.update_amps mol = mol_s2 mf = mf_s2 myucc = uccsd.UCCSD(mf) nocca, noccb = 6, 4 nmo = mol.nao_nr() nvira, nvirb = nmo - nocca, nmo - noccb numpy.random.seed(9) t1 = [ numpy.random.random((nocca, nvira)) - .9, numpy.random.random((noccb, nvirb)) - .9 ] t2 = [ numpy.random.random((nocca, nocca, nvira, nvira)) - .9, numpy.random.random((nocca, noccb, nvira, nvirb)) - .9, numpy.random.random((noccb, noccb, nvirb, nvirb)) - .9 ] t2[0] = t2[0] - t2[0].transpose(1, 0, 2, 3) t2[0] = t2[0] - t2[0].transpose(0, 1, 3, 2) t2[2] = t2[2] - t2[2].transpose(1, 0, 2, 3) t2[2] = t2[2] - t2[2].transpose(0, 1, 3, 2) mo_a = mf.mo_coeff[0] + numpy.sin(mf.mo_coeff[0]) * .01j mo_b = mf.mo_coeff[1] + numpy.sin(mf.mo_coeff[1]) * .01j nao = mo_a.shape[0] eri = ao2mo.restore(1, mf._eri, nao) eri0aa = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_a.conj(), mo_a) eri0ab = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_b.conj(), mo_b) eri0bb = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_b.conj(), mo_b, mo_b.conj(), mo_b) eri0ba = eri0ab.transpose(2, 3, 0, 1) nvira = nao - nocca nvirb = nao - noccb eris = uccsd._ChemistsERIs(mol) eris.oooo = eri0aa[:nocca, :nocca, :nocca, :nocca].copy() eris.ovoo = eri0aa[:nocca, nocca:, :nocca, :nocca].copy() eris.oovv = eri0aa[:nocca, :nocca, nocca:, nocca:].copy() eris.ovvo = eri0aa[:nocca, nocca:, nocca:, :nocca].copy() eris.ovov = eri0aa[:nocca, nocca:, :nocca, nocca:].copy() eris.ovvv = eri0aa[:nocca, nocca:, nocca:, nocca:].copy() eris.vvvv = eri0aa[nocca:, nocca:, nocca:, nocca:].copy() eris.OOOO = eri0bb[:noccb, :noccb, :noccb, :noccb].copy() eris.OVOO = eri0bb[:noccb, noccb:, :noccb, :noccb].copy() eris.OOVV = eri0bb[:noccb, :noccb, noccb:, noccb:].copy() eris.OVVO = eri0bb[:noccb, noccb:, noccb:, :noccb].copy() eris.OVOV = eri0bb[:noccb, noccb:, :noccb, noccb:].copy() eris.OVVV = eri0bb[:noccb, noccb:, noccb:, noccb:].copy() eris.VVVV = eri0bb[noccb:, noccb:, noccb:, noccb:].copy() eris.ooOO = eri0ab[:nocca, :nocca, :noccb, :noccb].copy() eris.ovOO = eri0ab[:nocca, nocca:, :noccb, :noccb].copy() eris.ooVV = eri0ab[:nocca, :nocca, noccb:, noccb:].copy() eris.ovVO = eri0ab[:nocca, nocca:, noccb:, :noccb].copy() eris.ovOV = eri0ab[:nocca, nocca:, :noccb, noccb:].copy() eris.ovVV = eri0ab[:nocca, nocca:, noccb:, noccb:].copy() eris.vvVV = eri0ab[nocca:, nocca:, noccb:, noccb:].copy() eris.OOoo = eri0ba[:noccb, :noccb, :nocca, :nocca].copy() eris.OVoo = eri0ba[:noccb, noccb:, :nocca, :nocca].copy() eris.OOvv = eri0ba[:noccb, :noccb, nocca:, nocca:].copy() eris.OVvo = eri0ba[:noccb, noccb:, nocca:, :nocca].copy() eris.OVov = eri0ba[:noccb, noccb:, :nocca, nocca:].copy() eris.OVvv = eri0ba[:noccb, noccb:, nocca:, nocca:].copy() eris.VVvv = eri0ba[noccb:, noccb:, nocca:, nocca:].copy() eris.focka = numpy.diag(mf.mo_energy[0]) eris.fockb = numpy.diag(mf.mo_energy[1]) eris.mo_energy = mf.mo_energy t1[0] = t1[0] + numpy.sin(t1[0]) * .05j t1[1] = t1[1] + numpy.sin(t1[1]) * .05j t2[0] = t2[0] + numpy.sin(t2[0]) * .05j t2[1] = t2[1] + numpy.sin(t2[1]) * .05j t2[2] = t2[2] + numpy.sin(t2[2]) * .05j t1new_ref, t2new_ref = uccsd.update_amps(myucc, t1, t2, eris) nocc = nocca + noccb orbspin = numpy.zeros(nao * 2, dtype=int) orbspin[1::2] = 1 orbspin[nocc - 1] = 0 orbspin[nocc] = 1 eri1 = numpy.zeros([nao * 2] * 4, dtype=numpy.complex) idxa = numpy.where(orbspin == 0)[0] idxb = numpy.where(orbspin == 1)[0] eri1[idxa[:, None, None, None], idxa[:, None, None], idxa[:, None], idxa] = eri0aa eri1[idxa[:, None, None, None], idxa[:, None, None], idxb[:, None], idxb] = eri0ab eri1[idxb[:, None, None, None], idxb[:, None, None], idxa[:, None], idxa] = eri0ba eri1[idxb[:, None, None, None], idxb[:, None, None], idxb[:, None], idxb] = eri0bb eri1 = eri1.transpose(0, 2, 1, 3) - eri1.transpose(0, 2, 3, 1) erig = gccsd._PhysicistsERIs() erig.oooo = eri1[:nocc, :nocc, :nocc, :nocc].copy() erig.ooov = eri1[:nocc, :nocc, :nocc, nocc:].copy() erig.ovov = eri1[:nocc, nocc:, :nocc, nocc:].copy() erig.ovvo = eri1[:nocc, nocc:, nocc:, :nocc].copy() erig.oovv = eri1[:nocc, :nocc, nocc:, nocc:].copy() erig.ovvv = eri1[:nocc, nocc:, nocc:, nocc:].copy() erig.vvvv = eri1[nocc:, nocc:, nocc:, nocc:].copy() mo_e = numpy.empty(nao * 2) mo_e[orbspin == 0] = mf.mo_energy[0] mo_e[orbspin == 1] = mf.mo_energy[1] erig.fock = numpy.diag(mo_e) erig.mo_energy = mo_e.real myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1 = myccg.spatial2spin(t1, orbspin) t2 = myccg.spatial2spin(t2, orbspin) t1new, t2new = gccsd.update_amps(myccg, t1, t2, erig) t1new = myccg.spin2spatial(t1new, orbspin) t2new = myccg.spin2spatial(t2new, orbspin) self.assertAlmostEqual(abs(t1new[0] - t1new_ref[0]).max(), 0, 12) self.assertAlmostEqual(abs(t1new[1] - t1new_ref[1]).max(), 0, 12) self.assertAlmostEqual(abs(t2new[0] - t2new_ref[0]).max(), 0, 12) self.assertAlmostEqual(abs(t2new[1] - t2new_ref[1]).max(), 0, 12) self.assertAlmostEqual(abs(t2new[2] - t2new_ref[2]).max(), 0, 12)
def test_update_lambda_complex(self): mo_coeff = mf.mo_coeff + np.sin(mf.mo_coeff) * .01j nao = mo_coeff.shape[0] eri = ao2mo.restore(1, mf._eri, nao) eri0 = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_coeff.conj(), mo_coeff, mo_coeff.conj(), mo_coeff) nocc, nvir = 5, nao - 5 eris = rccsd._ChemistsERIs(mol) eris.oooo = eri0[:nocc, :nocc, :nocc, :nocc].copy() eris.ovoo = eri0[:nocc, nocc:, :nocc, :nocc].copy() eris.oovv = eri0[:nocc, :nocc, nocc:, nocc:].copy() eris.ovvo = eri0[:nocc, nocc:, nocc:, :nocc].copy() eris.ovov = eri0[:nocc, nocc:, :nocc, nocc:].copy() eris.ovvv = eri0[:nocc, nocc:, nocc:, nocc:].copy() eris.vvvv = eri0[nocc:, nocc:, nocc:, nocc:].copy() eris.fock = np.diag(mf.mo_energy) np.random.seed(1) t1 = np.random.random((nocc, nvir)) + np.random.random( (nocc, nvir)) * .1j - .5 t2 = np.random.random((nocc, nocc, nvir, nvir)) - .5 t2 = t2 + np.sin(t2) * .1j t2 = t2 + t2.transpose(1, 0, 3, 2) l1 = np.random.random((nocc, nvir)) + np.random.random( (nocc, nvir)) * .1j - .5 l2 = np.random.random((nocc, nocc, nvir, nvir)) - .5 l2 = l2 + np.sin(l2) * .1j l2 = l2 + l2.transpose(1, 0, 3, 2) mycc = rccsd.RCCSD(mf) imds = rccsd_lambda.make_intermediates(mycc, t1, t2, eris) l1new_ref, l2new_ref = rccsd_lambda.update_lambda( mycc, t1, t2, l1, l2, eris, imds) orbspin = np.zeros(nao * 2, dtype=int) orbspin[1::2] = 1 eri1 = np.zeros([nao * 2] * 4, dtype=np.complex128) eri1[0::2,0::2,0::2,0::2] = \ eri1[0::2,0::2,1::2,1::2] = \ eri1[1::2,1::2,0::2,0::2] = \ eri1[1::2,1::2,1::2,1::2] = eri0 eri1 = eri1.transpose(0, 2, 1, 3) - eri1.transpose(0, 2, 3, 1) erig = gccsd._PhysicistsERIs(mol) nocc *= 2 nvir *= 2 erig.oooo = eri1[:nocc, :nocc, :nocc, :nocc].copy() erig.ooov = eri1[:nocc, :nocc, :nocc, nocc:].copy() erig.ovov = eri1[:nocc, nocc:, :nocc, nocc:].copy() erig.ovvo = eri1[:nocc, nocc:, nocc:, :nocc].copy() erig.oovv = eri1[:nocc, :nocc, nocc:, nocc:].copy() erig.ovvv = eri1[:nocc, nocc:, nocc:, nocc:].copy() erig.vvvv = eri1[nocc:, nocc:, nocc:, nocc:].copy() mo_e = np.array([mf.mo_energy] * 2) erig.fock = np.diag(mo_e.T.ravel()) erig.mo_energy = erig.fock.diagonal() myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1, t2 = myccg.amplitudes_from_ccsd(t1, t2) l1, l2 = myccg.amplitudes_from_ccsd(l1, l2) imds = gccsd_lambda.make_intermediates(myccg, t1, t2, erig) l1new, l2new = gccsd_lambda.update_lambda(myccg, t1, t2, l1, l2, erig, imds) self.assertAlmostEqual(float(abs(l1new[0::2, 0::2] - l1new_ref).max()), 0, 9) l2aa = l2new[0::2, 0::2, 0::2, 0::2] l2ab = l2new[0::2, 1::2, 0::2, 1::2] self.assertAlmostEqual(float(abs(l2ab - l2new_ref).max()), 0, 9) self.assertAlmostEqual( float(abs(l2ab - l2ab.transpose(1, 0, 2, 3) - l2aa).max()), 0, 9)
def _make_eris_incore_ghf(mycc, mo_coeff=None, ao2mofn=None): """ Make physist eri with incore ao2mo, for GGHF. """ cput0 = (logger.process_clock(), logger.perf_counter()) log = logger.Logger(mycc.stdout, mycc.verbose) _sync_(mycc) eris = gccsd._PhysicistsERIs() if rank == 0: eris._common_init_(mycc, mo_coeff) comm.bcast((eris.mo_coeff, eris.fock, eris.nocc, eris.mo_energy)) else: eris.mol = mycc.mol eris.mo_coeff, eris.fock, eris.nocc, eris.mo_energy = comm.bcast(None) nocc = eris.nocc nao, nmo = eris.mo_coeff.shape nvir = nmo - nocc vlocs = [_task_location(nvir, task_id) for task_id in range(mpi.pool.size)] vloc0, vloc1 = vlocs[rank] vseg = vloc1 - vloc0 if rank == 0: if callable(ao2mofn): raise NotImplementedError else: assert eris.mo_coeff.dtype == np.double eri = mycc._scf._eri if (nao == nmo) and (la.norm(eris.mo_coeff - np.eye(nmo)) < 1e-12): # ZHC NOTE special treatment for OO-CCD, # where the ao2mo is not needed for identity mo_coeff. from libdmet.utils import take_eri as fn o = np.arange(0, nocc) v = np.arange(nocc, nmo) if eri.size == nmo**4: eri = ao2mo.restore(8, eri, nmo) else: if mycc.save_mem: # ZHC NOTE the following is slower, although may save some memory. def fn(x, mo0, mo1, mo2, mo3): return ao2mo.general(x, (mo0, mo1, mo2, mo3), compact=False).reshape(mo0.shape[-1], mo1.shape[-1], mo2.shape[-1], mo3.shape[-1]) o = eris.mo_coeff[:, :nocc] v = eris.mo_coeff[:, nocc:] if eri.size == nao**4: eri = ao2mo.restore(8, eri, nao) else: from libdmet.utils import take_eri as fn o = np.arange(0, nocc) v = np.arange(nocc, nmo) if mycc.remove_h2: mycc._scf._eri = None _release_regs(mycc, remove_h2=True) eri = ao2mo.kernel(eri, eris.mo_coeff) if eri.size == nmo**4: eri = ao2mo.restore(8, eri, nmo) comm.Barrier() cput2 = log.timer('CCSD ao2mo initialization: ', *cput0) # chunck and scatter: # 1. oooo if rank == 0: tmp = fn(eri, o, o, o, o) eris.oooo = tmp.transpose(0, 2, 1, 3) - tmp.transpose(0, 2, 3, 1) tmp = None mpi.bcast(eris.oooo) else: eris.oooo = mpi.bcast(None) cput3 = log.timer('CCSD bcast oooo: ', *cput2) # 2. xooo if rank == 0: tmp = fn(eri, v, o, o, o) eri_sliced = [tmp[p0:p1] for (p0, p1) in vlocs] else: tmp = None eri_sliced = None tmp = mpi.scatter_new(eri_sliced, root=0, data=tmp) eri_sliced = None eris.xooo = tmp.transpose(0, 2, 1, 3) - tmp.transpose(0, 2, 3, 1) tmp = None cput4 = log.timer('CCSD scatter xooo: ', *cput3) # 3. xovo if rank == 0: tmp_vvoo = fn(eri, v, v, o, o) tmp_voov = fn(eri, v, o, o, v) # ZHC NOTE need to keep tmp_voov for xvoo eri_1 = [tmp_vvoo[p0:p1] for (p0, p1) in vlocs] eri_2 = [tmp_voov[p0:p1] for (p0, p1) in vlocs] else: tmp_vvoo = None tmp_voov = None eri_1 = None eri_2 = None tmp_1 = mpi.scatter_new(eri_1, root=0, data=tmp_vvoo) eri_1 = None tmp_vvoo = None tmp_2 = mpi.scatter_new(eri_2, root=0, data=tmp_voov) eri_2 = None tmp_voov = None eris.xovo = tmp_1.transpose(0, 2, 1, 3) - tmp_2.transpose(0, 2, 3, 1) tmp_1 = None cput5 = log.timer('CCSD scatter xovo: ', *cput4) # 4. xvoo eris.xvoo = tmp_2.transpose(0, 3, 1, 2) - tmp_2.transpose(0, 3, 2, 1) tmp_2 = None cput6 = log.timer('CCSD scatter xvoo: ', *cput5) # 5. 6. xovv, xvvo if rank == 0: tmp = fn(eri, v, v, o, v) eri_sliced = [tmp[p0:p1] for (p0, p1) in vlocs] else: tmp = None eri_sliced = None tmp_1 = mpi.scatter_new(eri_sliced, root=0, data=tmp) eri_sliced = None eris.xovv = tmp_1.transpose(0, 2, 1, 3) - tmp_1.transpose(0, 2, 3, 1) if rank == 0: tmp_2 = np.asarray(tmp.transpose(3, 2, 1, 0), order='C') # vovv tmp = None eri_sliced = [tmp_2[p0:p1] for (p0, p1) in vlocs] else: tmp_2 = None tmp = None eri_sliced = None tmp_2 = mpi.scatter_new(eri_sliced, root=0, data=tmp_2) eri_sliced = None eris.xvvo = tmp_1.transpose(0, 3, 1, 2) - tmp_2.transpose(0, 2, 3, 1) tmp_1 = None tmp_2 = None cput7 = log.timer('CCSD scatter xovv, xvvo: ', *cput6) # 7. xvvv if rank == 0: tmp = fn(eri, v, v, v, v) if mycc.remove_h2: eri = None if mycc._scf is not None: mycc._scf._eri = None eri_sliced = [tmp[p0:p1] for (p0, p1) in vlocs] else: tmp = None eri_sliced = None tmp = mpi.scatter_new(eri_sliced, root=0, data=tmp) eri_sliced = None eris.xvvv = tmp.transpose(0, 2, 1, 3) - tmp.transpose(0, 2, 3, 1) tmp = None eri = None cput8 = log.timer('CCSD scatter xvvv: ', *cput7) mycc._eris = eris log.timer('CCSD integral transformation ', *cput0) return eris
def _make_eris_incore(mycc, mo_coeff=None, ao2mofn=None): """ Make physist eri with incore ao2mo. """ cput0 = (logger.process_clock(), logger.perf_counter()) log = logger.Logger(mycc.stdout, mycc.verbose) _sync_(mycc) eris = gccsd._PhysicistsERIs() if rank == 0: eris._common_init_(mycc, mo_coeff) comm.bcast((eris.mo_coeff, eris.fock, eris.nocc, eris.mo_energy)) else: eris.mol = mycc.mol eris.mo_coeff, eris.fock, eris.nocc, eris.mo_energy = comm.bcast(None) # if workers does not have _eri, bcast from root if comm.allreduce(mycc._scf._eri is None, op=mpi.MPI.LOR): if rank == 0: mpi.bcast(mycc._scf._eri) else: mycc._scf._eri = mpi.bcast(None) cput1 = log.timer('CCSD ao2mo initialization: ', *cput0) nocc = eris.nocc nao, nmo = eris.mo_coeff.shape nvir = nmo - nocc vlocs = [_task_location(nvir, task_id) for task_id in range(mpi.pool.size)] vloc0, vloc1 = vlocs[rank] vseg = vloc1 - vloc0 plocs = [_task_location(nmo, task_id) for task_id in range(mpi.pool.size)] ploc0, ploc1 = plocs[rank] pseg = ploc1 - ploc0 mo_a = eris.mo_coeff[:nao//2] mo_b = eris.mo_coeff[nao//2:] mo_seg_a = mo_a[:, ploc0:ploc1] mo_seg_b = mo_b[:, ploc0:ploc1] fname = "gccsd_eri_tmp_%s.h5"%rank f = h5py.File(fname, 'w') eri_phys = f.create_dataset('eri_phys', (pseg, nmo, nmo, nmo), 'f8', chunks=(pseg, 1, nmo, nmo)) eri_a = ao2mo.incore.half_e1(mycc._scf._eri, (mo_seg_a, mo_a), compact=False) eri_b = ao2mo.incore.half_e1(mycc._scf._eri, (mo_seg_b, mo_b), compact=False) cput1 = log.timer('CCSD ao2mo half_e1: ', *cput1) unit = pseg * nmo * nmo * 2 mem_now = lib.current_memory()[0] max_memory = max(0, mycc.max_memory - mem_now) blksize = min(nmo, max(BLKMIN, int((max_memory*0.9e6/8)/unit))) for p0, p1 in lib.prange(0, nmo, blksize): klmosym_a, nkl_pair_a, mokl_a, klshape_a = \ ao2mo.incore._conc_mos(mo_a[:, p0:p1], mo_a, compact=False) klmosym_b, nkl_pair_b, mokl_b, klshape_b = \ ao2mo.incore._conc_mos(mo_b[:, p0:p1], mo_b, compact=False) eri = _ao2mo.nr_e2(eri_a, mokl_a, klshape_a, aosym='s4', mosym=klmosym_a) eri += _ao2mo.nr_e2(eri_a, mokl_b, klshape_b, aosym='s4', mosym=klmosym_b) eri += _ao2mo.nr_e2(eri_b, mokl_a, klshape_a, aosym='s4', mosym=klmosym_a) eri += _ao2mo.nr_e2(eri_b, mokl_b, klshape_b, aosym='s4', mosym=klmosym_b) eri = eri.reshape(pseg, nmo, p1-p0, nmo) eri_phys[:, p0:p1] = eri.transpose(0, 2, 1, 3) - eri.transpose(0, 2, 3, 1) eri = None eri_a = None eri_b = None f.close() comm.Barrier() cput1 = log.timer('CCSD ao2mo nr_e2: ', *cput1) o_idx = -1 v_idx = mpi.pool.size for r, (p0, p1) in enumerate(plocs): if p0 <= nocc - 1 < p1: o_idx = r if p0 <= nocc < p1: v_idx = r break o_files = np.arange(mpi.pool.size)[:(o_idx+1)] v_files = np.arange(mpi.pool.size)[v_idx:] eris.oooo = np.empty((nocc, nocc, nocc, nocc)) eris.xooo = np.empty((vseg, nocc, nocc, nocc)) eris.xovo = np.empty((vseg, nocc, nvir, nocc)) eris.xovv = np.empty((vseg, nocc, nvir, nvir)) eris.xvvo = np.empty((vseg, nvir, nvir, nocc)) eris.xvoo = np.empty((vseg, nvir, nocc, nocc)) eris.xvvv = np.empty((vseg, nvir, nvir, nvir)) for r in range(mpi.pool.size): f = lib.H5TmpFile(filename="gccsd_eri_tmp_%s.h5"%r, mode='r') eri_phys = f["eri_phys"] if r in o_files: p0, p1 = plocs[r] p1 = min(p1, nocc) pseg = p1 - p0 if pseg > 0: eris.oooo[p0:p1] = eri_phys[:pseg, :nocc, :nocc, :nocc] if r in v_files: p00, p10 = plocs[r] p0 = max(p00, nocc+vloc0) p1 = min(p10, nocc+vloc1) pseg = p1 - p0 if pseg > 0: eris.xooo[p0-(nocc+vloc0):p1-(nocc+vloc0)] = eri_phys[p0-p00:p1-p00, :nocc, :nocc, :nocc] eris.xovo[p0-(nocc+vloc0):p1-(nocc+vloc0)] = eri_phys[p0-p00:p1-p00, :nocc, nocc:, :nocc] eris.xvoo[p0-(nocc+vloc0):p1-(nocc+vloc0)] = eri_phys[p0-p00:p1-p00, nocc:, :nocc, :nocc] eris.xvvo[p0-(nocc+vloc0):p1-(nocc+vloc0)] = eri_phys[p0-p00:p1-p00, nocc:, nocc:, :nocc] eris.xovv[p0-(nocc+vloc0):p1-(nocc+vloc0)] = eri_phys[p0-p00:p1-p00, :nocc, nocc:, nocc:] eris.xvvv[p0-(nocc+vloc0):p1-(nocc+vloc0)] = eri_phys[p0-p00:p1-p00, nocc:, nocc:, nocc:] cput1 = log.timer('CCSD ao2mo load: ', *cput1) f.close() comm.Barrier() os.remove("gccsd_eri_tmp_%s.h5"%rank) mycc._eris = eris log.timer('CCSD integral transformation ', *cput0) return eris
t2 = np.random.random((nocc,nocc,nvir,nvir)) - .5 t2 = t2 + np.sin(t2) * .1j t2 = t2 + t2.transpose(1,0,3,2) mycc = RCCSD(mf) t1new_ref, t2new_ref = update_amps(mycc, t1, t2, eris) orbspin = np.zeros(nao*2, dtype=int) orbspin[1::2] = 1 eri1 = np.zeros([nao*2]*4, dtype=np.complex) eri1[0::2,0::2,0::2,0::2] = \ eri1[0::2,0::2,1::2,1::2] = \ eri1[1::2,1::2,0::2,0::2] = \ eri1[1::2,1::2,1::2,1::2] = eri0 eri1 = eri1.transpose(0,2,1,3) - eri1.transpose(0,2,3,1) erig = gccsd._PhysicistsERIs(mol) nocc *= 2 nvir *= 2 erig.oooo = eri1[:nocc,:nocc,:nocc,:nocc].copy() erig.ooov = eri1[:nocc,:nocc,:nocc,nocc:].copy() erig.ovov = eri1[:nocc,nocc:,:nocc,nocc:].copy() erig.ovvo = eri1[:nocc,nocc:,nocc:,:nocc].copy() erig.oovv = eri1[:nocc,:nocc,nocc:,nocc:].copy() erig.ovvv = eri1[:nocc,nocc:,nocc:,nocc:].copy() erig.vvvv = eri1[nocc:,nocc:,nocc:,nocc:].copy() mo_e = np.array([mf.mo_energy]*2) erig.fock = np.diag(mo_e.T.ravel()) myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1, t2 = myccg.amplitudes_from_ccsd(t1, t2) t1new, t2new = gccsd.update_amps(myccg, t1, t2, erig)
def test_update_amps2(self): # compare to gccsd.update_amps mol = mol_s2 mf = mf_s2 myucc = uccsd.UCCSD(mf) nocca, noccb = 6,4 nmo = mol.nao_nr() nvira,nvirb = nmo-nocca, nmo-noccb numpy.random.seed(9) t1 = [numpy.random.random((nocca,nvira))-.9, numpy.random.random((noccb,nvirb))-.9] t2 = [numpy.random.random((nocca,nocca,nvira,nvira))-.9, numpy.random.random((nocca,noccb,nvira,nvirb))-.9, numpy.random.random((noccb,noccb,nvirb,nvirb))-.9] t2[0] = t2[0] - t2[0].transpose(1,0,2,3) t2[0] = t2[0] - t2[0].transpose(0,1,3,2) t2[2] = t2[2] - t2[2].transpose(1,0,2,3) t2[2] = t2[2] - t2[2].transpose(0,1,3,2) mo_a = mf.mo_coeff[0] + numpy.sin(mf.mo_coeff[0]) * .01j mo_b = mf.mo_coeff[1] + numpy.sin(mf.mo_coeff[1]) * .01j nao = mo_a.shape[0] eri = ao2mo.restore(1, mf._eri, nao) eri0aa = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_a.conj(), mo_a) eri0ab = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_b.conj(), mo_b) eri0bb = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_b.conj(), mo_b, mo_b.conj(), mo_b) eri0ba = eri0ab.transpose(2,3,0,1) nvira = nao - nocca nvirb = nao - noccb eris = uccsd._ChemistsERIs(mol) eris.oooo = eri0aa[:nocca,:nocca,:nocca,:nocca].copy() eris.ovoo = eri0aa[:nocca,nocca:,:nocca,:nocca].copy() eris.oovv = eri0aa[:nocca,:nocca,nocca:,nocca:].copy() eris.ovvo = eri0aa[:nocca,nocca:,nocca:,:nocca].copy() eris.ovov = eri0aa[:nocca,nocca:,:nocca,nocca:].copy() eris.ovvv = eri0aa[:nocca,nocca:,nocca:,nocca:].copy() eris.vvvv = eri0aa[nocca:,nocca:,nocca:,nocca:].copy() eris.OOOO = eri0bb[:noccb,:noccb,:noccb,:noccb].copy() eris.OVOO = eri0bb[:noccb,noccb:,:noccb,:noccb].copy() eris.OOVV = eri0bb[:noccb,:noccb,noccb:,noccb:].copy() eris.OVVO = eri0bb[:noccb,noccb:,noccb:,:noccb].copy() eris.OVOV = eri0bb[:noccb,noccb:,:noccb,noccb:].copy() eris.OVVV = eri0bb[:noccb,noccb:,noccb:,noccb:].copy() eris.VVVV = eri0bb[noccb:,noccb:,noccb:,noccb:].copy() eris.ooOO = eri0ab[:nocca,:nocca,:noccb,:noccb].copy() eris.ovOO = eri0ab[:nocca,nocca:,:noccb,:noccb].copy() eris.ooVV = eri0ab[:nocca,:nocca,noccb:,noccb:].copy() eris.ovVO = eri0ab[:nocca,nocca:,noccb:,:noccb].copy() eris.ovOV = eri0ab[:nocca,nocca:,:noccb,noccb:].copy() eris.ovVV = eri0ab[:nocca,nocca:,noccb:,noccb:].copy() eris.vvVV = eri0ab[nocca:,nocca:,noccb:,noccb:].copy() eris.OOoo = eri0ba[:noccb,:noccb,:nocca,:nocca].copy() eris.OVoo = eri0ba[:noccb,noccb:,:nocca,:nocca].copy() eris.OOvv = eri0ba[:noccb,:noccb,nocca:,nocca:].copy() eris.OVvo = eri0ba[:noccb,noccb:,nocca:,:nocca].copy() eris.OVov = eri0ba[:noccb,noccb:,:nocca,nocca:].copy() eris.OVvv = eri0ba[:noccb,noccb:,nocca:,nocca:].copy() eris.VVvv = eri0ba[noccb:,noccb:,nocca:,nocca:].copy() eris.focka = numpy.diag(mf.mo_energy[0]) eris.fockb = numpy.diag(mf.mo_energy[1]) eris.mo_energy = mf.mo_energy t1[0] = t1[0] + numpy.sin(t1[0]) * .05j t1[1] = t1[1] + numpy.sin(t1[1]) * .05j t2[0] = t2[0] + numpy.sin(t2[0]) * .05j t2[1] = t2[1] + numpy.sin(t2[1]) * .05j t2[2] = t2[2] + numpy.sin(t2[2]) * .05j t1new_ref, t2new_ref = uccsd.update_amps(myucc, t1, t2, eris) nocc = nocca + noccb orbspin = numpy.zeros(nao*2, dtype=int) orbspin[1::2] = 1 orbspin[nocc-1] = 0 orbspin[nocc ] = 1 eri1 = numpy.zeros([nao*2]*4, dtype=numpy.complex) idxa = numpy.where(orbspin == 0)[0] idxb = numpy.where(orbspin == 1)[0] eri1[idxa[:,None,None,None],idxa[:,None,None],idxa[:,None],idxa] = eri0aa eri1[idxa[:,None,None,None],idxa[:,None,None],idxb[:,None],idxb] = eri0ab eri1[idxb[:,None,None,None],idxb[:,None,None],idxa[:,None],idxa] = eri0ba eri1[idxb[:,None,None,None],idxb[:,None,None],idxb[:,None],idxb] = eri0bb eri1 = eri1.transpose(0,2,1,3) - eri1.transpose(0,2,3,1) erig = gccsd._PhysicistsERIs() erig.oooo = eri1[:nocc,:nocc,:nocc,:nocc].copy() erig.ooov = eri1[:nocc,:nocc,:nocc,nocc:].copy() erig.ovov = eri1[:nocc,nocc:,:nocc,nocc:].copy() erig.ovvo = eri1[:nocc,nocc:,nocc:,:nocc].copy() erig.oovv = eri1[:nocc,:nocc,nocc:,nocc:].copy() erig.ovvv = eri1[:nocc,nocc:,nocc:,nocc:].copy() erig.vvvv = eri1[nocc:,nocc:,nocc:,nocc:].copy() mo_e = numpy.empty(nao*2) mo_e[orbspin==0] = mf.mo_energy[0] mo_e[orbspin==1] = mf.mo_energy[1] erig.fock = numpy.diag(mo_e) erig.mo_energy = mo_e.real myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1 = myccg.spatial2spin(t1, orbspin) t2 = myccg.spatial2spin(t2, orbspin) t1new, t2new = gccsd.update_amps(myccg, t1, t2, erig) t1new = myccg.spin2spatial(t1new, orbspin) t2new = myccg.spin2spatial(t2new, orbspin) self.assertAlmostEqual(abs(t1new[0] - t1new_ref[0]).max(), 0, 12) self.assertAlmostEqual(abs(t1new[1] - t1new_ref[1]).max(), 0, 12) self.assertAlmostEqual(abs(t2new[0] - t2new_ref[0]).max(), 0, 12) self.assertAlmostEqual(abs(t2new[1] - t2new_ref[1]).max(), 0, 12) self.assertAlmostEqual(abs(t2new[2] - t2new_ref[2]).max(), 0, 12)
def test_update_lambda_complex(self): nocca, noccb = mol.nelec nmo = mol.nao_nr() nvira, nvirb = nmo - nocca, nmo - noccb numpy.random.seed(9) t1 = [ numpy.random.random((nocca, nvira)) - .9, numpy.random.random((noccb, nvirb)) - .9 ] l1 = [ numpy.random.random((nocca, nvira)) - .9, numpy.random.random((noccb, nvirb)) - .9 ] t2 = [ numpy.random.random((nocca, nocca, nvira, nvira)) - .9, numpy.random.random((nocca, noccb, nvira, nvirb)) - .9, numpy.random.random((noccb, noccb, nvirb, nvirb)) - .9 ] t2[0] = t2[0] - t2[0].transpose(1, 0, 2, 3) t2[0] = t2[0] - t2[0].transpose(0, 1, 3, 2) t2[2] = t2[2] - t2[2].transpose(1, 0, 2, 3) t2[2] = t2[2] - t2[2].transpose(0, 1, 3, 2) l2 = [ numpy.random.random((nocca, nocca, nvira, nvira)) - .9, numpy.random.random((nocca, noccb, nvira, nvirb)) - .9, numpy.random.random((noccb, noccb, nvirb, nvirb)) - .9 ] l2[0] = l2[0] - l2[0].transpose(1, 0, 2, 3) l2[0] = l2[0] - l2[0].transpose(0, 1, 3, 2) l2[2] = l2[2] - l2[2].transpose(1, 0, 2, 3) l2[2] = l2[2] - l2[2].transpose(0, 1, 3, 2) # eris = mycc.ao2mo() # imds = make_intermediates(mycc, t1, t2, eris) # l1new, l2new = update_lambda(mycc, t1, t2, l1, l2, eris, imds) # print(lib.finger(l1new[0]) --104.55975252585894) # print(lib.finger(l1new[1]) --241.12677819375281) # print(lib.finger(l2new[0]) --0.4957533529669417) # print(lib.finger(l2new[1]) - 15.46423057451851 ) # print(lib.finger(l2new[2]) - 5.8430776663704407) nocca, noccb = mol.nelec mo_a = mf.mo_coeff[0] + numpy.sin(mf.mo_coeff[0]) * .01j mo_b = mf.mo_coeff[1] + numpy.sin(mf.mo_coeff[1]) * .01j nao = mo_a.shape[0] eri = ao2mo.restore(1, mf._eri, nao) eri0aa = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_a.conj(), mo_a) eri0ab = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_b.conj(), mo_b) eri0bb = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_b.conj(), mo_b, mo_b.conj(), mo_b) eri0ba = eri0ab.transpose(2, 3, 0, 1) nvira = nao - nocca nvirb = nao - noccb eris = uccsd._ChemistsERIs(mol) eris.oooo = eri0aa[:nocca, :nocca, :nocca, :nocca].copy() eris.ovoo = eri0aa[:nocca, nocca:, :nocca, :nocca].copy() eris.oovv = eri0aa[:nocca, :nocca, nocca:, nocca:].copy() eris.ovvo = eri0aa[:nocca, nocca:, nocca:, :nocca].copy() eris.ovov = eri0aa[:nocca, nocca:, :nocca, nocca:].copy() eris.ovvv = eri0aa[:nocca, nocca:, nocca:, nocca:].copy() eris.vvvv = eri0aa[nocca:, nocca:, nocca:, nocca:].copy() eris.OOOO = eri0bb[:noccb, :noccb, :noccb, :noccb].copy() eris.OVOO = eri0bb[:noccb, noccb:, :noccb, :noccb].copy() eris.OOVV = eri0bb[:noccb, :noccb, noccb:, noccb:].copy() eris.OVVO = eri0bb[:noccb, noccb:, noccb:, :noccb].copy() eris.OVOV = eri0bb[:noccb, noccb:, :noccb, noccb:].copy() eris.OVVV = eri0bb[:noccb, noccb:, noccb:, noccb:].copy() eris.VVVV = eri0bb[noccb:, noccb:, noccb:, noccb:].copy() eris.ooOO = eri0ab[:nocca, :nocca, :noccb, :noccb].copy() eris.ovOO = eri0ab[:nocca, nocca:, :noccb, :noccb].copy() eris.ooVV = eri0ab[:nocca, :nocca, noccb:, noccb:].copy() eris.ovVO = eri0ab[:nocca, nocca:, noccb:, :noccb].copy() eris.ovOV = eri0ab[:nocca, nocca:, :noccb, noccb:].copy() eris.ovVV = eri0ab[:nocca, nocca:, noccb:, noccb:].copy() eris.vvVV = eri0ab[nocca:, nocca:, noccb:, noccb:].copy() eris.OOoo = eri0ba[:noccb, :noccb, :nocca, :nocca].copy() eris.OVoo = eri0ba[:noccb, noccb:, :nocca, :nocca].copy() eris.OOvv = eri0ba[:noccb, :noccb, nocca:, nocca:].copy() eris.OVvo = eri0ba[:noccb, noccb:, nocca:, :nocca].copy() eris.OVov = eri0ba[:noccb, noccb:, :nocca, nocca:].copy() eris.OVvv = eri0ba[:noccb, noccb:, nocca:, nocca:].copy() eris.VVvv = eri0ba[noccb:, noccb:, nocca:, nocca:].copy() eris.focka = numpy.diag(mf.mo_energy[0]) eris.fockb = numpy.diag(mf.mo_energy[1]) t1[0] = t1[0] + numpy.sin(t1[0]) * .05j t1[1] = t1[1] + numpy.sin(t1[1]) * .05j t2[0] = t2[0] + numpy.sin(t2[0]) * .05j t2[1] = t2[1] + numpy.sin(t2[1]) * .05j t2[2] = t2[2] + numpy.sin(t2[2]) * .05j l1[0] = l1[0] + numpy.sin(l1[0]) * .05j l1[1] = l1[1] + numpy.sin(l1[1]) * .05j l2[0] = l2[0] + numpy.sin(l2[0]) * .05j l2[1] = l2[1] + numpy.sin(l2[1]) * .05j l2[2] = l2[2] + numpy.sin(l2[2]) * .05j imds = uccsd_lambda.make_intermediates(mycc, t1, t2, eris) l1new_ref, l2new_ref = uccsd_lambda.update_lambda( mycc, t1, t2, l1, l2, eris, imds) nocc = nocca + noccb orbspin = numpy.zeros(nao * 2, dtype=int) orbspin[1::2] = 1 orbspin[nocc - 1] = 0 orbspin[nocc] = 1 eri1 = numpy.zeros([nao * 2] * 4, dtype=numpy.complex) idxa = numpy.where(orbspin == 0)[0] idxb = numpy.where(orbspin == 1)[0] eri1[idxa[:, None, None, None], idxa[:, None, None], idxa[:, None], idxa] = eri0aa eri1[idxa[:, None, None, None], idxa[:, None, None], idxb[:, None], idxb] = eri0ab eri1[idxb[:, None, None, None], idxb[:, None, None], idxa[:, None], idxa] = eri0ba eri1[idxb[:, None, None, None], idxb[:, None, None], idxb[:, None], idxb] = eri0bb eri1 = eri1.transpose(0, 2, 1, 3) - eri1.transpose(0, 2, 3, 1) erig = gccsd._PhysicistsERIs() erig.oooo = eri1[:nocc, :nocc, :nocc, :nocc].copy() erig.ooov = eri1[:nocc, :nocc, :nocc, nocc:].copy() erig.ovov = eri1[:nocc, nocc:, :nocc, nocc:].copy() erig.ovvo = eri1[:nocc, nocc:, nocc:, :nocc].copy() erig.oovv = eri1[:nocc, :nocc, nocc:, nocc:].copy() erig.ovvv = eri1[:nocc, nocc:, nocc:, nocc:].copy() erig.vvvv = eri1[nocc:, nocc:, nocc:, nocc:].copy() mo_e = numpy.empty(nao * 2) mo_e[orbspin == 0] = mf.mo_energy[0] mo_e[orbspin == 1] = mf.mo_energy[1] erig.fock = numpy.diag(mo_e) myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1 = myccg.spatial2spin(t1, orbspin) t2 = myccg.spatial2spin(t2, orbspin) l1 = myccg.spatial2spin(l1, orbspin) l2 = myccg.spatial2spin(l2, orbspin) imds = gccsd_lambda.make_intermediates(myccg, t1, t2, erig) l1new, l2new = gccsd_lambda.update_lambda(myccg, t1, t2, l1, l2, erig, imds) l1new = myccg.spin2spatial(l1new, orbspin) l2new = myccg.spin2spatial(l2new, orbspin) self.assertAlmostEqual(abs(l1new[0] - l1new_ref[0]).max(), 0, 11) self.assertAlmostEqual(abs(l1new[1] - l1new_ref[1]).max(), 0, 11) self.assertAlmostEqual(abs(l2new[0] - l2new_ref[0]).max(), 0, 11) self.assertAlmostEqual(abs(l2new[1] - l2new_ref[1]).max(), 0, 11) self.assertAlmostEqual(abs(l2new[2] - l2new_ref[2]).max(), 0, 11)
def _make_eris_incore(cc, mo_coeff=None): from pyscf.pbc import tools from pyscf.pbc.cc.ccsd import _adjust_occ log = logger.Logger(cc.stdout, cc.verbose) cput0 = (time.clock(), time.time()) eris = gccsd._PhysicistsERIs() cell = cc._scf.cell kpts = cc.kpts nkpts = cc.nkpts nocc = cc.nocc nmo = cc.nmo nvir = nmo - nocc eris.nocc = nocc #if any(nocc != numpy.count_nonzero(cc._scf.mo_occ[k] > 0) for k in range(nkpts)): # raise NotImplementedError('Different occupancies found for different k-points') if mo_coeff is None: mo_coeff = cc.mo_coeff nao = mo_coeff[0].shape[0] dtype = mo_coeff[0].dtype moidx = get_frozen_mask(cc) nocc_per_kpt = numpy.asarray(get_nocc(cc, per_kpoint=True)) nmo_per_kpt = numpy.asarray(get_nmo(cc, per_kpoint=True)) padded_moidx = [] for k in range(nkpts): kpt_nocc = nocc_per_kpt[k] kpt_nvir = nmo_per_kpt[k] - kpt_nocc kpt_padded_moidx = numpy.concatenate((numpy.ones(kpt_nocc, dtype=numpy.bool), numpy.zeros(nmo - kpt_nocc - kpt_nvir, dtype=numpy.bool), numpy.ones(kpt_nvir, dtype=numpy.bool))) padded_moidx.append(kpt_padded_moidx) eris.mo_coeff = [] eris.orbspin = [] # Generate the molecular orbital coefficients with the frozen orbitals masked. # Each MO is tagged with orbspin, a list of 0's and 1's that give the overall # spin of each MO. # # Here we will work with two index arrays; one is for our original (small) moidx # array while the next is for our new (large) padded array. for k in range(nkpts): kpt_moidx = moidx[k] kpt_padded_moidx = padded_moidx[k] mo = numpy.zeros((nao, nmo), dtype=dtype) mo[:, kpt_padded_moidx] = mo_coeff[k][:, kpt_moidx] if getattr(mo_coeff[k], 'orbspin', None) is not None: orbspin_dtype = mo_coeff[k].orbspin[kpt_moidx].dtype orbspin = numpy.zeros(nmo, dtype=orbspin_dtype) orbspin[kpt_padded_moidx] = mo_coeff[k].orbspin[kpt_moidx] mo = lib.tag_array(mo, orbspin=orbspin) eris.orbspin.append(orbspin) # FIXME: What if the user freezes all up spin orbitals in # an RHF calculation? The number of electrons will still be # even. else: # guess orbital spin - assumes an RHF calculation assert (numpy.count_nonzero(kpt_moidx) % 2 == 0) orbspin = numpy.zeros(mo.shape[1], dtype=int) orbspin[1::2] = 1 mo = lib.tag_array(mo, orbspin=orbspin) eris.orbspin.append(orbspin) eris.mo_coeff.append(mo) # Re-make our fock MO matrix elements from density and fock AO dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ) with lib.temporary_env(cc._scf, exxdiv=None): # _scf.exxdiv affects eris.fock. HF exchange correction should be # excluded from the Fock matrix. fockao = cc._scf.get_hcore() + cc._scf.get_veff(cell, dm) eris.fock = numpy.asarray([reduce(numpy.dot, (mo.T.conj(), fockao[k], mo)) for k, mo in enumerate(eris.mo_coeff)]) eris.mo_energy = [eris.fock[k].diagonal().real for k in range(nkpts)] # Add HFX correction in the eris.mo_energy to improve convergence in # CCSD iteration. It is useful for the 2D systems since their occupied and # the virtual orbital energies may overlap which may lead to numerical # issue in the CCSD iterations. # FIXME: Whether to add this correction for other exxdiv treatments? # Without the correction, MP2 energy may be largely off the correct value. madelung = tools.madelung(cell, kpts) eris.mo_energy = [_adjust_occ(mo_e, nocc, -madelung) for k, mo_e in enumerate(eris.mo_energy)] # Get location of padded elements in occupied and virtual space. nocc_per_kpt = get_nocc(cc, per_kpoint=True) nonzero_padding = padding_k_idx(cc, kind="joint") # Check direct and indirect gaps for possible issues with CCSD convergence. mo_e = [eris.mo_energy[kp][nonzero_padding[kp]] for kp in range(nkpts)] mo_e = numpy.sort([y for x in mo_e for y in x]) # Sort de-nested array gap = mo_e[numpy.sum(nocc_per_kpt)] - mo_e[numpy.sum(nocc_per_kpt)-1] if gap < 1e-5: logger.warn(cc, 'H**O-LUMO gap %s too small for KCCSD. ' 'May cause issues in convergence.', gap) kconserv = kpts_helper.get_kconserv(cell, kpts) if getattr(mo_coeff[0], 'orbspin', None) is None: # The bottom nao//2 coefficients are down (up) spin while the top are up (down). mo_a_coeff = [mo[:nao // 2] for mo in eris.mo_coeff] mo_b_coeff = [mo[nao // 2:] for mo in eris.mo_coeff] eri = numpy.empty((nkpts, nkpts, nkpts, nmo, nmo, nmo, nmo), dtype=numpy.complex128) fao2mo = cc._scf.with_df.ao2mo for kp, kq, kr in kpts_helper.loop_kkk(nkpts): ks = kconserv[kp, kq, kr] eri_kpt = fao2mo( (mo_a_coeff[kp], mo_a_coeff[kq], mo_a_coeff[kr], mo_a_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt += fao2mo( (mo_b_coeff[kp], mo_b_coeff[kq], mo_b_coeff[kr], mo_b_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt += fao2mo( (mo_a_coeff[kp], mo_a_coeff[kq], mo_b_coeff[kr], mo_b_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt += fao2mo( (mo_b_coeff[kp], mo_b_coeff[kq], mo_a_coeff[kr], mo_a_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo) eri[kp, kq, kr] = eri_kpt else: mo_a_coeff = [mo[:nao // 2] + mo[nao // 2:] for mo in eris.mo_coeff] eri = numpy.empty((nkpts, nkpts, nkpts, nmo, nmo, nmo, nmo), dtype=numpy.complex128) fao2mo = cc._scf.with_df.ao2mo for kp, kq, kr in kpts_helper.loop_kkk(nkpts): ks = kconserv[kp, kq, kr] eri_kpt = fao2mo( (mo_a_coeff[kp], mo_a_coeff[kq], mo_a_coeff[kr], mo_a_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt[(eris.orbspin[kp][:, None] != eris.orbspin[kq]).ravel()] = 0 eri_kpt[:, (eris.orbspin[kr][:, None] != eris.orbspin[ks]).ravel()] = 0 eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo) eri[kp, kq, kr] = eri_kpt # Check some antisymmetrized properties of the integrals if DEBUG: check_antisymm_3412(cc, cc.kpts, eri) # Antisymmetrizing (pq|rs)-(ps|rq), where the latter integral is equal to # (rq|ps); done since we aren't tracking the kpoint of orbital 's' eri = eri - eri.transpose(2, 1, 0, 5, 4, 3, 6) # Chemist -> physics notation eri = eri.transpose(0, 2, 1, 3, 5, 4, 6) # Set the various integrals eris.dtype = eri.dtype eris.oooo = eri[:, :, :, :nocc, :nocc, :nocc, :nocc].copy() / nkpts eris.ooov = eri[:, :, :, :nocc, :nocc, :nocc, nocc:].copy() / nkpts eris.ovoo = eri[:, :, :, :nocc, nocc:, :nocc, :nocc].copy() / nkpts eris.oovv = eri[:, :, :, :nocc, :nocc, nocc:, nocc:].copy() / nkpts eris.ovov = eri[:, :, :, :nocc, nocc:, :nocc, nocc:].copy() / nkpts eris.ovvv = eri[:, :, :, :nocc, nocc:, nocc:, nocc:].copy() / nkpts eris.vvvv = eri[:, :, :, nocc:, nocc:, nocc:, nocc:].copy() / nkpts log.timer('CCSD integral transformation', *cput0) return eris
def test_update_lambda_complex(self): mo_coeff = mf.mo_coeff + np.sin(mf.mo_coeff) * .01j nao = mo_coeff.shape[0] eri = ao2mo.restore(1, mf._eri, nao) eri0 = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_coeff.conj(), mo_coeff, mo_coeff.conj(), mo_coeff) nocc, nvir = 5, nao-5 eris = rccsd._ChemistsERIs(mol) eris.oooo = eri0[:nocc,:nocc,:nocc,:nocc].copy() eris.ovoo = eri0[:nocc,nocc:,:nocc,:nocc].copy() eris.oovv = eri0[:nocc,:nocc,nocc:,nocc:].copy() eris.ovvo = eri0[:nocc,nocc:,nocc:,:nocc].copy() eris.ovov = eri0[:nocc,nocc:,:nocc,nocc:].copy() eris.ovvv = eri0[:nocc,nocc:,nocc:,nocc:].copy() eris.vvvv = eri0[nocc:,nocc:,nocc:,nocc:].copy() eris.fock = np.diag(mf.mo_energy) np.random.seed(1) t1 = np.random.random((nocc,nvir)) + np.random.random((nocc,nvir))*.1j - .5 t2 = np.random.random((nocc,nocc,nvir,nvir)) - .5 t2 = t2 + np.sin(t2) * .1j t2 = t2 + t2.transpose(1,0,3,2) l1 = np.random.random((nocc,nvir)) + np.random.random((nocc,nvir))*.1j - .5 l2 = np.random.random((nocc,nocc,nvir,nvir)) - .5 l2 = l2 + np.sin(l2) * .1j l2 = l2 + l2.transpose(1,0,3,2) mycc = rccsd.RCCSD(mf) imds = rccsd_lambda.make_intermediates(mycc, t1, t2, eris) l1new_ref, l2new_ref = rccsd_lambda.update_lambda(mycc, t1, t2, l1, l2, eris, imds) orbspin = np.zeros(nao*2, dtype=int) orbspin[1::2] = 1 eri1 = np.zeros([nao*2]*4, dtype=np.complex) eri1[0::2,0::2,0::2,0::2] = \ eri1[0::2,0::2,1::2,1::2] = \ eri1[1::2,1::2,0::2,0::2] = \ eri1[1::2,1::2,1::2,1::2] = eri0 eri1 = eri1.transpose(0,2,1,3) - eri1.transpose(0,2,3,1) erig = gccsd._PhysicistsERIs(mol) nocc *= 2 nvir *= 2 erig.oooo = eri1[:nocc,:nocc,:nocc,:nocc].copy() erig.ooov = eri1[:nocc,:nocc,:nocc,nocc:].copy() erig.ovov = eri1[:nocc,nocc:,:nocc,nocc:].copy() erig.ovvo = eri1[:nocc,nocc:,nocc:,:nocc].copy() erig.oovv = eri1[:nocc,:nocc,nocc:,nocc:].copy() erig.ovvv = eri1[:nocc,nocc:,nocc:,nocc:].copy() erig.vvvv = eri1[nocc:,nocc:,nocc:,nocc:].copy() mo_e = np.array([mf.mo_energy]*2) erig.fock = np.diag(mo_e.T.ravel()) erig.mo_energy = erig.fock.diagonal() myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1, t2 = myccg.amplitudes_from_ccsd(t1, t2) l1, l2 = myccg.amplitudes_from_ccsd(l1, l2) imds = gccsd_lambda.make_intermediates(myccg, t1, t2, erig) l1new, l2new = gccsd_lambda.update_lambda(myccg, t1, t2, l1, l2, erig, imds) self.assertAlmostEqual(float(abs(l1new[0::2,0::2]-l1new_ref).max()), 0, 9) l2aa = l2new[0::2,0::2,0::2,0::2] l2ab = l2new[0::2,1::2,0::2,1::2] self.assertAlmostEqual(float(abs(l2ab-l2new_ref).max()), 0, 9) self.assertAlmostEqual(float(abs(l2ab-l2ab.transpose(1,0,2,3) - l2aa).max()), 0, 9)
def test_uccsd_t_complex(self): mol = gto.M() numpy.random.seed(12) nocca, noccb, nvira, nvirb = 3, 2, 4, 5 nmo = nocca + nvira eris = cc.uccsd._ChemistsERIs() eris.nocca = nocca eris.noccb = noccb eris.nocc = (nocca, noccb) eri1 = (numpy.random.random((3,nmo,nmo,nmo,nmo)) + numpy.random.random((3,nmo,nmo,nmo,nmo)) * .8j - .5-.4j) eri1 = eri1 + eri1.transpose(0,2,1,4,3).conj() eri1[0] = eri1[0] + eri1[0].transpose(2,3,0,1) eri1[2] = eri1[2] + eri1[2].transpose(2,3,0,1) eri1 *= .1 eris.ovvv = eri1[0,:nocca,nocca:,nocca:,nocca:] eris.ovov = eri1[0,:nocca,nocca:,:nocca,nocca:] eris.ovoo = eri1[0,:nocca,nocca:,:nocca,:nocca] eris.OVVV = eri1[2,:noccb,noccb:,noccb:,noccb:] eris.OVOV = eri1[2,:noccb,noccb:,:noccb,noccb:] eris.OVOO = eri1[2,:noccb,noccb:,:noccb,:noccb] eris.voVP = eri1[1,nocca:,:nocca,noccb:,: ] eris.ovVV = eri1[1,:nocca,nocca:,noccb:,noccb:] eris.ovOV = eri1[1,:nocca,nocca:,:noccb,noccb:] eris.ovOO = eri1[1,:nocca,nocca:,:noccb,:noccb] eris.OVvv = eri1[1,nocca:,nocca:,:noccb,noccb:].transpose(2,3,0,1) eris.OVoo = eri1[1,:nocca,:nocca,:noccb,noccb:].transpose(2,3,0,1) t1a = .1 * numpy.random.random((nocca,nvira)) + numpy.random.random((nocca,nvira))*.1j t1b = .1 * numpy.random.random((noccb,nvirb)) + numpy.random.random((noccb,nvirb))*.1j t2aa = .1 * numpy.random.random((nocca,nocca,nvira,nvira)) + numpy.random.random((nocca,nocca,nvira,nvira))*.1j t2aa = t2aa - t2aa.transpose(0,1,3,2) t2aa = t2aa - t2aa.transpose(1,0,2,3) t2bb = .1 * numpy.random.random((noccb,noccb,nvirb,nvirb)) + numpy.random.random((noccb,noccb,nvirb,nvirb))*.1j t2bb = t2bb - t2bb.transpose(0,1,3,2) t2bb = t2bb - t2bb.transpose(1,0,2,3) t2ab = .1 * numpy.random.random((nocca,noccb,nvira,nvirb)) + numpy.random.random((nocca,noccb,nvira,nvirb))*.1j f = (numpy.random.random((2,nmo,nmo)) * .4 + numpy.random.random((2,nmo,nmo)) * .4j) eris.focka = f[0]+f[0].T.conj() + numpy.diag(numpy.arange(nmo)) eris.fockb = f[1]+f[1].T.conj() + numpy.diag(numpy.arange(nmo)) eris.mo_energy = (eris.focka.diagonal().real, eris.fockb.diagonal().real) t1 = t1a, t1b t2 = t2aa, t2ab, t2bb mcc = cc.UCCSD(scf.UHF(mol)) mcc.nocc = eris.nocc e0 = uccsd_t.kernel(mcc, eris, t1, t2) eri2 = numpy.zeros((nmo*2,nmo*2,nmo*2,nmo*2), dtype=eri1.dtype) orbspin = numpy.zeros(nmo*2,dtype=int) orbspin[1::2] = 1 eri2[0::2,0::2,0::2,0::2] = eri1[0] eri2[1::2,1::2,0::2,0::2] = eri1[1].transpose(2,3,0,1) eri2[0::2,0::2,1::2,1::2] = eri1[1] eri2[1::2,1::2,1::2,1::2] = eri1[2] eri2 = eri2.transpose(0,2,1,3) - eri2.transpose(0,2,3,1) fock = numpy.zeros((nmo*2,nmo*2), dtype=eris.focka.dtype) fock[0::2,0::2] = eris.focka fock[1::2,1::2] = eris.fockb eris1 = gccsd._PhysicistsERIs() nocc = nocca + noccb eris1.ovvv = eri2[:nocc,nocc:,nocc:,nocc:] eris1.oovv = eri2[:nocc,:nocc,nocc:,nocc:] eris1.ooov = eri2[:nocc,:nocc,:nocc,nocc:] eris1.fock = fock eris1.mo_energy = fock.diagonal().real t1 = gccsd.spatial2spin(t1, orbspin) t2 = gccsd.spatial2spin(t2, orbspin) gcc = gccsd.GCCSD(scf.GHF(gto.M())) e1 = gccsd_t.kernel(gcc, eris1, t1, t2) self.assertAlmostEqual(e0, e1.real, 9) self.assertAlmostEqual(e1, -0.056092415718338388-0.011390417704868244j, 9)
def _make_eris_incore(cc, mo_coeff=None): log = logger.Logger(cc.stdout, cc.verbose) cput0 = (time.clock(), time.time()) eris = gccsd._PhysicistsERIs() kpts = cc.kpts nkpts = cc.nkpts nocc = cc.nocc nmo = cc.nmo nvir = nmo - nocc eris.nocc = nocc #if any(nocc != numpy.count_nonzero(cc._scf.mo_occ[k] > 0) for k in range(nkpts)): # raise NotImplementedError('Different occupancies found for different k-points') if mo_coeff is None: mo_coeff = cc.mo_coeff #else: # # If mo_coeff is not canonical orbital # # TODO does this work for k-points? changed to conjugate. # raise NotImplementedError nao = mo_coeff[0].shape[0] dtype = mo_coeff[0].dtype moidx = get_frozen_mask(cc) nocc_per_kpt = numpy.asarray(get_nocc(cc, per_kpoint=True)) nmo_per_kpt = numpy.asarray(get_nmo(cc, per_kpoint=True)) padded_moidx = [] for k in range(nkpts): kpt_nocc = nocc_per_kpt[k] kpt_nvir = nmo_per_kpt[k] - kpt_nocc kpt_padded_moidx = numpy.concatenate( (numpy.ones(kpt_nocc, dtype=numpy.bool), numpy.zeros(nmo - kpt_nocc - kpt_nvir, dtype=numpy.bool), numpy.ones(kpt_nvir, dtype=numpy.bool))) padded_moidx.append(kpt_padded_moidx) eris.mo_coeff = [] eris.orbspin = [] # Generate the molecular orbital coefficients with the frozen orbitals masked. # Each MO is tagged with orbspin, a list of 0's and 1's that give the overall # spin of each MO. # # Here we will work with two index arrays; one is for our original (small) moidx # array while the next is for our new (large) padded array. for k in range(nkpts): kpt_moidx = moidx[k] kpt_padded_moidx = padded_moidx[k] mo = numpy.zeros((nao, nmo), dtype=dtype) mo[:, kpt_padded_moidx] = mo_coeff[k][:, kpt_moidx] if hasattr(mo_coeff[k], 'orbspin'): orbspin_dtype = mo_coeff[k].orbspin[kpt_moidx].dtype orbspin = numpy.zeros(nmo, dtype=orbspin_dtype) orbspin[kpt_padded_moidx] = mo_coeff[k].orbspin[kpt_moidx] mo = lib.tag_array(mo, orbspin=orbspin) eris.orbspin.append(orbspin) # FIXME: What if the user freezes all up spin orbitals in # an RHF calculation? The number of electrons will still be # even. else: # guess orbital spin - assumes an RHF calculation assert (numpy.count_nonzero(kpt_moidx) % 2 == 0) orbspin = numpy.zeros(mo.shape[1], dtype=int) orbspin[1::2] = 1 mo = lib.tag_array(mo, orbspin=orbspin) eris.orbspin.append(orbspin) eris.mo_coeff.append(mo) # Re-make our fock MO matrix elements from density and fock AO dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ) fockao = cc._scf.get_hcore() + cc._scf.get_veff(cc._scf.cell, dm) eris.fock = numpy.asarray([ reduce(numpy.dot, (mo.T.conj(), fockao[k], mo)) for k, mo in enumerate(eris.mo_coeff) ]) kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts) # The bottom nao//2 coefficients are down (up) spin while the top are up (down). # These are 'spin-less' quantities; spin-conservation will be added manually. so_coeff = [mo[:nao // 2] + mo[nao // 2:] for mo in eris.mo_coeff] eri = numpy.empty((nkpts, nkpts, nkpts, nmo, nmo, nmo, nmo), dtype=numpy.complex128) fao2mo = cc._scf.with_df.ao2mo for kp, kq, kr in kpts_helper.loop_kkk(nkpts): ks = kconserv[kp, kq, kr] eri_kpt = fao2mo( (so_coeff[kp], so_coeff[kq], so_coeff[kr], so_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt[(eris.orbspin[kp][:, None] != eris.orbspin[kq]).ravel()] = 0 eri_kpt[:, (eris.orbspin[kr][:, None] != eris.orbspin[ks]).ravel()] = 0 eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo) eri[kp, kq, kr] = eri_kpt # Check some antisymmetrized properties of the integrals if DEBUG: check_antisymm_3412(cc, cc.kpts, eri) # Antisymmetrizing (pq|rs)-(ps|rq), where the latter integral is equal to # (rq|ps); done since we aren't tracking the kpoint of orbital 's' eri = eri - eri.transpose(2, 1, 0, 5, 4, 3, 6) # Chemist -> physics notation eri = eri.transpose(0, 2, 1, 3, 5, 4, 6) # Set the various integrals eris.dtype = eri.dtype eris.oooo = eri[:, :, :, :nocc, :nocc, :nocc, :nocc].copy() / nkpts eris.ooov = eri[:, :, :, :nocc, :nocc, :nocc, nocc:].copy() / nkpts eris.ovoo = eri[:, :, :, :nocc, nocc:, :nocc, :nocc].copy() / nkpts eris.oovv = eri[:, :, :, :nocc, :nocc, nocc:, nocc:].copy() / nkpts eris.ovov = eri[:, :, :, :nocc, nocc:, :nocc, nocc:].copy() / nkpts eris.ovvv = eri[:, :, :, :nocc, nocc:, nocc:, nocc:].copy() / nkpts eris.vvvv = eri[:, :, :, nocc:, nocc:, nocc:, nocc:].copy() / nkpts log.timer('CCSD integral transformation', *cput0) return eris
def _make_eris_incore(cc, mo_coeff=None): from pyscf.pbc import tools from pyscf.pbc.cc.ccsd import _adjust_occ log = logger.Logger(cc.stdout, cc.verbose) cput0 = (time.clock(), time.time()) eris = gccsd._PhysicistsERIs() cell = cc._scf.cell kpts = cc.kpts nkpts = cc.nkpts nocc = cc.nocc nmo = cc.nmo nvir = nmo - nocc eris.nocc = nocc #if any(nocc != numpy.count_nonzero(cc._scf.mo_occ[k] > 0) for k in range(nkpts)): # raise NotImplementedError('Different occupancies found for different k-points') if mo_coeff is None: mo_coeff = cc.mo_coeff nao = mo_coeff[0].shape[0] dtype = mo_coeff[0].dtype moidx = get_frozen_mask(cc) nocc_per_kpt = numpy.asarray(get_nocc(cc, per_kpoint=True)) nmo_per_kpt = numpy.asarray(get_nmo(cc, per_kpoint=True)) padded_moidx = [] for k in range(nkpts): kpt_nocc = nocc_per_kpt[k] kpt_nvir = nmo_per_kpt[k] - kpt_nocc kpt_padded_moidx = numpy.concatenate( (numpy.ones(kpt_nocc, dtype=numpy.bool), numpy.zeros(nmo - kpt_nocc - kpt_nvir, dtype=numpy.bool), numpy.ones(kpt_nvir, dtype=numpy.bool))) padded_moidx.append(kpt_padded_moidx) eris.mo_coeff = [] eris.orbspin = [] # Generate the molecular orbital coefficients with the frozen orbitals masked. # Each MO is tagged with orbspin, a list of 0's and 1's that give the overall # spin of each MO. # # Here we will work with two index arrays; one is for our original (small) moidx # array while the next is for our new (large) padded array. for k in range(nkpts): kpt_moidx = moidx[k] kpt_padded_moidx = padded_moidx[k] mo = numpy.zeros((nao, nmo), dtype=dtype) mo[:, kpt_padded_moidx] = mo_coeff[k][:, kpt_moidx] if getattr(mo_coeff[k], 'orbspin', None) is not None: orbspin_dtype = mo_coeff[k].orbspin[kpt_moidx].dtype orbspin = numpy.zeros(nmo, dtype=orbspin_dtype) orbspin[kpt_padded_moidx] = mo_coeff[k].orbspin[kpt_moidx] mo = lib.tag_array(mo, orbspin=orbspin) eris.orbspin.append(orbspin) # FIXME: What if the user freezes all up spin orbitals in # an RHF calculation? The number of electrons will still be # even. else: # guess orbital spin - assumes an RHF calculation assert (numpy.count_nonzero(kpt_moidx) % 2 == 0) orbspin = numpy.zeros(mo.shape[1], dtype=int) orbspin[1::2] = 1 mo = lib.tag_array(mo, orbspin=orbspin) eris.orbspin.append(orbspin) eris.mo_coeff.append(mo) # Re-make our fock MO matrix elements from density and fock AO dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ) with lib.temporary_env(cc._scf, exxdiv=None): # _scf.exxdiv affects eris.fock. HF exchange correction should be # excluded from the Fock matrix. fockao = cc._scf.get_hcore() + cc._scf.get_veff(cell, dm) eris.fock = numpy.asarray([ reduce(numpy.dot, (mo.T.conj(), fockao[k], mo)) for k, mo in enumerate(eris.mo_coeff) ]) eris.mo_energy = [eris.fock[k].diagonal().real for k in range(nkpts)] # Add HFX correction in the eris.mo_energy to improve convergence in # CCSD iteration. It is useful for the 2D systems since their occupied and # the virtual orbital energies may overlap which may lead to numerical # issue in the CCSD iterations. # FIXME: Whether to add this correction for other exxdiv treatments? # Without the correction, MP2 energy may be largely off the correct value. madelung = tools.madelung(cell, kpts) eris.mo_energy = [ _adjust_occ(mo_e, nocc, -madelung) for k, mo_e in enumerate(eris.mo_energy) ] # Get location of padded elements in occupied and virtual space. nocc_per_kpt = get_nocc(cc, per_kpoint=True) nonzero_padding = padding_k_idx(cc, kind="joint") # Check direct and indirect gaps for possible issues with CCSD convergence. mo_e = [eris.mo_energy[kp][nonzero_padding[kp]] for kp in range(nkpts)] mo_e = numpy.sort([y for x in mo_e for y in x]) # Sort de-nested array gap = mo_e[numpy.sum(nocc_per_kpt)] - mo_e[numpy.sum(nocc_per_kpt) - 1] if gap < 1e-5: logger.warn( cc, 'H**O-LUMO gap %s too small for KCCSD. ' 'May cause issues in convergence.', gap) kconserv = kpts_helper.get_kconserv(cell, kpts) if getattr(mo_coeff[0], 'orbspin', None) is None: # The bottom nao//2 coefficients are down (up) spin while the top are up (down). mo_a_coeff = [mo[:nao // 2] for mo in eris.mo_coeff] mo_b_coeff = [mo[nao // 2:] for mo in eris.mo_coeff] eri = numpy.empty((nkpts, nkpts, nkpts, nmo, nmo, nmo, nmo), dtype=numpy.complex128) fao2mo = cc._scf.with_df.ao2mo for kp, kq, kr in kpts_helper.loop_kkk(nkpts): ks = kconserv[kp, kq, kr] eri_kpt = fao2mo((mo_a_coeff[kp], mo_a_coeff[kq], mo_a_coeff[kr], mo_a_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt += fao2mo((mo_b_coeff[kp], mo_b_coeff[kq], mo_b_coeff[kr], mo_b_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt += fao2mo((mo_a_coeff[kp], mo_a_coeff[kq], mo_b_coeff[kr], mo_b_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt += fao2mo((mo_b_coeff[kp], mo_b_coeff[kq], mo_a_coeff[kr], mo_a_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo) eri[kp, kq, kr] = eri_kpt else: mo_a_coeff = [mo[:nao // 2] + mo[nao // 2:] for mo in eris.mo_coeff] eri = numpy.empty((nkpts, nkpts, nkpts, nmo, nmo, nmo, nmo), dtype=numpy.complex128) fao2mo = cc._scf.with_df.ao2mo for kp, kq, kr in kpts_helper.loop_kkk(nkpts): ks = kconserv[kp, kq, kr] eri_kpt = fao2mo((mo_a_coeff[kp], mo_a_coeff[kq], mo_a_coeff[kr], mo_a_coeff[ks]), (kpts[kp], kpts[kq], kpts[kr], kpts[ks]), compact=False) eri_kpt[(eris.orbspin[kp][:, None] != eris.orbspin[kq]).ravel()] = 0 eri_kpt[:, (eris.orbspin[kr][:, None] != eris.orbspin[ks]).ravel()] = 0 eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo) eri[kp, kq, kr] = eri_kpt # Check some antisymmetrized properties of the integrals if DEBUG: check_antisymm_3412(cc, cc.kpts, eri) # Antisymmetrizing (pq|rs)-(ps|rq), where the latter integral is equal to # (rq|ps); done since we aren't tracking the kpoint of orbital 's' eri = eri - eri.transpose(2, 1, 0, 5, 4, 3, 6) # Chemist -> physics notation eri = eri.transpose(0, 2, 1, 3, 5, 4, 6) # Set the various integrals eris.dtype = eri.dtype eris.oooo = eri[:, :, :, :nocc, :nocc, :nocc, :nocc].copy() / nkpts eris.ooov = eri[:, :, :, :nocc, :nocc, :nocc, nocc:].copy() / nkpts eris.ovoo = eri[:, :, :, :nocc, nocc:, :nocc, :nocc].copy() / nkpts eris.oovv = eri[:, :, :, :nocc, :nocc, nocc:, nocc:].copy() / nkpts eris.ovov = eri[:, :, :, :nocc, nocc:, :nocc, nocc:].copy() / nkpts eris.ovvv = eri[:, :, :, :nocc, nocc:, nocc:, nocc:].copy() / nkpts eris.vvvv = eri[:, :, :, nocc:, nocc:, nocc:, nocc:].copy() / nkpts log.timer('CCSD integral transformation', *cput0) return eris
def test_uccsd_t_complex(self): mol = gto.M() numpy.random.seed(12) nocca, noccb, nvira, nvirb = 3, 2, 4, 5 nmo = nocca + nvira eris = cc.uccsd._ChemistsERIs() eris.nocca = nocca eris.noccb = noccb eris.nocc = (nocca, noccb) eri1 = (numpy.random.random((3,nmo,nmo,nmo,nmo)) + numpy.random.random((3,nmo,nmo,nmo,nmo)) * .8j - .5-.4j) eri1 = eri1 + eri1.transpose(0,2,1,4,3).conj() eri1[0] = eri1[0] + eri1[0].transpose(2,3,0,1) eri1[2] = eri1[2] + eri1[2].transpose(2,3,0,1) eri1 *= .1 eris.ovvv = eri1[0,:nocca,nocca:,nocca:,nocca:] eris.ovov = eri1[0,:nocca,nocca:,:nocca,nocca:] eris.ovoo = eri1[0,:nocca,nocca:,:nocca,:nocca] eris.OVVV = eri1[2,:noccb,noccb:,noccb:,noccb:] eris.OVOV = eri1[2,:noccb,noccb:,:noccb,noccb:] eris.OVOO = eri1[2,:noccb,noccb:,:noccb,:noccb] eris.voVP = eri1[1,nocca:,:nocca,noccb:,: ] eris.ovVV = eri1[1,:nocca,nocca:,noccb:,noccb:] eris.ovOV = eri1[1,:nocca,nocca:,:noccb,noccb:] eris.ovOO = eri1[1,:nocca,nocca:,:noccb,:noccb] eris.OVvv = eri1[1,nocca:,nocca:,:noccb,noccb:].transpose(2,3,0,1) eris.OVoo = eri1[1,:nocca,:nocca,:noccb,noccb:].transpose(2,3,0,1) t1a = .1 * numpy.random.random((nocca,nvira)) + numpy.random.random((nocca,nvira))*.1j t1b = .1 * numpy.random.random((noccb,nvirb)) + numpy.random.random((noccb,nvirb))*.1j t2aa = .1 * numpy.random.random((nocca,nocca,nvira,nvira)) + numpy.random.random((nocca,nocca,nvira,nvira))*.1j t2aa = t2aa - t2aa.transpose(0,1,3,2) t2aa = t2aa - t2aa.transpose(1,0,2,3) t2bb = .1 * numpy.random.random((noccb,noccb,nvirb,nvirb)) + numpy.random.random((noccb,noccb,nvirb,nvirb))*.1j t2bb = t2bb - t2bb.transpose(0,1,3,2) t2bb = t2bb - t2bb.transpose(1,0,2,3) t2ab = .1 * numpy.random.random((nocca,noccb,nvira,nvirb)) + numpy.random.random((nocca,noccb,nvira,nvirb))*.1j f = (numpy.random.random((2,nmo,nmo)) * .4 + numpy.random.random((2,nmo,nmo)) * .4j) eris.focka = f[0]+f[0].T.conj() + numpy.diag(numpy.arange(nmo)) eris.fockb = f[1]+f[1].T.conj() + numpy.diag(numpy.arange(nmo)) eris.mo_energy = (eris.focka.diagonal().real, eris.fockb.diagonal().real) t1 = t1a, t1b t2 = t2aa, t2ab, t2bb mcc = cc.UCCSD(scf.UHF(mol)) mcc.nocc = eris.nocc e0 = uccsd_t.kernel(mcc, eris, t1, t2) eri2 = numpy.zeros((nmo*2,nmo*2,nmo*2,nmo*2), dtype=eri1.dtype) orbspin = numpy.zeros(nmo*2,dtype=int) orbspin[1::2] = 1 eri2[0::2,0::2,0::2,0::2] = eri1[0] eri2[1::2,1::2,0::2,0::2] = eri1[1].transpose(2,3,0,1) eri2[0::2,0::2,1::2,1::2] = eri1[1] eri2[1::2,1::2,1::2,1::2] = eri1[2] eri2 = eri2.transpose(0,2,1,3) - eri2.transpose(0,2,3,1) fock = numpy.zeros((nmo*2,nmo*2), dtype=eris.focka.dtype) fock[0::2,0::2] = eris.focka fock[1::2,1::2] = eris.fockb eris1 = gccsd._PhysicistsERIs() nocc = nocca + noccb eris1.ovvv = eri2[:nocc,nocc:,nocc:,nocc:] eris1.oovv = eri2[:nocc,:nocc,nocc:,nocc:] eris1.ooov = eri2[:nocc,:nocc,:nocc,nocc:] eris1.fock = fock eris1.mo_energy = fock.diagonal().real t1 = gccsd.spatial2spin(t1, orbspin) t2 = gccsd.spatial2spin(t2, orbspin) gcc = gccsd.GCCSD(scf.GHF(gto.M())) e1 = gccsd_t.kernel(gcc, eris1, t1, t2) self.assertAlmostEqual(e0, e1.real, 9) self.assertAlmostEqual(e1, -0.056092415718338388-0.011390417704868244j, 9)
def test_update_lambda_complex(self): nocca, noccb = mol.nelec nmo = mol.nao_nr() nvira,nvirb = nmo-nocca, nmo-noccb numpy.random.seed(9) t1 = [numpy.random.random((nocca,nvira))-.9, numpy.random.random((noccb,nvirb))-.9] l1 = [numpy.random.random((nocca,nvira))-.9, numpy.random.random((noccb,nvirb))-.9] t2 = [numpy.random.random((nocca,nocca,nvira,nvira))-.9, numpy.random.random((nocca,noccb,nvira,nvirb))-.9, numpy.random.random((noccb,noccb,nvirb,nvirb))-.9] t2[0] = t2[0] - t2[0].transpose(1,0,2,3) t2[0] = t2[0] - t2[0].transpose(0,1,3,2) t2[2] = t2[2] - t2[2].transpose(1,0,2,3) t2[2] = t2[2] - t2[2].transpose(0,1,3,2) l2 = [numpy.random.random((nocca,nocca,nvira,nvira))-.9, numpy.random.random((nocca,noccb,nvira,nvirb))-.9, numpy.random.random((noccb,noccb,nvirb,nvirb))-.9] l2[0] = l2[0] - l2[0].transpose(1,0,2,3) l2[0] = l2[0] - l2[0].transpose(0,1,3,2) l2[2] = l2[2] - l2[2].transpose(1,0,2,3) l2[2] = l2[2] - l2[2].transpose(0,1,3,2) # eris = mycc.ao2mo() # imds = make_intermediates(mycc, t1, t2, eris) # l1new, l2new = update_lambda(mycc, t1, t2, l1, l2, eris, imds) # print(lib.finger(l1new[0]) --104.55975252585894) # print(lib.finger(l1new[1]) --241.12677819375281) # print(lib.finger(l2new[0]) --0.4957533529669417) # print(lib.finger(l2new[1]) - 15.46423057451851 ) # print(lib.finger(l2new[2]) - 5.8430776663704407) nocca, noccb = mol.nelec mo_a = mf.mo_coeff[0] + numpy.sin(mf.mo_coeff[0]) * .01j mo_b = mf.mo_coeff[1] + numpy.sin(mf.mo_coeff[1]) * .01j nao = mo_a.shape[0] eri = ao2mo.restore(1, mf._eri, nao) eri0aa = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_a.conj(), mo_a) eri0ab = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a, mo_b.conj(), mo_b) eri0bb = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_b.conj(), mo_b, mo_b.conj(), mo_b) eri0ba = eri0ab.transpose(2,3,0,1) nvira = nao - nocca nvirb = nao - noccb eris = uccsd._ChemistsERIs(mol) eris.oooo = eri0aa[:nocca,:nocca,:nocca,:nocca].copy() eris.ovoo = eri0aa[:nocca,nocca:,:nocca,:nocca].copy() eris.oovv = eri0aa[:nocca,:nocca,nocca:,nocca:].copy() eris.ovvo = eri0aa[:nocca,nocca:,nocca:,:nocca].copy() eris.ovov = eri0aa[:nocca,nocca:,:nocca,nocca:].copy() eris.ovvv = eri0aa[:nocca,nocca:,nocca:,nocca:].copy() eris.vvvv = eri0aa[nocca:,nocca:,nocca:,nocca:].copy() eris.OOOO = eri0bb[:noccb,:noccb,:noccb,:noccb].copy() eris.OVOO = eri0bb[:noccb,noccb:,:noccb,:noccb].copy() eris.OOVV = eri0bb[:noccb,:noccb,noccb:,noccb:].copy() eris.OVVO = eri0bb[:noccb,noccb:,noccb:,:noccb].copy() eris.OVOV = eri0bb[:noccb,noccb:,:noccb,noccb:].copy() eris.OVVV = eri0bb[:noccb,noccb:,noccb:,noccb:].copy() eris.VVVV = eri0bb[noccb:,noccb:,noccb:,noccb:].copy() eris.ooOO = eri0ab[:nocca,:nocca,:noccb,:noccb].copy() eris.ovOO = eri0ab[:nocca,nocca:,:noccb,:noccb].copy() eris.ooVV = eri0ab[:nocca,:nocca,noccb:,noccb:].copy() eris.ovVO = eri0ab[:nocca,nocca:,noccb:,:noccb].copy() eris.ovOV = eri0ab[:nocca,nocca:,:noccb,noccb:].copy() eris.ovVV = eri0ab[:nocca,nocca:,noccb:,noccb:].copy() eris.vvVV = eri0ab[nocca:,nocca:,noccb:,noccb:].copy() eris.OOoo = eri0ba[:noccb,:noccb,:nocca,:nocca].copy() eris.OVoo = eri0ba[:noccb,noccb:,:nocca,:nocca].copy() eris.OOvv = eri0ba[:noccb,:noccb,nocca:,nocca:].copy() eris.OVvo = eri0ba[:noccb,noccb:,nocca:,:nocca].copy() eris.OVov = eri0ba[:noccb,noccb:,:nocca,nocca:].copy() eris.OVvv = eri0ba[:noccb,noccb:,nocca:,nocca:].copy() eris.VVvv = eri0ba[noccb:,noccb:,nocca:,nocca:].copy() eris.focka = numpy.diag(mf.mo_energy[0]) eris.fockb = numpy.diag(mf.mo_energy[1]) eris.mo_energy = mf.mo_energy t1[0] = t1[0] + numpy.sin(t1[0]) * .05j t1[1] = t1[1] + numpy.sin(t1[1]) * .05j t2[0] = t2[0] + numpy.sin(t2[0]) * .05j t2[1] = t2[1] + numpy.sin(t2[1]) * .05j t2[2] = t2[2] + numpy.sin(t2[2]) * .05j l1[0] = l1[0] + numpy.sin(l1[0]) * .05j l1[1] = l1[1] + numpy.sin(l1[1]) * .05j l2[0] = l2[0] + numpy.sin(l2[0]) * .05j l2[1] = l2[1] + numpy.sin(l2[1]) * .05j l2[2] = l2[2] + numpy.sin(l2[2]) * .05j imds = uccsd_lambda.make_intermediates(mycc, t1, t2, eris) l1new_ref, l2new_ref = uccsd_lambda.update_lambda(mycc, t1, t2, l1, l2, eris, imds) nocc = nocca + noccb orbspin = numpy.zeros(nao*2, dtype=int) orbspin[1::2] = 1 orbspin[nocc-1] = 0 orbspin[nocc ] = 1 eri1 = numpy.zeros([nao*2]*4, dtype=numpy.complex) idxa = numpy.where(orbspin == 0)[0] idxb = numpy.where(orbspin == 1)[0] eri1[idxa[:,None,None,None],idxa[:,None,None],idxa[:,None],idxa] = eri0aa eri1[idxa[:,None,None,None],idxa[:,None,None],idxb[:,None],idxb] = eri0ab eri1[idxb[:,None,None,None],idxb[:,None,None],idxa[:,None],idxa] = eri0ba eri1[idxb[:,None,None,None],idxb[:,None,None],idxb[:,None],idxb] = eri0bb eri1 = eri1.transpose(0,2,1,3) - eri1.transpose(0,2,3,1) erig = gccsd._PhysicistsERIs() erig.oooo = eri1[:nocc,:nocc,:nocc,:nocc].copy() erig.ooov = eri1[:nocc,:nocc,:nocc,nocc:].copy() erig.ovov = eri1[:nocc,nocc:,:nocc,nocc:].copy() erig.ovvo = eri1[:nocc,nocc:,nocc:,:nocc].copy() erig.oovv = eri1[:nocc,:nocc,nocc:,nocc:].copy() erig.ovvv = eri1[:nocc,nocc:,nocc:,nocc:].copy() erig.vvvv = eri1[nocc:,nocc:,nocc:,nocc:].copy() mo_e = numpy.empty(nao*2) mo_e[orbspin==0] = mf.mo_energy[0] mo_e[orbspin==1] = mf.mo_energy[1] erig.fock = numpy.diag(mo_e) erig.mo_energy = mo_e.real myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf)) t1 = myccg.spatial2spin(t1, orbspin) t2 = myccg.spatial2spin(t2, orbspin) l1 = myccg.spatial2spin(l1, orbspin) l2 = myccg.spatial2spin(l2, orbspin) imds = gccsd_lambda.make_intermediates(myccg, t1, t2, erig) l1new, l2new = gccsd_lambda.update_lambda(myccg, t1, t2, l1, l2, erig, imds) l1new = myccg.spin2spatial(l1new, orbspin) l2new = myccg.spin2spatial(l2new, orbspin) self.assertAlmostEqual(abs(l1new[0] - l1new_ref[0]).max(), 0, 11) self.assertAlmostEqual(abs(l1new[1] - l1new_ref[1]).max(), 0, 11) self.assertAlmostEqual(abs(l2new[0] - l2new_ref[0]).max(), 0, 11) self.assertAlmostEqual(abs(l2new[1] - l2new_ref[1]).max(), 0, 11) self.assertAlmostEqual(abs(l2new[2] - l2new_ref[2]).max(), 0, 11)