def cart2spinor(l): '''Cartesian to spinor for angular moment l''' from pyscf import gto return gto.cart2spinor_l(l)
def so_by_shell(mol, shls, ecpatm_id, ecpbas): '''SO-ECP i/2 <Pauli_matrix dot l U(r)> ''' ish, jsh = shls li = mol.bas_angular(ish) npi = mol.bas_nprim(ish) nci = mol.bas_nctr(ish) ai = mol.bas_exp(ish) ci = mol._libcint_ctr_coeff(ish) icart = (li + 1) * (li + 2) // 2 lj = mol.bas_angular(jsh) npj = mol.bas_nprim(jsh) ncj = mol.bas_nctr(jsh) aj = mol.bas_exp(jsh) cj = mol._libcint_ctr_coeff(jsh) jcart = (lj + 1) * (lj + 2) // 2 rc = mol.atom_coord(ecpatm_id) rcb = rc - mol.bas_coord(jsh) r_cb = numpy.linalg.norm(rcb) rca = rc - mol.bas_coord(ish) r_ca = numpy.linalg.norm(rca) #rs, ws = radi.treutler(99) rs, ws = radi.gauss_chebyshev(99) i_fac_cache = cache_fac(li, rca) j_fac_cache = cache_fac(lj, rcb) g1 = numpy.zeros((nci, ncj, 3, icart, jcart), dtype=numpy.complex128) for lc in range(5): # up to g function ecpbasi = ecpbas[ecpbas[:, ANG_OF] == lc] if len(ecpbasi) == 0: continue ur = rad_part(mol, ecpbasi, rs) * ws idx = abs(ur) > 1e-80 rur = numpy.array( [ur[idx] * rs[idx]**lab for lab in range(li + lj + 1)]) fi = facs_rad(mol, ish, lc, r_ca, rs)[:, :, idx].copy() fj = facs_rad(mol, jsh, lc, r_cb, rs)[:, :, idx].copy() angi = facs_ang(type2_ang_part(li, lc, -rca), li, lc, i_fac_cache) angj = facs_ang(type2_ang_part(lj, lc, -rcb), lj, lc, j_fac_cache) # Note the factor 2/(2l+1) in JCP 82 2664 is not multiplied here # because the ECP parameter has been scaled by 2/(2l+1) in CRENBL jmm = angular_moment_matrix(lc) for ic in range(nci): for jc in range(ncj): rad_all = numpy.einsum('pr,ir,jr->pij', rur, fi[ic], fj[jc]) for i1 in range(li + 1): for j1 in range(lj + 1): g1[ic, jc] += numpy.einsum('pq,imp,jnq,lmn->lij', rad_all[i1 + j1], angi[i1], angj[j1], jmm) g1 *= (numpy.pi * 4)**2 gspinor = numpy.empty((nci, ncj, li * 4 + 2, lj * 4 + 2), dtype=numpy.complex128) for ic in range(nci): for jc in range(ncj): ui = numpy.asarray(gto.cart2spinor_l(li)) uj = numpy.asarray(gto.cart2spinor_l(lj)) s = lib.PauliMatrices * .5j gspinor[ic, jc] = numpy.einsum('sxy,spq,xpi,yqj->ij', s, g1[ic, jc], ui.conj(), uj) return gspinor.transpose(0, 2, 1, 3).reshape(nci * (li * 4 + 2), -1)