diff --git a/pyiron_atomistics/atomistics/structure/atoms.py b/pyiron_atomistics/atomistics/structure/atoms.py index 142635f0c..c8d55adfc 100644 --- a/pyiron_atomistics/atomistics/structure/atoms.py +++ b/pyiron_atomistics/atomistics/structure/atoms.py @@ -1948,6 +1948,25 @@ def get_voronoi_volume(self): return self._analyse.pyscal_voronoi_volume() get_voronoi_volume.__doc__ = Analyse.pyscal_voronoi_volume.__doc__ + def is_skewed(self, tolerance=1.0e-8): + """ + Check whether the simulation box is skewed/sheared. The algorithm compares the box volume + and the product of the box length in each direction. If these numbers do not match, the box + is considered to be skewed and the function returns True + + Args: + tolerance (float): Relative tolerance above which the structure is considered as skewed + + Returns: + (bool): Whether the box is skewed or not. + """ + volume = self.get_volume() + prod = np.linalg.norm(self.cell, axis=-1).prod() + if volume > 0: + if abs(volume-prod)/volume < tolerance: + return False + return True + def find_mic(self, v, vectors=True): """ Find vectors following minimum image convention (mic). In principle this diff --git a/pyiron_atomistics/lammps/interactive.py b/pyiron_atomistics/lammps/interactive.py index 9a236320f..617b558bb 100644 --- a/pyiron_atomistics/lammps/interactive.py +++ b/pyiron_atomistics/lammps/interactive.py @@ -108,33 +108,20 @@ def interactive_cells_setter(self, cell): "Warning: setting upper trangular matrix might slow down the calculation" ) - is_skewed = self._prism.is_skewed() - is_scaled = self.structure._is_scaled - if is_scaled: - warnings.warn('set_relative() is deprecated as of 2020-02-26. It is not guaranteed from pyiron_atomistics vers. 0.3') + is_skewed = self._structure_current.is_skewed(tolerance=1.0e-8) + was_skewed = self._structure_previous.is_skewed(tolerance=1.0e-8) - if is_skewed and is_scaled: - self._interactive_lib_command( - "change_box all triclinic" - ) + if is_skewed: + if not was_skewed: + self._interactive_lib_command( + "change_box all triclinic" + ) self._interactive_lib_command( "change_box all x final 0 %f y final 0 %f z final 0 %f \ xy final %f xz final %f yz final %f remap units box" % (lx, ly, lz, xy, xz, yz) ) - elif is_skewed and not is_scaled: - self._interactive_lib_command( - "change_box all triclinic" - ) - self._interactive_lib_command( - "change_box all x final 0 %f y final 0 %f z final 0 %f \ - xy final %f xz final %f yz final %f units box" - % (lx, ly, lz, xy, xz, yz) - ) - elif not is_skewed and is_scaled: - self._interactive_lib_command( - "change_box all triclinic" - ) + elif was_skewed: self._interactive_lib_command( "change_box all x final 0 %f y final 0 %f z final 0 %f \ xy final %f xz final %f yz final %f remap units box" @@ -143,17 +130,10 @@ def interactive_cells_setter(self, cell): self._interactive_lib_command( "change_box all ortho" ) - else: # is neither skewed nor scaled - self._interactive_lib_command( - "change_box all triclinic" - ) - self._interactive_lib_command( - "change_box all x final 0 %f y final 0 %f z final 0 %f \ - xy final %f xz final %f yz final %f units box" - % (lx, ly, lz, 0.0, 0.0, 0.0) - ) + else: self._interactive_lib_command( - "change_box all ortho" + "change_box all x final 0 %f y final 0 %f z final 0 %f remap units box" + % (lx, ly, lz) ) def interactive_volume_getter(self): diff --git a/tests/atomistics/structure/test_atoms.py b/tests/atomistics/structure/test_atoms.py index 6ff8b4a81..334f08ec8 100644 --- a/tests/atomistics/structure/test_atoms.py +++ b/tests/atomistics/structure/test_atoms.py @@ -1607,6 +1607,20 @@ def test_get_wrapped_coordinates(self): np.linalg.norm(position-structure.cell*0.1), 0 ) + def test_is_skewed(self): + structure = CrystalStructure("Fe", bravais_basis="bcc", lattice_constant=4.2, pbc=True) + self.assertFalse( + structure.is_skewed(), "is_skewed() returned True, while structure is not skewed" + ) + structure.cell[0,0] += 0.01 + self.assertFalse( + structure.is_skewed(), "is_skewed() returned True, while structure is not skewed" + ) + structure.cell[1,0] += 0.01 + self.assertTrue( + structure.is_skewed(), "is_skewed() returned False, while structure is skewed" + ) + @staticmethod def test_set_dihedral(): structure = ase_to_pyiron(molecule('H2COH')) diff --git a/tests/lammps/test_interactive.py b/tests/lammps/test_interactive.py index b7afb0c00..6af5e300a 100644 --- a/tests/lammps/test_interactive.py +++ b/tests/lammps/test_interactive.py @@ -63,19 +63,30 @@ def tearDownClass(cls): project.remove(enable=True) def test_interactive_cells_setter(self): - self.job.interactive_cells_setter(np.eye(3)) + atoms = Atoms("Fe8", positions=np.zeros((8, 3)), cell=np.eye(3), pbc=True) + self.job._structure_previous = atoms.copy() + self.job._structure_current = atoms.copy() + self.job.interactive_cells_setter(self.job._structure_current.cell) self.assertEqual( - self.job._interactive_library._command[-3], - "change_box all triclinic", - ) - self.assertEqual( - self.job._interactive_library._command[-2], - "change_box all x final 0 1.000000 y final 0 1.000000 z final 0 1.000000 xy final 0.000000 xz final 0.000000 yz final 0.000000 units box", + self.job._interactive_library._command[-1], + "change_box all x final 0 1.000000 y final 0 1.000000 z final 0 1.000000 remap units box", ) + self.job._structure_previous = atoms.copy() + self.job._structure_current = atoms.copy() + self.job._structure_previous.cell[1,0] += 0.01 + self.job.interactive_cells_setter(self.job._structure_current.cell) self.assertEqual( self.job._interactive_library._command[-1], "change_box all ortho", ) + self.job._structure_previous = atoms.copy() + self.job._structure_current = atoms.copy() + self.job._structure_current.cell[1,0] += 0.01 + self.job.interactive_cells_setter(self.job._structure_current.cell) + self.assertEqual( + self.job._interactive_library._command[-2], + "change_box all triclinic", + ) def test_interactive_positions_setter(self): self.job.interactive_positions_setter(np.arange(6).reshape(2, 3))