Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify argument shift for SlabGenerator.get_slab #3748

Merged
merged 60 commits into from
Jun 3, 2024
Merged
Changes from 3 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
65e3ec8
put `is_symmetric/polar` next to `property`
DanielYang59 Apr 12, 2024
90ef691
BREAKING: reverse `get_slab` shift direction
DanielYang59 Apr 12, 2024
185a79c
clarify `shift` for single atom
DanielYang59 Apr 12, 2024
f1d5433
use `isclose` to determine overlap atoms
DanielYang59 Apr 12, 2024
86bbc34
correct tolerance unit
DanielYang59 Apr 12, 2024
34c05e7
Merge branch 'master' into core-surface
DanielYang59 Apr 12, 2024
a7f7dc0
Revert "put `is_symmetric/polar` next to `property`"
DanielYang59 Apr 13, 2024
8c78e43
reapply docstring changes
DanielYang59 Apr 13, 2024
a787580
Merge branch 'master' into core-surface
DanielYang59 Apr 13, 2024
e57fc99
Merge branch 'master' into core-surface
DanielYang59 Apr 20, 2024
7c0a13d
Merge branch 'master' into core-surface
DanielYang59 Apr 21, 2024
c7420cf
use `isclose` to check close
DanielYang59 Apr 22, 2024
b4627e9
fix typo in tag
DanielYang59 Apr 22, 2024
dbd5d3a
Merge branch 'master' into core-surface
DanielYang59 Apr 23, 2024
6ac9530
Merge branch 'master' into core-surface
DanielYang59 Apr 29, 2024
93ef095
Merge branch 'master' into core-surface
DanielYang59 May 1, 2024
4be466c
remove debug tag
DanielYang59 May 1, 2024
16b1999
pre-commit auto-fixes
pre-commit-ci[bot] May 1, 2024
28a7c93
Merge branch 'master' into core-surface
DanielYang59 May 2, 2024
c7f0d32
make `center_slab` very simple
DanielYang59 May 3, 2024
f45c386
Failed: make center_slab and get_slab_regions methods for `Slab`
DanielYang59 May 3, 2024
8009dd7
Merge branch 'master' into core-surface
DanielYang59 May 3, 2024
4e801cf
Merge branch 'master' into core-surface
DanielYang59 May 4, 2024
81f441a
Merge branch 'master' into core-surface
DanielYang59 May 12, 2024
7d0871c
revert deprecation of `center_slab` function
DanielYang59 May 12, 2024
50bf70a
revert "overlap position check with isclose"
DanielYang59 May 12, 2024
8541a83
revert deprecation of center_slab and get_slab_regions
DanielYang59 May 12, 2024
60271c3
revert changes for `center_slab` function
DanielYang59 May 12, 2024
b138d18
recover docstring
DanielYang59 May 12, 2024
20aca0b
rename slab to struct (type is Structure)
DanielYang59 May 13, 2024
6c2803c
revert adding minus sign
DanielYang59 May 13, 2024
df7f0f9
fix slab type
DanielYang59 May 13, 2024
bb85596
Merge branch 'master' into core-surface
DanielYang59 May 13, 2024
06b2410
keep shift def consistent (need clarify)
DanielYang59 May 13, 2024
7f552c8
unify usage of shift outside Slab
DanielYang59 May 13, 2024
01a9458
fix unit test
DanielYang59 May 13, 2024
0a33ada
add missing minus sign for single atom shift
DanielYang59 May 13, 2024
d75ee61
[need confirm] fix test for coh-interface
DanielYang59 May 13, 2024
a77d6bd
add TODO tag
DanielYang59 May 13, 2024
71e102f
clarify shift definition
DanielYang59 May 13, 2024
3d664d2
revert ALL change related to the direction of shift
DanielYang59 May 13, 2024
adc6e60
rename arg shift to termination
DanielYang59 May 13, 2024
6703c95
tweak comments
DanielYang59 May 13, 2024
e0fc5f3
clarify `shift` attrib in `Slab`
DanielYang59 May 13, 2024
9cc5a04
clarify magic number
DanielYang59 May 13, 2024
79430a6
simplify doc
DanielYang59 May 13, 2024
d50328a
Merge branch 'master' into core-surface
DanielYang59 May 14, 2024
33fbd3e
Merge branch 'master' into core-surface
DanielYang59 May 14, 2024
b72ab44
Merge branch 'master' into core-surface
DanielYang59 May 14, 2024
28e20b1
Merge branch 'master' into core-surface
DanielYang59 May 16, 2024
b607536
reuse `center_slab` func
DanielYang59 May 16, 2024
191b959
remove unneeded TODO tag
DanielYang59 May 16, 2024
5384a27
Merge branch 'master' into core-surface
DanielYang59 May 17, 2024
e38efdb
Merge branch 'master' into core-surface
DanielYang59 May 18, 2024
ba4f83a
revert shift to termination rename
DanielYang59 May 18, 2024
c4f871b
remove finished TODO tag
DanielYang59 May 18, 2024
b887a5b
Merge branch 'master' into core-surface
DanielYang59 May 25, 2024
8413745
Merge branch 'master' into core-surface
DanielYang59 Jun 1, 2024
b423716
Merge branch 'master' into core-surface
DanielYang59 Jun 1, 2024
b0b4ac8
Merge branch 'master' into core-surface
janosh Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 52 additions & 56 deletions pymatgen/core/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@

