Skip to content

Commit 73486ac

Browse files
authored
Becke weight Hessian (#413)
* Becke Hessian complete offdiagonal term working * Becke Hessian same derivative direction diagonal term working * Becke Hessian main diagonal working * Improvement according to suggestions
1 parent 34a34b7 commit 73486ac

File tree

3 files changed

+489
-9
lines changed

3 files changed

+489
-9
lines changed

gpu4pyscf/hessian/rks.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,40 @@ def get_dweight_dA(mol, grids):
13831383

13841384
return dweight_dA
13851385

1386+
def get_d2weight_dAdB(mol, grids):
1387+
ngrids = grids.coords.shape[0]
1388+
assert grids.atm_idx.shape[0] == ngrids
1389+
assert grids.quadrature_weights.shape[0] == ngrids
1390+
atm_coords = cupy.asarray(mol.atom_coords(), order = "C")
1391+
1392+
from gpu4pyscf.dft import radi
1393+
a_factor = radi.get_treutler_fac(mol, grids.atomic_radii)
1394+
1395+
d2weight_dAdB = cupy.zeros([mol.natm, mol.natm, 3, 3, ngrids], order = "C")
1396+
libgdft.GDFTbecke_partition_weight_second_derivative(
1397+
ctypes.cast(d2weight_dAdB.data.ptr, ctypes.c_void_p),
1398+
ctypes.cast(grids.coords.data.ptr, ctypes.c_void_p),
1399+
ctypes.cast(grids.quadrature_weights.data.ptr, ctypes.c_void_p),
1400+
ctypes.cast(atm_coords.data.ptr, ctypes.c_void_p),
1401+
ctypes.cast(a_factor.data.ptr, ctypes.c_void_p),
1402+
ctypes.cast(grids.atm_idx.data.ptr, ctypes.c_void_p),
1403+
ctypes.c_int(ngrids),
1404+
ctypes.c_int(mol.natm),
1405+
)
1406+
1407+
range_ngrids = cupy.arange(ngrids)
1408+
for i_atom in range(mol.natm):
1409+
for i_xyz in range(3):
1410+
for j_xyz in range(3):
1411+
d2weight_dAdB[i_atom, grids.atm_idx, i_xyz, j_xyz, range_ngrids] = -cupy.sum(d2weight_dAdB[i_atom, :, i_xyz, j_xyz, :], axis=[0])
1412+
1413+
for i_atom in range(mol.natm):
1414+
for i_xyz in range(3):
1415+
for j_xyz in range(3):
1416+
d2weight_dAdB[grids.atm_idx, i_atom, i_xyz, j_xyz, range_ngrids] = -cupy.sum(d2weight_dAdB[:, i_atom, i_xyz, j_xyz, :], axis=[0])
1417+
1418+
return d2weight_dAdB
1419+
13861420
def _get_vnlc_deriv1(hessobj, mo_coeff, mo_occ, max_memory):
13871421
"""
13881422
Equation notation follows:

gpu4pyscf/hessian/tests/test_vv10_hessian.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
import unittest
1616
import numpy as np
17+
import cupy as cp
1718
import pyscf
1819
from gpu4pyscf.dft import rks
1920
from gpu4pyscf.hessian.rks import _get_vnlc_deriv1, _get_vnlc_deriv1_numerical, \
20-
_get_enlc_deriv2, _get_enlc_deriv2_numerical
21+
_get_enlc_deriv2, _get_enlc_deriv2_numerical, \
22+
get_dweight_dA, get_d2weight_dAdB
2123

2224
def setUpModule():
2325
global mol
@@ -425,6 +427,41 @@ def test_vv10_fock_first_derivative(self):
425427

426428
assert np.linalg.norm(test_dF - reference_dF) < 1e-8
427429

430+
def test_becke_second_derivative(self):
431+
mf = rks.RKS(mol, xc = "PBE")
432+
mf.grids.atom_grid = (50,194)
433+
mf.grids.build()
434+
grids = mf.grids
435+
436+
test_d2w = get_d2weight_dAdB(mol, grids)
437+
438+
reference_d2w = cp.empty([mol.natm, mol.natm, 3, 3, grids.coords.shape[0]])
439+
dx = 1e-5
440+
mol_copy = mol.copy()
441+
for i_atom in range(mol.natm):
442+
for i_xyz in range(3):
443+
xyz_p = mol.atom_coords()
444+
xyz_p[i_atom, i_xyz] += dx
445+
mol_copy.set_geom_(xyz_p, unit='Bohr')
446+
mol_copy.build()
447+
grids.reset(mol_copy)
448+
grids.build()
449+
w_p = get_dweight_dA(mol_copy, grids)
450+
451+
xyz_m = mol.atom_coords()
452+
xyz_m[i_atom, i_xyz] -= dx
453+
mol_copy.set_geom_(xyz_m, unit='Bohr')
454+
mol_copy.build()
455+
grids.reset(mol_copy)
456+
grids.build()
457+
w_m = get_dweight_dA(mol_copy, grids)
458+
459+
reference_d2w[i_atom, :, i_xyz, :, :] = (w_p - w_m) / (2 * dx)
460+
grids.build(mol)
461+
462+
assert cp.max(cp.abs(test_d2w - reference_d2w)) < 1e-7
463+
464+
428465
if __name__ == "__main__":
429466
print("Full Tests for RKS Hessian with VV10")
430467
unittest.main()

0 commit comments

Comments
 (0)