Example #1
0
File: pbc.py Project: eronca/pyscf
def get_lattice_Ls(cell, nimgs=None, rcut=None, dimension=None):
    '''Get the (Cartesian, unitful) lattice translation vectors for nearby images.
    The translation vectors can be used for the lattice summation.'''
    b = cell.reciprocal_vectors(norm_to=1)
    heights_inv = lib.norm(b, axis=1)

    if nimgs is None:
        if rcut is None:
            rcut = cell.rcut
# plus 1 image in rcut to handle the case atoms within the adjacent cells are
# close to each other
        rcut = rcut + min(1./heights_inv)
        nimgs = np.ceil(rcut*heights_inv)
    else:
        rcut = max((np.asarray(nimgs))/heights_inv) + min(1./heights_inv) # ~ the inradius

    if dimension is None:
        dimension = cell.dimension
    if dimension == 0:
        nimgs = [0, 0, 0]
    elif dimension == 1:
        nimgs = [nimgs[0], 0, 0]
    elif dimension == 2:
        nimgs = [nimgs[0], nimgs[1], 0]

    Ts = lib.cartesian_prod((np.arange(-nimgs[0],nimgs[0]+1),
                             np.arange(-nimgs[1],nimgs[1]+1),
                             np.arange(-nimgs[2],nimgs[2]+1)))
    Ls = np.dot(Ts, cell.lattice_vectors())
    Ls = Ls[lib.norm(Ls, axis=1)<rcut]
    return np.asarray(Ls, order='C')
Example #2
0
 def norm_xy(w, z):
     zp = e_ia * z.reshape(e_ia.shape)
     zm = w/e_ia * z.reshape(e_ia.shape)
     x = (zp + zm) * .5
     y = (zp - zm) * .5
     norm = lib.norm(x)**2 - lib.norm(y)**2
     norm = numpy.sqrt(.5/norm)  # normalize to 0.5 for alpha spin
     return (x*norm, y*norm)
Example #3
0
File: rks.py Project: eronca/pyscf
 def norm_xy(w, z):
     zp = eai * z.reshape(eai.shape)
     zm = w/eai * z.reshape(eai.shape)
     x = (zp + zm) * .5
     y = (zp - zm) * .5
     norm = 2*(lib.norm(x)**2 - lib.norm(y)**2)
     norm = 1/numpy.sqrt(norm)
     return x*norm,y*norm
Example #4
0
    def search_possible_rotations(self, zaxis=None):
        '''If zaxis is given, the rotation axis is parallel to zaxis'''
        maybe_cn = []
        for lst in self.group_atoms_by_distance:
            natm = len(lst)
            if natm > 1:
                coords = self.atoms[lst,1:]
# possible C2 axis
                for i in range(1, natm):
                    if abs(coords[0]+coords[i]).sum() > TOLERANCE:
                        maybe_cn.append((coords[0]+coords[i], 2))
                    else: # abs(coords[0]-coords[i]).sum() > TOLERANCE:
                        maybe_cn.append((coords[0]-coords[i], 2))

# atoms of equal distances may be associated with rotation axis > C2.
                r0 = coords - coords[0]
                distance = norm(r0, axis=1)
                eq_distance = abs(distance[:,None] - distance) < TOLERANCE
                for i in range(2, natm):
                    for j in numpy.where(eq_distance[i,:i])[0]:
                        cos = numpy.dot(r0[i],r0[j]) / (distance[i]*distance[j])
                        ang = numpy.arccos(cos)
                        nfrac = numpy.pi*2 / (numpy.pi-ang)
                        n = int(numpy.around(nfrac))
                        if abs(nfrac-n) < TOLERANCE:
                            maybe_cn.append((numpy.cross(r0[i],r0[j]),n))

        # remove zero-vectors and duplicated vectors
        vecs = numpy.vstack([x[0] for x in maybe_cn])
        idx = norm(vecs, axis=1) > TOLERANCE
        ns = numpy.hstack([x[1] for x in maybe_cn])
        vecs = _normalize(vecs[idx])
        ns = ns[idx]

        if zaxis is not None:  # Keep parallel rotation axes
            cos = numpy.dot(vecs, _normalize(zaxis))
            vecs = vecs[(abs(cos-1) < TOLERANCE) | (abs(cos+1) < TOLERANCE)]
            ns = ns[(abs(cos-1) < TOLERANCE) | (abs(cos+1) < TOLERANCE)]

        possible_cn = []
        seen = numpy.zeros(len(vecs), dtype=bool)
        for k, v in enumerate(vecs):
            if not seen[k]:
                where1 = numpy.einsum('ix->i', abs(vecs[k:] - v)) < TOLERANCE
                where1 = numpy.where(where1)[0] + k
                where2 = numpy.einsum('ix->i', abs(vecs[k:] + v)) < TOLERANCE
                where2 = numpy.where(where2)[0] + k
                seen[where1] = True
                seen[where2] = True

                vk = _normalize((numpy.einsum('ix->x', vecs[where1]) -
                                 numpy.einsum('ix->x', vecs[where2])))
                for n in (set(ns[where1]) | set(ns[where2])):
                    possible_cn.append((vk,n))
        return possible_cn
Example #5
0
def precompute_exx(cell, kpts):
    from pyscf.pbc import gto as pbcgto
    from pyscf.pbc.dft import gen_grid
    log = lib.logger.Logger(cell.stdout, cell.verbose)
    log.debug("# Precomputing Wigner-Seitz EXX kernel")
    Nk = get_monkhorst_pack_size(cell, kpts)
    log.debug("# Nk = %s", Nk)

    kcell = pbcgto.Cell()
    kcell.atom = 'H 0. 0. 0.'
    kcell.spin = 1
    kcell.unit = 'B'
    kcell.verbose = 0
    kcell.a = cell.lattice_vectors() * Nk
    Lc = 1.0/lib.norm(np.linalg.inv(kcell.a), axis=0)
    log.debug("# Lc = %s", Lc)
    Rin = Lc.min() / 2.0
    log.debug("# Rin = %s", Rin)
    # ASE:
    alpha = 5./Rin # sqrt(-ln eps) / Rc, eps ~ 10^{-11}
    log.info("WS alpha = %s", alpha)
    kcell.mesh = np.array([4*int(L*alpha*3.0) for L in Lc])  # ~ [60,60,60]
    # QE:
    #alpha = 3./Rin * np.sqrt(0.5)
    #kcell.mesh = (4*alpha*np.linalg.norm(kcell.a,axis=1)).astype(int)
    log.debug("# kcell.mesh FFT = %s", kcell.mesh)
    kcell.build(False,False)
    rs = gen_grid.gen_uniform_grids(kcell)
    kngs = len(rs)
    log.debug("# kcell kngs = %d", kngs)
    corners = np.dot(np.indices((2,2,2)).reshape((3,8)).T, kcell.a)
    #vR = np.empty(kngs)
    #for i, rv in enumerate(rs):
    #    # Minimum image convention to corners of kcell parallelepiped
    #    r = lib.norm(rv-corners, axis=1).min()
    #    if np.isclose(r, 0.):
    #        vR[i] = 2*alpha / np.sqrt(np.pi)
    #    else:
    #        vR[i] = scipy.special.erf(alpha*r) / r
    r = np.min([lib.norm(rs-c, axis=1) for c in corners], axis=0)
    vR = scipy.special.erf(alpha*r) / (r+1e-200)
    vR[r<1e-9] = 2*alpha / np.sqrt(np.pi)
    vG = (kcell.vol/kngs) * fft(vR, kcell.mesh)
    ws_exx = {'alpha': alpha,
              'kcell': kcell,
              'q'    : kcell.Gv,
              'vq'   : vG}
    log.debug("# Finished precomputing")
    return ws_exx
Example #6
0
    def vppnl_by_k(kpt):
        Gk = Gv + kpt
        G_rad = lib.norm(Gk, axis=1)
        aokG = ft_ao.ft_ao(cell, Gv, kpt=kpt) * (ngs / cell.vol)
        vppnl = 0
        for ia in range(cell.natm):
            symb = cell.atom_symbol(ia)
            if symb not in cell._pseudo:
                continue
            pp = cell._pseudo[symb]
            for l, proj in enumerate(pp[5:]):
                rl, nl, hl = proj
                if nl > 0:
                    hl = numpy.asarray(hl)
                    fakemol._bas[0, gto.ANG_OF] = l
                    fakemol._env[ptr + 3] = 0.5 * rl ** 2
                    fakemol._env[ptr + 4] = rl ** (l + 1.5) * numpy.pi ** 1.25
                    pYlm_part = dft.numint.eval_ao(fakemol, Gk, deriv=0)

                    pYlm = numpy.empty((nl, l * 2 + 1, ngs))
                    for k in range(nl):
                        qkl = pseudo.pp._qli(G_rad * rl, l, k)
                        pYlm[k] = pYlm_part.T * qkl
                    # pYlm is real
                    SPG_lmi = numpy.einsum("g,nmg->nmg", SI[ia].conj(), pYlm)
                    SPG_lm_aoG = numpy.einsum("nmg,gp->nmp", SPG_lmi, aokG)
                    tmp = numpy.einsum("ij,jmp->imp", hl, SPG_lm_aoG)
                    vppnl += numpy.einsum("imp,imq->pq", SPG_lm_aoG.conj(), tmp)
        return vppnl * (1.0 / ngs ** 2)
Example #7
0
def estimate_eta(cell, cutoff=1e-12):
    '''The exponent of the smooth gaussian model density, requiring that at
    boundary, density ~ 4pi rmax^2 exp(-eta*rmax^2) ~ 1e-12
    '''
    rmax = max(lib.norm(cell.lattice_vectors(), axis=0))
    eta = max(-numpy.log(cutoff/(4*numpy.pi*rmax**2))/rmax**2, .1)
    return eta
Example #8
0
def cosmo_fock_o1(cosmo, dm):
    mol = cosmo.mol
    nao = dm.shape[0]
    # phi
    cosmo.loadsegs()
    coords = cosmo.cosurf[:cosmo.nps*3].reshape(-1,3)
    fakemol = _make_fakemol(coords)
    j3c = df.incore.aux_e2(mol, fakemol, intor='cint3c2e_sph', aosym='s2ij')
    tril_dm = lib.pack_tril(dm) * 2
    diagidx = numpy.arange(nao)
    diagidx = diagidx*(diagidx+1)//2 + diagidx
    tril_dm[diagidx] *= .5
    cosmo.phi = -numpy.einsum('x,xk->k', tril_dm, j3c)
    for ia in range(mol.natm):
        cosmo.phi += mol.atom_charge(ia)/lib.norm(mol.atom_coord(ia)-coords, axis=1)
    cosmo.savesegs()
    # qk
    cosmo.charges()
    # vpot
    cosmo.loadsegs()
#X    fakemol = _make_fakemol(cosmo.cosurf[:cosmo.nps*3].reshape(-1,3))
#X    j3c = df.incore.aux_e2(mol, fakemol, intor='cint3c2e_sph', aosym='s2ij')
    fock = lib.unpack_tril(numpy.einsum('xk,k->x', j3c, -cosmo.qcos[:cosmo.nps]))
    fepsi = cosmo.fepsi() 
    fock = fepsi*fock
    return fock
