Add pair_modify option to allow separate cutoffs for each neigh list with pair hybrid/overlay

This commit is contained in:
Stan Gerald Moore
2022-07-07 16:48:03 -06:00
parent 7d06ee9aa7
commit de274cddef
22 changed files with 1069 additions and 73 deletions

View File

@ -13,7 +13,7 @@ Syntax
* one or more keyword/value pairs may be listed * one or more keyword/value pairs may be listed
* keyword = *pair* or *shift* or *mix* or *table* or *table/disp* or *tabinner* * keyword = *pair* or *shift* or *mix* or *table* or *table/disp* or *tabinner*
or *tabinner/disp* or *tail* or *compute* or *nofdotr* or *special* or or *tabinner/disp* or *tail* or *compute* or *nofdotr* or *special* or
*compute/tally* *compute/tally* or *neigh/trim*
.. parsed-literal:: .. parsed-literal::
@ -37,6 +37,7 @@ Syntax
which = *lj/coul* or *lj* or *coul* which = *lj/coul* or *lj* or *coul*
w1,w2,w3 = 1-2, 1-3, 1-4 weights from 0.0 to 1.0 inclusive w1,w2,w3 = 1-2, 1-3, 1-4 weights from 0.0 to 1.0 inclusive
*compute/tally* value = *yes* or *no* *compute/tally* value = *yes* or *no*
*neigh/trim* value = *yes* or *no*
Examples Examples
"""""""" """"""""
@ -283,6 +284,26 @@ the *pair* keyword. Use *no* to disable, or *yes* to enable.
The "pair_modify pair compute/tally" command must be issued The "pair_modify pair compute/tally" command must be issued
**before** the corresponding compute style is defined. **before** the corresponding compute style is defined.
The *neigh/trim* keyword controls whether an explicit cutoff is set
for each neighbor list requested by the individual pair sub-styles
when using :doc:`pair hybrid\*/overlay <pair_hybrid_overlay>`. When
this keyword is set to *no*, then the cutoff of the pair sub-style
neighbor will be set to the master list distance, and if possible the
neighbor list will be copied directly from another list. When this
keyword is set to *yes* then the cutoff of the neighbor list will be
explicitly set to the value requested by the pair sub-style, and if
possible the list will be created by trimming from another list with a
longer cutoff, otherwise a new neighbor list will be created with the
specified cutoff. The *yes* option can be faster when there are
multiple pair styles with different cutoffs since the number of
pair-wise distance checks between neighbors is reduced (but the time
required to build the neighbor lists is increased).
.. note::
The "pair_modify neigh/trim" command only applies when there are
multiple pair sub-styles, i.e. when using pair hybrid/overlay
---------- ----------
Restrictions Restrictions
@ -304,7 +325,7 @@ Default
""""""" """""""
The option defaults are mix = geometric, shift = no, table = 12, The option defaults are mix = geometric, shift = no, table = 12,
tabinner = sqrt(2.0), tail = no, and compute = yes. tabinner = sqrt(2.0), tail = no, compute = yes, and neigh/trim no.
Note that some pair styles perform mixing, but only a certain style of Note that some pair styles perform mixing, but only a certain style of
mixing. See the doc pages for individual pair styles for details. mixing. See the doc pages for individual pair styles for details.

View File

@ -204,6 +204,8 @@ action npair_halffull_kokkos.cpp
action npair_halffull_kokkos.h action npair_halffull_kokkos.h
action npair_skip_kokkos.cpp action npair_skip_kokkos.cpp
action npair_skip_kokkos.h action npair_skip_kokkos.h
action npair_trim_kokkos.cpp
action npair_trim_kokkos.h
action npair_kokkos.cpp action npair_kokkos.cpp
action npair_kokkos.h action npair_kokkos.h
action npair_ssa_kokkos.cpp npair_half_bin_newton_ssa.cpp action npair_ssa_kokkos.cpp npair_half_bin_newton_ssa.cpp

View File

@ -26,8 +26,8 @@ using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
template<class DeviceType, int NEWTON> template<class DeviceType, int NEWTON, int TRIM>
NPairHalffullKokkos<DeviceType,NEWTON>::NPairHalffullKokkos(LAMMPS *lmp) : NPair(lmp) { NPairHalffullKokkos<DeviceType,NEWTON,TRIM>::NPairHalffullKokkos(LAMMPS *lmp) : NPair(lmp) {
atomKK = (AtomKokkos *) atom; atomKK = (AtomKokkos *) atom;
execution_space = ExecutionSpaceFromDevice<DeviceType>::space; execution_space = ExecutionSpaceFromDevice<DeviceType>::space;
} }
@ -41,15 +41,17 @@ NPairHalffullKokkos<DeviceType,NEWTON>::NPairHalffullKokkos(LAMMPS *lmp) : NPair
if ghost, also store neighbors of ghost atoms & set inum,gnum correctly if ghost, also store neighbors of ghost atoms & set inum,gnum correctly
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
template<class DeviceType, int NEWTON> template<class DeviceType, int NEWTON, int TRIM>
void NPairHalffullKokkos<DeviceType,NEWTON>::build(NeighList *list) void NPairHalffullKokkos<DeviceType,NEWTON,TRIM>::build(NeighList *list)
{ {
if (NEWTON) { if (NEWTON || TRIM) {
x = atomKK->k_x.view<DeviceType>(); x = atomKK->k_x.view<DeviceType>();
atomKK->sync(execution_space,X_MASK); atomKK->sync(execution_space,X_MASK);
} }
nlocal = atom->nlocal; nlocal = atom->nlocal;
cutsq_custom = cutoff_custom*cutoff_custom;
NeighListKokkos<DeviceType>* k_list_full = static_cast<NeighListKokkos<DeviceType>*>(list->listfull); NeighListKokkos<DeviceType>* k_list_full = static_cast<NeighListKokkos<DeviceType>*>(list->listfull);
d_ilist_full = k_list_full->d_ilist; d_ilist_full = k_list_full->d_ilist;
d_numneigh_full = k_list_full->d_numneigh; d_numneigh_full = k_list_full->d_numneigh;
@ -76,14 +78,14 @@ void NPairHalffullKokkos<DeviceType,NEWTON>::build(NeighList *list)
k_list->k_ilist.template modify<DeviceType>(); k_list->k_ilist.template modify<DeviceType>();
} }
template<class DeviceType, int NEWTON> template<class DeviceType, int NEWTON, int TRIM>
KOKKOS_INLINE_FUNCTION KOKKOS_INLINE_FUNCTION
void NPairHalffullKokkos<DeviceType,NEWTON>::operator()(TagNPairHalffullCompute, const int &ii) const { void NPairHalffullKokkos<DeviceType,NEWTON,TRIM>::operator()(TagNPairHalffullCompute, const int &ii) const {
int n = 0; int n = 0;
const int i = d_ilist_full(ii); const int i = d_ilist_full(ii);
F_FLOAT xtmp,ytmp,ztmp; F_FLOAT xtmp,ytmp,ztmp;
if (NEWTON) { if (NEWTON || TRIM) {
xtmp = x(i,0); xtmp = x(i,0);
ytmp = x(i,1); ytmp = x(i,1);
ztmp = x(i,2); ztmp = x(i,2);
@ -108,9 +110,29 @@ void NPairHalffullKokkos<DeviceType,NEWTON>::operator()(TagNPairHalffullCompute,
if (x(j,1) == ytmp && x(j,0) < xtmp) continue; if (x(j,1) == ytmp && x(j,0) < xtmp) continue;
} }
} }
if (TRIM) {
const double delx = xtmp - x(j,0);
const double dely = ytmp - x(j,1);
const double delz = ztmp - x(j,2);
const double rsq = delx*delx + dely*dely + delz*delz;
if (rsq > cutsq_custom) continue;
}
neighbors_i(n++) = joriginal;
} else if (j > i) {
if (TRIM) {
const double delx = xtmp - x(j,0);
const double dely = ytmp - x(j,1);
const double delz = ztmp - x(j,2);
const double rsq = delx*delx + dely*dely + delz*delz;
if (rsq > cutsq_custom) continue;
}
neighbors_i(n++) = joriginal; neighbors_i(n++) = joriginal;
} else {
if (j > i) neighbors_i(n++) = joriginal;
} }
} }
@ -119,10 +141,14 @@ void NPairHalffullKokkos<DeviceType,NEWTON>::operator()(TagNPairHalffullCompute,
} }
namespace LAMMPS_NS { namespace LAMMPS_NS {
template class NPairHalffullKokkos<LMPDeviceType,0>; template class NPairHalffullKokkos<LMPDeviceType,0,0>;
template class NPairHalffullKokkos<LMPDeviceType,1>; template class NPairHalffullKokkos<LMPDeviceType,0,1>;
template class NPairHalffullKokkos<LMPDeviceType,1,0>;
template class NPairHalffullKokkos<LMPDeviceType,1,1>;
#ifdef LMP_KOKKOS_GPU #ifdef LMP_KOKKOS_GPU
template class NPairHalffullKokkos<LMPHostType,0>; template class NPairHalffullKokkos<LMPHostType,0,0>;
template class NPairHalffullKokkos<LMPHostType,1>; template class NPairHalffullKokkos<LMPHostType,0,1>;
template class NPairHalffullKokkos<LMPHostType,1,0>;
template class NPairHalffullKokkos<LMPHostType,1,1>;
#endif #endif
} }

