Skip to content

Commit f392c8d

Browse files
kaueltzenjanosh
andauthored
Fix floating point imprecision error in ordering property of CollinearMagneticStructureAnalyzer (#3574)
* Modified ordering property of CollinearMagneticStructureAnalyzer to account for floating point imprecision, added test for that. * improve CollinearMagneticStructureAnalyzer.ordering doc str, drop isclose in favor abs(tot_mag) > 1e-8 * compress tests/files/magnetic.example.CuO.mcif * add comment with source DOI for mcif file * link PR that added CuO AFM test --------- Co-authored-by: kueltzen <[email protected]> Co-authored-by: Janosh Riebesell <[email protected]>
1 parent b5c7d06 commit f392c8d

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

pymatgen/analysis/magnetism/analyzer.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,15 @@ def number_of_unique_magnetic_sites(self, symprec: float = 1e-3, angle_tolerance
481481
@property
482482
def ordering(self) -> Ordering:
483483
"""Applies heuristics to return a magnetic ordering for a collinear
484-
magnetic structure. Result is not guaranteed for correctness.
484+
magnetic structure. Result is not guaranteed to be correct, just a best
485+
guess. Tolerance for minimum total magnetization to be considered
486+
ferro/ferrimagnetic is 1e-8.
485487
486488
Returns:
487-
Ordering: Enum ('FiM' is used as the abbreviation for ferrimagnetic)
489+
Ordering: Enum with values FM: ferromagnetic, FiM: ferrimagnetic,
490+
AFM: antiferromagnetic, NM: non-magnetic or Unknown. Unknown is
491+
returned if magnetic moments are not defined or structure is not collinear
492+
(in which case a warning is issued).
488493
"""
489494
if not self.is_collinear:
490495
warnings.warn("Detecting ordering in non-collinear structures not yet implemented.")
@@ -503,9 +508,9 @@ def ordering(self) -> Ordering:
503508

504509
is_potentially_ferromagnetic = np.all(magmoms >= 0) or np.all(magmoms <= 0)
505510

506-
if total_magnetization > 0 and is_potentially_ferromagnetic:
511+
if abs(total_magnetization) > 1e-8 and is_potentially_ferromagnetic:
507512
return Ordering.FM
508-
if total_magnetization > 0:
513+
if abs(total_magnetization) > 1e-8:
509514
return Ordering.FiM
510515
if max_magmom > 0:
511516
return Ordering.AFM

tests/analysis/magnetism/test_analyzer.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ def setUp(self):
3434

3535
self.NiO_expt = Structure.from_file(f"{TEST_FILES_DIR}/magnetic.example.NiO.mcif", primitive=True)
3636

37+
# CuO.mcif sourced from https://www.cryst.ehu.es/magndata/index.php?index=1.62
38+
# doi: 10.1088/0022-3719/21/15/023
39+
self.CuO_expt = Structure.from_file(f"{TEST_FILES_DIR}/magnetic.example.CuO.mcif.gz", primitive=True)
40+
3741
lattice = Lattice.cubic(4.17)
3842
species = ["Ni", "O"]
3943
coords = [[0, 0, 0], [0.5, 0.5, 0.5]]
@@ -161,28 +165,32 @@ def test_get_ferromagnetic_structure(self):
161165
assert CollinearMagneticStructureAnalyzer(s1).matches_ordering(s2_prim)
162166

163167
def test_magnetic_properties(self):
164-
msa = CollinearMagneticStructureAnalyzer(self.GdB4)
165-
assert not msa.is_collinear
168+
mag_struct_analyzer = CollinearMagneticStructureAnalyzer(self.GdB4)
169+
assert not mag_struct_analyzer.is_collinear
166170

167-
msa = CollinearMagneticStructureAnalyzer(self.Fe)
168-
assert not msa.is_magnetic
171+
mag_struct_analyzer = CollinearMagneticStructureAnalyzer(self.Fe)
172+
assert not mag_struct_analyzer.is_magnetic
169173

170174
self.Fe.add_site_property("magmom", [5])
171175

172-
msa = CollinearMagneticStructureAnalyzer(self.Fe)
173-
assert msa.is_magnetic
174-
assert msa.is_collinear
175-
assert msa.ordering == Ordering.FM
176+
mag_struct_analyzer = CollinearMagneticStructureAnalyzer(self.Fe)
177+
assert mag_struct_analyzer.is_magnetic
178+
assert mag_struct_analyzer.is_collinear
179+
assert mag_struct_analyzer.ordering == Ordering.FM
176180

177-
msa = CollinearMagneticStructureAnalyzer(
181+
mag_struct_analyzer = CollinearMagneticStructureAnalyzer(
178182
self.NiO,
179183
make_primitive=False,
180184
overwrite_magmom_mode="replace_all_if_undefined",
181185
)
182-
assert msa.number_of_magnetic_sites == 4
183-
assert msa.number_of_unique_magnetic_sites() == 1
184-
assert msa.types_of_magnetic_species == (Element.Ni,)
185-
assert msa.get_exchange_group_info() == ("Fm-3m", 225)
186+
assert mag_struct_analyzer.number_of_magnetic_sites == 4
187+
assert mag_struct_analyzer.number_of_unique_magnetic_sites() == 1
188+
assert mag_struct_analyzer.types_of_magnetic_species == (Element.Ni,)
189+
assert mag_struct_analyzer.get_exchange_group_info() == ("Fm-3m", 225)
190+
191+
# https://github.com/materialsproject/pymatgen/pull/3574
192+
mag_struct_analyzer = CollinearMagneticStructureAnalyzer(self.CuO_expt)
193+
assert mag_struct_analyzer.ordering == Ordering.AFM
186194

187195
def test_str(self):
188196
msa = CollinearMagneticStructureAnalyzer(self.NiO_AFM_001)
1.35 KB
Binary file not shown.

0 commit comments

Comments
 (0)