Chapter 2
15 min read
Section 12 of 70

Symmetry Groups in Action

Mathematics of Symmetry — Group Theory Essentials

Learning Objectives

Section 1 gave us the abstract definition of a group. We met D3D_3, the symmetries of a triangle, and we verified the four axioms by counting. Beautiful — but D3D_3 is a toy. The real prize is the rest of the crystallographic landscape: water, ammonia, methane, the cubic rocksalt crystal, the hexagonal layers of graphene, and every other structure you will compute in VASP. Every one of them carries a finite group of point symmetries, and we now have the vocabulary to name, count, and use those groups.

By the end of this section you will be able to:

  1. Recognise the five building-block symmetry operations of a finite point group: EE, CnC_n, σ\sigma, ii, and SnS_n.
  2. Read and write a Schoenflies symbol (e.g. C2vC_{2v}, D3hD_{3h}, OhO_h) and predict the order G|G| from the symbol alone.
  3. Identify a small set of generators and explain how a few axes plus a few mirrors build every other operation in the group through closure.
  4. Walk through three real molecules — water, ammonia, methane — and, for each, list every operation in its point group and play with the symmetry elements live in 3D.
  5. Connect this geometric picture to a concrete VASP/spglib output: read the international symbol, the point group, and the order of the group from one Python call on a NaCl primitive cell.
The big idea: abstract group theory becomes useful the moment you stop asking “does this set form a group?” and start asking “which group is it?”. The Schoenflies notation is the answer to the second question, and it is the language every crystallography textbook, every DFT code, and every spectroscopy paper writes in.

From Abstract to Concrete

Imagine handing the four axioms of section 1 to a chemist who has never seen them. They would shrug: “this is just bookkeeping. Show me a molecule.” The conversion from axioms to molecules proceeds in three steps, all of them quick, all of them non-negotiable.

  1. Pick the universe. Stand a finite, rigid object in empty space — a molecule, a unit cell, a polyhedron. Its centroid stays fixed. We will only consider operations that fix this centre point. (Translations are deferred to the next chapter, where they join the point group to make a space group.)
  2. Find every isometry that maps the object to itself. An isometry is a rigid motion: a rotation about an axis through the centroid, a reflection across a plane through the centroid, an inversion through the centroid, or any composition of those. The axioms of section 1 guarantee these isometries form a group under composition.
  3. Name the group. Among the infinitely many possible finite point groups, the geometry of 3D space allows surprisingly few. Counting only those that are compatible with crystal translations leaves exactly 3232 — the famous 32 crystallographic point groups. Each has a Schoenflies symbol. Memorising the dozen or so most common is the same kind of investment as memorising the periodic table's first row: you will use them every day.

A picture is worth a thousand axioms

The axioms tell you a triangle's symmetries form a group of order 6. They do not tell you which group of order 6 it is — there are two: C6C_6 (the rotations of a hexagon) and D3D_3 (the symmetries of a triangle). Same order, different multiplication tables. Schoenflies notation distinguishes them in two characters.

The Five Building Blocks

Every operation in every finite point group falls into one of five types. Memorise these once and you will read any character table or VASP OUTCAR symmetry block at a glance.

SymbolNameDeterminantOrder in element
EIdentity+11
C_nProper rotation by 360°/n+1n
σMirror reflection (plane)−12
iInversion through a point−12
S_nImproper rotation (rotate, then mirror)−1n or 2n

The determinant column is the same proper/improper split we met at the end of section 1: +1+1 for operations that preserve handedness (a right-hand glove stays a right-hand glove), 1-1 for operations that flip it (a right-hand glove becomes a left-hand glove). The order column gives the smallest number of times you have to apply the operation before you return to the identity.

E — the Identity

The trivial “do nothing” operation. Every group contains exactly one identity element by axiom G3. As a 3×3 matrix it is the identity matrix; its determinant is +1+1; its order is 1.

Cₙ — Proper Rotations

A CnC_n axis is a line through the centroid such that rotation by 360/n360^\circ / n maps the object to itself. The single axis generates n1n - 1 non-trivial rotations (the angles 360k/n360^\circ k / n for k=1,2,,n1k = 1, 2, \ldots, n-1) plus the identity, for a total of nn elements in the cyclic subgroup it generates. So a single C3C_3 axis gives you the subgroup {E,C3,C32}\{E, C_3, C_3^2\} — three operations from one axis.

