Exemple #1
0
    def init_mo_from_pyscf(self, **kw):
        """ Initializing from a previous pySCF mean-field calc. """
        from pyscf.nao.m_fermi_energy import fermi_energy as comput_fermi_energy
        from pyscf.nao.m_color import color as tc
        self.telec = kw['telec'] if 'telec' in kw else 0.0000317  # 10K
        self.mf = mf = kw['mf']
        self.xc_code = mf.xc if hasattr(mf, 'xc') else 'HF'
        self.k2xyzw = np.array([[0.0, 0.0, 0.0, 1.0]])

        self.mo_energy = np.asarray(mf.mo_energy)
        self.nspin = self.mo_energy.ndim
        assert self.nspin in [1, 2]
        nspin, n = self.nspin, self.norbs
        self.mo_energy = require(self.mo_energy.reshape((1, nspin, n)),
                                 requirements='CW')
        self.mo_occ = require(mf.mo_occ.reshape((1, nspin, n)),
                              requirements='CW')
        self.mo_coeff = require(zeros((1, nspin, n, n, 1), dtype=self.dtype),
                                requirements='CW')
        conv = conv_yzx2xyz_c(kw['gto'])
        aaux = np.asarray(mf.mo_coeff).reshape((nspin, n, n))
        for s in range(nspin):
            self.mo_coeff[0, s, :, :,
                          0] = conv.conv_yzx2xyz_1d(aaux[s],
                                                    conv.m_xyz2m_yzx).T

        self.nelec = kw['nelec'] if 'nelec' in kw else np.array(
            [int(s2o.sum()) for s2o in self.mo_occ[0]])
        fermi = comput_fermi_energy(self.mo_energy, sum(self.nelec),
                                    self.telec)
        self.fermi_energy = kw[
            'fermi_energy'] if 'fermi_energy' in kw else fermi
 def test_overlap_gto_vs_nao(self):
     """ Test computation of overlaps computed between NAOs against overlaps computed between GTOs"""
     from pyscf.nao import conv_yzx2xyz_c, overlap_am
     sv = system_vars_c().init_pyscf_gto(mol)
     oref = conv_yzx2xyz_c(mol).conv_yzx2xyz_2d(
         mol.intor_symmetric('cint1e_ovlp_sph'), direction='pyscf2nao')
     over = sv.overlap_coo(funct=overlap_am).toarray()
     self.assertTrue(abs(over - oref).sum() < 5e-9)
Exemple #3
0
    def init_mo_from_pyscf(self, **kw):
        """ Initializing from a previous pySCF mean-field calc. """
        from pyscf.nao.m_fermi_energy import fermi_energy as comput_fermi_energy
        from pyscf.nao.m_color import color as tc
        self.telec = kw['telec'] if 'telec' in kw else 0.0000317  # 10K
        self.mf = mf = kw['mf']
        if type(mf.mo_energy) == tuple:
            self.nspin = len(mf.mo_energy)
        elif type(mf.mo_energy) == np.ndarray:
            self.nspin = 1
            assert mf.mo_coeff.shape[0] == mf.mo_coeff.shape[1]
            assert len(mf.mo_coeff.shape) == 2
        else:
            raise RuntimeError(tc.RED + 'unknown type of mo_energy %s %s' %
                               (type(mf.mo_energy), tc.ENDC))

        self.xc_code = mf.xc if hasattr(mf, 'xc') else 'HF'
        self.k2xyzw = np.array([[0.0, 0.0, 0.0, 1.0]])
        nspin, n = self.nspin, self.norbs
        self.mo_coeff = require(zeros((1, nspin, n, n, 1), dtype=self.dtype),
                                requirements='CW')
        self.mo_energy = require(zeros((1, nspin, n), dtype=self.dtype),
                                 requirements='CW')
        self.mo_occ = require(zeros((1, nspin, n), dtype=self.dtype),
                              requirements='CW')

        conv = conv_yzx2xyz_c(kw['gto'])
        if nspin == 1:
            self.mo_coeff[0, 0, :, :,
                          0] = conv.conv_yzx2xyz_1d(self.mf.mo_coeff,
                                                    conv.m_xyz2m_yzx).T
            self.mo_energy[0, 0, :] = self.mf.mo_energy
            self.mo_occ[0, 0, :] = self.mf.mo_occ
        else:
            for s in range(self.nspin):
                self.mo_coeff[0, s, :, :, 0] = conv.conv_yzx2xyz_1d(
                    self.mf.mo_coeff[s], conv.m_xyz2m_yzx).T
                self.mo_energy[0, s, :] = self.mf.mo_energy[s]
            self.mo_occ[0, 0:self.nspin, :] = self.mf.mo_occ

        self.nelec = kw['nelec'] if 'nelec' in kw else np.array(
            [int(s2o.sum()) for s2o in self.mo_occ[0]])
        fermi = comput_fermi_energy(self.mo_energy, sum(self.nelec),
                                    self.telec)
        self.fermi_energy = kw[
            'fermi_energy'] if 'fermi_energy' in kw else fermi
