gap-packages / cryst

Computing with crystallographic groups
https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php#Cryst
Other
3 stars 6 forks source link

Unexpected translation bases & generators for subgroups #51

Closed kiryph closed 5 months ago

kiryph commented 9 months ago

I observed unexpected translation bases & generators for maximal subgroups in following situations:

  1. non-square choice for isomorphic subgroup of p4 (10) with index [2]
  2. non-hexagonal choice for isomorphic subgroup of p3 (13) with index [3]
  3. same basis for conjugate subgroups with orientational conjugation for c2mm ←[3]— p6mm

Non-orthogonal basis and generators for isomorphic square subgroups

gap> G := SpaceGroupIT(2, 10);; # Hermann Mauguin Symbol p4
gap> H := MaximalSubgroupClassReps(G, rec(primes:=[2], classequal:=true))[1];;
gap> TH := TranslationBasis(H);;
gap> Display(TH);
[ [  1,  1 ],
  [  0,  2 ] ]
gap> TH[1]*TH[2] = 0;
false
gap> # above is unexpected
gap> gens := GeneratorsOfGroup(H);;
gap> Perform(GeneratorsOfGroup(H){[3..4]},Display);
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  1,  1,  1 ] ]
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  0,  2,  1 ] ]
gap> # above is unexpected

Workaround:

create subgroup by ConjugatorSpaceGroups with expected generators

gap> PT := ConjugatorSpaceGroups(SpaceGroupIT(2, 10), H);;
gap> Display(PT);
[ [   1,   1,   0 ],
  [  -1,   1,   0 ],
  [   0,   0,   1 ] ]
gap> H2 := SpaceGroupIT(2, 10) ^ PT; # create subgroup
# verify that H2 is identical to H, is subgroup of G and its subgroup index is 2:
gap> H2 = H;
true
gap> IsSubgroup(G, H2);
true
gap> Index(G, H2);
2
gap> Display(TranslationBasis(H2)); # STILL UNEXPECTED
[ [  1,  1 ],
  [  0,  2 ] ]
gap> gens := GeneratorsOfGroup(H2);;
gap> Perform(GeneratorsOfGroup(H2){[3..4]},Display); # NOW AS EXPECTED
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  1,  1,  1 ] ]
[ [   1,   0,   0 ],
  [   0,   1,   0 ],
  [  -1,   1,   1 ] ]
gap> t1 := gens[3][3]{[1..2]};
[ 1, 1 ]
gap> t2 := gens[4][3]{[1..2]};
[ -1, 1 ]
gap> t1*t2 = 0; # orthogonal
true
gap> t1*t1 = t2*t2; # |t1| = |t2| (same length)
true

Non-orthogonal basis and generators for isomorphic hexagonal subgroups

gap> G := SpaceGroupIT(2, 13);; # Hermann Mauguin Symbol p3
gap> H := MaximalSubgroupClassReps(G, rec(primes:=[3], classequal:=true))[1];;
gap> TranslationBasis(H);  # UNEXPECTED
[ [ 1, 2 ], [ 0, 3 ] ]
gap> Perform(GeneratorsOfGroup(H){[2..3]},Display);  # UNEXPECTED
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  1,  2,  1 ] ]
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  0,  3,  1 ] ]

Conjugated subgroups with orientational conjugation

Screenshot 2024-02-05 at 12 43 36

gap> G := SpaceGroupIT(2, 17);;  # Hermann Mauguin Symbol p6mm
gap> Hs := List(ConjugacyClassesMaximalSubgroups(G, rec(primes:=[3], latticeequal:=true))[1]);;
gap> Perform(Hs, function(H) Display(TranslationBasis(H));end);
[ [  1,  0 ],
  [  0,  1 ] ]
[ [  1,  0 ],
  [  0,  1 ] ]
[ [  1,  0 ],
  [  0,  1 ] ]