Example #9
0
def mesh_to_cutoff(a, mesh):
    '''
    Convert #grid points to KE cutoff
    '''
    b = 2 * np.pi * np.linalg.inv(a.T)
    Gmax = lib.norm(b, axis=1) * np.asarray(mesh) * .5
    return Gmax**2/2
Example #10
0
def make_mask(cell, coords, relativity=0, shls_slice=None, verbose=None):
    '''Mask to indicate whether a shell is zero on grid.
    The resultant mask array is an extension to the mask array used in
    molecular code (see also pyscf.dft.numint.make_mask function).
    For given shell ID and block ID, the value of the extended mask array
    means the number of images in Ls that does not vanish.
    '''
    coords = np.asarray(coords, order='F')
    natm = ctypes.c_int(cell._atm.shape[0])
    nbas = ctypes.c_int(cell.nbas)
    ngrids = len(coords)
    if shls_slice is None:
        shls_slice = (0, cell.nbas)
    assert(shls_slice == (0, cell.nbas))

    Ls = cell.get_lattice_Ls(dimension=3)
    Ls = Ls[np.argsort(lib.norm(Ls, axis=1))]

    non0tab = np.empty(((ngrids+BLKSIZE-1)//BLKSIZE, cell.nbas),
                          dtype=np.uint8)
    libpbc.PBCnr_ao_screen(non0tab.ctypes.data_as(ctypes.c_void_p),
                           coords.ctypes.data_as(ctypes.c_void_p),
                           ctypes.c_int(ngrids),
                           Ls.ctypes.data_as(ctypes.c_void_p),
                           ctypes.c_int(len(Ls)),
                           cell._atm.ctypes.data_as(ctypes.c_void_p), natm,
                           cell._bas.ctypes.data_as(ctypes.c_void_p), nbas,
                           cell._env.ctypes.data_as(ctypes.c_void_p))
    return non0tab
Example #11
0
def get_ewald_params(cell, precision=1e-8, gs=None):
    r'''Choose a reasonable value of Ewald 'eta' and 'cut' parameters.

    Choice is based on largest G vector and desired relative precision.

    The relative error in the G-space sum is given by (keeping only
    exponential factors)
        precision ~ e^{(-Gmax^2)/(4 \eta^2)}
    which determines eta. Then, real-space cutoff is determined by (exp.
    factors only)
        precision ~ erfc(eta*rcut) / rcut ~ e^{(-eta**2 rcut*2)}

    Returns:
        ew_eta, ew_cut : float
            The Ewald 'eta' and 'cut' parameters.
    '''
    if gs is None:
        gs = cell.gs

    #  See Martin, p. 85 
    _h = cell.lattice_vectors()
    Gmax = min([ 2.*np.pi*gs[i]/lib.norm(_h[i,:]) for i in range(3) ])

    log_precision = np.log(precision)
    ew_eta = float(np.sqrt(-Gmax**2/(4*log_precision)))

    rcut = np.sqrt(-log_precision)/ew_eta
    ew_cut = cell.get_bounding_sphere(rcut)
    return ew_eta, ew_cut
Example #12
0
def make_psi(mol, dm, r_vdw, lmax):
    grids = dft.gen_grid.Grids(mol)
    atom_grids_tab = grids.gen_atomic_grids(mol)
    grids.build()

    ao = dft.numint.eval_ao(mol, grids.coords)
    den = dft.numint.eval_rho(mol, ao, dm)
    den *= grids.weights
    natm = mol.natm
    nlm = (lmax+1)**2
    psi = numpy.empty((natm,nlm))
    i1 = 0
    for ia in range(natm):
        xnj, w = atom_grids_tab[mol.atom_symbol(ia)]
        i0, i1 = i1, i1 + w.size
        r = lib.norm(xnj, axis=1)
        snj = xnj/r.reshape(-1,1)
        Ys = sph.real_sph_vec(snj, lmax, True)
        p1 = 0
        for l in range(lmax+1):
            fac = 4*numpy.pi/(l*2+1)
            p0, p1 = p1, p1 + (l*2+1)
            rr = numpy.zeros_like(r)
            rr[r<=r_vdw[ia]] = r[r<=r_vdw[ia]]**l / r_vdw[ia]**(l+1)
            rr[r> r_vdw[ia]] = r_vdw[ia]**l / r[r>r_vdw[ia]]**(l+1)
            psi[ia,p0:p1] = -fac * numpy.einsum('n,n,mn->m', den[i0:i1], rr, Ys[l])
        psi[ia,0] += numpy.sqrt(4*numpy.pi)/r_vdw[ia] * mol.atom_charge(ia)
    return psi
Example #13
0
File: cell.py Project: eronca/pyscf
def get_ewald_params(cell, precision=1e-8, gs=None):
    r'''Choose a reasonable value of Ewald 'eta' and 'cut' parameters.

    Choice is based on largest G vector and desired relative precision.

    The relative error in the G-space sum is given by (keeping only
    exponential factors)

        precision ~ e^{(-Gmax^2)/(4 \eta^2)}

    which determines eta. Then, real-space cutoff is determined by (exp.
    factors only)

        precision ~ erfc(eta*rcut) / rcut ~ e^{(-eta**2 rcut*2)}

    Returns:
        ew_eta, ew_cut : float
            The Ewald 'eta' and 'cut' parameters.
    '''
    if gs is None:
        gs = cell.gs

    if cell.dimension == 3:
        Gmax = min(np.asarray(cell.gs) * lib.norm(cell.reciprocal_vectors(), axis=1))
        log_precision = np.log(precision*.1)
        ew_eta = np.sqrt(-Gmax**2/(4*log_precision))
        ew_cut = np.sqrt(-log_precision)/ew_eta
    else:
# Non-uniform PW grids are used for low-dimensional ewald summation.  The cutoff
# estimation for long range part based on exp(G^2/(4*eta^2)) does not work for
# non-uniform grids.  Smooth model density is preferred.
        ew_cut = cell.rcut
        ew_eta = np.sqrt(max(np.log(ew_cut**2/precision)/ew_cut**2, .1))
    return ew_eta, ew_cut
Example #14
0
        def energy_nuc(self):
# nuclei lattice interaction
            nuc = self.mol.energy_nuc()
            for j in range(self.mol.natm):
                q2, r2 = self.mol.atom_charge(j), self.mol.atom_coord(j)
                r = lib.norm(r2-coords, axis=1)
                nuc += q2*(charges/r).sum()
            return nuc
Example #15
0
File: itrf.py Project: pengdl/pyscf
        def energy_tot(self, dm=None, h1e=None, vhf=None):
# nuclei lattice interaction
            nuc = 0.0
            for j in range(self.mol.natm):
                q2, r2 = self.mol.atom_charge(j), self.mol.atom_coord(j)
                r = lib.norm(r2-coords, axis=1)
                nuc += q2*(charges/r).sum()
            return method_class.energy_tot(self, dm, h1e, vhf) + nuc
Example #16
0
File: kuhf.py Project: eronca/pyscf
 def makedm(mos, occs):
     where = [np.argmin(lib.norm(chk_kpts-kpt, axis=1)) for kpt in kpts]
     moa, mob = mos
     occa, occb = occs
     mos = ([fproj(moa[w], chk_kpts[w]-kpts[i]) for i,w in enumerate(where)],
            [fproj(mob[w], chk_kpts[w]-kpts[i]) for i,w in enumerate(where)])
     occs = (occa[where],occb[where])
     return make_rdm1(mos, occs)
Example #17
0
 def makedm(mos, occs):
     where = [np.argmin(lib.norm(chk_kpts-kpt, axis=1)) for kpt in kpts]
     moa, mob = mos
     occa, occb = occs
     dkpts = [chk_kpts[w]-kpts[i] for i,w in enumerate(where)]
     mos = (fproj([moa[w] for w in where], dkpts),
            fproj([mob[w] for w in where], dkpts))
     occs = ([occa[i] for i in where], [occb[i] for i in where])
     return make_rdm1(mos, occs)
Example #18
0
def get_bounding_sphere(cell, rcut):
    '''Finds all the lattice points within a sphere of radius rcut.  

    Defines a parallelipiped given by -N_x <= n_x <= N_x, with x in [1,3]
    See Martin p. 85

    Args:
        rcut : number
            real space cut-off for interaction

    Returns:
        cut : ndarray of 3 ints defining N_x
    '''
    Gmat = invh = scipy.linalg.inv(cell.lattice_vectors())
    n1 = np.ceil(lib.norm(Gmat[0,:])*rcut).astype(int)
    n2 = np.ceil(lib.norm(Gmat[1,:])*rcut).astype(int)
    n3 = np.ceil(lib.norm(Gmat[2,:])*rcut).astype(int)
    cut = np.array([n1, n2, n3])
    return cut
Example #19
0
File: pp.py Project: ncrubin/pyscf
def get_vlocG(cell):
    '''Local PP kernel in G space: Vloc(G) for G!=0, 0 for G=0.

    Returns:
        (natm, ngs) ndarray
    '''
    Gvnorm = lib.norm(cell.Gv, axis=1)
    vlocG = get_gth_vlocG(cell, Gvnorm)
    vlocG[:,0] = 0.
    return vlocG
Example #20
0
def enlarge_space(myci, civec_strs, eri, norb, nelec):
    if isinstance(civec_strs, (tuple, list)):
        nelec, (strsa, strsb) = _unpack(civec_strs[0], nelec)[1:]
        ci_coeff = lib.asarray(civec_strs)
    else:
        ci_coeff, nelec, (strsa, strsb) = _unpack(civec_strs, nelec)
    na = len(strsa)
    nb = len(strsb)
    ci0 = ci_coeff.reshape(-1,na,nb)
    civec_a_max = lib.norm(ci0, axis=2).max(axis=0)
    civec_b_max = lib.norm(ci0, axis=1).max(axis=0)
    ci_aidx = numpy.where(civec_a_max > myci.ci_coeff_cutoff)[0]
    ci_bidx = numpy.where(civec_b_max > myci.ci_coeff_cutoff)[0]
    civec_a_max = civec_a_max[ci_aidx]
    civec_b_max = civec_b_max[ci_bidx]
    strsa = strsa[ci_aidx]
    strsb = strsb[ci_bidx]

    eri = ao2mo.restore(1, eri, norb)
    eri_pq_max = abs(eri.reshape(norb**2,-1)).max(axis=1).reshape(norb,norb)

    strsa_add = select_strs(myci, eri, eri_pq_max, civec_a_max, strsa, norb, nelec[0])
    strsb_add = select_strs(myci, eri, eri_pq_max, civec_b_max, strsb, norb, nelec[1])
    strsa = numpy.append(strsa, strsa_add)
    strsb = numpy.append(strsb, strsb_add)
    aidx = numpy.argsort(strsa)
    bidx = numpy.argsort(strsb)
    ci_strs = (strsa[aidx], strsb[bidx])
    aidx = numpy.where(aidx < len(ci_aidx))[0]
    bidx = numpy.where(bidx < len(ci_bidx))[0]
    ma = len(strsa)
    mb = len(strsb)

    cs = []
    for i in range(ci0.shape[0]):
        ci1 = numpy.zeros((ma,mb))
        tmp = lib.take_2d(ci0[i], ci_aidx, ci_bidx)
        lib.takebak_2d(ci1, tmp, aidx, bidx)
        cs.append(_as_SCIvector(ci1, ci_strs))

    if not isinstance(civec_strs, (tuple, list)) and civec_strs.ndim < 3:
        cs = cs[0]
    return cs
Example #21
0
File: pp.py Project: chrinide/pyscf
def cart2polar(rvec):
    # The rows of rvec are the 3-component vectors
    # i.e. rvec is N x 3
    x,y,z = rvec.T
    r = lib.norm(rvec, axis=1)
    # theta is the polar angle, 0 < theta < pi
    # catch possible 0/0
    theta = np.arccos(z/(r+1e-200))
    # phi is the azimuthal angle, 0 < phi < 2pi (or -pi < phi < pi)
    phi = np.arctan2(y,x)
    return r, theta, phi
Example #22
0
def init_guess_by_chkfile(cell, chkfile_name, project=True, kpts=None):
    '''Read the KHF results from checkpoint file, then project it to the
    basis defined by ``cell``

    Returns:
        Density matrix, 3D ndarray
    '''
    chk_cell, scf_rec = chkfile.load_scf(chkfile_name)

    if kpts is None:
        kpts = scf_rec['kpts']

    if 'kpt' in scf_rec:
        chk_kpts = scf_rec['kpt'].reshape(-1,3)
    elif 'kpts' in scf_rec:
        chk_kpts = scf_rec['kpts']
    else:
        chk_kpts = np.zeros((1,3))

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if 'kpts' not in scf_rec:  # gamma point or single k-point
        if mo.ndim == 2:
            mo = mo.reshape((1,)+mo.shape)
            mo_occ = mo_occ.reshape((1,)+mo_occ.shape)
        else:  # UHF
            mo = mo.reshape((2,1)+mo.shape[1:])
            mo_occ = mo_occ.reshape((2,1)+mo_occ.shape[1:])

    def fproj(mo, kpt):
        if project:
            return addons.project_mo_nr2nr(chk_cell, mo, cell, kpt)
        else:
            return mo

    if kpts.shape == chk_kpts.shape and np.allclose(kpts, chk_kpts):
        def makedm(mos, occs):
            mos = [fproj(mo, None) for mo in mos]
            return make_rdm1(mos, occs)
    else:
        where = [np.argmin(lib.norm(chk_kpts-kpt, axis=1)) for kpt in kpts]
        def makedm(mos, occs):
            mos = [fproj(mos[w], chk_kpts[w]-kpts[i]) for i,w in enumerate(where)]
            return make_rdm1(mos, occs[where])

    if mo.ndim == 3:  # KRHF
        dm = makedm(mo, mo_occ)
    else:  # KUHF
        dm = makedm(mo[0], mo_occ[0]) + makedm(mo[1], mo_occ[1])

    # Real DM for gamma point
    if np.allclose(kpts, 0):
        dm = dm.real
    return dm
Example #23
0
File: itrf.py Project: v1j4y/pyscf
 def grad_nuc(self, mol=None, atmlst=None):
     if mol is None: mol = method.mol
     g_qm = method.grad_nuc(mol, atmlst)
     g_mm = numpy.empty((mol.natm,3))
     for i in range(mol.natm):
         q1 = mol.atom_charge(i)
         r1 = mol.atom_coord(i)
         r = lib.norm(r1-coords, axis=1)
         g_mm[i] = -q1 * numpy.einsum('i,ix,i->x', charges, r1-coords, 1/r**3)
     if atmlst is not None:
         g_mm = g_mm[atmlst]
     return g_qm + g_mm
Example #24
0
    def block_loop(self, cell, grids, nao, deriv=0, kpts=numpy.zeros((1,3)),
                   kpt_band=None, max_memory=2000, non0tab=None, blksize=None):
        '''Define this macro to loop over grids by blocks.
        '''
        ngrids = grids.weights.size
        nkpts = len(kpts)
        comp = (deriv+1)*(deriv+2)*(deriv+3)//6
# NOTE to index ni.non0tab, the blksize needs to be the integer multiplier of BLKSIZE
        if blksize is None:
            blksize = min(int(max_memory*1e6/(comp*2*nkpts*nao*16*BLKSIZE))*BLKSIZE, ngrids)
            blksize = max(blksize, BLKSIZE)
        if non0tab is None:
            non0tab = numpy.ones(((ngrids+BLKSIZE-1)//BLKSIZE,cell.nbas),
                                 dtype=numpy.int8)
        if kpt_band is None:
            kpt1 = kpt2 = kpts
        else:
            kpt1 = kpt_band
            kpt2 = kpts
            where = numpy.argmin(lib.norm(kpts-kpt1,axis=1))
            if abs(kpts[where]-kpt1).sum() > 1e-9:
                where = None

        if (self.cell is None or id(cell) != id(self.cell) or
            self._deriv < deriv or
            self._kpts.shape != kpts.shape or
            abs(self._kpts - kpts).sum() > 1e-9 or
            self._coords.shape != grids.coords.shape or
            abs(self._coords[::64] - grids.coords[::64]).sum() > 1e-7):
            self.cache_ao(cell, kpts, deriv, grids.coords, nao, blksize)

        with h5py.File(self._ao.name, 'r') as f:
            for p0, p1 in prange(0, ngrids, blksize):
                coords = grids.coords[p0:p1]
                weight = grids.weights[p0:p1]
                non0 = non0tab[p0//BLKSIZE:]
                #:ao_k2 = self.eval_ao(cell, coords, kpts, deriv=deriv)
                if comp == 1:
                    if self._deriv == 0:
                        ao_k2 = [f['ao/%d'%k][p0:p1] for k in range(nkpts)]
                    else:
                        ao_k2 = [f['ao/%d'%k][0,p0:p1] for k in range(nkpts)]
                else:
                    ao_k2 = [f['ao/%d'%k][:comp,p0:p1] for k in range(nkpts)]
                if kpt_band is None:
                    ao_k1 = ao_k2
                else:
                    if where is None:
                        ao_k1 = self.eval_ao(cell, coords, kpt1, deriv=deriv)
                    else:
                        ao_k1 = [ao_k2[where]]
                yield ao_k1, ao_k2, non0, weight, coords
                ao_k1 = ao_k2 = None
Example #25
0
def init_guess_by_chkfile(cell, chkfile_name, project=None, kpt=None):
    '''Read the HF results from checkpoint file and make the density matrix
    for UHF initial guess.

    Returns:
        Density matrix, (nao,nao) ndarray
    '''
    from pyscf import gto
    chk_cell, scf_rec = chkfile.load_scf(chkfile_name)
    if project is None:
        project = not gto.same_basis_set(chk_cell, cell)

    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if kpt is None:
        kpt = np.zeros(3)
    if 'kpt' in scf_rec:
        chk_kpt = scf_rec['kpt']
    elif 'kpts' in scf_rec:
        kpts = scf_rec['kpts'] # the closest kpt from KRHF results
        where = np.argmin(lib.norm(kpts-kpt, axis=1))
        chk_kpt = kpts[where]
        if getattr(mo[0], 'ndim', None) == 2:  # KRHF
            mo = mo[where]
            mo_occ = mo_occ[where]
        else:  # KUHF
            mo = [mo[0][where], mo[1][where]]
            mo_occ = [mo_occ[0][where], mo_occ[1][where]]
    else:  # from molecular code
        chk_kpt = np.zeros(3)

    if project:
        s = cell.pbc_intor('int1e_ovlp', kpt=kpt)
    def fproj(mo):
        if project:
            mo = addons.project_mo_nr2nr(chk_cell, mo, cell, chk_kpt-kpt)
            norm = np.einsum('pi,pi->i', mo.conj(), s.dot(mo))
            mo /= np.sqrt(norm)
        return mo

    if getattr(mo, 'ndim', None) == 2:
        mo = fproj(mo)
        mo_occa = (mo_occ>1e-8).astype(np.double)
        mo_occb = mo_occ - mo_occa
        dm = mol_uhf.make_rdm1([mo,mo], [mo_occa,mo_occb])
    else:  # UHF
        dm = mol_uhf.make_rdm1([fproj(mo[0]),fproj(mo[1])], mo_occ)

    # Real DM for gamma point
    if kpt is None or np.allclose(kpt, 0):
        dm = dm.real
    return dm
Example #26
0
    def kernel(self, x0=None):
        '''TDHF diagonalization with non-Hermitian eigenvalue solver
        '''
        self.check_sanity()
        self.dump_flags()

        vind, hdiag = self.get_vind(self._scf)
        precond = self.get_precond(hdiag)
        if x0 is None:
            x0 = self.init_guess(self._scf, self.nstates)

        # We only need positive eigenvalues
        def pickeig(w, v, nroots, envs):
            realidx = numpy.where((abs(w.imag) < REAL_EIG_THRESHOLD) &
                                  (w.real > POSTIVE_EIG_THRESHOLD))[0]
            return lib.linalg_helper._eigs_cmplx2real(w, v, realidx)

        self.converged, w, x1 = \
                lib.davidson_nosym1(vind, x0, precond,
                                    tol=self.conv_tol,
                                    nroots=self.nstates, lindep=self.lindep,
                                    max_space=self.max_space, pick=pickeig,
                                    verbose=self.verbose)

        mo_occ = self._scf.mo_occ
        e = []
        xy = []
        for i, z in enumerate(x1):
            xs, ys = z.reshape(2,-1)
            norm = lib.norm(xs)**2 - lib.norm(ys)**2
            if norm > 0:
                norm = 1/numpy.sqrt(norm)
                xs *= norm
                ys *= norm
                e.append(w[i])
                xy.append((_unpack(xs, mo_occ), _unpack(ys, mo_occ)))
        self.e = numpy.array(e)
        self.xy = xy
        return self.e, self.xy
Example #27
0
def get_pp_nl(cell, kpt=np.zeros(3)):
    coords = gen_grid.gen_uniform_grids(cell)
    aoR = numint.eval_ao(cell, coords, kpt)
    nao = cell.nao_nr()
    SI = cell.get_SI()
    aokG = tools.fftk(np.asarray(aoR.T, order='C'),
                      cell.gs, np.exp(-1j*np.dot(coords, kpt))).T
    ngs = len(aokG)

    fakemol = pyscf.gto.Mole()
    fakemol._atm = np.zeros((1,pyscf.gto.ATM_SLOTS), dtype=np.int32)
    fakemol._bas = np.zeros((1,pyscf.gto.BAS_SLOTS), dtype=np.int32)
    ptr = pyscf.gto.PTR_ENV_START
    fakemol._env = np.zeros(ptr+10)
    fakemol._bas[0,pyscf.gto.NPRIM_OF ] = 1
    fakemol._bas[0,pyscf.gto.NCTR_OF  ] = 1
    fakemol._bas[0,pyscf.gto.PTR_EXP  ] = ptr+3
    fakemol._bas[0,pyscf.gto.PTR_COEFF] = ptr+4
    Gv = np.asarray(cell.Gv+kpt)
    G_rad = lib.norm(Gv, axis=1)

    vppnl = np.zeros((nao,nao), dtype=np.complex128)
    for ia in range(cell.natm):
        symb = cell.atom_symbol(ia)
        if symb not in cell._pseudo:
            continue
        pp = cell._pseudo[symb]
        for l, proj in enumerate(pp[5:]):
            rl, nl, hl = proj
            if nl > 0:
                hl = np.asarray(hl)
                fakemol._bas[0,pyscf.gto.ANG_OF] = l
                fakemol._env[ptr+3] = .5*rl**2
                fakemol._env[ptr+4] = rl**(l+1.5)*np.pi**1.25
                pYlm_part = pyscf.dft.numint.eval_ao(fakemol, Gv, deriv=0)

                pYlm = np.empty((nl,l*2+1,ngs))
                for k in range(nl):
                    qkl = pseudo.pp._qli(G_rad*rl, l, k)
                    pYlm[k] = pYlm_part.T * qkl
                # pYlm is real
                SPG_lmi = np.einsum('g,nmg->nmg', SI[ia].conj(), pYlm)
                SPG_lm_aoG = np.einsum('nmg,gp->nmp', SPG_lmi, aokG)
                tmp = np.einsum('ij,jmp->imp', hl, SPG_lm_aoG)
                vppnl += np.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp)
    vppnl *= (1./ngs**2)

    if aoR.dtype == np.double:
        return vppnl.real
    else:
        return vppnl
Example #28
0
def make_L1(pcmobj, r_vdw, ylm_1sph, fi):
    # See JCTC, 9, 3637, Eq (18)
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    eta = pcmobj.eta
    nlm = (lmax+1)**2

    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    ngrid_1sph = weights_1sph.size
    atom_coords = mol.atom_coords()
    ylm_1sph = ylm_1sph.reshape(nlm,ngrid_1sph)

    Lmat = numpy.zeros((natm,3,natm,nlm,natm,nlm))
    fi1 = make_fi1(pcmobj, pcmobj.get_atomic_radii())

    for ja in range(natm):
        part_weights = weights_1sph.copy()
        part_weights[fi[ja]>1] /= fi[ja,fi[ja]>1]

        part_weights1 = numpy.zeros((natm,3,ngrid_1sph))
        tmp = part_weights[fi[ja]>1] / fi[ja,fi[ja]>1]
        part_weights1[:,:,fi[ja]>1] = -tmp * fi1[:,:,ja,fi[ja]>1]

        for ka in ddcosmo.atoms_with_vdw_overlap(ja, atom_coords, r_vdw):
            vjk = r_vdw[ja] * coords_1sph + atom_coords[ja] - atom_coords[ka]
            rv = lib.norm(vjk, axis=1)
            tjk = rv / r_vdw[ka]
            wjk0 = pcmobj.regularize_xt(tjk, eta, r_vdw[ka])
            wjk1 = regularize_xt1(tjk, eta*r_vdw[ka])
            sjk = vjk.T / rv
            wjk1 = 1./r_vdw[ka] * wjk1 * sjk

            wjk01 = wjk0 * part_weights1
            wjk0 *= part_weights
            wjk1 *= part_weights

            pol0 = sph.multipoles(vjk, lmax)
            pol1 = multipoles1(vjk, lmax)
            p1 = 0
            for l in range(lmax+1):
                fac = 4*numpy.pi/(l*2+1) / r_vdw[ka]**(l+1)
                p0, p1 = p1, p1 + (l*2+1)
                a = numpy.einsum('xn,zn,mn->zxm', ylm_1sph, wjk1, pol0[l])
                a+= numpy.einsum('xn,n,zmn->zxm', ylm_1sph, wjk0, pol1[l])
                Lmat[ja,:,ja,:,ka,p0:p1] += -fac * a
                Lmat[ka,:,ja,:,ka,p0:p1] -= -fac * a
                a = numpy.einsum('xn,azn,mn->azxm', ylm_1sph, wjk01, pol0[l])
                Lmat[:,:,ja,:,ka,p0:p1] += -fac * a
    return Lmat
Example #29
0
 def eval_xc(self, xc_code, rho, spin=1, relativity=0, deriv=1, verbose=None):
     # JTCC, 2, 257
     r, m = rho[:2]
     s = lib.norm(m, axis=0)
     rhou = (r + s) * .5
     rhod = (r - s) * .5
     rho = (rhou, rhod)
     xc = self.libxc.eval_xc(xc_code, rho, spin, relativity, deriv, verbose)
     exc, vxc = xc[:2]
     vrho = vxc[0]
     vr, vm = (vrho[:,0]+vrho[:,1])*.5, (vrho[:,0]-vrho[:,1])*.5
     vrho[:,0] = vr
     vrho[:,1] = vm
     return xc
Example #30
0
def get_lattice_Ls(cell, nimgs=None, rcut=None, dimension=None):
    '''Get the (Cartesian, unitful) lattice translation vectors for nearby images.
    The translation vectors can be used for the lattice summation.'''
    a = cell.lattice_vectors()
    b = cell.reciprocal_vectors(norm_to=1)
    heights_inv = lib.norm(b, axis=1)

    if nimgs is None:
        if rcut is None:
            rcut = cell.rcut
# plus 1 image in rcut to handle the case atoms within the adjacent cells are
# close to each other
        nimgs = np.ceil(rcut*heights_inv + 1.1).astype(int)
    else:
        rcut = max((np.asarray(nimgs))/heights_inv)

    if dimension is None:
        dimension = cell.dimension
    if dimension == 0:
        nimgs = [0, 0, 0]
    elif dimension == 1:
        nimgs = [nimgs[0], 0, 0]
    elif dimension == 2:
        nimgs = [nimgs[0], nimgs[1], 0]

    Ts = lib.cartesian_prod((np.arange(-nimgs[0],nimgs[0]+1),
                             np.arange(-nimgs[1],nimgs[1]+1),
                             np.arange(-nimgs[2],nimgs[2]+1)))
    Ls = np.dot(Ts, a)
    idx = np.zeros(len(Ls), dtype=bool)
    for ax in (-a[0], 0, a[0]):
        for ay in (-a[1], 0, a[1]):
            for az in (-a[2], 0, a[2]):
                idx |= lib.norm(Ls+(ax+ay+az), axis=1) < rcut
    Ls = Ls[idx]
    return np.asarray(Ls, order='C')
Example #31
0
def _vxc2x2_to_mat(mol, ao, weight, rho, vrho, non0tab, shls_slice, ao_loc):
    aoa, aob = ao
    r, m = rho
    vr, vm = vrho.T
    aow = numpy.empty_like(aoa)
    #    aow = numpy.einsum('pi,p->pi', aoa, weight*vr, out=aow)
    #    mat = _dot_ao_ao(mol, aoa, aow, non0tab, shls_slice, ao_loc)
    #    aow = numpy.einsum('pi,p->pi', aob, weight*vr, out=aow)
    #    mat+= _dot_ao_ao(mol, aob, aow, non0tab, shls_slice, ao_loc)
    #
    #    s = lib.norm(m, axis=0)
    #    ws = vm * weight / (s+1e-300)
    #    aow = numpy.einsum('pi,p->pi', aoa, ws*m[0], out=aow)  # Mx
    #    tmp = _dot_ao_ao(mol, aob, aow, non0tab, shls_slice, ao_loc)
    #    mat+= tmp + tmp.T.conj()
    #    aow = numpy.einsum('pi,p->pi', aoa, ws*m[1], out=aow)  # My
    #    tmp = _dot_ao_ao(mol, aob, aow, non0tab, shls_slice, ao_loc)
    #    mat+= (tmp - tmp.T.conj()) * 1j
    #    aow = numpy.einsum('pi,p->pi', aoa, ws*m[2], out=aow)  # Mz
    #    mat+= _dot_ao_ao(mol, aoa, aow, non0tab, shls_slice, ao_loc)
    #    aow = numpy.einsum('pi,p->pi', aob, ws*m[2], out=aow)
    #    mat-= _dot_ao_ao(mol, aob, aow, non0tab, shls_slice, ao_loc)

    s = lib.norm(m, axis=0)
    idx = s < 1e-20
    with numpy.errstate(divide='ignore', invalid='ignore'):
        ws = vm * weight / s
    ws[idx] = 0

    aow = numpy.einsum('pi,p->pi', aoa, ws * m[0], out=aow)  # Mx
    tmp = _dot_ao_ao(mol, aob, aow, non0tab, shls_slice, ao_loc)
    mat = tmp + tmp.T.conj()
    aow = numpy.einsum('pi,p->pi', aoa, ws * m[1], out=aow)  # My
    tmp = _dot_ao_ao(mol, aob, aow, non0tab, shls_slice, ao_loc)
    mat += (tmp - tmp.T.conj()) * 1j
    aow = numpy.einsum('pi,p->pi', aoa, weight * vr, out=aow)
    aow += numpy.einsum('pi,p->pi', aoa, ws * m[2])  # Mz
    mat += _dot_ao_ao(mol, aoa, aow, non0tab, shls_slice, ao_loc)
    aow = numpy.einsum('pi,p->pi', aob, weight * vr, out=aow)
    aow -= numpy.einsum('pi,p->pi', aob, ws * m[2])  # Mz
    mat += _dot_ao_ao(mol, aob, aow, non0tab, shls_slice, ao_loc)
    return mat
Example #32
0
    def vppnl_by_k(kpt):
        Gk = Gv + kpt
        G_rad = lib.norm(Gk, axis=1)
        aokG = ft_ao.ft_ao(cell, Gv, kpt=kpt) * (ngs/cell.vol)
        vppnl = 0
        for ia in range(cell.natm):
            symb = cell.atom_symbol(ia)
            if symb not in cell._pseudo:
                continue
            pp = cell._pseudo[symb]
            p1 = 0
            for l, proj in enumerate(pp[5:]):
                rl, nl, hl = proj
                if nl > 0:
                    fakemol._bas[0,gto.ANG_OF] = l
                    fakemol._env[ptr+3] = .5*rl**2
                    fakemol._env[ptr+4] = rl**(l+1.5)*numpy.pi**1.25
                    pYlm_part = dft.numint.eval_ao(fakemol, Gk, deriv=0)

                    p0, p1 = p1, p1+nl*(l*2+1)
                    # pYlm is real, SI[ia] is complex
                    pYlm = numpy.ndarray((nl,l*2+1,ngs), dtype=numpy.complex128, buffer=buf[p0:p1])
                    for k in range(nl):
                        qkl = pseudo.pp._qli(G_rad*rl, l, k)
                        pYlm[k] = pYlm_part.T * qkl
                    #:SPG_lmi = numpy.einsum('g,nmg->nmg', SI[ia].conj(), pYlm)
                    #:SPG_lm_aoG = numpy.einsum('nmg,gp->nmp', SPG_lmi, aokG)
                    #:tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG)
                    #:vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp)
            SPG_lmi = buf[:p1]
            SPG_lmi *= SI[ia].conj()
            SPG_lm_aoGs = lib.zdot(SPG_lmi, aokG)
            p1 = 0
            for l, proj in enumerate(pp[5:]):
                rl, nl, hl = proj
                if nl > 0:
                    p0, p1 = p1, p1+nl*(l*2+1)
                    hl = numpy.asarray(hl)
                    SPG_lm_aoG = SPG_lm_aoGs[p0:p1].reshape(nl,l*2+1,-1)
                    tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG)
                    vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp)
        return vppnl * (1./ngs**2)