Exemple #4
0
  def init_mo_from_pyscf(self, **kw):
    """ Initializing from a previous pySCF mean-field calc. """
    from pyscf.nao.m_fermi_energy import fermi_energy as comput_fermi_energy
    from pyscf.nao.m_color import color as tc
    self.telec = kw['telec'] if 'telec' in kw else 0.0000317 # 10K
    self.mf = mf = kw['mf']
    if type(mf.mo_energy) == tuple: 
      self.nspin = len(mf.mo_energy)
    elif type(mf.mo_energy) == np.ndarray:
      self.nspin = 1
      assert mf.mo_coeff.shape[0]==mf.mo_coeff.shape[1]
      assert len(mf.mo_coeff.shape)==2
    else:
      raise RuntimeError(tc.RED+'unknown type of mo_energy %s %s' % (type(mf.mo_energy), tc.ENDC))
    
    self.xc_code = mf.xc if hasattr(mf, 'xc') else 'HF'
    self.k2xyzw = np.array([[0.0,0.0,0.0,1.0]])
    nspin,n=self.nspin,self.norbs
    self.mo_coeff =  require(zeros((1,nspin,n,n,1), dtype=self.dtype), requirements='CW')
    self.mo_energy = require(zeros((1,nspin,n), dtype=self.dtype), requirements='CW')
    self.mo_occ =    require(zeros((1,nspin,n),dtype=self.dtype), requirements='CW')

    conv = conv_yzx2xyz_c(kw['gto'])
    if nspin==1 :
      self.mo_coeff[0,0,:,:,0] = conv.conv_yzx2xyz_1d(self.mf.mo_coeff, conv.m_xyz2m_yzx).T
      self.mo_energy[0,0,:] = self.mf.mo_energy
      self.mo_occ[0,0,:] = self.mf.mo_occ
    else:
      for s in range(self.nspin):
        self.mo_coeff[0,s,:,:,0] = conv.conv_yzx2xyz_1d(self.mf.mo_coeff[s], conv.m_xyz2m_yzx).T
        self.mo_energy[0,s,:] = self.mf.mo_energy[s]
      self.mo_occ[0,0:self.nspin,:] = self.mf.mo_occ
      
    self.nelec = kw['nelec'] if 'nelec' in kw else np.array([int(s2o.sum()) for s2o in self.mo_occ[0]])
    fermi = comput_fermi_energy(self.mo_energy, sum(self.nelec), self.telec)
    self.fermi_energy = kw['fermi_energy'] if 'fermi_energy' in kw else fermi
