Skip to content

Commit 5bf28b1

Browse files
Continue refactor and start to move default params to separate object
1 parent c999cdc commit 5bf28b1

File tree

1 file changed

+143
-147
lines changed

1 file changed

+143
-147
lines changed

pymatgen/io/validation/check_incar.py

+143-147
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,78 @@
22
import numpy as np
33
from emmet.core.vasp.calc_types.enums import TaskType
44

5+
_vasp_defaults = {
6+
"AEXX": 0.0,
7+
"AGGAC": 1.0,
8+
"AGGAX": 1.0,
9+
"ALDAX": 1.0,
10+
"AMGGAX": 1.0,
11+
"ALDAC": 1.0,
12+
"AMGGAC": 1.0,
13+
"DEPER": 0.3,
14+
"EBREAK": 0.0,
15+
"GGA_COMPAT": True,
16+
"ICHARG": 2,
17+
"ICORELEVEL": 0,
18+
"IMAGES": 0,
19+
"INIWAV": 1,
20+
"ISTART": 0,
21+
"IVDW": 0,
22+
"LASPH": True,
23+
"LBERRY": False,
24+
"LCALCEPS": False,
25+
"LCALCPOL": False,
26+
"LDAU": False,
27+
"LDAUU": [],
28+
"LDAUJ": [],
29+
"LDAUL": [],
30+
"LDAUTYPE": 2,
31+
"LEPSILON": False,
32+
"LHFCALC": False,
33+
"LHYPERFINE": False,
34+
"LKPOINTS_OPT": False,
35+
"LKPROJ": False,
36+
"LMP2LT": False,
37+
"LNONCOLLINEAR": False,
38+
"LOCPROJ": None,
39+
"LRPA": False,
40+
"LSMP2LT": False,
41+
"LSORBIT": False,
42+
"LSPECTRAL": False,
43+
"LSUBROT": False,
44+
"ML_LMLFF": False,
45+
"WEIMIN": 0.001,
46+
}
47+
48+
_categories = {
49+
"hybrid": ("AEXX", "AGGAC", "AGGAX", "ALDAX", "AMGGAX", "ALDAC", "AMGGAC", "LHFCALC"),
50+
"ldau": ("LDAUU", "LDAUJ", "LDAUL", "LDAUTYPE"),
51+
"misc": (
52+
"DEPER",
53+
"IMAGES",
54+
"IVDW",
55+
"LSPECTRAL",
56+
"LHYPERFINE",
57+
"LASPH",
58+
"LKPOINTS_OPT",
59+
"LRPA",
60+
"LCALCEPS",
61+
"EBREAK",
62+
"LOCPROJ",
63+
"GGA_COMPAT",
64+
"LEPSILON",
65+
"LKPROJ",
66+
"ICORELEVEL",
67+
"ML_LMLFF",
68+
"LSUBROT",
69+
"LMP2LT",
70+
"LBERRY",
71+
"LSMP2LT",
72+
"LCALCPOL",
73+
),
74+
"ncl": ("LNONCOLLINEAR", "LSORBIT"),
75+
}
76+
577