Crystals admit only n=1,2,3,4,6n = 1, 2, 3, 4, 6 (the famous crystallographic restriction theorem, proved in chapter 1). Quasicrystals can host C5C_5 and C8C_8, but classical crystals cannot.

Principal axis

When a group has several rotation axes, the one with the highest nn is called the principal axis, and we conventionally place it along the zz direction. Schoenflies symbols are always written from the perspective of the principal axis: “C3vC_{3v} means a 3-fold principal axis with vertical mirrors”.

σ — Mirror Reflections

A mirror plane σ\sigma is a plane through the centroid such that reflecting across it maps the object to itself. Every mirror has determinant 1-1; applying it twice returns the identity, so its order is 2. Mirrors come in three flavours, distinguished by their orientation relative to the principal axis:

SubscriptNameOrientation
σ_hHorizontalPlane perpendicular to the principal axis
σ_vVerticalPlane containing the principal axis
σ_dDihedralVertical plane that bisects two C₂ axes (a special σ_v)

The distinction between σv\sigma_v and σd\sigma_d is bookkeeping that pays off when you read character tables: σd\sigma_d sits in a different conjugacy class from σv\sigma_v in groups like D4hD_{4h}, and it transforms differently under the irreducible representations.

i — Inversion

Inversion takes the point at (x,y,z)(x, y, z) to the point at (x,y,z)(-x, -y, -z). A crystal has inversion symmetry — is centrosymmetric — if every atom at r\mathbf{r} has an identical atom at r-\mathbf{r}. Centrosymmetry is decisive for: piezoelectricity (forbidden in centrosymmetric crystals), second-harmonic generation (also forbidden), and selection rules in IR/Raman spectra. As a matrix,

i=(100010001),deti=1,i2=E.i = \begin{pmatrix} -1 & 0 & 0 \\ 0 & -1 & 0 \\ 0 & 0 & -1 \end{pmatrix}, \quad \det i = -1, \quad i^2 = E.

Of the 32 crystallographic point groups, exactly 11 contain inversion. They are called the Laue classes and they govern which Bragg reflections you observe in a powder XRD pattern.

Sₙ — Improper Rotations

An improper rotation SnS_n means: rotate by 360/n360^\circ / n, then reflect across the plane perpendicular to the rotation axis. It is one operation, not two — although you can decompose it as Sn=σhCnS_n = \sigma_h \cdot C_n for analysis. Two special cases collapse into the building blocks we have already met:

  • S1=σhS_1 = \sigma_h — a rotation by 360° is just the identity, so an S1S_1 is the same as a single mirror.
  • S2=iS_2 = i — rotating by 180° and then reflecting across the perpendicular plane sends (x,y,z)(x, y, z) through two axis flips to (x,y,z)(-x, -y, -z), which is exactly inversion.

Genuinely new improper rotations begin at S3,S4,S6S_3, S_4, S_6 — and in crystals only those three orders are allowed (same crystallographic restriction). The order of SnS_n as an element is nn if nn is even and 2n2n if nn is odd, so S4S_4 has order 4 but S3S_3 has order 6.

The five types (E,Cn,σ,i,Sn)(E, C_n, \sigma, i, S_n) are not independent. Inversion is a hidden S2S_2; horizontal mirrors are hidden S1S_1. So in principle every point group is built from EE, CnC_n, and SnS_n alone — but the extra symbols make the geometry transparent at a glance.

Schoenflies Notation

Schoenflies symbols are short, mnemonic, and almost entirely compositional: a one- or two-letter root names the rotation skeleton, and a subscript adds the mirror/inversion decoration. Memorise the table below and you can already name 90% of the groups you will encounter in this book.

SymbolGenerators|G|Reading
C_1{E}1No symmetry at all
C_i{E, i}2Inversion only
C_s{E, σ}2One mirror only
C_n{C_n}nOne n-fold axis
C_nv{C_n, σ_v}2nn-fold axis + n vertical mirrors
C_nh{C_n, σ_h}2nn-fold axis + horizontal mirror
D_n{C_n, n×C_2⊥}2nn-fold axis + n perpendicular C_2
D_nh{C_n, C_2⊥, σ_h}4nD_n plus horizontal mirror
D_nd{C_n, C_2⊥, σ_d}4nD_n plus dihedral mirrors (no σ_h)
S_2n{S_2n}2nImproper-rotation cyclic group
Ttetrahedral rotations12Rotational symmetry of a tetrahedron
T_dT + reflections24Full tetrahedral group (CH₄)
T_hT + i24Tetrahedral with inversion
Ooctahedral rotations24Rotational symmetry of a cube
O_hO + i48Full cubic group (NaCl, diamond, fcc metals)

