Symmetry Operations
What are Symmetry Operations?
A symmetry operation is a transformation of a configuration space that maps the vector positions onto each other. In the abstract vector representation, a symmetry operation is simply a permutation of the vector indices.
For a configuration space with n positions, a symmetry operation rearranges these positions while preserving the structure of the space. When applied to a configuration, a symmetry operation produces a new configuration by permuting the object labels according to the index permutation.
Example: Triangular Configuration Space
Consider three positions arranged conceptually as an equilateral triangle:
This is a 3-dimensional vector space with positions that we can label 0, 1, and 2 (corresponding to corners a, b, and c).
A specific configuration, such as [1, 1, 0], assigns labels to each position:
where positions 0 and 1 have object type 1 (shown in black), and position 2 has object type 0 (shown in white).
Identity Operation
Every configuration space has at least one symmetry operation: the identity operation (often labelled E), which leaves all positions unchanged:
This is the trivial permutation where every position maps to itself.
Rotations and Reflections
For the triangular system, there are other symmetry operations including rotations and reflections:
A reflection operation σ might swap positions, for example mapping position 1 to position 2 and position 2 to position 1, while leaving position 0 unchanged.
Physical Interpretation
While symmetry operations are defined abstractly as permutations, they often correspond to physical transformations:
Rotations: Rotating a structure around an axis
Reflections: Mirroring across a plane
Inversions: Mapping through a centre point
Translations: Shifting by a lattice vector (for space groups)
These physical transformations, when applied to discrete sites, simply permute the site indices.
Matrix and Vector Representation
Permutation Matrices
A symmetry operation can be represented as a permutation matrix that transforms configuration vectors. For an n-dimensional space, this is an n × n matrix where each row and column contains exactly one 1, with all other elements 0.
For the identity operation on a 3-dimensional space:
For a rotation operation that maps position 0→1, 1→2, 2→0:
Applying this matrix to configuration [1, 1, 0] gives:
Vector Notation
A more compact representation uses a permutation vector showing where each position maps. Instead of the full matrix, we can write the C₃ rotation as:
[2, 3, 1]
meaning:
Position 1 → Position 2
Position 2 → Position 3
Position 3 → Position 1
This vector notation is more compact and easier to read. In bsym, symmetry operations can be created from this vector form:
from bsym import SymmetryOperation
# Create rotation operation using vector notation
c3 = SymmetryOperation.from_vector([2, 3, 1], label='C3')
Note that the vector notation uses 1-based indexing (positions numbered 1, 2, 3, …), even though configurations use 0-based indexing internally (positions 0, 1, 2, …).
Applying Operations to Configurations
A symmetry operation transforms a configuration by permuting its elements:
from bsym import Configuration, SymmetryOperation
config = Configuration([1, 1, 0])
c3 = SymmetryOperation.from_vector([2, 3, 1], label='C3')
# Apply the operation
result = c3.operate_on(config)
# Or equivalently:
result = c3 * config
print(result) # Configuration([0, 1, 1])
Inverting Symmetry Operations
Mathematical Inverse
For every symmetry operation A, there exists an inverse operation A⁻¹ such that:
where E is the identity operation. The inverse operation “undoes” the original operation.
Example: C₃ and C₃⁻¹
For the triangular configuration space, the inverse of C₃ (clockwise rotation by 120°) is C₃⁻¹ (anticlockwise rotation by 120°):
from bsym import SymmetryOperation
c3 = SymmetryOperation.from_vector([2, 3, 1], label='C3')
c3_inv = SymmetryOperation.from_vector([3, 1, 2], label='C3_inv')
# The product gives the identity
result = c3 * c3_inv
print(result.matrix)
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
The .invert() Method
Symmetry operations can be inverted programmatically using the .invert() method:
c3 = SymmetryOperation.from_vector([2, 3, 1], label='C3')
# Generate the inverse
c3_inv = c3.invert()
The resulting operation initially has no label. Labels can be set directly or using the .set_label() method:
# Set label during inversion
c3_inv = c3.invert(label='C3_inv')
# Or set label afterwards
c3_inv = c3.invert().set_label('C3_inv')
Symmetry Groups
Definition
A symmetry group is a collection of symmetry operations. In bsym, a SymmetryGroup object contains a set of SymmetryOperation objects that describe the symmetries of a configuration space.
from bsym import SymmetryGroup, SymmetryOperation
# Create individual operations
e = SymmetryOperation.from_vector([1, 2, 3], label='E')
c3 = SymmetryOperation.from_vector([2, 3, 1], label='C3')
c3_inv = SymmetryOperation.from_vector([3, 1, 2], label='C3_inv')
# Combine into a symmetry group
symmetry_group = SymmetryGroup([e, c3, c3_inv])
Mathematical Groups
The term “symmetry group” is used by convention, but a SymmetryGroup in bsym is not required to be a complete mathematical group. It is simply a collection of symmetry operations that are relevant for a particular analysis.
A bsym SymmetryGroup may contain only a subset of operations - for example, you might include only the operations needed for a specific analysis, even if they don’t form a complete group.
The C3v Point Group Example
For the triangular configuration space, the complete C3v point group contains six operations: one identity, two rotations, and three reflections:
from bsym import PointGroup, SymmetryOperation
# Identity
e = SymmetryOperation.from_vector([1, 2, 3], label='E')
# Rotations
c3 = SymmetryOperation.from_vector([2, 3, 1], label='C3')
c3_inv = SymmetryOperation.from_vector([3, 1, 2], label='C3_inv')
# Reflections
sigma_a = SymmetryOperation.from_vector([1, 3, 2], label='sigma_a')
sigma_b = SymmetryOperation.from_vector([3, 2, 1], label='sigma_b')
sigma_c = SymmetryOperation.from_vector([2, 1, 3], label='sigma_c')
# Create point group
c3v = PointGroup([e, c3, c3_inv, sigma_a, sigma_b, sigma_c])
PointGroup and SpaceGroup
For convenience, bsym provides PointGroup and SpaceGroup classes that are functionally equivalent to SymmetryGroup:
from bsym import PointGroup, SpaceGroup
# These are all equivalent:
group1 = SymmetryGroup([e, c3])
group2 = PointGroup([e, c3])
group3 = SpaceGroup([e, c3])
The different class names simply make code more readable by indicating what type of symmetry is being described.
Creating Symmetry Groups from Files
Reading Unlabelled Operations
Symmetry groups can be read from files containing permutation vectors. Each line represents one symmetry operation:
# example file: pair_symmetry.txt
1 2
2 1
This defines a symmetry group for two equivalent sites with the identity (1→1, 2→2) and a swap operation (1→2, 2→1).
from bsym import SymmetryGroup
symmetry_group = SymmetryGroup.read_from_file('pair_symmetry.txt')
Reading Labelled Operations
For better readability, operations can be labelled:
# example file: c3v_symmetry.txt
E 1 2 3
C3 2 3 1
C3_inv 3 1 2
sigma_a 1 3 2
sigma_b 3 2 1
sigma_c 2 1 3
from bsym import SymmetryGroup
c3v = SymmetryGroup.read_from_file_with_labels('c3v_symmetry.txt')
The labels are used when displaying the symmetry group and can help identify specific operations during analysis.
File Format
Both file formats use space-separated values:
Unlabelled: Each line contains n integers representing the permutation
Labelled: Each line starts with a label string, followed by n integers
Comment lines starting with
#are ignoredPermutation vectors use 1-based indexing