Example #33
0
def get_lattice_Ls(cell, nimgs=None, rcut=None, dimension=None, discard=True):
    '''Get the (Cartesian, unitful) lattice translation vectors for nearby images.
    The translation vectors can be used for the lattice summation.'''
    a = cell.lattice_vectors()
    b = cell.reciprocal_vectors(norm_to=1)
    heights_inv = lib.norm(b, axis=1)

    if nimgs is None:
        if rcut is None:
            rcut = cell.rcut
        # For atoms outside the cell, distance between certain basis of nearby
        # images may be smaller than rcut threshold even the corresponding Ls is
        # larger than rcut. The boundary penalty ensures that Ls would be able to
        # cover the basis that sitting out of the cell.
        # See issue https://github.com/pyscf/pyscf/issues/1017
        scaled_atom_coords = cell.atom_coords().dot(b.T)
        boundary_penalty = np.max([
            abs(scaled_atom_coords).max(axis=0),
            abs(1 - scaled_atom_coords).max(axis=0)
        ],
                                  axis=0)
        nimgs = np.ceil(rcut * heights_inv + boundary_penalty).astype(int)
    else:
        rcut = max((np.asarray(nimgs)) / heights_inv)

    if dimension is None:
        dimension = cell.dimension
    if dimension == 0:
        nimgs = [0, 0, 0]
    elif dimension == 1:
        nimgs = [nimgs[0], 0, 0]
    elif dimension == 2:
        nimgs = [nimgs[0], nimgs[1], 0]

    Ts = lib.cartesian_prod(
        (np.arange(-nimgs[0], nimgs[0] + 1), np.arange(-nimgs[1],
                                                       nimgs[1] + 1),
         np.arange(-nimgs[2], nimgs[2] + 1)))
    Ls = np.dot(Ts, a)
    if discard:
        Ls = _discard_edge_images(cell, Ls, rcut)
    return np.asarray(Ls, order='C')