View File

@ -13,27 +13,30 @@
#ifdef NPAIR_CLASS #ifdef NPAIR_CLASS
// clang-format off // clang-format off
// Trim off
// Newton // Newton
typedef NPairHalffullKokkos<LMPDeviceType,1> NPairKokkosHalffullNewtonDevice; typedef NPairHalffullKokkos<LMPDeviceType,1,0> NPairKokkosHalffullNewtonDevice;
NPairStyle(halffull/newton/kk/device, NPairStyle(halffull/newton/kk/device,
NPairKokkosHalffullNewtonDevice, NPairKokkosHalffullNewtonDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1> NPairKokkosHalffullNewtonHost; typedef NPairHalffullKokkos<LMPHostType,1,0> NPairKokkosHalffullNewtonHost;
NPairStyle(halffull/newton/kk/host, NPairStyle(halffull/newton/kk/host,
NPairKokkosHalffullNewtonHost, NPairKokkosHalffullNewtonHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_KOKKOS_HOST); NP_ORTHO | NP_TRI | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,1> NPairKokkosHalffullNewtonDevice; typedef NPairHalffullKokkos<LMPDeviceType,1,0> NPairKokkosHalffullNewtonDevice;
NPairStyle(halffull/newton/skip/kk/device, NPairStyle(halffull/newton/skip/kk/device,
NPairKokkosHalffullNewtonDevice, NPairKokkosHalffullNewtonDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_SKIP | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_SKIP | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1> NPairKokkosHalffullNewtonHost; typedef NPairHalffullKokkos<LMPHostType,1,0> NPairKokkosHalffullNewtonHost;
NPairStyle(halffull/newton/skip/kk/host, NPairStyle(halffull/newton/skip/kk/host,
NPairKokkosHalffullNewtonHost, NPairKokkosHalffullNewtonHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
@ -41,25 +44,25 @@ NPairStyle(halffull/newton/skip/kk/host,
// Newtoff // Newtoff
typedef NPairHalffullKokkos<LMPDeviceType,0> NPairKokkosHalffullNewtoffDevice; typedef NPairHalffullKokkos<LMPDeviceType,0,0> NPairKokkosHalffullNewtoffDevice;
NPairStyle(halffull/newtoff/kk/device, NPairStyle(halffull/newtoff/kk/device,
NPairKokkosHalffullNewtoffDevice, NPairKokkosHalffullNewtoffDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0> NPairKokkosHalffullNewtoffHost; typedef NPairHalffullKokkos<LMPHostType,0,0> NPairKokkosHalffullNewtoffHost;
NPairStyle(halffull/newtoff/kk/host, NPairStyle(halffull/newtoff/kk/host,
NPairKokkosHalffullNewtoffHost, NPairKokkosHalffullNewtoffHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_KOKKOS_HOST); NP_ORTHO | NP_TRI | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,0> NPairKokkosHalffullNewtoffDevice; typedef NPairHalffullKokkos<LMPDeviceType,0,0> NPairKokkosHalffullNewtoffDevice;
NPairStyle(halffull/newtoff/skip/kk/device, NPairStyle(halffull/newtoff/skip/kk/device,
NPairKokkosHalffullNewtoffDevice, NPairKokkosHalffullNewtoffDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_SKIP | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_SKIP | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0> NPairKokkosHalffullNewtoffHost; typedef NPairHalffullKokkos<LMPHostType,0,0> NPairKokkosHalffullNewtoffHost;
NPairStyle(halffull/newtoff/skip/kk/host, NPairStyle(halffull/newtoff/skip/kk/host,
NPairKokkosHalffullNewtoffHost, NPairKokkosHalffullNewtoffHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
@ -69,25 +72,25 @@ NPairStyle(halffull/newtoff/skip/kk/host,
// Newton // Newton
typedef NPairHalffullKokkos<LMPDeviceType,1> NPairKokkosHalffullNewtonGhostDevice; typedef NPairHalffullKokkos<LMPDeviceType,1,0> NPairKokkosHalffullNewtonGhostDevice;
NPairStyle(halffull/newton/ghost/kk/device, NPairStyle(halffull/newton/ghost/kk/device,
NPairKokkosHalffullNewtonGhostDevice, NPairKokkosHalffullNewtonGhostDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1> NPairKokkosHalffullNewtonHost; typedef NPairHalffullKokkos<LMPHostType,1,0> NPairKokkosHalffullNewtonHost;
NPairStyle(halffull/newton/ghost/kk/host, NPairStyle(halffull/newton/ghost/kk/host,
NPairKokkosHalffullNewtonHost, NPairKokkosHalffullNewtonHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_HOST); NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,1> NPairKokkosHalffullNewtonGhostDevice; typedef NPairHalffullKokkos<LMPDeviceType,1,0> NPairKokkosHalffullNewtonGhostDevice;
NPairStyle(halffull/newton/skip/ghost/kk/device, NPairStyle(halffull/newton/skip/ghost/kk/device,
NPairKokkosHalffullNewtonGhostDevice, NPairKokkosHalffullNewtonGhostDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1> NPairKokkosHalffullNewtonHost; typedef NPairHalffullKokkos<LMPHostType,1,0> NPairKokkosHalffullNewtonHost;
NPairStyle(halffull/newton/skip/ghost/kk/host, NPairStyle(halffull/newton/skip/ghost/kk/host,
NPairKokkosHalffullNewtonHost, NPairKokkosHalffullNewtonHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
@ -95,29 +98,138 @@ NPairStyle(halffull/newton/skip/ghost/kk/host,
// Newtoff // Newtoff
typedef NPairHalffullKokkos<LMPDeviceType,0> NPairKokkosHalffullNewtoffGhostDevice; typedef NPairHalffullKokkos<LMPDeviceType,0,0> NPairKokkosHalffullNewtoffGhostDevice;
NPairStyle(halffull/newtoff/ghost/kk/device, NPairStyle(halffull/newtoff/ghost/kk/device,
NPairKokkosHalffullNewtoffGhostDevice, NPairKokkosHalffullNewtoffGhostDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0> NPairKokkosHalffullNewtoffHost; typedef NPairHalffullKokkos<LMPHostType,0,0> NPairKokkosHalffullNewtoffHost;
NPairStyle(halffull/newtoff/ghost/kk/host, NPairStyle(halffull/newtoff/ghost/kk/host,
NPairKokkosHalffullNewtoffHost, NPairKokkosHalffullNewtoffHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_HOST); NP_ORTHO | NP_TRI | NP_GHOST | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,0> NPairKokkosHalffullNewtoffGhostDevice; typedef NPairHalffullKokkos<LMPDeviceType,0,0> NPairKokkosHalffullNewtoffGhostDevice;
NPairStyle(halffull/newtoff/skip/ghost/kk/device, NPairStyle(halffull/newtoff/skip/ghost/kk/device,
NPairKokkosHalffullNewtoffGhostDevice, NPairKokkosHalffullNewtoffGhostDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_KOKKOS_DEVICE); NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0> NPairKokkosHalffullNewtoffHost; typedef NPairHalffullKokkos<LMPHostType,0,0> NPairKokkosHalffullNewtoffHost;
NPairStyle(halffull/newtoff/skip/ghost/kk/host, NPairStyle(halffull/newtoff/skip/ghost/kk/host,
NPairKokkosHalffullNewtoffHost, NPairKokkosHalffullNewtoffHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_KOKKOS_HOST); NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_KOKKOS_HOST);
//************ Trim **************
// Newton
typedef NPairHalffullKokkos<LMPDeviceType,1,1> NPairKokkosHalffullNewtonTrimDevice;
NPairStyle(halffull/newton/trim/kk/device,
NPairKokkosHalffullNewtonTrimDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1,1> NPairKokkosHalffullNewtonTrimHost;
NPairStyle(halffull/newton/trim/kk/host,
NPairKokkosHalffullNewtonTrimHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_TRIM | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,1,1> NPairKokkosHalffullNewtonTrimDevice;
NPairStyle(halffull/newton/skip/trim/kk/device,
NPairKokkosHalffullNewtonTrimDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_SKIP | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1,1> NPairKokkosHalffullNewtonTrimHost;
NPairStyle(halffull/newton/skip/trim/kk/host,
NPairKokkosHalffullNewtonTrimHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_SKIP | NP_TRIM | NP_KOKKOS_HOST);
// Newtoff
typedef NPairHalffullKokkos<LMPDeviceType,0,1> NPairKokkosHalffullNewtoffTrimDevice;
NPairStyle(halffull/newtoff/trim/kk/device,
NPairKokkosHalffullNewtoffTrimDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0,1> NPairKokkosHalffullNewtoffTrimHost;
NPairStyle(halffull/newtoff/trim/kk/host,
NPairKokkosHalffullNewtoffTrimHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_TRIM | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,0,1> NPairKokkosHalffullNewtoffTrimDevice;
NPairStyle(halffull/newtoff/skip/trim/kk/device,
NPairKokkosHalffullNewtoffTrimDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_SKIP | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0,1> NPairKokkosHalffullNewtoffTrimHost;
NPairStyle(halffull/newtoff/skip/trim/kk/host,
NPairKokkosHalffullNewtoffTrimHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_SKIP | NP_TRIM | NP_KOKKOS_HOST);
//************ Ghost **************
// Newton
typedef NPairHalffullKokkos<LMPDeviceType,1,1> NPairKokkosHalffullNewtonGhostTrimDevice;
NPairStyle(halffull/newton/ghost/trim/kk/device,
NPairKokkosHalffullNewtonGhostTrimDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1,1> NPairKokkosHalffullNewtonTrimHost;
NPairStyle(halffull/newton/ghost/trim/kk/host,
NPairKokkosHalffullNewtonTrimHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_TRIM | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,1,1> NPairKokkosHalffullNewtonGhostTrimDevice;
NPairStyle(halffull/newton/skip/ghost/trim/kk/device,
NPairKokkosHalffullNewtonGhostTrimDevice,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,1,1> NPairKokkosHalffullNewtonTrimHost;
NPairStyle(halffull/newton/skip/ghost/trim/kk/host,
NPairKokkosHalffullNewtonTrimHost,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_TRIM | NP_KOKKOS_HOST);
// Newtoff
typedef NPairHalffullKokkos<LMPDeviceType,0,1> NPairKokkosHalffullNewtoffGhostTrimDevice;
NPairStyle(halffull/newtoff/ghost/trim/kk/device,
NPairKokkosHalffullNewtoffGhostTrimDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0,1> NPairKokkosHalffullNewtoffTrimHost;
NPairStyle(halffull/newtoff/ghost/trim/kk/host,
NPairKokkosHalffullNewtoffTrimHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_TRIM | NP_KOKKOS_HOST);
typedef NPairHalffullKokkos<LMPDeviceType,0,1> NPairKokkosHalffullNewtoffGhostTrimDevice;
NPairStyle(halffull/newtoff/skip/ghost/trim/kk/device,
NPairKokkosHalffullNewtoffGhostTrimDevice,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_TRIM | NP_KOKKOS_DEVICE);
typedef NPairHalffullKokkos<LMPHostType,0,1> NPairKokkosHalffullNewtoffTrimHost;
NPairStyle(halffull/newtoff/skip/ghost/trim/kk/host,
NPairKokkosHalffullNewtoffTrimHost,
NP_HALF_FULL | NP_NEWTOFF | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI |
NP_ORTHO | NP_TRI | NP_GHOST | NP_SKIP | NP_TRIM | NP_KOKKOS_HOST);
// clang-format on // clang-format on
#else #else
@ -132,7 +244,7 @@ namespace LAMMPS_NS {
struct TagNPairHalffullCompute{}; struct TagNPairHalffullCompute{};
template<class DeviceType, int NEWTON> template<class DeviceType, int NEWTON, int TRIM>
class NPairHalffullKokkos : public NPair { class NPairHalffullKokkos : public NPair {
public: public:
typedef DeviceType device_type; typedef DeviceType device_type;
@ -146,6 +258,7 @@ class NPairHalffullKokkos : public NPair {
private: private:
int nlocal; int nlocal;
double cutsq_custom;
typename AT::t_x_array_randomread x; typename AT::t_x_array_randomread x;

View File

@ -0,0 +1,196 @@
// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Trimright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "npair_trim_kokkos.h"
#include "atom_kokkos.h"
#include "atom_masks.h"
#include "neigh_list_kokkos.h"
#include "my_page.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
template<class DeviceType>
NPairTrimKokkos<DeviceType>::NPairTrimKokkos(LAMMPS *lmp) : NPair(lmp) {}
/* ----------------------------------------------------------------------
create list which is simply a copy of parent list
------------------------------------------------------------------------- */
template<class DeviceType>
void NPairTrimKokkos<DeviceType>::build(NeighList *list)
{
NeighList *listcopy = list->listcopy;
cutsq_custom = cutoff_custom*cutoff_custom;
if (list->kokkos) {
if (!listcopy->kokkos)
error->all(FLERR,"Cannot trim non-Kokkos neighbor list to Kokkos neighbor list");
trim_to_kokkos(list);
} else {
if (!listcopy->kokkos)
error->all(FLERR,"Missing Kokkos neighbor list for trim");
trim_to_cpu(list);
}
}
/* ---------------------------------------------------------------------- */
template<class DeviceType>
void NPairTrimKokkos<DeviceType>::trim_to_kokkos(NeighList *list)
{
x = atomKK->k_x.view<DeviceType>();
atomKK->sync(execution_space,X_MASK);
cutsq_custom = cutoff_custom*cutoff_custom;
NeighListKokkos<DeviceType>* k_list_copy = static_cast<NeighListKokkos<DeviceType>*>(list->listcopy);
d_ilist_copy = k_list_copy->d_ilist;
d_numneigh_copy = k_list_copy->d_numneigh;
d_neighbors_copy = k_list_copy->d_neighbors;
int inum_copy = list->listcopy->inum;
if (list->ghost) inum_copy += list->listcopy->gnum;
NeighListKokkos<DeviceType>* k_list = static_cast<NeighListKokkos<DeviceType>*>(list);
k_list->maxneighs = k_list_copy->maxneighs; // simple, but could be made more memory efficient
k_list->grow(atom->nmax);
d_ilist = k_list->d_ilist;
d_numneigh = k_list->d_numneigh;
d_neighbors = k_list->d_neighbors;
// loop over parent list and trim
copymode = 1;
Kokkos::parallel_for(Kokkos::RangePolicy<DeviceType, TagNPairTrim>(0,inum_copy),*this);
copymode = 0;
list->inum = k_list_copy->inum;
list->gnum = k_list_copy->gnum;
k_list->k_ilist.template modify<DeviceType>();
}
template<class DeviceType>
KOKKOS_INLINE_FUNCTION
void NPairTrimKokkos<DeviceType>::operator()(TagNPairTrim, const int &ii) const {
int n = 0;
const int i = d_ilist_copy(ii);
const double xtmp = x(i,0);
const double ytmp = x(i,1);
const double ztmp = x(i,2);
// loop over copy neighbor list
const int jnum = d_numneigh_copy(i);
const AtomNeighbors neighbors_i = AtomNeighbors(&d_neighbors(i,0),d_numneigh(i),
&d_neighbors(i,1)-&d_neighbors(i,0));
for (int jj = 0; jj < jnum; jj++) {
const int joriginal = d_neighbors_copy(i,jj);
const int j = joriginal & NEIGHMASK;
const double delx = xtmp - x(j,0);
const double dely = ytmp - x(j,1);
const double delz = ztmp - x(j,2);
const double rsq = delx*delx + dely*dely + delz*delz;
if (rsq > cutsq_custom) continue;
neighbors_i(n++) = joriginal;
}
d_numneigh(i) = n;
d_ilist(ii) = i;
}
/* ---------------------------------------------------------------------- */
template<class DeviceType>
void NPairTrimKokkos<DeviceType>::trim_to_cpu(NeighList *list)
{
NeighList *listcopy = list->listcopy;
NeighListKokkos<DeviceType>* listcopy_kk = (NeighListKokkos<DeviceType>*) listcopy;
listcopy_kk->k_ilist.template sync<LMPHostType>();
double** x = atom->x;
int inum = listcopy->inum;
int gnum = listcopy->gnum;
int inum_all = inum;
if (list->ghost) inum_all += gnum;
auto h_ilist = listcopy_kk->k_ilist.h_view;
auto h_numneigh = Kokkos::create_mirror_view_and_copy(LMPHostType(),listcopy_kk->d_numneigh);
auto h_neighbors = Kokkos::create_mirror_view_and_copy(LMPHostType(),listcopy_kk->d_neighbors);
list->inum = inum;
list->gnum = gnum;
auto ilist = list->ilist;
auto numneigh = list->numneigh;
// Kokkos neighbor data is stored differently than regular CPU,
// must loop over lists
int *neighptr;
int **firstneigh = list->firstneigh;
MyPage<int> *ipage = list->ipage;
ipage->reset();
for (int ii = 0; ii < inum_all; ii++) {
int n = 0;
neighptr = ipage->vget();
const int i = h_ilist[ii];
ilist[ii] = i;
const double xtmp = x[i][0];
const double ytmp = x[i][1];
const double ztmp = x[i][2];
// loop over Kokkos neighbor list
const int jnum = h_numneigh[i];
for (int jj = 0; jj < jnum; jj++) {
const int joriginal = h_neighbors(i,jj);
const int j = joriginal & NEIGHMASK;
const double delx = xtmp - x[j][0];
const double dely = ytmp - x[j][1];
const double delz = ztmp - x[j][2];
const double rsq = delx*delx + dely*dely + delz*delz;
if (rsq > cutsq_custom) continue;
neighptr[n++] = joriginal;
}
firstneigh[i] = neighptr;
numneigh[i] = n;
ipage->vgot(n);
if (ipage->status())
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
}
}
namespace LAMMPS_NS {
template class NPairTrimKokkos<LMPDeviceType>;
#ifdef LMP_KOKKOS_GPU
template class NPairTrimKokkos<LMPHostType>;
#endif
}

View File

@ -0,0 +1,70 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Trimright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef NPAIR_CLASS
// clang-format off
NPairStyle(trim/kk/device,
NPairTrimKokkos<LMPDeviceType>,
NP_COPY | NP_TRIM | NP_KOKKOS_DEVICE);
NPairStyle(trim/kk/host,
NPairTrimKokkos<LMPHostType>,
NP_COPY | NP_TRIM | NP_KOKKOS_HOST);
// clang-format on
#else
// clang-format off
#ifndef LMP_NPAIR_TRIM_KOKKOS_H
#define LMP_NPAIR_TRIM_KOKKOS_H
#include "npair.h"
#include "kokkos_type.h"
namespace LAMMPS_NS {
struct TagNPairTrim{};
template<class DeviceType>
class NPairTrimKokkos : public NPair {
public:
typedef DeviceType device_type;
typedef ArrayTypes<DeviceType> AT;
NPairTrimKokkos(class LAMMPS *);
void build(class NeighList *) override;
KOKKOS_INLINE_FUNCTION
void operator()(TagNPairTrim, const int&) const;
private:
double cutsq_custom;
typename AT::t_x_array_randomread x;
typename AT::t_neighbors_2d_const d_neighbors_copy;
typename AT::t_int_1d_const d_ilist_copy;
typename AT::t_int_1d_const d_numneigh_copy;
typename AT::t_neighbors_2d d_neighbors;
typename AT::t_int_1d d_ilist;
typename AT::t_int_1d d_numneigh;
void trim_to_kokkos(class NeighList *);
void trim_to_cpu(class NeighList *);
};
}
#endif
#endif

View File

@ -48,6 +48,7 @@ NeighList::NeighList(LAMMPS *lmp) : Pointers(lmp)
respamiddle = 0; respamiddle = 0;
respainner = 0; respainner = 0;
copy = 0; copy = 0;
trim = 0;
copymode = 0; copymode = 0;
// ptrs // ptrs
@ -97,7 +98,8 @@ NeighList::NeighList(LAMMPS *lmp) : Pointers(lmp)
NeighList::~NeighList() NeighList::~NeighList()
{ {
if (copymode) return; if (copymode) return;
if (!copy) {
if (!copy || trim || kk2cpu) {
memory->destroy(ilist); memory->destroy(ilist);
memory->destroy(numneigh); memory->destroy(numneigh);
memory->sfree(firstneigh); memory->sfree(firstneigh);
@ -144,6 +146,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;
trim = nq->trim;
id = nq->id; id = nq->id;
if (nq->copy) { if (nq->copy) {

View File

@ -42,6 +42,7 @@ class NeighList : protected Pointers {
int respamiddle; // 1 if there is also a rRespa middle list int respamiddle; // 1 if there is also a rRespa middle list
int respainner; // 1 if there is also a rRespa inner list int respainner; // 1 if there is also a rRespa inner list
int copy; // 1 if this list is copied from another list int copy; // 1 if this list is copied from another list
int trim; // 1 if this list is trimmed 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 int id; // copied from neighbor list request

View File

@ -86,6 +86,7 @@ NeighRequest::NeighRequest(LAMMPS *_lmp) : Pointers(_lmp)
skiplist = -1; skiplist = -1;
off2on = 0; off2on = 0;
copy = 0; copy = 0;
trim = 0;
copylist = -1; copylist = -1;
halffull = 0; halffull = 0;
halffulllist = -1; halffulllist = -1;

View File

@ -102,6 +102,7 @@ class NeighRequest : protected Pointers {
int off2on; // 1 if this is newton on list, but skips from off list int off2on; // 1 if this is newton on list, but skips from off list
int copy; // 1 if this list copied from another list int copy; // 1 if this list copied from another list
int trim; // 1 if this list copied from another list and then trimmed
int copylist; // index of list to copy from int copylist; // index of list to copy from
int halffull; // 1 if half list computed from another full list int halffull; // 1 if half list computed from another full list

View File

@ -162,6 +162,7 @@ pairclass(nullptr), pairnames(nullptr), pairmasks(nullptr)
nrequest = maxrequest = 0; nrequest = maxrequest = 0;
requests = nullptr; requests = nullptr;
j_sorted = nullptr;
old_nrequest = 0; old_nrequest = 0;
old_requests = nullptr; old_requests = nullptr;
@ -254,6 +255,8 @@ Neighbor::~Neighbor()
if (old_requests[i]) delete old_requests[i]; if (old_requests[i]) delete old_requests[i];
memory->sfree(old_requests); memory->sfree(old_requests);
delete[] j_sorted;
delete[] binclass; delete[] binclass;
delete[] binnames; delete[] binnames;
delete[] binmasks; delete[] binmasks;
@ -827,6 +830,10 @@ int Neighbor::init_pair()
"with ghost info"); "with ghost info");
} }
// sort requests by cutoff distance for trimming
sort_requests();
// morph requests in various ways // morph requests in various ways
// purpose is to avoid duplicate or inefficient builds // purpose is to avoid duplicate or inefficient builds
// may add new requests if a needed request to derive from does not exist // may add new requests if a needed request to derive from does not exist
@ -840,7 +847,7 @@ int Neighbor::init_pair()
// (3) after (2), b/c it adjusts lists created by (2) // (3) after (2), b/c it adjusts lists created by (2)
// (4) after (2) and (3), // (4) after (2) and (3),
// b/c (2) may create new full lists, (3) may change them // b/c (2) may create new full lists, (3) may change them
// (5) last, after all lists are finalized, so all possible copies found // (5) last, after all lists are finalized, so all possible copies/trims found
int nrequest_original = nrequest; int nrequest_original = nrequest;
@ -848,7 +855,7 @@ int Neighbor::init_pair()
morph_skip(); morph_skip();
morph_granular(); // this method can change flags set by requestor morph_granular(); // this method can change flags set by requestor
morph_halffull(); morph_halffull();
morph_copy(); morph_copy_trim();
// create new lists, one per request including added requests // create new lists, one per request including added requests
// wait to allocate initial pages until copy lists are detected // wait to allocate initial pages until copy lists are detected
@ -1007,8 +1014,8 @@ int Neighbor::init_pair()
// allocate initial pages for each list, except if copy flag set // allocate initial pages for each list, except if copy flag set
for (i = 0; i < nlist; i++) { for (i = 0; i < nlist; i++) {
if (lists[i]->copy && !lists[i]->kk2cpu) if (lists[i]->copy && !lists[i]->trim && !lists[i]->kk2cpu)
continue; continue;
lists[i]->setup_pages(pgsize,oneatom); lists[i]->setup_pages(pgsize,oneatom);
} }
@ -1020,7 +1027,7 @@ int Neighbor::init_pair()
int maxatom = atom->nmax; int maxatom = atom->nmax;
for (i = 0; i < nlist; i++) { for (i = 0; i < nlist; i++) {
if (neigh_pair[i] && (!lists[i]->copy || lists[i]->kk2cpu)) if (neigh_pair[i] && (!lists[i]->copy || lists[i]->trim || lists[i]->kk2cpu))
lists[i]->grow(maxatom,maxatom); lists[i]->grow(maxatom,maxatom);
} }
@ -1092,6 +1099,42 @@ int Neighbor::init_pair()
return same; return same;
} }
/* ----------------------------------------------------------------------
sort NeighRequests by cutoff distance
to find smallest list for trimming
------------------------------------------------------------------------- */
void Neighbor::sort_requests()
{
NeighRequest *jrq;
int i,j,jmin;
double jcut;
delete[] j_sorted;
j_sorted = new int[nrequest];
for (i = 0; i < nrequest; i++)
j_sorted[i] = i;
for (i = 0; i < nrequest; i++) {
double cutoff_min = cutneighmax;
for (j = i; j < nrequest; j++) {
jrq = requests[j_sorted[j]];
if (jrq->cut) jcut = jrq->cutoff;
else jcut = cutneighmax;
if (jcut <= cutoff_min) {
cutoff_min = jcut;
jmin = j;
}
}
int tmp = j_sorted[i];
j_sorted[i] = jmin;
j_sorted[jmin] = tmp;
}
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
scan NeighRequests to set additional flags: scan NeighRequests to set additional flags:
custom cutoff lists and accelerator lists custom cutoff lists and accelerator lists
@ -1104,10 +1147,23 @@ void Neighbor::morph_unique()
for (int i = 0; i < nrequest; i++) { for (int i = 0; i < nrequest; i++) {
irq = requests[i]; irq = requests[i];
// if cut flag set by requestor, set unique flag // if cut flag set by requestor and cutoff is different than default,
// set unique flag, otherwise unset cut flag
// this forces Pair,Stencil,Bin styles to be instantiated separately // this forces Pair,Stencil,Bin styles to be instantiated separately
// also add skin to cutoff of perpetual lists
if (irq->cut) irq->unique = 1; if (irq->cut) {
if (!irq->occasional)
irq->cutoff += skin;
if (irq->cutoff != cutneighmax) {
irq->unique = 1;
} else {
irq->cut = 0;
irq->cutoff = 0.0;
}
}
// avoid flagging a neighbor list as both INTEL and OPENMP // avoid flagging a neighbor list as both INTEL and OPENMP
@ -1292,8 +1348,9 @@ void Neighbor::morph_granular()
void Neighbor::morph_halffull() void Neighbor::morph_halffull()
{ {
int i,j; int i,j,jj,jmin;
NeighRequest *irq,*jrq; NeighRequest *irq,*jrq;
double icut,jcut;
for (i = 0; i < nrequest; i++) { for (i = 0; i < nrequest; i++) {
irq = requests[i]; irq = requests[i];
@ -1309,8 +1366,10 @@ void Neighbor::morph_halffull()
// check all other lists // check all other lists
for (j = 0; j < nrequest; j++) { for (jj = 0; jj < nrequest; jj++) {
if (i == j) continue; if (irq->cut) j = j_sorted[jj];
else j = jj;
jrq = requests[j]; jrq = requests[j];
// can only derive from a perpetual full list // can only derive from a perpetual full list
@ -1319,10 +1378,20 @@ void Neighbor::morph_halffull()
if (jrq->occasional) continue; if (jrq->occasional) continue;
if (!jrq->full) continue; if (!jrq->full) continue;
// trim a list with longer cutoff
if (irq->cut) icut = irq->cutoff;
else icut = cutneighmax;
if (jrq->cut) jcut = jrq->cutoff;
else jcut = cutneighmax;
if (icut > jcut) continue;
else if (icut != jcut) irq->trim = 1;
// these flags must be same, // these flags must be same,
// else 2 lists do not store same pairs // else 2 lists do not store same pairs
// or their data structures are different // or their data structures are different
// this includes custom cutoff set by requestor
if (irq->ghost != jrq->ghost) continue; if (irq->ghost != jrq->ghost) continue;
if (irq->size != jrq->size) continue; if (irq->size != jrq->size) continue;
@ -1333,8 +1402,6 @@ void Neighbor::morph_halffull()
if (irq->kokkos_host != jrq->kokkos_host) continue; if (irq->kokkos_host != jrq->kokkos_host) continue;
if (irq->kokkos_device != jrq->kokkos_device) continue; if (irq->kokkos_device != jrq->kokkos_device) continue;
if (irq->ssa != jrq->ssa) continue; if (irq->ssa != jrq->ssa) continue;
if (irq->cut != jrq->cut) continue;
if (irq->cutoff != jrq->cutoff) continue;
// skip flag must be same // skip flag must be same
// if both are skip lists, skip info must match // if both are skip lists, skip info must match
@ -1349,22 +1416,23 @@ void Neighbor::morph_halffull()
// if matching list exists, point to it // if matching list exists, point to it
if (j < nrequest) { if (jj < nrequest) {
irq->halffull = 1; irq->halffull = 1;
irq->halffulllist = j; irq->halffulllist = j;
} } else irq->trim = 0;
} }
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
scan NeighRequests for possible copies scan NeighRequests for possible copies or trims
if 2 requests match, turn one into a copy of the other if 2 requests match, turn one into a copy or trim of the other
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Neighbor::morph_copy() void Neighbor::morph_copy_trim()
{ {
int i,j,inewton,jnewton; int i,j,jj,jmin,inewton,jnewton;
NeighRequest *irq,*jrq; NeighRequest *irq,*jrq;
double icut,jcut;
for (i = 0; i < nrequest; i++) { for (i = 0; i < nrequest; i++) {
irq = requests[i]; irq = requests[i];
@ -1375,7 +1443,10 @@ void Neighbor::morph_copy()
// check all other lists // check all other lists
for (j = 0; j < nrequest; j++) { for (jj = 0; jj < nrequest; jj++) {
if (irq->cut) j = j_sorted[jj];
else j = jj;
if (i == j) continue; if (i == j) continue;
jrq = requests[j]; jrq = requests[j];
@ -1383,13 +1454,24 @@ void Neighbor::morph_copy()
if (jrq->copy && jrq->copylist == i) continue; if (jrq->copy && jrq->copylist == i) continue;
// trim a list with longer cutoff
if (irq->cut) icut = irq->cutoff;
else icut = cutneighmax;
if (jrq->cut) jcut = jrq->cutoff;
else jcut = cutneighmax;
if (icut > jcut) continue;
else if (icut != jcut) irq->trim = 1;
// other list (jrq) to copy from must be perpetual // other list (jrq) to copy from must be perpetual
// list that becomes a copy list (irq) can be perpetual or occasional // list that becomes a copy list (irq) can be perpetual or occasional
// if both lists are perpetual, require j < i // if both lists are perpetual, require j < i
// to prevent circular dependence with 3 or more copies of a list // to prevent circular dependence with 3 or more copies of a list
if (jrq->occasional) continue; if (jrq->occasional) continue;
if (!irq->occasional && j > i) continue; if (!irq->occasional && !irq->cut && j > i) continue;
// both lists must be half, or both full // both lists must be half, or both full
@ -1418,7 +1500,6 @@ void Neighbor::morph_copy()
// these flags must be same, // these flags must be same,
// else 2 lists do not store same pairs // else 2 lists do not store same pairs
// or their data structures are different // or their data structures are different
// this includes custom cutoff set by requestor
// no need to check omp b/c it stores same pairs // no need to check omp b/c it stores same pairs
// NOTE: need check for 2 Kokkos flags? // NOTE: need check for 2 Kokkos flags?
@ -1429,8 +1510,6 @@ void Neighbor::morph_copy()
if (irq->kokkos_host && !jrq->kokkos_host) continue; if (irq->kokkos_host && !jrq->kokkos_host) continue;
if (irq->kokkos_device && !jrq->kokkos_device) continue; if (irq->kokkos_device && !jrq->kokkos_device) continue;
if (irq->ssa != jrq->ssa) continue; if (irq->ssa != jrq->ssa) continue;
if (irq->cut != jrq->cut) continue;
if (irq->cutoff != jrq->cutoff) continue;
// skip flag must be same // skip flag must be same
// if both are skip lists, skip info must match // if both are skip lists, skip info must match
@ -1446,11 +1525,11 @@ void Neighbor::morph_copy()
// turn list I into a copy of list J // turn list I into a copy of list J
// do not copy a list from another copy list, but from its parent list // do not copy a list from another copy list, but from its parent list
if (j < nrequest) { if (jj < nrequest) {
irq->copy = 1; irq->copy = 1;
if (jrq->copy) irq->copylist = jrq->copylist; if (jrq->copy) irq->copylist = jrq->copylist;
else irq->copylist = j; else irq->copylist = j;
} } else irq->trim = 0;
} }
} }
@ -1664,9 +1743,12 @@ void Neighbor::print_pairwise_info()
// order these to get single output of most relevant // order these to get single output of most relevant
if (rq->copy) if (rq->copy) {
out += fmt::format(", copy from ({})",rq->copylist+1); if (rq->trim)
else if (rq->halffull) out += fmt::format(", trim from ({})",rq->copylist+1);
else
out += fmt::format(", copy from ({})",rq->copylist+1);
} else if (rq->halffull)
out += fmt::format(", half/full from ({})",rq->halffulllist+1); out += fmt::format(", half/full from ({})",rq->halffulllist+1);
else if (rq->skip) else if (rq->skip)
out += fmt::format(", skip from ({})",rq->skiplist+1); out += fmt::format(", skip from ({})",rq->skiplist+1);
@ -1968,10 +2050,12 @@ int Neighbor::choose_pair(NeighRequest *rq)
// pairnames[i],pairmasks[i]); // pairnames[i],pairmasks[i]);
// if copy request, no further checks needed, just return or continue // if copy request, no further checks needed, just return or continue
// Kokkos device/host flags must also match in order to copy // Trim and Kokkos device/host flags must also match in order to copy
if (rq->copy) { if (rq->copy) {
if (!(mask & NP_COPY)) continue; if (!(mask & NP_COPY)) continue;
if (rq->trim)
if (!rq->trim != !(mask & NP_TRIM)) continue;
if (rq->kokkos_device || rq->kokkos_host) { if (rq->kokkos_device || rq->kokkos_host) {
if (!rq->kokkos_device != !(mask & NP_KOKKOS_DEVICE)) continue; if (!rq->kokkos_device != !(mask & NP_KOKKOS_DEVICE)) continue;
if (!rq->kokkos_host != !(mask & NP_KOKKOS_HOST)) continue; if (!rq->kokkos_host != !(mask & NP_KOKKOS_HOST)) continue;
@ -2023,6 +2107,8 @@ int Neighbor::choose_pair(NeighRequest *rq)
if (!rq->skip != !(mask & NP_SKIP)) continue; if (!rq->skip != !(mask & NP_SKIP)) continue;
if (!rq->trim != !(mask & NP_TRIM)) continue;
if (!rq->halffull != !(mask & NP_HALF_FULL)) continue; if (!rq->halffull != !(mask & NP_HALF_FULL)) continue;
if (!rq->off2on != !(mask & NP_OFF2ON)) continue; if (!rq->off2on != !(mask & NP_OFF2ON)) continue;
@ -2327,7 +2413,7 @@ void Neighbor::build(int topoflag)
for (i = 0; i < npair_perpetual; i++) { for (i = 0; i < npair_perpetual; i++) {
m = plist[i]; m = plist[i];
if (!lists[m]->copy || lists[m]->kk2cpu) if (!lists[m]->copy || lists[m]->trim || lists[m]->kk2cpu)
lists[m]->grow(nlocal,nall); lists[m]->grow(nlocal,nall);
neigh_pair[m]->build_setup(); neigh_pair[m]->build_setup();
neigh_pair[m]->build(lists[m]); neigh_pair[m]->build(lists[m]);
@ -2418,7 +2504,7 @@ void Neighbor::build_one(class NeighList *mylist, int preflag)
// build the list // build the list
if (!mylist->copy || mylist->kk2cpu) if (!mylist->copy || mylist->trim || mylist->kk2cpu)
mylist->grow(atom->nlocal,atom->nlocal+atom->nghost); mylist->grow(atom->nlocal,atom->nlocal+atom->nghost);
np->build_setup(); np->build_setup();
np->build(mylist); np->build(mylist);

View File

@ -94,6 +94,7 @@ class Neighbor : protected Pointers {
NeighList **lists; NeighList **lists;
NeighRequest **requests; // from Pair,Fix,Compute,Command classes NeighRequest **requests; // from Pair,Fix,Compute,Command classes
NeighRequest **old_requests; // copy of requests to compare to NeighRequest **old_requests; // copy of requests to compare to
int* j_sorted; // index of requests sorted by cutoff distance
// data from topology neighbor lists // data from topology neighbor lists
@ -245,11 +246,13 @@ class Neighbor : protected Pointers {
int init_pair(); int init_pair();
virtual void init_topology(); virtual void init_topology();
void sort_requests();
void morph_unique(); void morph_unique();
void morph_skip(); void morph_skip();
void morph_granular(); void morph_granular();
void morph_halffull(); void morph_halffull();
void morph_copy(); void morph_copy_trim();
void print_pairwise_info(); void print_pairwise_info();
void requests_new2old(); void requests_new2old();
@ -323,7 +326,8 @@ namespace NeighConst {
NP_SKIP = 1 << 22, NP_SKIP = 1 << 22,
NP_HALF_FULL = 1 << 23, NP_HALF_FULL = 1 << 23,
NP_OFF2ON = 1 << 24, NP_OFF2ON = 1 << 24,
NP_MULTI_OLD = 1 << 25 NP_MULTI_OLD = 1 << 25,
NP_TRIM = 1 << 26
}; };
enum { enum {

View File

@ -0,0 +1,101 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "npair_halffull_newtoff_trim.h"
#include "atom.h"
#include "error.h"
#include "my_page.h"
#include "neigh_list.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
NPairHalffullNewtoffTrim::NPairHalffullNewtoffTrim(LAMMPS *lmp) : NPair(lmp) {}
/* ----------------------------------------------------------------------
build half list from full list
pair stored once if i,j are both owned and i < j
pair stored by me if j is ghost (also stored by proc owning j)
works if full list is a skip list
works for owned (non-ghost) list, also for ghost list
if ghost, also store neighbors of ghost atoms & set inum,gnum correctly
------------------------------------------------------------------------- */
void NPairHalffullNewtoffTrim::build(NeighList *list)
{
int i, j, ii, jj, n, jnum, joriginal;
int *neighptr, *jlist;
double xtmp,ytmp,ztmp;
double delx,dely,delz,rsq;
double **x = atom->x;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
MyPage<int> *ipage = list->ipage;
int *ilist_full = list->listfull->ilist;
int *numneigh_full = list->listfull->numneigh;
int **firstneigh_full = list->listfull->firstneigh;
int inum_full = list->listfull->inum;
if (list->ghost) inum_full += list->listfull->gnum;
int inum = 0;
ipage->reset();
double cutsq_custom = cutoff_custom * cutoff_custom;
// loop over atoms in full list
for (ii = 0; ii < inum_full; ii++) {
n = 0;
neighptr = ipage->vget();
// loop over parent full list
i = ilist_full[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh_full[i];
jnum = numneigh_full[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (j > i) {
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
if (rsq > cutsq_custom) continue;
neighptr[n++] = joriginal;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
ipage->vgot(n);
if (ipage->status()) error->one(FLERR, "Neighbor list overflow, boost neigh_modify one");
}
list->inum = inum;
if (list->ghost) list->gnum = list->listfull->gnum;
}

View File

@ -0,0 +1,54 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef NPAIR_CLASS
// clang-format off
NPairStyle(halffull/newtoff/trim,
NPairHalffullNewtoffTrim,
NP_HALF_FULL | NP_NEWTOFF | NP_NSQ | NP_BIN | NP_MULTI | NP_MULTI_OLD | NP_HALF |
NP_ORTHO | NP_TRI | NP_TRIM);
NPairStyle(halffull/newtoff/skip/trim,
NPairHalffullNewtoffTrim,
NP_HALF_FULL | NP_NEWTOFF | NP_NSQ | NP_BIN | NP_MULTI | NP_MULTI_OLD | NP_HALF |
NP_ORTHO | NP_TRI | NP_SKIP | NP_TRIM);
NPairStyle(halffull/newtoff/ghost/trim,
NPairHalffullNewtoffTrim,
NP_HALF_FULL | NP_NEWTOFF | NP_NSQ | NP_BIN | NP_MULTI | NP_MULTI_OLD | NP_HALF |
NP_ORTHO | NP_TRI | NP_GHOST | NP_TRIM);
NPairStyle(halffull/newtoff/skip/ghost/trim,
NPairHalffullNewtoffTrim,
NP_HALF_FULL | NP_NEWTOFF | NP_NSQ | NP_BIN | NP_MULTI | NP_MULTI_OLD | NP_HALF |
NP_ORTHO | NP_TRI | NP_SKIP | NP_GHOST | NP_TRIM);
// clang-format on
#else
#ifndef LMP_NPAIR_HALFFULL_NEWTOFF_TRIM_H
#define LMP_NPAIR_HALFFULL_NEWTOFF_TRIM_H
#include "npair.h"
namespace LAMMPS_NS {
class NPairHalffullNewtoffTrim : public NPair {
public:
NPairHalffullNewtoffTrim(class LAMMPS *);
void build(class NeighList *) override;
};
} // namespace LAMMPS_NS
#endif
#endif

View File

@ -0,0 +1,108 @@
// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "npair_halffull_newton_trim.h"
#include "atom.h"
#include "error.h"
#include "my_page.h"
#include "neigh_list.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
NPairHalffullNewtonTrim::NPairHalffullNewtonTrim(LAMMPS *lmp) : NPair(lmp) {}
/* ----------------------------------------------------------------------
build half list from full list
pair stored once if i,j are both owned and i < j
if j is ghost, only store if j coords are "above and to the right" of i
works if full list is a skip list
------------------------------------------------------------------------- */
void NPairHalffullNewtonTrim::build(NeighList *list)
{
int i,j,ii,jj,n,jnum,joriginal;
int *neighptr,*jlist;
double xtmp,ytmp,ztmp;
double delx,dely,delz,rsq;
double **x = atom->x;
int nlocal = atom->nlocal;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
MyPage<int> *ipage = list->ipage;
int *ilist_full = list->listfull->ilist;
int *numneigh_full = list->listfull->numneigh;
int **firstneigh_full = list->listfull->firstneigh;
int inum_full = list->listfull->inum;
int inum = 0;
ipage->reset();
double cutsq_custom = cutoff_custom * cutoff_custom;
// loop over parent full list
for (ii = 0; ii < inum_full; ii++) {
n = 0;
neighptr = ipage->vget();
i = ilist_full[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over full neighbor list
jlist = firstneigh_full[i];
jnum = numneigh_full[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (j < nlocal) {
if (i > j) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
if (rsq > cutsq_custom) continue;
neighptr[n++] = joriginal;
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
ipage->vgot(n);
if (ipage->status())
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
}
list->inum = inum;
}

View File

@ -0,0 +1,44 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef NPAIR_CLASS
// clang-format off
NPairStyle(halffull/newton/trim,
NPairHalffullNewtonTrim,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_MULTI_OLD |
NP_ORTHO | NP_TRI | NP_TRIM);
NPairStyle(halffull/newton/skip/trim,
NPairHalffullNewtonTrim,
NP_HALF_FULL | NP_NEWTON | NP_HALF | NP_NSQ | NP_BIN | NP_MULTI | NP_MULTI_OLD |
NP_ORTHO | NP_TRI | NP_SKIP | NP_TRIM);
// clang-format on
#else
#ifndef LMP_NPAIR_HALFFULL_NEWTON_TRIM_H
#define LMP_NPAIR_HALFFULL_NEWTON_TRIM_H
#include "npair.h"
namespace LAMMPS_NS {
class NPairHalffullNewtonTrim : public NPair {
public:
NPairHalffullNewtonTrim(class LAMMPS *);
void build(class NeighList *) override;
};
} // namespace LAMMPS_NS
#endif
#endif

92
src/npair_trim.cpp Normal file
View File

@ -0,0 +1,92 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Trimright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "npair_trim.h"
#include "neigh_list.h"
#include "atom.h"
#include "error.h"
#include "my_page.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
NPairTrim::NPairTrim(LAMMPS *lmp) : NPair(lmp) {}
/* ----------------------------------------------------------------------
create list which is a trimmed version of parent list
------------------------------------------------------------------------- */
void NPairTrim::build(NeighList *list)
{
NeighList *listcopy = list->listcopy;
double cutsq_custom = cutoff_custom * cutoff_custom;
int i,j,ii,jj,n,jnum,joriginal;
int *neighptr,*jlist;
double xtmp,ytmp,ztmp;
double delx,dely,delz,rsq;
double **x = atom->x;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
MyPage<int> *ipage = list->ipage;
ipage->reset();
int *ilist_copy = listcopy->ilist;
int *numneigh_copy = listcopy->numneigh;
int **firstneigh_copy = listcopy->firstneigh;
int inum = listcopy->inum;
list->inum = inum;
list->gnum = listcopy->gnum;
for (ii = 0; ii < inum; ii++) {
n = 0;
neighptr = ipage->vget();
const int i = ilist_copy[ii];
ilist[i] = i;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over copy list with larger cutoff and trim to shorter cutoff
jlist = firstneigh_copy[i];
jnum = numneigh_copy[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
if (rsq > cutsq_custom) continue;
neighptr[n++] = joriginal;
}
firstneigh[i] = neighptr;
numneigh[i] = n;
ipage->vgot(n);
if (ipage->status())
error->one(FLERR,"Neighbor list overflow, boost neigh_modify one");
}
}

38
src/npair_trim.h Normal file
View File

@ -0,0 +1,38 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Trimright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef NPAIR_CLASS
// clang-format off
NPairStyle(trim,
NPairTrim,
NP_COPY | NP_TRIM);
// clang-format on
#else
#ifndef LMP_NPAIR_TRIM_H
#define LMP_NPAIR_TRIM_H
#include "npair.h"
namespace LAMMPS_NS {
class NPairTrim : public NPair {
public:
NPairTrim(class LAMMPS *);
void build(class NeighList *) override;
};
} // namespace LAMMPS_NS
#endif
#endif

View File

@ -204,6 +204,10 @@ void Pair::modify_params(int narg, char **arg)
} else if (strcmp(arg[iarg],"nofdotr") == 0) { } else if (strcmp(arg[iarg],"nofdotr") == 0) {
no_virial_fdotr_compute = 1; no_virial_fdotr_compute = 1;
++iarg; ++iarg;
} else if (strcmp(arg[iarg],"neigh/trim") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command");
trim_flag = utils::logical(FLERR,arg[iarg+1],false,lmp);
iarg += 2;
} else error->all(FLERR,"Illegal pair_modify command"); } else error->all(FLERR,"Illegal pair_modify command");
} }
} }

View File

@ -82,6 +82,7 @@ class Pair : protected Pointers {
int tail_flag; // pair_modify flag for LJ tail correction int tail_flag; // pair_modify flag for LJ tail correction
double etail, ptail; // energy/pressure tail corrections double etail, ptail; // energy/pressure tail corrections
double etail_ij, ptail_ij; double etail_ij, ptail_ij;
int trim_flag; // pair_modify flag for trimming neigh list
int evflag; // energy,virial settings int evflag; // energy,virial settings
int eflag_either, eflag_global, eflag_atom; int eflag_either, eflag_global, eflag_atom;

View File

@ -35,12 +35,13 @@ using namespace LAMMPS_NS;
PairHybrid::PairHybrid(LAMMPS *lmp) : Pair(lmp), PairHybrid::PairHybrid(LAMMPS *lmp) : Pair(lmp),
styles(nullptr), keywords(nullptr), multiple(nullptr), nmap(nullptr), styles(nullptr), keywords(nullptr), multiple(nullptr), nmap(nullptr),
map(nullptr), special_lj(nullptr), special_coul(nullptr), compute_tally(nullptr) map(nullptr), special_lj(nullptr), special_coul(nullptr), compute_tally(nullptr), cutmax_style(nullptr)
{ {
nstyles = 0; nstyles = 0;
outerflag = 0; outerflag = 0;
respaflag = 0; respaflag = 0;
style_cutoff_flag = 1;
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -56,6 +57,8 @@ PairHybrid::~PairHybrid()
} }
} }
delete[] styles; delete[] styles;
if (style_cutoff_flag)
delete[] cutmax_style;
delete[] keywords; delete[] keywords;
delete[] multiple; delete[] multiple;
@ -298,6 +301,10 @@ void PairHybrid::settings(int narg, char **arg)
// allocate list of sub-styles as big as possibly needed if no extra args // allocate list of sub-styles as big as possibly needed if no extra args
styles = new Pair *[narg]; styles = new Pair *[narg];
if (style_cutoff_flag) {
cutmax_style = new double[narg];
memset(cutmax_style, 0.0, narg*sizeof(double));
}
keywords = new char *[narg]; keywords = new char *[narg];
multiple = new int[narg]; multiple = new int[narg];
@ -716,6 +723,23 @@ double PairHybrid::init_one(int i, int j)
ptail_ij += styles[map[i][j][k]]->ptail_ij; ptail_ij += styles[map[i][j][k]]->ptail_ij;
} }
cutmax = MAX(cutmax,cut); cutmax = MAX(cutmax,cut);
if (style_cutoff_flag) {
int istyle;
for (istyle = 0; istyle < nstyles; istyle++)
if (styles[istyle] == styles[map[i][j][k]]) break;
if (cut > cutmax_style[istyle]) {
cutmax_style[istyle] = cut;
for (auto &request : neighbor->get_pair_requests()) {
if (styles[istyle] == request->get_requestor() && styles[istyle]->trim_flag) {
request->set_cutoff(cutmax_style[istyle]);
break;
}
}
}
}
} }
return cutmax; return cutmax;
@ -778,6 +802,10 @@ void PairHybrid::read_restart(FILE *fp)
delete[] compute_tally; delete[] compute_tally;
styles = new Pair*[nstyles]; styles = new Pair*[nstyles];
if (style_cutoff_flag) {
cutmax_style = new double[nstyles];
memset(cutmax_style, 0.0, nstyles*sizeof(double));
}
keywords = new char*[nstyles]; keywords = new char*[nstyles];
multiple = new int[nstyles]; multiple = new int[nstyles];

View File

@ -68,10 +68,12 @@ class PairHybrid : public Pair {
double radii2cut(double, double) override; double radii2cut(double, double) override;
protected: protected:
int nstyles; // # of sub-styles int nstyles; // # of sub-styles
Pair **styles; // list of Pair style classes Pair **styles; // list of Pair style classes
char **keywords; // style name of each Pair style int style_cutoff_flag; // 1 if build a separate neigh list for each style
int *multiple; // 0 if style used once, else Mth instance double *cutmax_style; // max cutoff for each style
char **keywords; // style name of each Pair style
int *multiple; // 0 if style used once, else Mth instance
int outerflag; // toggle compute() when invoked by outer() int outerflag; // toggle compute() when invoked by outer()
int respaflag; // 1 if different substyles are assigned to int respaflag; // 1 if different substyles are assigned to