Exemple #5
0
def pb_ae(self, sv, tol_loc=1e-5, tol_biloc=1e-6, ac_rcut_ratio=1.0):
    """ It should work with GTOs as well."""
    from pyscf.nao import coulomb_am, get_atom2bas_s, conv_yzx2xyz_c, prod_log_c, ls_part_centers, comp_coulomb_den
    from pyscf.nao.m_overlap_coo import overlap_coo
    from pyscf.nao.m_prod_biloc import prod_biloc_c
    from scipy.sparse import csr_matrix
    from pyscf import gto

    self.sv = sv
    self.tol_loc = tol_loc
    self.tol_biloc = tol_biloc
    self.ac_rcut_ratio = ac_rcut_ratio
    self.ac_rcut = ac_rcut_ratio * max(sv.ao_log.sp2rcut)

    self.prod_log = prod_log_c().init_prod_log_dp(
        sv.ao_log, tol_loc)  # local basis (for each specie)
    self.hkernel_csr = csr_matrix(
        overlap_coo(sv, self.prod_log,
                    coulomb_am))  # compute local part of Coulomb interaction
    self.c2s = zeros(
        (sv.natm + 1), dtype=int64
    )  # global product Center (atom) -> start in case of atom-centered basis
    for gc, sp in enumerate(sv.atom2sp):
        self.c2s[gc + 1] = self.c2s[gc] + self.prod_log.sp2norbs[sp]  #
    c2s = self.c2s  # What is the meaning of this copy ?? ... This is a pointer to self.c2s

    self.bp2info = [
    ]  # going to be some information including indices of atoms, list of contributing centres, conversion coefficients

    for ia1, n1 in enumerate(sv.atom2s[1:] - sv.atom2s[0:-1]):
        for ia2, n2 in enumerate(sv.atom2s[ia1 + 2:] - sv.atom2s[ia1 + 1:-1]):
            ia2 += ia1 + 1
            mol2 = gto.Mole(atom=[sv._atom[ia1], sv._atom[ia2]],
                            basis=sv.basis,
                            unit='bohr').build()
            bs = get_atom2bas_s(mol2._bas)
            ss = (bs[0], bs[1], bs[1], bs[2], bs[0], bs[1], bs[1], bs[2])
            eri = mol2.intor('cint2e_sph',
                             shls_slice=ss).reshape(n1, n2, n1, n2)
            eri = conv_yzx2xyz_c(mol2).conv_yzx2xyz_4d(eri, 'pyscf2nao',
                                                       ss).reshape(
                                                           n1 * n2, n1 * n2)
            ee, xx = np.linalg.eigh(
                eri
            )  # This the simplest way. TODO: diag in each m-channel separately
            mu2d = [domi for domi, eva in enumerate(ee) if eva > tol_biloc
                    ]  # The choice of important linear combinations is here
            nprod = len(mu2d)
            if nprod < 1:
                continue  # Skip the rest of operations in case there is no large linear combinations.

            # add new vertex
            vrtx = zeros([nprod, n1, n2])
            for p, d in enumerate(mu2d):
                vrtx[p, :, :] = xx[:, d].reshape(n1, n2)

            #print(ia1,ia2,nprod,abs(einsum('pab,qab->pq', lambdx, lambdx).reshape(nprod,nprod)-np.identity(nprod)).sum())

            lc2c = ls_part_centers(
                sv, ia1, ia2, ac_rcut_ratio)  # list of participating centers
            lc2s = zeros(
                (len(lc2c) + 1), dtype=int64
            )  # local product center -> start for the current bilocal pair
            for lc, c in enumerate(lc2c):
                lc2s[lc + 1] = lc2s[lc] + self.prod_log.sp2norbs[sv.atom2sp[c]]

            npbp = lc2s[
                -1]  # size of the functions which will contribute to the given pair ia1,ia2
            hkernel_bp = np.zeros(
                (npbp,
                 npbp))  # this is local kernel for the current bilocal pair
            for lc1, c1 in enumerate(lc2c):
                for lc2, c2 in enumerate(lc2c):
                    for i1 in range(lc2s[lc1 + 1] - lc2s[lc1]):
                        for i2 in range(lc2s[lc2 + 1] - lc2s[lc2]):
                            hkernel_bp[i1 + lc2s[lc1], i2 + lc2s[
                                lc2]] = self.hkernel_csr[i1 + c2s[c1], i2 + c2s[
                                    c2]]  # element-by-element construction here
            inv_hk = np.linalg.inv(hkernel_bp)

            llp = np.zeros((npbp, nprod))
            for c, s, f in zip(lc2c, lc2s, lc2s[1:]):
                n3 = sv.atom2s[c + 1] - sv.atom2s[c]
                lcd = self.prod_log.sp2lambda[sv.atom2sp[c]]
                mol3 = gto.Mole(
                    atom=[sv._atom[ia1], sv._atom[ia2], sv._atom[c]],
                    basis=sv.basis,
                    unit='bohr',
                    spin=1).build()
                bs = get_atom2bas_s(mol3._bas)
                ss = (bs[2], bs[3], bs[2], bs[3], bs[0], bs[1], bs[1], bs[2])
                tci_ao = mol3.intor('cint2e_sph',
                                    shls_slice=ss).reshape(n3, n3, n1, n2)
                tci_ao = conv_yzx2xyz_c(mol3).conv_yzx2xyz_4d(
                    tci_ao, 'pyscf2nao', ss)
                lp = einsum('lcd,cdp->lp', lcd,
                            einsum('cdab,pab->cdp', tci_ao, vrtx))
                llp[s:f, :] = lp

            cc = einsum('ab,bc->ac', inv_hk, llp)
            pbiloc = prod_biloc_c(atoms=array([ia1, ia2]),
                                  vrtx=vrtx,
                                  cc2a=lc2c,
                                  cc2s=lc2s,
                                  cc=cc.T)

            self.bp2info.append(pbiloc)
            #print(ia1, ia2, len(mu2d), lc2c, hkernel_bp.sum(), inv_hk.sum())
    self.dpc2s, self.dpc2t, self.dpc2sp = self.init_c2s_domiprod(
    )  # dominant product's counting
    return self
