Beispiel #1
0
    def check_sanity(self):
        lib.StreamObject.check_sanity(self)
        cell = self.cell
        if cell.dimension < 3:
            raise RuntimeError(
                'FFTDF method does not support low-dimension '
                'PBC system.  DF, MDF or AFTDF methods should '
                'be used.\nSee also examples/pbc/31-low_dimensional_pbc.py')

        if not cell.has_ecp():
            logger.warn(
                self, 'FFTDF integrals are found in all-electron '
                'calculation.  It often causes huge error.\n'
                'Recommended methods are DF or MDF. In SCF calculation, '
                'they can be initialized as\n'
                '        mf = mf.density_fit()\nor\n'
                '        mf = mf.mix_density_fit()')

        if cell.ke_cutoff is None:
            ke_cutoff = tools.gs_to_cutoff(cell.lattice_vectors(),
                                           self.gs).min()
        else:
            ke_cutoff = numpy.min(cell.ke_cutoff)
        ke_guess = estimate_ke_cutoff(cell, cell.precision)
        if ke_cutoff < ke_guess * .8:
            gs_guess = tools.cutoff_to_gs(cell.lattice_vectors(), ke_guess)
            logger.warn(
                self, 'ke_cutoff/gs (%g / %s) is not enough for FFTDF '
                'to get integral accuracy %g.\nCoulomb integral error '
                'is ~ %.2g Eh.\nRecomended ke_cutoff/gs are %g / %s.',
                ke_cutoff, self.gs, cell.precision,
                error_for_ke_cutoff(cell, ke_cutoff), ke_guess, gs_guess)
        return self
