Merge pull request #2694 from akohlmey/neighlist-interface-updates

Neighbor list library/python interface improvements
This commit is contained in:
Axel Kohlmeyer
2021-04-07 16:25:38 -04:00
committed by GitHub
18 changed files with 760 additions and 161 deletions

View File

@ -76,7 +76,7 @@ It documents the following functions:
----------------------- -----------------------
.. doxygenfunction:: lammps_create_atoms(void *handle, int n, int *id, int *type, double *x, double *v, int *image, int bexpand) .. doxygenfunction:: lammps_create_atoms(void *handle, int n, const int *id, const int *type, const double *x, const double *v, const int *image, int bexpand)
:project: progguide :project: progguide

View File

@ -142,7 +142,7 @@ Style Constants
Type Constants Type Constants
-------------- --------------
.. py:data:: LMP_TYPE_SCALAR, LMP_TYLE_VECTOR, LMP_TYPE_ARRAY, LMP_SIZE_VECTOR, LMP_SIZE_ROWS, LMP_SIZE_COLS .. py:data:: LMP_TYPE_SCALAR, LMP_TYPE_VECTOR, LMP_TYPE_ARRAY, LMP_SIZE_VECTOR, LMP_SIZE_ROWS, LMP_SIZE_COLS
:type: int :type: int
Constants in the :py:mod:`lammps` module to select what type of data Constants in the :py:mod:`lammps` module to select what type of data

View File

@ -1,6 +1,43 @@
Neighbor list access Neighbor list access
==================== ====================
Access to neighbor lists is handled through a couple of wrapper classes
that allows to treat it like either a python list or a NumPy array. The
access procedure is similar to that of the C-library interface: use one
of the "find" functions to look up the index of the neighbor list in the
global table of neighbor lists and then get access to the neighbor list
data. The code sample below demonstrates reading the neighbor list data
using the NumPy access method.
.. code-block:: python
from lammps import lammps
import numpy as np
lmp = lammps()
lmp.commands_string("""
region box block -2 2 -2 2 -2 2
lattice fcc 1.0
create_box 1 box
create_atoms 1 box
mass 1 1.0
pair_style lj/cut 2.5
pair_coeff 1 1 1.0 1.0
run 0 post no""")
# look up the neighbor list
nlidx = lmp.find_pair_neighlist('lj/cut')
nl = lmp.numpy.get_neighlist(nlidx)
tags = lmp.extract_atom('id')
print("half neighbor list with {} entries".format(nl.size))
# print neighbor list contents
for i in range(0,nl.size):
idx, nlist = nl.get(i)
print("\natom {} with ID {} has {} neighbors:".format(idx,tags[idx],nlist.size))
if nlist.size > 0:
for n in np.nditer(nlist):
print(" atom {} with ID {}".format(n,tags[n]))
**Methods:** **Methods:**
* :py:meth:`lammps.get_neighlist() <lammps.lammps.get_neighlist()>`: Get neighbor list for given index * :py:meth:`lammps.get_neighlist() <lammps.lammps.get_neighlist()>`: Get neighbor list for given index

View File

@ -138,8 +138,8 @@ vector or columns of the array had been listed one by one. E.g. these
.. code-block:: LAMMPS .. code-block:: LAMMPS
compute myCOM all com/chunk compute myCOM all com/chunk
fix 1 all ave/histo 100 1 100 c_myCOM[*] file tmp1.com mode vector fix 1 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[*] file tmp1.com mode vector
fix 2 all ave/histo 100 1 100 c_myCOM[1] c_myCOM[2] c_myCOM[3] file tmp2.com mode vector fix 2 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[1] c_myCOM[2] c_myCOM[3] file tmp2.com mode vector
If the fix ave/histo/weight command is used, exactly two values must If the fix ave/histo/weight command is used, exactly two values must
be specified. If the values are vectors, they must be the same be specified. If the values are vectors, they must be the same

View File

@ -2681,6 +2681,7 @@ representable
Reproducibility Reproducibility
reproducibility reproducibility
repuls repuls
reqid
rescale rescale
rescaled rescaled
rescales rescales

View File

@ -1747,17 +1747,23 @@ class lammps(object):
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
def find_pair_neighlist(self, style, exact=True, nsub=0, request=0): def find_pair_neighlist(self, style, exact=True, nsub=0, reqid=0):
"""Find neighbor list index of pair style neighbor list """Find neighbor list index of pair style neighbor list
Try finding pair instance that matches style. If exact is set, the pair must Search for a neighbor list requested by a pair style instance that
match style exactly. If exact is 0, style must only be contained. If pair is matches "style". If exact is True, the pair style name must match
of style pair/hybrid, style is instead matched the nsub-th hybrid sub-style. exactly. If exact is False, the pair style name is matched against
"style" as regular expression or sub-string. If the pair style is a
hybrid pair style, the style is instead matched against the hybrid
sub-styles. If the same pair style is used as sub-style multiple
types, you must set nsub to a value n > 0 which indicates the nth
instance of that sub-style to be used (same as for the pair_coeff
command). The default value of 0 will fail to match in that case.
Once the pair instance has been identified, multiple neighbor list requests Once the pair style instance has been identified, it may have
may be found. Every neighbor list is uniquely identified by its request requested multiple neighbor lists. Those are uniquely identified by
index. Thus, providing this request index ensures that the correct neighbor a request ID > 0 as set by the pair style. Otherwise the request
list index is returned. ID is 0.
:param style: name of pair style that should be searched for :param style: name of pair style that should be searched for
:type style: string :type style: string
@ -1765,44 +1771,58 @@ class lammps(object):
:type exact: bool, optional :type exact: bool, optional
:param nsub: match nsub-th hybrid sub-style, defaults to 0 :param nsub: match nsub-th hybrid sub-style, defaults to 0
:type nsub: int, optional :type nsub: int, optional
:param request: index of neighbor list request, in case there are more than one, defaults to 0 :param reqid: list request id, > 0 in case there are more than one, defaults to 0
:type request: int, optional :type reqid: int, optional
:return: neighbor list index if found, otherwise -1 :return: neighbor list index if found, otherwise -1
:rtype: int :rtype: int
"""
"""
style = style.encode() style = style.encode()
exact = int(exact) exact = int(exact)
idx = self.lib.lammps_find_pair_neighlist(self.lmp, style, exact, nsub, request) idx = self.lib.lammps_find_pair_neighlist(self.lmp, style, exact, nsub, reqid)
return idx return idx
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
def find_fix_neighlist(self, fixid, request=0): def find_fix_neighlist(self, fixid, reqid=0):
"""Find neighbor list index of fix neighbor list """Find neighbor list index of fix neighbor list
The fix instance requesting the neighbor list is uniquely identified
by the fix ID. In case the fix has requested multiple neighbor
lists, those are uniquely identified by a request ID > 0 as set by
the fix. Otherwise the request ID is 0 (the default).
:param fixid: name of fix :param fixid: name of fix
:type fixid: string :type fixid: string
:param request: index of neighbor list request, in case there are more than one, defaults to 0 :param reqid: id of neighbor list request, in case there are more than one request, defaults to 0
:type request: int, optional :type reqid: int, optional
:return: neighbor list index if found, otherwise -1 :return: neighbor list index if found, otherwise -1
:rtype: int :rtype: int
"""
"""
fixid = fixid.encode() fixid = fixid.encode()
idx = self.lib.lammps_find_fix_neighlist(self.lmp, fixid, request) idx = self.lib.lammps_find_fix_neighlist(self.lmp, fixid, reqid)
return idx return idx
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
def find_compute_neighlist(self, computeid, request=0): def find_compute_neighlist(self, computeid, reqid=0):
"""Find neighbor list index of compute neighbor list """Find neighbor list index of compute neighbor list
The compute instance requesting the neighbor list is uniquely
identified by the compute ID. In case the compute has requested
multiple neighbor lists, those are uniquely identified by a request
ID > 0 as set by the compute. Otherwise the request ID is 0 (the
default).
:param computeid: name of compute :param computeid: name of compute
:type computeid: string :type computeid: string
:param request: index of neighbor list request, in case there are more than one, defaults to 0 :param reqid: index of neighbor list request, in case there are more than one request, defaults to 0
:type request: int, optional :type reqid: int, optional
:return: neighbor list index if found, otherwise -1 :return: neighbor list index if found, otherwise -1
:rtype: int :rtype: int
"""
"""
computeid = computeid.encode() computeid = computeid.encode()
idx = self.lib.lammps_find_compute_neighlist(self.lmp, computeid, request) idx = self.lib.lammps_find_compute_neighlist(self.lmp, computeid, reqid)
return idx return idx

