@@ -737,6 +737,79 @@ def get_equi_sites(slab: Slab, sites: list[int]) -> list[int]:
737737 else :
738738 warnings .warn ("Equivalent sites could not be found for some indices. Surface unchanged." , stacklevel = 2 )
739739
740+ @staticmethod
741+ def get_slab_regions (
742+ slab ,
743+ blength : float = 3.5 ,
744+ ) -> list [tuple [float , float ]]:
745+ """Find the z-ranges for the slab region.
746+
747+ Useful for discerning where the slab ends and vacuum begins
748+ if the slab is not fully within the cell.
749+
750+ Args:
751+ slab (Slab): The Slab to analyse.
752+ blength (float): The bond length between atoms in Angstrom.
753+ You generally want this value to be larger than the actual
754+ bond length in order to find atoms that are part of the slab.
755+
756+ TODO (@DanielYang59): maybe project all z coordinates to 1D?
757+ """
758+ frac_coords : list = [] # TODO (@DanielYang59): zip site and coords?
759+ indices : list = []
760+
761+ all_indices : list = []
762+
763+ for site in slab :
764+ neighbors = slab .get_neighbors (site , blength )
765+ for nn in neighbors :
766+ # TODO (@DanielYang59): use z coordinate (z<0) to check
767+ # if a Slab is contiguous is suspicious (Slab could locate
768+ # entirely below z=0)
769+
770+ # Find sites with z < 0 (sites noncontiguous within cell)
771+ if nn [0 ].frac_coords [2 ] < 0 :
772+ frac_coords .append (nn [0 ].frac_coords [2 ])
773+ indices .append (nn [- 2 ])
774+
775+ if nn [- 2 ] not in all_indices :
776+ all_indices .append (nn [- 2 ])
777+
778+ # If slab is noncontiguous
779+ if frac_coords :
780+ # Locate the lowest site within the upper Slab
781+ last_frac_coords = []
782+ last_indices = []
783+ while frac_coords :
784+ last_frac_coords = copy .copy (frac_coords )
785+ last_indices = copy .copy (indices )
786+
787+ site = slab [indices [frac_coords .index (min (frac_coords ))]]
788+ neighbors = slab .get_neighbors (site , blength , include_index = True , include_image = True )
789+ frac_coords , indices = [], []
790+ for nn in neighbors :
791+ if 1 > nn [0 ].frac_coords [2 ] > 0 and nn [0 ].frac_coords [2 ] < site .frac_coords [2 ]:
792+ # Sites are noncontiguous within cell
793+ frac_coords .append (nn [0 ].frac_coords [2 ])
794+ indices .append (nn [- 2 ])
795+ if nn [- 2 ] not in all_indices :
796+ all_indices .append (nn [- 2 ])
797+
798+ # Locate the highest site within the lower Slab
799+ upper_fcoords : list = [
800+ site .frac_coords [2 ]
801+ for site in slab
802+ if all (nn .index not in all_indices for nn in slab .get_neighbors (site , blength ))
803+ ]
804+ coords : list = copy .copy (frac_coords ) if frac_coords else copy .copy (last_frac_coords )
805+ min_top = slab [last_indices [coords .index (min (coords ))]].frac_coords [2 ]
806+ return [(0 , max (upper_fcoords )), (min_top , 1 )]
807+
808+ # If the entire slab region is within the cell, just
809+ # set the range as the highest and lowest site in the Slab
810+ sorted_sites = sorted (slab , key = lambda site : site .frac_coords [2 ])
811+ return [(sorted_sites [0 ].frac_coords [2 ], sorted_sites [- 1 ].frac_coords [2 ])]
812+
740813
741814def center_slab (slab : Structure ) -> Structure :
742815 """Relocate the slab to the center such that its center
@@ -793,78 +866,13 @@ def center_slab(slab: Structure) -> Structure:
793866 return slab
794867
795868
796- def get_slab_regions (
797- slab : Slab ,
798- blength : float = 3.5 ,
799- ) -> list [tuple [float , float ]]:
869+ @deprecated (Slab .get_slab_regions , message = "use `Slab.get_slab_regions` instead." )
870+ def get_slab_regions (slab : Slab , blength : float = 3.5 ):
800871 """Find the z-ranges for the slab region.
801872
802- Useful for discerning where the slab ends and vacuum begins
803- if the slab is not fully within the cell.
804-
805- Args:
806- slab (Slab): The Slab to analyse.
807- blength (float): The bond length between atoms in Angstrom.
808- You generally want this value to be larger than the actual
809- bond length in order to find atoms that are part of the slab.
810-
811- TODO (@DanielYang59): this should be a method for `Slab`?
812- TODO (@DanielYang59): maybe project all z coordinates to 1D?
873+ Deprecated: use `Slab.get_slab_regions` instead.
813874 """
814- frac_coords : list = [] # TODO (@DanielYang59): zip site and coords?
815- indices : list = []
816-
817- all_indices : list = []
818-
819- for site in slab :
820- neighbors = slab .get_neighbors (site , blength )
821- for nn in neighbors :
822- # TODO (@DanielYang59): use z coordinate (z<0) to check
823- # if a Slab is contiguous is suspicious (Slab could locate
824- # entirely below z=0)
825-
826- # Find sites with z < 0 (sites noncontiguous within cell)
827- if nn [0 ].frac_coords [2 ] < 0 :
828- frac_coords .append (nn [0 ].frac_coords [2 ])
829- indices .append (nn [- 2 ])
830-
831- if nn [- 2 ] not in all_indices :
832- all_indices .append (nn [- 2 ])
833-
834- # If slab is noncontiguous
835- if frac_coords :
836- # Locate the lowest site within the upper Slab
837- last_frac_coords = []
838- last_indices = []
839- while frac_coords :
840- last_frac_coords = copy .copy (frac_coords )
841- last_indices = copy .copy (indices )
842-
843- site = slab [indices [frac_coords .index (min (frac_coords ))]]
844- neighbors = slab .get_neighbors (site , blength , include_index = True , include_image = True )
845- frac_coords , indices = [], []
846- for nn in neighbors :
847- if 1 > nn [0 ].frac_coords [2 ] > 0 and nn [0 ].frac_coords [2 ] < site .frac_coords [2 ]:
848- # Sites are noncontiguous within cell
849- frac_coords .append (nn [0 ].frac_coords [2 ])
850- indices .append (nn [- 2 ])
851- if nn [- 2 ] not in all_indices :
852- all_indices .append (nn [- 2 ])
853-
854- # Locate the highest site within the lower Slab
855- upper_fcoords : list = [
856- site .frac_coords [2 ]
857- for site in slab
858- if all (nn .index not in all_indices for nn in slab .get_neighbors (site , blength ))
859- ]
860- coords : list = copy .copy (frac_coords ) if frac_coords else copy .copy (last_frac_coords )
861- min_top = slab [last_indices [coords .index (min (coords ))]].frac_coords [2 ]
862- return [(0 , max (upper_fcoords )), (min_top , 1 )]
863-
864- # If the entire slab region is within the cell, just
865- # set the range as the highest and lowest site in the Slab
866- sorted_sites = sorted (slab , key = lambda site : site .frac_coords [2 ])
867- return [(sorted_sites [0 ].frac_coords [2 ], sorted_sites [- 1 ].frac_coords [2 ])]
875+ return Slab .get_slab_regions (slab , blength )
868876
869877
870878class SlabGenerator :
0 commit comments