A handful of regularities make the table painless to remember:

  • CC means “cyclic” — driven by a single axis. DD means “dihedral” — that axis plus a ring of perpendicular C2C_2s, like the spokes of a wheel. TT and OO are the two highly symmetric polyhedra (tetrahedron and octahedron/cube).
  • The subscript tells you which mirrors are present: vv for vertical, hh for horizontal, dd for dihedral.
  • Adding one mirror or inversion doubles G|G|. That is why Dnh=4n|D_{nh}| = 4n while Dn=2n|D_n| = 2n: the horizontal mirror brings a second “copy” of every existing operation along.
  • The cubic groups Td,OhT_d, O_h sit at the top of the symmetry hierarchy — and almost every common crystal lives in one of them. NaCl, KCl, LiF, MgO, all III-V semiconductors with zincblende structure, diamond, silicon, germanium, copper, gold, silver — every face-centred-cubic compound has OhO_h.

Why two notations?

Crystallographers write m3ˉmm\bar{3}m (the Hermann-Mauguin or international symbol); spectroscopists and chemists write OhO_h (the Schoenflies symbol). Same group, different traditions. spglib reports both — we will see this in the VASP block at the end of the section.

Interactive Point-Group Explorer

Time to see these groups. The explorer below shows three molecules in 3D — water, ammonia, and methane. For each molecule you can toggle the rotation axes (color-coded by nn) and the mirror planes (translucent amber discs). The right-hand panel shows the Schoenflies symbol, the order G|G|, and the breakdown of operations by type. Drag to rotate, scroll to zoom.

Loading 3D point-group explorer…

A few observations to make before you read on:

  1. Switch to water. Turn on rotation axes — exactly one red C2C_2 axis, vertical, bisecting the H–O–H angle. Turn on mirrors — two amber discs, both vertical, one containing all three atoms (the molecular plane) and one perpendicular to it.
  2. Switch to ammonia. One green C3C_3 axis through the nitrogen. Three mirror planes — each contains the C3C_3 axis and one N–H bond. G=6|G| = 6 matches D3D_3 from §1, but the planes here are σv\sigma_v rather than the in-plane reflections of the abstract triangle: same order, structurally identical, geometrically different incarnation.
  3. Switch to methane. Turn axes on and watch the forest light up: four green C3C_3 axes (one through each C–H bond) and three red C2C_2 axes along the cartesian directions. With 6 mirror planes added, you can already enumerate 1+8+3+6=181 + 8 + 3 + 6 = 18 operations. The remaining six are the S4S_4 improper rotations, which we cannot draw cleanly as static elements but live along the same axes as the C2C_2s.

Sanity check

For each molecule, count what you see and compare with the “ Operation classes ” panel. Every visible axis and plane is a symmetry element; the operations are the powers/products you can generate from them. Water: 1+1+2=41 + 1 + 2 = 4. Ammonia: 1+2+3=61 + 2 + 3 = 6. Methane: 1+8+3+6+6=241 + 8 + 3 + 6 + 6 = 24.

Generators — the DNA of a Group

Look at the breakdown for methane: 24 operations. Drawing 24 things sounds tedious, and in fact we did not — we drew four C3C_3 axes, three C2C_2 axes, and six mirrors, total 13 symmetry elements. The remaining 11 operations come for free: closure (axiom G1) forces them into existence the moment we declare the first 13. This is what mathematicians mean by a generating set.

A subset SGS \subseteq G is a generating set for GG if every element of GG can be written as a product of finitely many elements of SS and their inverses. We write G=SG = \langle S \rangle, read “GG generated by SS”.

GroupGeneratorsVerification
C_3v (ammonia){r, σ} with r = C_3, σ = one σ_v{E, r, r², σ, rσ, r²σ} → 6 elements
D_3 (triangle){r, s} with r = C_3, s = one C_2{E, r, r², s, rs, r²s} → 6 elements
T_d (methane){C_3, S_4} along any pair of axesEvery product reproduces one of the 24 operations
O_h (cube){C_4, C_3, i}Three generators → 48 elements