Beispiel #2
0
    def check_sanity(self):
        lib.StreamObject.check_sanity(self)
        cell = self.cell
        if not cell.has_ecp():
            logger.warn(
                self, 'AFTDF integrals are found in all-electron '
                'calculation.  It often causes huge error.\n'
                'Recommended methods are DF or MDF. In SCF calculation, '
                'they can be initialized as\n'
                '        mf = mf.density_fit()\nor\n'
                '        mf = mf.mix_density_fit()')

        if cell.dimension > 0:
            if cell.ke_cutoff is None:
                ke_cutoff = tools.mesh_to_cutoff(cell.lattice_vectors(),
                                                 self.mesh)
                ke_cutoff = ke_cutoff[:cell.dimension].min()
            else:
                ke_cutoff = numpy.min(cell.ke_cutoff)
            ke_guess = estimate_ke_cutoff(cell, cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if ke_cutoff < ke_guess * KE_SCALING:
                logger.warn(
                    self, 'ke_cutoff/mesh (%g / %s) is not enough for AFTDF '
                    'to get integral accuracy %g.\nCoulomb integral error '
                    'is ~ %.2g Eh.\nRecommended ke_cutoff/mesh are %g / %s.',
                    ke_cutoff, self.mesh, cell.precision,
                    error_for_ke_cutoff(cell, ke_cutoff), ke_guess, mesh_guess)
        else:
            mesh_guess = numpy.copy(self.mesh)

        if cell.dimension < 3:
            err = numpy.exp(-0.436392335 * min(self.mesh[cell.dimension:]) -
                            2.99944305)
            err *= cell.nelectron
            meshz = pbcgto.cell._mesh_inf_vaccum(cell)
            mesh_guess[cell.dimension:] = int(meshz)
            if err > cell.precision * 10:
                logger.warn(
                    self, 'mesh %s of AFTDF may not be enough to get '
                    'integral accuracy %g for %dD PBC system.\n'
                    'Coulomb integral error is ~ %.2g Eh.\n'
                    'Recommended mesh is %s.', self.mesh, cell.precision,
                    cell.dimension, err, mesh_guess)
            if (cell.mesh[cell.dimension:] / (1. * meshz) > 1.1).any():
                meshz = pbcgto.cell._mesh_inf_vaccum(cell)
                logger.warn(
                    self,
                    'setting mesh %s of AFTDF too high in non-periodic direction '
                    '(=%s) can result in an unnecessarily slow calculation.\n'
                    'For coulomb integral error of ~ %.2g Eh in %dD PBC, \n'
                    'a recommended mesh for non-periodic direction is %s.',
                    self.mesh, self.mesh[cell.dimension:], cell.precision,
                    cell.dimension, mesh_guess[cell.dimension:])
        return self
Beispiel #3
0
    def check_sanity(self):
        lib.StreamObject.check_sanity(self)
        cell = self.cell
        if not cell.has_ecp():
            logger.warn(self, 'AFTDF integrals are found in all-electron '
                        'calculation.  It often causes huge error.\n'
                        'Recommended methods are DF or MDF. In SCF calculation, '
                        'they can be initialized as\n'
                        '        mf = mf.density_fit()\nor\n'
                        '        mf = mf.mix_density_fit()')

        if cell.dimension > 0:
            if cell.ke_cutoff is None:
                ke_cutoff = tools.mesh_to_cutoff(cell.lattice_vectors(), self.mesh)
                ke_cutoff = ke_cutoff[:cell.dimension].min()
            else:
                ke_cutoff = numpy.min(cell.ke_cutoff)
            ke_guess = estimate_ke_cutoff(cell, cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if ke_cutoff < ke_guess * KE_SCALING:
                logger.warn(self, 'ke_cutoff/mesh (%g / %s) is not enough for AFTDF '
                            'to get integral accuracy %g.\nCoulomb integral error '
                            'is ~ %.2g Eh.\nRecommended ke_cutoff/mesh are %g / %s.',
                            ke_cutoff, self.mesh, cell.precision,
                            error_for_ke_cutoff(cell, ke_cutoff), ke_guess, mesh_guess)
        else:
            mesh_guess = numpy.copy(self.mesh)

        if cell.dimension < 3:
            err = numpy.exp(-0.436392335*min(self.mesh[cell.dimension:]) - 2.99944305)
            err *= cell.nelectron
            meshz = pbcgto.cell._mesh_inf_vaccum(cell)
            mesh_guess[cell.dimension:] = int(meshz)
            if err > cell.precision*10:
                logger.warn(self, 'mesh %s of AFTDF may not be enough to get '
                            'integral accuracy %g for %dD PBC system.\n'
                            'Coulomb integral error is ~ %.2g Eh.\n'
                            'Recommended mesh is %s.',
                            self.mesh, cell.precision, cell.dimension, err, mesh_guess)
            if (cell.mesh[cell.dimension:]/(1.*meshz) > 1.1).any():
                meshz = pbcgto.cell._mesh_inf_vaccum(cell)
                logger.warn(self, 'setting mesh %s of AFTDF too high in non-periodic direction '
                            '(=%s) can result in an unnecessarily slow calculation.\n'
                            'For coulomb integral error of ~ %.2g Eh in %dD PBC, \n'
                            'a recommended mesh for non-periodic direction is %s.',
                            self.mesh, self.mesh[cell.dimension:], cell.precision,
                            cell.dimension, mesh_guess[cell.dimension:])
        return self
Beispiel #4
0
    def check_sanity(self):
        lib.StreamObject.check_sanity(self)
        cell = self.cell
        if not cell.has_ecp():
            logger.warn(
                self, 'FFTDF integrals are found in all-electron '
                'calculation.  It often causes huge error.\n'
                'Recommended methods are DF or MDF. In SCF calculation, '
                'they can be initialized as\n'
                '        mf = mf.density_fit()\nor\n'
                '        mf = mf.mix_density_fit()')

        if cell.dimension > 0:
            if cell.ke_cutoff is None:
                ke_cutoff = tools.gs_to_cutoff(cell.lattice_vectors(), self.gs)
                ke_cutoff = ke_cutoff[:cell.dimension].min()
            else:
                ke_cutoff = numpy.min(cell.ke_cutoff)
            ke_guess = estimate_ke_cutoff(cell, cell.precision)
            if ke_cutoff < ke_guess * .8:
                gs_guess = tools.cutoff_to_gs(cell.lattice_vectors(), ke_guess)
                logger.warn(
                    self, 'ke_cutoff/gs (%g / %s) is not enough for FFTDF '
                    'to get integral accuracy %g.\nCoulomb integral error '
                    'is ~ %.2g Eh.\nRecomended ke_cutoff/gs are %g / %s.',
                    ke_cutoff, self.gs, cell.precision,
                    error_for_ke_cutoff(cell, ke_cutoff), ke_guess, gs_guess)
        else:
            gs_guess = numpy.copy(self.gs)

        if cell.dimension < 3:
            err = numpy.exp(-0.87278467 * min(self.gs[cell.dimension:]) -
                            2.99944305)
            err *= cell.nelectron
            if err > cell.precision * 10:
                gz = numpy.log(
                    cell.nelectron / cell.precision) / 0.8727847 - 3.4366358
                gs_guess[cell.dimension:] = int(gz)
                logger.warn(
                    self, 'gs %s of AFTDF may not be enough to get '
                    'integral accuracy %g for %dD PBC system.\n'
                    'Coulomb integral error is ~ %.2g Eh.\n'
                    'Recomended gs is %s.', self.gs, cell.precision,
                    cell.dimension, err, gs_guess)
        return self
Beispiel #5
0
    def check_sanity(self):
        lib.StreamObject.check_sanity(self)
        cell = self.cell
        if cell.dimension < 2:
            raise RuntimeError(
                'FFTDF method does not support 0D/1D low-dimension '
                'PBC system.  DF, MDF or AFTDF methods should '
                'be used.\nSee also examples/pbc/31-low_dimensional_pbc.py')
        if cell.dimension == 2 and self.low_dim_ft_type is None:
            raise RuntimeError(
                'FFTDF method does not support low_dim_ft_type of None '
                'for 2D systems.  Supported types include \'analytic_2d_1\'. '
                '\nSee also examples/pbc/32-graphene.py')

        if not cell.has_ecp():
            logger.warn(
                self, 'FFTDF integrals are found in all-electron '
                'calculation.  It often causes huge error.\n'
                'Recommended methods are DF or MDF. In SCF calculation, '
                'they can be initialized as\n'
                '        mf = mf.density_fit()\nor\n'
                '        mf = mf.mix_density_fit()')

        if cell.ke_cutoff is None:
            ke_cutoff = tools.mesh_to_cutoff(cell.lattice_vectors(),
                                             self.mesh).min()
        else:
            ke_cutoff = numpy.min(cell.ke_cutoff)
        ke_guess = estimate_ke_cutoff(cell, cell.precision)
        if ke_cutoff < ke_guess * KE_SCALING:
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            logger.warn(
                self, 'ke_cutoff/mesh (%g / %s) is not enough for FFTDF '
                'to get integral accuracy %g.\nCoulomb integral error '
                'is ~ %.2g Eh.\nRecommended ke_cutoff/mesh are %g / %s.',
                ke_cutoff, self.mesh, cell.precision,
                error_for_ke_cutoff(cell, ke_cutoff), ke_guess, mesh_guess)
        return self
Beispiel #6
0
def _dip_correction(mf):
    '''Makov-Payne corrections for charged systems.'''
    from pyscf.pbc import tools
    from pyscf.pbc.dft import gen_grid
    log = logger.new_logger(mf)
    cell = mf.cell
    a = cell.lattice_vectors()
    b = np.linalg.inv(a).T

    grids = gen_grid.UniformGrids(cell)
    ke_cutoff = gto.estimate_ke_cutoff(cell, 1e-5)
    grids.mesh = tools.cutoff_to_mesh(a, ke_cutoff)

    dm = mf.make_rdm1()
    rho = mf.get_rho(dm, grids, mf.kpt)
    origin = _search_dipole_gauge_origin(cell, grids, rho, log)

    def shift_grids(r):
        r_frac = lib.dot(r - origin, b.T)
        # Grids on the boundary (r_frac == +/-0.5) of the new cell may lead to
        # unbalanced contributions to the dipole moment. Exclude them from the
        # dipole and quadrupole
        r_frac[r_frac == 0.5] = 0
        r_frac[r_frac == -0.5] = 0
        r_frac[r_frac > 0.5] -= 1
        r_frac[r_frac < -0.5] += 1
        r = lib.dot(r_frac, a)
        return r

    #           SC              BCC             FCC
    madelung = (-2.83729747948, -3.63923344951, -4.58486207411)
    vol = cell.vol
    L = vol**(1. / 3)
    chg = cell.charge

    # epsilon is the dielectric constant of the system. For systems
    # surrounded by vacuum, epsilon = 1.
    epsilon = 1

    # Energy correction of point charges of a simple cubic lattice.
    de_mono = -chg**2 * np.array(madelung) / (2 * L * epsilon)

    # dipole energy correction
    r_e = shift_grids(grids.coords)
    r_nuc = shift_grids(cell.atom_coords())
    charges = cell.atom_charges()
    e_dip = np.einsum('g,g,gx->x', rho, grids.weights, r_e)
    nuc_dip = np.einsum('g,gx->x', charges, r_nuc)
    dip = nuc_dip - e_dip
    de_dip = -2. * np.pi / (3 * cell.vol) * np.linalg.norm(dip)**2

    # quadrupole energy correction
    if abs(a - np.eye(3) * L).max() > 1e-5:
        logger.warn(
            mf, 'System is not cubic cell. Quadrupole energy '
            'correction is inaccurate since it is developed based on '
            'cubic cell.')
    e_quad = np.einsum('g,g,gx,gx->', rho, grids.weights, r_e, r_e)
    nuc_quad = np.einsum('g,gx,gx->', charges, r_nuc, r_nuc)
    quad = nuc_quad - e_quad
    de_quad = 2. * np.pi / (3 * cell.vol) * quad

    de = de_mono + de_dip + de_quad
    return de_mono, de_dip, de_quad, de
Beispiel #7
0
def get_pp_loc_part1(mydf, kpts=None):
    cell = mydf.cell
    if kpts is None:
        kpts_lst = numpy.zeros((1, 3))
    else:
        kpts_lst = numpy.reshape(kpts, (-1, 3))

    log = logger.Logger(mydf.stdout, mydf.verbose)
    t0 = t1 = (time.clock(), time.time())

    mesh = numpy.asarray(mydf.mesh)
    nkpts = len(kpts_lst)
    nao = cell.nao_nr()
    nao_pair = nao * (nao + 1) // 2
    charges = cell.atom_charges()

    kpt_allow = numpy.zeros(3)
    if mydf.eta == 0:
        if cell.dimension > 0:
            ke_guess = estimate_ke_cutoff(cell, cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if numpy.any(
                    mesh[:cell.dimension] < mesh_guess[:cell.dimension] * .8):
                logger.warn(
                    mydf, 'mesh %s is not enough for AFTDF.get_nuc function '
                    'to get integral accuracy %g.\nRecommended mesh is %s.',
                    mesh, cell.precision, mesh_guess)
        Gv, Gvbase, kws = cell.get_Gv_weights(mesh)

        vpplocG = pseudo.pp_int.get_gth_vlocG_part1(cell, Gv)
        vpplocG = -numpy.einsum('ij,ij->j', cell.get_SI(Gv), vpplocG)

        vpplocG *= kws
        vG = vpplocG
        vj = numpy.zeros((nkpts, nao_pair), dtype=numpy.complex128)

    else:
        if cell.dimension > 0:
            ke_guess = estimate_ke_cutoff_for_eta(cell, mydf.eta,
                                                  cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if numpy.any(mesh < mesh_guess * .8):
                logger.warn(
                    mydf, 'mesh %s is not enough for AFTDF.get_nuc function '
                    'to get integral accuracy %g.\nRecommended mesh is %s.',
                    mesh, cell.precision, mesh_guess)
            mesh_min = numpy.min((mesh_guess, mesh), axis=0)
            if cell.dimension < 2 or cell.low_dim_ft_type == 'inf_vacuum':
                mesh[:cell.dimension] = mesh_min[:cell.dimension]
            else:
                mesh = mesh_min
        Gv, Gvbase, kws = cell.get_Gv_weights(mesh)

        nuccell = _compensate_nuccell(mydf)
        # PP-loc part1 is handled by fakenuc in _int_nuc_vloc
        vj = lib.asarray(mydf._int_nuc_vloc(nuccell, kpts_lst))
        t0 = t1 = log.timer_debug1('vnuc pass1: analytic int', *t0)

        coulG = tools.get_coulG(cell, kpt_allow, mesh=mesh, Gv=Gv) * kws
        aoaux = ft_ao.ft_ao(nuccell, Gv)
        vG = numpy.einsum('i,xi->x', -charges, aoaux) * coulG

    max_memory = max(2000, mydf.max_memory - lib.current_memory()[0])
    for aoaoks, p0, p1 in mydf.ft_loop(mesh,
                                       kpt_allow,
                                       kpts_lst,
                                       max_memory=max_memory,
                                       aosym='s2'):
        for k, aoao in enumerate(aoaoks):
            # rho_ij(G) nuc(-G) / G^2
            # = [Re(rho_ij(G)) + Im(rho_ij(G))*1j] [Re(nuc(G)) - Im(nuc(G))*1j] / G^2
            if gamma_point(kpts_lst[k]):
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].real, aoao.real)
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].imag, aoao.imag)
            else:
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].conj(), aoao)
        t1 = log.timer_debug1('contracting Vnuc [%s:%s]' % (p0, p1), *t1)
    log.timer_debug1('contracting Vnuc', *t0)

    vj_kpts = []
    for k, kpt in enumerate(kpts_lst):
        if gamma_point(kpt):
            vj_kpts.append(lib.unpack_tril(vj[k].real.copy()))
        else:
            vj_kpts.append(lib.unpack_tril(vj[k]))

    if kpts is None or numpy.shape(kpts) == (3, ):
        vj_kpts = vj_kpts[0]
    return numpy.asarray(vj_kpts)
