From 778ae37e6e53fbe1b41499c1d0159f8911370a67 Mon Sep 17 00:00:00 2001
From: sjplimp <sjplimp@f3b2605a-c512-4ea7-a41b-209d697bcdaa>
Date: Sat, 16 Jul 2016 22:27:01 +0000
Subject: [PATCH] git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@15338
 f3b2605a-c512-4ea7-a41b-209d697bcdaa

---
 src/Make.sh                     |   7 +-
 src/USER-OMP/neigh_gran_omp.cpp |  43 ++-
 src/neighbor.cpp                | 542 +++++++++++++++++++++++++++++++-
 src/neighbor.h                  |  24 +-
 4 files changed, 584 insertions(+), 32 deletions(-)

diff --git a/src/Make.sh b/src/Make.sh
index 3332be92c4..9c115e1bdf 100644
--- a/src/Make.sh
+++ b/src/Make.sh
@@ -54,7 +54,8 @@ style () {
 # col 1 = string to search for
 # col 2 = search in *.h files starting with this name
 # col 3 = prefix of style file
-# col 4 
+# col 4 = file that includes the style file
+# col 5 = optional 2nd file that includes the style file
 
 if (test $1 = "style") then
 
@@ -62,8 +63,9 @@ if (test $1 = "style") then
   style ATOM_CLASS      atom_vec_   atom       atom      atom_vec_hybrid
   style BODY_CLASS      body_       body       atom_vec_body
   style BOND_CLASS      bond_       bond       force
+  style BUILD_CLASS     build_      build      neighbor
   style COMMAND_CLASS   ""          command    input
-  style COMPUTE_CLASS   compute_    compute    modify    modify_cuda
+  style COMPUTE_CLASS   compute_    compute    modify
   style DIHEDRAL_CLASS  dihedral_   dihedral   force
   style DUMP_CLASS      dump_       dump       output    write_dump
   style FIX_CLASS       fix_        fix        modify
@@ -74,6 +76,7 @@ if (test $1 = "style") then
   style PAIR_CLASS      pair_       pair       force
   style READER_CLASS    reader_     reader     read_dump
   style REGION_CLASS    region_     region     domain
+  style STENCIL_CLASS   stencil_    stencil    neighbor
 
 # edit Makefile.lib, for creating non-shared lib
 # called by "make makelib"
diff --git a/src/USER-OMP/neigh_gran_omp.cpp b/src/USER-OMP/neigh_gran_omp.cpp
index 55ab604b02..82794ff739 100644
--- a/src/USER-OMP/neigh_gran_omp.cpp
+++ b/src/USER-OMP/neigh_gran_omp.cpp
@@ -11,6 +11,7 @@
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
+#include <string.h>
 #include "neighbor.h"
 #include "neighbor_omp.h"
 #include "neigh_list.h"
@@ -45,7 +46,7 @@ void Neighbor::granular_nsq_no_newton_omp(NeighList *list)
 #endif
   NEIGH_OMP_SETUP(nlocal);
 
-  int i,j,m,n,nn;
+  int i,j,m,n,nn,dnum,dnumbytes;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
   double radi,radsum,cutsq;
   int *neighptr,*touchptr;
@@ -53,7 +54,7 @@ void Neighbor::granular_nsq_no_newton_omp(NeighList *list)
 
   int *npartner;
   tagint **partner;
-  double (**shearpartner)[3];
+  double **shearpartner;
   int **firsttouch;
   double **firstshear;
   MyPage<int> *ipage_touch;
@@ -83,6 +84,8 @@ void Neighbor::granular_nsq_no_newton_omp(NeighList *list)
     firstshear = listgranhistory->firstdouble;
     ipage_touch = listgranhistory->ipage+tid;
     dpage_shear = listgranhistory->dpage+tid;
+    dnum = listgranhistory->dnum;
+    dnumbytes = dnum * sizeof(double);
     ipage_touch->reset();
     dpage_shear->reset();
   }
@@ -124,20 +127,17 @@ void Neighbor::granular_nsq_no_newton_omp(NeighList *list)
               if (partner[i][m] == tag[j]) break;
             if (m < npartner[i]) {
               touchptr[n] = 1;
-              shearptr[nn++] = shearpartner[i][m][0];
-              shearptr[nn++] = shearpartner[i][m][1];
-              shearptr[nn++] = shearpartner[i][m][2];
+              memcpy(&shearptr[nn],&shearpartner[i][dnum*m],dnumbytes);
+              nn += dnum;
             } else {
               touchptr[n] = 0;
-              shearptr[nn++] = 0.0;
-              shearptr[nn++] = 0.0;
-              shearptr[nn++] = 0.0;
+              memcpy(&shearptr[nn],zeroes,dnumbytes);
+              nn += dnum;
             }
           } else {
             touchptr[n] = 0;
-            shearptr[nn++] = 0.0;
-            shearptr[nn++] = 0.0;
-            shearptr[nn++] = 0.0;
+            memcpy(&shearptr[nn],zeroes,dnumbytes);
+            nn += dnum;
           }
         }
 
@@ -285,7 +285,7 @@ void Neighbor::granular_bin_no_newton_omp(NeighList *list)
 #endif
   NEIGH_OMP_SETUP(nlocal);
 
