Coverage for gpaw/xc/__init__.py: 96%
103 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-09 00:21 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-09 00:21 +0000
1from gpaw import get_libraries
2from gpaw.xc.functional import XCFunctional
3from gpaw.xc.gga import GGA
4from gpaw.xc.lda import LDA
5from gpaw.xc.libxc import LibXC
6from gpaw.xc.mgga import MGGA
7from gpaw.xc.noncollinear import NonCollinearLDAKernel
10libraries = get_libraries()
13def xc_string_to_dict(string):
14 """Convert XC specification string to dictionary.
16 'name:key1=value1:...' -> {'name': <name>, key1: value1, ...}."""
17 tokens = string.split(':')
19 d = {'name': tokens[0]}
20 for token in tokens[1:]:
21 kw, val = token.split('=')
22 # Convert value to int or float if possible
23 try:
24 val = int(val)
25 except ValueError:
26 try:
27 val = float(val)
28 except ValueError:
29 pass
30 d[kw] = val
31 return d
34def XC(kernel,
35 parameters=None,
36 atoms=None,
37 collinear=True) -> XCFunctional:
38 """Create XCFunctional object.
40 kernel: XCKernel object, dict or str
41 Kernel object or name of functional.
42 parameters: ndarray
43 Parameters for BEE functional.
45 Recognized names are: LDA, PW91, PBE, revPBE, RPBE, BLYP, HCTH407,
46 TPSS, M06-L, revTPSS, vdW-DF, vdW-DF2, EXX, PBE0, B3LYP, BEE,
47 GLLBSC. One can also use equivalent libxc names, for example
48 GGA_X_PBE+GGA_C_PBE is equivalent to PBE, and LDA_X to the LDA exchange.
49 In this way one has access to all the functionals defined in libxc.
50 See xc_funcs.h for the complete list.
52 Warning - if an MGGA from libxc is used, libxc should be compiled
53 with --disable-fhc. Otherwise the calcualtions won't converge"""
55 if isinstance(kernel, str):
56 kernel = xc_string_to_dict(kernel)
58 kwargs = {}
59 if isinstance(kernel, dict):
60 kwargs = kernel.copy()
61 name = kwargs.pop('name')
62 backend = kwargs.pop('backend', None)
64 if backend == 'libvdwxc' or name == 'vdW-DF-cx':
65 # Must handle libvdwxc before old vdw implementation to override
66 # behaviour for 'name'. Also, cx is not implemented by the old
67 # vdW module, so that always refers to libvdwxc.
68 from gpaw.xc.libvdwxc import get_libvdwxc_functional
69 return get_libvdwxc_functional(name=name, **kwargs)
70 elif backend == 'ri':
71 # Note: It is important that this if is before the next name is
72 # HSExx, since otherwise PWHybrid would hijack the control flow.
73 from gpaw.xc.ri import RI
74 return RI(name, **kwargs)
75 elif backend == 'pw' or name in ['HSE03', 'HSE06', 'YS-PBE0']:
76 from gpaw.hybrids import HybridXC
77 return HybridXC(name, **kwargs) # type: ignore
78 elif backend:
79 raise ValueError(
80 'A special backend for the XC functional was given, '
81 'but not understood. Please check if there is a typo.')
83 if name in ['vdW-DF', 'vdW-DF2', 'optPBE-vdW', 'optB88-vdW',
84 'C09-vdW', 'mBEEF-vdW', 'BEEF-vdW']:
85 from gpaw.xc.vdw import VDWFunctional
86 return VDWFunctional(name, **kwargs)
87 elif name in ['EXX', 'PBE0', 'B3LYP',
88 'CAMY-BLYP', 'CAMY-B3LYP', 'LCY-BLYP', 'LCY-PBE']:
89 from gpaw.xc.hybrid import HybridXC as OldHybridXC
90 return OldHybridXC(name, **kwargs) # type: ignore
91 elif name.startswith('LCY-') or name.startswith('CAMY-'):
92 parts = name.split('(')
93 from gpaw.xc.hybrid import HybridXC as OldHybridXC
94 return OldHybridXC(parts[0],
95 omega=float(parts[1][:-1]))
96 elif name == 'BEE2':
97 from gpaw.xc.bee import BEE2
98 kernel = BEE2(parameters)
99 elif name.startswith('GLLB'):
100 from gpaw.xc.gllb.nonlocalfunctionalfactory import \
101 get_nonlocal_functional
102 xc = get_nonlocal_functional(name, **kwargs)
103 return xc
104 elif name == 'LB94':
105 from gpaw.xc.lb94 import LB94
106 kernel = LB94()
107 elif name == 'TB09':
108 from gpaw.xc.tb09 import TB09
109 return TB09(**kwargs)
110 elif name.endswith('PZ-SIC'):
111 from gpaw.xc.sic import SIC
112 return SIC(xc=name[:-7], **kwargs)
113 elif name in {'TPSS', 'revTPSS', 'M06-L'}:
114 assert libraries['libxc'], 'Please compile with libxc'
115 from gpaw.xc.kernel import XCKernel
116 kernel = XCKernel(name)
117 elif name in {'LDA', 'PBE', 'revPBE', 'RPBE', 'PW91'}:
118 from gpaw.xc.kernel import XCKernel
119 kernel = XCKernel(name)
120 elif name.startswith('old'):
121 from gpaw.xc.kernel import XCKernel
122 kernel = XCKernel(name[3:])
123 elif name == 'PPLDA':
124 from gpaw.xc.lda import PurePythonLDAKernel
125 kernel = PurePythonLDAKernel()
126 elif name in ['pyPBE', 'pyPBEsol', 'pyRPBE', 'pyzvPBEsol']:
127 from gpaw.xc.gga import PurePythonGGAKernel
128 kernel = PurePythonGGAKernel(name)
129 elif name == '2D-MGGA':
130 from gpaw.xc.mgga import PurePython2DMGGAKernel
131 kernel = PurePython2DMGGAKernel(name, parameters)
132 elif name[0].isdigit():
133 from gpaw.xc.parametrizedxc import ParametrizedKernel
134 kernel = ParametrizedKernel(name)
135 elif name == 'null':
136 from gpaw.xc.kernel import XCNull
137 kernel = XCNull()
138 elif name == 'QNA':
139 from gpaw.xc.qna import QNA
140 return QNA(atoms, kernel['parameters'], kernel['setup_name'],
141 alpha=kernel['alpha'], stencil=kwargs.get('stencil', 2))
142 else:
143 kernel = LibXC(name)
145 if kernel.type == 'LDA':
146 if not collinear:
147 kernel = NonCollinearLDAKernel(kernel)
148 return LDA(kernel, **kwargs)
150 elif kernel.type == 'GGA':
151 return GGA(kernel, **kwargs)
152 else:
153 return MGGA(kernel, **kwargs)