\(\renewcommand{\AA}{\text{Å}}\)

1.1.6. Scatter/gather operations

This section has functions which gather per-atom data from one or more processors into a contiguous global list ordered by atom ID. The same list is returned to all calling processors. It also contains functions which scatter per-atom data from a contiguous global list across the processors that own those atom IDs. It also has a create_atoms() function which can create new atoms by scattering them appropriately to owning processors in the LAMMPS spatial decomposition.

It documents the following functions:


void lammps_gather_atoms(void *handle, char *name, int type, int count, void *data)

Gather the named atom-based entity for all atoms across all processors, in order.

This subroutine gathers data for all atoms and stores them in a one-dimensional array allocated by the user. The data will be ordered by atom ID, which requires consecutive atom IDs (1 to natoms). If you need a similar array but have non-consecutive atom IDs, see lammps_gather_atoms_concat(); for a similar array but for a subset of atoms, see lammps_gather_atoms_subset().

The data array will be ordered in groups of count values, sorted by atom ID (e.g., if name is x and count = 3, then data = x[0][0], x[0][1], x[0][2], x[1][0], x[1][1], x[1][2], x[2][0], \(\dots\)); data must be pre-allocated by the caller to length (count \(\times\) natoms), as queried by lammps_get_natoms(), lammps_extract_global(), or lammps_extract_setting().

Parameters:
  • handle – pointer to a previously created LAMMPS instance

  • name – desired quantity (e.g., x or charge)

  • type – 0 for int values, 1 for double values

  • count – number of per-atom values (e.g., 1 for type or charge, 3 for x or f); use count = 3 with image if you want a single image flag unpacked into (x,y,z) components.

  • data – per-atom values packed in a 1-dimensional array of length natoms * count.


void lammps_gather_atoms_concat(void *handle, char *name, int type, int count, void *data)

Gather the named atom-based entity for all atoms across all processors, unordered.

This subroutine gathers data for all atoms and stores them in a one-dimensional array allocated by the user. The data will be a concatenation of chunks from each processor’s owned atoms, in whatever order the atoms are in on each processor. This process has no requirement that the atom IDs be consecutive. If you need the ID of each atom, you can do another lammps_gather_atoms_concat() call with name set to id. If you have consecutive IDs and want the data to be in order, use lammps_gather_atoms(); for a similar array but for a subset of atoms, use lammps_gather_atoms_subset().

The data array will be in groups of count values, with natoms groups total, but not in order by atom ID (e.g., if name is x and count is 3, then data might be something like = x[10][0], x[10][1], x[10][2], x[2][0], x[2][1], x[2][2], x[4][0], \(\dots\)); data must be pre-allocated by the caller to length (count \(\times\) natoms), as queried by lammps_get_natoms(), lammps_extract_global(), or lammps_extract_setting().

Parameters:
  • handle – pointer to a previously created LAMMPS instance

  • name – desired quantity (e.g., x or charge\ )

  • type – 0 for int values, 1 for double values

  • count – number of per-atom values (e.g., 1 for type or charge, 3 for x or f); use count = 3 with “image” if you want single image flags unpacked into (x,y,z)

  • data – per-atom values packed in a 1-dimensional array of length natoms * count.


void lammps_gather_atoms_subset(void *handle, char *name, int type, int count, int ndata, int *ids, void *data)

Gather the named atom-based entity for a subset of atoms.

This subroutine gathers data for the requested atom IDs and stores them in a one-dimensional array allocated by the user. The data will be ordered by atom ID, but there is no requirement that the IDs be consecutive. If you wish to return a similar array for all the atoms, use lammps_gather_atoms() or lammps_gather_atoms_concat().

