Пример #1
0
def greens_e_vector_ea_rhf(cc, p, kp=None):
    nkpts, nocc, nvir = cc.t1.shape
    ds_type = cc.t1.dtype
    vector1 = np.zeros((nvir), dtype=ds_type)
    vector2 = np.zeros((nkpts, nkpts, nocc, nvir, nvir), dtype=ds_type)

    if hasattr(cc, 'l1') and cc.l1 is not None:
        l1 = cc.l1
        l2 = cc.l2
    else:
        l1 = np.conj(cc.t1)
        l2 = np.conj(cc.t2)

    if p < nocc:
        # Changed both to plus
        vector1 += l1[kp, p, :]
        for ki in range(nkpts):
            for kj in range(nkpts):
                vector2[ki, kj] += 2*l2[ki,kj,kp,p,:,:,:] - \
                                     l2[kj,ki,kp,:,p,:,:]
    else:
        vector1[p - nocc] = -1.0
        vector1 += np.einsum('ia,i->a', l1[kp], cc.t1[kp, :, p - nocc])
        for kk in range(nkpts):
            for kl in range(nkpts):
                kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
                ka = kconserv[kl, kp, kk]

                vector1 += 2 * np.einsum('klca,klc->a', l2[ka,kk,kl], \
                           cc.t2[ka,kk,kl,:,:,:,p-nocc])
                vector1 -= np.einsum('klca,lkc->a', l2[ka,kk,kl], \
                           cc.t2[kk,ka,kl,:,:,:,p-nocc])

        for kb in range(nkpts):
            vector2[kb, kp, :, p - nocc, :] += -2. * l1[kb]

        for ka in range(nkpts):
            # kj == ka
            # kb == kc == kp
            vector2[ka, ka, :, :, p - nocc] += l1[ka]

        for kj in range(nkpts):
            for kb in range(nkpts):
                kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
                ka = kconserv[kp, kj, kb]

                vector2[kj,ka] += 2*np.einsum('k,jkba->jab', \
                                  cc.t1[kp,:,p-nocc], l2[kj,kp,kb,:,:,:,:])
                vector2[kj,ka] -= np.einsum('k,jkab->jab', \
                                  cc.t1[kp,:,p-nocc], l2[kj,kp,ka,:,:,:,:])

    return eom_rccsd.amplitudes_to_vector_ea(vector1, vector2)
Пример #2
0
def greens_e_vector_ip_krhf(cc, p, kp):
    assert_non_padded(cc, p, kp)
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    return nested_to_vector((
        greens_e_singles_ip_krhf(cc.t1, cc.t2, cc.l1, cc.l2, p, kp, kconserv),
        greens_e_doubles_ip_krhf(cc.t1, cc.l1, cc.l2, p, kp, kconserv),
    ))[0]
Пример #3
0
def cc_Wovvo(cc,t1,t2,eris):
    nkpts, nocc, nvir = t1.shape
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    eris_ovvo = numpy.zeros(shape=(nkpts,nkpts,nkpts,nocc,nvir,nvir,nocc),dtype=t2.dtype)
    eris_oovo = numpy.zeros(shape=(nkpts,nkpts,nkpts,nocc,nocc,nvir,nocc),dtype=t2.dtype)
    for km in range(nkpts):
        for kb in range(nkpts):
            for ke in range(nkpts):
                kj = kconserv[km,ke,kb]
                # <mb||je> -> -<mb||ej>
                eris_ovvo[km,kb,ke] = -eris.ovov[km,kb,kj].transpose(0,1,3,2)
                # <mn||je> -> -<mn||ej>
                # let kb = kn as a dummy variable
                eris_oovo[km,kb,ke] = -eris.ooov[km,kb,kj].transpose(0,1,3,2)
    Wmbej = eris_ovvo.copy()
    for km in range(nkpts):
        for kb in range(nkpts):
            for ke in range(nkpts):
                kj = kconserv[km,ke,kb]
                Wmbej[km,kb,ke] += einsum('jf,mbef->mbej',t1[kj,:,:],eris.ovvv[km,kb,ke])
                Wmbej[km,kb,ke] += -einsum('nb,mnej->mbej',t1[kb,:,:],eris_oovo[km,kb,ke])
                for kn in range(nkpts):
                    kf = kconserv[km,ke,kn]
                    Wmbej[km,kb,ke] += -0.5*einsum('jnfb,mnef->mbej',t2[kj,kn,kf],
                                                   eris.oovv[km,kn,ke])
                    if kn == kb and kf == kj:
                        Wmbej[km,kb,ke] += -einsum('jf,nb,mnef->mbej',t1[kj],t1[kn],
                                                   eris.oovv[km,kn,ke])
    return Wmbej
Пример #4
0
def greens_e_vector_ip_rhf(cc, p, kp=None):
    nkpts, nocc, nvir = cc.t1.shape
    vector1 = np.zeros((nocc), dtype=complex)
    vector2 = np.zeros((nkpts, nkpts, nocc, nocc, nvir), dtype=complex)

    if hasattr(cc, 'l1') and cc.l1 is not None:
        l1 = cc.l1
        l2 = cc.l2
    else:
        l1 = np.conj(cc.t1)
        l2 = np.conj(cc.t2)

    #print '################################'
    #print 'max t1 kpt',np.max(np.abs(cc.t1))

    if p < nocc:
        vector1[p] = -1.0
        #vector1 += 0.5 * np.einsum('ia,i->a', l1[0], cc.t1[0,p,:])
        #vector1 += 0.5 * np.einsum('ia,i->a', l1[1], cc.t1[1,p,:])
        vector1 += np.einsum('ia,a->i', l1[kp], cc.t1[kp, p, :])
        for kc in range(nkpts):
            for kl in range(nkpts):
                #kconserv = cc.khelper.kconserv
                kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
                kd = kconserv[kp, kl, kc]
                print '#########################################'
                print 'kp, ', cc.kpts[kp]
                print 'kc, ', cc.kpts[kc]
                print 'kl, ', cc.kpts[kl]
                print 'kd, '
                print 'plc, ', cc.kpts[kconserv[kp, kl, kc]]
                print 'conv calc, ', cc.kpts[kp] - cc.kpts[kl] + cc.kpts[kc]
                #vector1 += 2 * np.einsum('ilcd,lcd->i', \
                vector1 += (2)*np.einsum('ilcd,lcd->i', \
                       l2[kp,kl,kc], cc.t2[kp,kl,kc,p,:,:,:])
                #l2[kp,kl,kc], cc.t2[kl,kc,kd,p,:,:,:])
                vector1 -= (1)*np.einsum('ilcd,lcd->i', \
                #vector1 -= np.einsum('ilcd,ldc->i',   \
                       l2[kp,kl,kc], cc.t2[kp,kl,kd,p,:,:,:])
                #l2[kp,kl,kc], cc.t2[kp,kl,kc,p,:,:,:])
        for kj in range(nkpts):
            vector2[kp, kj, p, :, :] += -2 * l1[kj]
        for ki in range(nkpts):
            # kj == kk == kp, ki == kb
            vector2[ki, kp, :, p, :] += l1[ki]

            for kj in range(nkpts):
                # kc == kk == kp
                vector2[ki,kj] += 2*np.einsum('c,ijcb->ijb', \
                       cc.t1[kp,p,:], l2[ki,kj,kp,:,:,:,:])
                vector2[ki,kj] -= np.einsum('c,jicb->ijb', \
                       cc.t1[kp,p,:], l2[kj,ki,kp,:,:,:,:])
    else:
        vector1 += -l1[kp, :, p - nocc]
        for ki in range(nkpts):
            for kj in range(nkpts):
                vector2[ki, kj] += -2*l2[ki,kj,kp,:,:,p-nocc,:] + \
                                   l2[kj,ki,kp,:,:,p-nocc,:]

    return cc.amplitudes_to_vector_ip(vector1, vector2)
Пример #5
0
        def rand_t1_t2(mycc):
            nkpts = mycc.nkpts
            nocca, noccb = mycc.nocc
            nmoa, nmob = mycc.nmo
            nvira, nvirb = nmoa - nocca, nmob - noccb
            np.random.seed(1)
            t1a = (np.random.random((nkpts,nocca,nvira)) +
                   np.random.random((nkpts,nocca,nvira))*1j - .5-.5j)
            t1b = (np.random.random((nkpts,noccb,nvirb)) +
                   np.random.random((nkpts,noccb,nvirb))*1j - .5-.5j)
            t2aa = (np.random.random((nkpts,nkpts,nkpts,nocca,nocca,nvira,nvira)) +
                    np.random.random((nkpts,nkpts,nkpts,nocca,nocca,nvira,nvira))*1j - .5-.5j)
            kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
            t2aa = t2aa - t2aa.transpose(1,0,2,4,3,5,6)
            tmp = t2aa.copy()
            for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
                kl = kconserv[ki, kk, kj]
                t2aa[ki,kj,kk] = t2aa[ki,kj,kk] - tmp[ki,kj,kl].transpose(0,1,3,2)
            t2ab = (np.random.random((nkpts,nkpts,nkpts,nocca,noccb,nvira,nvirb)) +
                    np.random.random((nkpts,nkpts,nkpts,nocca,noccb,nvira,nvirb))*1j - .5-.5j)
            t2bb = (np.random.random((nkpts,nkpts,nkpts,noccb,noccb,nvirb,nvirb)) +
                    np.random.random((nkpts,nkpts,nkpts,noccb,noccb,nvirb,nvirb))*1j - .5-.5j)
            t2bb = t2bb - t2bb.transpose(1,0,2,4,3,5,6)
            tmp = t2bb.copy()
            for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
                kl = kconserv[ki, kk, kj]
                t2bb[ki,kj,kk] = t2bb[ki,kj,kk] - tmp[ki,kj,kl].transpose(0,1,3,2)

            t1 = (t1a, t1b)
            t2 = (t2aa, t2ab, t2bb)
            return t1, t2
Пример #6
0
    def test_rand_ccsd_frozen3(self):
        '''Single (eom-)ccsd iteration with random t1/t2 and single frozen virtual
        orbital.'''
        kconserv = kpts_helper.get_kconserv(rand_kmf.cell, rand_kmf.kpts)

        kmf = pbcscf.addons.convert_to_ghf(rand_kmf)
        # Round to make this insensitive to small changes between PySCF versions
        mat_veff = kmf.get_veff().round(4)
        mat_hcore = kmf.get_hcore().round(4)
        kmf.get_veff = lambda *x: mat_veff
        kmf.get_hcore = lambda *x: mat_hcore

        frozen = [[],[],[5]]  # freezing one virtual
        rand_cc = pbcc.KGCCSD(kmf, frozen=frozen)
        eris = rand_cc.ao2mo(rand_cc.mo_coeff)
        eris.mo_energy = [eris.fock[k].diagonal() for k in range(rand_cc.nkpts)]
        t1, t2 = rand_t1_t2(kmf, rand_cc)
        # Manually zero'ing out the frozen elements of the t1/t2
        t1[2, :, 0] = 0.0
        for ki in range(rand_cc.nkpts):
          for kj in range(rand_cc.nkpts):
            for ka in range(rand_cc.nkpts):
              kb = kconserv[ki, ka, kj]
              if ka == 2:
                  t2[ki, kj, ka, :, :, 0] = 0.0
              if kb == 2:
                  t2[ki, kj, ka, :, :, :, 0] = 0.0

        Ht1, Ht2 = rand_cc.update_amps(t1, t2, eris)
        self.assertAlmostEqual(finger(Ht1), (-19.6637196882-16.2773841431j), 6)
        self.assertAlmostEqual(finger(Ht2), (881.655146297+1283.71020059j), 6)
Пример #7
0
    def test_ao2mo_7d(self):
        L = 3.
        n = 6
        cell = pgto.Cell()
        cell.a = numpy.diag([L,L,L])
        cell.mesh = [n,n,n]
        cell.atom = '''He    2.    2.2      2.
                       He    1.2   1.       1.'''
        cell.basis = {'He': [[0, (1.2, 1)], [1, (0.6, 1)]]}
        cell.verbose = 0
        cell.build(0,0)

        kpts = cell.make_kpts([1,3,1])
        nkpts = len(kpts)
        nao = cell.nao_nr()
        numpy.random.seed(1)
        mo =(numpy.random.random((nkpts,nao,nao)) +
             numpy.random.random((nkpts,nao,nao))*1j)

        with_df = df.GDF(cell, kpts)
        out = with_df.ao2mo_7d(mo, kpts)
        ref = numpy.empty_like(out)

        kconserv = kpts_helper.get_kconserv(cell, kpts)
        for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
            kl = kconserv[ki, kj, kk]
            tmp = with_df.ao2mo((mo[ki], mo[kj], mo[kk], mo[kl]), kpts[[ki,kj,kk,kl]])
            ref[ki,kj,kk] = tmp.reshape([nao]*4)

        self.assertAlmostEqual(abs(out-ref).max(), 0, 12)
Пример #8
0
    def test_ao2mo_7d(self):
        L = 3.
        n = 6
        cell = pgto.Cell()
        cell.a = numpy.diag([L, L, L])
        cell.mesh = [n, n, n]
        cell.atom = '''He    2.    2.2      2.
                       He    1.2   1.       1.'''
        cell.basis = {'He': [[0, (1.2, 1)], [1, (0.6, 1)]]}
        cell.verbose = 0
        cell.build(0, 0)

        kpts = cell.make_kpts([1, 3, 1])
        nkpts = len(kpts)
        nao = cell.nao_nr()
        numpy.random.seed(1)
        mo = (numpy.random.random((nkpts, nao, nao)) + numpy.random.random(
            (nkpts, nao, nao)) * 1j)

        with_df = mdf.MDF(cell, kpts)
        out = with_df.ao2mo_7d(mo, kpts)
        ref = numpy.empty_like(out)

        kconserv = kpts_helper.get_kconserv(cell, kpts)
        for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
            kl = kconserv[ki, kj, kk]
            tmp = with_df.ao2mo((mo[ki], mo[kj], mo[kk], mo[kl]),
                                kpts[[ki, kj, kk, kl]])
            ref[ki, kj, kk] = tmp.reshape([nao] * 4)

        self.assertAlmostEqual(abs(out - ref).max(), 0, 12)
Пример #9
0
    def test_rand_ccsd_frozen3(self):
        '''Single (eom-)ccsd iteration with random t1/t2 and single frozen virtual
        orbital.'''
        kmf = copy.copy(rand_kmf)
        mat_veff = kmf.get_veff().round(4)
        mat_hcore = kmf.get_hcore().round(4)
        kmf.get_veff = lambda *x: mat_veff
        kmf.get_hcore = lambda *x: mat_hcore

        kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)

        frozen = [[],[],[3]]  # freezing one virtual
        rand_cc = pbcc.KRCCSD(kmf, frozen=frozen)
        eris = rand_cc.ao2mo(kmf.mo_coeff)
        eris.mo_energy = [eris.fock[k].diagonal() for k in range(rand_cc.nkpts)]
        t1, t2 = rand_t1_t2(kmf, rand_cc)
        # Manually zero'ing out the frozen elements of the t1/t2
        t1[2, :, 0] = 0.0
        for ki in range(rand_cc.nkpts):
          for kj in range(rand_cc.nkpts):
            for ka in range(rand_cc.nkpts):
              kb = kconserv[ki, ka, kj]
              if ka == 2:
                  t2[ki, kj, ka, :, :, 0] = 0.0
              if kb == 2:
                  t2[ki, kj, ka, :, :, :, 0] = 0.0

        Ht1, Ht2 = rand_cc.update_amps(t1, t2, eris)
        self.assertAlmostEqual(lib.fp(Ht1), (5.3320153970710118-7.9402122992688602j), 6)
        self.assertAlmostEqual(lib.fp(Ht2), (-236.46389414847206-360.1605297160217j), 6)

        # Excited state results
        rand_cc.t1, rand_cc.t2, rand_cc.eris = t1, t2, eris

        kshift = 2
        r1, r2 = rand_r1_r2_ip(kmf, rand_cc)
        r1[0] = 0.0
        for ki in range(rand_cc.nkpts):
          for kj in range(rand_cc.nkpts):
            ka = kconserv[ki, kshift, kj]
            if ka == 2:
                r2[ki, kj, :, :, 0] = 0.0

        Hr1, Hr2 = _run_ip_matvec(rand_cc, r1, r2, kshift)
        self.assertAlmostEqual(lib.fp(Hr1), (0.4067595510145880 +  0.0770280877446436j), 6)
        self.assertAlmostEqual(lib.fp(Hr2), (0.0926714318228812 + -1.0702702421619084j), 6)

        r1, r2 = rand_r1_r2_ea(kmf, rand_cc)
        r1[0] = 0.0
        for kj in range(rand_cc.nkpts):
          for ka in range(rand_cc.nkpts):
            kb = kconserv[kshift, ka, kj]
            if ka == 2:
                r2[kj, ka, :, 0, :] = 0.0
            if kb == 2:
                r2[kj, ka, :, :, 0] = 0.0

        Hr1, Hr2 = _run_ea_matvec(rand_cc, r1, r2, kshift)
        self.assertAlmostEqual(lib.fp(Hr1), (0.0070404498167285 + -0.1646809321907418j), 6)
        self.assertAlmostEqual(lib.fp(Hr2), (0.4518315588945250 + -0.5508323185152750j), 6)
