Question about neighbour list

Dear all,

I have a simple question about the neighbourlist. Mainly about two methods: half_bin_newton and half_bin_no_newton. I wonder if I am correct that:

1\ half_bin_no_newton method: (assume i<j here)
if i and j are both local atom , the pair will only store in i’s list ( I mean array firstneigh[i] )

if i is local atom and j is ghost atom, the pair will be stored in the process owing i atom and the process owing j atom.

2\ half_bin_newton method:

if i and j are both local atom, the same way of storage as half_bin_no_newton method.
if i is local atom and j is ghost atom, the pair will only be stored in the process owing i or the process owing j.

Thanks

correct

Steve

Thanks Steve. I have some further questions. I developed a fix style which uses post_force method. It needs neighbor list to do some calculation. Previously, I use full neighborlist with the following command to request list (defined in Fix::init method).

int irequest = neighbor->request(this,instance_me);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;

It works well. Recently, I change to half list without newton pair by the following command. I need a list which is created by Neighbor::half_bin_no_newton method.

int irequest = neighbor->request(this,instance_me);
neighbor->requests[irequest]->half = 1;
neighbor->requests[irequest]->full = 0;
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
neighbor->requests[irequest]->newton = 2;

However, by debugging the code, I found even if I didn’t make any change to neighbor->requests[irequest]->copy (whose default value should be 0), the value becomes 1 when Neighbor::choose_build method is invoked to choose method to build the neighborlist for the fix. I’m curious where the value is changed. Should I add neighbor->requests[irequest]->copy = 0 in MyFix::init to ensure the correct method of creating neighborlist for the fix is used?

Thank you!

Thanks Steve. I have some further questions. I developed a fix style which uses post_force method. It needs neighbor list to do some calculation. Previously, I use full neighborlist with the following command to request list (defined in Fix::init method).

int irequest = neighbor->request(this,instance_me);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;

It works well. Recently, I change to half list without newton pair by the following command. I need a list which is created by Neighbor::half_bin_no_newton method.

Not sure if that is a good idea, but is selected via the newton keyword. So for your fix you have to either require newton off for pair or add the code to handle both cases.

Axel

I did use the first method and set requests[irequest]->newton to 2, which overrides with newton off. But It seems that even if I didn’t set request->copy to 1, the list is copied from somewhere but not set by half_bin_no_newton method.

After checking the code, I guess I possibly find a bug of LAMMPS code.

The condition is that if we have two neighborlist. First is for pair interaction. Second is for a fix which uses half neighborlist and newton=2. The neighborlist parameters are as the following:

  • requests[0]->pair = 1
  • requests[0]-> half = 0

I did use the first method and set requests[irequest]->newton to 2, which
overrides with newton off. But It seems that even if I didn't set
request->copy to 1, the list is copied from somewhere but not set by
half_bin_no_newton method.

After checking the code, I guess I possibly find a bug of LAMMPS code.

​i don't think so. LAMMPS detects that you are requesting the same neighbor
list twice and thus creates the second as a copy of the first. this is not
a bug, this is an optimization.

axel.​

But the two neighbor lists are not the same. Take a look at Neighbor::choose_build and we could find the neighborlist for general pair like lj_cut_tip4p_cut is built by Neighbor::half_bin_newton.(with the default setting: newton_pair= 1 and triclinic = 0). But if newton = 2, It’s built by Neighbor::half_bin_no_newton. According to the comment in neigh_half_bin.cpp, for pair i/j and j is ghost atom. The second one stores own/ghost pairs on both procs. The first one only stores if j coords are “above and to the right” of i.

I think the optimization doesn’t consider that the neighbor list requested by fix might have newton = 2.

But the two neighbor lists are not the same. Take a look at
Neighbor::choose_build and we could find the neighborlist for general pair
like lj_cut_tip4p_cut is built by Neighbor::half_bin_newton.(with the
default setting: newton_pair= 1 and triclinic = 0). But if newton = 2, It's
built by Neighbor::half_bin_no_newton. According to the comment in
neigh_half_bin.cpp, for pair i/j and j is ghost atom. The second one stores
own/ghost pairs on both procs. The first one only stores if j coords are
"above and to the right" of i.

I think the optimization doesn't consider that the neighbor list requested
by fix might have newton = 2.

​i think you are missing most of the picture. additional important
process​ing is in Neighbor::init()

​at any rate, i am very confused by now. i suggest you start all over and
present a simple test case explaining what and why you are trying what you
are looking for and perhaps a small test input that can demonstrate that
what you get is wrong.

in the end, it doesn't matter what the flags to the neighbor list request
are, but rather what the actual neighbor list contains ​and if that is
correct.

axel.

A simple case is just the provided example of fix_qeq_reax.

It requires two neighborlists. One is for the pair_reax. The other is for the fix_qeq_reax. It sets newton = 2 for the second neighborlist. But if you debug the code, you can find in the Neighbor::init method, the copy is set to 1 in line 623, which means in the later line 656, when choose_build is called to set method of creating neighborlist, the newton flag is USELESS here. This effect is that if a pair of atoms contains i and j atoms(i is local atom and j is ghost atom), the pair will only be stored in one process’s fix’s neighborlist. But the aim of newton = 2 is to make such ghost/local pair stored in both procs.

The problem doesn’t happen to fix_qeq_reax is because the flag of the neighborlist required by pair_reax is same as the fla​gs of fix_qeq_reax as the following. Thus it works.
image.png

I sincerely hope you could look into detail of the code from line 608 - 660 of Neighbor::init. It should include the condition that newton or ghost flag is set when deciding whether to copy neighborlist. Actually, it takes me a day to find out this bug.