Example #34
0
def init_guess_by_chkfile(cell, chkfile_name, project=True, kpt=None):
    '''Read the HF results from checkpoint file, then project it to the
    basis defined by ``cell``

    Returns:
        Density matrix, (nao,nao) ndarray
    '''
    chk_cell, scf_rec = chkfile.load_scf(chkfile_name)
    mo = scf_rec['mo_coeff']
    mo_occ = scf_rec['mo_occ']
    if kpt is None:
        kpt = np.zeros(3)
    if 'kpt' in scf_rec:
        chk_kpt = scf_rec['kpt']
    elif 'kpts' in scf_rec:
        kpts = scf_rec['kpts'] # the closest kpt from KRHF results
        where = np.argmin(lib.norm(kpts-kpt, axis=1))
        chk_kpt = kpts[where]
        if mo.ndim == 3:  # KRHF:
            mo = mo[where]
            mo_occ = mo_occ[where]
        else:
            mo = mo[:,where]
            mo_occ = mo_occ[:,where]
    else:
        chk_kpt = np.zeros(3)

    def fproj(mo):
        if project:
            return addons.project_mo_nr2nr(chk_cell, mo, cell, chk_kpt-kpt)
        else:
            return mo
    if mo.ndim == 2:
        dm = pyscf.scf.hf.make_rdm1(fproj(mo), mo_occ)
    else:  # UHF
        dm = np.asarray((pyscf.scf.hf.make_rdm1(fproj(mo[0]), mo_occ[0]),
                         pyscf.scf.hf.make_rdm1(fproj(mo[1]), mo_occ[1])))

    # Real DM for gamma point
    if kpt is None or np.allclose(kpt, 0):
        dm = dm.real
    return dm
