Skip to content

Commit

Permalink
Merge 4128044 into 159394a
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-janssen committed Jun 11, 2024
2 parents 159394a + 4128044 commit 2f77a27
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 76 deletions.
91 changes: 72 additions & 19 deletions pyiron_atomistics/vasp/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import print_function
import os
import posixpath
import shutil
import subprocess
import numpy as np

Expand All @@ -27,7 +28,7 @@
from pyiron_atomistics.vasp.parser.outcar import Outcar, OutcarCollectError
from pyiron_atomistics.vasp.parser.oszicar import Oszicar
from pyiron_atomistics.vasp.procar import Procar
from pyiron_atomistics.vasp.structure import read_atoms, write_poscar, vasp_sorter
from pyiron_atomistics.vasp.structure import read_atoms, get_poscar_content, vasp_sorter
from pyiron_atomistics.vasp.vasprun import Vasprun as Vr
from pyiron_atomistics.vasp.vasprun import VasprunError, VasprunWarning
from pyiron_atomistics.vasp.volumetric_data import (
Expand Down Expand Up @@ -373,7 +374,29 @@ def set_input_to_read_only(self):
# Compatibility functions
def write_input(self):
"""
Call routines that generate the INCAR, POTCAR, KPOINTS and POSCAR input files
Call routines that generate the code specific input files
Returns:
"""
input_dict = self.get_input_file_dict()
for file_name, content in input_dict["files_to_create"].items():
with open(os.path.join(self.working_directory, file_name), "w") as f:
f.writelines(content)
for file_name, source in input_dict["files_to_copy"].items():
shutil.copy(source, os.path.join(self.working_directory, file_name))

def get_input_file_dict(self) -> dict:
"""
Get an hierarchical dictionary of input files. On the first level the dictionary is divided in file_to_create
and files_to_copy. Both are dictionaries use the file names as keys. In file_to_create the values are strings
which represent the content which is going to be written to the corresponding file. In files_to_copy the values
are the paths to the source files to be copied.
The get_input_file_dict() function is called before the write_input() function to convert the input specified on
the job object to strings which can be written to the working directory as well as files which are copied to the
working directory. After the write_input() function wrote the input files the executable is called.
Returns:
dict: hierarchical dictionary of input files
"""
if self.input.incar["SYSTEM"] == "pyiron_jobname":
self.input.incar["SYSTEM"] = self.job_name
Expand All @@ -394,11 +417,13 @@ def write_input(self):
self.logger.info(
"The POSCAR file will be overwritten by the CONTCAR file specified in restart_file_list."
)
self.input.write(
structure=self.structure,
directory=self.working_directory,
modified_elements=modified_elements,
)
return {
"files_to_create": self.input.get_input_file_dict(
structure=self.structure,
modified_elements=modified_elements,
),
"files_to_copy": {},
}

def collect_output_parser(self, cwd):
"""
Expand Down Expand Up @@ -1959,23 +1984,51 @@ def write(self, structure, modified_elements, directory=None):
structure (atomistics.structure.atoms.Atoms instance): Structure to be written
directory (str): The working directory for the VASP run
"""
self.incar.write_file(file_name="INCAR", cwd=directory)
if "KSPACING" in self.incar.keys():
warnings.warn("'KSPACING' found in INCAR, no KPOINTS file written")
else:
self.kpoints.write_file(file_name="KPOINTS", cwd=directory)
self.potcar.potcar_set_structure(structure, modified_elements)
self.potcar.write_file(file_name="POTCAR", cwd=directory)
files_to_create_dict = self.get_input_file_dict(
structure=structure, modified_elements=modified_elements
)
for file_name, content in files_to_create_dict.items():
with open(os.path.join(directory, file_name), "w") as f:
f.writelines(content)

def get_input_file_dict(self, structure: Atoms, modified_elements: list) -> dict:
"""
Get an hierarchical dictionary of input files. On the first level the dictionary is divided in file_to_create
and files_to_copy. Both are dictionaries use the file names as keys. In file_to_create the values are strings
which represent the content which is going to be written to the corresponding file. In files_to_copy the values
are the paths to the source files to be copied.
Args:
structure (Atoms):
modified_elements (list):
Returns:
dict: hierarchical dictionary of input files
"""
self.potcar.potcar_set_structure(
structure=structure, modified_elements=modified_elements
)
# Write the species info in the POSCAR file only if there are no user defined species
is_user_defined = list()
for species in structure.get_species_objects():
is_user_defined.append(species.Parent is not None)
do_not_write_species = any(is_user_defined)
write_poscar(
structure,
filename=posixpath.join(directory, "POSCAR"),
write_species=not do_not_write_species,
)
files_to_create = {
"INCAR": "".join(self.incar.get_string_lst()),
"POTCAR": "".join(self.potcar.get_file_content()),
"POSCAR": "".join(
get_poscar_content(
structure=structure,
write_species=not do_not_write_species,
cartesian=True,
)
),
}
if "KSPACING" in self.incar.keys():
warnings.warn("'KSPACING' found in INCAR, no KPOINTS file written")
else:
files_to_create["KPOINTS"] = "".join(self.kpoints.get_string_lst())
return files_to_create

def to_dict(self):
input_dict = {"vasp_dict/eddrmm_handling": self._eddrmm}
Expand Down
26 changes: 14 additions & 12 deletions pyiron_atomistics/vasp/potential.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,29 +488,31 @@ def _set_potential_paths(self):
self._dataset["Comment"].append("")
self.el_path_lst.append(el_path)

def write_file(self, file_name, cwd=None):
"""
Args:
file_name:
cwd:
Returns:
"""
def get_file_content(self):
self.electrons_per_atom_lst = list()
self.max_cutoff_lst = list()
self._set_potential_paths()
if cwd is not None:
file_name = posixpath.join(cwd, file_name)
f = open(file_name, "w")
line_lst = []
for el_file in self.el_path_lst:
with open(el_file) as pot_file:
for i, line in enumerate(pot_file):
f.write(line)
line_lst.append(line)
if i == 1:
self.electrons_per_atom_lst.append(int(float(line)))
elif i == 14:
mystr = line.split()[2][:-1]
self.max_cutoff_lst.append(float(mystr))
f.close()
return line_lst

def write_file(self, file_name, cwd=None):
"""
Args:
file_name:
cwd:
Returns:
"""
with open(file_name, "w") as f:
f.writelines("".join(self.get_file_content()))

def load_default(self):
file_content = """\
Expand Down
102 changes: 57 additions & 45 deletions pyiron_atomistics/vasp/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,55 @@ def get_species_list_from_potcar(filename="POTCAR"):
return species_list


def get_poscar_content(structure, write_species=True, cartesian=True):
endline = "\n"
selec_dyn = False
line_lst = [
"Poscar file generated with pyiron" + endline,
"1.0" + endline,
]
for a_i in structure.get_cell():
x, y, z = a_i
line_lst.append("{0:.15f} {1:.15f} {2:.15f}".format(x, y, z) + endline)
atom_numbers = structure.get_number_species_atoms()
if write_species:
line_lst.append(" ".join(atom_numbers.keys()) + endline)
num_str = [str(val) for val in atom_numbers.values()]
line_lst.append(" ".join(num_str))
line_lst.append(endline)
if "selective_dynamics" in structure.get_tags():
selec_dyn = True
cartesian = False
line_lst.append("Selective dynamics" + endline)
sorted_coords = list()
selec_dyn_lst = list()
for species in atom_numbers.keys():
indices = structure.select_index(species)
for i in indices:
if cartesian:
sorted_coords.append(structure.positions[i])
else:
sorted_coords.append(structure.get_scaled_positions()[i])
if selec_dyn:
selec_dyn_lst.append(structure.selective_dynamics[i])
if cartesian:
line_lst.append("Cartesian" + endline)
else:
line_lst.append("Direct" + endline)
if selec_dyn:
for i, vec in enumerate(sorted_coords):
x, y, z = vec
sd_string = " ".join(["T" if sd else "F" for sd in selec_dyn_lst[i]])
line_lst.append(
"{0:.15f} {1:.15f} {2:.15f}".format(x, y, z) + " " + sd_string + endline
)
else:
for i, vec in enumerate(sorted_coords):
x, y, z = vec
line_lst.append("{0:.15f} {1:.15f} {2:.15f}".format(x, y, z) + endline)
return line_lst


def write_poscar(structure, filename="POSCAR", write_species=True, cartesian=True):
"""
Writes a POSCAR type file from a structure object
Expand All @@ -90,53 +139,16 @@ def write_poscar(structure, filename="POSCAR", write_species=True, cartesian=Tru
cartesian (bool): True if the positions are written in Cartesian coordinates
"""
endline = "\n"
with open(filename, "w") as f:
selec_dyn = False
f.write("Poscar file generated with pyiron" + endline)
f.write("1.0" + endline)
for a_i in structure.get_cell():
x, y, z = a_i
f.write("{0:.15f} {1:.15f} {2:.15f}".format(x, y, z) + endline)
atom_numbers = structure.get_number_species_atoms()
if write_species:
f.write(" ".join(atom_numbers.keys()) + endline)
num_str = [str(val) for val in atom_numbers.values()]
f.write(" ".join(num_str))
f.write(endline)
if "selective_dynamics" in structure.get_tags():
selec_dyn = True
cartesian = False
f.write("Selective dynamics" + endline)
sorted_coords = list()
selec_dyn_lst = list()
for species in atom_numbers.keys():
indices = structure.select_index(species)
for i in indices:
if cartesian:
sorted_coords.append(structure.positions[i])
else:
sorted_coords.append(structure.get_scaled_positions()[i])
if selec_dyn:
selec_dyn_lst.append(structure.selective_dynamics[i])
if cartesian:
f.write("Cartesian" + endline)
else:
f.write("Direct" + endline)
if selec_dyn:
for i, vec in enumerate(sorted_coords):
x, y, z = vec
sd_string = " ".join(["T" if sd else "F" for sd in selec_dyn_lst[i]])
f.write(
"{0:.15f} {1:.15f} {2:.15f}".format(x, y, z)
+ " "
+ sd_string
+ endline
f.writelines(
"".join(
get_poscar_content(
structure=structure,
write_species=write_species,
cartesian=cartesian,
)
else:
for i, vec in enumerate(sorted_coords):
x, y, z = vec
f.write("{0:.15f} {1:.15f} {2:.15f}".format(x, y, z) + endline)
)
)


def atoms_from_string(string, read_velocities=False, species_list=None):
Expand Down

0 comments on commit 2f77a27

Please sign in to comment.