Skip to content

Commit 2298dc6

Browse files
Ensure structure symmetrization in OrderDisorderedStructureTransformation (#4403)
* add optional symmetrization of disordered structure on the fly * ensure symm struct when oxi states are removed
1 parent f42028a commit 2298dc6

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

src/pymatgen/transformations/standard_transformations.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from pymatgen.core.operations import SymmOp
2020
from pymatgen.core.structure import Lattice, Structure
2121
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
22+
from pymatgen.symmetry.structure import SymmetrizedStructure
2223
from pymatgen.transformations.site_transformations import PartialRemoveSitesTransformation
2324
from pymatgen.transformations.transformation_abc import AbstractTransformation
2425

@@ -454,7 +455,15 @@ class OrderDisorderedStructureTransformation(AbstractTransformation):
454455
ALGO_BEST_FIRST = 2
455456
ALGO_RANDOM = -1
456457

457-
def __init__(self, algo=ALGO_FAST, symmetrized_structures=False, no_oxi_states=False, occ_tol=0.25):
458+
def __init__(
459+
self,
460+
algo: int = ALGO_FAST,
461+
symmetrized_structures: bool = False,
462+
no_oxi_states: bool = False,
463+
occ_tol: float = 0.25,
464+
symprec: float | None = None,
465+
angle_tolerance: float | None = None,
466+
):
458467
"""
459468
Args:
460469
algo (int): Algorithm to use.
@@ -466,15 +475,23 @@ def __init__(self, algo=ALGO_FAST, symmetrized_structures=False, no_oxi_states=F
466475
occ_tol (float): Occupancy tolerance. If the total occupancy of a group is within this value
467476
of an integer, it will be rounded to that integer otherwise raise a ValueError.
468477
Defaults to 0.25.
478+
symprec : float or None (default)
479+
If a float, and symmetrized_structures is True, the linear tolerance
480+
used to symmetrize structures with SpacegroupAnalyzer.
481+
angle_tolerance : float or None (default)
482+
If a float, and symmetrized_structures is True, the angle tolerance
483+
used to symmetrize structures with SpacegroupAnalyzer.
469484
"""
470485
self.algo = algo
471486
self._all_structures: list = []
472487
self.no_oxi_states = no_oxi_states
473488
self.symmetrized_structures = symmetrized_structures
489+
self.symprec = symprec
490+
self.angle_tolerance = angle_tolerance
474491
self.occ_tol = occ_tol
475492

476493
def apply_transformation(
477-
self, structure: Structure, return_ranked_list: bool | int = False
494+
self, structure: Structure | SymmetrizedStructure, return_ranked_list: bool | int = False
478495
) -> Structure | list[Structure] | list[dict[str, Any]]:
479496
"""For this transformation, the apply_transformation method will return
480497
only the ordered structure with the lowest Ewald energy, to be
@@ -510,6 +527,11 @@ def apply_transformation(
510527
for idx, site in enumerate(structure):
511528
structure[idx] = {f"{k.symbol}0+": v for k, v in site.species.items()} # type: ignore[assignment]
512529

530+
if self.symmetrized_structures and not isinstance(structure, SymmetrizedStructure):
531+
structure = SpacegroupAnalyzer(
532+
structure, **{k: getattr(self, k) for k in ("symprec", "angle_tolerance") if getattr(self, k, None)}
533+
).get_symmetrized_structure()
534+
513535
equivalent_sites: list[list[int]] = []
514536
exemplars: list[PeriodicSite] = []
515537
# generate list of equivalent sites to order

tests/transformations/test_standard_transformations.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from pymatgen.alchemy.transmuters import StandardTransmuter
1515
from pymatgen.core import Element, PeriodicSite
1616
from pymatgen.core.lattice import Lattice
17+
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
1718
from pymatgen.symmetry.structure import SymmetrizedStructure
1819
from pymatgen.transformations.standard_transformations import (
1920
AutoOxiStateDecorationTransformation,
@@ -358,10 +359,33 @@ def test_symmetrized_structure(self):
358359
]
359360
struct = Structure(lattice, [{"Si4+": 1}, *[{"Si4+": 0.5}] * 4], coords)
360361
test_site = PeriodicSite("Si4+", coords[2], lattice)
361-
struct = SymmetrizedStructure(struct, "not_real", [0, 1, 1, 2, 2], ["a", "b", "b", "c", "c"])
362-
output = trafo.apply_transformation(struct)
362+
symm_struct = SymmetrizedStructure(struct, "not_real", [0, 1, 1, 2, 2], ["a", "b", "b", "c", "c"])
363+
output = trafo.apply_transformation(symm_struct)
363364
assert test_site in output
364365

366+
ds_coords = [
367+
[0.0, 0.0, 0.0],
368+
[0.0, 0.5, 0.5],
369+
[0.5, 0.0, 0.5],
370+
[0.5, 0.5, 0.0],
371+
[0.25, 0.25, 0.75],
372+
[0.25, 0.75, 0.25],
373+
[0.75, 0.25, 0.25],
374+
[0.75, 0.75, 0.75],
375+
]
376+
structure = Structure(
377+
Lattice.cubic(5),
378+
[*[{"Si4-": 1}] * 4, *[{"Si4+": 0.5, "Ge4+": 0.5}] * 4],
379+
ds_coords,
380+
)
381+
symm_struct = SpacegroupAnalyzer(structure).get_symmetrized_structure()
382+
383+
for no_oxi_states in (True, False):
384+
_kwargs = {"symmetrized_structures": True, "no_oxi_states": no_oxi_states}
385+
assert OrderDisorderedStructureTransformation(**_kwargs).apply_transformation(
386+
symm_struct
387+
) == OrderDisorderedStructureTransformation(**_kwargs).apply_transformation(structure)
388+
365389
def test_too_small_cell(self):
366390
trafo = OrderDisorderedStructureTransformation()
367391
coords = [[0.5, 0.5, 0.5]]

0 commit comments

Comments
 (0)