Skip to content

Commit cb7df36

Browse files
authored
Merge pull request #87 from SMTG-Bham/displacements2
Add `calc_displacements_ellipsoid` function
2 parents 5897412 + d53b0e4 commit cb7df36

12 files changed

+48978
-499
lines changed

doped/core.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -1313,16 +1313,19 @@ def sc_entry_energy(self):
13131313

13141314
def plot_site_displacements(
13151315
self,
1316-
separated_by_direction: Optional[bool] = False,
1317-
relative_to_defect: Optional[bool] = False,
1316+
separated_by_direction: bool = False,
1317+
relative_to_defect: bool = False,
13181318
vector_to_project_on: Optional[list] = None,
1319-
use_plotly: Optional[bool] = False,
1320-
mpl_style_file: Optional[PathLike] = "",
1319+
use_plotly: bool = False,
1320+
style_file: Optional[PathLike] = "",
13211321
):
13221322
"""
13231323
Plot the site displacements as a function of distance from the defect
13241324
site.
13251325
1326+
Set ``use_plotly = True`` to get an interactive ``plotly`` plot, useful
1327+
for analysis!
1328+
13261329
Args:
13271330
separated_by_direction (bool):
13281331
Whether to plot the site displacements separated by the
@@ -1337,8 +1340,9 @@ def plot_site_displacements(
13371340
(e.g. [0, 0, 1]). Defaults to None (e.g. the displacements are calculated
13381341
in the cartesian basis x, y, z).
13391342
use_plotly (bool):
1340-
Whether to use plotly (True) or matplotlib (False).
1341-
mpl_style_file (PathLike):
1343+
Whether to use ``plotly`` (``True``) or ``matplotlib`` (``False``).
1344+
Defaults to ``False``. Set to ``True`` to get an interactive plot.
1345+
style_file (PathLike):
13421346
Path to a matplotlib style file to use for the plot. If None,
13431347
uses the default doped style file.
13441348
"""
@@ -1350,7 +1354,7 @@ def plot_site_displacements(
13501354
relative_to_defect=relative_to_defect,
13511355
vector_to_project_on=vector_to_project_on,
13521356
use_plotly=use_plotly,
1353-
style_file=mpl_style_file,
1357+
style_file=style_file,
13541358
)
13551359

13561360

doped/generation.py

+59-49
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,7 @@ def closest_site_info(
220220
)
221221

222222
if element_list is None:
223-
element_list = [el.symbol for el in defect.structure.composition.elements] # host elements
224-
element_list += sorted(
225-
[ # extrinsic elements, sorted alphabetically for deterministic ordering in output:
226-
el.symbol
227-
for el in defect.defect_structure.composition.elements
228-
if el.symbol not in element_list
229-
]
230-
)
223+
element_list = _get_element_list(defect)
231224