Beispiel #8
0
Datei: hf.py Projekt: sunqm/pyscf
def _dip_correction(mf):
    '''Makov-Payne corrections for charged systems.'''
    from pyscf.pbc import gto
    from pyscf.pbc import tools
    from pyscf.pbc.dft import gen_grid
    log = logger.new_logger(mf)
    cell = mf.cell
    a = cell.lattice_vectors()
    b = np.linalg.inv(a).T

    grids = gen_grid.UniformGrids(cell)
    ke_cutoff = gto.estimate_ke_cutoff(cell, 1e-5)
    grids.mesh = tools.cutoff_to_mesh(a, ke_cutoff)

    dm = mf.make_rdm1()
    rho = mf.get_rho(dm, grids, mf.kpt)
    origin = _search_dipole_gauge_origin(cell, grids, rho, log)

    def shift_grids(r):
        r_frac = lib.dot(r - origin, b.T)
        # Grids on the boundary (r_frac == +/-0.5) of the new cell may lead to
        # unbalanced contributions to the dipole moment. Exclude them from the
        # dipole and quadrupole
        r_frac[r_frac== 0.5] = 0
        r_frac[r_frac==-0.5] = 0
        r_frac[r_frac > 0.5] -= 1
        r_frac[r_frac <-0.5] += 1
        r = lib.dot(r_frac, a)
        return r

    #           SC              BCC             FCC
    madelung = (-2.83729747948, -3.63923344951, -4.58486207411)
    vol = cell.vol
    L = vol ** (1./3)
    chg = cell.charge

    # epsilon is the dielectric constant of the system. For systems
    # surrounded by vacuum, epsilon = 1.
    epsilon = 1

    # Energy correction of point charges of a simple cubic lattice.
    de_mono = - chg**2 * np.array(madelung) / (2 * L * epsilon)

    # dipole energy correction
    r_e = shift_grids(grids.coords)
    r_nuc = shift_grids(cell.atom_coords())
    charges = cell.atom_charges()
    e_dip = np.einsum('g,g,gx->x', rho, grids.weights, r_e)
    nuc_dip = np.einsum('g,gx->x', charges, r_nuc)
    dip = nuc_dip - e_dip
    de_dip = -2.*np.pi/(3*cell.vol) * np.linalg.norm(dip)**2

    # quadrupole energy correction
    if abs(a - np.eye(3)*L).max() > 1e-5:
        logger.warn(mf, 'System is not cubic cell. Quadrupole energy '
                    'correction is inaccurate since it is developed based on '
                    'cubic cell.')
    e_quad = np.einsum('g,g,gx,gx->', rho, grids.weights, r_e, r_e)
    nuc_quad = np.einsum('g,gx,gx->', charges, r_nuc, r_nuc)
    quad = nuc_quad - e_quad
    de_quad = 2.*np.pi/(3*cell.vol) * quad

    de = de_mono + de_dip + de_quad
    return de_mono, de_dip, de_quad, de