-  int i,j,k,m,n,nn,ibin;
+  int i,j,k,m,n,nn,ibin,dnum,dnumbytes;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
   double radi,radsum,cutsq;
   int *neighptr,*touchptr;
@@ -295,7 +295,7 @@ void Neighbor::granular_bin_no_newton_omp(NeighList *list)
 
   int *npartner;
   tagint **partner;
-  double (**shearpartner)[3];
+  double **shearpartner;
   int **firsttouch;
   double **firstshear;
 
@@ -326,6 +326,8 @@ void Neighbor::granular_bin_no_newton_omp(NeighList *list)
     firstshear = listgranhistory->firstdouble;
     ipage_touch = listgranhistory->ipage+tid;
     dpage_shear = listgranhistory->dpage+tid;
+    dnum = listgranhistory->dnum;
+    dnumbytes = dnum * sizeof(double);
     ipage_touch->reset();
     dpage_shear->reset();
   }
@@ -372,20 +374,17 @@ void Neighbor::granular_bin_no_newton_omp(NeighList *list)
                 if (partner[i][m] == tag[j]) break;
               if (m < npartner[i]) {
                 touchptr[n] = 1;
-                shearptr[nn++] = shearpartner[i][m][0];
-                shearptr[nn++] = shearpartner[i][m][1];
-                shearptr[nn++] = shearpartner[i][m][2];
+                memcpy(&shearptr[nn],&shearpartner[i][dnum*m],dnumbytes);
+                nn += dnum;
               } else {
                 touchptr[n] = 0;
-                shearptr[nn++] = 0.0;
-                shearptr[nn++] = 0.0;
-                shearptr[nn++] = 0.0;
+                memcpy(&shearptr[nn],zeroes,dnumbytes);
+                nn += dnum;
               }
             } else {
               touchptr[n] = 0;
-              shearptr[nn++] = 0.0;
-              shearptr[nn++] = 0.0;
-              shearptr[nn++] = 0.0;
+              memcpy(&shearptr[nn],zeroes,dnumbytes);
+              nn += dnum;
             }
           }
 
diff --git a/src/neighbor.cpp b/src/neighbor.cpp
index 5aad5bfd6f..c4ce8b2eeb 100644
--- a/src/neighbor.cpp
+++ b/src/neighbor.cpp
@@ -22,6 +22,8 @@
 #include "neighbor.h"
 #include "neigh_list.h"
 #include "neigh_request.h"
+#include "style_stencil.h"
+#include "style_build.h"
 #include "atom.h"
 #include "atom_vec.h"
 #include "comm.h"
@@ -35,10 +37,13 @@
 #include "update.h"
 #include "respa.h"
 #include "output.h"
+#include "stencil.h"
 #include "citeme.h"
 #include "memory.h"
 #include "error.h"
 
+#include <map>
+
 using namespace LAMMPS_NS;
 
 #define RQDELTA 1
@@ -51,6 +56,9 @@ using namespace LAMMPS_NS;
 
 enum{NSQ,BIN,MULTI};     // also in neigh_list.cpp
 
+enum{STENCIL_HALF_BIN_3D_NEWTON};
+enum{BUILD_HALF_BIN_NEWTON};
+
 static const char cite_neigh_multi[] =
   "neighbor multi command:\n\n"
   "@Article{Intveld08,\n"
@@ -125,7 +133,9 @@ Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp)
 
   nlist = 0;
   lists = NULL;
+  pair_build_new = NULL;
   pair_build = NULL;
+  stencil_create_new = NULL;
   stencil_create = NULL;
   blist = glist = slist = NULL;
   anyghostlist = 0;
@@ -159,6 +169,28 @@ Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp)
   improperlist = NULL;
 
   copymode = 0;
+
+  // fill map with stencil classes listed in style_stencil.h
+
+  stencil_map = new std::map<int,StencilCreator>();
+
+#define STENCIL_CLASS
+#define StencilStyle(key,Class) \
+  (*stencil_map)[key] = &stencil_creator<Class>;
+#include "style_stencil.h"
+#undef StencilStyle
+#undef STENCIL_CLASS
+
+  // fill map with build classes listed in style_build.h
+
+  build_map = new std::map<int,BuildCreator>();
+
+#define BUILD_CLASS
+#define BuildStyle(key,Class) \
+  (*build_map)[key] = &build_creator<Class>;
+#include "style_build.h"
+#undef BuildStyle
+#undef BUILD_CLASS
 }
 
 /* ---------------------------------------------------------------------- */
@@ -192,7 +224,11 @@ Neighbor::~Neighbor()
 
   for (int i = 0; i < nlist; i++) delete lists[i];
   delete [] lists;
+  for (int i = 0; i < nlist; i++) delete pair_build_new[i];
+  delete [] pair_build_new;
   delete [] pair_build;
+  for (int i = 0; i < nlist; i++) delete stencil_create_new[i];
+  delete [] stencil_create_new;
   delete [] stencil_create;
   delete [] blist;
   delete [] glist;
@@ -209,6 +245,9 @@ Neighbor::~Neighbor()
   memory->destroy(anglelist);
   memory->destroy(dihedrallist);
   memory->destroy(improperlist);
+
+  delete stencil_map;
+  delete build_map;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -492,21 +531,29 @@ void Neighbor::init()
 
     for (i = 0; i < nlist; i++) delete lists[i];
     delete [] lists;