Example #35
0
 def eval_xc(self,
             xc_code,
             rho,
             spin=1,
             relativity=0,
             deriv=1,
             verbose=None):
     # JTCC, 2, 257
     r, m = rho[:2]
     s = lib.norm(m, axis=0)
     rhou = (r + s) * .5
     rhod = (r - s) * .5
     rho = (rhou, rhod)
     xc = self.libxc.eval_xc(xc_code, rho, spin, relativity, deriv, verbose)
     exc, vxc = xc[:2]
     vrho = vxc[0]
     vr, vm = (vrho[:, 0] + vrho[:, 1]) * .5, (vrho[:, 0] - vrho[:, 1]) * .5
     vrho[:, 0] = vr
     vrho[:, 1] = vm
     return xc
Example #36
0
def _e_nuc(mol: gto.Mole, mm_mol: Union[None, gto.Mole]) -> np.ndarray:
        """
        this function returns the nuclear repulsion energy
        """
        # coordinates and charges of nuclei
        coords = mol.atom_coords()
        charges = mol.atom_charges()
        # internuclear distances (with self-repulsion removed)
        dist = gto.inter_distance(mol)
        dist[np.diag_indices_from(dist)] = 1e200
        e_nuc = contract('i,ij,j->i', charges, 1. / dist, charges) * .5
        # possible interaction with mm sites
        if mm_mol is not None:
            mm_coords = mm_mol.atom_coords()
            mm_charges = mm_mol.atom_charges()
            for j in range(mol.natm):
                q2, r2 = charges[j], coords[j]
                r = lib.norm(r2 - mm_coords, axis=1)
                e_nuc[j] += q2 * np.sum(mm_charges / r)
        return e_nuc
Example #37
0
def cutoff_to_mesh(a, cutoff):
    r'''
    Convert KE cutoff to FFT-mesh

        uses KE = k^2 / 2, where k_max ~ \pi / grid_spacing

    Args:
        a : (3,3) ndarray
            The real-space unit cell lattice vectors. Each row represents a
            lattice vector.
        cutoff : float
            KE energy cutoff in a.u.

    Returns:
        mesh : (3,) array
    '''
    b = 2 * np.pi * np.linalg.inv(a.T)
    cutoff = cutoff * _cubic2nonorth_factor(a)
    mesh = np.ceil(np.sqrt(2 * cutoff) / lib.norm(b, axis=1) * 2).astype(int)
    return mesh
Example #38
0
def cosmo_occ_o1(cosmo, dm):
    mol = cosmo.mol
    nao = dm.shape[0]
    #cosmo.check()
    cosmo.occ0()
    cosmo.loadsegs()
    #cosmo.check()
    ioff = 3*cosmo.nps
    coords = cosmo.cosurf[ioff:ioff+cosmo.npspher*3].reshape(-1,3)
    fakemol = _make_fakemol(coords)
    j3c = df.incore.aux_e2(mol, fakemol, intor='cint3c2e_sph', aosym='s2ij')
    tril_dm = lib.pack_tril(dm) * 2
    diagidx = numpy.arange(nao)
    diagidx = diagidx*(diagidx+1)//2 + diagidx
    tril_dm[diagidx] *= .5
    cosmo.phio = -numpy.einsum('x,xk->k', tril_dm, j3c)
    for ia in range(mol.natm):
        cosmo.phio += mol.atom_charge(ia)/lib.norm(mol.atom_coord(ia)-coords, axis=1)
    cosmo.savesegs()
    return cosmo.occ1()
Example #39
0
def cutoff_to_gs(a, cutoff):
    '''
    Convert KE cutoff to #grid points (gs variable) for FFT-mesh

        uses KE = k^2 / 2, where k_max ~ \pi / grid_spacing

    Args:
        a : (3,3) ndarray
            The real-space unit cell lattice vectors. Each row represents a
            lattice vector.
        cutoff : float
            KE energy cutoff in a.u.

    Returns:
        gs : (3,) array
    '''
    grid_spacing = np.pi / np.sqrt(2 * cutoff)

    # number of grid points is 2gs+1 (~ 2 gs) along each direction
    gs = np.ceil(lib.norm(a, axis=1) / (2 * grid_spacing)).astype(int)
    return gs
Example #40
0
def get_bounding_sphere(cell, rcut):
    '''Finds all the lattice points within a sphere of radius rcut.  

    Defines a parallelipiped given by -N_x <= n_x <= N_x, with x in [1,3]
    See Martin p. 85

    Args:
        rcut : number
            real space cut-off for interaction

    Returns:
        cut : ndarray of 3 ints defining N_x
    '''
    #Gmat = cell.reciprocal_vectors(norm_to=1)
    #n1 = np.ceil(lib.norm(Gmat[0,:])*rcut)
    #n2 = np.ceil(lib.norm(Gmat[1,:])*rcut)
    #n3 = np.ceil(lib.norm(Gmat[2,:])*rcut)
    #cut = np.array([n1, n2, n3]).astype(int)
    b = cell.reciprocal_vectors(norm_to=1)
    heights_inv = lib.norm(b, axis=1)
    return np.ceil(rcut * heights_inv).astype(int)
Example #41
0
    def __init__(self, atoms, basis=None):
        self.atomtypes = mole.atom_types(atoms, basis)
        # fake systems, which treates the atoms of different basis as different atoms.
        # the fake systems do not have the same symmetry as the potential
        # it's only used to determine the main (Z-)axis
        chg1 = numpy.pi - 2
        coords = []
        fake_chgs = []
        idx = []
        for k, lst in self.atomtypes.items():
            idx.append(lst)
            coords.append([atoms[i][1] for i in lst])
            ksymb = mole._rm_digit(k)
            if ksymb != k:
                # Put random charges on the decorated atoms
                fake_chgs.append([chg1] * len(lst))
                chg1 *= numpy.pi - 2
            elif 'GHOST' in ksymb:
                ksymb = mole._remove_prefix_ghost(ksymb)
                fake_chgs.append([mole._charge(ksymb) + .3] * len(lst))
            else:
                fake_chgs.append([mole._charge(ksymb)] * len(lst))
        coords = numpy.array(numpy.vstack(coords), dtype=float)
        fake_chgs = numpy.hstack(fake_chgs)
        self.charge_center = numpy.einsum('i,ij->j', fake_chgs,
                                          coords) / fake_chgs.sum()
        coords = coords - self.charge_center

        idx = numpy.argsort(numpy.hstack(idx))
        self.atoms = numpy.hstack((fake_chgs.reshape(-1, 1), coords))[idx]

        self.group_atoms_by_distance = []
        decimals = int(-numpy.log10(TOLERANCE)) - 1
        for index in self.atomtypes.values():
            index = numpy.asarray(index)
            c = self.atoms[index, 1:]
            dists = numpy.around(norm(c, axis=1), decimals)
            u, idx = numpy.unique(dists, return_inverse=True)
            for i, s in enumerate(u):
                self.group_atoms_by_distance.append(index[idx == i])
