Niggli cell

Usage of the code

The code is written in C and a python wrapper is prepared in python directory. The C code is used to compile with your code. Usual library interface is not prepared. The python code is used as a module. To use this, numpy is required.

In both C and python codes, there are two input arguments, lattice and eps. lattice is a double array with nine elements,

(a_x, b_x, c_x, a_y, b_y, c_y, a_z, b_z, c_z).

In python, the input array will be fattened in the module. Therefore, e.g., the following 3\times 3 shape of a numpy array or a python list is accepted:

\begin{pmatrix}
a_x & b_x & c_x \\
a_y & b_y & c_y \\
a_z & b_z & c_z \\
\end{pmatrix}.

The double variable of eps is used as the tolerance parameter. The value should be much smaller than lattice parameters, e.g., 1e-8. How it works is shown in the following section.

Test

The test is found in python directory as a python code. A set of lattice parameters is found in lattices.dat and the references, which are the reduced lattice parameter made in the version 0.1.1, are stored in reduced_lattices.dat.

Example

An example is found in python directory as a python code.

Algorithm to determine Niggli cell

Reference

  1. A Unified Algorithm for Determining the Reduced (Niggli) Cell, I. Krivý and B. Gruber, Acta Cryst., A32, 297-298 (1976)
  2. The Relationship between Reduced Cells in a General Bravais lattice, B. Gruber, Acta Cryst., A29, 433-440 (1973)
  3. Numerically stable algorithms for the computation of reduced unit cells, R. W. Grosse-Kunstleve, N. K. Sauter and P. D. Adams, Acta Cryst., A60, 1-6 (2004)

Algorithm

Update variables

The following variables used in this algorithm are initialized at the beginning of the algorithm and updated at the every end of A1-8 steps.

Define following variables as

&A = \mathbf{a}\cdot\mathbf{a}\\
&B = \mathbf{b}\cdot\mathbf{b}\\
&C = \mathbf{c}\cdot\mathbf{c}\\
&\xi=2\mathbf{b}\cdot\mathbf{c}\\
&\eta=2\mathbf{c}\cdot\mathbf{a}\\
&\zeta=2\mathbf{a}\cdot\mathbf{b}.

They are elements of metric tensor where the off-diagonal elements are doubled. Therefore the metric tensor \mathbf{G} is represented as

\mathbf{G} =
\begin{pmatrix}
A & \zeta/2 & \eta/2 \\
\zeta/2 & B & \xi/2 \\
\eta/2 & \xi/2 & C
\end{pmatrix}.

\xi, \eta, \zeta are sorted by their ranges of angles as shown below.

Angle value
Acute 1
Obtuse -1
Right 0

These values are stored in variables l, m, n as follows.

  • Set initially l=m=n=0.
  • If \xi<-\varepsilon, l=-1.
  • If \xi>\varepsilon, l=1.
  • If \eta<-\varepsilon, m=-1.
  • If \eta>\varepsilon, m=1.
  • If \zeta<-\varepsilon, n=-1.
  • If \zeta>\varepsilon, n=1.

\mathbf{C} found in each step is the transformation matrix that is applied to basis vectors:

(\mathbf{a}', \mathbf{b}', \mathbf{c}') = (\mathbf{a}, \mathbf{b}, \mathbf{c})\mathbf{C}.

A1

If A > B + \varepsilon or (\overline{|A-B|>\varepsilon} and |\xi|>|\eta| + \varepsilon),

\mathbf{C} =
\begin{pmatrix}
0 & -1 & 0 \\
-1 & 0 & 0 \\
0 & 0 & -1 \\
\end{pmatrix}.

A2

If B > C + \varepsilon or (\overline{|B-C|>\varepsilon} and |\eta|>|\zeta| + \varepsilon),

\mathbf{C} =
\begin{pmatrix}
-1 & 0 & 0 \\
0 & 0 & -1 \\
0 & -1 & 0 \\
\end{pmatrix}.

Go to A1.

A3

If lmn = 1:

  • i=-1 if l=-1 else i=1
  • j=-1 if m=-1 else j=1
  • k=-1 if n=-1 else k=1

\mathbf{C} =
\begin{pmatrix}
i & 0 & 0 \\
0 & j & 0 \\
0 & 0 & k \\
\end{pmatrix}.

A4

If l=-1, m=-1, and n=-1, do nothing in A4.

If lmn = 0 or lmn = -1:

Set i=j=k=1. r is used as a reference to i, j, or k, and is initially undefined.

  • i=-1 if l=1
  • r\rightarrow i if l=0
  • j=-1 if m=1
  • r\rightarrow j if j=0
  • k=-1 if n=1
  • r\rightarrow k if k=0

If ijk=-1:

  • i, j, or k refered by r is set to -1.

\mathbf{C} =
\begin{pmatrix}
i & 0 & 0 \\
0 & j & 0 \\
0 & 0 & k \\
\end{pmatrix}.

A5

If |\xi|>B + \varepsilon or (\overline{|B - \xi| > \varepsilon} and 2\eta< \zeta
-\varepsilon) or (\overline{|B + \xi| > \varepsilon} and \zeta< -\varepsilon):

\mathbf{C} =
\begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & -\mathrm{sign}(\xi) \\
0 & 0 & 1 \\
\end{pmatrix}.

Go to A1.

A6

If |\eta|>A + \varepsilon or (\overline{|A - \eta| > \varepsilon} and 2\xi < \zeta -\varepsilon) or (\overline{|A + \eta| >
\varepsilon} and \zeta< -\varepsilon):

\mathbf{C} =
\begin{pmatrix}
1 & 0 & -\mathrm{sign}(\eta) \\
0 & 1 & 0 \\
0 & 0 & 1 \\
\end{pmatrix}.

Go to A1.

A7

If |\zeta|>A + \varepsilon or (\overline{|A - \zeta| > \varepsilon},
2\xi < \eta -\varepsilon) or (\overline{|A + \zeta| > \varepsilon} and \eta< -\varepsilon):

\mathbf{C} =
\begin{pmatrix}
1 & -\mathrm{sign}(\zeta) & 0 \\
0 & 1 & 0 \\
0 & 0 & 1 \\
\end{pmatrix}.

Go to A1.

A8

If \xi + \eta + \zeta + A + B < -\varepsilon or (\overline{|\xi +
\eta + \zeta + A + B| > \varepsilon} and 2(A + \eta) + \zeta > \varepsilon):

\mathbf{C} =
\begin{pmatrix}
1 & 0 & 1 \\
0 & 1 & 1 \\
0 & 0 & 1 \\
\end{pmatrix}.

Go to A1.