+    for (i = 0; i < nlist; i++) delete pair_build_new[i];
+    delete [] pair_build_new;
     delete [] pair_build;
+    for (i = 0; i < nlist; i++) delete stencil_create_new[i];
+    delete [] stencil_create_new;
     delete [] stencil_create;
 
     if (lmp->kokkos) nlist = init_lists_kokkos();
     else nlist = nrequest;
 
     lists = new NeighList*[nrequest];
+    pair_build_new = new Build*[nrequest];
     pair_build = new PairPtr[nrequest];
+    stencil_create_new = new Stencil*[nrequest];
     stencil_create = new StencilPtr[nrequest];
 
     // initialize to NULL since some may be Kokkos lists
 
     for (i = 0; i < nrequest; i++) {
       lists[i] = NULL;
+      pair_build_new[i] = NULL;
       pair_build[i] = NULL;
+      stencil_create_new[i] = NULL;
       stencil_create[i] = NULL;
     }
 
@@ -671,9 +718,15 @@ void Neighbor::init()
     // ptrs set to NULL if not set explicitly
 
     for (i = 0; i < nrequest; i++) {
+      choose_build_new(i,requests[i]);
       choose_build(i,requests[i]);
-      if (style != NSQ) choose_stencil(i,requests[i]);
-      else stencil_create[i] = NULL;
+      if (style != NSQ) {
+        choose_stencil_new(i,requests[i]);
+        choose_stencil(i,requests[i]);
+      } else {
+        stencil_create_new[i] = NULL;
+        stencil_create[i] = NULL;
+      }
     }
 
     // set each list's build/grow/stencil/ghost flags based on neigh request