The pattern is striking: two generators usually suffice for a finite point group, three are enough for any of the 32 crystallographic ones. This is why a real molecule's symmetry can be verified by inspecting only a handful of axes and mirrors — closure does the rest of the work for you.

Practical consequence: when you set up a calculation in VASP, spglib only has to detect the generators. The full list of 48 operations for a cubic crystal is then computed by repeated composition, exactly the way we built up the Cayley table for D3D_3 in §1.

Three Worked Examples

Pull the explorer above into the same field of view as this section and switch molecules as you read. The aim is to see each operation while you read its symbol.

Water — C₂ᵥ, |G| = 4

Water's three atoms lie in a plane, with the oxygen at the apex of an obtuse triangle. Place the C2C_2 axis along the bisector of the H–O–H angle. The four operations are:

OperationWhat it doesDeterminant
EIdentity+1
C_2Rotate 180° about the bisector → swaps the two H atoms+1
σ_vReflect across the molecular plane → leaves every atom fixed−1
σ_v'Reflect across the plane perpendicular to the molecular plane (contains the C_2) → swaps the two H atoms−1

Two of the operations swap the H atoms; the other two leave them fixed. As 3×3 matrices in the convention “yy is the C2C_2 direction, xyxy is the molecular plane”:

E=(100010001),C2=(100010001)E = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix}, \quad C_2 = \begin{pmatrix} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & -1 \end{pmatrix}
σv=(100010001),σv=(100010001)\sigma_v = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & -1 \end{pmatrix}, \quad \sigma_v' = \begin{pmatrix} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix}

Notice that C2=σvσvC_2 = \sigma_v \cdot \sigma_v' — the rotation is the composition of the two mirrors. So the group is generated by any two of {C2,σv,σv}\{C_2, \sigma_v, \sigma_v'\}; the third is redundant. C2vC_{2v} is abelian — composing any two of these elements gives the same answer in either order, because their matrices are all diagonal.

Ammonia — C₃ᵥ, |G| = 6

Ammonia is a low pyramid: nitrogen at the apex, three hydrogens forming the triangular base. The C3C_3 axis runs through the nitrogen perpendicular to the base. The six operations are:

  • EE — identity.
  • C3C_3 — rotate +120° about the vertical axis. Permutes the three H's cyclically.
  • C32C_3^2 — rotate +240°. Inverse of C3C_3.
  • Three vertical mirrors σv(1),σv(2),σv(3)\sigma_v^{(1)}, \sigma_v^{(2)}, \sigma_v^{(3)} — each containing the C3C_3 axis and one N–H bond, fixing that bond and swapping the other two.

The order is 6 — the same as D3D_3 from §1 — and indeed C3vC_{3v} and D3D_3 are the same abstract group. Two groups are isomorphic when their multiplication tables agree up to relabelling. Geometrically: C3vC_{3v} is a 3D pyramid, D3D_3 is a 2D triangle, but algebraically they are indistinguishable. This is your first taste of an important principle: the same abstract group can sit in many different geometric realisations, and group theory cares only about the algebra.

Classes inside C_3v

The six elements split into three conjugacy classes: {E}\{E\}, {C3,C32}\{C_3, C_3^2\}, and {σv(1),σv(2),σv(3)}\{\sigma_v^{(1)}, \sigma_v^{(2)}, \sigma_v^{(3)}\}. The two rotations are in the same class because they are “the same rotation looked at from opposite sides”; the three mirrors are in the same class because they are interchanged by the rotations. Classes are the natural columns of a character table — coming up in §4.

Methane — Tₐ, |G| = 24

Methane (CH4\text{CH}_4) is the showpiece. The carbon sits at the centre of a regular tetrahedron with a hydrogen at each vertex. The 24 operations of TdT_d come from five distinct classes:

ClassCountDescription
E1Identity
8 C_38Two rotations (C_3, C_3²) about each of the four C–H bonds → 4 × 2 = 8
3 C_23Rotations about the three cartesian axes (each passes through midpoints of two opposite edges)
6 σ_d6Mirror planes, each containing the carbon and exactly two hydrogens
6 S_46Improper rotations along the three C_2 axes (S_4, S_4³ on each → 3 × 2 = 6)

Add the counts: 1+8+3+6+6=241 + 8 + 3 + 6 + 6 = 24. Two generators suffice — for instance, one C3C_3 axis and one S4S_4 axis. The other 22 operations follow by composition.

