Beispiel #1
0
def _int_nuc_vloc(mydf, nuccell, kpts, intor='int3c2e_sph'):
    '''Vnuc - Vloc'''
    cell = mydf.cell
    nkpts = len(kpts)

    # Use the 3c2e code with steep s gaussians to mimic nuclear density
    fakenuc = aft._fake_nuc(cell)
    fakenuc._atm, fakenuc._bas, fakenuc._env = \
            gto.conc_env(nuccell._atm, nuccell._bas, nuccell._env,
                         fakenuc._atm, fakenuc._bas, fakenuc._env)

    kptij_lst = numpy.hstack((kpts, kpts)).reshape(-1, 2, 3)
    ishs = mpi.work_balanced_partition(numpy.arange(cell.nbas),
                                       costs=numpy.arange(1, cell.nbas + 1))
    if len(ishs) > 0:
        ish0, ish1 = ishs[0], ishs[-1] + 1
        buf = incore.aux_e2(cell,
                            fakenuc,
                            intor,
                            aosym='s2',
                            kptij_lst=kptij_lst,
                            shls_slice=(ish0, ish1, 0, cell.nbas, 0,
                                        fakenuc.nbas))
    else:
        buf = numpy.zeros(0)

    charge = cell.atom_charges()
    charge = numpy.append(charge,
                          -charge)  # (charge-of-nuccell, charge-of-fakenuc)
    nao = cell.nao_nr()
    nchg = len(charge)
    nao_pair = nao * (nao + 1) // 2
    buf = buf.reshape(nkpts, -1, nchg)
    # scaled by 1./mpi.pool.size because nuc is mpi.reduced in get_nuc function
    buf = numpy.einsum('kxz,z->kx', buf, 1. / mpi.pool.size * charge)
    mat = numpy.empty((nkpts, nao_pair), dtype=numpy.complex128)
    for k in range(nkpts):
        mat[k] = mpi.allgather(buf[k])

    if rank == 0 and cell.dimension == 3:
        nucbar = sum([
            z / nuccell.bas_exp(i)[0]
            for i, z in enumerate(cell.atom_charges())
        ])
        nucbar *= numpy.pi / cell.vol
        ovlp = cell.pbc_intor('int1e_ovlp_sph', 1, lib.HERMITIAN, kpts)
        for k in range(nkpts):
            s = lib.pack_tril(ovlp[k])
            mat[k] += nucbar * s
    return mat
Beispiel #2
0
def _int_nuc_vloc(mydf, nuccell, kpts, dm_kpts):
    '''Vnuc - Vloc'''
    cell = mydf.cell
    nkpts = len(kpts)

    # Use the 3c2e code with steep s gaussians to mimic nuclear density
    fakenuc = aft._fake_nuc(cell)
    fakenuc._atm, fakenuc._bas, fakenuc._env = \
            gto.conc_env(nuccell._atm, nuccell._bas, nuccell._env,
                         fakenuc._atm, fakenuc._bas, fakenuc._env)

    kptij_lst = numpy.hstack((kpts,kpts)).reshape(-1,2,3)
    v3c = df.incore.aux_e2(cell, fakenuc, 'int3c2e_ipip1', aosym='s1', comp=9,
                           kptij_lst=kptij_lst)
    v3c += df.incore.aux_e2(cell, fakenuc, 'int3c2e_ipvip1', aosym='s1', comp=9,
                            kptij_lst=kptij_lst)

    nao = cell.nao_nr()
    natm = cell.natm
    v3c = v3c.reshape(nkpts,3,3,nao,nao,natm*2)
    efg_loc = 1./nkpts * numpy.einsum('kxypqz,kqp->zxy', v3c, dm_kpts)
    efg_loc+= 1./nkpts * numpy.einsum('kyxqpz,kqp->zxy', v3c, dm_kpts)
    v3c = None

    # Fermi contact
    fc = df.incore.aux_e2(cell, fakenuc, 'int3c1e', aosym='s1', kptij_lst=kptij_lst)
    fc = fc.reshape(nkpts,nao,nao,natm*2)
    vfc = 1./nkpts * numpy.einsum('kpqz,kqp->z', fc, dm_kpts)
    for i in range(3):
        efg_loc[:,i,i] += 4./3*numpy.pi * vfc

    nuc_part = efg_loc[:natm]
    modchg_part = efg_loc[natm:]
    efg_loc = nuc_part - modchg_part

    if cell.dimension == 3:
        fac = numpy.pi/cell.vol
        nucbar = numpy.array([fac/nuccell.bas_exp(i)[0] for i in range(natm)])

        ipip = cell.pbc_intor('int1e_ipipovlp', 9, lib.HERMITIAN, kpts)
        ipvip = cell.pbc_intor('int1e_ipovlpip', 9, lib.HERMITIAN, kpts)
        d2rho_bar = 0
        for k in range(nkpts):
            v = (ipip[k] + ipvip[k]).reshape(3,3,nao,nao)
            d2rho_bar += numpy.einsum('xypq,qp->xy', v, dm_kpts[k])
            d2rho_bar += numpy.einsum('yxqp,qp->xy', v, dm_kpts[k])
        d2rho_bar *= 1./nkpts

        efg_loc -= numpy.einsum('z,xy->zxy', nucbar, d2rho_bar)
    return efg_loc.real
