image flags from gather_atoms, segmentation fault

Dear All,

I have been attempting to use ‘gather_atoms’ via LAMMPS’ python interface to extract the image flags for each atom. Unfortunately, when I invoke the command lmp.gather_atoms(“image”,0,3), I immediately get a segmentation fault. Calls such as lmp.gather_atoms(“x”,1,3) and lmp.gather_atoms(“v”,1,3), however, work fine.

I was wondering if anyone has any suggestions regarding what I might be doing wrong. I am using the 17 NOV 16 build of LAMMPS, and my test inputs are below.

Thanks in advance.

Best,
JC

test.py:

from ctypes import *
from lammps import lammps

lmp = lammps()

Load script/data

lmp.file(“in.nve”)

Get initial system properties

natoms = lmp.extract_global(“natoms”,0)
x = ((3*natoms)c_double)()
v = ((3
natoms)c_double)()
image = ((3
natoms)*c_int)()

mass = lmp.extract_atom(“mass”,2)
atomid = lmp.gather_atoms(“id”,0,1)
atype = lmp.gather_atoms(“type”,0,1)
x = lmp.gather_atoms(“x”,1,3)
v = lmp.gather_atoms(“v”,1,3)
image = lmp.gather_atoms(“image”,0,3)
for i in range(3*natoms):
print i,x[i],v[i],image[i]

in.nve:

Units and atom style

units real
atom_style atomic

Needs to be here to get atom order correct with gather and scatter

atom_modify map array sort 0 0.0

Read

read_data in.dat

Pair info

pair_style sw
pair_coeff * * mW.sw W

Neighbor list

neighbor 2.5 bin
neigh_modify every 5 delay 0 check yes

Integrator and time step

fix 2 all nve
timestep 18.0
run 0

in.dat:

LAMMPS data file via write_data, version 17 Nov 2016, timestep = 159200

1 atoms
1 atom types

0.0000000000000000e+00 2.485700000e+01 xlo xhi
0.0000000000000000e+00 2.48570000e+01 ylo yhi
0.0000000000000000e+00 2.48570000e+01 zlo zhi

Masses

1 18.0153

Atoms # atomic

1 1 0.000 0.000 0.000 0 0 0

Dear All,

I have been attempting to use 'gather_atoms' via LAMMPS' python interface
to extract the image flags for each atom. Unfortunately, when I invoke the
command lmp.gather_atoms("image",0,3), I immediately get a segmentation
fault. Calls such as lmp.gather_atoms("x",1,3) and
lmp.gather_atoms("v",1,3), however, work fine.

I was wondering if anyone has any suggestions regarding what I might be
doing wrong. I am using the 17 NOV 16 build of LAMMPS, and my test inputs
are below.

​image flags are stored in packed format in a single integer per atom, not
3 integers, hence the segfault on your command. you have to use the same
gather command as for atom type or atom id.
with standard compilation flags, you have 3x 10-bit signed integer for
image flags packed into a single signed 32-bit ​integer.
​just search the C++ source code for IMGMASK, IMGBITS, and IMGMAX and see
for yourself.

axel.​

Do you mean you get a segfault before you are back in your Python code?

Don’t see why that should happen. You will have to unpack the individual

values as Axel explained.

We should probably add “imagex”, “imagey”, etc options

to the lib gather/scatter functions, or document better

what to do on the Python side.

Steve

Do you mean you get a segfault before you are back in your Python code?
Don't see why that should happen. You will have to unpack the individual

​steve,

if you try to access data that is stored in an nlocal length 1d-vector as a
3 by nlocal 2d-array, you *will* get a segfault.​
look at the code around lines 770 to 800 in library.cpp.

in addition, there is a bug:

