Skip to content

Commit 0f931a0

Browse files
committed
UKS hessian with grid response in progress, each individual term is correct, DF hessian is correct, direct hessian is wrong
1 parent a29c92c commit 0f931a0

File tree

6 files changed

+1455
-42
lines changed

6 files changed

+1455
-42
lines changed

gpu4pyscf/df/hessian/uks.py

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,8 @@ def partial_hess_elec(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None,
4646

4747
mocca = mo_coeff[0][:,mo_occ[0]>0]
4848
moccb = mo_coeff[1][:,mo_occ[1]>0]
49-
dm0a = numpy.dot(mocca, mocca.T)
50-
dm0b = numpy.dot(moccb, moccb.T)
51-
if mf.do_nlc():
52-
raise NotImplementedError("2nd derivative of NLC is not implemented.")
49+
dm0a = mocca.dot(mocca.T)
50+
dm0b = moccb.dot(moccb.T)
5351

5452
omega, alpha, hyb = mf._numint.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin)
5553
with_k = mf._numint.libxc.is_hybrid_xc(mf.xc)
@@ -68,24 +66,11 @@ def partial_hess_elec(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None,
6866

6967
max_memory = None
7068
t1 = log.timer_debug1('computing ej, ek', *t1)
71-
veffa_diag, veffb_diag = uks_hess._get_vxc_diag(hessobj, mo_coeff, mo_occ, max_memory)
72-
73-
t1 = log.timer_debug1('computing veff_diag', *t1)
74-
aoslices = mol.aoslice_by_atom()
75-
vxca_dm, vxcb_dm = uks_hess._get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory)
76-
t1 = log.timer_debug1('computing veff_deriv2', *t1)
77-
for i0, ia in enumerate(atmlst):
78-
shl0, shl1, p0, p1 = aoslices[ia]
79-
veffa_dm = vxca_dm[ia]
80-
veffb_dm = vxcb_dm[ia]
81-
de2[i0,i0] += contract('xypq,pq->xy', veffa_diag[:,:,p0:p1], dm0a[p0:p1])*2
82-
de2[i0,i0] += contract('xypq,pq->xy', veffb_diag[:,:,p0:p1], dm0b[p0:p1])*2
83-
for j0, ja in enumerate(atmlst[:i0+1]):
84-
q0, q1 = aoslices[ja][2:]
85-
de2[i0,j0] += 2.0*cupy.sum(veffa_dm[:,:,q0:q1], axis=2)
86-
de2[i0,j0] += 2.0*cupy.sum(veffb_dm[:,:,q0:q1], axis=2)
87-
for j0 in range(i0):
88-
de2[j0,i0] = de2[i0,j0].T
69+
de2 += uks_hess._get_exc_deriv2(hessobj, mo_coeff, mo_occ, (dm0a, dm0b), max_memory)
70+
if mf.do_nlc():
71+
raise NotImplementedError("2nd derivative of NLC is not implemented.")
72+
# de2 += _get_enlc_deriv2(hessobj, mo_coeff, mo_occ, max_memory)
73+
8974
log.timer('RKS partial hessian', *time0)
9075
return de2
9176

gpu4pyscf/grad/tests/test_vv10_grid.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ def numerical_denlc(mf, dm, denlc_only = True):
101101
energy_p = mf.enlc
102102
else:
103103
energy_p = mf.kernel()
104+
assert mf.converged
104105

105106
xyz_m = mol.atom_coords()
106107
xyz_m[i_atom, i_xyz] -= dx
@@ -114,6 +115,7 @@ def numerical_denlc(mf, dm, denlc_only = True):
114115
energy_m = mf.enlc
115116
else:
116117
energy_m = mf.kernel()
118+
assert mf.converged
117119

118120
numerical_gradient[i_atom, i_xyz] = (energy_p - energy_m) / (2 * dx)
119121
mf.reset(mol)