Example #42
0
    def test_make_ylm(self):
        numpy.random.seed(1)
        lmax = 6
        r = numpy.random.random((100, 3)) - numpy.ones(3) * .5
        r = r / lib.norm(r, axis=1).reshape(-1, 1)

        ngrid = r.shape[0]
        cosphi = r[:, 2]
        sinphi = (1 - cosphi**2)**.5
        costheta = numpy.ones(ngrid)
        sintheta = numpy.zeros(ngrid)
        costheta[sinphi != 0] = r[sinphi != 0, 0] / sinphi[sinphi != 0]
        sintheta[sinphi != 0] = r[sinphi != 0, 1] / sinphi[sinphi != 0]
        costheta[costheta > 1] = 1
        costheta[costheta < -1] = -1
        sintheta[sintheta > 1] = 1
        sintheta[sintheta < -1] = -1
        varphi = numpy.arccos(cosphi)
        theta = numpy.arccos(costheta)
        theta[sintheta < 0] = 2 * numpy.pi - theta[sintheta < 0]
        ylmref = []
        for l in range(lmax + 1):
            ylm = numpy.empty((l * 2 + 1, ngrid))
            ylm[l] = scipy.special.sph_harm(0, l, theta, varphi).real
            for m in range(1, l + 1):
                f1 = scipy.special.sph_harm(-m, l, theta, varphi)
                f2 = scipy.special.sph_harm(m, l, theta, varphi)
                # complex to real spherical functions
                if m % 2 == 1:
                    ylm[l - m] = (-f1.imag - f2.imag) / numpy.sqrt(2)
                    ylm[l + m] = (f1.real - f2.real) / numpy.sqrt(2)
                else:
                    ylm[l - m] = (-f1.imag + f2.imag) / numpy.sqrt(2)
                    ylm[l + m] = (f1.real + f2.real) / numpy.sqrt(2)
            if l == 1:
                ylm = ylm[[2, 0, 1]]
            ylmref.append(ylm)
        ylmref = numpy.vstack(ylmref)
        ylm = numpy.vstack(sph.real_sph_vec(r, lmax, True))
        self.assertTrue(abs(ylmref - ylm).max() < 1e-14)
Example #43
0
def make_L(pcmobj, r_vdw, lebedev_order, lmax, eta=0.1):
    mol = pcmobj.mol
    natm = mol.natm
    nlm = (lmax + 1)**2

    leb_coords, leb_weights = ddcosmo.make_grids_one_sphere(lebedev_order)
    nleb_grid = leb_weights.size
    atom_coords = mol.atom_coords()
    Ylm_sphere = numpy.vstack(sph.real_sph_vec(leb_coords, lmax, True))
    fi = ddcosmo.make_fi(pcmobj, r_vdw)

    L_diag = numpy.zeros((natm, nlm))
    p1 = 0
    for l in range(lmax + 1):
        p0, p1 = p1, p1 + (l * 2 + 1)
        L_diag[:, p0:p1] = 4 * numpy.pi / (l * 2 + 1)
    L_diag /= r_vdw.reshape(-1, 1)
    L = numpy.diag(L_diag.ravel()).reshape(natm, nlm, natm, nlm)
    for ja in range(natm):
        for ka in range(natm):
            if ja == ka:
                continue
            vjk = r_vdw[ja] * leb_coords + atom_coords[ja] - atom_coords[ka]
            v = lib.norm(vjk, axis=1)
            tjk = v / r_vdw[ka]
            sjk = vjk / v.reshape(-1, 1)
            Ys = sph.real_sph_vec(sjk, lmax, True)
            # scale the weight, see JCTC 9, 3637, Eq (16)
            wjk = pcmobj.regularize_xt(tjk, eta, r_vdw[ka])
            wjk[fi[ja] > 1] /= fi[ja, fi[ja] > 1]
            tt = numpy.ones_like(wjk)
            p1 = 0
            for l in range(lmax + 1):
                fac = 4 * numpy.pi / (l * 2 + 1) / r_vdw[ka]
                p0, p1 = p1, p1 + (l * 2 + 1)
                val = numpy.einsum('n,xn,n,mn->xm', leb_weights, Ylm_sphere,
                                   wjk * tt, Ys[l])
                L[ja, :, ka, p0:p1] += -fac * val
                tt *= tjk
    return L.reshape(natm * nlm, natm * nlm)
Example #44
0
def make_vmat(pcm, r_vdw, lebedev_order, lmax, LX, LS):
    mol = pcm.mol
    grids = dft.gen_grid.Grids(mol)
    atom_grids_tab = grids.gen_atomic_grids(mol)
    grids.build()
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(lebedev_order)
    ao = dft.numint.eval_ao(mol, grids.coords)
    nao = ao.shape[1]
    vmat = numpy.zeros((nao, nao))
    i1 = 0
    for ia in range(mol.natm):
        xnj, w = atom_grids_tab[mol.atom_symbol(ia)]
        i0, i1 = i1, i1 + w.size
        r = lib.norm(xnj, axis=1)
        Ys = sph.real_sph_vec(xnj / r.reshape(-1, 1), lmax, True)
        p1 = 0
        for l in range(lmax + 1):
            fac = 4 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            rr = numpy.zeros_like(r)
            rr[r <= r_vdw[ia]] = r[r <= r_vdw[ia]]**l / r_vdw[ia]**(l + 1)
            rr[r > r_vdw[ia]] = r_vdw[ia]**l / r[r > r_vdw[ia]]**(l + 1)
            eta_nj = fac * numpy.einsum('n,mn,m->n', rr, Ys[l], LX[ia, p0:p1])
            vmat -= numpy.einsum('n,np,nq->pq', grids.weights[i0:i1] * eta_nj,
                                 ao[i0:i1], ao[i0:i1])

    atom_coords = mol.atom_coords()
    Ylm_sphere = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))
    fi = ddcosmo.make_fi(pcm, r_vdw)
    ui = 1 - fi
    ui[ui < 0] = 0
    xi_nj = numpy.einsum('n,jn,xn,jx->jn', weights_1sph, ui, Ylm_sphere, LS)

    pmol = mol.copy()
    for ia in range(mol.natm):
        for i, c in enumerate(coords_1sph):
            r = atom_coords[ia] + r_vdw[ia] * c
            pmol.set_rinv_orig(r)
            vmat += pmol.intor('int1e_rinv') * xi_nj[ia, i]
    return vmat
Example #45
0
def get_ewald_params(cell, precision=1e-8, gs=None):
    r'''Choose a reasonable value of Ewald 'eta' and 'cut' parameters.

    Choice is based on largest G vector and desired relative precision.

    The relative error in the G-space sum is given by

        precision ~ 4\pi Gmax^2 e^{(-Gmax^2)/(4 \eta^2)}

    which determines eta. Then, real-space cutoff is determined by (exp.
    factors only)

        precision ~ erfc(eta*rcut) / rcut ~ e^{(-eta**2 rcut*2)}

    Returns:
        ew_eta, ew_cut : float
            The Ewald 'eta' and 'cut' parameters.
    '''
    if cell.natm == 0:
        return 0, 0
    elif cell.dimension == 3:
        if gs is None:
            gs = 5
        else:
            gs = np.copy(gs)
            gs[gs > 40] = 40
        Gmax = min(
            np.asarray(gs) * lib.norm(cell.reciprocal_vectors(), axis=1))
        log_precision = np.log(precision / (4 * np.pi * Gmax**2))
        ew_eta = np.sqrt(-Gmax**2 / (4 * log_precision))
        ew_cut = _estimate_rcut(ew_eta**2, 0, 1., precision)
    else:
        # Non-uniform PW grids are used for low-dimensional ewald summation.  The cutoff
        # estimation for long range part based on exp(G^2/(4*eta^2)) does not work for
        # non-uniform grids.  Smooth model density is preferred.
        ew_cut = cell.rcut
        ew_eta = np.sqrt(
            max(np.log(4 * np.pi * ew_cut**2 / precision) / ew_cut**2, .1))
    return ew_eta, ew_cut
Example #46
0
def make_fi1(pcmobj, r_vdw):
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    mol = pcmobj.mol
    eta = pcmobj.eta
    natm = mol.natm
    atom_coords = mol.atom_coords()
    ngrid_1sph = coords_1sph.shape[0]
    fi1 = numpy.zeros((natm,3,natm,ngrid_1sph))
    for ia in range(natm):
        for ja in ddcosmo.atoms_with_vdw_overlap(ia, atom_coords, r_vdw):
            v = r_vdw[ia]*coords_1sph + atom_coords[ia] - atom_coords[ja]
            rv = lib.norm(v, axis=1)
            t = rv / r_vdw[ja]
            xt1 = regularize_xt1(t, eta*r_vdw[ja])
            s_ij = v.T / rv
            xt1 = 1./r_vdw[ja] * xt1 * s_ij
            fi1[ia,:,ia] += xt1
            fi1[ja,:,ia] -= xt1

    fi = ddcosmo.make_fi(pcmobj, r_vdw)
    fi1[:,:,fi<1e-20] = 0
    return fi1
Example #47
0
def get_nimgs(cell, precision=None):
    r'''Choose number of basis function images in lattice sums
    to include for given precision in overlap, using

    precision ~ 4 * pi * r^2 * e^{-\alpha r^2}

    where \alpha is the smallest exponent in the basis. Note
    that assumes an isolated exponent in the middle of the box, so
    it adds one additional lattice vector to be safe.
    '''
    if precision is None:
        precision = cell.precision
    min_exp = np.min([np.min(cell.bas_exp(ib)) for ib in range(cell.nbas)])

    def fn(r):
        return np.log(4 * np.pi * r**2) - min_exp * r**2 - np.log(precision)

    guess = np.sqrt((5 - np.log(precision)) / min_exp)
    rcut = scipy.optimize.fsolve(fn, guess, xtol=1e-4)[0]
    rlengths = lib.norm(cell.lattice_vectors(), axis=1) + 1e-200
    nimgs = np.ceil(np.reshape(rcut / rlengths, rlengths.shape[0])).astype(int)

    return nimgs + 1  # additional lattice vector to take into account
Example #48
0
def make_fi(pcmobj, r_vdw):
    coords_1sph, weights_1sph = make_grids_one_sphere(pcmobj.lebedev_order)
    mol = pcmobj.mol
    eta = pcmobj.eta
    natm = mol.natm
    natm_tot = natm
    atom_coords = mol.atom_coords()
    ngrid_1sph = coords_1sph.shape[0]
    if pcmobj.mm_mol is not None:
        atom_coords = numpy.vstack((atom_coords, pcmobj.mm_mol.atom_coords()))
        natm_tot += pcmobj.mm_mol.natm

    ngrid_1sph = coords_1sph.shape[0]
    fi = numpy.zeros((natm_tot, ngrid_1sph))
    for ia in range(natm_tot):
        for ja in atoms_with_vdw_overlap(ia, atom_coords, r_vdw):
            v = r_vdw[ia] * coords_1sph + atom_coords[ia] - atom_coords[ja]
            rv = lib.norm(v, axis=1)
            t = rv / r_vdw[ja]
            xt = pcmobj.regularize_xt(t, eta, r_vdw[ja])
            fi[ia] += xt
    fi[fi < 1e-20] = 0
    return fi
