def _mcol_lda_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi): '''Vxc matrix of multi-collinear LDA''' wv = weight * vxc if hermi: wv *= .5 # * .5 because of v+v.conj().T in r_vxc wr, wmx, wmy, wmz = wv # einsum('g,g,xgi,xgj->ij', vxc, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sx, vxc, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sy, vxc, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sz, vxc, weight, ao, ao) aow = None aow = _scale_ao(ao, wmx[0], out=aow) # Mx tmpx = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) aow = _scale_ao(ao, wmy[0], out=aow) # My tmpy = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) if hermi: # conj(mx+my*1j) == mx-my*1j, tmpx and tmpy should be real matba = (tmpx + tmpx.T) + (tmpy + tmpy.T) * 1j matab = np.zeros_like(matba) else: # conj(mx+my*1j) != mx-my*1j, tmpx and tmpy should be complex matba = tmpx + tmpy * 1j matab = tmpx - tmpy * 1j tmpx = tmpy = None aow = _scale_ao(ao, wr[0]+wmz[0], out=aow) # Mz mataa = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) aow = _scale_ao(ao, wr[0]-wmz[0], out=aow) # Mz matbb = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) mat = np.block([[mataa, matab], [matba, matbb]]) return mat
def _col_lda_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi, on_LL=True): '''Vxc matrix of collinear LDA''' # NOTE vxc in u/d representation aoa, aob = ao wv = weight * vxc if hermi: wv *= .5 if on_LL: wva, wvb = wv else: # for SS block # v_rho = (vxc_a + vxc_b) * .5 # v_mz = (vxc_a - vxc_b) * .5 # For small components, M = \beta\Sigma leads to # (v_rho - sigma_z*v_mz) = [vxc_b, 0 ] # [0 , vxc_a] wvb, wva = wv mat = _dot_ao_ao(mol, aoa, _scale_ao(aoa, wva[0]), mask, shls_slice, ao_loc) mat += _dot_ao_ao(mol, aob, _scale_ao(aob, wvb[0]), mask, shls_slice, ao_loc) return mat
def _col_gga_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi, on_LL=True): '''Vxc matrix of collinear GGA''' # NOTE vxc in u/d representation aoa, aob = ao wv = weight * vxc if hermi: wv[:, 0] *= .5 if on_LL: wva, wvb = wv else: # for SS block wvb, wva = wv aow = None aow = _scale_ao(aoa[:4], wva[:4], out=aow) mat = _dot_ao_ao(mol, aoa[0], aow, mask, shls_slice, ao_loc) aow = _scale_ao(aob[:4], wvb[:4], out=aow) mat += _dot_ao_ao(mol, aob[0], aow, mask, shls_slice, ao_loc) if hermi != 1: aow = _scale_ao(aoa[1:4], wva[1:4].conj(), out=aow) mat += _dot_ao_ao(mol, aow, aoa[0], mask, shls_slice, ao_loc) aow = _scale_ao(aob[1:4], wvb[1:4].conj(), out=aow) mat += _dot_ao_ao(mol, aow, aob[0], mask, shls_slice, ao_loc) return mat
def _tau_grad_dot_(vmat, mol, ao, wv, mask, ao_loc, dR1_on_bra=True): '''The tau part of MGGA functional''' aow = numint._scale_ao(ao[1], wv) _d1_dot_(vmat, mol, [ao[4], ao[5], ao[6]], aow, mask, ao_loc, True) aow = numint._scale_ao(ao[2], wv, aow) _d1_dot_(vmat, mol, [ao[5], ao[7], ao[8]], aow, mask, ao_loc, True) aow = numint._scale_ao(ao[3], wv, aow) _d1_dot_(vmat, mol, [ao[6], ao[8], ao[9]], aow, mask, ao_loc, True)
def mgga_sum_(vmat, ao, wv, mask): aow = numint._scale_ao(ao[:4], wv[:4]) tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) aow = numint._scale_ao(ao[1], wv[5], aow) tmp += numint._dot_ao_ao(mol, ao[1], aow, mask, shls_slice, ao_loc) aow = numint._scale_ao(ao[2], wv[5], aow) tmp += numint._dot_ao_ao(mol, ao[2], aow, mask, shls_slice, ao_loc) aow = numint._scale_ao(ao[3], wv[5], aow) tmp += numint._dot_ao_ao(mol, ao[3], aow, mask, shls_slice, ao_loc) vmat[0] += tmp + tmp.T rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv[:4], mask, ao_loc) rks_grad._tau_grad_dot_(vmat[1:], mol, ao, wv[5] * 2, mask, ao_loc, True)
def _ncol_lda_vxc_mat(mol, ao, weight, rho_tm, vxc, mask, shls_slice, ao_loc, hermi, on_LL=True): '''Vxc matrix of non-collinear LDA''' # NOTE vxc in u/d representation aoa, aob = ao r, mx, my, mz = rho_tm vxc = xc_deriv.ud2ts(vxc) vr, vs = vxc[:, 0] s = lib.norm(rho_tm[1:4], axis=0) wv = weight * vr with numpy.errstate(divide='ignore', invalid='ignore'): ws = vs * weight / s ws[s < 1e-20] = 0 if not on_LL: # flip the sign for small components because # M = \beta\Sigma = [sigma, 0 ] # [0 , -sigma] ws *= -1 # * .5 because of v+v.conj().T in r_vxc if hermi: wv *= .5 ws *= .5 # einsum('g,g,xgi,xgj->ij', vr, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sx, vs*m[0]/s, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sy, vs*m[1]/s, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sz, vs*m[2]/s, weight, ao, ao) aow = None aow = _scale_ao(aoa, ws * (mx + my * 1j), out=aow) mat = _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc) if hermi: mat = mat + mat.conj().T else: aow = _scale_ao(aob, ws * (mx - my * 1j), out=aow) # Mx mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc) aow = _scale_ao(aoa, wv + ws * mz, out=aow) # Mz mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc) aow = _scale_ao(aob, wv - ws * mz, out=aow) # Mz mat += _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc) return mat
def _mcol_mgga_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi, on_LL=True): '''Vxc matrix of multi-collinear MGGA''' # NOTE vxc in t/m representation aoa, aob = ao wv = weight * vxc tau_idx = 4 wv[:, tau_idx] *= .5 # *.5 for 1/2 in tau if hermi: wv[:, 0] *= .5 wv[:, tau_idx] *= .5 if not on_LL: # flip the sign for small components because # M = \beta\Sigma = [sigma, 0 ] # [0 , -sigma] wv[1:4] *= -1 wr, wmx, wmy, wmz = wv aow = None aow = _scale_ao(aoa[:4], wmx[:4] + wmy[:4] * 1j, out=aow) mat = _dot_ao_ao(mol, aob[0], aow, mask, shls_slice, ao_loc) mat += _tau_dot(mol, aob, aoa, wmx[tau_idx] + wmy[tau_idx] * 1j, mask, shls_slice, ao_loc) if hermi: assert vxc.dtype == numpy.double mat = mat + mat.conj().T else: aow = _scale_ao(aob[:4], wmx[:4] - wmy[:4] * 1j, out=aow) mat += _dot_ao_ao(mol, aoa[0], aow, mask, shls_slice, ao_loc) mat += _tau_dot(mol, aoa, aob, wmx[tau_idx] - wmy[tau_idx] * 1j, mask, shls_slice, ao_loc) aow = _scale_ao(aob[1:4], (wmx[1:4] + wmy[1:4] * 1j).conj(), out=aow) mat += _dot_ao_ao(mol, aow, aoa[0], mask, shls_slice, ao_loc) aow = _scale_ao(aoa[1:4], (wmx[1:4] - wmy[1:4] * 1j).conj(), out=aow) mat += _dot_ao_ao(mol, aow, aob[0], mask, shls_slice, ao_loc) aow = _scale_ao(aoa[1:4], (wr[1:4] + wmz[1:4]).conj(), out=aow) # Mz mat += _dot_ao_ao(mol, aow, aoa[0], mask, shls_slice, ao_loc) aow = _scale_ao(aob[1:4], (wr[1:4] - wmz[1:4]).conj(), out=aow) # Mz mat += _dot_ao_ao(mol, aow, aob[0], mask, shls_slice, ao_loc) aow = _scale_ao(aoa, wr[:4] + wmz[:4], out=aow) # Mz mat += _dot_ao_ao(mol, aoa[0], aow, mask, shls_slice, ao_loc) mat += _tau_dot(mol, aoa, aoa, wr[tau_idx] + wmz[tau_idx], mask, shls_slice, ao_loc) aow = _scale_ao(aob, wr[:4] - wmz[:4], out=aow) # Mz mat += _dot_ao_ao(mol, aob[0], aow, mask, shls_slice, ao_loc) mat += _tau_dot(mol, aob, aob, wr[tau_idx] - wmz[tau_idx], mask, shls_slice, ao_loc) return mat
def _gga_grad_sum_(vmat, mol, ao, wv, mask, ao_loc): #:aow = numpy.einsum('npi,np->pi', ao[:4], wv[:4]) aow = numint._scale_ao(ao[:4], wv[:4]) _d1_dot_(vmat, mol, ao[1:4], aow, mask, ao_loc, True) aow = _make_dR_dao_w(ao, wv[:4]) _d1_dot_(vmat, mol, aow, ao[0], mask, ao_loc, True) return vmat
def get_veff_nuc_epc(self, mol, dm, dm_last=None, vhf_last=None, hermi=1): '''Add EPC contribution to nuclear veff''' nao = mol.nao_nr() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() nnuc = 0 excsum = 0 vmat = numpy.zeros((nao, nao)) grids = self.mf_elec.grids ni = self.mf_elec._numint aow = None for ao, mask, weight, coords in ni.block_loop(mol, grids, nao): aow = numpy.ndarray(ao.shape, order='F', buffer=aow) ao_elec = eval_ao(self.mol.elec, coords) if self.dm_elec.ndim > 2: rho_elec = eval_rho(self.mol.elec, ao_elec, self.dm_elec[0] + self.dm_elec[1]) else: rho_elec = eval_rho(self.mol.elec, ao_elec, self.dm_elec) ao_nuc = eval_ao(mol, coords) rho_nuc = eval_rho(mol, ao_nuc, dm) exc, vxc = eval_xc_nuc(self.epc, rho_elec, rho_nuc) den = rho_nuc * weight nnuc += den.sum() excsum += numpy.dot(den, exc) # times 0.5 because vmat + vmat.T aow = _scale_ao(ao_nuc, 0.5 * weight * vxc, out=aow) vmat += _dot_ao_ao(mol, ao_nuc, aow, mask, shls_slice, ao_loc) logger.debug(self, 'The number of nuclei: %.5f', nnuc) vmat += vmat.conj().T # attach E_ep to vmat to retrieve later vmat = lib.tag_array(vmat, exc=excsum, ecoul=0, vj=0, vk=0) return vmat
def get_veff_elec_epc(self, mol, dm, dm_last=None, vhf_last=None, hermi=1): '''Add EPC contribution to electronic veff''' nao = mol.nao_nr() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((nao, nao)) grids = self.mf_elec.grids ni = self.mf_elec._numint aow = None for i in range(self.mol.nuc_num): ia = self.mol.nuc[i].atom_index if self.mol.atom_symbol(ia) == 'H': for ao, mask, weight, coords in ni.block_loop(mol, grids, nao): aow = numpy.ndarray(ao.shape, order='F', buffer=aow) ao_elec = eval_ao(mol, coords) if dm.ndim > 2: rho_elec = eval_rho(mol, ao_elec, dm[0] + dm[1]) else: rho_elec = eval_rho(mol, ao_elec, dm) ao_nuc = eval_ao(self.mol.nuc[i], coords) rho_nuc = eval_rho(self.mol.nuc[i], ao_nuc, self.dm_nuc[i]) vxc_i = eval_xc_elec(self.epc, rho_elec, rho_nuc) # times 0.5 because vmat + vmat.T aow = _scale_ao(ao_elec, 0.5 * weight * vxc_i, out=aow) vmat += _dot_ao_ao(mol, ao_elec, aow, mask, shls_slice, ao_loc) vmat += vmat.conj().T if dm.ndim > 2: veff = dft.uks.get_veff(self.mf_elec, mol, dm, dm_last, vhf_last, hermi) else: veff = dft.rks.get_veff(self.mf_elec, mol, dm, dm_last, vhf_last, hermi) vxc = lib.tag_array(veff + vmat, ecoul=veff.ecoul, exc=veff.exc, vj=veff.vj, vk=veff.vk) return vxc
def _contract_vot_ao(vot, ao, out=None): ''' REQUIRES array in shape = (nderiv,nao,ngrids) and data layout = (nderiv,ngrids,nao)/row-major ''' nderiv = vot.shape[0] ao = np.ascontiguousarray(ao.transpose(0, 2, 1)) #vao = (ao[0][None,:,:] * vot[:,None,:]).transpose (0,2,1) #ao = ao.transpose (0,2,1) #if nderiv > 1: #vao[0] += (ao[1:4] * vot[1:4,:,None]).sum (0) #vao[0] += numint._scale_ao (ao[1:4], vot[1:4]) nao, ngrids = ao.shape[1:] vao = np.ndarray((nderiv, nao, ngrids), dtype=ao.dtype, buffer=out).transpose(0, 2, 1) ao = ao.transpose(0, 2, 1) vao[0] = numint._scale_ao(ao[:nderiv], vot, out=vao[0]) if nderiv > 1: for i in range(1, 4): vao[i] = numint._scale_ao(ao[0:1, :, :], vot[i:i + 1, :], out=vao[i]) return vao
def _mcol_lda_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi, on_LL=True): '''Vxc matrix of multi-collinear LDA''' # NOTE vxc in t/m representation aoa, aob = ao wv = weight * vxc if hermi: wv *= .5 # * .5 because of v+v.conj().T in r_vxc if not on_LL: # flip the sign for small components because # M = \beta\Sigma = [sigma, 0 ] # [0 , -sigma] wv[1:4] *= -1 wr, wmx, wmy, wmz = wv # einsum('g,g,xgi,xgj->ij', vxc, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sx, vxc, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sy, vxc, weight, ao, ao) # + einsum('xy,g,g,xgi,ygj->ij', sz, vxc, weight, ao, ao) aow = None aow = _scale_ao(aoa, wmx[0] + wmy[0] * 1j, out=aow) mat = _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc) if hermi: assert vxc.dtype == numpy.double mat = mat + mat.conj().T else: aow = _scale_ao(aob, wmx[0] - wmy[0] * 1j, out=aow) mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc) aow = _scale_ao(aoa, wr[0] + wmz[0], out=aow) # Mz mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc) aow = _scale_ao(aob, wr[0] - wmz[0], out=aow) # Mz mat += _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc) return mat
def _ncol_lda_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi): '''Vxc matrix of non-collinear LDA''' # NOTE vxc in u/d representation r, mx, my, mz = rho vxc = xc_deriv.ud2ts(vxc) vr, vs = vxc[:,0] s = lib.norm(rho[1:4], axis=0) wv = weight * vr with np.errstate(divide='ignore',invalid='ignore'): ws = vs * weight / s ws[s < 1e-20] = 0 # * .5 because of v+v.conj().T in r_vxc if hermi: wv *= .5 ws *= .5 aow = None aow = _scale_ao(ao, ws*mx, out=aow) # Mx tmpx = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) aow = _scale_ao(ao, ws*my, out=aow) # My tmpy = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) if hermi: # conj(mx+my*1j) == mx-my*1j, tmpx and tmpy should be real matba = (tmpx + tmpx.T) + (tmpy + tmpy.T) * 1j matab = np.zeros_like(matba) else: # conj(mx+my*1j) != mx-my*1j, tmpx and tmpy should be complex matba = tmpx + tmpy * 1j matab = tmpx - tmpy * 1j tmpx = tmpy = None aow = _scale_ao(ao, wv+ws*mz, out=aow) # Mz mataa = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) aow = _scale_ao(ao, wv-ws*mz, out=aow) # Mz matbb = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) mat = np.block([[mataa, matab], [matba, matbb]]) return mat
def _mcol_mgga_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi): '''Vxc matrix of multi-collinear MGGA''' wv = weight * vxc tau_idx = 4 wv[:,tau_idx] *= .5 # *.5 for 1/2 in tau if hermi: wv[:,0] *= .5 # * .5 because of v+v.conj().T in r_vxc wv[:,tau_idx] *= .5 wr, wmx, wmy, wmz = wv aow = None aow = _scale_ao(ao[:4], wr[:4]+wmz[:4], out=aow) # Mz mataa = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) mataa += _tau_dot(mol, ao, ao, wr[tau_idx]+wmz[tau_idx], mask, shls_slice, ao_loc) aow = _scale_ao(ao[:4], wr[:4]-wmz[:4], out=aow) # Mz matbb = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) matbb += _tau_dot(mol, ao, ao, wr[tau_idx]-wmz[tau_idx], mask, shls_slice, ao_loc) aow = _scale_ao(ao[:4], wmx[:4], out=aow) # Mx tmpx = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) tmpx += _tau_dot(mol, ao, ao, wmx[tau_idx], mask, shls_slice, ao_loc) aow = _scale_ao(ao[:4], wmy[:4], out=aow) # My tmpy = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) tmpy += _tau_dot(mol, ao, ao, wmy[tau_idx], mask, shls_slice, ao_loc) if hermi: assert vxc.dtype == np.double # conj(mx+my*1j) == mx-my*1j, tmpx and tmpy should be real matba = (tmpx + tmpx.T) + (tmpy + tmpy.T) * 1j matab = np.zeros_like(matba) else: # conj(mx+my*1j) != mx-my*1j, tmpx and tmpy should be complex aow = _scale_ao(ao[1:4], wmx[1:4].conj(), out=aow) # Mx tmpx += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) aow = _scale_ao(ao[1:4], wmy[1:4].conj(), out=aow) # My tmpy += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) matba = tmpx + tmpy * 1j matab = tmpx - tmpy * 1j aow = _scale_ao(ao[1:4], (wr[1:4]+wmz[1:4]).conj(), out=aow) # Mz mataa += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) aow = _scale_ao(ao[1:4], (wr[1:4]-wmz[1:4]).conj(), out=aow) # Mz matbb += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) mat = np.block([[mataa, matab], [matba, matbb]]) return mat
def make_psi_vmat(pcmobj, dm, r_vdw, ui, ylm_1sph, cached_pol, Xvec, L, with_nuc=True): ''' The first order derivative of E_ddCOSMO wrt density matrix Kwargs: with_nuc (bool): Mute the contribution of nuclear charges when computing the second order derivatives of energy. ''' mol = pcmobj.mol natm = mol.natm lmax = pcmobj.lmax nlm = (lmax + 1)**2 dms = numpy.asarray(dm) is_single_dm = dms.ndim == 2 grids = pcmobj.grids ni = numint.NumInt() max_memory = pcmobj.max_memory - lib.current_memory()[0] make_rho, n_dm, nao = ni._gen_rho_evaluator(mol, dms) dms = dms.reshape(n_dm, nao, nao) Xvec = Xvec.reshape(n_dm, natm, nlm) i1 = 0 scaled_weights = numpy.empty((n_dm, grids.weights.size)) for ia in range(natm): fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)] fac_pol = _vstack_factor_fak_pol(fak_pol, lmax) i0, i1 = i1, i1 + fac_pol.shape[1] scaled_weights[:, i0:i1] = numpy.einsum('mn,im->in', fac_pol, Xvec[:, ia]) scaled_weights *= grids.weights shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() den = numpy.empty((n_dm, grids.weights.size)) vmat = numpy.zeros((n_dm, nao, nao)) p1 = 0 aow = None for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, 0, max_memory): p0, p1 = p1, p1 + weight.size for i in range(n_dm): den[i, p0:p1] = make_rho(i, ao, mask, 'LDA') aow = numint._scale_ao(ao, scaled_weights[i, p0:p1], out=aow) vmat[i] -= numint._dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc) den *= grids.weights ao = aow = scaled_weights = None nelec_leak = 0 psi = numpy.zeros((n_dm, natm, nlm)) i1 = 0 for ia in range(natm): fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)] fac_pol = _vstack_factor_fak_pol(fak_pol, lmax) i0, i1 = i1, i1 + fac_pol.shape[1] nelec_leak += den[:, i0:i1][:, leak_idx].sum(axis=1) psi[:, ia] = -numpy.einsum('in,mn->im', den[:, i0:i1], fac_pol) logger.debug(pcmobj, 'electron leaks %s', nelec_leak) # Contribution of nuclear charges to the total density # The factor numpy.sqrt(4*numpy.pi) is due to the product of 4*pi * Y_0^0 if with_nuc: for ia in range(natm): psi[:, ia, 0] += numpy.sqrt( 4 * numpy.pi) / r_vdw[ia] * mol.atom_charge(ia) # <Psi, L^{-1}g> -> Psi = SL the adjoint equation to LX = g L_S = numpy.linalg.solve( L.reshape(natm * nlm, -1).T, psi.reshape(n_dm, -1).T) L_S = L_S.reshape(natm, nlm, n_dm).transpose(2, 0, 1) coords_1sph, weights_1sph = make_grids_one_sphere(pcmobj.lebedev_order) # JCP, 141, 184108, Eq (39) xi_jn = numpy.einsum('n,jn,xn,ijx->ijn', weights_1sph, ui, ylm_1sph, L_S) extern_point_idx = ui > 0 cav_coords = (mol.atom_coords().reshape(natm, 1, 3) + numpy.einsum('r,gx->rgx', r_vdw, coords_1sph)) cav_coords = cav_coords[extern_point_idx] xi_jn = xi_jn[:, extern_point_idx] max_memory = pcmobj.max_memory - lib.current_memory()[0] blksize = int(max(max_memory * .9e6 / 8 / nao**2, 400)) cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env, 'int3c2e') vmat_tril = 0 for i0, i1 in lib.prange(0, cav_coords.shape[0], blksize): fakemol = gto.fakemol_for_charges(cav_coords[i0:i1]) v_nj = df.incore.aux_e2(mol, fakemol, intor='int3c2e', aosym='s2ij', cintopt=cintopt) vmat_tril += numpy.einsum('xn,in->ix', v_nj, xi_jn[:, i0:i1]) vmat += lib.unpack_tril(vmat_tril) if is_single_dm: psi = psi[0] L_S = L_S[0] vmat = vmat[0] return psi, vmat, L_S
def _get_vxc_diag(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff[0].shape ni = mf._numint xctype = ni._xc_type(mf.xc) shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmata = numpy.zeros((6, nao, nao)) vmatb = numpy.zeros((6, nao, nao)) if xctype == 'LDA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask, xctype) vxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=1)[1] vrho = vxc[0] aowa = numint._scale_ao(ao[0], weight * vrho[:, 0]) aowb = numint._scale_ao(ao[0], weight * vrho[:, 1]) for i in range(6): vmata[i] += numint._dot_ao_ao(mol, ao[i + 4], aowa, mask, shls_slice, ao_loc) vmatb[i] += numint._dot_ao_ao(mol, ao[i + 4], aowb, mask, shls_slice, ao_loc) aowa = aowb = None elif xctype == 'GGA': def contract_(mat, ao, aoidx, wv, mask): aow = numint._scale_ao(ao[aoidx[0]], wv[1]) aow += numint._scale_ao(ao[aoidx[1]], wv[2]) aow += numint._scale_ao(ao[aoidx[2]], wv[3]) mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) ao_deriv = 3 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[:4], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[:4], mo_coeff[1], mo_occ[1], mask, xctype) vxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=1)[1] wva, wvb = numint._uks_gga_wv0((rhoa, rhob), vxc, weight) # *2 because v.T is not applied. wva[0] *= 2 wvb[0] *= 2 aowa = numint._scale_ao(ao[:4], wva[:4]) aowb = numint._scale_ao(ao[:4], wvb[:4]) for i in range(6): vmata[i] += numint._dot_ao_ao(mol, ao[i + 4], aowa, mask, shls_slice, ao_loc) vmatb[i] += numint._dot_ao_ao(mol, ao[i + 4], aowb, mask, shls_slice, ao_loc) contract_(vmata[0], ao, [XXX, XXY, XXZ], wva, mask) contract_(vmata[1], ao, [XXY, XYY, XYZ], wva, mask) contract_(vmata[2], ao, [XXZ, XYZ, XZZ], wva, mask) contract_(vmata[3], ao, [XYY, YYY, YYZ], wva, mask) contract_(vmata[4], ao, [XYZ, YYZ, YZZ], wva, mask) contract_(vmata[5], ao, [XZZ, YZZ, ZZZ], wva, mask) contract_(vmatb[0], ao, [XXX, XXY, XXZ], wvb, mask) contract_(vmatb[1], ao, [XXY, XYY, XYZ], wvb, mask) contract_(vmatb[2], ao, [XXZ, XYZ, XZZ], wvb, mask) contract_(vmatb[3], ao, [XYY, YYY, YYZ], wvb, mask) contract_(vmatb[4], ao, [XYZ, YYZ, YZZ], wvb, mask) contract_(vmatb[5], ao, [XZZ, YZZ, ZZZ], wvb, mask) vxc = aowa = aowb = None elif xctype == 'MGGA': def contract_(mat, ao, aoidx, wv, mask): aow = numint._scale_ao(ao[aoidx[0]], wv[1]) aow += numint._scale_ao(ao[aoidx[1]], wv[2]) aow += numint._scale_ao(ao[aoidx[2]], wv[3]) mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) ao_deriv = 3 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[:10], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[:10], mo_coeff[1], mo_occ[1], mask, xctype) vxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=1)[1] wva, wvb = numint._uks_mgga_wv0((rhoa, rhob), vxc, weight) # *2 because v.T is not applied. wva[0] *= 2 wvb[0] *= 2 wva[5] *= 2 wvb[5] *= 2 aowa = numint._scale_ao(ao[:4], wva[:4]) aowb = numint._scale_ao(ao[:4], wvb[:4]) for i in range(6): vmata[i] += numint._dot_ao_ao(mol, ao[i + 4], aowa, mask, shls_slice, ao_loc) vmatb[i] += numint._dot_ao_ao(mol, ao[i + 4], aowb, mask, shls_slice, ao_loc) contract_(vmata[0], ao, [XXX, XXY, XXZ], wva, mask) contract_(vmata[1], ao, [XXY, XYY, XYZ], wva, mask) contract_(vmata[2], ao, [XXZ, XYZ, XZZ], wva, mask) contract_(vmata[3], ao, [XYY, YYY, YYZ], wva, mask) contract_(vmata[4], ao, [XYZ, YYZ, YZZ], wva, mask) contract_(vmata[5], ao, [XZZ, YZZ, ZZZ], wva, mask) contract_(vmatb[0], ao, [XXX, XXY, XXZ], wvb, mask) contract_(vmatb[1], ao, [XXY, XYY, XYZ], wvb, mask) contract_(vmatb[2], ao, [XXZ, XYZ, XZZ], wvb, mask) contract_(vmatb[3], ao, [XYY, YYY, YYZ], wvb, mask) contract_(vmatb[4], ao, [XYZ, YYZ, YZZ], wvb, mask) contract_(vmatb[5], ao, [XZZ, YZZ, ZZZ], wvb, mask) aowa = [numint._scale_ao(ao[i], wva[5]) for i in range(1, 4)] aowb = [numint._scale_ao(ao[i], wvb[5]) for i in range(1, 4)] for i, j in enumerate([XXX, XXY, XXZ, XYY, XYZ, XZZ]): vmata[i] += numint._dot_ao_ao(mol, ao[j], aowa[0], mask, shls_slice, ao_loc) vmatb[i] += numint._dot_ao_ao(mol, ao[j], aowb[0], mask, shls_slice, ao_loc) for i, j in enumerate([XXY, XYY, XYZ, YYY, YYZ, YZZ]): vmata[i] += numint._dot_ao_ao(mol, ao[j], aowa[1], mask, shls_slice, ao_loc) vmatb[i] += numint._dot_ao_ao(mol, ao[j], aowb[1], mask, shls_slice, ao_loc) for i, j in enumerate([XXZ, XYZ, XZZ, YYZ, YZZ, ZZZ]): vmata[i] += numint._dot_ao_ao(mol, ao[j], aowa[2], mask, shls_slice, ao_loc) vmatb[i] += numint._dot_ao_ao(mol, ao[j], aowb[2], mask, shls_slice, ao_loc) vmata = vmata[[0, 1, 2, 1, 3, 4, 2, 4, 5]].reshape(3, 3, nao, nao) vmatb = vmatb[[0, 1, 2, 1, 3, 4, 2, 4, 5]].reshape(3, 3, nao, nao) return vmata, vmatb
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff[0].shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0a, dm0b = mf.make_rdm1(mo_coeff, mo_occ) vmata = numpy.zeros((mol.natm, 3, 3, nao, nao)) vmatb = numpy.zeros((mol.natm, 3, 3, nao, nao)) ipipa = numpy.zeros((3, 3, nao, nao)) ipipb = numpy.zeros((3, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3] vrho = vxc[0] u_u, u_d, d_d = fxc[0].T aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight * vrho[:, 0]) rks_hess._d1d2_dot_(ipipa, mol, aow, ao[1:4], mask, ao_loc, False) aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight * vrho[:, 1]) rks_hess._d1d2_dot_(ipipb, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0a = numint._dot_ao_dm(mol, ao[0], dm0a, mask, shls_slice, ao_loc) ao_dm0b = numint._dot_ao_dm(mol, ao[0], dm0b, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # *2 for \nabla|ket> in rho1 rho1a = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0a[:, p0:p1]) * 2 rho1b = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0b[:, p0:p1]) * 2 wv = u_u * rho1a + u_d * rho1b wv *= weight # aow ~ rho1 ~ d/dR1 aow = numpy.einsum('pi,xp->xpi', ao[0], wv) rks_hess._d1d2_dot_(vmata[ia], mol, ao[1:4], aow, mask, ao_loc, False) wv = u_d * rho1a + d_d * rho1b wv *= weight aow = numpy.einsum('pi,xp->xpi', ao[0], wv) rks_hess._d1d2_dot_(vmatb[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0a = ao_dm0b = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmata[ia, :, :, :, p0:p1] += ipipa[:, :, :, p0:p1] vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, :, p0:p1] elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[:4], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[:4], mo_coeff[1], mo_occ[1], mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3] wva, wvb = numint._uks_gga_wv0((rhoa, rhob), vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wva) rks_hess._d1d2_dot_(ipipa, mol, aow, ao[1:4], mask, ao_loc, False) aow = rks_grad._make_dR_dao_w(ao, wvb) rks_hess._d1d2_dot_(ipipb, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0a = [ numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc) for i in range(4) ] ao_dm0b = [ numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wva = dR_rho1a = rks_hess._make_dR_rho1( ao, ao_dm0a, ia, aoslices) wvb = dR_rho1b = rks_hess._make_dR_rho1( ao, ao_dm0b, ia, aoslices) wva[0], wvb[0] = numint._uks_gga_wv1( (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight) wva[1], wvb[1] = numint._uks_gga_wv1( (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight) wva[2], wvb[2] = numint._uks_gga_wv1( (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wva[0]) rks_grad._d1_dot_(vmata[ia, 0], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wva[1]) rks_grad._d1_dot_(vmata[ia, 1], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wva[2]) rks_grad._d1_dot_(vmata[ia, 2], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)] rks_hess._d1d2_dot_(vmata[ia], mol, ao[1:4], aow, mask, ao_loc, False) aow = rks_grad._make_dR_dao_w(ao, wvb[0]) rks_grad._d1_dot_(vmatb[ia, 0], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wvb[1]) rks_grad._d1_dot_(vmatb[ia, 1], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wvb[2]) rks_grad._d1_dot_(vmatb[ia, 2], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)] rks_hess._d1d2_dot_(vmatb[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0a = ao_dm0b = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmata[ia, :, :, :, p0:p1] += ipipa[:, :, :, p0:p1] vmata[ia, :, :, :, p0:p1] += ipipa[:, :, p0:p1].transpose(1, 0, 3, 2) vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, :, p0:p1] vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, p0:p1].transpose(1, 0, 3, 2) elif xctype == 'MGGA': XX, XY, XZ = 4, 5, 6 YX, YY, YZ = 5, 7, 8 ZX, ZY, ZZ = 6, 8, 9 ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[:10], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[:10], mo_coeff[1], mo_occ[1], mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3] wva, wvb = numint._uks_mgga_wv0((rhoa, rhob), vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wva) rks_hess._d1d2_dot_(ipipa, mol, aow, ao[1:4], mask, ao_loc, False) aow = rks_grad._make_dR_dao_w(ao, wvb) rks_hess._d1d2_dot_(ipipb, mol, aow, ao[1:4], mask, ao_loc, False) aow = [numint._scale_ao(ao[i], wva[5]) for i in range(4, 10)] rks_hess._d1d2_dot_(ipipa, mol, [aow[0], aow[1], aow[2]], [ao[XX], ao[XY], ao[XZ]], mask, ao_loc, False) rks_hess._d1d2_dot_(ipipa, mol, [aow[1], aow[3], aow[4]], [ao[YX], ao[YY], ao[YZ]], mask, ao_loc, False) rks_hess._d1d2_dot_(ipipa, mol, [aow[2], aow[4], aow[5]], [ao[ZX], ao[ZY], ao[ZZ]], mask, ao_loc, False) aow = [numint._scale_ao(ao[i], wvb[5]) for i in range(4, 10)] rks_hess._d1d2_dot_(ipipb, mol, [aow[0], aow[1], aow[2]], [ao[XX], ao[XY], ao[XZ]], mask, ao_loc, False) rks_hess._d1d2_dot_(ipipb, mol, [aow[1], aow[3], aow[4]], [ao[YX], ao[YY], ao[YZ]], mask, ao_loc, False) rks_hess._d1d2_dot_(ipipb, mol, [aow[2], aow[4], aow[5]], [ao[ZX], ao[ZY], ao[ZZ]], mask, ao_loc, False) ao_dm0a = [ numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc) for i in range(4) ] ao_dm0b = [ numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wva = dR_rho1a = rks_hess._make_dR_rho1( ao, ao_dm0a, ia, aoslices, xctype) wvb = dR_rho1b = rks_hess._make_dR_rho1( ao, ao_dm0b, ia, aoslices, xctype) wva[0], wvb[0] = numint._uks_mgga_wv1( (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight) wva[1], wvb[1] = numint._uks_mgga_wv1( (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight) wva[2], wvb[2] = numint._uks_mgga_wv1( (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wva[0]) rks_grad._d1_dot_(vmata[ia, 0], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wva[1]) rks_grad._d1_dot_(vmata[ia, 1], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wva[2]) rks_grad._d1_dot_(vmata[ia, 2], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)] rks_hess._d1d2_dot_(vmata[ia], mol, ao[1:4], aow, mask, ao_loc, False) aow = rks_grad._make_dR_dao_w(ao, wvb[0]) rks_grad._d1_dot_(vmatb[ia, 0], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wvb[1]) rks_grad._d1_dot_(vmatb[ia, 1], mol, aow, ao[0], mask, ao_loc, True) aow = rks_grad._make_dR_dao_w(ao, wvb[2]) rks_grad._d1_dot_(vmatb[ia, 2], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)] rks_hess._d1d2_dot_(vmatb[ia], mol, ao[1:4], aow, mask, ao_loc, False) # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv1 wv = wva[:, 5] * 2 aow = [numint._scale_ao(ao[1], wv[i]) for i in range(3)] rks_hess._d1d2_dot_(vmata[ia], mol, [ao[XX], ao[XY], ao[XZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[2], wv[i]) for i in range(3)] rks_hess._d1d2_dot_(vmata[ia], mol, [ao[YX], ao[YY], ao[YZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[3], wv[i]) for i in range(3)] rks_hess._d1d2_dot_(vmata[ia], mol, [ao[ZX], ao[ZY], ao[ZZ]], aow, mask, ao_loc, False) wv = wvb[:, 5] * 2 aow = [numint._scale_ao(ao[1], wv[i]) for i in range(3)] rks_hess._d1d2_dot_(vmatb[ia], mol, [ao[XX], ao[XY], ao[XZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[2], wv[i]) for i in range(3)] rks_hess._d1d2_dot_(vmatb[ia], mol, [ao[YX], ao[YY], ao[YZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[3], wv[i]) for i in range(3)] rks_hess._d1d2_dot_(vmatb[ia], mol, [ao[ZX], ao[ZY], ao[ZZ]], aow, mask, ao_loc, False) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmata[ia, :, :, :, p0:p1] += ipipa[:, :, :, p0:p1] vmata[ia, :, :, :, p0:p1] += ipipa[:, :, p0:p1].transpose(1, 0, 3, 2) vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, :, p0:p1] vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, p0:p1].transpose(1, 0, 3, 2) return vmata, vmatb
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff[0].shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0a, dm0b = mf.make_rdm1(mo_coeff, mo_occ) vmata = numpy.zeros((mol.natm, 3, nao, nao)) vmatb = numpy.zeros((mol.natm, 3, nao, nao)) max_memory = max(2000, max_memory - (vmata.size + vmatb.size) * 8 / 1e6) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3] vrho = vxc[0] u_u, u_d, d_d = fxc[0].T ao_dm0a = numint._dot_ao_dm(mol, ao[0], dm0a, mask, shls_slice, ao_loc) ao_dm0b = numint._dot_ao_dm(mol, ao[0], dm0b, mask, shls_slice, ao_loc) aow1a = numpy.einsum('xpi,p->xpi', ao[1:], weight * vrho[:, 0]) aow1b = numpy.einsum('xpi,p->xpi', ao[1:], weight * vrho[:, 1]) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # First order density = rho1 * 2. *2 is not applied because + c.c. in the end rho1a = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0a[:, p0:p1]) rho1b = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0b[:, p0:p1]) wv = u_u * rho1a + u_d * rho1b wv *= weight aow = numpy.einsum('pi,xp->xpi', ao[0], wv) aow[:, :, p0:p1] += aow1a[:, :, p0:p1] rks_grad._d1_dot_(vmata[ia], mol, aow, ao[0], mask, ao_loc, True) wv = u_d * rho1a + d_d * rho1b wv *= weight aow = numpy.einsum('pi,xp->xpi', ao[0], wv) aow[:, :, p0:p1] += aow1b[:, :, p0:p1] rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0a = ao_dm0b = aow = aow1a = aow1b = None for ia in range(mol.natm): vmata[ia] = -vmata[ia] - vmata[ia].transpose(0, 2, 1) vmatb[ia] = -vmatb[ia] - vmatb[ia].transpose(0, 2, 1) elif xctype == 'GGA': ao_deriv = 2 vipa = numpy.zeros((3, nao, nao)) vipb = numpy.zeros((3, nao, nao)) for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[:4], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[:4], mo_coeff[1], mo_occ[1], mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3] wva, wvb = numint._uks_gga_wv0((rhoa, rhob), vxc, weight) rks_grad._gga_grad_sum_(vipa, mol, ao, wva, mask, ao_loc) rks_grad._gga_grad_sum_(vipb, mol, ao, wvb, mask, ao_loc) ao_dm0a = [ numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc) for i in range(4) ] ao_dm0b = [ numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wva = dR_rho1a = rks_hess._make_dR_rho1( ao, ao_dm0a, ia, aoslices) wvb = dR_rho1b = rks_hess._make_dR_rho1( ao, ao_dm0b, ia, aoslices) wva[0], wvb[0] = numint._uks_gga_wv1( (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight) wva[1], wvb[1] = numint._uks_gga_wv1( (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight) wva[2], wvb[2] = numint._uks_gga_wv1( (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight) aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmata[ia], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0a = ao_dm0b = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmata[ia, :, p0:p1] += vipa[:, p0:p1] vmatb[ia, :, p0:p1] += vipb[:, p0:p1] vmata[ia] = -vmata[ia] - vmata[ia].transpose(0, 2, 1) vmatb[ia] = -vmatb[ia] - vmatb[ia].transpose(0, 2, 1) elif xctype == 'MGGA': if grids.level < 5: logger.warn(mol, 'MGGA Hessian is sensitive to dft grids.') ao_deriv = 2 vipa = numpy.zeros((3, nao, nao)) vipb = numpy.zeros((3, nao, nao)) for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rhoa = ni.eval_rho2(mol, ao[:10], mo_coeff[0], mo_occ[0], mask, xctype) rhob = ni.eval_rho2(mol, ao[:10], mo_coeff[1], mo_occ[1], mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3] wva, wvb = numint._uks_mgga_wv0((rhoa, rhob), vxc, weight) rks_grad._gga_grad_sum_(vipa, mol, ao, wva, mask, ao_loc) rks_grad._gga_grad_sum_(vipb, mol, ao, wvb, mask, ao_loc) rks_grad._tau_grad_dot_(vipa, mol, ao, wva[5] * 2, mask, ao_loc, True) rks_grad._tau_grad_dot_(vipb, mol, ao, wvb[5] * 2, mask, ao_loc, True) ao_dm0a = [ numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc) for i in range(4) ] ao_dm0b = [ numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wva = dR_rho1a = rks_hess._make_dR_rho1( ao, ao_dm0a, ia, aoslices, xctype) wvb = dR_rho1b = rks_hess._make_dR_rho1( ao, ao_dm0b, ia, aoslices, xctype) wva[0], wvb[0] = numint._uks_mgga_wv1( (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight) wva[1], wvb[1] = numint._uks_mgga_wv1( (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight) wva[2], wvb[2] = numint._uks_mgga_wv1( (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight) aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmata[ia], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[0], mask, ao_loc, True) for j in range(1, 4): aow = [ numint._scale_ao(ao[j], wva[i, 5]) for i in range(3) ] rks_grad._d1_dot_(vmata[ia], mol, aow, ao[j], mask, ao_loc, True) aow = [ numint._scale_ao(ao[j], wvb[i, 5]) for i in range(3) ] rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[j], mask, ao_loc, True) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmata[ia, :, p0:p1] += vipa[:, p0:p1] vmatb[ia, :, p0:p1] += vipb[:, p0:p1] vmata[ia] = -vmata[ia] - vmata[ia].transpose(0, 2, 1) vmatb[ia] = -vmatb[ia] - vmatb[ia].transpose(0, 2, 1) return vmata, vmatb
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) v_ip = numpy.zeros((3, nao, nao)) vmat = numpy.zeros((mol.natm, 3, nao, nao)) max_memory = max(2000, max_memory - vmat.size * 8 / 1e6) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] aow = numint._scale_ao(ao[0], weight * vrho) rks_grad._d1_dot_(v_ip, mol, ao[1:4], aow, mask, ao_loc, True) ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # First order density = rho1 * 2. *2 is not applied because + c.c. in the end rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0[:, p0:p1]) wv = weight * frr * rho1 aow = [numint._scale_ao(ao[0], wv[i]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) ao_dm0 = aow = None elif xctype == 'MGGA': if grids.level < 5: logger.warn(mol, 'MGGA Hessian is sensitive to dft grids.') ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:10], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_mgga_wv0(rho, vxc, weight) rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc) # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv0 rks_grad._tau_grad_dot_(v_ip, mol, ao, wv[5] * 2, mask, ao_loc, True) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices, xctype) wv[0] = numint._rks_mgga_wv1(rho, dR_rho1[0], vxc, fxc, weight) wv[1] = numint._rks_mgga_wv1(rho, dR_rho1[1], vxc, fxc, weight) wv[2] = numint._rks_mgga_wv1(rho, dR_rho1[2], vxc, fxc, weight) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True) for j in range(1, 4): aow = [numint._scale_ao(ao[j], wv[i, 5]) for i in range(3)] rks_grad._d1_dot_(vmat[ia], mol, aow, ao[j], mask, ao_loc, True) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, p0:p1] += v_ip[:, p0:p1] vmat[ia] = -vmat[ia] - vmat[ia].transpose(0, 2, 1) return vmat
def _make_dR_dao_w(ao, wv): #:aow = numpy.einsum('npi,p->npi', ao[1:4], wv[0]) aow = [ numint._scale_ao(ao[1], wv[0]), # dX nabla_x numint._scale_ao(ao[2], wv[0]), # dX nabla_y numint._scale_ao(ao[3], wv[0]), # dX nabla_z ] # XX, XY, XZ = 4, 5, 6 # YX, YY, YZ = 5, 7, 8 # ZX, ZY, ZZ = 6, 8, 9 aow[0] += numint._scale_ao(ao[4], wv[1]) # dX nabla_x aow[0] += numint._scale_ao(ao[5], wv[2]) # dX nabla_y aow[0] += numint._scale_ao(ao[6], wv[3]) # dX nabla_z aow[1] += numint._scale_ao(ao[5], wv[1]) # dY nabla_x aow[1] += numint._scale_ao(ao[7], wv[2]) # dY nabla_y aow[1] += numint._scale_ao(ao[8], wv[3]) # dY nabla_z aow[2] += numint._scale_ao(ao[6], wv[1]) # dZ nabla_x aow[2] += numint._scale_ao(ao[8], wv[2]) # dZ nabla_y aow[2] += numint._scale_ao(ao[9], wv[3]) # dZ nabla_z return aow
def contract_(mat, ao, aoidx, wv, mask): aow = numint._scale_ao(ao[aoidx[0]], wv[1]) aow += numint._scale_ao(ao[aoidx[1]], wv[2]) aow += numint._scale_ao(ao[aoidx[2]], wv[3]) mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) aoslices = mol.aoslice_by_atom() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() dm0 = mf.make_rdm1(mo_coeff, mo_occ) vmat = numpy.zeros((mol.natm, 3, 3, nao, nao)) ipip = numpy.zeros((3, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vrho = vxc[0] frr = fxc[0] wv = weight * vrho aow = [numint._scale_ao(ao[i], wv) for i in range(1, 4)] _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] # *2 for \nabla|ket> in rho1 rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1], ao_dm0[:, p0:p1]) * 2 # aow ~ rho1 ~ d/dR1 wv = weight * frr * rho1 aow = [numint._scale_ao(ao[0], wv[i]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_gga_wv0(rho, vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices) for i in range(3): wv[i] = numint._rks_gga_wv1(rho, dR_rho1[i], vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv[i]) rks_grad._d1_dot_(vmat[ia, i], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) ao_dm0 = aow = None for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2) elif xctype == 'MGGA': XX, XY, XZ = 4, 5, 6 YX, YY, YZ = 5, 7, 8 ZX, ZY, ZZ = 6, 8, 9 ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:10], mo_coeff, mo_occ, mask, xctype) vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] wv = numint._rks_mgga_wv0(rho, vxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv) _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False) aow = [numint._scale_ao(ao[i], wv[5]) for i in range(4, 10)] _d1d2_dot_(ipip, mol, [aow[0], aow[1], aow[2]], [ao[XX], ao[XY], ao[XZ]], mask, ao_loc, False) _d1d2_dot_(ipip, mol, [aow[1], aow[3], aow[4]], [ao[YX], ao[YY], ao[YZ]], mask, ao_loc, False) _d1d2_dot_(ipip, mol, [aow[2], aow[4], aow[5]], [ao[ZX], ao[ZY], ao[ZZ]], mask, ao_loc, False) ao_dm0 = [ numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc) for i in range(4) ] for ia in range(mol.natm): wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices, xctype) for i in range(3): wv[i] = numint._rks_mgga_wv1(rho, dR_rho1[i], vxc, fxc, weight) aow = rks_grad._make_dR_dao_w(ao, wv[i]) rks_grad._d1_dot_(vmat[ia, i], mol, aow, ao[0], mask, ao_loc, True) aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False) # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv1 wv[:, 5] *= 2 aow = [numint._scale_ao(ao[1], wv[i, 5]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, [ao[XX], ao[XY], ao[XZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[2], wv[i, 5]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, [ao[YX], ao[YY], ao[YZ]], aow, mask, ao_loc, False) aow = [numint._scale_ao(ao[3], wv[i, 5]) for i in range(3)] _d1d2_dot_(vmat[ia], mol, [ao[ZX], ao[ZY], ao[ZZ]], aow, mask, ao_loc, False) for ia in range(mol.natm): p0, p1 = aoslices[ia][2:] vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1] vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2) return vmat
def _get_vxc_diag(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base if hessobj.grids is not None: grids = hessobj.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) nao, nmo = mo_coeff.shape ni = mf._numint xctype = ni._xc_type(mf.xc) shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((6, nao, nao)) if xctype == 'LDA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, xctype) vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1] vrho = vxc[0] aow = numint._scale_ao(ao[0], weight * vrho) for i in range(6): vmat[i] += numint._dot_ao_ao(mol, ao[i + 4], aow, mask, shls_slice, ao_loc) aow = None elif xctype == 'GGA': def contract_(mat, ao, aoidx, wv, mask): aow = numint._scale_ao(ao[aoidx[0]], wv[1]) aow += numint._scale_ao(ao[aoidx[1]], wv[2]) aow += numint._scale_ao(ao[aoidx[2]], wv[3]) mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) ao_deriv = 3 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, xctype) vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) # *2 because v.T is not applied. Only v is computed in the next _dot_ao_ao wv[0] *= 2 #:aow = numpy.einsum('npi,np->pi', ao[:4], wv[:4]) aow = numint._scale_ao(ao[:4], wv[:4]) for i in range(6): vmat[i] += numint._dot_ao_ao(mol, ao[i + 4], aow, mask, shls_slice, ao_loc) contract_(vmat[0], ao, [XXX, XXY, XXZ], wv, mask) contract_(vmat[1], ao, [XXY, XYY, XYZ], wv, mask) contract_(vmat[2], ao, [XXZ, XYZ, XZZ], wv, mask) contract_(vmat[3], ao, [XYY, YYY, YYZ], wv, mask) contract_(vmat[4], ao, [XYZ, YYZ, YZZ], wv, mask) contract_(vmat[5], ao, [XZZ, YZZ, ZZZ], wv, mask) rho = vxc = wv = aow = None elif xctype == 'MGGA': def contract_(mat, ao, aoidx, wv, mask): aow = numint._scale_ao(ao[aoidx[0]], wv[1]) aow += numint._scale_ao(ao[aoidx[1]], wv[2]) aow += numint._scale_ao(ao[aoidx[2]], wv[3]) mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc) ao_deriv = 3 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho = ni.eval_rho2(mol, ao[:10], mo_coeff, mo_occ, mask, xctype) vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1] wv = numint._rks_mgga_wv0(rho, vxc, weight) # *2 because v.T is not applied. Only v is computed in the next _dot_ao_ao wv[0] *= 2 wv[5] *= 2 #:aow = numpy.einsum('npi,np->pi', ao[:4], wv[:4]) aow = numint._scale_ao(ao[:4], wv[:4]) for i in range(6): vmat[i] += numint._dot_ao_ao(mol, ao[i + 4], aow, mask, shls_slice, ao_loc) contract_(vmat[0], ao, [XXX, XXY, XXZ], wv, mask) contract_(vmat[1], ao, [XXY, XYY, XYZ], wv, mask) contract_(vmat[2], ao, [XXZ, XYZ, XZZ], wv, mask) contract_(vmat[3], ao, [XYY, YYY, YYZ], wv, mask) contract_(vmat[4], ao, [XYZ, YYZ, YZZ], wv, mask) contract_(vmat[5], ao, [XZZ, YZZ, ZZZ], wv, mask) aow = [numint._scale_ao(ao[i], wv[5]) for i in range(1, 4)] for i, j in enumerate([XXX, XXY, XXZ, XYY, XYZ, XZZ]): vmat[i] += numint._dot_ao_ao(mol, ao[j], aow[0], mask, shls_slice, ao_loc) for i, j in enumerate([XXY, XYY, XYZ, YYY, YYZ, YZZ]): vmat[i] += numint._dot_ao_ao(mol, ao[j], aow[1], mask, shls_slice, ao_loc) for i, j in enumerate([XXZ, XYZ, XZZ, YYZ, YZZ, ZZZ]): vmat[i] += numint._dot_ao_ao(mol, ao[j], aow[2], mask, shls_slice, ao_loc) vmat = vmat[[0, 1, 2, 1, 3, 4, 2, 4, 5]] return vmat.reshape(3, 3, nao, nao)
def get_vxc_full_response(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): '''Full response including the response of the grids''' xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) ao_loc = mol.ao_loc_nr() excsum = 0 vmat = numpy.zeros((3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 vtmp = numpy.empty((3, nao, nao)) for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)): mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho = make_rho(0, ao[0], mask, xctype) exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[:2] vrho = vxc[0] vtmp = numpy.zeros((3, nao, nao)) #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho) aow = numint._scale_ao(ao[0], weight * vrho) _d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True) vmat += vtmp # response of weights excsum += numpy.einsum('r,r,nxr->nx', exc, rho, weight1) # response of grids coordinates excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2 rho = vxc = vrho = aow = None elif xctype == 'GGA': ao_deriv = 2 for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)): mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho = make_rho(0, ao[:4], mask, xctype) exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[:2] vtmp = numpy.zeros((3, nao, nao)) wv = numint._rks_gga_wv0(rho, vxc, weight) _gga_grad_sum_(vtmp, mol, ao, wv, mask, ao_loc) vmat += vtmp # response of weights excsum += numpy.einsum('r,r,nxr->nx', exc, rho[0], weight1) # response of grids coordinates excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2 rho = vxc = vrho = wv = None elif xctype == 'NLC': raise NotImplementedError('NLC') elif xctype == 'MGGA': ao_deriv = 2 for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)): mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho = make_rho(0, ao[:10], mask, xctype) exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[:2] vtmp = numpy.zeros((3, nao, nao)) wv = numint._rks_mgga_wv0(rho, vxc, weight) _gga_grad_sum_(vtmp, mol, ao, wv, mask, ao_loc) _tau_grad_dot_(vtmp, mol, ao, wv[5] * 2, mask, ao_loc, True) vmat += vtmp # response of weights excsum += numpy.einsum('r,r,nxr->nx', exc, rho[0], weight1) # response of grids coordinates excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2 rho = vxc = vrho = wv = None # - sign because nabla_X = -nabla_x return excsum, -vmat
def get_vxc(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((2, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho_a = make_rho(0, ao[0], mask, xctype) rho_b = make_rho(1, ao[0], mask, xctype) vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1, verbose=verbose)[1] vrho = vxc[0] #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,0]) aow = numint._scale_ao(ao[0], weight * vrho[:, 0]) rks_grad._d1_dot_(vmat[0], mol, ao[1:4], aow, mask, ao_loc, True) #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,1]) aow = numint._scale_ao(ao[0], weight * vrho[:, 1]) rks_grad._d1_dot_(vmat[1], mol, ao[1:4], aow, mask, ao_loc, True) elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho_a = make_rho(0, ao[:4], mask, xctype) rho_b = make_rho(1, ao[:4], mask, xctype) vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1, verbose=verbose)[1] wva, wvb = numint._uks_gga_wv0((rho_a, rho_b), vxc, weight) rks_grad._gga_grad_sum_(vmat[0], mol, ao, wva, mask, ao_loc) rks_grad._gga_grad_sum_(vmat[1], mol, ao, wvb, mask, ao_loc) elif xctype == 'NLC': raise NotImplementedError('NLC') elif xctype == 'MGGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): rho_a = make_rho(0, ao[:10], mask, xctype) rho_b = make_rho(1, ao[:10], mask, xctype) vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1, verbose=verbose)[1] wva, wvb = numint._uks_mgga_wv0((rho_a, rho_b), vxc, weight) rks_grad._gga_grad_sum_(vmat[0], mol, ao, wva, mask, ao_loc) rks_grad._gga_grad_sum_(vmat[1], mol, ao, wvb, mask, ao_loc) # *2 because wv[5] is scaled by 0.5 in _uks_mgga_wv0 rks_grad._tau_grad_dot_(vmat[0], mol, ao, wva[5] * 2, mask, ao_loc, True) rks_grad._tau_grad_dot_(vmat[1], mol, ao, wvb[5] * 2, mask, ao_loc, True) exc = numpy.zeros((mol.natm, 3)) # - sign because nabla_X = -nabla_x return exc, -vmat
def lda_sum_(vmat, ao, wv, mask): aow = numint._scale_ao(ao[0], wv) for k in range(4): vmat[k] += numint._dot_ao_ao(mol, ao[k], aow, mask, shls_slice, ao_loc)
def get_vxc(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((nset, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[0], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] vrho = vxc[0] #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho) aow = numint._scale_ao(ao[0], weight * vrho) _d1_dot_(vmat[idm], mol, ao[1:4], aow, mask, ao_loc, True) elif xctype == 'GGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[:4], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] wv = numint._rks_gga_wv0(rho, vxc, weight) _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc) elif xctype == 'NLC': raise NotImplementedError('NLC') elif xctype == 'MGGA': ao_deriv = 2 for ao, mask, weight, coords \ in ni.block_loop(mol, grids, nao, ao_deriv, max_memory): for idm in range(nset): rho = make_rho(idm, ao[:10], mask, xctype) vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose=verbose)[1] wv = numint._rks_mgga_wv0(rho, vxc, weight) _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc) # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv0 _tau_grad_dot_(vmat[idm], mol, ao, wv[5] * 2, mask, ao_loc, True) exc = None if nset == 1: vmat = vmat[0] # - sign because nabla_X = -nabla_x return exc, -vmat
def gga_sum_(vmat, ao, wv, mask): aow = numint._scale_ao(ao[:4], wv[:4]) tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc) vmat[0] += tmp + tmp.T rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv, mask, ao_loc)
def get_vxc_full_response(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, max_memory=2000, verbose=None): '''Full response including the response of the grids''' xctype = ni._xc_type(xc_code) make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi) ao_loc = mol.ao_loc_nr() aoslices = mol.aoslice_by_atom() excsum = 0 vmat = numpy.zeros((2, 3, nao, nao)) if xctype == 'LDA': ao_deriv = 1 for atm_id, (coords, weight, weight1) \ in enumerate(rks_grad.grids_response_cc(grids)): sh0, sh1 = aoslices[atm_id][:2] mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho_a = make_rho(0, ao[0], mask, xctype) rho_b = make_rho(1, ao[0], mask, xctype) exc, vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1, verbose=verbose)[:2] vrho = vxc[0] vtmp = numpy.zeros((3, nao, nao)) #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,0]) aow = numint._scale_ao(ao[0], weight * vrho[:, 0]) rks_grad._d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True) vmat[0] += vtmp excsum += numpy.einsum('r,r,nxr->nx', exc, rho_a + rho_b, weight1) excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[0]) * 2 vtmp = numpy.zeros((3, nao, nao)) #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,1]) aow = numint._scale_ao(ao[0], weight * vrho[:, 1]) rks_grad._d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True) vmat[1] += vtmp excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[1]) * 2 elif xctype == 'GGA': ao_deriv = 2 for atm_id, (coords, weight, weight1) \ in enumerate(rks_grad.grids_response_cc(grids)): sh0, sh1 = aoslices[atm_id][:2] mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho_a = make_rho(0, ao[:4], mask, xctype) rho_b = make_rho(1, ao[:4], mask, xctype) exc, vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1, verbose=verbose)[:2] wva, wvb = numint._uks_gga_wv0((rho_a, rho_b), vxc, weight) vtmp = numpy.zeros((3, nao, nao)) rks_grad._gga_grad_sum_(vtmp, mol, ao, wva, mask, ao_loc) vmat[0] += vtmp excsum += numpy.einsum('r,r,nxr->nx', exc, rho_a[0] + rho_b[0], weight1) excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[0]) * 2 vtmp = numpy.zeros((3, nao, nao)) rks_grad._gga_grad_sum_(vtmp, mol, ao, wvb, mask, ao_loc) vmat[1] += vtmp excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[1]) * 2 elif xctype == 'NLC': raise NotImplementedError('NLC') elif xctype == 'MGGA': ao_deriv = 2 for atm_id, (coords, weight, weight1) \ in enumerate(rks_grad.grids_response_cc(grids)): sh0, sh1 = aoslices[atm_id][:2] mask = gen_grid.make_mask(mol, coords) ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask) rho_a = make_rho(0, ao[:10], mask, xctype) rho_b = make_rho(1, ao[:10], mask, xctype) exc, vxc = ni.eval_xc(xc_code, (rho_a, rho_b), 1, relativity, 1, verbose=verbose)[:2] wva, wvb = numint._uks_mgga_wv0((rho_a, rho_b), vxc, weight) vtmp = numpy.zeros((3, nao, nao)) rks_grad._gga_grad_sum_(vtmp, mol, ao, wva, mask, ao_loc) # *2 because wv[5] is scaled by 0.5 in _uks_mgga_wv0 rks_grad._tau_grad_dot_(vtmp, mol, ao, wva[5] * 2, mask, ao_loc, True) vmat[0] += vtmp excsum += numpy.einsum('r,r,nxr->nx', exc, rho_a[0] + rho_b[0], weight1) excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[0]) * 2 vtmp = numpy.zeros((3, nao, nao)) rks_grad._gga_grad_sum_(vtmp, mol, ao, wvb, mask, ao_loc) rks_grad._tau_grad_dot_(vtmp, mol, ao, wvb[5] * 2, mask, ao_loc, True) vmat[1] += vtmp excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[1]) * 2 # - sign because nabla_X = -nabla_x return excsum, -vmat