Crystal symmetry in ONETEP

Author:

Chengcheng Xiao

Date:

July 2025

Symmetry operations in ONETEP

Crystal symmetry operations can be defined using rotation and translation pairs. In ONETEP, symmetry operations (in fractional coordinates) are obtained by passing the crystal information (lattice, ionic positions, and types) to spglib.

These operations can then be used to find symmetry-related k-points:

\[\mathbf{k}_\mathrm{rot} = \mathbf{R} \mathbf{k}\]

where \(\mathbf{R}\) is the rotation operator in reciprocal space, which is the inverse of the rotation operator in the real space.

Symmetry-related k-points have the same energy; hence, we can use only one k-point for each k-point group that is symmetry-related to achieve more efficient calculations. Note that the k-point weights are also adjusted based on the number of symmetry-related k-points in the group.

In addition to the crystal symmetry, ONETEP also supports time-reversal symmetry (TRS) to further reduce the number of k-points. In practice, this means that one can eliminate half of the k-points in the first Brillouin zone because TRS dictates that k-points (k) and their time-reversed counterparts (-k) have the same energy.

However, while the energy calculated by symmetry-related k-points is the same, the wavefunctions are not. Luckily, the wavefunctions of symmetry-related k-points are also symmetry-related, and we symmetrise the charge density (for each spin channel if spin-polarised) so that the charge density and energy is correct.

The symmetrisation of the charge density is done in reciprocal space. First, the charge density in the simulation cell is Fourier transformed to reciprocal space. Then, we apply the rotation operations in fractional coordinates to the indices of the G-vectors to find the indices of their symmetry-related counterparts,

\[\mathbf{G}_\mathrm{rot} = \mathbf{R} \mathbf{G}\]

where \(\mathbf{G}\) is the G-vector in reciprocal space. Finally, we extract the corresponding value of the charge density at the symmetry-related point in reciprocal space and perform a phase-weighted average. The phase is caused by the non-primitive cell translation part of the symmetry operation. And the whole process is repeated for each symmetry operation. Mathematically this can be expressed as:

\[n(\mathbf{G}) = \frac{1}{N} \sum_i^N n( \textbf{R}_i \mathbf{G})e^{i2 \pi \textbf{R}_i \mathbf{G}\cdot T_i}\]

We also leverage the fact that if the cell we are calculating is not primitive, we’ll have pure non-primitive translation operations, and if a G-vector is not commensurate with the total number of non-primitive translations, it will have zero amplitude so we can avoid applying symmetry operations to these G-vectors altogether.

Symmetry operations reductions

In ONETEP, the default crystal symmetry is detected by pseudopotential types instead of species labels. This ensures that if the symmetry is not broken even if user has specified different species labels for atoms with the same pseudopotential and initial configurations.

It is important to know that initial atomic configurations can affect the symmetry operations in a crystal. For example, the presence of certain magnetic moments can lead to the existence of additional symmetry operations - Time-reversal operations that swap the spin components of the wavefunctions.

In ONETEP, the entire crystal symmetry is lowered by treating the atoms that belong to the same species but have different initial configurations (e.g., magnetic moments) as if they belong to different species. Doing this allows the possibility for the lower symmetry magnetic structure (such as antiferromagnetic) to relax into a higher symmetry structure (such as ferrimagnetic).

This is done automatically by ONETEP when the use_symmetry keyword is set to True and SPECIES_ATOMIC_SET is used to specify different initial configurations for different atoms of the same species (how this is done is documented in Initial Guess Density: Setting initial charges and spins). If the initial configurations such as magnetic moments do change the symmetry, ONETEP will report the symmetry operations written:

Number of symmetry operations =          NUMBER
 (reduced by initial magmoms)

Compiling ONETEP with spglib

ONETEP now ships with spglib and can be enabled by BUILD_SPGLIB=yes, i.e.,

make onetep ARCH=YOUR_ARCH BUILD_SPGLIB=yes

This is by default turned on, and you can turn it off by setting BUILD_SPGLIB=no.

You can also change the C-compiler by setting the CC environment variable in your ARCH file, e.g.,

CC=gcc-11

Running ONETEP with symmetry

To run ONETEP with symmetry, the user only needs to set the use_symmetry keyword to True. To leverage the time-reversal symmetry to reduce the number of k-points, the use_time_reversal keyword can also be set to True.

One thing to note is that only MP grids set up by kpoint_grid_size will get symmetrised (i.e., reduced by applying symmetry). User-supplied k-point list (via block kpoints_list) will not be modified.

Once these tags are set (along with output_detail set to verbose), ONETEP will report the symmetry operations and the reduced k-points in the output file, and the symmetry-related k-points will be used in the calculation.

Keywords

  • use_symmetry: [Basic, bool, default F] Whether to use symmetry or not (only works if compiled with spglib)

  • use_time_reversal: [Basic, bool, define T] use TRS to reduce the number of k-points or not.

  • symmetry_tol: [Basic, float, default 0.001889726 Bohr (0.001 Å)] Precision in determining the symmetry.