Defining systems

There are two ways you can define systems to pass to rascal_calculator_compute(): the easy way is to use rascal_basic_systems_read() to read all systems defined in a file, and run the calculation on all these systems. The more complex but also more flexible way is to create a rascal_system_t manually, implementing all required functions; and then passing one or more systems to rascal_calculator_compute().

struct rascal_system_t

A rascal_system_t deals with the storage of atoms and related information, as well as the computation of neighbor lists.

This struct contains a manual implementation of a virtual table, allowing to implement the rust System trait in C and other languages. Speaking in Rust terms, user_data contains a pointer (analog to Box<Self>) to the struct implementing the System trait; and then there is one function pointers (Option<unsafe extern fn(XXX)>) for each function in the System trait.

The rascal_status_t return value for the function is used to communicate error messages. It should be 0/RASCAL_SUCCESS in case of success, any non-zero value in case of error. The error will be propagated to the top-level caller as a RASCAL_SYSTEM_ERROR

A new implementation of the System trait can then be created in any language supporting a C API (meaning any language for our purposes); by correctly setting user_data to the actual data storage, and setting all function pointers to the correct functions. For an example of code doing this, see the SystemBase class in the Python interface to rascaline.

WARNING: all function implementations MUST be thread-safe, function taking const pointer parameters can be called from multiple threads at the same time. The rascal_system_t itself might be moved from one thread to another.

Public Members

void *user_data

User-provided data should be stored here, it will be passed as the first parameter to all function pointers below.

rascal_status_t (*size)(const void *user_data, uintptr_t *size)

This function should set *size to the number of atoms in this system

rascal_status_t (*types)(const void *user_data, const int32_t **types)

This function should set *types to a pointer to the first element of a contiguous array containing the atomic types of each atom in the system. Different atomic types should be identified with a different value. These values are usually the atomic number, but don’t have to be. The array should contain rascal_system_t::size() elements.

rascal_status_t (*positions)(const void *user_data, const double **positions)

This function should set *positions to a pointer to the first element of a contiguous array containing the atomic cartesian coordinates. positions[0], positions[1], positions[2] must contain the x, y, z cartesian coordinates of the first atom, and so on.

rascal_status_t (*cell)(const void *user_data, double *cell)

This function should write the unit cell matrix in cell, which have space for 9 values. The cell should be written in row major order, i.e. ax ay az bx by bz cx cy cz, where a/b/c are the unit cell vectors.

rascal_status_t (*compute_neighbors)(void *user_data, double cutoff)

This function should compute the neighbor list with the given cutoff, and store it for later access using pairs or pairs_containing.

rascal_status_t (*pairs)(const void *user_data, const struct rascal_pair_t **pairs, uintptr_t *count)

This function should set *pairs to a pointer to the first element of a contiguous array containing all pairs in this system; and *count to the size of the array/the number of pairs.

This list of pair should only contain each pair once (and not twice as i-j and j-i), should not contain self pairs (i-i); and should only contains pairs where the distance between atoms is actually bellow the cutoff passed in the last call to compute_neighbors. This function is only valid to call after a call to compute_neighbors.

rascal_status_t (*pairs_containing)(const void *user_data, uintptr_t atom, const struct rascal_pair_t **pairs, uintptr_t *count)

This function should set *pairs to a pointer to the first element of a contiguous array containing all pairs in this system containing the atom with index atom; and *count to the size of the array/the number of pairs.

The same restrictions on the list of pairs as rascal_system_t::pairs applies, with the additional condition that the pair i-j should be included both in the return of pairs_containing(i) and pairs_containing(j).

struct rascal_pair_t

Pair of atoms coming from a neighbor list

Public Members

uintptr_t first

index of the first atom in the pair

uintptr_t second

index of the second atom in the pair

double distance

distance between the two atoms

double vector[3]

vector from the first atom to the second atom, accounting for periodic boundary conditions. This should be position[second] - position[first] + H * cell_shift where H is the cell matrix.

int32_t cell_shift_indices[3]

How many cell shift where applied to the second atom to create this pair.


rascal_status_t rascal_basic_systems_read(const char *path, struct rascal_system_t **systems, uintptr_t *count)

Read all structures in the file at the given path using chemfiles, and convert them to an array of rascal_system_t.

This function can read all formats supported by chemfiles.

This function allocates memory, which must be released using rascal_basic_systems_free.

If you need more control over the system behavior, consider writing your own instance of rascal_system_t.

Parameters:
  • path – path of the file to read from in the local filesystem

  • systems*systems will be set to a pointer to the first element of the array of rascal_system_t

  • count*count will be set to the number of systems read from the file

Returns:

The status code of this operation. If the status is not RASCAL_SUCCESS, you can use rascal_last_error() to get the full error message.

rascal_status_t rascal_basic_systems_free(struct rascal_system_t *systems, uintptr_t count)

Release memory allocated by rascal_basic_systems_read.

This function is only valid to call with a pointer to systems obtained from rascal_basic_systems_read, and the corresponding count. Any other use will probably result in segmentation faults or double free. If systems is NULL, this function does nothing.

Parameters:
  • systems – pointer to the first element of the array of rascal_system_t

  • count – number of systems in the array

Returns:

The status code of this operation. If the status is not RASCAL_SUCCESS, you can use rascal_last_error() to get the full error message.