@@ -689,6 +742,8 @@ void Neighbor::init()
     for (i = 0; i < nrequest; i++) {
       if (lists[i]) {
         lists[i]->buildflag = 1;
+        // NOTE: let old pair_build determine buildflag
+        //if (pair_build_new[i] == NULL) lists[i]->buildflag = 0;
         if (pair_build[i] == NULL) lists[i]->buildflag = 0;
         if (requests[i]->occasional) lists[i]->buildflag = 0;
         if (lists[i]->buildflag) anybuild = 1;
@@ -698,6 +753,8 @@ void Neighbor::init()
 
         lists[i]->stencilflag = 1;
         if (style == NSQ) lists[i]->stencilflag = 0;
+        // NOTE: let old stencil_create determine stencilflag
+        //if (stencil_create_new[i] == NULL) lists[i]->stencilflag = 0;
         if (stencil_create[i] == NULL) lists[i]->stencilflag = 0;
 
         lists[i]->ghostflag = 0;
@@ -1018,6 +1075,331 @@ int Neighbor::request(void *requestor, int instance)
   return nrequest-1;
 }
 
+/* ----------------------------------------------------------------------
+   determine which Build class each neigh list needs
+   based on settings of neigh request
+   copy -> copy_from function
+   skip -> granular function if gran, several options
+           respa function if respaouter,
+           skip_from function for everything else
+   ssa -> special case for USER-DPD pair styles
+   half_from_full, half, full, gran, respaouter ->
+     choose by newton and rq->newton and triclinic settings
+     style NSQ options = newton off, newton on
+     style BIN options = newton off, newton on and not tri, newton on and tri
+     stlye MULTI options = same options as BIN
+   if none of these, ptr = NULL since pair_build is not invoked for this list
+   use "else if" logic b/c skip,copy can be set in addition to half,full,etc
+------------------------------------------------------------------------- */
+
+void Neighbor::choose_build_new(int index, NeighRequest *rq)
+{
+  int build = -1;
+
+  if (rq->omp == 0 && rq->intel == 0) {
+
+    if (rq->copy) build = -1; // BUILD_COPY_FROM;
+
+    else if (rq->skip) {
+      if (rq->gran) {
+        NeighRequest *otherrq = requests[rq->otherlist];
+        if (otherrq->newton == 0) {
+          build = -1; // BUILD_SKIP_FROM_GRANULAR;
+        } else if (otherrq->newton == 1) {
+          error->all(FLERR,"Neighbor build method not supported");
+        } else if (otherrq->newton == 2) {
+          if (rq->granonesided == 0)
+            build = -1; // BUILD_SKIP_FROM_GRANULAR_OFF2ON;
+          else if (rq->granonesided == 1)
+            build = -1; // BUILD_SKIP_FROM_GRANULAR_OFF2ON_ONESIDED;
+        }
+      } 
+      else if (rq->respaouter) build = -1; // BUILD_SKIP_FROM_RESPA;
+      else build = -1; // BUILD_SKIP_FROM;
+
+    } else if (rq->ssa) {
+      if (rq->half_from_full) build = -1; // BUILD_HALF_FROM_FULL_NEWTON_SSA;
+      else build = -1; // BUILD_HALF_BIN_NEWTON_SSA;
+
+    } else if (rq->half_from_full) {
+      if (rq->newton == 0) {
+        if (newton_pair == 0) build = -1; // BUILD_HALF_FROM_FULL_NO_NEWTON;
+        else if (newton_pair == 1) build = -1; // BUILD_HALF_FROM_FULL_NEWTON;
+      } else if (rq->newton == 1) {
+        build = -1; // BUILD_HALF_FROM_FULL_NEWTON;
+      } else if (rq->newton == 2) {
+        build = -1; // BUILD_HALF_FROM_FULL_NO_NEWTON;
+      }
+
+    } else if (rq->half) {
+      if (style == NSQ) {
+        if (rq->newton == 0) {
+          if (newton_pair == 0) {
+            if (rq->ghost == 0) build = -1; // BUILD_HALF_NSQ_NO_NEWTON;
+            else if (includegroup)
+              error->all(FLERR,"Neighbor include group not allowed "
+                         "with ghost neighbors");
+            else build = -1; // BUILD_HALF_NSQ_NO_NEWTON_GHOST;
+          } else if (newton_pair == 1) build = -1; // BUILD_HALF_NSQ_NEWTON;
+        } else if (rq->newton == 1) {
+          build = -1; // BUILD_HALF_NSQ_NEWTON;
+        } else if (rq->newton == 2) {
+          if (rq->ghost == 0) build = -1; // BUILD_HALF_NSQ_NO_NEWTON;
+          else if (includegroup)
+            error->all(FLERR,"Neighbor include group not allowed "
+                       "with ghost neighbors");
+          else build = -1; // BUILD_HALF_NSQ_NO_NEWTON_GHOST;
+        }
+      } else if (style == BIN) {
+        if (rq->newton == 0) {
+          if (newton_pair == 0) {
+            if (rq->ghost == 0) build = -1; // BUILD_HALF_BIN_NO_NEWTON;
+            else if (includegroup)
+              error->all(FLERR,"Neighbor include group not allowed "
+                         "with ghost neighbors");
+            else build = -1; // BUILD_HALF_BIN_NO_NEWTON_GHOST;
+          } else if (triclinic == 0) {
+            build = BUILD_HALF_BIN_NEWTON;
+          } else if (triclinic == 1)
+            build = -1; // BUILD_HALF_BIN_NEWTON_TRI;
+        } else if (rq->newton == 1) {
+          if (triclinic == 0) build = BUILD_HALF_BIN_NEWTON;
+          else if (triclinic == 1) build = -1; // BUILD_HALF_BIN_NEWTON_TRI;
+        } else if (rq->newton == 2) {
+          if (rq->ghost == 0) build = -1; // BUILD_HALF_BIN_NO_NEWTON;
+          else if (includegroup)
+            error->all(FLERR,"Neighbor include group not allowed "
+                       "with ghost neighbors");
+          else build = -1; // BUILD_HALF_BIN_NO_NEWTON_GHOST;
+        }
+      } else if (style == MULTI) {
+        if (rq->ghost == 1)
+          error->all(FLERR,
+                     "Neighbor multi not yet enabled for ghost neighbors");
+        if (rq->newton == 0) {
+          if (newton_pair == 0) build = -1; // BUILD_HALF_MULTI_NO_NEWTON;
+          else if (triclinic == 0) build = -1; // BUILD_HALF_MULTI_NEWTON;
+          else if (triclinic == 1) build = -1; // BUILD_HALF_MULTI_NEWTON_TRI;
+        } else if (rq->newton == 1) {
+          if (triclinic == 0) build = -1; // BUILD_HALF_MULTI_NEWTON;
+          else if (triclinic == 1) build = -1; // BUILD_HALF_MULTI_NEWTON_TRI;
+        } else if (rq->newton == 2) build = -1; // BUILD_HALF_MULTI_NO_NEWTON;
+      }
+
+    } else if (rq->full) {
+      if (style == NSQ) {
+        if (rq->ghost == 0) build = -1; // BUILD_FULL_NSQ;
+        else if (includegroup)
+          error->all(FLERR,
+                     "Neighbor include group not allowed with ghost neighbors");
+        else build = -1; // BUILD_FULL_NSQ_GHOST;
+      } else if (style == BIN) {
+        if (rq->ghost == 0) build = -1; // BUILD_FULL_BIN;
+        else if (includegroup)
+          error->all(FLERR,
+                     "Neighbor include group not allowed with ghost neighbors");
+        else build = -1; // BUILD_FULL_BIN_GHOST;
+      } else if (style == MULTI) {
+        if (rq->ghost == 1)
+          error->all(FLERR,
+                     "Neighbor multi not yet enabled for ghost neighbors");
+        build = -1; // BUILD_FULL_MULTI;
+      }
+
+    } else if (rq->gran) {
+      if (rq->newton == 0) {
+        if (style == NSQ) {
+          if (newton_pair == 0) build = -1; // BUILD_GRANULAR_NSQ_NO_NEWTON;
+          else if (newton_pair == 1) {
+            if (rq->granonesided == 0) build = -1; // BUILD_GRANULAR_NSQ_NEWTON;
+            else build = -1; // BUILD_GRANULAR_NSQ_NEWTON_ONESIDED;
+          }
+        } else if (style == BIN) {
+          if (newton_pair == 0) build = -1; // BUILD_GRANULAR_BIN_NO_NEWTON;
+          else if (newton_pair == 1) {
+            if (triclinic == 0) {
+              if (rq->granonesided == 0) build = -1; // BUILD_GRANULAR_BIN_NEWTON;
+              else build = -1; // BUILD_GRANULAR_BIN_NEWTON_ONESIDED;
+            } else if (triclinic == 1) {
+              if (rq->granonesided == 0) 
+                build = -1; // BUILD_GRANULAR_BIN_NEWTON_TRI;
+              else error->all(FLERR,"Neighbor build method not supported");
+            }
+          }
+        } else if (style == MULTI)
+          error->all(FLERR,"Neighbor multi not yet enabled for granular");
+      } else if (rq->newton == 1) {
+        error->all(FLERR,"Neighbor build method not yet supported");
+      } else if (rq->newton == 2) {
+        if (style == NSQ) build = -1; // BUILD_GRANULAR_NSQ_NO_NEWTON;
+        else if (style == BIN) {
+          if (triclinic == 0) build = -1; // BUILD_GRANULAR_BIN_NO_NEWTON;
+          else if (triclinic == 1) 
+            error->all(FLERR,"Neighbor build method not yet supported");
+        } else if (style == MULTI)
+          error->all(FLERR,"Neighbor multi not yet enabled for granular");
+      }
+      
+    } else if (rq->respaouter) {
+      if (style == NSQ) {
+        if (newton_pair == 0) build = -1; // BUILD_RESPA_NSQ_NO_NEWTON;
+        else if (newton_pair == 1) build = -1; // BUILD_RESPA_NSQ_NEWTON;
+      } else if (style == BIN) {
+        if (newton_pair == 0) build = -1; // BUILD_RESPA_BIN_NO_NEWTON;
+        else if (triclinic == 0) build = -1; // BUILD_RESPA_BIN_NEWTON;
+        else if (triclinic == 1) build = -1; // BUILD_RESPA_BIN_NEWTON_TRI;
+      } else if (style == MULTI)
+        error->all(FLERR,"Neighbor multi not yet enabled for rRESPA");
+    }
+
+  // OMP versions of build methods
+
+  } else {
+
+    if (rq->copy) build = -1; // BUILD_COPY_FROM;
+
+    else if (rq->skip) {
+      if (rq->gran && lists[index]->listgranhistory)
+        build = -1; // BUILD_SKIP_FROM_GRANULAR;
+      else if (rq->respaouter) build = -1; // BUILD_SKIP_FROM_RESPA;
+      else build = -1; // BUILD_SKIP_FROM;
+
+    } else if (rq->half_from_full) {
+      if (newton_pair == 0) build = -1; // BUILD_HALF_FROM_FULL_NO_NEWTON_OMP;
+      else if (newton_pair == 1) build = -1; // BUILD_HALF_FROM_FULL_NEWTON_OMP;
+
+    } else if (rq->half) {
+      if (style == NSQ) {
+        if (rq->newton == 0) {
+          if (newton_pair == 0) {
+            if (rq->ghost == 0) build = -1; // BUILD_HALF_NSQ_NO_NEWTON_OMP;
+            else if (includegroup)
+              error->all(FLERR,"Neighbor include group not allowed "
+                         "with ghost neighbors");
+            else build = -1; // BUILD_HALF_NSQ_NO_NEWTON_GHOST_OMP;
+          } else if (newton_pair == 1) build = -1; // BUILD_HALF_NSQ_NEWTON_OMP;
+        } else if (rq->newton == 1) {
+          build = -1; // BUILD_HALF_NSQ_NEWTON_OMP;
+        } else if (rq->newton == 2) {
+          if (rq->ghost == 0) build = -1; // BUILD_HALF_NSQ_NO_NEWTON_OMP;
+          else if (includegroup)
+            error->all(FLERR,"Neighbor include group not allowed "
+                       "with ghost neighbors");
+          else build = -1; // BUILD_HALF_NSQ_NO_NEWTON_GHOST_OMP;
+        }
+      } else if (style == BIN) {
+        if (rq->newton == 0) {
+          if (newton_pair == 0) {
+            if (rq->ghost == 0) {
+	      if (rq->intel) build = -1; // BUILD_HALF_BIN_NO_NEWTON_INTEL;
+	      else build = -1; // BUILD_HALF_BIN_NO_NEWTON_OMP;
+            } else if (includegroup)
+              error->all(FLERR,"Neighbor include group not allowed "
+                         "with ghost neighbors");
+            else build = -1; // BUILD_HALF_BIN_NO_NEWTON_GHOST_OMP;
+          } else if (triclinic == 0) {
+            if (rq->intel) build = -1; // BUILD_HALF_BIN_NEWTON_INTEL;
+            else build = -1; // BUILD_HALF_BIN_NEWTON_OMP;
+          } else if (triclinic == 1) {
+            if (rq->intel) build = -1; // BUILD_HALF_BIN_NEWTON_TRI_INTEL;
+            else build = -1; // BUILD_HALF_BIN_NEWTON_TRI_OMP;
+	  }
+        } else if (rq->newton == 1) {
+          if (triclinic == 0) {
+	    if (rq->intel) build = -1; // BUILD_HALF_BIN_NEWTON_INTEL;
+	    else build = -1; // BUILD_HALF_BIN_NEWTON_OMP;
+          } else if (triclinic == 1) {
+            if (rq->intel) build = -1; // BUILD_HALF_BIN_NEWTON_TRI_INTEL;
+            else build = -1; // BUILD_HALF_BIN_NEWTON_TRI_OMP;
+	  }
+        } else if (rq->newton == 2) {
+          if (rq->ghost == 0) {
+	    if (rq->intel) build = -1; // BUILD_HALF_BIN_NO_NEWTON_INTEL;
+	    else build = -1; // BUILD_HALF_BIN_NO_NEWTON_OMP;
+          } else if (includegroup)
+            error->all(FLERR,"Neighbor include group not allowed "
+                       "with ghost neighbors");
+          else build = -1; // BUILD_HALF_BIN_NO_NEWTON_GHOST_OMP;
+        }
+      } else if (style == MULTI) {
+        if (rq->ghost == 1)
+          error->all(FLERR,
+                     "Neighbor multi not yet enabled for ghost neighbors");
+        if (rq->newton == 0) {
+          if (newton_pair == 0) build = -1; // BUILD_HALF_MULTI_NO_NEWTON_OMP;
+          else if (triclinic == 0) build = -1; // BUILD_HALF_MULTI_NEWTON_OMP;
+          else if (triclinic == 1) build = -1; // BUILD_HALF_MULTI_NEWTON_TRI_OMP;
+        } else if (rq->newton == 1) {
+          if (triclinic == 0) build = -1; // BUILD_HALF_MULTI_NEWTON_OMP;
+          else if (triclinic == 1) build = -1; // BUILD_HALF_MULTI_NEWTON_TRI_OMP;
+        } else if (rq->newton == 2) build = -1; // BUILD_HALF_MULTI_NO_NEWTON_OMP;
+      }
+
+    } else if (rq->full) {
+      if (style == NSQ) {
+        if (rq->ghost == 0) build = -1; // BUILD_FULL_NSQ_OMP;
+        else if (includegroup)
+          error->all(FLERR,
+                     "Neighbor include group not allowed with ghost neighbors");
+        else build = -1; // BUILD_FULL_NSQ_GHOST_OMP;
+      } else if (style == BIN) {
+        if (rq->ghost == 0) {
+	  if (rq->intel) build = -1; // BUILD_FULL_BIN_INTEL;
+	  else build = -1; // BUILD_FULL_BIN_OMP;
+        } else if (includegroup)
+          error->all(FLERR,
+                     "Neighbor include group not allowed with ghost neighbors");
+        else build = -1; // BUILD_FULL_BIN_GHOST_OMP;
+      } else if (style == MULTI) {
+        if (rq->ghost == 1)
+          error->all(FLERR,
+                     "Neighbor multi not yet enabled for ghost neighbors");
+        build = -1; // BUILD_FULL_MULTI_OMP;
+      }
+
+    } else if (rq->gran) {
+      if (style == NSQ) {
+        if (newton_pair == 0) build = -1; // BUILD_GRANULAR_NSQ_NO_NEWTON_OMP;
+        else if (newton_pair == 1) build = -1; // BUILD_GRANULAR_NSQ_NEWTON_OMP;
+      } else if (style == BIN) {
+        if (newton_pair == 0) build = -1; // BUILD_GRANULAR_BIN_NO_NEWTON_OMP;
+        else if (triclinic == 0) build = -1; // BUILD_GRANULAR_BIN_NEWTON_OMP;
+        else if (triclinic == 1) build = -1; // BUILD_GRANULAR_BIN_NEWTON_TRI_OMP;
+      } else if (style == MULTI)
+        error->all(FLERR,"Neighbor multi not yet enabled for granular");
+
+    } else if (rq->respaouter) {
+      if (style == NSQ) {
+        if (newton_pair == 0) build = -1; // BUILD_RESPA_NSQ_NO_NEWTON_OMP;
+        else if (newton_pair == 1) build = -1; // BUILD_RESPA_NSQ_NEWTON_OMP;
+      } else if (style == BIN) {
+        if (newton_pair == 0) build = -1; // BUILD_RESPA_BIN_NO_NEWTON_OMP;
+        else if (triclinic == 0) build = -1; // BUILD_RESPA_BIN_NEWTON_OMP;
+        else if (triclinic == 1) build = -1; // BUILD_RESPA_BIN_NEWTON_TRI_OMP;
+      } else if (style == MULTI)
+        error->all(FLERR,"Neighbor multi not yet enabled for rRESPA");
+    }
+  }
+
+  // instantiate selected Stencil class
+
+  if (build < 0) pair_build_new[index] = NULL;
+  else if (build_map->find(build) != build_map->end()) {
+    BuildCreator build_creator = (*build_map)[build];
+    pair_build_new[index] = build_creator(lmp);
+  } else error->all(FLERR,"Neighbor build class does not exit");
+}
+
+/* ----------------------------------------------------------------------
+   one instance per fix in style_build.h
+------------------------------------------------------------------------- */
+
+template <typename T>
+Build *Neighbor::build_creator(LAMMPS *lmp)
+{
+  return new T(lmp);
+}
+
 /* ----------------------------------------------------------------------
    determine which pair_build function each neigh list needs
    based on settings of neigh request
@@ -1327,6 +1709,133 @@ void Neighbor::choose_build(int index, NeighRequest *rq)
   pair_build[index] = pb;
 }
 
+/* ----------------------------------------------------------------------
+   determine which Stencil class each neigh list needs
+   based on settings of neigh request, only called if style != NSQ
+   skip or copy or half_from_full -> no stencil
+   ssa = special case for USER-DPD pair styles
+   half, gran, respaouter, full -> choose by newton and tri and dimension
+   if none of these, ptr = NULL since this list needs no stencils
+   use "else if" b/c skip,copy can be set in addition to half,full,etc
+------------------------------------------------------------------------- */
+
+void Neighbor::choose_stencil_new(int index, NeighRequest *rq)
+{
+  int stencil = -1;
+
+  if (rq->skip || rq->copy || rq->half_from_full) stencil = -1;
+
+  else if (rq->ssa) {
+    if (dimension == 2) stencil = -1; // STENCIL_HALF_BIN_2D_SSA;
+    else if (dimension == 3) stencil = -1; // STENCIL_HALF_BIN_3D_SSA;
+
+  } else if (rq->half || rq->gran || rq->respaouter) {
+    if (style == BIN) {
+      if (rq->newton == 0) {
+        if (newton_pair == 0) {
+          if (dimension == 2) {
+            if (rq->ghost) stencil = -1; // STENCIL_HALF_GHOST_BIN_2D_NO_NEWTON;
+            else stencil = -1; // STENCIL_HALF_BIN_2D_NO_NEWTON;
+          } else if (dimension == 3) {
+            if (rq->ghost) stencil = -1; // STENCIL_HALF_GHOST_BIN_3D_NO_NEWTON;
+            else stencil = -1; // STENCIL_HALF_BIN_3D_NO_NEWTON;
+          }
+        } else if (triclinic == 0) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_BIN_2D_NEWTON;
+          else if (dimension == 3)
+            stencil = STENCIL_HALF_BIN_3D_NEWTON;
+        } else if (triclinic == 1) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_BIN_2D_NEWTON_TRI;
+          else if (dimension == 3)
+            stencil = -1; // STENCIL_HALF_BIN_3D_NEWTON_TRI;
+        }
+      } else if (rq->newton == 1) {
+        if (triclinic == 0) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_BIN_2D_NEWTON;
+          else if (dimension == 3)
+            stencil = STENCIL_HALF_BIN_3D_NEWTON;
+        } else if (triclinic == 1) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_BIN_2D_NEWTON_TRI;
+          else if (dimension == 3)
+            stencil = -1; // STENCIL_HALF_BIN_3D_NEWTON_TRI;
+        }
+      } else if (rq->newton == 2) {
+        if (dimension == 2)
+          if (rq->ghost) stencil = -1; // STENCIL_HALF_GHOST_BIN_2D_NO_NEWTON;
+          else stencil = -1; // STENCIL_HALF_BIN_2D_NO_NEWTON;
+        else if (dimension == 3) {
+          if (rq->ghost) stencil = -1; // STENCIL_HALF_GHOST_BIN_3D_NO_NEWTON;
+          else stencil = -1; // STENCIL_HALF_BIN_3D_NO_NEWTON;
+        }
+      }
+
+    } else if (style == MULTI) {
+      if (rq->newton == 0) {
+        if (newton_pair == 0) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_MULTI_2D_NO_NEWTON;
+          else if (dimension == 3)
+            stencil = -1; // STENCIL_HALF_MULTI_3D_NO_NEWTON;
+        } else if (triclinic == 0) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_MULTI_2D_NEWTON;
+          else if (dimension == 3)
+            stencil = -1; // STENCIL_HALF_MULTI_3D_NEWTON;
+        } else if (triclinic == 1) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_MULTI_2D_NEWTON_TRI;
+          else if (dimension == 3)
+            stencil = -1; // STENCIL_HALF_MULTI_3D_NEWTON_TRI;
+        }
+      } else if (rq->newton == 1) {
+        if (triclinic == 0) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_MULTI_2D_NEWTON;
+          else if (dimension == 3)
+            stencil = -1; // STENCIL_HALF_MULTI_3D_NEWTON;
+        } else if (triclinic == 1) {
+          if (dimension == 2)
+            stencil = -1; // STENCIL_HALF_MULTI_2D_NEWTON_TRI;
+          else if (dimension == 3)
+            stencil = -1; // STENCIL_HALF_MULTI_3D_NEWTON_TRI;
+        }
+      } else if (rq->newton == 2) {
+        if (dimension == 2)
+          stencil = -1; // STENCIL_HALF_MULTI_2D_NO_NEWTON;
+        else if (dimension == 3)
+          stencil = -1; // STENCIL_HALF_MULTI_3D_NO_NEWTON;
+      }
+    }
+
+  } else if (rq->full) {
+    if (style == BIN) {
+      if (dimension == 2) {
+        if (rq->ghost) stencil = -1; // STENCIL_FULL_GHOST_BIN_2D;
+        else stencil = -1; // STENCIL_FULL_BIN_2D;
+      }
+      else if (dimension == 3) {
+        if (rq->ghost) stencil = -1; // STENCIL_FULL_GHOST_BIN_3D;
+        else stencil = -1; // STENCIL_FULL_BIN_3D;
+      }
+    } else if (style == MULTI) {
+      if (dimension == 2) stencil = -1; // STENCIL_FULL_MULTI_2D;
+      else if (dimension == 3) stencil = -1; // STENCIL_FULL_MULTI_3D;
+    }
+  }
+
+  // instantiate selected Stencil class
+
+  if (stencil < 0) stencil_create_new[index] = NULL;
+  else if (stencil_map->find(stencil) != stencil_map->end()) {
+    StencilCreator stencil_creator = (*stencil_map)[stencil];
+    stencil_create_new[index] = stencil_creator(lmp);
+  } else error->all(FLERR,"Neighbor stencil class does not exit");
+}
+
 /* ----------------------------------------------------------------------
    determine which stencil_create function each neigh list needs
    based on settings of neigh request, only called if style != NSQ
@@ -1448,6 +1957,16 @@ void Neighbor::choose_stencil(int index, NeighRequest *rq)
   stencil_create[index] = sc;
 }
 
+/* ----------------------------------------------------------------------
+   one instance per fix in style_stencil.h
+------------------------------------------------------------------------- */
+
+template <typename T>
+Stencil *Neighbor::stencil_creator(LAMMPS *lmp)
+{
+  return new T(lmp);
+}
+
 /* ---------------------------------------------------------------------- */
 
 void Neighbor::print_lists_of_lists()
