Skip to content

Commit 88921da

Browse files
tomdemeyerejanosh
andauthored
Add magmom support in get_phonopy_structure (#3555)
* Add magmom support in get_phonopy_structure * add test for struct_ph.magnetic_moments * fix TypeError: 'NoneType' object is not subscriptable prop = {key: val[idx] for key, val in site_properties.items()} * fix StructureError stating wrong DISTANCE_TOLERANCE --------- Co-authored-by: Janosh Riebesell <[email protected]>
1 parent 31981d5 commit 88921da

File tree

5 files changed

+32
-23
lines changed

5 files changed

+32
-23
lines changed

pymatgen/core/structure.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ def __init__(
927927
for idx, specie in enumerate(species):
928928
prop = None
929929
if site_properties:
930-
prop = {key: val[idx] for key, val in site_properties.items()}
930+
prop = {key: val[idx] for key, val in site_properties.items() if val is not None}
931931

932932
label = labels[idx] if labels else None
933933

@@ -943,7 +943,7 @@ def __init__(
943943
sites.append(site)
944944
self._sites: tuple[PeriodicSite, ...] = tuple(sites)
945945
if validate_proximity and not self.is_valid():
946-
raise StructureError("Structure contains sites that are less than 0.01 Angstrom apart!")
946+
raise StructureError(f"sites are less than {self.DISTANCE_TOLERANCE} Angstrom apart!")
947947
self._charge = charge
948948
self._properties = properties or {}
949949

pymatgen/io/phonopy.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ def get_pmg_structure(phonopy_structure: PhonopyAtoms) -> Structure:
3434
frac_coords = phonopy_structure.scaled_positions
3535
symbols = phonopy_structure.symbols
3636
masses = phonopy_structure.masses
37-
mms = getattr(phonopy_structure, "magnetic_moments", None) or [0] * len(symbols)
37+
magmoms = getattr(phonopy_structure, "magnetic_moments", [0] * len(symbols))
3838

3939
return Structure(
4040
lattice,
4141
symbols,
4242
frac_coords,
43-
site_properties={"phonopy_masses": masses, "magnetic_moments": mms},
43+
site_properties={"phonopy_masses": masses, "magnetic_moments": magmoms},
4444
)
4545

4646

@@ -58,6 +58,7 @@ def get_phonopy_structure(pmg_structure: Structure) -> PhonopyAtoms:
5858
symbols=symbols,
5959
cell=pmg_structure.lattice.matrix,
6060
scaled_positions=pmg_structure.frac_coords,
61+
magnetic_moments=pmg_structure.site_properties.get("magmom"),
6162
)
6263

6364

tests/core/test_structure.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ def setUp(self):
7373
assert self.struct.is_ordered
7474
assert self.struct.ntypesp == 1
7575
coords = [[0, 0, 0], [0.0, 0, 0.0000001]]
76-
with pytest.raises(StructureError, match="Structure contains sites that are less than 0.01 Angstrom apart"):
76+
with pytest.raises(
77+
StructureError, match=f"sites are less than {self.struct.DISTANCE_TOLERANCE} Angstrom apart"
78+
):
7779
IStructure(self.lattice, ["Si"] * 2, coords, validate_proximity=True)
7880
self.propertied_structure = IStructure(
7981
self.lattice, ["Si"] * 2, coords, site_properties={"magmom": [5, -5]}, properties={"test_property": "test"}
@@ -104,7 +106,7 @@ def test_get_orderings(self):
104106

105107
def test_as_dataframe(self):
106108
df = self.propertied_structure.as_dataframe()
107-
assert df.attrs["Reduced Formula"] == "Si"
109+
assert df.attrs["Reduced Formula"] == self.propertied_structure.composition.reduced_formula
108110
assert df.shape == (2, 8)
109111

110112
def test_equal(self):
@@ -130,7 +132,7 @@ def test_matches(self):
130132

131133
def test_bad_structure(self):
132134
coords = [[0, 0, 0], [0.75, 0.5, 0.75], [0.75, 0.5, 0.75]]
133-
with pytest.raises(StructureError, match="Structure contains sites that are less than 0.01 Angstrom apart"):
135+
with pytest.raises(StructureError, match=f"sites are less than {Structure.DISTANCE_TOLERANCE} Angstrom apart"):
134136
IStructure(self.lattice, ["Si"] * 3, coords, validate_proximity=True)
135137
# these shouldn't raise an error
136138
IStructure(self.lattice, ["Si"] * 2, coords[:2], validate_proximity=True)

tests/io/test_ase.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def test_get_structure():
147147
atoms = read(f"{TEST_FILES_DIR}/POSCAR_overlap")
148148
struct = AseAtomsAdaptor.get_structure(atoms)
149149
assert [s.species_string for s in struct] == atoms.get_chemical_symbols()
150-
with pytest.raises(StructureError, match="Structure contains sites that are less than 0.01 Angstrom apart"):
150+
with pytest.raises(StructureError, match=f"sites are less than {struct.DISTANCE_TOLERANCE} Angstrom apart"):
151151
struct = AseAtomsAdaptor.get_structure(atoms, validate_proximity=True)
152152

153153

tests/io/test_phonopy.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,28 @@ def test_get_complete_dos(self):
9898
@unittest.skipIf(Phonopy is None, "Phonopy not present")
9999
class TestStructureConversion(PymatgenTest):
100100
def test_structure_conversion(self):
101-
s_pmg = PymatgenTest.get_structure("LiFePO4")
102-
s_ph = get_phonopy_structure(s_pmg)
103-
s_pmg2 = get_pmg_structure(s_ph)
104-
105-
coords_ph = s_ph.get_scaled_positions()
106-
symbols_pmg = {e.symbol for e in s_pmg.composition}
107-
symbols_pmg2 = {e.symbol for e in s_pmg2.composition}
108-
109-
assert s_ph.get_cell()[1, 1] == approx(s_pmg.lattice._matrix[1, 1], abs=1e-7)
110-
assert s_pmg.lattice._matrix[1, 1] == approx(s_pmg2.lattice._matrix[1, 1], abs=1e-7)
111-
assert symbols_pmg == set(s_ph.symbols)
101+
struct_pmg = PymatgenTest.get_structure("LiFePO4")
102+
# add magmoms to site_properties
103+
struct_pmg.add_site_property("magmom", magmoms := [1] * len(struct_pmg))
104+
struct_ph = get_phonopy_structure(struct_pmg)
105+
struct_pmg_round_trip = get_pmg_structure(struct_ph)
106+
assert struct_pmg_round_trip.matches(struct_pmg)
107+
108+
coords_ph = struct_ph.get_scaled_positions()
109+
symbols_pmg = {e.symbol for e in struct_pmg.composition}
110+
symbols_pmg2 = {e.symbol for e in struct_pmg_round_trip.composition}
111+
112+
assert struct_ph.get_cell()[1, 1] == approx(struct_pmg.lattice._matrix[1, 1], abs=1e-7)
113+
assert struct_pmg.lattice._matrix[1, 1] == approx(struct_pmg_round_trip.lattice._matrix[1, 1], abs=1e-7)
114+
assert symbols_pmg == set(struct_ph.symbols)
112115
assert symbols_pmg == symbols_pmg2
113-
assert_allclose(coords_ph[3], s_pmg.frac_coords[3])
114-
assert_allclose(s_pmg.frac_coords[3], s_pmg2.frac_coords[3])
115-
assert s_ph.get_number_of_atoms() == len(s_pmg)
116-
assert len(s_pmg) == len(s_pmg2)
116+
assert_allclose(coords_ph[3], struct_pmg.frac_coords[3])
117+
assert_allclose(struct_pmg.frac_coords[3], struct_pmg_round_trip.frac_coords[3])
118+
assert struct_ph.get_number_of_atoms() == len(struct_pmg)
119+
assert len(struct_pmg) == len(struct_pmg_round_trip)
120+
121+
# https://github.com/materialsproject/pymatgen/pull/3555
122+
assert list(struct_ph.magnetic_moments) == magmoms
117123

118124

119125
@unittest.skipIf(Phonopy is None, "Phonopy not present")

0 commit comments

Comments
 (0)