# UnitCell¶

class `chemfiles::``UnitCell`

An UnitCell represent the box containing the atoms, and its periodicity

A unit cell is represented by the cell matrix, containing the three cell vectors:

```| a_x   b_x   c_x |
| a_y   b_y   c_y |
| a_z   b_z   c_z |
```

Public Types

enum `CellShape`

Possible shapes for the unit cell.

Values:

enumerator `ORTHORHOMBIC`

Orthorhombic cell, with the three angles equals to 90°

enumerator `TRICLINIC`

Triclinic cell, with any values for the angles.

enumerator `INFINITE`

Infinite cell, to use when there is no cell.

Public Functions

`UnitCell`()

Construct an `INFINITE` unit cell, with all lengths set to 0

```auto cell = UnitCell();

assert(cell.shape() == UnitCell::INFINITE);

assert(cell.lengths() == Vector3D(0, 0, 0));
assert(cell.angles() == Vector3D(90, 90, 90));
```

`UnitCell`(Vector3D lengths)

Construct an `ORTHORHOMBIC` unit cell with the given cell `lengths`

```auto cell = UnitCell({11, 22, 33});

assert(cell.shape() == UnitCell::ORTHORHOMBIC);

assert(cell.lengths() == Vector3D(11, 22, 33));
assert(cell.angles() == Vector3D(90, 90, 90));
```

`UnitCell`(Vector3D lengths, Vector3D angles)

Construct a unit cell with the given cell `lengths` and `angles`

If all lengths are set to 0, then the cell is `INFINITE`. If at least one length is not zero and all angles are 90.0, then the cell is `ORTHORHOMBIC`. Else a `TRICLINIC` cell is created.

```auto cell = UnitCell({11, 22, 33}, {80, 90, 70});

assert(cell.shape() == UnitCell::TRICLINIC);

assert(cell.lengths() == Vector3D(11, 22, 33));
assert(cell.angles() == Vector3D(80, 90, 70));
```

`UnitCell`(Matrix3D matrix)

Construct a unit cell from a cell matrix.

If `matrix` contains only zeros, then an infinite cell is created. If only the diagonal of the matrix is non-zero, then the cell is `ORTHORHOMBIC`. Else a `TRICLINIC` cell is created. The matrix entries should be in Angstroms.

```auto cell = UnitCell({
10, 0, 0,
0, 11, 0,
0, 0, 12
});

assert(cell.shape() == UnitCell::ORTHORHOMBIC);
assert(cell.lengths() == Vector3D(10, 11, 12));
assert(cell.angles() == Vector3D(90, 90, 90));
```

Matrix3D `matrix`() const

Get the cell matrix

```auto cell = UnitCell({11, 22, 33});
auto matrix = cell.matrix();

assert(matrix[0][0] == 11);
assert(matrix[1][1] == 22);
assert(matrix[2][2] == 33);

assert(fabs(matrix[0][1]) < 1e-12);
assert(fabs(matrix[0][2]) < 1e-12);
assert(fabs(matrix[1][2]) < 1e-12);

assert(fabs(matrix[1][0]) < 1e-12);
assert(fabs(matrix[2][0]) < 1e-12);
assert(fabs(matrix[2][1]) < 1e-12);
```

CellShape `shape`() const

Get the cell shape

```auto cell = UnitCell({11, 22, 33});
assert(cell.shape() == UnitCell::ORTHORHOMBIC);

cell.set_shape(UnitCell::TRICLINIC);
assert(cell.shape() == UnitCell::TRICLINIC);
```

void `set_shape`(CellShape shape)

Set the cell shape to `shape`

```auto cell = UnitCell({11, 22, 33});
assert(cell.shape() == UnitCell::ORTHORHOMBIC);

cell.set_shape(UnitCell::TRICLINIC);
assert(cell.shape() == UnitCell::TRICLINIC);
```

Exceptions
• `Error`: if `shape` is `ORTHORHOMBIC` and some angles are not 90°, or if `shape` is `INFINITE` and some lengths are not 0.0.

Vector3D `lengths`() const

Get the lengths of the cell’s vectors, in angstroms.

```auto cell = UnitCell({11, 22, 33});

assert(cell.lengths() == Vector3D(11, 22, 33));

cell.set_lengths({111, 222, 333});
assert(cell.lengths() == Vector3D(111, 222, 333));
```

Vector3D `angles`() const

Get the angles between the cell’s vectors in degrees

```auto cell = UnitCell({1, 1, 1}, {60, 80, 123});

// due to the way unit cell is stored, there can be a few floating point
// rounding error when accessing angles
auto angles = cell.angles();
assert(fabs(angles[0] - 60) < 1e-12);
assert(fabs(angles[1] - 80) < 1e-12);
assert(fabs(angles[2] - 123) < 1e-12);

cell.set_angles({91, 92, 93});
angles = cell.angles();
assert(fabs(angles[0] - 91) < 1e-12);
assert(fabs(angles[1] - 92) < 1e-12);
assert(fabs(angles[2] - 93) < 1e-12);
```

void `set_lengths`(Vector3D lengths)

Set the lengths of the cell’s vectors. The values should be in angstroms.

This function reset cell orientation!

After the call, the cell is aligned such that the first cell vector is along the x axis, and the second cell vector is in the xy plane.

```auto cell = UnitCell({11, 22, 33});

assert(cell.lengths() == Vector3D(11, 22, 33));

cell.set_lengths({111, 222, 333});
assert(cell.lengths() == Vector3D(111, 222, 333));
```

Exceptions
• `Error`: if the cell shape is `INFINITE`.

void `set_angles`(Vector3D angles)

Set the angles between the cell’s vectors. The values should be in degrees.

This function reset cell orientation!

After the call, the cell is aligned such that the first cell vector is along the x axis, and the second cell vector is in the xy plane.

```auto cell = UnitCell({1, 1, 1}, {60, 80, 123});

// due to the way unit cell is stored, there can be a few floating point
// rounding error when accessing angles
auto angles = cell.angles();
assert(fabs(angles[0] - 60) < 1e-12);
assert(fabs(angles[1] - 80) < 1e-12);
assert(fabs(angles[2] - 123) < 1e-12);

cell.set_angles({91, 92, 93});
angles = cell.angles();
assert(fabs(angles[0] - 91) < 1e-12);
assert(fabs(angles[1] - 92) < 1e-12);
assert(fabs(angles[2] - 93) < 1e-12);
```

Exceptions
• `Error`: if the cell shape is not `TRICLINIC`.

double `volume`() const

Get the unit cell volume

```auto cell = UnitCell({11, 22, 33});
assert(cell.volume() == 11 * 22 * 33);
```

Vector3D `wrap`(const Vector3D &vector) const

Wrap the `vector` in the unit cell, using periodic boundary conditions.

For an orthorhombic unit cell, this make sure that all the vector components are between `-L/2` and `L/2` where `L` is the corresponding cell length.

```auto cell = UnitCell({11, 22, 33});
auto wrapped = cell.wrap(Vector3D(14, -12, 5));
assert(wrapped == Vector3D(3, 10, 5));
```