diff --git a/src/py/mat3ra/made/tools/build/grain_boundary/__init__.py b/src/py/mat3ra/made/tools/build/grain_boundary/__init__.py index 75a674e0..69396acd 100644 --- a/src/py/mat3ra/made/tools/build/grain_boundary/__init__.py +++ b/src/py/mat3ra/made/tools/build/grain_boundary/__init__.py @@ -7,47 +7,48 @@ from mat3ra.made.tools.build.interface.builders import CommensurateLatticeTwistedInterfaceBuilder from mat3ra.made.tools.build.supercell import create_supercell from mat3ra.made.tools.build.utils import merge_materials -from mat3ra.made.tools.modify import translate_by_vector, filter_by_box +from mat3ra.made.tools.modify import filter_by_box -class SurfaceGrainBoundaryConfiguration(BaseConfiguration): +from mat3ra.made.tools.build.interface.configuration import TwistedInterfaceConfiguration + + +class SurfaceGrainBoundaryConfiguration(TwistedInterfaceConfiguration): """ Configuration for creating a surface grain boundary. Args: - material (Material): The material to create two phases of the grain boundary. - angle (float): The angle between the orientations of the two phases. gap (float): The gap between the two phases. """ - material: Material - angle: float = 0.0 gap: float = 0.0 @property def _json(self): return { "type": self.get_cls_name(), - "material": self.material.to_json(), - "angle": self.angle, + "gap": self.gap, } class SurfaceGrainBoundaryBuilder(CommensurateLatticeTwistedInterfaceBuilder): - def _post_process( - self, - items: List[CommensurateLatticeTwistedInterfaceBuilder._GeneratedItemType], - post_process_parameters=None, - ) -> List[Material]: - grain_boundary_materials = [] + _ConfigurationType: type(SurfaceGrainBoundaryConfiguration) = SurfaceGrainBoundaryConfiguration # type: ignore + + def _post_process(self, items: List[Material], post_process_parameters=None) -> List[Material]: + grain_boundaries = [] for item in items: phase_1_material_initial = create_supercell(item.configuration.film, item.matrix1.tolist()) - phase_1_material_doubled = create_supercell(phase_1_material_initial, scaling_factors=[2, 1, 1]) + phase_1_material_doubled = create_supercell(phase_1_material_initial, scaling_factor=[2, 1, 1]) phase_1_material = filter_by_box(phase_1_material_doubled, [0, 0, 0], [0.5, 1, 1]) - phase_2_material_initial = create_supercell(item.configuration.substrate, item.matrix2.tolist()) - phase_2_material_doubled = create_supercell(phase_2_material_initial, scaling_factors=[2, 1, 1]) + phase_2_material_initial = create_supercell(item.configuration.film, item.matrix2.tolist()) + phase_2_material_doubled = create_supercell(phase_2_material_initial, scaling_factor=[2, 1, 1]) phase_2_material = filter_by_box(phase_2_material_doubled, [0.5, 0, 0], [1, 1, 1]) + interface = merge_materials([phase_1_material, phase_2_material]) - interface.metadata["actual_twist_angle"] = item.angle - grain_boundary_materials.append(interface) - return grain_boundary_materials + grain_boundaries.append(interface) + + return grain_boundaries + + def _update_material_name(self, material: Material, configuration: SurfaceGrainBoundaryConfiguration) -> Material: + material.name = f"Surface Grain Boundary ({configuration.twist_angle:.2f}°)" + return material diff --git a/src/py/mat3ra/made/tools/build/interface/configuration.py b/src/py/mat3ra/made/tools/build/interface/configuration.py index 8d29f827..5269c7aa 100644 --- a/src/py/mat3ra/made/tools/build/interface/configuration.py +++ b/src/py/mat3ra/made/tools/build/interface/configuration.py @@ -1,3 +1,5 @@ +from typing import Optional + from mat3ra.code.entity import InMemoryEntity from pydantic import BaseModel @@ -35,7 +37,7 @@ def _json(self): class TwistedInterfaceConfiguration(BaseConfiguration): film: Material - substrate: Material + substrate: Optional[Material] = None twist_angle: float = 0.0 distance_z: float = 3.0 @@ -44,7 +46,7 @@ def _json(self): return { "type": self.get_cls_name(), "film": self.film.to_json(), - "substrate": self.substrate.to_json(), + "substrate": self.substrate.to_json() if self.substrate else None, "twist_angle": self.twist_angle, "distance_z": self.distance_z, }