I was wondering if someone could explain the role of ghost atoms in LAMMPS calculations, and how they relate to the actual owned atoms and the neighbor lists.
I’m particularly curious to know if there is a method that would update the ghosts (or ghosts and neighbors) after a change in simulation conditions without actually re-distributing atoms across processors.
I was wondering if someone could explain the role of ghost atoms in LAMMPS
calculations, and how they relate to the actual owned atoms and the neighbor
lists.
when you do domain decomposition, you split your total simulation cell
into subdomains, one per MPI process. all atoms that fall into one of
these subdomains are the local atoms of that subdomain. the local
atoms interact with all atoms within the cutoff. now you have a
problem. not all atoms that are within the cutoff of the local atoms
are in the same subdomain. this is where the ghost atoms come in. they
are copies from the other domain. during the MD loop their positions
are updated after their original's positions are updated and after
computing forces any forces attributed to ghost atoms are added back
to the originals. ghost atoms deleted and newly created every time you
build a new neighbor list. since this starts by updating the domain
decomposition, you have a new set of local atoms. from these atoms you
build the neighbor lists (each contains first the local atoms and then
any ghost atoms).
I'm particularly curious to know if there is a method that would update the
ghosts (or ghosts and neighbors) after a change in simulation conditions
without actually re-distributing atoms across processors.
what kind of change?
the entire process from above is just one process. however, there are
ways to defer the need to do neighborlist build, e.g. by using a
larger "skin" distance. this will however increase the number of
neighbors and thus increase the cost of the individual MD step, since
you now need to compute more "useless" distances.
Regarding my second question, suppose I have a small subset of atoms (2-3) where the charge and possibly position change (although the position by only 1.0 A or so) and I'd like the ghosts to reflect that change, but I don't want atom ownership to change between the processors. In other words, if proc 0 has atoms 1, 2, 3 and proc 1 has 4 and 5, I'd like to have 1, 2, 3 still on proc 0 after the update and so forth.
My understanding is that in general, I could end up with something like 1, 2, 4 and 3, 5 or something like that.
1. Ghost atoms are an implementation detail and they are not part of
the user interface. For example, there is no mechanism in LAMMPS for
writing out ghost atom properties. If you are trying to do a
calculation that depends on how ghost atoms are implemented, you are
probably thinking about it wrong.
2. The allocation of atoms to different MPI processes is a little
different. It affects things like the order in which atoms are written
to a dump file. If that is causing you trouble, you can do two
things. a) sort the atoms using dump_modify sort. b) Suppress
reneighboring using e.g. neigh_modify once. Atoms are only reallocated
to different processes prior to rebuilding the neighbor list, so this
will have the effect of supressing reallocation. Of course,
suppressing reneighboring may result in an incomplete neighbor list,
unless you use a sufficiently large skin distance that is good for the
duration of the simulation. Increasing the skin distance will increase
the flops, communication and memory per atom.
3. If you are trying to write you own fix or compute, you should use
Comm class functions to help you out. See for example fix_qeq_reax.cpp
Regarding my second question, suppose I have a small subset of atoms (2-3) where the charge and possibly position change (although the position by only 1.0 A or so) and I'd like the ghosts to reflect that change, but I don't want atom ownership to change between the processors. In other words, if proc 0 has atoms 1, 2, 3 and proc 1 has 4 and 5, I'd like to have 1, 2, 3 still on proc 0 after the update and so forth.
My understanding is that in general, I could end up with something like 1, 2, 4 and 3, 5 or something like that.
not until the next neighbor list rebuild. and how often this happens,
you can influence.
however, you also have to consider the correctness of your neighbor
list. if an atom moves too far, before the neighbor list are rebuild.
the computed interactions will be wrong. that atoms will in some
neighbor list. with the neigh_modify check yes setting, LAMMPS will
check how far an atom has moved and if it has moved too far, it will
rebuild the neighbor list.
if you increase the neighbor list skin, this can be a longer distance.
mind you, this comes at a price: you have more entries in your
neighbor list and thus you compute more "useless" distances, i.e. your
calculation will slow down.
it is difficult to give any advice beyond that without knowing more
about what you are trying to achieve, but these are the general
boundary conditions. there is no such thing as a free lunch...