def init_inp_param_prod_log_dp(self, sv, tol_loc=1e-5, tol_biloc=1e-6, ac_rcut_ratio=1.0, ac_npc_max=8, jcutoff=14, metric_type=2, optimize_centers=0, ngl=96, **kvargs): """ Talman's procedure should be working well with a pseudo-potential hamiltonians. This subroutine prepares the class for a later atom pair by atom pair generation of the dominant product vertices and the conversion coefficients by calling subroutines from the library libnao. """ from pyscf.nao import prod_log_c from pyscf.nao.m_libnao import libnao self.sv = sv self.tol_loc, self.tol_biloc, self.ac_rcut_ratio, self.ac_npc_max = tol_loc, tol_biloc, ac_rcut_ratio, ac_npc_max self.jcutoff, self.metric_type, self.optimize_centers, self.ngl = jcutoff, metric_type, optimize_centers, ngl 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) # Checking routine: Load Fortran data #self.prod_log = prod_log_c().load_prod_log_dp(sv.ao_log, sv.sp2charge, tol_loc) # tests Fortran input 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] # return self
def test_gto2sv_prod_log(self): """ Test what ? """ sv = system_vars_c().init_pyscf_gto(mol) prod_log = prod_log_c().init_prod_log_dp(sv.ao_log, tol_loc=1e-4) mae, mxe, lll = prod_log.overlap_check() self.assertTrue(all(lll)) self.assertEqual(prod_log.nspecies, 2) self.assertEqual(prod_log.sp2nmult[0], 7) self.assertEqual(prod_log.sp2nmult[1], 20) self.assertEqual(prod_log.sp2norbs[0], 15) self.assertEqual(prod_log.sp2norbs[1], 70)
def test_gto2sv_df(self): from pyscf import scf """ Test import of density-fitting Gaussian functions ... hm """ mf = scf.density_fit(scf.RHF(mol)) self.assertAlmostEqual(mf.scf(), -76.025936299702536, 2) sv = system_vars_c().init_pyscf_gto(mol) prod_log = prod_log_c().init_prod_log_df(mf.with_df.auxmol, sv) self.assertEqual(prod_log.rr[0], sv.ao_log.rr[0]) self.assertEqual(prod_log.pp[0], sv.ao_log.pp[0]) self.assertEqual(prod_log.nspecies, sv.ao_log.nspecies) self.assertEqual(prod_log.sp2charge, sv.ao_log.sp2charge)
def test_gto2sv_prod_log(self): """ Test what ? """ sv = nao(gto=mol) prod_log = prod_log_c().init_prod_log_dp(sv.ao_log, tol_loc=1e-4) mae,mxe,lll=prod_log.overlap_check() self.assertTrue(all(lll)) self.assertEqual(prod_log.nspecies, 2) self.assertEqual(prod_log.sp2nmult[0], 7) self.assertEqual(prod_log.sp2nmult[1], 20) self.assertEqual(prod_log.sp2norbs[0], 15) self.assertEqual(prod_log.sp2norbs[1], 70)
def test_gto2sv_df(self): from pyscf import scf """ Test import of density-fitting Gaussian functions ... hm """ mf = scf.density_fit(scf.RHF(mol)) self.assertAlmostEqual(mf.scf(), -76.025936299702536, 2) sv = nao(gto=mol) prod_log = prod_log_c().init_prod_log_df(mf.with_df.auxmol, sv) self.assertEqual(prod_log.rr[0], sv.ao_log.rr[0]) self.assertEqual(prod_log.pp[0], sv.ao_log.pp[0]) self.assertEqual(prod_log.nspecies, sv.ao_log.nspecies) self.assertEqual(prod_log.sp2charge, sv.ao_log.sp2charge)
def init_inp_param_prod_log_dp(self, sv, tol_loc=1e-5, tol_biloc=1e-6, ac_rcut_ratio=1.0, ac_npc_max=8, jcutoff=14, metric_type=2, optimize_centers=0, ngl=96, **kw): """ Talman's procedure should be working well with a pseudo-potential hamiltonians. This subroutine prepares the class for a later atom pair by atom pair generation of the dominant product vertices and the conversion coefficients by calling subroutines from the library libnao. """ from pyscf.nao import prod_log_c from pyscf.nao.m_libnao import libnao self.sv = sv self.tol_loc,self.tol_biloc,self.ac_rcut_ratio,self.ac_npc_max = tol_loc, tol_biloc, ac_rcut_ratio, ac_npc_max self.jcutoff,self.metric_type,self.optimize_centers,self.ngl = jcutoff, metric_type, optimize_centers, ngl self.ac_rcut = ac_rcut_ratio*max(sv.ao_log.sp2rcut) lload = kw['load_from_hdf5'] if 'load_from_hdf5' in kw else False if lload : self.prod_log = prod_log_c().load_prod_log_dp(sv.ao_log, sv.sp2charge, tol_loc) # tests Fortran input # Checking routine: Load Fortran data else : self.prod_log = prod_log_c().init_prod_log_dp(sv.ao_log, tol_loc) # local basis (for each specie) 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] # return self
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
# 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 from pyscf.nao import system_vars_c, prod_log_c, conv_yzx2xyz_c, get_atom2bas_s, ao_matelem_c from pyscf.nao.m_system_vars import diag_check, overlap_check from pyscf.nao.m_prod_log import dipole_check from pyscf import gto import numpy as np mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='ccpvdz') # coordinates in Angstrom! 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()
o_xyz = self.conv_yzx2xyz_1d(np.einsum('bcda->cdab', o_xyz), m2m, sh[2]) o_xyz = self.conv_yzx2xyz_1d(np.einsum('cdab->dabc', o_xyz), m2m, sh[3]) return np.einsum('dabc->abcd', o_xyz) if __name__=='__main__': """ Computes coulomb overlaps (ab|cd) between 4 orbitals sitting on the same atom with GTO and compares to NAO """ from pyscf.nao import system_vars_c, prod_log_c, ao_matelem_c import numpy as np from timeit import default_timer as timer from scipy.sparse import csr_matrix mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='ccpvtz') # coordinates in Angstrom! sv = system_vars_c(gto=mol) t1s = timer() prod_log = prod_log_c(sv.ao_log, tol=1e-5) print(timer() - t1s) t1s = timer() me = ao_matelem_c(prod_log) print(timer() - t1s) m1 = gto.Mole_pure() for ia,sp in enumerate(sv.atom2sp): pab2v=prod_log.sp2vertex[sp] n = pab2v.shape[1] pab_shape = [pab2v.shape[0], pab2v.shape[1]*pab2v.shape[2]] pab2v_csr = csr_matrix(pab2v.reshape(pab_shape)) print(pab2v_csr.getnnz(), pab_shape[0]*pab_shape[1]) t1s = timer()
from pyscf.nao.m_ao_matelem import build_3dgrid from pyscf.nao.m_ao_eval_libnao import ao_eval_libnao as ao_eval grids = build_3dgrid(me, sp1, np.array(R1), sp2, np.array(R2), **kvargs) pf = grids.weights * ao_eval(me.ao2, np.array(R1), sp1, grids.coords) qv = ao_eval(me.ao2_hartree, np.array(R2), sp2, grids.coords) pq2eri = np.einsum('pr,qr->pq', pf, qv) return pq2eri if __name__ == "__main__": from pyscf.nao import system_vars_c, ao_matelem_c, prod_log_c from pyscf.nao.m_eri2c import eri2c sv = system_vars_c(label='siesta') R0 = sv.atom2coord[0, :] prod_log = prod_log_c(sv.ao_log) print(prod_log.sp2norbs) me_prod = ao_matelem_c(prod_log) vc_am = me_prod.coulomb_am(0, R0, 0, R0) print(vc_am.shape, vc_am.max(), vc_am.min()) vc_ni = eri2c(me_prod, 0, R0, 0, R0, level=5) print(vc_ni.shape, vc_ni.max(), vc_ni.min()) print(abs(vc_ni - vc_am).sum() / vc_am.size, abs(vc_ni - vc_am).max())
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
# 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 from pyscf.nao import system_vars_c, prod_log_c, conv_yzx2xyz_c, get_atom2bas_s, ao_matelem_c from pyscf.nao.m_system_vars import diag_check, overlap_check from pyscf.nao.m_prod_log import dipole_check from pyscf import gto import numpy as np mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='ccpvdz') # coordinates in Angstrom! 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])