Пример #10
0
def rand_t1_t2(cell, kpts, nocc, nvir):
    nkpts = len(kpts)
    nocca, noccb = nocc
    nvira, nvirb = nvir
    t1a = (numpy.random.random((nkpts,nocca,nvira)) +
           numpy.random.random((nkpts,nocca,nvira))*1j - .5-.5j)
    t1b = (numpy.random.random((nkpts,noccb,nvirb)) +
           numpy.random.random((nkpts,noccb,nvirb))*1j - .5-.5j)
    t2aa = (numpy.random.random((nkpts,nkpts,nkpts,nocca,nocca,nvira,nvira)) +
            numpy.random.random((nkpts,nkpts,nkpts,nocca,nocca,nvira,nvira))*1j - .5-.5j)
    kconserv = kpts_helper.get_kconserv(cell, kpts)
    t2aa = t2aa - t2aa.transpose(1,0,2,4,3,5,6)
    tmp = t2aa.copy()
    for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
        kl = kconserv[ki, kk, kj]
        t2aa[ki,kj,kk] = t2aa[ki,kj,kk] - tmp[ki,kj,kl].transpose(0,1,3,2)
    t2ab = (numpy.random.random((nkpts,nkpts,nkpts,nocca,noccb,nvira,nvirb)) +
            numpy.random.random((nkpts,nkpts,nkpts,nocca,noccb,nvira,nvirb))*1j - .5-.5j)
    t2bb = (numpy.random.random((nkpts,nkpts,nkpts,noccb,noccb,nvirb,nvirb)) +
            numpy.random.random((nkpts,nkpts,nkpts,noccb,noccb,nvirb,nvirb))*1j - .5-.5j)
    t2bb = t2bb - t2bb.transpose(1,0,2,4,3,5,6)
    tmp = t2bb.copy()
    for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
        kl = kconserv[ki, kk, kj]
        t2bb[ki,kj,kk] = t2bb[ki,kj,kk] - tmp[ki,kj,kl].transpose(0,1,3,2)

    t1 = (t1a, t1b)
    t2 = (t2aa, t2ab, t2bb)
    return t1, t2
Пример #11
0
    def test_spatial2spin_ea(self):
        numpy.random.seed(1)
        kpts = cell.make_kpts([1,2,3])
        nkpts = len(kpts)
        nmo = (8, 8)
        nocc = (3, 2)
        nvir = (nmo[0]-nocc[0], nmo[1]-nocc[1])

        orbspin = numpy.zeros((len(kpts),nmo[0]+nmo[1]), dtype=int)
        orbspin[:,1::2] = 1
        kconserv = kpts_helper.get_kconserv(cell, kpts)

        kshift = 0
        spin_r1_ea = (numpy.random.rand(nvir[0]+nvir[1])*1j +
                      numpy.random.rand(nvir[0]+nvir[1]) - 0.5 - 0.5*1j)
        spin_r2_ea = (numpy.random.rand(nkpts**2 * (nocc[0]+nocc[1])* (nvir[0]+nvir[1])**2) +
                      numpy.random.rand(nkpts**2 * (nocc[0]+nocc[1])* (nvir[0]+nvir[1])**2)*1j -
                      0.5 - 0.5*1j)
        spin_r2_ea = spin_r2_ea.reshape(nkpts, nkpts, (nocc[0]+nocc[1]),
                                        (nvir[0]+nvir[1]), (nvir[0]+nvir[1]))
        spin_r2_ea = eom_kccsd_ghf.enforce_2p_spin_ea_doublet(spin_r2_ea, kconserv, kshift, orbspin)

        [r1a, r1b], [r2aaa, r2baa, r2abb, r2bbb] = \
            eom_kccsd_ghf.spin2spatial_ea_doublet(spin_r1_ea, spin_r2_ea, kconserv, kshift, orbspin)

        r1, r2 = eom_kccsd_ghf.spatial2spin_ea_doublet([r1a, r1b], [r2aaa, r2baa, r2abb, r2bbb],
                                                       kconserv, kshift, orbspin=orbspin)

        self.assertAlmostEqual(abs(r1-spin_r1_ea).max(), 0, 12)
        self.assertAlmostEqual(abs(r2-spin_r2_ea).max(), 0, 12)
Пример #12
0
    def test_rand_ccsd_frozen3(self):
        '''Single (eom-)ccsd iteration with random t1/t2 and single frozen virtual
        orbital.'''
        kconserv = kpts_helper.get_kconserv(rand_kmf.cell, rand_kmf.kpts)

        kmf = pbcscf.addons.convert_to_ghf(rand_kmf)
        # Round to make this insensitive to small changes between PySCF versions
        mat_veff = kmf.get_veff().round(4)
        mat_hcore = kmf.get_hcore().round(4)
        kmf.get_veff = lambda *x: mat_veff
        kmf.get_hcore = lambda *x: mat_hcore

        frozen = [[], [], [5]]  # freezing one virtual
        rand_cc = pbcc.KGCCSD(kmf, frozen=frozen)
        eris = rand_cc.ao2mo(rand_cc.mo_coeff)
        eris.mo_energy = [
            eris.fock[k].diagonal() for k in range(rand_cc.nkpts)
        ]
        t1, t2 = rand_t1_t2(kmf, rand_cc)
        # Manually zero'ing out the frozen elements of the t1/t2
        t1[2, :, 0] = 0.0
        for ki in range(rand_cc.nkpts):
            for kj in range(rand_cc.nkpts):
                for ka in range(rand_cc.nkpts):
                    kb = kconserv[ki, ka, kj]
                    if ka == 2:
                        t2[ki, kj, ka, :, :, 0] = 0.0
                    if kb == 2:
                        t2[ki, kj, ka, :, :, :, 0] = 0.0

        Ht1, Ht2 = rand_cc.update_amps(t1, t2, eris)
        self.assertAlmostEqual(finger(Ht1), (-19.6637196882 - 16.2773841431j),
                               6)
        self.assertAlmostEqual(finger(Ht2), (881.655146297 + 1283.71020059j),
                               6)
Пример #13
0
    def test_rand_ccsd_frozen3(self):
        '''Single (eom-)ccsd iteration with random t1/t2 and single frozen virtual
        orbital.'''
        kconserv = kpts_helper.get_kconserv(rand_kmf.cell, rand_kmf.kpts)

        frozen = [[],[],[3]]  # freezing one virtual
        rand_cc = pbcc.KRCCSD(rand_kmf, frozen=frozen)
        eris = rand_cc.ao2mo(rand_kmf.mo_coeff)
        eris.mo_energy = [eris.fock[k].diagonal() for k in range(rand_cc.nkpts)]
        t1, t2 = rand_t1_t2(rand_kmf, rand_cc)
        # Manually zero'ing out the frozen elements of the t1/t2
        t1[2, :, 0] = 0.0
        for ki in range(rand_cc.nkpts):
          for kj in range(rand_cc.nkpts):
            for ka in range(rand_cc.nkpts):
              kb = kconserv[ki, ka, kj]
              if ka == 2:
                  t2[ki, kj, ka, :, :, 0] = 0.0
              if kb == 2:
                  t2[ki, kj, ka, :, :, :, 0] = 0.0

        Ht1, Ht2 = rand_cc.update_amps(t1, t2, eris)
        self.assertAlmostEqual(finger(Ht1), (5.3320153970710118-7.9402122992688602j), 6)
        self.assertAlmostEqual(finger(Ht2), (-236.46389414847206-360.1605297160217j), 6)

        # Excited state results
        rand_cc.t1, rand_cc.t2, rand_cc.eris = t1, t2, eris

        kshift = 2
        r1, r2 = rand_r1_r2_ip(rand_kmf, rand_cc)
        r1[0] = 0.0
        for ki in range(rand_cc.nkpts):
          for kj in range(rand_cc.nkpts):
            ka = kconserv[ki, kshift, kj]
            if ka == 2:
                r2[ki, kj, :, :, 0] = 0.0

        Hr1, Hr2 = _run_ip_matvec(rand_cc, r1, r2, kshift)
        self.assertAlmostEqual(finger(Hr1), (0.4067595510145880 +  0.0770280877446436j), 6)
        self.assertAlmostEqual(finger(Hr2), (0.0926714318228812 + -1.0702702421619084j), 6)

        r1, r2 = rand_r1_r2_ea(rand_kmf, rand_cc)
        r1[0] = 0.0
        for kj in range(rand_cc.nkpts):
          for ka in range(rand_cc.nkpts):
            kb = kconserv[kshift, ka, kj]
            if ka == 2:
                r2[kj, ka, :, 0, :] = 0.0
            if kb == 2:
                r2[kj, ka, :, :, 0] = 0.0

        Hr1, Hr2 = _run_ea_matvec(rand_cc, r1, r2, kshift)
        self.assertAlmostEqual(finger(Hr1), (0.0070404498167285 + -0.1646809321907418j), 6)
        self.assertAlmostEqual(finger(Hr2), (0.4518315588945250 + -0.5508323185152750j), 6)
Пример #14
0
 def spin2spatial(self, tx, orbspin=None, kconserv=None):
     if orbspin is None:
         if getattr(self.mo_coeff[0], 'orbspin', None) is not None:
             orbspin = [self.mo_coeff[k].orbspin[idx]
                        for k, idx in enumerate(self.get_frozen_mask())]
         else:
             orbspin = numpy.zeros((self.nkpts,self.nmo), dtype=int)
             orbspin[:,1::2] = 1
     if kconserv is None:
         kconserv = kpts_helper.get_kconserv(self._scf.cell, self.kpts)
     return spin2spatial(tx, orbspin, kconserv)
Пример #15
0
 def spin2spatial(self, tx, orbspin=None, kconserv=None):
     if orbspin is None:
         if getattr(self.mo_coeff[0], 'orbspin', None) is not None:
             orbspin = [self.mo_coeff[k].orbspin[idx]
                        for k, idx in enumerate(self.get_frozen_mask())]
         else:
             orbspin = numpy.zeros((self.nkpts,self.nmo), dtype=int)
             orbspin[:,1::2] = 1
     if kconserv is None:
         kconserv = kpts_helper.get_kconserv(self._scf.cell, self.kpts)
     return spin2spatial(tx, orbspin, kconserv)
Пример #16
0
 def rand_t1_t2(mycc):
     nkpts = mycc.nkpts
     nocc = mycc.nocc
     nmo = mycc.nmo
     nvir = nmo - nocc
     np.random.seed(1)
     t1 = (np.random.random((nkpts, nocc, nvir)) +
           np.random.random((nkpts, nocc, nvir)) * 1j - .5 - .5j)
     t2 = (np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) +
           np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) * 1j - .5 - .5j)
     kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
     Ps = kconserve_pmatrix(nkpts, kconserv)
     t2 = t2 + np.einsum('xyzijab,xyzw->yxwjiba', t2, Ps)
     return t1, t2
Пример #17
0
def rand_t1_t2(kmf, mycc):
    nkpts = mycc.nkpts
    nocc = mycc.nocc
    nmo = mycc.nmo
    nvir = nmo - nocc
    np.random.seed(1)
    t1 = (np.random.random((nkpts, nocc, nvir)) +
          np.random.random((nkpts, nocc, nvir)) * 1j - .5 - .5j)
    t2 = (np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) +
          np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) * 1j - .5 - .5j)
    kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
    Ps = kconserve_pmatrix(nkpts, kconserv)
    t2 = t2 + np.einsum('xyzijab,xyzw->yxwjiba', t2, Ps)
    return t1, t2
Пример #18
0
def rand_r1_r2_ip(kmf, mycc, kshift):
    '''Antisymmetrized 1p/2p1h operators for spin-orbitals.'''
    nkpts = mycc.nkpts
    nocc = mycc.nocc
    nmo = mycc.nmo
    nvir = nmo - nocc
    np.random.seed(1)
    r1 = (np.random.random((nocc,)) +
          np.random.random((nocc,)) * 1j - .5 - .5j)
    r2 = (np.random.random((nkpts, nkpts, nocc, nocc, nvir)) +
          np.random.random((nkpts, nkpts, nocc, nocc, nvir)) * 1j - .5 - .5j)
    kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
    Ps = kconserve_pmatrix(nkpts, kconserv)
    r2 = r2 - np.einsum('xyija,xyz->yxjia', r2, Ps[:, :, kshift, :])
    return r1, r2
Пример #19
0
def rand_r1_r2_ip(kmf, mycc, kshift):
    '''Antisymmetrized 1p/2p1h operators for spin-orbitals.'''
    nkpts = mycc.nkpts
    nocc = mycc.nocc
    nmo = mycc.nmo
    nvir = nmo - nocc
    np.random.seed(1)
    r1 = (np.random.random((nocc,)) +
          np.random.random((nocc,)) * 1j - .5 - .5j)
    r2 = (np.random.random((nkpts, nkpts, nocc, nocc, nvir)) +
          np.random.random((nkpts, nkpts, nocc, nocc, nvir)) * 1j - .5 - .5j)
    kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
    Ps = kconserve_pmatrix(nkpts, kconserv)
    r2 = r2 - np.einsum('xyija,xyz->yxjia', r2, Ps[:, :, kshift, :])
    return r1, r2
Пример #20
0
def rand_t1_t2(kmf, mycc):
    '''Antisymmetrized t1/t2 for spin-orbitals.'''
    nkpts = mycc.nkpts
    nocc = mycc.nocc
    nmo = mycc.nmo
    nvir = nmo - nocc
    np.random.seed(1)
    t1 = (np.random.random((nkpts, nocc, nvir)) +
          np.random.random((nkpts, nocc, nvir)) * 1j - .5 - .5j)
    t2 = (np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) +
          np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) * 1j - .5 - .5j)
    kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
    Ps = kconserve_pmatrix(nkpts, kconserv)
    t2 = t2 - np.einsum('xyzijab,xyzw->yxzjiab', t2, Ps)
    t2 = t2 + np.einsum('xyzijab,xyzw->yxwjiba', t2, Ps)
    return t1, t2
Пример #21
0
def rand_t1_t2(kmf, mycc):
    '''Antisymmetrized t1/t2 for spin-orbitals.'''
    nkpts = mycc.nkpts
    nocc = mycc.nocc
    nmo = mycc.nmo
    nvir = nmo - nocc
    np.random.seed(1)
    t1 = (np.random.random((nkpts, nocc, nvir)) +
          np.random.random((nkpts, nocc, nvir)) * 1j - .5 - .5j)
    t2 = (np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) +
          np.random.random((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir)) * 1j - .5 - .5j)
    kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
    Ps = kconserve_pmatrix(nkpts, kconserv)
    t2 = t2 - np.einsum('xyzijab,xyzw->yxzjiab', t2, Ps)
    t2 = t2 + np.einsum('xyzijab,xyzw->yxwjiba', t2, Ps)
    return t1, t2
Пример #22
0
def greens_e_vector_ip_rhf(cc, p, kp=None):
    nkpts, nocc, nvir = cc.t1.shape
    vector1 = np.zeros((nocc), dtype=complex)
    vector2 = np.zeros((nkpts, nkpts, nocc, nocc, nvir), dtype=complex)

    if hasattr(cc, 'l1') and cc.l1 is not None:
        l1 = cc.l1
        l2 = cc.l2
    else:
        l1 = np.conj(cc.t1)
        l2 = np.conj(cc.t2)

    if p < nocc:
        vector1[p] = -1.0
        vector1 += np.einsum('ia,a->i', l1[kp], cc.t1[kp, p, :])
        for kl in range(nkpts):
            for kc in range(nkpts):
                kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
                kd = kconserv[kp, kl, kc]
                vector1 += 2 * np.einsum('ilcd,lcd->i', \
                      l2[kp,kl,kc], cc.t2[kp,kl,kc,p,:,:,:])
                vector1 -= np.einsum('ilcd,ldc->i',   \
                      l2[kp,kl,kc], cc.t2[kp,kl,kd,p,:,:,:])

        for kj in range(nkpts):
            vector2[kp, kj, p, :, :] += -2 * l1[kj]

        for ki in range(nkpts):
            # kj == kk == kp, ki == kb
            vector2[ki, kp, :, p, :] += l1[ki]

            for kj in range(nkpts):
                # kc == kk == kp
                vector2[ki,kj] += 2*np.einsum('c,ijcb->ijb', \
                       cc.t1[kp,p,:], l2[ki,kj,kp,:,:,:,:])

                vector2[ki,kj] -= np.einsum('c,jicb->ijb', \
                       cc.t1[kp,p,:], l2[kj,ki,kp,:,:,:,:])

    else:
        vector1 += -l1[kp, :, p - nocc]
        for ki in range(nkpts):
            for kj in range(nkpts):
                vector2[ki, kj] += -2*l2[ki,kj,kp,:,:,p-nocc,:] + \
                                   l2[ki,kj,kp,:,:,:,p-nocc]

    return eom_rccsd.amplitudes_to_vector_ip(vector1, vector2)
Пример #23
0
 def __init__(self, cc, eris=None, t1=None, t2=None):
     self._cc = cc
     self.verbose = cc.verbose
     self.kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
     self.stdout = cc.stdout
     if t1 is None:
         t1 = cc.t1
     self.t1 = t1
     if t2 is None:
         t2 = cc.t2
     self.t2 = t2
     if eris is None:
         eris = cc.ao2mo()
     self.eris = eris
     self._made_shared = False
     self.made_ip_imds = False
     self.made_ea_imds = False
     self.made_ee_imds = False
Пример #24
0
 def __init__(self, cc, eris=None, t1=None, t2=None):
     self._cc = cc
     self.verbose = cc.verbose
     self.kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
     self.stdout = cc.stdout
     if t1 is None:
         t1 = cc.t1
     self.t1 = t1
     if t2 is None:
         t2 = cc.t2
     self.t2 = t2
     if eris is None:
         eris = cc.ao2mo()
     self.eris = eris
     self._made_shared = False
     self.made_ip_imds = False
     self.made_ea_imds = False
     self.made_ee_imds = False
