\(\renewcommand\AA{\unicode{x212B}}\)

Symmetry groups

This is an introduction to group theoretical concepts for symmetry in Mantid. It is the basis for further descriptions covering point groups and space groups.

Introduction

Symmetry in space of any dimensionality can be described by symmetry groups. This and the following guides cover symmetry in three dimensions, as it is most commonly used in crystallography and how it is integrated into Mantid. All code samples are given as Python code and can be executed directly in the program.

Groups

A group \((G, \cdot)\) is defined as a set of elements \(G\) with a binary operation \(\cdot\) which combines two elements of \(G\). \((G, \cdot)\) is a group if the four group axioms are satisfied [Groups]:

  1. Closure: For all \(a, b\) in \(G\) the result of \(a \cdot b\) is also in \(G\).

  2. Associativity: For all \(a, b\) in \(G\), \((a \cdot b) \cdot c\) is equal to \(a \cdot (b \cdot c)\).

  3. Identity element: There exists an element \(e\) in \(G\) such that \(e \cdot a = a\).

  4. Inverse element: For each \(a\) in \(G\) there exists an element \(b\) in \(G\) such that \(a \cdot b = e\).

There are many examples for groups, for example the group defined by the set of signed integer numbers and the addition operation. Any two integers added result again in an integer, integer addition is associative, there is an identity element (the number 0) and for each integer there is an inverse element (the number with the same magnitude, but opposite sign). For describing symmetry, groups are required that consist of a set of symmetry operations and a binary operation that combines them. The next section describes how symmetry operations can be represented and how to work with them in Mantid.

Symmetry operations

Theory

