Function manipulating CHFL_FRAME

typedef struct CHFL_FRAME CHFL_FRAME

An opaque type handling frames.

A `CHFL_FRAME` contains data from one simulation step: the current unit cell, the topology, the positions, and the velocities of the particles in the system. If some information is missing (topology or velocity or unit cell), the corresponding data is filled with a default value.

CHFL_FRAME *chfl_frame(void)

Create a new empty frame.

The caller of this function should free the allocated memory using `chfl_frame_free`.

CHFL_FRAME* frame = chfl_frame();

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

chfl_frame_free(frame);
Return
A pointer to the frame, or NULL in case of error. You can use `chfl_last_error` to learn about the error.

CHFL_FRAME *chfl_frame_copy(const CHFL_FRAME *const frame)

Get a copy of a `frame`.

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

CHFL_FRAME* frame = chfl_frame();
CHFL_FRAME* copy = chfl_frame_copy(frame);

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

chfl_frame_free(copy);
chfl_frame_free(frame);
Return
A pointer to the new frame, or NULL in case of error. You can use `chfl_last_error` to learn about the error.

chfl_status chfl_frame_atoms_count(const CHFL_FRAME *const frame, uint64_t *natoms)

Get the current number of atoms in a `frame` in the integer pointed to by `natoms`

CHFL_FRAME* frame = chfl_frame();
chfl_frame_resize(frame, 42);

uint64_t atoms = 0;
chfl_frame_atoms_count(frame, &atoms);
assert(atoms == 42);

chfl_frame_free(frame);
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_frame_resize(CHFL_FRAME *const frame, uint64_t natoms)

Resize the positions, velocities and topology in the `frame`, to have space for `natoms` atoms.

This function may invalidate any pointer to the positions or the velocities if the new size is bigger than the old one. In all the cases, previous data is conserved. This function conserve the presence or absence of velocities.

CHFL_FRAME* frame = chfl_frame();

chfl_frame_resize(frame, 55);

uint64_t atoms = 0;
chfl_frame_atoms_count(frame, &atoms);
assert(atoms == 55);

chfl_frame_free(frame);
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_frame_add_atom(CHFL_FRAME *const frame, const CHFL_ATOM *const atom, const chfl_vector_t position, const chfl_vector_t velocity)

Add an `atom` and the corresponding `position` and `velocity` data to a `frame`.

`velocity` can be `NULL` if no velocity is associated with the atom.

CHFL_FRAME* frame = chfl_frame();
CHFL_ATOM* atom = chfl_atom("C");

chfl_frame_add_atom(frame, atom, (chfl_vector_t){1, 2, 3}, NULL);

chfl_atom_free(atom);
chfl_frame_free(frame);
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_frame_remove(CHFL_FRAME *const frame, uint64_t i)

Remove the atom at index `i` in the frame.

This modify all the atoms indexes after `i`, and invalidate any pointer obtained using `chfl_frame_positions` or `chfl_frame_velocities`.

CHFL_FRAME* frame = chfl_frame();
chfl_frame_resize(frame, 42);

uint64_t atoms = 0;
chfl_frame_atoms_count(frame, &atoms);
assert(atoms == 42);

chfl_frame_remove(frame, 37);
chfl_frame_remove(frame, 30);
chfl_frame_remove(frame, 15);

chfl_frame_atoms_count(frame, &atoms);
assert(atoms == 39);

chfl_frame_free(frame);
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_frame_positions(CHFL_FRAME *const frame, chfl_vector_t **positions, uint64_t *size)

Get a pointer to the positions array from a `frame`.

Positions are stored as a `natoms x 3` array, this function set the pointer pointed to by `positions` to point to the first element of this array, and give the number of atoms in the integer pointed to by `size`.

If the frame is resized (by writing to it, or calling `chfl_frame_resize`), the pointer is invalidated. If the frame is freed using `chfl_frame_free`, the pointer is freed too. There is then no need to free the `*positions` pointer for the caller of this function.

CHFL_FRAME* frame = chfl_frame();

chfl_vector_t* positions = NULL;
uint64_t natoms = 0;
chfl_frame_positions(frame, &positions, &natoms);

for (uint64_t i=0; i<natoms; i++) {
    // use positions[i] here
}

chfl_frame_free(frame);
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_frame_velocities(CHFL_FRAME *const frame, chfl_vector_t **velocities, uint64_t *size)

Get a pointer to the velocities array from a `frame`.

Velocities are stored as a `natoms x 3` array, this function set the pointer pointed to by `positions` to point to the first element of this array, and give the number of atoms in the integer pointed to by `size`.