diff --git a/src/library.cpp b/src/library.cpp
index ca3276e..f9c5ad4 100644
--- a/src/library.cpp
+++ b/src/library.cpp
@@ -790,7 +790,7 @@ void lammps_gather_atoms(void *ptr, char *name,
         for (i = 0; i < nlocal; i++) {
           offset = count*(tag[i]-1);
           for (j = 0; j < count; j++)
- copy[offset++] = array[i][0];
+ copy[offset++] = array[i][j];
         }

       MPI_Allreduce(copy,data,count*natoms,MPI_INT,MPI_SUM,lmp->world);

​axel.​

I agree that’s a bug. However, there are no non-vector integer

per-atom data that LAMMPS currently eturns. So it’s really a user-error

to request an integer array. I.e. that code should currently never
be executed if the lib interface is called correctly.
What we haven’t done is document

that image flags are not returned as a 3d array, but a 1d vector.

Steve

Steve and Axel,

I am interested as well in getting this functionality to work.

Would it be hard to add “imagex”, “imagey”, etc options to the lib gather/scatter functions?

It would be very useful.

Best regards,

Ross

Steve and Axel,

I am interested as well in getting this functionality to work.

Would it be hard to add "imagex", "imagey", etc options to the lib
gather/scatter functions?

​no, not very difficult. rather than having imagex, imagey, imagez as
individual flags, i'd be implementing it so that if you request ​
lmp.gather_atoms("image",0,3)
​ you would get a list with the unpacked x, y, and z image flags similar to
coordinates or velocities and for backward compatibility have
​lmp.gather_atoms("image",0,1) return the packed image flags as it
currently needs to be done.

​this way the image flags need to be communicated only once and no
additional buffering or copying needs to be done.​

​axel.​

Axel,

Thanks for getting on this so quickly. It would be great to have the routines you suggested:

lmp.gather_atoms(“image”,0,3)

lmp.scatter_atoms(“image”,0,3,IMAGEFLAGS)

I am curious though as to how you would use the current command of:

lmp.gather_atoms(“image”,0,1)

How would you unpack this vector in Python, alter the flags, then repack them to scatter back to LAMMPS? Can you use Python’s struct.unpack()? It would be great if Steve updated the documentation on this!

Best regards,

Ross

Axel,

Thanks for getting on this so quickly. It would be great to have the
routines you suggested:

lmp.gather_atoms("image",0,3)

lmp.scatter_atoms("image",0,3,IMAGEFLAGS)

I am curious though as to how you would use the current command of:

lmp.gather_atoms("image",0,1)

How would you unpack this vector in Python, alter the flags, then repack
them to scatter back to LAMMPS? Can you use Python's struct.unpack()? It
would be great if Steve updated the documentation on this!

​unpacking is done with bitmasks and bitshifts.​ here is a simple example:

from lammps import *

IMGMASK=1023
IMGMAX=512
IMGBITS=10
IMG2BITS=20

lmp = lammps()

lmp.command("region box block -5 5 -5 5 -5 5")
lmp.command("create_box 1 box")
lmp.command("create_atoms 1 single -1.0 3.0 2.5")
lmp.command("set atom 1 image 1 -1 2")
lmp.command("mass * 1.0")

pos = lmp.gather_atoms("x",1,3)
image = lmp.gather_atoms("image",0,1)
ix = image[0] & IMGMASK - IMGMAX
iy = ((image[0] >> IMGBITS) & IMGMASK) - IMGMAX
iz = ((image[0] >> IMG2BITS) & IMGMASK) - IMGMAX
print("\nposition: x=%4.1f y=%4.1f z=%4.1f packed image data: %d
unpacked: ix=%d iy=%d iz=d\\n&quot; (pos[0],pos[1],pos[2],image[0],ix,iy,iz))

*From:* Axel Kohlmeyer <[email protected]>

*Sent:* Tuesday, March 28, 2017 12:23:54 AM
*To:* Verploegh, Ross J
*Cc:* Steve Plimpton; LAMMPS Users Mailing List

*Subject:* Re: [lammps-users] image flags from gather_atoms,
segmentation fault

Steve and Axel,

I am interested as well in getting this functionality to work.

Would it be hard to add "imagex", "imagey", etc options to the lib
gather/scatter functions?

no, not very difficult. rather than having imagex, imagey, imagez as
individual flags, i'd be implementing it so that if you request
lmp.gather_atoms("image",0,3)
you would get a list with the unpacked x, y, and z image flags similar to
coordinates or velocities and for backward compatibility have
lmp.gather_atoms("image",0,1) return the packed image flags as it currently
needs to be done.

this way the image flags need to be communicated only once and no
additional buffering or copying needs to be done.

​please find attached a patch that tries to implement the feature into the
library (and python) interface as described above.

axel.​

library-24-Mar-2017.diff.gz (710 Bytes)