@@ -1627,8 +2146,11 @@ void Neighbor::build(int topoflag)
   // only for pairwise lists with buildflag set
   // blist is for standard neigh lists, otherwise is a Kokkos list
 
-  for (i = 0; i < nblist; i++)
-    (this->*pair_build[blist[i]])(lists[blist[i]]);
+  for (i = 0; i < nblist; i++) {
+    if (pair_build_new[blist[i]])
+      pair_build_new[blist[i]]->compute(lists[blist[i]]);
+    else (this->*pair_build[blist[i]])(lists[blist[i]]);
+  }
 
   if (atom->molecular && topoflag) build_topology();
 }
@@ -1677,7 +2199,9 @@ void Neighbor::build_one(class NeighList *mylist, int preflag)
 
   if (mylist->stencilflag) {
     mylist->stencil_allocate(smax,style);
-    (this->*stencil_create[mylist->index])(mylist,sx,sy,sz);
+    if (stencil_create_new[mylist->index])
+      stencil_create_new[mylist->index]->compute(mylist,sx,sy,sz);
+    else (this->*stencil_create[mylist->index])(mylist,sx,sy,sz);
   }
 
   if (mylist->growflag) mylist->grow(maxatom);
@@ -1688,7 +2212,9 @@ void Neighbor::build_one(class NeighList *mylist, int preflag)
   //   leading to errors or even a crash
 
   binatomflag = 0;