If the frame is resized (by writing to it, or calling `chfl_frame_resize`), the pointer is invalidated. If the frame is freed using `chfl_frame_free`, the pointer is freed too. There is then no need to free the `*velocity` pointer for the caller of this function.

If the frame do not have velocity, this will return an error. Use `chfl_frame_add_velocities` to add velocities to a frame before calling this function.

CHFL_FRAME* frame = chfl_frame();
chfl_frame_add_velocities(frame);

chfl_vector_t* velocities = NULL;
uint64_t natoms = 0;
chfl_frame_positions(frame, &velocities, &natoms);

for (uint64_t i=0; i<natoms; i++) {
    // use velocities[i] here
}

chfl_frame_free(frame);
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_frame_has_velocities(const CHFL_FRAME *const frame, bool *has_velocities)

Check if this `frame` contains velocity data, and store the result in `has_velocities`

CHFL_FRAME* frame = chfl_frame();

bool velocities = true;
chfl_frame_has_velocities(frame, &velocities);
assert(velocities == false);

chfl_frame_free(frame);
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_frame_add_velocities(CHFL_FRAME *const frame)

Add velocity data to this `frame`.

The velocities ar initialized to `(chfl_vector_t){0, 0, 0}`. If the frame already has velocities, this does nothing.

CHFL_FRAME* frame = chfl_frame();

chfl_frame_add_velocities(frame);

bool velocities = false;
chfl_frame_has_velocities(frame, &velocities);
assert(velocities = true);

chfl_frame_free(frame);
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_frame_set_cell(CHFL_FRAME *const frame, const CHFL_CELL *const cell)

Set the unit cell of a `frame` to `cell`.

CHFL_FRAME* frame = chfl_frame();
CHFL_CELL* cell = chfl_cell((chfl_vector_t){10, 10, 12});

chfl_frame_set_cell(frame, cell);

chfl_cell_free(cell);
chfl_frame_free(frame);
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_frame_set_topology(CHFL_FRAME *const frame, const CHFL_TOPOLOGY *const topology)

Set the topology of a `frame` to `topology`.

Calling this function with a topology that does not contain the right number of atom will return an error.

CHFL_FRAME* frame = chfl_frame();

CHFL_TOPOLOGY* topology = chfl_topology();

{
    // Build the topology
    CHFL_ATOM* O = chfl_atom("O");
    CHFL_ATOM* H = chfl_atom("H");

    chfl_topology_add_atom(topology, O);
    chfl_topology_add_atom(topology, H);
    chfl_topology_add_atom(topology, H);

    chfl_atom_free(O);
    chfl_atom_free(H);
}

chfl_frame_set_topology(frame, topology);

chfl_topology_free(topology);
chfl_frame_free(frame);
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_frame_step(const CHFL_FRAME *const frame, uint64_t *step)

Get a `frame` step, *i.e.* the frame number in the trajectory in the integer pointed to by `step`.

CHFL_FRAME* frame = chfl_frame();

uint64_t step = 3;
chfl_frame_step(frame, &step);
assert(step == 0);

chfl_frame_free(frame);
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_frame_set_step(CHFL_FRAME *const frame, uint64_t step)

Set a `frame` step, *i.e.* the frame number in the trajectory to `step`.

CHFL_FRAME* frame = chfl_frame();

chfl_frame_set_step(frame, 678);

uint64_t step = 0;
chfl_frame_step(frame, &step);
assert(step == 678);

chfl_frame_free(frame);
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_frame_guess_topology(CHFL_FRAME *const frame)

Guess the bonds, angles and dihedrals in a `frame`.

The bonds are guessed using a distance-based algorithm, and then angles and dihedrals are guessed from the bonds.

// Building a frame containing a Cl2 molecule
CHFL_FRAME* frame = chfl_frame();

CHFL_ATOM* Cl = chfl_atom("Cl");
chfl_frame_add_atom(frame, Cl, (chfl_vector_t){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, Cl, (chfl_vector_t){2, 0, 0}, NULL);
chfl_atom_free(Cl);

// Check that the topology does not contain any bond
CHFL_TOPOLOGY* topology = chfl_topology_from_frame(frame);
uint64_t bonds = 0;
chfl_topology_bonds_count(topology, &bonds);
assert(bonds == 0);
chfl_topology_free(topology);

chfl_frame_guess_topology(frame);

// Get a copie of the new topology
topology = chfl_topology_from_frame(frame);
chfl_topology_bonds_count(topology, &bonds);
assert(bonds == 1);

chfl_topology_free(topology);
chfl_frame_free(frame);
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_frame_free(CHFL_FRAME *const frame)

Free the memory associated with a `frame`.

CHFL_FRAME* frame = chfl_frame();

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

chfl_frame_free(frame);
Return
`CHFL_SUCCESS`