Пример #25
0
def check_antisymm_34(cc, kpts, integrals):
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    nkpts = len(kpts)
    diff = 0.0
    for kp, kq, kr in kpts_helper.loop_kkk(nkpts):
        ks = kconserv[kp, kr, kq]
        for p in range(integrals.shape[3]):
            for q in range(integrals.shape[4]):
                for r in range(integrals.shape[5]):
                    for s in range(integrals.shape[6]):
                        pqrs = integrals[kp, kq, kr, p, q, r, s]
                        pqsr = integrals[kp, kq, ks, p, q, s, r]
                        cdiff = numpy.linalg.norm(pqrs + pqsr).real
                        if diff > 1e-5:
                            print("AS diff = %.15g" % cdiff, pqrs, pqsr, kp, kq, kr, ks, p, q, r, s)
                        diff = max(diff, cdiff)
    print("antisymmetrization : max diff = %.15g" % diff)
    if diff > 1e-5:
        print("Energy cutoff (or cell.mesh) is not enough to converge AO integrals.")
Пример #26
0
def check_antisymm_34(cc, kpts, integrals):
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    nkpts = len(kpts)
    diff = 0.0
    for kp, kq, kr in kpts_helper.loop_kkk(nkpts):
        ks = kconserv[kp, kr, kq]
        for p in range(integrals.shape[3]):
            for q in range(integrals.shape[4]):
                for r in range(integrals.shape[5]):
                    for s in range(integrals.shape[6]):
                        pqrs = integrals[kp, kq, kr, p, q, r, s]
                        pqsr = integrals[kp, kq, ks, p, q, s, r]
                        cdiff = numpy.linalg.norm(pqrs + pqsr).real
                        if diff > 1e-5:
                            print("AS diff = %.15g" % cdiff, pqrs, pqsr, kp, kq, kr, ks, p, q, r, s)
                        diff = max(diff, cdiff)
    print("antisymmetrization : max diff = %.15g" % diff)
    if diff > 1e-5:
        print("Energy cutoff (or cell.mesh) is not enough to converge AO integrals.")
Пример #27
0
    def init_amps(self, eris):
        time0 = time.clock(), time.time()
        nocc = self.nocc
        nvir = self.nmo - nocc
        nkpts = self.nkpts
        mo_e_o = [eris.mo_energy[k][:nocc] for k in range(nkpts)]
        mo_e_v = [eris.mo_energy[k][nocc:] for k in range(nkpts)]
        t1 = numpy.zeros((nkpts, nocc, nvir), dtype=numpy.complex128)
        t2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir),
                         dtype=numpy.complex128)
        self.emp2 = 0
        foo = eris.fock[:, :nocc, :nocc].copy()
        fvv = eris.fock[:, nocc:, nocc:].copy()
        fov = eris.fock[:, :nocc, nocc:].copy()
        eris_oovv = eris.oovv.copy()

        # Get location of padded elements in occupied and virtual space
        nonzero_opadding, nonzero_vpadding = padding_k_idx(self, kind="split")

        kconserv = kpts_helper.get_kconserv(self._scf.cell, self.kpts)
        for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
            kb = kconserv[ki, ka, kj]
            # For LARGE_DENOM, see t1new update above
            eia = LARGE_DENOM * numpy.ones(
                (nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_ia = numpy.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
            eia[n0_ovp_ia] = (mo_e_o[ki][:, None] - mo_e_v[ka])[n0_ovp_ia]

            ejb = LARGE_DENOM * numpy.ones(
                (nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_jb = numpy.ix_(nonzero_opadding[kj], nonzero_vpadding[kb])
            ejb[n0_ovp_jb] = (mo_e_o[kj][:, None] - mo_e_v[kb])[n0_ovp_jb]
            eijab = eia[:, None, :, None] + ejb[:, None, :]

            t2[ki, kj, ka] = eris_oovv[ki, kj, ka] / eijab

        t2 = numpy.conj(t2)
        self.emp2 = 0.25 * numpy.einsum('pqrijab,pqrijab', t2, eris_oovv).real
        self.emp2 /= nkpts

        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2.real)
        logger.timer(self, 'init mp2', *time0)
        return self.emp2, t1, t2
Пример #28
0
def check_antisymm_34(cc, kpts, integrals):
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    nkpts = len(kpts)
    diff = 0.0
    for kp in range(nkpts):
        for kq in range(nkpts):
            for kr in range(nkpts):
                ks = kconserv[kp, kr, kq]
                for p in range(integrals.shape[3]):
                    for q in range(integrals.shape[4]):
                        for r in range(integrals.shape[5]):
                            for s in range(integrals.shape[6]):
                                pqrs = integrals[kp, kq, kr, p, q, r, s]
                                pqsr = integrals[kp, kq, ks, p, q, s, r]
                                cdiff = numpy.linalg.norm(pqrs + pqsr).real
                                print("AS diff = %.15g" % cdiff, pqrs, pqsr,
                                      kp, kq, kr, ks, p, q, r, s)
                                diff = max(diff, cdiff)
    print("antisymmetrization : max diff = %.15g" % diff)
Пример #29
0
def make_tau(cc, t2, t1a, t1b, fac=1., out=None):
    nkpts, nocc, nvir = t1a.shape
    tau1 = t2.copy()
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    for ki in range(nkpts):
        for ka in range(nkpts):
            for kj in range(nkpts):
                    kb = kconserv[ki,ka,kj]
                    tmp = numpy.zeros((nocc,nocc,nvir,nvir),dtype=t2.dtype)
                    if ki == ka and kj == kb:
                        tmp += einsum('ia,jb->ijab',t1a[ki],t1b[kj])
                    if ki == kb and kj == ka:
                        tmp -= einsum('ib,ja->ijab',t1a[ki],t1b[kj])
                    if kj == ka and ki == kb:
                        tmp -= einsum('ja,ib->ijab',t1a[kj],t1b[ki])
                    if kj == kb and ki == ka:
                        tmp += einsum('jb,ia->ijab',t1a[kj],t1b[ki])
                    tau1[ki,kj,ka] += fac*0.5*tmp
    return tau1
Пример #30
0
def cc_Woooo(cc,t1,t2,eris):
    nkpts, nocc, nvir = t1.shape
    tau = make_tau(cc,t2,t1,t1)
    Wmnij = eris.oooo.copy()
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    for km in range(nkpts):
        for kn in range(nkpts):
            # Since it's not enough just to switch i and j and need to create the k_i and k_j
            # so that P(ij) switches both i,j and k_i,k_j
            #   t1[ k_j, j, e ] * v[ k_m, k_n, k_i, m, n, i, e ] -> tmp[ k_i, k_j, m, n, i, j ]
            # Here, x = k_j and y = k_i
            tmp = einsum('xje,ymnie->yxmnij',t1,eris.ooov[km,kn])
            tmp = tmp - tmp.transpose(1,0,2,3,5,4)
            for ki in range(nkpts):
                kj = kconserv[km,ki,kn]
                Wmnij[km,kn,ki] += tmp[ki,kj]
                # Here, x = k_e
                Wmnij[km,kn,ki] += 0.25*einsum('xijef,xmnef->mnij',
                        tau[ki,kj],eris.oovv[km,kn])
    return Wmnij
Пример #31
0
def cc_Wvvvv(cc,t1,t2,eris):
    nkpts, nocc, nvir = t1.shape
    eris_vovv = - eris.ovvv.transpose(1,0,2,4,3,5,6)
    tau = make_tau(cc,t2,t1,t1)
    Wabef = eris.vvvv.copy()
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    for ka in range(nkpts):
        for kb in range(nkpts):
            for ke in range(nkpts):
                km = kb
                tmp  = einsum('mb,amef->abef',t1[kb],eris_vovv[ka,km,ke])
                km = ka
                tmp -= einsum('ma,bmef->abef',t1[ka],eris_vovv[kb,km,ke])
                Wabef[ka,kb,ke] += -tmp
                # km + kn - ka = kb
                # => kn = ka - km + kb
                for km in range(nkpts):
                    kn = kconserv[ka,km,kb]
                    Wabef[ka,kb,ke] += 0.25*einsum('mnab,mnef->abef',tau[km,kn,ka],
                                                   eris.oovv[km,kn,ke])
    return Wabef
Пример #32
0
    def init_amps(self, eris):
        time0 = time.clock(), time.time()
        nocc = self.nocc
        nvir = self.nmo - nocc
        nkpts = self.nkpts
        mo_e_o = [eris.mo_energy[k][:nocc] for k in range(nkpts)]
        mo_e_v = [eris.mo_energy[k][nocc:] for k in range(nkpts)]
        t1 = numpy.zeros((nkpts, nocc, nvir), dtype=numpy.complex128)
        t2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir), dtype=numpy.complex128)
        self.emp2 = 0
        foo = eris.fock[:, :nocc, :nocc].copy()
        fvv = eris.fock[:, nocc:, nocc:].copy()
        fov = eris.fock[:, :nocc, nocc:].copy()
        eris_oovv = eris.oovv.copy()

        # Get location of padded elements in occupied and virtual space
        nonzero_opadding, nonzero_vpadding = padding_k_idx(self, kind="split")

        kconserv = kpts_helper.get_kconserv(self._scf.cell, self.kpts)
        for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
            kb = kconserv[ki, ka, kj]
            # For LARGE_DENOM, see t1new update above
            eia = LARGE_DENOM * numpy.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_ia = numpy.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
            eia[n0_ovp_ia] = (mo_e_o[ki][:,None] - mo_e_v[ka])[n0_ovp_ia]

            ejb = LARGE_DENOM * numpy.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_jb = numpy.ix_(nonzero_opadding[kj], nonzero_vpadding[kb])
            ejb[n0_ovp_jb] = (mo_e_o[kj][:,None] - mo_e_v[kb])[n0_ovp_jb]
            eijab = eia[:, None, :, None] + ejb[:, None, :]

            t2[ki, kj, ka] = eris_oovv[ki, kj, ka] / eijab

        t2 = numpy.conj(t2)
        self.emp2 = 0.25 * numpy.einsum('pqrijab,pqrijab', t2, eris_oovv).real
        self.emp2 /= nkpts

        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2.real)
        logger.timer(self, 'init mp2', *time0)
        return self.emp2, t1, t2
Пример #33
0
    def init_amps(self, eris):
        time0 = time.clock(), time.time()
        nocc = self.get_nocc()
        nvir = self.get_nmo() - nocc
        nkpts = self.nkpts
        t1 = numpy.zeros((nkpts, nocc, nvir), dtype=numpy.complex128)
        t2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir),
                         dtype=numpy.complex128)
        self.emp2 = 0
        foo = eris.fock[:, :nocc, :nocc].copy()
        fvv = eris.fock[:, nocc:, nocc:].copy()
        eris_oovv = eris.oovv.copy()
        eia = numpy.zeros((nocc, nvir))
        eijab = numpy.zeros((nocc, nocc, nvir, nvir))

        kconserv = kpts_helper.get_kconserv(self._scf.cell, self.kpts)
        for ki in range(nkpts):
            for kj in range(nkpts):
                for ka in range(nkpts):
                    kb = kconserv[ki, ka, kj]
                    for i in range(nocc):
                        for a in range(nvir):
                            eia[i, a] = foo[ki, i, i] - fvv[ka, a, a]
                            for j in range(nocc):
                                for b in range(nvir):
                                    eijab[i, j, a,
                                          b] = (foo[ki, i, i] + foo[kj, j, j] -
                                                fvv[ka, a, a] - fvv[kb, b, b])
                                    t2[ki, kj, ka, i, j, a,
                                       b] = eris_oovv[ki, kj, ka, i, j, a,
                                                      b] / eijab[i, j, a, b]

        t2 = numpy.conj(t2)
        self.emp2 = 0.25 * numpy.einsum('pqrijab,pqrijab', t2, eris_oovv).real
        self.emp2 /= nkpts
        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2.real)
        logger.timer(self, 'init mp2', *time0)
        #print("MP2 energy =", self.emp2)
        return self.emp2, t1, t2
Пример #34
0
    def test_spatial2spin(self):
        numpy.random.seed(1)
        kpts = cell.make_kpts([1, 2, 3])
        nmo = (8, 8)
        nocc = (3, 2)
        nvir = (nmo[0] - nocc[0], nmo[1] - nocc[1])
        t1, t2 = rand_t1_t2(cell, kpts, nocc, nvir)

        orbspin = numpy.zeros((len(kpts), nmo[0] + nmo[1]), dtype=int)
        orbspin[:, 1::2] = 1
        kconserv = kpts_helper.get_kconserv(cell, kpts)

        r1 = kccsd.spatial2spin(t1, orbspin, kconserv)
        r1 = kccsd.spin2spatial(r1, orbspin, kconserv)
        self.assertAlmostEqual(abs(r1[0] - t1[0]).max(), 0, 12)
        self.assertAlmostEqual(abs(r1[1] - t1[1]).max(), 0, 12)

        r2 = kccsd.spatial2spin(t2, orbspin, kconserv)
        r2 = kccsd.spin2spatial(r2, orbspin, kconserv)
        self.assertAlmostEqual(abs(r2[0] - t2[0]).max(), 0, 12)
        self.assertAlmostEqual(abs(r2[1] - t2[1]).max(), 0, 12)
        self.assertAlmostEqual(abs(r2[2] - t2[2]).max(), 0, 12)
Пример #35
0
    def init_amps(self, eris):
        time0 = time.clock(), time.time()
        nocc = self.nocc
        nvir = self.nmo - nocc
        nkpts = self.nkpts
        t1 = numpy.zeros((nkpts, nocc, nvir), dtype=numpy.complex128)
        t2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir),
                         dtype=numpy.complex128)
        self.emp2 = 0
        foo = eris.fock[:, :nocc, :nocc].copy()
        fvv = eris.fock[:, nocc:, nocc:].copy()
        fov = eris.fock[:, :nocc, nocc:].copy()
        eris_oovv = eris.oovv.copy()
        eia = numpy.zeros((nocc, nvir))
        eijab = numpy.zeros((nocc, nocc, nvir, nvir))

        kconserv = kpts_helper.get_kconserv(self._scf.cell, self.kpts)
        for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
            kb = kconserv[ki, ka, kj]
            eijab = (foo[ki].diagonal()[:, None, None, None] +
                     foo[kj].diagonal()[None, :, None, None] -
                     fvv[ka].diagonal()[None, None, :, None] -
                     fvv[kb].diagonal()[None, None, None, :])
            # Due to padding; see above discussion concerning t1new in update_amps()
            idx = numpy.where(abs(eijab) < LOOSE_ZERO_TOL)[0]
            eijab[idx] = LARGE_DENOM

            t2[ki, kj, ka] = eris_oovv[ki, kj, ka] / eijab

        t2 = numpy.conj(t2)
        self.emp2 = 0.25 * numpy.einsum('pqrijab,pqrijab', t2, eris_oovv).real
        self.emp2 /= nkpts

        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2.real)
        logger.timer(self, 'init mp2', *time0)
        return self.emp2, t1, t2