class Slab(Structure):
"""Class to hold information for a Slab, with additional
attributes pertaining to slabs, but the init method does not
actually create a slab. Also has additional methods that returns other information
about a Slab such as the surface area, normal, and atom adsorption.
attributes pertaining to slabs, but does not actually create a slab.
Also has additional methods for a Slab such as the surface area,
normal, and adsorbate atoms.

Note that all Slabs have the surface normal oriented perpendicular to the a
and b lattice vectors. This means the lattice vectors a and b are in the
Note that all Slabs have the surface normal oriented perpendicular to the
a and b lattice vectors. This means the lattice vectors a and b are in the
surface plane and the c vector is out of the surface plane (though not
necessarily perpendicular to the surface).
"""
Expand Down Expand Up @@ -214,14 +214,52 @@ def surface_area(self) -> float:
matrix = self.lattice.matrix
return np.linalg.norm(np.cross(matrix[0], matrix[1]))

def is_symmetric(self, symprec: float = 0.1) -> bool:
DanielYang59 marked this conversation as resolved.
Show resolved Hide resolved
"""Check if Slab is symmetric, i.e., contains inversion, mirror on (hkl) plane,
or screw axis (rotation and translation) about [hkl].

Args:
symprec (float): Symmetry precision used for SpaceGroup analyzer.

Returns:
bool: Whether surfaces are symmetric.
"""
spg_analyzer = SpacegroupAnalyzer(self, symprec=symprec)
symm_ops = spg_analyzer.get_point_group_operations()

# Check for inversion symmetry. Or if sites from surface (a) can be translated
# to surface (b) along the [hkl]-axis, surfaces are symmetric. Or because the
# two surfaces of our slabs are always parallel to the (hkl) plane,
# any operation where there's an (hkl) mirror plane has surface symmetry
return (
spg_analyzer.is_laue()
or any(op.translation_vector[2] != 0 for op in symm_ops)
or any(np.all(op.rotation_matrix[2] == np.array([0, 0, -1])) for op in symm_ops)
)

def is_polar(self, tol_dipole_per_unit_area: float = 1e-3) -> bool:
"""Check if the Slab is polar by computing the normalized dipole per unit area.
Normalized dipole per unit area is used as it is more reliable than
using the absolute value, which varies with surface area.

Note that the Slab must be oxidation state decorated for this to work properly.
Otherwise, the Slab will always have a dipole moment of 0.

Args:
tol_dipole_per_unit_area (float): A tolerance above which the Slab is
considered polar.
"""
dip_per_unit_area = self.dipole / self.surface_area
return np.linalg.norm(dip_per_unit_area) > tol_dipole_per_unit_area

@classmethod
def from_dict(cls, dct: dict[str, Any]) -> Self: # type: ignore[override]
"""
Args:
dct: dict.

Returns:
Creates slab from dict.
Slab: Created from dict.
"""
lattice = Lattice.from_dict(dct["lattice"])
sites = [PeriodicSite.from_dict(sd, lattice) for sd in dct["sites"]]
Expand Down Expand Up @@ -279,44 +317,6 @@ def copy(self, site_properties: dict[str, Any] | None = None) -> Slab: # type:
reorient_lattice=self.reorient_lattice,
)

def is_symmetric(self, symprec: float = 0.1) -> bool:
"""Check if Slab is symmetric, i.e., contains inversion, mirror on (hkl) plane,
or screw axis (rotation and translation) about [hkl].

Args:
symprec (float): Symmetry precision used for SpaceGroup analyzer.

Returns:
bool: Whether surfaces are symmetric.
"""
spg_analyzer = SpacegroupAnalyzer(self, symprec=symprec)
symm_ops = spg_analyzer.get_point_group_operations()