The tetrahedral group TdT_d shows up constantly in materials science: methane, every CH4{\rm CH}_4-like molecule, the local environment of every silicon atom in c-Si or every Zn in ZnS, and the local symmetry around defects in zincblende semiconductors. When you compute charge densities or phonon modes near a tetrahedral site, the TdT_d point group pre-classifies every result.

The 32 Crystallographic Point Groups

We have built up the language; now the punchline. Of the infinitely many ways to arrange axes and mirrors in 3D, exactly 32 point groups are compatible with a periodic crystal lattice. The compatibility condition is the crystallographic restriction theorem: only CnC_n with n{1,2,3,4,6}n \in \{1, 2, 3, 4, 6\} are allowed, because no other rotation order tiles space periodically.

These 32 groups partition into 7 crystal systems by the maximum allowed rotation order:

Crystal system# point groupsHighest |G|Highest-symmetry group
Triclinic22C_i (1̄)
Monoclinic34C_2h (2/m)
Orthorhombic38D_2h (mmm)
Tetragonal716D_4h (4/mmm)
Trigonal512D_3d (3̄m)
Hexagonal724D_6h (6/mmm)
Cubic548O_h (m3̄m)

Notice the ceiling: Oh=48|O_h| = 48 is the largest order any crystallographic point group can have. NaCl, diamond, copper, silicon — every cubic crystal you compute in VASP — sits in OhO_h or one of its subgroups. The practical consequence is the kind of speedup we cited at the top of the chapter: VASP can shrink a Brillouin-zone sum by up to a factor of 48 simply by recognising OhO_h from your POSCAR.

Why 32 — and not more or fewer

Counting the 32 is a non-trivial exercise: you have to combine the five allowed rotation orders (1,2,3,4,6)(1, 2, 3, 4, 6) with the possible mirror/inversion decorations and check which combinations give a closed group whose lattice is invariant. Bravais did the partial bookkeeping for lattices in 1849; Hessel completed the point-group classification in 1830. Every inorganic crystal in the ICSD (≈260,000 entries) sits in exactly one of these 32 boxes.

VASP Connection — Reading the Point Group

Time to make the language concrete. The script below gives spglib a primitive NaCl cell and asks for the symmetry dataset. It prints the international symbol, the space-group number, the Hermann-Mauguin point-group symbol, and the order G|G| — the four numbers you will read whenever VASP analyses a structure. This is exactly the line of the OUTCAR that begins “Found 48 space group operations”.

Click any line of the code below to see, on the left, what each variable holds, exactly which arguments each library function consumes, and the value at that line. Watch especially line 27, where we walk through every one of the 48 rotation matrices and classify each by determinant.

Detecting the point group of NaCl with spglib
🐍nacl_pointgroup.py
1import numpy as np

NumPy gives us the 3×3 lattice matrix, the N×3 fractional-position array, and the determinant routine we need to classify each rotation as proper (+1) or improper (−1).

EXECUTION STATE
numpy = Numerical-array library — provides ndarray, np.linalg.det, broadcasting. Aliased as 'np' by convention.
2import spglib

spglib is the symmetry-finder used by VASP, ASE, pymatgen, and Atomate. It analyses a (lattice, positions, species) tuple and returns the full crystallographic symmetry — space group, point group, and every (rotation, translation) pair.

EXECUTION STATE
spglib = Crystallographic symmetry library written in C with Python bindings. Exposes get_symmetry, get_symmetry_dataset, get_pointgroup, refine_cell, and more.
5a = 5.64 — lattice constant in Å

NaCl has a conventional cubic lattice constant a ≈ 5.64 Å (room temperature). Note the value of a does not affect the symmetry — only the geometry does — so any positive a would give the same Fm-3m space group.

EXECUTION STATE
a = 5.64 — Å (lattice parameter of the conventional cubic NaCl cell)
→ why primitive cell? = We use the FCC primitive cell (volume a³/4) instead of the conventional cubic cell (volume a³, contains 4 NaCl pairs). The primitive cell has only 2 atoms — the smallest input that captures the full symmetry.
6lattice = np.array([...]) — primitive FCC vectors

