Sorting by atom type

I am aware that it is possible to sort by atom types when outputting data to a dump file, but I am trying to "internally" sort the atoms within LAMMPS by atom type.

I'll provide a simplified example of what I am doing to better show my issue, with a zinc blende diatomic structure since my main issue revolves around this.

I have a C++ code that is coupled with LAMMPS, where I setup the simulation as follows (in C++):

  lmp->input->one("neighbor 1.0 multi");
  lmp->input->one("boundary p p p");
  lmp->input->one("units metal");
  lmp->input->one("atom_style atomic");
  lmp->input->one("atom_modify map array");

  // System geometry and atom creation
  lmp->input->one("lattice diamond 5.469");
  lmp->input->one("region box block 0 2 0 2 0 2 units lattice");
  lmp->input->one("create_box 2 box");
  lmp->input->one("create_atoms 2 box basis 1 1 basis 2 1 basis 3 1 basis 4 1 basis 5 2 basis 6 2 basis 7 2 basis 8 2"); // atom1 on basis 1, atom2 on basis 2
  lmp->input->one("mass 1 69.723"); // arsenic mass
  lmp->input->one("mass 2 74.9216"); // gallium mass

  // Pair style and pair coefficients
  lmp->input->one("pair_style tersoff");
  lmp->input->one("pair_coeff * * GaAs.tersoff Ga As");

These inputs simply prepare the atoms and the simulation. The potential file is irrelevant, as my question is just about how to sort the atoms by atom type.

Next, I would like to "scatter" the atoms using (in C++):

  lammps_scatter_atoms(lmp,"x",1,3,r_vector);

where "r_vector" is a vector of position values (x, y, z) for each atom in the system.

The issue I have is that the atoms in "r_vector" are sorted according to atom type, so the first portion is atom 1 (arsenic in this case) and the second portion is atom 2 (gallium in this case). Basically, for 64 atoms the first 32 are arsenic, and the next 32 are gallium in my "r_vector".

Because of this, I cannot simply scatter the atoms according to these positions because of the way the atoms are created in LAMMPS.

I would therefore like to create the atoms in a zinc blende structure like I am doing, but have them sorted by atom type so that when I scatter them with "r_vector", the positions and atom types match up. Is there a way to do this?

Thanks for your time.

I am aware that it is possible to sort by atom types when outputting data
to a dump file, but I am trying to "internally" sort the atoms within
LAMMPS by atom type.

I'll provide a simplified example of what I am doing to better show my
issue, with a zinc blende diatomic structure since my main issue revolves
around this.

I have a C++ code that is coupled with LAMMPS, where I setup the
simulation as follows (in C++):

  lmp->input->one("neighbor 1.0 multi");
  lmp->input->one("boundary p p p");
  lmp->input->one("units metal");
  lmp->input->one("atom_style atomic");
  lmp->input->one("atom_modify map array");

  // System geometry and atom creation
  lmp->input->one("lattice diamond 5.469");
  lmp->input->one("region box block 0 2 0 2 0 2 units lattice");
  lmp->input->one("create_box 2 box");
  lmp->input->one("create_atoms 2 box basis 1 1 basis 2 1 basis 3 1 basis
4 1 basis 5 2 basis 6 2 basis 7 2 basis 8 2"); // atom1 on basis 1, atom2
on basis 2
  lmp->input->one("mass 1 69.723"); // arsenic mass
  lmp->input->one("mass 2 74.9216"); // gallium mass

  // Pair style and pair coefficients
  lmp->input->one("pair_style tersoff");
  lmp->input->one("pair_coeff * * GaAs.tersoff Ga As");

These inputs simply prepare the atoms and the simulation. The potential
file is irrelevant, as my question is just about how to sort the atoms by
atom type.

Next, I would like to "scatter" the atoms using (in C++):

  lammps_scatter_atoms(lmp,"x",1,3,r_vector);

where "r_vector" is a vector of position values (x, y, z) for each atom in
the system.

The issue I have is that the atoms in "r_vector" are sorted according to
atom type, so the first portion is atom 1 (arsenic in this case) and the
second portion is atom 2 (gallium in this case). Basically, for 64 atoms
the first 32 are arsenic, and the next 32 are gallium in my "r_vector".

Because of this, I cannot simply scatter the atoms according to these
positions because of the way the atoms are created in LAMMPS.

I would therefore like to create the atoms in a zinc blende structure like
I am doing, but have them sorted by atom type so that when I scatter them
with "r_vector", the positions and atom types match up. Is there a way to
do this?

​data sent out with scatter *has* to be sorted by atom id. LAMMPS has to
match each data item with a specific atom. thus if you want to match up
your data with what LAMMPS has, you'd have to first retrieve the type array
via gather and then order your r_vector accordingly. ​

axel.

Thanks Axel.

What do you mean by “type” array? From what I’ve seen, the data sent out with “scatter” is ordered by count and atom ID. I’m not concerned with the specific atom IDs, but just the type of atom.

Sorry if I’m not understanding what you said, but are you saying it is possible to use “gather” to determine which atoms are of a certain type? I mean which atoms are arsenic (atom type 1) and which atoms are gallium (atom type 2), etc.? I could easily sort my r_vector accordingly if that was the case.

If it helps make my question more clear, this isn’t an issue at all with a single atom type because all the atoms scattered with r_vector are of the same atom type. But when I have more than 1 atom type, I just need to make sure that I’m scattering the correct atoms (eg. gallium is getting scattered with correct coordinates and arsenic is getting scattered with correct coordinates).

To simplify my question: How can make sure that I’m scattering the gallium atoms with certain displacements, and scattering the arsenic atoms with separate displacements? The specific atom IDs don’t really matter to me, just the type of atom.

I just realized that you can gather atom types by setting the name pointer to “type” in “lammps_gather_atoms”. I should be able to sort my r_vector accordingly accordingly.

Thanks Axel.

What do you mean by "type" array? From what I've seen, the data sent out
with "scatter" is ordered by count and atom ID. I'm not concerned with the
specific atom IDs, but just the type of atom.

​yes, but LAMMPS doesn't care what you are concerned about about or not.
​when you send out data, LAMMPS has to know which data to send where, and
the only reasonable way to do this from the scatter library call is via the
atom id.

Sorry if I'm not understanding what you said, but are you saying it is

possible to use "gather" to determine which atoms are of a certain type? I
mean which atoms are arsenic (atom type 1) and which atoms are gallium
(atom type 2), etc.? I could easily sort my r_vector accordingly if that
was the case.

​yes. ​if you "gather" any atom property, it will be sorted by the atom id,
and thus you can infer from that, how you need to order the data that you
want to scatter.

depending on what you are doing, it may be simpler (and much faster), to do
the assignments in parallel and via the atom coordinate arrays directly.
you keep mentioning displacements, for that it would be simple to have the
displacements stored in a "per-type" array, send it out via MPI_Bcast() and
then just loop over the local atoms and apply the displacement.
then a reneighboring and you should be good.

axel.