-
Notifications
You must be signed in to change notification settings - Fork 843
/
regen_libxcfunc.py
executable file
·125 lines (97 loc) · 3.46 KB
/
regen_libxcfunc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python
"""
This script regenerates the enum values in pymatgen.core.libxc_func.py.
It requires in input the path of the `libxc_docs.txt` file contained in libxc/src
The script parses this file, creates a new json file inside pymatgen.core
and update the enum values declared in LibxcFunc.
The script must be executed inside pymatgen/dev_scripts.
"""
from __future__ import annotations
import json
import os
import sys
def parse_libxc_docs(path):
"""
Parse libxc_docs.txt file, return dictionary with mapping:
libxc_id --> info_dict.
"""
def parse_section(section):
dct = {}
for line in section:
key, value = line.split(":")
dct[key.strip()] = value.strip()
return int(dct["Number"]), dct
dct = {}
with open(path) as fh:
section = []
for line in fh:
if not line.startswith("-"):
section.append(line)
else:
num, entry = parse_section(section)
assert num not in dct
dct[num] = entry
section = []
assert not section
return dct
def write_libxc_docs_json(xcfuncs, jpath):
"""Write json file with libxc metadata to path jpath."""
from copy import deepcopy
xcfuncs = deepcopy(xcfuncs)
# Remove XC_FAMILY from Family and XC_ from Kind to make strings more human-readable.
for d in xcfuncs.values():
d["Family"] = d["Family"].replace("XC_FAMILY_", "", 1)
d["Kind"] = d["Kind"].replace("XC_", "", 1)
# Build lightweight version with a subset of keys.
for num, d in xcfuncs.items():
xcfuncs[num] = {key: d[key] for key in ("Family", "Kind", "References")}
# Descriptions are optional
for opt in ("Description 1", "Description 2"):
desc = d.get(opt)
if desc is not None:
xcfuncs[num][opt] = desc
with open(jpath, "w") as fh:
json.dump(xcfuncs, fh)
return xcfuncs
def main():
"""Main function."""
if "-h" in sys.argv or "--help" in sys.argv:
print(__doc__)
print("Usage: regen_libxcfunc.py path_to_libxc_docs.txt")
return 0
try:
path = sys.argv[1]
except IndexError:
print(__doc__)
print("Usage: regen_libxcfunc.py path_to_libxc_docs.txt")
return 1
xc_funcs = parse_libxc_docs(path)
# Generate new json file in pycore
pmg_core = os.path.abspath("../pymatgen/core/")
json_path = os.path.join(pmg_core, "libxc_docs.json")
write_libxc_docs_json(xc_funcs, json_path)
# Build new enum list.
enum_list = []
for num, d in xc_funcs.items():
# Remove XC_ from codename
codename = d["Codename"][3:]
enum_list.append(f" {codename} = {num}")
enum_list = "\n".join(enum_list) + "\n"
# Re-generate enumerations.
# [0] read py module.
xc_funcpy_path = os.path.join(pmg_core, "libxcfunc.py")
with open(xc_funcpy_path) as fh:
lines = fh.readlines()
# [1] insert new enum values in list
start = lines.index("#begin_include_dont_touch\n")
stop = lines.index("#end_include_dont_touch\n")
lines.insert(stop, enum_list)
del lines[start + 1 : stop]
# [2] write new py module
with open(xc_funcpy_path, "w") as fh:
fh.writelines(lines)
print("Files have been regenerated")
print("Remember to update libxc_version in libxcfuncs.py!")
return 0
if __name__ == "__main__":
raise SystemExit(main())