Stack the three primitive lattice vectors as ROWS of a 3×3 matrix. For FCC the primitive vectors connect the cube corner to the centres of the three adjacent faces: (0, ½, ½)a, (½, 0, ½)a, (½, ½, 0)a. The determinant of this matrix is a³/4, exactly one quarter of the cubic-cell volume — confirming we have a primitive cell.

EXECUTION STATE
row 0 (a₁ vector) = [0.000, 2.820, 2.820] Å — to centre of x-face
row 1 (a₂ vector) = [2.820, 0.000, 2.820] Å — to centre of y-face
row 2 (a₃ vector) = [2.820, 2.820, 0.000] Å — to centre of z-face
→ det(lattice) = a³/4 = 5.64³ / 4 ≈ 44.86 ų (volume of the primitive cell)
11positions = np.array([...]) — fractional coordinates

Two atoms per primitive cell: Na at the origin, Cl displaced by (½, ½, ½) along the primitive vectors. In FRACTIONAL coordinates an atom at (u, v, w) sits at u·a₁ + v·a₂ + w·a₃ in real space. The fractional convention is critical: it decouples the symmetry analysis from the choice of a.

EXECUTION STATE
positions (2×3, fractional) =
      u     v     w
0   0.0   0.0   0.0    (Na)
1   0.5   0.5   0.5    (Cl)
→ real-space Cl position = 0.5·a₁ + 0.5·a₂ + 0.5·a₃ = (a/2, a/2, a/2) = (2.82, 2.82, 2.82) Å
→ why (½, ½, ½)? = In rocksalt the Cl sublattice is shifted from the Na sublattice by one body-diagonal of the conventional cube. In primitive FCC coordinates that diagonal becomes (½, ½, ½).
15numbers = [11, 17] — atomic numbers

Atomic-number list, one per atom. Z(Na) = 11, Z(Cl) = 17. Different Z means spglib treats them as distinguishable species, so any symmetry operation must map Na→Na and Cl→Cl. If we replaced [11, 17] with [11, 11] (both Na) the symmetry would not change — Na and Cl already sit on equivalent FCC sublattices — but a real ionic compound has them inequivalent.

EXECUTION STATE
numbers = [11, 17] — Z(Na) = 11, Z(Cl) = 17
→ species map = spglib enforces: any symmetry operation must permute atoms WITHIN the same species. Z=11 stays with Z=11; Z=17 stays with Z=17.
16cell = (lattice, positions, numbers)

spglib's universal cell format: a 3-tuple of (3×3 lattice, N×3 fractional positions, length-N atomic numbers). Every symmetry-finder in computational crystallography accepts essentially this same triple — VASP, ASE, pymatgen all use it under the hood.

EXECUTION STATE
cell = Tuple of (lattice, positions, numbers) — sufficient to define a crystal up to the choice of unit cell.
19ds = spglib.get_symmetry_dataset(cell, symprec=1e-5)

The single line that does all the heavy lifting. spglib detects the space group (a Bravais lattice + a basis), then derives the point group as the rotational part of every (R, t) operation, and packages everything into one dictionary.

EXECUTION STATE
📚 spglib.get_symmetry_dataset = Searches for every (R, t) such that R·positions + t reproduces the structure modulo the lattice. Returns a dict with: 'international' (HM space-group symbol), 'number' (1–230), 'pointgroup' (HM point-group), 'rotations' (N × 3×3 ints), 'translations' (N × 3 floats), 'wyckoffs', and more.
⬇ arg 1: cell = The (lattice, positions, numbers) tuple from line 16.
⬇ arg 2: symprec=1e-5 = Fractional-coordinate tolerance for matching atoms. 1e-5 ≈ 0.06 mÅ on this 5.64 Å cell — strict enough to reject numerical noise from a converged DFT relaxation, loose enough to forgive the last bit of rounding. Increase to 1e-3 for sloppy structures, but you risk over-symmetrising.
⬆ result: ds (dict) = {'international': 'Fm-3m', 'number': 225, 'pointgroup': 'm-3m', 'rotations': ndarray (48, 3, 3, int), 'translations': ndarray (48, 3, float), ...}
21print international symbol

The international Hermann-Mauguin symbol — the same string you would copy-paste into a VASP POSCAR comment or a publication's structure table. 'Fm-3m' encodes: F (face-centred lattice), m (mirror perpendicular to a), 3-bar (rotoinversion of order 3 along [111]), m (mirror perpendicular to [110]).