gap> # above is unexpected
gap> Perform(Hs, function(H) Perform(GeneratorsOfGroup(H){[3..4]}, function(gen) Display(gen);end); Print("\n"); end);
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  1,  0,  1 ] ]
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  0,  1,  1 ] ]

[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  0,  1,  1 ] ]
[ [   1,   0,   0 ],
  [   0,   1,   0 ],
  [  -1,  -1,   1 ] ]

[ [   1,   0,   0 ],
  [   0,   1,   0 ],
  [  -1,  -1,   1 ] ]
[ [  1,  0,  0 ],
  [  0,  1,  0 ],
  [  1,  0,  1 ] ]
gap> # above is as expected: different translations for the different orientations

Resolving the issue

The documentation of the package mentions the method AddTranslationBasis:

If a generating set $B$ of the translation lattice of $S$ is known from somewhere, this knowledge can be added to $S$ with AddTranslationBasis( S, B ). This function must do further work, so that SetTranslationBasis cannot be used for this purpose.

But again, B will be changed in "further work".

I guess it has something to do with the application of ReducedLatticeBasis before returning TranslationBasis which changes the expected basis to the unexpected basis:

gap> L := [[ 1, 1 ], [ -1, 1 ]];; Display(L);
[ [   1,   1 ],
  [  -1,   1 ] ]
gap> Display(ReducedLatticeBasis(L));
[ [  1,  1 ],
  [  0,  2 ] ]

Commenting it in TranslationBasisFun did not help and there might be a reason to apply it.

From a space group type view, this issue might be irrelevant. However, I am interested in different space groups with different bases and shifts as they are relevant for crystallographers. See for example the book "Symmetry Relationships between Crystal Structures" by Ulrich Müller (2013) which emphasizes the importance of bases transformations and origin shifts as they occur in crystallography.

 ┌───────┐   GAP 4.12.2 of 2022-12-18
 │  GAP  │   https://www.gap-system.org
 └───────┘   Architecture: x86_64-apple-darwin22-default64-kv8
 Configuration:  gmp 6.3.0, GASMAN, readline
 Loading the library and packages ...
 Packages:   AClib 1.3.2, Alnuth 3.2.1, AtlasRep 2.1.6, AutPGrp 1.11, Browse 1.8.19, CaratInterface 2.3.6, CRISP 1.4.6,
             crypting 0.10.4, Cryst 4.1.27, CrystCat 1.1.10, CTblLib 1.3.4, curlInterface 2.3.1, datastructures 0.3.0, debugger 0.4,
             Digraphs 1.6.1, FactInt 1.6.3, FGA 1.4.0, float 1.0.3, Forms 1.2.9, GAPDoc 1.6.6, genss 1.6.8, GRAPE 4.9.0, IO 4.8.0,
             IRREDSOL 1.4.4, json 2.1.1, LAGUNA 3.9.5, Memoisation 1.0, orb 4.9.0, PackageManager 1.3.2, Polenta 1.3.10,
             Polycyclic 2.16, polymaking 0.8.6, PrimGrp 3.4.3, RadiRoot 2.9, recog 1.4.2, ResClasses 4.7.3, SmallGrp 1.5.1,
             Sophus 1.27, SpinSym 1.5.2, TomLib 1.2.9, TransGrp 3.6.3, typeset 1.1, utils 0.81
 Try '??help' for help. See also '?copyright', '?cite' and '?authors'
gaehler commented 6 months ago

Space groups in Cryst are concrete groups of matrices. The lattice of translations need not be orthogonal or aligned along any particular axis. In fact, even if one starts with a lattice aligned along certain axis, there will be subgroups whose lattices have different orientations. Cryst can work with those just as well. For each lattice, a standard primitive basis is used, which is chosen purely by computational criteria, not by crystallographic conventions. Cryst works with concrete space groups, not with standard representatives of space group types.

kiryph commented 6 months ago

@gaehler Also thank you here.

Cryst works with concrete space groups, not with standard representatives of space group types.

The question is: why does Cryst enforce a specific basis even though there is a method to add a custom basis by the user with AddTranslationBasis?

