diff --git a/sumo/io/castep.py b/sumo/io/castep.py index 7e2b3d71..b297e7d5 100644 --- a/sumo/io/castep.py +++ b/sumo/io/castep.py @@ -30,6 +30,8 @@ unsupported_dosplot_args = {"elements", "lm_orbitals", "atoms"} +logger = logging.getLogger("io.castep") + class CastepCell: """Structure information and more: CASTEP seedname.cell file @@ -76,14 +78,16 @@ def structure(self): lengths_and_angles = lattice_abc[1:] else: unit = "ang" - lengths_and_angles = lattice_abc[1:] + lengths_and_angles = lattice_abc if len(lengths_and_angles) != 2: raise ValueError("lattice_abc should have two rows") lengths_and_angles = [list(map(float, row)) for row in lengths_and_angles] lengths_and_angles[0] = [ x * to_angstrom[unit] for x in lengths_and_angles[0] ] - lattice = Lattice.from_lengths_and_angles(*lengths_and_angles) + lattice = Lattice.from_parameters( + *lengths_and_angles[0], *lengths_and_angles[1] + ) else: raise ValueError("Couldn't find a lattice in cell file") @@ -95,6 +99,12 @@ def structure(self): elements, coords = zip(*elements_coords) return Structure(lattice, elements, coords, coords_are_cartesian=False) elif "positions_abs" in self.blocks: + if "lattice_abc" in self.blocks: + logger.warning( + "Positions are given in absolute coordinates and lattice " + "in angles/lengths format. Structure may not be consistent." + ) + positions_abs = self.blocks["positions_abs"].values if positions_abs[0][0].lower() in ("ang", "nm", "cm", "m", "bohr", "a0"): unit = positions_abs[0][0].lower() diff --git a/tests/data/NiO/NiO_abc.cell b/tests/data/NiO/NiO_abc.cell new file mode 100644 index 00000000..46a84eee --- /dev/null +++ b/tests/data/NiO/NiO_abc.cell @@ -0,0 +1,20 @@ +%BLOCK LATTICE_ABC +2.983077 2.98308198 5.15994087 +106.80215981 73.19772637 119.99807072 +%ENDBLOCK LATTICE_ABC + +%BLOCK POSITIONS_ABS +Ni 0.000000 0.000000 0.000000 SPIN=1 +Ni 1.491603 0.861143 2.432002 SPIN=-1 +O 0.000069 1.722313 1.215967 SPIN=0 +O 2.983138 -0.000026 3.648036 SPIN=0 +%ENDBLOCK POSITIONS_ABS + +%BLOCK SPECIES_POT +Ni C19 +O C19 +%ENDBLOCK SPECIES_POT + +KPOINTS_MP_GRID 7 7 7 +SPECTRAL_KPOINTS_MP_GRID 2 2 2 + diff --git a/tests/data/NiO/NiO_abc_units.cell b/tests/data/NiO/NiO_abc_units.cell new file mode 100644 index 00000000..d89d422d --- /dev/null +++ b/tests/data/NiO/NiO_abc_units.cell @@ -0,0 +1,22 @@ +%BLOCK LATTICE_ABC +Ang +2.983077 2.98308198 5.15994087 +106.80215981 73.19772637 119.99807072 +%ENDBLOCK LATTICE_ABC + +%BLOCK POSITIONS_ABS +Ang +Ni 0.000000 0.000000 0.000000 SPIN=1 +Ni 1.491603 0.861143 2.432002 SPIN=-1 +O 0.000069 1.722313 1.215967 SPIN=0 +O 2.983138 -0.000026 3.648036 SPIN=0 +%ENDBLOCK POSITIONS_ABS + +%BLOCK SPECIES_POT +Ni C19 +O C19 +%ENDBLOCK SPECIES_POT + +KPOINTS_MP_GRID 7 7 7 +SPECTRAL_KPOINTS_MP_GRID 2 2 2 + diff --git a/tests/tests_io/test_castep.py b/tests/tests_io/test_castep.py index d641808c..70404b4c 100644 --- a/tests/tests_io/test_castep.py +++ b/tests/tests_io/test_castep.py @@ -17,6 +17,7 @@ CastepCell, CastepPhonon, labels_from_cell, + logger, read_bands_eigenvalues, read_bands_header, read_dos, @@ -31,12 +32,18 @@ def setUp(self): self.si_cell_alt = os.path.join( ilr_files("tests"), "data", "Si", "Si2-alt.cell" ) + si_structure_file = os.path.join(ilr_files("tests"), "data", "Si", "Si8.json") + self.si_structure = Structure.from_file(si_structure_file) self.zns_band_cell = os.path.join(ilr_files("tests"), "data", "ZnS", "zns.cell") self.zns_singlepoint_cell = os.path.join( ilr_files("tests"), "data", "ZnS", "zns-sp.cell" ) - si_structure_file = os.path.join(ilr_files("tests"), "data", "Si", "Si8.json") - self.si_structure = Structure.from_file(si_structure_file) + self.nio_abc_cell = os.path.join( + ilr_files("tests"), "data", "NiO", "NiO_abc.cell" + ) + self.nio_abc_units_cell = os.path.join( + ilr_files("tests"), "data", "NiO", "NiO_abc_units.cell" + ) def test_castep_cell_null_init(self): null_cell = CastepCell() @@ -72,6 +79,23 @@ def test_castep_cell_from_singlepoint_file(self): [[0.0, 2.71, 2.71], [2.71, 0.0, 2.71], [2.71, 2.71, 0.0]], ) + def test_castep_cell_abc(self): + """Test .cell file using lattice_abc to define unit cell""" + for filename in self.nio_abc_cell, self.nio_abc_units_cell: + with self.assertLogs(logger) as log: + cc = CastepCell.from_file(filename) + structure = cc.structure + self.assertIn("Structure may not be consistent.", log.output[-1]) + + assert_array_almost_equal( + structure.lattice.matrix, + [ + [2.855724, 0.0, 0.862317], + [-1.297582, 2.54391, -0.862313], + [0.0, 0.0, 5.159941], + ], + ) + def test_castep_cell_from_structure(self): cell = CastepCell.from_structure(self.si_structure) self.assertEqual(