Beispiel #9
0
def get_nuc(mydf, kpts=None):
    cell = mydf.cell
    if kpts is None:
        kpts_lst = numpy.zeros((1, 3))
    else:
        kpts_lst = numpy.reshape(kpts, (-1, 3))

    log = logger.Logger(mydf.stdout, mydf.verbose)
    t0 = t1 = (time.clock(), time.time())

    mesh = numpy.asarray(mydf.mesh)
    nkpts = len(kpts_lst)
    nao = cell.nao_nr()
    nao_pair = nao * (nao + 1) // 2
    charges = cell.atom_charges()

    kpt_allow = numpy.zeros(3)
    if mydf.eta == 0:
        if cell.dimension > 0:
            ke_guess = estimate_ke_cutoff(cell, cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if numpy.any(mesh < mesh_guess * .8):
                logger.warn(
                    mydf, 'mesh %s is not enough for AFTDF.get_nuc function '
                    'to get integral accuracy %g.\nRecommended mesh is %s.',
                    mesh, cell.precision, mesh_guess)
        Gv, Gvbase, kws = cell.get_Gv_weights(mesh)

        vpplocG = pseudo.pp_int.get_gth_vlocG_part1(cell, Gv)
        vpplocG = -numpy.einsum('ij,ij->j', cell.get_SI(Gv), vpplocG)
        v1 = -vpplocG.copy()

        if cell.dimension == 1 or cell.dimension == 2:
            G0idx, SI_on_z = pbcgto.cell._SI_for_uniform_model_charge(cell, Gv)
            coulG = 4 * numpy.pi / numpy.linalg.norm(Gv[G0idx], axis=1)**2
            vpplocG[G0idx] += charges.sum() * SI_on_z * coulG

        vpplocG *= kws
        vG = vpplocG
        vj = numpy.zeros((nkpts, nao_pair), dtype=numpy.complex128)

    else:
        if cell.dimension > 0:
            ke_guess = estimate_ke_cutoff_for_eta(cell, mydf.eta,
                                                  cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if numpy.any(mesh < mesh_guess * .8):
                logger.warn(
                    mydf, 'mesh %s is not enough for AFTDF.get_nuc function '
                    'to get integral accuracy %g.\nRecommended mesh is %s.',
                    mesh, cell.precision, mesh_guess)
            mesh_min = numpy.min(
                (mesh_guess[:cell.dimension], mesh[:cell.dimension]), axis=0)
            mesh[:cell.dimension] = mesh_min.astype(int)
        Gv, Gvbase, kws = cell.get_Gv_weights(mesh)

        nuccell = copy.copy(cell)
        half_sph_norm = .5 / numpy.sqrt(numpy.pi)
        norm = half_sph_norm / gto.gaussian_int(2, mydf.eta)
        chg_env = [mydf.eta, norm]
        ptr_eta = cell._env.size
        ptr_norm = ptr_eta + 1
        chg_bas = [[ia, 0, 1, 1, 0, ptr_eta, ptr_norm, 0]
                   for ia in range(cell.natm)]
        nuccell._atm = cell._atm
        nuccell._bas = numpy.asarray(chg_bas, dtype=numpy.int32)
        nuccell._env = numpy.hstack((cell._env, chg_env))

        # PP-loc part1 is handled by fakenuc in _int_nuc_vloc
        vj = lib.asarray(mydf._int_nuc_vloc(nuccell, kpts_lst))
        t0 = t1 = log.timer_debug1('vnuc pass1: analytic int', *t0)

        coulG = tools.get_coulG(cell, kpt_allow, mesh=mesh, Gv=Gv) * kws
        aoaux = ft_ao.ft_ao(nuccell, Gv)
        vG = numpy.einsum('i,xi->x', -charges, aoaux) * coulG

        if cell.dimension == 1 or cell.dimension == 2:
            G0idx, SI_on_z = pbcgto.cell._SI_for_uniform_model_charge(cell, Gv)
            vG[G0idx] += charges.sum() * SI_on_z * coulG[G0idx]

    max_memory = max(2000, mydf.max_memory - lib.current_memory()[0])
    for aoaoks, p0, p1 in mydf.ft_loop(mesh,
                                       kpt_allow,
                                       kpts_lst,
                                       max_memory=max_memory,
                                       aosym='s2'):
        for k, aoao in enumerate(aoaoks):
            # rho_ij(G) nuc(-G) / G^2
            # = [Re(rho_ij(G)) + Im(rho_ij(G))*1j] [Re(nuc(G)) - Im(nuc(G))*1j] / G^2
            if gamma_point(kpts_lst[k]):
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].real, aoao.real)
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].imag, aoao.imag)
            else:
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].conj(), aoao)
        t1 = log.timer_debug1('contracting Vnuc [%s:%s]' % (p0, p1), *t1)
    log.timer_debug1('contracting Vnuc', *t0)

    vj_kpts = []
    for k, kpt in enumerate(kpts_lst):
        if gamma_point(kpt):
            vj_kpts.append(lib.unpack_tril(vj[k].real.copy()))
        else:
            vj_kpts.append(lib.unpack_tril(vj[k]))

    if kpts is None or numpy.shape(kpts) == (3, ):
        vj_kpts = vj_kpts[0]
    return numpy.asarray(vj_kpts)