EXECUTION STATE
ds['international'] = 'Fm-3m'
⬆ stdout = International symbol : Fm-3m
22print space-group number

The 230 crystallographic space groups are numbered 1–230 in the International Tables for Crystallography. Fm-3m is #225. Knowing the number alone is enough to look up every Wyckoff position, allowed reflection condition, and high-symmetry k-path for the structure.

EXECUTION STATE
ds['number'] = 225
⬆ stdout = Space group number : 225
23print point group (Hermann-Mauguin)

The point-group string is the rotational part of the space group, with all translations dropped. 'm-3m' is the HM symbol for the cubic point group of highest symmetry — the same group as the Schoenflies symbol Oₕ. This is the group we cared about when we built the visualizer above: 48 operations on a cube.

EXECUTION STATE
ds['pointgroup'] = 'm-3m' (Schoenflies: Oₕ)
⬆ stdout = Point group (HM) : m-3m
→ HM ↔ Schoenflies = m-3m ⇔ Oₕ 4/mmm ⇔ D₄ₕ 6/mmm ⇔ D₆ₕ 3m ⇔ C₃ᵥ 23 ⇔ T
24print |G|

len(ds['rotations']) is the number of distinct symmetry operations — i.e. |G|. For Fm-3m the value is 48: 24 proper rotations (E, 8C₃, 6C₄, 3C₂, 6C₂′) and 24 improper (i, 8S₆, 6S₄, 3σₕ, 6σ_d).

EXECUTION STATE
len(ds['rotations']) = 48
⬆ stdout = Order |G| : 48
→ why this matters = VASP can replace the full Brillouin-zone integral by a sum over irreducible k-points only. Cost reduction: up to ×|G| = ×48 for cubic crystals. THIS is why your KPOINTS file with 21×21×21 expands to ≈9.3k points but VASP only computes ≈190.
27proper = sum(1 for R in ds['rotations'] if det(R) == +1)

Walk through all 48 rotation matrices. For each, take the determinant; round to the nearest integer (since orthogonal-matrix determinants are exactly ±1 up to ~1e-16 floating-point noise); count how many equal +1. Those are the PROPER operations — the identity and the pure rotations Cₙ.

EXECUTION STATE
📚 sum(1 for ... if cond) = Generator-expression idiom for counting items that match a condition. Equivalent to len([R for R in rotations if det(R)==+1]) but uses O(1) memory.
📚 np.linalg.det(M) = Computes det(M) by LU decomposition. For an orthogonal 3×3 matrix the result is exactly ±1 in exact arithmetic; we round to clean up floating-point noise.
→ loop body = for k=0..47: R = ds['rotations'][k] # a 3×3 integer matrix d = round(det(R)) # +1 or -1 if d == +1: count += 1
⬆ proper = 24 = 1 (E) + 8 (C₃) + 6 (C₄) + 3 (C₂) + 6 (C₂′)
29improper = len(ds['rotations']) - proper

Every operation is either proper or improper, so the improper count is simply 48 − 24. The improper class includes inversion i, the three kinds of mirrors (σₕ, σᵥ, σ_d), and the improper rotations Sₙ. For Oₕ they break down as 1 (i) + 8 (S₆) + 6 (S₄) + 3 (σₕ) + 6 (σ_d) = 24.

EXECUTION STATE
improper = 24 = 1 (i) + 8 (S₆) + 6 (S₄) + 3 (σₕ) + 6 (σ_d)
→ invariant = For ANY centrosymmetric point group (one containing i), proper and improper counts are equal: |G| / 2 each. NaCl is centrosymmetric, so we expect 24 + 24.
30print proper count

Pretty-print the proper operations. Reading this line out loud is exactly what you do when you read a 'character table' header (next section): the columns of a character table are these classes of proper + improper operations.

EXECUTION STATE
⬆ stdout = proper (E, C_n) : 24
31print improper count

And the improper operations. Comparing the two lines tells you at a glance whether your crystal is centrosymmetric (proper = improper) or not (proper ≠ improper, no inversion).

EXECUTION STATE
⬆ stdout = improper (sigma, i, S_n) : 24
→ final output =
International symbol : Fm-3m
Space group number   : 225
Point group (HM)     : m-3m
Order |G|            : 48
  proper   (E, C_n)        : 24
  improper (sigma, i, S_n) : 24