Exemple #6
0
me = ao_matelem_c(prod_log)

errmx = 0
for ia1 in range(sv.natoms):
    for ia2 in range(sv.natoms):

        n1, n2 = [sv.atom2s[ia + 1] - sv.atom2s[ia] for ia in [ia1, ia2]]
        mol3 = gto.Mole_pure(atom=[sv._atom[ia1], sv._atom[ia2]],
                             basis=sv.basis,
                             unit='bohr').build()
        bs = get_atom2bas_s(mol3._bas)
        ss = (bs[0], bs[1], bs[0], bs[1], bs[1], bs[2], bs[1], bs[2])
        tci_ao = mol3.intor('cint2e_sph',
                            shls_slice=ss).reshape(n1, n1, n2, n2)
        tci_ao = conv_yzx2xyz_c(mol3).conv_yzx2xyz_4d(tci_ao, 'pyscf2nao', ss)

        sp1, sp2 = [sv.atom2sp[ia] for ia in [ia1, ia2]]
        R1, R2 = [sv.atom2coord[ia] for ia in [ia1, ia2]]
        pq2v = me.coulomb_am(sp1, R1, sp2, R2)
        tci_ni = np.einsum(
            'abq,qcd->abcd',
            np.einsum('pab,pq->abq', prod_log.sp2vertex[sp1], pq2v),
            prod_log.sp2vertex[sp2])
        print(ia1, ia2,
              abs(tci_ao - tci_ni).sum() / tci_ao.size,
              abs(tci_ao - tci_ni).max())
        errmx = max(errmx, abs(tci_ao - tci_ni).max())

assert (errmx < 3e-5)
# limitations under the License.

from __future__ import print_function, division
import unittest, numpy as np
from pyscf import gto
from pyscf.nao import system_vars_c, conv_yzx2xyz_c

mol = gto.M(
    verbose=1,
    atom='''
        O     0    0        0
        H     0    -0.757   0.587
        H     0    0.757    0.587''',
    basis='cc-pvdz',
)
conv = conv_yzx2xyz_c(mol)
sv = system_vars_c().init_pyscf_gto(mol)


class KnowValues(unittest.TestCase):
    def test_gto2sv(self):
        """ Test transformation of the radial orbitals from GTO to NAO type"""
        self.assertEqual((sv.natoms, sv.norbs, len(sv.ao_log.psi_log)),
                         (3, 24, 2))
        rr = sv.ao_log.rr
        self.assertEqual(len(rr), 1024)
        dr = np.log(rr[1] / rr[0])
        for mu2ff in sv.ao_log.psi_log:
            for ff in mu2ff:
                norm = (ff**2 * sv.ao_log.rr**3).sum() * dr
                self.assertAlmostEqual(norm, 1.0)
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function, division
import unittest, numpy as np
from pyscf import gto, scf
from pyscf.nao import nao, scf as scf_nao, conv_yzx2xyz_c

mol = gto.M( verbose = 1,
    atom = '''
        H     0    0        0
        H     0    0.757    0.587''', basis = 'cc-pvdz',)
