Skip to content

Commit c7730cc

Browse files
authored
Support D4S (#3)
* support d4s * remove tmp file * upgrade dftd4 * update compilation tool * gcc-9 * gcc-10 * update tools * gcc * rollback dftd4 version * bugfix dftd4 * wb97x * d4s gradient * grad=True * add warning * add test for wb97x * unit test for wb97x * unit test
1 parent f1cec2b commit c7730cc

File tree

5 files changed

+141
-29
lines changed

5 files changed

+141
-29
lines changed

.github/workflows/ci.yml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,17 @@ jobs:
1818
python-version: ${{ matrix.python-version }}
1919
- name: Install
2020
run: |
21-
sudo apt-get install -y libopenblas-dev
22-
pip install .
23-
pip install pytest
21+
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
22+
sudo apt-get update
23+
sudo apt install gcc-10 g++-10 gfortran-10
24+
sudo update-alternatives \
25+
--install /usr/bin/gcc gcc /usr/bin/gcc-10 100 \
26+
--slave /usr/bin/gfortran gfortran /usr/bin/gfortran-10 \
27+
--slave /usr/bin/gcov gcov /usr/bin/gcov-10
28+
sudo apt-get install -y libopenblas-dev
29+
pip install .
30+
pip install pytest
2431
- name: Test
2532
run: |
26-
export PYSCF_EXT_PATH=$(pwd):$PYSCF_EXT_PATH
27-
pytest -s pyscf/dispersion
33+
export PYSCF_EXT_PATH=$(pwd):$PYSCF_EXT_PATH
34+
pytest -s pyscf/dispersion

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,12 @@ Makefile
6262
cmake_install.cmake
6363
pyscf/lib/deps
6464
pyscf/lib/config.h
65-
65+
pyscf/lib/cmake/
66+
pyscf/lib/pkgconfig/
67+
pyscf/lib/libdftd4.*
68+
pyscf/lib/libs-dftd3.*
6669
settings.py
70+
*.cmake
6771

6872
# Memoization and caching
6973
tmp/

pyscf/dispersion/dftd4.py

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ class _d4_restype(ctypes.Structure):
2828
libdftd4.dftd4_new_error.restype = _d4_p
2929
libdftd4.dftd4_new_structure.restype = _d4_p
3030
libdftd4.dftd4_new_d4_model.restype = _d4_p
31+
libdftd4.dftd4_new_d4s_model.restype = _d4_p
3132
libdftd4.dftd4_custom_d4_model.restype = _d4_p
33+
libdftd4.dftd4_custom_d4s_model.restype = _d4_p
3234
libdftd4.dftd4_load_rational_damping.restype = _d4_p
3335
libdftd4.dftd4_new_rational_damping.restype = _d4_p
3436

@@ -40,18 +42,22 @@ def error_check(err):
4042
raise RuntimeError(message.value.decode())
4143

4244
class DFTD4Dispersion(lib.StreamObject):
43-
def __init__(self, mol, xc, ga=None, gc=None, wf=None, atm=False):
45+
def __init__(self, mol, xc, version='d4', ga=None, gc=None, wf=None, atm=False):
4446
xc_lc = xc.lower().encode()
4547
self._disp = None
4648
self._mol = None
4749
self._param = None
4850

51+
log = lib.logger.new_logger(mol)
52+
# https://github.com/dftd4/dftd4/pull/276
53+
if xc_lc == 'wb97x':
54+
log.warn('The previous wb97x is renamed as wb97x-2008. Now D4 dispersion for wb97x is the replacement of vv10 in wb97x-v. See https://github.com/dftd4/dftd4/blob/main/README.md')
4955
coords = np.asarray(mol.atom_coords(), dtype=np.double, order='C')
5056
charge = np.array([mol.charge], dtype=np.double)
5157
nuc_types = [gto.charge(mol.atom_symbol(ia))
5258
for ia in range(mol.natm)]
5359
nuc_types = np.asarray(nuc_types, dtype=np.int32)
54-
60+
5561
self.natm = mol.natm
5662
if isinstance(mol, gto.Mole):
5763
lattice = lib.c_null_ptr()
@@ -71,20 +77,29 @@ def __init__(self, mol, xc, ga=None, gc=None, wf=None, atm=False):
7177
lattice, periodic,
7278
)
7379
error_check(err)
74-
if ga is None and gc is None and wf is None:
75-
self._disp = libdftd4.dftd4_new_d4_model(err, self._mol)
80+
if version.lower() == 'd4':
81+
if ga is None and gc is None and wf is None:
82+
self._disp = libdftd4.dftd4_new_d4_model(err, self._mol)
83+
else:
84+
# Default from DFTD4 repo, https://github.com/dftd4/dftd4/blob/main/python/dftd4/interface.py#L290
85+
if ga is None: ga = 3.0
86+
if gc is None: gc = 2.0
87+
if wf is None: wf = 6.0
88+
self._disp = libdftd4.dftd4_custom_d4_model(err, self._mol,
89+
ctypes.c_double(ga),
90+
ctypes.c_double(gc),
91+
ctypes.c_double(wf))
92+
elif version.lower() == 'd4s':
93+
if ga is None and gc is None:
94+
self._disp = libdftd4.dftd4_new_d4s_model(err, self._mol)
95+
else:
96+
if ga is None: ga = 3.0
97+
if gc is None: gc = 2.0
98+
self._disp = libdftd4.dftd4_custom_d4s_model(err, self._mol,
99+
ctypes.c_double(ga),
100+
ctypes.c_double(gc))
76101
else:
77-
# Default from DFTD4 repo, https://github.com/dftd4/dftd4/blob/main/python/dftd4/interface.py#L290
78-
if ga is None:
79-
ga = 3.0
80-
if gc is None:
81-
gc = 2.0
82-
if wf is None:
83-
wf = 6.0
84-
self._disp = libdftd4.dftd4_custom_d4_model(err, self._mol,
85-
ctypes.c_double(ga),
86-
ctypes.c_double(gc),
87-
ctypes.c_double(wf))
102+
raise ValueError('version must be d4 or d4s')
88103
error_check(err)
89104
self._param = libdftd4.dftd4_load_rational_damping(
90105
err,
@@ -107,10 +122,10 @@ def __del__(self):
107122
def set_param(self, s8, a1, a2, s6=1.0, s9=1.0, alp=16.0):
108123
self._param = libdftd4.dftd4_new_rational_damping(
109124
ctypes.c_double(s6),
110-
ctypes.c_double(s8),
111-
ctypes.c_double(s9),
112-
ctypes.c_double(a1),
113-
ctypes.c_double(a2),
125+
ctypes.c_double(s8),
126+
ctypes.c_double(s9),
127+
ctypes.c_double(a1),
128+
ctypes.c_double(a2),
114129
ctypes.c_double(alp))
115130
return
116131

pyscf/dispersion/tests/test_d4.py

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@ def test_d4_unknown_xc():
2525

2626
def test_d4_energy():
2727
mol = pyscf.M(atom='H 0 0 0; H 0 0 1')
28-
model = DFTD4Dispersion(mol, xc='WB97X')
28+
model = DFTD4Dispersion(mol, xc='WB97X-2008')
2929
out = model.get_dispersion()
3030
assert abs(out['energy'] - -2.21334459527e-05) < 1e-10
3131

32+
def test_wb97x_d4_energy():
33+
mol = pyscf.M(atom='H 0 0 0; H 0 0 1')
34+
model = DFTD4Dispersion(mol, xc='WB97X')
35+
out = model.get_dispersion()
36+
assert abs(out['energy'] - -0.00027002) < 1e-8
37+
3238
def test_d4_gradients():
3339
mol = pyscf.M(atom='H 0 0 0; H 0 0 1')
3440
model = DFTD4Dispersion(mol, xc='HF')
@@ -39,6 +45,82 @@ def test_d4_gradients():
3945

4046
def test_d4_with_pbc():
4147
mol = pyscf.M(atom='H 0 0 0; H 0 0 1', a=np.eye(3)*2)
42-
model = DFTD4Dispersion(mol, xc='WB97X')
48+
model = DFTD4Dispersion(mol, xc='WB97X-2008')
4349
out = model.get_dispersion()
4450
assert abs(out['energy'] - -0.002715970438476524) < 1e-10
51+
52+
def test_d4s_energy():
53+
''' Test copied from DFTD4
54+
'''
55+
mol = pyscf.M(
56+
atom="""
57+
Na -1.855282634 3.586705153 -2.417637293
58+
H 4.401780235 0.023388444 -4.954577493
59+
O -2.987060334 4.762520654 1.270433015
60+
H 0.799808860 1.411034556 -5.046553216
61+
F -4.206474694 1.842757675 4.550380848
62+
H -3.543561218 -3.188356651 1.462400217
63+
H 2.700321601 1.068184525 -1.732346503
64+
O 3.731140888 -2.070015433 2.231609376
65+
N -1.753068192 0.359514171 1.053234061
66+
H 5.417557885 -1.578818300 1.753940027
67+
H -2.234628682 -2.138565050 4.109222857
68+
Cl 1.015658662 -3.219521545 -3.360509630
69+
B 2.421192557 0.266264350 -3.918624743
70+
B -3.025260988 2.536678890 2.316649847
71+
N -2.004389486 -2.292351369 2.197828073
72+
Al 1.122265541 -1.369420070 0.484550554
73+
"""
74+
)
75+
model = DFTD4Dispersion(mol, xc="TPSS", version="d4s")
76+
out = model.get_dispersion()
77+
assert abs(out['energy'] - -0.016049411775539424) < 1.0e-7
78+
79+
def test_d4s_gradient():
80+
''' Test copied from DFTD4
81+
'''
82+
mol = pyscf.M(
83+
atom="""
84+
H -1.795376258 -3.778664229 -1.078835583
85+
S -2.682788333 0.388926662 1.662148652
86+
B 0.114846497 1.488579332 3.656603965
87+
O -1.079988795 -0.162591216 -4.557030658
88+
Mg 0.603028329 4.088161496 -0.025893731
89+
H -1.225340893 -1.799813824 -3.707731733
90+
H -1.334609820 -4.248190824 2.727919027
91+
H -0.162780825 2.412679941 5.690306951
92+
Si 2.878024440 -0.331205250 1.883113735
93+
H 0.684893279 0.327902040 -4.205476937
94+
B -1.209197735 -2.872537625 0.940642042
95+
Li -3.255726045 2.212410929 -2.867155493
96+
F -1.831474682 5.205272937 -2.269762706
97+
H 4.908858657 -1.925765619 2.990699194
98+
H 1.268062422 -2.604093417 0.551628052
99+
S 4.119569763 1.598928667 -1.391174777
100+
""",
101+
spin=1
102+
)
103+
ref = np.array(
104+
[
105+
[-1.04361222e-04, -1.65054791e-04, -1.36662175e-04],
106+
[-1.41500522e-03, +1.89282651e-04, +2.16639105e-04],
107+
[-1.18067839e-04, +4.50543787e-04, +1.50087553e-03],
108+
[+3.37690080e-04, -4.10348598e-04, -3.02311767e-04],
109+
[+4.39892308e-04, +1.54862493e-03, +1.33655085e-04],
110+
[+1.31259180e-06, -7.51721105e-05, -1.39848135e-04],
111+
[-4.61111364e-05, -1.65382677e-04, +1.81820530e-04],
112+
[-1.94292825e-05, +7.21791149e-05, +1.79879351e-04],
113+
[+1.14226323e-03, -6.08455689e-04, +6.24007890e-04],
114+
[+6.95738570e-05, -1.86718359e-05, -1.25837081e-04],
115+
[-1.66091884e-04, -1.03519307e-03, -1.71797180e-04],
116+
[-1.29925668e-03, +6.18658801e-05, -6.30138324e-04],
117+
[-1.58991399e-04, +5.73306273e-04, -2.35799582e-04],
118+
[+2.90056077e-04, -2.14985916e-04, +1.62430848e-04],
119+
[+6.43808246e-05, -3.35585457e-04, -2.45131168e-04],
120+
[+9.82145702e-04, +1.33047503e-04, -1.01178292e-03],
121+
]
122+
)
123+
124+
model = DFTD4Dispersion(mol, xc="BLYP", version="d4s")
125+
out = model.get_dispersion(grad=True)
126+
assert np.linalg.norm(out['gradient'] - ref) < 1.0e-7

pyscf/lib/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
cmake_minimum_required (VERSION 3.5)
1616
project (pyscf-dispersion)
1717

18+
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -cpp -ffree-line-length-none -Wall")
19+
1820
include(ExternalProject)
1921
# statically compile deps mctc mstore
2022
ExternalProject_Add(dftd3_static
@@ -46,23 +48,25 @@ add_dependencies(dftd3 dftd3_static)
4648
# statically compile deps mctc mstore
4749
ExternalProject_Add(dftd4_static
4850
GIT_REPOSITORY "https://github.com/dftd4/dftd4"
49-
GIT_TAG v3.7.0
51+
GIT_TAG cf1af36a0f89fdaa2faa15def912148db9f7cb07
5052
GIT_SHALLOW FALSE
5153
GIT_PROGRESS TRUE
5254
PREFIX ${PROJECT_BINARY_DIR}/deps
5355
INSTALL_DIR ${PROJECT_SOURCE_DIR}/deps
5456
CMAKE_ARGS -DWITH_OpenMP=OFF
57+
-DCMAKE_Fortran_FLAGS=-cpp\ -ffree-line-length-none\ -Wall
5558
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
5659
-DCMAKE_INSTALL_LIBDIR:PATH=lib
5760
)
5861
ExternalProject_Add(dftd4
5962
GIT_REPOSITORY "https://github.com/dftd4/dftd4"
60-
GIT_TAG v3.7.0
63+
GIT_TAG cf1af36a0f89fdaa2faa15def912148db9f7cb07
6164
GIT_SHALLOW FALSE
6265
GIT_PROGRESS TRUE
6366
PREFIX ${PROJECT_BINARY_DIR}/deps
6467
INSTALL_DIR ${PROJECT_SOURCE_DIR}/deps
6568
CMAKE_ARGS -DWITH_OpenMP=OFF -DBUILD_SHARED_LIBS=ON
69+
-DCMAKE_Fortran_FLAGS=-cpp\ -ffree-line-length-none\ -Wall
6670
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
6771
-DCMAKE_INSTALL_LIBDIR:PATH=${PROJECT_SOURCE_DIR}
6872
)

0 commit comments

Comments
 (0)