# Check for inversion symmetry. Or if sites from surface (a) can be translated
# to surface (b) along the [hkl]-axis, surfaces are symmetric. Or because the
# two surfaces of our slabs are always parallel to the (hkl) plane,
# any operation where there's an (hkl) mirror plane has surface symmetry
return (
spg_analyzer.is_laue()
or any(op.translation_vector[2] != 0 for op in symm_ops)
or any(np.all(op.rotation_matrix[2] == np.array([0, 0, -1])) for op in symm_ops)
)

def is_polar(self, tol_dipole_per_unit_area: float = 1e-3) -> bool:
"""Check if the Slab is polar by computing the normalized dipole per unit area.
Normalized dipole per unit area is used as it is more reliable than
using the absolute value, which varies with surface area.

Note that the Slab must be oxidation state decorated for this to work properly.
Otherwise, the Slab will always have a dipole moment of 0.

Args:
tol_dipole_per_unit_area (float): A tolerance above which the Slab is
considered polar.
"""
dip_per_unit_area = self.dipole / self.surface_area
return np.linalg.norm(dip_per_unit_area) > tol_dipole_per_unit_area

def get_surface_sites(self, tag: bool = False) -> dict[str, list]:
"""Returns the surface sites and their indices in a dictionary.
Useful for analysis involving broken bonds and for finding adsorption sites.
Expand All @@ -329,8 +329,8 @@ def get_surface_sites(self, tag: bool = False) -> dict[str, list]:
site as well. This will only work for single-element systems for now.

Args:
tag (bool): Option to adds site attribute "is_surfsite" (bool)
to all sites of slab. Defaults to False
tag (bool): Add attribute "is_surf_site" (bool)
to all sites of the Slab. Defaults to False.

Returns:
A dictionary grouping sites on top and bottom of the slab together.
Expand Down Expand Up @@ -638,8 +638,8 @@ def symmetrically_add_atom(
specie: str | Element | Species | None = None,
coords_are_cartesian: bool = False,
) -> None:
"""Add a species at a specified site in a slab. Will also add an
equivalent site on the other side of the slab to maintain symmetry.
"""Add a species at a selected site in a Slab. Will also add an
equivalent site on the other side to maintain symmetry.

TODO (@DanielYang59): use "site" over "point" as arg name for consistency

Expand All @@ -649,8 +649,6 @@ def symmetrically_add_atom(
specie: Deprecated argument name in #3691. Use 'species' instead.
coords_are_cartesian (bool): If the site is in Cartesian coordinates.
"""
# For now just use the species of the surface atom as the element to add

# Check if deprecated argument is used
if specie is not None:
warnings.warn("The argument 'specie' is deprecated. Use 'species' instead.", DeprecationWarning)
Expand Down Expand Up @@ -1075,7 +1073,8 @@ def get_slab(self, shift: float = 0, tol: float = 0.1, energy: float | None = No
intended for other generation methods.

Args:
shift (float): The shift value along the lattice c direction in Angstrom.
shift (float): The shift value along the lattice c direction
in fractional coordinates.
tol (float): Tolerance to determine primitive cell.
energy (float): The energy to assign to the slab.

Expand Down Expand Up @@ -1104,10 +1103,8 @@ def get_slab(self, shift: float = 0, tol: float = 0.1, energy: float | None = No
species = self.oriented_unit_cell.species_and_occu

# Shift all atoms
# DEBUG(@DanielYang59): shift value in Angstrom inconsistent with frac_coordis
frac_coords = self.oriented_unit_cell.frac_coords
# DEBUG(@DanielYang59): suspicious shift direction (positive for downwards shift)
frac_coords = np.array(frac_coords) + np.array([0, 0, -shift])[None, :]
frac_coords = np.array(frac_coords) + np.array([0, 0, shift])[None, :]
DanielYang59 marked this conversation as resolved.
Show resolved Hide resolved
frac_coords -= np.floor(frac_coords) # wrap frac_coords to the [0, 1) range

# Scale down z-coordinate by the number of layers
Expand Down Expand Up @@ -1231,8 +1228,7 @@ def gen_possible_shifts(ftol: float) -> list[float]:

# Clustering does not work when there is only one atom
if n_atoms == 1:
# TODO (@DanielYang59): why this magic number 0.5?
shift = frac_coords[0][2] + 0.5
shift = -frac_coords[0][2] + 0.5 # shift to center
DanielYang59 marked this conversation as resolved.
Show resolved Hide resolved
return [shift - math.floor(shift)]

# Compute a Cartesian z-coordinate distance matrix
Expand Down
Loading