conv = conv_yzx2xyz_c(mol)
gto_hf = scf.RHF(mol)
gto_hf.kernel()
rdm1 = conv.conv_yzx2xyz_2d(gto_hf.make_rdm1())

class KnowValues(unittest.TestCase):

  def test_kmat_gto_vs_nao(self):
    """ Test computation of Fock exchange between NAOs against this computed between GTOs"""
    vh_gto,k_gto = gto_hf.get_jk()
    k_gto = conv.conv_yzx2xyz_2d(k_gto)
    mf = scf_nao(mf=gto_hf, gto=mol)
    k_nao = mf.get_k(dm=rdm1)
    self.assertTrue(abs(k_nao-k_gto).sum()/k_gto.size<2.5e-5)
    
  def test_overlap_gto_vs_nao(self):
Exemple #9
0
def pb_ae(self, sv, tol_loc=1e-5, tol_biloc=1e-6, ac_rcut_ratio=1.0):
  """ It should work with GTOs as well."""
  from pyscf.nao import coulomb_am, get_atom2bas_s, conv_yzx2xyz_c, prod_log_c, ls_part_centers, comp_coulomb_den
  from pyscf.nao.m_overlap_coo import overlap_coo
  from pyscf.nao.m_prod_biloc import prod_biloc_c
  from scipy.sparse import csr_matrix
  from pyscf import gto
    
  self.sv = sv
  self.tol_loc = tol_loc
  self.tol_biloc = tol_biloc
  self.ac_rcut_ratio = ac_rcut_ratio
  self.ac_rcut = ac_rcut_ratio*max(sv.ao_log.sp2rcut)
   
  self.prod_log = prod_log_c().init_prod_log_dp(sv.ao_log, tol_loc) # local basis (for each specie) 
  self.hkernel_csr  = csr_matrix(overlap_coo(sv, self.prod_log, coulomb_am)) # compute local part of Coulomb interaction
  self.c2s = zeros((sv.natm+1), dtype=int64) # global product Center (atom) -> start in case of atom-centered basis
  for gc,sp in enumerate(sv.atom2sp): self.c2s[gc+1]=self.c2s[gc]+self.prod_log.sp2norbs[sp] # 
  c2s = self.c2s      # What is the meaning of this copy ?? ... This is a pointer to self.c2s
   
  self.bp2info   = [] # going to be some information including indices of atoms, list of contributing centres, conversion coefficients
  
  for ia1,n1 in enumerate(sv.atom2s[1:]-sv.atom2s[0:-1]):
    for ia2,n2 in enumerate(sv.atom2s[ia1+2:]-sv.atom2s[ia1+1:-1]):
      ia2 += ia1+1
      mol2 = gto.Mole(atom=[sv._atom[ia1], sv._atom[ia2]], basis=sv.basis, unit='bohr').build()
      bs = get_atom2bas_s(mol2._bas)
      ss = (bs[0],bs[1], bs[1],bs[2], bs[0],bs[1], bs[1],bs[2])
      eri = mol2.intor('cint2e_sph', shls_slice=ss).reshape(n1,n2,n1,n2)
      eri = conv_yzx2xyz_c(mol2).conv_yzx2xyz_4d(eri, 'pyscf2nao', ss).reshape(n1*n2,n1*n2)
      ee,xx = np.linalg.eigh(eri)   # This the simplest way. TODO: diag in each m-channel separately
      mu2d = [domi for domi,eva in enumerate(ee) if eva>tol_biloc] # The choice of important linear combinations is here
      nprod=len(mu2d)
      if nprod<1: continue # Skip the rest of operations in case there is no large linear combinations.

      # add new vertex
      vrtx = zeros([nprod,n1,n2])
      for p,d in enumerate(mu2d): vrtx[p,:,:] = xx[:,d].reshape(n1,n2)
        
      #print(ia1,ia2,nprod,abs(einsum('pab,qab->pq', lambdx, lambdx).reshape(nprod,nprod)-np.identity(nprod)).sum())

      lc2c = ls_part_centers(sv, ia1, ia2, ac_rcut_ratio) # list of participating centers
      lc2s = zeros((len(lc2c)+1), dtype=int64) # local product center -> start for the current bilocal pair
      for lc,c in enumerate(lc2c): lc2s[lc+1]=lc2s[lc]+self.prod_log.sp2norbs[sv.atom2sp[c]]

      npbp = lc2s[-1] # size of the functions which will contribute to the given pair ia1,ia2
      hkernel_bp = np.zeros((npbp, npbp)) # this is local kernel for the current bilocal pair
      for lc1,c1 in enumerate(lc2c):
        for lc2,c2 in enumerate(lc2c):
          for i1 in range(lc2s[lc1+1]-lc2s[lc1]):
            for i2 in range(lc2s[lc2+1]-lc2s[lc2]):
              hkernel_bp[i1+lc2s[lc1],i2+lc2s[lc2]] = self.hkernel_csr[i1+c2s[c1],i2+c2s[c2]] # element-by-element construction here
      inv_hk = np.linalg.inv(hkernel_bp)

      llp = np.zeros((npbp, nprod))
      for c,s,f in zip(lc2c,lc2s,lc2s[1:]):
        n3 = sv.atom2s[c+1]-sv.atom2s[c]
        lcd = self.prod_log.sp2lambda[sv.atom2sp[c]]
        mol3 = gto.Mole(atom=[sv._atom[ia1], sv._atom[ia2], sv._atom[c]], basis=sv.basis, unit='bohr', spin=1).build()
        bs = get_atom2bas_s(mol3._bas)
        ss = (bs[2],bs[3], bs[2],bs[3], bs[0],bs[1], bs[1],bs[2])
        tci_ao = mol3.intor('cint2e_sph', shls_slice=ss).reshape(n3,n3,n1,n2)
        tci_ao = conv_yzx2xyz_c(mol3).conv_yzx2xyz_4d(tci_ao, 'pyscf2nao', ss)
        lp = einsum('lcd,cdp->lp', lcd,einsum('cdab,pab->cdp', tci_ao, vrtx))
        llp[s:f,:] = lp

      cc = einsum('ab,bc->ac', inv_hk, llp)
      pbiloc = prod_biloc_c(atoms=array([ia1,ia2]), vrtx=vrtx, cc2a=lc2c, cc2s=lc2s, cc=cc.T)
      
      self.bp2info.append(pbiloc)
      #print(ia1, ia2, len(mu2d), lc2c, hkernel_bp.sum(), inv_hk.sum())
  self.dpc2s,self.dpc2t,self.dpc2sp = self.init_c2s_domiprod() # dominant product's counting 
  return self
