MaterSim / PyXtal

A code to generate atomic structure with symmetry
MIT License
257 stars 68 forks source link

Subgroup function may not work well for molecular crystals #142

Closed qzhu2017 closed 2 years ago

qzhu2017 commented 3 years ago

For example, an aspirin crystal with space group P21/c should be splitted to Pc, P21, P-1,

Currently, splittings to Pc and P-1 need to be double checked.

qzhu2017 commented 3 years ago

@kevinparrish1 There is a bug in wyckoff_splitter.

Wycokff split from 14 to 7
4e -> 2a
x, y, z                        -> x, y-1/4, z                    -> x, y, z                       
x, -y-1/2, z+1/2               -> x, -y-3/4, z+1/2               -> x, -y, z+1/2                  
2a
-x, y-1/2, -z+1/2              -> -x, y-3/4, -z+1/2              -> x, y, z                       
-x, -y, -z                     -> -x, -y-1/4, -z                 -> x, -y, z+1/2                  
image

In the last row, the 1st column of -x, -y, -z should correspond to x,y,z in the 3rd column.

qzhu2017 commented 3 years ago
qzhu2017 commented 3 years ago

@kevinparrish1 This needs to be fixed asap after you are done with Phys493 presentation.

qzhu2017 commented 3 years ago

@kevinparrish1

import numpy as np
from pkg_resources import resource_filename
from pymatgen.core import Structure
import pymatgen.analysis.structure_matcher as sm
from pyxtal import pyxtal

cif_path = resource_filename("pyxtal", "database/cifs/")

for name in ["aspirin", "resorcinol", "coumarin", "HAHCOI", "WEXBOS", "MERQIM", "LAGNAL", "YICMOP", "LUFHAW", "JAPWIH", "AXOSOW01", "PAHYON01"]:
    cif = cif_path + name + ".cif"
    pmg_s1 = Structure.from_file(cif)
    struc = pyxtal(molecular=True)
    struc.from_seed(seed=cif, molecules=[name])
    pmg_struc = struc.to_pymatgen()
    print(name, sm.StructureMatcher().fit(pmg_struc, pmg_s1))

    Cs = struc.subgroup(eps=0, max_cell=1)
    for C in Cs:
        pmg_s2 = C.to_pymatgen()
        print(struc.group.number, C.group.number, sm.StructureMatcher().fit(pmg_struc, pmg_s2))
(base) qiangzhu@Qiangs-MacBook-Pro-2 PyXtal (master) $ python s.py 
aspirin True
14 2 True
14 4 True
14 7 True
resorcinol True
19 4 False
19 4 True
19 4 False
coumarin True
29 4 False
29 7 False
29 7 False
HAHCOI True
4 1 True
WEXBOS True
14 4 True
14 7 True
MERQIM True
14 4 True
14 7 True
LAGNAL True
18 4 True
18 4 True
YICMOP True
14 7 True
LUFHAW True
14 7 True
JAPWIH True
31 4 True
AXOSOW01 True
61 14 False
61 14 True
61 14 False
61 19 True
61 29 False
61 29 False
61 29 False
PAHYON01 True
15 5 True
15 9 True

Please use the above script to test your code.

qzhu2017 commented 3 years ago

Now it is not working because sometimes the cell transformation will swap between a, b, c axes.

qzhu2017 commented 3 years ago

after 3698d11, the code should work when the transformation matrix is [a, b, c] or some permutations. However, it won't work for cases like

qzhu2017 commented 3 years ago

Remaining issues

qzhu2017 commented 3 years ago

Needs to check more cases.

qzhu2017 commented 3 years ago

I2/c -> C2/c

qzhu2017 commented 2 years ago

Not work for rhombehedral/cubic

qzhu2017 commented 2 years ago

For organic crystals, we want to turn the representation of G with special sites to H with general sites. If G-H transition needs to take multiple steps, there should be a function to derive the relation path.

qzhu2017 commented 2 years ago

@kevinparrish1 Can you help me to add a function within the group class to do the following?

from pyxtal.symmetry import Group

def path_to_general_wp(group, index):
    """
    Find the path to transform the special wp into general site

    Args:
        group: Group object 
        index: the index of starting wp

    Return:
        a list of (g_types, subgroup_id, spg_number)
    """

    pass