The data array will be in groups of count values, sorted by atom ID in the same order as the array ids (e.g., if name is x, count = 3, and ids is {100, 57, 210}, then data might look like {x[100][0], x[100][1], x[100][2], x[57][0], x[57][1], x[57][2], x[210][0], \(\dots\)); ids must be provided by the user with length ndata, and data must be pre-allocated by the caller to length (count \(\times\) ndata).

Parameters:
  • handle – pointer to a previously created LAMMPS instance

  • name – desired quantity (e.g., x or charge)

  • type – 0 for int values, 1 for double values

  • count – number of per-atom values (e.g., 1 for type or charge, 3 for x or f); use count = 3 with “image” if you want single image flags unpacked into (x,y,z)

  • ndata – number of atoms for which to return data (can be all of them)

  • ids – list of ndata atom IDs for which to return data

  • data – per-atom values packed in a 1-dimensional array of length ndata * count.


void lammps_scatter_atoms(void *handle, char *name, int type, int count, void *data)

Scatter the named atom-based entities in data to all processors.

This subroutine takes data stored in a one-dimensional array supplied by the user and scatters them to all atoms on all processors. The data must be ordered by atom ID, with the requirement that the IDs be consecutive. Use lammps_scatter_atoms_subset() to scatter data for some (or all) atoms, unordered.

The data array needs to be ordered in groups of count values, sorted by atom ID (e.g., if name is x and count = 3, then data = x[0][0], x[0][1], x[0][2], x[1][0], x[1][1], x[1][2], x[2][0], \(\dots\)); data must be of length (count \(\times\) natoms).

Parameters:
  • handle – pointer to a previously created LAMMPS instance

  • name – desired quantity (e.g., x or charge)

  • type – 0 for int values, 1 for double values

  • count – number of per-atom values (e.g., 1 for type or charge, 3 for x or f); use count = 3 with image if you have a single image flag packed into (x,y,z) components.

  • data – per-atom values packed in a 1-dimensional array of length natoms * count.


void lammps_scatter_atoms_subset(void *handle, char *name, int type, int count, int ndata, int *ids, void *data)

Scatter the named atom-based entities in data from a subset of atoms to all processors.

This subroutine takes data stored in a one-dimensional array supplied by the user and scatters them to a subset of atoms on all processors. The array data contains data associated with atom IDs, but there is no requirement that the IDs be consecutive, as they are provided in a separate array. Use lammps_scatter_atoms() to scatter data for all atoms, in order.

The data array needs to be organized in groups of count values, with the groups in the same order as the array ids. For example, if you want data to be the array {x[1][0], x[1][1], x[1][2], x[100][0], x[100][1], x[100][2], x[57][0], x[57][1], x[57][2]}, then count = 3, ndata = 3, and ids would be {1, 100, 57}.

Parameters:
  • handle – pointer to a previously created LAMMPS instance

  • name – desired quantity (e.g., x or charge)

  • type – 0 for int values, 1 for double values

  • count – number of per-atom values (e.g., 1 for type or charge, 3 for x or f); use count = 3 with “image” if you have all the image flags packed into (xyz)

  • ndata – number of atoms listed in ids and data arrays

  • ids – list of ndata atom IDs to scatter data to

  • data – per-atom values packed in a 1-dimensional array of length ndata * count.


void lammps_gather_bonds(void *handle, void *data)

Gather type and constituent atom info for all bonds

This function copies the list of all bonds into a buffer provided by the calling code. The buffer will be filled with bond type, bond atom 1, bond atom 2 for each bond. Thus the buffer has to be allocated to the dimension of 3 times the total number of bonds times the size of the LAMMPS “tagint” type, which is either 4 or 8 bytes depending on whether they are stored in 32-bit or 64-bit integers, respectively. This size depends on the compile time settings used when compiling the LAMMPS library and can be queried by calling lammps_extract_setting() with the keyword “tagint”.

When running in parallel, the data buffer must be allocated on all MPI ranks and will be filled with the information for all bonds in the system.

New in version 28Jul2021.

Below is a brief C code demonstrating accessing this collected bond information.

#include "library.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    int tagintsize;
    int64_t i, nbonds;
    void *handle, *bonds;

    handle = lammps_open_no_mpi(0, NULL, NULL);
    lammps_file(handle, "in.some_input");

    tagintsize = lammps_extract_setting(handle, "tagint");
    if (tagintsize == 4)
        nbonds = *(int32_t *)lammps_extract_global(handle, "nbonds");
     else
        nbonds = *(int64_t *)lammps_extract_global(handle, "nbonds");
    bonds = malloc(nbonds * 3 * tagintsize);

    lammps_gather_bonds(handle, bonds);

    if (lammps_extract_setting(handle, "world_rank") == 0) {
        if (tagintsize == 4) {
            int32_t *bonds_real = (int32_t *)bonds;
            for (i = 0; i < nbonds; ++i) {
                printf("bond % 4ld: type = %d, atoms: % 4d  % 4d\n",i,
                       bonds_real[3*i], bonds_real[3*i+1], bonds_real[3*i+2]);
            }
        } else {
            int64_t *bonds_real = (int64_t *)bonds;
            for (i = 0; i < nbonds; ++i) {
                printf("bond % 4ld: type = %ld, atoms: % 4ld  % 4ld\n",i,
                       bonds_real[3*i], bonds_real[3*i+1], bonds_real[3*i+2]);
            }
        }
    }

    lammps_close(handle);
    lammps_mpi_finalize();
    free(bonds);
    return 0;
}