Beispiel #10
0
def get_pp_loc_part1(mydf, kpts=None):
    cell = mydf.cell
    if kpts is None:
        kpts_lst = numpy.zeros((1,3))
    else:
        kpts_lst = numpy.reshape(kpts, (-1,3))

    log = logger.Logger(mydf.stdout, mydf.verbose)
    t0 = t1 = (time.clock(), time.time())

    mesh = numpy.asarray(mydf.mesh)
    nkpts = len(kpts_lst)
    nao = cell.nao_nr()
    nao_pair = nao * (nao+1) // 2
    charges = cell.atom_charges()

    kpt_allow = numpy.zeros(3)
    if mydf.eta == 0:
        if cell.dimension > 0:
            ke_guess = estimate_ke_cutoff(cell, cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if numpy.any(mesh[:cell.dimension] < mesh_guess[:cell.dimension]*.8):
                logger.warn(mydf, 'mesh %s is not enough for AFTDF.get_nuc function '
                            'to get integral accuracy %g.\nRecommended mesh is %s.',
                            mesh, cell.precision, mesh_guess)
        Gv, Gvbase, kws = cell.get_Gv_weights(mesh)

        vpplocG = pseudo.pp_int.get_gth_vlocG_part1(cell, Gv)
        vpplocG = -numpy.einsum('ij,ij->j', cell.get_SI(Gv), vpplocG)

        vpplocG *= kws
        vG = vpplocG
        vj = numpy.zeros((nkpts,nao_pair), dtype=numpy.complex128)

    else:
        if cell.dimension > 0:
            ke_guess = estimate_ke_cutoff_for_eta(cell, mydf.eta, cell.precision)
            mesh_guess = tools.cutoff_to_mesh(cell.lattice_vectors(), ke_guess)
            if numpy.any(mesh < mesh_guess*.8):
                logger.warn(mydf, 'mesh %s is not enough for AFTDF.get_nuc function '
                            'to get integral accuracy %g.\nRecommended mesh is %s.',
                            mesh, cell.precision, mesh_guess)
            mesh_min = numpy.min((mesh_guess, mesh), axis=0)
            if cell.dimension < 2 or cell.low_dim_ft_type == 'inf_vacuum':
                mesh[:cell.dimension] = mesh_min[:cell.dimension]
            else:
                mesh = mesh_min
        Gv, Gvbase, kws = cell.get_Gv_weights(mesh)

        nuccell = _compensate_nuccell(mydf)
        # PP-loc part1 is handled by fakenuc in _int_nuc_vloc
        vj = lib.asarray(mydf._int_nuc_vloc(nuccell, kpts_lst))
        t0 = t1 = log.timer_debug1('vnuc pass1: analytic int', *t0)

        coulG = tools.get_coulG(cell, kpt_allow, mesh=mesh, Gv=Gv) * kws
        aoaux = ft_ao.ft_ao(nuccell, Gv)
        vG = numpy.einsum('i,xi->x', -charges, aoaux) * coulG

    max_memory = max(2000, mydf.max_memory-lib.current_memory()[0])
    for aoaoks, p0, p1 in mydf.ft_loop(mesh, kpt_allow, kpts_lst,
                                       max_memory=max_memory, aosym='s2'):
        for k, aoao in enumerate(aoaoks):
# rho_ij(G) nuc(-G) / G^2
# = [Re(rho_ij(G)) + Im(rho_ij(G))*1j] [Re(nuc(G)) - Im(nuc(G))*1j] / G^2
            if gamma_point(kpts_lst[k]):
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].real, aoao.real)
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].imag, aoao.imag)
            else:
                vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].conj(), aoao)
        t1 = log.timer_debug1('contracting Vnuc [%s:%s]'%(p0, p1), *t1)
    log.timer_debug1('contracting Vnuc', *t0)

    vj_kpts = []
    for k, kpt in enumerate(kpts_lst):
        if gamma_point(kpt):
            vj_kpts.append(lib.unpack_tril(vj[k].real.copy()))
        else:
            vj_kpts.append(lib.unpack_tril(vj[k]))

    if kpts is None or numpy.shape(kpts) == (3,):
        vj_kpts = vj_kpts[0]
    return numpy.asarray(vj_kpts)