res = path_to_general_wp(g, index=1)
#some reference results
#path_to_general_wp(64, index=1) => [('k', 6, 61), ('t', *, *)]
#path_to_general_wp(113, index=1) => [('t', 0, 18), ('t', *, *)]
#path_to_general_wp(217, index=1) => [('t', 0, 121), ('t', 0, 23), ('t', 0, 5), ('t', *, *)]

Let me know if you need any clarification.

kevinparrish1 commented 2 years ago

I will give it a try as soon as I can. Today is not good for me at all, but I will be able to work on it tonight and tomorrow.

On Sun, Jan 23, 2022 at 6:17 PM Qiang Zhu @.***> wrote:

@kevinparrish1 https://github.com/kevinparrish1 Can you help me to add a function within the group class to do the following?

from pyxtal.symmetry import Group def path_to_general_wp(group, index): """ Find the path to transform the special wp into general site Args: group: Group object index: the index of starting wp Return: a list of (g_types, subgroup_id, spg_number) """

pass

res = path_to_general_wp(g, index=1)#some reference results#path_to_general_wp(64, index=1) => [('k', 6, 61)]#path_to_general_wp(113, index=1) => [('t', 0, 18)]#path_to_general_wp(217, index=1) => [('t', 0, 121), ('t', 0, 23), ('t', 0, 5)]

Let me know if you need any clarification.

— Reply to this email directly, view it on GitHub https://github.com/qzhu2017/PyXtal/issues/142#issuecomment-1019651297, or unsubscribe https://github.com/notifications/unsubscribe-auth/AE45ASACQ525VNDMOFLKCDTUXSZEPANCNFSM424NAYNA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you were mentioned.Message ID: @.***>

kevinparrish1 commented 2 years ago

I believe that I understand what the goal is. The only thing that I am not too sure about is how many results you want returned.

For example, in your first reference results, you have the space group 64 with wyckoff position index=1 needing to transition to group 61. By examining Bilbao, I can see that the 8f position of group 64 (the first special wyckoff position) turns into position 8c of the 61 group. 8c is the general position of group 61, so this path is complete here.

However, I notice that for the 64->60 transition, the 8f position of group 64 turns into position 8d of the 60 group, where 8d is also a general position, so this should also be a valid solution of path_to_general_wp.

So would you like this function to find just one valid solution or all valid solutions? If you would like the function to find the paths to all the possible groups h such that the special position of g has turned into the general position of h, I believe it will be a much longer list.

qzhu2017 commented 2 years ago

@kevinparrish1 Let's return all valid solutions. After that, we can also add an option like first=True. When First is True, the search will be terminated as long as one valid path is found.

kevinparrish1 commented 2 years ago

I've added the function to the Group class. For now, it just does one step search, but I will add more layers as options.

>>> from pyxtal.symmetry import Group
>>> g=Group(64)
>>> paths=g.path_to_general_wp(index=1)
>>> for p in paths:
...     print(p)
... 
[('t', 1, 14, ['4e'])]
[('t', 2, 15, ['8f'])]
[('t', 3, 20, ['8c'])]
[('t', 6, 41, ['8b'])]
[('k', 1, 54, ['8f'])]
[('k', 3, 56, ['8e'])]
[('k', 5, 60, ['8d'])]
[('k', 6, 61, ['8c'])]
>>> g=Group(113)
>>> paths=g.path_to_general_wp(index=1)
>>> for p in paths:
...     print(p)
... 
[('t', 0, 18, ['4c'])]
[('t', 2, 81, ['4h'])]
[('k', 26, 114, ['8e'])]
[('k', 27, 114, ['8e'])]
>>> g=Group(217)
>>> paths=g.path_to_general_wp(index=1)
>>> for p in paths:
...     print(p)
... 
[('t', 7, 197, ['24f'])]
[('k', 1, 218, ['24i'])]
kevinparrish1 commented 2 years ago

My commit seems to have made an error. I'm trying to stop committing through atom and start using the command line, but it seems I did something wrong. The code was working OK for me before I pushed it. I'm not sure what happened.

qzhu2017 commented 2 years ago

@kevinparrish1 It should be due to some other issues. It is possible that you need to go though multiple steps to get the general wp. Can you enable the following example?

>>> from pyxtal.symmetry import Group
>>> g=Group(217)
>>> paths=g.path_to_general_wp(index=7)
kevinparrish1 commented 2 years ago

Yes, I just need to generalize it to n steps. I can finish the program soon.

