materialsproject / pymatgen

Python Materials Genomics (pymatgen) is a robust materials analysis code that defines classes for structures and molecules with support for many electronic structure codes. It powers the Materials Project.
https://pymatgen.org
Other
1.51k stars 864 forks source link

refined/conventional structure retaining properties not working as expected #2905

Open SiLiKhon opened 1 year ago

SiLiKhon commented 1 year ago

When converting a primitive cell to a conventional one with keep_site_properties=True (https://github.com/materialsproject/pymatgen/pull/2349), the resulting properties are incorrect.

To Reproduce In this example I mark each site with a different label to find where the corresponding cite is in the resulting cell. (this is based on mp-35591)

import numpy as np
from pymatgen.core import Structure
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer

matrix = [[7.5866, 0.0, 0.0], [7.5866, 6.7002, 0.0], [3.7932, 4.5096, 3.1886]]
species = ["Li", "Li", "Er", "Er"] + ["S"] * 4
frac_coords = np.array([
    [0.00, 0.00, 0.00],
    [0.75, 0.50, 0.00],
    [0.25, 0.50, 0.00],
    [0.50, 0.00, 0.00],
    [0.25, 0.00, 0.50],
    [0.75, 0.00, 0.50],
    [0.50, 0.50, 0.50],
    [0.00, 0.50, 0.50],
])

structure = Structure(matrix, species, frac_coords, site_properties={"site_id" : "abcdefgh"})
structure_refined = SpacegroupAnalyzer(structure).get_refined_structure(keep_site_properties=True)
structure_conventional = SpacegroupAnalyzer(structure).get_conventional_standard_structure(keep_site_properties=True)

print(structure.site_properties["site_id"])
print(structure_refined.site_properties["site_id"])
print(structure_conventional.site_properties["site_id"])

Output:

['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c']
['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c']

Expected behavior Ideally, I'd expect the sites with different properties to be treated as different ones and therefore I expect the output structures to have all the labels from a to h. Note that the result is incorrect even if the same-element sites are treated as equivalent ones. E.g., Er got a label that belonged to Li, and S got a label from Er.

fyalcin commented 1 year ago

I recently ran into the same issue, with magnetic moments this time. After querying FeNi (mp-2213) and calling SpaceGroupAnalyzer(struct).get_conventional_standard_structure(keep_site_properties=True) on it, the magnetic moments on Ni sites are incorrect. Taking a closer look, the culprit seems to be the get_refined_structure(), more specifically how the site_properties are transferred at https://github.com/materialsproject/pymatgen/blob/e2b0801ea6bf5aa30b57d922395dadd729e8f122/pymatgen/symmetry/analyzer.py#L340

I won't attempt a PR at this moment but for the time being transferring the site properties some other way is probably safer.

This is a minimal repro with magnetic moments;

from mp_api.client import MPRester
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer

with MPRester() as mpr:
    struct = mpr.get_structure_by_material_id("mp-2213")

sga = SpacegroupAnalyzer(struct)

refined_bulk = sga.get_refined_structure(keep_site_properties=True)

where in the original structure the magnetic moments on Fe and Ni sites are 2.941 and 0.767, respectively, while in the refined structure they are both set to 2.941.