232225
site_distances = sorted(
233226
[
@@ -1453,18 +1446,22 @@ class (such as ``clustering_tol``, ``stol``, ``min_dist`` etc), or to
14531446
extrinsic_elements = list(set(extrinsic_elements)) # get only unique elements
14541447
else:
14551448
extrinsic_elements = []
1449+
14561450
host_element_list = [el.symbol for el in self.primitive_structure.composition.elements]
1457-
# if any "extrinsic" elements are actually host elements, remove them from the list and warn
1458-
# user:
1451+
# if any "extrinsic" elements are actually host elements, remove them and warn user:
14591452
if any(el in host_element_list for el in extrinsic_elements):
14601453
warnings.warn(
14611454
f"\nSpecified 'extrinsic' elements "
14621455
f"{[el for el in extrinsic_elements if el in host_element_list]} are present in "
14631456
f"the host structure, so do not need to be specified as 'extrinsic' in "
14641457
f"DefectsGenerator(). These will be ignored."
14651458
)
1466-
# sort extrinsic elements alphabetically for deterministic ordering in output:
1467-
extrinsic_elements = sorted([el for el in extrinsic_elements if el not in host_element_list])
1459+
1460+
# sort extrinsic elements by periodic group and atomic number for deterministic ordering:
1461+
extrinsic_elements = sorted(
1462+
[el for el in extrinsic_elements if el not in host_element_list],
1463+
key=_element_sort_func,
1464+
)
14681465

14691466
substitution_generator_obj = SubstitutionGenerator()
14701467
if isinstance(self.extrinsic, (str, list)): # substitute all host elements:
@@ -2227,6 +2224,52 @@ def __repr__(self):
22272224
)
22282225

22292226

2227+
def _get_element_list(defect: Union[Defect, DefectEntry, dict, list]) -> list[str]:
2228+
"""
2229+
Given an input ``Defect`` or ``DefectEntry``, or dictionary/list of these,
2230+
return a (non-duplicated) list of elements present in the defect
2231+
structures.
2232+
"""
2233+
2234+
def _get_single_defect_element_list(single_defect):
2235+
element_list = [el.symbol for el in single_defect.structure.composition.elements]
2236+
element_list += sorted(
2237+
[ # extrinsic elements, sorted by periodic group and atomic number for deterministic ordering
2238+
el.symbol
2239+
for el in single_defect.defect_structure.composition.elements
2240+
if el.symbol not in element_list
2241+
],
2242+
key=_element_sort_func,
2243+
)
2244+
return element_list
2245+
2246+
if isinstance(defect, (Defect, DefectEntry)):
2247+
return _get_single_defect_element_list(defect if isinstance(defect, Defect) else defect.defect)
2248+
2249+
# else is dict/list
2250+
defect_list = defect if isinstance(defect, list) else list(defect.values())
2251+
defect_list = [
2252+
entry_or_defect.defect if isinstance(entry_or_defect, DefectEntry) else entry_or_defect
2253+
for entry_or_defect in defect_list
2254+
]
2255+
host_element_list = [el.symbol for el in next(iter(defect_list)).structure.composition.elements]
2256+
extrinsic_element_list: list[str] = []
2257+
for single_defect in defect_list:
2258+
extrinsic_element_list.extend(
2259+
[
2260+
el.symbol
2261+
for el in single_defect.defect_structure.composition.elements
2262+
if el.symbol not in host_element_list
2263+
]
2264+
)
2265+
# sort extrinsic elements by periodic group and atomic number for deterministic ordering:
2266+
extrinsic_element_list = sorted(
2267+
set(extrinsic_element_list),
2268+
key=_element_sort_func,
2269+
)
2270+
return host_element_list + extrinsic_element_list
2271+
2272+
22302273
def _first_and_second_element(defect_name: str) -> tuple[str, str]:
22312274
"""
22322275
Return a tuple of the first and second element in the defect name.
@@ -2292,27 +2335,7 @@ def _sort_defect_entries(
22922335
state (from positive to negative).
22932336
"""
22942337
if element_list is None:
2295-
host_element_list = [
2296-
el.symbol
2297-
for el in next(iter(defect_entries_dict.values())).defect.structure.composition.elements
2298-
]
2299-
extrinsic_element_list: list[str] = []
2300-
for defect_entry in defect_entries_dict.values():
2301-
extrinsic_element_list.extend(
2302-
el.symbol
2303-
for el in [
2304-
*defect_entry.defect.structure.composition.elements,
2305-
*defect_entry.defect.site.species.elements,
2306-
]
2307-
if el.symbol not in host_element_list
2308-
)
2309-
2310-
# sort extrinsic elements by periodic group and atomic number for deterministic ordering in output:
2311-
extrinsic_element_list = sorted(
2312-
[el for el in extrinsic_element_list if el not in host_element_list],
2313-
key=_element_sort_func,
2314-
)
2315-
element_list = host_element_list + extrinsic_element_list
2338+
element_list = _get_element_list(defect_entries_dict)
23162339

23172340
try:
23182341
return dict(
@@ -2373,24 +2396,11 @@ def _sort_defects(defects_dict: dict, element_list: Optional[list[str]] = None):
23732396
23742397
Sorts defects by defect type (vacancies, substitutions, interstitials),
23752398
then by order of appearance of elements in the composition, then
2376-
alphabetically, then according to symmetry._frac_coords_sort_func.
2399+
by periodic group (main groups 1, 2, 13-18 first, then TMs), then by
2400+
atomic number, then according to ``symmetry._frac_coords_sort_func``.
23772401
"""
23782402
if element_list is None:
2379-
all_elements: list[str] = []
2380-
host_element_list = [
2381-
el.symbol for el in next(iter(defects_dict.values())).structure.composition.elements
2382-
]
2383-
2384-
for _defect_type, defect_list in defects_dict.items():
2385-
for defect in defect_list:
2386-
all_elements.extend(el.symbol for el in defect.defect_structure.composition.elements)
2387-
extrinsic_element_list = list(set(all_elements) - set(host_element_list))
2388-
2389-
# sort extrinsic elements alphabetically for deterministic ordering in output:
2390-
extrinsic_element_list = sorted(
2391-
[el for el in extrinsic_element_list if el not in host_element_list]
2392-
)
2393-
element_list = host_element_list + extrinsic_element_list
2403+
element_list = _get_element_list(defects_dict)
23942404

23952405
return {
23962406
defect_type: sorted(

0 commit comments

Comments
 (0)