Пример #36
0
def kernel(mycc, eris, t1=None, t2=None, max_memory=2000, verbose=logger.INFO):
    '''Returns the CCSD(T) for restricted closed-shell systems with k-points.

    Note:
        Returns real part of the CCSD(T) energy, raises warning if there is
        a complex part.

    Args:
        mycc (:class:`RCCSD`): Coupled-cluster object storing results of
            a coupled-cluster calculation.
        eris (:class:`_ERIS`): Integral object holding the relevant electron-
            repulsion integrals and Fock matrix elements
        t1 (:obj:`ndarray`): t1 coupled-cluster amplitudes
        t2 (:obj:`ndarray`): t2 coupled-cluster amplitudes
        max_memory (float): Maximum memory used in calculation (NOT USED)
        verbose (int, :class:`Logger`): verbosity of calculation

    Returns:
        energy_t (float): The real-part of the k-point CCSD(T) energy.
    '''
    assert isinstance(mycc, pyscf.pbc.cc.kccsd_rhf.RCCSD)
    cpu1 = cpu0 = (time.clock(), time.time())
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(mycc.stdout, verbose)

    if t1 is None: t1 = mycc.t1
    if t2 is None: t2 = mycc.t2

    if eris is None:
        raise TypeError(
            'Electron repulsion integrals, `eris`, must be passed in '
            'to the CCSD(T) kernel or created in the cc object for '
            'the k-point CCSD(T) to run!')
    if t1 is None or t2 is None:
        raise TypeError(
            'Must pass in t1/t2 amplitudes to k-point CCSD(T)! (Maybe '
            'need to run `.ccsd()` on the ccsd object?)')

    cell = mycc._scf.cell
    kpts = mycc.kpts

    # The dtype of any local arrays that will be created
    dtype = t1.dtype

    nkpts, nocc, nvir = t1.shape

    mo_energy_occ = [eris.mo_energy[ki][:nocc] for ki in range(nkpts)]
    mo_energy_vir = [eris.mo_energy[ki][nocc:] for ki in range(nkpts)]
    mo_energy = np.asarray([eris.mo_energy[ki] for ki in range(nkpts)],
                           dtype=np.float,
                           order='C')
    fov = eris.fock[:, :nocc, nocc:]

    mo_e = mo_energy
    mo_e_o = mo_energy_occ
    mo_e_v = mo_energy_vir

    # Set up class for k-point conservation
    kconserv = kpts_helper.get_kconserv(cell, kpts)

    # Create necessary temporary eris for fast read
    feri_tmp, t2T, eris_vvop, eris_vooo_C = create_t3_eris(
        mycc, kconserv, [eris.vovv, eris.oovv, eris.ooov, t2])
    t1T = np.array([x.T for x in t1], dtype=np.complex, order='C')
    fvo = np.array([x.T for x in fov], dtype=np.complex, order='C')
    cpu1 = log.timer_debug1('CCSD(T) tmp eri creation', *cpu1)

    #def get_w_old(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1, out=None):
    #    '''Wijkabc intermediate as described in Scuseria paper before Pijkabc acts'''
    #    km = kconserv[kc, kk, kb]
    #    kf = kconserv[kk, kc, kj]
    #    ret = einsum('kjcf,fiba->abcijk', t2[kk,kj,kc,:,:,c0:c1,:], eris.vovv[kf,ki,kb,:,:,b0:b1,a0:a1].conj())
    #    ret = ret - einsum('mkbc,jima->abcijk', t2[km,kk,kb,:,:,b0:b1,c0:c1], eris.ooov[kj,ki,km,:,:,:,a0:a1].conj())
    #    return ret

    def get_w(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1):
        '''Wijkabc intermediate as described in Scuseria paper before Pijkabc acts

        Uses tranposed eris for fast data access.'''
        km = kconserv[kc, kk, kb]
        kf = kconserv[kk, kc, kj]
        out = einsum('cfjk,abif->abcijk', t2T[kc, kf, kj, c0:c1, :, :, :],
                     eris_vvop[ka, kb, ki, a0:a1, b0:b1, :, nocc:])
        out = out - einsum('cbmk,aijm->abcijk', t2T[kc, kb, km, c0:c1,
                                                    b0:b1, :, :],
                           eris_vooo_C[ka, ki, kj, a0:a1, :, :, :])
        return out

    def get_permuted_w(ki, kj, kk, ka, kb, kc, orb_indices):
        '''Pijkabc operating on Wijkabc intermediate as described in Scuseria paper'''
        a0, a1, b0, b1, c0, c1 = orb_indices
        out = get_w(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1)
        out = out + get_w(kj, kk, ki, kb, kc, ka, b0, b1, c0, c1, a0,
                          a1).transpose(2, 0, 1, 5, 3, 4)
        out = out + get_w(kk, ki, kj, kc, ka, kb, c0, c1, a0, a1, b0,
                          b1).transpose(1, 2, 0, 4, 5, 3)
        out = out + get_w(ki, kk, kj, ka, kc, kb, a0, a1, c0, c1, b0,
                          b1).transpose(0, 2, 1, 3, 5, 4)
        out = out + get_w(kk, kj, ki, kc, kb, ka, c0, c1, b0, b1, a0,
                          a1).transpose(2, 1, 0, 5, 4, 3)
        out = out + get_w(kj, ki, kk, kb, ka, kc, b0, b1, a0, a1, c0,
                          c1).transpose(1, 0, 2, 4, 3, 5)
        return out

    def get_rw(ki, kj, kk, ka, kb, kc, orb_indices):
        '''R operating on Wijkabc intermediate as described in Scuseria paper'''
        a0, a1, b0, b1, c0, c1 = orb_indices
        ret = (4. * get_permuted_w(ki, kj, kk, ka, kb, kc, orb_indices) +
               1. * get_permuted_w(kj, kk, ki, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 5, 3, 4) +
               1. * get_permuted_w(kk, ki, kj, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 4, 5, 3) -
               2. * get_permuted_w(ki, kk, kj, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 3, 5, 4) -
               2. * get_permuted_w(kk, kj, ki, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 5, 4, 3) -
               2. * get_permuted_w(kj, ki, kk, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 4, 3, 5))
        return ret

    #def get_v_old(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1):
    #    '''Vijkabc intermediate as described in Scuseria paper'''
    #    km = kconserv[ki,ka,kj]
    #    kf = kconserv[ki,ka,kj]
    #    out = np.zeros((a1-a0,b1-b0,c1-c0) + (nocc,)*3, dtype=dtype)
    #    if kk == kc:
    #        out = out + einsum('kc,ijab->abcijk', 0.5*t1[kk,:,c0:c1], eris.oovv[ki,kj,ka,:,:,a0:a1,b0:b1].conj())
    #        out = out + einsum('kc,ijab->abcijk', 0.5*fov[kk,:,c0:c1], t2[ki,kj,ka,:,:,a0:a1,b0:b1])
    #    return out

    def get_v(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1):
        '''Vijkabc intermediate as described in Scuseria paper'''
        km = kconserv[ki, ka, kj]
        kf = kconserv[ki, ka, kj]
        out = np.zeros((a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3, dtype=dtype)
        if kk == kc:
            out = out + einsum('ck,baji->abcijk', 0.5 * t1T[kk, c0:c1, :],
                               eris_vvop[kb, ka, kj, b0:b1, a0:a1, :, :nocc])
            # We see this is the same t2T term needed for the `w` contraction:
            #     einsum('cbmk,aijm->abcijk', t2T[kc,kb,km,c0:c1,b0:b1], eris_vooo_C[ka,ki,kj,a0:a1])
            #
            # For the kpoint indices [kk,ki,kj,kc,ka,kb] we have that we need
            #     t2T[kb,ka,km], where km = kconserv[kb,kj,ka]
            # The remaining k-point not used in t2T, i.e. kc, has the condition kc == kk in the case of
            # get_v.  So, we have from 3-particle conservation
            #     (kk-kc) + ki + kj - ka - kb = 0,
            # i.e. ki = km.
            out = out + einsum('ck,baij->abcijk', 0.5 * fvo[kk, c0:c1, :],
                               t2T[kb, ka, ki, b0:b1, a0:a1, :, :])
        return out

    def get_permuted_v(ki, kj, kk, ka, kb, kc, orb_indices):
        '''Pijkabc operating on Vijkabc intermediate as described in Scuseria paper'''
        a0, a1, b0, b1, c0, c1 = orb_indices
        tmp = np.zeros((a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3, dtype=dtype)
        ret = get_v(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1)
        ret = ret + get_v(kj, kk, ki, kb, kc, ka, b0, b1, c0, c1, a0,
                          a1).transpose(2, 0, 1, 5, 3, 4)
        ret = ret + get_v(kk, ki, kj, kc, ka, kb, c0, c1, a0, a1, b0,
                          b1).transpose(1, 2, 0, 4, 5, 3)
        ret = ret + get_v(ki, kk, kj, ka, kc, kb, a0, a1, c0, c1, b0,
                          b1).transpose(0, 2, 1, 3, 5, 4)
        ret = ret + get_v(kk, kj, ki, kc, kb, ka, c0, c1, b0, b1, a0,
                          a1).transpose(2, 1, 0, 5, 4, 3)
        ret = ret + get_v(kj, ki, kk, kb, ka, kc, b0, b1, a0, a1, c0,
                          c1).transpose(1, 0, 2, 4, 3, 5)
        return ret

    def contract_t3Tv(kpt_indices, orb_indices, data):
        '''Calculate t3T(ransposed) array using C driver.'''
        ki, kj, kk, ka, kb, kc = kpt_indices
        a0, a1, b0, b1, c0, c1 = orb_indices
        slices = np.array([a0, a1, b0, b1, c0, c1], dtype=np.int32)

        mo_offset = np.array([ki, kj, kk, ka, kb, kc], dtype=np.int32)

        vvop_ab = np.asarray(data[0][0], dtype=np.complex, order='C')
        vvop_ac = np.asarray(data[0][1], dtype=np.complex, order='C')
        vvop_ba = np.asarray(data[0][2], dtype=np.complex, order='C')
        vvop_bc = np.asarray(data[0][3], dtype=np.complex, order='C')
        vvop_ca = np.asarray(data[0][4], dtype=np.complex, order='C')
        vvop_cb = np.asarray(data[0][5], dtype=np.complex, order='C')

        vooo_aj = np.asarray(data[1][0], dtype=np.complex, order='C')
        vooo_ak = np.asarray(data[1][1], dtype=np.complex, order='C')
        vooo_bi = np.asarray(data[1][2], dtype=np.complex, order='C')
        vooo_bk = np.asarray(data[1][3], dtype=np.complex, order='C')
        vooo_ci = np.asarray(data[1][4], dtype=np.complex, order='C')
        vooo_cj = np.asarray(data[1][5], dtype=np.complex, order='C')

        t2T_cj = np.asarray(data[2][0], dtype=np.complex, order='C')
        t2T_bk = np.asarray(data[2][1], dtype=np.complex, order='C')
        t2T_ci = np.asarray(data[2][2], dtype=np.complex, order='C')
        t2T_ak = np.asarray(data[2][3], dtype=np.complex, order='C')
        t2T_bi = np.asarray(data[2][4], dtype=np.complex, order='C')
        t2T_aj = np.asarray(data[2][5], dtype=np.complex, order='C')

        t2T_cb = np.asarray(data[3][0], dtype=np.complex, order='C')
        t2T_bc = np.asarray(data[3][1], dtype=np.complex, order='C')
        t2T_ca = np.asarray(data[3][2], dtype=np.complex, order='C')
        t2T_ac = np.asarray(data[3][3], dtype=np.complex, order='C')
        t2T_ba = np.asarray(data[3][4], dtype=np.complex, order='C')
        t2T_ab = np.asarray(data[3][5], dtype=np.complex, order='C')

        data = [
            vvop_ab, vvop_ac, vvop_ba, vvop_bc, vvop_ca, vvop_cb, vooo_aj,
            vooo_ak, vooo_bi, vooo_bk, vooo_ci, vooo_cj, t2T_cj, t2T_cb,
            t2T_bk, t2T_bc, t2T_ci, t2T_ca, t2T_ak, t2T_ac, t2T_bi, t2T_ba,
            t2T_aj, t2T_ab
        ]
        data_ptrs = [x.ctypes.data_as(ctypes.c_void_p) for x in data]
        data_ptrs = (ctypes.c_void_p * 24)(*data_ptrs)

        a0, a1, b0, b1, c0, c1 = task
        t3Tw = np.empty((a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                        dtype=np.complex,
                        order='C')
        t3Tv = np.empty((a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                        dtype=np.complex,
                        order='C')

        drv = _ccsd.libcc.CCsd_zcontract_t3T
        drv(t3Tw.ctypes.data_as(ctypes.c_void_p),
            t3Tv.ctypes.data_as(ctypes.c_void_p),
            mo_e.ctypes.data_as(ctypes.c_void_p),
            t1T.ctypes.data_as(ctypes.c_void_p),
            fvo.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(nocc),
            ctypes.c_int(nvir), ctypes.c_int(nkpts),
            mo_offset.ctypes.data_as(ctypes.c_void_p),
            slices.ctypes.data_as(ctypes.c_void_p), data_ptrs)
        return t3Tw, t3Tv

    def get_data(kpt_indices):
        idx_args = get_data_slices(kpt_indices, task, kconserv)
        vvop_indices, vooo_indices, t2T_vvop_indices, t2T_vooo_indices = idx_args
        vvop_data = [eris_vvop[tuple(x)] for x in vvop_indices]
        vooo_data = [eris_vooo_C[tuple(x)] for x in vooo_indices]
        t2T_vvop_data = [t2T[tuple(x)] for x in t2T_vvop_indices]
        t2T_vooo_data = [t2T[tuple(x)] for x in t2T_vooo_indices]
        data = [vvop_data, vooo_data, t2T_vvop_data, t2T_vooo_data]
        return data

    energy_t = 0.0

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(mycc, kind="split")

    mem_now = lib.current_memory()[0]
    max_memory = max(0, mycc.max_memory - mem_now)
    blkmin = 4
    # temporary t3 array is size:    2 * nkpts**3 * blksize**3 * nocc**3 * 16
    vir_blksize = min(
        nvir,
        max(blkmin,
            int((max_memory * .9e6 / 16 / nocc**3 / nkpts**3 / 2)**(1. / 3))))
    tasks = []
    log.debug('max_memory %d MB (%d MB in use)', max_memory, mem_now)
    log.debug('virtual blksize = %d (nvir = %d)', nvir, vir_blksize)
    for a0, a1 in lib.prange(0, nvir, vir_blksize):
        for b0, b1 in lib.prange(0, nvir, vir_blksize):
            for c0, c1 in lib.prange(0, nvir, vir_blksize):
                tasks.append((a0, a1, b0, b1, c0, c1))

    for ka in range(nkpts):
        for kb in range(ka + 1):
            for task_id, task in enumerate(tasks):
                a0, a1, b0, b1, c0, c1 = task
                my_permuted_w = np.zeros(
                    (nkpts, ) * 3 + (a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                    dtype=dtype)
                my_permuted_v = np.zeros(
                    (nkpts, ) * 3 + (a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                    dtype=dtype)
                for ki, kj, kk in product(range(nkpts), repeat=3):
                    # Find momentum conservation condition for triples
                    # amplitude t3ijkabc
                    kc = kpts_helper.get_kconserv3(cell, kpts,
                                                   [ki, kj, kk, ka, kb])
                    if not (ka >= kb and kb >= kc):
                        continue

                    kpt_indices = [ki, kj, kk, ka, kb, kc]
                    data = get_data(kpt_indices)
                    t3Tw, t3Tv = contract_t3Tv(kpt_indices, task, data)
                    my_permuted_w[ki, kj, kk] = t3Tw
                    my_permuted_v[ki, kj, kk] = t3Tv
                    #my_permuted_w[ki,kj,kk] = get_permuted_w(ki,kj,kk,ka,kb,kc,task)
                    #my_permuted_v[ki,kj,kk] = get_permuted_v(ki,kj,kk,ka,kb,kc,task)

                for ki, kj, kk in product(range(nkpts), repeat=3):
                    # eigenvalue denominator: e(i) + e(j) + e(k)
                    eijk = _get_epqr([0, nocc, ki, mo_e_o, nonzero_opadding],
                                     [0, nocc, kj, mo_e_o, nonzero_opadding],
                                     [0, nocc, kk, mo_e_o, nonzero_opadding])

                    # Find momentum conservation condition for triples
                    # amplitude t3ijkabc
                    kc = kpts_helper.get_kconserv3(cell, kpts,
                                                   [ki, kj, kk, ka, kb])
                    if not (ka >= kb and kb >= kc):
                        continue

                    if ka == kb and kb == kc:
                        symm_kpt = 1.
                    elif ka == kb or kb == kc:
                        symm_kpt = 3.
                    else:
                        symm_kpt = 6.

                    eabc = _get_epqr([a0, a1, ka, mo_e_v, nonzero_vpadding],
                                     [b0, b1, kb, mo_e_v, nonzero_vpadding],
                                     [c0, c1, kc, mo_e_v, nonzero_vpadding],
                                     fac=[-1., -1., -1.])
                    eijkabc = (eijk[None, None, None, :, :, :] +
                               eabc[:, :, :, None, None, None])

                    pwijk = my_permuted_w[ki, kj, kk] + my_permuted_v[ki, kj,
                                                                      kk]
                    rwijk = (
                        4. * my_permuted_w[ki, kj, kk] + 1. *
                        my_permuted_w[kj, kk, ki].transpose(0, 1, 2, 5, 3, 4) +
                        1. *
                        my_permuted_w[kk, ki, kj].transpose(0, 1, 2, 4, 5, 3) -
                        2. *
                        my_permuted_w[ki, kk, kj].transpose(0, 1, 2, 3, 5, 4) -
                        2. *
                        my_permuted_w[kk, kj, ki].transpose(0, 1, 2, 5, 4, 3) -
                        2. *
                        my_permuted_w[kj, ki, kk].transpose(0, 1, 2, 4, 3, 5))
                    rwijk = rwijk / eijkabc
                    energy_t += symm_kpt * einsum('abcijk,abcijk', rwijk,
                                                  pwijk.conj())

    energy_t *= (1. / 3)
    energy_t /= nkpts

    if abs(energy_t.imag) > 1e-4:
        log.warn('Non-zero imaginary part of CCSD(T) energy was found %s',
                 energy_t.imag)
    log.timer('CCSD(T)', *cpu0)
    log.note('CCSD(T) correction per cell = %.15g', energy_t.real)
    log.note('CCSD(T) correction per cell (imag) = %.15g', energy_t.imag)
    return energy_t.real
Пример #37
0
def kernel(mycc, eris, t1=None, t2=None, max_memory=2000, verbose=logger.INFO):
    '''Returns the CCSD(T) for restricted closed-shell systems with k-points.

    Note:
        Returns real part of the CCSD(T) energy, raises warning if there is
        a complex part.

    Args:
        mycc (:class:`RCCSD`): Coupled-cluster object storing results of
            a coupled-cluster calculation.
        eris (:class:`_ERIS`): Integral object holding the relevant electron-
            repulsion integrals and Fock matrix elements
        t1 (:obj:`ndarray`): t1 coupled-cluster amplitudes
        t2 (:obj:`ndarray`): t2 coupled-cluster amplitudes
        max_memory (float): Maximum memory used in calculation (NOT USED)
        verbose (int, :class:`Logger`): verbosity of calculation

    Returns:
        energy_t (float): The real-part of the k-point CCSD(T) energy.
    '''
    assert isinstance(mycc, pyscf.pbc.cc.kccsd_rhf.RCCSD)
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(mycc.stdout, verbose)

    if t1 is None: t1 = mycc.t1
    if t2 is None: t2 = mycc.t2

    if eris is None:
        raise TypeError('Electron repulsion integrals, `eris`, must be passed in '
                        'to the CCSD(T) kernel or created in the cc object for '
                        'the k-point CCSD(T) to run!')
    if t1 is None or t2 is None:
        raise TypeError('Must pass in t1/t2 amplitudes to k-point CCSD(T)! (Maybe '
                        'need to run `.ccsd()` on the ccsd object?)')

    cell = mycc._scf.cell
    kpts = mycc.kpts

    # The dtype of any local arrays that will be created
    dtype = t1.dtype

    nkpts, nocc, nvir = t1.shape

    mo_energy_occ = [eris.mo_energy[ki][:nocc] for ki in range(nkpts)]
    mo_energy_vir = [eris.mo_energy[ki][nocc:] for ki in range(nkpts)]
    fov = eris.fock[:, :nocc, nocc:]

    # Set up class for k-point conservation
    kconserv = kpts_helper.get_kconserv(cell, kpts)

    def get_w(ki, kj, kk, ka, kb, kc, a, b, c):
        '''Wijkabc intermediate as described in Scuseria paper before Pijkabc acts'''
        km = kconserv[ki, ka, kj]
        kf = kconserv[kk, kc, kj]
        ret = einsum('kjf,fi->ijk', t2[kk, kj, kc, :, :, c, :], eris.vovv[kf, ki, kb, :, :, b, a].conj())
        ret = ret - einsum('mk,jim->ijk', t2[km, kk, kb, :, :, b, c], eris.ooov[kj, ki, km, :, :, :, a].conj())
        return ret

    def get_permuted_w(ki, kj, kk, ka, kb, kc, a, b, c):
        '''Pijkabc operating on Wijkabc intermediate as described in Scuseria paper'''
        ret = get_w(ki, kj, kk, ka, kb, kc, a, b, c)
        ret = ret + get_w(kj, kk, ki, kb, kc, ka, b, c, a).transpose(2, 0, 1)
        ret = ret + get_w(kk, ki, kj, kc, ka, kb, c, a, b).transpose(1, 2, 0)
        ret = ret + get_w(ki, kk, kj, ka, kc, kb, a, c, b).transpose(0, 2, 1)
        ret = ret + get_w(kk, kj, ki, kc, kb, ka, c, b, a).transpose(2, 1, 0)
        ret = ret + get_w(kj, ki, kk, kb, ka, kc, b, a, c).transpose(1, 0, 2)
        return ret

    def get_rw(ki, kj, kk, ka, kb, kc, a, b, c):
        '''R operating on Wijkabc intermediate as described in Scuseria paper'''
        ret = (4. * get_permuted_w(ki, kj, kk, ka, kb, kc, a, b, c) +
               1. * get_permuted_w(kk, ki, kj, ka, kb, kc, a, b, c).transpose(1, 2, 0) +
               1. * get_permuted_w(kj, kk, ki, ka, kb, kc, a, b, c).transpose(2, 0, 1) -
               2. * get_permuted_w(kk, kj, ki, ka, kb, kc, a, b, c).transpose(2, 1, 0) -
               2. * get_permuted_w(ki, kk, kj, ka, kb, kc, a, b, c).transpose(0, 2, 1) -
               2. * get_permuted_w(kj, ki, kk, ka, kb, kc, a, b, c).transpose(1, 0, 2))
        return ret

    def get_v(ki, kj, kk, ka, kb, kc, a, b, c):
        '''Vijkabc intermediate as described in Scuseria paper'''
        km = kconserv[ki, ka, kj]
        kf = kconserv[ki, ka, kj]
        ret = np.zeros((nocc, nocc, nocc), dtype=dtype)
        if kk == kc:
            ret = ret + einsum('k,ij->ijk', t1[kk, :, c], eris.oovv[ki, kj, ka, :, :, a, b].conj())
            ret = ret + einsum('k,ij->ijk', fov[kk, :, c], t2[ki, kj, ka, :, :, a, b])
        return ret

    def get_permuted_v(ki, kj, kk, ka, kb, kc, a, b, c):
        '''Pijkabc operating on Vijkabc intermediate as described in Scuseria paper'''
        ret = get_v(ki, kj, kk, ka, kb, kc, a, b, c)
        ret = ret + get_v(kj, kk, ki, kb, kc, ka, b, c, a).transpose(2, 0, 1)
        ret = ret + get_v(kk, ki, kj, kc, ka, kb, c, a, b).transpose(1, 2, 0)
        ret = ret + get_v(ki, kk, kj, ka, kc, kb, a, c, b).transpose(0, 2, 1)
        ret = ret + get_v(kk, kj, ki, kc, kb, ka, c, b, a).transpose(2, 1, 0)
        ret = ret + get_v(kj, ki, kk, kb, ka, kc, b, a, c).transpose(1, 0, 2)
        return ret

    energy_t = 0.0

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(mycc, kind="split")

    for ki in range(nkpts):
        for kj in range(ki + 1):
            for kk in range(kj + 1):
                # eigenvalue denominator: e(i) + e(j) + e(k)
                eijk = LARGE_DENOM * np.ones((nocc,)*3, dtype=mo_energy_occ[0].dtype)
                n0_ovp_ijk = np.ix_(nonzero_opadding[ki], nonzero_opadding[kj], nonzero_opadding[kk])
                eijk[n0_ovp_ijk] = lib.direct_sum('i,j,k->ijk', mo_energy_occ[ki], mo_energy_occ[kj], mo_energy_occ[kk])[n0_ovp_ijk]

                for ka in range(nkpts):
                    for kb in range(nkpts):
                        # Find momentum conservation condition for triples
                        # amplitude t3ijkabc
                        kc = kpts_helper.get_kconserv3(cell, kpts, [ki, kj, kk, ka, kb])

                        ia_index = ki * nkpts + ka
                        jb_index = kj * nkpts + kb
                        kc_index = kk * nkpts + kc
                        if not (ia_index >= jb_index and jb_index >= kc_index):
                            continue

                        # Factors to include for permutational symmetry among k-points
                        if (ia_index == jb_index and jb_index == kc_index):
                            symm_kpt = 1.  # only one unique [ia, jb, kc] index
                        elif (ia_index == jb_index or jb_index == kc_index):
                            symm_kpt = 3.  # three unique permutations of [ia, jb, kc]
                        else:
                            symm_kpt = 6.  # six unique permutations of [ia, jb, kc]

                        # Determine the a, b, c indices we will loop over as
                        # determined by the k-point symmetry.
                        abc_indices = cartesian_prod([range(nvir)] * 3)
                        symm_3d = symm_2d_ab = symm_2d_bc = False
                        if ia_index == jb_index == kc_index:  # ka == kb == kc
                            symm_3d = True
                            abc_indices = tril_product(range(nvir), repeat=3, tril_idx=[0, 1, 2])  # loop a >= b >= c
                            symm_3d = True
                        elif ia_index == jb_index:  # ka == kb
                            abc_indices = tril_product(range(nvir), repeat=3, tril_idx=[0, 1])  # loop a >= b
                            symm_2d_ab = True
                        elif jb_index == kc_index:
                            abc_indices = tril_product(range(nvir), repeat=3, tril_idx=[1, 2])  # loop b >= c
                            symm_2d_bc = True

                        for a, b, c in abc_indices:
                            # Form energy denominator
                            # Make sure we only loop over non-frozen and/or padded elements
                            if( not ((a in nonzero_vpadding[ka]) and (b in nonzero_vpadding[kb]) and (c in nonzero_vpadding[kc]))):
                                continue
                            eijkabc = (eijk - mo_energy_vir[ka][a] - mo_energy_vir[kb][b] - mo_energy_vir[kc][c])

                            # See symm_3d and abc_indices above for description of factors
                            symm_abc = 1.
                            if symm_3d:
                                if a == b == c:
                                    symm_abc = 1.
                                elif a == b or b == c:
                                    symm_abc = 3.
                                else:
                                    symm_abc = 6.
                            elif symm_2d_ab:
                                if a == b:
                                    symm_abc = 1.
                                else:
                                    symm_abc = 2.
                            elif symm_2d_bc:
                                if b == c:
                                    symm_abc = 1.
                                else:
                                    symm_abc = 2.

                            # The simplest written algorithm can be accomplished with the following four lines

                            #pwijk = (       get_permuted_w(ki, kj, kk, ka, kb, kc, a, b, c) +
                            #          0.5 * get_permuted_v(ki, kj, kk, ka, kb, kc, a, b, c) )
                            #rwijk = get_rw(ki, kj, kk, ka, kb, kc, a, b, c) / eijkabc
                            #energy_t += symm_fac * einsum('ijk,ijk', pwijk, rwijk.conj())

                            # Creating permuted W_ijkabc intermediate
                            w_int0 = get_w(ki, kj, kk, ka, kb, kc, a, b, c)
                            w_int1 = get_w(kj, kk, ki, kb, kc, ka, b, c, a).transpose(2, 0, 1)
                            w_int2 = get_w(kk, ki, kj, kc, ka, kb, c, a, b).transpose(1, 2, 0)
                            w_int3 = get_w(ki, kk, kj, ka, kc, kb, a, c, b).transpose(0, 2, 1)
                            w_int4 = get_w(kk, kj, ki, kc, kb, ka, c, b, a).transpose(2, 1, 0)
                            w_int5 = get_w(kj, ki, kk, kb, ka, kc, b, a, c).transpose(1, 0, 2)

                            # Creating permuted V_ijkabc intermediate
                            v_int0 = get_v(ki, kj, kk, ka, kb, kc, a, b, c)
                            v_int1 = get_v(kj, kk, ki, kb, kc, ka, b, c, a).transpose(2, 0, 1)
                            v_int2 = get_v(kk, ki, kj, kc, ka, kb, c, a, b).transpose(1, 2, 0)
                            v_int3 = get_v(ki, kk, kj, ka, kc, kb, a, c, b).transpose(0, 2, 1)
                            v_int4 = get_v(kk, kj, ki, kc, kb, ka, c, b, a).transpose(2, 1, 0)
                            v_int5 = get_v(kj, ki, kk, kb, ka, kc, b, a, c).transpose(1, 0, 2)

                            # Creating permuted W_ijkabc + 0.5 * V_ijkabc intermediate
                            pwijk = w_int0 + 0.5 * v_int0
                            pwijk += w_int1 + 0.5 * v_int1
                            pwijk += w_int2 + 0.5 * v_int2
                            pwijk += w_int3 + 0.5 * v_int3
                            pwijk += w_int4 + 0.5 * v_int4
                            pwijk += w_int5 + 0.5 * v_int5

                            # Creating R[W] intermediate
                            rwijk = np.zeros((nocc, nocc, nocc), dtype=dtype)

                            # Adding in contribution 4. * P[(i, j, k) -> (i, j, k)]
                            rwijk += 4. * w_int0
                            rwijk += 4. * w_int1
                            rwijk += 4. * w_int2
                            rwijk += 4. * w_int3
                            rwijk += 4. * w_int4
                            rwijk += 4. * w_int5

                            # Adding in contribution 1. * P[(i, j, k) -> (k, i, j)]
                            rwijk += 1. * get_w(kk, ki, kj, ka, kb, kc, a, b, c).transpose(1, 2, 0)
                            rwijk += 1. * get_w(ki, kj, kk, kb, kc, ka, b, c, a).transpose(2, 0, 1).transpose(1, 2, 0)
                            rwijk += 1. * get_w(kj, kk, ki, kc, ka, kb, c, a, b).transpose(1, 2, 0).transpose(1, 2, 0)
                            rwijk += 1. * get_w(kk, kj, ki, ka, kc, kb, a, c, b).transpose(0, 2, 1).transpose(1, 2, 0)
                            rwijk += 1. * get_w(kj, ki, kk, kc, kb, ka, c, b, a).transpose(2, 1, 0).transpose(1, 2, 0)
                            rwijk += 1. * get_w(ki, kk, kj, kb, ka, kc, b, a, c).transpose(1, 0, 2).transpose(1, 2, 0)

                            # Adding in contribution 1. * P[(i, j, k) -> (j, k, i)]
                            rwijk += 1. * get_w(kj, kk, ki, ka, kb, kc, a, b, c).transpose(2, 0, 1)
                            rwijk += 1. * get_w(kk, ki, kj, kb, kc, ka, b, c, a).transpose(2, 0, 1).transpose(2, 0, 1)
                            rwijk += 1. * get_w(ki, kj, kk, kc, ka, kb, c, a, b).transpose(1, 2, 0).transpose(2, 0, 1)
                            rwijk += 1. * get_w(kj, ki, kk, ka, kc, kb, a, c, b).transpose(0, 2, 1).transpose(2, 0, 1)
                            rwijk += 1. * get_w(ki, kk, kj, kc, kb, ka, c, b, a).transpose(2, 1, 0).transpose(2, 0, 1)
                            rwijk += 1. * get_w(kk, kj, ki, kb, ka, kc, b, a, c).transpose(1, 0, 2).transpose(2, 0, 1)

                            # Adding in contribution -2. * P[(i, j, k) -> (k, j, i)]
                            rwijk += -2. * get_w(kk, kj, ki, ka, kb, kc, a, b, c).transpose(2, 1, 0)
                            rwijk += -2. * get_w(kj, ki, kk, kb, kc, ka, b, c, a).transpose(2, 0, 1).transpose(2, 1, 0)
                            rwijk += -2. * get_w(ki, kk, kj, kc, ka, kb, c, a, b).transpose(1, 2, 0).transpose(2, 1, 0)
                            rwijk += -2. * get_w(kk, ki, kj, ka, kc, kb, a, c, b).transpose(0, 2, 1).transpose(2, 1, 0)
                            rwijk += -2. * get_w(ki, kj, kk, kc, kb, ka, c, b, a).transpose(2, 1, 0).transpose(2, 1, 0)
                            rwijk += -2. * get_w(kj, kk, ki, kb, ka, kc, b, a, c).transpose(1, 0, 2).transpose(2, 1, 0)

                            # Adding in contribution -2. * P[(i, j, k) -> (i, k, j)]
                            rwijk += -2. * get_w(ki, kk, kj, ka, kb, kc, a, b, c).transpose(0, 2, 1)
                            rwijk += -2. * get_w(kk, kj, ki, kb, kc, ka, b, c, a).transpose(2, 0, 1).transpose(0, 2, 1)
                            rwijk += -2. * get_w(kj, ki, kk, kc, ka, kb, c, a, b).transpose(1, 2, 0).transpose(0, 2, 1)
                            rwijk += -2. * get_w(ki, kj, kk, ka, kc, kb, a, c, b).transpose(0, 2, 1).transpose(0, 2, 1)
                            rwijk += -2. * get_w(kj, kk, ki, kc, kb, ka, c, b, a).transpose(2, 1, 0).transpose(0, 2, 1)
                            rwijk += -2. * get_w(kk, ki, kj, kb, ka, kc, b, a, c).transpose(1, 0, 2).transpose(0, 2, 1)

                            # Adding in contribution -2. * P[(i, j, k) -> (j, i, k)]
                            rwijk += -2. * get_w(kj, ki, kk, ka, kb, kc, a, b, c).transpose(1, 0, 2)
                            rwijk += -2. * get_w(ki, kk, kj, kb, kc, ka, b, c, a).transpose(2, 0, 1).transpose(1, 0, 2)
                            rwijk += -2. * get_w(kk, kj, ki, kc, ka, kb, c, a, b).transpose(1, 2, 0).transpose(1, 0, 2)
                            rwijk += -2. * get_w(kj, kk, ki, ka, kc, kb, a, c, b).transpose(0, 2, 1).transpose(1, 0, 2)
                            rwijk += -2. * get_w(kk, ki, kj, kc, kb, ka, c, b, a).transpose(2, 1, 0).transpose(1, 0, 2)
                            rwijk += -2. * get_w(ki, kj, kk, kb, ka, kc, b, a, c).transpose(1, 0, 2).transpose(1, 0, 2)

                            rwijk /= eijkabc

                            energy_t += symm_abc * symm_kpt * einsum('ijk,ijk', pwijk, rwijk.conj())

    energy_t *= (1. / 3)
    energy_t /= nkpts

    if abs(energy_t.imag) > 1e-4:
        log.warn('Non-zero imaginary part of CCSD(T) energy was found %s', energy_t.imag)
    log.note('CCSD(T) correction per cell = %.15g', energy_t.real)
    log.note('CCSD(T) correction per cell (imag) = %.15g', energy_t.imag)
    return energy_t.real
Пример #38
0
def get_ea_identity(kshift,nocc_a,nocc_b,nvir_a,nvir_b,nkpts,I,cc):
    count = 0
    indices = []
    nocc = nocc_a + nocc_b
    nvir = nvir_a + nvir_b
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)

    # a
    for i in range(nvir_a):
        indices.append(i)
    # b
    offset = nvir_a
    for i in range(nvir_b):
        indices.append(i + offset)
    offset = nvir
    for kj in range(nkpts):
        for ka in range(nkpts):
            # aaa
            for j in range(nocc_a):
                for a in range(nvir_a):
                    for b in range(nvir_a):
                        r1a = np.zeros(nvir_a,dtype=complex)
                        r1b = np.zeros(nvir_b,dtype=complex)
                        r2aaa = np.zeros((nkpts,nkpts,nocc_a,nvir_a,nvir_a),dtype=complex)
                        r2aba = np.zeros((nkpts,nkpts,nocc_a,nvir_b,nvir_a),dtype=complex)
                        r2bab = np.zeros((nkpts,nkpts,nocc_b,nvir_a,nvir_b),dtype=complex)
                        r2bbb = np.zeros((nkpts,nkpts,nocc_b,nvir_b,nvir_b),dtype=complex)
                        if b >= a:
                            pass
                        else:
                            kb = kconserv[kshift,ka,kj]
                            r2aaa[kj,ka,j,a,b] = 1.0
                            r2aaa[kj,kb,j,b,a] = -1.0
                            I[:,nvir + count] = kccsd_uhf.amplitudes_to_vector_ea(
                                    (r1a,r1b),(r2aaa,r2aba,r2bab,r2bbb))
                            indices.append(offset + count)
                        count = count + 1
    for kj in range(nkpts):
        for ka in range(nkpts):
            # aba
            for j in range(nocc_a):
                for a in range(nvir_b):
                    for b in range(nvir_a):
                        r1a = np.zeros(nvir_a,dtype=complex)
                        r1b = np.zeros(nvir_b,dtype=complex)
                        r2aaa = np.zeros((nkpts,nkpts,nocc_a,nvir_a,nvir_a),dtype=complex)
                        r2aba = np.zeros((nkpts,nkpts,nocc_a,nvir_b,nvir_a),dtype=complex)
                        r2bab = np.zeros((nkpts,nkpts,nocc_b,nvir_a,nvir_b),dtype=complex)
                        r2bbb = np.zeros((nkpts,nkpts,nocc_b,nvir_a,nvir_b),dtype=complex)
                        r2aba[kj,ka,j,a,b] = 1.0
                        I[:,nvir + count] = kccsd_uhf.amplitudes_to_vector_ea(
                                (r1a,r1b),(r2aaa,r2aba,r2bab,r2bbb))
                        indices.append(offset + count)
                        count = count + 1
    for kj in range(nkpts):
        for ka in range(nkpts):
            # bab
            for j in range(nocc_b):
                for a in range(nvir_a):
                    for b in range(nvir_b):
                        r1a = np.zeros(nvir_a,dtype=complex)
                        r1b = np.zeros(nvir_b,dtype=complex)
                        r2aaa = np.zeros((nkpts,nkpts,nocc_a,nvir_a,nvir_a),dtype=complex)
                        r2aba = np.zeros((nkpts,nkpts,nocc_a,nvir_b,nvir_a),dtype=complex)
                        r2bab = np.zeros((nkpts,nkpts,nocc_b,nvir_a,nvir_b),dtype=complex)
                        r2bbb = np.zeros((nkpts,nkpts,nocc_b,nvir_a,nvir_b),dtype=complex)
                        r2bab[kj,ka,j,a,b] = 1.0
                        I[:,nvir + count] = kccsd_uhf.amplitudes_to_vector_ea(
                                (r1a,r1b),(r2aaa,r2aba,r2bab,r2bbb))
                        indices.append(offset + count)
                        count = count + 1
    for kj in range(nkpts):
        for ka in range(nkpts):
            # bbb
            for j in range(nocc_b):
                for a in range(nvir_b):
                    for b in range(nvir_b):
                        r1a = np.zeros(nvir_a,dtype=complex)
                        r1b = np.zeros(nvir_b,dtype=complex)
                        r2aaa = np.zeros((nkpts,nkpts,nocc_a,nvir_a,nvir_a),dtype=complex)
                        r2aba = np.zeros((nkpts,nkpts,nocc_a,nvir_b,nvir_a),dtype=complex)
                        r2bab = np.zeros((nkpts,nkpts,nocc_b,nvir_a,nvir_b),dtype=complex)
                        r2bbb = np.zeros((nkpts,nkpts,nocc_b,nvir_b,nvir_b),dtype=complex)
                        if b >= a:
                            pass
                        else:
                            kb = kconserv[kshift,ka,kj]
                            r2bbb[kj,ka,j,a,b] = 1.0
                            r2bbb[kj,kb,j,b,a] = -1.0
                            I[:,nvir + count] = kccsd_uhf.amplitudes_to_vector_ea(
                                    (r1a,r1b),(r2aaa,r2aba,r2bab,r2bbb))
                            indices.append(offset + count)
                        count = count + 1
    return indices
Пример #39
0
def ao2mo_7d(mydf, mo_coeff_kpts, kpts=None, factor=1, out=None):
    cell = mydf.cell
    if kpts is None:
        kpts = mydf.kpts
    nkpts = len(kpts)

    if isinstance(mo_coeff_kpts, numpy.ndarray) and mo_coeff_kpts.ndim == 3:
        mo_coeff_kpts = [mo_coeff_kpts] * 4
    else:
        mo_coeff_kpts = list(mo_coeff_kpts)

    # Shape of the orbitals can be different on different k-points. The
    # orbital coefficients must be formatted (padded by zeros) so that the
    # shape of the orbital coefficients are the same on all k-points. This can
    # be achieved by calling pbc.mp.kmp2.padded_mo_coeff function
    nmoi, nmoj, nmok, nmol = [x.shape[2] for x in mo_coeff_kpts]
    eri_shape = (nkpts, nkpts, nkpts, nmoi, nmoj, nmok, nmol)
    if gamma_point(kpts):
        dtype = numpy.result_type(*mo_coeff_kpts)
    else:
        dtype = numpy.complex128

    if out is None:
        out = numpy.empty(eri_shape, dtype=dtype)
    else:
        assert(out.shape == eri_shape)

    kptij_lst = numpy.array([(ki, kj) for ki in kpts for kj in kpts])
    kptis_lst = kptij_lst[:,0]
    kptjs_lst = kptij_lst[:,1]
    kpt_ji = kptjs_lst - kptis_lst
    uniq_kpts, uniq_index, uniq_inverse = unique(kpt_ji)

    nao = cell.nao_nr()
    max_memory = max(2000, mydf.max_memory-lib.current_memory()[0]-nao**4*16/1e6) * .5

    tao = []
    ao_loc = None
    kconserv = kpts_helper.get_kconserv(cell, kpts)
    for uniq_id, kpt in enumerate(uniq_kpts):
        adapted_ji_idx = numpy.where(uniq_inverse == uniq_id)[0]

        for ji, ji_idx in enumerate(adapted_ji_idx):
            ki = ji_idx // nkpts
            kj = ji_idx % nkpts

            moij, ijslice = _conc_mos(mo_coeff_kpts[0][ki], mo_coeff_kpts[1][kj])[2:]
            zij = []
            for LpqR, LpqI, sign in mydf.sr_loop(kpts[[ki,kj]], max_memory, False, mydf.blockdim):
                zij.append(_ao2mo.r_e2(LpqR+LpqI*1j, moij, ijslice, tao, ao_loc))

            for kk in range(nkpts):
                kl = kconserv[ki, kj, kk]
                mokl, klslice = _conc_mos(mo_coeff_kpts[2][kk], mo_coeff_kpts[3][kl])[2:]
                eri_mo = numpy.zeros((nmoi*nmoj,nmok*nmol), dtype=numpy.complex128)
                for i, (LrsR, LrsI, sign) in \
                        enumerate(mydf.sr_loop(kpts[[kk,kl]], max_memory, False, mydf.blockdim)):
                    zkl = _ao2mo.r_e2(LrsR+LrsI*1j, mokl, klslice, tao, ao_loc)
                    lib.dot(zij[i].T, zkl, sign*factor, eri_mo, 1)

                if dtype == numpy.double:
                    eri_mo = eri_mo.real
                out[ki,kj,kk] = eri_mo.reshape(eri_shape[3:])
    return out
Пример #40
0
def ao2mo_7d(mydf, mo_coeff_kpts, kpts=None, factor=1, out=None):
    cell = mydf.cell
    if kpts is None:
        kpts = mydf.kpts
    nkpts = len(kpts)

    if isinstance(mo_coeff_kpts, numpy.ndarray) and mo_coeff_kpts.ndim == 3:
        mo_coeff_kpts = [mo_coeff_kpts] * 4
    else:
        mo_coeff_kpts = list(mo_coeff_kpts)

    # Shape of the orbitals can be different on different k-points. The
    # orbital coefficients must be formatted (padded by zeros) so that the
    # shape of the orbital coefficients are the same on all k-points. This can
    # be achieved by calling pbc.mp.kmp2.padded_mo_coeff function
    nmoi, nmoj, nmok, nmol = [x.shape[2] for x in mo_coeff_kpts]
    eri_shape = (nkpts, nkpts, nkpts, nmoi, nmoj, nmok, nmol)
    if gamma_point(kpts):
        dtype = numpy.result_type(*mo_coeff_kpts)
    else:
        dtype = numpy.complex128

    if out is None:
        out = numpy.empty(eri_shape, dtype=dtype)
    else:
        assert(out.shape == eri_shape)

    kptij_lst = numpy.array([(ki, kj) for ki in kpts for kj in kpts])
    kptis_lst = kptij_lst[:,0]
    kptjs_lst = kptij_lst[:,1]
    kpt_ji = kptjs_lst - kptis_lst
    uniq_kpts, uniq_index, uniq_inverse = unique(kpt_ji)
    ngrids = numpy.prod(mydf.mesh)

    nao = cell.nao_nr()
    max_memory = max(2000, mydf.max_memory-lib.current_memory()[0]-nao**4*16/1e6) * .5

    fswap = lib.H5TmpFile()
    tao = []
    ao_loc = None
    kconserv = kpts_helper.get_kconserv(cell, kpts)
    for uniq_id, kpt in enumerate(uniq_kpts):
        q = uniq_kpts[uniq_id]
        adapted_ji_idx = numpy.where(uniq_inverse == uniq_id)[0]

        kptjs = kptjs_lst[adapted_ji_idx]
        coulG = mydf.weighted_coulG(q, False, mydf.mesh)
        coulG *= factor

        moij_list = []
        ijslice_list = []
        for ji, ji_idx in enumerate(adapted_ji_idx):
            ki = ji_idx // nkpts
            kj = ji_idx % nkpts
            moij, ijslice = _conc_mos(mo_coeff_kpts[0][ki], mo_coeff_kpts[1][kj])[2:]
            moij_list.append(moij)
            ijslice_list.append(ijslice)
            fswap.create_dataset('zij/'+str(ji), (ngrids,nmoi*nmoj), 'D')

        for aoaoks, p0, p1 in mydf.ft_loop(mydf.mesh, q, kptjs):
            for ji, aoao in enumerate(aoaoks):
                ki = adapted_ji_idx[ji] // nkpts
                kj = adapted_ji_idx[ji] %  nkpts
                buf = aoao.transpose(1,2,0).reshape(nao**2,ngrids)
                zij = _ao2mo.r_e2(lib.transpose(buf), moij_list[ji],
                                  ijslice_list[ji], tao, ao_loc)
                zij *= coulG[p0:p1,None]
                fswap['zij/'+str(ji)][p0:p1] = zij

        mokl_list = []
        klslice_list = []
        for kk in range(nkpts):
            kl = kconserv[ki, kj, kk]
            mokl, klslice = _conc_mos(mo_coeff_kpts[2][kk], mo_coeff_kpts[3][kl])[2:]
            mokl_list.append(mokl)
            klslice_list.append(klslice)
            fswap.create_dataset('zkl/'+str(kk), (ngrids,nmok*nmol), 'D')

        ki = adapted_ji_idx[0] // nkpts
        kj = adapted_ji_idx[0] % nkpts
        kptls = kpts[kconserv[ki, kj, :]]
        for aoaoks, p0, p1 in mydf.ft_loop(mydf.mesh, q, -kptls):
            for kk, aoao in enumerate(aoaoks):
                buf = aoao.conj().transpose(1,2,0).reshape(nao**2,ngrids)
                zkl = _ao2mo.r_e2(lib.transpose(buf), mokl_list[kk],
                                  klslice_list[kk], tao, ao_loc)
                fswap['zkl/'+str(kk)][p0:p1] = zkl

        for ji, ji_idx in enumerate(adapted_ji_idx):
            ki = ji_idx // nkpts
            kj = ji_idx % nkpts

            moij, ijslice = _conc_mos(mo_coeff_kpts[0][ki], mo_coeff_kpts[1][kj])[2:]
            zij = []
            for LpqR, LpqI, sign in mydf.sr_loop(kpts[[ki,kj]], max_memory, False, mydf.blockdim):
                zij.append(_ao2mo.r_e2(LpqR+LpqI*1j, moij, ijslice, tao, ao_loc))

            for kk in range(nkpts):
                kl = kconserv[ki, kj, kk]
                eri_mo = lib.dot(numpy.asarray(fswap['zij/'+str(ji)]).T,
                                 numpy.asarray(fswap['zkl/'+str(kk)]))

                for i, (LrsR, LrsI, sign) in \
                        enumerate(mydf.sr_loop(kpts[[kk,kl]], max_memory, False, mydf.blockdim)):
                    zkl = _ao2mo.r_e2(LrsR+LrsI*1j, mokl_list[kk],
                                      klslice_list[kk], tao, ao_loc)
                    lib.dot(zij[i].T, zkl, sign*factor, eri_mo, 1)

                if dtype == numpy.double:
                    eri_mo = eri_mo.real
                out[ki,kj,kk] = eri_mo.reshape(eri_shape[3:])
        del(fswap['zij'])
        del(fswap['zkl'])

    return out
Пример #41
0
def update_amps(cc, t1, t2, eris):
    time0 = time.clock(), time.time()
    log = logger.Logger(cc.stdout, cc.verbose)
    nkpts, nocc, nvir = t1.shape
    fock = eris.fock
    mo_e_o = [e[:nocc] for e in eris.mo_energy]
    mo_e_v = [e[nocc:] + cc.level_shift for e in eris.mo_energy]

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(cc, kind="split")

    fov = fock[:, :nocc, nocc:].copy()
    foo = fock[:, :nocc, :nocc].copy()
    fvv = fock[:, nocc:, nocc:].copy()

    # Get the momentum conservation array
    # Note: chemist's notation for momentum conserving t2(ki,kj,ka,kb), even though
    # integrals are in physics notation
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)

    tau = imdk.make_tau(cc, t2, t1, t1, kconserv)

    Fvv = imdk.cc_Fvv(cc, t1, t2, eris, kconserv)
    Foo = imdk.cc_Foo(cc, t1, t2, eris, kconserv)
    Fov = imdk.cc_Fov(cc, t1, t2, eris, kconserv)
    Woooo = imdk.cc_Woooo(cc, t1, t2, eris, kconserv)
    Wvvvv = imdk.cc_Wvvvv(cc, t1, t2, eris, kconserv)
    Wovvo = imdk.cc_Wovvo(cc, t1, t2, eris, kconserv)

    # Move energy terms to the other side
    for k in range(nkpts):
        Foo[k][numpy.diag_indices(nocc)] -= mo_e_o[k]
        Fvv[k][numpy.diag_indices(nvir)] -= mo_e_v[k]

    eris_ovvo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nocc, nvir, nvir,
                                   nocc),
                            dtype=t2.dtype)
    eris_oovo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nocc, nocc, nvir,
                                   nocc),
                            dtype=t2.dtype)
    eris_vvvo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nvir, nvir, nvir,
                                   nocc),
                            dtype=t2.dtype)
    for km, kb, ke in kpts_helper.loop_kkk(nkpts):
        kj = kconserv[km, ke, kb]
        # <mb||je> -> -<mb||ej>
        eris_ovvo[km, kb, ke] = -eris.ovov[km, kb, kj].transpose(0, 1, 3, 2)
        # <mn||je> -> -<mn||ej>
        # let kb = kn as a dummy variable
        eris_oovo[km, kb, ke] = -eris.ooov[km, kb, kj].transpose(0, 1, 3, 2)
        # <ma||be> -> - <be||am>*
        # let kj = ka as a dummy variable
        kj = kconserv[km, ke, kb]
        eris_vvvo[ke, kj,
                  kb] = -eris.ovvv[km, kb, ke].transpose(2, 3, 1, 0).conj()

    # T1 equation
    t1new = numpy.zeros(shape=t1.shape, dtype=t1.dtype)
    for ka in range(nkpts):
        ki = ka
        t1new[ka] += numpy.array(fov[ka, :, :]).conj()
        t1new[ka] += einsum('ie,ae->ia', t1[ka], Fvv[ka])
        t1new[ka] += -einsum('ma,mi->ia', t1[ka], Foo[ka])
        for km in range(nkpts):
            t1new[ka] += einsum('imae,me->ia', t2[ka, km, ka], Fov[km])
            t1new[ka] += -einsum('nf,naif->ia', t1[km], eris.ovov[km, ka, ki])
            for kn in range(nkpts):
                ke = kconserv[km, ki, kn]
                t1new[ka] += -0.5 * einsum('imef,maef->ia', t2[ki, km, ke],
                                           eris.ovvv[km, ka, ke])
                t1new[ka] += -0.5 * einsum('mnae,nmei->ia', t2[km, kn, ka],
                                           eris_oovo[kn, km, ke])

    # T2 equation
    t2new = numpy.array(eris.oovv).conj()
    for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
        # Chemist's notation for momentum conserving t2(ki,kj,ka,kb)
        kb = kconserv[ki, ka, kj]

        Ftmp = Fvv[kb] - 0.5 * einsum('mb,me->be', t1[kb], Fov[kb])
        tmp = einsum('ijae,be->ijab', t2[ki, kj, ka], Ftmp)
        t2new[ki, kj, ka] += tmp

        #t2new[ki,kj,kb] -= tmp.transpose(0,1,3,2)
        Ftmp = Fvv[ka] - 0.5 * einsum('ma,me->ae', t1[ka], Fov[ka])
        tmp = einsum('ijbe,ae->ijab', t2[ki, kj, kb], Ftmp)
        t2new[ki, kj, ka] -= tmp

        Ftmp = Foo[kj] + 0.5 * einsum('je,me->mj', t1[kj], Fov[kj])
        tmp = einsum('imab,mj->ijab', t2[ki, kj, ka], Ftmp)
        t2new[ki, kj, ka] -= tmp

        #t2new[kj,ki,ka] += tmp.transpose(1,0,2,3)
        Ftmp = Foo[ki] + 0.5 * einsum('ie,me->mi', t1[ki], Fov[ki])
        tmp = einsum('jmab,mi->ijab', t2[kj, ki, ka], Ftmp)
        t2new[ki, kj, ka] += tmp

        for km in range(nkpts):
            # Wminj
            #   - km - kn + ka + kb = 0
            # =>  kn = ka - km + kb
            kn = kconserv[ka, km, kb]
            t2new[ki, kj, ka] += 0.5 * einsum(
                'mnab,mnij->ijab', tau[km, kn, ka], Woooo[km, kn, ki])
            ke = km
            t2new[ki, kj, ka] += 0.5 * einsum(
                'ijef,abef->ijab', tau[ki, kj, ke], Wvvvv[ka, kb, ke])

            # Wmbej
            #     - km - kb + ke + kj = 0
            #  => ke = km - kj + kb
            ke = kconserv[km, kj, kb]
            tmp = einsum('imae,mbej->ijab', t2[ki, km, ka], Wovvo[km, kb, ke])
            #     - km - kb + ke + kj = 0
            # =>  ke = km - kj + kb
            #
            # t[i,e] => ki = ke
            # t[m,a] => km = ka
            if km == ka and ke == ki:
                tmp -= einsum('ie,ma,mbej->ijab', t1[ki], t1[km],
                              eris_ovvo[km, kb, ke])
            t2new[ki, kj, ka] += tmp
            t2new[ki, kj, kb] -= tmp.transpose(0, 1, 3, 2)
            t2new[kj, ki, ka] -= tmp.transpose(1, 0, 2, 3)
            t2new[kj, ki, kb] += tmp.transpose(1, 0, 3, 2)

        ke = ki
        tmp = einsum('ie,abej->ijab', t1[ki], eris_vvvo[ka, kb, ke])
        t2new[ki, kj, ka] += tmp
        # P(ij) term
        ke = kj
        tmp = einsum('je,abei->ijab', t1[kj], eris_vvvo[ka, kb, ke])
        t2new[ki, kj, ka] -= tmp

        km = ka
        tmp = einsum('ma,mbij->ijab', t1[ka], eris.ovoo[km, kb, ki])
        t2new[ki, kj, ka] -= tmp
        # P(ab) term
        km = kb
        tmp = einsum('mb,maij->ijab', t1[kb], eris.ovoo[km, ka, ki])
        t2new[ki, kj, ka] += tmp

    for ki in range(nkpts):
        ka = ki
        # Remove zero/padded elements from denominator
        eia = LARGE_DENOM * numpy.ones(
            (nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = numpy.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:, None] - mo_e_v[ka])[n0_ovp_ia]
        t1new[ki] /= eia

    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
        kb = kconserv[ki, ka, kj]
        # For LARGE_DENOM, see t1new update above
        eia = LARGE_DENOM * numpy.ones(
            (nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = numpy.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:, None] - mo_e_v[ka])[n0_ovp_ia]

        ejb = LARGE_DENOM * numpy.ones(
            (nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_jb = numpy.ix_(nonzero_opadding[kj], nonzero_vpadding[kb])
        ejb[n0_ovp_jb] = (mo_e_o[kj][:, None] - mo_e_v[kb])[n0_ovp_jb]
        eijab = eia[:, None, :, None] + ejb[:, None, :]

        t2new[ki, kj, ka] /= eijab

    time0 = log.timer_debug1('update t1 t2', *time0)

    return t1new, t2new
Пример #42
0
def ao2mo_7d(mydf, mo_coeff_kpts, kpts=None, factor=1, out=None):
    cell = mydf.cell
    if kpts is None:
        kpts = mydf.kpts
    nkpts = len(kpts)

    if isinstance(mo_coeff_kpts, numpy.ndarray) and mo_coeff_kpts.ndim == 3:
        mo_coeff_kpts = [mo_coeff_kpts] * 4
    else:
        mo_coeff_kpts = list(mo_coeff_kpts)

    mo_ids = [id(x) for x in mo_coeff_kpts]
    moTs = []
    coords = cell.gen_uniform_grids(mydf.mesh)
    aos = mydf._numint.eval_ao(cell, coords, kpts)
    for n, mo_id in enumerate(mo_ids):
        if mo_id in mo_ids[:n]:
            moTs.append(moTs[mo_ids[:n].index(mo_id)])
        else:
            moTs.append([lib.dot(mo.T, aos[k].T) for k,mo in enumerate(mo_coeff_kpts[n])])

    # Shape of the orbitals can be different on different k-points. The
    # orbital coefficients must be formatted (padded by zeros) so that the
    # shape of the orbital coefficients are the same on all k-points. This can
    # be achieved by calling pbc.mp.kmp2.padded_mo_coeff function
    nmoi, nmoj, nmok, nmol = [x.shape[2] for x in mo_coeff_kpts]
    eri_shape = (nkpts, nkpts, nkpts, nmoi, nmoj, nmok, nmol)
    if gamma_point(kpts):
        dtype = numpy.result_type(*mo_coeff_kpts)
    else:
        dtype = numpy.complex128

    if out is None:
        out = numpy.empty(eri_shape, dtype=dtype)
    else:
        assert(out.shape == eri_shape)

    kptij_lst = numpy.array([(ki, kj) for ki in kpts for kj in kpts])
    kptis_lst = kptij_lst[:,0]
    kptjs_lst = kptij_lst[:,1]
    kpt_ji = kptjs_lst - kptis_lst
    uniq_kpts, uniq_index, uniq_inverse = unique(kpt_ji)
    ngrids = numpy.prod(mydf.mesh)

    # To hold intermediates
    fswap = lib.H5TmpFile()
    kconserv = kpts_helper.get_kconserv(cell, kpts)
    for uniq_id, kpt in enumerate(uniq_kpts):
        q = uniq_kpts[uniq_id]
        adapted_ji_idx = numpy.where(uniq_inverse == uniq_id)[0]
        ki = adapted_ji_idx[0] // nkpts
        kj = adapted_ji_idx[0] % nkpts

        coulG = tools.get_coulG(cell, q, mesh=mydf.mesh)
        coulG *= (cell.vol/ngrids) * factor
        phase = numpy.exp(-1j * numpy.dot(coords, q))

        for kk in range(nkpts):
            kl = kconserv[ki, kj, kk]
            mokT = moTs[2][kk]
            molT = moTs[3][kl]
            mo_pairs = numpy.einsum('ig,g,jg->ijg', mokT.conj(), phase.conj(), molT)
            v = tools.ifft(mo_pairs.reshape(-1,ngrids), mydf.mesh)
            v *= coulG
            v = tools.fft(v.reshape(-1,ngrids), mydf.mesh)
            v *= phase
            fswap['zkl/'+str(kk)] = v

        for ji_idx in adapted_ji_idx:
            ki = ji_idx // nkpts
            kj = ji_idx % nkpts
            for kk in range(nkpts):
                moiT = moTs[0][ki]
                mojT = moTs[1][kj]
                mo_pairs = numpy.einsum('ig,jg->ijg', moiT.conj(), mojT)
                tmp = lib.dot(mo_pairs.reshape(-1,ngrids),
                              numpy.asarray(fswap['zkl/'+str(kk)]).T)
                if dtype == numpy.double:
                    tmp = tmp.real
                out[ki,kj,kk] = tmp.reshape(eri_shape[3:])
        del(fswap['zkl'])

    return out
Пример #43
0
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
Пример #44
0
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
Пример #45
0
def update_amps(cc, t1, t2, eris):
    time0 = time.clock(), time.time()
    log = logger.Logger(cc.stdout, cc.verbose)
    nkpts, nocc, nvir = t1.shape
    fock = eris.fock
    mo_e_o = [e[:nocc] for e in eris.mo_energy]
    mo_e_v = [e[nocc:] + cc.level_shift for e in eris.mo_energy]

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(cc, kind="split")

    fov = fock[:, :nocc, nocc:].copy()
    foo = fock[:, :nocc, :nocc].copy()
    fvv = fock[:, nocc:, nocc:].copy()

    # Get the momentum conservation array
    # Note: chemist's notation for momentum conserving t2(ki,kj,ka,kb), even though
    # integrals are in physics notation
    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)

    tau = imdk.make_tau(cc, t2, t1, t1, kconserv)

    Fvv = imdk.cc_Fvv(cc, t1, t2, eris, kconserv)
    Foo = imdk.cc_Foo(cc, t1, t2, eris, kconserv)
    Fov = imdk.cc_Fov(cc, t1, t2, eris, kconserv)
    Woooo = imdk.cc_Woooo(cc, t1, t2, eris, kconserv)
    Wvvvv = imdk.cc_Wvvvv(cc, t1, t2, eris, kconserv)
    Wovvo = imdk.cc_Wovvo(cc, t1, t2, eris, kconserv)

    # Move energy terms to the other side
    for k in range(nkpts):
        Foo[k][numpy.diag_indices(nocc)] -= mo_e_o[k]
        Fvv[k][numpy.diag_indices(nvir)] -= mo_e_v[k]

    eris_ovvo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nocc, nvir, nvir, nocc), dtype=t2.dtype)
    eris_oovo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nocc, nocc, nvir, nocc), dtype=t2.dtype)
    eris_vvvo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nvir, nvir, nvir, nocc), dtype=t2.dtype)
    for km, kb, ke in kpts_helper.loop_kkk(nkpts):
        kj = kconserv[km, ke, kb]
        # <mb||je> -> -<mb||ej>
        eris_ovvo[km, kb, ke] = -eris.ovov[km, kb, kj].transpose(0, 1, 3, 2)
        # <mn||je> -> -<mn||ej>
        # let kb = kn as a dummy variable
        eris_oovo[km, kb, ke] = -eris.ooov[km, kb, kj].transpose(0, 1, 3, 2)
        # <ma||be> -> - <be||am>*
        # let kj = ka as a dummy variable
        kj = kconserv[km, ke, kb]
        eris_vvvo[ke, kj, kb] = -eris.ovvv[km, kb, ke].transpose(2, 3, 1, 0).conj()

    # T1 equation
    t1new = numpy.zeros(shape=t1.shape, dtype=t1.dtype)
    for ka in range(nkpts):
        ki = ka
        t1new[ka] += numpy.array(fov[ka, :, :]).conj()
        t1new[ka] += einsum('ie,ae->ia', t1[ka], Fvv[ka])
        t1new[ka] += -einsum('ma,mi->ia', t1[ka], Foo[ka])
        for km in range(nkpts):
            t1new[ka] += einsum('imae,me->ia', t2[ka, km, ka], Fov[km])
            t1new[ka] += -einsum('nf,naif->ia', t1[km], eris.ovov[km, ka, ki])
            for kn in range(nkpts):
                ke = kconserv[km, ki, kn]
                t1new[ka] += -0.5 * einsum('imef,maef->ia', t2[ki, km, ke], eris.ovvv[km, ka, ke])
                t1new[ka] += -0.5 * einsum('mnae,nmei->ia', t2[km, kn, ka], eris_oovo[kn, km, ke])

    # T2 equation
    t2new = numpy.array(eris.oovv).conj()
    for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
        # Chemist's notation for momentum conserving t2(ki,kj,ka,kb)
        kb = kconserv[ki, ka, kj]

        Ftmp = Fvv[kb] - 0.5 * einsum('mb,me->be', t1[kb], Fov[kb])
        tmp = einsum('ijae,be->ijab', t2[ki, kj, ka], Ftmp)
        t2new[ki, kj, ka] += tmp

        #t2new[ki,kj,kb] -= tmp.transpose(0,1,3,2)
        Ftmp = Fvv[ka] - 0.5 * einsum('ma,me->ae', t1[ka], Fov[ka])
        tmp = einsum('ijbe,ae->ijab', t2[ki, kj, kb], Ftmp)
        t2new[ki, kj, ka] -= tmp

        Ftmp = Foo[kj] + 0.5 * einsum('je,me->mj', t1[kj], Fov[kj])
        tmp = einsum('imab,mj->ijab', t2[ki, kj, ka], Ftmp)
        t2new[ki, kj, ka] -= tmp

        #t2new[kj,ki,ka] += tmp.transpose(1,0,2,3)
        Ftmp = Foo[ki] + 0.5 * einsum('ie,me->mi', t1[ki], Fov[ki])
        tmp = einsum('jmab,mi->ijab', t2[kj, ki, ka], Ftmp)
        t2new[ki, kj, ka] += tmp

        for km in range(nkpts):
            # Wminj
            #   - km - kn + ka + kb = 0
            # =>  kn = ka - km + kb
            kn = kconserv[ka, km, kb]
            t2new[ki, kj, ka] += 0.5 * einsum('mnab,mnij->ijab', tau[km, kn, ka], Woooo[km, kn, ki])
            ke = km
            t2new[ki, kj, ka] += 0.5 * einsum('ijef,abef->ijab', tau[ki, kj, ke], Wvvvv[ka, kb, ke])

            # Wmbej
            #     - km - kb + ke + kj = 0
            #  => ke = km - kj + kb
            ke = kconserv[km, kj, kb]
            tmp = einsum('imae,mbej->ijab', t2[ki, km, ka], Wovvo[km, kb, ke])
            #     - km - kb + ke + kj = 0
            # =>  ke = km - kj + kb
            #
            # t[i,e] => ki = ke
            # t[m,a] => km = ka
            if km == ka and ke == ki:
                tmp -= einsum('ie,ma,mbej->ijab', t1[ki], t1[km], eris_ovvo[km, kb, ke])
            t2new[ki, kj, ka] += tmp
            t2new[ki, kj, kb] -= tmp.transpose(0, 1, 3, 2)
            t2new[kj, ki, ka] -= tmp.transpose(1, 0, 2, 3)
            t2new[kj, ki, kb] += tmp.transpose(1, 0, 3, 2)

        ke = ki
        tmp = einsum('ie,abej->ijab', t1[ki], eris_vvvo[ka, kb, ke])
        t2new[ki, kj, ka] += tmp
        # P(ij) term
        ke = kj
        tmp = einsum('je,abei->ijab', t1[kj], eris_vvvo[ka, kb, ke])
        t2new[ki, kj, ka] -= tmp

        km = ka
        tmp = einsum('ma,mbij->ijab', t1[ka], eris.ovoo[km, kb, ki])
        t2new[ki, kj, ka] -= tmp
        # P(ab) term
        km = kb
        tmp = einsum('mb,maij->ijab', t1[kb], eris.ovoo[km, ka, ki])
        t2new[ki, kj, ka] += tmp

    for ki in range(nkpts):
        ka = ki
        # Remove zero/padded elements from denominator
        eia = LARGE_DENOM * numpy.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = numpy.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:,None] - mo_e_v[ka])[n0_ovp_ia]
        t1new[ki] /= eia

    kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
    for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
        kb = kconserv[ki, ka, kj]
        # For LARGE_DENOM, see t1new update above
        eia = LARGE_DENOM * numpy.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = numpy.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:,None] - mo_e_v[ka])[n0_ovp_ia]

        ejb = LARGE_DENOM * numpy.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_jb = numpy.ix_(nonzero_opadding[kj], nonzero_vpadding[kb])
        ejb[n0_ovp_jb] = (mo_e_o[kj][:,None] - mo_e_v[kb])[n0_ovp_jb]
        eijab = eia[:, None, :, None] + ejb[:, None, :]

        t2new[ki, kj, ka] /= eijab

    time0 = log.timer_debug1('update t1 t2', *time0)

    return t1new, t2new
