Skip to content

Commit aedaecc

Browse files
committed
Update dft_parser; Add tests for dft_parser
1 parent fb77fd8 commit aedaecc

File tree

4 files changed

+41
-12
lines changed

4 files changed

+41
-12
lines changed

pyscf/dft/dft_parser.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,11 @@
2929
@lru_cache(128)
3030
def parse_dft(dft_method):
3131
''' conventional dft method ->
32-
(xc, enable nlc, dispersion, with 3-body dispersion)
32+
(xc, enable nlc, (xc for dftd3, dispersion version, with 3-body dispersion))
3333
'''
3434
if not isinstance(dft_method, str):
35-
return dft_method, None, None, False
35+
return dft_method, None, (dft_method, None, False)
3636
method_lower = dft_method.lower()
37-
xc = dft_method
38-
disp = None
3937

4038
# special cases:
4139
# - wb97x-d is not supported yet
@@ -53,24 +51,30 @@ def parse_dft(dft_method):
5351
if method_lower == 'wb97x-d3bj':
5452
return 'wb97x-v', False, ('wb97x', 'd3bj', False)
5553

56-
# J. Chem. Theory Comput. 2013, 9, 1, 263272
54+
# J. Chem. Theory Comput. 2013, 9, 1, 263-272
5755
if method_lower in ['wb97x-d3']:
5856
raise NotImplementedError('wb97x-d3 is not supported yet.')
5957

6058
if method_lower.endswith('-3c'):
6159
raise NotImplementedError('*-3c methods are not supported yet.')
6260

61+
xc = dft_method
62+
disp = None
6363
for d in DISP_VERSIONS:
6464
if method_lower.endswith(d):
6565
disp = d
6666
xc = method_lower.replace(f'-{d}','')
67-
return xc, None, (xc, disp, False)
6867
if method_lower.endswith(d+'2b'):
6968
disp = d
7069
xc = method_lower.replace(f'-{d}2b', '')
71-
return xc, None, (xc, disp, False)
7270
if method_lower.endswith(d+'atm'):
7371
disp = d
7472
xc = method_lower.replace(f'-{d}atm', '')
75-
return xc, None, (xc, disp, True)
73+
74+
if disp is not None:
75+
if xc in ('b97m', 'wb97m', 'wb97x'):
76+
return xc+'-v', False, (xc, disp, False)
77+
else:
78+
return xc, None, (xc, disp, False)
79+
7680
return xc, None, (xc, None, False)