Example #49
0
def get_pp_loc_part2(cell, kpt=np.zeros(3)):
    coords = gen_grid.gen_uniform_grids(cell)
    aoR = numint.eval_ao(cell, coords, kpt)
    nao = cell.nao_nr()

    SI = cell.get_SI()
    G = lib.norm(cell.Gv, axis=1)
    vlocG = np.zeros((cell.natm,len(G)))
    for ia in range(cell.natm):
        Zia = cell.atom_charge(ia)
        symb = cell.atom_symbol(ia)
        if symb not in cell._pseudo:
            vlocG[ia] = 0
            continue
        pp = cell._pseudo[symb]
        rloc, nexp, cexp = pp[1:3+1]

        G_red = G*rloc
        cfacs = np.array(
                [1*G_red**0,
                 3 - G_red**2,
                 15 - 10*G_red**2 + G_red**4,
                 105 - 105*G_red**2 + 21*G_red**4 - G_red**6])

        with np.errstate(divide='ignore'):
            # Note the signs -- potential here is positive
            vlocG[ia,:] = (# 4*np.pi * Zia * np.exp(-0.5*G_red**2)/G**2
                           - (2*np.pi)**(3/2.)*rloc**3*np.exp(-0.5*G_red**2)*(
                                np.dot(cexp, cfacs[:nexp])) )

    vpplocG = -np.sum(SI * vlocG, axis=0)
    vpplocR = tools.ifft(vpplocG, cell.gs).real
    vpploc = np.dot(aoR.T.conj(), vpplocR.reshape(-1,1)*aoR)
    if aoR.dtype == np.double:
        return vpploc.real
    else:
        return vpploc
Example #50
0
def _ncol_lda_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi):
    '''Vxc matrix of non-collinear LDA'''
    # NOTE vxc in u/d representation
    r, mx, my, mz = rho
    vxc = xc_deriv.ud2ts(vxc)
    vr, vs = vxc[:,0]
    s = lib.norm(rho[1:4], axis=0)

    wv = weight * vr
    with np.errstate(divide='ignore',invalid='ignore'):
        ws = vs * weight / s
    ws[s < 1e-20] = 0

    # * .5 because of v+v.conj().T in r_vxc
    if hermi:
        wv *= .5
        ws *= .5
    aow = None
    aow = _scale_ao(ao, ws*mx, out=aow)  # Mx
    tmpx = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(ao, ws*my, out=aow)  # My
    tmpy = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    if hermi:
        # conj(mx+my*1j) == mx-my*1j, tmpx and tmpy should be real
        matba = (tmpx + tmpx.T) + (tmpy + tmpy.T) * 1j
        matab = np.zeros_like(matba)
    else:
        # conj(mx+my*1j) != mx-my*1j, tmpx and tmpy should be complex
        matba = tmpx + tmpy * 1j
        matab = tmpx - tmpy * 1j
    tmpx = tmpy = None
    aow = _scale_ao(ao, wv+ws*mz, out=aow)  # Mz
    mataa = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(ao, wv-ws*mz, out=aow)  # Mz
    matbb = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    mat = np.block([[mataa, matab], [matba, matbb]])
    return mat
Example #51
0
    def search_c2x(self, zaxis, n):
        '''C2 axis which is perpendicular to z-axis'''
        decimals = int(-numpy.log10(TOLERANCE)) - 1
        for lst in self.group_atoms_by_distance:
            if len(lst) > 1:
                r0 = self.atoms[lst, 1:]
                zcos = numpy.around(numpy.einsum('ij,j->i', r0, zaxis),
                                    decimals=decimals)
                uniq_zcos = numpy.unique(zcos)
                maybe_c2x = []
                for d in uniq_zcos:
                    if d > TOLERANCE:
                        mirrord = abs(zcos + d) < TOLERANCE
                        if mirrord.sum() == (zcos == d).sum():
                            above = r0[zcos == d]
                            below = r0[mirrord]
                            nelem = len(below)
                            maybe_c2x.extend(
                                [above[0] + below[i] for i in range(nelem)])
                    elif abs(d) < TOLERANCE:  # plane which crosses the orig
                        r1 = r0[zcos == d][0]
                        maybe_c2x.append(r1)
                        r2 = numpy.dot(rotation_mat(zaxis, numpy.pi * 2 / n),
                                       r1)
                        if abs(r1 + r2).sum() > TOLERANCE:
                            maybe_c2x.append(r1 + r2)
                        else:
                            maybe_c2x.append(r2 - r1)

                if len(maybe_c2x) > 0:
                    idx = norm(maybe_c2x, axis=1) > TOLERANCE
                    maybe_c2x = _normalize(maybe_c2x)[idx]
                    maybe_c2x = _remove_dupvec(maybe_c2x)
                    for c2x in maybe_c2x:
                        if (not parallel_vectors(c2x, zaxis)
                                and self.has_rotation(c2x, 2)):
                            return c2x
Example #52
0
def make_A(pcmobj, r_vdw, ylm_1sph, ui):
    # Part of A matrix defined in JCP, 144, 054101, Eq (43), (44)
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    eta = pcmobj.eta
    nlm = (lmax + 1)**2

    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ngrid_1sph = weights_1sph.size
    atom_coords = mol.atom_coords()
    ylm_1sph = ylm_1sph.reshape(nlm, ngrid_1sph)
    Amat = numpy.zeros((natm, nlm, natm, nlm))

    for ja in range(natm):
        # w_u = precontract w_n U_j
        w_u = weights_1sph * ui[ja]
        p1 = 0
        for l in range(lmax + 1):
            fac = 2 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            a = numpy.einsum('xn,n,mn->xm', ylm_1sph, w_u, ylm_1sph[p0:p1])
            Amat[ja, :, ja, p0:p1] += -fac * a

        for ka in ddcosmo.atoms_with_vdw_overlap(ja, atom_coords, r_vdw):
            vjk = r_vdw[ja] * coords_1sph + atom_coords[ja] - atom_coords[ka]
            rjk = lib.norm(vjk, axis=1)
            pol = sph.multipoles(vjk, lmax)
            p1 = 0
            weights = w_u / rjk**(l * 2 + 1)
            for l in range(lmax + 1):
                fac = 4 * numpy.pi * l / (l * 2 + 1) * r_vdw[ka]**(l + 1)
                p0, p1 = p1, p1 + (l * 2 + 1)
                a = numpy.einsum('xn,n,mn->xm', ylm_1sph, weights, pol[l])
                Amat[ja, :, ka, p0:p1] += -fac * a
    return Amat
Example #53
0
def cache_fake_multipoles(grids, r_vdw, lmax):
    # For each type of atoms, cache the product of last two terms in
    # JCP, 141, 184108, Eq (31):
    # x_{<}^{l} / x_{>}^{l+1} Y_l^m
    mol = grids.mol
    atom_grids_tab = grids.gen_atomic_grids(mol)
    r_vdw_type = {}
    for ia in range(mol.natm):
        symb = mol.atom_symbol(ia)
        if symb not in r_vdw_type:
            r_vdw_type[symb] = r_vdw[ia]

    cached_pol = {}
    for symb in atom_grids_tab:
        x_nj, w = atom_grids_tab[symb]
        r = lib.norm(x_nj, axis=1)
        # Different equations are used in JCTC, 9, 3637. r*Ys (the fake_pole)
        # is computed as r^l/r_vdw. "leak_idx" is not needed.
        # Here, the implementation is based on JCP, 141, 184108
        leak_idx = r > r_vdw_type[symb]

        pol = sph.multipoles(x_nj, lmax)
        fak_pol = []
        for l in range(lmax + 1):
            # x_{<}^{l} / x_{>}^{l+1} Y_l^m  in JCP, 141, 184108, Eq (31)
            #:Ys = sph.real_sph_vec(x_nj/r.reshape(-1,1), lmax, True)
            #:rr = numpy.zeros_like(r)
            #:rr[r<=r_vdw[ia]] = r[r<=r_vdw[ia]]**l / r_vdw[ia]**(l+1)
            #:rr[r> r_vdw[ia]] = r_vdw[ia]**l / r[r>r_vdw[ia]]**(l+1)
            #:xx_ylm = numpy.einsum('n,mn->mn', rr, Ys[l])
            xx_ylm = pol[l] * (1. / r_vdw_type[symb]**(l + 1))
            # The line below is not needed for JCTC, 9, 3637
            xx_ylm[:,
                   leak_idx] *= (r_vdw_type[symb] / r[leak_idx])**(2 * l + 1)
            fak_pol.append(xx_ylm)
        cached_pol[symb] = (fak_pol, leak_idx)
    return cached_pol
Example #54
0
 def eval_xc(self,
             xc_code,
             rho,
             spin=1,
             relativity=0,
             deriv=1,
             omega=None,
             verbose=None):
     if omega is None: omega = self.omega
     # JTCC, 2, 257
     r, m = rho[:2]
     s = lib.norm(m, axis=0)
     rhou = (r + s) * .5
     rhod = (r - s) * .5
     rho = (rhou, rhod)
     xc = self.libxc.eval_xc(xc_code, rho, 1, relativity, deriv, omega,
                             verbose)
     exc, vxc = xc[:2]
     # update vxc[0] inplace
     vrho = vxc[0]
     vr, vm = (vrho[:, 0] + vrho[:, 1]) * .5, (vrho[:, 0] - vrho[:, 1]) * .5
     vrho[:, 0] = vr
     vrho[:, 1] = vm
     return xc
Example #55
0
 def nimgs(self, x):
     b = self.reciprocal_vectors(norm_to=1)
     heights_inv = lib.norm(b, axis=1)
     self.rcut = max((np.asarray(x) + 1) / heights_inv)
