Skip to content

Commit

Permalink
Merge 853ec6e into 12d6e2b
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Tran committed May 3, 2021
2 parents 12d6e2b + 853ec6e commit 904f840
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 44 deletions.
64 changes: 21 additions & 43 deletions pymatgen/core/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,17 +300,30 @@ def equi_index(site):

def is_symmetric(self, symprec=0.1):
"""
Checks if slab is symmetric, i.e., contains inversion symmetry.
Checks if surfaces are 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 slab contains inversion symmetry.
(bool) Whether surfaces are symmetric.
"""

sg = SpacegroupAnalyzer(self, symprec=symprec)
return sg.is_laue()
symmops = sg.get_point_group_operations()

if (
sg.is_laue()
or any(op.translation_vector[2] != 0 for op in symmops)
or any(np.alltrue(op.rotation_matrix[2] == np.array([0,0,-1])) for op in symmops)
):
# 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 theres an (hkl) mirror plane has surface symmetry
return True
return False

def get_sorted_structure(self, key=None, reverse=False):
"""
Expand Down Expand Up @@ -597,38 +610,6 @@ def get_surface_sites(self, tag=False):
self.add_site_property("is_surf_site", properties)
return surf_sites_dict

def have_equivalent_surfaces(self):
"""
Check if we have same number of equivalent sites on both surfaces.
This is an alternative to checking Laue symmetry (is_symmetric())
if we want to ensure both surfaces in the slab are the same
"""

# tag the sites as either surface sites or not
self.get_surface_sites(tag=True)

a = SpacegroupAnalyzer(self)
symm_structure = a.get_symmetrized_structure()

# ensure each site on one surface has a
# corresponding equivalent site on the other
equal_surf_sites = []
for equ in symm_structure.equivalent_sites:
# Top and bottom are arbitrary, we will just determine
# if one site is on one side of the slab or the other
top, bottom = 0, 0
for s in equ:
if s.is_surf_site:
if s.frac_coords[2] > self.center_of_mass[2]:
top += 1
else:
bottom += 1
# Check to see if the number of equivalent sites
# on one side of the slab are equal to the other
equal_surf_sites.append(top == bottom)

return all(equal_surf_sites)

def get_symmetric_site(self, point, cartesian=False):
"""
This method uses symmetry operations to find equivalent sites on
Expand Down Expand Up @@ -1305,7 +1286,8 @@ def move_to_other_side(self, init_slab, index_of_sites):
energy=init_slab.energy,
)

def nonstoichiometric_symmetrized_slab(self, init_slab, tol=1e-3):
def nonstoichiometric_symmetrized_slab(self, init_slab):

"""
This method checks whether or not the two surfaces of the slab are
equivalent. If the point group of the slab has an inversion symmetry (
Expand All @@ -1317,15 +1299,12 @@ def nonstoichiometric_symmetrized_slab(self, init_slab, tol=1e-3):
Arg:
init_slab (Structure): A single slab structure
tol (float): Tolerance for SpaceGroupanalyzer.
Returns:
Slab (structure): A symmetrized Slab object.
"""

sg = SpacegroupAnalyzer(init_slab, symprec=tol)

if sg.is_laue():
if init_slab.is_symmetric():
return [init_slab]

nonstoich_slabs = []
Expand All @@ -1350,13 +1329,12 @@ def nonstoichiometric_symmetrized_slab(self, init_slab, tol=1e-3):
break

# Check if the altered surface is symmetric
sg = SpacegroupAnalyzer(slab, symprec=tol)
if sg.is_laue():
if slab.is_symmetric():
asym = False
nonstoich_slabs.append(slab)

if len(slab) <= len(self.parent):
warnings.warn("Too many sites removed, please use a larger slab " "size.")
warnings.warn("Too many sites removed, please use a larger slab size.")

return nonstoich_slabs

Expand Down
12 changes: 11 additions & 1 deletion pymatgen/core/tests/test_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,16 @@ def setUp(self):
],
)

m = [[3.913449, 0, 0], [0, 3.913449, 0], [0, 0, 5.842644]]
latt = Lattice(m)
fcoords = [[0.5, 0, 0.222518], [0, 0.5, 0.777482], [0, 0, 0], [0, 0, 0.5], [0.5, 0.5, 0]]
non_laue = Structure(latt, ['Nb', 'Nb', 'N', 'N', 'N'], fcoords)

self.ti = Ti
self.agfcc = Ag_fcc
self.zno1 = zno1
self.zno55 = zno55
self.nonlaue = non_laue
self.h = Structure(Lattice.cubic(3), ["H"], [[0, 0, 0]])
self.libcc = Structure(Lattice.cubic(3.51004), ["Li", "Li"], [[0, 0, 0], [0.5, 0.5, 0.5]])

Expand Down Expand Up @@ -174,7 +180,6 @@ def test_surface_sites_and_symmetry(self):
total_surf_sites = sum([len(surf_sites_dict[key]) for key in surf_sites_dict.keys()])
self.assertTrue(slab.is_symmetric())
self.assertEqual(total_surf_sites / 2, 4)
self.assertTrue(slab.have_equivalent_surfaces())

# Test if the ratio of surface sites per area is
# constant, ie are the surface energies the same
Expand Down Expand Up @@ -243,6 +248,11 @@ def test_symmetrization(self):
self.assertEqual(assymetric_count, 0)
self.assertEqual(symmetric_count, len(slabs))

# Check if we can generate symmetric slabs from bulk with no inversion
all_non_laue_slabs = generate_all_slabs(self.nonlaue, 1, 15, 15, symmetrize=True)
self.assertTrue(len(all_non_laue_slabs) > 0)


def test_get_symmetric_sites(self):

# Check to see if we get an equivalent site on one
Expand Down

0 comments on commit 904f840

Please sign in to comment.