Source code for pyscf.df.hessian.uhf

#!/usr/bin/env python
#
# This code was copied from the data generation program of Tencent Alchemy
# project (https://github.com/tencent-alchemy).
#

#
# Copyright 2019 Tencent America LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: Qiming Sun <osirpt.sun@gmail.com>
#

'''
Non-relativistic UHF analytical Hessian
'''


import numpy
import numpy as np
import scipy.linalg
from pyscf import lib
from pyscf.lib import logger
from pyscf import ao2mo
from pyscf.hessian import rhf as rhf_hess
from pyscf.hessian import uhf as uhf_hess
from pyscf.df.hessian.rhf import _load_dim0, _pinv
from pyscf.df.grad.rhf import (_int3c_wrapper, _gen_metric_solver,
                               LINEAR_DEP_THRESHOLD)


[docs] def partial_hess_elec(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None, max_memory=4000, verbose=None): e1, ej, ek = _partial_hess_ejk(hessobj, mo_energy, mo_coeff, mo_occ, atmlst, max_memory, verbose, True) return e1 + ej - ek
def _partial_hess_ejk(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None, max_memory=4000, verbose=None, with_k=True): log = logger.new_logger(hessobj, verbose) time0 = t1 = (logger.process_clock(), logger.perf_counter()) mol = hessobj.mol mf = hessobj.base if mo_energy is None: mo_energy = mf.mo_energy if mo_occ is None: mo_occ = mf.mo_occ if mo_coeff is None: mo_coeff = mf.mo_coeff if atmlst is None: atmlst = range(mol.natm) nao, nmo = mo_coeff[0].shape mocca = mo_coeff[0][:,mo_occ[0]>0] moccb = mo_coeff[1][:,mo_occ[1]>0] nocca = mocca.shape[1] noccb = moccb.shape[1] dm0a = numpy.dot(mocca, mocca.T) dm0b = numpy.dot(moccb, moccb.T) dm0 = dm0a + dm0b # Energy weighted density matrix mo_ea = mo_energy[0][mo_occ[0]>0] mo_eb = mo_energy[1][mo_occ[1]>0] dme0 = numpy.einsum('pi,qi,i->pq', mocca, mocca, mo_ea) dme0+= numpy.einsum('pi,qi,i->pq', moccb, moccb, mo_eb) auxmol = hessobj.base.with_df.auxmol naux = auxmol.nao nbas = mol.nbas auxslices = auxmol.aoslice_by_atom() aoslices = mol.aoslice_by_atom() aux_loc = auxmol.ao_loc blksize = min(480, hessobj.max_memory*.3e6/8/nao**2) aux_ranges = ao2mo.outcore.balance_partition(auxmol.ao_loc, blksize) hcore_deriv = hessobj.hcore_generator(mol) s1aa, s1ab, s1a = rhf_hess.get_ovlp(mol) ftmp = lib.H5TmpFile() get_int3c = _int3c_wrapper(mol, auxmol, 'int3c2e', 's1') # Without RI basis response # (20|0)(0|00) # (11|0)(0|00) # (10|0)(0|10) int2c = auxmol.intor('int2c2e', aosym='s1') solve_j2c = _gen_metric_solver(int2c) int2c_ip1 = auxmol.intor('int2c2e_ip1', aosym='s1') rhoj0_P = 0 if with_k: if hessobj.max_memory*.4e6/8 < naux*nocca*(nocca+nao): raise RuntimeError('Memory not enough. You need to increase mol.max_memory') rhok0a_Pl_ = np.empty((naux,nao,nocca)) rhok0b_Pl_ = np.empty((naux,nao,noccb)) for i, (shl0, shl1, p0, p1) in enumerate(aoslices): int3c = get_int3c((shl0, shl1, 0, nbas, 0, auxmol.nbas)) rhoj0_P += np.einsum('klp,kl->p', int3c, dm0[p0:p1]) if with_k: tmp = lib.einsum('ijp,jk->pik', int3c, mocca) tmp = solve_j2c(tmp.reshape(naux,-1)) rhok0a_Pl_[:,p0:p1] = tmp.reshape(naux,p1-p0,nocca) tmp = lib.einsum('ijp,jk->pik', int3c, moccb) tmp = solve_j2c(tmp.reshape(naux,-1)) rhok0b_Pl_[:,p0:p1] = tmp.reshape(naux,p1-p0,noccb) int3c = tmp = None rhoj0_P = solve_j2c(rhoj0_P) get_int3c_ipip1 = _int3c_wrapper(mol, auxmol, 'int3c2e_ipip1', 's1') vj1_diag = 0 vk1a_diag = 0 vk1b_diag = 0 for shl0, shl1, nL in aux_ranges: shls_slice = (0, nbas, 0, nbas, shl0, shl1) p0, p1 = aux_loc[shl0], aux_loc[shl1] int3c_ipip1 = get_int3c_ipip1(shls_slice) vj1_diag += np.einsum('xijp,p->xij', int3c_ipip1, rhoj0_P[p0:p1]).reshape(3,3,nao,nao) if with_k: tmp = lib.einsum('Plj,Jj->PlJ', rhok0a_Pl_[p0:p1], mocca) vk1a_diag += lib.einsum('xijp,plj->xil', int3c_ipip1, tmp).reshape(3,3,nao,nao) tmp = lib.einsum('Plj,Jj->PlJ', rhok0b_Pl_[p0:p1], moccb) vk1b_diag += lib.einsum('xijp,plj->xil', int3c_ipip1, tmp).reshape(3,3,nao,nao) t1 = log.timer_debug1('contracting int2e_ipip1', *t1) int3c_ipip1 = get_int3c_ipip1 = tmp = None get_int3c_ip1 = _int3c_wrapper(mol, auxmol, 'int3c2e_ip1', 's1') rho_ip1 = ftmp.create_dataset('rho_ip1', (nao,nao,naux,3), 'f8') rhoka_ip1_IkP = ftmp.create_group('rhoka_ip1_IkP') rhokb_ip1_IkP = ftmp.create_group('rhokb_ip1_IkP') rhoka_ip1_PkI = ftmp.create_group('rhoka_ip1_PkI') rhokb_ip1_PkI = ftmp.create_group('rhokb_ip1_PkI') rhoj1 = np.empty((mol.natm,naux,3)) wj1 = np.empty((mol.natm,naux,3)) for i0, ia in enumerate(atmlst): shl0, shl1, p0, p1 = aoslices[ia] shls_slice = (shl0, shl1, 0, nbas, 0, auxmol.nbas) int3c_ip1 = get_int3c_ip1(shls_slice) tmp_ip1 = solve_j2c(int3c_ip1.reshape(-1,naux).T).reshape(naux,3,p1-p0,nao) rhoj1[i0] = np.einsum('pxij,ji->px', tmp_ip1, dm0[:,p0:p1]) wj1[i0] = np.einsum('xijp,ji->px', int3c_ip1, dm0[:,p0:p1]) rho_ip1[p0:p1] = tmp_ip1.transpose(2,3,0,1) if with_k: tmp = lib.einsum('pykl,li->ikpy', tmp_ip1, dm0a) rhoka_ip1_IkP['%.4d'%ia] = tmp rhoka_ip1_PkI['%.4d'%ia] = tmp.transpose(2,1,0,3) tmp = None tmp = lib.einsum('pykl,li->ikpy', tmp_ip1, dm0b) rhokb_ip1_IkP['%.4d'%ia] = tmp rhokb_ip1_PkI['%.4d'%ia] = tmp.transpose(2,1,0,3) tmp = None ej = lib.einsum('ipx,jpy->ijxy', rhoj1, wj1) * 4 ek = np.zeros_like(ej) e1 = np.zeros_like(ej) rhoj1 = wj1 = None if with_k: vk2a_buf = 0 vk2b_buf = 0 for shl0, shl1, nL in aux_ranges: shls_slice = (0, nbas, 0, nbas, shl0, shl1) p0, p1 = aux_loc[shl0], aux_loc[shl1] int3c_ip1 = get_int3c_ip1(shls_slice) vk2a_buf += lib.einsum('xijp,pkjy->xyki', int3c_ip1, _load_dim0(rhoka_ip1_PkI, p0, p1)) vk2b_buf += lib.einsum('xijp,pkjy->xyki', int3c_ip1, _load_dim0(rhokb_ip1_PkI, p0, p1)) get_int3c_ip2 = _int3c_wrapper(mol, auxmol, 'int3c2e_ip2', 's1') wj_ip2 = np.empty((naux,3)) wka_ip2_Ipk = ftmp.create_dataset('wka_ip2', (nao,naux,3,nao), 'f8') wkb_ip2_Ipk = ftmp.create_dataset('wkb_ip2', (nao,naux,3,nao), 'f8') if hessobj.auxbasis_response > 1: wka_ip2_P__ = np.empty((naux,3,nocca,nocca)) wkb_ip2_P__ = np.empty((naux,3,noccb,noccb)) for shl0, shl1, nL in aux_ranges: shls_slice = (0, nbas, 0, nbas, shl0, shl1) p0, p1 = aux_loc[shl0], aux_loc[shl1] int3c_ip2 = get_int3c_ip2(shls_slice) wj_ip2[p0:p1] = np.einsum('yklp,lk->py', int3c_ip2, dm0) if with_k: wka_ip2_Ipk[:,p0:p1] = lib.einsum('yklp,il->ipyk', int3c_ip2, dm0a) wkb_ip2_Ipk[:,p0:p1] = lib.einsum('yklp,il->ipyk', int3c_ip2, dm0b) if hessobj.auxbasis_response > 1: wka_ip2_P__[p0:p1] = lib.einsum('xuvp,ui,vj->pxij', int3c_ip2, mocca, mocca) wkb_ip2_P__[p0:p1] = lib.einsum('xuvp,ui,vj->pxij', int3c_ip2, moccb, moccb) int3c_ip2 = None if hessobj.auxbasis_response > 1: get_int3c_ipip2 = _int3c_wrapper(mol, auxmol, 'int3c2e_ipip2', 's1') rhok0a_P__ = lib.einsum('plj,li->pij', rhok0a_Pl_, mocca) rhok0b_P__ = lib.einsum('plj,li->pij', rhok0b_Pl_, moccb) rho2c_0 = lib.einsum('pij,qij->pq', rhok0a_P__, rhok0a_P__) rho2c_0 += lib.einsum('pij,qij->pq', rhok0b_P__, rhok0b_P__) int2c_inv = _pinv(int2c, lindep=LINEAR_DEP_THRESHOLD) int2c_ipip1 = auxmol.intor('int2c2e_ipip1', aosym='s1') int2c_ip_ip = lib.einsum('xpq,qr,ysr->xyps', int2c_ip1, int2c_inv, int2c_ip1) int2c_ip_ip -= auxmol.intor('int2c2e_ip1ip2', aosym='s1').reshape(3,3,naux,naux) int2c = solve_j2c = None get_int3c_ipvip1 = _int3c_wrapper(mol, auxmol, 'int3c2e_ipvip1', 's1') get_int3c_ip1ip2 = _int3c_wrapper(mol, auxmol, 'int3c2e_ip1ip2', 's1') for i0, ia in enumerate(atmlst): shl0, shl1, p0, p1 = aoslices[ia] shls_slice = (shl0, shl1, 0, nbas, 0, auxmol.nbas) # (10|0)(0|10) without response of RI basis if with_k: int3c_ip1 = get_int3c_ip1(shls_slice) vk1a = lib.einsum('xijp,ikpy->xykj', int3c_ip1, _load_dim0(rhoka_ip1_IkP, p0, p1)) vk1b = lib.einsum('xijp,ikpy->xykj', int3c_ip1, _load_dim0(rhokb_ip1_IkP, p0, p1)) vk1a[:,:,:,p0:p1] += vk2a_buf[:,:,:,p0:p1] vk1b[:,:,:,p0:p1] += vk2b_buf[:,:,:,p0:p1] t1 = log.timer_debug1('contracting int2e_ip1ip2 for atom %d'%ia, *t1) int3c_ip1 = None # (11|0)(0|00) without response of RI basis int3c_ipvip1 = get_int3c_ipvip1(shls_slice) vj1 = np.einsum('xijp,p->xji', int3c_ipvip1, rhoj0_P).reshape(3,3,nao,p1-p0) if with_k: tmp = lib.einsum('pki,ji->pkj', rhok0a_Pl_, mocca[p0:p1]) vk1a += lib.einsum('xijp,pki->xjk', int3c_ipvip1, tmp).reshape(3,3,nao,nao) tmp = lib.einsum('pki,ji->pkj', rhok0b_Pl_, moccb[p0:p1]) vk1b += lib.einsum('xijp,pki->xjk', int3c_ipvip1, tmp).reshape(3,3,nao,nao) t1 = log.timer_debug1('contracting int2e_ipvip1 for atom %d'%ia, *t1) int3c_ipvip1 = tmp = None e1[i0,i0] -= numpy.einsum('xypq,pq->xy', s1aa[:,:,p0:p1], dme0[p0:p1])*2 ej[i0,i0] += numpy.einsum('xypq,pq->xy', vj1_diag[:,:,p0:p1], dm0[p0:p1])*2 if with_k: ek[i0,i0] += numpy.einsum('xypq,pq->xy', vk1a_diag[:,:,p0:p1], dm0a[p0:p1])*2 ek[i0,i0] += numpy.einsum('xypq,pq->xy', vk1b_diag[:,:,p0:p1], dm0b[p0:p1])*2 for j0, ja in enumerate(atmlst[:i0+1]): q0, q1 = aoslices[ja][2:] ej[i0,j0] += numpy.einsum('xypq,pq->xy', vj1[:,:,q0:q1], dm0[q0:q1,p0:p1])*2 e1[i0,j0] -= numpy.einsum('xypq,pq->xy', s1ab[:,:,p0:p1,q0:q1], dme0[p0:p1,q0:q1])*2 if with_k: ek[i0,j0] += numpy.einsum('xypq,pq->xy', vk1a[:,:,q0:q1], dm0a[q0:q1])*2 ek[i0,j0] += numpy.einsum('xypq,pq->xy', vk1b[:,:,q0:q1], dm0b[q0:q1])*2 h1ao = hcore_deriv(ia, ja) e1[i0,j0] += numpy.einsum('xypq,pq->xy', h1ao, dm0) # # The first order RI basis response # # (10|1)(0|00) # (10|0)(1|0)(0|00) # (10|0)(0|1)(0|00) # (10|0)(1|00) # if hessobj.auxbasis_response: wk1_Pij = rho_ip1[p0:p1].transpose(2,3,0,1) rhoj1_P = np.einsum('pxij,ji->px', wk1_Pij, dm0[:,p0:p1]) # (10|1)(0|0)(0|00) int3c_ip1ip2 = get_int3c_ip1ip2(shls_slice) wj11_p = np.einsum('xijp,ji->xp', int3c_ip1ip2, dm0[:,p0:p1]) # (10|0)(1|0)(0|00) wj0_01 = np.einsum('ypq,q->yp', int2c_ip1, rhoj0_P) if with_k: rhok0_P_I = lib.einsum('plj,il->pji', rhok0a_Pl_, dm0a[p0:p1]) rhok0_PJI = lib.einsum('pji,Jj->pJi', rhok0_P_I, mocca) rhok0_P_I = lib.einsum('plj,il->pji', rhok0b_Pl_, dm0b[p0:p1]) rhok0_PJI+= lib.einsum('pji,Jj->pJi', rhok0_P_I, moccb) wk1_pJI = lib.einsum('ypq,qji->ypji', int2c_ip1, rhok0_PJI) wk1_IpJ = lib.einsum('ipyk,kj->ipyj', wka_ip2_Ipk[p0:p1], dm0a) wk1_IpJ+= lib.einsum('ipyk,kj->ipyj', wkb_ip2_Ipk[p0:p1], dm0b) rho2c_PQ = lib.einsum('pxij,qji->xqp', wk1_Pij, rhok0_PJI) for j0, (q0, q1) in enumerate(auxslices[:,2:]): # (10|1)(0|00) _ej = np.einsum('xp,p->x', wj11_p[:,q0:q1], rhoj0_P[q0:q1]).reshape(3,3) # (10|0)(0|1)(0|00) _ej -= lib.einsum('yqp,q,px->xy', int2c_ip1[:,q0:q1], rhoj0_P[q0:q1], rhoj1_P) # (10|0)(1|0)(0|00) _ej -= lib.einsum('px,yp->xy', rhoj1_P[q0:q1], wj0_01[:,q0:q1]) # (10|0)(1|00) _ej += lib.einsum('px,py->xy', rhoj1_P[q0:q1], wj_ip2[q0:q1]) if hessobj.auxbasis_response > 1: ej[i0,j0] += _ej * 2 ej[j0,i0] += _ej.T * 2 else: ej[i0,j0] += _ej ej[j0,i0] += _ej.T if with_k: _ek = lib.einsum('xijp,pji->x', int3c_ip1ip2[:,:,:,q0:q1], rhok0_PJI[q0:q1]).reshape(3,3) _ek -= lib.einsum('pxij,ypji->xy', wk1_Pij[q0:q1], wk1_pJI[:,q0:q1]) _ek -= lib.einsum('xqp,yqp->xy', rho2c_PQ[:,q0:q1], int2c_ip1[:,q0:q1]) _ek += lib.einsum('pxij,ipyj->xy', wk1_Pij[q0:q1], wk1_IpJ[:,q0:q1]) if hessobj.auxbasis_response > 1: ek[i0,j0] += _ek * 2 ek[j0,i0] += _ek.T * 2 else: ek[i0,j0] += _ek ek[j0,i0] += _ek.T int3c_ip1ip2 = None # # The second order RI basis response # if hessobj.auxbasis_response > 1: # (00|2)(0|00) # (00|0)(2|0)(0|00) shl0, shl1, p0, p1 = auxslices[ia] shls_slice = (0, nbas, 0, nbas, shl0, shl1) int3c_ipip2 = get_int3c_ipip2(shls_slice) ej[i0,i0] += np.einsum('xijp,ji,p->x', int3c_ipip2, dm0, rhoj0_P[p0:p1]).reshape(3,3) ej[i0,i0] -= np.einsum('p,xpq,q->x', rhoj0_P[p0:p1], int2c_ipip1[:,p0:p1], rhoj0_P).reshape(3,3) if with_k: rhok0_PJI = lib.einsum('Pij,Jj,Ii->PJI', rhok0a_P__[p0:p1], mocca, mocca) rhok0_PJI += lib.einsum('Pij,Jj,Ii->PJI', rhok0b_P__[p0:p1], moccb, moccb) ek[i0,i0] += np.einsum('xijp,pij->x', int3c_ipip2, rhok0_PJI).reshape(3,3) ek[i0,i0] -= np.einsum('pq,xpq->x', rho2c_0[p0:p1], int2c_ipip1[:,p0:p1]).reshape(3,3) rhok0_PJI = None # (00|0)(1|1)(0|00) # (00|1)(1|0)(0|00) # (00|1)(0|1)(0|00) # (00|1)(1|00) rhoj1 = lib.einsum('px,pq->xq', wj_ip2[p0:p1], int2c_inv[p0:p1]) # (00|0)(0|1)(1|0)(0|00) rhoj0_01 = lib.einsum('xp,pq->xq', wj0_01[:,p0:p1], int2c_inv[p0:p1]) # (00|0)(1|0)(1|0)(0|00) ip1_2c_2c = lib.einsum('xpq,qr->xpr', int2c_ip1[:,p0:p1], int2c_inv) rhoj0_10 = lib.einsum('p,xpq->xq', rhoj0_P[p0:p1], ip1_2c_2c) if with_k: # (00|0)(0|1)(1|0)(0|00) ip1_rho2c = .5 * lib.einsum('xpq,qr->xpr', int2c_ip1[:,p0:p1], rho2c_0) rho2c_1 = lib.einsum('xrq,rp->xpq', ip1_rho2c, int2c_inv[p0:p1]) # (00|0)(1|0)(1|0)(0|00) rho2c_1 += lib.einsum('xrp,rq->xpq', ip1_2c_2c, rho2c_0[p0:p1]) # (00|1)(0|1)(0|00) # (00|1)(1|0)(0|00) int3c_ip2 = get_int3c_ip2(shls_slice) tmp = lib.einsum('xuvr,vj,ui,qij,rp->xpq', int3c_ip2, mocca, mocca, rhok0a_P__, int2c_inv[p0:p1]) tmp+= lib.einsum('xuvr,vj,ui,qij,rp->xpq', int3c_ip2, moccb, moccb, rhok0b_P__, int2c_inv[p0:p1]) rho2c_1 -= tmp rho2c_1 -= tmp.transpose(0,2,1) int3c_ip2 = tmp = None for j0, (q0, q1) in enumerate(auxslices[:,2:]): _ej = 0 # (00|0)(1|1)(0|00) # (00|0)(1|0)(0|1)(0|00) _ej += .5 * np.einsum('p,xypq,q->xy', rhoj0_P[p0:p1], int2c_ip_ip[:,:,p0:p1,q0:q1], rhoj0_P[q0:q1]) # (00|1)(1|0)(0|00) _ej -= lib.einsum('xp,yp->xy', rhoj1[:,q0:q1], wj0_01[:,q0:q1]) # (00|1)(1|00) _ej += .5 * lib.einsum('xp,py->xy', rhoj1[:,q0:q1], wj_ip2[q0:q1]) # (00|0)(0|1)(1|0)(0|00) _ej += .5 * np.einsum('xp,yp->xy', rhoj0_01[:,q0:q1], wj0_01[:,q0:q1]) # (00|1)(0|1)(0|00) _ej -= lib.einsum('yqp,q,xp->xy', int2c_ip1[:,q0:q1], rhoj0_P[q0:q1], rhoj1) # (00|0)(1|0)(1|0)(0|00) _ej += np.einsum('xp,yp->xy', rhoj0_10[:,q0:q1], wj0_01[:,q0:q1]) ej[i0,j0] += _ej ej[j0,i0] += _ej.T if with_k: # (00|0)(1|1)(0|00) # (00|0)(1|0)(0|1)(0|00) _ek = .5 * np.einsum('pq,xypq->xy', rho2c_0[p0:p1,q0:q1], int2c_ip_ip[:,:,p0:p1,q0:q1]) # (00|1)(0|1)(0|00) # (00|1)(1|0)(0|00) # (00|0)(0|1)(1|0)(0|00) # (00|0)(1|0)(1|0)(0|00) _ek += np.einsum('xpq,ypq->xy', rho2c_1[:,q0:q1], int2c_ip1[:,q0:q1]) # (00|1)(1|00) _ek += .5 * lib.einsum('pxij,pq,qyij->xy', wka_ip2_P__[p0:p1], int2c_inv[p0:p1,q0:q1], wka_ip2_P__[q0:q1]) _ek += .5 * lib.einsum('pxij,pq,qyij->xy', wkb_ip2_P__[p0:p1], int2c_inv[p0:p1,q0:q1], wkb_ip2_P__[q0:q1]) ek[i0,j0] += _ek ek[j0,i0] += _ek.T for i0, ia in enumerate(atmlst): for j0 in range(i0): e1[j0,i0] = e1[i0,j0].T ej[j0,i0] = ej[i0,j0].T ek[j0,i0] = ek[i0,j0].T log.timer('UHF partial hessian', *time0) return e1, ej, ek
[docs] def make_h1(hessobj, mo_coeff, mo_occ, chkfile=None, atmlst=None, verbose=None): mol = hessobj.mol if atmlst is None: atmlst = range(mol.natm) h1aoa = [None] * mol.natm h1aob = [None] * mol.natm for ia, h1, vj1, vk1 in _gen_jk(hessobj, mo_coeff, mo_occ, chkfile, atmlst, verbose, True): vk1a, vk1b = vk1 h1aoa[ia] = h1 + vj1 - vk1a h1aob[ia] = h1 + vj1 - vk1b return (h1aoa,h1aob)
def _gen_jk(hessobj, mo_coeff, mo_occ, chkfile=None, atmlst=None, verbose=None, with_k=True): mol = hessobj.mol if atmlst is None: atmlst = range(mol.natm) auxmol = hessobj.base.with_df.auxmol nbas = mol.nbas auxslices = auxmol.aoslice_by_atom() aux_loc = auxmol.ao_loc nao, nmo = mo_coeff[0].shape mocca = mo_coeff[0][:,mo_occ[0]>0] moccb = mo_coeff[1][:,mo_occ[1]>0] nocca = mocca.shape[1] noccb = moccb.shape[1] dm0a = numpy.dot(mocca, mocca.T) dm0b = numpy.dot(moccb, moccb.T) dm0 = dm0a + dm0b hcore_deriv = hessobj.base.nuc_grad_method().hcore_generator(mol) get_int3c = _int3c_wrapper(mol, auxmol, 'int3c2e', 's1') aoslices = mol.aoslice_by_atom() naux = auxmol.nao ftmp = lib.H5TmpFile() rho0_Pij = ftmp.create_group('rho0_Pij') wj_Pij = ftmp.create_group('wj_Pij') int2c = auxmol.intor('int2c2e', aosym='s1') solve_j2c = _gen_metric_solver(int2c) int2c = None int2c_ip1 = auxmol.intor('int2c2e_ip1', aosym='s1') rhoj0_P = 0 if with_k: rhok0a_Pl_ = np.empty((naux,nao,nocca)) rhok0b_Pl_ = np.empty((naux,nao,noccb)) for i, (shl0, shl1, p0, p1) in enumerate(aoslices): int3c = get_int3c((shl0, shl1, 0, nbas, 0, auxmol.nbas)) coef3c = solve_j2c(int3c.reshape(-1,naux).T) rho0_Pij['%.4d'%i] = coef3c = coef3c.reshape(naux,p1-p0,nao) rhoj0_P += np.einsum('pkl,kl->p', coef3c, dm0[p0:p1]) if with_k: rhok0a_Pl_[:,p0:p1] = lib.einsum('pij,jk->pik', coef3c, mocca) rhok0b_Pl_[:,p0:p1] = lib.einsum('pij,jk->pik', coef3c, moccb) if hessobj.auxbasis_response: wj_Pij['%.4d'%i] = lib.einsum('xqp,pij->qixj', int2c_ip1, coef3c) int3c = coef3c = None get_int3c_ip1 = _int3c_wrapper(mol, auxmol, 'int3c2e_ip1', 's1') get_int3c_ip2 = _int3c_wrapper(mol, auxmol, 'int3c2e_ip2', 's1') aux_ranges = ao2mo.outcore.balance_partition(auxmol.ao_loc, 480) vk1a_buf = np.zeros((3,nao,nao)) vk1b_buf = np.zeros((3,nao,nao)) vj1_buf = np.zeros((mol.natm,3,nao,nao)) for shl0, shl1, nL in aux_ranges: shls_slice = (0, nbas, 0, nbas, shl0, shl1) p0, p1 = aux_loc[shl0], aux_loc[shl1] int3c_ip1 = get_int3c_ip1(shls_slice) coef3c = _load_dim0(rho0_Pij, p0, p1) for i, (shl0, shl1, q0, q1) in enumerate(aoslices): wj1 = np.einsum('xijp,ji->xp', int3c_ip1[:,q0:q1], dm0[:,q0:q1]) vj1_buf[i] += np.einsum('xp,pij->xij', wj1, coef3c) if with_k: rhok0_PlJ = lib.einsum('plj,Jj->plJ', rhok0a_Pl_[p0:p1], mocca) vk1a_buf += lib.einsum('xijp,plj->xil', int3c_ip1, rhok0_PlJ[p0:p1]) rhok0_PlJ = lib.einsum('plj,Jj->plJ', rhok0b_Pl_[p0:p1], moccb) vk1b_buf += lib.einsum('xijp,plj->xil', int3c_ip1, rhok0_PlJ[p0:p1]) int3c_ip1 = None vj1_buf = ftmp['vj1_buf'] = vj1_buf vk1a = vk1b = np.zeros((3,nao,nao)) for i0, ia in enumerate(atmlst): shl0, shl1, p0, p1 = aoslices[ia] shls_slice = (shl0, shl1, 0, nbas, 0, auxmol.nbas) int3c_ip1 = get_int3c_ip1(shls_slice) vj1 = -np.asarray(vj1_buf[ia]) vj1[:,p0:p1] -= np.einsum('xijp,p->xij', int3c_ip1, rhoj0_P) if with_k: rhok0_PlJ = lib.einsum('plj,Jj->plJ', rhok0a_Pl_, mocca[p0:p1]) vk1a = -lib.einsum('xijp,pki->xkj', int3c_ip1, rhok0_PlJ) rhok0_PlJ = lib.einsum('plj,Jj->plJ', rhok0b_Pl_, moccb[p0:p1]) vk1b = -lib.einsum('xijp,pki->xkj', int3c_ip1, rhok0_PlJ) vk1a[:,p0:p1] -= vk1a_buf[:,p0:p1] vk1b[:,p0:p1] -= vk1b_buf[:,p0:p1] if hessobj.auxbasis_response: shl0, shl1, q0, q1 = auxslices[ia] shls_slice = (0, nbas, 0, nbas, shl0, shl1) int3c_ip2 = get_int3c_ip2(shls_slice) rhoj1 = np.einsum('xijp,ji->xp', int3c_ip2, dm0) coef3c = _load_dim0(rho0_Pij, q0, q1) Pij = _load_dim0(wj_Pij, q0, q1) vj1 += .5 * np.einsum('pij,xp->xij', coef3c, -rhoj1) vj1 += .5 * np.einsum('xijp,p->xij', int3c_ip2, -rhoj0_P[q0:q1]) vj1 -= .5 * lib.einsum('xpq,q,pij->xij', int2c_ip1[:,q0:q1], -rhoj0_P, coef3c) vj1 -= .5 * lib.einsum('pixj,p->xij', Pij, -rhoj0_P[q0:q1]) if with_k: rhok0_PlJ = lib.einsum('plj,Jj->plJ', rhok0a_Pl_[q0:q1], mocca) vk1a -= lib.einsum('plj,xijp->xil', rhok0_PlJ, int3c_ip2) vk1a += lib.einsum('pjxi,plj->xil', Pij, rhok0_PlJ) rhok0_PlJ = lib.einsum('plj,Jj->plJ', rhok0b_Pl_[q0:q1], moccb) vk1b -= lib.einsum('plj,xijp->xil', rhok0_PlJ, int3c_ip2) vk1b += lib.einsum('pjxi,plj->xil', Pij, rhok0_PlJ) vj1 = vj1 + vj1.transpose(0,2,1) if with_k: vk1a = vk1a + vk1a.transpose(0,2,1) vk1b = vk1b + vk1b.transpose(0,2,1) h1 = hcore_deriv(ia) yield ia, h1, vj1, (vk1a, vk1b)
[docs] class Hessian(uhf_hess.Hessian): '''Non-relativistic UHF hessian''' def __init__(self, mf): uhf_hess.Hessian.__init__(self, mf) auxbasis_response = 1 partial_hess_elec = partial_hess_elec make_h1 = make_h1
#TODO: Insert into DF class if __name__ == '__main__': from pyscf import gto from pyscf import scf mol = gto.Mole() mol.verbose = 0 mol.output = None mol.atom = [ [1 , (1. , 0. , 0.000)], [1 , (0. , 1. , 0.000)], [1 , (0. , -1.517 , 1.177)], [1 , (0. , 1.517 , 1.177)] ] mol.basis = '631g' mol.spin = 2 mol.unit = 'B' mol.build() mf = scf.UHF(mol).density_fit() mf.conv_tol = 1e-14 mf.scf() n3 = mol.natm * 3 hobj = Hessian(mf) e2 = hobj.kernel() ref = scf.UHF(mol).run().Hessian().kernel() print(abs(e2-ref).max()) print(lib.finger(e2) - -0.23856667321975722) e2 = hobj.set(auxbasis_response=2).kernel() print(abs(e2-ref).max()) print(lib.finger(e2), - 0.72321237584876141)