From fbade3f0afc8a5e32e8ebad12fae2134a2081485 Mon Sep 17 00:00:00 2001 From: VsevolodX <79542055+VsevolodX@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:26:02 -0800 Subject: [PATCH 1/4] update: add switch with factory based on config --- src/py/mat3ra/made/tools/build/defect/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/py/mat3ra/made/tools/build/defect/__init__.py b/src/py/mat3ra/made/tools/build/defect/__init__.py index ac60d436e..db3359c4a 100644 --- a/src/py/mat3ra/made/tools/build/defect/__init__.py +++ b/src/py/mat3ra/made/tools/build/defect/__init__.py @@ -80,11 +80,19 @@ def create_slab_defect( Args: configuration: The configuration of the defect to be added. - builder: The builder to be used to create the defect. + builder: Optional builder to be used to create the defect. + If None, builder will be selected based on configuration. Returns: The material with the defect added. """ if builder is None: - builder = AdatomSlabDefectBuilder(build_parameters=SlabDefectBuilderParameters()) + if configuration.defect_type == PointDefectTypeEnum.ADATOM: + builder_key = f"adatom:{configuration.placement_method.lower()}" + else: + builder_key = configuration.defect_type.lower() + + BuilderClass = DefectBuilderFactory.get_class_by_name(builder_key) + builder = BuilderClass(build_parameters=SlabDefectBuilderParameters()) + return builder.get_material(configuration) From 50ab92c981f0263fc6567b8c820c59fdc6737d80 Mon Sep 17 00:00:00 2001 From: VsevolodX <79542055+VsevolodX@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:20:21 -0800 Subject: [PATCH 2/4] update: add first implementation of hollow sites --- .../made/tools/build/defect/builders.py | 31 +++++++++++++++++++ .../mat3ra/made/tools/build/defect/enums.py | 6 ++++ 2 files changed, 37 insertions(+) diff --git a/src/py/mat3ra/made/tools/build/defect/builders.py b/src/py/mat3ra/made/tools/build/defect/builders.py index 95f7f9a51..8da09313b 100644 --- a/src/py/mat3ra/made/tools/build/defect/builders.py +++ b/src/py/mat3ra/made/tools/build/defect/builders.py @@ -44,6 +44,7 @@ PointDefectPairConfiguration, ) from .factories import DefectBuilderFactory +from pymatgen.analysis.adsorption import AdsorbateSiteFinder class PointDefectBuilderParameters(BaseModel): @@ -434,6 +435,36 @@ def create_adatom( return self.merge_slab_and_defect(new_material, only_adatom_material) +class HollowSiteAdatomSlabDefectBuilder(AdatomSlabDefectBuilder): + """ + Builder class for generating adatoms at hollow sites. + + The adatom is placed at the hollow site closest to the specified position on the surface of the material. + + """ + + def _calculate_coordinate_from_position_and_distance( + self, material: Material, position_on_surface: List[float], distance_z: float + ) -> List[float]: + coordinate = super()._calculate_coordinate_from_position_and_distance(material, position_on_surface, distance_z) + pymatgen_structure = to_pymatgen(material) + asf = AdsorbateSiteFinder(pymatgen_structure) + + sites = asf.find_adsorption_sites( + positions=[ + "hollow", + ], + no_obtuse_hollow=False, + ) + hollow_coordinates = [array.tolist() for array in sites["hollow"]] + print(hollow_coordinates) + closest_hollow_site_coordinate = min( + hollow_coordinates, key=lambda x: np.linalg.norm(np.array(x) - np.array(coordinate)) + ) + print(closest_hollow_site_coordinate[0:2] + [coordinate[2]]) + return closest_hollow_site_coordinate[0:2] + [coordinate[2]] + + class DefectPairBuilder(DefectBuilder): def create_defect_pair( self, diff --git a/src/py/mat3ra/made/tools/build/defect/enums.py b/src/py/mat3ra/made/tools/build/defect/enums.py index bdc222790..014e6f585 100644 --- a/src/py/mat3ra/made/tools/build/defect/enums.py +++ b/src/py/mat3ra/made/tools/build/defect/enums.py @@ -26,6 +26,12 @@ class AtomPlacementMethodEnum(str, Enum): EQUIDISTANT = "equidistant" # Places the atom at the existing or extrapolated crystal site closest to the given coordinate. CRYSTAL_SITE = "crystal_site" + # Places the atom at the hollow site of the surface (for HEX) + HOLLOW_SITE = "hollow" + # Places the atom at the bridge site of the surface (for HEX) + BRIDGE_SITE = "bridge" + # Places the atom at the on-top site of the surface (for HEX) + ON_TOP_SITE = "on_top" class CoordinatesShapeEnum(str, Enum): From 27fe6fff09389a4e61f0bd4dbcfe1d823b244677 Mon Sep 17 00:00:00 2001 From: VsevolodX <79542055+VsevolodX@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:44:43 -0800 Subject: [PATCH 3/4] chore: remove unused --- .../made/tools/build/defect/builders.py | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/src/py/mat3ra/made/tools/build/defect/builders.py b/src/py/mat3ra/made/tools/build/defect/builders.py index 8da09313b..95f7f9a51 100644 --- a/src/py/mat3ra/made/tools/build/defect/builders.py +++ b/src/py/mat3ra/made/tools/build/defect/builders.py @@ -44,7 +44,6 @@ PointDefectPairConfiguration, ) from .factories import DefectBuilderFactory -from pymatgen.analysis.adsorption import AdsorbateSiteFinder class PointDefectBuilderParameters(BaseModel): @@ -435,36 +434,6 @@ def create_adatom( return self.merge_slab_and_defect(new_material, only_adatom_material) -class HollowSiteAdatomSlabDefectBuilder(AdatomSlabDefectBuilder): - """ - Builder class for generating adatoms at hollow sites. - - The adatom is placed at the hollow site closest to the specified position on the surface of the material. - - """ - - def _calculate_coordinate_from_position_and_distance( - self, material: Material, position_on_surface: List[float], distance_z: float - ) -> List[float]: - coordinate = super()._calculate_coordinate_from_position_and_distance(material, position_on_surface, distance_z) - pymatgen_structure = to_pymatgen(material) - asf = AdsorbateSiteFinder(pymatgen_structure) - - sites = asf.find_adsorption_sites( - positions=[ - "hollow", - ], - no_obtuse_hollow=False, - ) - hollow_coordinates = [array.tolist() for array in sites["hollow"]] - print(hollow_coordinates) - closest_hollow_site_coordinate = min( - hollow_coordinates, key=lambda x: np.linalg.norm(np.array(x) - np.array(coordinate)) - ) - print(closest_hollow_site_coordinate[0:2] + [coordinate[2]]) - return closest_hollow_site_coordinate[0:2] + [coordinate[2]] - - class DefectPairBuilder(DefectBuilder): def create_defect_pair( self, From 00a6bedc5eb18868556bccf6d2d5f1b49632abef Mon Sep 17 00:00:00 2001 From: VsevolodX <79542055+VsevolodX@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:46:43 -0800 Subject: [PATCH 4/4] feat: add hollow site builder --- .../made/tools/build/defect/builders.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/py/mat3ra/made/tools/build/defect/builders.py b/src/py/mat3ra/made/tools/build/defect/builders.py index 95f7f9a51..ae5f40439 100644 --- a/src/py/mat3ra/made/tools/build/defect/builders.py +++ b/src/py/mat3ra/made/tools/build/defect/builders.py @@ -44,6 +44,7 @@ PointDefectPairConfiguration, ) from .factories import DefectBuilderFactory +from pymatgen.analysis.adsorption import AdsorbateSiteFinder class PointDefectBuilderParameters(BaseModel): @@ -434,6 +435,35 @@ def create_adatom( return self.merge_slab_and_defect(new_material, only_adatom_material) +class HollowSiteAdatomSlabDefectBuilder(AdatomSlabDefectBuilder): + """ + Builder class for generating adatoms at hollow sites. + + The adatom is placed at the hollow site closest to the specified position on the surface of the material. + + """ + + def _calculate_coordinate_from_position_and_distance( + self, material: Material, position_on_surface: List[float], distance_z: float + ) -> List[float]: + coordinate = super()._calculate_coordinate_from_position_and_distance(material, position_on_surface, distance_z) + pymatgen_structure = to_pymatgen(material) + asf = AdsorbateSiteFinder(pymatgen_structure) + + sites = asf.find_adsorption_sites( + positions=[ + "hollow", + ], + no_obtuse_hollow=False, + ) + hollow_coordinates = [array.tolist() for array in sites["hollow"]] + print("Hollow site coordinates:\n", hollow_coordinates) + closest_hollow_site_coordinate = min( + hollow_coordinates, key=lambda x: np.linalg.norm(np.array(x) - np.array(coordinate)) + ) + return closest_hollow_site_coordinate[0:2] + [coordinate[2]] + + class DefectPairBuilder(DefectBuilder): def create_defect_pair( self,