I would expect Cryst can work with any basis, even a conventional one as a crystallographer would choose.

gaehler commented 6 months ago

One can define the group with any basis, which is then converted into the internally used one. This applies also the basis added with AddTranslationBasis.

kiryph commented 6 months ago

But the method TranslationBasis does not return it anymore. (It is not an attribute getter but ensures it is the one Cryst works with).

gaehler commented 6 months ago

AddTranslationBasis does not add the basis literally, but first converts it into standard form, and stores that.

kiryph commented 6 months ago

Yes this is what I realized, but did not expect. The standard form could be the internal basis.

bfield1 commented 5 months ago

TranslationBasis gives you some basis vectors of the translation lattice. If two systems have the same TranslationBasis, then they must have the same lattice. By always reducing the translation basis, we can also state the opposite with confidence (different TranslationBasis implies different lattices). Per the documentation, "The basis returned is unique for the translation lattice." Thus, by the documentation, TranslationBasis must always return the same result for groups with the same translation lattice, no matter how many other operations have been performed on them.

If your application requires differentiating space groups with different settings on the same lattice, then you should probably investigate the symmetry operators and elements. I would not count on the given generators to be in any specific form, as the choice of generators is not unique.

You could probably get most of the information you need from the WyckoffPositions, which give you the locations (WyckoffTranslation and WyckoffBasis) and point groups (WyckoffStabilizer) of the symmetry elements.

You can get all the operators M in a point group (such as the WyckoffStabilizer) using List. You can identify the type of operators in the point group by checking their Order and Determinant. But you may also want to determine the orientation of the operator, that is, its rotation axis or mirror normal. You can determine this from the eigenvalues. The rotation axis will have an eigenvalue of 1. The mirror normal will have an eigenvalue of -1. In general, this is an eigenvalue of Determinant(M). The following code snippet assumes M is right-acting.

GeneratorsOfVectorSpace(Eigenspaces(Rationals, M)[Position(Eigenvalues(Rationals, M), Determinant(M))])[1];

If you have a non-symmorphic operator g, then you might want to find the intrinsic part of its translation (i.e. the glide vector or screw vector). This is simply

d := Length(g) - 1;
M := g{[1..d]}{[1..d]};
n := Order(M);
v := (g^n)[d+1]{[1..d]} / n;

If you need to identify an origin shift, you should find where the standard origin is, either by the Wyckoff positions or finding an inversion operator.

This information would probably be sufficient to identify the setting for a given space group.

kiryph commented 5 months ago

@bfield1 Thank you for your detailed comment. I very much appreciate getting here feedback.

I am struggling with the first paragraph a bit.

TranslationBasis gives you some basis vectors of the translation lattice.

For clarification: The wording "some basis vectors" for the concrete method TranslationBasis of the GAP package Cryst does not reflect the current state. It is the uniquely reduced form what TranslationBasis returns which is mentioned later.

But I think I get the point, a hypothetical method MyTranslationBasis would at first not say anything about the returned basis, except that it spans the lattice in question. So any returned basis fulfilling this property would be a possible return value. It does not say Conventional/Standard/HNF/...

If two systems have the same TranslationBasis, then they must have the same lattice.

Agreed.

By always reducing the translation basis, we can also state the opposite with confidence (different TranslationBasis implies different lattices).

Yes, but for comparisons one could call on demand reduce lattice and then compare, possibly store it as an additional attribute. IMHO, it is not strictly necessary to enforce how it is stored in the AffineCrystGroup, any compatible basis would be again ok.

I actually think, I need clarification what same lattices mean. Does an origin shift or orientation transformation change a lattice or not?

I added in the issue above a picture of orientational conjugation. Right now TranslationBasis returns for all conjugated subgroups the same translational basis and hence it would be said they have the same translation lattice, even though they have different sublattices of the original lattice of the supergroup.

Is this correct?

Per the documentation, "The basis returned is unique for the translation lattice." Thus, by the documentation, TranslationBasis must always return the same result for groups with the same translation lattice, no matter how many other operations have been performed on them.