Beispiel #3
0
def _int_nuc_vloc(mydf, nuccell, kpts, dm_kpts):
    '''Vnuc - Vloc'''
    cell = mydf.cell
    nkpts = len(kpts)

    # Use the 3c2e code with steep s gaussians to mimic nuclear density
    fakenuc = aft._fake_nuc(cell)
    fakenuc._atm, fakenuc._bas, fakenuc._env = \
            gto.conc_env(nuccell._atm, nuccell._bas, nuccell._env,
                         fakenuc._atm, fakenuc._bas, fakenuc._env)

    kptij_lst = numpy.hstack((kpts,kpts)).reshape(-1,2,3)
    v3c = df.incore.aux_e2(cell, fakenuc, 'int3c2e_ipip1', aosym='s1', comp=9,
                           kptij_lst=kptij_lst)
    v3c += df.incore.aux_e2(cell, fakenuc, 'int3c2e_ipvip1', aosym='s1', comp=9,
                            kptij_lst=kptij_lst)

    nao = cell.nao_nr()
    natm = cell.natm
    v3c = v3c.reshape(nkpts,3,3,nao,nao,natm*2)
    efg_loc = 1./nkpts * numpy.einsum('kxypqz,kqp->zxy', v3c, dm_kpts)
    efg_loc+= 1./nkpts * numpy.einsum('kyxqpz,kqp->zxy', v3c, dm_kpts)
    v3c = None

    # Fermi contact
    fc = df.incore.aux_e2(cell, fakenuc, 'int3c1e', aosym='s1', kptij_lst=kptij_lst)
    fc = fc.reshape(nkpts,nao,nao,natm*2)
    vfc = 1./nkpts * numpy.einsum('kpqz,kqp->z', fc, dm_kpts)
    for i in range(3):
        efg_loc[:,i,i] += 4./3*numpy.pi * vfc

    nuc_part = efg_loc[:natm]
    modchg_part = efg_loc[natm:]
    efg_loc = nuc_part - modchg_part

    if cell.dimension == 3:
        fac = numpy.pi/cell.vol
        nucbar = numpy.array([fac/nuccell.bas_exp(i)[0] for i in range(natm)])

        ipip = cell.pbc_intor('int1e_ipipovlp', 9, lib.HERMITIAN, kpts)
        ipvip = cell.pbc_intor('int1e_ipovlpip', 9, lib.HERMITIAN, kpts)
        d2rho_bar = 0
        for k in range(nkpts):
            v = (ipip[k] + ipvip[k]).reshape(3,3,nao,nao)
            d2rho_bar += numpy.einsum('xypq,qp->xy', v, dm_kpts[k])
            d2rho_bar += numpy.einsum('yxqp,qp->xy', v, dm_kpts[k])
        d2rho_bar *= 1./nkpts

        efg_loc -= numpy.einsum('z,xy->zxy', nucbar, d2rho_bar)
    return efg_loc.real
Beispiel #4
0
def _int_nuc_vloc(mydf, nuccell, kpts, intor='int3c2e_sph', aosym='s2', comp=1):
    '''Vnuc - Vloc'''
    cell = mydf.cell
    nkpts = len(kpts)

# Use the 3c2e code with steep s gaussians to mimic nuclear density
    fakenuc = aft._fake_nuc(cell)
    fakenuc._atm, fakenuc._bas, fakenuc._env = \
            gto.conc_env(nuccell._atm, nuccell._bas, nuccell._env,
                         fakenuc._atm, fakenuc._bas, fakenuc._env)

    kptij_lst = numpy.hstack((kpts,kpts)).reshape(-1,2,3)
    ishs = mpi.work_balanced_partition(numpy.arange(cell.nbas),
                                       costs=numpy.arange(1, cell.nbas+1))
    if len(ishs) > 0:
        ish0, ish1 = ishs[0], ishs[-1]+1
        buf = incore.aux_e2(cell, fakenuc, intor, aosym='s2', kptij_lst=kptij_lst,
                            shls_slice=(ish0,ish1,0,cell.nbas,0,fakenuc.nbas))
    else:
        buf = numpy.zeros(0)

    charge = cell.atom_charges()
    charge = numpy.append(charge, -charge)  # (charge-of-nuccell, charge-of-fakenuc)
    nao = cell.nao_nr()
    nchg = len(charge)
    nao_pair = nao*(nao+1)//2
    buf = buf.reshape(nkpts,-1,nchg)
# scaled by 1./mpi.pool.size because nuc is mpi.reduced in get_nuc function
    buf = numpy.einsum('kxz,z->kx', buf, 1./mpi.pool.size*charge)
    mat = numpy.empty((nkpts,nao_pair), dtype=numpy.complex128)
    for k in range(nkpts):
        mat[k] = mpi.allgather(buf[k])

    if (rank == 0 and
        cell.dimension == 3 and intor in ('int3c2e', 'int3c2e_sph',
                                          'int3c2e_cart')):
        assert(comp == 1)
        charges = cell.atom_charges()

        nucbar = sum([z/nuccell.bas_exp(i)[0] for i,z in enumerate(charges)])
        nucbar *= numpy.pi/cell.vol

        ovlp = cell.pbc_intor('int1e_ovlp_sph', 1, lib.HERMITIAN, kpts)
        for k in range(nkpts):
            if aosym == 's1':
                mat[k] += nucbar * ovlp[k].reshape(nao_pair)
            else:
                mat[k] += nucbar * lib.pack_tril(ovlp[k])

    return mat