Exemple #1
0
def coulomb_am(self, sp1, R1, sp2, R2, **kvargs):
  """
    Computes Coulomb overlap for an atom pair. The atom pair is given by a pair of species indices and the coordinates of the atoms.
    <a|r^-1|b> = \iint a(r)|r-r'|b(r')  dr dr'
    Args: 
      self: class instance of ao_matelem_c
      sp1,sp2 : specie indices, and
      R1,R2 :   respective coordinates
    Result:
      matrix of Coulomb overlaps
    The procedure uses the angular momentum algebra and spherical Bessel transform. It is almost a repetition of bilocal overlaps.
  """

  shape = [self.ao1.sp2norbs[sp] for sp in (sp1,sp2)]
  oo2co = np.zeros(shape)
  R2mR1 = np.array(R2)-np.array(R1)
  dist,ylm = np.sqrt(sum(R2mR1*R2mR1)), csphar( R2mR1, 2*self.jmx+1 )
  cS = np.zeros((self.jmx*2+1,self.jmx*2+1), dtype=np.complex128)
  cmat = np.zeros((self.jmx*2+1,self.jmx*2+1), dtype=np.complex128)
  rS = np.zeros((self.jmx*2+1,self.jmx*2+1))

  f1f2_mom = np.zeros((self.nr))
  l2S = np.zeros((2*self.jmx+1), dtype = np.float64)
  _j = self.jmx
  dkappa = np.log(self.kk[self.nr-1]/self.kk[0])/(self.nr-1)

  if use_numba:
    bessel_pp = np.zeros((_j*2+1, self.nr))
    for L in range(2*_j+1):
        bessel_pp[L, :] = scipy.special.spherical_jn(L, dist*self.kk)*self.kk
    calc_oo2co(bessel_pp, dkappa, np.array(self.ao1.sp2info[sp1]),
      np.array(self.ao1.sp2info[sp2]), self.ao1.psi_log_mom[sp1], self.ao1.psi_log_mom[sp2],
      self.njm, self._gaunt_iptr, self._gaunt_data, ylm, _j, self.jmx, self._tr_c2r,
      self._conj_c2r, l2S, cS, rS, cmat, oo2co)
  else:
    bessel_pp = np.zeros((_j*2+1, self.nr))
    for L in range(2*_j+1):
        bessel_pp[L, :] = scipy.special.spherical_jn(L, dist*self.kk)*self.kk

    for mu2,l2,s2,f2 in self.ao1.sp2info[sp2]:
      for mu1,l1,s1,f1 in self.ao1.sp2info[sp1]:
        f1f2_mom = self.ao1.psi_log_mom[sp2][mu2,:] * self.ao1.psi_log_mom[sp1][mu1,:]
        l2S.fill(0.0)
        for l3 in range( abs(l1-l2), l1+l2+1):
          l2S[l3] = (f1f2_mom[:]*bessel_pp[l3,:]).sum() + f1f2_mom[0]*bessel_pp[l3,0]/dkappa
        cS.fill(0.0)
        for m1 in range(-l1,l1+1):
          for m2 in range(-l2,l2+1):
            gc,m3 = self.get_gaunt(l1,-m1,l2,m2), m2-m1
            for l3ind,l3 in enumerate(range(abs(l1-l2),l1+l2+1)):
              if abs(m3) > l3 : continue
              cS[m1+_j,m2+_j] = cS[m1+_j,m2+_j] + l2S[l3]*ylm[ l3*(l3+1)+m3] *\
                    gc[l3ind] * (-1.0)**((3*l1+l2+l3)//2+m2)
        self.c2r_( l1,l2, self.jmx,cS,rS,cmat)
        oo2co[s1:f1,s2:f2] = rS[-l1+_j:l1+_j+1,-l2+_j:l2+_j+1]
  #sys.exit()

  oo2co = oo2co * (4*np.pi)**2 * self.interp_pp.dg_jt
  return oo2co
Exemple #2
0
  def test_csphar(self):
    """  """
    from pyscf.nao.m_csphar_talman_libnao import csphar_talman_libnao, talman2world
    
    rvec = np.array([0.1, 0.2, -0.4])
    lmax = 3
    ylm_py = csphar(rvec, lmax)
    ylm_jt = csphar_talman_libnao(rvec, lmax)
    self.assertEqual(len(ylm_py), (lmax+1)**2)
    self.assertEqual(len(ylm_jt), (lmax+1)**2)
    
    self.assertAlmostEqual(ylm_py[1], 0.075393004386513446-0.15078600877302686j)

    rvecs = [[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.1, 0.2, -0.4], [5.1, 2.2, -9.4], [0.9, 0.6, -0.2]]
    for rvec in rvecs:
       ylm_py_ref = csphar(rvec, lmax)
       ylm_py = talman2world(csphar_talman_libnao(rvec, lmax))
       for y1,y2 in zip(ylm_py_ref, ylm_py):
         self.assertAlmostEqual(y1,y2)
Exemple #3
0
  def test_csphar(self):
    """  """
    from pyscf.nao.m_csphar import csphar
    from pyscf.nao.m_csphar_talman_libnao import csphar_talman_libnao, talman2world
    
    rvec = np.array([0.1, 0.2, -0.4])
    lmax = 3
    ylm_py = csphar(rvec, lmax)
    ylm_jt = csphar_talman_libnao(rvec, lmax)
    self.assertEqual(len(ylm_py), (lmax+1)**2)
    self.assertEqual(len(ylm_jt), (lmax+1)**2)
    
    self.assertAlmostEqual(ylm_py[1], 0.075393004386513446-0.15078600877302686j)

    rvecs = [[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.1, 0.2, -0.4], [5.1, 2.2, -9.4], [0.9, 0.6, -0.2]]
    for rvec in rvecs:
       ylm_py_ref = csphar(rvec, lmax)
       ylm_py = talman2world(csphar_talman_libnao(rvec, lmax))
       for y1,y2 in zip(ylm_py_ref, ylm_py):
         self.assertAlmostEqual(y1,y2)
Exemple #4
0
def coulomb_am(self, sp1, R1, sp2, R2, **kvargs):
    r"""
    Computes Coulomb overlap for an atom pair. The atom pair is given by a pair of species indices and the coordinates of the atoms.
    <a|r^-1|b> = \iint a(r)|r-r'|b(r')  dr dr'
    Args:
      self: class instance of ao_matelem_c
      sp1,sp2 : specie indices, and
      R1,R2 :   respective coordinates
    Result:
      matrix of Coulomb overlaps
    The procedure uses the angular momentum algebra and spherical Bessel transform. It is almost a repetition of bilocal overlaps.
  """

    shape = [self.ao1.sp2norbs[sp] for sp in (sp1, sp2)]
    oo2co = np.zeros(shape)
    R2mR1 = np.array(R2) - np.array(R1)
    dist, ylm = np.sqrt(sum(R2mR1 * R2mR1)), csphar(R2mR1, 2 * self.jmx + 1)
    cS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    cmat = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    rS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1))

    f1f2_mom = np.zeros((self.nr))
    l2S = np.zeros((2 * self.jmx + 1), dtype=np.float64)
    _j = self.jmx
    dkappa = np.log(self.kk[self.nr - 1] / self.kk[0]) / (self.nr - 1)

    if use_numba:
        bessel_pp = np.zeros((_j * 2 + 1, self.nr))
        for L in range(2 * _j + 1):
            bessel_pp[L, :] = scipy.special.spherical_jn(
                L, dist * self.kk) * self.kk
        calc_oo2co(bessel_pp, dkappa, np.array(self.ao1.sp2info[sp1]),
                   np.array(self.ao1.sp2info[sp2]), self.ao1.psi_log_mom[sp1],
                   self.ao1.psi_log_mom[sp2], self.njm, self._gaunt_iptr,
                   self._gaunt_data, ylm, _j, self.jmx, self._tr_c2r,
                   self._conj_c2r, l2S, cS, rS, cmat, oo2co)
    else:
        bessel_pp = np.zeros((_j * 2 + 1, self.nr))
        for L in range(2 * _j + 1):
            bessel_pp[L, :] = scipy.special.spherical_jn(
                L, dist * self.kk) * self.kk

        for mu2, l2, s2, f2 in self.ao1.sp2info[sp2]:
            for mu1, l1, s1, f1 in self.ao1.sp2info[sp1]:
                f1f2_mom = self.ao1.psi_log_mom[sp2][
                    mu2, :] * self.ao1.psi_log_mom[sp1][mu1, :]
                l2S.fill(0.0)
                for l3 in range(abs(l1 - l2), l1 + l2 + 1):
                    l2S[l3] = (f1f2_mom[:] * bessel_pp[l3, :]).sum(
                    ) + f1f2_mom[0] * bessel_pp[l3, 0] / dkappa
                cS.fill(0.0)
                for m1 in range(-l1, l1 + 1):
                    for m2 in range(-l2, l2 + 1):
                        gc, m3 = self.get_gaunt(l1, -m1, l2, m2), m2 - m1
                        for l3ind, l3 in enumerate(
                                range(abs(l1 - l2), l1 + l2 + 1)):
                            if abs(m3) > l3: continue
                            cS[m1+_j,m2+_j] = cS[m1+_j,m2+_j] + l2S[l3]*ylm[ l3*(l3+1)+m3] *\
                                  gc[l3ind] * (-1.0)**((3*l1+l2+l3)//2+m2)
                self.c2r_(l1, l2, self.jmx, cS, rS, cmat)
                oo2co[s1:f1, s2:f2] = rS[-l1 + _j:l1 + _j + 1,
                                         -l2 + _j:l2 + _j + 1]
    #sys.exit()

    oo2co = oo2co * (4 * np.pi)**2 * self.interp_pp.dg_jt
    return oo2co
Exemple #5
0
def overlap_am(self, sp1, R1, sp2, R2):
    """
    Computes overlap for an atom pair. The atom pair is given by a pair of species indices
    and the coordinates of the atoms.
    Args: 
      self: class instance of ao_matelem_c
      sp1,sp2 : specie indices, and
      R1,R2 :   respective coordinates
    Result:
      matrix of orbital overlaps
    The procedure uses the angular momentum algebra and spherical Bessel transform
    to compute the bilocal overlaps.
  """
    shape = [self.ao1.sp2norbs[sp] for sp in (sp1, sp2)]
    overlaps = np.zeros(shape)

    R2mR1 = np.array(R2) - np.array(R1)

    psi_log = self.ao1.psi_log
    psi_log_mom = self.ao1.psi_log_mom
    sp_mu2rcut = self.ao1.sp_mu2rcut
    sp2info = self.ao1.sp2info

    ylm = csphar(R2mR1, 2 * self.jmx + 1)
    dist = np.sqrt(sum(R2mR1 * R2mR1))
    cS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    cmat = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    rS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1))
    if (dist < 1.0e-5):
        for [mu1, l1, s1, f1], ff1 in zip(sp2info[sp1], psi_log[sp1]):
            for [mu2, l2, s2, f2], ff2 in zip(sp2info[sp2], psi_log[sp2]):
                cS.fill(0.0)
                rS.fill(0.0)
                if l1 == l2:
                    sum1 = sum(ff1 * ff2 * self.rr3_dr)
                    for m1 in range(-l1, l1 + 1):
                        cS[m1 + self.jmx, m1 + self.jmx] = sum1
                    self.c2r_(l1, l2, self.jmx, cS, rS, cmat)
                overlaps[s1:f1, s2:f2] = rS[-l1 + self.jmx:l1 + 1 + self.jmx,
                                            -l2 + self.jmx:l2 + 1 + self.jmx]

    else:

        f1f2_mom = np.zeros((self.nr))
        l2S = np.zeros((2 * self.jmx + 1))
        ir, coeffs = comp_coeffs(self.interp_rr, dist)
        _j = self.jmx
        for [mu2, l2, s2, f2], rcut2, ff2 in zip(sp2info[sp2], sp_mu2rcut[sp2],
                                                 psi_log_mom[sp2]):
            for [mu1, l1, s1,
                 f1], rcut1, ff1 in zip(sp2info[sp1], sp_mu2rcut[sp1],
                                        psi_log_mom[sp1]):
                if rcut1 + rcut2 < dist: continue
                f1f2_mom = ff2 * ff1
                l2S.fill(0.0)
                for l3 in range(abs(l1 - l2), l1 + l2 + 1):
                    f1f2_rea = self.sbt(f1f2_mom, l3, -1)
                    l2S[l3] = (f1f2_rea[ir:ir + 6] *
                               coeffs).sum() * self.const * 4 * np.pi

                cS.fill(0.0)
                for m1 in range(-l1, l1 + 1):
                    for m2 in range(-l2, l2 + 1):
                        gc, m3 = self.get_gaunt(l1, -m1, l2, m2), m2 - m1
                        for l3ind, l3 in enumerate(
                                range(abs(l1 - l2), l1 + l2 + 1)):
                            if abs(m3) > l3: continue
                            cS[m1 + _j,
                               m2 + _j] = cS[m1 + _j, m2 + _j] + l2S[l3] * ylm[
                                   l3 * (l3 + 1) + m3] * gc[l3ind] * (-1.0)**(
                                       (3 * l1 + l2 + l3) // 2 + m2)

                self.c2r_(l1, l2, self.jmx, cS, rS, cmat)
                overlaps[s1:f1, s2:f2] = rS[-l1 + _j:l1 + _j + 1,
                                            -l2 + _j:l2 + _j + 1]

    return overlaps
Exemple #6
0
def comp_vext_tem_pyth(self, ao_log=None, numba_parallel=True):
    """
        Compute the external potential created by a moving charge
        Python version
    """
    def c2r_lm(conv, clm, clmm, m):
        """
            clm: sph harmonic l and m
            clmm: sph harmonic l and -m
            convert from real to complex spherical harmonic
            for an unique value of l and m
        """
        rlm = 0.0
        if m == 0:
            rlm = conv._c2r[conv._j, conv._j] * clm
        else:
            rlm = conv._c2r[m+conv._j, m+conv._j]*clm +\
                    conv._c2r[m+conv._j, -m+conv._j]*clmm

        if rlm.imag > 1e-10:
            print(rlm)
            raise ValueError("Non nul imaginary paert for c2r conversion")
        return rlm.real

    def get_index_lm(l, m):
        """
            return the index of an array ordered as 
            [l=0 m=0, l=1 m=-1, l=1 m=0, l=1 m=1, ....]
        """
        return (l + 1)**2 - 1 - l + m

    warnings.warn("Obselete routine use comp_vext_tem")

    if use_numba:
        get_time_potential = nb.jit(
            nopython=True, parallel=numba_parallel)(get_tem_potential_numba)
    V_time = np.zeros((self.time.size), dtype=np.complex64)

    aome = ao_matelem_c(self.ao_log.rr, self.ao_log.pp)
    me = ao_matelem_c(
        self.ao_log) if ao_log is None else aome.init_one_set(ao_log)
    atom2s = np.zeros((self.natm + 1), dtype=np.int64)
    for atom, sp in enumerate(self.atom2sp):
        atom2s[atom + 1] = atom2s[atom] + me.ao1.sp2norbs[sp]

    R0 = self.vnorm * self.time[0] * self.vdir + self.beam_offset
    rr = self.ao_log.rr
    dr = (np.log(rr[-1]) - np.log(rr[0])) / (rr.size - 1)
    dt = self.time[1] - self.time[0]
    dw = self.freq_symm[1] - self.freq_symm[0]
    wmin = self.freq_symm[0]
    tmin = self.time[0]
    nff = self.freq.size
    ub = self.freq_symm.size // 2 - 1
    l2m = []  # list storing m value to corresponding l
    fact_fft = np.exp(-1.0j * self.freq_symm[ub:ub + nff] * tmin)
    pre_fact = dt * np.exp(-1.0j * wmin * (self.time - tmin))

    for l in range(me.jmx + 1):
        lm = []
        for m in range(-l, l + 1):
            lm.append(m)
        l2m.append(np.array(lm))

    for atm, sp in enumerate(self.atom2sp):
        rcut = self.ao_log.sp2rcut[sp]
        center = self.atom2coord[atm, :]
        rmax = find_nearrest_index(rr, rcut)

        si = atom2s[atm]
        fi = atom2s[atm + 1]

        for mu, l in enumerate(self.pb.prod_log.sp_mu2j[sp]):
            s = self.pb.prod_log.sp_mu2s[sp][mu]
            f = self.pb.prod_log.sp_mu2s[sp][mu + 1]

            fr_val = self.pb.prod_log.psi_log[sp][mu, :]
            inte1 = np.sum(fr_val[0:rmax + 1] * rr[0:rmax + 1]**(l + 2) *
                           rr[0:rmax + 1] * dr)

            for k in range(s, f):
                V_time.fill(0.0)

                m = l2m[l][k - s]
                ind_lm = get_index_lm(l, m)
                ind_lmm = get_index_lm(l, -m)

                if use_numba:
                    get_time_potential(self.time, R0, self.vnorm, self.vdir,
                                       center, rcut, inte1, rr, dr, fr_val,
                                       me._c2r, l, m, me._j, ind_lm, ind_lmm,
                                       V_time)
                else:
                    for it, t in enumerate(self.time):
                        R_sub = R0 + self.vnorm * self.vdir * (
                            t - self.time[0]) - center
                        norm = np.sqrt(np.dot(R_sub, R_sub))

                        if norm > rcut:
                            I1 = inte1 / (norm**(l + 1))
                            I2 = 0.0
                        else:
                            rsub_max = find_nearrest_index(rr, norm)

                            I1 = np.sum(fr_val[0:rsub_max + 1] *
                                        rr[0:rsub_max + 1]**(l + 2) *
                                        rr[0:rsub_max + 1])
                            I2 = np.sum(fr_val[rsub_max + 1:] *
                                        rr[rsub_max + 1:] /
                                        (rr[rsub_max + 1:]**(l - 1)))

                            I1 = I1 * dr / (norm**(l + 1))
                            I2 = I2 * (norm**l) * dr
                        clm_tem = csphar(R_sub, l)
                        clm = (4 * np.pi /
                               (2 * l + 1)) * clm_tem[ind_lm] * (I1 + I2)
                        clmm = (4 * np.pi /
                                (2 * l + 1)) * clm_tem[ind_lmm] * (I1 + I2)
                        rlm = c2r_lm(me, clm, clmm, m)
                        V_time[it] = rlm + 0.0j

                V_time *= pre_fact

                FT = fft(V_time)

                self.V_freq[:, si + k] = FT[ub:ub + nff] * fact_fft
Exemple #7
0
def laplace_am(self, sp1, R1, sp2, R2):
    """
    Computes brakets of Laplace operator for an atom pair. 
    The atom pair is given by a pair of species indices
    and the coordinates of the atoms.
    Args: 
      self: class instance of ao_matelem_c
      sp1,sp2 : specie indices, and
      R1,R2 :   respective coordinates
    Result:
      matrix of Laplace operator brakets
  """
    shape = [self.ao1.sp2norbs[sp] for sp in (sp1, sp2)]
    overlaps = np.zeros(shape)

    R2mR1 = np.array(R2) - np.array(R1)

    psi_log = self.ao1.psi_log
    psi_log_mom = self.ao1.psi_log_mom
    sp_mu2rcut = self.ao1.sp_mu2rcut
    sp2info = self.ao1.sp2info
    pp = self.ao1.pp
    rr = self.ao1.rr
    ylm = csphar(R2mR1, 2 * self.jmx + 1)
    dist = np.sqrt(sum(R2mR1 * R2mR1))
    cS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    cmat = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    rS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1))
    j = self.jmx

    if (dist < 1.0e-5):

        for [mu1, l1, s1, f1], ff1 in zip(sp2info[sp1], psi_log[sp1]):
            ff1_diff = self.interp_rr.diff(ff1)
            for [mu2, l2, s2, f2], ff2 in zip(sp2info[sp2], psi_log[sp2]):
                ff2_diff = self.interp_rr.diff(ff2)
                cS.fill(0.0)
                rS.fill(0.0)
                if l1 == l2:
                    sum2 = sum(ff1_diff * ff2_diff * self.rr3_dr) + l1 * (
                        l1 + 1) * sum(ff1 * ff2 * rr) * self.dr_jt
                    for m1 in range(-l1, l1 + 1):
                        cS[m1 + self.jmx, m1 + self.jmx] = sum2
                    self.c2r_(l1, l2, self.jmx, cS, rS, cmat)

                overlaps[s1:f1, s2:f2] = rS[-l1 + j:l1 + 1 + j,
                                            -l2 + j:l2 + 1 + j]

    else:

        f1f2_mom = np.zeros((self.nr))
        l2S = np.zeros((2 * self.jmx + 1))
        ir, coeffs = comp_coeffs(self.interp_rr, dist)
        for [mu2, l2, s2, f2], rcut2, ff2 in zip(sp2info[sp2], sp_mu2rcut[sp2],
                                                 psi_log_mom[sp2]):
            for [mu1, l1, s1,
                 f1], rcut1, ff1 in zip(sp2info[sp1], sp_mu2rcut[sp1],
                                        psi_log_mom[sp1]):
                if rcut1 + rcut2 < dist: continue
                f1f2_mom = ff2 * ff1 * self.pp2
                l2S.fill(0.0)
                for l3 in range(abs(l1 - l2), l1 + l2 + 1):
                    f1f2_rea = self.sbt(f1f2_mom, l3, -1)
                    l2S[l3] = (f1f2_rea[ir:ir + 6] * coeffs).sum()

                l2S = l2S * self.const * 4 * np.pi

                cS.fill(0.0)
                for m1 in range(-l1, l1 + 1):
                    for m2 in range(-l2, l2 + 1):
                        gc, m3 = self.get_gaunt(l1, -m1, l2, m2), m2 - m1
                        for l3ind, l3 in enumerate(
                                range(abs(l1 - l2), l1 + l2 + 1)):
                            if abs(m3) > l3: continue
                            cS[m1 + j,
                               m2 + j] = cS[m1 + j, m2 + j] + l2S[l3] * ylm[
                                   l3 * (l3 + 1) + m3] * gc[l3ind] * (-1.0)**(
                                       (3 * l1 + l2 + l3) // 2 + m2)

                self.c2r_(l1, l2, self.jmx, cS, rS, cmat)
                overlaps[s1:f1, s2:f2] = rS[-l1 + j:l1 + j + 1,
                                            -l2 + j:l2 + j + 1]

    return -overlaps
Exemple #8
0
def laplace_am(self, sp1, R1, sp2, R2):
  """
    Computes brakets of Laplace operator for an atom pair. 
    The atom pair is given by a pair of species indices
    and the coordinates of the atoms.
    Args: 
      self: class instance of ao_matelem_c
      sp1,sp2 : specie indices, and
      R1,R2 :   respective coordinates
    Result:
      matrix of Laplace operator brakets
  """
  shape = [self.ao1.sp2norbs[sp] for sp in (sp1,sp2)]
  overlaps = np.zeros(shape)
  
  R2mR1 = np.array(R2)-np.array(R1)
  
  psi_log = self.ao1.psi_log
  psi_log_mom = self.ao1.psi_log_mom
  sp_mu2rcut = self.ao1.sp_mu2rcut
  sp2info = self.ao1.sp2info
  pp = self.ao1.pp
  rr = self.ao1.rr
  ylm = csphar( R2mR1, 2*self.jmx+1 )
  dist = np.sqrt(sum(R2mR1*R2mR1))
  cS = np.zeros((self.jmx*2+1,self.jmx*2+1), dtype=np.complex128)
  cmat = np.zeros((self.jmx*2+1,self.jmx*2+1), dtype=np.complex128)
  rS = np.zeros((self.jmx*2+1,self.jmx*2+1))
  j = self.jmx
  
  if(dist<1.0e-5): 
    
    for [mu1,l1,s1,f1],ff1 in zip(sp2info[sp1],psi_log[sp1]):
      ff1_diff = self.interp_rr.diff(ff1)
      for [mu2,l2,s2,f2],ff2 in zip(sp2info[sp2],psi_log[sp2]):
        ff2_diff = self.interp_rr.diff(ff2)
        cS.fill(0.0); rS.fill(0.0);
        if l1==l2 : 
          sum2 = sum(ff1_diff*ff2_diff*self.rr3_dr)+l1*(l1+1)*sum(ff1*ff2*rr)*self.dr_jt
          for m1 in range(-l1,l1+1): cS[m1+self.jmx,m1+self.jmx]=sum2
          self.c2r_( l1,l2, self.jmx,cS,rS,cmat)

        overlaps[s1:f1,s2:f2] = rS[-l1+j:l1+1+j,-l2+j:l2+1+j]

  else:

    f1f2_mom = np.zeros((self.nr))
    l2S = np.zeros((2*self.jmx+1))
    ir,coeffs = comp_coeffs(self.interp_rr, dist)
    for [mu2,l2,s2,f2],rcut2,ff2 in zip(sp2info[sp2],sp_mu2rcut[sp2],psi_log_mom[sp2]):
      for [mu1,l1,s1,f1],rcut1,ff1 in zip(sp2info[sp1],sp_mu2rcut[sp1],psi_log_mom[sp1]):
        if rcut1+rcut2<dist: continue
        f1f2_mom = ff2 * ff1 * self.pp2
        l2S.fill(0.0)
        for l3 in range( abs(l1-l2), l1+l2+1):
          f1f2_rea = self.sbt(f1f2_mom, l3, -1)
          l2S[l3] = (f1f2_rea[ir:ir+6]*coeffs).sum()
        
        l2S = l2S*self.const*4*np.pi
          
        cS.fill(0.0) 
        for m1 in range(-l1,l1+1):
          for m2 in range(-l2,l2+1):
            gc, m3 = self.get_gaunt(l1,-m1,l2,m2), m2-m1
            for l3ind,l3 in enumerate(range(abs(l1-l2),l1+l2+1)):
              if abs(m3) > l3 : continue
              cS[m1+j,m2+j] = cS[m1+j,m2+j] + l2S[l3]*ylm[ l3*(l3+1)+m3] * gc[l3ind] * (-1.0)**((3*l1+l2+l3)//2+m2)

        self.c2r_( l1,l2, self.jmx,cS,rS,cmat)
        overlaps[s1:f1,s2:f2] = rS[-l1+j:l1+j+1,-l2+j:l2+j+1]

  return overlaps
Exemple #9
0
def overlap_am(self, sp1, R1, sp2, R2):
  """
    Computes overlap for an atom pair. The atom pair is given by a pair of species indices
    and the coordinates of the atoms.
    Args: 
      self: class instance of ao_matelem_c
      sp1,sp2 : specie indices, and
      R1,R2 :   respective coordinates
    Result:
      matrix of orbital overlaps
    The procedure uses the angular momentum algebra and spherical Bessel transform
    to compute the bilocal overlaps.
  """
  shape = [self.ao1.sp2norbs[sp] for sp in (sp1,sp2)]
  overlaps = np.zeros(shape)
  
  R2mR1 = np.array(R2)-np.array(R1)
  
  psi_log = self.ao1.psi_log
  psi_log_mom = self.ao1.psi_log_mom
  sp_mu2rcut = self.ao1.sp_mu2rcut
  sp2info = self.ao1.sp2info
  
  ylm = csphar( R2mR1, 2*self.jmx+1 )
  dist = np.sqrt(sum(R2mR1*R2mR1))
  cS = np.zeros((self.jmx*2+1,self.jmx*2+1), dtype=np.complex128)
  cmat = np.zeros((self.jmx*2+1,self.jmx*2+1), dtype=np.complex128)
  rS = np.zeros((self.jmx*2+1,self.jmx*2+1))
  if(dist<1.0e-5): 
    for [mu1,l1,s1,f1],ff1 in zip(sp2info[sp1],psi_log[sp1]):
      for [mu2,l2,s2,f2],ff2 in zip(sp2info[sp2],psi_log[sp2]):
        cS.fill(0.0); rS.fill(0.0);
        if l1==l2 : 
          sum1 = sum(ff1 * ff2 *self.rr3_dr)
          for m1 in range(-l1,l1+1): cS[m1+self.jmx,m1+self.jmx]=sum1
          self.c2r_( l1,l2, self.jmx,cS,rS,cmat)
        overlaps[s1:f1,s2:f2] = rS[-l1+self.jmx:l1+1+self.jmx,-l2+self.jmx:l2+1+self.jmx]

  else:

    f1f2_mom = np.zeros((self.nr))
    l2S = np.zeros((2*self.jmx+1))
    ir,coeffs = comp_coeffs(self.interp_rr, dist)
    _j = self.jmx
    for [mu2,l2,s2,f2],rcut2,ff2 in zip(sp2info[sp2],sp_mu2rcut[sp2],psi_log_mom[sp2]):
      for [mu1,l1,s1,f1],rcut1,ff1 in zip(sp2info[sp1],sp_mu2rcut[sp1],psi_log_mom[sp1]):
        if rcut1+rcut2<dist: continue
        f1f2_mom = ff2 * ff1
        l2S.fill(0.0)
        for l3 in range( abs(l1-l2), l1+l2+1):
          f1f2_rea = self.sbt(f1f2_mom, l3, -1)
          l2S[l3] = (f1f2_rea[ir:ir+6]*coeffs).sum()*self.const*4*np.pi
          
        cS.fill(0.0) 
        for m1 in range(-l1,l1+1):
          for m2 in range(-l2,l2+1):
            gc, m3 = self.get_gaunt(l1,-m1,l2,m2), m2-m1
            for l3ind,l3 in enumerate(range(abs(l1-l2),l1+l2+1)):
              if abs(m3) > l3 : continue
              cS[m1+_j,m2+_j] = cS[m1+_j,m2+_j] + l2S[l3]*ylm[ l3*(l3+1)+m3] * gc[l3ind] * (-1.0)**((3*l1+l2+l3)//2+m2)
                  
        self.c2r_( l1,l2, self.jmx,cS,rS,cmat)
        overlaps[s1:f1,s2:f2] = rS[-l1+_j:l1+_j+1,-l2+_j:l2+_j+1]

  return overlaps
Exemple #10
0
def coulomb_am(self, sp1, R1, sp2, R2, **kvargs):
    """
    Computes Coulomb overlap for an atom pair. The atom pair is given by a pair of species indices and the coordinates of the atoms.
    <a|r^-1|b> = \iint a(r)|r-r'|b(r')  dr dr'
    Args: 
      self: class instance of ao_matelem_c
      sp1,sp2 : specie indices, and
      R1,R2 :   respective coordinates
    Result:
      matrix of Coulomb overlaps
    The procedure uses the angular momentum algebra and spherical Bessel transform. It is almost a repetition of bilocal overlaps.
  """

    shape = [self.ao1.sp2norbs[sp] for sp in (sp1, sp2)]
    oo2co = np.zeros(shape)
    R2mR1 = np.array(R2) - np.array(R1)
    dist, ylm = np.sqrt(sum(R2mR1 * R2mR1)), csphar(R2mR1, 2 * self.jmx + 1)
    cS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    cmat = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1), dtype=np.complex128)
    rS = np.zeros((self.jmx * 2 + 1, self.jmx * 2 + 1))

    f1f2_mom = np.zeros((self.nr))
    l2S = np.zeros((2 * self.jmx + 1), dtype=np.float64)
    _j = self.jmx

    #  use_numba = False

    #  import h5py
    #  import matplotlib.pyplot as plt
    #  fig = plt.figure(1, figsize=(15, 10))
    #  log_mom_fortran = h5py.File("pb_coul_aux.hdf5", "r")["sp_local2functs_mom"]
    #  psi_range = np.arange(self.ao1.psi_log_mom[0].shape[1])
    #  for sp in range(len(self.ao1.psi_log_mom)):
    #      for mu in range(self.ao1.psi_log_mom[sp].shape[0]):
    #        ax = fig.add_subplot(2, 3, mu+1)
    #        error = np.zeros(self.ao1.psi_log_mom[sp].shape[0])
    #        pyt = self.ao1.psi_log_mom[sp][mu, :]
    #        fort = log_mom_fortran["specie_{0}/ir_mu2v".format(sp+1)].value[mu, :]
    #        ax.plot(psi_range, pyt, "b", linewidth=3, label="python")
    #        ax_twin = ax.twinx()
    #        ax_twin.plot(psi_range, fort, "--g", linewidth=3, label="fortran mu")
    #        for mu2 in range(self.ao1.psi_log_mom[sp].shape[0]):
    #            fort = log_mom_fortran["specie_{0}/ir_mu2v".format(sp+1)].value[mu2, :]
    #            error[mu2] = np.sum(abs(fort-pyt))
    #        mu_fort = np.argmin(error)
    #        fort = log_mom_fortran["specie_{0}/ir_mu2v".format(sp+1)].value[mu_fort, :]
    #        ax.plot(psi_range, fort, "--r", linewidth=3, label="fortran mumod")
    #        ax.legend()
    #        ax.set_title("mu_python = {0}, mu_fort = {1}".format(mu+1, mu_fort+1), fontsize=20)
    #        #print("look fort: ", np.sum(abs(fort-pyt)))
    #
    #  fig.tight_layout()
    #  fig.savefig("psi_log_diff.pdf", format="pdf")
    #  #plt.show()
    #  #print("shape: ", self.ao1.psi_log_mom[0].shape)
    #  #sys.exit()
    #self.ao1.psi_log_mom[sp] = log_mom_fortran["specie_{0}/ir_mu2v".format(sp+1)].value
    #  use_numba=False

    if use_numba:
        bessel_pp = np.zeros((_j * 2 + 1, self.nr))
        for L in range(2 * _j + 1):
            bessel_pp[L, :] = scipy.special.spherical_jn(
                L, dist * self.kk) * self.kk
        calc_oo2co(bessel_pp, self.interp_pp.dg_jt,
                   np.array(self.ao1.sp2info[sp1]),
                   np.array(self.ao1.sp2info[sp2]), self.ao1.psi_log_mom[sp1],
                   self.ao1.psi_log_mom[sp2], self.njm, self._gaunt_iptr,
                   self._gaunt_data, ylm, _j, self.jmx, self._tr_c2r,
                   self._conj_c2r, l2S, cS, rS, cmat, oo2co)
    else:
        bessel_pp = np.zeros((_j * 2 + 1, self.nr))
        for L in range(2 * _j + 1):
            bessel_pp[L, :] = scipy.special.spherical_jn(
                L, dist * self.kk) * self.kk

        #print("##############################################")
        for mu2, l2, s2, f2 in self.ao1.sp2info[sp2]:
            for mu1, l1, s1, f1 in self.ao1.sp2info[sp1]:
                f1f2_mom = self.ao1.psi_log_mom[sp2][
                    mu2, :] * self.ao1.psi_log_mom[sp1][mu1, :]
                #print("mu1 = {0}, mu2 = {1}: sum(f1f2_mom) = ".format(mu1, mu2), np.sum(abs(f1f2_mom)))
                l2S.fill(0.0)
                for l3 in range(abs(l1 - l2), l1 + l2 + 1):
                    l2S[l3] = (f1f2_mom[:] * bessel_pp[l3, :]
                               ).sum() + f1f2_mom[0] * bessel_pp[
                                   l3, 0] / self.interp_pp.dg_jt * 0.995
                #print("sum(S) = ", np.sum(abs(l2S)))

                cS.fill(0.0)
                for m1 in range(-l1, l1 + 1):
                    for m2 in range(-l2, l2 + 1):
                        gc, m3 = self.get_gaunt(l1, -m1, l2, m2), m2 - m1
                        for l3ind, l3 in enumerate(
                                range(abs(l1 - l2), l1 + l2 + 1)):
                            if abs(m3) > l3: continue
                            cS[m1+_j,m2+_j] = cS[m1+_j,m2+_j] + l2S[l3]*ylm[ l3*(l3+1)+m3] *\
                                  gc[l3ind] * (-1.0)**((3*l1+l2+l3)//2+m2)
                self.c2r_(l1, l2, self.jmx, cS, rS, cmat)
                oo2co[s1:f1, s2:f2] = rS[-l1 + _j:l1 + _j + 1,
                                         -l2 + _j:l2 + _j + 1]
    #sys.exit()

    oo2co = oo2co * (4 * np.pi)**2 * self.interp_pp.dg_jt
    return oo2co