pymatgen icon indicating copy to clipboard operation
pymatgen copied to clipboard

Issue with symmetrization (CifWrite) in newer pymatgen version

Open deecadance opened this issue 1 year ago • 13 comments

Python version

Python 3.10.13

Pymatgen version

Version: 2023.11.12

Operating system version

Mac OSX 13.2.1

Current behavior

I try to symmetrize a POSCAR file. The symmetrization is successful but the structure produced is wrong: space group is 8 and the atoms are clearly overlapping. Using an older version of pymatgen (2023.5.31) gives the right structure instead.

Expected Behavior

I expect the structure to be correctly symmetrized (space group 12).

Minimal example

Using the zip file provided run from terminal:
python3 poscar2cif POSCAR_src_166.vasp 0.05 5

Using pymatgen 2023.5.31 gives the right cif
Using pymatgen 2023.11.12 gives the wrong cif

Relevant files to reproduce this bug

mwe.zip

deecadance avatar Jan 09 '24 13:01 deecadance

Note added: the bug persists in pymatgen version 2023.12.18.

deecadance avatar Jan 09 '24 17:01 deecadance

Hi @deecadance, can you explain why you expect to get space group 12 here? The space group of the POSCAR you attached is 8, and you're not directly symmetrizating the structure.

symprec and angprec control the tolerance with which pymatgen handles equality of distances and angles, respectively. They maybe indirectly symmetrize a structure.

I'll just note the following simpler syntax for writing CIFs than in your file:

from pymatgen.core import Structure

struct = Structure.from_file("POSCAR_src_166.vasp")
cif_writer_kwargs = {"symprec": symprec, "angle_tolerance" : angprec}
struct.to("filename.cif", **cif_writer_kwargs)

esoteric-ephemera avatar Jan 11 '24 17:01 esoteric-ephemera

can you explain why you expect to get space group 12 here?

Two reasons:

  1. Pasting the POSCAR file in a different symmetrizer (e.g. https://uspex-team.org/online_utilities/poscar2cif/#end) returns space group 12
  2. If you inspect the structure (e.g. using VESTA) before and after the symmetrization you can see that when space group 12 is return the structure correctly matches the original POSCAR. On the other hand, going through pymatgen 2023.11.12, when space group 8 is returned, the structure is just wrong (e.g. the W atoms are overlapping), see attached structures.zip, I also re-added the poscar in a VESTA-friendly format.

symprec and angprec control the tolerance with which pymatgen handles equality of distances and angles, respectively. They maybe indirectly symmetrize a structure.

Yes, they do. I don't know if that was intentional or not, but the code does work as a symmetrizer (exceptionally well in the previous version), and I have been using it for that way for a long time. Even if you don't care about my use case, cif_writer is not reading this poscar correctly, though it used to.

I'll just note the following simpler syntax for writing CIFs than in your file:

Thanks

deecadance avatar Jan 12 '24 11:01 deecadance

Hey @deecadance, sorry if my message came across as dismissive! I'm trying to understand what might have changed so we can look into it further

When I load in your POSCAR and write it to a CIF (still space group 8), I'm not getting overlapping W sites, so hopefully this is an issue of conflicting packages. You might want to try pip install --upgrade spglib, which handles PMG's symmetry determination

I'm using spglib==2.2.0 and pymatgen==2023.12.18

esoteric-ephemera avatar Jan 12 '24 18:01 esoteric-ephemera

Excuse me for interrupting. I am a maintainer of spglib.

It seems the POSCAR structure is rather distorted from C2/m. The following script shows a detected space group type depends on symprec around 1e-2 to 1e-1. If the behavior of CifWriter changed at some point, I guess a default symprec may be changed.

from importlib.metadata import version

from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
from pymatgen.io.vasp import Poscar
import spglib

print(f"pymatgen: {version('pymatgen')}")
print(f"spglib: {spglib.__version__}")

structure = Poscar.from_file('mwe/POSCAR_src_166.vasp').structure
cell = SpacegroupAnalyzer(structure)._cell

for symprec in [1e-4, 1e-2, 3e-2, 1e-1]:
    dataset = spglib.get_symmetry_dataset(cell, symprec=symprec)
    print(f"symprec={symprec}")
    print("     Space group type:", dataset['international'])
    print("     Number of atoms:", len(dataset['std_types']))

Output

pymatgen: 2023.12.18
spglib: 2.2.0
symprec=1e-08
     Space group type: Cm
     Number of atoms: 14
symprec=0.0001
     Space group type: Cm
     Number of atoms: 14
symprec=0.01
     Space group type: Cm
     Number of atoms: 14
symprec=0.03
     Space group type: C2/m
     Number of atoms: 14
symprec=0.1
     Space group type: C2/m
     Number of atoms: 14

lan496 avatar Jan 13 '24 03:01 lan496

Much appreciated @lan496! While I can't clearly see a spot in pymatgen where symprec may have been lowered recently, that seems to be a reasonable fix. When I use a larger / looser symprec > 0.02, I get a space group of 12 for the symmetrized structure. Can you check that you get the same behavior @deecadance?

esoteric-ephemera avatar Jan 16 '24 20:01 esoteric-ephemera

Hi, thanks to both for the nice replies, and sorry if I sounded salty, it was not my intention! @lan496 Thanks for joining the discussion! I tried to your script. Depending on the version of spglib/pymatgen that I'm using it runs or it doesn't. In particular: spglib 2.0.2, pymatgen 2023.5.31, numpy 1.23.5 I reproduce exactly your result spglib 2.2.0, pymatgen 2023.12.18, numpy 1.26.0 the code fails with error: spglib: ssm_get_exact_positions failed. (line 479, /private/var/folders/gb/48p5g82s29b2zzvm7yzcrwwh0000gn/T/pip-install-96qlk6rd/spglib_021622f088764b9bb72fef489c5e415e/src/refinement.c).

I guess it's not so much a matter of exactly which space group, rather than a problem of overlapping atoms. Using a smaller symprec with the two versions of the libraries I can get to some cif file with both, and in both cases it has the same space group (8), except in the newer configuration the crystal structure is wrong (see png's/cifs in new_mwe.zip).

