diff --git a/doc/src/Developer.rst b/doc/src/Developer.rst index 406dd26f59..b0cfcc14fc 100644 --- a/doc/src/Developer.rst +++ b/doc/src/Developer.rst @@ -13,6 +13,7 @@ of time and requests from the LAMMPS user community. Developer_org Developer_code_design Developer_parallel + Developer_atom Developer_comm_ops Developer_flow Developer_write diff --git a/doc/src/Developer_atom.rst b/doc/src/Developer_atom.rst new file mode 100644 index 0000000000..704e4a8961 --- /dev/null +++ b/doc/src/Developer_atom.rst @@ -0,0 +1,88 @@ +Accessing per-atom data +----------------------- + +This page discusses how per-atom data is managed in LAMMPS, how it can +be accessed, what communication patters apply, and some of the utility +functions that exist for a variety of purposes. + + +Owned and ghost atoms +^^^^^^^^^^^^^^^^^^^^^ + +As described on the :doc:`parallel partitioning algorithms +` page, LAMMPS uses a domain decomposition of the +simulation domain, either in a *brick* or *tiled* manner. Each MPI +process *owns* exactly one subdomain and the atoms within it. To compute +forces for tuples of atoms that are spread across sub-domain boundaries, +also a "halo" of *ghost* atoms are maintained within a the communication +cutoff distance of its subdomain. + +The total number of atoms is stored in `Atom::natoms` (within any +typical class this can be referred to at `atom->natoms`. The number of +*owned* (or "local" atoms) are stored in `Atom::nlocal`; the number of +*ghost* atoms is stored in `Atom::nghost`. The sum of `Atom::nlocal` +over all MPI processes should be `Atom::natoms`. This is by default +regularly checked by the Thermo class, and if the sum does not match, +LAMMPS stops with a "lost atoms" error. For convenience also the +property `Atom::nmax` is available, this is the maximum of +`Atom::nlocal + Atom::nghost` across all MPI processes. + +Per-atom properties are either managed by the atom style, or individual +classes. or as custom arrays by the individual classes. If only access +to *owned* atoms is needed, they are usually allocated to be of size +`Atom::nlocal`, otherwise of size `Atom::nmax`. Please note that not all +per-atom properties are available or updated on *ghost* atoms. For +example, per-atom velocities are only updated with :doc:`comm_modify vel +yes `. + + +Atom indexing +^^^^^^^^^^^^^ + +When referring to individual atoms, they may be indexed by their local +*index*, their index in their `Atom::x` array. This is densely populated +containing first all *owned* atoms (index < `Atom::nlocal`) and then all +*ghost* atoms. The order of atoms in these arrays can change due to +atoms migrating between between subdomains, atoms being added or +deleted, or atoms being sorted for better cach efficiency. Atoms are +globally uniquely identified by their *atom ID*. There may be multiple +atoms with the same atom ID present, but only one of them may be an +*owned* atom. + +To find the local *index* of an atom, when the *atom ID* is known, the +`Atom::map()` function may be used. It will return the local atom index +or -1. If the returned value is between 0 (inclusive) and `Atom::nlocal` +(exclusive) it is an *owned* or "local" atom; for larger values the atom +is present as a ghost atom; for a value of -1, the atom is not present +on the current subdomain at all. + +If multiple atoms with the same tag exist in the same subdomain, they +can be found via the `Atom::sametag` array. It points to the next atom +index with the same tag or -1 if there are no more atoms with the same +tag. The list will be exhaustive when starting with an index of an +*owned* atom, since the atom IDs are unique, so there can only be one +such atom. Example code to count atoms with same atom ID in subdomain: + +.. code-block:: c++ + + for (int i = 0; i < atom->nlocal; ++i) { + int count = 0; + while (sametag[i] >= 0) { + i = sametag[i]; + ++count; + } + printf("Atom ID: %ld is present %d times\n", atom->tag[i], count); + } + +Atom class versus AtomVec classes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `Atom` class contains all kinds of flags and counters about atoms in +the system and that includes pointers to **all** per-atom properties +availabel for atoms. However, only a subset of these pointers are +non-NULL and which those are depends on the atom style. For each atom +style there is a corresponding `AtomVecXXX` class derived from the +`AtomVec` base class, where the XXX indicates the atom style. This +`AtomVecXXX` class will update the counters and per-atom pointers if +atoms are added or removed to the system or migrate between subdomains. +