diff --git a/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/builder.py b/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/builder.py index ddab3a8c6..2fcd2627e 100644 --- a/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/builder.py +++ b/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/builder.py @@ -15,3 +15,11 @@ class StrainBuilder(BaseSingleBuilder): def _generate(self, configuration: StrainConfiguration) -> MaterialWithBuildMetadata: strained_material = strain(configuration.material, configuration.strain_matrix) return MaterialWithBuildMetadata.create(strained_material.to_dict()) + + def _update_material_name( + self, material: MaterialWithBuildMetadata, configuration: StrainConfiguration + ) -> MaterialWithBuildMetadata: + if configuration.scale_factor is not None: + base_name = configuration.material.name + material.name = f"{base_name} (scale={configuration.scale_factor:.4f})" + return material diff --git a/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/configuration.py b/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/configuration.py index b6e26da7a..360bf034c 100644 --- a/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/configuration.py +++ b/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/configuration.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Optional, Union from mat3ra.esse.models.core.abstract.matrix_3x3 import Matrix3x3Schema from mat3ra.made.material import Material @@ -8,6 +8,16 @@ class StrainConfiguration(BaseConfigurationPydantic): + """ + Configuration for a strain operation on a Material. + + Args: + material (Material): The Material object to be strained. + strain_matrix (Matrix3x3Schema): The 3x3 strain matrix defining the deformation. + scale_factor (Optional[float]): An optional scale factor for isotropic scaling instead of a full strain matrix. + """ + type: str = "StrainConfiguration" material: Union[Material, MaterialWithBuildMetadata] strain_matrix: Matrix3x3Schema + scale_factor: Optional[float] = None diff --git a/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/helpers.py b/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/helpers.py index cda499245..d8f92ce57 100644 --- a/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/helpers.py +++ b/src/py/mat3ra/made/tools/build_components/operations/core/modifications/strain/helpers.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Optional, Union from mat3ra.esse.models.core.abstract.matrix_3x3 import Matrix3x3Schema from mat3ra.made.material import Material @@ -23,8 +23,27 @@ def get_isotropic_strain_matrix(scale_factor: float) -> Matrix3x3Schema: def create_strain( material: Union[Material, MaterialWithBuildMetadata], - strain_matrix: Matrix3x3Schema, + strain_matrix: Optional[Matrix3x3Schema] = None, + scale_factor: Optional[float] = None, ) -> MaterialWithBuildMetadata: - configuration = StrainConfiguration(material=material, strain_matrix=strain_matrix) + """ + Creates a strained Material based on the provided strain matrix or scale factor. + + Args: + material (Union[Material, MaterialWithBuildMetadata]): The material to be strained. + strain_matrix (Optional[Matrix3x3Schema]): The 3x3 strain matrix defining the deformation. + scale_factor (Optional[float]): An optional scale factor for isotropic scaling instead of a full strain matrix. + + Returns: + MaterialWithBuildMetadata: The strained material with build metadata. + """ + if scale_factor is not None: + if scale_factor <= 0: + raise ValueError("scale_factor must be positive.") + strain_matrix = get_isotropic_strain_matrix(scale_factor) + if strain_matrix is None: + raise ValueError("Either strain_matrix or scale_factor must be provided.") + + configuration = StrainConfiguration(material=material, strain_matrix=strain_matrix, scale_factor=scale_factor) builder = StrainBuilder() return builder.get_material(configuration) diff --git a/tests/py/unit/test_tools_build_strain.py b/tests/py/unit/test_tools_build_strain.py index 1751718ef..1542e95d6 100644 --- a/tests/py/unit/test_tools_build_strain.py +++ b/tests/py/unit/test_tools_build_strain.py @@ -24,3 +24,13 @@ def test_create_strain(material_config, strain_matrix, expected_material_config) assert build_step.configuration["type"] == "StrainConfiguration" assert build_step.configuration["strain_matrix"] == strain_matrix assert build_step.build_parameters == {} + + +def test_create_strain_with_scale_factor(): + material = Material.create(BULK_Si_CONVENTIONAL) + strained_material = create_strain(material, scale_factor=1.1) + + assert strained_material.name == f"{material.name} (scale=1.1000)" + build_step = strained_material.metadata.build[-1] + assert build_step.configuration["scale_factor"] == 1.1 + assert build_step.configuration["strain_matrix"] == [[1.1, 0.0, 0.0], [0.0, 1.1, 0.0], [0.0, 0.0, 1.1]]