pyscf/dft/libxc.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -923,9 +923,9 @@ def is_gga(xc_code):
923923
@lru_cache(100)
924924
def is_nlc(xc_code):
925925
enable_nlc = dft_parser.parse_dft(xc_code)[1]
926-
if enable_nlc is False:
926+
if not (enable_nlc is None and enable_nlc):
927927
return False
928-
928+
# identify nlc by xc_code itself if enable_nlc is None
929929
if isinstance(xc_code, str):
930930
if xc_code.isdigit():
931931
return _itrf.LIBXC_is_nlc(ctypes.c_int(int(xc_code)))
@@ -1092,7 +1092,6 @@ def parse_xc(description):
10921092
(hybrid, alpha, omega), ((libxc-Id, fac), (libxc-Id, fac), ...)
10931093
''' # noqa: E501
10941094

1095-
description = dft_parser.parse_dft(description)[0]
10961095
hyb = [0, 0, 0] # hybrid, alpha, omega (== SR_HF, LR_HF, omega)
10971096
if description is None:
10981097
return tuple(hyb), ()
@@ -1111,6 +1110,8 @@ def parse_xc(description):
11111110
'To restore the VWN5 definition, you can put the setting '
11121111
'"B3LYP_WITH_VWN5 = True" in pyscf_conf.py')
11131112

1113+
description = dft_parser.parse_dft(description)[0]
1114+
11141115
def assign_omega(omega, hyb_or_sr, lr=0):
11151116
if hyb[2] == omega or omega == 0:
11161117
hyb[0] += hyb_or_sr
@@ -1237,6 +1238,8 @@ def possible_c_for(key):
12371238
parse_token(token, 'C')
12381239
else:
12391240
for token in description.replace('-', '+-').replace(';+', ';').split('+'):
1241+
# dftd3 cannot be used in a custom xc description
1242+
assert '-d3' not in token
12401243
parse_token(token, 'compound XC', search_xc_alias=True)
12411244
if hyb[2] == 0: # No omega is assigned. LR_HF is 0 for normal Coulomb operator
12421245
hyb[1] = 0

pyscf/dft/test/test_libxc.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,20 @@ def test_m06(self):
341341
self.assertAlmostEqual(abs(numpy.hstack([fxc[i] for i in [0,1,2,4,6,9]])-fxc_ref).max(), 0, 7)
342342
self.assertAlmostEqual(abs(numpy.hstack([kxc[i] for i in [0,1,2,3,5,7,10,12,15,19]])-kxc_ref).max(), 0, 6)
343343

344+
def test_dft_parser(self):
345+
from pyscf.dft.dft_parser import parse_dft
346+
self.assertEqual(parse_dft('wb97m-d3bj'), ('wb97m-v', False, ('wb97m', 'd3bj', False)))
347+
self.assertEqual(dft.libxc.parse_xc('wb97m-d3bj')[1][0][0] == 531)
348+
self.assertTrue(not dft.libxc.is_nlc('wb97m-d3bj'))
349+
350+
self.assertEqual(parse_dft('wb97-d3zerom'), ('wb97', None, ('wb97', 'd3zerom', False)))
351+
self.assertTrue(not dft.libxc.is_nlc('wb97-d3zerom'))
352+
353+
self.assertEqual(parse_dft('wb97m-d3bjatm'), ('wb97m-v', False, ('wb97m', 'd3bj', True)))
354+
self.assertTrue(not dft.libxc.is_nlc('wb97m-d3bjatm'))
355+
356+
self.assertEqual(parse_dft('wb97x-d3zero2b'), ('wb97x-v', False, ('wb97x', 'd3zero', False)))
357+
self.assertTrue(not dft.libxc.is_nlc('wb97x-d3zero2b'))
344358

345359
if __name__ == "__main__":
346360
print("Test libxc")

pyscf/dft/xcfun.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import numpy
2929
from pyscf import lib
3030
from pyscf.dft.xc.utils import remove_dup, format_xc_code
31-
from pyscf.dft import xc_deriv
31+
from pyscf.dft import xc_deriv, dft_parser
3232
from pyscf import __config__
3333

3434
_itrf = lib.load_library('libxcfun_itrf')
@@ -318,6 +318,9 @@ def is_gga(xc_code):
318318
VV10_XC.update([(5000+i, VV10_XC[key]) for i, key in enumerate(VV10_XC)])
319319

320320
def is_nlc(xc_code):
321+
enable_nlc = dft_parser.parse_dft(xc_code)[1]
322+
if not (enable_nlc is None and enable_nlc):
323+
return False
321324
fn_facs = parse_xc(xc_code)[1]
322325
return any(xid >= 5000 for xid, c in fn_facs)
323326

@@ -420,6 +423,8 @@ def parse_xc(description):
420423
elif not isinstance(description, str): #isinstance(description, (tuple,list)):
421424
return parse_xc('%s,%s' % tuple(description))
422425

426+
description = dft_parser.parse_dft(description)[0]
427+
423428
def assign_omega(omega, hyb_or_sr, lr=0):
424429
if hyb[2] == omega or omega == 0:
425430
hyb[0] += hyb_or_sr
@@ -430,6 +435,7 @@ def assign_omega(omega, hyb_or_sr, lr=0):
430435
hyb[2] = omega
431436
else:
432437
raise ValueError('Different values of omega found for RSH functionals')
438+
433439
fn_facs = []
434440
def parse_token(token, suffix, search_xc_alias=False):
435441
if token:
@@ -503,6 +509,8 @@ def parse_token(token, suffix, search_xc_alias=False):
503509
parse_token(token, 'C')
504510
else:
505511
for token in description.replace('-', '+-').replace(';+', ';').split('+'):
512+
# dftd3 cannot be used in a custom xc description
513+
assert '-d3' not in token
506514
parse_token(token, 'XC', search_xc_alias=True)
507515
if hyb[2] == 0: # No omega is assigned. LR_HF is 0 for normal Coulomb operator
508516
hyb[1] = 0

0 commit comments

Comments
 (0)