678
def _check_incar(
779
reasons,
@@ -324,16 +396,8 @@ def _check_fft_params(
324396
def _check_hybrid_functional_params(reasons, parameters, valid_input_set):
325397
valid_lhfcalc = valid_input_set.incar.get("LHFCALC", False)
326398

327-
default_values = {
328-
"AEXX": 0.0,
329-
"AGGAC": 1.0,
330-
"AGGAX": 1.0,
331-
"ALDAX": 1.0,
332-
"AMGGAX": 1.0,
333-
"ALDAC": 1.0,
334-
"AMGGAC": 1.0,
335-
"LHFCALC": False,
336-
}
399+
default_values = {key: _vasp_defaults[key] for key in _categories["hybrid"]}
400+
337401
if valid_lhfcalc:
338402
default_values["AEXX"] = 0.25
339403
default_values["AGGAC"] = 0.0
@@ -344,13 +408,13 @@ def _check_hybrid_functional_params(reasons, parameters, valid_input_set):
344408
default_values["ALDAC"] = 0.0
345409
default_values["AMGGAC"] = 0.0
346410

347-
for hybrid_key in default_values:
411+
for key in _categories["hybrid"]:
348412
_check_required_params(
349413
reasons,
350414
parameters,
351-
hybrid_key,
352-
default_values[hybrid_key],
353-
valid_input_set.incar.get(hybrid_key, default_values[hybrid_key]),
415+
key,
416+
default_values[key],
417+
valid_input_set.incar.get(key, default_values[key]),
354418
allow_close=True,
355419
)
356420

@@ -560,15 +624,14 @@ def _check_lmaxmix_and_lmaxtau(reasons, warnings, parameters, incar, valid_input
560624

561625

562626
def _check_magnetism_params(reasons, parameters, valid_input_set):
563-
# LNONCOLLINEAR.
564-
default_lnoncollinear = False
565-
valid_lnoncollinear = valid_input_set.incar.get("LNONCOLLINEAR", default_lnoncollinear)
566-
_check_required_params(reasons, parameters, "LNONCOLLINEAR", default_lnoncollinear, valid_lnoncollinear)
567-
568-
# LSORBIT.
569-
default_lsorbit = False
570-
valid_lsorbit = valid_input_set.incar.get("LSORBIT", default_lsorbit)
571-
_check_required_params(reasons, parameters, "LSORBIT", default_lsorbit, valid_lsorbit)
627+
for key in _categories["ncl"]:
628+
_check_required_params(
629+
reasons,
630+
parameters,
631+
key,
632+
_vasp_defaults[key],
633+
valid_input_set.incar.get("LNONCOLLINEAR", _vasp_defaults[key]),
634+
)
572635

573636

574637
def _check_misc_params(
@@ -582,106 +645,46 @@ def _check_misc_params(
582645
vasp_minor_version,
583646
structure,
584647
):
585-
# DEPER.
586-
valid_deper = valid_input_set.incar.get("DEPER", 0.3)
587-
_check_required_params(reasons, parameters, "DEPER", 0.3, valid_deper, allow_close=True)
588-
589-
# EBREAK.
590-
valid_ebreak = valid_input_set.incar.get("EBREAK", 0.0)
591-
_check_required_params(reasons, parameters, "EBREAK", 0.0, valid_ebreak, allow_close=True)
592-
593-
# GGA_COMPAT.
594-
valid_gga_compat = valid_input_set.incar.get("GGA_COMPAT", True)
595-
_check_required_params(reasons, parameters, "GGA_COMPAT", True, valid_gga_compat)
596-
597-
# ICORELEVEL.
598-
valid_icorelevel = valid_input_set.incar.get("ICORELEVEL", 0)
599-
_check_required_params(reasons, parameters, "ICORELEVEL", 0, valid_icorelevel)
600-
601-
# IMAGES.
602-
valid_images = valid_input_set.incar.get("IMAGES", 0)
603-
_check_required_params(reasons, parameters, "IMAGES", 0, valid_images)
604-
605-
# IVDW.
606-
valid_ivdw = valid_input_set.incar.get("IVDW", 0)
607-
_check_required_params(reasons, parameters, "IVDW", 0, valid_ivdw)
608-
609-
# LBERRY.
610-
valid_lberry = valid_input_set.incar.get("LBERRY", False)
611-
_check_required_params(reasons, parameters, "LBERRY", False, valid_lberry)
612-
613-
# LCALCEPS.
614-
valid_lcalceps = valid_input_set.incar.get("LCALCEPS", False)
615-
_check_required_params(reasons, parameters, "LCALCEPS", False, valid_lcalceps)
616-
617-
# LCALCPOL.
618-
valid_lcalcpol = valid_input_set.incar.get("LCALCPOL", False)
619-
_check_required_params(reasons, parameters, "LCALCPOL", False, valid_lcalcpol)
620-
621-
# LEPSILON.
622-
valid_lepsilon = valid_input_set.incar.get("LEPSILON", False)
623-
_check_required_params(reasons, parameters, "LEPSILON", False, valid_lepsilon)
624-
625-
# LHYPERFINE.
626-
valid_lhyperfine = valid_input_set.incar.get("LHYPERFINE", False)
627-
_check_required_params(reasons, parameters, "LHYPERFINE", False, valid_lhyperfine)
628-
629-
# LKPOINTS_OPT.
630-
valid_lkpoints_opt = valid_input_set.incar.get("LKPOINTS_OPT", False)
631-
_check_required_params(reasons, parameters, "LKPOINTS_OPT", False, valid_lkpoints_opt)
632-
633-
# LKPROJ.
634-
valid_lkproj = valid_input_set.incar.get("LKPROJ", False)
635-
_check_required_params(reasons, parameters, "LKPROJ", False, valid_lkproj)
636-
637-
# LMP2LT.
638-
valid_lmp2lt = valid_input_set.incar.get("LMP2LT", False)
639-
_check_required_params(reasons, parameters, "LMP2LT", False, valid_lmp2lt)
640-
641-
# LOCPROJ.
642-
valid_locproj = valid_input_set.incar.get("LOCPROJ", None)
643-
_check_required_params(reasons, parameters, "LOCPROJ", None, valid_locproj)
644-
645-
# LRPA.
646-
valid_lrpa = valid_input_set.incar.get("LRPA", False)
647-
_check_required_params(reasons, parameters, "LRPA", False, valid_lrpa)
648-
649-
# LSMP2LT.
650-
valid_lsmp2lt = valid_input_set.incar.get("LSMP2LT", False)
651-
_check_required_params(reasons, parameters, "LSMP2LT", False, valid_lsmp2lt)
652-
653-
# LSPECTRAL.
654-
valid_lspectral = valid_input_set.incar.get("LSPECTRAL", False)
655-
_check_required_params(reasons, parameters, "LSPECTRAL", False, valid_lspectral)
656-
657-
# LSUBROT.
658-
valid_lsubrot = valid_input_set.incar.get("LSUBROT", False)
659-
_check_required_params(reasons, parameters, "LSUBROT", False, valid_lsubrot)
660-
661-
# ML_LMLFF.
662-
valid_ml_lmlff = valid_input_set.incar.get("ML_LMLFF", False)
663-
_check_required_params(reasons, parameters, "ML_LMLFF", False, valid_ml_lmlff)
648+
for key in _categories["misc"]:
649+
valid_deper = valid_input_set.incar.get(key, _vasp_defaults[key])
650+
_check_required_params(
651+
reasons,
652+
parameters,
653+
key,
654+
_vasp_defaults[key],
655+
valid_deper,
656+
allow_close=False if isinstance(key, int) else True,
657+
)
664658

665659
# WEIMIN.
666-
valid_weimin = valid_input_set.incar.get("WEIMIN", 0.001)
667-
_check_relative_params(reasons, parameters, "WEIMIN", 0.001, valid_weimin, "less than or equal to")
660+
_check_relative_params(
661+
reasons,
662+
parameters,
663+
"WEIMIN",
664+
_vasp_defaults["WEIMIN"],
665+
valid_input_set.incar.get("WEIMIN", _vasp_defaults["WEIMIN"]),
666+
"less than or equal to",
667+
)
668668

669-
# EFERMI. Only available for VASP >= 6.4. Should not be set to a numerical value, as this may change the number of electrons.
669+
"""
670+
EFERMI. Only available for VASP >= 6.4. Should not be set to a numerical
671+
value, as this may change the number of electrons.
672+
"""
670673
if (vasp_major_version >= 6) and (vasp_minor_version >= 4):
671-
# must check EFERMI in the *incar*, as it is saved as a numerical value after VASP guesses it in the vasprun.xml `parameters`
672-
# (which would always cause this check to fail, even if the user set EFERMI properly in the INCAR).
674+
"""
675+
Must check EFERMI in the *incar*, as it is saved as a numerical
676+
value after VASP guesses it in the vasprun.xml `parameters`
677+
(which would always cause this check to fail, even if the user
678+
set EFERMI properly in the INCAR).
679+
"""
673680
cur_efermi = incar.get("EFERMI", "LEGACY")
674681
allowed_efermis = ["LEGACY", "MIDGAP"]
675682
if cur_efermi not in allowed_efermis:
676683
reasons.append(f"INPUT SETTINGS --> EFERMI: should be one of {allowed_efermis}.")
677684

678685
# IWAVPR.
679686
if "IWAVPR" in incar.keys():
680-
reasons.append("INPUT SETTINGS --> VASP discourages users from setting the IWAVPR tag (as of July 2023).")
681-
682-
# LASPH.
683-
valid_lasph = valid_input_set.incar.get("LASPH", True)
684-
_check_required_params(reasons, parameters, "LASPH", False, valid_lasph)
687+
reasons.append("INPUT SETTINGS --> VASP discourages users from setting " "the IWAVPR tag (as of July 2023).")
685688

686689
# LCORR.
687690
cur_ialgo = parameters.get("IALGO", 38)
@@ -693,7 +696,9 @@ def _check_misc_params(
693696
# cur_lorbit = incar.get("LORBIT") if "LORBIT" in incar.keys() else parameters.get("LORBIT", None)
694697
if (cur_ispin == 2) and (len(calcs_reversed[0]["output"]["outcar"]["magnetization"]) != structure.num_sites):
695698
reasons.append(
696-
"INPUT SETTINGS --> LORBIT: magnetization values were not written to the OUTCAR. This is usually due to LORBIT being set to None or False for calculations with ISPIN=2."
699+
"INPUT SETTINGS --> LORBIT: magnetization values were not written "
700+
"to the OUTCAR. This is usually due to LORBIT being set to None or "
701+
"False for calculations with ISPIN=2."
697702
)
698703

699704
if parameters.get("LORBIT", -np.inf) >= 11 and parameters.get("ISYM", 2) and (vasp_major_version < 6):
@@ -704,15 +709,15 @@ def _check_misc_params(
704709
)
705710

706711
# RWIGS.
707-
if True in (
712+
if any(
708713
x != -1.0 for x in parameters.get("RWIGS", [-1])
709714
): # do not allow RWIGS to be changed, as this affects outputs like the magmom on each atom
710715
reasons.append(
711716
"INPUT SETTINGS --> RWIGS: should not be set. This is because it will change some outputs like the magmom on each site."
712717
)
713718

714719
# VCA.
715-
if True in (x != 1.0 for x in parameters.get("VCA", [1])): # do not allow VCA calculations
720+
if any(x != 1.0 for x in parameters.get("VCA", [1])): # do not allow VCA calculations
716721
reasons.append("INPUT SETTINGS --> VCA: should not be set")
717722

718723

@@ -751,21 +756,22 @@ def _check_precision_params(reasons, parameters, valid_input_set):
751756

752757
def _check_startup_params(reasons, parameters, incar, valid_input_set):
753758
# ICHARG.
754-
if valid_input_set.incar.get("ICHARG", 2) < 10:
759+
if valid_input_set.incar.get("ICHARG", _vasp_defaults["ICHARG"]) < 10:
755760
valid_icharg = 9 # should be <10 (SCF calcs)
756-
_check_relative_params(reasons, parameters, "ICHARG", 2, valid_icharg, "less than or equal to")
761+
_check_relative_params(
762+
reasons, parameters, "ICHARG", _vasp_defaults["ICHARG"], valid_icharg, "less than or equal to"
763+
)
757764
else:
758765
valid_icharg = valid_input_set.incar.get("ICHARG")
759-
_check_required_params(reasons, parameters, "ICHARG", 2, valid_icharg)
766+
_check_required_params(reasons, parameters, "ICHARG", _vasp_defaults["ICHARG"], valid_icharg)
760767

761768
# INIWAV.
762-
default_iniwav = 1
763-
valid_iniwav = valid_input_set.incar.get("INIWAV", default_iniwav)
764-
_check_required_params(reasons, parameters, "INIWAV", default_iniwav, valid_iniwav)
769+
valid_iniwav = valid_input_set.incar.get("INIWAV", _vasp_defaults["INIWAV"])
770+
_check_required_params(reasons, parameters, "INIWAV", _vasp_defaults["INIWAV"], valid_iniwav)
765771

766772
# ISTART.
767773
valid_istarts = [0, 1, 2]
768-
_check_allowed_params(reasons, parameters, "ISTART", 0, valid_istarts)
774+
_check_allowed_params(reasons, parameters, "ISTART", _vasp_defaults["ISTART"], valid_istarts)
769775

770776

771777
def _check_symmetry_params(reasons, parameters, valid_input_set):
@@ -801,30 +807,20 @@ def _check_symmetry_params(reasons, parameters, valid_input_set):
801807

802808

803809
def _check_u_params(reasons, incar, parameters, valid_input_set):
804-
if parameters.get("LDAU", False):
805-
valid_ldauu = valid_input_set.incar.get("LDAUU", [])
806-
cur_ldauu = incar.get("LDAUU", [])
807-
if cur_ldauu != valid_ldauu:
808-
reasons.append(f"INPUT SETTINGS --> LDAUU: set to {cur_ldauu}, but should be set to {valid_ldauu}.")
809-
810-
valid_ldauj = valid_input_set.incar.get("LDAUJ", [])
811-
cur_ldauj = incar.get("LDAUJ", [])
812-
if cur_ldauj != valid_ldauj:
813-
reasons.append(f"INPUT SETTINGS --> LDAUJ: set to {cur_ldauj}, but should be set to {valid_ldauj}.")
814-
815-
valid_ldaul = valid_input_set.incar.get("LDAUL", [])
816-
cur_ldaul = incar.get("LDAUL", [])
817-
if cur_ldaul != valid_ldaul:
818-
reasons.append(f"INPUT SETTINGS --> LDAUL: set to {cur_ldaul}, but should be set to {valid_ldaul}.")
819-
820-
valid_ldautype = valid_input_set.incar.get("LDAUTYPE", [2])
821-
if isinstance(valid_ldautype, list):
822-
valid_ldautype = valid_ldautype[0]
823-
cur_ldautype = parameters.get("LDAUTYPE", [2])[0]
824-
if cur_ldautype != valid_ldautype:
825-
reasons.append(
826-
f"INPUT SETTINGS --> LDAUTYPE: set to {cur_ldautype}, but should be set to {valid_ldautype}."
827-
)
810+
if parameters.get("LDAU", _vasp_defaults["LDAU"]):
811+
for key in _categories["ldau"]:
812+
valid_val = valid_input_set.incar.get(key, _vasp_defaults[key])
813+
814+
# TODO: ADK: is LDAUTYPE usually specified as a list??
815+
if key == "LDAUTYPE":
816+
cur_val = parameters.get(key, _vasp_defaults[key])
817+
cur_val = cur_val[0] if isinstance(cur_val, list) else cur_val
818+
valid_val = valid_val[0] if isinstance(valid_val, list) else valid_val
819+
else:
820+
cur_val = incar.get(key, _vasp_defaults[key])
821+
822+
if cur_val != valid_val:
823+
reasons.append(f"INPUT SETTINGS --> {key}: set to {cur_val}, " f"but should be set to {valid_val}.")
828824

829825

830826
def _check_write_params(reasons, parameters, valid_input_set):
@@ -855,7 +851,7 @@ def _check_required_params(
855851
):
856852
cur_val = parameters.get(input_tag, default_val)
857853

858-
if allow_close and isinstance(cur_val, (int, float)):
854+
if allow_close and isinstance(cur_val, float):
859855
if not np.isclose(cur_val, required_val, rtol=1e-05, atol=1e-05): # need to be careful of this
860856
msg = f"INPUT SETTINGS --> {input_tag}: set to {cur_val}, but should be {required_val}."
861857
if extra_comments_upon_failure != "":

0 commit comments

Comments
 (0)