# `CHFL_CELL`¶

typedef struct CHFL_CELL `CHFL_CELL`

An opaque type handling an unit cell.

A `CHFL_CELL` represent the box containing the atoms, and its periodicity.

An unit cell is fully represented by three lengths (a, b, c); and three angles (alpha, beta, gamma). The angles are stored in degrees, and the lengths in Angstroms.

A cell also has a matricial representation, by projecting the three base vector into an orthonormal base. We choose to represent such matrix as an upper triangular matrix:

```| a_x   b_x   c_x |
|  0    b_y   c_y |
|  0     0    c_z |
```

Here is the full list of functions acting on `CHFL_CELL`:

CHFL_CELL *`chfl_cell`(const chfl_vector3d lengths, const chfl_vector3d angles)

Create an unit cell using the optional `lengths` and `angles` parameters

If both `lengths` and `angles` are NULL, this creates an infinite unit cell. If `angles` is NULL, it defaults to `[90, 90, 90]`.

The shape of the cell depends on the angles: it will be ORTHORHOMBIC if the three angles are 90°, TRICLINIC otherwise.

The cell lengths should be in Angstroms, and the angles in degree.

The caller of this function should free the associated memory using `chfl_free`.

```/* Orthorhombic cell */
CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);

if (cell == NULL) { /* handle error */ }

chfl_free(cell);

/* Triclinic cell */
cell = chfl_cell((chfl_vector3d){10, 10, 10}, (chfl_vector3d){92, 88, 100});

if (cell == NULL) { /* handle error */ }

chfl_free(cell);
```

Return

A pointer to the unit cell, or NULL in case of error. You can use `chfl_last_error` to learn about the error.

CHFL_CELL *`chfl_cell_from_matrix`(const chfl_vector3d matrix)

Create an unit cell from the unit 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.

The caller of this function should free the associated memory using `chfl_free`.

```chfl_vector3d matrix = {
{10, 0, 0},
{0, 12, 0},
{0, 0, 15}
};

CHFL_CELL* cell = chfl_cell_from_matrix(matrix);

chfl_vector3d lengths;
chfl_cell_lengths(cell, lengths);
assert(lengths == 10);
assert(lengths == 12);
assert(lengths == 15);

chfl_free(cell);
```

Return

A pointer to the unit cell, or NULL in case of error. You can use `chfl_last_error` to learn about the error.

CHFL_CELL *`chfl_cell_from_frame`(CHFL_FRAME *frame)

Get access to the cell of a `frame`

Any modification to the cell will be reflected in the `frame`. The `frame` will be kept alive, even if `chfl_free(frame)` is called, until `chfl_free` is also called on the pointer returned by this function.

If `chfl_frame_set_cell` is called, this pointer will point to the new cell.

```CHFL_FRAME* frame = chfl_frame();
CHFL_CELL* cell = chfl_cell_from_frame(frame);

if (cell == NULL) {
/* handle error */
}

chfl_free(cell);
chfl_free(frame);
```

Return

A pointer to the unit cell, or NULL in case of error. You can use `chfl_last_error` to learn about the error.

CHFL_CELL *`chfl_cell_copy`(const CHFL_CELL *cell)

Get a copy of a `cell`.

The caller of this function should free the associated memory using `chfl_free`.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);
CHFL_CELL* copy = chfl_cell_copy(cell);

if (copy == NULL) {
/* handle error */
}

