Skip to content

Commit 7198b86

Browse files
Hui Zhenghuizheng7174pre-commit-ci[bot]
authored
Move occ_tol to init in OrderDisorderedStructureTransformation (#4274)
* move occ_tol to initialization parameters * add tests * fix: ruff formatting issues * pre-commit auto-fixes --------- Co-authored-by: Hui Zheng <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 7cc19c3 commit 7198b86

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

src/pymatgen/transformations/standard_transformations.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ class OrderDisorderedStructureTransformation(AbstractTransformation):
454454
ALGO_BEST_FIRST = 2
455455
ALGO_RANDOM = -1
456456

457-
def __init__(self, algo=ALGO_FAST, symmetrized_structures=False, no_oxi_states=False):
457+
def __init__(self, algo=ALGO_FAST, symmetrized_structures=False, no_oxi_states=False, occ_tol=0.25):
458458
"""
459459
Args:
460460
algo (int): Algorithm to use.
@@ -463,15 +463,17 @@ def __init__(self, algo=ALGO_FAST, symmetrized_structures=False, no_oxi_states=F
463463
should be used for the grouping of sites.
464464
no_oxi_states (bool): Whether to remove oxidation states prior to
465465
ordering.
466+
occ_tol (float): Occupancy tolerance. If the total occupancy of a group is within this value
467+
of an integer, it will be rounded to that integer otherwise raise a ValueError.
468+
Defaults to 0.25.
466469
"""
467470
self.algo = algo
468471
self._all_structures: list = []
469472
self.no_oxi_states = no_oxi_states
470473
self.symmetrized_structures = symmetrized_structures
474+
self.occ_tol = occ_tol
471475

472-
def apply_transformation(
473-
self, structure: Structure, return_ranked_list: bool | int = False, occ_tol=0.25
474-
) -> Structure:
476+
def apply_transformation(self, structure: Structure, return_ranked_list: bool | int = False) -> Structure:
475477
"""For this transformation, the apply_transformation method will return
476478
only the ordered structure with the lowest Ewald energy, to be
477479
consistent with the method signature of the other transformations.
@@ -482,9 +484,6 @@ def apply_transformation(
482484
structure: Oxidation state decorated disordered structure to order
483485
return_ranked_list (bool | int, optional): If return_ranked_list is int, that number of structures
484486
is returned. If False, only the single lowest energy structure is returned. Defaults to False.
485-
occ_tol (float): Occupancy tolerance. If the total occupancy of a group is within this value
486-
of an integer, it will be rounded to that integer otherwise raise a ValueError.
487-
Defaults to 0.25.
488487
489488
Returns:
490489
Depending on returned_ranked list, either a transformed structure
@@ -554,7 +553,7 @@ def apply_transformation(
554553
)
555554
# round total occupancy to possible values
556555
for key, val in total_occupancy.items():
557-
if abs(val - round(val)) > occ_tol:
556+
if abs(val - round(val)) > self.occ_tol:
558557
raise ValueError("Occupancy fractions not consistent with size of unit cell")
559558
total_occupancy[key] = round(val)
560559
# start with an ordered structure

tests/transformations/test_standard_transformations.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from numpy.testing import assert_allclose
1313
from pytest import approx
1414

15+
from pymatgen.alchemy.transmuters import StandardTransmuter
1516
from pymatgen.core import Element, PeriodicSite
1617
from pymatgen.core.lattice import Lattice
1718
from pymatgen.symmetry.structure import SymmetrizedStructure
@@ -427,6 +428,38 @@ def test_random_sample(self):
427428
output = trafo.apply_transformation(struct * [2, 2, 2], return_ranked_list=False)
428429
assert output.composition.reduced_formula == struct.composition.reduced_formula
429430

431+
def test_occ_tol_with_supercell(self):
432+
"""Test occ_tol parameter behavior with supercell structures."""
433+
# Create a disordered structure
434+
coords = [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]
435+
lattice = Lattice(
436+
[
437+
[2.9823991724941643, 0.0, 1.8261928001873466e-16],
438+
[4.796063659664723e-16, 2.9823991724941643, 1.8261928001873466e-16],
439+
[0.0, 0.0, 2.9823991724941643],
440+
]
441+
)
442+
struct = Structure(lattice, [{"V": 0.75, "Ti": 0.25}, {"V": 0.75, "Ti": 0.25}], coords)
443+
444+
# Create a 5x5x5 supercell structure
445+
supercell = struct * [5, 5, 5]
446+
447+
# Test 1: Default occ_tol (0.25) should raise error
448+
ts_strict = OrderDisorderedStructureTransformation(algo=-1, no_oxi_states=True, occ_tol=0.25)
449+
with pytest.raises(ValueError, match="Occupancy fractions not consistent with size of unit cell"):
450+
StandardTransmuter.from_structures([supercell], transformations=[ts_strict], extend_collection=3)
451+
452+
# Test 2: Relaxed occ_tol (0.5) should work
453+
ts_relaxed = OrderDisorderedStructureTransformation(algo=-1, no_oxi_states=True, occ_tol=0.5)
454+
transmuter = StandardTransmuter.from_structures([supercell], transformations=[ts_relaxed], extend_collection=3)
455+
456+
# Verify the transformation worked and produced expected composition
457+
transformed_structs = transmuter.transformed_structures
458+
assert len(transformed_structs) == 3
459+
# Check composition matches expected Ti31V94
460+
composition = transformed_structs[0].final_structure.composition
461+
assert composition.reduced_formula == "Ti31V94"
462+
430463

431464
class TestPrimitiveCellTransformation:
432465
def test_apply_transformation(self):

0 commit comments

Comments
 (0)