As symmetry operations are used for the definition of space groups, the mathematics behind this are covered in depth in the International Tables for Crystallography A (ITA), namely part 11 [ITASymmetry]. A symmetry operation describes the transformation of an object \(O\) into its image \(O'\):

\[O' = S \cdot O\]

For a coordinate \(\mathbf{x}\) in three dimensions, any transformation can be described using a transformation matrix \(\mathbf{W}\) and a translation vector \(\mathbf{w}\). This leads to the following equation:

\[\mathbf{x}' = \mathbf{W} \cdot \mathbf{x} + \mathbf{w}\]

\(\mathbf{W}\) is a \(3\times3\)-matrix and for affine transformations, the determinant of the matrix is always equal to 1 or -1 (except for hexagonal coordinates, which are handled transparently in Mantid so this is not covered here).

Coordinates \(x\) are assumed to be fractional in terms of a unit cell, which defines the smallest unit of an infinite lattice that is repeated over and over.

Of course it is also possible to transform vectors (such as reciprocal vectors \(\mathbf{h}\) described by Miller indices h, k and l), in which case the translation does not apply and the matrix needs to be inverted and transposed:

\[\mathbf{h}' = {\mathbf{W}_i^{-1}}^T \cdot \mathbf{h}\]

For the definition of the group \((G, \cdot)\) this means that \(G\) is a set of matrix and vector pairs \((\mathbf{W}_i, \mathbf{w}_i) = S_i\). All that’s missing for completing the description of a symmetry group is the definition of the binary operation \(\cdot\):

\[S_3 = S_1 \cdot S_2 = \left(\mathbf{W}_1 \cdot \mathbf{W}_2, \left[\mathbf{W}_1 \cdot \mathbf{w}_2\right] + \mathbf{w}_1\right)\]

While matrix and vector pairs are very well suited for modelling symmetry operaitions in a computer language, they are not very convenient for human language. A very common notation is the “Jones-faithful” system, which is for example used in the symmetry operations section in the space group descriptions in ITA. It uses \((x,y,z)\) triplets to describe the rows of the matrix (\(x\) meaning \(1, 0, 0\) and so on) and the translation vector (for example \(x,y,z+1/2\) for a translation of half a unit cell vector in \(c\)-direction). The following table shows some more examples:

Examples for symmetry operations in Jones-faithful notation.

Symbol

Symmetry operation

x,y,z

Identity

-x,-y,-z

Inversion

-x,-y,z

2-fold rotation around \(z\)

x,y,-z

Mirror plane perpendicular to \(z\)

-x,-y,z+1/2

\(2_1\) screw axis along \(z\)

There are several advantages to this notation. First of all it’s very concise and secondly it directly shows how a point \(x\) behaves under the symmetry transformation. As such this notation was chosen for generation of symmetry operations in Mantid.

Last but not least, each symmetry operation has a so called order \(k\), which describes how many times the operation has to be chained together to arrive at identity:

\[I = S^k = S \cdot S \cdot \dots \cdot S\]

The same is true for transforming coordinates as well. Applying a symmetry operation of order \(k\) exactly \(k\) times to a point \(x\) will result in \(x\) again, which is the definition of identity.

Symmetry operations in Mantid

Symmetry operations are implemented in Mantid following the scheme described above with matrix and vector pairs, it is written in C++ and resides in the Geometry library. How to use this code is described in the doxygen documentation and shall not be covered at this point. Instead this section describes how symmetry operations can be used in the Python environment of Mantid.

As described above, the operations are represented using the Jones-faithful notation, so they can be created by a factory that parses these strings. It returns a SymmetryOperation-object which can be queried for certain characteristics. The most obvious one is the identifier string. It may differ from the one used to create the operation, because the strings are normalized internally so that a specific matrix and vector pair always has the same identifier.

from mantid.geometry import SymmetryOperationFactory

# This time the identifier is already normalized
symOp = SymmetryOperationFactory.createSymOp("x,y,-z")
print(symOp.getIdentifier())

# This is an example for an identifier that changes
symOp = SymmetryOperationFactory.createSymOp("1/2+x,y,z")
print(symOp.getIdentifier())

Executing the above code yields the following output, which shows how the operation identifier is modified in some cases:

x,y,-z
x+1/2,y,z

For ease of use with multiple symmetry operations it’s also possible to create multiple operations at once, using a semi-colon separated string of identifiers:

from mantid.geometry import SymmetryOperationFactory

# Create a list of symmetry operations
symOps = SymmetryOperationFactory.createSymOps("x,y,-z; -x,-y,-z; z,x,y")

print("Number of operations: " + str(len(symOps)))
print("Operations:")

for op in symOps:
   print(op.getIdentifier())

This prints each identifier on a new line:

Number of operations: 3
Operations:
x,y,-z
-x,-y,-z
z,x,y

Symmetry operation objects can be used to transform coordinates or Miller indices, which are handled differently as detailed in the theory section above, so different methods exists for each of the two tasks.

from mantid.geometry import SymmetryOperationFactory

symOp = SymmetryOperationFactory.createSymOp("x-y,x,z")

coordinates = [0.3, 0.4, 0.5]
coordinatesPrime = symOp.transformCoordinates(coordinates)

print("Transformed coordinates: " + str(coordinatesPrime))

This script generates a symmetry operation that is used in hexagonal coordinate systems and uses it to transform the given coordinates:

Transformed coordinates: [-0.1,0.3,0.5]

As transforming HKLs requires slightly different math, there is a special method for this as well:

from mantid.geometry import SymmetryOperationFactory

symOp = SymmetryOperationFactory.createSymOp("x,y,-z")

hkl = [1, -1, 3]
hklPrime = symOp.transformHKL(hkl)

print("Transformed hkl: " + str(hklPrime))

The above code will print the transformed Miller index triplet:

Transformed hkl: [1,-1,-3]

It’s also possible to query the order of a symmetry operation. The next example generates a fourfold rotation around the \(z\)-axis and prints some information about it.

from mantid.geometry import SymmetryOperationFactory

symOp = SymmetryOperationFactory.createSymOp("-y,x,z")

k = symOp.getOrder()
print("Order of the symmetry operation: " + str(k))

x = [0.3, 0.4, 0.5]
print("Original point: ["+(','.join(" %.1f"%c for c in x)).strip()+"]")
for i in range(k):
    x = symOp.transformCoordinates(x)
    print("After {0} application(s): {1}".format(i + 1, x))
Order of the symmetry operation: 4
Original point: [0.3, 0.4, 0.5]
After 1 application(s): [-0.4,0.3,0.5]
After 2 application(s): [-0.3,-0.4,0.5]
After 3 application(s): [0.4,-0.3,0.5]
After 4 application(s): [0.3,0.4,0.5]

Symmetry elements

Sometimes it’s easier to describe symmetry in terms of the symmetry element that is associated to an operation. Several notation systems exist for these elements, but Hermann-Mauguin symbols are most commonly used in crystallography. Information on how to read these symbols can be found in ITA. Except identity, inversions and translations, all symmetry elements have a characteristic axis. In case of mirror and glide planes, this axis is perpendicular to the plane.

Section 11.2 in the same book describes how to derive symmetry elements from matrix and vector pairs. The algorithms from that text are implemented in Mantid as well, so after a symmetry operation has been created using the factory, another factory can be used to generate the symmetry element corresponding to the operation. The resulting object can be queried for its Hermann-Mauguin symbol, its axis and its rotation sense (only for rotation axes). For identity, inversion and translation this returns [0, 0, 0].

from mantid.geometry import SymmetryOperationFactory, SymmetryElementFactory

symOp = SymmetryOperationFactory.createSymOp("x,y,-z")
element = SymmetryElementFactory.createSymElement(symOp)

print("The element corresponding to 'x,y,-z' has the following symbol: " + str(element.getHMSymbol()))
print("The mirror plane is perpendicular to: " + str(element.getAxis()))
print("Sense of rotation (or NoRotation): " + str(element.getRotationSense()))

In this case, it’s a mirror plane perpendicular to the \(z\)-axis:

The element corresponding to 'x,y,-z' has the following symbol: m
The mirror plane is perpendicular to: [0,0,1]
Sense of rotation (or NoRotation): NoRotation

Symmetry groups

In the previous section, symmetry operations and a binary operation combining them were introduced, which is finally sufficient to define symmetry groups. For the purpose of defining groups, it is assumed that coordinates \(x\) and \(x + 1\), \(x + 2\), \(x - 1\) and so forth are equivalent. That means that translation vectors are limited to have it’s elements on the interval \([0, 1)\). The most simple group possible contains only one element, the identity:

\[G = \left\{1\right\}\]

This group fulfills all four group axioms. The identity matrix multiplied with itself is again identity, so the group is closed. Associativity holds as well, since it does not matter in which order multiple identical operations are performed. Since the only element of the group is the identity, the third axiom is fulfilled as well. So is the fourth, since the inverse of the identity is again identity. This group exists as the point group \(1\) and describes objects that do not show any symmetry except identity.

As more operations are added to a group, it can be useful to display the group in terms of a group table, which makes it easy to check the group axioms. The following example group contains the symmetry operations \(1\), \(\bar{1}\), \(2\) and \(m\), the latter two being characterized by the same axis. The cells of the group tables show the result of the binary operation combining the symmetry operations in the header row and header column:

Group table example

\(1\)

\(\bar{1}\)

\(2\)

\(m\)

\(1\)

\(1\)

\(\bar{1}\)

\(2\)

\(m\)

\(\bar{1}\)

\(\bar{1}\)

\(1\)

\(m\)

\(2\)

\(2\)

\(2\)

\(m\)

\(1\)

\(\bar{1}\)

\(m\)

\(m\)

\(2\)

\(\bar{1}\)

\(1\)

Combining the symmetry operations does not result into any new operations, so the group is closed. Each element has an inverse (in this case, each element is its own inverse). :math:` and an identity element exists (all elements in the first row are the same as in the header row). Groups are available through the Python interface of Mantid. The following code generates the group in the table above (with the y-axis being characteristic for rotation and mirror symmetry) and checks whether this set of symmetry operations is indeed a Group:

from mantid.geometry import Group

group = Group("x,y,z; -x,-y,-z; -x,y,-z; x,-y,z")

print("Order of group: " + str(group.getOrder()))
print("Fulfills group axioms: " + str(group.isGroup()))

This code confirms what was demonstrated by the group table above, the specified set of symmetry operations fulfills the group axioms:

Order of group: 4
Fulfills group axioms: True

For more fine-grained information, the four axioms can also be checked separately. Please note that the associativity axiom is always fulfilled due to the way the binary operation for symmetry operations is defined, it’s included for completeness reasons. In the next example, the inversion operation is removed and the four axioms are checked:

from mantid.geometry import Group, GroupAxiom

group = Group("x,y,z; -x,y,-z; x,-y,z")

print("Group axioms fulfilled:")
print("  1. Closure: " + str(group.fulfillsAxiom(GroupAxiom.Closure)))
print("  2. Associativity: " + str(group.fulfillsAxiom(GroupAxiom.Associativity)))
print("  3. Identity: " + str(group.fulfillsAxiom(GroupAxiom.Identity)))
print("  4. Inversion: " + str(group.fulfillsAxiom(GroupAxiom.Inversion)))

The code reveals that axioms 2 - 4 are fulfilled, but that the group is not closed:

Group axioms fulfilled:
  1. Closure: False
  2. Associativity: True
  3. Identity: True
  4. Inversion: True

Looking into the group table above shows the reason: The combination of a mirror plane and a two-fold rotation axis implies the presence of an inversion center. Similarly, the identity can be removed:

from mantid.geometry import Group, GroupAxiom

group = Group("-x,-y,-z; -x,y,-z; x,-y,z")

print("Group axioms fulfilled:")
print("  1. Closure: " + str(group.fulfillsAxiom(GroupAxiom.Closure)))
print("  2. Associativity: " + str(group.fulfillsAxiom(GroupAxiom.Associativity)))
print("  3. Identity: " + str(group.fulfillsAxiom(GroupAxiom.Identity)))
print("  4. Inversion: " + str(group.fulfillsAxiom(GroupAxiom.Inversion)))

In contrast to removing the inversion, the group now also lacks an identity element:

Group axioms fulfilled:
  1. Closure: False
  2. Associativity: True
  3. Identity: False
  4. Inversion: True

Using these specific checks can be helpful for finding out why a certain set of symmetry operations is not a group.

Some groups are so called cyclic groups, all elements of the group can be expressed as powers of one symmetry operation (which are explained above) from 0 to \(k-1\), where k is the order of the operation. The group with elements \(1\) and \(2\) is an example for such a cyclic group, it can be expressed as \(2^0 = 1\) and \(2^1 = 2\).

Just like in the case of symmetry operations, it’s also possible to define a binary operation that combines two groups. For this, each symmetry operation of the first group is multiplied with each symmetry operation of the second group. If the resulting new set of operations fulfills the group axioms, the product of the two groups is again a group.

These general group concepts are available in the C++ library of Mantid and are described in the API documentation (Mantid::Geometry::SymmetryOperation, Mantid::Geometry::SymmetryElement, Mantid::Geometry::Group). The most important specializations of symmetry groups implemented in Mantid are point- and space groups. They are explained in an additional document.

[Groups]

Wikipedia article on groups. Can be found in different formulations in various places such as Wolfram MathWorld.

[ITASymmetry]

International Tables for Crystallography (2006). Vol. A, part 11, p. 810 (chapters 11.1 and 11.2).

Category: Concepts