Пример #46
0
def ao2mo_7d(mydf, mo_coeff_kpts, kpts=None, factor=1, out=None):
    cell = mydf.cell
    if kpts is None:
        kpts = mydf.kpts
    nkpts = len(kpts)

    if isinstance(mo_coeff_kpts, numpy.ndarray) and mo_coeff_kpts.ndim == 3:
        mo_coeff_kpts = [mo_coeff_kpts] * 4
    else:
        mo_coeff_kpts = list(mo_coeff_kpts)

    # Shape of the orbitals can be different on different k-points. The
    # orbital coefficients must be formatted (padded by zeros) so that the
    # shape of the orbital coefficients are the same on all k-points. This can
    # be achieved by calling pbc.mp.kmp2.padded_mo_coeff function
    nmoi, nmoj, nmok, nmol = [x.shape[2] for x in mo_coeff_kpts]
    eri_shape = (nkpts, nkpts, nkpts, nmoi, nmoj, nmok, nmol)
    if gamma_point(kpts):
        dtype = numpy.result_type(*mo_coeff_kpts)
    else:
        dtype = numpy.complex128

    if out is None:
        out = numpy.empty(eri_shape, dtype=dtype)
    else:
        assert(out.shape == eri_shape)

    kptij_lst = numpy.array([(ki, kj) for ki in kpts for kj in kpts])
    kptis_lst = kptij_lst[:,0]
    kptjs_lst = kptij_lst[:,1]
    kpt_ji = kptjs_lst - kptis_lst
    uniq_kpts, uniq_index, uniq_inverse = unique(kpt_ji)
    ngrids = numpy.prod(mydf.mesh)

    nao = cell.nao_nr()
    max_memory = max(2000, mydf.max_memory-lib.current_memory()[0]-nao**4*16/1e6) * .5

    tao = []
    ao_loc = None
    kconserv = kpts_helper.get_kconserv(cell, kpts)
    for uniq_id, kpt in enumerate(uniq_kpts):
        q = uniq_kpts[uniq_id]
        adapted_ji_idx = numpy.where(uniq_inverse == uniq_id)[0]

        for ji, ji_idx in enumerate(adapted_ji_idx):
            ki = ji_idx // nkpts
            kj = ji_idx % nkpts

            moij, ijslice = _conc_mos(mo_coeff_kpts[0][ki], mo_coeff_kpts[1][kj])[2:]
            zij = []
            for LpqR, LpqI, sign in mydf.sr_loop(kpts[[ki,kj]], max_memory, False, mydf.blockdim):
                zij.append(_ao2mo.r_e2(LpqR+LpqI*1j, moij, ijslice, tao, ao_loc))

            for kk in range(nkpts):
                kl = kconserv[ki, kj, kk]
                mokl, klslice = _conc_mos(mo_coeff_kpts[2][kk], mo_coeff_kpts[3][kl])[2:]
                eri_mo = numpy.zeros((nmoi*nmoj,nmok*nmol), dtype=numpy.complex128)
                for i, (LrsR, LrsI, sign) in \
                        enumerate(mydf.sr_loop(kpts[[kk,kl]], max_memory, False, mydf.blockdim)):
                    zkl = _ao2mo.r_e2(LrsR+LrsI*1j, mokl, klslice, tao, ao_loc)
                    lib.dot(zij[i].T, zkl, sign*factor, eri_mo, 1)

                if dtype == numpy.double:
                    eri_mo = eri_mo.real
                out[ki,kj,kk] = eri_mo.reshape(eri_shape[3:])
    return out