gpu4pyscf/hessian/rks.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,13 @@ def partial_hess_elec(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None,
8787
de2 += rhf_hess._partial_ejk_ip2(
8888
mol, dm0, vhfopt, j_factor, k_factor, verbose=verbose)
8989

90-
t1 = log.timer_debug1('hessian of 2e part', *t1)
90+
t1 = log.timer_debug1('hessian of JK part', *t1)
91+
9192
de2 += _get_exc_deriv2(hessobj, mo_coeff, mo_occ, dm0, max_memory, atmlst, log)
9293
if mf.do_nlc():
9394
de2 += _get_enlc_deriv2(hessobj, mo_coeff, mo_occ, max_memory, log)
9495

96+
t1 = log.timer_debug1('hessian of XC part', *t1)
9597
log.timer('RKS partial hessian', *time0)
9698
return de2
9799

@@ -1086,8 +1088,20 @@ def _get_enlc_deriv2(hessobj, mo_coeff, mo_occ, max_memory, log = None):
10861088
mol = hessobj.mol
10871089
mf = hessobj.base
10881090

1089-
mocc = mo_coeff[:,mo_occ>0]
1090-
dm0 = 2 * mocc @ mocc.T
1091+
if mo_coeff.ndim == 3:
1092+
assert mo_coeff.shape[0] == 2
1093+
assert mo_occ.ndim == 2 and mo_occ.shape[0] == 2
1094+
mocc0 = mo_coeff[0][:, mo_occ[0]>0]
1095+
mocc1 = mo_coeff[1][:, mo_occ[1]>0]
1096+
dm0 = mocc0 @ mocc0.T + mocc1 @ mocc1.T
1097+
mocc0 = None
1098+
mocc1 = None
1099+
else:
1100+
mocc = mo_coeff[:,mo_occ>0]
1101+
dm0 = 2 * mocc @ mocc.T
1102+
mocc = None
1103+
mo_coeff = None
1104+
mo_occ = None
10911105

10921106
grids = mf.nlcgrids
10931107
if grids.coords is None:
@@ -1845,7 +1859,7 @@ def _get_vxc_deriv1_task(hessobj, grids, mo_coeff, mo_occ, max_memory, device_id
18451859

18461860
# rho = rho_drho[0]
18471861
# drho_dr = rho_drho[1:4]
1848-
rho_drho_tau = None
1862+
rho_drho = None
18491863

18501864
depsilon_drho = vxc[0]
18511865
depsilon_dnablarho = vxc[1:4]
@@ -2368,6 +2382,8 @@ def _get_vnlc_deriv1(hessobj, mo_coeff, mo_occ, max_memory):
23682382
mf = hessobj.base
23692383
natm = mol.natm
23702384

2385+
if mo_coeff.ndim != 2:
2386+
raise NotImplementedError("")
23712387
mocc = mo_coeff[:,mo_occ>0]
23722388
dm0 = 2 * mocc @ mocc.T
23732389

@@ -3428,6 +3444,7 @@ def _get_exc_deriv2_grid_response(hessobj, mo_coeff, mo_occ, max_memory):
34283444
aoslices = mol.aoslice_by_atom()
34293445

34303446
dm0 = mf.make_rdm1(mo_coeff, mo_occ)
3447+
assert dm0.ndim == 2
34313448

34323449
d2e = cupy.zeros([mol.natm, mol.natm, 3, 3])
34333450

gpu4pyscf/hessian/tests/test_rks_hessian_grid_response.py

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,16 @@ def _get_exc_deriv2_numerical(hessobj, mo_coeff, mo_occ, max_memory):
4949
"""
5050
mol = hessobj.mol
5151
mf = hessobj.base
52-
mocc = mo_coeff[:,mo_occ>0]
53-
dm0 = np.dot(mocc, mocc.T) * 2
52+
dm0 = mf.make_rdm1(mo_coeff, mo_occ)
5453

5554
de2 = np.empty([mol.natm, mol.natm, 3, 3])
5655

5756
def get_xc_de(grad_obj, dm):
5857
assert grad_obj.grid_response
59-
from gpu4pyscf.grad.rks import get_exc_full_response
58+
if dm.ndim == 2:
59+
from gpu4pyscf.grad.rks import get_exc_full_response
60+
else:
61+
from gpu4pyscf.grad.uks import get_exc_full_response
6062
mol = grad_obj.mol
6163
ni = mf._numint
6264
mf.grids.build()
@@ -95,16 +97,21 @@ def _get_vxc_deriv1_numerical(hessobj, mo_coeff, mo_occ, max_memory):
9597
"""
9698
mol = hessobj.mol
9799
mf = hessobj.base
98-
mocc = mo_coeff[:,mo_occ>0]
99-
dm0 = np.dot(mocc, mocc.T) * 2
100+
dm0 = mf.make_rdm1(mo_coeff, mo_occ)
100101

101102
nao = mol.nao
102-
vmat = cp.empty([mol.natm, 3, nao, nao])
103+
if dm0.ndim == 2:
104+
vmat = cp.empty([mol.natm, 3, nao, nao])
105+
else:
106+
vmat = cp.empty([mol.natm, 3, 2, nao, nao])
103107

104108
def get_vxc_vmat(mol, mf, dm):
105109
ni = mf._numint
106110
mf.grids.build()
107-
n, exc, vxc = ni.nr_rks(mol, mf.grids, mf.xc, dm)
111+
if dm.ndim == 2:
112+
n, exc, vxc = ni.nr_rks(mol, mf.grids, mf.xc, dm)
113+
else:
114+
n, exc, vxc = ni.nr_uks(mol, mf.grids, mf.xc, dm)
108115
return vxc
109116

110117
dx = 1e-5
@@ -125,12 +132,22 @@ def get_vxc_vmat(mol, mf, dm):
125132
mf.reset(mol_copy)
126133
vmat_m = get_vxc_vmat(mol_copy, mf, dm0)
127134

128-
vmat[i_atom, i_xyz, :, :] = (vmat_p - vmat_m) / (2 * dx)
135+
vmat[i_atom, i_xyz] = (vmat_p - vmat_m) / (2 * dx)
129136
mf.reset(mol)
130137

131-
vmat = cp.einsum('Adij,jq->Adiq', vmat, mocc)
132-
vmat = cp.einsum('Adiq,ip->Adpq', vmat, mo_coeff)
133-
return vmat
138+
if dm0.ndim == 3:
139+
mocc0 = mo_coeff[0][:, mo_occ[0]>0]
140+
mocc1 = mo_coeff[1][:, mo_occ[1]>0]
141+
vmat0 = cp.einsum('Adij,jq->Adiq', vmat[:,:,0,:,:], mocc0)
142+
vmat0 = cp.einsum('Adiq,ip->Adpq', vmat0, mo_coeff[0])
143+
vmat1 = cp.einsum('Adij,jq->Adiq', vmat[:,:,1,:,:], mocc1)
144+
vmat1 = cp.einsum('Adiq,ip->Adpq', vmat1, mo_coeff[1])
145+
return vmat0, vmat1
146+
else:
147+
mocc = mo_coeff[:,mo_occ>0]
148+
vmat = cp.einsum('Adij,jq->Adiq', vmat, mocc)
149+
vmat = cp.einsum('Adiq,ip->Adpq', vmat, mo_coeff)
150+
return vmat
134151

135152
class KnownValues(unittest.TestCase):
136153
# All reference results from the same calculation with mf.level_shift = 0

0 commit comments

Comments
 (0)