Example #56
0
def ewald(cell, ew_eta=None, ew_cut=None):
    '''Perform real (R) and reciprocal (G) space Ewald sum for the energy.

    Formulation of Martin, App. F2.

    Returns:
        float
            The Ewald energy consisting of overlap, self, and G-space sum.

    See Also:
        pyscf.pbc.gto.get_ewald_params
    '''
    if ew_eta is None: ew_eta = cell.ew_eta
    if ew_cut is None: ew_cut = cell.ew_cut
    chargs = cell.atom_charges()
    coords = cell.atom_coords()

    Lall = cell.get_lattice_Ls(rcut=ew_cut)
    ewovrl = 0.
    for i, qi in enumerate(chargs):
        ri = coords[i]
        for j in range(i):
            qj = chargs[j]
            rj = coords[j]
            r1 = ri - rj + Lall
            r = np.sqrt(np.einsum('ji,ji->j', r1, r1))
            ewovrl += (qi * qj / r * scipy.special.erfc(ew_eta * r)).sum()
    # exclude the point where Lall == 0
    r = lib.norm(Lall, axis=1)
    r[r < 1e-16] = 1e200
    ewovrl += .5 * (chargs**
                    2).sum() * (1. / r * scipy.special.erfc(ew_eta * r)).sum()

    # last line of Eq. (F.5) in Martin
    ewself = -.5 * np.dot(chargs, chargs) * 2 * ew_eta / np.sqrt(np.pi)
    if cell.dimension == 3:
        ewself += -.5 * np.sum(chargs)**2 * np.pi / (ew_eta**2 * cell.vol)

    # g-space sum (using g grid) (Eq. (F.6) in Martin, but note errors as below)
    # Eq. (F.6) in Martin is off by a factor of 2, the
    # exponent is wrong (8->4) and the square is in the wrong place
    #
    # Formula should be
    #   1/2 * 4\pi / Omega \sum_I \sum_{G\neq 0} |ZS_I(G)|^2 \exp[-|G|^2/4\eta^2]
    # where
    #   ZS_I(G) = \sum_a Z_a exp (i G.R_a)
    # See also Eq. (32) of ewald.pdf at
    #   http://www.fisica.uniud.it/~giannozz/public/ewald.pdf

    gs = cell.gs
    Gv, Gvbase, weights = cell.get_Gv_weights(gs)
    absG2 = np.einsum('gi,gi->g', Gv, Gv)
    absG2[absG2 == 0] = 1e200
    coulG = 4 * np.pi / absG2
    coulG *= weights
    JexpG2 = np.exp(-absG2 / (4 * ew_eta**2)) * coulG

    ZSI = np.einsum("i,ij->j", chargs, cell.get_SI(Gv))
    ZSIG2 = np.abs(ZSI)**2
    ewg = .5 * np.dot(ZSIG2, JexpG2)

    logger.debug(cell, 'Ewald components = %.15g, %.15g, %.15g', ewovrl,
                 ewself, ewg)
    return ewovrl + ewself + ewg
Example #57
0
 def norm_xy(z):
     x, y = z.reshape(2, nocc, nvir)
     norm = lib.norm(x)**2 - lib.norm(y)**2
     norm = numpy.sqrt(.5 / norm)  # normalize to 0.5 for alpha spin
     return x * norm, y * norm
Example #58
0
    def build(self):

        t0 = (time.clock(), time.time())
        lib.logger.TIMER_LEVEL = 3

        cell = libpbc.chkfile.load_cell(self.chkfile)
        cell.ecp = None
        self.cell = cell
        self.a = self.cell.lattice_vectors()
        self.b = self.cell.reciprocal_vectors()
        self.vol = self.cell.vol
        self.nelectron = self.cell.nelectron 
        self.charge = self.cell.charge    
        self.spin = self.cell.spin      
        self.natm = self.cell.natm		
        self.kpts = lib.chkfile.load(self.chkfile, 'kcell/kpts')
        self.nkpts = len(self.kpts)
        self.ls = cell.get_lattice_Ls(dimension=3)
        self.ls = self.ls[numpy.argsort(lib.norm(self.ls, axis=1))]
        self.atm = numpy.asarray(cell._atm, dtype=numpy.int32, order='C')
        self.bas = numpy.asarray(cell._bas, dtype=numpy.int32, order='C')
        self.env = numpy.asarray(cell._env, dtype=numpy.double, order='C')
        self.nbas = self.bas.shape[0]
        self.ao_loc = cell.ao_loc_nr()
        self.shls_slice = (0, self.nbas)
        sh0, sh1 = self.shls_slice
        self.nao = self.ao_loc[sh1] - self.ao_loc[sh0]
        self.non0tab = numpy.empty((1,self.nbas), dtype=numpy.int8)
        # non0tab stores the number of images to be summed in real space.
        # Initializing it to 255 means all images are summed
        self.non0tab[:] = 0xff
        self.coords = numpy.asarray([(numpy.asarray(atom[1])).tolist() for atom in cell._atom])
        self.charges = cell.atom_charges()
        self.mo_coeff = lib.chkfile.load(self.chkfile, 'scf/mo_coeff')
        self.mo_occ = lib.chkfile.load(self.chkfile, 'scf/mo_occ')
        nprims, nmo = self.mo_coeff[0].shape 
        self.nprims = nprims
        self.nmo = nmo
        self.cart = cell.cart
        if (not self.leb):
            self.npang = self.npphi*self.nptheta

        self.rcut = _estimate_rcut(self)
        kpts = numpy.reshape(self.kpts, (-1,3))
        kpts_lst = numpy.reshape(kpts, (-1,3))
        self.explk = numpy.exp(1j * numpy.asarray(numpy.dot(self.ls, kpts_lst.T), order='C'))

        if (self.ntrial%2 == 0): self.ntrial += 1
        geofac = numpy.power(((self.rmaxsurf-0.1)/self.rprimer),(1.0/(self.ntrial-1.0)))
        self.rpru = numpy.zeros((self.ntrial))
        for i in range(self.ntrial): 
            self.rpru[i] = self.rprimer*numpy.power(geofac,(i+1)-1)
        self.rsurf = numpy.zeros((self.npang,self.ntrial), order='C')
        self.nlimsurf = numpy.zeros((self.npang), dtype=numpy.int32)

        if self.verbose >= logger.WARN:
            self.check_sanity()
        if self.verbose > logger.NOTE:
            self.dump_input()

        if (self.iqudt == 'legendre'):
            self.iqudt = 1
        
        if (self.leb):
            self.grids = grid.lebgrid(self.npang)
        else:
            self.grids = grid.anggrid(self.iqudt,self.nptheta,self.npphi)
         
        self.xyzrho = numpy.zeros((self.natm,3))
        t = time.time()
        logger.info(self,'Time finding nucleus %.3f (sec)' % (time.time()-t))

        if (self.backend == 'rkck'):
            backend = 1
        elif (self.backend == 'rkdp'):
            backend = 2
        else:
            raise NotImplementedError('Only rkck or rkdp ODE solver yet available') 
         
        ct_ = numpy.asarray(self.grids[:,0], order='C')
        st_ = numpy.asarray(self.grids[:,1], order='C')
        cp_ = numpy.asarray(self.grids[:,2], order='C')
        sp_ = numpy.asarray(self.grids[:,3], order='C')

        mo_coeff = numpy.zeros((self.nkpts,self.nprims,self.nmo), dtype=numpy.complex128)
        mo_occ = numpy.zeros((self.nkpts,self.nmo))
        for k in range(self.nkpts):
            mo_coeff[k,:,:] = self.mo_coeff[k][:,:]
            mo_occ[k,:] = self.mo_occ[k][:]
        
        t = time.time()
        feval = 'surf_driver'
        drv = getattr(libaim, feval)
        with lib.with_omp_threads(self.nthreads):
            drv(ctypes.c_int(self.inuc), 
                self.xyzrho.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.npang), 
                ct_.ctypes.data_as(ctypes.c_void_p),
                st_.ctypes.data_as(ctypes.c_void_p),
                cp_.ctypes.data_as(ctypes.c_void_p),
                sp_.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.ntrial), 
                self.rpru.ctypes.data_as(ctypes.c_void_p), 
                ctypes.c_double(self.epsiscp), 
                ctypes.c_double(self.epsroot), 
                ctypes.c_double(self.rmaxsurf), 
                ctypes.c_int(backend),
                ctypes.c_double(self.epsilon), 
                ctypes.c_double(self.step), 
                ctypes.c_int(self.mstep),
                ctypes.c_int(self.natm), 
                self.coords.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.cart),
                ctypes.c_int(self.nmo),  
                ctypes.c_int(self.nprims), 
                self.atm.ctypes.data_as(ctypes.c_void_p), 
                ctypes.c_int(self.nbas), 
                self.bas.ctypes.data_as(ctypes.c_void_p), 
                self.env.ctypes.data_as(ctypes.c_void_p), 
                self.ao_loc.ctypes.data_as(ctypes.c_void_p),
                mo_coeff.ctypes.data_as(ctypes.c_void_p),
                mo_occ.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_double(self.occdrop), 
                #
                self.a.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(len(self.ls)), 
                self.ls.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.nkpts), 
                self.explk.ctypes.data_as(ctypes.c_void_p),
                self.rcut.ctypes.data_as(ctypes.c_void_p),
                self.non0tab.ctypes.data_as(ctypes.c_void_p),
                #
                self.nlimsurf.ctypes.data_as(ctypes.c_void_p),
                self.rsurf.ctypes.data_as(ctypes.c_void_p))
        for i in range(self.nkpts):
            print k,self.mo_occ[k][:]
        logger.info(self,'Time finding surface %.3f (sec)' % (time.time()-t))
        r = numpy.array([0.00000, 0.00000, 0.00000]) 
        r = numpy.reshape(r, (-1,3))
        ao = dft.numint.eval_ao_kpts(self.cell, r, kpts=self.kpts, deriv=1)
        print rhograd(self,[0,0,0]) 
             
        logger.info(self,'Surface of atom %d saved',self.inuc)
        logger.timer(self,'BaderSurf build', *t0)

        return self
Example #59
0
occup = 2.0
norb = cell.nelectron // 2
for i in range(norb):
    fspt.write('%i %i %.8f\n' % ((i + 1), (i + 1), occup))
fspt.write('t2_iajb:\n')
for i in range(nocc):
    for j in range(nvir):
        for k in range(nocc):
            for l in range(nvir):
                if (abs(t2[i, j, k, l]) > 1e-8):
                    fspt.write('%i %i %i %i %.10f\n' % ((i+1+ncore), \
                    (j+1+nocc+ncore), (k+1+ncore), (l+1+nocc+ncore), \
                    t2[i,j,k,l]*2.0))
a = cell.a
t = cell.get_lattice_Ls()
t = t[numpy.argsort(lib.norm(t, axis=1))]
kpts = numpy.asarray([0.0, 0.0, 0.0])
fspt.write('CRYSTAL\n')
fspt.write('GAMMA %11.8f %11.8f %11.8f\n' % (kpts[0], kpts[1], kpts[2]))
fspt.write('CELL\n')
fspt.write(' %11.8f %11.8f %11.8f\n' % (a[0][0], a[0][1], a[0][2]))
fspt.write(' %11.8f %11.8f %11.8f\n' % (a[1][0], a[1][1], a[1][2]))
fspt.write(' %11.8f %11.8f %11.8f\n' % (a[2][0], a[2][1], a[2][2]))
fspt.write('T-VECTORS %3d\n' % len(t))
for i in range(len(t)):
    fspt.write(' %11.8f %11.8f %11.8f\n' % (t[i][0], t[i][1], t[i][2]))
fspt.close()

#cv, ev = utils.getdffno(mf,ncore,eri_mo,thresh_vir=1e-4)
#lib.logger.info(mf,"* FNO GAMMA point MP2 ")
#nvir = len(ev)
Example #60
0
def _normalize(vecs):
    vecs = numpy.asarray(vecs)
    if vecs.ndim == 1:
        return vecs / (numpy.linalg.norm(vecs) + 1e-200)
    else:
        return vecs / (norm(vecs, axis=1).reshape(-1, 1) + 1e-200)