Function manipulating CHFL_TOPOLOGY

typedef struct CHFL_TOPOLOGY CHFL_TOPOLOGY

An opaque type handling a topology.

A `CHFL_TOPOLOGY` contains the definition of all the atoms in the system, and the liaisons between the atoms (bonds, angles, dihedrals, ...). It will also contain all the residues information if it is available.

CHFL_TOPOLOGY *chfl_topology(void)

Create a new empty topology.

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

CHFL_TOPOLOGY* topology = chfl_topology();

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

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

CHFL_TOPOLOGY *chfl_topology_from_frame(const CHFL_FRAME *const frame)

Get a copy of the topology of a `frame`.

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

CHFL_FRAME* frame = chfl_frame();
CHFL_TOPOLOGY* topology = chfl_topology_from_frame(frame);

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

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

CHFL_TOPOLOGY *chfl_topology_copy(const CHFL_TOPOLOGY *const topology)

Get a copy of a `topology`.

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

CHFL_TOPOLOGY* topology = chfl_topology();

CHFL_ATOM* atom = chfl_atom("F");
chfl_topology_add_atom(topology, atom);
chfl_topology_add_atom(topology, atom);
chfl_topology_add_atom(topology, atom);
chfl_atom_free(atom);

CHFL_TOPOLOGY* copy = chfl_topology_copy(topology);

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

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

chfl_status chfl_topology_atoms_count(const CHFL_TOPOLOGY *const topology, uint64_t *natoms)

Get the number of atoms in the `topology` in the integer pointed to by `natoms`.

CHFL_TOPOLOGY* topology = chfl_topology();

CHFL_ATOM* atom = chfl_atom("F");
chfl_topology_add_atom(topology, atom);
chfl_topology_add_atom(topology, atom);
chfl_topology_add_atom(topology, atom);
chfl_atom_free(atom);

uint64_t atoms = 0;
chfl_topology_atoms_count(topology, &atoms);
assert(atoms == 3);

chfl_topology_free(topology);
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_topology_resize(CHFL_TOPOLOGY *const topology, uint64_t natoms)

Resize the `topology` to hold `natoms` atoms. If the new number of atoms is bigger than the current number, new atoms will be created with an empty name and type. If it is lower than the current number of atoms, the last atoms will be removed, together with the associated bonds, angles and dihedrals.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_resize(topology, 67);

uint64_t atoms = 0;
chfl_topology_atoms_count(topology, &atoms);
assert(atoms == 67);

chfl_topology_free(topology);
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_topology_add_atom(CHFL_TOPOLOGY *const topology, const CHFL_ATOM *const atom)

Add a copy of an `atom` at the end of a `topology`.

CHFL_TOPOLOGY* topology = chfl_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_topology_free(topology);
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_topology_remove(CHFL_TOPOLOGY *const topology, uint64_t i)

Remove the atom at index `i` from a `topology`.

This shifts all the atoms indexes after `i` by 1 (n becomes n-1).

CHFL_TOPOLOGY* topology = chfl_topology();

// Add a fex atoms to 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_topology_add_atom(topology, O);
chfl_atom_free(O);
chfl_atom_free(H);

uint64_t atoms = 0;
chfl_topology_atoms_count(topology, &atoms);
assert(atoms == 4);

chfl_topology_remove(topology, 2);

chfl_topology_atoms_count(topology, &atoms);
assert(atoms == 3);

chfl_topology_free(topology);
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_topology_add_bond(CHFL_TOPOLOGY *const topology, uint64_t i, uint64_t j)

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

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);

uint64_t bonds = 0;
chfl_topology_bonds_count(topology, &bonds);
assert(bonds == 1);

chfl_topology_free(topology);
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_topology_remove_bond(CHFL_TOPOLOGY *const topology, uint64_t i, uint64_t j)

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

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

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 1, 2);
chfl_topology_add_bond(topology, 2, 3);

uint64_t bonds = 0;
chfl_topology_bonds_count(topology, &bonds);
assert(bonds == 3);

chfl_topology_remove_bond(topology, 1, 2);

chfl_topology_bonds_count(topology, &bonds);
assert(bonds == 2);

chfl_topology_free(topology);
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_topology_isbond(const CHFL_TOPOLOGY *const topology, uint64_t i, uint64_t j, bool *result)

Check if the atoms at indexes `i` and `j` are bonded together, and store the result in `result`.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);

bool result = false;
chfl_topology_isbond(topology, 0, 1, &result);
assert(result == true);

chfl_topology_isbond(topology, 0, 2, &result);
assert(result == false);

chfl_topology_free(topology);
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_topology_isangle(const CHFL_TOPOLOGY *const topology, uint64_t i, uint64_t j, uint64_t k, bool *result)

Check if the atoms at indexes `i`, `j` and `k` form an angle, and store the result in `result`.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 1, 2);

bool result = false;
chfl_topology_isangle(topology, 0, 1, 2, &result);
assert(result == true);

chfl_topology_isangle(topology, 0, 2, 1, &result);
assert(result == false);

chfl_topology_free(topology);
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_topology_isdihedral(const CHFL_TOPOLOGY *const topology, uint64_t i, uint64_t j, uint64_t k, uint64_t m, bool *result)

Check if the atoms at indexes `i`, `j`, `k` and `m` form a dihedral angle, and store the result in `result`.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 1, 2);
chfl_topology_add_bond(topology, 2, 3);

bool result = false;
chfl_topology_isdihedral(topology, 0, 1, 2, 3, &result);
assert(result == true);

chfl_topology_isdihedral(topology, 0, 2, 1, 3, &result);
assert(result == false);