Exemple #10
0
sv  = system_vars_c().init_pyscf_gto(mol)
prod_log = prod_log_c().init_prod_log_dp(sv.ao_log)
print(prod_log.overlap_check())
print(prod_log.lambda_check_overlap())
print(dipole_check(sv, prod_log))
print('builtin simple center checks done \n')

me = ao_matelem_c(prod_log)

errmx = 0
for ia1 in range(sv.natoms):
  for ia2 in range(sv.natoms):

    n1,n2 = [sv.atom2s[ia+1]-sv.atom2s[ia] for ia in [ia1,ia2]]
    mol3 = gto.Mole_pure(atom=[sv._atom[ia1], sv._atom[ia2]], basis=sv.basis, unit='bohr').build()
    bs = get_atom2bas_s(mol3._bas)
    ss = (bs[0],bs[1], bs[0],bs[1], bs[1],bs[2], bs[1],bs[2])
    tci_ao = mol3.intor('cint2e_sph', shls_slice=ss).reshape(n1,n1,n2,n2)
    tci_ao = conv_yzx2xyz_c(mol3).conv_yzx2xyz_4d(tci_ao, 'pyscf2nao', ss)

    sp1,sp2 = [sv.atom2sp[ia] for ia in [ia1,ia2]]
    R1,R2 = [sv.atom2coord[ia] for ia in [ia1,ia2]]
    pq2v = me.coulomb_am(sp1, R1, sp2, R2)
    tci_ni = np.einsum('abq,qcd->abcd', np.einsum('pab,pq->abq', prod_log.sp2vertex[sp1], pq2v), prod_log.sp2vertex[sp2])
    print(ia1, ia2, abs(tci_ao-tci_ni).sum()/tci_ao.size, abs(tci_ao-tci_ni).max())
    errmx = max(errmx, abs(tci_ao-tci_ni).max())

assert(errmx<3e-5)