I do not think the documentation itself can be the motivation. Documentation can be changed.

For instance, I could understand that the internal method VectorModL works only for reduced lattices and does not require the inverse (useful for performance reasons and to deal with subperiodic groups without specialisation).

Afaik, the GAP package HAPCryst has avoided this issue by only considering standard space groups, i.e. with identity as the basis which is not possible for me.

I want to finish my feedback about the first paragraph with:

I have accepted that the package Cryst is written under the assumption that TranslationBasis returns a uniquely reduced lattice which can be different to the translational generators. This is the current state and when I want to get the setting (basis and origin), I have to write my own methods.

If your application requires differentiating space groups with different settings on the same lattice, then you should probably investigate the symmetry operators and elements.

Yes, it requires space groups with different settings which is inherent to crystallographic subgroup analysis which I would consider is part of the “bread and butter” functionality of software dealing predominantly with group theory. The quoted book from U. Müller emphasises the importance of the specification of the setting for space groups and their subgroups.

Again to be clear: the package Cryst already handles different settings. It is only the method TranslationBasis which returns not the given basis but the reduced one and is often the same for subgroups despite only being differently orientated.

I would not count on the given generators to be in any specific form, as the choice of generators is not unique.

Agreed.

You could probably get most of the information you need from the WyckoffPositions, which give you the locations (WyckoffTranslation and WyckoffBasis) and point groups (WyckoffStabilizer) of the symmetry elements.

I started looking into this and will look into your rest of the comment in detail.

Hopefully, I figure out how to get the setting.

bfield1 commented 5 months ago

I actually think, I need clarification what same lattices mean. Does an origin shift or orientation transformation change a lattice or not?

I added in the issue above a picture of orientational conjugation. Right now TranslationBasis returns for all conjugated subgroups the same translational basis and hence it would be said they have the same translation lattice, even though they have different sublattices of the original lattice of the supergroup.

Is this correct?

In this case, I refer to the lattice as the set of all pure translations in the symmetry group (so, more formally it would be the translation subgroup). So TranslationBasis is unique for each translation subgroup. The picture you show has the same translation lattice for all three orientations; the centering translation counts as a translation. You might pick some lattice vectors as the "expected" basis for each setting, but all those bases are valid bases for all three of those orientations. So, mathematically (which is all a computer knows), there is no intrinsic property of any of those bases which would make one a better fit than another.

Changing the orientation can change the lattice, but it won't if the orientation transformation respects the symmetry of the translation subgroup (e.g. 3-fold rotation in a trigonal crystal).

Origin shifts do not change the translation subgroup. Shifting a crystal rigidly does not change the distances and directions between unit cells.

I do not think the documentation itself can be the motivation. Documentation can be changed.

Documentation can be changed. But documentation defines expected behaviour and changing the expected behaviour is a breaking change, so should not be taken lightly.

Hopefully, I figure out how to get the setting.

If you're working with space groups, you might also find ConjugatorSpaceGroups useful. Provided you can narrow your options down to a small number of possible space groups, you can use this function to find a transformation from your group to the group in conventional form (as given by SpaceGroupIT). You should be able to extract orientation and origin shift information from there.

kiryph commented 5 months ago

The picture you show has the same translation lattice for all three orientations; the centering translation counts as a translation.

I picked not a good example. The centering translation has mislead me. Thanks for pointing this out.

If you're working with space groups, you might also find ConjugatorSpaceGroups useful. Provided you can narrow your options down to a small number of possible space groups, you can use this function to find a transformation from your group to the group in conventional form (as given by SpaceGroupIT). You should be able to extract orientation and origin shift information from there.

I already use ConjugatorSpaceGroups. However, it is computationally slow to find the appropriate SpaceGroupIT. Right now I use CaratName and a precompiled asscociation between CaratName and the international space group number.

Thanks for all the answers. I consider my issue with "unexpected" translation bases as closed.