-  (this->*pair_build[mylist->index])(mylist);
+  if (pair_build_new[mylist->index])
+    pair_build_new[mylist->index]->compute(mylist);
+  else (this->*pair_build[mylist->index])(mylist);
   binatomflag = 1;
 }
 
@@ -1880,7 +2406,9 @@ void Neighbor::setup_bins()
   for (int i = 0; i < nslist; i++) {
     if (lists[slist[i]]) {
       lists[slist[i]]->stencil_allocate(smax,style);
-      (this->*stencil_create[slist[i]])(lists[slist[i]],sx,sy,sz);
+      if (stencil_create_new[slist[i]])
+        stencil_create_new[slist[i]]->compute(lists[slist[i]],sx,sy,sz);
+      else (this->*stencil_create[slist[i]])(lists[slist[i]],sx,sy,sz);
     } else setup_bins_kokkos(i);
   }
 }
diff --git a/src/neighbor.h b/src/neighbor.h
index 7a098e9be2..c2c3cdde97 100644
--- a/src/neighbor.h
+++ b/src/neighbor.h
@@ -15,11 +15,13 @@
 #define LMP_NEIGHBOR_H
 
 #include "pointers.h"
+#include <map>
 
 namespace LAMMPS_NS {
 
 class Neighbor : protected Pointers {
-  friend class Cuda;
+  friend class StencilHalfBin3dNewton;
+  friend class BuildHalfBinNewton;
 
  public:
   int style;                       // 0,1,2 = nsq, bin, multi
@@ -186,9 +188,29 @@ class Neighbor : protected Pointers {
   int exclusion(int, int, int,
                 int, int *, tagint *) const;    // test for pair exclusion
 
+  // choose stencil and build methods
+
   virtual void choose_build(int, class NeighRequest *);
   void choose_stencil(int, class NeighRequest *);
 
+  // new versions
+  // choose stencil and build classes
+
+  void choose_stencil_new(int, class NeighRequest *);
+  void choose_build_new(int, class NeighRequest *);
+
+  typedef class Stencil *(*StencilCreator)(class LAMMPS *);
+  std::map<int,StencilCreator> *stencil_map;
+
+  typedef class Build *(*BuildCreator)(class LAMMPS *);
+  std::map<int,BuildCreator> *build_map;
+
+  template <typename T> static Stencil *stencil_creator(class LAMMPS *);
+  template <typename T> static Build *build_creator(class LAMMPS *);
+
+  class Stencil **stencil_create_new;
+  class Build **pair_build_new;
+
   // dummy functions provided by NeighborKokkos
 
   virtual void init_cutneighsq_kokkos(int) {}
-- 
GitLab