Parameters:
  • handle – pointer to a previously created LAMMPS instance

  • data – pointer to data to copy the result to


void lammps_gather(void *handle, char *name, int type, int count, void *data)

void lammps_gather_concat(void *handle, char *name, int type, int count, void *data)

void lammps_gather_subset(void *handle, char *name, int type, int count, int ndata, int *ids, void *data)

void lammps_scatter(void *handle, char *name, int type, int count, void *data)

void lammps_scatter_subset(void *handle, char *name, int type, int count, int ndata, int *ids, void *data)

int lammps_create_atoms(void *handle, int n, const int *id, const int *type, const double *x, const double *v, const int *image, int bexpand)

Create N atoms from list of coordinates

The prototype for this function when compiling with -DLAMMPS_BIGBIG is:

int lammps_create_atoms(void *handle, int n, int64_t *id, int *type, double *x, double *v, int64_t *image, int bexpand);

This function creates additional atoms from a given list of coordinates and a list of atom types. Additionally the atom-IDs, velocities, and image flags may be provided. If atom-IDs are not provided, they will be automatically created as a sequence following the largest existing atom-ID.

This function is useful to add atoms to a simulation or - in tandem with lammps_reset_box() - to restore a previously extracted and saved state of a simulation. Additional properties for the new atoms can then be assigned via the lammps_scatter_atoms() lammps_extract_atom() functions.

For non-periodic boundaries, atoms will not be created that have coordinates outside the box unless it is a shrink-wrap boundary and the shrinkexceed flag has been set to a non-zero value. For periodic boundaries atoms will be wrapped back into the simulation cell and its image flags adjusted accordingly, unless explicit image flags are provided.

The function returns the number of atoms created or -1 on failure (e.g., when called before as box has been created).

Coordinates and velocities have to be given in a 1d-array in the order X(1),Y(1),Z(1),X(2),Y(2),Z(2),…,X(N),Y(N),Z(N).

Parameters:
  • handle – pointer to a previously created LAMMPS instance

  • n – number of atoms, N, to be added to the system

  • id – pointer to N atom IDs; NULL will generate IDs

  • type – pointer to N atom types (required)

  • x – pointer to 3N doubles with x-,y-,z- positions of the new atoms (required)

  • v – pointer to 3N doubles with x-,y-,z- velocities of the new atoms (set to 0.0 if NULL)

  • image – pointer to N imageint sets of image flags, or NULL

  • bexpand – if 1, atoms outside of shrink-wrap boundaries will still be created and not dropped and the box extended

Returns:

number of atoms created on success; -1 on failure (no box, no atom IDs, etc.)