15 lines without explanation
1import numpy as np
2import spglib
3
4# NaCl rocksalt (space group Fm-3m, #225) — primitive FCC cell.
5a = 5.64                              # lattice constant in Å
6lattice = np.array([
7    [0.0,   0.5*a, 0.5*a],
8    [0.5*a, 0.0,   0.5*a],
9    [0.5*a, 0.5*a, 0.0  ],
10])
11positions = np.array([
12    [0.0, 0.0, 0.0],                  # Na at origin
13    [0.5, 0.5, 0.5],                  # Cl at (1/2, 1/2, 1/2)
14])
15numbers = [11, 17]                    # Z(Na)=11, Z(Cl)=17
16cell = (lattice, positions, numbers)
17
18# One call extracts the space-group + point-group.
19ds = spglib.get_symmetry_dataset(cell, symprec=1e-5)
20
21print(f"International symbol : {ds['international']}")
22print(f"Space group number   : {ds['number']}")
23print(f"Point group (HM)     : {ds['pointgroup']}")
24print(f"Order |G|            : {len(ds['rotations'])}")
25
26# Split each operation into proper / improper by determinant.
27proper = sum(1 for R in ds['rotations']
28             if int(round(np.linalg.det(R))) == +1)
29improper = len(ds['rotations']) - proper
30print(f"  proper   (E, C_n)        : {proper}")
31print(f"  improper (sigma, i, S_n) : {improper}")

The expected console output:

International symbol : Fm-3m
Space group number   : 225
Point group (HM)     : m-3m
Order |G|            : 48
  proper   (E, C_n)        : 24
  improper (sigma, i, S_n) : 24

Read this output back to the table at the top of the previous section: G=48|G| = 48 is the maximum any crystallographic point group can have, the proper/improper split is 24/24 (NaCl is centrosymmetric, so half the operations contain a reflection), and the Hermann-Mauguin symbol m3ˉmm\bar{3}m translates one-to-one into the Schoenflies symbol OhO_h. Every cubic crystal in this book — silicon, germanium, gold, NaCl, MgO — will produce essentially this same line.

Try this

Edit the script and replace the second atom by a different species, e.g. numbers = [11, 11] (turn Cl into Na). spglib will report Fm-3m → still OhO_h, still |G| = 48. Now try shifting the Cl off-centre by 0.05: positions[1] = [0.55, 0.5, 0.5]. The point group collapses to a much smaller group (as low as C4vC_{4v}), reflecting the fact that breaking the cubic symmetry by even one atom destroys most of OhO_h. This is the same way VASP detects the polar distortions in BaTiO₃ and the symmetry-lowering of a substitutional dopant.

Summary

  1. Every finite molecule or unit cell carries a point group — the set of isometries that fix the centroid and map the object to itself. Closure is automatic, by axiom G1.
  2. Five symmetry building blocks generate every point group: EE, CnC_n, σ\sigma, ii, SnS_n. Their determinants split them into proper (+1+1) and improper (1-1).
  3. Schoenflies notation labels a point group by its generators: CnC_n, CnvC_{nv}, CnhC_{nh}, DnD_n, DnhD_{nh}, DndD_{nd}, TT, TdT_d, ThT_h, OO, OhO_h. Counting generators predicts G|G|.
  4. The crystallographic restriction admits only n{1,2,3,4,6}n \in \{1, 2, 3, 4, 6\} for CnC_n, which whittles the infinite zoo of possible point groups down to exactly 32. They partition into 7 crystal systems, with OhO_h as the highest-order group at G=48|G| = 48.
  5. Three molecules anchor the typology: H2OC2v\text{H}_2\text{O} \to C_{2v} with 4 operations, NH3C3v\text{NH}_3 \to C_{3v} with 6, CH4Td\text{CH}_4 \to T_d with 24.
  6. spglib reads a (lattice, positions, numbers) tuple and reports the international symbol, the space-group number, the Hermann-Mauguin point group, and the full list of rotation matrices in one call. For NaCl: Fm-3m, #225, m3ˉmOhm\bar{3}m \equiv O_h, G=48|G| = 48.
Looking ahead. We now have a vocabulary of point groups and can spot them on real molecules and crystals. The next section asks: how does each operation act on a function — say, an electron orbital or a phonon mode? The answer is a 3×3 matrix per operation, called a representation — and the rest of the chapter (sections 3–7) extracts every meaningful physical statement from those matrices alone.
Loading comments...