From 708a64304455b09e909231014413a151d4b144b0 Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Wed, 14 Feb 2024 18:01:32 +0100 Subject: [PATCH 1/5] Recreate structure fresh during get_primitive_cell This avoids a problem, when you pass standardize=True and the resulting cell would be larger than the original. --- structuretoolkit/analyse/symmetry.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/structuretoolkit/analyse/symmetry.py b/structuretoolkit/analyse/symmetry.py index 2da660fee..ca2944af6 100644 --- a/structuretoolkit/analyse/symmetry.py +++ b/structuretoolkit/analyse/symmetry.py @@ -345,27 +345,36 @@ def get_primitive_cell( >>> len(symmetry.get_primitive_cell()) == len(basis) True """ + if not all(self._structure.pbc): + raise ValueError("Can only symmetrize periodic structures.") ret = spglib.standardize_cell( self._get_spglib_cell(use_elements=use_elements, use_magmoms=use_magmoms), to_primitive=not standardize, ) if ret is None: raise SymmetryError(spglib.spglib.spglib_error.message) - cell, positions, indices = ret - positions = (cell.T @ positions.T).T - new_structure = self._structure.copy() - new_structure.cell = cell - new_structure = new_structure[: len(indices)] + cell, scaled_positions, indices = ret indices_dict = { v: k for k, v in structuretoolkit.common.helper.get_species_indices_dict( structure=self._structure ).items() } - new_structure.symbols = [indices_dict[i] for i in indices] - new_structure.positions = positions + symbols = [indices_dict[i] for i in indices] + arrays = {k: self._structure.arrays[k] for k in self._structure.arrays + if k not in ('numbers', 'positions')} + new_structure = type(self._structure)( + symbols=symbols, + scaled_positions=scaled_positions, + cell=cell, + pbc=[True, True, True] + ) + for k, a in arrays.items(): + new_structure.arrays[k] = a + return new_structure + def get_ir_reciprocal_mesh( self, mesh, From 354d825f2dacc5dea978783d180ffd293811a10f Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Wed, 14 Feb 2024 17:02:20 +0000 Subject: [PATCH 2/5] Format black --- structuretoolkit/analyse/symmetry.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/structuretoolkit/analyse/symmetry.py b/structuretoolkit/analyse/symmetry.py index ca2944af6..2c6149d05 100644 --- a/structuretoolkit/analyse/symmetry.py +++ b/structuretoolkit/analyse/symmetry.py @@ -361,20 +361,22 @@ def get_primitive_cell( ).items() } symbols = [indices_dict[i] for i in indices] - arrays = {k: self._structure.arrays[k] for k in self._structure.arrays - if k not in ('numbers', 'positions')} + arrays = { + k: self._structure.arrays[k] + for k in self._structure.arrays + if k not in ("numbers", "positions") + } new_structure = type(self._structure)( symbols=symbols, scaled_positions=scaled_positions, cell=cell, - pbc=[True, True, True] + pbc=[True, True, True], ) for k, a in arrays.items(): new_structure.arrays[k] = a return new_structure - def get_ir_reciprocal_mesh( self, mesh, From 4942144922b8affdf4fee781b56f351ca66a9c46 Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Wed, 14 Feb 2024 18:23:39 +0100 Subject: [PATCH 3/5] Adapt tests --- tests/test_symmetry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_symmetry.py b/tests/test_symmetry.py index 46c11b520..bc4906018 100644 --- a/tests/test_symmetry.py +++ b/tests/test_symmetry.py @@ -143,7 +143,7 @@ def test_get_ir_reciprocal_mesh(self): def test_get_primitive_cell(self): cell = 2.2 * np.identity(3) - basis = Atoms("AlFe", scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)], cell=cell) + basis = Atoms("AlFe", scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)], cell=cell, pbc=True) structure = basis.repeat([2, 2, 2]) sym = stk.analyse.get_symmetry(structure=structure) self.assertEqual(len(basis), len(sym.get_primitive_cell(standardize=True))) @@ -169,7 +169,7 @@ def test_get_primitive_cell_hex(self): [0.77, 1.57, 5.74], ] cell = [[2.519, 1.454, 4.590], [-2.519, 1.454, 4.590], [0.0, -2.909, 4.590]] - structure = Atoms(symbols=elements, positions=positions, cell=cell) + structure = Atoms(symbols=elements, positions=positions, cell=cell, pbc=True) structure_repeat = structure.repeat([2, 2, 2]) sym = stk.analyse.get_symmetry(structure=structure_repeat) structure_prim_base = sym.get_primitive_cell() From bfc42f0cf5b69d1084b6ae1c5fa8f3d424ce8a62 Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Wed, 14 Feb 2024 19:33:30 +0100 Subject: [PATCH 4/5] Remove array copies and add warning The trouble is that when spglib returns the symmetrized cell, it may permute, add or remove atoms so that we cannot tell anymore which values from the original arrays we would need to copy or remove. --- structuretoolkit/analyse/symmetry.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/structuretoolkit/analyse/symmetry.py b/structuretoolkit/analyse/symmetry.py index 2c6149d05..7f1dcbc57 100644 --- a/structuretoolkit/analyse/symmetry.py +++ b/structuretoolkit/analyse/symmetry.py @@ -3,6 +3,7 @@ # Distributed under the terms of "New BSD License", see the LICENSE file. import ast +from logging import warning import numpy as np import spglib @@ -344,6 +345,10 @@ def get_primitive_cell( >>> symmetry = Symmetry(structure) >>> len(symmetry.get_primitive_cell()) == len(basis) True + + .. warning:: + Custom arrays defined in the base structures + :attr:`ase.atoms.Atoms.arrays` are not copied to the new structure! """ if not all(self._structure.pbc): raise ValueError("Can only symmetrize periodic structures.") @@ -372,8 +377,9 @@ def get_primitive_cell( cell=cell, pbc=[True, True, True], ) - for k, a in arrays.items(): - new_structure.arrays[k] = a + keys = set(arrays) - {"numbers", "positions"} + if len(keys) > 0: + warning(f"Custom arrays {keys} do not carry over to new structure!") return new_structure From 8f5fbab6e42aad6f6a6806ce61d1ee82563652b3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 06:35:03 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_symmetry.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_symmetry.py b/tests/test_symmetry.py index 0d689552c..c7c30eda4 100644 --- a/tests/test_symmetry.py +++ b/tests/test_symmetry.py @@ -173,7 +173,9 @@ def test_get_ir_reciprocal_mesh(self): def test_get_primitive_cell(self): cell = 2.2 * np.identity(3) - basis = Atoms("AlFe", scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)], cell=cell, pbc=True) + basis = Atoms( + "AlFe", scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)], cell=cell, pbc=True + ) structure = basis.repeat([2, 2, 2]) sym = stk.analyse.get_symmetry(structure=structure) self.assertEqual(len(basis), len(sym.get_primitive_cell(standardize=True)))