I'm using spglib==2.2.0 and pymatgen==2023.12.18

Very interesting. I am using the same when I get the wrong structure. What is your numpy version? Could it be something silly like a transpose in the wrong place?

deecadance avatar Jan 17 '24 17:01 deecadance

Possibly related error:

from pymatgen.ext.matproj import MPRester
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer\
struct = mpr.get_structure_by_material_id("mp-886")
sa = SpacegroupAnalyzer(struct)
sstruct = sa.get_symmetrized_structure() #errors out

Produces:

    132 def get_space_group_number(self) -> int:
    133     """Get the international spacegroup number (e.g., 62) for structure.
    134 
    135     Returns:
    136         int: International spacegroup number for structure.
    137     """
--> 138     return int(self._space_group_data["number"])

TypeError: 'NoneType' object is not subscriptable

So it looks like spglib is was not able to populate _space_group_data.

jmmshn avatar Jan 30 '24 20:01 jmmshn

Just tested the code above using different managers:

pip install spglib -> gives error

conda install -c conda-forge spglib -> no error

I’m guessing this is some weird interplay between the way data is represented in the numpy parts of the spglib python wrapper and the specific compilation of the C code. ~We probably have to ping one of their developer to resolve this one.~ nvm @lan496 is already here!

jmmshn avatar Jan 30 '24 21:01 jmmshn

Hi @lan496 dear spglib developer, I recently had an issue related to this. For the same structure, I got a different number of symmetry operations after updating my pymatgen, let me reproduce the issue here

from importlib.metadata import version
from pymatgen.analysis.structure_matcher import StructureMatcher
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
from pymatgen.ext.matproj import MPRester
from pymatgen.io.vasp import Poscar
import spglib
from pymatgen.core import Structure

sm=StructureMatcher()

print(f"pymatgen: {version('pymatgen')}")
print(f"spglib: {spglib.__version__}")

mpr=MPRester()
s1=mpr.get_structure_by_material_id("mp-2133")
s2 = Poscar.from_file('./ZnO_2133/ZnO.poscar').structure ## poscar downloaded from MP website
print (f"structure_matcher={sm.fit_anonymous(s1,s2)}")

for symprec in [1e-5,1e-1]:
    for s in [s1,s2]:
        spg=SpacegroupAnalyzer(structure=s,symprec=symprec)
        print(f"symprec={symprec}")
        print("Space group type:", spg.get_space_group_symbol())
        print("Number of operations:", len(spg.get_space_group_operations()))

The output is

pymatgen: 2023.8.10
spglib: 2.3.0
structure_matcher = True
symprec=1e-05
Space group type: P6_3mc
Number of operations: 24
symprec=1e-05
Space group type: P6_3mc
Number of operations: 12
symprec=0.1
Space group type: P6_3mc
Number of operations: 24
symprec=0.1
Space group type: P6_3mc
Number of operations: 12

Two things that I want to confirm are:

  1. Anyone knows whether mpr.get_structure_by_material_id() switched the defaultconventional_unit_cell setting (from True to False)?
  2. For the same structure (passed structure_matcher), the symmetry operation numbers might be different (depending on whether it is a conventional unit cell or not)? Here we exclude the reasoning from symprec setting by tuning it from 1e-5 to 1e-1, plus the space group type remains the same.

ZnO_2133.zip

Zhuoying avatar Jan 30 '24 23:01 Zhuoying

Just locate the bug from spglib update (from 1.16.5 to 2.3.0). I have submitted a new issue there https://github.com/spglib/spglib/issues/413

Zhuoying avatar Jan 31 '24 00:01 Zhuoying

@esoteric-ephemera For the first case of this issue, the distinction between Cm and C2/m would be challenging for such a large symprec. It may be helpful to check atoms are not overlapped in pymatgen's cif parser side.

lan496 avatar Feb 01 '24 10:02 lan496

@jmmshn I could not reproduce your result with spglib==2.3.1 and pymatgen==2024.1.27. If your error still presents in the latest, please open an issue at spglib. In that case, please use a raw input for spglib by SpacegroupAnalyzer(structure)._cell.

lan496 avatar Feb 01 '24 10:02 lan496