Skip to content

Commit

Permalink
Update auto-charge determination, should now work always regardless o…
Browse files Browse the repository at this point in the history
…f whether
  • Loading branch information
kavanase committed Nov 20, 2023
1 parent ffe8d82 commit 29524d6
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 59 deletions.
98 changes: 45 additions & 53 deletions doped/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -976,18 +976,19 @@ def __init__(
]
vasp_type_count_dict = { # Count Dik
i: len([subdir for subdir in vasp_subfolders if i in subdir])
for i in ["vasp_ncl", "vasp_std", "vasp_gam"]
for i in ["vasp_ncl", "vasp_std", "vasp_nkred_std", "vasp_gam"]
}
# take first entry with non-zero count, else use defect folder itself:
self.subfolder = next((subdir for subdir, count in vasp_type_count_dict.items() if count), ".")

possible_bulk_folders = [dir for dir in possible_defect_folders if "bulk" in dir]
possible_bulk_folders = [dir for dir in possible_defect_folders if "bulk" in str(dir).lower()]
if self.bulk_path is None: # determine bulk_path to use
if len(possible_bulk_folders) == 1:
self.bulk_path = os.path.join(self.output_path, possible_bulk_folders[0])
elif len([dir for dir in possible_bulk_folders if dir.endswith("_bulk")]) == 1:
self.bulk_path = os.path.join(
self.output_path, [dir for dir in possible_bulk_folders if dir.endswith("_bulk")][0]
self.output_path,
[dir for dir in possible_bulk_folders if str(dir).lower().endswith("_bulk")][0],
)
else:
raise ValueError(
Expand All @@ -997,6 +998,15 @@ def __init__(
f"specify `bulk_path` manually."
)

self.defect_folders = [
dir
for dir in possible_defect_folders
if dir not in possible_bulk_folders
and (
self.subfolder in os.listdir(os.path.join(self.output_path, dir)) or self.subfolder == "."
)
]

# add subfolder to bulk_path if present with vasprun.xml(.gz), otherwise use bulk_path as is:
if os.path.isdir(os.path.join(self.bulk_path, self.subfolder)) and any(
"vasprun.xml" in file for file in os.listdir(os.path.join(self.bulk_path, self.subfolder))
Expand All @@ -1010,15 +1020,6 @@ def __init__(
)

self.defect_dict = {}
self.defect_folders = [
dir
for dir in possible_defect_folders
if dir not in possible_bulk_folders
and (
self.subfolder in os.listdir(os.path.join(self.output_path, dir)) or self.subfolder == "."
)
]

self.bulk_corrections_data = { # so we only load and parse bulk data once
"bulk_locpot_dict": None,
"bulk_site_potentials": None,
Expand Down Expand Up @@ -1204,8 +1205,6 @@ def __init__(

dumpfn(self.defect_dict, os.path.join(self.output_path, self.json_filename)) # type: ignore

# TODO: Warning/error handling for failed parsing defect folders?

def _update_pbar_and_return_warnings_from_parsing(self, result, pbar):
pbar.update()

Expand Down Expand Up @@ -1390,9 +1389,8 @@ def from_paths(
set to true.
charge_state (int):
Charge state of defect. If not provided, will be automatically determined
from the defect calculation outputs (requires `POTCAR`s to be set up
with `pymatgen`), or if that fails, using the defect folder name (must
end in "_+X" or "_-X" where +/-X is the defect charge state).
from the defect calculation outputs, or if that fails, using the defect
folder name (must end in "_+X" or "_-X" where +/-X is the defect charge state).
initial_defect_structure_path (str):
Path to the initial/unrelaxed defect structure. Only recommended for use
if structure matching with the relaxed defect structure(s) fails (rare).
Expand Down Expand Up @@ -1539,44 +1537,38 @@ def from_paths(
)

except RuntimeError:
if initial_defect_structure_path:
defect_structure_for_ID = Poscar.from_file(initial_defect_structure_path).structure.copy()
(
defect,
defect_site_in_initial_struct,
defect_site_in_bulk, # bulk site for vacancies/substitutions, relaxed defect site
# w/interstitials
defect_site_index, # in this initial_defect_structure
bulk_site_index,
guessed_initial_defect_structure,
unrelaxed_defect_structure,
bulk_voronoi_node_dict,
) = defect_from_structures(
bulk_supercell,
defect_structure_for_ID,
return_all_info=True,
bulk_voronoi_node_dict=bulk_voronoi_node_dict,
)

# then try get defect_site in final structure:
# need to check that this is the correct defect site, and hasn't been reordered/changed
# compared to the initial_defect_structure used here, check same element and distance
# reasonable:
defect_site = defect_site_in_initial_struct

if defect.defect_type != core.DefectType.Vacancy:
final_defect_site = defect_structure[defect_site_index]
if (
defect_site_in_initial_struct.species.elements[0].symbol
== final_defect_site.species.elements[0].symbol
) and final_defect_site.distance(defect_site_in_initial_struct) < 2:
defect_site = final_defect_site
if not initial_defect_structure_path:
raise

if defect.defect_type == core.DefectType.Interstitial:
pass
defect_structure_for_ID = Poscar.from_file(initial_defect_structure_path).structure.copy()
(
defect,
defect_site_in_initial_struct,
defect_site_in_bulk, # bulk site for vac/sub, relaxed defect site w/interstitials
defect_site_index, # in this initial_defect_structure
bulk_site_index,
guessed_initial_defect_structure,
unrelaxed_defect_structure,
bulk_voronoi_node_dict,
) = defect_from_structures(
bulk_supercell,
defect_structure_for_ID,
return_all_info=True,
bulk_voronoi_node_dict=bulk_voronoi_node_dict,
)

else:
raise
# then try get defect_site in final structure:
# need to check that it's the correct defect site and hasn't been reordered/changed compared to
# the initial_defect_structure used here -> check same element and distance reasonable:
defect_site = defect_site_in_initial_struct

if defect.defect_type != core.DefectType.Vacancy:
final_defect_site = defect_structure[defect_site_index]
if (
defect_site_in_initial_struct.species.elements[0].symbol
== final_defect_site.species.elements[0].symbol
) and final_defect_site.distance(defect_site_in_initial_struct) < 2:
defect_site = final_defect_site

calculation_metadata["guessed_initial_defect_structure"] = guessed_initial_defect_structure
calculation_metadata["unrelaxed_defect_structure"] = unrelaxed_defect_structure
Expand Down
5 changes: 3 additions & 2 deletions doped/utils/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,9 @@ def _compare_kpoints(bulk_kpoints, defect_kpoints):
Check bulk and defect KPOINTS are the same.
"""
# sort kpoints, in case same KPOINTS just different ordering:
sorted_bulk_kpoints = sorted(np.array(bulk_kpoints.kpts), key=lambda x: tuple(x))
sorted_defect_kpoints = sorted(np.array(defect_kpoints.kpts), key=lambda x: tuple(x))
sorted_bulk_kpoints = sorted(np.array(bulk_kpoints.kpts), key=tuple)
sorted_defect_kpoints = sorted(np.array(defect_kpoints.kpts), key=tuple)

if not np.allclose(sorted_bulk_kpoints, sorted_defect_kpoints):
warnings.warn(
f"The KPOINTS for your bulk and defect calculations do not match, which is likely to cause "
Expand Down
2 changes: 1 addition & 1 deletion examples/CdTe/CdTe_example_dpd.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/YTOS/YTOS_example_dpd.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/data/Sb2Se3/Sb2Se3_O_example_dpd.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/data/Sb2Se3/defect/Sb2Se3_defect_dict.json

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions tests/test_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,7 @@ def test_bulk_defect_compatibility_checks(self):
bulk_path=self.CdTe_BULK_DATA_DIR,
dielectric=9.13,
skip_corrections=True,
charge_state=+1, # manually specify charge state here, as our edited POTCAR doesn't exist
)
assert len(w) == 3 # now INCAR and KPOINTS and POTCAR warnings!
assert any(
Expand Down Expand Up @@ -1604,6 +1605,7 @@ def test_bulk_defect_compatibility_checks(self):
bulk_path=self.CdTe_BULK_DATA_DIR,
dielectric=9.13,
skip_corrections=True,
charge_state=+1, # manually specify charge state here, as our edited POTCAR doesn't exist
)
assert any(
"The defect and bulk supercells are not the same size, having volumes of 513790.5 and "
Expand Down

0 comments on commit 29524d6

Please sign in to comment.