# Tutorial¶

In this short tutorial, we will describe the mathematical notation used in the `symmetry-representation`

library, and show how the symmetry operations for InAs can be constructed.

## Notation¶

In general, the symmetries of a crystal can be described as a space group \(G\), with symmetry operations \(g \in G\). The real-space effect of a symmetry \(\{S_g | \boldsymbol{\alpha}_g \}\) (using the so-called Seitz notation) is given by

where \(S_g\) is a rotation matrix, and \(\boldsymbol{\alpha}_g\) is a translation vector.

For a Hamiltonian \(\mathcal{H}(\mathbf{k})\), the effect of these symmetries can be captured in the symmetry constraint

where \(D^\mathbf{k}(g)\) are the symmetry representations. The \(\mathbf{k}\) - dependence of these representations comes from the translational part of the symmetry operation, and can be expressed as

where \(D(g)\) is a \(\mathbf{k}\) - independent representation matrix. In the symmetry constraint, these \(\mathbf{k}\) - dependent phase factors cancel out:

For this reason, we consider only the \(\mathbf{k}\) - independent representation matrices \(D(g)\) in the symmetry-representation code.

Depending on the kind of symmetry operation, these representation matrices are either unitary or anti-unitary. That is, we can write them as either \(D(g) = U_g\) (unitary) or \(D(g) = U_g \hat{K}\) (anti-unitary), where \(U_g\) is a unitary matrix, and \(\hat{K}\) is the complex conjugation operator.

## The `SymmetryOperation`

and `SymmetryGroup`

classes¶

The main purpose of the symmetry-representation code is to provide classes which describe these symmetry operations and their representations. These can then be used by other codes, such as TBmodels or kdotp-symmetry. It also provides helper functions which allow for more easily constructing such symmetry operations.

Within symmetry-representation, symmetry operations are described using the `SymmetryOperation`

class. This class has the following parameters:

`rotation_matrix`

: The rotation matrix \(S_g\), in reduced coordinates.`translation_vector`

: The translation vector \(\boldsymbol{\alpha}_{g}\), in reduced coordinates.`repr_matrix`

: The matrix \(U_g\) of the representation matrix.`has_cc`

: A Boolean, which describes if the representation \(D(g)\) contains the complex conjugation operator \(\hat{K}\).

These symmetry operations can be combined into a group, using the `SymmetryGroup`

class. In addition to the list of symmetry operations, it has a Boolean parameter `full_group`

. This parameter describes if the symmetries given represent the full group (`True`

), or only a generating subset (`False`

).

## Automatic construction from orbitals¶

A common obstacle to creating such symmetry operations is that their representation matrices are not known. Commonly, only the shape of the orbitals which span the basis of a given model is known. For this case, symmetry-representation provides helper functions to create the symmetry operations directly from the orbitals, and real-space symmetry operations only.

Here, we show the use of these helper functions for the case of a model for InAs, with \(s\) and \(p\) orbitals located on the In atom, and \(p\) orbitals located on As. The first task is to create a list of orbitals in the model. Each orbital requires three inputs:

The position, in reduced coordinates.

The shape of the orbital, as a string which expresses the shape in terms of cartesian coordinates

`x`

,`y`

and`z`

.The spin of the orbital, as a

`Spin`

instance.

For the case of InAs, the following code constructs the correct orbitals:

```
In [1]: import symmetry_representation as sr
In [2]: pos_In = (0, 0, 0)
In [3]: pos_As = (0.25, 0.25, 0.25)
In [4]: orbitals = []
In [5]: for spin in (sr.SPIN_UP, sr.SPIN_DOWN):
...: orbitals.extend([
...: sr.Orbital(position=pos_In, function_string=fct, spin=spin)
...: for fct in sr.WANNIER_ORBITALS['s'] + sr.WANNIER_ORBITALS['p']
...: ])
...: orbitals.extend([
...: sr.Orbital(position=pos_As, function_string=fct, spin=spin)
...: for fct in sr.WANNIER_ORBITALS['p']
...: ])
...:
```

Here we used some pre-defined constants of the symmetry-representation code, namely the spins

```
In [6]: sr.SPIN_UP
Out[6]: Spin(total=Fraction(1, 2), z_component=Fraction(1, 2))
In [7]: sr.SPIN_DOWN
Out[7]: Spin(total=Fraction(1, 2), z_component=Fraction(-1, 2))
```

and the orbitals as created by the Wanier90 code

```
In [8]: sr.WANNIER_ORBITALS['s']
Out[8]: ['1']
In [9]: sr.WANNIER_ORBITALS['p']
Out[9]: ['z', 'x', 'y']
```

Having defined the orbitals, we also need to obtain the real-space symmetry operations of InAs. Since it has a symmorphic symmetry group, we only need rotation matrices, in both cartesian and reduced coordinates. We can use the pymatgen code to simplify this:

```
In [10]: import pymatgen as mg
In [11]: structure = mg.Structure(
....: lattice=[[0., 3.029, 3.029], [3.029, 0., 3.029], [3.029, 3.029, 0.]],
....: species=['In', 'As'],
....: coords=np.array([pos_In, pos_As])
....: )
....:
In [12]: analyzer = mg.symmetry.analyzer.SpacegroupAnalyzer(structure)
In [13]: sym_ops = analyzer.get_symmetry_operations(cartesian=False)
In [14]: sym_ops_cart = analyzer.get_symmetry_operations(cartesian=True)
```

And finally, we can use the symmetry group using the `from_orbitals()`

method of the `SymmetryOperation`

class:

```
In [15]: symmetry_group = sr.SymmetryGroup(
....: symmetries=[
....: sr.SymmetryOperation.from_orbitals(
....: orbitals=orbitals,
....: real_space_operator=sr.RealSpaceOperator.
....: from_pymatgen(sym_reduced),
....: rotation_matrix_cartesian=sym_cart.rotation_matrix,
....: numeric=True
....: ) for sym_reduced, sym_cart in zip(sym_ops, sym_ops_cart)
....: ],
....: full_group=True
....: )
....:
```

The `numeric`

flag determines whether `numpy`

arrays (`True`

) or `sympy`

matrices (`False`

) are created. The former are suited for use with the TBmodels code, while the latter should be used for kdotp-symmetry. Note that in order to create correct `sympy`

matrices, the real space matrices should also be sympy matrices.

Additionally, there is a special helper function to create a representation of the time-reversal symmetry operation:

```
In [16]: time_reversal = sr.get_time_reversal(orbitals=orbitals, numeric=True)
```