View File

@ -52,7 +52,9 @@ class NeighList:
def get(self, element): def get(self, element):
""" """
:return: tuple with atom local index, numpy array of neighbor local atom indices Access a specific neighbor list entry. "element" must be a number from 0 to the size-1 of the list
:return: tuple with atom local index, number of neighbors and ctypes pointer to neighbor's local atom indices
:rtype: (int, int, ctypes.POINTER(c_int)) :rtype: (int, int, ctypes.POINTER(c_int))
""" """
iatom, numneigh, neighbors = self.lmp.get_neighlist_element_neighbors(self.idx, element) iatom, numneigh, neighbors = self.lmp.get_neighlist_element_neighbors(self.idx, element)
@ -71,3 +73,20 @@ class NeighList:
for ii in range(inum): for ii in range(inum):
yield self.get(ii) yield self.get(ii)
def find(self, iatom):
"""
Find the neighbor list for a specific (local) atom iatom.
If there is no list for iatom, (-1, None) is returned.
:return: tuple with number of neighbors and ctypes pointer to neighbor's local atom indices
:rtype: (int, ctypes.POINTER(c_int))
"""
inum = self.size
for ii in range(inum):
idx, numneigh, neighbors = self.get(ii)
if idx == iatom:
return numneigh, neighbors
return -1, None

View File

@ -331,8 +331,25 @@ class NumPyNeighList(NeighList):
def get(self, element): def get(self, element):
""" """
Access a specific neighbor list entry. "element" must be a number from 0 to the size-1 of the list
:return: tuple with atom local index, numpy array of neighbor local atom indices :return: tuple with atom local index, numpy array of neighbor local atom indices
:rtype: (int, numpy.array) :rtype: (int, numpy.array)
""" """
iatom, neighbors = self.lmp.numpy.get_neighlist_element_neighbors(self.idx, element) iatom, neighbors = self.lmp.numpy.get_neighlist_element_neighbors(self.idx, element)
return iatom, neighbors return iatom, neighbors
def find(self, iatom):
"""
Find the neighbor list for a specific (local) atom iatom.
If there is no list for iatom, None is returned.
:return: numpy array of neighbor local atom indices
:rtype: numpy.array or None
"""
inum = self.size
for ii in range(inum):
idx, neighbors = self.get(ii)
if idx == iatom:
return neighbors
return None

View File

@ -318,7 +318,6 @@ void PairQUIP::init_style()
// Initialise neighbor list // Initialise neighbor list
int irequest_full = neighbor->request(this); int irequest_full = neighbor->request(this);
neighbor->requests[irequest_full]->id = 1;
neighbor->requests[irequest_full]->half = 0; neighbor->requests[irequest_full]->half = 0;
neighbor->requests[irequest_full]->full = 1; neighbor->requests[irequest_full]->full = 1;
} }

View File

