def project_dm_nr2nr(cell1, dm1, cell2, kpts=None): r''' Project density matrix representation from basis set 1 (cell1) to basis set 2 (cell2). .. 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 ''' s22 = cell2.pbc_intor('int1e_ovlp', hermi=1, kpts=kpts) s21 = pbcgto.intor_cross('int1e_ovlp', cell2, cell1, kpts=kpts) if kpts is None or numpy.shape(kpts) == (3, ): # A single k-point p21 = scipy.linalg.solve(s22, s21, sym_pos=True) return numpy.einsum( "pi,...ij,qj->...pq", p21, dm1, p21.conj(), optimize=True) # Ellipsis for potential spin dimension in UHF else: p21 = [ scipy.linalg.solve(s22[k], s21[k], sym_pos=True) for k, kpt in enumerate(kpts) ] return numpy.einsum("kpi,...kij,kqj->...kpq", p21, dm1, p21.conj(), optimize=True)
def get_nuc_less_accurate(mydf, kpts=None): log = logger.Logger(mydf.stdout, mydf.verbose) t1 = t0 = (time.clock(), time.time()) if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) nkpts = len(kpts_lst) if mydf._cderi is None: mydf.build() cell = mydf.cell fused_cell, fuse = fuse_auxcell_(mydf, mydf.auxcell) nao = cell.nao_nr() charge = -cell.atom_charges() j2c = pgto.intor_cross("cint2c2e_sph", fused_cell, _fake_nuc(cell)) jaux = j2c.dot(charge) jaux -= charge.sum() * mydf.auxbar(fused_cell) Gv = cell.get_Gv(mydf.gs) SI = cell.get_SI(Gv) # The normal nuclues have been considered in function get_gth_vlocG_part1 # The result vG is the potential in G-space for erf part of the pp nuclues and # "numpy.dot(charge, SI) * coulG" for normal nuclues. vpplocG = pgto.pseudo.pp_int.get_gth_vlocG_part1(cell, Gv) vG = -1.0 / cell.vol * numpy.einsum("ij,ij->j", SI, vpplocG) kpt_allow = numpy.zeros(3) if is_zero(kpts_lst): vj = numpy.zeros((nkpts, nao ** 2)) else: vj = numpy.zeros((nkpts, nao ** 2), dtype=numpy.complex128) max_memory = max(2000, mydf.max_memory - lib.current_memory()[0]) for k, pqkR, pqkI, p0, p1 in mydf.ft_loop(cell, mydf.gs, kpt_allow, kpts_lst, max_memory=max_memory): if not gamma_point(kpts_lst[k]): vj[k] += numpy.einsum("k,xk->x", vG.real, pqkI) * 1j vj[k] += numpy.einsum("k,xk->x", vG.imag, pqkR) * -1j vj[k] += numpy.einsum("k,xk->x", vG.real, pqkR) vj[k] += numpy.einsum("k,xk->x", vG.imag, pqkI) pqkR = pqkI = None Gv = cell.get_Gv(mydf.gs) aoaux = ft_ao.ft_ao(fused_cell, Gv) jaux -= numpy.einsum("x,xj->j", vG.real, aoaux.real) jaux -= numpy.einsum("x,xj->j", vG.imag, aoaux.imag) jaux = fuse(jaux) vj = vj.reshape(-1, nao, nao) for k, kpt in enumerate(kpts_lst): with mydf.load_Lpq((kpt, kpt)) as Lpq: v = 0 for p0, p1 in lib.prange(0, jaux.size, mydf.blockdim): v += numpy.dot(jaux[p0:p1], numpy.asarray(Lpq[p0:p1])) if gamma_point(kpt): vj[k] += lib.unpack_tril(numpy.asarray(v.real, order="C")) else: vj[k] += lib.unpack_tril(v) if kpts is None or numpy.shape(kpts) == (3,): vj = vj[0] return vj
def get_int1e_cross(intor, cell1, cell2, kpt=None, comp=1): r'''1-electron integrals from two molecules like .. math:: \langle \mu | intor | \nu \rangle, \mu \in cell1, \nu \in cell2 ''' return pgto.intor_cross(intor, cell1, cell2, comp, 0, kpt)
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 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 project_mo_nr2nr(cell1, mo1, cell2, kpt=None): 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 = cell2.pbc_intor('cint1e_ovlp_sph', hermi=1, kpts=kpt) s21 = pbcgto.intor_cross('cint1e_ovlp_sph', cell2, cell1, kpts=kpt) mo2 = numpy.dot(s21, mo1) return scipy.linalg.cho_solve(scipy.linalg.cho_factor(s22), mo2)
def project_mo_nr2nr(cell1, mo1, cell2, kpts=None): 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 = cell2.pbc_intor('int1e_ovlp', hermi=1, kpts=kpts) s21 = pbcgto.intor_cross('int1e_ovlp', cell2, cell1, kpts=kpts) if kpts is None or numpy.shape(kpts) == (3,): # A single k-point return scipy.linalg.solve(s22, s21.dot(mo1), sym_pos=True) else: assert(len(kpts) == len(mo1)) return [scipy.linalg.solve(s22[k], s21[k].dot(mo1[k]), sym_pos=True) for k, kpt in enumerate(kpts)]
def get_nuc(mydf, kpts=None): cell = mydf.cell if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) if mydf._cderi is None: mydf.build() log = logger.Logger(mydf.stdout, mydf.verbose) t1 = t0 = (time.clock(), time.time()) fused_cell, fuse = fuse_auxcell_(mydf, mydf.auxcell) nuccell = make_modchg_basis(cell, mydf.eta, 0) nuccell._bas = numpy.asarray(nuccell._bas[nuccell._bas[:, gto.ANG_OF] == 0], dtype=numpy.int32, order='C') charge = -cell.atom_charges() nucbar = sum([z / nuccell.bas_exp(i)[0] for i, z in enumerate(charge)]) nucbar *= numpy.pi / cell.vol vj = [v.ravel() for v in _int_nuc_vloc(cell, nuccell, kpts_lst)] t1 = log.timer_debug1('vnuc pass1: analytic int', *t1) j2c = pgto.intor_cross('cint2c2e_sph', fused_cell, nuccell) jaux = j2c.dot(charge) kpt_allow = numpy.zeros(3) coulG = tools.get_coulG(cell, kpt_allow, gs=mydf.gs) / cell.vol Gv = cell.get_Gv(mydf.gs) aoaux = ft_ao.ft_ao(nuccell, Gv) vGR = numpy.einsum('i,xi->x', charge, aoaux.real) * coulG vGI = numpy.einsum('i,xi->x', charge, aoaux.imag) * coulG max_memory = mydf.max_memory - lib.current_memory()[0] for k, pqkR, pqkI, p0, p1 \ in mydf.ft_loop(cell, mydf.gs, kpt_allow, kpts_lst, max_memory=max_memory): # rho_ij(G) nuc(-G) / G^2 # = [Re(rho_ij(G)) + Im(rho_ij(G))*1j] [Re(nuc(G)) - Im(nuc(G))*1j] / G^2 if not gamma_point(kpts_lst[k]): vj[k] += numpy.einsum('k,xk->x', vGR[p0:p1], pqkI) * 1j vj[k] += numpy.einsum('k,xk->x', vGI[p0:p1], pqkR) * -1j vj[k] += numpy.einsum('k,xk->x', vGR[p0:p1], pqkR) vj[k] += numpy.einsum('k,xk->x', vGI[p0:p1], pqkI) pqkR = pqkI = None t1 = log.timer_debug1('contracting Vnuc', *t1) vG = numpy.einsum('i,xi,x->x', charge, ft_ao.ft_ao(nuccell, Gv), coulG) aoaux = ft_ao.ft_ao(fused_cell, Gv) jaux -= numpy.einsum('x,xj->j', vG.real, aoaux.real) jaux -= numpy.einsum('x,xj->j', vG.imag, aoaux.imag) jaux -= charge.sum() * mydf.auxbar(fused_cell) jaux = fuse(jaux) aoaux = None ovlp = cell.pbc_intor('cint1e_ovlp_sph', 1, lib.HERMITIAN, kpts_lst) nao = cell.nao_nr() nao_pair = nao * (nao + 1) // 2 max_memory = max(2000, mydf.max_memory - lib.current_memory()[0]) blksize = max(16, min(int(max_memory * 1e6 / 16 / nao_pair), mydf.blockdim)) for k, kpt in enumerate(kpts_lst): with mydf.load_Lpq((kpt, kpt)) as Lpq: v = 0 for p0, p1 in lib.prange(0, jaux.size, blksize): v += numpy.dot(jaux[p0:p1], numpy.asarray(Lpq[p0:p1])) vj[k] = vj[k].reshape(nao, nao) - nucbar * ovlp[k] if gamma_point(kpt): vj[k] += lib.unpack_tril(numpy.asarray(v.real, order='C')) else: vj[k] += lib.unpack_tril(v) if kpts is None or numpy.shape(kpts) == (3, ): vj = vj[0] return vj
def get_nuc_less_accurate(mydf, kpts=None): log = logger.Logger(mydf.stdout, mydf.verbose) t1 = t0 = (time.clock(), time.time()) if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) nkpts = len(kpts_lst) if mydf._cderi is None: mydf.build() cell = mydf.cell fused_cell, fuse = fuse_auxcell_(mydf, mydf.auxcell) nao = cell.nao_nr() charge = -cell.atom_charges() j2c = pgto.intor_cross('cint2c2e_sph', fused_cell, _fake_nuc(cell)) jaux = j2c.dot(charge) jaux -= charge.sum() * mydf.auxbar(fused_cell) Gv = cell.get_Gv(mydf.gs) SI = cell.get_SI(Gv) # The normal nuclues have been considered in function get_gth_vlocG_part1 # The result vG is the potential in G-space for erf part of the pp nuclues and # "numpy.dot(charge, SI) * coulG" for normal nuclues. vpplocG = pgto.pseudo.pp_int.get_gth_vlocG_part1(cell, Gv) vG = -1. / cell.vol * numpy.einsum('ij,ij->j', SI, vpplocG) kpt_allow = numpy.zeros(3) if is_zero(kpts_lst): vj = numpy.zeros((nkpts, nao**2)) else: vj = numpy.zeros((nkpts, nao**2), dtype=numpy.complex128) max_memory = max(2000, mydf.max_memory - lib.current_memory()[0]) for k, pqkR, pqkI, p0, p1 \ in mydf.ft_loop(cell, mydf.gs, kpt_allow, kpts_lst, max_memory=max_memory): if not gamma_point(kpts_lst[k]): vj[k] += numpy.einsum('k,xk->x', vG.real, pqkI) * 1j vj[k] += numpy.einsum('k,xk->x', vG.imag, pqkR) * -1j vj[k] += numpy.einsum('k,xk->x', vG.real, pqkR) vj[k] += numpy.einsum('k,xk->x', vG.imag, pqkI) pqkR = pqkI = None Gv = cell.get_Gv(mydf.gs) aoaux = ft_ao.ft_ao(fused_cell, Gv) jaux -= numpy.einsum('x,xj->j', vG.real, aoaux.real) jaux -= numpy.einsum('x,xj->j', vG.imag, aoaux.imag) jaux = fuse(jaux) vj = vj.reshape(-1, nao, nao) for k, kpt in enumerate(kpts_lst): with mydf.load_Lpq((kpt, kpt)) as Lpq: v = 0 for p0, p1 in lib.prange(0, jaux.size, mydf.blockdim): v += numpy.dot(jaux[p0:p1], numpy.asarray(Lpq[p0:p1])) if gamma_point(kpt): vj[k] += lib.unpack_tril(numpy.asarray(v.real, order='C')) else: vj[k] += lib.unpack_tril(v) if kpts is None or numpy.shape(kpts) == (3, ): vj = vj[0] return vj
def get_nuc(mydf, kpts=None): cell = mydf.cell if kpts is None: kpts_lst = numpy.zeros((1,3)) else: kpts_lst = numpy.reshape(kpts, (-1,3)) if mydf._cderi is None: mydf.build() log = logger.Logger(mydf.stdout, mydf.verbose) t1 = t0 = (time.clock(), time.time()) auxcell = mydf.auxcell nuccell = make_modchg_basis(cell, mydf.eta, 0) nuccell._bas = numpy.asarray(nuccell._bas[nuccell._bas[:,gto.ANG_OF]==0], dtype=numpy.int32, order='C') charge = -cell.atom_charges() nucbar = sum([z/nuccell.bas_exp(i)[0] for i,z in enumerate(charge)]) nucbar *= numpy.pi/cell.vol vj = [v.ravel() for v in _int_nuc_vloc(cell, nuccell, kpts_lst)] t1 = log.timer_debug1('vnuc pass1: analytic int', *t1) j2c = pgto.intor_cross('cint2c2e_sph', auxcell, nuccell) jaux = j2c.dot(charge) kpt_allow = numpy.zeros(3) coulG = tools.get_coulG(cell, kpt_allow, gs=mydf.gs) / cell.vol Gv = cell.get_Gv(mydf.gs) aoaux = ft_ao.ft_ao(nuccell, Gv) vGR = numpy.einsum('i,xi->x', charge, aoaux.real) * coulG vGI = numpy.einsum('i,xi->x', charge, aoaux.imag) * coulG max_memory = mydf.max_memory - lib.current_memory()[0] for k, pqkR, pqkI, p0, p1 \ in mydf.ft_loop(cell, mydf.gs, kpt_allow, kpts_lst, max_memory=max_memory): # rho_ij(G) nuc(-G) / G^2 # = [Re(rho_ij(G)) + Im(rho_ij(G))*1j] [Re(nuc(G)) - Im(nuc(G))*1j] / G^2 if not gamma_point(kpts_lst[k]): vj[k] += numpy.einsum('k,xk->x', vGR[p0:p1], pqkI) * 1j vj[k] += numpy.einsum('k,xk->x', vGI[p0:p1], pqkR) *-1j vj[k] += numpy.einsum('k,xk->x', vGR[p0:p1], pqkR) vj[k] += numpy.einsum('k,xk->x', vGI[p0:p1], pqkI) t1 = log.timer_debug1('contracting Vnuc', *t1) # Append nuccell to auxcell, so that they can be FT together in pw_loop # the first [:naux] of ft_ao are aux fitting functions. nuccell._atm, nuccell._bas, nuccell._env = \ gto.conc_env(auxcell._atm, auxcell._bas, auxcell._env, nuccell._atm, nuccell._bas, nuccell._env) naux = auxcell.nao_nr() aoaux = ft_ao.ft_ao(nuccell, Gv) vG = numpy.einsum('i,xi,x->x', charge, aoaux[:,naux:], coulG) jaux -= numpy.einsum('x,xj->j', vG.real, aoaux[:,:naux].real) jaux -= numpy.einsum('x,xj->j', vG.imag, aoaux[:,:naux].imag) jaux -= charge.sum() * mydf.auxbar(auxcell) ovlp = cell.pbc_intor('cint1e_ovlp_sph', 1, lib.HERMITIAN, kpts_lst) nao = cell.nao_nr() nao_pair = nao * (nao+1) // 2 max_memory = max(2000, mydf.max_memory-lib.current_memory()[0]) blksize = max(16, min(int(max_memory*1e6/16/nao_pair), mydf.blockdim)) for k, kpt in enumerate(kpts_lst): with mydf.load_Lpq((kpt,kpt)) as Lpq: v = 0 for p0, p1 in lib.prange(0, jaux.size, blksize): v += numpy.dot(jaux[p0:p1], numpy.asarray(Lpq[p0:p1])) vj[k] = vj[k].reshape(nao,nao) - nucbar * ovlp[k] if gamma_point(kpt): vj[k] += lib.unpack_tril(numpy.asarray(v.real,order='C')) else: vj[k] += lib.unpack_tril(v) if kpts is None or numpy.shape(kpts) == (3,): vj = vj[0] return vj