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.

Here is the full list of functions acting on CHFL_FRAME:


CHFL_FRAME *chfl_frame(void)

Create a new empty frame.

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

CHFL_FRAME* frame = chfl_frame();

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

chfl_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 *frame)

Get a copy of a frame.

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

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

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

chfl_free(copy);
chfl_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 *frame, uint64_t *count)

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

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

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

chfl_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 *frame, uint64_t size)

Resize the positions, velocities and topology in the frame, to have space for size 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_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 *frame, const CHFL_ATOM *atom, const chfl_vector3d position, const chfl_vector3d 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_vector3d){1, 2, 3}, NULL);

chfl_free(atom);
chfl_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 *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_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 *frame, chfl_vector3d **positions, uint64_t *size)

Get a pointer to the positions array from a frame.

Positions are stored as a size 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, chfl_frame_remove or chfl_frame_add_atom), the pointer is invalidated.

If the frame memory is released using chfl_free, the memory behind the *positions pointer is released too.

CHFL_FRAME* frame = chfl_frame();

chfl_vector3d* 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_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 *frame, chfl_vector3d **velocities, uint64_t *size)

Get a pointer to the velocities array from a frame.

Velocities are stored as a size x 3 array, this function set the pointer pointed to by velocities 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, chfl_frame_remove or chfl_frame_add_atom), the pointer is invalidated.

If the frame memory is released using chfl_free, the memory behind the *velocities pointer is released too.

If the frame does not have velocity, this will return an error. You can use chfl_frame_add_velocities to ensure that a frame contains velocity data before calling this function.

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

chfl_vector3d* 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_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 *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_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 *frame)

Add velocity data to this frame.

The velocities are initialized to (chfl_vector3d){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_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 *frame, const CHFL_CELL *cell)

Set the unit cell of a frame to cell.

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

chfl_frame_set_cell(frame, cell);

chfl_free(cell);
chfl_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 *frame, const CHFL_TOPOLOGY *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_free(O);
    chfl_free(H);
}

chfl_frame_set_topology(frame, topology);

chfl_free(topology);
chfl_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_bond(CHFL_FRAME *frame, uint64_t i, uint64_t j)

Add a bond between the atoms at indexes i and j in the frame.

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

chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 1.2}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, -1.0}, NULL);
chfl_frame_add_bond(frame, 0, 1);
chfl_frame_bond_with_order(frame, 0, 2, CHFL_BOND_DOUBLE);

chfl_free(atom);
chfl_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_bond_with_order(CHFL_FRAME *frame, uint64_t i, uint64_t j, chfl_bond_order bond_order)

Add a bond between the atoms at indexes i and j with bond order bond_order in the frame.

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

chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 1.2}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, -1.0}, NULL);
chfl_frame_add_bond(frame, 0, 1);
chfl_frame_bond_with_order(frame, 0, 2, CHFL_BOND_DOUBLE);

chfl_free(atom);
chfl_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_bond(CHFL_FRAME *frame, uint64_t i, uint64_t j)

Remove any existing bond between the atoms at indexes i and j in the frame.

This function does nothing if there is no bond between i and j.

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

chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){1, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 1, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 1}, NULL);

chfl_frame_add_bond(frame, 0, 1);
chfl_frame_add_bond(frame, 0, 3);
chfl_frame_add_bond(frame, 2, 1);

chfl_frame_remove_bond(frame, 0, 1);
chfl_frame_remove_bond(frame, 1, 2);
// Removing non-existing bond
chfl_frame_remove_bond(frame, 2, 3);

chfl_free(atom);
chfl_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_residue(CHFL_FRAME *frame, const CHFL_RESIDUE *residue)

Add a copy of residue to this frame.

The residue id must not already be in this frame’s topology, and the residue must contain only atoms that are not already in another residue.

CHFL_FRAME* frame = chfl_frame();
CHFL_RESIDUE* residue = chfl_residue("res");

chfl_frame_add_residue(frame, residue);

chfl_free(residue);
chfl_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 *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_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 *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_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_bonds(CHFL_FRAME *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_vector3d){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, Cl, (chfl_vector3d){2, 0, 0}, NULL);
chfl_free(Cl);

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

chfl_frame_guess_bonds(frame);

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

chfl_free(topology);
chfl_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_distance(const CHFL_FRAME *frame, uint64_t i, uint64_t j, double *distance)

Get the distance between the atoms at indexes i and j in the frame, accounting for periodic boundary conditions. The result is placed in distance, and expressed in angstroms.

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

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

double distance = 0;
chfl_frame_distance(frame, 0, 1, &distance);
assert(distance == sqrt(14));

