Skip to content

Commit b40ce6e

Browse files
tpurcell90janoshpre-commit-ci[bot]
authored
Aims input sets (#3482)
* Add aims InputSets move them from atomate2 to pymatgen as @utf requested * Move input set and file tests from atomate2 to here Also adjust the tests for not having all fixtures * Initial setup to move all input generators to pymatgen * Add AimsInputGenerator to aims/sets/base Move default input set generator to pymatgen * Move Core input sets from atomate2 into pymatgen * Add bs sets from atomate2 * Correct sets import in core forgot an io * Move input generator tests into pymatgen * BS and GW tests work * All generator tests now work * Add input generator refs from atomate2 * See if this fixes the windows path str errror * This should fix the windows tests json encoder did not use base string for path * pre-commit auto-fixes * Fix ruff error pre-commit conflict resolved incorrectly * fix error in species_dir Somehow this was removed * fix typo * remove cwd context manager, use monty instead * Make requested changes to the test sets Monkeypatch cahnge env Actually test check_bands * Fix Bugs in modifications 1) InputSet remove_parameters error message became more verbose 2) Have to assert True not raise False * pre-commit auto-fixes * rename GWSetGenerator(user_parameters->user_params), simplify tests in tests/io/aims/test_sets/test_input_set.py * del deepcopy method * Test if `compare_files` in __init__.py works I think my previous error was in the conftest file and not __init__ * Add test_sets __init__.py * Create a helper module in tests for common aims test function removal 1) remove tests.__init__.py and similar files in io and io/aims this conflicts with a latex package that is a depdency that installs a "tests" directory into site-packages 2) creates a helpers and helpers/aims folder for what would be in tests/io/aims/__init__ 3) Modify conftest and pytest ini in pyproject.toml to fix this * Remove AimsInputFile This class is not really needed * Bug Fix: AimsControlIn Preamble write time The content of the preamble should be made upon writing file not generating content * Remove uncessary files * rm tests/helpers/__init__.py, add pymatgen/util/testing/aims.py instead after moving pymatgen/util/(testing.py -> testing/__init__.py) * Remove aims_sd_monkeypatch from tests Make it once in conf tests * refactor _set_aims_species_dir_env_var fixture * 1) Remove seperate static_restart tests comp_system 2) Add more diverse docstrings to the testing.aims files * Specify species_dir for windows tests --------- Signed-off-by: Thomas Purcell <[email protected]> Co-authored-by: Thomas Purcell <[email protected]> Co-authored-by: Janosh Riebesell <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent d677a0a commit b40ce6e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1668
-74
lines changed

pymatgen/io/aims/inputs.py

