@mat3ra/made 2026.5.7-0 → 2026.5.21-1
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
CHANGED
|
@@ -4,6 +4,7 @@ from .simple import InterfaceAnalyzer
|
|
|
4
4
|
from .twisted_nanoribbons import TwistedNanoribbonsInterfaceAnalyzer
|
|
5
5
|
from .utils.holders import MatchedSubstrateFilmConfigurationHolder
|
|
6
6
|
from .zsl import ZSLInterfaceAnalyzer, ZSLMatchHolder
|
|
7
|
+
from .utils import calculate_interfacial_distance_from_rdf
|
|
7
8
|
|
|
8
9
|
__all__ = [
|
|
9
10
|
"InterfaceAnalyzer",
|
|
@@ -15,4 +16,5 @@ __all__ = [
|
|
|
15
16
|
"GrainBoundaryPlanarMatchHolder",
|
|
16
17
|
"TwistedNanoribbonsInterfaceAnalyzer",
|
|
17
18
|
"MatchedSubstrateFilmConfigurationHolder",
|
|
19
|
+
"calculate_interfacial_distance_from_rdf",
|
|
18
20
|
]
|
|
@@ -1,5 +1,77 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
from mat3ra.made.material import Material
|
|
4
|
+
|
|
5
|
+
from ....build.pristine_structures.two_dimensional.slab import SlabConfiguration
|
|
6
|
+
from ....build_components.entities.reusable.three_dimensional.supercell.helpers import create_supercell
|
|
7
|
+
from ...rdf import RadialDistributionFunction
|
|
1
8
|
from .holders import MatchedSubstrateFilmConfigurationHolder
|
|
2
9
|
|
|
10
|
+
|
|
11
|
+
def calculate_interfacial_distance_from_rdf(
|
|
12
|
+
substrate_material: Union[Material, dict, "SlabConfiguration"],
|
|
13
|
+
film_material: Union[Material, dict, "SlabConfiguration"],
|
|
14
|
+
rdf_cutoff: float = 10.0,
|
|
15
|
+
rdf_bin_size: float = 0.1,
|
|
16
|
+
supercell_size: tuple = (3, 3, 3),
|
|
17
|
+
) -> float:
|
|
18
|
+
"""
|
|
19
|
+
Calculate interfacial distance based on RDF analysis of bulk materials.
|
|
20
|
+
|
|
21
|
+
Creates temporary supercells of substrate and film bulk materials,
|
|
22
|
+
calculates their RDFs to find the first peak (nearest neighbor distance),
|
|
23
|
+
and returns the average of these distances as the initial guess for interfacial distance.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
substrate_material: Material, dict, or SlabConfiguration for the substrate
|
|
27
|
+
film_material: Material, dict, or SlabConfiguration for the film
|
|
28
|
+
rdf_cutoff: Maximum distance for RDF calculation in Angstroms
|
|
29
|
+
rdf_bin_size: Bin size for RDF histogram in Angstroms
|
|
30
|
+
supercell_size: Size of supercell for RDF analysis (default: 3x3x3)
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
float: Calculated interfacial distance in Angstroms
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
if isinstance(substrate_material, SlabConfiguration):
|
|
37
|
+
substrate_bulk = substrate_material.atomic_layers.crystal
|
|
38
|
+
elif isinstance(substrate_material, dict):
|
|
39
|
+
substrate_bulk = Material.create(substrate_material)
|
|
40
|
+
else:
|
|
41
|
+
substrate_bulk = substrate_material
|
|
42
|
+
|
|
43
|
+
if isinstance(film_material, SlabConfiguration):
|
|
44
|
+
film_bulk = film_material.atomic_layers.crystal
|
|
45
|
+
elif isinstance(film_material, dict):
|
|
46
|
+
film_bulk = Material.create(film_material)
|
|
47
|
+
else:
|
|
48
|
+
film_bulk = film_material
|
|
49
|
+
|
|
50
|
+
substrate_supercell = create_supercell(material=substrate_bulk, scaling_factor=list(supercell_size))
|
|
51
|
+
|
|
52
|
+
film_supercell = create_supercell(material=film_bulk, scaling_factor=list(supercell_size))
|
|
53
|
+
|
|
54
|
+
substrate_rdf = RadialDistributionFunction.from_material(
|
|
55
|
+
substrate_supercell,
|
|
56
|
+
cutoff=rdf_cutoff,
|
|
57
|
+
bin_size=rdf_bin_size,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
film_rdf = RadialDistributionFunction.from_material(
|
|
61
|
+
film_supercell,
|
|
62
|
+
cutoff=rdf_cutoff,
|
|
63
|
+
bin_size=rdf_bin_size,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
substrate_first_peak = substrate_rdf.first_peak_distance
|
|
67
|
+
film_first_peak = film_rdf.first_peak_distance
|
|
68
|
+
|
|
69
|
+
interfacial_distance = (substrate_first_peak + film_first_peak) / 2.0
|
|
70
|
+
|
|
71
|
+
return interfacial_distance
|
|
72
|
+
|
|
73
|
+
|
|
3
74
|
__all__ = [
|
|
4
75
|
"MatchedSubstrateFilmConfigurationHolder",
|
|
76
|
+
"calculate_interfacial_distance_from_rdf",
|
|
5
77
|
]
|
|
@@ -3,8 +3,10 @@ from typing import Final
|
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pytest
|
|
6
|
+
from mat3ra.made.material import Material
|
|
6
7
|
from mat3ra.made.tools.analyze.interface import InterfaceAnalyzer
|
|
7
8
|
from mat3ra.made.tools.analyze.interface.commensurate import CommensurateLatticeInterfaceAnalyzer
|
|
9
|
+
from mat3ra.made.tools.analyze.interface.utils import calculate_interfacial_distance_from_rdf
|
|
8
10
|
from mat3ra.made.tools.build.pristine_structures.two_dimensional.slab import SlabConfiguration
|
|
9
11
|
from unit.fixtures.bulk import BULK_GRAPHENE, BULK_Ge_CONVENTIONAL, BULK_Si_CONVENTIONAL
|
|
10
12
|
|
|
@@ -195,3 +197,27 @@ def test_optimal_supercell_functions(substrate, film, expected_n, expected_m):
|
|
|
195
197
|
|
|
196
198
|
assert optimal_n == expected_n
|
|
197
199
|
assert optimal_m == expected_m
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@pytest.mark.parametrize(
|
|
203
|
+
"substrate_config, film_config, expected_distance_range",
|
|
204
|
+
[
|
|
205
|
+
(BULK_Si_CONVENTIONAL, BULK_Si_CONVENTIONAL, (3.8, 3.9)),
|
|
206
|
+
(BULK_Si_CONVENTIONAL, BULK_Ge_CONVENTIONAL, (3.1, 3.2)),
|
|
207
|
+
],
|
|
208
|
+
)
|
|
209
|
+
def test_calculate_interfacial_distance_from_rdf(substrate_config, film_config, expected_distance_range):
|
|
210
|
+
"""Test RDF-based interfacial distance calculation with different material types."""
|
|
211
|
+
substrate_material = Material.create(substrate_config)
|
|
212
|
+
film_material = Material.create(film_config)
|
|
213
|
+
|
|
214
|
+
distance = calculate_interfacial_distance_from_rdf(
|
|
215
|
+
substrate_material=substrate_material,
|
|
216
|
+
film_material=film_material,
|
|
217
|
+
rdf_cutoff=10.0,
|
|
218
|
+
rdf_bin_size=0.1,
|
|
219
|
+
supercell_size=(3, 3, 3),
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
assert isinstance(distance, float)
|
|
223
|
+
assert expected_distance_range[0] <= distance <= expected_distance_range[1]
|