@mat3ra/made 2025.4.30-0 → 2025.5.13-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/pyproject.toml +1 -1
- package/src/py/mat3ra/made/basis/__init__.py +1 -2
- package/src/py/mat3ra/made/lattice.py +0 -1
- package/src/py/mat3ra/made/tools/build/__init__.py +14 -1
- package/src/py/mat3ra/made/tools/build/defect/builders.py +1 -1
- package/src/py/mat3ra/made/tools/build/grain_boundary/builders.py +1 -1
- package/src/py/mat3ra/made/tools/build/interface/builders.py +2 -2
- package/src/py/mat3ra/made/tools/build/nanoparticle/builders.py +1 -1
- package/src/py/mat3ra/made/tools/build/slab/__init__.py +3 -3
- package/src/py/mat3ra/made/tools/build/slab/builders.py +15 -11
- package/src/py/mat3ra/made/tools/build/slab/configuration.py +19 -56
- package/src/py/mat3ra/made/tools/build/slab/termination.py +2 -5
- package/src/py/mat3ra/made/tools/utils/__init__.py +52 -6
- package/tests/js/material.test.ts +1 -1
- package/tests/js/tools/supercell.ts +1 -1
- package/tests/py/unit/fixtures/generated/fixtures.py +3 -3
- package/tests/py/unit/fixtures/interface.py +2 -2
- package/tests/py/unit/fixtures/slab.py +60 -2
- package/tests/py/unit/test_tools_build_grain_boundary.py +3 -3
- package/tests/py/unit/test_tools_build_slab.py +12 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mat3ra/made",
|
|
3
|
-
"version": "2025.
|
|
3
|
+
"version": "2025.5.13-0",
|
|
4
4
|
"description": "MAterials DEsign library",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"lint": "eslint --cache src/js tests/js && prettier --write src/js tests/js",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"@babel/preset-react": "^7.16.7",
|
|
33
33
|
"@babel/register": "^7.22.15",
|
|
34
34
|
"@babel/runtime-corejs3": "^7.16.8",
|
|
35
|
-
"@exabyte-io/eslint-config": "
|
|
35
|
+
"@exabyte-io/eslint-config": "2025.5.13-0",
|
|
36
36
|
"@mat3ra/code": "2025.4.27-0",
|
|
37
|
-
"@mat3ra/esse": "2025.
|
|
37
|
+
"@mat3ra/esse": "2025.5.13-0",
|
|
38
38
|
"@mat3ra/tsconfig": "2024.6.3-0",
|
|
39
39
|
"@mat3ra/utils": "2025.4.14-0",
|
|
40
40
|
"@types/crypto-js": "^4.2.2",
|
package/pyproject.toml
CHANGED
|
@@ -19,7 +19,7 @@ dependencies = [
|
|
|
19
19
|
# new verison of numpy==2.0.0 is not handled by pymatgen yet
|
|
20
20
|
"numpy<=1.26.4",
|
|
21
21
|
"mat3ra-utils",
|
|
22
|
-
"mat3ra-esse",
|
|
22
|
+
"mat3ra-esse @ git+https://github.com/Exabyte-io/esse.git@347180df586aa7629629749943c02a22136dc3d9",
|
|
23
23
|
"mat3ra-code",
|
|
24
24
|
]
|
|
25
25
|
|
|
@@ -2,8 +2,7 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
2
2
|
|
|
3
3
|
from mat3ra.code.array_with_ids import ArrayWithIds
|
|
4
4
|
from mat3ra.code.entity import InMemoryEntityPydantic
|
|
5
|
-
from mat3ra.esse.models.material import BasisSchema
|
|
6
|
-
from mat3ra.esse.models.material import BasisUnitsEnum
|
|
5
|
+
from mat3ra.esse.models.material import BasisSchema, BasisUnitsEnum
|
|
7
6
|
from mat3ra.made.basis.coordinates import Coordinates
|
|
8
7
|
from mat3ra.made.cell import Cell
|
|
9
8
|
from mat3ra.made.utils import get_overlapping_coordinates
|
|
@@ -6,7 +6,6 @@ from mat3ra.code.entity import InMemoryEntityPydantic
|
|
|
6
6
|
from mat3ra.esse.models.properties_directory.structural.lattice.lattice_bravais import (
|
|
7
7
|
LatticeImplicitSchema as LatticeBravaisSchema,
|
|
8
8
|
)
|
|
9
|
-
|
|
10
9
|
from mat3ra.esse.models.properties_directory.structural.lattice.lattice_bravais import (
|
|
11
10
|
LatticeTypeEnum,
|
|
12
11
|
LatticeUnitsSchema,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import List, Optional, Any
|
|
2
2
|
|
|
3
|
-
from mat3ra.code.entity import InMemoryEntity
|
|
3
|
+
from mat3ra.code.entity import InMemoryEntityPydantic, InMemoryEntity
|
|
4
4
|
from pydantic import BaseModel
|
|
5
5
|
|
|
6
6
|
from ...material import Material
|
|
@@ -23,6 +23,19 @@ class BaseConfiguration(BaseModel, InMemoryEntity):
|
|
|
23
23
|
raise NotImplementedError
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
class BaseConfigurationPydantic(InMemoryEntityPydantic):
|
|
27
|
+
"""
|
|
28
|
+
Base class for material build configurations.
|
|
29
|
+
This class provides an interface for defining the configuration parameters.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
type: str = "BaseConfiguration"
|
|
33
|
+
|
|
34
|
+
# TODO: remove this in the next PR
|
|
35
|
+
def to_json(self): # typing: ignore
|
|
36
|
+
return self.to_dict()
|
|
37
|
+
|
|
38
|
+
|
|
26
39
|
class BaseSelectorParameters(BaseModel):
|
|
27
40
|
default_index: int = 0
|
|
28
41
|
|
|
@@ -198,7 +198,7 @@ class SlabDefectBuilder(DefectBuilder):
|
|
|
198
198
|
if build_config["type"] != "SlabConfiguration":
|
|
199
199
|
raise ValueError("Material is not a slab.")
|
|
200
200
|
build_config.pop("type")
|
|
201
|
-
build_config["
|
|
201
|
+
build_config["number_of_layers"] = build_config["number_of_layers"] + added_thickness
|
|
202
202
|
|
|
203
203
|
new_slab_config = SlabConfiguration(**build_config)
|
|
204
204
|
material_with_additional_layers = create_slab(new_slab_config, termination)
|
|
@@ -65,7 +65,7 @@ class SlabGrainBoundaryBuilder(ZSLStrainMatchingInterfaceBuilder):
|
|
|
65
65
|
bulk=interface,
|
|
66
66
|
vacuum=configuration.slab_configuration.vacuum,
|
|
67
67
|
miller_indices=configuration.slab_configuration.miller_indices,
|
|
68
|
-
|
|
68
|
+
number_of_layers=configuration.slab_configuration.number_of_layers,
|
|
69
69
|
use_conventional_cell=False, # Keep false to prevent Pymatgen from simplifying the interface
|
|
70
70
|
use_orthogonal_z=True,
|
|
71
71
|
)
|
|
@@ -193,8 +193,8 @@ class ZSLStrainMatchingInterfaceBuilder(ConvertGeneratedItemsPymatgenStructureMi
|
|
|
193
193
|
termination=termination_pair.to_pymatgen(),
|
|
194
194
|
gap=configuration.distance_z,
|
|
195
195
|
vacuum_over_film=configuration.vacuum,
|
|
196
|
-
film_thickness=configuration.film_configuration.
|
|
197
|
-
substrate_thickness=configuration.substrate_configuration.
|
|
196
|
+
film_thickness=configuration.film_configuration.number_of_layers,
|
|
197
|
+
substrate_thickness=configuration.substrate_configuration.number_of_layers,
|
|
198
198
|
in_layers=True,
|
|
199
199
|
)
|
|
200
200
|
|
|
@@ -37,7 +37,7 @@ class SlabBasedNanoparticleBuilder(BaseBuilder):
|
|
|
37
37
|
slab_config = SlabConfiguration(
|
|
38
38
|
bulk=config.material,
|
|
39
39
|
miller_indices=config.orientation_z,
|
|
40
|
-
|
|
40
|
+
number_of_layers=config.supercell_size,
|
|
41
41
|
use_conventional_cell=True,
|
|
42
42
|
use_orthogonal_z=True,
|
|
43
43
|
make_primitive=False,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import List, Optional
|
|
2
2
|
|
|
3
3
|
from mat3ra.made.material import Material
|
|
4
|
-
from .builders import SlabBuilder, SlabSelectorParameters,
|
|
4
|
+
from .builders import SlabBuilder, SlabSelectorParameters, SlabBuilderParameters
|
|
5
5
|
from .configuration import SlabConfiguration
|
|
6
6
|
from .termination import Termination
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ CACHED_BUILDER = None
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def get_terminations(
|
|
12
|
-
configuration: SlabConfiguration, build_parameters: Optional[
|
|
12
|
+
configuration: SlabConfiguration, build_parameters: Optional[SlabBuilderParameters] = None
|
|
13
13
|
) -> List[Termination]:
|
|
14
14
|
global CACHED_BUILDER
|
|
15
15
|
CACHED_BUILDER = SlabBuilder(build_parameters=build_parameters)
|
|
@@ -19,7 +19,7 @@ def get_terminations(
|
|
|
19
19
|
def create_slab(
|
|
20
20
|
configuration: SlabConfiguration,
|
|
21
21
|
termination: Optional[Termination] = None,
|
|
22
|
-
build_parameters: Optional[
|
|
22
|
+
build_parameters: Optional[SlabBuilderParameters] = None,
|
|
23
23
|
use_cached_builder: bool = True,
|
|
24
24
|
) -> Material:
|
|
25
25
|
builder = (
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
from typing import List, Optional
|
|
2
|
+
|
|
2
3
|
from pydantic import BaseModel
|
|
3
4
|
|
|
4
5
|
from mat3ra.made.material import Material
|
|
5
|
-
|
|
6
|
-
from
|
|
7
|
-
from
|
|
6
|
+
from .configuration import SlabConfiguration
|
|
7
|
+
from .termination import Termination
|
|
8
|
+
from ..supercell import create_supercell
|
|
8
9
|
from ...analyze.other import get_chemical_formula
|
|
9
|
-
from ...convert import to_pymatgen
|
|
10
10
|
from ...build import BaseBuilder
|
|
11
11
|
from ...build.mixins import ConvertGeneratedItemsPymatgenStructureMixin
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
12
|
+
from ...convert import to_pymatgen
|
|
13
|
+
from ...modify import add_vacuum
|
|
14
|
+
from ...third_party import PymatgenSlab, PymatgenSlabGenerator, label_pymatgen_slab_termination
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class SlabSelectorParameters(BaseModel):
|
|
@@ -26,19 +26,23 @@ class PymatgenSlabGeneratorParameters(BaseModel):
|
|
|
26
26
|
symmetrize: bool = True
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
class SlabBuilderParameters(PymatgenSlabGeneratorParameters):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
29
33
|
class SlabBuilder(ConvertGeneratedItemsPymatgenStructureMixin, BaseBuilder):
|
|
30
|
-
build_parameters: Optional[
|
|
34
|
+
build_parameters: Optional[SlabBuilderParameters] = None
|
|
31
35
|
_ConfigurationType: type(SlabConfiguration) = SlabConfiguration # type: ignore
|
|
32
36
|
_GeneratedItemType: PymatgenSlab = PymatgenSlab # type: ignore
|
|
33
37
|
_SelectorParametersType: type(SlabSelectorParameters) = SlabSelectorParameters # type: ignore
|
|
34
38
|
__configuration: SlabConfiguration
|
|
35
39
|
|
|
36
40
|
def _generate(self, configuration: _ConfigurationType) -> List[_GeneratedItemType]: # type: ignore
|
|
37
|
-
build_parameters = self.build_parameters or
|
|
41
|
+
build_parameters = self.build_parameters or SlabBuilderParameters()
|
|
38
42
|
generator = PymatgenSlabGenerator(
|
|
39
43
|
initial_structure=to_pymatgen(configuration.bulk),
|
|
40
44
|
miller_index=configuration.miller_indices,
|
|
41
|
-
min_slab_size=configuration.
|
|
45
|
+
min_slab_size=configuration.number_of_layers,
|
|
42
46
|
min_vacuum_size=build_parameters.min_vacuum_size,
|
|
43
47
|
in_unit_planes=build_parameters.in_unit_planes,
|
|
44
48
|
reorient_lattice=build_parameters.reorient_lattice,
|
|
@@ -61,7 +65,7 @@ class SlabBuilder(ConvertGeneratedItemsPymatgenStructureMixin, BaseBuilder):
|
|
|
61
65
|
def _post_process(self, items: List[_GeneratedItemType], post_process_parameters=None) -> List[Material]:
|
|
62
66
|
materials = super()._post_process(items, post_process_parameters)
|
|
63
67
|
materials = [create_supercell(material, self.__configuration.xy_supercell_matrix) for material in materials]
|
|
64
|
-
build_parameters = self.build_parameters or
|
|
68
|
+
build_parameters = self.build_parameters or SlabBuilderParameters()
|
|
65
69
|
|
|
66
70
|
# Adding total vacuum to be exactly as specified in configuration, including already added vacuum
|
|
67
71
|
added_vacuum = (
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
from mat3ra.esse.models.materials_category.single_material.two_dimensional.slab.configuration import (
|
|
2
|
+
SlabConfigurationSchema,
|
|
3
|
+
)
|
|
4
4
|
|
|
5
5
|
from mat3ra.made.material import Material
|
|
6
|
-
|
|
7
|
-
from .. import BaseConfiguration
|
|
8
|
-
from ...third_party import PymatgenSpacegroupAnalyzer
|
|
6
|
+
from .. import BaseConfigurationPydantic
|
|
9
7
|
from ...convert import to_pymatgen, from_pymatgen
|
|
8
|
+
from ...third_party import PymatgenSpacegroupAnalyzer
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
class SlabConfiguration(
|
|
11
|
+
class SlabConfiguration(SlabConfigurationSchema, BaseConfigurationPydantic):
|
|
13
12
|
"""
|
|
14
13
|
Configuration for building a slab.
|
|
15
14
|
|
|
@@ -24,56 +23,20 @@ class SlabConfiguration(BaseConfiguration):
|
|
|
24
23
|
make_primitive (bool): Whether to try to find primitive cell for the created slab.
|
|
25
24
|
"""
|
|
26
25
|
|
|
26
|
+
type: str = "SlabConfiguration"
|
|
27
27
|
bulk: Material
|
|
28
|
-
miller_indices: Tuple[int, int, int] = (0, 0, 1)
|
|
29
|
-
thickness: int = 1
|
|
30
|
-
vacuum: float = 5.0
|
|
31
|
-
xy_supercell_matrix: List[List[int]] = np.eye(2).tolist()
|
|
32
|
-
use_conventional_cell: bool = True
|
|
33
|
-
use_orthogonal_z: bool = False
|
|
34
|
-
make_primitive: bool = False
|
|
35
28
|
|
|
36
|
-
def __init__(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
thickness=thickness,
|
|
41
|
-
vacuum=vacuum,
|
|
42
|
-
xy_supercell_matrix=None,
|
|
43
|
-
use_conventional_cell=use_conventional_cell,
|
|
44
|
-
use_orthogonal_z=use_orthogonal_z,
|
|
45
|
-
make_primitive=make_primitive,
|
|
46
|
-
):
|
|
47
|
-
if xy_supercell_matrix is None:
|
|
48
|
-
xy_supercell_matrix = np.eye(2).tolist()
|
|
49
|
-
bulk = bulk or Material.create_default()
|
|
50
|
-
__bulk_pymatgen_structure = (
|
|
51
|
-
PymatgenSpacegroupAnalyzer(to_pymatgen(bulk)).get_conventional_standard_structure()
|
|
52
|
-
if use_conventional_cell
|
|
53
|
-
else to_pymatgen(bulk)
|
|
54
|
-
)
|
|
55
|
-
__bulk_config = from_pymatgen(__bulk_pymatgen_structure)
|
|
56
|
-
super().__init__(
|
|
57
|
-
bulk=Material.create(__bulk_config),
|
|
58
|
-
miller_indices=miller_indices,
|
|
59
|
-
thickness=thickness,
|
|
60
|
-
vacuum=vacuum,
|
|
61
|
-
xy_supercell_matrix=xy_supercell_matrix,
|
|
62
|
-
use_conventional_cell=use_conventional_cell,
|
|
63
|
-
use_orthogonal_z=use_orthogonal_z,
|
|
64
|
-
make_primitive=make_primitive,
|
|
29
|
+
def __init__(self, **kwargs):
|
|
30
|
+
bulk = kwargs.pop("bulk", None) or Material.create_default()
|
|
31
|
+
use_conventional = kwargs.get(
|
|
32
|
+
"use_conventional_cell", SlabConfigurationSchema.model_fields["use_conventional_cell"].default
|
|
65
33
|
)
|
|
66
34
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"xy_supercell_matrix": self.xy_supercell_matrix,
|
|
76
|
-
"use_conventional_cell": self.use_conventional_cell,
|
|
77
|
-
"use_orthogonal_z": self.use_orthogonal_z,
|
|
78
|
-
"make_primitive": self.make_primitive,
|
|
79
|
-
}
|
|
35
|
+
bulk_pmg = to_pymatgen(bulk)
|
|
36
|
+
if use_conventional:
|
|
37
|
+
bulk_pmg = PymatgenSpacegroupAnalyzer(bulk_pmg).get_conventional_standard_structure()
|
|
38
|
+
|
|
39
|
+
bulk_config = from_pymatgen(bulk_pmg)
|
|
40
|
+
kwargs["bulk"] = Material.create(bulk_config)
|
|
41
|
+
|
|
42
|
+
super().__init__(**kwargs)
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
from
|
|
1
|
+
from mat3ra.esse.models.material.reusable.slab.termination import TerminationSchema
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class Termination(
|
|
5
|
-
chemical_elements: str
|
|
6
|
-
space_group_symmetry_label: str
|
|
7
|
-
|
|
4
|
+
class Termination(TerminationSchema):
|
|
8
5
|
def __str__(self):
|
|
9
6
|
return f"{self.chemical_elements}_{self.space_group_symmetry_label}"
|
|
10
7
|
|
|
@@ -1,24 +1,70 @@
|
|
|
1
1
|
from functools import wraps
|
|
2
|
-
from typing import Callable, List, Optional
|
|
2
|
+
from typing import Any, Callable, List, Optional, Union, cast
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
|
+
from mat3ra.esse.models.material.reusable.supercell_matrix_2d import SupercellMatrix2DSchema
|
|
6
|
+
from mat3ra.esse.models.materials_category.single_material.two_dimensional.slab.configuration import (
|
|
7
|
+
SupercellMatrix2DSchemaItem,
|
|
8
|
+
)
|
|
5
9
|
from mat3ra.utils.matrix import convert_2x2_to_3x3
|
|
6
10
|
|
|
7
|
-
from ..third_party import PymatgenStructure
|
|
8
|
-
|
|
9
11
|
DEFAULT_SCALING_FACTOR = np.array([3, 3, 3])
|
|
10
12
|
DEFAULT_TRANSLATION_VECTOR = 1 / DEFAULT_SCALING_FACTOR
|
|
11
13
|
|
|
12
14
|
|
|
15
|
+
def is_primitive_2x2_matrix(matrix: Any) -> bool:
|
|
16
|
+
return (
|
|
17
|
+
isinstance(matrix, list) and len(matrix) == 2 and all(isinstance(row, list) and len(row) == 2 for row in matrix)
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def normalize_2x2_matrix(
|
|
22
|
+
matrix: Union[
|
|
23
|
+
List[List[float]],
|
|
24
|
+
SupercellMatrix2DSchema,
|
|
25
|
+
]
|
|
26
|
+
) -> Optional[List[List[float]]]:
|
|
27
|
+
"""
|
|
28
|
+
Normalize any matrix-like structure to a plain 2x2 list of floats.
|
|
29
|
+
Returns None if normalization is not possible.
|
|
30
|
+
"""
|
|
31
|
+
if isinstance(matrix, SupercellMatrix2DSchema) and matrix.root:
|
|
32
|
+
matrix = matrix.root
|
|
33
|
+
|
|
34
|
+
if isinstance(matrix, SupercellMatrix2DSchemaItem):
|
|
35
|
+
return [matrix.root]
|
|
36
|
+
|
|
37
|
+
if (
|
|
38
|
+
isinstance(matrix, list)
|
|
39
|
+
and len(matrix) == 2
|
|
40
|
+
and all(isinstance(row, SupercellMatrix2DSchemaItem) for row in matrix)
|
|
41
|
+
):
|
|
42
|
+
return [cast(SupercellMatrix2DSchemaItem, row).root for row in matrix]
|
|
43
|
+
|
|
44
|
+
if is_primitive_2x2_matrix(matrix):
|
|
45
|
+
return matrix # already normalized
|
|
46
|
+
|
|
47
|
+
return None # unrecognized format
|
|
48
|
+
|
|
49
|
+
|
|
13
50
|
def decorator_convert_2x2_to_3x3(func: Callable) -> Callable:
|
|
14
51
|
"""
|
|
15
|
-
Decorator
|
|
52
|
+
Decorator that converts a 2x2 matrix input to a 3x3 matrix.
|
|
53
|
+
Supports schema-based formats and raw nested lists.
|
|
16
54
|
"""
|
|
17
55
|
|
|
18
56
|
@wraps(func)
|
|
19
57
|
def wrapper(*args, **kwargs):
|
|
20
|
-
|
|
21
|
-
|
|
58
|
+
def convert_if_matrix(arg):
|
|
59
|
+
matrix = normalize_2x2_matrix(arg)
|
|
60
|
+
return convert_2x2_to_3x3(matrix) if matrix else arg
|
|
61
|
+
|
|
62
|
+
args = tuple(convert_if_matrix(arg) for arg in args)
|
|
63
|
+
|
|
64
|
+
if "supercell_matrix" in kwargs:
|
|
65
|
+
kwargs["supercell_matrix"] = convert_if_matrix(kwargs["supercell_matrix"])
|
|
66
|
+
|
|
67
|
+
return func(*args, **kwargs)
|
|
22
68
|
|
|
23
69
|
return wrapper
|
|
24
70
|
|
|
@@ -3,7 +3,7 @@ import { expect } from "chai";
|
|
|
3
3
|
import { Material } from "../../src/js/material";
|
|
4
4
|
import { Na4Cl4, Silicon } from "./fixtures";
|
|
5
5
|
|
|
6
|
-
const newBasisXYZ = `Si 0.000000 0.000000 0.000000
|
|
6
|
+
const newBasisXYZ = `Si 0.000000 0.000000 0.000000
|
|
7
7
|
Ge 0.250000 0.250000 0.250000
|
|
8
8
|
`;
|
|
9
9
|
|
|
@@ -27,7 +27,7 @@ describe("Tools:Supercell", () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
it("should generate supercell with removed constraints", () => {
|
|
30
|
-
const newBasisXYZ = `Si 0.000000 0.000000 0.000000
|
|
30
|
+
const newBasisXYZ = `Si 0.000000 0.000000 0.000000
|
|
31
31
|
Ge 0.250000 0.250000 0.250000
|
|
32
32
|
`;
|
|
33
33
|
const poscarNoConstraints = `Silicon FCC - supercell [[2,0,0],[0,1,0],[0,0,1]]
|
|
@@ -19,7 +19,7 @@ INTERFACE_ATOMS.set_tags([1] * len(substrate) + [2] * len(film))
|
|
|
19
19
|
SUBSTRATE_MATERIAL = Material.create(from_ase(substrate))
|
|
20
20
|
FILM_MATERIAL = Material.create(from_ase(film))
|
|
21
21
|
|
|
22
|
-
SUBSTRATE_CONFIGURATION = SlabConfiguration(bulk=SUBSTRATE_MATERIAL,
|
|
22
|
+
SUBSTRATE_CONFIGURATION = SlabConfiguration(bulk=SUBSTRATE_MATERIAL, number_of_layers=3)
|
|
23
23
|
FILM_CONFIGURATION = SlabConfiguration(bulk=FILM_MATERIAL)
|
|
24
24
|
|
|
25
25
|
substrate_terminations = get_terminations(SUBSTRATE_CONFIGURATION)
|
|
@@ -63,7 +63,7 @@ clean_material = Material.create_default()
|
|
|
63
63
|
slab_111_config = SlabConfiguration(
|
|
64
64
|
bulk=clean_material,
|
|
65
65
|
miller_indices=(1, 1, 1),
|
|
66
|
-
|
|
66
|
+
number_of_layers=4,
|
|
67
67
|
vacuum=6,
|
|
68
68
|
xy_supercell_matrix=[[1, 0], [0, 1]],
|
|
69
69
|
use_orthogonal_z=True,
|
|
@@ -74,7 +74,7 @@ SLAB_111 = create_slab(slab_111_config, t_111)
|
|
|
74
74
|
slab_001_config = SlabConfiguration(
|
|
75
75
|
bulk=clean_material,
|
|
76
76
|
miller_indices=(0, 0, 1),
|
|
77
|
-
|
|
77
|
+
number_of_layers=3,
|
|
78
78
|
vacuum=3,
|
|
79
79
|
xy_supercell_matrix=[[2, 0], [0, 1]],
|
|
80
80
|
use_orthogonal_z=True,
|
|
@@ -62,7 +62,7 @@ GRAPHENE_NICKEL_INTERFACE = {
|
|
|
62
62
|
"type": "SlabConfiguration",
|
|
63
63
|
"bulk": {**GRAPHENE, "name": "C2"},
|
|
64
64
|
"miller_indices": [0, 0, 1],
|
|
65
|
-
"
|
|
65
|
+
"number_of_layers": 1,
|
|
66
66
|
"vacuum": 0,
|
|
67
67
|
"xy_supercell_matrix": [[1, 0], [0, 1]],
|
|
68
68
|
"use_conventional_cell": True,
|
|
@@ -104,7 +104,7 @@ GRAPHENE_NICKEL_INTERFACE = {
|
|
|
104
104
|
"metadata": {"boundaryConditions": {"type": "pbc", "offset": 0}},
|
|
105
105
|
},
|
|
106
106
|
"miller_indices": [1, 1, 1],
|
|
107
|
-
"
|
|
107
|
+
"number_of_layers": 3,
|
|
108
108
|
"vacuum": 3,
|
|
109
109
|
"xy_supercell_matrix": [[1, 0], [0, 1]],
|
|
110
110
|
"use_conventional_cell": True,
|
|
@@ -8,7 +8,7 @@ SI_SLAB_001_CONFIGURATION: Dict[str, Any] = {
|
|
|
8
8
|
"type": "SlabConfiguration",
|
|
9
9
|
"bulk": SI_CONVENTIONAL_CELL,
|
|
10
10
|
"miller_indices": (0, 0, 1),
|
|
11
|
-
"
|
|
11
|
+
"number_of_layers": 1,
|
|
12
12
|
"vacuum": 5.0,
|
|
13
13
|
"xy_supercell_matrix": [[1, 0], [0, 1]],
|
|
14
14
|
"use_conventional_cell": True,
|
|
@@ -131,7 +131,7 @@ SI_SLAB_100: Dict[str, Any] = {
|
|
|
131
131
|
"metadata": {"boundaryConditions": {"type": "pbc", "offset": 0}},
|
|
132
132
|
},
|
|
133
133
|
"miller_indices": (0, 0, 1),
|
|
134
|
-
"
|
|
134
|
+
"number_of_layers": 2,
|
|
135
135
|
"vacuum": 5.0,
|
|
136
136
|
"xy_supercell_matrix": [[1, 0], [0, 1]],
|
|
137
137
|
"use_conventional_cell": True,
|
|
@@ -196,3 +196,61 @@ SI_SLAB_001_WITH_VACUUM["basis"]["coordinates"] = [
|
|
|
196
196
|
{"id": 0, "value": [0.583333333, 0.833333333, 0.149981861]},
|
|
197
197
|
{"id": 1, "value": [0.25, 0.5, 0.089989116]},
|
|
198
198
|
]
|
|
199
|
+
|
|
200
|
+
SI_SLAB_DEFAULT_PARAMETERS = {
|
|
201
|
+
"basis": {
|
|
202
|
+
"constraints": [],
|
|
203
|
+
"coordinates": [
|
|
204
|
+
{"id": 0, "value": [0.5, 0.0, 0.457090105]},
|
|
205
|
+
{"id": 1, "value": [0.25, 0.25, 0.326492932]},
|
|
206
|
+
{"id": 2, "value": [0.5, 0.5, 0.195895759]},
|
|
207
|
+
{"id": 3, "value": [0.25, 0.75, 0.065298586]},
|
|
208
|
+
{"id": 4, "value": [0.0, 0.0, 0.195895759]},
|
|
209
|
+
{"id": 5, "value": [0.75, 0.25, 0.065298586]},
|
|
210
|
+
{"id": 6, "value": [0.0, 0.5, 0.457090105]},
|
|
211
|
+
{"id": 7, "value": [0.75, 0.75, 0.326492932]},
|
|
212
|
+
],
|
|
213
|
+
"elements": [
|
|
214
|
+
{"id": 0, "value": "Si"},
|
|
215
|
+
{"id": 1, "value": "Si"},
|
|
216
|
+
{"id": 2, "value": "Si"},
|
|
217
|
+
{"id": 3, "value": "Si"},
|
|
218
|
+
{"id": 4, "value": "Si"},
|
|
219
|
+
{"id": 5, "value": "Si"},
|
|
220
|
+
{"id": 6, "value": "Si"},
|
|
221
|
+
{"id": 7, "value": "Si"},
|
|
222
|
+
],
|
|
223
|
+
"labels": [],
|
|
224
|
+
"units": "crystal",
|
|
225
|
+
},
|
|
226
|
+
"isDefault": False,
|
|
227
|
+
"isNonPeriodic": False,
|
|
228
|
+
"lattice": {
|
|
229
|
+
"a": 5.468763846,
|
|
230
|
+
"alpha": 90.0,
|
|
231
|
+
"b": 5.468763846,
|
|
232
|
+
"beta": 90.0,
|
|
233
|
+
"c": 10.468763846,
|
|
234
|
+
"gamma": 90.0,
|
|
235
|
+
"type": "TRI",
|
|
236
|
+
"units": {"angle": "degree", "length": "angstrom"},
|
|
237
|
+
},
|
|
238
|
+
"metadata": {
|
|
239
|
+
"boundaryConditions": {"offset": 0, "type": "pbc"},
|
|
240
|
+
"build": {
|
|
241
|
+
"configuration": {
|
|
242
|
+
"bulk": SI_CONVENTIONAL_CELL,
|
|
243
|
+
"make_primitive": False,
|
|
244
|
+
"miller_indices": [0, 0, 1],
|
|
245
|
+
"number_of_layers": 1,
|
|
246
|
+
"type": "SlabConfiguration",
|
|
247
|
+
"use_conventional_cell": True,
|
|
248
|
+
"use_orthogonal_z": False,
|
|
249
|
+
"vacuum": 5.0,
|
|
250
|
+
"xy_supercell_matrix": [[1, 0], [0, 1]],
|
|
251
|
+
},
|
|
252
|
+
"termination": "Si_P4/mmm_2",
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
"name": "Si8(001), termination Si_P4/mmm_2, Slab",
|
|
256
|
+
}
|
|
@@ -21,14 +21,14 @@ def test_slab_grain_boundary_builder():
|
|
|
21
21
|
phase_1_configuration = SlabConfiguration(
|
|
22
22
|
bulk=material,
|
|
23
23
|
vacuum=0,
|
|
24
|
-
|
|
24
|
+
number_of_layers=2,
|
|
25
25
|
miller_indices=(0, 0, 1),
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
phase_2_configuration = SlabConfiguration(
|
|
29
29
|
bulk=material,
|
|
30
30
|
vacuum=0,
|
|
31
|
-
|
|
31
|
+
number_of_layers=2,
|
|
32
32
|
miller_indices=(0, 0, 1),
|
|
33
33
|
)
|
|
34
34
|
|
|
@@ -38,7 +38,7 @@ def test_slab_grain_boundary_builder():
|
|
|
38
38
|
slab_config = SlabConfiguration(
|
|
39
39
|
vacuum=1,
|
|
40
40
|
miller_indices=(0, 0, 1),
|
|
41
|
-
|
|
41
|
+
number_of_layers=2,
|
|
42
42
|
xy_supercell_matrix=[[1, 0], [0, 1]],
|
|
43
43
|
)
|
|
44
44
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from mat3ra.made.material import Material
|
|
2
2
|
from mat3ra.made.tools.build.slab import (
|
|
3
|
-
|
|
3
|
+
SlabBuilderParameters,
|
|
4
4
|
SlabConfiguration,
|
|
5
5
|
create_slab,
|
|
6
6
|
get_terminations,
|
|
7
7
|
)
|
|
8
|
-
from unit.fixtures.slab import SI_SLAB_100
|
|
8
|
+
from unit.fixtures.slab import SI_SLAB_100, SI_SLAB_DEFAULT_PARAMETERS
|
|
9
9
|
|
|
10
10
|
from .utils import assert_two_entities_deep_almost_equal
|
|
11
11
|
|
|
@@ -16,17 +16,23 @@ def test_build_slab():
|
|
|
16
16
|
slab_config = SlabConfiguration(
|
|
17
17
|
bulk=material,
|
|
18
18
|
miller_indices=(0, 0, 1),
|
|
19
|
-
|
|
19
|
+
number_of_layers=2,
|
|
20
20
|
vacuum=5.0,
|
|
21
21
|
xy_supercell_matrix=[[1, 0], [0, 1]],
|
|
22
22
|
use_orthogonal_z=True,
|
|
23
23
|
use_conventional_cell=True,
|
|
24
24
|
make_primitive=True,
|
|
25
25
|
)
|
|
26
|
-
params =
|
|
27
|
-
min_vacuum_size=1, in_unit_planes=True, reorient_lattice=True, symmetrize=True
|
|
28
|
-
)
|
|
26
|
+
params = SlabBuilderParameters(min_vacuum_size=1, in_unit_planes=True, reorient_lattice=True, symmetrize=True)
|
|
29
27
|
terminations = get_terminations(slab_config, build_parameters=params)
|
|
30
28
|
termination = terminations[0]
|
|
31
29
|
slab = create_slab(slab_config, termination, params)
|
|
32
30
|
assert_two_entities_deep_almost_equal(slab, SI_SLAB_100)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_build_slab_with_default_parameters():
|
|
34
|
+
slab_config = SlabConfiguration(
|
|
35
|
+
bulk=material,
|
|
36
|
+
)
|
|
37
|
+
slab = create_slab(slab_config)
|
|
38
|
+
assert_two_entities_deep_almost_equal(slab, SI_SLAB_DEFAULT_PARAMETERS)
|