Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/pymatgen/analysis/interfaces/coherent_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(
film_miller: tuple[int, int, int],
substrate_miller: tuple[int, int, int],
zslgen: ZSLGenerator | None = None,
termination_ftol: float = 0.25,
termination_ftol: float | tuple[float, float] = 0.25,
label_index: bool = False, # necessary to add index to termination
filter_out_sym_slabs: bool = True,
):
Expand All @@ -43,7 +43,7 @@ def __init__(
film_miller (tuple[int, int, int]): miller index for the film layer
substrate_miller (tuple[int, int, int]): miller index for the substrate layer
zslgen (ZSLGenerator | None): BiDirectionalZSL if you want custom lattice matching tolerances for coherency.
termination_ftol (float): tolerance to distinguish different terminating atomic planes.
termination_ftol (float): tolerances (film, substrate) to distinguish different terminating atomic planes.
Copy link
Contributor

@DanielYang59 DanielYang59 Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very familiar with the use case of CoherentInterfaceBuilder but I assume it's reasonable to allow more fine-grained control over the film and substrate. In this case I guess: either you allow termination_ftol to be float | tuple[float, float] but you should update the docstring accordingly (currently it's still float), or you could deprecate this arg with two args like film/substrate_termination_tol.

label_index (bool): If True add an extra index at the beginning of the termination label.
filter_out_sym_slabs (bool): If True filter out identical slabs with different terminations.
This might need to be set as False to find more non-identical terminations because slab
Expand Down Expand Up @@ -133,24 +133,29 @@ def _find_terminations(self):
reorient_lattice=False, # This is necessary to not screw up the lattice
)

film_slabs = film_sg.get_slabs(ftol=self.termination_ftol, filter_out_sym_slabs=self.filter_out_sym_slabs)
sub_slabs = sub_sg.get_slabs(ftol=self.termination_ftol, filter_out_sym_slabs=self.filter_out_sym_slabs)
if type(self.termination_ftol) is not tuple:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use isinstance here as type() is would only allow exact tuple but not subclasses

self.termination_ftol = (self.termination_ftol, self.termination_ftol)
Copy link
Contributor

@DanielYang59 DanielYang59 Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's more readable to unpack within __init__ instead of accessing with index, something like:

if isinstance(termination_ftol, tuple):
    self.film_termination_ftol, self.substrate_termination_ftol = termination_ftol
else:
    self.film_termination_ftol = self.substrate_termination_ftol = termination_ftol

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Daniel, many thanks for these helpful suggestions. I have commited these changes.


film_slabs = film_sg.get_slabs(ftol=self.termination_ftol[0], filter_out_sym_slabs=self.filter_out_sym_slabs)
sub_slabs = sub_sg.get_slabs(ftol=self.termination_ftol[1], filter_out_sym_slabs=self.filter_out_sym_slabs)
film_shifts = [slab.shift for slab in film_slabs]

if self.label_index:
film_terminations = [
label_termination(slab, self.termination_ftol, t_idx) for t_idx, slab in enumerate(film_slabs, start=1)
label_termination(slab, self.termination_ftol[0], t_idx)
for t_idx, slab in enumerate(film_slabs, start=1)
]
else:
film_terminations = [label_termination(slab, self.termination_ftol) for slab in film_slabs]
film_terminations = [label_termination(slab, self.termination_ftol[0]) for slab in film_slabs]

sub_shifts = [slab.shift for slab in sub_slabs]
if self.label_index:
sub_terminations = [
label_termination(slab, self.termination_ftol, t_idx) for t_idx, slab in enumerate(sub_slabs, start=1)
label_termination(slab, self.termination_ftol[1], t_idx)
for t_idx, slab in enumerate(sub_slabs, start=1)
]
else:
sub_terminations = [label_termination(slab, self.termination_ftol) for slab in sub_slabs]
sub_terminations = [label_termination(slab, self.termination_ftol[1]) for slab in sub_slabs]

self._terminations = {
(film_label, sub_label): (film_shift, sub_shift)
Expand Down
21 changes: 18 additions & 3 deletions tests/analysis/interfaces/test_coherent_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def setup_method(self):
def test_termination_searching(self):
sub_analyzer = SubstrateAnalyzer()
matches = list(sub_analyzer.calculate(substrate=self.substrate, film=self.film))
cib = CoherentInterfaceBuilder(
cib1 = CoherentInterfaceBuilder(
film_structure=self.film,
substrate_structure=self.substrate,
film_miller=matches[0].film_miller,
Expand All @@ -69,9 +69,24 @@ def test_termination_searching(self):
label_index=True,
filter_out_sym_slabs=False,
)
assert cib.terminations == [
cib2 = CoherentInterfaceBuilder(
film_structure=self.film,
substrate_structure=self.substrate,
film_miller=matches[0].film_miller,
substrate_miller=matches[0].substrate_miller,
zslgen=sub_analyzer,
termination_ftol=(2, 0.1),
label_index=True,
filter_out_sym_slabs=False,
)
assert cib1.terminations == [
("1_Ge_P4/mmm_1", "1_Si_P4/mmm_1"),
("1_Ge_P4/mmm_1", "2_Si_P4/mmm_1"),
("2_Ge_P4/mmm_1", "1_Si_P4/mmm_1"),
("2_Ge_P4/mmm_1", "2_Si_P4/mmm_1"),
], "termination results wrong"
], "cib1 termination results wrong"

assert cib2.terminations == [
("1_Ge_C2/m_2", "1_Si_P4/mmm_1"),
("1_Ge_C2/m_2", "2_Si_P4/mmm_1"),
], "cib2 termination results wrong"
Loading