21
21
"""
22
22
23
23
try :
24
- from pyscf import lib , gto
24
+ from pyscf import gto , lib , mcscf , scf
25
+ from pyscf .grad import rhf as rhf_grad
25
26
except ModuleNotFoundError :
26
27
raise ModuleNotFoundError ("This submodule requires pyscf installed" )
27
28
28
29
import numpy as np
29
- from typing import Tuple
30
+ from typing import Dict , Optional , Tuple
30
31
31
32
from .interface import (
32
33
DispersionModel ,
@@ -66,6 +67,52 @@ class DFTD3Dispersion(lib.StreamObject):
66
67
``"d3op"``
67
68
Optimized power damping function
68
69
70
+ Custom parameters can be provided with the `param` dictionary.
71
+ The `param` dict contains the damping parameters, at least s8, a1 and a2
72
+ must be provided for rational damping, while s8 and rs6 are required in case
73
+ of zero damping.
74
+
75
+ Parameters for (modified) rational damping are:
76
+
77
+ ======================== =========== ============================================
78
+ Tweakable parameter Default Description
79
+ ======================== =========== ============================================
80
+ s6 1.0 Scaling of the dipole-dipole dispersion
81
+ s8 None Scaling of the dipole-quadrupole dispersion
82
+ s9 1.0 Scaling of the three-body dispersion energy
83
+ a1 None Scaling of the critical radii
84
+ a2 None Offset of the critical radii
85
+ alp 14.0 Exponent of the zero damping (ATM only)
86
+ ======================== =========== ============================================
87
+
88
+ Parameters for (modified) zero damping are:
89
+
90
+ ======================== =========== ===================================================
91
+ Tweakable parameter Default Description
92
+ ======================== =========== ===================================================
93
+ s6 1.0 Scaling of the dipole-dipole dispersion
94
+ s8 None Scaling of the dipole-quadrupole dispersion
95
+ s9 1.0 Scaling of the three-body dispersion energy
96
+ rs6 None Scaling of the dipole-dipole damping
97
+ rs8 1.0 Scaling of the dipole-quadrupole damping
98
+ alp 14.0 Exponent of the zero damping
99
+ bet None Offset for damping radius (modified zero damping)
100
+ ======================== =========== ===================================================
101
+
102
+ Parameters for optimized power damping are:
103
+
104
+ ======================== =========== ============================================
105
+ Tweakable parameter Default Description
106
+ ======================== =========== ============================================
107
+ s6 1.0 Scaling of the dipole-dipole dispersion
108
+ s8 None Scaling of the dipole-quadrupole dispersion
109
+ s9 1.0 Scaling of the three-body dispersion energy
110
+ a1 None Scaling of the critical radii
111
+ a2 None Offset of the critical radii
112
+ alp 14.0 Exponent of the zero damping (ATM only)
113
+ bet None Power for the zero-damping component
114
+ ======================== =========== ============================================
115
+
69
116
The version of the damping can be changed after constructing the dispersion correction.
70
117
With the `atm` boolean the three-body dispersion energy can be enabled, which is
71
118
generally recommended.
@@ -107,14 +154,22 @@ class DFTD3Dispersion(lib.StreamObject):
107
154
array(-0.00574289)
108
155
"""
109
156
110
- def __init__ (self , mol , xc = "hf" , version = "d3bj" , atm = False ):
157
+ def __init__ (
158
+ self ,
159
+ mol : gto .Mole ,
160
+ xc : str = "hf" ,
161
+ version : str = "d3bj" ,
162
+ atm : bool = False ,
163
+ param : Optional [Dict [str , float ]] = None ,
164
+ ):
111
165
self .mol = mol
112
166
self .verbose = mol .verbose
113
167
self .xc = xc
168
+ self .param = param
114
169
self .atm = atm
115
170
self .version = version
116
171
117
- def dump_flags (self , verbose = None ):
172
+ def dump_flags (self , verbose : Optional [ bool ] = None ):
118
173
"""
119
174
Show options used for the DFT-D3 dispersion correction.
120
175
"""
@@ -168,16 +223,19 @@ def kernel(self) -> Tuple[float, np.ndarray]:
168
223
mol .atom_coords (),
169
224
)
170
225
171
- param = _damping_param [self .version ](
172
- method = self .xc ,
173
- atm = self .atm ,
174
- )
226
+ if self .param is not None :
227
+ param = _damping_param [self .version ](** self .param )
228
+ else :
229
+ param = _damping_param [self .version ](
230
+ method = self .xc ,
231
+ atm = self .atm ,
232
+ )
175
233
176
234
res = disp .get_dispersion (param = param , grad = True )
177
235
178
236
return res .get ("energy" ), res .get ("gradient" )
179
237
180
- def reset (self , mol ):
238
+ def reset (self , mol : gto . Mole ):
181
239
"""Reset mol and clean up relevant attributes for scanner mode"""
182
240
self .mol = mol
183
241
return self
@@ -199,7 +257,7 @@ class _DFTD3Grad:
199
257
pass
200
258
201
259
202
- def energy (mf ) :
260
+ def energy (mf : scf . hf . SCF , ** kwargs ) -> scf . hf . SCF :
203
261
"""
204
262
Apply DFT-D3 corrections to SCF or MCSCF methods by returning an
205
263
instance of a new class built from the original instances class.
@@ -208,8 +266,10 @@ def energy(mf):
208
266
209
267
Parameters
210
268
----------
211
- mf
269
+ mf: scf.hf.SCF
212
270
The method to which DFT-D3 corrections will be applied.
271
+ **kwargs
272
+ Keyword arguments passed to the `DFTD3Dispersion` class.
213
273
214
274
Returns
215
275
-------
@@ -237,17 +297,15 @@ def energy(mf):
237
297
-110.93260361702605
238
298
"""
239
299
240
- from pyscf .scf import hf
241
- from pyscf .mcscf import casci
242
-
243
- if not isinstance (mf , (hf .SCF , casci .CASCI )):
300
+ if not isinstance (mf , (scf .hf .SCF , mcscf .casci .CASCI )):
244
301
raise TypeError ("mf must be an instance of SCF or CASCI" )
245
302
246
303
with_dftd3 = DFTD3Dispersion (
247
304
mf .mol ,
248
305
xc = "hf"
249
- if isinstance (mf , casci .CASCI )
306
+ if isinstance (mf , mcscf . casci .CASCI )
250
307
else getattr (mf , "xc" , "HF" ).upper ().replace (" " , "" ),
308
+ ** kwargs ,
251
309
)
252
310
253
311
if isinstance (mf , _DFTD3 ):
@@ -287,7 +345,7 @@ def nuc_grad_method(self):
287
345
return DFTD3 (mf , with_dftd3 )
288
346
289
347
290
- def grad (scf_grad ):
348
+ def grad (scf_grad : rhf_grad . Gradients , ** kwargs ):
291
349
"""
292
350
Apply DFT-D3 corrections to SCF or MCSCF nuclear gradients methods
293
351
by returning an instance of a new class built from the original class.
@@ -296,8 +354,10 @@ def grad(scf_grad):
296
354
297
355
Parameters
298
356
----------
299
- mfgrad
357
+ scf_grad: rhf_grad.Gradients
300
358
The method to which DFT-D3 corrections will be applied.
359
+ **kwargs
360
+ Keyword arguments passed to the `DFTD3Dispersion` class.
301
361
302
362
Returns
303
363
-------
@@ -330,14 +390,13 @@ def grad(scf_grad):
330
390
5 H -0.0154527822 0.0229409425 -0.0215141991
331
391
----------------------------------------------
332
392
"""
333
- from pyscf .grad import rhf as rhf_grad
334
393
335
394
if not isinstance (scf_grad , rhf_grad .Gradients ):
336
395
raise TypeError ("scf_grad must be an instance of Gradients" )
337
396
338
397
# Ensure that the zeroth order results include DFTD3 corrections
339
398
if not getattr (scf_grad .base , "with_dftd3" , None ):
340
- scf_grad .base = dftd3 (scf_grad .base )
399
+ scf_grad .base = energy (scf_grad .base , ** kwargs )
341
400
342
401
class DFTD3Grad (_DFTD3Grad , scf_grad .__class__ ):
343
402
def grad_nuc (self , mol = None , atmlst = None ):
0 commit comments