Extracting neighbor list in LAMMPS C++ library

Hello,

I’m trying to extract a neighbor list array for every atom using the LAMMPS C++ library, in a similar way that pair styles access the neighbor list during force and energy calculation. Here’s a minimum example of code:

#include
#include “mpi.h”
#include “lammps.h”
#include “input.h”
#include “atom.h”
#include “library.h”

using namespace LAMMPS_NS;
char *args1[] = {
(char *) “lmp”,
(char ) “-screen”,
(char
) “none”,
0};
LAMMPS *lmp;

int main(int argc, char **argv)
{

int color,key,global,local;
MPI_Comm comm;

/* Initialize MPI */
MPI_Init(&argc,&argv);

/* Split the communicators so that multiple instances of LAMMPS can be run */
MPI_Comm_rank(MPI_COMM_WORLD, &global);
color = global / 1; // Change “1” to 2 in order to use 2 procs per instance, etc…
key = global;
MPI_Comm_split(MPI_COMM_WORLD, color, key, &comm);
MPI_Comm_rank(comm,&local);

/* Create LAMMPS object */
lmp = new LAMMPS(3,args1,comm);

/* Set up system */
lmp->input->one(“neighbor 0.0 bin”);
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”);
lmp->input->one(“region box prism 0 1 0 1 0 1 0 0 0 units lattice”);
lmp->input->one(“create_box 1 box”);
lmp->input->one(“create_atoms 1 random 100 10101 NULL”);

/* Get neighbors for every atom /
/
??? How to do this ??? */

/* Delete LAMMPS object */
delete lmp;

/* Close MPI */
int MPI_Comm_free(MPI_Comm *comm);
MPI_Finalize();
}

This short script can be compiled with the attached Makefile (just set the LAMMPS directory and shared library paths).

After creating the LAMMPS pointer, I set up a simple system of 100 randomly placed atoms in a simple box. I can easily access per-atom quantities now via lmp->atom, for example. But how can I compute and access the neighbor list for every atom in this system? I don’t necessarily even want to declare a pair style, even though it may be necessary. For example, the 2-body neighbor list in the Morse pair style is accessed via:

inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;

But I don’t have access to the “list” pointer in my code, nor do I know how to build a neighbor list using the C++ library.

I’ve thought about making a custom pair style that just gets the neighbor list, and then retrieving that list with via pointer in my main code. I was just wondering if there was a more simple solution.

Thanks for your time.

Makefile (267 Bytes)

The list pointer is a member of the pair.h parent; the actual neighbor list objects belong to the Neigh_List Class I think. Usually, computes I’ve seen will implement the inherited virtual function “init_list”. This is then called in some other parent class that handles the provision of NeighList objects to computes and the compute will take the pointer to the neighbor list object from the init_list method’s input arguments. Also, why are you programming it with such a direct implementation? Is there a reason why you would not want to create a per atom dump or compute that uses the neighbor list information for your purposes?

pardon, the NeighLists belong to the Neighbor class. This is also one of the pointers inherited by almost every class and thus should be one of the members defined in the lammps class; thus calling something like lmp->Neighbor->nlist to get the number of lists and lmp->Neighbor->lists would give you the set of lists. You can then dereference the list of lists to get the desired list if you find the right one. This can then be used just like in the pair styles, although I’m hazy on how to find the specific list you might want without looking into it more. This might then let you do it in that top level fashion you were trying in the main function.

Hello,

I'm trying to extract a neighbor list array for every atom using the
LAMMPS C++ library, in a similar way that pair styles access the neighbor
list during force and energy calculation. Here's a minimum example of code:

#include <iostream>
#include "mpi.h"
#include "lammps.h"
#include "input.h"
#include "atom.h"
#include "library.h"

using namespace LAMMPS_NS;
char *args1[] = {
    (char *) "lmp",
    (char *) "-screen",
    (char*) "none",
     0};
LAMMPS *lmp;

int main(int argc, char **argv)
{

    int color,key,global,local;
    MPI_Comm comm;

    /* Initialize MPI */
    MPI_Init(&argc,&argv);

    /* Split the communicators so that multiple instances of LAMMPS can be
run */
    MPI_Comm_rank(MPI_COMM_WORLD, &global);
    color = global / 1; // Change "1" to 2 in order to use 2 procs per
instance, etc..
    key = global;
    MPI_Comm_split(MPI_COMM_WORLD, color, key, &comm);
    MPI_Comm_rank(comm,&local);

    /* Create LAMMPS object */
    lmp = new LAMMPS(3,args1,comm);

    /* Set up system */
    lmp->input->one("neighbor 0.0 bin");
    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");
    lmp->input->one("region box prism 0 1 0 1 0 1 0 0 0 units lattice");
    lmp->input->one("create_box 1 box");
    lmp->input->one("create_atoms 1 random 100 10101 NULL");

    /* Get neighbors for every atom */
    /* ??? How to do this ??? */

    /* Delete LAMMPS object */
    delete lmp;

    /* Close MPI */
    int MPI_Comm_free(MPI_Comm *comm);
    MPI_Finalize();
}

This short script can be compiled with the attached Makefile (just set the
LAMMPS directory and shared library paths).

After creating the LAMMPS pointer, I set up a simple system of 100
randomly placed atoms in a simple box. I can easily access per-atom
quantities now via lmp->atom, for example. But how can I compute and access
the neighbor list for every atom in this system? I don't necessarily even
want to declare a pair style, even though it may be necessary. For example,
the 2-body neighbor list in the Morse pair style is accessed via:

  inum = list->inum;
  ilist = list->ilist;
  numneigh = list->numneigh;
  firstneigh = list->firstneigh;

But I don't have access to the "list" pointer in my code, nor do I know
how to build a neighbor list using the C++ library.

I've thought about making a custom pair style that just gets the neighbor
list, and then retrieving that list with via pointer in my main code. I was
just wondering if there was a more simple solution.

​neighbor lists have to be "owned" by some style (either a pair style or a
fix style or a compute style or a command style) and they have to be
created through generating a NeighRequest instance and selecting which kind
of neighbor list you want. generating neighbor lists is a rather complex
operation to be done right in parallel and also LAMMPS tries to minimize
the computational effort and reuse lists whenever possible, so they depend
a certain amount of "prep work"​ before you can build and access them.

for a pair style the request is generated in the Pair::init_style() method,
which is called from Pair::init(), which is called (if a pair style is
defined) from Force::init() which is called from LAMMPS::init()
trigger a neighbor list build, quite a few steps are required. just look at
the code in, e.g. Verlet::setup() until neighbor->build() is called.

how to actually set this up for a custom use depends a lot on what you want
to do with the neighbor list.

there is no need to implement a dummy pair style, as this already exists.
http://lammps.sandia.gov/doc/pair_zero.html
define this pair style and perform all other required setup to run a
simulation and then do a "run 0".
after that, you should have the neighbor list in lmp->force->pair->list

but probably the best approach to what you seem to be trying to do is to
write your own command style. please have a look at create_bonds.{cpp,h},
which uses a neighbor list for the "many" option.

axel.