chfl_free(copy);
chfl_free(cell);
```

Return

A pointer to the new cell, or NULL in case of error. You can use `chfl_last_error` to learn about the error.

chfl_status `chfl_cell_volume`(const CHFL_CELL *cell, double *volume)

Get the unit cell volume of `cell` in the double pointed to by `volume`.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);

double volume = 0;
chfl_cell_volume(cell, &volume);
assert(volume == 1000);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

chfl_status `chfl_cell_lengths`(const CHFL_CELL *cell, chfl_vector3d lengths)

Get the unit cell lengths in `lengths`. The cell lengths are in Angstroms.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 11, 12}, NULL);

chfl_vector3d lengths = {0, 0, 0};
chfl_cell_lengths(cell, lengths);
assert(lengths == 10);
assert(lengths == 11);
assert(lengths == 12);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

chfl_status `chfl_cell_set_lengths`(CHFL_CELL *cell, const chfl_vector3d lengths)

Set the unit cell lengths to `lengths`.

The cell lengths 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.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);

chfl_cell_set_lengths(cell, (chfl_vector3d){42, 8, 3});

chfl_vector3d lengths = {0, 0, 0};
chfl_cell_lengths(cell, lengths);
assert(lengths == 42);
assert(lengths == 8);
assert(lengths == 3);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

chfl_status `chfl_cell_angles`(const CHFL_CELL *cell, chfl_vector3d angles)

Get the cell angles in `angles`. The cell angles are in degrees.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);

chfl_vector3d angles = {0, 0, 0};
chfl_cell_angles(cell, angles);
assert(angles == 90);
assert(angles == 90);
assert(angles == 90);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

chfl_status `chfl_cell_set_angles`(CHFL_CELL *cell, const chfl_vector3d angles)

Set the cell angles to `angles`.

The cell lengths should be in degree. Trying to set cell angles on a cell which is not triclinic (does not have the `CHFL_CELL_TRICLINIC` shape) is an error.

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.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);
chfl_cell_set_shape(cell, CHFL_CELL_TRICLINIC);

chfl_cell_set_angles(cell, (chfl_vector3d){120, 110, 100});

chfl_vector3d angles = {0, 0, 0};
chfl_cell_angles(cell, angles);
// Floating point rounding error can exist when accessing angles
assert(fabs(angles - 120) < 1e-12);
assert(fabs(angles - 110) < 1e-12);
assert(fabs(angles - 100) < 1e-12);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

chfl_status `chfl_cell_matrix`(const CHFL_CELL *cell, chfl_vector3d matrix)

Get the unit `cell` matricial representation in `matrix`.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 11, 12}, NULL);

chfl_vector3d matrix;
chfl_cell_matrix(cell, matrix);
assert(matrix == 10);
assert(matrix == 11);
assert(matrix == 12);

// Out of diagonal terms are zero
assert(matrix == 0);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

enum `chfl_cellshape`

Available cell shapes in chemfiles.

Values:

enumerator `CHFL_CELL_ORTHORHOMBIC`

The three angles are 90°

enumerator `CHFL_CELL_TRICLINIC`

The three angles may not be 90°

enumerator `CHFL_CELL_INFINITE`

Cell shape when there is no periodic boundary conditions.

chfl_status `chfl_cell_shape`(const CHFL_CELL *cell, chfl_cellshape *shape)

Get the unit `cell` shape in `shape`.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);

chfl_cellshape shape;
chfl_cell_shape(cell, &shape);
assert(shape == CHFL_CELL_ORTHORHOMBIC);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

chfl_status `chfl_cell_set_shape`(CHFL_CELL *cell, chfl_cellshape shape)

Set the unit `cell` shape to `shape`.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);

chfl_cell_set_shape(cell, CHFL_CELL_TRICLINIC);

chfl_cellshape shape;
chfl_cell_shape(cell, &shape);
assert(shape == CHFL_CELL_TRICLINIC);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.

chfl_status `chfl_cell_wrap`(const CHFL_CELL *cell, chfl_vector3d vector)

Wrap a `vector` in the unit `cell`.

```CHFL_CELL* cell = chfl_cell((chfl_vector3d){10, 10, 10}, NULL);

chfl_vector3d position = {4, 12, -18};
chfl_cell_wrap(cell, position);

assert(position == 4);
assert(position == 2);
assert(position == 2);

chfl_free(cell);
```

Return

The operation status code. You can use `chfl_last_error` to learn about the error if the status code is not `CHFL_SUCCESS`.