Пример #47
0
def kernel(mycc, eris, t1=None, t2=None, max_memory=2000, verbose=logger.INFO):
    '''Returns the CCSD(T) for general spin-orbital integrals with k-points.

    Note:
        Returns real part of the CCSD(T) energy, raises warning if there is
        a complex part.

    Args:
        mycc (:class:`GCCSD`): Coupled-cluster object storing results of
            a coupled-cluster calculation.
        eris (:class:`_ERIS`): Integral object holding the relevant electron-
            repulsion integrals and Fock matrix elements
        t1 (:obj:`ndarray`): t1 coupled-cluster amplitudes
        t2 (:obj:`ndarray`): t2 coupled-cluster amplitudes
        max_memory (float): Maximum memory used in calculation (NOT USED)
        verbose (int, :class:`Logger`): verbosity of calculation

    Returns:
        energy_t (float): The real-part of the k-point CCSD(T) energy.
    '''
    assert isinstance(mycc, pyscf.pbc.cc.kccsd.GCCSD)
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(mycc.stdout, verbose)

    if t1 is None: t1 = mycc.t1
    if t2 is None: t2 = mycc.t2

    if t1 is None or t2 is None:
        raise TypeError('Must pass in t1/t2 amplitudes to k-point CCSD(T)! (Maybe '
                        'need to run `.ccsd()` on the ccsd object?)')

    cell = mycc._scf.cell
    kpts = mycc.kpts

    # The dtype of any local arrays that will be created
    dtype = t1.dtype

    nkpts, nocc, nvir = t1.shape

    mo_energy_occ = [eris.mo_energy[ki][:nocc] for ki in range(nkpts)]
    mo_energy_vir = [eris.mo_energy[ki][nocc:] for ki in range(nkpts)]
    fov = eris.fock[:, :nocc, nocc:]

    # Set up class for k-point conservation
    kconserv = kpts_helper.get_kconserv(cell, kpts)

    energy_t = 0.0

    for ki in range(nkpts):
        for kj in range(ki + 1):
            for kk in range(kj + 1):
                # eigenvalue denominator: e(i) + e(j) + e(k)
                eijk = lib.direct_sum('i,j,k->ijk', mo_energy_occ[ki], mo_energy_occ[kj], mo_energy_occ[kk])

                # Factors to include for permutational symmetry among k-points for occupied space
                if ki == kj and kj == kk:
                    symm_ijk_kpt = 1.  # only one degeneracy
                elif ki == kj or kj == kk:
                    symm_ijk_kpt = 3.  # 3 degeneracies when only one k-point is unique
                else:
                    symm_ijk_kpt = 6.  # 3! combinations of arranging 3 distinct k-points

                for ka in range(nkpts):
                    for kb in range(ka + 1):

                        # Find momentum conservation condition for triples
                        # amplitude t3ijkabc
                        kc = kpts_helper.get_kconserv3(cell, kpts, [ki, kj, kk, ka, kb])
                        if kc not in range(kb + 1):
                            continue

                        # Factors to include for permutational symmetry among k-points for virtual space
                        if ka == kb and kb == kc:
                            symm_abc_kpt = 1.  # one unique combination of (ka, kb, kc)
                        elif ka == kb or kb == kc:
                            symm_abc_kpt = 3.  # 3 unique combinations of (ka, kb, kc)
                        else:
                            symm_abc_kpt = 6.  # 6 unique combinations of (ka, kb, kc)

                        # Determine the a, b, c indices we will loop over as
                        # determined by the k-point symmetry.
                        abc_indices = cartesian_prod([range(nvir)] * 3)
                        symm_3d = symm_2d_ab = symm_2d_bc = False
                        if ka == kc:  # == kb from lower triangular summation
                            abc_indices = tril_product(range(nvir), repeat=3, tril_idx=[0, 1, 2])  # loop a >= b >= c
                            symm_3d = True
                        elif ka == kb:
                            abc_indices = tril_product(range(nvir), repeat=3, tril_idx=[0, 1])  # loop a >= b
                            symm_2d_ab = True
                        elif kb == kc:
                            abc_indices = tril_product(range(nvir), repeat=3, tril_idx=[1, 2])  # loop b >= c
                            symm_2d_bc = True

                        for a, b, c in abc_indices:
                            # See symm_3d and abc_indices above for description of factors
                            symm_abc = 1.
                            if symm_3d:
                                if a == b == c:
                                    symm_abc = 1.
                                elif a == b or b == c:
                                    symm_abc = 3.
                                else:
                                    symm_abc = 6.
                            elif symm_2d_ab:
                                if a == b:
                                    symm_abc = 1.
                                else:
                                    symm_abc = 2.
                            elif symm_2d_bc:
                                if b == c:
                                    symm_abc = 1.
                                else:
                                    symm_abc = 2.

                            # Form energy denominator
                            eijkabc = (eijk - mo_energy_vir[ka][a] - mo_energy_vir[kb][b] - mo_energy_vir[kc][c])
                            # When padding for non-equal nocc per k-point, some fock elements will be zero
                            idx = np.where(abs(eijkabc) < LOOSE_ZERO_TOL)[0]
                            eijkabc[idx] = LARGE_DENOM

                            # Form connected triple excitation amplitude
                            t3c = np.zeros((nocc, nocc, nocc), dtype=dtype)

                            # First term: 1 - p(ij) - p(ik)
                            ke = kconserv[kj, ka, kk]
                            t3c = t3c + einsum('jke,ie->ijk', t2[kj, kk, ka, :, :, a, :], -eris.ovvv[ki, ke, kc, :, :, c, b].conj())
                            ke = kconserv[ki, ka, kk]
                            t3c = t3c - einsum('ike,je->ijk', t2[ki, kk, ka, :, :, a, :], -eris.ovvv[kj, ke, kc, :, :, c, b].conj())
                            ke = kconserv[kj, ka, ki]
                            t3c = t3c - einsum('jie,ke->ijk', t2[kj, ki, ka, :, :, a, :], -eris.ovvv[kk, ke, kc, :, :, c, b].conj())

                            km = kconserv[kb, ki, kc]
                            t3c = t3c - einsum('mi,jkm->ijk', t2[km, ki, kb, :, :, b, c], eris.ooov[kj, kk, km, :, :, :, a].conj())
                            km = kconserv[kb, kj, kc]
                            t3c = t3c + einsum('mj,ikm->ijk', t2[km, kj, kb, :, :, b, c], eris.ooov[ki, kk, km, :, :, :, a].conj())
                            km = kconserv[kb, kk, kc]
                            t3c = t3c + einsum('mk,jim->ijk', t2[km, kk, kb, :, :, b, c], eris.ooov[kj, ki, km, :, :, :, a].conj())

                            # Second term: - p(ab) + p(ab) p(ij) + p(ab) p(ik)
                            ke = kconserv[kj, kb, kk]
                            t3c = t3c - einsum('jke,ie->ijk', t2[kj, kk, kb, :, :, b, :], -eris.ovvv[ki, ke, kc, :, :, c, a].conj())
                            ke = kconserv[ki, kb, kk]
                            t3c = t3c + einsum('ike,je->ijk', t2[ki, kk, kb, :, :, b, :], -eris.ovvv[kj, ke, kc, :, :, c, a].conj())
                            ke = kconserv[kj, kb, ki]
                            t3c = t3c + einsum('jie,ke->ijk', t2[kj, ki, kb, :, :, b, :], -eris.ovvv[kk, ke, kc, :, :, c, a].conj())

                            km = kconserv[ka, ki, kc]
                            t3c = t3c + einsum('mi,jkm->ijk', t2[km, ki, ka, :, :, a, c], eris.ooov[kj, kk, km, :, :, :, b].conj())
                            km = kconserv[ka, kj, kc]
                            t3c = t3c - einsum('mj,ikm->ijk', t2[km, kj, ka, :, :, a, c], eris.ooov[ki, kk, km, :, :, :, b].conj())
                            km = kconserv[ka, kk, kc]
                            t3c = t3c - einsum('mk,jim->ijk', t2[km, kk, ka, :, :, a, c], eris.ooov[kj, ki, km, :, :, :, b].conj())

                            # Third term: - p(ac) + p(ac) p(ij) + p(ac) p(ik)
                            ke = kconserv[kj, kc, kk]
                            t3c = t3c - einsum('jke,ie->ijk', t2[kj, kk, kc, :, :, c, :], -eris.ovvv[ki, ke, ka, :, :, a, b].conj())
                            ke = kconserv[ki, kc, kk]
                            t3c = t3c + einsum('ike,je->ijk', t2[ki, kk, kc, :, :, c, :], -eris.ovvv[kj, ke, ka, :, :, a, b].conj())
                            ke = kconserv[kj, kc, ki]
                            t3c = t3c + einsum('jie,ke->ijk', t2[kj, ki, kc, :, :, c, :], -eris.ovvv[kk, ke, ka, :, :, a, b].conj())

                            km = kconserv[kb, ki, ka]
                            t3c = t3c + einsum('mi,jkm->ijk', t2[km, ki, kb, :, :, b, a], eris.ooov[kj, kk, km, :, :, :, c].conj())
                            km = kconserv[kb, kj, ka]
                            t3c = t3c - einsum('mj,ikm->ijk', t2[km, kj, kb, :, :, b, a], eris.ooov[ki, kk, km, :, :, :, c].conj())
                            km = kconserv[kb, kk, ka]
                            t3c = t3c - einsum('mk,jim->ijk', t2[km, kk, kb, :, :, b, a], eris.ooov[kj, ki, km, :, :, :, c].conj())

                            # Form disconnected triple excitation amplitude contribution
                            t3d = np.zeros((nocc, nocc, nocc), dtype=dtype)

                            # First term: 1 - p(ij) - p(ik)
                            if ki == ka:
                                t3d = t3d + einsum('i,jk->ijk',  t1[ki, :, a], -eris.oovv[kj, kk, kb, :, :, b, c].conj())
                                t3d = t3d + einsum('i,jk->ijk',-fov[ki, :, a],         t2[kj, kk, kb, :, :, b, c])

                            if kj == ka:
                                t3d = t3d - einsum('j,ik->ijk',  t1[kj, :, a], -eris.oovv[ki, kk, kb, :, :, b, c].conj())
                                t3d = t3d - einsum('j,ik->ijk',-fov[kj, :, a],         t2[ki, kk, kb, :, :, b, c])

                            if kk == ka:
                                t3d = t3d - einsum('k,ji->ijk',  t1[kk, :, a], -eris.oovv[kj, ki, kb, :, :, b, c].conj())
                                t3d = t3d - einsum('k,ji->ijk',-fov[kk, :, a],         t2[kj, ki, kb, :, :, b, c])

                            # Second term: - p(ab) + p(ab) p(ij) + p(ab) p(ik)
                            if ki == kb:
                                t3d = t3d - einsum('i,jk->ijk',  t1[ki, :, b], -eris.oovv[kj, kk, ka, :, :, a, c].conj())
                                t3d = t3d - einsum('i,jk->ijk',-fov[ki, :, b],         t2[kj, kk, ka, :, :, a, c])

                            if kj == kb:
                                t3d = t3d + einsum('j,ik->ijk',  t1[kj, :, b], -eris.oovv[ki, kk, ka, :, :, a, c].conj())
                                t3d = t3d + einsum('j,ik->ijk',-fov[kj, :, b],         t2[ki, kk, ka, :, :, a, c])

                            if kk == kb:
                                t3d = t3d + einsum('k,ji->ijk',  t1[kk, :, b], -eris.oovv[kj, ki, ka, :, :, a, c].conj())
                                t3d = t3d + einsum('k,ji->ijk',-fov[kk, :, b],         t2[kj, ki, ka, :, :, a, c])

                            # Third term: - p(ac) + p(ac) p(ij) + p(ac) p(ik)
                            if ki == kc:
                                t3d = t3d - einsum('i,jk->ijk',  t1[ki, :, c], -eris.oovv[kj, kk, kb, :, :, b, a].conj())
                                t3d = t3d - einsum('i,jk->ijk',-fov[ki, :, c],         t2[kj, kk, kb, :, :, b, a])

                            if kj == kc:
                                t3d = t3d + einsum('j,ik->ijk',  t1[kj, :, c], -eris.oovv[ki, kk, kb, :, :, b, a].conj())
                                t3d = t3d + einsum('j,ik->ijk',-fov[kj, :, c],         t2[ki, kk, kb, :, :, b, a])

                            if kk == kc:
                                t3d = t3d + einsum('k,ji->ijk',  t1[kk, :, c], -eris.oovv[kj, ki, kb, :, :, b, a].conj())
                                t3d = t3d + einsum('k,ji->ijk',-fov[kk, :, c],         t2[kj, ki, kb, :, :, b, a])

                            t3c_plus_d = t3c + t3d
                            t3c_plus_d /= eijkabc

                            energy_t += symm_abc_kpt * symm_ijk_kpt * symm_abc * einsum('ijk,ijk', t3c, t3c_plus_d.conj())

    energy_t = (1. / 36) * energy_t / nkpts

    if abs(energy_t.imag) > 1e-4:
        log.warn('Non-zero imaginary part of CCSD(T) energy was found %s',
                 energy_t.imag)
    log.note('CCSD(T) correction per cell = %.15g', energy_t.real)
    return energy_t.real