chfl_free(atom);
chfl_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_angle(const CHFL_FRAME *frame, uint64_t i, uint64_t j, uint64_t k, double *angle)

Get the angle formed by the atoms at indexes i, j and k in the frame, accounting for periodic boundary conditions. The result is placed in angle, and expressed in radians.

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

chfl_frame_add_atom(frame, atom, (chfl_vector3d){1, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 1, 0}, NULL);

double angle = 0;
chfl_frame_angle(frame, 0, 1, 2, &angle);
assert(fabs(angle - M_PI / 2) < 1e-12);

chfl_free(atom);
chfl_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_dihedral(const CHFL_FRAME *frame, uint64_t i, uint64_t j, uint64_t k, uint64_t m, double *dihedral)

Get the angle formed by the atoms at indexes i, j, k and m in the frame, accounting for periodic boundary conditions. The result is placed in dihedral, and expressed in radians.

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

chfl_frame_add_atom(frame, atom, (chfl_vector3d){1, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 1, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 1, 1}, NULL);

double dihedral = 0;
chfl_frame_dihedral(frame, 0, 1, 2, 3, &dihedral);
assert(fabs(dihedral - M_PI / 2) < 1e-12);

chfl_free(atom);
chfl_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_out_of_plane(const CHFL_FRAME *frame, uint64_t i, uint64_t j, uint64_t k, uint64_t m, double *distance)

Get the out of plane distance formed by the atoms at indexes i, j, k and m in the frame, accounting for periodic boundary conditions. The result is placed in distance and expressed in angstroms.

This is the distance betweent the atom j and the ikm plane. The j atom is the center of the improper dihedral angle formed by i, j, k and m.

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

chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 0, 2}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){1, 0, 0}, NULL);
chfl_frame_add_atom(frame, atom, (chfl_vector3d){0, 1, 0}, NULL);

double distance = 0;
chfl_frame_out_of_plane(frame, 0, 1, 2, 3, &distance);
assert(fabs(distance - 2) < 1e-12);

chfl_free(atom);
chfl_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_property(CHFL_FRAME *frame, const char *name, const CHFL_PROPERTY *property)

Add a new property with the given name to this frame.

If a property with the same name already exists, this function override the existing property with the new one.

CHFL_FRAME* frame = chfl_frame();
CHFL_PROPERTY* property = chfl_property_double(-23);

chfl_frame_set_property(frame, "this", property);
chfl_free(property);

property = chfl_frame_get_property(frame, "this");

double value = 0;
chfl_property_get_double(property, &value);
assert(value == -23);

chfl_free(property);
chfl_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_PROPERTY *chfl_frame_get_property(const CHFL_FRAME *frame, const char *name)

Get a property with the given name in this frame.

This function returns NULL if no property exists with the given name.

The user of this function is responsible to deallocate memory using the chfl_free function.

CHFL_FRAME* frame = chfl_frame();
CHFL_PROPERTY* property = chfl_property_double(-23);

chfl_frame_set_property(frame, "this", property);
chfl_free(property);

property = chfl_frame_get_property(frame, "this");

double value = 0;
chfl_property_get_double(property, &value);
assert(value == -23);

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

chfl_status chfl_frame_properties_count(const CHFL_FRAME *frame, uint64_t *count)

Get the number of properties associated with this frame in count.

CHFL_FRAME* frame = chfl_frame();
CHFL_PROPERTY* property = chfl_property_double(-23);

chfl_frame_set_property(frame, "this", property);
chfl_frame_set_property(frame, "that", property);
chfl_free(property);

uint64_t count = 0;
chfl_frame_properties_count(frame, &count);
assert(count == 2);

chfl_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_list_properties(const CHFL_FRAME *frame, const char *names[], uint64_t count)

Get the names of all properties of this frame in the pre-allocated array names of size count.

names size must be passed in the count parameter, and be equal to the result of chfl_frame_properties_count.

The pointers in names are only valid until a new property is added to the frame with chfl_frame_set_property.

CHFL_FRAME* frame = chfl_frame();
CHFL_PROPERTY* property = chfl_property_double(-23);

chfl_frame_set_property(frame, "this", property);
chfl_frame_set_property(frame, "that", property);
chfl_free(property);

uint64_t count = 0;
chfl_frame_properties_count(frame, &count);
assert(count == 2);

const char* names[2] = {NULL};
chfl_frame_list_properties(frame, names, count);

// Properties are not ordered
assert(strcmp(names[0], "this") == 0 || strcmp(names[0], "that") == 0);
assert(strcmp(names[1], "this") == 0 || strcmp(names[1], "that") == 0);

chfl_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.