Merge pull request #3471 from rohskopf/pair-zero-full

Optional full neighbor list with pair zero
This commit is contained in:
Axel Kohlmeyer
2022-10-04 16:49:45 -04:00
committed by GitHub
10 changed files with 233 additions and 18 deletions

View File

@ -12,6 +12,11 @@ endif()
if(POLICY CMP0109)
cmake_policy(SET CMP0109 OLD)
endif()
# set policy to silence warnings about timestamps of downloaded files. review occasionally if it may be set to NEW
if(POLICY CMP0135)
cmake_policy(SET CMP0135 OLD)
endif()
########################################
project(lammps CXX)

View File

@ -49,6 +49,14 @@ if(DOWNLOAD_MDI)
set(MDI_USE_PYTHON_PLUGINS ON)
endif()
endif()
# python plugins are not supported and thus must be always off on Windows
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
unset(Python_Development_FOUND)
set(MDI_USE_PYTHON_PLUGINS OFF)
if(CMAKE_CROSSCOMPILING)
set(CMAKE_INSTALL_LIBDIR lib)
endif()
endif()
# download/ build MDI library
# always build static library with -fpic
@ -57,8 +65,9 @@ if(DOWNLOAD_MDI)
ExternalProject_Add(mdi_build
URL ${MDI_URL}
URL_MD5 ${MDI_MD5}
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/mdi_build_ext
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/mdi_build_ext
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
@ -70,23 +79,23 @@ if(DOWNLOAD_MDI)
-Dplugins=ON
-Dpython_plugins=${MDI_USE_PYTHON_PLUGINS}
UPDATE_COMMAND ""
INSTALL_COMMAND ""
BUILD_BYPRODUCTS "<BINARY_DIR>/MDI_Library/libmdi.a"
INSTALL_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/mdi_build_ext/src/mdi_build-build --target install
BUILD_BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/mdi_build_ext/${CMAKE_INSTALL_LIBDIR}/mdi/${CMAKE_STATIC_LIBRARY_PREFIX}mdi${CMAKE_STATIC_LIBRARY_SUFFIX}"
)
# where is the compiled library?
ExternalProject_get_property(mdi_build BINARY_DIR)
set(MDI_BINARY_DIR "${BINARY_DIR}/MDI_Library")
ExternalProject_get_property(mdi_build PREFIX)
# workaround for older CMake versions
file(MAKE_DIRECTORY ${MDI_BINARY_DIR})
file(MAKE_DIRECTORY ${PREFIX}/${CMAKE_INSTALL_LIBDIR}/mdi)
file(MAKE_DIRECTORY ${PREFIX}/include/mdi)
# create imported target for the MDI library
add_library(LAMMPS::MDI UNKNOWN IMPORTED)
add_dependencies(LAMMPS::MDI mdi_build)
set_target_properties(LAMMPS::MDI PROPERTIES
IMPORTED_LOCATION "${MDI_BINARY_DIR}/libmdi.a"
INTERFACE_INCLUDE_DIRECTORIES ${MDI_BINARY_DIR}
)
IMPORTED_LOCATION "${PREFIX}/${CMAKE_INSTALL_LIBDIR}/mdi/${CMAKE_STATIC_LIBRARY_PREFIX}mdi${CMAKE_STATIC_LIBRARY_SUFFIX}"
INTERFACE_INCLUDE_DIRECTORIES ${PREFIX}/include/mdi
)
set(MDI_DEP_LIBS "")
# if compiling with python plugins we need

View File