chfl_topology_free(topology);
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_topology_bonds_count(const CHFL_TOPOLOGY *const topology, uint64_t *nbonds)

Get the number of bonds in the `topology` in `nbonds`.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 2, 3);

uint64_t bonds = 0;
chfl_topology_bonds_count(topology, &bonds);
assert(bonds == 2);

chfl_topology_free(topology);
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_topology_angles_count(const CHFL_TOPOLOGY *const topology, uint64_t *nangles)

Get the number of angles in the `topology` in `nangles`.

CHFL_TOPOLOGY* topology = chfl_topology();

// We have two angles: 0-1-2 and 1-2-3
chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 1, 2);
chfl_topology_add_bond(topology, 2, 3);

uint64_t angles = 0;
chfl_topology_angles_count(topology, &angles);
assert(angles == 2);

chfl_topology_free(topology);
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_topology_dihedrals_count(const CHFL_TOPOLOGY *const topology, uint64_t *ndihedrals)

Get the number of dihedral angles in the `topology` in `ndihedrals`.

CHFL_TOPOLOGY* topology = chfl_topology();

// We have one dihedral angle: 0-1-2-3
chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 1, 2);
chfl_topology_add_bond(topology, 2, 3);

uint64_t dihedrals = 0;
chfl_topology_dihedrals_count(topology, &dihedrals);
assert(dihedrals == 1);

chfl_topology_free(topology);
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_topology_bonds(const CHFL_TOPOLOGY *const topology, uint64_t (*data)[2], uint64_t nbonds)

Get the list of bonds in the `topology` in the pre-allocated array `data` of size `nbonds`.

`data` size must be passed in the `nbonds` parameter, and be equal to the result of `chfl_topology_bonds_count`.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 2, 3);

uint64_t bonds[2][2] = {{0}};
chfl_topology_bonds(topology, bonds, 2);
assert(bonds[0][0] == 0);
assert(bonds[0][1] == 1);

assert(bonds[1][0] == 2);
assert(bonds[1][1] == 3);

chfl_topology_free(topology);
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_topology_angles(const CHFL_TOPOLOGY *const topology, uint64_t (*data)[3], uint64_t nangles)

Get the list of angles in the `topology` in the pre-allocated array `data` of size `nangles`.

`data` size must be passed in the `nangles` parameter, and be equal to the result of `chfl_topology_angles_count`.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 1, 2);
chfl_topology_add_bond(topology, 2, 3);

uint64_t angles[2][3] = {{0}};
chfl_topology_angles(topology, angles, 2);
assert(angles[0][0] == 0);
assert(angles[0][1] == 1);
assert(angles[0][2] == 2);

assert(angles[1][0] == 1);
assert(angles[1][1] == 2);
assert(angles[1][2] == 3);

chfl_topology_free(topology);
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_topology_dihedrals(const CHFL_TOPOLOGY *const topology, uint64_t (*data)[4], uint64_t ndihedrals)

Get the list of dihedral angles in the `topology` in the pre-allocated array `data` of size `ndihedrals`.

`data` size must be passed in the `ndihedrals` parameter, and be equal to the result of `chfl_topology_dihedrals_count`.

CHFL_TOPOLOGY* topology = chfl_topology();

chfl_topology_add_bond(topology, 0, 1);
chfl_topology_add_bond(topology, 1, 2);
chfl_topology_add_bond(topology, 2, 3);

uint64_t dihedrals[1][4] = {{0}};
chfl_topology_dihedrals(topology, dihedrals, 1);
assert(dihedrals[0][0] == 0);
assert(dihedrals[0][1] == 1);
assert(dihedrals[0][2] == 2);
assert(dihedrals[0][3] == 3);

chfl_topology_free(topology);
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_topology_add_residue(CHFL_TOPOLOGY *const topology, const CHFL_RESIDUE *const residue)

Add a copy of `residue` to this `topology`.

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

CHFL_TOPOLOGY* topology = chfl_topology();
CHFL_RESIDUE* residue = chfl_residue("res", 1);

chfl_topology_add_residue(topology, residue);

chfl_residue_free(residue);
chfl_topology_free(topology);
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_topology_residues_count(const CHFL_TOPOLOGY *const topology, uint64_t *nresidues)

Get the number of residues in the `topology` in the integer pointed to by `nresidues`.

CHFL_TOPOLOGY* topology = chfl_topology();

CHFL_RESIDUE* residue = chfl_residue("res", 1);
chfl_topology_add_residue(topology, residue);
chfl_residue_free(residue);

uint64_t residues = 0;
chfl_topology_residues_count(topology, &residues);
assert(residues == 1);

chfl_topology_free(topology);
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_topology_residues_linked(const CHFL_TOPOLOGY *const topology, const CHFL_RESIDUE *const first, const CHFL_RESIDUE *const second, bool *result)

Check if the two residues `first` and `second` from the `topology` are linked together, *i.e.* if there is a bond between one atom in the first residue and one atom in the second one, and store the result in `result.`

CHFL_TOPOLOGY* topology = chfl_topology();

// Build the topology ...

CHFL_RESIDUE* first = chfl_residue_from_topology(topology, 0);
CHFL_RESIDUE* second = chfl_residue_from_topology(topology, 1);

bool linked = false;
chfl_topology_residues_linked(topology, first, second, &linked);

chfl_residue_free(first);
chfl_residue_free(second);

chfl_topology_free(topology);
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_topology_free(CHFL_TOPOLOGY *const topology)

Free the memory associated with a `topology`.

CHFL_TOPOLOGY* topology = chfl_topology();

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

chfl_topology_free(topology);
Return
`CHFL_SUCCESS`