예제 #1
0
def comp_coulomb_pack(sv, ao_log=None, funct=coulomb_am, dtype=np.float64, **kw):
  """
    Computes the matrix elements given by funct, for instance coulomb interaction
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
      ao_log : description of functions (either orbitals or product basis functions)
    Returns:
      matrix elements for the whole system in packed form (lower triangular part)
  """
  from pyscf.nao.m_ao_matelem import ao_matelem_c
  from pyscf.nao.m_pack2den import cp_block_pack_u
  
  aome = ao_matelem_c(sv.ao_log.rr, sv.ao_log.pp)
  me = ao_matelem_c(sv.ao_log) if ao_log is None else aome.init_one_set(ao_log)
  atom2s = np.zeros((sv.natm+1), dtype=np.int64)
  for atom,sp in enumerate(sv.atom2sp): atom2s[atom+1]=atom2s[atom]+me.ao1.sp2norbs[sp]
  norbs = atom2s[-1]

  res = np.zeros(norbs*(norbs+1)//2, dtype=dtype)

  for atom1,[sp1,rv1,s1,f1] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
    #print("atom1 = {0}, rv1 = {1}".format(atom1, rv1))
    for atom2,[sp2,rv2,s2,f2] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
      if atom2>atom1: continue # skip 
      oo2f = funct(me,sp1,rv1,sp2,rv2, **kw)
      cp_block_pack_u(oo2f, s1,f1,s2,f2, res)

  return res, norbs
예제 #2
0
def overlap_lil(sv, ao_log=None, funct=overlap_ni,**kvargs):
  """
  Computes the overlap matrix and returns it in List of Lists format (easy to index)
  Args:
  sv : (System Variables), this must have arrays of coordinates and species, etc
  Returns:
  overlap (real-space overlap) for the whole system
  """
  from pyscf.nao.m_ao_matelem import ao_matelem_c
  from scipy.sparse import lil_matrix
  from numpy import array, int64, zeros

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

  n = atom2s[-1]
  lil_mat = lil_matrix((n,n))

  for atom1,[sp1,rv1,s1,f1] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
    for atom2,[sp2,rv2,s2,f2] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
      if (sp2rcut[sp1]+sp2rcut[sp2])**2<=sum((rv1-rv2)**2) : continue
      lil_mat[s1:f1,s2:f2] = funct(me,sp1,rv1,sp2,rv2,**kvargs)

  return lil_mat
예제 #3
0
def vxc_lil(sv, dm, xc_code, deriv, ao_log=None, dtype=float64, **kvargs):
    """
    Computes the exchange-correlation matrix elements
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      vxc,exc
  """
    from pyscf.nao.m_xc_scalar_ni import xc_scalar_ni
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from scipy.sparse import lil_matrix

    aome = ao_matelem_c(sv.ao_log.rr, sv.ao_log.pp, sv, dm)
    me = aome.init_one_set(
        sv.ao_log) if ao_log is None else aome.init_one_set(ao_log)
    atom2s = zeros((sv.natm + 1), dtype=int64)
    for atom, sp in enumerate(sv.atom2sp):
        atom2s[atom + 1] = atom2s[atom] + me.ao1.sp2norbs[sp]
    sp2rcut = array([max(mu2rcut) for mu2rcut in me.ao1.sp_mu2rcut])

    lil = lil_matrix((atom2s[-1], atom2s[-1]), dtype=dtype)

    for atom1, [sp1, rv1, s1, f1] in enumerate(
            zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            if (sp2rcut[sp1] + sp2rcut[sp2])**2 <= sum((rv1 - rv2)**2):
                continue
            lil[s1:f1, s2:f2] = xc_scalar_ni(me, sp1, rv1, sp2, rv2, xc_code,
                                             deriv, **kvargs)

    return lil
예제 #4
0
def overlap_lil(sv, ao_log=None, funct=overlap_ni,**kvargs):
  """
  Computes the overlap matrix and returns it in List of Lists format (easy to index)
  Args:
  sv : (System Variables), this must have arrays of coordinates and species, etc
  Returns:
  overlap (real-space overlap) for the whole system
  """
  from pyscf.nao.m_ao_matelem import ao_matelem_c
  from scipy.sparse import lil_matrix
  from numpy import array, int64, zeros

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

  n = atom2s[-1]
  lil_mat = lil_matrix((n,n))

  for atom1,[sp1,rv1,s1,f1] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
    for atom2,[sp2,rv2,s2,f2] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
      if (sp2rcut[sp1]+sp2rcut[sp2])**2<=sum((rv1-rv2)**2) : continue
      lil_mat[s1:f1,s2:f2] = funct(me,sp1,rv1,sp2,rv2,**kvargs)

  return lil_mat
예제 #5
0
def comp_coulomb_den(sv, ao_log=None, funct=coulomb_am, dtype=np.float64, **kvargs):
  """
    Computes the matrix elements given by funct, for instance coulomb interaction
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      matrix elements (real-space overlap) for the whole system
  """
  from pyscf.nao.m_ao_matelem import ao_matelem_c
  
  aome = ao_matelem_c(sv.ao_log.rr, sv.ao_log.pp)
  me = aome.init_one_set(sv.ao_log) if ao_log is None else aome.init_one_set(ao_log)
  atom2s = np.zeros((sv.natm+1), dtype=np.int32)
  for atom,sp in enumerate(sv.atom2sp): atom2s[atom+1]=atom2s[atom]+me.ao1.sp2norbs[sp]
  norbs = atom2s[-1]

  # dim triangular matrix: n*(n+1)/2
  res = np.zeros((norbs,norbs), dtype=dtype)

  for atom1,[sp1,rv1,s1,f1] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
    for atom2,[sp2,rv2,s2,f2] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
      oo2f = funct(me,sp1,rv1,sp2,rv2,**kvargs)
      res[s1:f1,s2:f2] = oo2f[:,:]

  #np.savetxt("kernel_pyscf_dens.txt", res)
  #print("sum(kernel) = ", np.sum(abs(res)))
  #import sys
  #sys.exit()

  return res
예제 #6
0
def comp_coulomb_den(sv,
                     ao_log=None,
                     funct=coulomb_am,
                     dtype=np.float64,
                     **kvargs):
    """
    Computes the matrix elements given by funct, for instance coulomb interaction
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      matrix elements (real-space overlap) for the whole system
  """
    from pyscf.nao.m_ao_matelem import ao_matelem_c

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

    # dim triangular matrix: n*(n+1)/2
    res = np.zeros((norbs, norbs), dtype=dtype)

    for atom1, [sp1, rv1, s1, f1] in enumerate(
            zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            oo2f = funct(me, sp1, rv1, sp2, rv2, **kvargs)
            res[s1:f1, s2:f2] = oo2f[:, :]

    return res
예제 #7
0
def comp_coulomb_pack(sv,
                      ao_log=None,
                      funct=coulomb_am,
                      dtype=np.float64,
                      **kvargs):
    """
    Computes the matrix elements given by funct, for instance coulomb interaction
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
      ao_log : description of functions (either orbitals or product basis functions)
    Returns:
      matrix elements (real-space overlap) for the whole system
  """
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from pyscf.nao.m_pack2den import triu_indices

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

    res = np.zeros(norbs * (norbs + 1) // 2, dtype=dtype)
    ind = triu_indices(norbs)

    for atom1, [sp1, rv1, s1, f1] in enumerate(
            zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            #if atom2>atom1: continue # skip
            oo2f = funct(me, sp1, rv1, sp2, rv2, **kvargs)
            if use_numba:
                fill_triu(oo2f, ind, res, s1, f1, s2, f2)
            else:
                for i1 in range(s1, f1):
                    for i2 in range(s2, f2):
                        if ind[i1, i2] >= 0:
                            res[ind[i1, i2]] = oo2f[i1 - s1, i2 - s2]

    return res, norbs
예제 #8
0
def vxc_pack(self, **kw):
  """
    Computes the exchange-correlation matrix elements packed version (upper triangular)
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      vxc,exc
  """
  from pyscf.nao.m_xc_scalar_ni import xc_scalar_ni
  from pyscf.nao.m_ao_matelem import ao_matelem_c

  #sv, dm, xc_code, deriv, kernel=None, ao_log=None, dtype=float64, **kvargs
  sv = self
  dm = kw['dm'] if 'dm' in kw else self.make_rdm1()
  kernel = kw['kernel'] if 'kernel' in kw else None
  ao_log = kw['ao_log'] if 'ao_log' in kw else self.ao_log
  (xc_code,iskw) = (kw['xc_code'],True) if 'xc_code' in kw else (self.xc_code,False)
  dtype = kw['dtype'] if 'dtype' in kw else float64

  aome = ao_matelem_c(ao_log.rr, ao_log.pp, sv, dm)
  me = aome.init_one_set(ao_log)
  atom2s = zeros((sv.natm+1), dtype=int64)
  for atom,sp in enumerate(sv.atom2sp): atom2s[atom+1]=atom2s[atom]+me.ao1.sp2norbs[sp]
  sp2rcut = array([max(mu2rcut) for mu2rcut in me.ao1.sp_mu2rcut])
  norbs = atom2s[-1]

  #ind = triu_indices(norbs)
  if kernel is None: kernel = zeros(norbs*(norbs+1)//2, dtype=dtype)

  if kernel.size != int(norbs*(norbs+1)//2):
    print('kernel.size        ', kernel.size)
    print('norbs*(norbs+1)//2 ', int(norbs*(norbs+1)//2))
    raise ValueError("wrong dimension for kernel")
    

  for atom1,[sp1,rv1,s1,f1] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
    for atom2,[sp2,rv2,s2,f2] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
      if atom2>atom1: continue
      if (sp2rcut[sp1]+sp2rcut[sp2])**2<=sum((rv1-rv2)**2) : continue
      
      xc = xc_scalar_ni(me,sp1,rv1,sp2,rv2,**kw) if iskw else xc_scalar_ni(me,sp1,rv1,sp2,rv2,xc_code=xc_code,**kw)
      
      if use_numba:
          fill_triu_v2(xc, kernel, s1, f1, s2, f2, norbs, add=True)
      else:
          for i1 in range(s1,f1):
            for i2 in range(s2, min(i1+1, f2)):
                ind = 0
                if i2 > 0:
                    for beta in range(1, i2+1):
                        ind += norbs -beta
                ind += i1
                kernel[ind] += xc[i1-s1,i2-s2] 
  return kernel
예제 #9
0
def comp_coulomb_pack(sv,
                      ao_log=None,
                      funct=coulomb_am,
                      dtype=np.float64,
                      **kvargs):
    """
    Computes the matrix elements given by funct, for instance coulomb interaction
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
      ao_log : description of functions (either orbitals or product basis functions)
    Returns:
      matrix elements for the whole system in packed form (lower triangular part)
  """
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from pyscf.nao.m_pack2den import ij2pack_l

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

    res = np.zeros(norbs * (norbs + 1) // 2, dtype=dtype)

    for atom1, [sp1, rv1, s1, f1] in enumerate(
            zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            if atom2 > atom1: continue  # skip
            oo2f = funct(me, sp1, rv1, sp2, rv2, **kvargs)
            if use_numba:
                fill_triu_v2(oo2f, res, s1, f1, s2, f2, norbs)
            else:
                for i1 in range(s1, f1):
                    for i2 in range(s2, min(i1 + 1, f2)):
                        res[ij2pack_l(i1, i2, norbs)] = oo2f[i1 - s1, i2 - s2]

    #print("sum kernel: ", np.sum(abs(res)))
    return res, norbs
예제 #10
0
파일: m_vxc_pack.py 프로젝트: zzy2014/pyscf
def vxc_pack(self, **kw):
    """
    Computes the exchange-correlation matrix elements packed version (upper triangular)
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      vxc,exc
  """
    from pyscf.nao.m_xc_scalar_ni import xc_scalar_ni
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from pyscf.nao.m_pack2den import cp_block_pack_u, pack2den_u

    #sv, dm, xc_code, deriv, kernel=None, ao_log=None, dtype=float64, **kvargs
    sv = self
    dm = kw['dm'] if 'dm' in kw else self.make_rdm1()
    ao_log = kw['ao_log'] if 'ao_log' in kw else self.ao_log
    xc_code = kw['xc_code'] if 'xc_code' in kw else self.xc_code
    kw.pop('xc_code', None)
    dtype = kw['dtype'] if 'dtype' in kw else self.dtype

    aome = ao_matelem_c(ao_log.rr, ao_log.pp, sv, dm)
    me = aome.init_one_set(ao_log)
    atom2s = zeros((sv.natm + 1), dtype=int64)
    for atom, sp in enumerate(sv.atom2sp):
        atom2s[atom + 1] = atom2s[atom] + me.ao1.sp2norbs[sp]
    sp2rcut = array([max(mu2rcut) for mu2rcut in me.ao1.sp_mu2rcut])
    norbs = atom2s[-1]

    nq, npk = (self.nspin - 1) * 2 + 1, norbs * (norbs + 1) // 2
    kernel = kw['kernel'].reshape((nq, npk)) if 'kernel' in kw else zeros(
        (nq, npk), dtype=dtype)

    for atom1, [sp1, rv1, s1, f1] in enumerate(
            zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            if atom2 > atom1: continue
            if (sp2rcut[sp1] + sp2rcut[sp2])**2 <= sum((rv1 - rv2)**2):
                continue

            iab2block = xc_scalar_ni(me,
                                     sp1,
                                     rv1,
                                     sp2,
                                     rv2,
                                     xc_code=xc_code,
                                     **kw)
            for i, ab2v in enumerate(iab2block):
                cp_block_pack_u(ab2v, s1, f1, s2, f2, kernel[i], add=True)

    return kernel
예제 #11
0
def comp_coulomb_pack(sv, ao_log=None, funct=coulomb_am, dtype=np.float64, **kvargs):
  """
    Computes the matrix elements given by funct, for instance coulomb interaction
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
      ao_log : description of functions (either orbitals or product basis functions)
    Returns:
      matrix elements for the whole system in packed form (lower triangular part)
  """
  from pyscf.nao.m_ao_matelem import ao_matelem_c
  from pyscf.nao.m_pack2den import ij2pack_l
  
  aome = ao_matelem_c(sv.ao_log.rr, sv.ao_log.pp)
  me = ao_matelem_c(sv.ao_log) if ao_log is None else aome.init_one_set(ao_log)
  atom2s = np.zeros((sv.natm+1), dtype=np.int64)
  for atom,sp in enumerate(sv.atom2sp): atom2s[atom+1]=atom2s[atom]+me.ao1.sp2norbs[sp]
  norbs = atom2s[-1]

  res = np.zeros(norbs*(norbs+1)//2, dtype=dtype)

  for atom1,[sp1,rv1,s1,f1] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
    #print("atom1 = {0}, rv1 = {1}".format(atom1, rv1))
    for atom2,[sp2,rv2,s2,f2] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
      if atom2>atom1: continue # skip 
      oo2f = funct(me,sp1,rv1,sp2,rv2, **kvargs)
      if use_numba:
          fill_triu_v2(oo2f, res, s1, f1, s2, f2, norbs)
      else:
          for i1 in range(s1,f1):
            for i2 in range(s2, min(i1+1, f2)):
              res[ij2pack_l(i1,i2,norbs)] = oo2f[i1-s1,i2-s2]

  #print("number call = ", count)
  #print("sum kernel: {0:.6f}".format(np.sum(abs(res))))
  #np.savetxt("kernel_pyscf.txt", res)
  #import sys
  #sys.exit()
  return res, norbs
예제 #12
0
def dipole_coo(sv, ao_log=None, funct=dipole_ni, **kvargs):
    """
    Computes the dipole matrix and returns it in coo format (simplest sparse format to construct)
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      overlap (real-space overlap) for the whole system
  """
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from scipy.sparse import coo_matrix
    from numpy import array, int64, zeros

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

    nnz = 0
    for sp1, rv1 in zip(sv.atom2sp, sv.atom2coord):
        n1, rc1 = me.ao1.sp2norbs[sp1], sp2rcut[sp1]
        for sp2, rv2 in zip(sv.atom2sp, sv.atom2coord):
            if (rc1 + sp2rcut[sp2])**2 > ((rv1 - rv2)**2).sum():
                nnz = nnz + n1 * me.ao1.sp2norbs[sp2]

    irow, icol, data = zeros(nnz, dtype=int64), zeros(nnz, dtype=int64), zeros(
        (3, nnz))  # Start to construct three coo matrices

    inz = -1
    for atom1, [sp1, rv1, s1, f1] in enumerate(
            zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            if (sp2rcut[sp1] + sp2rcut[sp2])**2 <= sum((rv1 - rv2)**2):
                continue
            dd = funct(me, sp1, rv1, sp2, rv2, **kvargs)
            for o1 in range(s1, f1):
                for o2 in range(s2, f2):
                    inz = inz + 1
                    irow[inz], icol[inz], data[:, inz] = o1, o2, dd[:, o1 - s1,
                                                                    o2 - s2]

    norbs = atom2s[-1]
    sh = (norbs, norbs)
    rc = (irow, icol)
    return coo_matrix((data[0], rc), shape=sh), coo_matrix(
        (data[1], rc), shape=sh), coo_matrix((data[2], rc), shape=sh)
예제 #13
0
def vxc_lil(self, **kw):
    """
    Computes the exchange-correlation matrix elements
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      fxc,vxc,exc
  """
    from pyscf.nao.m_xc_scalar_ni import xc_scalar_ni
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from scipy.sparse import lil_matrix

    #dm, xc_code, deriv, ao_log=None, dtype=float64, **kvargs

    dm = kw['dm'] if 'dm' in kw else self.make_rdm1()
    kernel = kw['kernel'] if 'kernel' in kw else None
    ao_log = kw['ao_log'] if 'ao_log' in kw else self.ao_log
    xc_code = kw['xc_code'] if 'xc_code' in kw else self.xc_code
    kw.pop('xc_code', None)
    dtype = kw['dtype'] if 'dtype' in kw else self.dtype

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

    lil = [
        lil_matrix((atom2s[-1], atom2s[-1]), dtype=dtype)
        for i in range((self.nspin - 1) * 2 + 1)
    ]

    for atom1, [sp1, rv1, s1, f1] in enumerate(
            zip(self.atom2sp, self.atom2coord, atom2s, atom2s[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(self.atom2sp, self.atom2coord, atom2s, atom2s[1:])):
            blk = xc_scalar_ni(me, sp1, rv1, sp2, rv2, xc_code=xc_code, **kw)
            for i, b in enumerate(blk):
                lil[i][s1:f1, s2:f2] = b[:, :]

    return lil
예제 #14
0
def dipole_coo(sv, ao_log=None, funct=dipole_ni, **kvargs):
  """
    Computes the dipole matrix and returns it in coo format (simplest sparse format to construct)
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      overlap (real-space overlap) for the whole system
  """
  from pyscf.nao.m_ao_matelem import ao_matelem_c
  from scipy.sparse import coo_matrix
  from numpy import array, int64, zeros

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

  nnz = 0
  for sp1,rv1 in zip(sv.atom2sp,sv.atom2coord):
    n1,rc1 = me.ao1.sp2norbs[sp1],sp2rcut[sp1]
    for sp2,rv2 in zip(sv.atom2sp,sv.atom2coord):
      if (rc1+sp2rcut[sp2])**2>((rv1-rv2)**2).sum() : nnz = nnz + n1*me.ao1.sp2norbs[sp2]

  irow,icol,data = zeros(nnz, dtype=int64),zeros(nnz, dtype=int64),zeros((3,nnz)) # Start to construct three coo matrices
  
  inz=-1
  for atom1,[sp1,rv1,s1,f1] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
    for atom2,[sp2,rv2,s2,f2] in enumerate(zip(sv.atom2sp,sv.atom2coord,atom2s,atom2s[1:])):
      if (sp2rcut[sp1]+sp2rcut[sp2])**2<=sum((rv1-rv2)**2) : continue
      dd = funct(me,sp1,rv1,sp2,rv2,**kvargs)
      for o1 in range(s1,f1):
        for o2 in range(s2,f2):
          inz = inz+1
          irow[inz],icol[inz],data[:,inz] = o1,o2,dd[:,o1-s1,o2-s2]

  norbs = atom2s[-1]
  sh = (norbs,norbs)
  rc = (irow,icol)
  return coo_matrix((data[0], rc), shape=sh),coo_matrix((data[1], rc), shape=sh),coo_matrix((data[2],rc), shape=sh)
예제 #15
0
                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


if __name__ == '__main__':
    from pyscf.nao.m_system_vars import system_vars_c
    from pyscf.nao.m_ao_matelem import ao_matelem_c

    sv = system_vars_c("siesta")
    ra = np.array([0.0, 0.1, 0.2])
    rb = np.array([0.0, 0.1, 0.0])
    coulo = ao_matelem_c(sv.ao_log).coulomb_am(me, 0, ra, 0, rb)
예제 #16
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
예제 #17
0
      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


if __name__ == '__main__':
  from pyscf.nao.m_system_vars import system_vars_c
  from pyscf.nao.m_prod_log import prod_log_c
  from pyscf.nao.m_ao_matelem import ao_matelem_c
  
  sv = system_vars_c("siesta")
  ra = np.array([0.0, 0.1, 0.2])
  rb = np.array([0.0, 0.1, 0.0])
  coulo = ao_matelem_c(sv.ao_log).coulomb_am(me, 0, ra, 0, rb)
예제 #18
0
def overlap_coo(sv, ao_log=None, funct=overlap_ni, ao_log2=None, **kw):
    """
  Computes the overlap matrix and returns it in coo format (simplest sparse format to construct)
  Args:
    sv : (System Variables), this must have arrays of coordinates and species, etc
  Returns:
    overlap (real-space overlap) for the whole system
  """
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from scipy.sparse import coo_matrix
    from numpy import array, float64, int64, zeros

    aome = ao_matelem_c(sv.ao_log.rr, sv.ao_log.pp)

    if ao_log is None and ao_log2 is None:
        me = aome.init_one_set(sv.ao_log)
    elif ao_log is not None and ao_log2 is None:
        me = aome.init_one_set(ao_log)
    elif ao_log is None and ao_log2 is not None:
        me = aome.init_one_set(ao_log2)
    else:
        me = aome.init_two_sets(ao_log, ao_log2)

    a2s1 = zeros((sv.natm + 1), dtype=int)
    a2s2 = zeros((sv.natm + 1), dtype=int)

    for atom, sp in enumerate(sv.atom2sp):
        a2s1[atom + 1] = a2s1[atom] + me.ao1.sp2norbs[sp]
        a2s2[atom + 1] = a2s2[atom] + me.ao2.sp2norbs[sp]

    sp2rcut1 = array([max(mu2rcut) for mu2rcut in me.ao1.sp_mu2rcut])
    sp2rcut2 = array([max(mu2rcut) for mu2rcut in me.ao2.sp_mu2rcut])

    nnz = 0
    for sp1, rv1 in zip(sv.atom2sp, sv.atom2coord):
        n1, rc1 = me.ao1.sp2norbs[sp1], sp2rcut1[sp1]
        for sp2, rv2 in zip(sv.atom2sp, sv.atom2coord):
            n2, rc2 = me.ao2.sp2norbs[sp2], sp2rcut2[sp2]
            if (rc1 + rc2)**2 > ((rv1 - rv2)**2).sum(): nnz = nnz + n1 * n2

    irow, icol, data = zeros(nnz, dtype=int64), zeros(nnz, dtype=int64), zeros(
        nnz)  # Start to construct coo matrix

    inz = -1
    for atom1, [sp1, rv1, s1,
                f1] in enumerate(zip(sv.atom2sp, sv.atom2coord, a2s1,
                                     a2s1[1:])):
        for atom2, [sp2, rv2, s2, f2] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, a2s2, a2s2[1:])):
            if (sp2rcut1[sp1] + sp2rcut2[sp2])**2 <= sum((rv1 - rv2)**2):
                continue
            oo = funct(me, sp1, rv1, sp2, rv2, **kw)
            for o1 in range(s1, f1):
                for o2 in range(s2, f2):
                    inz = inz + 1
                    irow[inz], icol[inz], data[inz] = o1, o2, oo[o1 - s1,
                                                                 o2 - s2]

    norbs1 = a2s1[-1]
    norbs2 = a2s2[-1]
    return coo_matrix((data, (irow, icol)), shape=(norbs1, norbs2))
예제 #19
0
def vxc_pack(sv,
             dm,
             xc_code,
             deriv,
             kernel=None,
             ao_log=None,
             dtype=float64,
             **kvargs):
    """
    Computes the exchange-correlation matrix elements packed version (upper triangular)
    Args:
      sv : (System Variables), this must have arrays of coordinates and species, etc
    Returns:
      vxc,exc
  """
    from pyscf.nao.m_xc_scalar_ni import xc_scalar_ni
    from pyscf.nao.m_ao_matelem import ao_matelem_c
    from pyscf.nao.m_pack2den import triu_indices

    aome = ao_matelem_c(sv.ao_log.rr, sv.ao_log.pp, sv, dm)
    me = aome.init_one_set(
        sv.ao_log) if ao_log is None else aome.init_one_set(ao_log)
    atom2s = zeros((sv.natm + 1), dtype=int64)
    for atom, sp in enumerate(sv.atom2sp):
        atom2s[atom + 1] = atom2s[atom] + me.ao1.sp2norbs[sp]
    sp2rcut = array([max(mu2rcut) for mu2rcut in me.ao1.sp_mu2rcut])
    norbs = atom2s[-1]

    ind = triu_indices(norbs)
    if kernel is None:
        kernel = zeros(norbs * (norbs + 1) // 2, dtype=dtype)
        for atom1, [sp1, rv1, s1, f1] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            for atom2, [sp2, rv2, s2, f2] in enumerate(
                    zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
                if (sp2rcut[sp1] + sp2rcut[sp2])**2 <= sum((rv1 - rv2)**2):
                    continue
                xc = xc_scalar_ni(me, sp1, rv1, sp2, rv2, xc_code, deriv,
                                  **kvargs)
                if use_numba:
                    fill_triu(xc, ind, kernel, s1, f1, s2, f2)
                else:
                    for i1 in range(s1, f1):
                        for i2 in range(s2, f2):
                            if ind[i1, i2] >= 0:
                                kernel[ind[i1, i2]] = xc[i1 - s1, i2 - s2]
        return kernel

    else:
        if kernel.size != int(norbs * (norbs + 1) // 2):
            raise ValueError("wrong dimension for kernel")

        for atom1, [sp1, rv1, s1, f1] in enumerate(
                zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
            for atom2, [sp2, rv2, s2, f2] in enumerate(
                    zip(sv.atom2sp, sv.atom2coord, atom2s, atom2s[1:])):
                if (sp2rcut[sp1] + sp2rcut[sp2])**2 <= sum((rv1 - rv2)**2):
                    continue
                xc = xc_scalar_ni(me, sp1, rv1, sp2, rv2, xc_code, deriv,
                                  **kvargs)
                if use_numba:
                    fill_triu(xc, ind, kernel, s1, f1, s2, f2, add=True)
                else:
                    for i1 in range(s1, f1):
                        for i2 in range(s2, f2):
                            if ind[i1, i2] >= 0:
                                kernel[ind[i1, i2]] += xc[i1 - s1, i2 - s2]