Пример #48
0
    def __init__(self,cell,kpts):
        kconserv = kpts_helper.get_kconserv(cell,kpts)
        nkpts = len(kpts)
        temp = range(0,nkpts)
        klist = pyscf.lib.cartesian_prod((temp,temp,temp))
        completed = numpy.zeros((nkpts,nkpts,nkpts),dtype=int)

        self.operations = numpy.zeros((nkpts,nkpts,nkpts),dtype=int)
        self.equivalentList = numpy.zeros((nkpts,nkpts,nkpts,3),dtype=int)
        self.nUnique = 0
        self.uniqueList = numpy.array([],dtype=int)

        ivec = 0
        not_done = True
        while( not_done ):
            current_kvec = klist[ivec]
            # check to see if it's been done...
            kp = current_kvec[0]
            kq = current_kvec[1]
            kr = current_kvec[2]
            #print "computing ",kp,kq,kr
            if completed[kp,kq,kr] == 0:
                self.nUnique += 1
                self.uniqueList = numpy.append(self.uniqueList,current_kvec)
                ks = kconserv[kp,kq,kr]

                # Now find all equivalent kvectors by permuting it all possible ways...
                # and then storing how its related by symmetry
                completed[kp,kq,kr] = 1
                self.operations[kp,kq,kr] = 0
                self.equivalentList[kp,kq,kr] = current_kvec.copy()

                completed[kr,ks,kp] = 1
                self.operations[kr,ks,kp] = 1 #.transpose(2,3,0,1)
                self.equivalentList[kr,ks,kp] = current_kvec.copy()

                completed[kq,kp,ks] = 1
                self.operations[kq,kp,ks] = 2 #numpy.conj(.transpose(1,0,3,2))
                self.equivalentList[kq,kp,ks] = current_kvec.copy()

                completed[ks,kr,kq] = 1
                self.operations[ks,kr,kq] = 3 #numpy.conj(.transpose(3,2,1,0))
                self.equivalentList[ks,kr,kq] = current_kvec.copy()

            ivec += 1
            if ivec == len(klist):
                not_done = False

        self.uniqueList = self.uniqueList.reshape(self.nUnique,-1)
        if DEBUG == 1:
            print("::: kpoint helper :::")
            print("kvector list (in)")
            print("   shape = ", klist.shape)
            print("kvector list (out)")
            print("   shape  = ", self.uniqueList.shape)
            print("   unique list =")
            print(self.uniqueList)
            print("transformation =")
            for i in range(klist.shape[0]):
                pqr = klist[i]
                irr_pqr = self.equivalentList[pqr[0],pqr[1],pqr[2]]
                print("%3d %3d %3d   ->  %3d %3d %3d" % (pqr[0],pqr[1],pqr[2],
                                                         irr_pqr[0],irr_pqr[1],irr_pqr[2]))