@ -38,6 +38,40 @@ using the NumPy access method.
for n in np.nditer(nlist):
print(" atom {} with ID {}".format(n,tags[n]))
Another example for extracting a full neighbor list without evaluating a
potential is shown below.
.. code-block:: python
from lammps import lammps
import numpy as np
lmp = lammps()
lmp.commands_string("""
newton off
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 zero 1.0 full
pair_coeff * *
run 0 post no""")
# look up the neighbor list
nlidx = lmp.find_pair_neighlist('zero')
nl = lmp.numpy.get_neighlist(nlidx)
tags = lmp.extract_atom('id')
print("full 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):
pass
print(" atom {} with ID {}".format(n,tags[n]))
**Methods:**
* :py:meth:`lammps.get_neighlist() <lammps.lammps.get_neighlist()>`: Get neighbor list for given index

View File

@ -8,11 +8,12 @@ Syntax
.. code-block:: LAMMPS
pair_style zero cutoff [nocoeff]
pair_style zero cutoff [nocoeff] [full]
* zero = style name of this pair style
* cutoff = global cutoff (distance units)
* nocoeff = ignore all pair_coeff parameters (optional)
* full = build full neighbor list (optional)
Examples
""""""""
@ -45,6 +46,9 @@ section for any pair style. Similarly, any pair_coeff commands
will only be checked for the atom type numbers and the rest ignored.
In this case, only the global cutoff will be used.
The optional *full* flag builds a full neighbor list instead of the default
half neighbor list.
The following coefficients must be defined for each pair of atoms
types via the :doc:`pair_coeff <pair_coeff>` command as in the examples
above, or in the data file or restart files read by the

View File

@ -895,7 +895,7 @@ void FixAveTime::invoke_vector(bigint ntimestep)
int FixAveTime::column_length(int dynamic)
{
int m,length,lengthone;
int length,lengthone;
// determine nrows for static values

View File

@ -21,6 +21,8 @@
#include "comm.h"
#include "error.h"
#include "memory.h"
#include "neigh_list.h"
#include "neighbor.h"
#include <cstring>
@ -34,6 +36,7 @@ PairZero::PairZero(LAMMPS *lmp) : Pair(lmp)
writedata = 1;
single_enable = 1;
respa_enable = 1;
fullneighflag = 0;
}
/* ---------------------------------------------------------------------- */
@ -85,14 +88,24 @@ void PairZero::allocate()
void PairZero::settings(int narg, char **arg)
{
if ((narg != 1) && (narg != 2)) error->all(FLERR, "Illegal pair_style command");
if (narg < 1) utils::missing_cmd_args(FLERR, "pair_style zero", error);
cut_global = utils::numeric(FLERR, arg[0], false, lmp);
if (narg == 2) {
if (strcmp("nocoeff", arg[1]) == 0)
// reset to defaults
coeffflag = 1;
fullneighflag = 0;
int iarg = 1;
while (iarg < narg) {
if (strcmp("nocoeff", arg[iarg]) == 0) {
coeffflag = 0;
else
error->all(FLERR, "Illegal pair_style command");
++iarg;
} else if (strcmp("full", arg[iarg]) == 0) {
fullneighflag = 1;
++iarg;
} else
error->all(FLERR, "Unknown pair style zero option {}", arg[iarg]);
}
// reset cutoffs that have been explicitly set
@ -134,6 +147,18 @@ void PairZero::coeff(int narg, char **arg)
if (count == 0) error->all(FLERR, "Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairZero::init_style()
{
if (fullneighflag)
neighbor->add_request(this, NeighConst::REQ_FULL);
else
neighbor->add_request(this, NeighConst::REQ_DEFAULT);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */

View File

@ -42,6 +42,7 @@ class PairZero : public Pair {
void compute_outer(int, int) override;
void settings(int, char **) override;
void coeff(int, char **) override;
void init_style() override;
double init_one(int, int) override;
void write_restart(FILE *) override;
void read_restart(FILE *) override;
@ -55,11 +56,10 @@ class PairZero : public Pair {
double cut_global;
double **cut;
int coeffflag;
int fullneighflag; // 0 for half list, 1 for full list
virtual void allocate();
};
} // namespace LAMMPS_NS
#endif
#endif

View File

@ -52,6 +52,7 @@ namespace LAMMPS_NS {
TEST(PairList, ListVsPairBond)
{
if (!lammps_config_has_package("MOLECULE")) GTEST_SKIP();
if (!lammps_config_has_package("MISC")) GTEST_SKIP();
const char *lmpargv[] = {"melt", "-log", "none", "-nocite"};
int lmpargc = sizeof(lmpargv) / sizeof(const char *);

View File

@ -209,6 +209,75 @@ create_atoms 1 single &
self.assertEqual(idx,i)
self.assertEqual(num,nlocal-1)
def testNeighborListZeroHalf(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 zero 4.0
pair_coeff 1 1
""")
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("zero"),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)
def testNeighborListZeroFull(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 zero 4.0 full
pair_coeff * *
""")
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("zero"),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("""

View File

@ -412,6 +412,74 @@ class PythonNumpy(unittest.TestCase):
idx, neighs = nlist.get(i)
self.assertEqual(neighs.size,nlocal-1-i)
def testNeighborListZeroHalf(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 zero 4.0
pair_coeff 1 1
""")
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("zero"),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)
def testNeighborListZeroFull(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 zero 4.0 full
pair_coeff * *
""")
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("zero"),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)
def testNeighborListCompute(self):
self.lmp.commands_string("""
boundary f f f