On Wed, Jan 26, 2022 at 5:26 AM Qiang Zhu @.***> wrote:

@kevinparrish1 https://github.com/kevinparrish1 It should be due to some other issues. It is possible that you need to go though multiple steps to get the general wp. Can you enable the following example?

from pyxtal.symmetry import Group>>> g=Group(217)>>> paths=g.path_to_general_wp(index=7)

— Reply to this email directly, view it on GitHub https://github.com/qzhu2017/PyXtal/issues/142#issuecomment-1022195193, or unsubscribe https://github.com/notifications/unsubscribe-auth/AE45ASCCL2CVUCT7OUGQTSTUX7Y6TANCNFSM424NAYNA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you were mentioned.Message ID: @.***>

kevinparrish1 commented 2 years ago

I have the code working now, but there is one issue with the results. The potential issue comes up with this reference example from the original assignment

#path_to_general_wp(217, index=1) => [('t', 0, 121), ('t', 0, 23), ('t', 0, 5), ('t', *, *)]

Now, if we are to trace this path, we have we have

(None, None, 217, ['24g']) -> ('t',0,121,['8i','16j']) -> ('t',0,23,['8k','8k','8k']) -> ('t',0,5, ['4c','4c','4c','4c','4c','4c'])

The problem is that my code will not continue searching after the 121->23 transition. After we have traced the 1st special wyckoff position of group 217 (which is '24g') down to group 23, we can see that it will be represented as three '8k' positions of group 23. '8k' is already the general position of group 23, and so we already have a path to a general wyckoff position, and the additional transition to group 5 is not needed.

From my knowledge of subgroup transition theory, every single transition past group 23 will result in the '8k' position mapping onto another general position because general positions can only map onto general positions in maximal subgroup transitions, so literally the whole subgroup branch under 23 would be solutions. Would you like the code to just stop at 23, or give all solutions under 23 as well by setting some required number of steps? Currently, if we set the max number of steps to search to say 3, my code will return all solutions that take 1,2, or 3 steps. It's just that the particular example here (121->23->5) would not be included as it would have been caught and not further investigated after just the first two steps.

kevinparrish1 commented 2 years ago

I actually just noticed that the 121->23 transition is unique in that you have two different wyckoff positions becoming one kind ( ['8i','16j']->['8k']) while the 23->5 transition has one position going to one position (['8k'] -> ['4c']). Is it the case that you want the path to terminate once you have only one specific wp turning into another one position?

qzhu2017 commented 2 years ago

@kevinparrish1 Sorry, I meant to ask you to check the case for (group=211, index=7). When index=1, there is no need to go to group 5.

kevinparrish1 commented 2 years ago

I believe that it should be working now. There is still additional functionality I can add though,

>>> from pyxtal.symmetry import Group
>>> g=Group(211)
>>> paths=g.path_to_general_wp(index=7,max_steps=2, include_wp_list=True)
>>> for p in paths:
...     print(p)
... 
[('t', 0, 97, ['8j']), ('t', 0, 23, ['8k'])]
[('t', 0, 97, ['8j']), ('t', 1, 79, ['8c'])]
[('t', 0, 97, ['8j']), ('k', 0, 89, ['8p'])]
[('t', 0, 97, ['8j']), ('k', 3, 94, ['8g'])]
[('t', 1, 97, ['8j']), ('t', 0, 23, ['8k'])]
[('t', 1, 97, ['8j']), ('t', 1, 79, ['8c'])]
[('t', 1, 97, ['8j']), ('k', 0, 89, ['8p'])]
[('t', 1, 97, ['8j']), ('k', 3, 94, ['8g'])]
[('t', 2, 97, ['8j']), ('t', 0, 23, ['8k'])]
[('t', 2, 97, ['8j']), ('t', 1, 79, ['8c'])]
[('t', 2, 97, ['8j']), ('k', 0, 89, ['8p'])]
[('t', 2, 97, ['8j']), ('k', 3, 94, ['8g'])]
[('t', 7, 197, ['8c']), ('t', 0, 23, ['8k'])]
[('k', 0, 207, ['8g']), ('t', 0, 89, ['8p'])]
[('k', 0, 207, ['8g']), ('t', 1, 89, ['8p'])]
[('k', 0, 207, ['8g']), ('t', 2, 89, ['8p'])]
qzhu2017 commented 2 years ago

Should be working now after the fix of group path and lattice optimization