@ -1615,7 +1615,7 @@ lists the available options.
* \return pointer (cast to ``void *``) to the location of the * \return pointer (cast to ``void *``) to the location of the
* requested data or ``NULL`` if not found. */ * requested data or ``NULL`` if not found. */
void *lammps_extract_compute(void *handle, char *id, int style, int type) void *lammps_extract_compute(void *handle, const char *id, int style, int type)
{ {
LAMMPS *lmp = (LAMMPS *) handle; LAMMPS *lmp = (LAMMPS *) handle;
@ -1801,7 +1801,7 @@ The following table lists the available options.
* \return pointer (cast to ``void *``) to the location of the * \return pointer (cast to ``void *``) to the location of the
* requested data or ``NULL`` if not found. */ * requested data or ``NULL`` if not found. */
void *lammps_extract_fix(void *handle, char *id, int style, int type, void *lammps_extract_fix(void *handle, const char *id, int style, int type,
int nrow, int ncol) int nrow, int ncol)
{ {
LAMMPS *lmp = (LAMMPS *) handle; LAMMPS *lmp = (LAMMPS *) handle;
@ -3822,8 +3822,8 @@ X(1),Y(1),Z(1),X(2),Y(2),Z(2),...,X(N),Y(N),Z(N).
* \return number of atoms created on success; * \return number of atoms created on success;
-1 on failure (no box, no atom IDs, etc.) */ -1 on failure (no box, no atom IDs, etc.) */
int lammps_create_atoms(void *handle, int n, tagint *id, int *type, int lammps_create_atoms(void *handle, int n, const tagint *id, const int *type,
double *x, double *v, imageint *image, const double *x, const double *v, const imageint *image,
int bexpand) int bexpand)
{ {
LAMMPS *lmp = (LAMMPS *) handle; LAMMPS *lmp = (LAMMPS *) handle;
@ -3859,13 +3859,17 @@ int lammps_create_atoms(void *handle, int n, tagint *id, int *type,
int nlocal_prev = nlocal; int nlocal_prev = nlocal;
double xdata[3]; double xdata[3];
imageint idata, *img;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
xdata[0] = x[3*i]; xdata[0] = x[3*i];
xdata[1] = x[3*i+1]; xdata[1] = x[3*i+1];
xdata[2] = x[3*i+2]; xdata[2] = x[3*i+2];
imageint * img = image ? image + i : nullptr; if (image) {
tagint tag = id ? id[i] : 0; idata = image[i];
img = &idata;
} else img = nullptr;
const tagint tag = id ? id[i] : 0;
// create atom only on MPI rank that would own it // create atom only on MPI rank that would own it
@ -3917,40 +3921,43 @@ int lammps_create_atoms(void *handle, int n, tagint *id, int *type,
// Library functions for accessing neighbor lists // Library functions for accessing neighbor lists
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** Find neighbor list index of pair style neighbor list /** Find index of a neighbor list requested by a pair style
* *
* Try finding pair instance that matches style. If exact is set, the pair must * This function determines which of the available neighbor lists for
* match style exactly. If exact is 0, style must only be contained. If pair is * pair styles matches the given conditions. It first matches the style
* of style pair/hybrid, style is instead matched the nsub-th hybrid sub-style. * name. If exact is 1 the name must match exactly, if exact is 0, a
* regular expression or sub-string match is done. If the pair style is
* hybrid or hybrid/overlay the style is matched against the sub styles
* instead.
* If a the same pair style is used multiple times as a sub-style, the
* nsub argument must be > 0 and represents the nth instance of the sub-style
* (same as for the pair_coeff command, for example). In that case
* nsub=0 will not produce a match and this function will return -1.
* *
* Once the pair instance has been identified, multiple neighbor list requests * The final condition to be checked is the request ID (reqid). This
* may be found. Every neighbor list is uniquely identified by its request * will normally be 0, but some pair styles request multiple neighbor
* index. Thus, providing this request index ensures that the correct neighbor * lists and set the request ID to a value > 0.
* list index is returned.
* *
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``. * \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
* \param style String used to search for pair style instance * \param style String used to search for pair style instance
* \param exact Flag to control whether style should match exactly or only * \param exact Flag to control whether style should match exactly or only
* must be contained in pair style name * a regular expression / sub-string match is applied.
* \param nsub match nsub-th hybrid sub-style * \param nsub match nsub-th hybrid sub-style instance of the same style
* \param request request index that specifies which neighbor list should be * \param reqid request id to identify neighbor list in case there are
* returned, in case there are multiple neighbor lists requests * multiple requests from the same pair style instance
* for the found pair style
* \return return neighbor list index if found, otherwise -1 */ * \return return neighbor list index if found, otherwise -1 */
int lammps_find_pair_neighlist(void* handle, char * style, int exact, int nsub, int request) { int lammps_find_pair_neighlist(void *handle, const char *style, int exact, int nsub, int reqid) {
LAMMPS * lmp = (LAMMPS *) handle; LAMMPS *lmp = (LAMMPS *) handle;
Pair* pair = lmp->force->pair_match(style, exact, nsub); Pair *pair = lmp->force->pair_match(style, exact, nsub);
if (pair != nullptr) { if (pair != nullptr) {
// find neigh list // find neigh list
for (int i = 0; i < lmp->neighbor->nlist; i++) { for (int i = 0; i < lmp->neighbor->nlist; i++) {
NeighList * list = lmp->neighbor->lists[i]; NeighList *list = lmp->neighbor->lists[i];
if (list->requestor_type != NeighList::PAIR || pair != list->requestor) continue; if ( (list->requestor_type == NeighList::PAIR)
&& (pair == list->requestor)
if (list->index == request) { && (list->id == reqid) ) return i;
return i;
}
} }
} }
return -1; return -1;
@ -3958,74 +3965,60 @@ int lammps_find_pair_neighlist(void* handle, char * style, int exact, int nsub,
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/** Find neighbor list index of fix neighbor list /** Find index of a neighbor list requested by a fix
*
* The neighbor list request from a fix is identified by the fix ID and
* the request ID. The request ID is typically 0, but will be > 0 in
* case a fix has multiple neighbor list requests.
* *
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``. * \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
* \param id Identifier of fix instance * \param id Identifier of fix instance
* \param request request index that specifies which request should be returned, * \param reqid request id to identify neighbor list in case there are
* in case there are multiple neighbor lists for this fix * multiple requests from the same fix
* \return return neighbor list index if found, otherwise -1 */ * \return return neighbor list index if found, otherwise -1 */
int lammps_find_fix_neighlist(void* handle, char *id, int request) { int lammps_find_fix_neighlist(void *handle, const char *id, int reqid) {
LAMMPS * lmp = (LAMMPS *) handle; LAMMPS *lmp = (LAMMPS *) handle;
Fix* fix = nullptr; const int ifix = lmp->modify->find_fix(id);
const int nfix = lmp->modify->nfix; if (ifix < 0) return -1;
// find fix with name Fix *fix = lmp->modify->fix[ifix];
for (int ifix = 0; ifix < nfix; ifix++) { // find neigh list
if (strcmp(lmp->modify->fix[ifix]->id, id) == 0) { for (int i = 0; i < lmp->neighbor->nlist; i++) {
fix = lmp->modify->fix[ifix]; NeighList *list = lmp->neighbor->lists[i];
break; if ( (list->requestor_type == NeighList::FIX)
} && (fix == list->requestor)
} && (list->id == reqid) ) return i;
if (fix != nullptr) {
// find neigh list
for (int i = 0; i < lmp->neighbor->nlist; i++) {
NeighList * list = lmp->neighbor->lists[i];
if (list->requestor_type != NeighList::FIX || fix != list->requestor) continue;
if (list->index == request) {
return i;
}
}
} }
return -1; return -1;
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/** Find neighbor list index of compute neighbor list /** Find index of a neighbor list requested by a compute
*
* The neighbor list request from a compute is identified by the compute
* ID and the request ID. The request ID is typically 0, but will be
* > 0 in case a compute has multiple neighbor list requests.
* *
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``. * \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
* \param id Identifier of fix instance * \param id Identifier of compute instance
* \param request request index that specifies which request should be returned, * \param reqid request id to identify neighbor list in case there are
* in case there are multiple neighbor lists for this fix * multiple requests from the same compute
* \return return neighbor list index if found, otherwise -1 */ * \return return neighbor list index if found, otherwise -1 */
int lammps_find_compute_neighlist(void* handle, char *id, int request) { int lammps_find_compute_neighlist(void* handle, const char *id, int reqid) {
LAMMPS * lmp = (LAMMPS *) handle; LAMMPS *lmp = (LAMMPS *) handle;
Compute* compute = nullptr; const int icompute = lmp->modify->find_compute(id);
const int ncompute = lmp->modify->ncompute; if (icompute < 0) return -1;
// find compute with name Compute *compute = lmp->modify->compute[icompute];
for (int icompute = 0; icompute < ncompute; icompute++) { // find neigh list
if (strcmp(lmp->modify->compute[icompute]->id, id) == 0) { for (int i = 0; i < lmp->neighbor->nlist; i++) {
compute = lmp->modify->compute[icompute]; NeighList * list = lmp->neighbor->lists[i];
break; if ( (list->requestor_type == NeighList::COMPUTE)
} && (compute == list->requestor)
} && (list->id == reqid) ) return i;
if (compute != nullptr) {
// find neigh list
for (int i = 0; i < lmp->neighbor->nlist; i++) {
NeighList * list = lmp->neighbor->lists[i];
if (list->requestor_type != NeighList::COMPUTE || compute != list->requestor) continue;
if (list->index == request) {
return i;
}
}
} }
return -1; return -1;
} }

View File

@ -138,8 +138,8 @@ void *lammps_extract_atom(void *handle, const char *name);
* Library functions to access data from computes, fixes, variables in LAMMPS * Library functions to access data from computes, fixes, variables in LAMMPS
* ---------------------------------------------------------------------- */ * ---------------------------------------------------------------------- */
void *lammps_extract_compute(void *handle, char *id, int, int); void *lammps_extract_compute(void *handle, const char *, int, int);
void *lammps_extract_fix(void *handle, char *, int, int, int, int); void *lammps_extract_fix(void *handle, const char *, int, int, int, int);
void *lammps_extract_variable(void *handle, const char *, const char *); void *lammps_extract_variable(void *handle, const char *, const char *);
int lammps_set_variable(void *, char *, char *); int lammps_set_variable(void *, char *, char *);
@ -160,20 +160,20 @@ void lammps_scatter(void *handle, char *name, int type, int count, void *data);
void lammps_scatter_subset(void *handle, char *name, int type, int count, int ndata, int *ids, void *data); void lammps_scatter_subset(void *handle, char *name, int type, int count, int ndata, int *ids, void *data);
#if !defined(LAMMPS_BIGBIG) #if !defined(LAMMPS_BIGBIG)
int lammps_create_atoms(void *handle, int n, int *id, int *type, int lammps_create_atoms(void *handle, int n, const int *id, const int *type,
double *x, double *v, int *image, int bexpand); const double *x, const double *v, const int *image, int bexpand);
#else #else
int lammps_create_atoms(void *handle, int n, int64_t *id, int *type, int lammps_create_atoms(void *handle, int n, const int64_t *id, const int *type,
double *x, double *v, int64_t* image, int bexpand); const double *x, const double *v, const int64_t* image, int bexpand);
#endif #endif
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Library functions for accessing neighbor lists * Library functions for accessing neighbor lists
* ---------------------------------------------------------------------- */ * ---------------------------------------------------------------------- */
int lammps_find_pair_neighlist(void *handle, char *style, int exact, int nsub, int request); int lammps_find_pair_neighlist(void *handle, const char *style, int exact, int nsub, int request);
int lammps_find_fix_neighlist(void *handle, char *id, int request); int lammps_find_fix_neighlist(void *handle, const char *id, int request);
int lammps_find_compute_neighlist(void *handle, char *id, int request); int lammps_find_compute_neighlist(void *handle, const char *id, int request);
int lammps_neighlist_num_elements(void *handle, int idx); int lammps_neighlist_num_elements(void *handle, int idx);
void lammps_neighlist_element_neighbors(void *handle, int idx, int element, int *iatom, int *numneigh, int **neighbors); void lammps_neighlist_element_neighbors(void *handle, int idx, int element, int *iatom, int *numneigh, int **neighbors);

View File

@ -143,6 +143,7 @@ void NeighList::post_constructor(NeighRequest *nq)
respamiddle = nq->respamiddle; respamiddle = nq->respamiddle;
respainner = nq->respainner; respainner = nq->respainner;
copy = nq->copy; copy = nq->copy;
id = nq->id;
if (nq->copy) { if (nq->copy) {
listcopy = neighbor->lists[nq->copylist]; listcopy = neighbor->lists[nq->copylist];

View File

@ -44,6 +44,7 @@ class NeighList : protected Pointers {
int copy; // 1 if this list is copied from another list int copy; // 1 if this list is copied from another list
int kk2cpu; // 1 if this list is copied from Kokkos to CPU int kk2cpu; // 1 if this list is copied from Kokkos to CPU
int copymode; // 1 if this is a Kokkos on-device copy int copymode; // 1 if this is a Kokkos on-device copy
int id; // copied from neighbor list request
// data structs to store neighbor pairs I,J and associated values // data structs to store neighbor pairs I,J and associated values

View File

@ -11,6 +11,7 @@ add_executable(test_library_properties test_library_properties.cpp test_main.cpp
target_link_libraries(test_library_properties PRIVATE lammps GTest::GTest GTest::GMock) target_link_libraries(test_library_properties PRIVATE lammps GTest::GTest GTest::GMock)
target_compile_definitions(test_library_properties PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(test_library_properties PRIVATE -DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR})
add_test(LibraryProperties test_library_properties) add_test(LibraryProperties test_library_properties)
set_tests_properties(LibraryProperties PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
set(TEST_CONFIG_DEFS "-DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR};-DLAMMPS_${LAMMPS_SIZES}") set(TEST_CONFIG_DEFS "-DTEST_INPUT_FOLDER=${CMAKE_CURRENT_SOURCE_DIR};-DLAMMPS_${LAMMPS_SIZES}")
set(PKG_COUNT 0) set(PKG_COUNT 0)

View File

@ -160,7 +160,9 @@ TEST_F(LibraryProperties, box)
boxlo[0] = -6.1; boxlo[0] = -6.1;
boxhi[1] = 7.3; boxhi[1] = 7.3;
xy = 0.1; xy = 0.1;
if (!verbose) ::testing::internal::CaptureStdout();
lammps_reset_box(lmp, boxlo, boxhi, xy, yz, xz); lammps_reset_box(lmp, boxlo, boxhi, xy, yz, xz);
if (!verbose) ::testing::internal::GetCapturedStdout();
lammps_extract_box(lmp, boxlo, boxhi, &xy, &yz, &xz, pflags, &boxflag); lammps_extract_box(lmp, boxlo, boxhi, &xy, &yz, &xz, pflags, &boxflag);
EXPECT_DOUBLE_EQ(boxlo[0], -6.1); EXPECT_DOUBLE_EQ(boxlo[0], -6.1);
EXPECT_DOUBLE_EQ(boxlo[1], -7.692866); EXPECT_DOUBLE_EQ(boxlo[1], -7.692866);
@ -313,6 +315,121 @@ TEST_F(LibraryProperties, global)
EXPECT_DOUBLE_EQ((*d_ptr), 0.1); EXPECT_DOUBLE_EQ((*d_ptr), 0.1);
}; };
TEST_F(LibraryProperties, neighlist)
{
if (!lammps_has_style(lmp, "pair", "sw")) GTEST_SKIP();
const char sysinit[] = "boundary f f f\n"
"units real\n"
"region box block -5 5 -5 5 -5 5\n"
"create_box 2 box\n"
"mass 1 1.0\n"
"mass 2 1.0\n"
"pair_style hybrid/overlay lj/cut 4.0 lj/cut 4.0 morse 4.0 sw\n"
"pair_coeff * * sw Si.sw Si NULL\n"
"pair_coeff 1 2 morse 0.2 2.0 2.0\n"
"pair_coeff 2 2 lj/cut 1 0.1 2.0\n"
"pair_coeff * * lj/cut 2 0.01 2.0\n"
"compute dist all pair/local dist\n"
"fix dist all ave/histo 1 1 1 0.0 3.0 4 c_dist mode vector\n"
"thermo_style custom f_dist[*]";
const double pos[] = {0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0};
const tagint ids[] = {1, 2, 3, 4, 5, 6, 7};
const int types[] = {1, 1, 1, 1, 2, 2, 2};
const int numatoms = sizeof(ids) / sizeof(tagint);
if (!verbose) ::testing::internal::CaptureStdout();
lammps_commands_string(lmp, sysinit);
lammps_create_atoms(lmp, numatoms, ids, types, pos, nullptr, nullptr, 0);
lammps_command(lmp, "run 0 post no");
if (!verbose) ::testing::internal::GetCapturedStdout();
int nhisto =
*(double *)lammps_extract_fix(lmp, "dist", LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR, 0, 0);
int nskip = *(double *)lammps_extract_fix(lmp, "dist", LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR, 1, 0);
double minval =
*(double *)lammps_extract_fix(lmp, "dist", LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR, 2, 0);
double maxval =
*(double *)lammps_extract_fix(lmp, "dist", LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR, 3, 0);
// 21 pair distances counted, none skipped, smallest 1.0, largest 2.1
EXPECT_EQ(nhisto, 21);
EXPECT_EQ(nskip, 0);
EXPECT_DOUBLE_EQ(minval, 1.0);
EXPECT_DOUBLE_EQ(maxval, 2.1);
const int nlocal = lammps_extract_setting(lmp, "nlocal");
EXPECT_EQ(nlocal, numatoms);
EXPECT_NE(lammps_find_pair_neighlist(lmp, "sw", 1, 0, 0), -1);
EXPECT_NE(lammps_find_pair_neighlist(lmp, "morse", 1, 0, 0), -1);
EXPECT_NE(lammps_find_pair_neighlist(lmp, "lj/cut", 1, 1, 0), -1);
EXPECT_NE(lammps_find_pair_neighlist(lmp, "lj/cut", 1, 2, 0), -1);
EXPECT_EQ(lammps_find_pair_neighlist(lmp, "lj/cut", 1, 0, 0), -1);
EXPECT_EQ(lammps_find_pair_neighlist(lmp, "hybrid/overlay", 1, 0, 0), -1);
EXPECT_NE(lammps_find_compute_neighlist(lmp, "dist", 0), -1);
EXPECT_EQ(lammps_find_fix_neighlist(lmp, "dist", 0), -1);
EXPECT_EQ(lammps_find_compute_neighlist(lmp, "xxx", 0), -1);
// full neighbor list for 4 type 1 atoms
// all have 3 type 1 atom neighbors
int idx = lammps_find_pair_neighlist(lmp, "sw", 1, 0, 0);
int num = lammps_neighlist_num_elements(lmp, idx);
EXPECT_EQ(num, 4);
int iatom, inum, *neighbors;
for (int i = 0; i < num; ++i) {
lammps_neighlist_element_neighbors(lmp, idx, i, &iatom, &inum, &neighbors);
EXPECT_EQ(iatom, i);
EXPECT_EQ(inum, 3);
EXPECT_NE(neighbors, nullptr);
}
// half neighbor list for all pairs between type 1 and type 2
// 4 type 1 atoms with 3 type 2 neighbors and 3 type 2 atoms without neighbors
idx = lammps_find_pair_neighlist(lmp, "morse", 0, 0, 0);
num = lammps_neighlist_num_elements(lmp, idx);
EXPECT_EQ(num, nlocal);
for (int i = 0; i < num; ++i) {
lammps_neighlist_element_neighbors(lmp, idx, i, &iatom, &inum, &neighbors);
if (i < 4)
EXPECT_EQ(inum, 3);
else
EXPECT_EQ(inum, 0);
EXPECT_NE(neighbors, nullptr);
}
// half neighbor list between type 2 atoms only
// 3 pairs with 2, 1, 0 neighbors
idx = lammps_find_pair_neighlist(lmp, "lj/cut", 1, 1, 0);
num = lammps_neighlist_num_elements(lmp, idx);
EXPECT_EQ(num, 3);
for (int i = 0; i < num; ++i) {
lammps_neighlist_element_neighbors(lmp, idx, i, &iatom, &inum, &neighbors);
EXPECT_EQ(inum, 2 - i);
EXPECT_NE(neighbors, nullptr);
}
// half neighbor list between all pairs. same as simple lj/cut case
idx = lammps_find_pair_neighlist(lmp, "lj/cut", 1, 2, 0);
num = lammps_neighlist_num_elements(lmp, idx);
EXPECT_EQ(num, nlocal);
for (int i = 0; i < num; ++i) {
lammps_neighlist_element_neighbors(lmp, idx, i, &iatom, &inum, &neighbors);
EXPECT_EQ(inum, nlocal - 1 - i);
EXPECT_NE(neighbors, nullptr);
}
// the compute has a half neighbor list
idx = lammps_find_compute_neighlist(lmp, "dist", 0);
num = lammps_neighlist_num_elements(lmp, idx);
EXPECT_EQ(num, nlocal);
for (int i = 0; i < num; ++i) {
lammps_neighlist_element_neighbors(lmp, idx, i, &iatom, &inum, &neighbors);
EXPECT_EQ(inum, nlocal - 1 - i);
EXPECT_NE(neighbors, nullptr);
}
};
class AtomProperties : public ::testing::Test { class AtomProperties : public ::testing::Test {
protected: protected:
void *lmp; void *lmp;

View File

@ -28,6 +28,7 @@ endif()
if(Python_EXECUTABLE) if(Python_EXECUTABLE)
# prepare to augment the environment so that the LAMMPS python module and the shared library is found. # prepare to augment the environment so that the LAMMPS python module and the shared library is found.
set(PYTHON_TEST_ENVIRONMENT PYTHONPATH=${LAMMPS_PYTHON_DIR}:$ENV{PYTHONPATH}) set(PYTHON_TEST_ENVIRONMENT PYTHONPATH=${LAMMPS_PYTHON_DIR}:$ENV{PYTHONPATH})
list(APPEND PYTHON_TEST_ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}")
if(APPLE) if(APPLE)
list(APPEND PYTHON_TEST_ENVIRONMENT "DYLD_LIBRARY_PATH=${CMAKE_BINARY_DIR}:$ENV{DYLD_LIBRARY_PATH};LAMMPS_CMAKE_CACHE=${CMAKE_BINARY_DIR}/CMakeCache.txt") list(APPEND PYTHON_TEST_ENVIRONMENT "DYLD_LIBRARY_PATH=${CMAKE_BINARY_DIR}:$ENV{DYLD_LIBRARY_PATH};LAMMPS_CMAKE_CACHE=${CMAKE_BINARY_DIR}/CMakeCache.txt")
else() else()

View File

@ -1,6 +1,17 @@
import sys,os,unittest import sys,os,unittest
from lammps import lammps, LMP_VAR_ATOM from lammps import lammps, LMP_VAR_ATOM, LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR
has_manybody=False
try:
machine=None
if 'LAMMPS_MACHINE_NAME' in os.environ:
machine=os.environ['LAMMPS_MACHINE_NAME']
lmp=lammps(name=machine)
has_manybody = lmp.has_style("pair","sw")
lmp.close()
except:
pass
class PythonCommand(unittest.TestCase): class PythonCommand(unittest.TestCase):
@ -85,36 +96,35 @@ create_atoms 1 single &
natoms = self.lmp.get_natoms() natoms = self.lmp.get_natoms()
self.assertEqual(natoms,2) self.assertEqual(natoms,2)
def testNeighborList(self): def testNeighborListSimple(self):
self.lmp.command("units lj") self.lmp.commands_string("""
self.lmp.command("atom_style atomic") units lj
self.lmp.command("atom_modify map array") atom_style atomic
self.lmp.command("boundary f f f") atom_modify map array
self.lmp.command("region box block 0 2 0 2 0 2") boundary f f f
self.lmp.command("create_box 1 box") region box block 0 2 0 2 0 2
create_box 1 box""")
x = [
1.0, 1.0, 1.0,
1.0, 1.0, 1.5
]
x = [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.5 ]
types = [1, 1] types = [1, 1]
self.assertEqual(self.lmp.create_atoms(2, id=None, type=types, x=x), 2) self.assertEqual(self.lmp.create_atoms(2, id=None, type=types, x=x), 2)
nlocal = self.lmp.extract_global("nlocal") nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 2) self.assertEqual(nlocal, 2)
self.lmp.command("mass 1 1.0") self.lmp.commands_string("""
self.lmp.command("velocity all create 3.0 87287") mass 1 1.0
self.lmp.command("pair_style lj/cut 2.5") velocity all create 3.0 87287
self.lmp.command("pair_coeff 1 1 1.0 1.0 2.5") pair_style lj/cut 2.5
self.lmp.command("neighbor 0.1 bin") pair_coeff 1 1 1.0 1.0 2.5
self.lmp.command("neigh_modify every 20 delay 0 check no") neighbor 0.1 bin
neigh_modify every 20 delay 0 check no
run 0 post no""")
self.lmp.command("run 0") idx = self.lmp.find_pair_neighlist("lj/cut")
self.assertNotEqual(idx, -1)
self.assertEqual(self.lmp.find_pair_neighlist("lj/cut"), 0) self.assertEqual(self.lmp.find_pair_neighlist("morse"), -1)
nlist = self.lmp.get_neighlist(0) nlist = self.lmp.get_neighlist(idx)
self.assertEqual(len(nlist), 2) self.assertEqual(len(nlist), 2)
atom_i, numneigh_i, neighbors_i = nlist[0] atom_i, numneigh_i, neighbors_i = nlist[0]
atom_j, numneigh_j, _ = nlist[1] atom_j, numneigh_j, _ = nlist[1]
@ -127,6 +137,193 @@ create_atoms 1 single &
self.assertEqual(1, neighbors_i[0]) self.assertEqual(1, neighbors_i[0])
def testNeighborListHalf(self):
self.lmp.commands_string("""
boundary f f f
units real
region box block -5 5 -5 5 -5 5
create_box 1 box
mass 1 1.0
pair_style lj/cut 4.0
pair_coeff 1 1 0.2 2.0
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 1, 1, 1]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
self.assertEqual(self.lmp.find_pair_neighlist("lj/cut"),0)
nlist = self.lmp.get_neighlist(0)
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, num, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(num,nlocal-1-i)
# look up neighbor list by atom index
num, neighs = nlist.find(2)
self.assertEqual(num,4)
self.assertIsNotNone(neighs,None)
# this one will fail
num, neighs = nlist.find(10)
self.assertEqual(num,-1)
self.assertIsNone(neighs,None)
@unittest.skipIf(not has_manybody,"Full neighbor list test for manybody potential")
def testNeighborListFull(self):
self.lmp.commands_string("""
boundary f f f
units metal
region box block -5 5 -5 5 -5 5
create_box 1 box
mass 1 1.0
pair_style sw
pair_coeff * * Si.sw Si
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 1, 1, 1]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
self.assertEqual(self.lmp.find_pair_neighlist("sw"),0)
nlist = self.lmp.get_neighlist(0)
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, num, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(num,nlocal-1)
@unittest.skipIf(not has_manybody,"Hybrid neighbor list test for manybody potential")
def testNeighborListHybrid(self):
self.lmp.commands_string("""
boundary f f f
units metal
region box block -5 5 -5 5 -5 5
create_box 2 box
mass * 1.0
pair_style hybrid/overlay morse 4.0 lj/cut 4.0 lj/cut 4.0 sw
pair_coeff * * sw Si.sw Si NULL
pair_coeff 1 2 morse 0.2 2.0 2.0
pair_coeff 2 2 lj/cut 1 0.1 2.0
pair_coeff * * lj/cut 2 0.01 2.0
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 2, 2, 2]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
# valid and invalid lookups
self.assertNotEqual(self.lmp.find_pair_neighlist("sw"),-1)
self.assertNotEqual(self.lmp.find_pair_neighlist("morse"),-1)
self.assertNotEqual(self.lmp.find_pair_neighlist("lj/cut",nsub=1),-1)
self.assertNotEqual(self.lmp.find_pair_neighlist("lj/cut",nsub=2),-1)
self.assertEqual(self.lmp.find_pair_neighlist("lj/cut"),-1)
self.assertEqual(self.lmp.find_pair_neighlist("hybrid/overlay"),-1)
self.assertNotEqual(self.lmp.get_neighlist(4).size,0)
self.assertEqual(self.lmp.get_neighlist(5).size,-1)
# full neighbor list for 4 type 1 atoms
# all have 3 type 1 atom neighbors
nlist = self.lmp.get_neighlist(self.lmp.find_pair_neighlist("sw"))
self.assertEqual(nlist.size, 4)
for i in range(0,nlist.size):
idx, num, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(num,3)
# half neighbor list for all pairs between type 1 and type 2
# 4 type 1 atoms with 3 type 2 neighbors and 3 type 2 atoms without neighbors
nlist = self.lmp.get_neighlist(self.lmp.find_pair_neighlist("morse"))
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, num, neighs = nlist.get(i)
if (i < 4): self.assertEqual(num,3)
else: self.assertEqual(num,0)
# half neighbor list between type 2 atoms only
# 3 pairs with 2, 1, 0 neighbors
nlist = self.lmp.get_neighlist(self.lmp.find_pair_neighlist("lj/cut",nsub=1))
self.assertEqual(nlist.size, 3)
for i in range(0,nlist.size):
idx, num, neighs = nlist.get(i)
self.assertEqual(num,2-i)
# half neighbor list between all pairs. same as simple lj/cut case
nlist = self.lmp.get_neighlist(self.lmp.find_pair_neighlist("lj/cut",nsub=2))
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, num, neighs = nlist.get(i)
self.assertEqual(num,nlocal-1-i)
def testNeighborListCompute(self):
self.lmp.commands_string("""
boundary f f f
units real
region box block -5 5 -5 5 -5 5
create_box 1 box
mass 1 1.0
pair_style lj/cut 4.0
pair_coeff 1 1 0.2 2.0
compute dist all pair/local dist
fix dist all ave/histo 1 1 1 0.0 3.0 4 c_dist mode vector
thermo_style custom f_dist[*]
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 1, 1, 1]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
# check compute data from histogram summary
nhisto = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=0)
nskip = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=1)
minval = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=2)
maxval = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=3)
# 21 pair distances counted, none skipped, smallest 1.0, largest 2.1
self.assertEqual(nhisto,21)
self.assertEqual(nskip,0)
self.assertEqual(minval,1.0)
self.assertEqual(maxval,2.1)
self.assertNotEqual(self.lmp.find_pair_neighlist("lj/cut"),-1)
self.assertNotEqual(self.lmp.find_compute_neighlist("dist"),-1)
self.assertEqual(self.lmp.find_compute_neighlist("xxx"),-1)
self.assertEqual(self.lmp.find_fix_neighlist("dist"),-1)
# the compute has a half neighbor list
nlist = self.lmp.get_neighlist(self.lmp.find_compute_neighlist("dist"))
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, num, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(num,nlocal-1-i)
def test_extract_box_non_periodic(self): def test_extract_box_non_periodic(self):
self.lmp.command("boundary f f f") self.lmp.command("boundary f f f")
self.lmp.command("region box block 0 2 0 2 0 2") self.lmp.command("region box block 0 2 0 2 0 2")

View File

@ -4,6 +4,17 @@ from lammps import lammps, LAMMPS_INT, LMP_STYLE_GLOBAL, LMP_STYLE_LOCAL, \
LMP_VAR_ATOM LMP_VAR_ATOM
from ctypes import c_void_p from ctypes import c_void_p
has_manybody=False
try:
machine=None
if 'LAMMPS_MACHINE_NAME' in os.environ:
machine=os.environ['LAMMPS_MACHINE_NAME']
lmp=lammps(name=machine)
has_manybody = lmp.has_style("pair","sw")
lmp.close()
except:
pass
try: try:
import numpy import numpy
NUMPY_INSTALLED = True NUMPY_INSTALLED = True
@ -137,36 +148,34 @@ class PythonNumpy(unittest.TestCase):
self.assertTrue((x[1] == (1.0, 1.0, 1.5)).all()) self.assertTrue((x[1] == (1.0, 1.0, 1.5)).all())
self.assertEqual(len(v), 2) self.assertEqual(len(v), 2)
def testNeighborList(self): def testNeighborListSimple(self):
self.lmp.command("units lj") self.lmp.commands_string("""
self.lmp.command("atom_style atomic") units lj
self.lmp.command("atom_modify map array") atom_style atomic
self.lmp.command("boundary f f f") atom_modify map array
self.lmp.command("region box block 0 2 0 2 0 2") boundary f f f
self.lmp.command("create_box 1 box") region box block 0 2 0 2 0 2
create_box 1 box""")
x = [
1.0, 1.0, 1.0,
1.0, 1.0, 1.5
]
x = [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.5 ]
types = [1, 1] types = [1, 1]
self.assertEqual(self.lmp.create_atoms(2, id=None, type=types, x=x), 2) self.assertEqual(self.lmp.create_atoms(2, id=None, type=types, x=x), 2)
nlocal = self.lmp.extract_global("nlocal") nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 2) self.assertEqual(nlocal, 2)
self.lmp.command("mass 1 1.0") self.lmp.commands_string("""
self.lmp.command("velocity all create 3.0 87287") mass 1 1.0
self.lmp.command("pair_style lj/cut 2.5") velocity all create 3.0 87287
self.lmp.command("pair_coeff 1 1 1.0 1.0 2.5") pair_style lj/cut 2.5
self.lmp.command("neighbor 0.1 bin") pair_coeff 1 1 1.0 1.0 2.5
self.lmp.command("neigh_modify every 20 delay 0 check no") neighbor 0.1 bin
neigh_modify every 20 delay 0 check no
run 0 post no""")
self.lmp.command("run 0") idx = self.lmp.find_pair_neighlist("lj/cut")
self.assertNotEqual(idx, -1)
self.assertEqual(self.lmp.find_pair_neighlist("lj/cut"), 0) nlist = self.lmp.numpy.get_neighlist(idx)
nlist = self.lmp.numpy.get_neighlist(0)
self.assertEqual(len(nlist), 2) self.assertEqual(len(nlist), 2)
atom_i, neighbors_i = nlist[0] atom_i, neighbors_i = nlist[0]
atom_j, neighbors_j = nlist[1] atom_j, neighbors_j = nlist[1]
@ -180,6 +189,192 @@ class PythonNumpy(unittest.TestCase):
self.assertIn(1, neighbors_i) self.assertIn(1, neighbors_i)
self.assertNotIn(0, neighbors_j) self.assertNotIn(0, neighbors_j)
def testNeighborListHalf(self):
self.lmp.commands_string("""
boundary f f f
units real
region box block -5 5 -5 5 -5 5
create_box 1 box
mass 1 1.0
pair_style lj/cut 4.0
pair_coeff 1 1 0.2 2.0
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 1, 1, 1]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
self.assertEqual(self.lmp.find_pair_neighlist("lj/cut"),0)
nlist = self.lmp.numpy.get_neighlist(0)
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(neighs.size,nlocal-1-i)
# look up neighbor list by atom index
neighs = nlist.find(2)
self.assertEqual(neighs.size,4)
self.assertIsNotNone(neighs,None)
# this one will fail
neighs = nlist.find(10)
self.assertIsNone(neighs,None)
@unittest.skipIf(not has_manybody,"Full neighbor list test for manybody potential")
def testNeighborListFull(self):
self.lmp.commands_string("""
boundary f f f
units metal
region box block -5 5 -5 5 -5 5
create_box 1 box
mass 1 1.0
pair_style sw
pair_coeff * * Si.sw Si
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 1, 1, 1]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
self.assertEqual(self.lmp.find_pair_neighlist("sw"),0)
nlist = self.lmp.numpy.get_neighlist(0)
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(neighs.size,nlocal-1)
@unittest.skipIf(not has_manybody,"Hybrid neighbor list test for manybody potential")
def testNeighborListHybrid(self):
self.lmp.commands_string("""
boundary f f f
units metal
region box block -5 5 -5 5 -5 5
create_box 2 box
mass * 1.0
pair_style hybrid/overlay morse 4.0 lj/cut 4.0 lj/cut 4.0 sw
pair_coeff * * sw Si.sw Si NULL
pair_coeff 1 2 morse 0.2 2.0 2.0
pair_coeff 2 2 lj/cut 1 0.1 2.0
pair_coeff * * lj/cut 2 0.01 2.0
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 2, 2, 2]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
# valid and invalid lookups
self.assertNotEqual(self.lmp.find_pair_neighlist("sw"),-1)
self.assertNotEqual(self.lmp.find_pair_neighlist("morse"),-1)
self.assertNotEqual(self.lmp.find_pair_neighlist("lj/cut",nsub=1),-1)
self.assertNotEqual(self.lmp.find_pair_neighlist("lj/cut",nsub=2),-1)
self.assertEqual(self.lmp.find_pair_neighlist("lj/cut"),-1)
self.assertEqual(self.lmp.find_pair_neighlist("hybrid/overlay"),-1)
self.assertNotEqual(self.lmp.numpy.get_neighlist(4).size,0)
self.assertEqual(self.lmp.numpy.get_neighlist(5).size,-1)
# full neighbor list for 4 type 1 atoms
# all have 3 type 1 atom neighbors
nlist = self.lmp.numpy.get_neighlist(self.lmp.find_pair_neighlist("sw"))
self.assertEqual(nlist.size, 4)
for i in range(0,nlist.size):
idx, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(neighs.size,3)
# half neighbor list for all pairs between type 1 and type 2
# 4 type 1 atoms with 3 type 2 neighbors and 3 type 2 atoms without neighbors
nlist = self.lmp.numpy.get_neighlist(self.lmp.find_pair_neighlist("morse"))
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, neighs = nlist.get(i)
if (i < 4): self.assertEqual(neighs.size,3)
else: self.assertEqual(neighs.size,0)
# half neighbor list between type 2 atoms only
# 3 pairs with 2, 1, 0 neighbors
nlist = self.lmp.numpy.get_neighlist(self.lmp.find_pair_neighlist("lj/cut",nsub=1))
self.assertEqual(nlist.size, 3)
for i in range(0,nlist.size):
idx, neighs = nlist.get(i)
self.assertEqual(neighs.size,2-i)
# half neighbor list between all pairs. same as simple lj/cut case
nlist = self.lmp.numpy.get_neighlist(self.lmp.find_pair_neighlist("lj/cut",nsub=2))
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, neighs = nlist.get(i)
self.assertEqual(neighs.size,nlocal-1-i)
def testNeighborListCompute(self):
self.lmp.commands_string("""
boundary f f f
units real
region box block -5 5 -5 5 -5 5
create_box 1 box
mass 1 1.0
pair_style lj/cut 4.0
pair_coeff 1 1 0.2 2.0
compute dist all pair/local dist
fix dist all ave/histo 1 1 1 0.0 3.0 4 c_dist mode vector
thermo_style custom f_dist[*]
""")
x = [ 0.0, 0.0, 0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, -1.1, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.1,
0.0, 0.0, 1.0 ]
tags = [1, 2, 3, 4, 5, 6, 7]
types = [1, 1, 1, 1, 1, 1, 1]
self.assertEqual(self.lmp.create_atoms(7, id=tags, type=types, x=x), 7)
nlocal = self.lmp.extract_global("nlocal")
self.assertEqual(nlocal, 7)
self.lmp.command("run 0 post no")
# check compute data from histogram summary
nhisto = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=0)
nskip = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=1)
minval = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=2)
maxval = self.lmp.extract_fix("dist",LMP_STYLE_GLOBAL,LMP_TYPE_VECTOR,nrow=3)
# 21 pair distances counted, none skipped, smallest 1.0, largest 2.1
self.assertEqual(nhisto,21)
self.assertEqual(nskip,0)
self.assertEqual(minval,1.0)
self.assertEqual(maxval,2.1)
self.assertNotEqual(self.lmp.find_pair_neighlist("lj/cut"),-1)
self.assertNotEqual(self.lmp.find_compute_neighlist("dist"),-1)
self.assertEqual(self.lmp.find_compute_neighlist("xxx"),-1)
self.assertEqual(self.lmp.find_fix_neighlist("dist"),-1)
# the compute has a half neighbor list
nlist = self.lmp.numpy.get_neighlist(self.lmp.find_compute_neighlist("dist"))
self.assertEqual(nlist.size, 7)
for i in range(0,nlist.size):
idx, neighs = nlist.get(i)
self.assertEqual(idx,i)
self.assertEqual(neighs.size,nlocal-1-i)
def test_extract_variable_equalstyle(self): def test_extract_variable_equalstyle(self):
self.lmp.command("variable a equal 100") self.lmp.command("variable a equal 100")
a = self.lmp.numpy.extract_variable("a") a = self.lmp.numpy.extract_variable("a")