Skip to content

Commit

Permalink
Merge pull request #165 from Exabyte-io/update/SOF-7461
Browse files Browse the repository at this point in the history
Update/SOF-7461 Update: various cleanups
  • Loading branch information
VsevolodX authored Oct 5, 2024
2 parents 655692c + 1a75837 commit 8196b75
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 97 deletions.
3 changes: 2 additions & 1 deletion src/py/mat3ra/made/tools/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .convert import decorator_convert_material_args_kwargs_to_atoms, to_pymatgen
from .enums import SurfaceTypes
from .third_party import ASEAtoms, PymatgenIStructure, PymatgenVoronoiNN
from .utils import decorator_handle_periodic_boundary_conditions
from .utils import decorator_convert_position_to_coordinate, decorator_handle_periodic_boundary_conditions


@decorator_convert_material_args_kwargs_to_atoms
Expand Down Expand Up @@ -471,6 +471,7 @@ def get_undercoordinated_atom_indices(
return undercoordinated_atoms_indices


@decorator_convert_position_to_coordinate
def get_local_extremum_atom_index(
material: Material,
coordinate: List[float],
Expand Down
14 changes: 9 additions & 5 deletions src/py/mat3ra/made/tools/build/defect/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@

from ...modify import (
add_vacuum,
filter_material_by_ids,
filter_by_ids,
filter_by_box,
filter_by_condition_on_coordinates,
translate_to_z_level,
rotate_material,
rotate,
)
from ...build import BaseBuilder
from ...convert import to_pymatgen
Expand All @@ -28,6 +28,7 @@
get_atomic_coordinates_extremum,
get_closest_site_id_from_coordinate,
get_closest_site_id_from_coordinate_and_element,
get_local_extremum_atom_index,
)
from ....utils import get_center_of_coordinates
from ...utils import transform_coordinate_to_supercell, coordinate as CoordinateCondition
Expand Down Expand Up @@ -174,7 +175,10 @@ def create_adatom(
def _calculate_coordinate_from_position_and_distance(
self, material: Material, position_on_surface: List[float], distance_z: float
) -> List[float]:
max_z = get_atomic_coordinates_extremum(material, use_cartesian_coordinates=False)
max_z_id = get_local_extremum_atom_index(
material, position_on_surface, "max", vicinity=3.0, use_cartesian_coordinates=False
)
max_z = material.basis.coordinates.get_element_value_by_index(max_z_id)[2]
distance_in_crystal_units = distance_z / material.lattice.c
return [position_on_surface[0], position_on_surface[1], max_z + distance_in_crystal_units]

Expand Down Expand Up @@ -290,7 +294,7 @@ def create_isolated_adatom(
closest_site_id = get_closest_site_id_from_coordinate_and_element(
material, approximate_adatom_coordinate_cartesian, chemical_element
)
only_adatom_material = filter_material_by_ids(material, [closest_site_id])
only_adatom_material = filter_by_ids(material, [closest_site_id])
return only_adatom_material

def create_adatom(
Expand Down Expand Up @@ -612,7 +616,7 @@ def create_terrace(

if rotate_to_match_pbc:
adjusted_material = self._increase_lattice_size(result_material, delta_length, normalized_direction_vector)
result_material = rotate_material(material=adjusted_material, axis=normalized_rotation_axis, angle=angle)
result_material = rotate(material=adjusted_material, axis=normalized_rotation_axis, angle=angle)
return result_material

def _generate(self, configuration: _ConfigurationType) -> List[_GeneratedItemType]:
Expand Down
4 changes: 2 additions & 2 deletions src/py/mat3ra/made/tools/build/interface/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from mat3ra.made.material import Material
from ...calculate.calculators import InterfaceMaterialCalculator
from ...modify import displace_interface_part
from ...modify import interface_displace_part
from ...optimize import evaluate_calculator_on_xy_grid
from .builders import (
SimpleInterfaceBuilder,
Expand Down Expand Up @@ -64,7 +64,7 @@ def get_optimal_film_displacement(
xy_matrix, results_matrix = evaluate_calculator_on_xy_grid(
material=material,
calculator_function=calculator.get_energy,
modifier=displace_interface_part,
modifier=interface_displace_part,
modifier_parameters={},
grid_size_xy=grid_size_xy,
grid_offset_position=grid_offset_position,
Expand Down
4 changes: 2 additions & 2 deletions src/py/mat3ra/made/tools/build/interface/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from ....utils import create_2d_supercell_matrices, get_angle_from_rotation_matrix_2d
from ...modify import (
translate_to_z_level,
rotate_material,
rotate,
translate_by_vector,
add_vacuum_sides,
)
Expand Down Expand Up @@ -229,7 +229,7 @@ def _generate(self, configuration: _ConfigurationType) -> List[Material]:
length=configuration.ribbon_length,
)
top_ribbon = create_nanoribbon(top_ribbon_configuration)
top_ribbon = rotate_material(top_ribbon, [0, 0, 1], configuration.twist_angle, wrap=False)
top_ribbon = rotate(top_ribbon, [0, 0, 1], configuration.twist_angle, wrap=False)

translation_vector = [0, 0, configuration.distance_z]
top_ribbon = translate_by_vector(top_ribbon, translation_vector, use_cartesian_coordinates=True)
Expand Down
5 changes: 3 additions & 2 deletions src/py/mat3ra/made/tools/build/slab/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Optional

from mat3ra.made.material import Material
from .builders import SlabBuilder, SlabSelectorParameters
Expand All @@ -10,6 +10,7 @@ def get_terminations(configuration: SlabConfiguration) -> List[Termination]:
return SlabBuilder().get_terminations(configuration)


def create_slab(configuration: SlabConfiguration, termination: Termination) -> Material:
def create_slab(configuration: SlabConfiguration, termination: Optional[Termination] = None) -> Material:
builder = SlabBuilder()
termination = termination or builder.get_terminations(configuration)[0]
return builder.get_material(configuration, selector_parameters=SlabSelectorParameters(termination=termination))
6 changes: 3 additions & 3 deletions src/py/mat3ra/made/tools/calculate/calculators.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ..analyze import get_surface_atom_indices
from ..convert.utils import InterfacePartsEnum
from ..enums import SurfaceTypes
from ..modify import get_interface_part
from ..modify import interface_get_part
from .interaction_functions import sum_of_inverse_distances_squared


Expand Down Expand Up @@ -101,8 +101,8 @@ def get_energy(
Returns:
float: The calculated interaction energy between the film and substrate.
"""
film_material = get_interface_part(material, part=InterfacePartsEnum.FILM)
substrate_material = get_interface_part(material, part=InterfacePartsEnum.SUBSTRATE)
film_material = interface_get_part(material, part=InterfacePartsEnum.FILM)
substrate_material = interface_get_part(material, part=InterfacePartsEnum.SUBSTRATE)

film_surface_atom_indices = get_surface_atom_indices(
film_material, SurfaceTypes.BOTTOM, shadowing_radius=shadowing_radius
Expand Down
15 changes: 8 additions & 7 deletions src/py/mat3ra/made/tools/modify.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def wrap_to_unit_cell(material: Material) -> Material:
return Material(from_ase(atoms))


def filter_material_by_ids(material: Material, ids: List[int], invert: bool = False) -> Material:
def filter_by_ids(material: Material, ids: List[int], invert: bool = False) -> Material:
"""
Filter out only atoms corresponding to the ids.
Expand Down Expand Up @@ -174,7 +174,7 @@ def filter_by_condition_on_coordinates(
use_cartesian_coordinates=use_cartesian_coordinates,
)

new_material = filter_material_by_ids(new_material, ids, invert=invert_selection)
new_material = filter_by_ids(new_material, ids, invert=invert_selection)
return new_material


Expand Down Expand Up @@ -234,7 +234,7 @@ def filter_by_sphere(
coordinate=center_coordinate,
radius=radius,
)
return filter_material_by_ids(material, ids, invert=invert)
return filter_by_ids(material, ids, invert=invert)


def filter_by_circle_projection(
Expand Down Expand Up @@ -482,7 +482,7 @@ def remove_vacuum(material: Material, from_top=True, from_bottom=True, fixed_pad
return new_material


def rotate_material(material: Material, axis: List[int], angle: float, wrap: bool = True) -> Material:
def rotate(material: Material, axis: List[int], angle: float, wrap: bool = True, rotate_cell=False) -> Material:
"""
Rotate the material around a given axis by a specified angle.
Expand All @@ -491,6 +491,7 @@ def rotate_material(material: Material, axis: List[int], angle: float, wrap: boo
axis (List[int]): The axis to rotate around, expressed as [x, y, z].
angle (float): The angle of rotation in degrees.
wrap (bool): Whether to wrap the material to the unit cell.
rotate_cell (bool): Whether to rotate the cell.
Returns:
Atoms: The rotated material.
"""
Expand All @@ -499,14 +500,14 @@ def rotate_material(material: Material, axis: List[int], angle: float, wrap: boo
crystal_basis.to_crystal()
material.basis = crystal_basis
atoms = to_ase(material)
atoms.rotate(v=axis, a=angle, center="COU")
atoms.rotate(v=axis, a=angle, center="COU", rotate_cell=rotate_cell)
if wrap:
atoms.wrap()

return Material(from_ase(atoms))


def displace_interface_part(
def interface_displace_part(
interface: Material,
displacement: List[float],
label: InterfacePartsEnum = InterfacePartsEnum.FILM,
Expand Down Expand Up @@ -542,7 +543,7 @@ def displace_interface_part(
return new_material


def get_interface_part(
def interface_get_part(
interface: Material,
part: InterfacePartsEnum = InterfacePartsEnum.FILM,
) -> Material:
Expand Down
31 changes: 30 additions & 1 deletion src/py/mat3ra/made/tools/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from functools import wraps
from typing import Callable, List, Optional, Tuple
from typing import Any, Callable, List, Optional, Tuple

import numpy as np
from mat3ra.made.material import Material
Expand Down Expand Up @@ -42,6 +42,35 @@ def wrapper(*args, **kwargs):
return wrapper


def decorator_convert_position_to_coordinate(func: Callable) -> Callable:
"""
A decorator that converts a 2D position [x, y] to a 3D coordinate [x, y, 0.0].
"""

@wraps(func)
def wrapper(*args, **kwargs):
if "coordinate" in kwargs:
coordinate = kwargs["coordinate"]
else:
# Find the position of the 'coordinate' argument and get its value
coordinate_index = func.__code__.co_varnames.index("coordinate")
coordinate = args[coordinate_index]

if len(coordinate) == 2:
coordinate = [coordinate[0], coordinate[1], 0.0]

if "coordinate" in kwargs:
kwargs["coordinate"] = coordinate
else:
args = list(args)
args[coordinate_index] = coordinate
args = tuple(args)

return func(*args, **kwargs)

return wrapper


def get_distance_between_coordinates(coordinate1: List[float], coordinate2: List[float]) -> float:
"""
Get the distance between two coordinates.
Expand Down
66 changes: 2 additions & 64 deletions tests/py/unit/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
"bulk": SI_CONVENTIONAL_CELL,
"miller_indices": (0, 0, 1),
"thickness": 1,
"vacuum": 1,
"vacuum": 5.0,
"xy_supercell_matrix": [[1, 0], [0, 1]],
"use_conventional_cell": True,
"use_orthogonal_z": True,
Expand Down Expand Up @@ -211,69 +211,7 @@
"_id": "",
"metadata": {
"boundaryConditions": {"type": "pbc", "offset": 0},
"build": {
"termination": "Si_P6/mmm_1",
"configuration": {
"type": "SlabConfiguration",
"bulk": {
"name": "Si8",
"basis": {
"elements": [
{"id": 0, "value": "Si"},
{"id": 1, "value": "Si"},
{"id": 2, "value": "Si"},
{"id": 3, "value": "Si"},
{"id": 4, "value": "Si"},
{"id": 5, "value": "Si"},
{"id": 6, "value": "Si"},
{"id": 7, "value": "Si"},
],
"coordinates": [
{"id": 0, "value": [0.5, 0.0, 0.0]},
{"id": 1, "value": [0.25, 0.25, 0.75]},
{"id": 2, "value": [0.5, 0.5, 0.5]},
{"id": 3, "value": [0.25, 0.75, 0.25]},
{"id": 4, "value": [0.0, 0.0, 0.5]},
{"id": 5, "value": [0.75, 0.25, 0.25]},
{"id": 6, "value": [0.0, 0.5, 0.0]},
{"id": 7, "value": [0.75, 0.75, 0.75]},
],
"units": "crystal",
"cell": [[5.468763846, 0.0, 0.0], [-0.0, 5.468763846, 0.0], [0.0, 0.0, 5.468763846]],
"constraints": [],
"labels": [],
},
"lattice": {
"a": 5.468763846,
"b": 5.468763846,
"c": 5.468763846,
"alpha": 90.0,
"beta": 90.0,
"gamma": 90.0,
"units": {"length": "angstrom", "angle": "degree"},
"type": "TRI",
"vectors": {
"a": [5.468763846, 0.0, 0.0],
"b": [-0.0, 5.468763846, 0.0],
"c": [0.0, 0.0, 5.468763846],
"alat": 1,
"units": "angstrom",
},
},
"isNonPeriodic": False,
"_id": "",
"metadata": {"boundaryConditions": {"type": "pbc", "offset": 0}},
"isUpdated": True,
},
"miller_indices": (0, 0, 1),
"thickness": 1,
"vacuum": 5.0,
"xy_supercell_matrix": [[1, 0], [0, 1]],
"use_conventional_cell": True,
"use_orthogonal_z": True,
"make_primitive": True,
},
},
"build": {"configuration": SI_SLAB_CONFIGURATION, "termination": "Si_P6/mmm_1"},
},
"isUpdated": True,
}
Expand Down
2 changes: 1 addition & 1 deletion tests/py/unit/test_tools_build_defect.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def test_create_crystal_site_adatom():

assert defect.basis.elements.values[-1] == "Si"
assertion_utils.assert_deep_almost_equal(
# TO pass on GHA
# Adjusted expected value to pass tests on GHA due to slab generation differences between GHA and local
[0.083333333, 0.458333333, 0.561569594],
defect.basis.coordinates.values[-1],
)
Expand Down
2 changes: 1 addition & 1 deletion tests/py/unit/test_tools_build_grain_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_slab_grain_boundary_builder():
[0.0, 3.867, 0.0],
[0.0, 0.0, 8.734],
]
# To pass on GHA
# Adjusted expected value to pass tests on GHA due to slab generation differences between GHA and local
expected_coordinate_15 = [0.777190818, 0.0, 0.110688115]

assert len(gb.basis.elements.values) == 32
Expand Down
1 change: 0 additions & 1 deletion tests/py/unit/test_tools_build_slab.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ def test_build_slab():
)
termination = get_terminations(slab_config)[0]
slab = create_slab(slab_config, termination)
print(slab.to_json())
assertion_utils.assert_deep_almost_equal(SI_SLAB, slab.to_json())
Loading

0 comments on commit 8196b75

Please sign in to comment.