def project_mo_nr2nr(mol1, mo1, mol2): r''' Project orbital coefficients from basis set 1 (C1 for mol1) to basis set 2 (C2 for mol2). .. math:: |\psi1\rangle = |AO1\rangle C1 |\psi2\rangle = P |\psi1\rangle = |AO2\rangle S^{-1}\langle AO2| AO1\rangle> C1 = |AO2\rangle> C2 C2 = S^{-1}\langle AO2|AO1\rangle C1 There are three relevant functions: :func:`project_mo_nr2nr` is the projection for non-relativistic (scalar) basis. :func:`project_mo_nr2r` projects from non-relativistic to relativistic basis. :func:`project_mo_r2r` is the projection between relativistic (spinor) basis. ''' s22 = mol2.intor_symmetric('int1e_ovlp') s21 = mole.intor_cross('int1e_ovlp', mol2, mol1) if isinstance(mo1, numpy.ndarray) and mo1.ndim == 2: return lib.cho_solve(s22, numpy.dot(s21, mo1), strict_sym_pos=False) else: return [ lib.cho_solve(s22, numpy.dot(s21, x), strict_sym_pos=False) for x in mo1 ]
def project_mo_r2r(mol1, mo1, mol2): s22 = mol2.intor_symmetric('int1e_ovlp_spinor') t22 = mol2.intor_symmetric('int1e_spsp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', mol2, mol1) t21 = mole.intor_cross('int1e_spsp_spinor', mol2, mol1) n2c = s21.shape[1] pl = lib.cho_solve(s22, s21) ps = lib.cho_solve(t22, t21) return numpy.vstack((numpy.dot(pl, mo1[:n2c]), numpy.dot(ps, mo1[n2c:])))
def project_mo_r2r(mol1, mo1, mol2): s22 = mol2.intor_symmetric('cint1e_ovlp') t22 = mol2.intor_symmetric('cint1e_spsp') s21 = mole.intor_cross('cint1e_ovlp', mol2, mol1) t21 = mole.intor_cross('cint1e_spsp', mol2, mol1) n2c = s21.shape[1] pl = lib.cho_solve(s22, s21) ps = lib.cho_solve(t22, t21) return numpy.vstack((numpy.dot(pl, mo1[:n2c]), numpy.dot(ps, mo1[n2c:])))
def project_dm_r2r(mol1, dm1, mol2): s22 = mol2.intor_symmetric('int1e_ovlp_spinor') t22 = mol2.intor_symmetric('int1e_spsp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', mol2, mol1) t21 = mole.intor_cross('int1e_spsp_spinor', mol2, mol1) pl = lib.cho_solve(s22, s21, strict_sym_pos=False) ps = lib.cho_solve(t22, t21, strict_sym_pos=False) p21 = scipy.linalg.block_diag(pl, ps) if isinstance(dm1, numpy.ndarray) and dm1.ndim == 2: return reduce(numpy.dot, (p21, dm1, p21.conj().T)) else: return lib.einsum('pi,nij,qj->npq', p21, dm1, p21.conj())
def project_mo_r2r(mol1, mo1, mol2): s22 = mol2.intor_symmetric('int1e_ovlp_spinor') t22 = mol2.intor_symmetric('int1e_spsp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', mol2, mol1) t21 = mole.intor_cross('int1e_spsp_spinor', mol2, mol1) n2c = s21.shape[1] pl = lib.cho_solve(s22, s21, strict_sym_pos=False) ps = lib.cho_solve(t22, t21, strict_sym_pos=False) if isinstance(mo1, numpy.ndarray) and mo1.ndim == 2: return numpy.vstack((numpy.dot(pl, mo1[:n2c]), numpy.dot(ps, mo1[n2c:]))) else: return [numpy.vstack((numpy.dot(pl, x[:n2c]), numpy.dot(ps, x[n2c:]))) for x in mo1]
def project_dm_r2r(mol1, dm1, mol2): __doc__ = project_dm_nr2nr.__doc__ s22 = mol2.intor_symmetric('int1e_ovlp_spinor') t22 = mol2.intor_symmetric('int1e_spsp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', mol2, mol1) t21 = mole.intor_cross('int1e_spsp_spinor', mol2, mol1) n2c = s21.shape[1] pl = lib.cho_solve(s22, s21) ps = lib.cho_solve(t22, t21) p21 = scipy.linalg.block_diag(pl, ps) if isinstance(dm1, numpy.ndarray) and dm1.ndim == 2: return reduce(numpy.dot, (p21, dm1, p21.conj().T)) else: return lib.einsum('pi,nij,qj->npq', p21, dm1, p21.conj())
def project_mo_nr2r(mol1, mo1, mol2): assert(not mol1.cart) s22 = mol2.intor_symmetric('int1e_ovlp_spinor') s21 = mole.intor_cross('int1e_ovlp_sph', mol2, mol1) ua, ub = mol2.sph2spinor_coeff() s21 = numpy.dot(ua.T.conj(), s21) + numpy.dot(ub.T.conj(), s21) # (*) # mo2: alpha, beta have been summed in Eq. (*) # so DM = mo2[:,:nocc] * 1 * mo2[:,:nocc].H if isinstance(mo1, numpy.ndarray) and mo1.ndim == 2: mo2 = numpy.dot(s21, mo1) return lib.cho_solve(s22, mo2, strict_sym_pos=False) else: return [lib.cho_solve(s22, numpy.dot(s21, x), strict_sym_pos=False) for x in mo1]
def project_dm_nr2nr(mol1, dm1, mol2): r''' Project density matrix representation from basis set 1 (mol1) to basis set 2 (mol2). .. math:: |AO2\rangle DM_AO2 \langle AO2| = |AO2\rangle P DM_AO1 P \langle AO2| DM_AO2 = P DM_AO1 P P = S_{AO2}^{-1}\langle AO2|AO1\rangle There are three relevant functions: :func:`project_dm_nr2nr` is the projection for non-relativistic (scalar) basis. :func:`project_dm_nr2r` projects from non-relativistic to relativistic basis. :func:`project_dm_r2r` is the projection between relativistic (spinor) basis. ''' s22 = mol2.intor_symmetric('int1e_ovlp') s21 = mole.intor_cross('int1e_ovlp', mol2, mol1) p21 = lib.cho_solve(s22, s21) if isinstance(dm1, numpy.ndarray) and dm1.ndim == 2: return reduce(numpy.dot, (p21, dm1, p21.conj().T)) else: return lib.einsum('pi,nij,qj->npq', p21, dm1, p21.conj())
def project_mo_r2r(mol1, mo1, mol2): __doc__ = project_mo_nr2nr.__doc__ s22 = mol2.intor_symmetric('int1e_ovlp_spinor') t22 = mol2.intor_symmetric('int1e_spsp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', mol2, mol1) t21 = mole.intor_cross('int1e_spsp_spinor', mol2, mol1) n2c = s21.shape[1] pl = lib.cho_solve(s22, s21) ps = lib.cho_solve(t22, t21) if isinstance(mo1, numpy.ndarray) and mo1.ndim == 2: return numpy.vstack((numpy.dot(pl, mo1[:n2c]), numpy.dot(ps, mo1[n2c:]))) else: return [numpy.vstack((numpy.dot(pl, x[:n2c]), numpy.dot(ps, x[n2c:]))) for x in mo1]
def project_mo_nr2r(mol1, mo1, mol2): __doc__ = project_mo_nr2nr.__doc__ assert(not mol1.cart) s22 = mol2.intor_symmetric('int1e_ovlp_spinor') s21 = mole.intor_cross('int1e_ovlp_sph', mol2, mol1) ua, ub = mol2.sph2spinor_coeff() s21 = numpy.dot(ua.T.conj(), s21) + numpy.dot(ub.T.conj(), s21) # (*) # mo2: alpha, beta have been summed in Eq. (*) # so DM = mo2[:,:nocc] * 1 * mo2[:,:nocc].H if isinstance(mo1, numpy.ndarray) and mo1.ndim == 2: mo2 = numpy.dot(s21, mo1) return lib.cho_solve(s22, mo2) else: return [lib.cho_solve(s22, numpy.dot(s21, x)) for x in mo1]
def project(mfmo, init_mo, ncore, s): s_init_mo = numpy.einsum('pi,pi->i', init_mo.conj(), s.dot(init_mo)) if abs(s_init_mo - 1).max() < 1e-7 and mfmo.shape[1] == init_mo.shape[1]: # Initial guess orbitals are orthonormal return init_mo # TODO: test whether the canonicalized orbitals are better than the projected orbitals # Be careful that the ordering of the canonicalized orbitals may be very different # to the CASSCF orbitals. # else: # fock = casscf.get_fock(mc, init_mo, casscf.ci) # return casscf._scf.eig(fock, s)[1] nocc = ncore + casscf.ncas if ncore > 0: mo0core = init_mo[:, :ncore] s1 = reduce(numpy.dot, (mfmo.T, s, mo0core)) s1core = reduce(numpy.dot, (mo0core.T, s, mo0core)) coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T)) coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore]) logger.debug(casscf, 'Core indices %s', coreidx) logger.debug(casscf, 'Core components %s', coreocc[coreidx]) # take HF core mocore = mfmo[:, coreidx] # take projected CAS space mocas = init_mo[:,ncore:nocc] \ - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc])) mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s) else: mocc = lo.orth.vec_lowdin(init_mo[:, :nocc], s) # remove core and active space from rest if mocc.shape[1] < mfmo.shape[1]: if casscf.mol.symmetry: restorb = [] orbsym = scf.hf_symm.get_orbsym(casscf.mol, mfmo, s) for ir in set(orbsym): mo_ir = mfmo[:, orbsym == ir] rest = mo_ir - reduce(numpy.dot, (mocc, mocc.T, s, mo_ir)) e, u = numpy.linalg.eigh( reduce(numpy.dot, (rest.T, s, rest))) restorb.append(numpy.dot(rest, u[:, e > 1e-7])) restorb = numpy.hstack(restorb) else: rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb = numpy.dot(rest, u[:, e > 1e-7]) mo = numpy.hstack((mocc, restorb)) else: mo = mocc if casscf.verbose >= logger.DEBUG: s1 = reduce(numpy.dot, (mo[:, ncore:nocc].T, s, mfmo)) idx = numpy.argwhere(abs(s1) > 0.4) for i, j in idx: logger.debug(casscf, 'Init guess <mo-CAS|mo-hf> %d %d %12.8f', ncore + i + 1, j + 1, s1[i, j]) return mo
def get_hcore(self, mol=None): if mol is None: mol = self.mol xmol, contr_coeff = self.get_xmol(mol) c = lib.param.LIGHT_SPEED assert('1E' in self.approx.upper()) t = xmol.intor_symmetric('cint1e_kin_sph') v = xmol.intor_symmetric('cint1e_nuc_sph') s = xmol.intor_symmetric('cint1e_ovlp_sph') w = xmol.intor_symmetric('cint1e_pnucp_sph') if 'ATOM' in self.approx.upper(): atom_slices = xmol.offset_nr_by_atom() nao = xmol.nao_nr() x = numpy.zeros((nao,nao)) for ia in range(xmol.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) t1 = xmol.intor('cint1e_kin_sph', shls_slice=shls_slice) v1 = xmol.intor('cint1e_nuc_sph', shls_slice=shls_slice) s1 = xmol.intor('cint1e_ovlp_sph', shls_slice=shls_slice) w1 = xmol.intor('cint1e_pnucp_sph', shls_slice=shls_slice) x[p0:p1,p0:p1] = _x2c1e_xmatrix(t1, v1, w1, s1, c) h1 = _get_hcore_fw(t, v, w, s, x, c) else: h1 = _x2c1e_get_hcore(t, v, w, s, c) if self.basis is not None: s22 = xmol.intor_symmetric('cint1e_ovlp_sph') s21 = mole.intor_cross('cint1e_ovlp_sph', xmol, mol) c = lib.cho_solve(s22, s21) h1 = reduce(numpy.dot, (c.T, h1, c)) if self.xuncontract and contr_coeff is not None: h1 = reduce(numpy.dot, (contr_coeff.T, h1, contr_coeff)) return h1
def symmetrize_orb(mol, mo, orbsym=None, s=None, check=getattr(__config__, 'symm_addons_symmetrize_orb_check', False)): '''Symmetrize the given orbitals. This function is different to the :func:`symmetrize_space`: In this function, each orbital is symmetrized by removing non-symmetric components. :func:`symmetrize_space` symmetrizes the entire space by mixing different orbitals. Note this function might return non-orthorgonal orbitals. Call :func:`symmetrize_space` to find the symmetrized orbitals that are close to the given orbitals. Args: mo : 2D float array The orbital space to symmetrize Kwargs: orbsym : integer list Irrep id for each orbital. If not given, the irreps are guessed by calling :func:`label_orb_symm`. s : 2D float array Overlap matrix. If given, use this overlap than the the overlap of the input mol. Returns: 2D orbital coefficients Examples: >>> from pyscf import gto, symm, scf >>> mol = gto.M(atom = 'C 0 0 0; H 1 1 1; H -1 -1 1; H 1 -1 -1; H -1 1 -1', ... basis = 'sto3g') >>> mf = scf.RHF(mol).run() >>> mol.build(0, 0, symmetry='D2') >>> mo = symm.symmetrize_orb(mol, mf.mo_coeff) >>> print(symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo)) ['A', 'A', 'B1', 'B2', 'B3', 'A', 'B1', 'B2', 'B3'] ''' if s is None: s = mol.intor_symmetric('int1e_ovlp') if orbsym is None: orbsym = label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mo, s=s, check=check) orbsym = numpy.asarray(orbsym) s_mo = numpy.dot(s, mo) mo1 = numpy.empty_like(mo) if orbsym[0] in mol.irrep_name: irrep_id = mol.irrep_name else: irrep_id = mol.irrep_id for i, ir in enumerate(irrep_id): idx = orbsym == ir csym = mol.symm_orb[i] ovlpso = reduce(numpy.dot, (csym.T, s, csym)) sc = lib.cho_solve(ovlpso, numpy.dot(csym.T, s_mo[:,idx])) mo1[:,idx] = numpy.dot(csym, sc) return mo1
def picture_change(self, even_operator=(None, None), odd_operator=None): '''Picture change for even_operator + odd_operator even_operator has two terms at diagonal blocks [ v 0 ] [ 0 w ] odd_operator has the term at off-diagonal blocks [ 0 p ] [ p^T 0 ] v, w, and p can be strings (integral name) or matrices. ''' mol = self.mol xmol, c = self.get_xmol(mol) pc_mat = self._picture_change(xmol, even_operator, odd_operator) if self.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp') s21 = gto.mole.intor_cross('int1e_ovlp', xmol, mol) c = lib.cho_solve(s22, s21) elif self.xuncontract: pass else: return pc_mat if pc_mat.ndim == 2: return lib.einsum('pi,pq,qj->ij', c, pc_mat, c) else: return lib.einsum('pi,xpq,qj->xij', c, pc_mat, c)
def picture_change(self, even_operator=(None, None), odd_operator=None): '''Picture change for even_operator + odd_operator even_operator has two terms at diagonal blocks [ v 0 ] [ 0 w ] odd_operator has the term at off-diagonal blocks [ 0 p ] [ p^T 0 ] v, w, and p can be strings (integral name) or matrices. ''' mol = self.mol xmol, contr_coeff_nr = self.get_xmol(mol) pc_mat = self._picture_change(xmol, even_operator, odd_operator) if self.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', xmol, mol) c = lib.cho_solve(s22, s21) elif self.xuncontract: np, nc = contr_coeff_nr.shape c = numpy.zeros((np * 2, nc * 2)) c[0::2, 0::2] = contr_coeff_nr c[1::2, 1::2] = contr_coeff_nr else: return pc_mat if pc_mat.ndim == 2: return lib.einsum('pi,pq,qj->ij', c.conj(), pc_mat, c) else: return lib.einsum('pi,xpq,qj->xij', c.conj(), pc_mat, c)
def get_hcore(self, mol=None): if mol is None: mol = self.mol xmol, contr_coeff = self.get_xmol(mol) c = lib.param.LIGHT_SPEED assert ('1E' in self.approx.upper()) t = xmol.intor_symmetric('cint1e_kin_sph') v = xmol.intor_symmetric('cint1e_nuc_sph') s = xmol.intor_symmetric('cint1e_ovlp_sph') w = xmol.intor_symmetric('cint1e_pnucp_sph') if 'ATOM' in self.approx.upper(): atom_slices = xmol.offset_nr_by_atom() nao = xmol.nao_nr() x = numpy.zeros((nao, nao)) for ia in range(xmol.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) t1 = xmol.intor('cint1e_kin_sph', shls_slice=shls_slice) v1 = xmol.intor('cint1e_nuc_sph', shls_slice=shls_slice) s1 = xmol.intor('cint1e_ovlp_sph', shls_slice=shls_slice) w1 = xmol.intor('cint1e_pnucp_sph', shls_slice=shls_slice) x[p0:p1, p0:p1] = _x2c1e_xmatrix(t1, v1, w1, s1, c) h1 = _get_hcore_fw(t, v, w, s, x, c) else: h1 = _x2c1e_get_hcore(t, v, w, s, c) if self.basis is not None: s22 = xmol.intor_symmetric('cint1e_ovlp_sph') s21 = mole.intor_cross('cint1e_ovlp_sph', xmol, mol) c = lib.cho_solve(s22, s21) h1 = reduce(numpy.dot, (c.T, h1, c)) if self.xuncontract and contr_coeff is not None: h1 = reduce(numpy.dot, (contr_coeff.T, h1, contr_coeff)) return h1
def build_Lpq_nonpbc(mydf, auxcell): if mydf.metric.upper() == 'S': j3c = pyscf.df.incore.aux_e2(mydf.cell, auxcell, 'cint3c1e_sph', aosym='s2ij') j2c = auxcell.intor_symmetric('cint1e_ovlp_sph') else: # mydf.metric.upper() == 'T' j3c = pyscf.df.incore.aux_e2(mydf.cell, auxcell, 'cint3c1e_p2_sph', aosym='s2ij') j2c = auxcell.intor_symmetric('cint1e_kin_sph') * 2 naux = auxcell.nao_nr() nao = mydf.cell.nao_nr() nao_pair = nao * (nao + 1) // 2 with h5py.File(mydf._cderi) as feri: if 'Lpq' in feri: del (feri['Lpq']) chunks = (min(mydf.blockdim, naux), min(mydf.blockdim, nao_pair)) # 512K Lpq = feri.create_dataset('Lpq/0', (naux, nao_pair), 'f8', chunks=chunks) Lpq[:] = lib.cho_solve(j2c, j3c.T)
def project(mfmo, init_mo, ncore, s): s_init_mo = numpy.einsum('pi,pi->i', init_mo.conj(), s.dot(init_mo)) if abs(s_init_mo - 1).max() < 1e-7 and mfmo.shape[1] == init_mo.shape[1]: # Initial guess orbitals are orthonormal return init_mo # TODO: test whether the canonicalized orbitals are better than the projected orbitals # Be careful that the ordering of the canonicalized orbitals may be very different # to the CASSCF orbitals. # else: # fock = casscf.get_fock(mc, init_mo, casscf.ci) # return casscf._scf.eig(fock, s)[1] nocc = ncore + casscf.ncas if ncore > 0: mo0core = init_mo[:,:ncore] s1 = reduce(numpy.dot, (mfmo.T, s, mo0core)) s1core = reduce(numpy.dot, (mo0core.T, s, mo0core)) coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T)) coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore]) logger.debug(casscf, 'Core indices %s', coreidx) logger.debug(casscf, 'Core components %s', coreocc[coreidx]) # take HF core mocore = mfmo[:,coreidx] # take projected CAS space mocas = init_mo[:,ncore:nocc] \ - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc])) mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s) else: mocc = lo.orth.vec_lowdin(init_mo[:,:nocc], s) # remove core and active space from rest if mocc.shape[1] < mfmo.shape[1]: if casscf.mol.symmetry: restorb = [] orbsym = scf.hf_symm.get_orbsym(casscf.mol, mfmo, s) for ir in set(orbsym): mo_ir = mfmo[:,orbsym==ir] rest = mo_ir - reduce(numpy.dot, (mocc, mocc.T, s, mo_ir)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb.append(numpy.dot(rest, u[:,e>1e-7])) restorb = numpy.hstack(restorb) else: rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb = numpy.dot(rest, u[:,e>1e-7]) mo = numpy.hstack((mocc, restorb)) else: mo = mocc if casscf.verbose >= logger.DEBUG: s1 = reduce(numpy.dot, (mo[:,ncore:nocc].T, s, mfmo)) idx = numpy.argwhere(abs(s1) > 0.4) for i,j in idx: logger.debug(casscf, 'Init guess <mo-CAS|mo-hf> %d %d %12.8f', ncore+i+1, j+1, s1[i,j]) return mo
def get_hcore(self, cell=None, kpts=None): if cell is None: cell = self.cell if kpts is None: kpts_lst = numpy.zeros((1,3)) else: kpts_lst = numpy.reshape(kpts, (-1,3)) xcell, contr_coeff = self.get_xmol(cell) with_df = aft.AFTDF(xcell) c = lib.param.LIGHT_SPEED assert('1E' in self.approx.upper()) if 'ATOM' in self.approx.upper(): atom_slices = xcell.offset_nr_by_atom() nao = xcell.nao_nr() x = numpy.zeros((nao,nao)) vloc = numpy.zeros((nao,nao)) wloc = numpy.zeros((nao,nao)) for ia in range(xcell.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) t1 = xcell.intor('int1e_kin', shls_slice=shls_slice) s1 = xcell.intor('int1e_ovlp', shls_slice=shls_slice) with xcell.with_rinv_as_nucleus(ia): z = -xcell.atom_charge(ia) v1 = z * xcell.intor('int1e_rinv', shls_slice=shls_slice) w1 = z * xcell.intor('int1e_prinvp', shls_slice=shls_slice) vloc[p0:p1,p0:p1] = v1 wloc[p0:p1,p0:p1] = w1 x[p0:p1,p0:p1] = x2c._x2c1e_xmatrix(t1, v1, w1, s1, c) else: raise NotImplementedError t = xcell.pbc_intor('int1e_kin', 1, lib.HERMITIAN, kpts_lst) s = xcell.pbc_intor('int1e_ovlp', 1, lib.HERMITIAN, kpts_lst) v = with_df.get_nuc(kpts_lst) #w = get_pnucp(with_df, kpts_lst) if self.basis is not None: s22 = s s21 = pbcgto.intor_cross('int1e_ovlp', xcell, cell, kpts=kpts_lst) h1_kpts = [] for k in range(len(kpts_lst)): # The treatment of pnucp local part has huge effects to hcore #h1 = x2c._get_hcore_fw(t[k], vloc, wloc, s[k], x, c) - vloc + v[k] #h1 = x2c._get_hcore_fw(t[k], v[k], w[k], s[k], x, c) h1 = x2c._get_hcore_fw(t[k], v[k], wloc, s[k], x, c) if self.basis is not None: c = lib.cho_solve(s22[k], s21[k]) h1 = reduce(numpy.dot, (c.T, h1, c)) if self.xuncontract and contr_coeff is not None: h1 = reduce(numpy.dot, (contr_coeff.T, h1, contr_coeff)) h1_kpts.append(h1) if kpts is None or numpy.shape(kpts) == (3,): h1_kpts = h1_kpts[0] return lib.asarray(h1_kpts)
def get_hcore(self, cell=None, kpts=None): if cell is None: cell = self.cell if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) xcell, contr_coeff = self.get_xmol(cell) with_df = aft.AFTDF(xcell) c = lib.param.LIGHT_SPEED assert ('1E' in self.approx.upper()) if 'ATOM' in self.approx.upper(): atom_slices = xcell.offset_nr_by_atom() nao = xcell.nao_nr() x = numpy.zeros((nao, nao)) vloc = numpy.zeros((nao, nao)) wloc = numpy.zeros((nao, nao)) for ia in range(xcell.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) t1 = xcell.intor('int1e_kin', shls_slice=shls_slice) s1 = xcell.intor('int1e_ovlp', shls_slice=shls_slice) with xcell.with_rinv_at_nucleus(ia): z = -xcell.atom_charge(ia) v1 = z * xcell.intor('int1e_rinv', shls_slice=shls_slice) w1 = z * xcell.intor('int1e_prinvp', shls_slice=shls_slice) vloc[p0:p1, p0:p1] = v1 wloc[p0:p1, p0:p1] = w1 x[p0:p1, p0:p1] = x2c._x2c1e_xmatrix(t1, v1, w1, s1, c) else: raise NotImplementedError t = xcell.pbc_intor('int1e_kin', 1, lib.HERMITIAN, kpts_lst) s = xcell.pbc_intor('int1e_ovlp', 1, lib.HERMITIAN, kpts_lst) v = with_df.get_nuc(kpts_lst) #w = get_pnucp(with_df, kpts_lst) if self.basis is not None: s22 = s s21 = pbcgto.intor_cross('int1e_ovlp', xcell, cell, kpts=kpts_lst) h1_kpts = [] for k in range(len(kpts_lst)): # The treatment of pnucp local part has huge effects to hcore #h1 = x2c._get_hcore_fw(t[k], vloc, wloc, s[k], x, c) - vloc + v[k] #h1 = x2c._get_hcore_fw(t[k], v[k], w[k], s[k], x, c) h1 = x2c._get_hcore_fw(t[k], v[k], wloc, s[k], x, c) if self.basis is not None: c = lib.cho_solve(s22[k], s21[k]) h1 = reduce(numpy.dot, (c.T, h1, c)) if self.xuncontract and contr_coeff is not None: h1 = reduce(numpy.dot, (contr_coeff.T, h1, contr_coeff)) h1_kpts.append(h1) if kpts is None or numpy.shape(kpts) == (3, ): h1_kpts = h1_kpts[0] return lib.asarray(h1_kpts)
def project_mo_nr2r(mol1, mo1, mol2): s22 = mol2.intor_symmetric('cint1e_ovlp') s21 = mole.intor_cross('cint1e_ovlp_sph', mol2, mol1) ua, ub = symm.cg.real2spinor_whole(mol2) s21 = numpy.dot(ua.T.conj(), s21) + numpy.dot(ub.T.conj(), s21) # (*) # mo2: alpha, beta have been summed in Eq. (*) # so DM = mo2[:,:nocc] * 1 * mo2[:,:nocc].H mo2 = numpy.dot(s21, mo1) return lib.cho_solve(s22, mo2)
def get_hcore(self, mol=None): '''2-component X2c Foldy-Wouthuysen (FW) Hamiltonian (including spin-free and spin-dependent terms) in the j-adapted spinor basis. ''' if mol is None: mol = self.mol if mol.has_ecp(): raise NotImplementedError xmol, contr_coeff_nr = self.get_xmol(mol) c = lib.param.LIGHT_SPEED assert ('1E' in self.approx.upper()) s = xmol.intor_symmetric('int1e_ovlp_spinor') t = xmol.intor_symmetric('int1e_spsp_spinor') * .5 v = xmol.intor_symmetric('int1e_nuc_spinor') w = xmol.intor_symmetric('int1e_spnucsp_spinor') if 'get_xmat' in self.__dict__: # If the get_xmat method is overwritten by user, build the X # matrix with the external get_xmat method x = self.get_xmat(xmol) h1 = _get_hcore_fw(t, v, w, s, x, c) elif 'ATOM' in self.approx.upper(): atom_slices = xmol.offset_2c_by_atom() n2c = xmol.nao_2c() x = numpy.zeros((n2c, n2c), dtype=numpy.complex) for ia in range(xmol.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) s1 = xmol.intor('int1e_ovlp_spinor', shls_slice=shls_slice) t1 = xmol.intor('int1e_spsp_spinor', shls_slice=shls_slice) * .5 with xmol.with_rinv_at_nucleus(ia): z = -xmol.atom_charge(ia) v1 = z * xmol.intor('int1e_rinv_spinor', shls_slice=shls_slice) w1 = z * xmol.intor('int1e_sprinvsp_spinor', shls_slice=shls_slice) x[p0:p1, p0:p1] = _x2c1e_xmatrix(t1, v1, w1, s1, c) h1 = _get_hcore_fw(t, v, w, s, x, c) else: h1 = _x2c1e_get_hcore(t, v, w, s, c) if self.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', xmol, mol) c = lib.cho_solve(s22, s21) h1 = reduce(numpy.dot, (c.T.conj(), h1, c)) elif self.xuncontract: np, nc = contr_coeff_nr.shape contr_coeff = numpy.zeros((np * 2, nc * 2)) contr_coeff[0::2, 0::2] = contr_coeff_nr contr_coeff[1::2, 1::2] = contr_coeff_nr h1 = reduce(numpy.dot, (contr_coeff.T.conj(), h1, contr_coeff)) return h1
def get_hcore(self, mol=None): if mol is None: mol = self.mol if mol.has_ecp(): raise NotImplementedError xmol, contr_coeff = self.get_xmol(mol) c = lib.param.LIGHT_SPEED assert ('1E' in self.approx.upper()) t = _block_diag(xmol.intor_symmetric('int1e_kin')) v = _block_diag(xmol.intor_symmetric('int1e_nuc')) s = _block_diag(xmol.intor_symmetric('int1e_ovlp')) w = _sigma_dot(xmol.intor('int1e_spnucsp')) if 'get_xmat' in self.__dict__: # If the get_xmat method is overwritten by user, build the X # matrix with the external get_xmat method x = self.get_xmat(xmol) h1 = _get_hcore_fw(t, v, w, s, x, c) elif 'ATOM' in self.approx.upper(): atom_slices = xmol.offset_nr_by_atom() # spin-orbital basis is twice the size of NR basis atom_slices[:, 2:] *= 2 nao = xmol.nao_nr() * 2 x = numpy.zeros((nao, nao)) for ia in range(xmol.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) t1 = _block_diag(xmol.intor('int1e_kin', shls_slice=shls_slice)) s1 = _block_diag( xmol.intor('int1e_ovlp', shls_slice=shls_slice)) with xmol.with_rinv_at_nucleus(ia): z = -xmol.atom_charge(ia) v1 = _block_diag( z * xmol.intor('int1e_rinv', shls_slice=shls_slice)) w1 = _sigma_dot( z * xmol.intor('int1e_sprinvsp', shls_slice=shls_slice)) x[p0:p1, p0:p1] = _x2c1e_xmatrix(t1, v1, w1, s1, c) h1 = _get_hcore_fw(t, v, w, s, x, c) else: h1 = _x2c1e_get_hcore(t, v, w, s, c) if self.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp') s21 = mole.intor_cross('int1e_ovlp', xmol, mol) c = _block_diag(lib.cho_solve(s22, s21)) h1 = reduce(lib.dot, (c.T, h1, c)) if self.xuncontract and contr_coeff is not None: contr_coeff = _block_diag(contr_coeff) h1 = reduce(lib.dot, (contr_coeff.T, h1, contr_coeff)) return h1
def project_dm_nr2r(mol1, dm1, mol2): assert(not mol1.cart) s22 = mol2.intor_symmetric('int1e_ovlp_spinor') s21 = mole.intor_cross('int1e_ovlp_sph', mol2, mol1) ua, ub = mol2.sph2spinor_coeff() s21 = numpy.dot(ua.T.conj(), s21) + numpy.dot(ub.T.conj(), s21) # (*) # mo2: alpha, beta have been summed in Eq. (*) # so DM = mo2[:,:nocc] * 1 * mo2[:,:nocc].H p21 = lib.cho_solve(s22, s21, strict_sym_pos=False) if isinstance(dm1, numpy.ndarray) and dm1.ndim == 2: return reduce(numpy.dot, (p21, dm1, p21.conj().T)) else: return lib.einsum('pi,nij,qj->npq', p21, dm1, p21.conj())
def project_mo_nr2nr(mol1, mo1, mol2): r''' Project orbital coefficients .. math:: |\psi1> = |AO1> C1 |\psi2> = P |\psi1> = |AO2>S^{-1}<AO2| AO1> C1 = |AO2> C2 C2 = S^{-1}<AO2|AO1> C1 ''' s22 = mol2.intor_symmetric('cint1e_ovlp_sph') s21 = mole.intor_cross('cint1e_ovlp_sph', mol2, mol1) return lib.cho_solve(s22, numpy.dot(s21, mo1))
def project_mo_nr2nr(mol1, mo1, mol2): r''' Project orbital coefficients .. math:: |\psi1> = |AO1> C1 |\psi2> = P |\psi1> = |AO2>S^{-1}<AO2| AO1> C1 = |AO2> C2 C2 = S^{-1}<AO2|AO1> C1 ''' s22 = mol2.intor_symmetric('int1e_ovlp') s21 = mole.intor_cross('int1e_ovlp', mol2, mol1) return lib.cho_solve(s22, numpy.dot(s21, mo1))
def project_mo_nr2nr(mol1, mo1, mol2): r''' Project orbital coefficients from basis set 1 (C1 for mol1) to basis set 2 (C2 for mol2). .. math:: |\psi1\rangle = |AO1\rangle C1 |\psi2\rangle = P |\psi1\rangle = |AO2\rangle S^{-1}\langle AO2| AO1\rangle> C1 = |AO2\rangle> C2 C2 = S^{-1}\langle AO2|AO1\rangle C1 There are three relevant functions: :func:`project_mo_nr2nr` is the projection for non-relativistic (scalar) basis. :func:`project_mo_nr2r` projects from non-relativistic to relativistic basis. :func:`project_mo_r2r` is the projection between relativistic (spinor) basis. ''' s22 = mol2.intor_symmetric('int1e_ovlp') s21 = mole.intor_cross('int1e_ovlp', mol2, mol1) if isinstance(mo1, numpy.ndarray) and mo1.ndim == 2: return lib.cho_solve(s22, numpy.dot(s21, mo1)) else: return [lib.cho_solve(s22, numpy.dot(s21, x)) for x in mo1]
def project_dm_nr2r(mol1, dm1, mol2): __doc__ = project_dm_nr2nr.__doc__ assert(not mol1.cart) s22 = mol2.intor_symmetric('int1e_ovlp_spinor') s21 = mole.intor_cross('int1e_ovlp_sph', mol2, mol1) ua, ub = mol2.sph2spinor_coeff() s21 = numpy.dot(ua.T.conj(), s21) + numpy.dot(ub.T.conj(), s21) # (*) # mo2: alpha, beta have been summed in Eq. (*) # so DM = mo2[:,:nocc] * 1 * mo2[:,:nocc].H p21 = lib.cho_solve(s22, s21) if isinstance(dm1, numpy.ndarray) and dm1.ndim == 2: return reduce(numpy.dot, (p21, dm1, p21.conj().T)) else: return lib.einsum('pi,nij,qj->npq', p21, dm1, p21.conj())
def get_hcore(self, mol=None): '''1-component X2c Foldy-Wouthuysen (FW Hamiltonian (spin-free part only) ''' if mol is None: mol = self.mol if mol.has_ecp(): raise NotImplementedError xmol, contr_coeff = self.get_xmol(mol) c = lib.param.LIGHT_SPEED assert ('1E' in self.approx.upper()) t = xmol.intor_symmetric('int1e_kin') v = xmol.intor_symmetric('int1e_nuc') s = xmol.intor_symmetric('int1e_ovlp') w = xmol.intor_symmetric('int1e_pnucp') if 'get_xmat' in self.__dict__: # If the get_xmat method is overwritten by user, build the X # matrix with the external get_xmat method x = self.get_xmat(xmol) h1 = x2c._get_hcore_fw(t, v, w, s, x, c) elif 'ATOM' in self.approx.upper(): atom_slices = xmol.offset_nr_by_atom() nao = xmol.nao_nr() x = numpy.zeros((nao, nao)) for ia in range(xmol.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) t1 = xmol.intor('int1e_kin', shls_slice=shls_slice) s1 = xmol.intor('int1e_ovlp', shls_slice=shls_slice) with xmol.with_rinv_at_nucleus(ia): z = -xmol.atom_charge(ia) v1 = z * xmol.intor('int1e_rinv', shls_slice=shls_slice) w1 = z * xmol.intor('int1e_prinvp', shls_slice=shls_slice) x[p0:p1, p0:p1] = x2c._x2c1e_xmatrix(t1, v1, w1, s1, c) h1 = x2c._get_hcore_fw(t, v, w, s, x, c) else: h1 = x2c._x2c1e_get_hcore(t, v, w, s, c) if self.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp') s21 = gto.intor_cross('int1e_ovlp', xmol, mol) c = lib.cho_solve(s22, s21) h1 = reduce(numpy.dot, (c.T, h1, c)) if self.xuncontract and contr_coeff is not None: h1 = reduce(numpy.dot, (contr_coeff.T, h1, contr_coeff)) return h1
def build_Lpq_nonpbc(mydf, auxcell): if mydf.metric.upper() == "S": j3c = pyscf.df.incore.aux_e2(mydf.cell, auxcell, "cint3c1e_sph", aosym="s2ij") j2c = auxcell.intor_symmetric("cint1e_ovlp_sph") else: # mydf.metric.upper() == 'T' j3c = pyscf.df.incore.aux_e2(mydf.cell, auxcell, "cint3c1e_p2_sph", aosym="s2ij") j2c = auxcell.intor_symmetric("cint1e_kin_sph") * 2 naux = auxcell.nao_nr() nao = mydf.cell.nao_nr() nao_pair = nao * (nao + 1) // 2 with h5py.File(mydf._cderi) as feri: if "Lpq" in feri: del (feri["Lpq"]) chunks = (min(mydf.blockdim, naux), min(mydf.blockdim, nao_pair)) # 512K Lpq = feri.create_dataset("Lpq/0", (naux, nao_pair), "f8", chunks=chunks) Lpq[:] = lib.cho_solve(j2c, j3c.T)
def hcore_hess_generator(x2cobj, mol=None): '''nuclear gradients of 1-component X2c hcore Hamiltonian (spin-free part only) ''' if mol is None: mol = x2cobj.mol xmol, contr_coeff = x2cobj.get_xmol(mol) if x2cobj.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp') s21 = gto.intor_cross('int1e_ovlp', xmol, mol) contr_coeff = lib.cho_solve(s22, s21) get_h1_xmol = gen_sf_hfw(xmol, x2cobj.approx) def hcore_deriv(ia, ja): h1 = get_h1_xmol(ia, ja) if contr_coeff is not None: h1 = lib.einsum('pi,xypq,qj->xyij', contr_coeff, h1, contr_coeff) return numpy.asarray(h1) return hcore_deriv
def build_Lpq_nonpbc(mydf, auxcell): if mydf.metric.upper() == 'S': j3c = pyscf.df.incore.aux_e2(mydf.cell, auxcell, 'cint3c1e_sph', aosym='s2ij') j2c = auxcell.intor_symmetric('cint1e_ovlp_sph') else: # mydf.metric.upper() == 'T' j3c = pyscf.df.incore.aux_e2(mydf.cell, auxcell, 'cint3c1e_p2_sph', aosym='s2ij') j2c = auxcell.intor_symmetric('cint1e_kin_sph') * 2 naux = auxcell.nao_nr() nao = mydf.cell.nao_nr() nao_pair = nao * (nao+1) // 2 with h5py.File(mydf._cderi) as feri: if 'Lpq' in feri: del(feri['Lpq']) chunks = (min(mydf.blockdim,naux), min(mydf.blockdim,nao_pair)) # 512K Lpq = feri.create_dataset('Lpq/0', (naux,nao_pair), 'f8', chunks=chunks) Lpq[:] = lib.cho_solve(j2c, j3c.T)
def project(mfmo, init_mo, ncore, s): nocc = ncore + casscf.ncas if ncore > 0: mo0core = init_mo[:, :ncore] s1 = reduce(numpy.dot, (mfmo.T, s, mo0core)) s1core = reduce(numpy.dot, (mo0core.T, s, mo0core)) coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T)) coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore]) logger.debug(casscf, 'Core indices %s', coreidx) logger.debug(casscf, 'Core components %s', coreocc[coreidx]) # take HF core mocore = mfmo[:, coreidx] # take projected CAS space mocas = init_mo[:,ncore:nocc] \ - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc])) mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s) else: mocc = init_mo[:, :nocc] # remove core and active space from rest if mocc.shape[1] < mfmo.shape[1]: rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb = numpy.dot(rest, u[:, e > 1e-7]) if casscf.mol.symmetry: t = casscf.mol.intor_symmetric('int1e_kin') t = reduce(numpy.dot, (restorb.T, t, restorb)) e, u = numpy.linalg.eigh(t) restorb = numpy.dot(restorb, u) mo = numpy.hstack((mocc, restorb)) else: mo = mocc if casscf.verbose >= logger.DEBUG: s1 = reduce(numpy.dot, (mo[:, ncore:nocc].T, s, mfmo)) idx = numpy.argwhere(abs(s1) > 0.4) for i, j in idx: logger.debug(casscf, 'Init guess <mo-CAS|mo-hf> %d %d %12.8f', ncore + i + 1, j + 1, s1[i, j]) return mo
def project(mfmo, init_mo, ncore, s): nocc = ncore + casscf.ncas if ncore > 0: mo0core = init_mo[:,:ncore] s1 = reduce(numpy.dot, (mfmo.T, s, mo0core)) s1core = reduce(numpy.dot, (mo0core.T, s, mo0core)) coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T)) coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore]) logger.debug(casscf, 'Core indices %s', coreidx) logger.debug(casscf, 'Core components %s', coreocc[coreidx]) # take HF core mocore = mfmo[:,coreidx] # take projected CAS space mocas = init_mo[:,ncore:nocc] \ - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc])) mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s) else: mocc = init_mo[:,:nocc] # remove core and active space from rest if mocc.shape[1] < mfmo.shape[1]: rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb = numpy.dot(rest, u[:,e>1e-7]) if casscf.mol.symmetry: t = casscf.mol.intor_symmetric('cint1e_kin_sph') t = reduce(numpy.dot, (restorb.T, t, restorb)) e, u = numpy.linalg.eigh(t) restorb = numpy.dot(restorb, u) mo = numpy.hstack((mocc, restorb)) else: mo = mocc if casscf.verbose >= logger.DEBUG: s1 = reduce(numpy.dot, (mo[:,ncore:nocc].T, s, mfmo)) idx = numpy.argwhere(abs(s1) > 0.4) for i,j in idx: logger.debug(casscf, 'Init guess <mo-CAS|mo-hf> %d %d %12.8f', ncore+i+1, j+1, s1[i,j]) return mo
def get_hcore(self, mol=None): '''2-component X2c hcore Hamiltonian (including spin-free and spin-dependent terms) in the j-adapted spinor basis. ''' if mol is None: mol = self.mol xmol, contr_coeff_nr = self.get_xmol(mol) c = lib.param.LIGHT_SPEED assert ('1E' in self.approx.upper()) s = xmol.intor_symmetric('int1e_ovlp_spinor') t = xmol.intor_symmetric('int1e_spsp_spinor') * .5 v = xmol.intor_symmetric('int1e_nuc_spinor') w = xmol.intor_symmetric('int1e_spnucsp_spinor') if 'ATOM' in self.approx.upper(): atom_slices = xmol.offset_2c_by_atom() n2c = xmol.nao_2c() x = numpy.zeros((n2c, n2c), dtype=numpy.complex) for ia in range(xmol.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) s1 = xmol.intor('int1e_ovlp_spinor', shls_slice=shls_slice) t1 = xmol.intor('int1e_spsp_spinor', shls_slice=shls_slice) * .5 v1 = xmol.intor('int1e_nuc_spinor', shls_slice=shls_slice) w1 = xmol.intor('int1e_spnucsp_spinor', shls_slice=shls_slice) x[p0:p1, p0:p1] = _x2c1e_xmatrix(t1, v1, w1, s1, c) h1 = _get_hcore_fw(t, v, w, s, x, c) else: h1 = _x2c1e_get_hcore(t, v, w, s, c) if self.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp_spinor') s21 = mole.intor_cross('int1e_ovlp_spinor', xmol, mol) c = lib.cho_solve(s22, s21) h1 = reduce(numpy.dot, (c.T.conj(), h1, c)) elif self.xuncontract: np, nc = contr_coeff_nr.shape contr_coeff = numpy.zeros((np * 2, nc * 2)) contr_coeff[0::2, 0::2] = contr_coeff_nr contr_coeff[1::2, 1::2] = contr_coeff_nr h1 = reduce(numpy.dot, (contr_coeff.T.conj(), h1, contr_coeff)) return h1
def picture_change(self, even_operator=(None, None), odd_operator=None): mol = self.mol xmol, c = self.get_xmol(mol) pc_mat = self._picture_change(xmol, even_operator, odd_operator) if self.basis is not None: s22 = xmol.intor_symmetric('int1e_ovlp') s21 = mole.intor_cross('int1e_ovlp', xmol, mol) c = lib.cho_solve(s22, s21) elif self.xuncontract: pass else: return pc_mat c = _block_diag(c) if pc_mat.ndim == 2: return lib.einsum('pi,pq,qj->ij', c, pc_mat, c) else: return lib.einsum('pi,xpq,qj->xij', c, pc_mat, c)
def get_hcore(self, mol=None): if mol is None: mol = self.mol xmol, contr_coeff_nr = self.get_xmol(mol) c = lib.param.LIGHT_SPEED assert('1E' in self.approx.upper()) s = xmol.intor_symmetric('cint1e_ovlp') t = xmol.intor_symmetric('cint1e_spsp') * .5 v = xmol.intor_symmetric('cint1e_nuc') w = xmol.intor_symmetric('cint1e_spnucsp') if 'ATOM' in self.approx.upper(): atom_slices = xmol.offset_2c_by_atom() n2c = xmol.nao_2c() x = numpy.zeros((n2c,n2c), dtype=numpy.complex) for ia in range(xmol.natm): ish0, ish1, p0, p1 = atom_slices[ia] shls_slice = (ish0, ish1, ish0, ish1) s1 = xmol.intor('cint1e_ovlp', shls_slice=shls_slice) t1 = xmol.intor('cint1e_spsp', shls_slice=shls_slice) * .5 v1 = xmol.intor('cint1e_nuc', shls_slice=shls_slice) w1 = xmol.intor('cint1e_spnucsp', shls_slice=shls_slice) x[p0:p1,p0:p1] = _x2c1e_xmatrix(t1, v1, w1, s1, c) h1 = _get_hcore_fw(t, v, w, s, x, c) else: h1 = _x2c1e_get_hcore(t, v, w, s, c) if self.basis is not None: s22 = xmol.intor_symmetric('cint1e_ovlp') s21 = mole.intor_cross('cint1e_ovlp', xmol, mol) c = lib.cho_solve(s22, s21) h1 = reduce(numpy.dot, (c.T.conj(), h1, c)) elif self.xuncontract: np, nc = contr_coeff_nr.shape contr_coeff = numpy.zeros((np*2,nc*2)) contr_coeff[0::2,0::2] = contr_coeff_nr contr_coeff[1::2,1::2] = contr_coeff_nr h1 = reduce(numpy.dot, (contr_coeff.T.conj(), h1, contr_coeff)) return h1
def symmetrize_space(mol, mo, s=None, check=True): '''Symmetrize the given orbital space. This function is different to the :func:`symmetrize_orb`: In this function, the given orbitals are mixed to reveal the symmtery; :func:`symmetrize_orb` projects out non-symmetric components for each orbital. Args: mo : 2D float array The orbital space to symmetrize Kwargs: s : 2D float array Overlap matrix. If not given, overlap is computed with the input mol. Returns: 2D orbital coefficients Examples: >>> from pyscf import gto, symm, scf >>> mol = gto.M(atom = 'C 0 0 0; H 1 1 1; H -1 -1 1; H 1 -1 -1; H -1 1 -1', ... basis = 'sto3g') >>> mf = scf.RHF(mol).run() >>> mol.build(0, 0, symmetry='D2') >>> mo = symm.symmetrize_space(mol, mf.mo_coeff) >>> print(symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo)) ['A', 'A', 'A', 'B1', 'B1', 'B2', 'B2', 'B3', 'B3'] ''' from pyscf.tools import mo_mapping if s is None: s = mol.intor_symmetric('cint1e_ovlp_sph') nmo = mo.shape[1] mo_s = numpy.dot(mo.T, s) if check: assert (numpy.allclose(numpy.dot(mo_s, mo), numpy.eye(nmo))) mo1 = [] for i, csym in enumerate(mol.symm_orb): moso = numpy.dot(mo_s, csym) ovlpso = reduce(numpy.dot, (csym.T, s, csym)) # excluding orbitals which are already symmetrized try: diag = numpy.einsum('ik,ki->i', moso, lib.cho_solve(ovlpso, moso.T)) except: ovlpso[numpy.diag_indices(csym.shape[1])] += 1e-12 diag = numpy.einsum('ik,ki->i', moso, lib.cho_solve(ovlpso, moso.T)) idx = abs(1 - diag) < 1e-8 orb_exclude = mo[:, idx] mo1.append(orb_exclude) moso1 = moso[~idx] dm = numpy.dot(moso1.T, moso1) if dm.trace() > 1e-8: e, u = scipy.linalg.eigh(dm, ovlpso) mo1.append(numpy.dot(csym, u[:, abs(1 - e) < 1e-6])) mo1 = numpy.hstack(mo1) if mo1.shape[1] != nmo: raise ValueError('The input orbital space is not symmetrized.\n It is ' 'probably because the input mol and orbitals are of ' 'different orientation.') snorm = numpy.linalg.norm( reduce(numpy.dot, (mo1.T, s, mo1)) - numpy.eye(nmo)) if check and snorm > 1e-6: raise ValueError('Orbitals are not orthogonalized') idx = mo_mapping.mo_1to1map(reduce(numpy.dot, (mo.T, s, mo1))) return mo1[:, idx]
def label_orb_symm(mol, irrep_name, symm_orb, mo, s=None, check=True, tol=1e-9): """Label the symmetry of given orbitals irrep_name can be either the symbol or the ID of the irreducible representation. If the ID is provided, it returns the numeric code associated with XOR operator, see :py:meth:`symm.param.IRREP_ID_TABLE` Args: mol : an instance of :class:`Mole` irrep_name : list of str or int A list of irrep ID or name, it can be either mol.irrep_id or mol.irrep_name. It can affect the return "label". symm_orb : list of 2d array the symmetry adapted basis mo : 2d array the orbitals to label Returns: list of symbols or integers to represent the irreps for the given orbitals Examples: >>> from pyscf import gto, scf, symm >>> mol = gto.M(atom='H 0 0 0; H 0 0 1', basis='ccpvdz',verbose=0, symmetry=1) >>> mf = scf.RHF(mol) >>> mf.kernel() >>> symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mf.mo_coeff) ['Ag', 'B1u', 'Ag', 'B1u', 'B2u', 'B3u', 'Ag', 'B2g', 'B3g', 'B1u'] >>> symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mf.mo_coeff) [0, 5, 0, 5, 6, 7, 0, 2, 3, 5] """ nmo = mo.shape[1] if s is None: s = mol.intor_symmetric("cint1e_ovlp_sph") mo_s = numpy.dot(mo.T, s) norm = numpy.zeros((len(irrep_name), nmo)) for i, csym in enumerate(symm_orb): moso = numpy.dot(mo_s, csym) ovlpso = reduce(numpy.dot, (csym.T, s, csym)) try: norm[i] = numpy.einsum("ik,ki->i", moso, lib.cho_solve(ovlpso, moso.T)) except: ovlpso[numpy.diag_indices(csym.shape[1])] += 1e-12 norm[i] = numpy.einsum("ik,ki->i", moso, lib.cho_solve(ovlpso, moso.T)) norm /= numpy.sum(norm, axis=0) # for orbitals which are not normalized iridx = numpy.argmax(norm, axis=0) orbsym = numpy.asarray([irrep_name[i] for i in iridx]) logger.debug(mol, "irreps of each MO %s", orbsym) if check: largest_norm = norm[iridx, numpy.arange(nmo)] orbidx = numpy.where(largest_norm < 1 - tol)[0] if orbidx.size > 0: idx = numpy.where(largest_norm < 1 - tol * 1e2)[0] if idx.size > 0: raise ValueError("orbitals %s not symmetrized, norm = %s" % (idx, largest_norm[idx])) else: logger.warn(mol, "orbitals %s not strictly symmetrized.", numpy.unique(orbidx)) logger.warn(mol, "They can be symmetrized with " "pyscf.symm.symmetrize_space function.") logger.debug(mol, "norm = %s", largest_norm[orbidx]) return orbsym
def symmetrize_space(mol, mo, s=None, check=True): """Symmetrize the given orbital space. This function is different to the :func:`symmetrize_orb`: In this function, the given orbitals are mixed to reveal the symmtery; :func:`symmetrize_orb` projects out non-symmetric components for each orbital. Args: mo : 2D float array The orbital space to symmetrize Kwargs: s : 2D float array Overlap matrix. If not given, overlap is computed with the input mol. Returns: 2D orbital coefficients Examples: >>> from pyscf import gto, symm, scf >>> mol = gto.M(atom = 'C 0 0 0; H 1 1 1; H -1 -1 1; H 1 -1 -1; H -1 1 -1', ... basis = 'sto3g') >>> mf = scf.RHF(mol).run() >>> mol.build(0, 0, symmetry='D2') >>> mo = symm.symmetrize_space(mol, mf.mo_coeff) >>> print(symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo)) ['A', 'A', 'A', 'B1', 'B1', 'B2', 'B2', 'B3', 'B3'] """ from pyscf.tools import mo_mapping if s is None: s = mol.intor_symmetric("cint1e_ovlp_sph") nmo = mo.shape[1] mo_s = numpy.dot(mo.T, s) if check: assert numpy.allclose(numpy.dot(mo_s, mo), numpy.eye(nmo)) mo1 = [] for i, csym in enumerate(mol.symm_orb): moso = numpy.dot(mo_s, csym) ovlpso = reduce(numpy.dot, (csym.T, s, csym)) # excluding orbitals which are already symmetrized try: diag = numpy.einsum("ik,ki->i", moso, lib.cho_solve(ovlpso, moso.T)) except: ovlpso[numpy.diag_indices(csym.shape[1])] += 1e-12 diag = numpy.einsum("ik,ki->i", moso, lib.cho_solve(ovlpso, moso.T)) idx = abs(1 - diag) < 1e-8 orb_exclude = mo[:, idx] mo1.append(orb_exclude) moso1 = moso[~idx] dm = numpy.dot(moso1.T, moso1) if dm.trace() > 1e-8: e, u = scipy.linalg.eigh(dm, ovlpso) mo1.append(numpy.dot(csym, u[:, abs(1 - e) < 1e-6])) mo1 = numpy.hstack(mo1) if mo1.shape[1] != nmo: raise ValueError( "The input orbital space is not symmetrized.\n It is " "probably because the input mol and orbitals are of " "different orientation." ) snorm = numpy.linalg.norm(reduce(numpy.dot, (mo1.T, s, mo1)) - numpy.eye(nmo)) if check and snorm > 1e-6: raise ValueError("Orbitals are not orthogonalized") idx = mo_mapping.mo_1to1map(reduce(numpy.dot, (mo.T, s, mo1))) return mo1[:, idx]
def symmetrize_space(mol, mo, s=None, check=getattr(__config__, 'symm_addons_symmetrize_space_check', True), tol=getattr(__config__, 'symm_addons_symmetrize_space_tol', 1e-7)): '''Symmetrize the given orbital space. This function is different to the :func:`symmetrize_orb`: In this function, the given orbitals are mixed to reveal the symmtery; :func:`symmetrize_orb` projects out non-symmetric components for each orbital. Args: mo : 2D float array The orbital space to symmetrize Kwargs: s : 2D float array Overlap matrix. If not given, overlap is computed with the input mol. Returns: 2D orbital coefficients Examples: >>> from pyscf import gto, symm, scf >>> mol = gto.M(atom = 'C 0 0 0; H 1 1 1; H -1 -1 1; H 1 -1 -1; H -1 1 -1', ... basis = 'sto3g') >>> mf = scf.RHF(mol).run() >>> mol.build(0, 0, symmetry='D2') >>> mo = symm.symmetrize_space(mol, mf.mo_coeff) >>> print(symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo)) ['A', 'A', 'A', 'B1', 'B1', 'B2', 'B2', 'B3', 'B3'] ''' from pyscf.tools import mo_mapping if s is None: s = mol.intor_symmetric('int1e_ovlp') nmo = mo.shape[1] s_mo = numpy.dot(s, mo) if check and abs(numpy.dot(mo.conj().T, s_mo) - numpy.eye(nmo)).max() > tol: raise ValueError('Orbitals are not orthogonalized') mo1 = [] for i, csym in enumerate(mol.symm_orb): moso = numpy.dot(csym.T.conj(), s_mo) ovlpso = reduce(numpy.dot, (csym.T.conj(), s, csym)) # excluding orbitals which are already symmetrized try: diag = numpy.einsum('ki,ki->i', moso.conj(), lib.cho_solve(ovlpso, moso)) except numpy.linalg.LinAlgError: ovlpso[numpy.diag_indices(csym.shape[1])] += 1e-12 diag = numpy.einsum('ki,ki->i', moso.conj(), lib.cho_solve(ovlpso, moso)) idx = abs(1 - diag) < 1e-8 orb_exclude = mo[:, idx] mo1.append(orb_exclude) moso1 = moso[:, ~idx] dm = numpy.dot(moso1, moso1.T.conj()) if dm.trace() > 1e-8: e, u = scipy.linalg.eigh(dm, ovlpso) mo1.append(numpy.dot(csym, u[:, abs(1 - e) < 1e-6])) mo1 = numpy.hstack(mo1) if mo1.shape[1] != nmo: raise ValueError('The input orbital space is not symmetrized.\n One ' 'possible reason is that the input mol and orbitals ' 'are of different orientation.') if (check and abs(reduce(numpy.dot, (mo1.conj().T, s, mo1)) - numpy.eye(nmo)).max() > tol): raise ValueError('Orbitals are not orthogonalized') idx = mo_mapping.mo_1to1map(reduce(numpy.dot, (mo.T.conj(), s, mo1))) return mo1[:, idx]
def label_orb_symm(mol, irrep_name, symm_orb, mo, s=None, check=True, tol=1e-9): '''Label the symmetry of given orbitals irrep_name can be either the symbol or the ID of the irreducible representation. If the ID is provided, it returns the numeric code associated with XOR operator, see :py:meth:`symm.param.IRREP_ID_TABLE` Args: mol : an instance of :class:`Mole` irrep_name : list of str or int A list of irrep ID or name, it can be either mol.irrep_id or mol.irrep_name. It can affect the return "label". symm_orb : list of 2d array the symmetry adapted basis mo : 2d array the orbitals to label Returns: list of symbols or integers to represent the irreps for the given orbitals Examples: >>> from pyscf import gto, scf, symm >>> mol = gto.M(atom='H 0 0 0; H 0 0 1', basis='ccpvdz',verbose=0, symmetry=1) >>> mf = scf.RHF(mol) >>> mf.kernel() >>> symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mf.mo_coeff) ['Ag', 'B1u', 'Ag', 'B1u', 'B2u', 'B3u', 'Ag', 'B2g', 'B3g', 'B1u'] >>> symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, mf.mo_coeff) [0, 5, 0, 5, 6, 7, 0, 2, 3, 5] ''' nmo = mo.shape[1] if s is None: s = mol.intor_symmetric('cint1e_ovlp_sph') mo_s = numpy.dot(mo.T, s) norm = numpy.zeros((len(irrep_name), nmo)) for i, csym in enumerate(symm_orb): moso = numpy.dot(mo_s, csym) ovlpso = reduce(numpy.dot, (csym.T, s, csym)) try: norm[i] = numpy.einsum('ik,ki->i', moso, lib.cho_solve(ovlpso, moso.T)) except: ovlpso[numpy.diag_indices(csym.shape[1])] += 1e-12 norm[i] = numpy.einsum('ik,ki->i', moso, lib.cho_solve(ovlpso, moso.T)) norm /= numpy.sum(norm, axis=0) # for orbitals which are not normalized iridx = numpy.argmax(norm, axis=0) orbsym = numpy.asarray([irrep_name[i] for i in iridx]) logger.debug(mol, 'irreps of each MO %s', orbsym) if check: largest_norm = norm[iridx, numpy.arange(nmo)] orbidx = numpy.where(largest_norm < 1 - tol)[0] if orbidx.size > 0: idx = numpy.where(largest_norm < 1 - tol * 1e2)[0] if idx.size > 0: raise ValueError('orbitals %s not symmetrized, norm = %s' % (idx, largest_norm[idx])) else: logger.warn(mol, 'orbitals %s not strictly symmetrized.', numpy.unique(orbidx)) logger.warn( mol, 'They can be symmetrized with ' 'pyscf.symm.symmetrize_space function.') logger.debug(mol, 'norm = %s', largest_norm[orbidx]) return orbsym
def symmetrize_space(mol, mo, s=None, check=getattr(__config__, 'symm_addons_symmetrize_space_check', True), tol=getattr(__config__, 'symm_addons_symmetrize_space_tol', 1e-7)): '''Symmetrize the given orbital space. This function is different to the :func:`symmetrize_orb`: In this function, the given orbitals are mixed to reveal the symmtery; :func:`symmetrize_orb` projects out non-symmetric components for each orbital. Args: mo : 2D float array The orbital space to symmetrize Kwargs: s : 2D float array Overlap matrix. If not given, overlap is computed with the input mol. Returns: 2D orbital coefficients Examples: >>> from pyscf import gto, symm, scf >>> mol = gto.M(atom = 'C 0 0 0; H 1 1 1; H -1 -1 1; H 1 -1 -1; H -1 1 -1', ... basis = 'sto3g') >>> mf = scf.RHF(mol).run() >>> mol.build(0, 0, symmetry='D2') >>> mo = symm.symmetrize_space(mol, mf.mo_coeff) >>> print(symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo)) ['A', 'A', 'A', 'B1', 'B1', 'B2', 'B2', 'B3', 'B3'] ''' from pyscf.tools import mo_mapping if s is None: s = mol.intor_symmetric('int1e_ovlp') nmo = mo.shape[1] s_mo = numpy.dot(s, mo) if check and abs(numpy.dot(mo.conj().T, s_mo) - numpy.eye(nmo)).max() > tol: raise ValueError('Orbitals are not orthogonalized') mo1 = [] for i, csym in enumerate(mol.symm_orb): moso = numpy.dot(csym.T, s_mo) ovlpso = reduce(numpy.dot, (csym.T, s, csym)) # excluding orbitals which are already symmetrized try: diag = numpy.einsum('ki,ki->i', moso.conj(), lib.cho_solve(ovlpso, moso)) except: ovlpso[numpy.diag_indices(csym.shape[1])] += 1e-12 diag = numpy.einsum('ki,ki->i', moso.conj(), lib.cho_solve(ovlpso, moso)) idx = abs(1-diag) < 1e-8 orb_exclude = mo[:,idx] mo1.append(orb_exclude) moso1 = moso[:,~idx] dm = numpy.dot(moso1, moso1.T.conj()) if dm.trace() > 1e-8: e, u = scipy.linalg.eigh(dm, ovlpso) mo1.append(numpy.dot(csym, u[:,abs(1-e) < 1e-6])) mo1 = numpy.hstack(mo1) if mo1.shape[1] != nmo: raise ValueError('The input orbital space is not symmetrized.\n One ' 'possible reason is that the input mol and orbitals ' 'are of different orientation.') if (check and abs(reduce(numpy.dot, (mo1.conj().T, s, mo1)) - numpy.eye(nmo)).max() > tol): raise ValueError('Orbitals are not orthogonalized') idx = mo_mapping.mo_1to1map(reduce(numpy.dot, (mo.T, s, mo1))) return mo1[:,idx]