Lines changed: 77 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,81 @@ def get_aims_control_parameter_str(self, key: str, value: Any, fmt: str) -> str:
481481
"""
482482
return f"{key:35s}{fmt % value}\n"
483483

484+
def get_content(
485+
self, structure: Structure | Molecule, verbose_header: bool = False, directory: str | Path | None = None
486+
) -> str:
487+
"""Get the content of the file
488+
489+
Args:
490+
structure (Structure or Molecule): The structure to write the input
491+
file for
492+
verbose_header (bool): If True print the input option dictionary
493+
directory: str | Path | None = The directory for the calculation,
494+
495+
Returns:
496+
str: The content of the file for a given structure
497+
"""
498+
parameters = deepcopy(self._parameters)
499+
500+
if directory is None:
501+
directory = ""
502+
503+
lim = "#" + "=" * 79
504+
content = ""
505+
506+
if parameters["xc"] == "LDA":
507+
parameters["xc"] = "pw-lda"
508+
509+
cubes = parameters.pop("cubes", None)
510+
511+
if verbose_header:
512+
content += "# \n# List of parameters used to initialize the calculator:"
513+
for param, val in parameters.items():
514+
s = f"# {param}:{val}\n"
515+
content += s
516+
content += lim + "\n"
517+
518+
assert not ("smearing" in parameters and "occupation_type" in parameters)
519+
520+
for key, value in parameters.items():
521+
if key in ["species_dir", "plus_u"]:
522+
continue
523+
if key == "smearing":
524+
name = parameters["smearing"][0].lower()
525+
if name == "fermi-dirac":
526+
name = "fermi"
527+
width = parameters["smearing"][1]
528+
if name == "methfessel-paxton":
529+
order = parameters["smearing"][2]
530+
order = " %d" % order
531+
else:
532+
order = ""
533+
534+
content += self.get_aims_control_parameter_str("occupation_type", (name, width, order), "%s %f%s")
535+
elif key == "output":
536+
for output_type in value:
537+
content += self.get_aims_control_parameter_str(key, output_type, "%s")
538+
elif key == "vdw_correction_hirshfeld" and value:
539+
content += self.get_aims_control_parameter_str(key, "", "%s")
540+
elif isinstance(value, bool):
541+
content += self.get_aims_control_parameter_str(key, str(value).lower(), ".%s.")
542+
elif isinstance(value, (tuple, list)):
543+
content += self.get_aims_control_parameter_str(key, " ".join([str(x) for x in value]), "%s")
544+
elif isinstance(value, str):
545+
content += self.get_aims_control_parameter_str(key, value, "%s")
546+
else:
547+
content += self.get_aims_control_parameter_str(key, value, "%r")
548+
549+
if cubes:
550+
for cube in cubes:
551+
content += cube.control_block
552+
553+
content += lim + "\n\n"
554+
species_dir = self._parameters.get("species_dir", os.environ.get("AIMS_SPECIES_DIR"))
555+
content += self.get_species_block(structure, species_dir)
556+
557+
return content
558+
484559
def write_file(
485560
self,
486561
structure: Structure | Molecule,
@@ -507,14 +582,12 @@ def write_file(
507582
if (Path(directory) / "control.in").exists() and not overwrite:
508583
raise ValueError(f"control.in file already in {directory}")
509584

510-
lim = "#" + "=" * 79
511-
512585
if isinstance(structure, Structure) and (
513586
"k_grid" not in self._parameters and "k_grid_density" not in self._parameters
514587
):
515588
raise ValueError("k-grid must be defined for periodic systems")
516589

517-
parameters = deepcopy(self._parameters)
590+
content = self.get_content(structure, verbose_header)
518591

519592
with open(f"{directory}/control.in", mode="w") as file:
520593
file.write(f"#{'=' * 72}\n")
@@ -523,56 +596,7 @@ def write_file(
523596
file.write(f"# {time.asctime()}\n")
524597
file.write(f"#{'=' * 72}\n")
525598

526-
if parameters["xc"] == "LDA":
527-
parameters["xc"] = "pw-lda"
528-
529-
cubes = parameters.pop("cubes", None)
530-
531-
if verbose_header:
532-
file.write("# \n# List of parameters used to initialize the calculator:")
533-
for param, val in parameters.items():
534-
s = f"# {param}:{val}\n"
535-
file.write(s)
536-
file.write(lim + "\n")
537-
538-
assert not ("smearing" in parameters and "occupation_type" in parameters)
539-
540-
for key, value in parameters.items():
541-
if key in ["species_dir", "plus_u"]:
542-
continue
543-
if key == "smearing":
544-
name = parameters["smearing"][0].lower()
545-
if name == "fermi-dirac":
546-
name = "fermi"
547-
width = parameters["smearing"][1]
548-
if name == "methfessel-paxton":
549-
order = parameters["smearing"][2]
550-
order = " %d" % order
551-
else:
552-
order = ""
553-
554-
file.write(self.get_aims_control_parameter_str("occupation_type", (name, width, order), "%s %f%s"))
555-
elif key == "output":
556-
for output_type in value:
557-
file.write(self.get_aims_control_parameter_str(key, output_type, "%s"))
558-
elif key == "vdw_correction_hirshfeld" and value:
559-
file.write(self.get_aims_control_parameter_str(key, "", "%s"))
560-
elif isinstance(value, bool):
561-
file.write(self.get_aims_control_parameter_str(key, str(value).lower(), ".%s."))
562-
elif isinstance(value, (tuple, list)):
563-
file.write(self.get_aims_control_parameter_str(key, " ".join([str(x) for x in value]), "%s"))
564-
elif isinstance(value, str):
565-
file.write(self.get_aims_control_parameter_str(key, value, "%s"))
566-
else:
567-
file.write(self.get_aims_control_parameter_str(key, value, "%r"))
568-
569-
if cubes:
570-
for cube in cubes:
571-
file.write(cube.control_block)
572-
573-
file.write(lim + "\n\n")
574-
species_dir = self._parameters.get("species_dir", os.environ.get("AIMS_SPECIES_DIR"))
575-
file.write(self.get_species_block(structure, species_dir))
599+
file.write(content)
576600

577601
def get_species_block(self, structure: Structure | Molecule, species_dir: str | Path) -> str:
578602
"""Get the basis set information for a structure

pymatgen/io/aims/sets/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from __future__ import annotations
2+
3+
from pymatgen.io.aims.sets.base import AimsInputSet

0 commit comments

Comments
 (0)