Пример #49
0
from pyscf.pbc.lib.kpts_helper import get_kconserv
from pyscf.pbc import tools
nao = cell.nao_nr()
mydf = df.FFTDF(cell, kpts=kpts)
Lpq_kpts = []
for i, kpti in enumerate(kpts):
    Lpq_kpts.append([])
    for j, kptj in enumerate(kpts):
        q = kptj - kpti
        coulG = tools.get_coulG(cell, q)
        ngrids = len(coulG)
        ao_pairs_G = mydf.get_ao_pairs_G([kpti,kptj], q, compact=False)
        ao_pairs_G *= numpy.sqrt(coulG*cell.vol/ngrids**2).reshape(-1,1)
        Lpq_kpts[i].append(ao_pairs_G.reshape(-1,nao,nao))

kconserv = get_kconserv(cell, kpts)
Lrs_kpts = []
for i, kpti in enumerate(kpts):
    Lrs_kpts.append([])
    for j, kptj in enumerate(kpts):
        Lrs_kpts[i].append([])
        q = kptj - kpti
        coulG = tools.get_coulG(cell, q)
        ngrids = len(coulG)
        for k, kptk in enumerate(kpts):
            # Handle the wrap-around k-points
            l = kconserv[i,j,k]
            kptl = kpts[l]
            ao_pairs_invG = mydf.get_ao_pairs_G([-kptk,-kptl], q, compact=False).conj()
            ao_pairs_invG *= numpy.sqrt(coulG*cell.vol/ngrids**2).reshape(-1,1)
            Lrs_kpts[i][j].append(ao_pairs_invG.reshape(-1,nao,nao))