-
Notifications
You must be signed in to change notification settings - Fork 875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update POTCAR summary stats to include 6.4 POTCARs and add dev_script
utils for future updates
#3370
Update POTCAR summary stats to include 6.4 POTCARs and add dev_script
utils for future updates
#3370
Changes from 4 commits
afbbf79
4a84723
f3b62f8
5828944
404bbb9
a90e2a4
66cfac8
cca9d39
ac2408d
ca5d50d
b955eeb
5c54cd0
93d3bcd
a916a68
6ace41b
209c0b0
baef777
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1607,6 +1607,7 @@ class PotcarSingle: | |
PBE="POT_GGA_PAW_PBE", | ||
PBE_52="POT_GGA_PAW_PBE_52", | ||
PBE_54="POT_GGA_PAW_PBE_54", | ||
PBE_64="POT_PAW_PBE_64", | ||
LDA="POT_LDA_PAW", | ||
LDA_52="POT_LDA_PAW_52", | ||
LDA_54="POT_LDA_PAW_54", | ||
|
@@ -2150,7 +2151,7 @@ def is_valid(self) -> bool: | |
tol is then used to match statistical values within a tolerance | ||
""" | ||
functional_lexch = { | ||
"PE": ["PBE", "PBE_52", "PBE_54"], | ||
"PE": ["PBE", "PBE_52", "PBE_54", "PBE_64"], | ||
"CA": ["LDA", "LDA_52", "LDA_54", "LDA_US", "Perdew_Zunger81"], | ||
"91": ["PW91", "PW91_US"], | ||
} | ||
|
@@ -2231,7 +2232,9 @@ def data_stats(data_list: Sequence) -> dict: | |
"MAX": arr.max(), | ||
} | ||
|
||
summary_stats = { # for this PotcarSingle instance | ||
# NB: to add future summary stats in a way that's consistent with PMG, | ||
# it's easiest to save the summary stats as an attr of PotcarSingle | ||
self._summary_stats = { # for this PotcarSingle instance | ||
"keywords": { | ||
"header": [kwd.lower() for kwd in self.keywords], | ||
"data": psp_keys, | ||
|
@@ -2245,12 +2248,12 @@ def data_stats(data_list: Sequence) -> dict: | |
data_match_tol = 1e-6 | ||
for ref_psp in possible_potcar_matches: | ||
key_match = all( | ||
set(ref_psp["keywords"][key]) == set(summary_stats["keywords"][key]) # type: ignore | ||
set(ref_psp["keywords"][key]) == set(self._summary_stats["keywords"][key]) # type: ignore | ||
for key in ["header", "data"] | ||
) | ||
|
||
data_diff = [ | ||
abs(ref_psp["stats"][key][stat] - summary_stats["stats"][key][stat]) # type: ignore | ||
abs(ref_psp["stats"][key][stat] - self._summary_stats["stats"][key][stat]) # type: ignore | ||
for stat in ["MEAN", "ABSMEAN", "VAR", "MIN", "MAX"] | ||
for key in ["header", "data"] | ||
] | ||
|
@@ -2280,6 +2283,43 @@ def __repr__(self) -> str: | |
return f"{cls_name}({symbol=}, {functional=}, {TITEL=}, {VRHFIN=}, {n_valence_elec=:.0f})" | ||
|
||
|
||
def _gen_potcar_summary_stats(): | ||
""" | ||
This function solely intended to be used for PMG development to regenerate the | ||
potcar_summary_stats.json.gz file used to validate POTCARs | ||
""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perfect! This is great to have. Even though it's marked as private, we should add a test for this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a |
||
from monty.shutil import compress_file | ||
|
||
func_dir_exist = {} | ||
PMG_VASP_PSP_DIR = SETTINGS.get("PMG_VASP_PSP_DIR") | ||
for func in PotcarSingle.functional_dir: | ||
cpsp_dir = f"{PMG_VASP_PSP_DIR}/{PotcarSingle.functional_dir[func]}" | ||
if os.path.isdir(cpsp_dir): | ||
func_dir_exist[func] = PotcarSingle.functional_dir[func] | ||
else: | ||
print(f"WARNING: missing {PotcarSingle.functional_dir[func]} POTCAR directory") | ||
|
||
new_summary_stats = {func: {} for func in func_dir_exist} | ||
for func in func_dir_exist: | ||
potcar_list = glob(f"{PMG_VASP_PSP_DIR}/{func_dir_exist[func]}/POTCAR*") + glob( | ||
f"{PMG_VASP_PSP_DIR}/{func_dir_exist[func]}/*/POTCAR" | ||
) | ||
for potcar in potcar_list: | ||
psp = PotcarSingle.from_file(potcar) | ||
new_summary_stats[func][psp.TITEL.replace(" ", "")] = { | ||
"LEXCH": psp.LEXCH, | ||
"VRHFIN": psp.VRHFIN.replace(" ", ""), | ||
**psp._summary_stats, | ||
} | ||
|
||
with open(f"{module_dir}/potcar_summary_stats.json", "w+") as _fl: | ||
json.dump(new_summary_stats, _fl) | ||
|
||
compress_file(f"{module_dir}/potcar_summary_stats.json") | ||
|
||
return | ||
|
||
|
||
class Potcar(list, MSONable): | ||
""" | ||
Object for reading and writing POTCAR files for calculations. Consists of a | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine here, but noting there is also a top-level
dev_scripts
folder (largely undocumented). On balance it's probably better here for discoverability for anyone curious how this file was generated.Minor comments: the bare
return
is unnecessary, andmonty.serialization.dumpfn
can be used directly withdumpfn(new_summary_stats, "filename.json.gz")
which is a convenience function we use a lot.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Much better way of doing this. For placement, you and @janosh probably have a better sense of where this belongs.
_gen_potcar_summary_stats
is a "destructive" function, in that it overwrites the file that's distributed with PMG.dev_scripts
might then be a better place for it