diff --git a/src/Makefile b/src/Makefile
index 6d21661b6ce228b1e369a5f4f5289bcb1d403547..b844cfad6bf25e9e38fc7c69e849d965673583e1 100755
--- a/src/Makefile
+++ b/src/Makefile
@@ -15,7 +15,12 @@ OBJ = 	$(SRC:.cpp=.o)
 
 PACKAGE = asphere class2 colloid dipole dpd granular \
 	  kspace manybody meam molecule opt poems xtc
+
+PACKUSER = user-ackland user-ewaldn
+
 PACKUC = $(shell perl -e 'printf("%s", uc("$(PACKAGE)"));')
+PACKUSERUC = $(shell perl -e 'printf("%s", uc("$(PACKUSER)"));')
+
 YESDIR = $(shell perl -e 'printf("%s", uc("$(@:yes-%=%)"));')
 NODIR  = $(shell perl -e 'printf("%s", uc("$(@:no-%=%)"));')
 
@@ -31,10 +36,15 @@ help:
 	@echo ''
 	@echo 'make package             list available packages'
 	@echo 'make package-status      status of all packages'
-	@echo 'make yes-package         install a package in src dir'
-	@echo 'make no-package          remove package files from src dir'
+	@echo 'make yes-package         install a single package in src dir'
+	@echo 'make no-package          remove a single package from src dir'
 	@echo 'make yes-all             install all packages in src dir'
-	@echo 'make no-all              remove all package files from src dir'
+	@echo 'make no-all              remove all packages from src dir'
+	@echo 'make yes-standard        install all standard packages'
+	@echo 'make no-standard         remove all standard packages'
+	@echo 'make yes-user            install all user packages'
+	@echo 'make no-user             remove all user packages'
+	@echo ''
 	@echo 'make package-update      replace src files with package files'
 	@echo 'make package-overwrite   replace package files with src files'
 	@echo ''
@@ -86,27 +96,45 @@ makelist:
 	@csh Make.csh Makefile.list
 
 # Package management
-# status =    list differences between src and package files
-# update =    replace src files with newer package files
-# overwrite = overwrite package files with newer src files
 
 package:
-	@echo 'Available packages:'
-	@echo $(PACKAGE)
+	@echo 'Standard packages:' $(PACKAGE)
 	@echo ''
+	@echo 'User-contributed packages:' $(PACKUSER)
+	@echo ''
+	@echo 'make package             list available packages'
 	@echo 'make package-status      status of all packages'
-	@echo 'make yes-package         install a package in src dir'
-	@echo 'make no-package          remove package files from src dir'
+	@echo 'make yes-package         install a single package in src dir'
+	@echo 'make no-package          remove a single package from src dir'
 	@echo 'make yes-all             install all packages in src dir'
-	@echo 'make no-all              remove all package files from src dir'
+	@echo 'make no-all              remove all packages from src dir'
+	@echo 'make yes-standard        install all standard packages'
+	@echo 'make no-standard         remove all standard packages'
+	@echo 'make yes-user            install all user packages'
+	@echo 'make no-user             remove all user packages'
+	@echo ''
 	@echo 'make package-update      replace src files with package files'
 	@echo 'make package-overwrite   replace package files with src files'
 
 yes-all:
 	@for p in $(PACKAGE); do $(MAKE) yes-$$p; done
+	@for p in $(PACKUSER); do $(MAKE) yes-$$p; done
 
 no-all:
 	@for p in $(PACKAGE); do $(MAKE) no-$$p; done
+	@for p in $(PACKUSER); do $(MAKE) no-$$p; done
+
+yes-standard:
+	@for p in $(PACKAGE); do $(MAKE) yes-$$p; done
+
+no-standard:
+	@for p in $(PACKAGE); do $(MAKE) no-$$p; done
+
+yes-user:
+	@for p in $(PACKUSER); do $(MAKE) yes-$$p; done
+
+no-user:
+	@for p in $(PACKUSER); do $(MAKE) no-$$p; done
 
 yes-%:
 	@if [ ! -e $(YESDIR) ]; then \
@@ -124,11 +152,21 @@ no-%:
 	  cd $(NODIR); csh -f Install.csh 0; cd ..; $(MAKE) clean-all; \
         fi;
 
+# status = list differences between src and package files
+# update = replace src files with newer package files
+# overwrite = overwrite package files with newer src files
+
 package-status:
 	@for p in $(PACKUC); do csh -f Package.csh $$p status; done
+	@echo ''
+	@for p in $(PACKUSERUC); do csh -f Package.csh $$p status; done
 
 package-update:
 	@for p in $(PACKUC); do csh -f Package.csh $$p update; done
+	@echo ''
+	@for p in $(PACKUSERUC); do csh -f Package.csh $$p update; done
 
 package-overwrite:
 	@for p in $(PACKUC); do csh -f Package.csh $$p overwrite; done
+	@echo ''
+	@for p in $(PACKUSERUC); do csh -f Package.csh $$p overwrite; done
diff --git a/src/Package.csh b/src/Package.csh
index 538572d413c364ab98fd434d4644f4c5a849ac07..0ab65a7752296a6fbd0ef52d2d655427baf39378 100644
--- a/src/Package.csh
+++ b/src/Package.csh
@@ -27,7 +27,7 @@
 #   just longer than the other (has new stuff added)
 
 set glob
-set style = `echo $1 | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+set style = `echo $1 | sed 'y/-ABCDEFGHIJKLMNOPQRSTUVWXYZ/_abcdefghijklmnopqrstuvwxyz/'`
 cd $1
 
 if ($2 == "status") then
diff --git a/src/atom.cpp b/src/atom.cpp
index 97cf66558e9ebb3c8d5a95c07489c53b705ce7fb..943205b50a4557a22885e5124eb6305b6b28ef55 100644
--- a/src/atom.cpp
+++ b/src/atom.cpp
@@ -212,7 +212,7 @@ Atom::~Atom()
    called from input script, restart file, replicate
 ------------------------------------------------------------------------- */
 
-void Atom::create_avec(char *style, int narg, char **arg)
+void Atom::create_avec(const char *style, int narg, char **arg)
 {
   delete [] atom_style;
   if (avec) delete avec;
@@ -232,7 +232,7 @@ void Atom::create_avec(char *style, int narg, char **arg)
    generate an AtomVec class
 ------------------------------------------------------------------------- */
 
-AtomVec *Atom::new_avec(char *style, int narg, char **arg)
+AtomVec *Atom::new_avec(const char *style, int narg, char **arg)
 {
   if (0) return NULL;
 
@@ -274,7 +274,7 @@ void Atom::init()
    else return 0
 ------------------------------------------------------------------------- */
 
-int Atom::style_match(char *style)
+int Atom::style_match(const char *style)
 {
   if (strcmp(atom_style,style) == 0) return 1;
   else if (strcmp(atom_style,"hybrid") == 0) {
@@ -602,7 +602,7 @@ int Atom::tag_consecutive()
    trim anything from '#' onward
 ------------------------------------------------------------------------- */
 
-int Atom::count_words(char *line)
+int Atom::count_words(const char *line)
 {
   int n = strlen(line) + 1;
   char *copy = (char *) memory->smalloc(n*sizeof(char),"copy");
@@ -991,7 +991,7 @@ void Atom::allocate_type_arrays()
    called from reading of data file
 ------------------------------------------------------------------------- */
 
-void Atom::set_mass(char *str)
+void Atom::set_mass(const char *str)
 {
   if (mass == NULL) error->all("Cannot set mass for this atom style");
 
@@ -1067,7 +1067,7 @@ void Atom::check_mass()
    called from reading of data file
 ------------------------------------------------------------------------- */
 
-void Atom::set_shape(char *str)
+void Atom::set_shape(const char *str)
 {
   if (shape == NULL) error->all("Cannot set shape for this atom style");
 
@@ -1140,7 +1140,7 @@ void Atom::check_shape()
    called from reading of data file
 ------------------------------------------------------------------------- */
 
-void Atom::set_dipole(char *str)
+void Atom::set_dipole(const char *str)
 {
   if (dipole == NULL) error->all("Cannot set dipole for this atom style");
 
@@ -1244,7 +1244,7 @@ void Atom::add_callback(int flag)
    flag = 0 for grow, 1 for restart
 ------------------------------------------------------------------------- */
 
-void Atom::delete_callback(char *id, int flag)
+void Atom::delete_callback(const char *id, int flag)
 {
   int ifix;
   for (ifix = 0; ifix < modify->nfix; ifix++)
diff --git a/src/atom.h b/src/atom.h
index 3f18c33c14a0c4a51c5e90897c9796695f149a04..c2e1e0462b88bd8d0a4427af51484cb705895de6 100644
--- a/src/atom.h
+++ b/src/atom.h
@@ -97,17 +97,17 @@ class Atom : protected Pointers {
   Atom(class LAMMPS *);
   ~Atom();
 
-  void create_avec(char *, int, char **);
-  class AtomVec *new_avec(char *, int, char **);
+  void create_avec(const char *, int, char **);
+  class AtomVec *new_avec(const char *, int, char **);
   void init();
 
-  int style_match(char *);
+  int style_match(const char *);
   void modify_params(int, char **);
   void tag_extend();
   int tag_consecutive();
 
-  int parse_data(char *);
-  int count_words(char *);
+  int parse_data(const char *);
+  int count_words(const char *);
 
   void data_atoms(int, char *);
   void data_vels(int, char *);
@@ -117,22 +117,22 @@ class Atom : protected Pointers {
   void data_impropers(int, char *);
 
   void allocate_type_arrays();
-  void set_mass(char *);
+  void set_mass(const char *);
   void set_mass(int, double);
   void set_mass(int, char **);
   void set_mass(double *);
   void check_mass();
-  void set_shape(char *);
+  void set_shape(const char *);
   void set_shape(int, char **);
   void set_shape(double **);
   void check_shape();
-  void set_dipole(char *);
+  void set_dipole(const char *);
   void set_dipole(int, char **);
   void set_dipole(double *);
   void check_dipole();
 
   void add_callback(int);
-  void delete_callback(char *, int);
+  void delete_callback(const char *, int);
   void update_callback(int);
 
   int memory_usage();
diff --git a/src/compute.cpp b/src/compute.cpp
index 0a6312068ec031ac2fdfd17592769a83bb175a81..1e0eee51f6c353c3ed76fff761b36f29c2176975 100644
--- a/src/compute.cpp
+++ b/src/compute.cpp
@@ -49,9 +49,9 @@ Compute::Compute(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
   
   scalar_flag = vector_flag = peratom_flag = 0;
   tempflag = pressflag = 0;
+  npre = 0;
   id_pre = NULL;
   comm_forward = comm_reverse = 0;
-  neigh_half_once = neigh_full_once = 0;
 
   // set modify defaults
 
@@ -65,6 +65,9 @@ Compute::~Compute()
 {
   delete [] id;
   delete [] style;
+
+  for (int i = 0; i < npre; i++) delete [] id_pre[i];
+  delete [] id_pre;
 }
 
 /* ---------------------------------------------------------------------- */
diff --git a/src/compute.h b/src/compute.h
index bae6bc1ab6e80cd0f07f1d17ec7231084096a848..a8f1b0f98f36dbc702179103dd8c25123c9fb3a5 100644
--- a/src/compute.h
+++ b/src/compute.h
@@ -39,18 +39,19 @@ class Compute : protected Pointers {
                       // must have both compute_scalar, compute_vector
   int pressflag;      // 1 if Compute can be used as pressure (uses virial)
                       // must have both compute_scalar, compute_vector
-  char *id_pre;       // ID of Compute that needs to be computed before this
   double dof;         // degrees-of-freedom for temperature
 
+  int npre;           // # of computes to compute before this one
+  char **id_pre;      // IDs of Computes to compute before this one
+
   int comm_forward;     // size of forward communication (0 if none)
   int comm_reverse;     // size of reverse communication (0 if none)
-  int neigh_half_once;  // 1 if requires half neighbor lists
-  int neigh_full_once;  // 1 if requires full neighbor lists
 
   Compute(class LAMMPS *, int, char **);
   virtual ~Compute();
   void modify_params(int, char **);
   virtual void init() = 0;
+  virtual void init_list(int, class NeighList *) {}
   virtual double compute_scalar() {return 0.0;}
   virtual void compute_vector() {}
   virtual void compute_peratom() {}
diff --git a/src/compute_centro_atom.cpp b/src/compute_centro_atom.cpp
index 04b9383f3282ea6e8e8c0761e936e173a228897b..3506cc8dced2c984a4e9f755777d92d012ba5744 100644
--- a/src/compute_centro_atom.cpp
+++ b/src/compute_centro_atom.cpp
@@ -17,6 +17,8 @@
 #include "modify.h"
 #include "update.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "force.h"
 #include "pair.h"
 #include "comm.h"
@@ -34,7 +36,6 @@ ComputeCentroAtom::ComputeCentroAtom(LAMMPS *lmp, int narg, char **arg) :
 
   peratom_flag = 1;
   size_peratom = 0;
-  neigh_full_once = 1;
 
   nmax = 0;
   centro = NULL;
@@ -61,15 +62,31 @@ void ComputeCentroAtom::init()
     if (strcmp(modify->compute[i]->style,"centro/atom") == 0) count++;
   if (count > 1 && comm->me == 0)
     error->warning("More than one compute centro/atom");
+
+  // need an occasional full neighbor list
+
+  int irequest = neighbor->request((void *) this);
+  neighbor->requests[irequest]->pair = 0;
+  neighbor->requests[irequest]->compute = 1;
+  neighbor->requests[irequest]->half = 0;
+  neighbor->requests[irequest]->full = 1;
+  neighbor->requests[irequest]->occasional = 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ComputeCentroAtom::init_list(int id, NeighList *ptr)
+{
+  list = ptr;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void ComputeCentroAtom::compute_peratom()
 {
-  int j,k,jj,kk,n,numneigh;
+  int i,j,k,ii,jj,kk,n,inum,jnum;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq,value;
-  int *neighs;
+  int *ilist,*jlist,*numneigh,**firstneigh;
   double pairs[66];
 
   // grow centro array if necessary
@@ -82,9 +99,14 @@ void ComputeCentroAtom::compute_peratom()
     scalar_atom = centro;
   }
 
-  // if needed, build a full neighbor list
+  // invoke full neighbor list (will copy or build if necessary)
+
+  neighbor->build_one(list->index);
 
-  if (!neighbor->full_every) neighbor->build_full();
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
 
   // compute centro-symmetry parameter for each atom in group
   // use full neighbor list
@@ -95,20 +117,21 @@ void ComputeCentroAtom::compute_peratom()
   int nall = atom->nlocal + atom->nghost;
   double cutsq = force->pair->cutforce * force->pair->cutforce;
 
-  for (int i = 0; i < nlocal; i++)
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     if (mask[i] & groupbit) {
       xtmp = x[i][0];
       ytmp = x[i][1];
       ztmp = x[i][2];
-      neighs = neighbor->firstneigh_full[i];
-      numneigh = neighbor->numneigh_full[i];
+      jlist = firstneigh[i];
+      jnum = numneigh[i];
 
       // insure distsq and nearest arrays are long enough
 
-      if (numneigh > maxneigh) {
+      if (jnum > maxneigh) {
 	memory->sfree(distsq);
 	memory->sfree(nearest);
-	maxneigh = numneigh;
+	maxneigh = jnum;
 	distsq = (double *) memory->smalloc(maxneigh*sizeof(double),
 					    "compute/centro/atom:distsq");
 	nearest = (int *) memory->smalloc(maxneigh*sizeof(int),
@@ -120,8 +143,8 @@ void ComputeCentroAtom::compute_peratom()
       // nearest[] = atom indices of neighbors
 
       n = 0;
-      for (k = 0; k < numneigh; k++) {
-	j = neighs[k];
+      for (jj = 0; jj < jnum; jj++) {
+	j = jlist[jj];
 	if (j >= nall) j %= nall;
 
 	delx = xtmp - x[j][0];
@@ -169,7 +192,8 @@ void ComputeCentroAtom::compute_peratom()
       value = 0.0;
       for (j = 0; j < 6; j++) value += pairs[j];
       centro[i] = value;
-    }
+    } else centro[i] = 0.0;
+  }
 }
 
 /* ----------------------------------------------------------------------
diff --git a/src/compute_centro_atom.h b/src/compute_centro_atom.h
index 6a16d7c0593379e9626f8c23a2bec5a71349f583..1aa47a1d521abb4a50710ba9e679040bbaf5d271 100644
--- a/src/compute_centro_atom.h
+++ b/src/compute_centro_atom.h
@@ -23,6 +23,7 @@ class ComputeCentroAtom : public Compute {
   ComputeCentroAtom(class LAMMPS *, int, char **);
   ~ComputeCentroAtom();
   void init();
+  void init_list(int, class NeighList *);
   void compute_peratom();
   int memory_usage();
 
@@ -31,6 +32,7 @@ class ComputeCentroAtom : public Compute {
   double *distsq;
   int *nearest;
   double *centro;
+  class NeighList *list;
 
   void select(int, int, double *);
   void select2(int, int, double *, int *);
diff --git a/src/compute_coord_atom.cpp b/src/compute_coord_atom.cpp
index 285ad1aa71982bc6e3f0d266e20abefde58817b6..f2d70915c6ea5c5d2fc21a1af530c7923edbf260 100644
--- a/src/compute_coord_atom.cpp
+++ b/src/compute_coord_atom.cpp
@@ -17,6 +17,8 @@
 #include "atom.h"
 #include "modify.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "force.h"
 #include "pair.h"
 #include "comm.h"
@@ -30,13 +32,12 @@ using namespace LAMMPS_NS;
 ComputeCoordAtom::ComputeCoordAtom(LAMMPS *lmp, int narg, char **arg) :
   Compute(lmp, narg, arg)
 {
-  if (narg != 4) error->all("Illegal compute centro/atom command");
+  if (narg != 4) error->all("Illegal compute coord/atom command");
 
   cutoff = atof(arg[3]);
 
   peratom_flag = 1;
   size_peratom = 0;
-  neigh_full_once = 1;
 
   nmax = 0;
   coordination = NULL;
@@ -56,6 +57,15 @@ void ComputeCoordAtom::init()
   if (force->pair == NULL || cutoff > force->pair->cutforce) 
     error->all("Compute coord/atom cutoff is longer than pairwise cutoff");
 
+  // need an occasional full neighbor list
+
+  int irequest = neighbor->request((void *) this);
+  neighbor->requests[irequest]->pair = 0;
+  neighbor->requests[irequest]->compute = 1;
+  neighbor->requests[irequest]->half = 0;
+  neighbor->requests[irequest]->full = 1;
+  neighbor->requests[irequest]->occasional = 1;
+
   int count = 0;
   for (int i = 0; i < modify->ncompute; i++)
     if (strcmp(modify->compute[i]->style,"coord/atom") == 0) count++;
@@ -65,11 +75,18 @@ void ComputeCoordAtom::init()
 
 /* ---------------------------------------------------------------------- */
 
+void ComputeCoordAtom::init_list(int id, NeighList *ptr)
+{
+  list = ptr;
+}
+
+/* ---------------------------------------------------------------------- */
+
 void ComputeCoordAtom::compute_peratom()
 {
-  int j,k,n,numneigh;
+  int i,j,ii,jj,inum,jnum,n;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighs;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   // grow coordination array if necessary
 
@@ -81,9 +98,14 @@ void ComputeCoordAtom::compute_peratom()
     scalar_atom = coordination;
   }
 
-  // if needed, build a full neighbor list
+  // invoke full neighbor list (will copy or build if necessary)
+
+  neighbor->build_one(list->index);
 
-  if (!neighbor->full_every) neighbor->build_full();
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
 
   // compute coordination number for each atom in group
   // use full neighbor list to count atoms less than cutoff
@@ -94,17 +116,18 @@ void ComputeCoordAtom::compute_peratom()
   int nall = atom->nlocal + atom->nghost;
   double cutsq = cutoff*cutoff;
 
-  for (int i = 0; i < nlocal; i++)
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     if (mask[i] & groupbit) {
       xtmp = x[i][0];
       ytmp = x[i][1];
       ztmp = x[i][2];
-      neighs = neighbor->firstneigh_full[i];
-      numneigh = neighbor->numneigh_full[i];
+      jlist = firstneigh[i];
+      jnum = numneigh[i];
 
       n = 0;
-      for (k = 0; k < numneigh; k++) {
-	j = neighs[k];
+      for (jj = 0; jj < jnum; jj++) {
+	j = jlist[jj];
 	if (j >= nall) j %= nall;
 
 	delx = xtmp - x[j][0];
@@ -115,8 +138,10 @@ void ComputeCoordAtom::compute_peratom()
       }
 
       coordination[i] = n;
-    }
+    } else coordination[i] = 0.0;
+  }
 }
+
 /* ----------------------------------------------------------------------
    memory usage of local atom-based array
 ------------------------------------------------------------------------- */
diff --git a/src/compute_coord_atom.h b/src/compute_coord_atom.h
index 74ff9410873bbfecdcda6b2487bdc58a2d4b329f..ca121c1914dcd8bc996e108b9d3dac00d3a6dde9 100644
--- a/src/compute_coord_atom.h
+++ b/src/compute_coord_atom.h
@@ -23,6 +23,7 @@ class ComputeCoordAtom : public Compute {
   ComputeCoordAtom(class LAMMPS *, int, char **);
   ~ComputeCoordAtom();
   void init();
+  void init_list(int, class NeighList *);
   void compute_peratom();
   int memory_usage();
 
@@ -30,6 +31,7 @@ class ComputeCoordAtom : public Compute {
   int nmax;
   double cutoff;
   double *coordination;
+  class NeighList *list;
 };
 
 }
diff --git a/src/compute_ebond_atom.cpp b/src/compute_ebond_atom.cpp
index 664a036e0b8626159931afcebd777ba1953c2981..f3f902bc07bd11e81889f223c3e2929a78ffda64 100644
--- a/src/compute_ebond_atom.cpp
+++ b/src/compute_ebond_atom.cpp
@@ -56,7 +56,7 @@ ComputeEbondAtom::~ComputeEbondAtom()
 void ComputeEbondAtom::init()
 {
   if (force->bond == NULL)
-    error->all("Bond style does not support computing per-atom energy");
+    error->all("Bond style does not support computing per-atom bond energy");
 
   int count = 0;
   for (int i = 0; i < modify->ncompute; i++)
@@ -69,7 +69,7 @@ void ComputeEbondAtom::init()
 
 void ComputeEbondAtom::compute_peratom()
 {
-  int i,n,i1,i2,type;
+  int i,n,i1,i2,type,iflag,jflag;
   double delx,dely,delz,rsq,fforce,eng;
 
   // grow energy array if necessary
@@ -95,6 +95,7 @@ void ComputeEbondAtom::compute_peratom()
 
   // compute bond energy for atoms via bond->single()
   // if neither atom is in compute group, skip that bond
+  // only add energy to atoms in group
 
   double **x = atom->x;
   int *mask = atom->mask;
@@ -105,7 +106,9 @@ void ComputeEbondAtom::compute_peratom()
     i1 = bondlist[n][0];
     i2 = bondlist[n][1];
     type = bondlist[n][2];
-    if ((mask[i1] & groupbit) == 0 && (mask[i2] & groupbit) == 0) continue;
+    iflag = mask[i1] & groupbit;
+    jflag = mask[i2] & groupbit;
+    if (iflag == 0 && jflag == 0) continue;
 
     delx = x[i1][0] - x[i2][0];
     dely = x[i1][1] - x[i2][1];
@@ -114,8 +117,8 @@ void ComputeEbondAtom::compute_peratom()
       
     rsq = delx*delx + dely*dely + delz*delz;
     force->bond->single(type,rsq,i1,i2,0,fforce,eng);
-    energy[i] += eng;
-    if (newton_bond || i2 < nlocal) energy[i2] += eng;
+    if (iflag) energy[i1] += eng;
+    if (jflag && (newton_bond || i2 < nlocal)) energy[i2] += eng;
   }
 
   // communicate energy between neigchbor procs
diff --git a/src/compute_epair_atom.cpp b/src/compute_epair_atom.cpp
index 36a16d92be03b9c75bb83974ab2987a74d1bd946..f7b3a4b7eb49024e89b47feb44ae4efd89725a88 100644
--- a/src/compute_epair_atom.cpp
+++ b/src/compute_epair_atom.cpp
@@ -15,6 +15,8 @@
 #include "compute_epair_atom.h"
 #include "atom.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "modify.h"
 #include "comm.h"
 #include "update.h"
@@ -38,7 +40,6 @@ ComputeEpairAtom::ComputeEpairAtom(LAMMPS *lmp, int narg, char **arg) :
   peratom_flag = 1;
   size_peratom = 0;
   comm_reverse = 1;
-  neigh_half_once = 1;
 
   nmax = 0;
   energy = NULL;
@@ -58,6 +59,13 @@ void ComputeEpairAtom::init()
   if (force->pair == NULL || force->pair->single_enable == 0)
     error->all("Pair style does not support computing per-atom energy");
 
+  // need an occasional half neighbor list
+
+  int irequest = neighbor->request((void *) this);
+  neighbor->requests[irequest]->pair = 0;
+  neighbor->requests[irequest]->compute = 1;
+  neighbor->requests[irequest]->occasional = 1;
+
   if (force->pair_match("eam")) eamstyle = 1;
   else eamstyle = 0;
 
@@ -70,12 +78,19 @@ void ComputeEpairAtom::init()
 
 /* ---------------------------------------------------------------------- */
 
+void ComputeEpairAtom::init_list(int id, NeighList *ptr)
+{
+  list = ptr;
+}
+
+/* ---------------------------------------------------------------------- */
+
 void ComputeEpairAtom::compute_peratom()
 {
-  int i,j,k,n,itype,jtype,numneigh,iflag;
+  int i,j,ii,jj,n,inum,jnum,itype,jtype,iflag,jflag;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
   double factor_coul,factor_lj,eng;
-  int *neighs;
+  int *ilist,*jlist,*numneigh,**firstneigh;
   Pair::One one;
 
   // grow energy array if necessary
@@ -99,12 +114,18 @@ void ComputeEpairAtom::compute_peratom()
 
   for (i = 0; i < n; i++) energy[i] = 0.0;
 
-  // if needed, build a half neighbor list
+  // invoke half neighbor list (will copy or build if necessary)
+
+  neighbor->build_one(list->index);
 
-  if (!neighbor->half_every) neighbor->build_half();
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
 
   // compute pairwise energy for atoms via pair->single()
   // if neither atom is in compute group, skip that pair
+  // only add energy to atoms in group
 
   double *special_coul = force->special_coul;
   double *special_lj = force->special_lj;
@@ -115,18 +136,20 @@ void ComputeEpairAtom::compute_peratom()
   int *type = atom->type;
   int nall = nlocal + atom->nghost;
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
     iflag = mask[i] & groupbit;
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
-    
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
-      if (iflag == 0 && (mask[j] & groupbit) == 0) continue;
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
+
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
+      jflag = mask[j] & groupbit;
+      if (iflag == 0 && jflag == 0) continue;
 
       if (j < nall) factor_coul = factor_lj = 1.0;
       else {
@@ -144,8 +167,8 @@ void ComputeEpairAtom::compute_peratom()
       if (rsq < cutsq[itype][jtype]) {
 	force->pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,1,one);
 	eng = one.eng_coul + one.eng_vdwl;
-	energy[i] += eng;
-	if (newton_pair || j < nlocal) energy[j] += eng;
+	if (iflag) energy[i] += eng;
+	if (jflag && (newton_pair || j < nlocal)) energy[j] += eng;
       }
     }
   }
@@ -162,7 +185,8 @@ void ComputeEpairAtom::compute_peratom()
   // only for atoms in compute group
 
   if (eamstyle) {
-    for (i = 0; i < nlocal; i++) {
+    for (ii = 0; ii < inum; ii++) {
+      i = ilist[ii];
       if (mask[i] & groupbit) {
 	force->pair->single_embed(i,type[i],eng);
 	energy[i] += eng;
diff --git a/src/compute_epair_atom.h b/src/compute_epair_atom.h
index 6ead5058f52aa73e68f3eb34a0bd366e2e701aca..6ab6160b5b8f1658157330ff3c11f6578156432d 100644
--- a/src/compute_epair_atom.h
+++ b/src/compute_epair_atom.h
@@ -23,6 +23,7 @@ class ComputeEpairAtom : public Compute {
   ComputeEpairAtom(class LAMMPS *, int, char **);
   ~ComputeEpairAtom();
   void init();
+  void init_list(int, class NeighList *);
   void compute_peratom();
   int pack_reverse_comm(int, int, double *);
   void unpack_reverse_comm(int, int *, double *);
@@ -30,6 +31,7 @@ class ComputeEpairAtom : public Compute {
 
  private:
   int nmax,eamstyle;
+  class NeighList *list;
   double *energy;
 };
 
diff --git a/src/compute_etotal_atom.cpp b/src/compute_etotal_atom.cpp
deleted file mode 100644
index e287cdd6f928735f80ba6084ce4e3dc3cfceec73..0000000000000000000000000000000000000000
--- a/src/compute_etotal_atom.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/* ----------------------------------------------------------------------
-   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
-   http://lammps.sandia.gov, 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 "string.h"
-#include "compute_etotal_atom.h"
-#include "atom.h"
-#include "modify.h"
-#include "force.h"
-#include "comm.h"
-#include "memory.h"
-#include "error.h"
-
-using namespace LAMMPS_NS;
-
-/* ---------------------------------------------------------------------- */
-
-ComputeEtotalAtom::ComputeEtotalAtom(LAMMPS *lmp, int narg, char **arg) :
-  Compute(lmp, narg, arg)
-{
-  if (narg != 4) error->all("Illegal compute etotal/atom command");
-
-  // store epair ID used by energy computation
-
-  int n = strlen(arg[3]) + 1;
-  id_pre = new char[n];
-  strcpy(id_pre,arg[3]);
-
-  peratom_flag = 1;
-  size_peratom = 0;
-
-  nmax = 0;
-  etotal = NULL;
-}
-
-/* ---------------------------------------------------------------------- */
-
-ComputeEtotalAtom::~ComputeEtotalAtom()
-{
-  delete [] id_pre;
-  memory->sfree(etotal);
-}
-
-/* ---------------------------------------------------------------------- */
-
-void ComputeEtotalAtom::init()
-{
-  int count = 0;
-  for (int i = 0; i < modify->ncompute; i++)
-    if (strcmp(modify->compute[i]->style,"etotal/atom") == 0) count++;
-  if (count > 1 && comm->me == 0)
-    error->warning("More than one compute etotal/atom");
-
-  // set epair Compute used by this compute
-
-  int icompute = modify->find_compute(id_pre);
-  if (icompute < 0)
-    error->all("Could not find compute etotal/atom pre-compute ID");
-  compute_epair = modify->compute[icompute];
-
-  if (groupbit != compute_epair->groupbit && comm->me == 0)
-    error->warning("Group for compute etotal and its epair are not the same");
-}
-
-/* ---------------------------------------------------------------------- */
-
-void ComputeEtotalAtom::compute_peratom()
-{
-  // grow etotal array if necessary
-
-  if (atom->nlocal > nmax) {
-    memory->sfree(etotal);
-    nmax = atom->nmax;
-    etotal = (double *) 
-      memory->smalloc(nmax*sizeof(double),"compute/etotal/atom:etotal");
-    scalar_atom = etotal;
-  }
-
-  // compute total energy for each atom in group
-
-  double *epair = compute_epair->scalar_atom;
-  double mvv2e = force->mvv2e;
-  double **v = atom->v;
-  double *mass = atom->mass;
-  double *rmass = atom->rmass;
-  int *mask = atom->mask;
-  int *type = atom->type;
-  int nlocal = atom->nlocal;
-
-  double ke;
-
-  if (mass)
-    for (int i = 0; i < nlocal; i++) {
-      if (mask[i] & groupbit) {
-	ke = 0.5 * mvv2e * mass[type[i]] *
-	  (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
-	etotal[i] = ke + epair[i];
-      }
-    }
-  else
-    for (int i = 0; i < nlocal; i++) {
-      if (mask[i] & groupbit) {
-	ke = 0.5 * mvv2e * rmass[i] *
-	  (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
-	etotal[i] = ke + epair[i];
-      }
-    }
-}
-
-/* ----------------------------------------------------------------------
-   memory usage of local atom-based array
-------------------------------------------------------------------------- */
-
-int ComputeEtotalAtom::memory_usage()
-{
-  int bytes = nmax * sizeof(double);
-  return bytes;
-}
diff --git a/src/compute_ke_atom.cpp b/src/compute_ke_atom.cpp
index 9734594165bed771c7b83e9ad13692d3e81ee901..27d123bd5d230e18b2611a90df2fc37f61d77e60 100644
--- a/src/compute_ke_atom.cpp
+++ b/src/compute_ke_atom.cpp
@@ -82,14 +82,15 @@ void ComputeKEAtom::compute_peratom()
       if (mask[i] & groupbit) {
 	ke[i] = 0.5 * mvv2e * mass[type[i]] *
 	  (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
-      }
+      } else ke[i] = 0.0;
     }
+
   else
     for (int i = 0; i < nlocal; i++) {
       if (mask[i] & groupbit) {
 	ke[i] = 0.5 * mvv2e * rmass[i] *
 	  (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
-      }
+      } else ke[i] = 0.0;
     }
 }
 
diff --git a/src/compute_pressure.cpp b/src/compute_pressure.cpp
index d32f16230df790961be366d9c924a65bc402ed1e..554fb57837b6e82ffa29db02cd553ede6bacb0c1 100644
--- a/src/compute_pressure.cpp
+++ b/src/compute_pressure.cpp
@@ -42,11 +42,13 @@ ComputePressure::ComputePressure(LAMMPS *lmp, int narg, char **arg) :
   // store temperature ID used by pressure computation
   // insure it is valid for temperature computation
 
+  npre = 1;
+  id_pre = new char*[1];
   int n = strlen(arg[3]) + 1;
-  id_pre = new char[n];
-  strcpy(id_pre,arg[3]);
+  id_pre[0] = new char[n];
+  strcpy(id_pre[0],arg[3]);
 
-  int icompute = modify->find_compute(id_pre);
+  int icompute = modify->find_compute(id_pre[0]);
 
   if (icompute < 0) error->all("Could not find compute pressure temp ID");
   if (modify->compute[icompute]->tempflag == 0)
@@ -66,7 +68,6 @@ ComputePressure::ComputePressure(LAMMPS *lmp, int narg, char **arg) :
 
 ComputePressure::~ComputePressure()
 {
-  delete [] id_pre;
   delete [] vector;
   delete [] vptr;
 }
@@ -81,7 +82,7 @@ void ComputePressure::init()
 
   // set temperature used by pressure
 
-  int icompute = modify->find_compute(id_pre);
+  int icompute = modify->find_compute(id_pre[0]);
   if (icompute < 0) error->all("Could not find compute pressure temp ID");
   temperature = modify->compute[icompute];
 
diff --git a/src/compute_stress_atom.cpp b/src/compute_stress_atom.cpp
index 1ff75411244487ba297db8799a4356ef9899b30b..eb113fec274fbe7508e911d3146953240528eb50 100644
--- a/src/compute_stress_atom.cpp
+++ b/src/compute_stress_atom.cpp
@@ -15,6 +15,8 @@
 #include "compute_stress_atom.h"
 #include "atom.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "modify.h"
 #include "comm.h"
 #include "update.h"
@@ -40,7 +42,6 @@ ComputeStressAtom::ComputeStressAtom(LAMMPS *lmp, int narg, char **arg) :
   peratom_flag = 1;
   size_peratom = 6;
   comm_reverse = 6;
-  neigh_half_once = 1;
 
   // process args
 
@@ -85,6 +86,14 @@ void ComputeStressAtom::init()
     if (force->pair == NULL || force->pair->single_enable == 0)
       error->all("Pair style does not support computing per-atom stress");
     pairflag = 1;
+
+    // need an occasional half neighbor list
+
+    int irequest = neighbor->request((void *) this);
+    neighbor->requests[irequest]->pair = 0;
+    neighbor->requests[irequest]->compute = 1;
+    neighbor->requests[irequest]->occasional = 1;
+
   } else pairflag = 0;
 
   if (bondrequest && force->bond) bondflag = 1;
@@ -99,12 +108,19 @@ void ComputeStressAtom::init()
 
 /* ---------------------------------------------------------------------- */
 
+void ComputeStressAtom::init_list(int id, NeighList *ptr)
+{
+  list = ptr;
+}
+
+/* ---------------------------------------------------------------------- */
+
 void ComputeStressAtom::compute_peratom()
 {
-  int i,j,k,n,i1,i2,itype,jtype,numneigh,iflag;
+  int i,j,ii,jj,n,i1,i2,inum,jnum,itype,jtype,iflag,jflag;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq,eng;
   double factor_coul,factor_lj,fforce,rmass;
-  int *neighs;
+  int *ilist,*jlist,*numneigh,**firstneigh;
   Pair::One one;
 
   // grow stress array if necessary
@@ -136,12 +152,18 @@ void ComputeStressAtom::compute_peratom()
 
   // compute pairwise stress for atoms via pair->single()
   // if neither atom is in compute group, skip that pair
+  // only add stress to atoms in group
 
   if (pairflag) {
 
-    // if needed, build a half neighbor list
+    // invoke half neighbor list (will copy or build if necessary)
 
-    if (!neighbor->half_every) neighbor->build_half();
+    neighbor->build_one(list->index);
+
+    inum = list->inum;
+    ilist = list->ilist;
+    numneigh = list->numneigh;
+    firstneigh = list->firstneigh;
 
     double *special_coul = force->special_coul;
     double *special_lj = force->special_lj;
@@ -153,18 +175,20 @@ void ComputeStressAtom::compute_peratom()
     int *type = atom->type;
     int nall = nlocal + atom->nghost;
 
-    for (i = 0; i < nlocal; i++) {
+    for (ii = 0; ii < inum; ii++) {
+      i = ilist[ii];
       xtmp = x[i][0];
       ytmp = x[i][1];
       ztmp = x[i][2];
       itype = type[i];
       iflag = mask[i] & groupbit;
-      neighs = neighbor->firstneigh[i];
-      numneigh = neighbor->numneigh[i];
-      
-      for (k = 0; k < numneigh; k++) {
-	j = neighs[k];
-	if (iflag == 0 && (mask[j] & groupbit) == 0) continue;
+      jlist = firstneigh[i];
+      jnum = numneigh[i];
+
+      for (jj = 0; jj < jnum; jj++) {
+	j = jlist[jj];
+	jflag = mask[j] & groupbit;
+	if (iflag == 0 && jflag == 0) continue;
 
 	if (j < nall) factor_coul = factor_lj = 1.0;
 	else {
@@ -183,13 +207,15 @@ void ComputeStressAtom::compute_peratom()
 	  force->pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,0,one);
 	  fforce = one.fforce;
 	  
-	  stress[i][0] -= delx*delx*fforce;
-	  stress[i][1] -= dely*dely*fforce;
-	  stress[i][2] -= delz*delz*fforce;
-	  stress[i][3] -= delx*dely*fforce;
-	  stress[i][4] -= delx*delz*fforce;
-	  stress[i][5] -= dely*delz*fforce;
-	  if (newton_pair || j < nlocal) {
+	  if (iflag) {
+	    stress[i][0] -= delx*delx*fforce;
+	    stress[i][1] -= dely*dely*fforce;
+	    stress[i][2] -= delz*delz*fforce;
+	    stress[i][3] -= delx*dely*fforce;
+	    stress[i][4] -= delx*delz*fforce;
+	    stress[i][5] -= dely*delz*fforce;
+	  }
+	  if (jflag && (newton_pair || j < nlocal)) {
 	    stress[j][0] -= delx*delx*fforce;
 	    stress[j][1] -= dely*dely*fforce;
 	    stress[j][2] -= delz*delz*fforce;
@@ -205,6 +231,7 @@ void ComputeStressAtom::compute_peratom()
 
   // compute bond stress for atoms via bond->single()
   // if neither atom is in compute group, skip that bond
+  // only add stress to atoms in group
 
   if (bondflag) {
     double **x = atom->x;
@@ -218,7 +245,9 @@ void ComputeStressAtom::compute_peratom()
       i1 = bondlist[n][0];
       i2 = bondlist[n][1];
       type = bondlist[n][2];
-      if ((mask[i1] & groupbit) == 0 && (mask[i2] & groupbit) == 0) continue;
+      iflag = mask[i1] & groupbit;
+      jflag = mask[i2] & groupbit;
+      if (iflag == 0 && jflag == 0) continue;
       
       delx = x[i1][0] - x[i2][0];
       dely = x[i1][1] - x[i2][1];
@@ -228,14 +257,16 @@ void ComputeStressAtom::compute_peratom()
       rsq = delx*delx + dely*dely + delz*delz;
       force->bond->single(type,rsq,i1,i2,0,fforce,eng);
       
-      stress[i1][0] -= delx*delx*fforce;
-      stress[i1][1] -= dely*dely*fforce;
-      stress[i1][2] -= delz*delz*fforce;
-      stress[i1][3] -= delx*dely*fforce;
-      stress[i1][4] -= delx*delz*fforce;
-      stress[i1][5] -= dely*delz*fforce;
-      
-      if (newton_bond || i2 < nlocal) {
+      if (iflag) {
+	stress[i1][0] -= delx*delx*fforce;
+	stress[i1][1] -= dely*dely*fforce;
+	stress[i1][2] -= delz*delz*fforce;
+	stress[i1][3] -= delx*dely*fforce;
+	stress[i1][4] -= delx*delz*fforce;
+	stress[i1][5] -= dely*delz*fforce;
+      }
+
+      if (jflag && (newton_bond || i2 < nlocal)) {
 	stress[i2][0] -= delx*delx*fforce;
 	stress[i2][1] -= dely*dely*fforce;
 	stress[i2][2] -= delz*delz*fforce;
diff --git a/src/compute_stress_atom.h b/src/compute_stress_atom.h
index 469fc331e30deeda5ae8ce9cbfa99e15fc7f6275..b936be80415446d9bbaf8fa04da058bb384efe9a 100644
--- a/src/compute_stress_atom.h
+++ b/src/compute_stress_atom.h
@@ -24,6 +24,7 @@ class ComputeStressAtom : public Compute {
   ComputeStressAtom(class LAMMPS *, int, char **);
   ~ComputeStressAtom();
   void init();
+  void init_list(int, class NeighList *);
   void compute_peratom();
   int pack_reverse_comm(int, int, double *);
   void unpack_reverse_comm(int, int *, double *);
@@ -33,7 +34,7 @@ class ComputeStressAtom : public Compute {
   int pairrequest,bondrequest,kerequest;
   int pairflag,bondflag;
   int nmax;
-
+  class NeighList *list;
   double **stress;
 };
 
diff --git a/src/delete_atoms.cpp b/src/delete_atoms.cpp
index 081741541a6d8102e64fb54f651bf68180a2d2ea..4fcc982956f50f3a76a9ec56dc9461ffdeb1348e 100644
--- a/src/delete_atoms.cpp
+++ b/src/delete_atoms.cpp
@@ -22,6 +22,8 @@
 #include "group.h"
 #include "region.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "comm.h"
 #include "force.h"
 #include "error.h"
@@ -53,15 +55,15 @@ void DeleteAtoms::command(int narg, char **arg)
   // allocate and initialize deletion list
   
   int nlocal = atom->nlocal;
-  int *list = new int[nlocal];
+  int *dlist = new int[nlocal];
 
-  for (int i = 0; i < nlocal; i++) list[i] = 0;
+  for (int i = 0; i < nlocal; i++) dlist[i] = 0;
 
   // delete the atoms
 
-  if (strcmp(arg[0],"group") == 0) delete_group(narg,arg,list);
-  else if (strcmp(arg[0],"region") == 0) delete_region(narg,arg,list);
-  else if (strcmp(arg[0],"overlap") == 0) delete_overlap(narg,arg,list);
+  if (strcmp(arg[0],"group") == 0) delete_group(narg,arg,dlist);
+  else if (strcmp(arg[0],"region") == 0) delete_region(narg,arg,dlist);
+  else if (strcmp(arg[0],"overlap") == 0) delete_overlap(narg,arg,dlist);
   else error->all("Illegal delete_atoms command");
 
   // delete local atoms in list
@@ -71,14 +73,14 @@ void DeleteAtoms::command(int narg, char **arg)
 
   int i = 0;
   while (i < nlocal) {
-    if (list[i]) {
+    if (dlist[i]) {
       avec->copy(nlocal-1,i);
-      list[i] = list[nlocal-1];
+      dlist[i] = dlist[nlocal-1];
       nlocal--;
     } else i++;
   }
   atom->nlocal = nlocal;
-  delete [] list;
+  delete [] dlist;
 
   // if non-molecular system, reset atom tags to be contiguous
   // set all atom IDs to 0, call tag_extend()
@@ -120,7 +122,7 @@ void DeleteAtoms::command(int narg, char **arg)
    group will still exist
 ------------------------------------------------------------------------- */
 
-void DeleteAtoms::delete_group(int narg, char **arg, int *list)
+void DeleteAtoms::delete_group(int narg, char **arg, int *dlist)
 {
   if (narg != 2) error->all("Illegal delete_atoms command");
 
@@ -132,14 +134,14 @@ void DeleteAtoms::delete_group(int narg, char **arg, int *list)
   int groupbit = group->bitmask[igroup];
 
   for (int i = 0; i < nlocal; i++)
-    if (mask[i] & groupbit) list[i] = 1;
+    if (mask[i] & groupbit) dlist[i] = 1;
 }
 
 /* ----------------------------------------------------------------------
    delete all atoms in region
 ------------------------------------------------------------------------- */
 
-void DeleteAtoms::delete_region(int narg, char **arg, int *list)
+void DeleteAtoms::delete_region(int narg, char **arg, int *dlist)
 {
   if (narg != 2) error->all("Illegal delete_atoms command");
   
@@ -150,7 +152,7 @@ void DeleteAtoms::delete_region(int narg, char **arg, int *list)
   int nlocal = atom->nlocal;
 
   for (int i = 0; i < nlocal; i++)
-    if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2])) list[i] = 1;
+    if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2])) dlist[i] = 1;
 }
 
 /* ----------------------------------------------------------------------
@@ -160,7 +162,7 @@ void DeleteAtoms::delete_region(int narg, char **arg, int *list)
    no guarantee that minimium number of atoms will be deleted
 ------------------------------------------------------------------------- */
 
-void DeleteAtoms::delete_overlap(int narg, char **arg, int *list)
+void DeleteAtoms::delete_overlap(int narg, char **arg, int *dlist)
 {
   if (narg < 2) error->all("Illegal delete_atoms command");
     
@@ -180,19 +182,29 @@ void DeleteAtoms::delete_overlap(int narg, char **arg, int *list)
     type2 = atoi(arg[3]);
   } else error->all("Illegal delete_atoms command");
 
-  // init entire system since comm->borders and neighbor->build is done
-  // comm::init needs neighbor::init needs pair::init needs kspace::init, etc
-  // set half_command since will require half neigh list even if
-  //   neighbor would otherwise not create one, then unset it
-
   if (comm->me == 0 && screen)
     fprintf(screen,"System init for delete_atoms ...\n");
-  neighbor->half_command = 1;
+
+  // request a half neighbor list for use by this command
+
+  int irequest = neighbor->request((void *) this);
+  neighbor->requests[irequest]->pair = 0;
+  neighbor->requests[irequest]->command = 1;
+  neighbor->requests[irequest]->occasional = 1;
+
+  // init entire system since comm->borders and neighbor->build is done
+  // comm::init needs neighbor::init needs pair::init needs kspace::init, etc
+  
   lmp->init();
-  neighbor->half_command = 0;
+
+  // error check on cutoff
+
+  if (cut > neighbor->cutghost) 
+    error->all("Delete_atoms cutoff > ghost cutoff");
 
   // setup domain, communication and neighboring
   // acquire ghosts
+  // build neighbor list based on earlier request
 
   if (domain->triclinic) domain->x2lamda(atom->nlocal);
   domain->pbc();
@@ -203,16 +215,8 @@ void DeleteAtoms::delete_overlap(int narg, char **arg, int *list)
   comm->borders();
   if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
 
-  // call to build() forces memory allocation for neighbor lists
-  // build half list explicitly if build() doesn't do it
-
-  neighbor->build();
-  if (!neighbor->half_every) neighbor->build_half();
-
-  // error check on cutoff
-
-  if (cut > neighbor->cutghost) 
-    error->all("Delete_atoms cutoff > ghost cutoff");
+  NeighList *list = neighbor->lists[irequest];
+  neighbor->build_one(irequest);
 
   // create an atom map if one doesn't exist already
 
@@ -245,30 +249,37 @@ void DeleteAtoms::delete_overlap(int narg, char **arg, int *list)
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
-  int i,j,k,m,itype,jtype,numneigh;
+  int i,j,ii,jj,m,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighs;
+  int *ilist,*jlist,*numneigh,**firstneigh;
+
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
-    
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
+
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
+
       if (j >= nall) {
 	if (special_coul[j/nall] == 0.0 && special_lj[j/nall] == 0.0) continue;
 	j %= nall;
       }
 
       if (j < nlocal) {
-	if (list[j]) continue;
+	if (dlist[j]) continue;
       } else {
 	m = atom->map(tag[j]);
-	if (m < nlocal && list[m]) continue;
+	if (m < nlocal && dlist[m]) continue;
       }
 
       delx = xtmp - x[j][0];
@@ -286,7 +297,7 @@ void DeleteAtoms::delete_overlap(int narg, char **arg, int *list)
 
       if (j >= nlocal && newton_pair == 0 && tag[j] < tag[i]) continue;
 
-      list[i] = 1;
+      dlist[i] = 1;
       break;
     }
   }
diff --git a/src/domain.cpp b/src/domain.cpp
index c4a69443eb24e7077de419c0ab517f98aea19de4..cece653486f5cb86e0805e442319618c455bf541 100644
--- a/src/domain.cpp
+++ b/src/domain.cpp
@@ -811,7 +811,7 @@ void Domain::set_boundary(int narg, char **arg)
    print box info, orthogonal or triclinic
 ------------------------------------------------------------------------- */
 
-void Domain::print_box(char *str)
+void Domain::print_box(const char *str)
 {
   if (comm->me == 0) {
     if (screen) {
@@ -819,7 +819,7 @@ void Domain::print_box(char *str)
 	fprintf(screen,"%sorthogonal box = (%g %g %g) to (%g %g %g)\n",
 		str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2]);
       else {
-	char *format = 
+	char *format = (char *)
 	  "%striclinic box = (%g %g %g) to (%g %g %g) with tilt (%g %g %g)\n";
 	fprintf(screen,format,
 		str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2],
@@ -831,7 +831,7 @@ void Domain::print_box(char *str)
 	fprintf(logfile,"%sorthogonal box = (%g %g %g) to (%g %g %g)\n",
 		str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2]);
       else {
-	char *format = 
+	char *format = (char *)
 	  "%striclinic box = (%g %g %g) to (%g %g %g) with tilt (%g %g %g)\n";
 	fprintf(logfile,format,
 		str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2],
diff --git a/src/domain.h b/src/domain.h
index 07b4d13594270136e15a1cc0ca636d9179c43639..a0bd61eec5984c0581f4adb9d5d6a98df7c1a96b 100644
--- a/src/domain.h
+++ b/src/domain.h
@@ -97,7 +97,7 @@ class Domain : protected Pointers {
   void add_region(int, char **);
   int find_region(char *);
   void set_boundary(int, char **);
-  void print_box(char *);
+  void print_box(const char *);
 
   void lamda2x(int);
   void x2lamda(int);
diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp
index 02bcd0836c47ee7c15161a011d348e778277a7b9..50aea9be29042a82c8e4f2a2fc402b83deb8889d 100644
--- a/src/dump_atom.cpp
+++ b/src/dump_atom.cpp
@@ -59,8 +59,8 @@ void DumpAtom::init()
     strcat(format,"\n");
   } else {
     char *str;
-    if (image_flag == 0) str = "%d %d %g %g %g";
-    else str = "%d %d %g %g %g %d %d %d";
+    if (image_flag == 0) str = (char *) "%d %d %g %g %g";
+    else str = (char *) "%d %d %g %g %g %d %d %d";
     int n = strlen(str) + 2;
     format = new char[n];
     strcpy(format,str);
diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp
index 3561aea034a2983d8a3ba743c330b5b76b88a2ee..a167a5e3ce841c5646f017a258d3c9143e9cf524 100644
--- a/src/dump_custom.cpp
+++ b/src/dump_custom.cpp
@@ -22,6 +22,7 @@
 #include "update.h"
 #include "modify.h"
 #include "compute.h"
+#include "fix.h"
 #include "memory.h"
 #include "error.h"
 
@@ -33,8 +34,7 @@ enum{TAG,MOL,TYPE,X,Y,Z,XS,YS,ZS,XU,YU,ZU,IX,IY,IZ,
      VX,VY,VZ,FX,FY,FZ,
      Q,MUX,MUY,MUZ,
      QUATW,QUATI,QUATJ,QUATK,TQX,TQY,TQZ,
-     EPAIR,EBOND,KE,ETOTAL,CENTRO,SXX,SYY,SZZ,SXY,SXZ,SYZ,
-     COMPUTE};
+     COMPUTE,FIX};
 enum{LT,LE,GT,GE,EQ,NEQ};
 enum{INT,DOUBLE};
 
@@ -45,6 +45,8 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) :
 {
   if (narg == 5) error->all("No dump custom arguments specified");
 
+  nevery = atoi(arg[3]);
+
   size_one = nfield = narg-5;
   pack_choice = new FnPtrPack[nfield];
   vtype = new int[nfield];
@@ -55,17 +57,7 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) :
   thresh_op = NULL;
   thresh_value = NULL;
 
-  // flags, IDs, and memory for compute objects dump may create
-
-  index_epair = index_ebond = index_ke = 
-    index_etotal = index_centro = index_stress = -1;
-
-  style_epair = "epair/atom";
-  style_ebond = "ebond/atom";
-  style_ke = "ke/atom";
-  style_etotal = "etotal/atom";
-  style_centro = "centro/atom";
-  style_stress = "stress/atom";
+  // compute and fix objects dump may create
 
   ncompute = 0;
   id_compute = NULL;
@@ -74,19 +66,16 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) :
 					  "dump:field2compute");
   arg_compute = (int *) memory->smalloc(nfield*sizeof(int),"dump:arg_compute");
 
+  nfix = 0;
+  id_fix = NULL;
+  fix = NULL;
+  field2fix = (int *) memory->smalloc(nfield*sizeof(int),"dump:field2fix");
+  arg_fix = (int *) memory->smalloc(nfield*sizeof(int),"dump:arg_fix");
+
   // process keywords
 
   parse_fields(narg,arg);
 
-  // create the requested Computes
-
-  if (index_epair >= 0) create_compute(style_epair,NULL);
-  if (index_ebond >= 0) create_compute(style_ebond,NULL);
-  if (index_ke >= 0) create_compute(style_ke,NULL);
-  if (index_etotal >= 0) create_compute(style_etotal,style_epair);
-  if (index_centro >= 0) create_compute(style_centro,NULL);
-  if (index_stress >= 0) create_compute(style_stress,NULL);
-
   // atom selection arrays
 
   maxlocal = 0;
@@ -122,21 +111,18 @@ DumpCustom::~DumpCustom()
   memory->sfree(thresh_op);
   memory->sfree(thresh_value);
 
-  // delete Compute classes if dump custom created them
-
-  if (index_epair >= 0)  modify->delete_compute(id_compute[index_epair]);
-  if (index_ebond >= 0)  modify->delete_compute(id_compute[index_ebond]);
-  if (index_ke >= 0)  modify->delete_compute(id_compute[index_ke]);
-  if (index_etotal >= 0)  modify->delete_compute(id_compute[index_etotal]);
-  if (index_centro >= 0)  modify->delete_compute(id_compute[index_centro]);
-  if (index_stress >= 0)  modify->delete_compute(id_compute[index_stress]);
-
   for (int i = 0; i < ncompute; i++) delete [] id_compute[i];
   memory->sfree(id_compute);
   memory->sfree(compute);
   memory->sfree(field2compute);
   memory->sfree(arg_compute);
 
+  for (int i = 0; i < nfix; i++) delete [] id_fix[i];
+  memory->sfree(id_fix);
+  memory->sfree(fix);
+  memory->sfree(field2fix);
+  memory->sfree(arg_fix);
+
   delete [] choose;
   delete [] dchoose;
 
@@ -177,7 +163,8 @@ void DumpCustom::init()
   if (binary) write_choice = &DumpCustom::write_binary;
   else write_choice = &DumpCustom::write_text;
 
-  // find current ptr for each Compute ID
+  // find current ptr for each compute and fix ID
+  // check that fix frequency is acceptable
 
   int icompute;
   for (int i = 0; i < ncompute; i++) {
@@ -185,6 +172,15 @@ void DumpCustom::init()
     if (icompute < 0) error->all("Could not find dump custom compute ID");
     compute[i] = modify->compute[icompute];
   }
+
+  int ifix;
+  for (int i = 0; i < nfix; i++) {
+    ifix = modify->find_fix(id_fix[i]);
+    if (ifix < 0) error->all("Could not find dump custom fix ID");
+    fix[i] = modify->fix[ifix];
+    if (nevery % modify->fix[ifix]->peratom_freq)
+      error->all("Dump custom and fix not computed at compatible times");
+  }
 }
 
 /* ---------------------------------------------------------------------- */
@@ -431,39 +427,7 @@ int DumpCustom::count()
       } else if (thresh_array[ithresh] == TQZ) {
 	ptr = &atom->torque[0][2];
 	nstride = 3;
-      } else if (thresh_array[ithresh] == EPAIR) {
-	ptr = compute[index_epair]->scalar_atom;
-	nstride = 1;
-      } else if (thresh_array[ithresh] == EBOND) {
-	ptr = compute[index_ebond]->scalar_atom;
-	nstride = 1;
-      } else if (thresh_array[ithresh] == KE) {
-	ptr = compute[index_ke]->scalar_atom;
-	nstride = 1;
-      } else if (thresh_array[ithresh] == ETOTAL) {
-	ptr = compute[index_etotal]->scalar_atom;
-	nstride = 1;
-      } else if (thresh_array[ithresh] == CENTRO) {
-	ptr = compute[index_centro]->scalar_atom;
-	nstride = 1;
-      } else if (thresh_array[ithresh] == SXX) {
-	ptr = &compute[index_stress]->vector_atom[0][0];
-	nstride = 6;
-      } else if (thresh_array[ithresh] == SYY) {
-	ptr = &compute[index_stress]->vector_atom[0][1];
-	nstride = 6;
-      } else if (thresh_array[ithresh] == SZZ) {
-	ptr = &compute[index_stress]->vector_atom[0][2];
-	nstride = 6;
-      } else if (thresh_array[ithresh] == SXY) {
-	ptr = &compute[index_stress]->vector_atom[0][3];
-	nstride = 6;
-      } else if (thresh_array[ithresh] == SXZ) {
-	ptr = &compute[index_stress]->vector_atom[0][4];
-	nstride = 6;
-      } else if (thresh_array[ithresh] == SYZ) {
-	ptr = &compute[index_stress]->vector_atom[0][5];
-	nstride = 6;
+
       } else if (thresh_array[ithresh] == COMPUTE) {
 	i = nfield + ithresh;
 	if (arg_compute[i] == 0) {
@@ -473,6 +437,16 @@ int DumpCustom::count()
 	  ptr = &compute[field2compute[i]]->vector_atom[0][arg_compute[i]-1];
 	  nstride = compute[field2compute[i]]->size_peratom;
 	}
+
+      } else if (thresh_array[ithresh] == FIX) {
+	i = nfield + ithresh;
+	if (arg_fix[i] == 0) {
+	  ptr = fix[field2fix[i]]->scalar_atom;
+	  nstride = 1;
+	} else {
+	  ptr = &fix[field2fix[i]]->vector_atom[0][arg_fix[i]-1];
+	  nstride = fix[field2fix[i]]->size_peratom;
+	}
       }
 
       // unselect atoms that don't meet threshhold criterion
@@ -704,56 +678,9 @@ void DumpCustom::parse_fields(int narg, char **arg)
       pack_choice[i] = &DumpCustom::pack_tqz;
       vtype[i] = DOUBLE;
 
-    } else if (strcmp(arg[iarg],"epair") == 0) {
-      pack_choice[i] = &DumpCustom::pack_epair;
-      vtype[i] = DOUBLE;
-      index_epair = add_compute(style_epair,1);
-    } else if (strcmp(arg[iarg],"ebond") == 0) {
-      pack_choice[i] = &DumpCustom::pack_ebond;
-      vtype[i] = DOUBLE;
-      index_ebond = add_compute(style_ebond,1);
-    } else if (strcmp(arg[iarg],"ke") == 0) {
-      pack_choice[i] = &DumpCustom::pack_ke;
-      vtype[i] = DOUBLE;
-      index_ke = add_compute(style_ke,1);
-    } else if (strcmp(arg[iarg],"etotal") == 0) {
-      pack_choice[i] = &DumpCustom::pack_etotal;
-      vtype[i] = DOUBLE;
-      index_epair = add_compute(style_epair,1);
-      index_etotal = add_compute(style_etotal,1);
-    } else if (strcmp(arg[iarg],"centro") == 0) {
-      pack_choice[i] = &DumpCustom::pack_centro;
-      vtype[i] = DOUBLE;
-      index_centro = add_compute(style_centro,1);
-
-    } else if (strcmp(arg[iarg],"sxx") == 0) {
-      pack_choice[i] = &DumpCustom::pack_sxx;
-      vtype[i] = DOUBLE;
-      index_stress = add_compute(style_stress,1);
-    } else if (strcmp(arg[iarg],"syy") == 0) {
-      pack_choice[i] = &DumpCustom::pack_syy;
-      vtype[i] = DOUBLE;
-      index_stress = add_compute(style_stress,1);
-    } else if (strcmp(arg[iarg],"szz") == 0) {
-      pack_choice[i] = &DumpCustom::pack_szz;
-      vtype[i] = DOUBLE;
-      index_stress = add_compute(style_stress,1);
-    } else if (strcmp(arg[iarg],"sxy") == 0) {
-      pack_choice[i] = &DumpCustom::pack_sxy;
-      vtype[i] = DOUBLE;
-      index_stress = add_compute(style_stress,1);
-    } else if (strcmp(arg[iarg],"sxz") == 0) {
-      pack_choice[i] = &DumpCustom::pack_sxz;
-      vtype[i] = DOUBLE;
-      index_stress = add_compute(style_stress,1);
-    } else if (strcmp(arg[iarg],"syz") == 0) {
-      pack_choice[i] = &DumpCustom::pack_syz;
-      vtype[i] = DOUBLE;
-      index_stress = add_compute(style_stress,1);
-
     // compute value = c_ID
     // if no trailing [], then arg is set to 0, else arg is between []
-    // if Compute has pre-compute, first add it to list
+    // if Compute has pre-computes, first add them to list
 
     } else if (strncmp(arg[iarg],"c_",2) == 0) {
       pack_choice[i] = &DumpCustom::pack_compute;
@@ -782,9 +709,43 @@ void DumpCustom::parse_fields(int narg, char **arg)
       if (arg_compute[i] > 0 && 
 	  arg_compute[i] > modify->compute[n]->size_peratom)
 	error->all("Dump custom compute ID vector is not large enough");
-      if (modify->compute[n]->id_pre)
-	int tmp = add_compute(modify->compute[n]->id_pre,0);
-      field2compute[i] = add_compute(suffix,0);
+      if (modify->compute[n]->npre)
+	for (int ic = 0; ic < modify->compute[n]->npre; ic++)
+	  int tmp = add_compute(modify->compute[n]->id_pre[ic]);
+      field2compute[i] = add_compute(suffix);
+      delete [] suffix;
+      
+    // fix value = f_ID
+    // if no trailing [], then arg is set to 0, else arg is between []
+
+    } else if (strncmp(arg[iarg],"f_",2) == 0) {
+      pack_choice[i] = &DumpCustom::pack_fix;
+      vtype[i] = DOUBLE;
+
+      int n = strlen(arg[iarg]);
+      char *suffix = new char[n];
+      strcpy(suffix,&arg[iarg][2]);
+
+      char *ptr = strchr(suffix,'[');
+      if (ptr) {
+	if (suffix[strlen(suffix)-1] != ']')
+	  error->all("Invalid keyword in dump custom command");
+	arg_fix[i] = atoi(ptr+1);
+	*ptr = '\0';
+      } else arg_fix[i] = 0;
+
+      n = modify->find_fix(suffix);
+      if (n < 0) error->all("Could not find dump custom fix ID");
+      if (modify->fix[n]->peratom_flag == 0)
+	error->all("Dump custom fix ID does not compute peratom info");
+      if (arg_fix[i] == 0 && modify->fix[n]->size_peratom > 0)
+	error->all("Dump custom fix ID does not compute scalar per atom");
+      if (arg_fix[i] > 0 && modify->fix[n]->size_peratom == 0)
+	error->all("Dump custom fix ID does not compute vector per atom");
+      if (arg_fix[i] > 0 && 
+	  arg_fix[i] > modify->fix[n]->size_peratom)
+	error->all("Dump custom fix ID vector is not large enough");
+      field2fix[i] = add_fix(suffix);
       delete [] suffix;
 
     } else error->all("Invalid keyword in dump custom command");
@@ -792,76 +753,53 @@ void DumpCustom::parse_fields(int narg, char **arg)
 }
 
 /* ----------------------------------------------------------------------
-   add Compute to list of Compute objects to call
-   return index of where this Compute is in call list
-   compute ID = dump-ID + "_" + keyword if appendflag is set, else just keyword
-   if already in call list, do not add, just return index, else add to list
+   add Compute to list of Compute objects used by dump
+   return index of where this Compute is in list
+   if already in list, do not add, just return index, else add to list
 ------------------------------------------------------------------------- */
 
-int DumpCustom::add_compute(char *keyword, int appendflag)
+int DumpCustom::add_compute(char *id)
 {
-  int n = strlen(id) + strlen(keyword) + 2;
-  char *name = new char[n];
-  if (appendflag) {
-    strcpy(name,id);
-    strcat(name,"_");
-    strcat(name,keyword);
-  } else strcpy(name,keyword);
-
   int icompute;
   for (icompute = 0; icompute < ncompute; icompute++)
-    if (strcmp(name,id_compute[icompute]) == 0) break;
-  if (icompute < ncompute) {
-    delete [] name;
-    return icompute;
-  }
+    if (strcmp(id,id_compute[icompute]) == 0) break;
+  if (icompute < ncompute) return icompute;
   
   id_compute = (char **)
     memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),"dump:id_compute");
   compute = (Compute **) 
     memory->srealloc(compute,(ncompute+1)*sizeof(Compute *),"dump:compute");
 
-  n = strlen(name) + 1;
+  int n = strlen(id) + 1;
   id_compute[ncompute] = new char[n];
-  strcpy(id_compute[ncompute],name);
-  delete [] name;
+  strcpy(id_compute[ncompute],id);
   ncompute++;
   return ncompute-1;
 }
 
 /* ----------------------------------------------------------------------
-   create a compute
-   compute ID = dump-ID + "_" + keyword, compute style = keyword
-   pass additional extra arg to Modify::add_compute() if defined
+   add Fix to list of Fix objects used by dump
+   return index of where this Fix is in list
+   if already in list, do not add, just return index, else add to list
 ------------------------------------------------------------------------- */
 
-void DumpCustom::create_compute(char *keyword, char *extra)
+int DumpCustom::add_fix(char *id)
 {
-  int n = strlen(id) + strlen(keyword) + 2;
-  char *name = new char[n];
-  strcpy(name,id);
-  strcat(name,"_");
-  strcat(name,keyword);
-
-  char **newarg = new char*[4];
-  newarg[0] = name;
-  newarg[1] = group->names[igroup];
-  newarg[2] = keyword;
-
-  if (extra) {
-    n = strlen(id) + strlen(extra) + 2;
-    newarg[3] = new char[n];
-    strcpy(newarg[3],id);
-    strcat(newarg[3],"_");
-    strcat(newarg[3],extra);
-  } else newarg[3] = NULL;
-
-  if (extra) modify->add_compute(4,newarg);
-  else modify->add_compute(3,newarg);
-
-  delete [] name;
-  delete [] newarg[3];
-  delete [] newarg;
+  int ifix;
+  for (ifix = 0; ifix < nfix; ifix++)
+    if (strcmp(id,id_fix[ifix]) == 0) break;
+  if (ifix < nfix) return ifix;
+  
+  id_fix = (char **)
+    memory->srealloc(id_fix,(nfix+1)*sizeof(char *),"dump:id_fix");
+  fix = (Fix **)
+    memory->srealloc(fix,(nfix+1)*sizeof(Fix *),"dump:fix");
+
+  int n = strlen(id) + 1;
+  id_fix[nfix] = new char[n];
+  strcpy(id_fix[nfix],id);
+  nfix++;
+  return nfix-1;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -948,84 +886,14 @@ int DumpCustom::modify_param(int narg, char **arg)
     else if (strcmp(arg[1],"tqx") == 0) thresh_array[nthresh] = TQX;
     else if (strcmp(arg[1],"tqy") == 0) thresh_array[nthresh] = TQY;
     else if (strcmp(arg[1],"tqz") == 0) thresh_array[nthresh] = TQZ;
-    else if (strcmp(arg[1],"epair") == 0) {
-      thresh_array[nthresh] = EPAIR;
-      if (index_epair < 0) {
-	index_epair = add_compute(style_epair,1);
-	create_compute(style_epair,NULL);
-      }
-    } else if (strcmp(arg[1],"ebond") == 0) {
-      thresh_array[nthresh] = EBOND;
-      if (index_ebond < 0) {
-	index_ebond = add_compute(style_ebond,1);
-	create_compute(style_ebond,NULL);
-      }
-    } else if (strcmp(arg[1],"ke") == 0) {
-      thresh_array[nthresh] = KE;
-      if (index_ke < 0) {
-	index_ke = add_compute(style_ke,1);
-	create_compute(style_ke,NULL);
-      }
-    } else if (strcmp(arg[1],"etotal") == 0) {
-      thresh_array[nthresh] = ETOTAL;
-      if (index_etotal < 0) {
-	if (index_epair < 0) {
-	  index_epair = add_compute(style_epair,1);
-	  create_compute(style_epair,NULL);
-	}
-	index_etotal = add_compute(style_etotal,1);
-	create_compute(style_etotal,style_epair);
-      }
-    } else if (strcmp(arg[1],"centro") == 0) {
-      thresh_array[nthresh] = CENTRO;
-      if (index_centro < 0) {
-	index_centro = add_compute(style_centro,1);
-	create_compute(style_centro,NULL);
-      }
-    } else if (strcmp(arg[1],"sxx") == 0) {
-      thresh_array[nthresh] = SXX;
-      if (index_stress < 0) {
-	index_stress = add_compute(style_stress,1);
-	create_compute(style_stress,NULL);
-      }
-    } else if (strcmp(arg[1],"syy") == 0) {
-      thresh_array[nthresh] = SYY;
-      if (index_stress < 0) {
-	index_stress = add_compute(style_stress,1);
-	create_compute(style_stress,NULL);
-      }
-    } else if (strcmp(arg[1],"szz") == 0) {
-      thresh_array[nthresh] = SZZ;
-      if (index_stress < 0) {
-	index_stress = add_compute(style_stress,1);
-	create_compute(style_stress,NULL);
-      }
-    } else if (strcmp(arg[1],"sxy") == 0) {
-      thresh_array[nthresh] = SXY;
-      if (index_stress < 0) {
-	index_stress = add_compute(style_stress,1);
-	create_compute(style_stress,NULL);
-      }
-    } else if (strcmp(arg[1],"sxz") == 0) {
-      thresh_array[nthresh] = SXZ;
-      if (index_stress < 0) {
-	index_stress = add_compute(style_stress,1);
-	create_compute(style_stress,NULL);
-      }
-    } else if (strcmp(arg[1],"syz") == 0) {
-      thresh_array[nthresh] = SYZ;
-      if (index_stress < 0) {
-	index_stress = add_compute(style_stress,1);
-	create_compute(style_stress,NULL);
-      }
     
     // compute value = c_ID
     // if no trailing [], then arg is set to 0, else arg is between []
     // must grow field2compute and arg_compute arrays,
     //   since access is beyond nfield
-    // if Compute has pre-compute, first add it to list
+    // if Compute has pre-computes, first add them to list
 
-    } else if (strncmp(arg[1],"c_",2) == 0) {
+    else if (strncmp(arg[1],"c_",2) == 0) {
       thresh_array[nthresh] = COMPUTE;
       field2compute = (int *) memory->srealloc(field2compute,
 					       (nfield+nthresh+1)*sizeof(int),
@@ -1059,9 +927,52 @@ int DumpCustom::modify_param(int narg, char **arg)
       if (arg_compute[nfield+nthresh] > 0 && 
 	  arg_compute[nfield+nthresh] > modify->compute[n]->size_peratom)
 	error->all("Dump custom compute ID vector is not large enough");
-      if (modify->compute[n]->id_pre)
-	int tmp = add_compute(modify->compute[n]->id_pre,0);
-      field2compute[nfield+nthresh] = add_compute(suffix,0);
+      if (modify->compute[n]->npre)
+	for (int ic = 0; ic < modify->compute[n]->npre; ic++)
+	  int tmp = add_compute(modify->compute[n]->id_pre[ic]);
+      field2compute[nfield+nthresh] = add_compute(suffix);
+      delete [] suffix;
+
+    // fix value = f_ID
+    // if no trailing [], then arg is set to 0, else arg is between []
+    // must grow field2compute and arg_compute arrays,
+    //   since access is beyond nfield
+
+    } else if (strncmp(arg[1],"f_",2) == 0) {
+      thresh_array[nthresh] = FIX;
+      field2fix = (int *) memory->srealloc(field2fix,
+					   (nfield+nthresh+1)*sizeof(int),
+					   "dump:field2fix");
+      arg_fix = (int *) memory->srealloc(arg_fix,
+					 (nfield+nthresh+1)*sizeof(int),
+					 "dump:arg_fix");
+      int n = strlen(arg[1]);
+      char *suffix = new char[n];
+      strcpy(suffix,&arg[1][2]);
+    
+      char *ptr = strchr(suffix,'[');
+      if (ptr) {
+	if (suffix[strlen(suffix)-1] != ']')
+	  error->all("Invalid keyword in dump custom command");
+	arg_fix[nfield+nthresh] = atoi(ptr+1);
+	*ptr = '\0';
+      } else arg_fix[nfield+nthresh] = 0;
+      
+      n = modify->find_fix(suffix);
+      if (n < 0) error->all("Could not find dump custom fix ID");
+
+      if (modify->fix[n]->peratom_flag == 0)
+	error->all("Dump custom fix ID does not compute peratom info");
+      if (arg_fix[nfield+nthresh] == 0 && 
+	  modify->fix[n]->size_peratom > 0)
+	error->all("Dump custom fix ID does not compute scalar per atom");
+      if (arg_fix[nfield+nthresh] > 0 && 
+	  modify->fix[n]->size_peratom == 0)
+	error->all("Dump custom fix ID does not compute vector per atom");
+      if (arg_fix[nfield+nthresh] > 0 && 
+	  arg_fix[nfield+nthresh] > modify->fix[n]->size_peratom)
+	error->all("Dump custom fix ID vector is not large enough");
+      field2fix[nfield+nthresh] = add_fix(suffix);
       delete [] suffix;
 
     } else error->all("Invalid dump_modify threshhold operator");
@@ -1083,6 +994,7 @@ int DumpCustom::modify_param(int narg, char **arg)
     nthresh++;
     return 4;
   }
+
   return 0;
 }
 
@@ -1106,31 +1018,6 @@ int DumpCustom::memory_usage()
 
 /* ---------------------------------------------------------------------- */
 
-void DumpCustom::pack_compute(int n)
-{
-  double *vector = compute[field2compute[n]]->scalar_atom;
-  double **array = compute[field2compute[n]]->vector_atom;
-  int index = arg_compute[n];
-  int nlocal = atom->nlocal;
-
-  if (index == 0) {
-    for (int i = 0; i < nlocal; i++)
-      if (choose[i]) {
-	buf[n] = vector[i];
-	n += size_one;
-      }
-  } else {
-    index--;
-    for (int i = 0; i < nlocal; i++)
-      if (choose[i]) {
-	buf[n] = array[i][index];
-	n += size_one;
-      }
-  }
-}
-
-/* ---------------------------------------------------------------------- */
-
 void DumpCustom::pack_tag(int n)
 {
   int *tag = atom->tag;
@@ -1594,154 +1481,50 @@ void DumpCustom::pack_tqz(int n)
 
 /* ---------------------------------------------------------------------- */
 
-void DumpCustom::pack_epair(int n)
-{
-  double *epair = compute[index_epair]->scalar_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = epair[i];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_ebond(int n)
-{
-  double *ebond = compute[index_ebond]->scalar_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = ebond[i];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_ke(int n)
-{
-  double *ke = compute[index_ke]->scalar_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = ke[i];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_etotal(int n)
-{
-  double *etotal = compute[index_etotal]->scalar_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = etotal[i];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_centro(int n)
-{
-  double *centro = compute[index_centro]->scalar_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = centro[i];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_sxx(int n)
-{
-  double **stress = compute[index_stress]->vector_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = stress[i][0];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_syy(int n)
-{
-  double **stress = compute[index_stress]->vector_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = stress[i][1];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_szz(int n)
-{
-  double **stress = compute[index_stress]->vector_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = stress[i][2];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_sxy(int n)
-{
-  double **stress = compute[index_stress]->vector_atom;
-  int nlocal = atom->nlocal;
-
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = stress[i][3];
-      n += size_one;
-    }
-}
-
-/* ---------------------------------------------------------------------- */
-
-void DumpCustom::pack_sxz(int n)
+void DumpCustom::pack_compute(int n)
 {
-  double **stress = compute[index_stress]->vector_atom;
+  double *vector = compute[field2compute[n]]->scalar_atom;
+  double **array = compute[field2compute[n]]->vector_atom;
+  int index = arg_compute[n];
   int nlocal = atom->nlocal;
 
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = stress[i][4];
-      n += size_one;
-    }
+  if (index == 0) {
+    for (int i = 0; i < nlocal; i++)
+      if (choose[i]) {
+	buf[n] = vector[i];
+	n += size_one;
+      }
+  } else {
+    index--;
+    for (int i = 0; i < nlocal; i++)
+      if (choose[i]) {
+	buf[n] = array[i][index];
+	n += size_one;
+      }
+  }
 }
 
 /* ---------------------------------------------------------------------- */
 
-void DumpCustom::pack_syz(int n)
+void DumpCustom::pack_fix(int n)
 {
-  double **stress = compute[index_stress]->vector_atom;
+  double *vector = fix[field2fix[n]]->scalar_atom;
+  double **array = fix[field2fix[n]]->vector_atom;
+  int index = arg_fix[n];
   int nlocal = atom->nlocal;
 
-  for (int i = 0; i < nlocal; i++)
-    if (choose[i]) {
-      buf[n] = stress[i][5];
-      n += size_one;
-    }
+  if (index == 0) {
+    for (int i = 0; i < nlocal; i++)
+      if (choose[i]) {
+	buf[n] = vector[i];
+	n += size_one;
+      }
+  } else {
+    index--;
+    for (int i = 0; i < nlocal; i++)
+      if (choose[i]) {
+	buf[n] = array[i][index];
+	n += size_one;
+      }
+  }
 }
diff --git a/src/dump_custom.h b/src/dump_custom.h
index 501a9fa03ee98d8e00bda487b444042f54e176c7..878f7c6a45d4bcb8c376adb2e16d7ad00421fc71 100644
--- a/src/dump_custom.h
+++ b/src/dump_custom.h
@@ -26,6 +26,7 @@ class DumpCustom : public Dump {
   int memory_usage();
 
  private:
+  int nevery;                // dump frequency to check Fix against
   int iregion;               // -1 if no region, else which region
   int nthresh;               // # of defined threshholds
   int *thresh_array;         // array to threshhhold on for each nthresh
@@ -41,18 +42,20 @@ class DumpCustom : public Dump {
   double *dchoose;           // value for each atom to threshhold against
 
   int nfield;                // # of keywords listed by user
-  int ncompute;              // # of Compute objects called by dump
+
+  int ncompute;              // # of Compute objects used by dump
   char **id_compute;         // their IDs
   class Compute **compute;   // list of ptrs to the Compute objects
-  int *field2compute;        // which Compute computes this field
+  int *field2compute;        // which Compute calculates this field
   int *arg_compute;          // index into Compute scalar_atom,vector_atom
                              // 0 for scalar_atom, 1-N for vector_atom values
 
-                             // index = where keyword's Compute is in list
-                             // style = style of Compute object
-  int index_epair,index_ebond,index_ke,index_etotal,index_centro,index_stress;
-  char *style_epair,*style_ebond,*style_ke,*style_etotal;
-  char *style_centro,*style_stress;
+  int nfix;                  // # of Fix objects used by dump
+  char **id_fix;             // their IDs
+  class Fix **fix;           // list of ptrs to the Fix objects
+  int *field2fix;            // which Fix calculates this field
+  int *arg_fix;              // index into Fix scalar_atom,vector_atom
+                             // 0 for scalar_atom, 1-N for vector_atom values
 
   // private methods
 
@@ -62,8 +65,8 @@ class DumpCustom : public Dump {
   void write_data(int, double *);
 
   void parse_fields(int, char **);
-  int add_compute(char *, int);
-  void create_compute(char *, char *);
+  int add_compute(char *);
+  int add_fix(char *);
   int modify_param(int, char **);
 
   typedef void (DumpCustom::*FnPtrHeader)(int);
@@ -81,8 +84,6 @@ class DumpCustom : public Dump {
   typedef void (DumpCustom::*FnPtrPack)(int);
   FnPtrPack *pack_choice;              // ptrs to pack functions
 
-  void pack_compute(int);
-
   void pack_tag(int);
   void pack_molecule(int);
   void pack_type(int);
@@ -115,17 +116,9 @@ class DumpCustom : public Dump {
   void pack_tqx(int);
   void pack_tqy(int);
   void pack_tqz(int);
-  void pack_etotal(int);
-  void pack_ke(int);
-  void pack_epair(int);
-  void pack_ebond(int);
-  void pack_centro(int);
-  void pack_sxx(int);
-  void pack_syy(int);
-  void pack_szz(int);
-  void pack_sxy(int);
-  void pack_sxz(int);
-  void pack_syz(int);
+
+  void pack_compute(int);
+  void pack_fix(int);
 };
 
 }
diff --git a/src/dump_dcd.cpp b/src/dump_dcd.cpp
index 92c5a3382c86ce6030299e124feb6b7b47a9a88c..701cb050b02abe446620bcce1417f73cc544c359 100644
--- a/src/dump_dcd.cpp
+++ b/src/dump_dcd.cpp
@@ -245,7 +245,7 @@ void DumpDCD::write_frame()
 
 /* ---------------------------------------------------------------------- */
 
-void DumpDCD::write_dcd_header(char *remarks)
+void DumpDCD::write_dcd_header(const char *remarks)
 {
   uint32_t out_integer;
   float out_float;
diff --git a/src/dump_dcd.h b/src/dump_dcd.h
index f190eb1432b70f7136ea8ddbbb681217803e9b74..defd52fc46f959c745ca57b24f2dbc673208f627 100644
--- a/src/dump_dcd.h
+++ b/src/dump_dcd.h
@@ -38,7 +38,7 @@ class DumpDCD : public Dump {
   void write_data(int, double *);
 
   void write_frame();
-  void write_dcd_header(char *);
+  void write_dcd_header(const char *);
   void fwrite_int32(FILE *, uint32_t);
 };
 
diff --git a/src/dump_xyz.cpp b/src/dump_xyz.cpp
index 5a5ba59974b3df3222ed373d2e5fdf21af7bcc66..4c8b9ab9acaacd6e88da33818c33dd3db5afd9c6 100644
--- a/src/dump_xyz.cpp
+++ b/src/dump_xyz.cpp
@@ -29,7 +29,7 @@ DumpXYZ::DumpXYZ(LAMMPS *lmp, int narg, char **arg) : Dump(lmp, narg, arg)
 
   size_one = 5;
 
-  char *str = "%d %g %g %g";
+  char *str = (char *) "%d %g %g %g";
   int n = strlen(str) + 1;
   format_default = new char[n];
   strcpy(format_default,str);
diff --git a/src/error.cpp b/src/error.cpp
index 8307760aefc3b3bc0870c7cbb8d83297fe4ed9e2..b63b8a895ec58c9ebcb6251102fa4ea72dd50e3f 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -29,7 +29,7 @@ Error::Error(LAMMPS *lmp) : Pointers(lmp) {}
    close all output, screen, and log files in world and universe
 ------------------------------------------------------------------------- */
 
-void Error::universe_all(char *str)
+void Error::universe_all(const char *str)
 {
   MPI_Barrier(universe->uworld);
 
@@ -53,7 +53,7 @@ void Error::universe_all(char *str)
    called by one proc in universe
 ------------------------------------------------------------------------- */
 
-void Error::universe_one(char *str)
+void Error::universe_one(const char *str)
 {
   if (universe->uscreen)
     fprintf(universe->uscreen,"ERROR on proc %d: %s\n",universe->me,str);
@@ -65,7 +65,7 @@ void Error::universe_one(char *str)
    close all output, screen, and log files in world
 ------------------------------------------------------------------------- */
 
-void Error::all(char *str)
+void Error::all(const char *str)
 {
   MPI_Barrier(world);
 
@@ -91,7 +91,7 @@ void Error::all(char *str)
    always write to universe screen 
 ------------------------------------------------------------------------- */
 
-void Error::one(char *str)
+void Error::one(const char *str)
 {
   int me;
   MPI_Comm_rank(world,&me);
@@ -106,7 +106,7 @@ void Error::one(char *str)
    only write to screen if non-NULL on this proc since could be file 
 ------------------------------------------------------------------------- */
 
-void Error::warning(char *str)
+void Error::warning(const char *str)
 {
   if (screen) fprintf(screen,"WARNING: %s\n",str);
 }
diff --git a/src/error.h b/src/error.h
index 248ecdd6049de04196c8978316496de88f5ad7cc..b6c1d53f80739e04df96b1344f4d02be8b5f1ff7 100644
--- a/src/error.h
+++ b/src/error.h
@@ -22,12 +22,12 @@ class Error : protected Pointers {
  public:
   Error(class LAMMPS *);
 
-  void universe_all(char *);
-  void universe_one(char *);
+  void universe_all(const char *);
+  void universe_one(const char *);
 
-  void all(char *);
-  void one(char *);
-  void warning(char *);
+  void all(const char *);
+  void one(const char *);
+  void warning(const char *);
 };
 
 }
diff --git a/src/finish.cpp b/src/finish.cpp
index 8af0f57743fcd2b503476f8dad268d74a175c415..09441d4ff4a988fbacbfacb8c4229893a32963d6 100644
--- a/src/finish.cpp
+++ b/src/finish.cpp
@@ -23,6 +23,8 @@
 #include "update.h"
 #include "min.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "output.h"
 #include "memory.h"
 
@@ -36,7 +38,7 @@ Finish::Finish(LAMMPS *lmp) : Pointers(lmp) {}
 
 void Finish::end(int flag)
 {
-  int i;
+  int i,m;
   int histo[10];
   double time,tmp,ave,max,min;
 
@@ -291,11 +293,17 @@ void Finish::end(int flag)
     }
   }
 
+  // find a half non-skip neighbor list
+
+  for (m = 0; m < neighbor->old_nrequest; m++)
+    if ((neighbor->old_requests[m]->half || 
+	neighbor->old_requests[m]->half_from_full) &&
+	neighbor->old_requests[m]->skip == 0) break;
+
   int nneigh = 0;
-  if (neighbor->half_every)
-    for (i = 0; i < atom->nlocal; i++) nneigh += neighbor->numneigh[i];
-  else if (neighbor->full_every)
-    for (i = 0; i < atom->nlocal; i++) nneigh += neighbor->numneigh_full[i];
+  if (m < neighbor->old_nrequest)
+    for (i = 0; i < atom->nlocal; i++)
+      nneigh += neighbor->lists[m]->numneigh[i];
 
   tmp = nneigh;
   stats(1,&tmp,&ave,&max,&min,10,histo);
@@ -314,10 +322,17 @@ void Finish::end(int flag)
     }
   }
 
-  if (neighbor->half_every && neighbor->full_every) {
+  // find a full non-skip neighbor list
+
+  for (m = 0; m < neighbor->old_nrequest; m++)
+    if (neighbor->old_requests[m]->full &&
+	neighbor->old_requests[m]->skip == 0) break;
+
+  if (m < neighbor->old_nrequest) {
 
     nneigh = 0;
-    for (i = 0; i < atom->nlocal; i++) nneigh += neighbor->numneigh_full[i];
+    for (i = 0; i < atom->nlocal; i++)
+      nneigh += neighbor->lists[m]->numneigh[i];
 
     tmp = nneigh;
     stats(1,&tmp,&ave,&max,&min,10,histo);
diff --git a/src/fix.cpp b/src/fix.cpp
index 1a50c866433814908a038740b22a9c0a176ab69d..ae48cf47646db052568c0ef20bdd71519021641a 100644
--- a/src/fix.cpp
+++ b/src/fix.cpp
@@ -42,10 +42,9 @@ Fix::Fix(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
   rigid_flag = 0;
   virial_flag = 0;
   no_change_box = 0;
+  peratom_flag = 0;
 
   comm_forward = comm_reverse = 0;
-  neigh_half_once = neigh_half_every = 0;
-  neigh_full_once = neigh_full_every = 0;
 
   // mask settings - same as in modify.cpp
 
diff --git a/src/fix.h b/src/fix.h
index 9d1fc93cfd3306ab6391bf20a44c3f9b9c041186..e43ce3c72c57563404de70acf4ac268435656bf1 100644
--- a/src/fix.h
+++ b/src/fix.h
@@ -35,12 +35,14 @@ class Fix : protected Pointers {
   int virial_flag;               // 1 if Fix contributes to virial, 0 if not
   int no_change_box;             // 1 if cannot swap ortho <-> triclinic
 
+  int peratom_flag;              // 0/1 if per-atom data is stored
+  int size_peratom;              // 0 = scalar_atom, N = size of vector_atom
+  double *scalar_atom;           // computed per-atom scalar
+  double **vector_atom;          // computed per-atom vector
+  int peratom_freq;              // frequency per-atom data is available at
+
   int comm_forward;              // size of forward communication (0 if none)
   int comm_reverse;              // size of reverse communication (0 if none)
-  int neigh_half_once;           // 0/1 if needs half neigh list occasionally
-  int neigh_half_every;          // 0/1 if needs half neigh list every step
-  int neigh_full_once;           // 0/1 if needs full neigh list occasionally
-  int neigh_full_every;          // 0/1 if needs full neigh list every step
 
   double virial[6];              // fix contribution to pressure virial
 
@@ -56,6 +58,7 @@ class Fix : protected Pointers {
   virtual int setmask() = 0;
 
   virtual void init() {}
+  virtual void init_list(int, class NeighList *) {}
   virtual void setup() {}
   virtual void min_setup() {}
   virtual void initial_integrate() {}
diff --git a/src/fix_ave_spatial.cpp b/src/fix_ave_spatial.cpp
index a7ef8d40e5ca1b47384af41adca4bc6f2a51b960..f9697c053bb2505069888e999618d5f4b670712c 100644
--- a/src/fix_ave_spatial.cpp
+++ b/src/fix_ave_spatial.cpp
@@ -31,7 +31,7 @@
 using namespace LAMMPS_NS;
 
 enum{LOWER,CENTER,UPPER,COORD};
-enum{DENSITY_MASS,DENSITY_NUM,VX,VY,VZ,FX,FY,FZ,COMPUTE};
+enum{DENSITY_MASS,DENSITY_NUM,COMPUTE,FIX};
 enum{SAMPLE,ALL};
 enum{BOX,LATTICE,REDUCED};
 
@@ -40,56 +40,51 @@ enum{BOX,LATTICE,REDUCED};
 FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) :
   Fix(lmp, narg, arg)
 {
-  if (narg < 11) error->all("Illegal fix ave/spatial command");
+  if (narg < 12) error->all("Illegal fix ave/spatial command");
 
   no_change_box = 1;
 
   nevery = atoi(arg[3]);
-  nfreq = atoi(arg[4]);
+  nrepeat = atoi(arg[4]);
+  nfreq = atoi(arg[5]);
 
-  if (strcmp(arg[5],"x") == 0) dim = 0;
-  else if (strcmp(arg[5],"y") == 0) dim = 1;
-  else if (strcmp(arg[5],"z") == 0) dim = 2;
+  if (strcmp(arg[6],"x") == 0) dim = 0;
+  else if (strcmp(arg[6],"y") == 0) dim = 1;
+  else if (strcmp(arg[6],"z") == 0) dim = 2;
   else error->all("Illegal fix ave/spatial command");
 
-  if (strcmp(arg[6],"lower") == 0) originflag = LOWER;
-  if (strcmp(arg[6],"center") == 0) originflag = CENTER;
-  if (strcmp(arg[6],"upper") == 0) originflag = UPPER;
+  if (strcmp(arg[7],"lower") == 0) originflag = LOWER;
+  if (strcmp(arg[7],"center") == 0) originflag = CENTER;
+  if (strcmp(arg[7],"upper") == 0) originflag = UPPER;
   else originflag = COORD;
   if (originflag == COORD) origin = atof(arg[6]);
 
-  delta = atof(arg[7]);
+  delta = atof(arg[8]);
 
   MPI_Comm_rank(world,&me);
   if (me == 0) {
-    fp = fopen(arg[8],"w");
+    fp = fopen(arg[9],"w");
     if (fp == NULL) {
       char str[128];
-      sprintf(str,"Cannot open fix ave/spatial file %s",arg[8]);
+      sprintf(str,"Cannot open fix ave/spatial file %s",arg[9]);
       error->one(str);
     }
   }
 
-  if (strcmp(arg[9],"density") == 0) {
-    if (strcmp(arg[10],"mass") == 0) which = DENSITY_MASS;
-    else if (strcmp(arg[10],"number") == 0) which = DENSITY_NUM;
+  if (strcmp(arg[10],"density") == 0) {
+    if (strcmp(arg[11],"mass") == 0) which = DENSITY_MASS;
+    else if (strcmp(arg[11],"number") == 0) which = DENSITY_NUM;
     else error->all("Illegal fix ave/spatial command");
-
-  } else if (strcmp(arg[9],"atom") == 0) {
-    if (strcmp(arg[10],"vx") == 0) which = VX;
-    else if (strcmp(arg[10],"vy") == 0) which = VY;
-    else if (strcmp(arg[10],"vz") == 0) which = VZ;
-    else if (strcmp(arg[10],"fx") == 0) which = FX;
-    else if (strcmp(arg[10],"fy") == 0) which = FY;
-    else if (strcmp(arg[10],"fz") == 0) which = FZ;
-    else error->all("Illegal fix ave/spatial command");
-
-  } else if (strcmp(arg[9],"compute") == 0) {
+  } else if (strcmp(arg[10],"compute") == 0) {
     which = COMPUTE;
-    int n = strlen(arg[10]) + 1;
+    int n = strlen(arg[11]) + 1;
     id_compute = new char[n];
-    strcpy(id_compute,arg[10]);
-
+    strcpy(id_compute,arg[11]);
+  } else if (strcmp(arg[10],"fix") == 0) {
+    which = FIX;
+    int n = strlen(arg[11]) + 1;
+    id_fix = new char[n];
+    strcpy(id_fix,arg[11]);
   } else error->all("Illegal fix ave/spatial command");
 
   // parse optional args
@@ -97,7 +92,7 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) :
   normflag = ALL;
   scaleflag = BOX;
 
-  int iarg = 11;
+  int iarg = 12;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"norm") == 0) {
       if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
@@ -149,34 +144,61 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) :
   // setup and error check
 
   if (nevery <= 0) error->all("Illegal fix ave/spatial command");
-  if (nfreq < nevery || nfreq % nevery)
+  if (nfreq < nevery || nfreq % nevery || (nrepeat-1)*nevery >= nfreq)
     error->all("Illegal fix ave/spatial command");
 
   if (delta <= 0.0) error->all("Illegal fix ave/spatial command");
   invdelta = 1.0/delta;
 
+  // nvalues = # of quantites per line of output file
+  // for COMPUTE, setup list of computes to call, including pre-computes
+
   nvalues = 1;
+  compute = NULL;
+
   if (which == COMPUTE) {
     int icompute = modify->find_compute(id_compute);
     if (icompute < 0)
       error->all("Compute ID for fix ave/spatial does not exist");
     if (modify->compute[icompute]->peratom_flag == 0)
       error->all("Fix ave/spatial compute does not calculate per-atom info");
-    nvalues = compute_size_peratom = modify->compute[icompute]->size_peratom;
+    nvalues = size_peratom = modify->compute[icompute]->size_peratom;
     if (nvalues == 0) nvalues = 1;
+    ncompute = 1 + modify->compute[icompute]->npre;
+    compute = new Compute*[ncompute];
   }
 
+  if (which == FIX) {
+    int ifix = modify->find_fix(id_fix);
+    if (ifix < 0)
+      error->all("Fix ID for fix ave/spatial does not exist");
+    if (modify->fix[ifix]->peratom_flag == 0)
+      error->all("Fix ave/spatial fix does not calculate per-atom info");
+    nvalues = size_peratom = modify->fix[ifix]->size_peratom;
+    if (nvalues == 0) nvalues = 1;
+  }
+
+  // print header into file
+
   if (me == 0) {
     fprintf(fp,"Spatial-averaged data for fix %s, group %s, and %s %s\n",
-	    id,group->names[igroup],arg[9],arg[10]);
+	    id,group->names[igroup],arg[10],arg[11]);
     fprintf(fp,"TimeStep Number-of-layers (one per snapshot)\n");
     fprintf(fp,"Layer Coord Atoms Value(s) (one per layer)\n");
   }
   
-  nsum = nlayers = maxlayer = 0;
+  nlayers = maxlayer = 0;
   coord = NULL;
   count_one = count_many = count_total = NULL;
   values_one = values_many = values_total = NULL;
+
+  // nvalid = next step on which end_of_step does something
+
+  irepeat = 0;
+  nvalid = (update->ntimestep/nfreq)*nfreq + nfreq;
+  nvalid -= (nrepeat-1)*nevery;
+  if (nvalid <= update->ntimestep)
+    error->all("Fix ave/spatial cannot be started on this timestep");
 }
 
 /* ---------------------------------------------------------------------- */
@@ -184,8 +206,11 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) :
 FixAveSpatial::~FixAveSpatial()
 {
   if (which == COMPUTE) delete [] id_compute;
+  if (which == FIX) delete [] id_fix;
   if (me == 0) fclose(fp);
 
+  delete [] compute;
+
   memory->sfree(coord);
   memory->sfree(count_one);
   memory->sfree(count_many);
@@ -208,21 +233,37 @@ int FixAveSpatial::setmask()
 
 void FixAveSpatial::init()
 {
-  // set ptrs to current compute and precompute
+  // set ptrs to one or more computes called each end-of-step
 
   if (which == COMPUTE) {
     int icompute = modify->find_compute(id_compute);
-    if (icompute < 0) 
+    if (icompute < 0)
       error->all("Compute ID for fix ave/spatial does not exist");
-    compute = modify->compute[icompute];
     
-    if (compute->id_pre) {
-      icompute = modify->find_compute(compute->id_pre);
-      if (icompute < 0)
-	error->all("Precompute ID for fix ave/spatial does not exist");
-      precompute = modify->compute[icompute];
-    } else precompute = NULL;
+    ncompute = 0;
+    if (modify->compute[icompute]->npre)
+      for (int i = 0; i < modify->compute[icompute]->npre; i++) {
+	int ic = modify->find_compute(modify->compute[icompute]->id_pre[i]);
+	if (ic < 0)
+	  error->all("Precompute ID for fix ave/spatial does not exist");
+	compute[ncompute++] = modify->compute[ic];
+      }
+    
+    compute[ncompute++] = modify->compute[icompute];
+  }
+
+  // set ptr to fix ID
+  // check that fix frequency is acceptable
+
+  if (which == FIX) {
+    int ifix = modify->find_fix(id_fix);
+    if (ifix < 0) 
+      error->all("Fix ID for fix ave/spatial does not exist");
+    fix = modify->fix[ifix];
+    if (nevery % modify->fix[ifix]->peratom_freq)
+      error->all("Fix ave/spatial and fix not computed at compatible times");
   }
+
 }
 
 /* ---------------------------------------------------------------------- */
@@ -232,13 +273,17 @@ void FixAveSpatial::end_of_step()
   int i,j,m,ilayer;
   double lo,hi;
 
+  // skip if not step which requires doing something
+
+  if (update->ntimestep != nvalid) return;
+
   // if computing the first sample, setup layers
   // compute current origin = boundary for some layer
   // lo = layer boundary immediately below boxlo
   // hi = layer boundary immediately above boxhi
   // allocate and initialize arrays based on new layer count
 
-  if (nsum == 0) {
+  if (irepeat == 0) {
     double *boxlo,*boxhi,*prd;
     if (scaleflag == REDUCED) {
       boxlo = domain->boxlo_lamda;
@@ -306,7 +351,6 @@ void FixAveSpatial::end_of_step()
   
   // zero out arrays for one sample
 
-  nsum++;
   for (m = 0; m < nlayers; m++) {
     count_one[m] = 0.0;
     for (i = 0; i < nvalues; i++) values_one[m][i] = 0.0;
@@ -361,17 +405,12 @@ void FixAveSpatial::end_of_step()
 
     if (scaleflag == REDUCED) domain->lamda2x(nlocal);
 
-  // ATOM (VX,FX,etc) adds atom attribute to values
+  // COMPUTE adds its scalar or vector quantity to values
 
-  } else if (which != COMPUTE) {
-    double *vector;
-    int nstride = 3;
-    if (which == VX) vector = &atom->v[0][0];
-    else if (which == VY) vector = &atom->v[0][1];
-    else if (which == VZ) vector = &atom->v[0][2];
-    else if (which == FX) vector = &atom->f[0][0];
-    else if (which == FY) vector = &atom->f[0][1];
-    else if (which == FZ) vector = &atom->f[0][2];
+  } else if (which == COMPUTE) {
+    for (i = 0; i < ncompute; i++) compute[i]->compute_peratom();
+    double *scalar = compute[ncompute-1]->scalar_atom;
+    double **vector = compute[ncompute-1]->vector_atom;
 
     if (scaleflag == REDUCED) domain->x2lamda(nlocal);
 
@@ -382,20 +421,20 @@ void FixAveSpatial::end_of_step()
 	if (ilayer < 0) ilayer = 0;
 	if (ilayer >= nlayers) ilayer = nlayers-1;
 	count_one[ilayer] += 1.0;
-	values_one[ilayer][0] += vector[m];
+	if (size_peratom == 0) values_one[ilayer][0] += scalar[i];
+	else
+	  for (j = 0; j < nvalues; j++)
+	    values_one[ilayer][j] += vector[i][j];
       }
-      m += nstride;
     }
 
     if (scaleflag == REDUCED) domain->lamda2x(nlocal);
 
-  // COMPUTE adds its compute scalar or vector quantity to values
+  // FIX adds its scalar or vector quantity to values
 
-  } else {
-    if (precompute) precompute->compute_peratom();
-    compute->compute_peratom();
-    double *scalar = compute->scalar_atom;
-    double **vector = compute->vector_atom;
+  } else if (which == FIX) {
+    double *scalar = fix->scalar_atom;
+    double **vector = fix->vector_atom;
 
     if (scaleflag == REDUCED) domain->x2lamda(nlocal);
 
@@ -406,7 +445,7 @@ void FixAveSpatial::end_of_step()
 	if (ilayer < 0) ilayer = 0;
 	if (ilayer >= nlayers) ilayer = nlayers-1;
 	count_one[ilayer] += 1.0;
-	if (compute_size_peratom == 0) values_one[ilayer][0] += scalar[i];
+	if (size_peratom == 0) values_one[ilayer][0] += scalar[i];
 	else
 	  for (j = 0; j < nvalues; j++)
 	    values_one[ilayer][j] += vector[i][j];
@@ -434,11 +473,19 @@ void FixAveSpatial::end_of_step()
     }
   }
 
+  // update counters
+
+  irepeat++;
+  nvalid += nevery;
+
   // output the results
   // time average across samples
   // if density, also normalize by volume
+  // reset irepeat and nvalid
+
+  if (irepeat == nrepeat) {
+    double repeat = nrepeat;
 
-  if (update->ntimestep % nfreq == 0) {
     if (normflag == ALL) {
       MPI_Allreduce(count_many,count_total,nlayers,MPI_DOUBLE,MPI_SUM,world);
       MPI_Allreduce(&values_many[0][0],&values_total[0][0],nlayers*nvalues,
@@ -447,15 +494,15 @@ void FixAveSpatial::end_of_step()
 	if (count_total[m] > 0.0)
 	  for (j = 0; j < nvalues; j++)
 	    values_total[m][j] /= count_total[m];
-	count_total[m] /= nsum;
+	count_total[m] /= repeat;
       }
     } else {
       MPI_Allreduce(&values_many[0][0],&values_total[0][0],nlayers*nvalues,
 		    MPI_DOUBLE,MPI_SUM,world);
       for (m = 0; m < nlayers; m++) {
 	for (j = 0; j < nvalues; j++)
-	  values_total[m][j] /= nsum;
-	count_total[m] /= nsum;
+	  values_total[m][j] /= repeat;
+	count_total[m] /= repeat;
       }
     }
 
@@ -474,6 +521,7 @@ void FixAveSpatial::end_of_step()
       fflush(fp);
     }
 
-    nsum = 0;
+    irepeat = 0;
+    nvalid = update->ntimestep+nfreq - (nrepeat-1)*nevery;
  }
 }
diff --git a/src/fix_ave_spatial.h b/src/fix_ave_spatial.h
index 2e23ac782133d7db612195a336683b6aca4ff516..9c9cff604c429054ab714b39d4da80ed8747b793 100644
--- a/src/fix_ave_spatial.h
+++ b/src/fix_ave_spatial.h
@@ -29,22 +29,22 @@ class FixAveSpatial : public Fix {
 
  private:
   int me;
-  int nfreq;
+  int nrepeat,nfreq,irepeat,nvalid;
   int dim,originflag,which,normflag;
   double origin,delta;
-  char *id_compute;
+  char *id_compute,*id_fix;
   FILE *fp;
 
-  int nlayers,nvalues,nsum,maxlayer,scaleflag;
-  int compute_size_peratom;
+  int nlayers,nvalues,maxlayer,scaleflag,size_peratom;
   double xscale,yscale,zscale;
   double layer_volume;
   double *coord;
   double *count_one,*count_many,*count_total;
   double **values_one,**values_many,**values_total;
   double offset,invdelta; 
-  class Compute *compute;
-  class Compute *precompute;
+  int ncompute;
+  class Compute **compute;
+  class Fix *fix;
 };
 
 }
diff --git a/src/fix_ave_time.cpp b/src/fix_ave_time.cpp
index c0f1f1569019ffbd0bd48908012d1416a9e7e960..ac8f7b1adf53700362095137d1d36dbd0ec2f91e 100644
--- a/src/fix_ave_time.cpp
+++ b/src/fix_ave_time.cpp
@@ -31,23 +31,24 @@ using namespace LAMMPS_NS;
 FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
   Fix(lmp, narg, arg)
 {
-  if (narg != 8) error->all("Illegal fix ave/time command");
+  if (narg != 9) error->all("Illegal fix ave/time command");
 
   nevery = atoi(arg[3]);
-  nfreq = atoi(arg[4]);
+  nrepeat = atoi(arg[4]);
+  nfreq = atoi(arg[5]);
 
-  int n = strlen(arg[5]) + 1;
+  int n = strlen(arg[6]) + 1;
   id_compute = new char[n];
-  strcpy(id_compute,arg[5]);
+  strcpy(id_compute,arg[6]);
 
-  int flag = atoi(arg[6]);
+  int flag = atoi(arg[7]);
 
   MPI_Comm_rank(world,&me);
   if (me == 0) {
-    fp = fopen(arg[7],"w");
+    fp = fopen(arg[8],"w");
     if (fp == NULL) {
       char str[128];
-      sprintf(str,"Cannot open fix ave/time file %s",arg[7]);
+      sprintf(str,"Cannot open fix ave/time file %s",arg[8]);
       error->one(str);
     }
   }
@@ -55,7 +56,7 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
   // setup and error check
 
   if (nevery <= 0) error->all("Illegal fix ave/time command");
-  if (nfreq < nevery || nfreq % nevery)
+  if (nfreq < nevery || nfreq % nevery || (nrepeat-1)*nevery >= nfreq)
     error->all("Illegal fix ave/time command");
 
   int icompute = modify->find_compute(id_compute);
@@ -73,6 +74,13 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
 
   if (modify->compute[icompute]->pressflag) pressure_every = nevery;
 
+  // setup list of computes to call, including pre-computes
+
+  ncompute = 1 + modify->compute[icompute]->npre;
+  compute = new Compute*[ncompute];
+
+  // print header into file
+
   if (me == 0) {
     fprintf(fp,"Time-averaged data for fix %s, group %s, and compute %s\n",
 	    id,group->names[modify->compute[icompute]->igroup],id_compute);
@@ -84,14 +92,19 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
       fprintf(fp,"TimeStep Scalar-value Vector-values\n");
   }
 
-  nsum = 0;
-  scalar = 0.0;
   vector = NULL;
   if (vflag) {
     size_vector = modify->compute[icompute]->size_vector;
     vector = new double[size_vector];
-    for (int i = 0; i < size_vector; i++) vector[i] = 0.0;
   }
+
+  // nvalid = next step on which end_of_step does something
+
+  irepeat = 0;
+  nvalid = (update->ntimestep/nfreq)*nfreq + nfreq;
+  nvalid -= (nrepeat-1)*nevery;
+  if (nvalid <= update->ntimestep)
+    error->all("Fix ave/time cannot be started on this timestep");
 }
 
 /* ---------------------------------------------------------------------- */
@@ -100,6 +113,7 @@ FixAveTime::~FixAveTime()
 {
   delete [] id_compute;
   if (me == 0) fclose(fp);
+  delete [] compute;
   delete [] vector;
 }
 
@@ -116,18 +130,22 @@ int FixAveTime::setmask()
 
 void FixAveTime::init()
 {
-  // set ptrs to current compute and precompute
+  // set ptrs to one or more computes called each end-of-step
 
   int icompute = modify->find_compute(id_compute);
-  if (icompute < 0) error->all("Compute ID for fix ave/time does not exist");
-  compute = modify->compute[icompute];
-
-  if (compute->id_pre) {
-    icompute = modify->find_compute(compute->id_pre);
-    if (icompute < 0)
-      error->all("Precompute ID for fix ave/time does not exist");
-    precompute = modify->compute[icompute];
-  } else precompute = NULL;
+  if (icompute < 0)
+    error->all("Compute ID for fix ave/time does not exist");
+  
+  ncompute = 0;
+  if (modify->compute[icompute]->npre)
+    for (int i = 0; i < modify->compute[icompute]->npre; i++) {
+      int ic = modify->find_compute(modify->compute[icompute]->id_pre[i]);
+      if (ic < 0)
+	error->all("Precompute ID for fix ave/time does not exist");
+      compute[ncompute++] = modify->compute[ic];
+    }
+  
+  compute[ncompute++] = modify->compute[icompute];
 }
 
 /* ---------------------------------------------------------------------- */
@@ -136,32 +154,50 @@ void FixAveTime::end_of_step()
 {
   int i;
 
-  if (precompute) {
-    if (sflag) double tmp = precompute->compute_scalar();
-    if (vflag) precompute->compute_vector();
+  // skip if not step which requires doing something
+
+  if (update->ntimestep != nvalid) return;
+
+  // zero if first step
+
+  if (irepeat == 0) {
+    scalar = 0.0;
+    if (vflag) 
+      for (i = 0; i < size_vector; i++) vector[i] = 0.0;
   }
 
-  nsum++;
-  if (sflag) scalar += compute->compute_scalar();
+  // accumulate results of compute to local copy
+  
+  if (sflag) {
+    double value;
+    for (i = 0; i < ncompute; i++) value = compute[i]->compute_scalar();
+    scalar += value;
+  }
   if (vflag) {
-    compute->compute_vector();
-    double *cvector = compute->vector;
+    for (i = 0; i < ncompute; i++) compute[i]->compute_vector();
+    double *cvector = compute[ncompute-1]->vector;
     for (i = 0; i < size_vector; i++) vector[i] += cvector[i];
   }
 
-  if (update->ntimestep % nfreq == 0) {
+  irepeat++;
+  nvalid += nevery;
+
+  // output the results
+  // reset irepeat and nvalid
+
+  if (irepeat == nrepeat) {
+    double repeat = nrepeat;
+
     if (me == 0) {
       fprintf(fp,"%d",update->ntimestep);
-      if (sflag) fprintf(fp," %g",scalar/nsum);
+      if (sflag) fprintf(fp," %g",scalar/repeat);
       if (vflag)
-	for (i = 0; i < size_vector; i++) fprintf(fp," %g",vector[i]/nsum);
+	for (i = 0; i < size_vector; i++) fprintf(fp," %g",vector[i]/repeat);
       fprintf(fp,"\n");
       fflush(fp);
     }
 
-    nsum = 0;
-    scalar = 0.0;
-    if (vflag) 
-      for (i = 0; i < size_vector; i++) vector[i] = 0.0;
- }
+    irepeat = 0;
+    nvalid = update->ntimestep+nfreq - (nrepeat-1)*nevery;
+  }
 }
diff --git a/src/fix_ave_time.h b/src/fix_ave_time.h
index 8c732064d956c88e137e8f72f8fcf3f3fa0cf014..01fb897c483582b521818f0effc049dab55f5825 100644
--- a/src/fix_ave_time.h
+++ b/src/fix_ave_time.h
@@ -29,16 +29,15 @@ class FixAveTime : public Fix {
 
  private:
   int me;
-
-  int nfreq;
+  int nrepeat,nfreq,nvalid,irepeat;
   char *id_compute;
   FILE *fp;
 
   int sflag,vflag;
   int size_vector,nsum;
   double scalar,*vector;
-  class Compute *compute;
-  class Compute *precompute;
+  int ncompute;
+  class Compute **compute;
 };
 
 }
diff --git a/src/fix_nph.cpp b/src/fix_nph.cpp
index f9fc6e70873cd1d52fd6613e2d4fbbee51c03ca5..d8b2076d8851c72c7524553627526212618a6d18 100644
--- a/src/fix_nph.cpp
+++ b/src/fix_nph.cpp
@@ -162,8 +162,8 @@ FixNPH::FixNPH(LAMMPS *lmp, int narg, char **arg) :
 
   char **newarg = new char*[3];
   newarg[0] = id_temp;
-  newarg[1] = "all";
-  newarg[2] = "temp";
+  newarg[1] = (char *) "all";
+  newarg[2] = (char *) "temp";
   modify->add_compute(3,newarg);
   delete [] newarg;
   tflag = 1;
@@ -179,8 +179,8 @@ FixNPH::FixNPH(LAMMPS *lmp, int narg, char **arg) :
 
   newarg = new char*[4];
   newarg[0] = id_press;
-  newarg[1] = "all";
-  newarg[2] = "pressure";
+  newarg[1] = (char *) "all";
+  newarg[2] = (char *) "pressure";
   newarg[3] = id_temp;
   modify->add_compute(4,newarg);
   delete [] newarg;
@@ -231,7 +231,7 @@ void FixNPH::init()
     error->all("Cannot use fix nph without per-type mass defined");
 
   // set temperature and pressure ptrs
-  // set ptemperature only if pressure's id_pre is not id_temp
+  // set ptemperature only if pressure's id_pre[0] is not id_temp
 
   int icompute = modify->find_compute(id_temp);
   if (icompute < 0) error->all("Temp ID for fix nph does not exist");
@@ -241,9 +241,9 @@ void FixNPH::init()
   if (icompute < 0) error->all("Press ID for fix nph does not exist");
   pressure = modify->compute[icompute];
 
-  if (strcmp(id_temp,pressure->id_pre) == 0) ptemperature = NULL;
+  if (strcmp(id_temp,pressure->id_pre[0]) == 0) ptemperature = NULL;
   else {
-    icompute = modify->find_compute(pressure->id_pre);
+    icompute = modify->find_compute(pressure->id_pre[0]);
     if (icompute < 0)
       error->all("Temp ID of press ID for fix nph does not exist");
     ptemperature = modify->compute[icompute];
@@ -733,13 +733,13 @@ int FixNPH::modify_param(int narg, char **arg)
     if (temperature->igroup != 0 && comm->me == 0)
       error->warning("Temperature for NPH is not for group all");
 
-    // reset id_pre of pressure to new temp ID
+    // reset id_pre[0] of pressure to new temp ID
     
     icompute = modify->find_compute(id_press);
     if (icompute < 0) error->all("Press ID for fix npt does not exist");
-    delete [] modify->compute[icompute]->id_pre;
-    modify->compute[icompute]->id_pre = new char[n];
-    strcpy(modify->compute[icompute]->id_pre,id_temp);
+    delete [] modify->compute[icompute]->id_pre[0];
+    modify->compute[icompute]->id_pre[0] = new char[n];
+    strcpy(modify->compute[icompute]->id_pre[0],id_temp);
 
     return 2;
 
diff --git a/src/fix_npt.cpp b/src/fix_npt.cpp
index 6b2c6f2b99bd6d193db19f851b87a5e68e5bd1b1..f57df6fc25743dae32a7cc71626ad1580a84c3d7 100644
--- a/src/fix_npt.cpp
+++ b/src/fix_npt.cpp
@@ -169,9 +169,10 @@ FixNPT::FixNPT(LAMMPS *lmp, int narg, char **arg) :
 
   char **newarg = new char*[3];
   newarg[0] = id_temp;
-  newarg[1] = "all";
-  if (strcmp(style,"npt") == 0) newarg[2] = "temp";
-  else if (strcmp(style,"npt/asphere") == 0) newarg[2] = "temp/asphere";
+  newarg[1] = (char *) "all";
+  if (strcmp(style,"npt") == 0) newarg[2] = (char *) "temp";
+  else if (strcmp(style,"npt/asphere") == 0)
+    newarg[2] = (char *) "temp/asphere";
   modify->add_compute(3,newarg);
   delete [] newarg;
   tflag = 1;
@@ -187,8 +188,8 @@ FixNPT::FixNPT(LAMMPS *lmp, int narg, char **arg) :
 
   newarg = new char*[4];
   newarg[0] = id_press;
-  newarg[1] = "all";
-  newarg[2] = "pressure";
+  newarg[1] = (char *) "all";
+  newarg[2] = (char *) "pressure";
   newarg[3] = id_temp;
   modify->add_compute(4,newarg);
   delete [] newarg;
@@ -240,7 +241,7 @@ void FixNPT::init()
     error->all("Cannot use fix npt without per-type mass defined");
 
   // set temperature and pressure ptrs
-  // set ptemperature only if pressure's id_pre is not id_temp
+  // set ptemperature only if pressure's id_pre[0] is not id_temp
 
   int icompute = modify->find_compute(id_temp);
   if (icompute < 0) error->all("Temp ID for fix npt does not exist");
@@ -250,9 +251,9 @@ void FixNPT::init()
   if (icompute < 0) error->all("Press ID for fix npt does not exist");
   pressure = modify->compute[icompute];
 
-  if (strcmp(id_temp,pressure->id_pre) == 0) ptemperature = NULL;
+  if (strcmp(id_temp,pressure->id_pre[0]) == 0) ptemperature = NULL;
   else {
-    icompute = modify->find_compute(pressure->id_pre);
+    icompute = modify->find_compute(pressure->id_pre[0]);
     if (icompute < 0)
       error->all("Temp ID of press ID for fix npt does not exist");
     ptemperature = modify->compute[icompute];
@@ -761,13 +762,13 @@ int FixNPT::modify_param(int narg, char **arg)
     if (temperature->igroup != 0 && comm->me == 0)
       error->warning("Temperature for NPT is not for group all");
 
-    // reset id_pre of pressure to new temp ID
+    // reset id_pre[0] of pressure to new temp ID
     
     icompute = modify->find_compute(id_press);
     if (icompute < 0) error->all("Press ID for fix npt does not exist");
-    delete [] modify->compute[icompute]->id_pre;
-    modify->compute[icompute]->id_pre = new char[n];
-    strcpy(modify->compute[icompute]->id_pre,id_temp);
+    delete [] modify->compute[icompute]->id_pre[0];
+    modify->compute[icompute]->id_pre[0] = new char[n];
+    strcpy(modify->compute[icompute]->id_pre[0],id_temp);
 
     return 2;
 
diff --git a/src/fix_nvt.cpp b/src/fix_nvt.cpp
index 1d0cb9a8eab01bf75c0c843a2aefb24f3b8283ae..7a56cbd23b88728c98a44e87aa6b9b84c00afe92 100644
--- a/src/fix_nvt.cpp
+++ b/src/fix_nvt.cpp
@@ -69,9 +69,9 @@ FixNVT::FixNVT(LAMMPS *lmp, int narg, char **arg) :
   char **newarg = new char*[3];
   newarg[0] = id_temp;
   newarg[1] = group->names[igroup];
-  if (strcmp(style,"nvt") == 0) newarg[2] = "temp";
-  else if (strcmp(style,"nvt/asphere") == 0) newarg[2] = "temp/asphere";
-  else if (strcmp(style,"nvt/sllod") == 0) newarg[2] = "temp/deform";
+  if (strcmp(style,"nvt") == 0) newarg[2] = (char *) "temp";
+  else if (strcmp(style,"nvt/asphere") == 0) newarg[2] = (char *) "temp/asphere";
+  else if (strcmp(style,"nvt/sllod") == 0) newarg[2] = (char *) "temp/deform";
   modify->add_compute(3,newarg);
   delete [] newarg;
   tflag = 1;
diff --git a/src/fix_orient_fcc.cpp b/src/fix_orient_fcc.cpp
index 73b9f3b8958bec574ec5a20c374c5c1ca02015db..c4b9246179ddd69c7986f2f06d67031ec17dc5c3 100644
--- a/src/fix_orient_fcc.cpp
+++ b/src/fix_orient_fcc.cpp
@@ -24,6 +24,8 @@
 #include "update.h"
 #include "respa.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "comm.h"
 #include "output.h"
 #include "error.h"
@@ -44,8 +46,6 @@ FixOrientFCC::FixOrientFCC(LAMMPS *lmp, int narg, char **arg) :
 
   if (narg != 11) error->all("Illegal fix orient/fcc command");
 
-  neigh_full_every = 1;
-
   nstats = atoi(arg[3]);
   direction_of_motion = atoi(arg[4]);
   a = atof(arg[5]);
@@ -173,6 +173,21 @@ void FixOrientFCC::init()
 {
   if (strcmp(update->integrate_style,"respa") == 0)
     nlevels_respa = ((Respa *) update->integrate)->nlevels;
+
+  // need a full neighbor list, built when ever re-neighboring occurs
+
+  int irequest = neighbor->request((void *) this);
+  neighbor->requests[irequest]->pair = 0;
+  neighbor->requests[irequest]->fix = 1;
+  neighbor->requests[irequest]->half = 0;
+  neighbor->requests[irequest]->full = 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void FixOrientFCC::init_list(int id, NeighList *ptr)
+{
+  list = ptr;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -194,8 +209,8 @@ void FixOrientFCC::setup()
 
 void FixOrientFCC::post_force(int vflag)
 {
-  int i,j,k,m,n,nn,nsort,id_self;
-  int *neighs;
+  int i,j,k,ii,jj,inum,jnum,m,n,nn,nsort,id_self;
+  int *ilist,*jlist,*numneigh,**firstneigh;
   double edelta,added_energy,omega;
   double dx,dy,dz,rsq,xismooth,xi_sq,duxi,duxi_other;
   double dxi[3];
@@ -215,6 +230,11 @@ void FixOrientFCC::post_force(int vflag)
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+
   // insure nbr data structure is adequate size
 
   if (nall > nmax) {
@@ -231,15 +251,16 @@ void FixOrientFCC::post_force(int vflag)
   int mincount = BIG;
   int maxcount = 0;
 
-  for (i = 0; i < nlocal; i++) {
-    neighs = neighbor->firstneigh_full[i];
-    n = neighbor->numneigh_full[i];
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    if (n < mincount) mincount = n;
-    if (n > maxcount) {
+    if (jnum < mincount) mincount = jnum;
+    if (jnum > maxcount) {
       if (maxcount) delete [] sort;
-      sort = new Sort[n];
-      maxcount = n;
+      sort = new Sort[jnum];
+      maxcount = jnum;
     }
 
     // loop over all neighbors of atom i
@@ -247,8 +268,8 @@ void FixOrientFCC::post_force(int vflag)
     // store local id, rsq, delta vector, xismooth (if included)
 
     nsort = 0;
-    for (k = 0; k < n; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
       count++;
 
       dx = x[i][0] - x[j][0];
@@ -319,7 +340,8 @@ void FixOrientFCC::post_force(int vflag)
   // compute grain boundary force on each owned atom
   // skip atoms not in group
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     if (!(mask[i] & groupbit)) continue;
     n = nbr[i].n;
     duxi = nbr[i].duxi;
diff --git a/src/fix_orient_fcc.h b/src/fix_orient_fcc.h
index 9b34e41535fb9d703ba71853f6c1b49cc9a69dc0..a28f6181874323ecb3dbd2a09df9d5e0b13e3757 100644
--- a/src/fix_orient_fcc.h
+++ b/src/fix_orient_fcc.h
@@ -41,6 +41,7 @@ class FixOrientFCC : public Fix {
   ~FixOrientFCC();
   int setmask();
   void init();
+  void init_list(int, class NeighList *);
   void setup();
   void post_force(int);
   void post_force_respa(int, int, int);
@@ -70,6 +71,7 @@ class FixOrientFCC : public Fix {
 
   Nbr *nbr;
   Sort *sort;
+  class NeighList *list;
 
   void find_best_ref(double *, int, double &, double *);
   static int compare(const void *, const void *);
diff --git a/src/fix_rdf.cpp b/src/fix_rdf.cpp
index f671687baef9dbb50c031f4d514575fadd96decc..f39081ce470cc9513eda0cf052fd4c9a27cbac3f 100644
--- a/src/fix_rdf.cpp
+++ b/src/fix_rdf.cpp
@@ -27,6 +27,8 @@
 #include "group.h"
 #include "modify.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "pair.h"
 #include "force.h"
 #include "memory.h"
@@ -41,8 +43,6 @@ FixRDF::FixRDF(LAMMPS *lmp, int narg, char **arg) :
 {
   if (narg < 8 || (narg-6) % 2) error->all("Illegal fix rdf command");
 
-  neigh_half_once = 1;
-
   nevery = atoi(arg[3]);
   if (nevery <= 0) error->all("Illegal fix rdf command");
   first = 1;
@@ -129,6 +129,13 @@ void FixRDF::init()
   if (force->pair) delr = force->pair->cutforce / maxbin;
   else error->all("Fix rdf requires a pair style be defined");
 
+  // need an occasional half neighbor list
+
+  int irequest = neighbor->request((void *) this);
+  neighbor->requests[irequest]->pair = 0;
+  neighbor->requests[irequest]->fix = 1;
+  neighbor->requests[irequest]->occasional = 1;
+  
   delrinv = 1.0/delr;
   nframes = 0;
 
@@ -143,6 +150,14 @@ void FixRDF::init()
 	for (bin = 0; bin < maxbin; bin++)
           gr_ave[irdf][bin] = ncoord_ave[irdf][bin] = 0.0;         
       }
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+void FixRDF::init_list(int id, NeighList *ptr)
+{
+  list = ptr;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -166,13 +181,18 @@ void FixRDF::end_of_step()
   int nall = atom->nlocal + atom->nghost;
   int newton_pair = force->newton_pair;
 
-  int i,j,k,numneigh,itype,jtype,ipair,jpair,bin;
+  int i,j,ii,jj,inum,jnum,itype,jtype,ipair,jpair,bin;
   double xtmp,ytmp,ztmp,delx,dely,delz,r;
-  int *neighs;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
-  // if needed, build a half neighbor list
+  // invoke half neighbor list (will copy or build if necessary)
 
-  if (!neighbor->half_every) neighbor->build_half();
+  neighbor->build_one(list->index);
+
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
 
   // zero the histogram counts
 
@@ -188,17 +208,19 @@ void FixRDF::end_of_step()
   // count the interaction once even if neighbor pair is stored on 2 procs
   // if itype = jtype, count the interaction twice
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     if (mask[i] & groupbit) {
       xtmp = x[i][0];
       ytmp = x[i][1];
       ztmp = x[i][2];
       itype = type[i];
-      neighs = neighbor->firstneigh[i];
-      numneigh = neighbor->numneigh[i];
+      jlist = firstneigh[i];
+      jnum = numneigh[i];
+
+      for (jj = 0; jj < jnum; jj++) {
+	j = jlist[jj];
 
-      for (k = 0; k < numneigh; k++) {
-        j = neighs[k];
 	if (j >= nall) {
 	  if (special_coul[j/nall] == 0.0 && special_lj[j/nall] == 0.0)
 	    continue;
diff --git a/src/fix_rdf.h b/src/fix_rdf.h
index 47a3f97fc4ac4e46c8a1df0476faf2fbdff91e0b..4b2148402bd1771b97b785d58bd2127237990b56 100644
--- a/src/fix_rdf.h
+++ b/src/fix_rdf.h
@@ -25,6 +25,7 @@ class FixRDF : public Fix {
   ~FixRDF();
   int setmask();
   void init();
+  void init_list(int, class NeighList *);
   void setup();
   void end_of_step();
 
@@ -39,6 +40,7 @@ class FixRDF : public Fix {
   int **hist,**hist_all;	 // histogram bins
   int *nrdfatoms;             	 // # of atoms of each type in the group
   double **gr_ave,**ncoord_ave;  // accumulators for average rdf statistics
+  class NeighList *list;         // half neighbor list
 };
 
 }
diff --git a/src/fix_shear_history.cpp b/src/fix_shear_history.cpp
index cde7edcdadc9bb7532d0e1301ccb86f77ac1af9b..54956003efa3e3b2dbf5e00e8eb4c6fc4f362bc3 100644
--- a/src/fix_shear_history.cpp
+++ b/src/fix_shear_history.cpp
@@ -16,7 +16,9 @@
 #include "fix_shear_history.h"
 #include "atom.h"
 #include "neighbor.h"
+#include "neigh_list.h"
 #include "force.h"
+#include "pair.h"
 #include "update.h"
 #include "modify.h"
 #include "memory.h"
@@ -89,7 +91,10 @@ void FixShearHistory::init()
 
 void FixShearHistory::pre_exchange()
 {
-  int i,j,k,m;
+  int i,j,ii,jj,m,inum,jnum;
+  int *ilist,*jlist,*numneigh,**firstneigh;
+  int *touch,**firsttouch;
+  double *shear,*allshear,**firstshear;
 
   // zero npartners for all current atoms
 
@@ -97,24 +102,28 @@ void FixShearHistory::pre_exchange()
   for (i = 0; i < nlocal; i++) npartner[i] = 0;
 
   // copy shear info from neighbor list atoms to atom arrays
-  // nlocal = nlocal_neighbor = nlocal when neighbor list last built,
-  //   which might be pre-insert on this step
 
-  int numneigh;
-  int *neighs,*touch;
-  double *firstshear,*shear;
   int *tag = atom->tag;
-  nlocal = neighbor->nlocal_neighbor;
-
-  for (i = 0; i < nlocal; i++) {
-    neighs = neighbor->firstneigh[i];
-    touch = neighbor->firsttouch[i];
-    firstshear = neighbor->firstshear[i];
-    numneigh = neighbor->numneigh[i];
-    for (k = 0; k < numneigh; k++) {
-      if (touch[k]) {
-	shear = &firstshear[3*k];
-	j = neighs[k];
+
+  NeighList *list = pair->list;
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  firsttouch = list->listgranhistory->firstneigh;
+  firstshear = list->listgranhistory->firstdouble;
+
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
+    jlist = firstneigh[i];
+    allshear = firstshear[i];
+    jnum = numneigh[i];
+    touch = firsttouch[i];
+
+    for (jj = 0; jj < jnum; jj++) {
+      if (touch[jj]) {
+	shear = &allshear[3*jj];
+	j = jlist[jj];
 	if (npartner[i] < MAXTOUCH) {
 	  m = npartner[i];
 	  partner[i][m] = tag[j];
diff --git a/src/fix_shear_history.h b/src/fix_shear_history.h
index 7b2d7346b5cd962f9b9491ff16ae4dd5f9cd8b2c..054834f269bb67104b38f11ddb1e9192295a0ba0 100644
--- a/src/fix_shear_history.h
+++ b/src/fix_shear_history.h
@@ -20,6 +20,7 @@ namespace LAMMPS_NS {
 
 class FixShearHistory : public Fix {
   friend class Neighbor;
+  friend class PairGranHistory;
   friend class FixPour;
 
  public:
@@ -43,6 +44,8 @@ class FixShearHistory : public Fix {
   int *npartner;                // # of touching partners of each atom
   int **partner;                // tags for the partners
   double ***shearpartner;       // 3 shear values with the partner
+
+  class Pair *pair;
 };
 
 }
diff --git a/src/fix_temp_rescale.cpp b/src/fix_temp_rescale.cpp
index 05ecfe836da4778a0fa7f8415209452978d78531..7d5f20003062bdb2990e6eeb80c0342c18d8a015 100644
--- a/src/fix_temp_rescale.cpp
+++ b/src/fix_temp_rescale.cpp
@@ -86,20 +86,20 @@ FixTempRescale::FixTempRescale(LAMMPS *lmp, int narg, char **arg) :
   newarg[0] = id_temp;
   newarg[1] = group->names[igroup];
   if (type == STANDARD) {
-    newarg[2] = "temp";
+    newarg[2] = (char *) "temp";
     modify->add_compute(3,newarg);
   } else if (type == REGION) {
-    newarg[2] = "temp/region";
+    newarg[2] = (char *) "temp/region";
     newarg[3] = domain->regions[iregion]->id;
     modify->add_compute(4,newarg);
   } else if (type == PARTIAL) {
-    newarg[2] = "temp/partial";
-    if (xflag) newarg[3] = "1";
-    else newarg[3] = "0";
-    if (yflag) newarg[4] = "1";
-    else newarg[4] = "0";
-    if (zflag) newarg[5] = "1";
-    else newarg[5] = "0";
+    newarg[2] = (char *) "temp/partial";
+    if (xflag) newarg[3] = (char *) "1";
+    else newarg[3] = (char *) "0";
+    if (yflag) newarg[4] = (char *) "1";
+    else newarg[4] = (char *) "0";
+    if (zflag) newarg[5] = (char *) "1";
+    else newarg[5] = (char *) "0";
     modify->add_compute(6,newarg);
   }
   delete [] newarg;
diff --git a/src/force.cpp b/src/force.cpp
index 802c1061d214184f7492405d7c1138bef4b872c3..e7cf40ea41e94992014676510435212064db721e 100644
--- a/src/force.cpp
+++ b/src/force.cpp
@@ -65,7 +65,7 @@ Force::Force(LAMMPS *lmp) : Pointers(lmp)
   improper = NULL;
   kspace = NULL;
 
-  char *str = "none";
+  char *str = (char *) "none";
   int n = strlen(str) + 1;
   pair_style = new char[n];
   strcpy(pair_style,str);
@@ -120,7 +120,7 @@ void Force::init()
    create a pair style, called from input script or restart file
 ------------------------------------------------------------------------- */
 
-void Force::create_pair(char *style)
+void Force::create_pair(const char *style)
 {
   delete [] pair_style;
   if (pair) delete pair;
@@ -135,7 +135,7 @@ void Force::create_pair(char *style)
    generate a pair class
 ------------------------------------------------------------------------- */
 
-Pair *Force::new_pair(char *style)
+Pair *Force::new_pair(const char *style)
 {
   if (strcmp(style,"none") == 0) return NULL;
 
@@ -154,14 +154,21 @@ Pair *Force::new_pair(char *style)
    else return NULL
 ------------------------------------------------------------------------- */
 
-Pair *Force::pair_match(char *word)
+Pair *Force::pair_match(const char *word)
 {
   if (strstr(pair_style,word)) return pair;
   else if (strcmp(pair_style,"hybrid") == 0) {
-    PairHybrid *pair_hybrid = (PairHybrid *) pair;
-    for (int i = 0; i < pair_hybrid->nstyles; i++)
-      if (strstr(pair_hybrid->keywords[i],word))
-	return pair_hybrid->styles[i];
+    PairHybrid *hybrid = (PairHybrid *) pair;
+    for (int i = 0; i < hybrid->nstyles; i++) {
+      if (strstr(hybrid->keywords[i],word))
+	return hybrid->styles[i];
+    }
+  } else if (strcmp(pair_style,"hybrid/overlay") == 0) {
+    PairHybridOverlay *hybrid = (PairHybridOverlay *) pair;
+    for (int i = 0; i < hybrid->nstyles; i++) {
+      if (strstr(hybrid->keywords[i],word))
+	return hybrid->styles[i];
+    }
   }
   return NULL;
 }
@@ -170,7 +177,7 @@ Pair *Force::pair_match(char *word)
    create a bond style, called from input script or restart file
 ------------------------------------------------------------------------- */
 
-void Force::create_bond(char *style)
+void Force::create_bond(const char *style)
 {
   delete [] bond_style;
   if (bond) delete bond;
@@ -185,7 +192,7 @@ void Force::create_bond(char *style)
    generate a bond class
 ------------------------------------------------------------------------- */
 
-Bond *Force::new_bond(char *style)
+Bond *Force::new_bond(const char *style)
 {
   if (strcmp(style,"none") == 0) return NULL;
 
@@ -203,13 +210,13 @@ Bond *Force::new_bond(char *style)
    return ptr to current bond class or hybrid sub-class if matches style
 ------------------------------------------------------------------------- */
 
-Bond *Force::bond_match(char *style)
+Bond *Force::bond_match(const char *style)
 {
   if (strcmp(bond_style,style) == 0) return bond;
   else if (strcmp(bond_style,"hybrid") == 0) {
-    BondHybrid *hbond = (BondHybrid *) bond;
-    for (int i = 0; i < hbond->nstyles; i++)
-      if (strcmp(hbond->keywords[i],style) == 0) return hbond->styles[i];
+    BondHybrid *hybrid = (BondHybrid *) bond;
+    for (int i = 0; i < hybrid->nstyles; i++)
+      if (strcmp(hybrid->keywords[i],style) == 0) return hybrid->styles[i];
   }
   return NULL;
 }
@@ -218,7 +225,7 @@ Bond *Force::bond_match(char *style)
    create an angle style, called from input script or restart file
 ------------------------------------------------------------------------- */
 
-void Force::create_angle(char *style)
+void Force::create_angle(const char *style)
 {
   delete [] angle_style;
   if (angle) delete angle;
@@ -233,7 +240,7 @@ void Force::create_angle(char *style)
    generate an angle class
 ------------------------------------------------------------------------- */
 
-Angle *Force::new_angle(char *style)
+Angle *Force::new_angle(const char *style)
 {
   if (strcmp(style,"none") == 0) return NULL;
 
@@ -251,7 +258,7 @@ Angle *Force::new_angle(char *style)
    create a dihedral style, called from input script or restart file
 ------------------------------------------------------------------------- */
 
-void Force::create_dihedral(char *style)
+void Force::create_dihedral(const char *style)
 {
   delete [] dihedral_style;
   if (dihedral) delete dihedral;
@@ -266,7 +273,7 @@ void Force::create_dihedral(char *style)
    generate a dihedral class
 ------------------------------------------------------------------------- */
 
-Dihedral *Force::new_dihedral(char *style)
+Dihedral *Force::new_dihedral(const char *style)
 {
   if (strcmp(style,"none") == 0) return NULL;
 
@@ -284,7 +291,7 @@ Dihedral *Force::new_dihedral(char *style)
    create an improper style, called from input script or restart file
 ------------------------------------------------------------------------- */
 
-void Force::create_improper(char *style)
+void Force::create_improper(const char *style)
 {
   delete [] improper_style;
   if (improper) delete improper;
@@ -299,7 +306,7 @@ void Force::create_improper(char *style)
    generate a improper class
 ------------------------------------------------------------------------- */
 
-Improper *Force::new_improper(char *style)
+Improper *Force::new_improper(const char *style)
 {
   if (strcmp(style,"none") == 0) return NULL;
 
diff --git a/src/force.h b/src/force.h
index a1ae61ddd1ce30d1ca8502f29958d02fb9307f32..7bf52ac7c52417417b285ade1f871e016a3286e6 100644
--- a/src/force.h
+++ b/src/force.h
@@ -56,22 +56,22 @@ class Force : protected Pointers {
   ~Force();
   void init();
 
-  void create_pair(char *);
-  class Pair *new_pair(char *);
-  class Pair *pair_match(char *);
+  void create_pair(const char *);
+  class Pair *new_pair(const char *);
+  class Pair *pair_match(const char *);
 
-  void create_bond(char *);
-  class Bond *new_bond(char *);
-  class Bond *bond_match(char *); 
+  void create_bond(const char *);
+  class Bond *new_bond(const char *);
+  class Bond *bond_match(const char *); 
 
-  void create_angle(char *);
-  class Angle *new_angle(char *);
+  void create_angle(const char *);
+  class Angle *new_angle(const char *);
 
-  void create_dihedral(char *);
-  class Dihedral *new_dihedral(char *);
+  void create_dihedral(const char *);
+  class Dihedral *new_dihedral(const char *);
 
-  void create_improper(char *);
-  class Improper *new_improper(char *);
+  void create_improper(const char *);
+  class Improper *new_improper(const char *);
 
   void create_kspace(int, char **);
 
diff --git a/src/group.cpp b/src/group.cpp
index 9b21a54f75bdd2505455a55b53d2e12874f486ad..9ea1cf2b07ed7ed6731bc430f2db53bfe38074cc 100644
--- a/src/group.cpp
+++ b/src/group.cpp
@@ -52,7 +52,7 @@ Group::Group(LAMMPS *lmp) : Pointers(lmp)
 
   // create "all" group
 
-  char *str = "all";
+  char *str = (char *) "all";
   int n = strlen(str) + 1;
   names[0] = (char *) memory->smalloc(n*sizeof(char),"group:names[]");
   strcpy(names[0],str);
@@ -352,7 +352,7 @@ void Group::create(char *name, int *flag)
    return group index if name matches existing group, -1 if no such group
 ------------------------------------------------------------------------- */
 
-int Group::find(char *name)
+int Group::find(const char *name)
 {
   for (int igroup = 0; igroup < ngroup; igroup++)
     if (strcmp(name,names[igroup]) == 0) return igroup;
diff --git a/src/group.h b/src/group.h
index 34789e5c75a01eb40ad0e1549d5a27cb901a87d4..fc855ad5a1cd9d9d975ccb092c51615ee87fc123 100644
--- a/src/group.h
+++ b/src/group.h
@@ -31,7 +31,7 @@ class Group : protected Pointers {
   ~Group();
   void assign(int, char **);         // assign atoms to a group
   void create(char *, int *);        // add flagged atoms to a group
-  int find(char *);                  // lookup name in list of groups
+  int find(const char *);                  // lookup name in list of groups
   void write_restart(FILE *);
   void read_restart(FILE *);
 
diff --git a/src/memory.cpp b/src/memory.cpp
index 430f7d8165a3ce9fb71f8ad1e3ce0c5237e8a3ac..caf553120a61f74d821beaa2ddf837c77b612eb2 100644
--- a/src/memory.cpp
+++ b/src/memory.cpp
@@ -28,7 +28,7 @@ Memory::Memory(LAMMPS *lmp) : Pointers(lmp) {}
    safe malloc 
 ------------------------------------------------------------------------- */
 
-void *Memory::smalloc(int n, char *name)
+void *Memory::smalloc(int n, const char *name)
 {
   if (n == 0) return NULL;
   void *ptr = malloc(n);
@@ -54,7 +54,7 @@ void Memory::sfree(void *ptr)
    safe realloc 
 ------------------------------------------------------------------------- */
 
-void *Memory::srealloc(void *ptr, int n, char *name)
+void *Memory::srealloc(void *ptr, int n, const char *name)
 {
   if (n == 0) return NULL;
   ptr = realloc(ptr,n);
@@ -70,7 +70,7 @@ void *Memory::srealloc(void *ptr, int n, char *name)
    create a 1d double array with index from nlo to nhi inclusive 
 ------------------------------------------------------------------------- */
 
-double *Memory::create_1d_double_array(int nlo, int nhi, char *name)
+double *Memory::create_1d_double_array(int nlo, int nhi, const char *name)
 {
   int n = nhi - nlo + 1;
   double *array = (double *) smalloc(n*sizeof(double),name);
@@ -91,7 +91,7 @@ void Memory::destroy_1d_double_array(double *array, int offset)
    create a 2d double array 
 ------------------------------------------------------------------------- */
 
-double **Memory::create_2d_double_array(int n1, int n2, char *name)
+double **Memory::create_2d_double_array(int n1, int n2, const char *name)
 
 {
   double *data = (double *) smalloc(n1*n2*sizeof(double),name);
@@ -125,7 +125,7 @@ void Memory::destroy_2d_double_array(double **array)
 ------------------------------------------------------------------------- */
 
 double **Memory::grow_2d_double_array(double **array,
-				      int n1, int n2, char *name)
+				      int n1, int n2, const char *name)
 
 {
   if (array == NULL) return create_2d_double_array(n1,n2,name);
@@ -147,7 +147,7 @@ double **Memory::grow_2d_double_array(double **array,
    if either dim is 0, return NULL 
 ------------------------------------------------------------------------- */
 
-int **Memory::create_2d_int_array(int n1, int n2, char *name)
+int **Memory::create_2d_int_array(int n1, int n2, const char *name)
 
 {
   if (n1 == 0 || n2 == 0) return NULL;
@@ -182,7 +182,7 @@ void Memory::destroy_2d_int_array(int **array)
    if either dim is 0, return NULL 
 ------------------------------------------------------------------------- */
 
-int **Memory::grow_2d_int_array(int **array, int n1, int n2, char *name)
+int **Memory::grow_2d_int_array(int **array, int n1, int n2, const char *name)
 
 {
   if (n1 == 0 || n2 == 0) {
@@ -208,7 +208,8 @@ int **Memory::grow_2d_int_array(int **array, int n1, int n2, char *name)
    create a 2d double array with 2nd index from n2lo to n2hi inclusive 
 ------------------------------------------------------------------------- */
 
-double **Memory::create_2d_double_array(int n1, int n2lo, int n2hi, char *name)
+double **Memory::create_2d_double_array(int n1, int n2lo, int n2hi,
+					const char *name)
 {
   int n2 = n2hi - n2lo + 1;
   double **array = create_2d_double_array(n1,n2,name);
@@ -232,7 +233,8 @@ void Memory::destroy_2d_double_array(double **array, int offset)
    create a 3d double array 
 ------------------------------------------------------------------------- */
 
-double ***Memory::create_3d_double_array(int n1, int n2, int n3, char *name)
+double ***Memory::create_3d_double_array(int n1, int n2, int n3,
+					 const char *name)
 {
   int i,j;
 
@@ -271,7 +273,8 @@ void Memory::destroy_3d_double_array(double ***array)
 ------------------------------------------------------------------------- */
 
 double ***Memory::grow_3d_double_array(double ***array,
-				       int n1, int n2, int n3, char *name)
+				       int n1, int n2, int n3,
+				       const char *name)
 {
   int i,j;
 
@@ -303,7 +306,7 @@ double ***Memory::grow_3d_double_array(double ***array,
 ------------------------------------------------------------------------- */
 
 double ***Memory::create_3d_double_array(int n1lo, int n1hi, 
-					 int n2, int n3, char *name)
+					 int n2, int n3, const char *name)
 {
   int n1 = n1hi - n1lo + 1;
   double ***array = create_3d_double_array(n1,n2,n3,name);
@@ -328,7 +331,7 @@ void Memory::destroy_3d_double_array(double ***array, int offset)
 
 double ***Memory::create_3d_double_array(int n1lo, int n1hi,
 					 int n2lo, int n2hi,
-					 int n3lo, int n3hi, char *name)
+					 int n3lo, int n3hi, const char *name)
 {
   int n1 = n1hi - n1lo + 1;
   int n2 = n2hi - n2lo + 1;
@@ -358,7 +361,7 @@ void Memory::destroy_3d_double_array(double ***array, int n1_offset,
    create a 3d int array 
 ------------------------------------------------------------------------- */
 
-int ***Memory::create_3d_int_array(int n1, int n2, int n3, char *name)
+int ***Memory::create_3d_int_array(int n1, int n2, int n3, const char *name)
 {
   int i,j;
 
@@ -394,7 +397,8 @@ void Memory::destroy_3d_int_array(int ***array)
    create a 4d double array 
 ------------------------------------------------------------------------- */
 
-double ****Memory::create_4d_double_array(int n1, int n2, int n3, int n4, char *name)
+double ****Memory::create_4d_double_array(int n1, int n2, int n3, int n4,
+					  const char *name)
 {
   int i,j,k;
 
diff --git a/src/memory.h b/src/memory.h
index e5f2cf73daf81e9b9349b0bc7ca7e628049d00a9..39b79f7060a74def1569856bb8e6ea2b433955ff 100644
--- a/src/memory.h
+++ b/src/memory.h
@@ -22,38 +22,38 @@ class Memory : protected Pointers {
  public:
   Memory(class LAMMPS *);
 
-  void *smalloc(int n, char *);
+  void *smalloc(int n, const char *);
   void sfree(void *);
-  void *srealloc(void *, int n, char *name);
+  void *srealloc(void *, int n, const char *name);
 
-  double *create_1d_double_array(int, int, char *);
+  double *create_1d_double_array(int, int, const char *);
   void destroy_1d_double_array(double *, int);
   
-  double **create_2d_double_array(int, int, char *);
+  double **create_2d_double_array(int, int, const char *);
   void destroy_2d_double_array(double **);
-  double **grow_2d_double_array(double **, int, int, char *);
+  double **grow_2d_double_array(double **, int, int, const char *);
 
-  int **create_2d_int_array(int, int, char *);
+  int **create_2d_int_array(int, int, const char *);
   void destroy_2d_int_array(int **);
-  int **grow_2d_int_array(int **, int, int, char *);
+  int **grow_2d_int_array(int **, int, int, const char *);
 
-  double **create_2d_double_array(int, int, int, char *);
+  double **create_2d_double_array(int, int, int, const char *);
   void destroy_2d_double_array(double **, int);
 
-  double ***create_3d_double_array(int, int, int, char *);
+  double ***create_3d_double_array(int, int, int, const char *);
   void destroy_3d_double_array(double ***);
-  double ***grow_3d_double_array(double ***, int, int, int, char *);
+  double ***grow_3d_double_array(double ***, int, int, int, const char *);
 
-  double ***create_3d_double_array(int, int, int, int, char *);
+  double ***create_3d_double_array(int, int, int, int, const char *);
   void destroy_3d_double_array(double ***, int);
 
-  double ***create_3d_double_array(int, int, int, int, int, int, char *);
+  double ***create_3d_double_array(int, int, int, int, int, int, const char *);
   void destroy_3d_double_array(double ***, int, int, int);
 
-  int ***create_3d_int_array(int, int, int, char *);
+  int ***create_3d_int_array(int, int, int, const char *);
   void destroy_3d_int_array(int ***);
 
-  double ****create_4d_double_array(int, int, int, int, char *);
+  double ****create_4d_double_array(int, int, int, int, const char *);
   void destroy_4d_double_array(double ****);
 };
 
diff --git a/src/min_cg.cpp b/src/min_cg.cpp
index 4390e27e5c9da6fa9fb5178c8c539194b2be9a24..ad0a74740e0e4db09d9798a3bbf282da4ee5797a 100644
--- a/src/min_cg.cpp
+++ b/src/min_cg.cpp
@@ -65,9 +65,9 @@ void MinCG::init()
   // will delete it at end of run
 
   char **fixarg = new char*[3];
-  fixarg[0] = "MINIMIZE";
-  fixarg[1] = "all";
-  fixarg[2] = "MINIMIZE";
+  fixarg[0] = (char *) "MINIMIZE";
+  fixarg[1] = (char *) "all";
+  fixarg[2] = (char *) "MINIMIZE";
   modify->add_fix(3,fixarg);
   delete [] fixarg;
   fix_minimize = (FixMinimize *) modify->fix[modify->nfix-1];
@@ -85,12 +85,9 @@ void MinCG::init()
 
   // set flags for what arrays to clear in force_clear()
   // need to clear torques if array exists
-  // don't need to clear f_pair if atom_style is only granular (no virial)
 
   torqueflag = 0;
   if (atom->torque) torqueflag = 1;
-  pairflag = 1;
-  if (strcmp(atom->atom_style,"granular") == 0) pairflag = 0;
 
   // orthogonal vs triclinic simulation box
 
@@ -115,11 +112,6 @@ void MinCG::init()
 
   if (linestyle == SCAN) linemin = &MinCG::linemin_scan;
   else if (linestyle == SECANT) linemin = &MinCG::linemin_secant;
-
-  // local versions of Update quantities
-
-  maxpair = update->maxpair;
-  f_pair = update->f_pair;
 }
 
 /* ----------------------------------------------------------------------
@@ -233,6 +225,8 @@ void MinCG::setup()
   int vflag = virial_thermo;
   force_clear(vflag);
   
+  if (force->pair) force->pair->compute(eflag,vflag);
+
   if (atom->molecular) {
     if (force->bond) force->bond->compute(eflag,vflag);
     if (force->angle) force->angle->compute(eflag,vflag);
@@ -240,8 +234,6 @@ void MinCG::setup()
     if (force->improper) force->improper->compute(eflag,vflag);
   }
 
-  if (force->pair) force->pair->compute(eflag,vflag);
-
   if (force->kspace) {
     force->kspace->setup();
     force->kspace->compute(eflag,vflag);
@@ -391,6 +383,12 @@ void MinCG::eng_force(int *pndof, double **px, double **ph, double *peng)
   force_clear(vflag);
 
   timer->stamp();
+
+  if (force->pair) {
+    force->pair->compute(eflag,vflag);
+    timer->stamp(TIME_PAIR);
+  }
+
   if (atom->molecular) {
     if (force->bond) force->bond->compute(eflag,vflag);
     if (force->angle) force->angle->compute(eflag,vflag);
@@ -399,11 +397,6 @@ void MinCG::eng_force(int *pndof, double **px, double **ph, double *peng)
     timer->stamp(TIME_BOND);
   }
 
-  if (force->pair) {
-    force->pair->compute(eflag,vflag);
-    timer->stamp(TIME_PAIR);
-  }
-
   if (force->kspace) {
     force->kspace->compute(eflag,vflag);
     timer->stamp(TIME_KSPACE);
@@ -462,23 +455,6 @@ void MinCG::force_clear(int vflag)
       torque[i][2] = 0.0;
     }
   }
-
-  // clear f_pair array if using it this timestep to compute virial
-
-  if (vflag == 2 && pairflag) {
-    if (atom->nmax > maxpair) {
-      maxpair = atom->nmax;
-      memory->destroy_2d_double_array(f_pair);
-      f_pair = memory->create_2d_double_array(maxpair,3,"min:f_pair");
-      update->maxpair = maxpair;
-      update->f_pair = f_pair;
-    }
-    for (i = 0; i < nall; i++) {
-      f_pair[i][0] = 0.0;
-      f_pair[i][1] = 0.0;
-      f_pair[i][2] = 0.0;
-    }
-  }
 }
 
 /* ----------------------------------------------------------------------
diff --git a/src/modify.cpp b/src/modify.cpp
index 6d6c85da56a1fc14649b59b67a0f63e4432211be..7a53ea754122e036e75f90aab59c7bd8885c1f63 100644
--- a/src/modify.cpp
+++ b/src/modify.cpp
@@ -406,8 +406,8 @@ void Modify::add_fix(int narg, char **arg)
 	strcmp(style_restart_global[i],fix[ifix]->style) == 0) {
       fix[ifix]->restart(state_restart_global[i]);
       if (comm->me == 0) {
-	char *str = "Resetting global state of Fix %s Style %s "
-	  "from restart file info\n";
+	char *str = (char *) ("Resetting global state of Fix %s Style %s "
+			      "from restart file info\n");
 	if (screen) fprintf(screen,str,fix[ifix]->id,fix[ifix]->style);
 	if (logfile) fprintf(logfile,str,fix[ifix]->id,fix[ifix]->style);
       }
@@ -422,8 +422,8 @@ void Modify::add_fix(int narg, char **arg)
       for (int j = 0; j < atom->nlocal; j++)
 	fix[ifix]->unpack_restart(j,index_restart_peratom[i]);
       if (comm->me == 0) {
-	char *str = "Resetting per-atom state of Fix %s Style %s "
-	  "from restart file info\n";
+	char *str = (char *) ("Resetting per-atom state of Fix %s Style %s "
+		     "from restart file info\n");
 	if (screen) fprintf(screen,str,fix[ifix]->id,fix[ifix]->style);
 	if (logfile) fprintf(logfile,str,fix[ifix]->id,fix[ifix]->style);
       }
@@ -453,7 +453,7 @@ void Modify::modify_fix(int narg, char **arg)
    Atom class must update indices in its list of callbacks to fixes
 ------------------------------------------------------------------------- */
 
-void Modify::delete_fix(char *id)
+void Modify::delete_fix(const char *id)
 {
   int ifix = find_fix(id);
   if (ifix < 0) error->all("Could not find fix ID to delete");
@@ -472,7 +472,7 @@ void Modify::delete_fix(char *id)
    return index of fix or -1 if not found
 ------------------------------------------------------------------------- */
 
-int Modify::find_fix(char *id)
+int Modify::find_fix(const char *id)
 {
   int ifix;
   for (ifix = 0; ifix < nfix; ifix++)
diff --git a/src/modify.h b/src/modify.h
index e49bef7f740b99515a0602fae4314cde695c0bdd..88411fe11cd026de57a272092ed1da6701a949d9 100644
--- a/src/modify.h
+++ b/src/modify.h
@@ -58,8 +58,8 @@ class Modify : protected Pointers {
 
   void add_fix(int, char **);
   void modify_fix(int, char **);
-  void delete_fix(char *);
-  int find_fix(char *);
+  void delete_fix(const char *);
+  int find_fix(const char *);
 
   void add_compute(int, char **);
   void modify_compute(int, char **);
diff --git a/src/neigh_full.cpp b/src/neigh_full.cpp
index f5385e11e05a1563f9113d406bc843cb403e831e..878ab0819c8c5cc9b373b4b209ac29accd43c69f 100644
--- a/src/neigh_full.cpp
+++ b/src/neigh_full.cpp
@@ -12,6 +12,7 @@
 ------------------------------------------------------------------------- */
 
 #include "neighbor.h"
+#include "neigh_list.h"
 #include "atom.h"
 #include "error.h"
 
@@ -22,7 +23,7 @@ using namespace LAMMPS_NS;
    every neighbor pair appears in list of both atoms i and j
 ------------------------------------------------------------------------- */
 
-void Neighbor::full_nsq()
+void Neighbor::full_nsq(NeighList *list)
 {
   int i,j,n,itype,jtype,which;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
@@ -36,6 +37,12 @@ void Neighbor::full_nsq()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -44,10 +51,10 @@ void Neighbor::full_nsq()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage_full) add_pages_full(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
 
-    neighptr = &pages_full[npage][npnt];
+    neighptr = &pages[npage][npnt];
     n = 0;
 
     itype = type[i];
@@ -60,9 +67,10 @@ void Neighbor::full_nsq()
 
     for (j = 0; j < nall; j++) {
       if (i == j) continue;
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
 
       jtype = type[j];
+      if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
       delx = xtmp - x[j][0];
       dely = ytmp - x[j][1];
       delz = ztmp - x[j][2];
@@ -75,12 +83,16 @@ void Neighbor::full_nsq()
       }
     }
 
-    firstneigh_full[i] = neighptr;
-    numneigh_full[i] = n;
+    ilist[inum] = i;
+    firstneigh[i] = neighptr;
+    numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -88,7 +100,7 @@ void Neighbor::full_nsq()
    every neighbor pair appears in list of both atoms i and j
 ------------------------------------------------------------------------- */
 
-void Neighbor::full_bin()
+void Neighbor::full_bin(NeighList *list)
 {
   int i,j,k,n,itype,jtype,ibin,which;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
@@ -108,6 +120,14 @@ void Neighbor::full_bin()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -116,10 +136,10 @@ void Neighbor::full_bin()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage_full) add_pages_full(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
 
-    neighptr = &pages_full[npage][npnt];
+    neighptr = &pages[npage][npnt];
     n = 0;
 
     itype = type[i];
@@ -132,12 +152,13 @@ void Neighbor::full_bin()
 
     ibin = coord2bin(x[i]);
 
-    for (k = 0; k < nstencil_full; k++) {
-      for (j = binhead[ibin+stencil_full[k]]; j >= 0; j = bins[j]) {
+    for (k = 0; k < nstencil; k++) {
+      for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
 	if (i == j) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
 
 	jtype = type[j];
+	if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
 	delz = ztmp - x[j][2];
@@ -152,12 +173,16 @@ void Neighbor::full_bin()
       }
     }
 
-    firstneigh_full[i] = neighptr;
-    numneigh_full[i] = n;
+    ilist[inum] = i;
+    firstneigh[i] = neighptr;
+    numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -166,7 +191,7 @@ void Neighbor::full_bin()
    every neighbor pair appears in list of both atoms i and j
 ------------------------------------------------------------------------- */
 
-void Neighbor::full_bin_multi()
+void Neighbor::full_multi(NeighList *list)
 {
   int i,j,k,n,itype,jtype,ibin,which,ns;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
@@ -187,6 +212,15 @@ void Neighbor::full_bin_multi()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -195,10 +229,10 @@ void Neighbor::full_bin_multi()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage_full) add_pages_full(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
 
-    neighptr = &pages_full[npage][npnt];
+    neighptr = &pages[npage][npnt];
     n = 0;
 
     itype = type[i];
@@ -211,16 +245,17 @@ void Neighbor::full_bin_multi()
     // skip i = j
 
     ibin = coord2bin(x[i]);
-    s = stencil_full_multi[itype];
-    distsq = distsq_full_multi[itype];
+    s = stencil_multi[itype];
+    distsq = distsq_multi[itype];
     cutsq = cutneighsq[itype];
-    ns = nstencil_full_multi[itype];
+    ns = nstencil_multi[itype];
     for (k = 0; k < ns; k++) {
       for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
 	jtype = type[j];
 	if (cutsq[jtype] < distsq[k]) continue;
 	if (i == j) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
+
+	if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
 
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
@@ -236,10 +271,14 @@ void Neighbor::full_bin_multi()
       }
     }
 
-    firstneigh_full[i] = neighptr;
-    numneigh_full[i] = n;
+    ilist[inum] = i;
+    firstneigh[i] = neighptr;
+    numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
diff --git a/src/neigh_gran.cpp b/src/neigh_gran.cpp
index ef12943b4070cdd60a438f034e86fee2599d051a..17c35fdb660d4e6d8fcf2e2f61da1ea3bac35aa2 100644
--- a/src/neigh_gran.cpp
+++ b/src/neigh_gran.cpp
@@ -12,8 +12,8 @@
 ------------------------------------------------------------------------- */
 
 #include "neighbor.h"
+#include "neigh_list.h"
 #include "atom.h"
-#include "modify.h"
 #include "fix_shear_history.h"
 #include "error.h"
 
@@ -27,22 +27,21 @@ using namespace LAMMPS_NS;
    pair added if j is ghost (also stored by proc owning j)
 ------------------------------------------------------------------------- */
 
-void Neighbor::granular_nsq_no_newton()
+void Neighbor::granular_nsq_no_newton(NeighList *list)
 {
   int i,j,m,n,nn;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
   double radi,radsum,cutsq;
   int *neighptr,*touchptr;
   double *shearptr;
-  int *npartner;
-  int **partner;
-  double ***shearpartner;
 
-  if (fix_history) {
-    npartner = fix_history->npartner;
-    partner = fix_history->partner;
-    shearpartner = fix_history->shearpartner;
-  }
+  NeighList *listgranhistory;
+  int *npartner,**partner;
+  double ***shearpartner;
+  int **firsttouch;
+  double **firstshear;
+  int **pages_touch;
+  double **pages_shear;
 
   double **x = atom->x;
   double *radius = atom->radius;
@@ -53,6 +52,26 @@ void Neighbor::granular_nsq_no_newton()
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  FixShearHistory *fix_history = list->fix_history;
+  if (fix_history) {
+    npartner = fix_history->npartner;
+    partner = fix_history->partner;
+    shearpartner = fix_history->shearpartner;
+    listgranhistory = list->listgranhistory;
+    firsttouch = listgranhistory->firstneigh;
+    firstshear = listgranhistory->firstdouble;
+    pages_touch = listgranhistory->pages;
+    pages_shear = listgranhistory->dpages;
+  }
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -61,9 +80,12 @@ void Neighbor::granular_nsq_no_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) {
-	add_pages(npage);
-	if (fix_history) add_pages_history(npage);
+      if (npage == list->maxpage) {
+	pages = list->add_pages();
+	if (fix_history) {
+	  pages_touch = listgranhistory->add_pages();
+	  pages_shear = listgranhistory->dpages;
+	}
       }
     }
 
@@ -83,7 +105,7 @@ void Neighbor::granular_nsq_no_newton()
     // loop over remaining atoms, owned and ghost
 
     for (j = i+1; j < nall; j++) {
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
+      if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
 
       delx = xtmp - x[j][0];
       dely = ytmp - x[j][1];
@@ -122,16 +144,21 @@ void Neighbor::granular_nsq_no_newton()
       }
     }	       
 
+    ilist[inum] = i;
+    firstneigh[i] = neighptr;
+    numneigh[i] = n;
     if (fix_history) {
       firsttouch[i] = touchptr;
       firstshear[i] = shearptr;
     }
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
+
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -143,7 +170,7 @@ void Neighbor::granular_nsq_no_newton()
    decision based on itag,jtag tests
 ------------------------------------------------------------------------- */
 
-void Neighbor::granular_nsq_newton()
+void Neighbor::granular_nsq_newton(NeighList *list)
 {
   int i,j,n,itag,jtag;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
@@ -159,6 +186,14 @@ void Neighbor::granular_nsq_newton()
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -167,7 +202,7 @@ void Neighbor::granular_nsq_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
 
     n = 0;
@@ -196,7 +231,7 @@ void Neighbor::granular_nsq_newton()
 	}
       }
 
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
+      if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
 
       delx = xtmp - x[j][0];
       dely = ytmp - x[j][1];
@@ -208,12 +243,16 @@ void Neighbor::granular_nsq_newton()
       if (rsq <= cutsq) neighptr[n++] = j;
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -225,22 +264,21 @@ void Neighbor::granular_nsq_newton()
    pair stored by me if j is ghost (also stored by proc owning j)
 ------------------------------------------------------------------------- */
 
-void Neighbor::granular_bin_no_newton()
+void Neighbor::granular_bin_no_newton(NeighList *list)
 {
   int i,j,k,m,n,nn,ibin;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
   double radi,radsum,cutsq;
   int *neighptr,*touchptr;
   double *shearptr;
-  int *npartner;
-  int **partner;
-  double ***shearpartner;
 
-  if (fix_history) {
-    npartner = fix_history->npartner;
-    partner = fix_history->partner;
-    shearpartner = fix_history->shearpartner;
-  }
+  NeighList *listgranhistory;
+  int *npartner,**partner;
+  double ***shearpartner;
+  int **firsttouch;
+  double **firstshear;
+  int **pages_touch;
+  double **pages_shear;
 
   // bin local & ghost atoms
 
@@ -256,6 +294,26 @@ void Neighbor::granular_bin_no_newton()
   int *molecule = atom->molecule;
   int nlocal = atom->nlocal;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  FixShearHistory *fix_history = list->fix_history;
+  if (fix_history) {
+    npartner = fix_history->npartner;
+    partner = fix_history->partner;
+    shearpartner = fix_history->shearpartner;
+    listgranhistory = list->listgranhistory;
+    firsttouch = listgranhistory->firstneigh;
+    firstshear = listgranhistory->firstdouble;
+    pages_touch = listgranhistory->pages;
+    pages_shear = listgranhistory->dpages;
+  }
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -264,9 +322,12 @@ void Neighbor::granular_bin_no_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) {
-	add_pages(npage);
-	if (fix_history) add_pages_history(npage);
+      if (npage == list->maxpage) {
+	pages = list->add_pages();
+	if (fix_history) {
+	  pages_touch = listgranhistory->add_pages();
+	  pages_shear = listgranhistory->dpages;
+	}
       }
     }
 
@@ -292,7 +353,7 @@ void Neighbor::granular_bin_no_newton()
     for (k = 0; k < nstencil; k++) {
       for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
 	if (j <= i) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
+	if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
 
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
@@ -332,16 +393,21 @@ void Neighbor::granular_bin_no_newton()
       }
     }
 
+    ilist[inum] = i;
+    firstneigh[i] = neighptr;
+    numneigh[i] = n;
     if (fix_history) {
       firsttouch[i] = touchptr;
       firstshear[i] = shearptr;
     }
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
+
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -352,7 +418,7 @@ void Neighbor::granular_bin_no_newton()
    every pair stored exactly once by some processor
 ------------------------------------------------------------------------- */
 
-void Neighbor::granular_bin_newton()
+void Neighbor::granular_bin_newton(NeighList *list)
 {
   int i,j,k,n,ibin;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
@@ -372,6 +438,14 @@ void Neighbor::granular_bin_newton()
   int *molecule = atom->molecule;
   int nlocal = atom->nlocal;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -380,7 +454,7 @@ void Neighbor::granular_bin_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
 
     n = 0;
@@ -400,7 +474,7 @@ void Neighbor::granular_bin_newton()
 	if (x[j][2] < ztmp) continue;
 	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
 	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
+	if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
       }
 
       delx = xtmp - x[j][0];
@@ -418,7 +492,7 @@ void Neighbor::granular_bin_newton()
     ibin = coord2bin(x[i]);
     for (k = 0; k < nstencil; k++) {
       for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
+	if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
 
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
@@ -431,12 +505,16 @@ void Neighbor::granular_bin_newton()
       }
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -447,7 +525,7 @@ void Neighbor::granular_bin_newton()
    every pair stored exactly once by some processor
 ------------------------------------------------------------------------- */
 
-void Neighbor::granular_bin_newton_tri()
+void Neighbor::granular_bin_newton_tri(NeighList *list)
 {
   int i,j,k,n,ibin;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
@@ -467,6 +545,14 @@ void Neighbor::granular_bin_newton_tri()
   int *molecule = atom->molecule;
   int nlocal = atom->nlocal;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
 
@@ -475,7 +561,7 @@ void Neighbor::granular_bin_newton_tri()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
 
     n = 0;
@@ -497,7 +583,7 @@ void Neighbor::granular_bin_newton_tri()
 	if (x[j][2] < ztmp) continue;
 	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
 	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] <= xtmp) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
+	if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
 
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
@@ -510,10 +596,14 @@ void Neighbor::granular_bin_newton_tri()
       }
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
   }
+
+  list->inum = inum;
 }
diff --git a/src/neigh_half.cpp b/src/neigh_half.cpp
deleted file mode 100644
index 63f1edff7ec432cf76c599199f88727ff0086810..0000000000000000000000000000000000000000
--- a/src/neigh_half.cpp
+++ /dev/null
@@ -1,820 +0,0 @@
-/* ----------------------------------------------------------------------
-   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
-   http://lammps.sandia.gov, 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 "neighbor.h"
-#include "atom.h"
-#include "error.h"
-
-using namespace LAMMPS_NS;
-
-/* ----------------------------------------------------------------------
-   N^2 / 2 search for neighbor pairs with partial Newton's 3rd law
-   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)
-------------------------------------------------------------------------- */
-
-void Neighbor::half_nsq_no_newton()
-{
-  int i,j,n,itype,jtype,which;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr;
-
-  double **x = atom->x;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over remaining atoms, owned and ghost
-
-    for (j = i+1; j < nall; j++) {
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
-      jtype = type[j];
-      delx = xtmp - x[j][0];
-      dely = ytmp - x[j][1];
-      delz = ztmp - x[j][2];
-      rsq = delx*delx + dely*dely + delz*delz;
-
-      if (rsq <= cutneighsq[itype][jtype]) {
-	if (molecular) which = find_special(i,j);
-	else which = 0;
-	if (which == 0) neighptr[n++] = j;
-	else if (which > 0) neighptr[n++] = which*nall + j;
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   N^2 / 2 search for neighbor pairs with full Newton's 3rd law
-   every pair stored exactly once by some processor
-   decision on ghost atoms based on itag,jtag tests
-------------------------------------------------------------------------- */
-
-void Neighbor::half_nsq_newton()
-{
-  int i,j,n,itype,jtype,itag,jtag,which;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr;
-
-  double **x = atom->x;
-  int *tag = atom->tag;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itag = tag[i];
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over remaining atoms, owned and ghost
-    // itag = jtag is possible for long cutoffs that include images of self
-
-    for (j = i+1; j < nall; j++) {
-      if (j >= nlocal) {
-	jtag = tag[j];
-	if (itag > jtag) {
-	  if ((itag+jtag) % 2 == 0) continue;
-	} else if (itag < jtag) {
-	  if ((itag+jtag) % 2 == 1) continue;
-	} else {
-	  if (x[j][2] < ztmp) continue;
-	  else if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
-	  else if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp)
-	    continue;
-	}
-      }
-
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
-      jtype = type[j];
-      delx = xtmp - x[j][0];
-      dely = ytmp - x[j][1];
-      delz = ztmp - x[j][2];
-      rsq = delx*delx + dely*dely + delz*delz;
-
-      if (rsq <= cutneighsq[itype][jtype]) {
-	if (molecular) which = find_special(i,j);
-	else which = 0;
-	if (which == 0) neighptr[n++] = j;
-	else if (which > 0) neighptr[n++] = which*nall + j;
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   binned neighbor list construction with partial Newton's 3rd law
-   each owned atom i checks own bin and other bins in stencil
-   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)
-------------------------------------------------------------------------- */
-
-void Neighbor::half_bin_no_newton()
-{
-  int i,j,k,n,itype,jtype,ibin,which;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr;
-
-  // bin local & ghost atoms
-
-  bin_atoms();
-
-  // loop over each atom, storing neighbors
-
-  double **x = atom->x;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over all atoms in other bins in stencil including self
-    // only store pair if i < j
-    // stores own/own pairs only once
-    // stores own/ghost pairs on both procs
-
-    ibin = coord2bin(x[i]);
-
-    for (k = 0; k < nstencil; k++) {
-      for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
-	if (j <= i) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
-	jtype = type[j];
-	delx = xtmp - x[j][0];
-	dely = ytmp - x[j][1];
-	delz = ztmp - x[j][2];
-	rsq = delx*delx + dely*dely + delz*delz;
-
-	if (rsq <= cutneighsq[itype][jtype]) {
-	  if (molecular) which = find_special(i,j);
-	  else which = 0;
-	  if (which == 0) neighptr[n++] = j;
-	  else if (which > 0) neighptr[n++] = which*nall + j;
-	}
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   binned neighbor list construction with partial Newton's 3rd law
-   each owned atom i checks own bin and other bins in stencil
-   multi-type stencil is itype dependent and is distance checked
-   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)
-------------------------------------------------------------------------- */
-
-void Neighbor::half_bin_no_newton_multi()
-{
-  int i,j,k,n,itype,jtype,ibin,which,ns;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr,*s;
-  double *cutsq,*distsq;
-
-  // bin local & ghost atoms
-
-  bin_atoms();
-
-  // loop over each atom, storing neighbors
-
-  double **x = atom->x;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over all atoms in other bins in stencil including self
-    // only store pair if i < j
-    // skip if i,j neighbor cutoff is less than bin distance
-    // stores own/own pairs only once
-    // stores own/ghost pairs on both procs
-
-    ibin = coord2bin(x[i]);
-    s = stencil_multi[itype];
-    distsq = distsq_multi[itype];
-    cutsq = cutneighsq[itype];
-    ns = nstencil_multi[itype];
-    for (k = 0; k < ns; k++) {
-      for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
-	if (j <= i) continue;
-	jtype = type[j];
-	if (cutsq[jtype] < distsq[k]) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) 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 <= cutneighsq[itype][jtype]) {
-	  if (molecular) which = find_special(i,j);
-	  else which = 0;
-	  if (which == 0) neighptr[n++] = j;
-	  else if (which > 0) neighptr[n++] = which*nall + j;
-	}
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   binned neighbor list construction with full Newton's 3rd law
-   each owned atom i checks its own bin and other bins in Newton stencil
-   every pair stored exactly once by some processor
-------------------------------------------------------------------------- */
-
-void Neighbor::half_bin_newton()
-{
-  int i,j,k,n,itype,jtype,ibin,which;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr;
-
-  // bin local & ghost atoms
-
-  bin_atoms();
-
-  // loop over each atom, storing neighbors
-
-  double **x = atom->x;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over rest of atoms in i's bin, ghosts are at end of linked list
-    // if j is owned atom, store it, since j is beyond i in linked list
-    // if j is ghost, only store if j coords are "above and to the right" of i
-
-    for (j = bins[i]; j >= 0; j = bins[j]) {
-      if (j >= nlocal) {
-	if (x[j][2] < ztmp) continue;
-	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
-	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
-      }
-
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
-      jtype = type[j];
-      delx = xtmp - x[j][0];
-      dely = ytmp - x[j][1];
-      delz = ztmp - x[j][2];
-      rsq = delx*delx + dely*dely + delz*delz;
-
-      if (rsq <= cutneighsq[itype][jtype]) {
-	if (molecular) which = find_special(i,j);
-	else which = 0;
-	if (which == 0) neighptr[n++] = j;
-	else if (which > 0) neighptr[n++] = which*nall + j;
-      }
-    }
-
-    // loop over all atoms in other bins in stencil, store every pair
-
-    ibin = coord2bin(x[i]);
-    for (k = 0; k < nstencil; k++) {
-      for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
-	jtype = type[j];
-	delx = xtmp - x[j][0];
-	dely = ytmp - x[j][1];
-	delz = ztmp - x[j][2];
-	rsq = delx*delx + dely*dely + delz*delz;
-
-	if (rsq <= cutneighsq[itype][jtype]) {
-	  if (molecular) which = find_special(i,j);
-	  else which = 0;
-	  if (which == 0) neighptr[n++] = j;
-	  else if (which > 0) neighptr[n++] = which*nall + j;
-	}
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   binned neighbor list construction with full Newton's 3rd law
-   each owned atom i checks its own bin and other bins in Newton stencil
-   multi-type stencil is itype dependent and is distance checked
-   every pair stored exactly once by some processor
-------------------------------------------------------------------------- */
-
-void Neighbor::half_bin_newton_multi()
-{
-  int i,j,k,n,itype,jtype,ibin,which,ns;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr,*s;
-  double *cutsq,*distsq;
-
-  // bin local & ghost atoms
-
-  bin_atoms();
-
-  // loop over each atom, storing neighbors
-
-  double **x = atom->x;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over rest of atoms in i's bin, ghosts are at end of linked list
-    // if j is owned atom, store it, since j is beyond i in linked list
-    // if j is ghost, only store if j coords are "above and to the right" of i
-
-    for (j = bins[i]; j >= 0; j = bins[j]) {
-      if (j >= nlocal) {
-	if (x[j][2] < ztmp) continue;
-	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
-	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
-      }
-
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
-      jtype = type[j];
-      delx = xtmp - x[j][0];
-      dely = ytmp - x[j][1];
-      delz = ztmp - x[j][2];
-      rsq = delx*delx + dely*dely + delz*delz;
-
-      if (rsq <= cutneighsq[itype][jtype]) {
-	if (molecular) which = find_special(i,j);
-	else which = 0;
-	if (which == 0) neighptr[n++] = j;
-	else if (which > 0) neighptr[n++] = which*nall + j;
-      }
-    }
-
-    // loop over all atoms in other bins in stencil, store every pair
-    // skip if i,j neighbor cutoff is less than bin distance
-
-    ibin = coord2bin(x[i]);
-    s = stencil_multi[itype];
-    distsq = distsq_multi[itype];
-    cutsq = cutneighsq[itype];
-    ns = nstencil_multi[itype];
-    for (k = 0; k < ns; k++) {
-      for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
-	jtype = type[j];
-	if (cutsq[jtype] < distsq[k]) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) 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 <= cutneighsq[itype][jtype]) {
-	  if (molecular) which = find_special(i,j);
-	  else which = 0;
-	  if (which == 0) neighptr[n++] = j;
-	  else if (which > 0) neighptr[n++] = which*nall + j;
-	}
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   binned neighbor list construction with Newton's 3rd law for triclinic
-   each owned atom i checks its own bin and other bins in triclinic stencil
-   every pair stored exactly once by some processor
-------------------------------------------------------------------------- */
-
-void Neighbor::half_bin_newton_tri()
-{
-  int i,j,k,n,itype,jtype,ibin,which;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr;
-
-  // bin local & ghost atoms
-
-  bin_atoms();
-
-  // loop over each atom, storing neighbors
-
-  double **x = atom->x;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over all atoms in bins in stencil
-    // pairs for atoms j "below" i are excluded
-    // below = lower z or (equal z and lower y) or (equal zy and <= x)
-    // this excludes self-self interaction
-
-    ibin = coord2bin(x[i]);
-    for (k = 0; k < nstencil; k++) {
-      for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
-	if (x[j][2] < ztmp) continue;
-	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
-	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] <= xtmp) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
-	jtype = type[j];
-	delx = xtmp - x[j][0];
-	dely = ytmp - x[j][1];
-	delz = ztmp - x[j][2];
-	rsq = delx*delx + dely*dely + delz*delz;
-
-	if (rsq <= cutneighsq[itype][jtype]) {
-	  if (molecular) which = find_special(i,j);
-	  else which = 0;
-	  if (which == 0) neighptr[n++] = j;
-	  else if (which > 0) neighptr[n++] = which*nall + j;
-	}
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   binned neighbor list construction with Newton's 3rd law for triclinic
-   each owned atom i checks its own bin and other bins in triclinic stencil
-   multi-type stencil is itype dependent and is distance checked
-   every pair stored exactly once by some processor
-------------------------------------------------------------------------- */
-
-void Neighbor::half_bin_newton_multi_tri()
-{
-  int i,j,k,n,itype,jtype,ibin,which,ns;
-  double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr,*s;
-  double *cutsq,*distsq;
-
-  // bin local & ghost atoms
-
-  bin_atoms();
-
-  // loop over each atom, storing neighbors
-
-  double **x = atom->x;
-  int *type = atom->type;
-  int *mask = atom->mask;
-  int *molecule = atom->molecule;
-  int nlocal = atom->nlocal;
-  int nall = atom->nlocal + atom->nghost;
-  int molecular = atom->molecular;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    itype = type[i];
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over all atoms in bins, including self, in stencil
-    // skip if i,j neighbor cutoff is less than bin distance
-    // bins below self are excluded from stencil
-    // pairs for atoms j below i are excluded
-
-    ibin = coord2bin(x[i]);
-    s = stencil_multi[itype];
-    distsq = distsq_multi[itype];
-    cutsq = cutneighsq[itype];
-    ns = nstencil_multi[itype];
-    for (k = 0; k < ns; k++) {
-      for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
-	jtype = type[j];
-	if (cutsq[jtype] < distsq[k]) continue;
-	if (x[j][2] < ztmp) continue;
-	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
-	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] <= xtmp) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) 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 <= cutneighsq[itype][jtype]) {
-	  if (molecular) which = find_special(i,j);
-	  else which = 0;
-	  if (which == 0) neighptr[n++] = j;
-	  else if (which > 0) neighptr[n++] = which*nall + j;
-	}
-      }
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   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)
-------------------------------------------------------------------------- */
-
-void Neighbor::half_full_no_newton()
-{
-  int i,j,k,n,nfull;
-  int *neighptr,*neighs;
-
-  int nlocal = atom->nlocal;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    // loop over full neighbor list
-
-    neighs = firstneigh_full[i];
-    nfull = numneigh_full[i];
-
-    for (k = 0; k < nfull; k++) {
-      j = neighs[k];
-      if (j > i) neighptr[n++] = j;
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
-
-/* ----------------------------------------------------------------------
-   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)
-------------------------------------------------------------------------- */
-
-void Neighbor::half_full_newton()
-{
-  int i,j,k,n,nfull;
-  int *neighptr,*neighs;
-  double xtmp,ytmp,ztmp;
-
-  double **x = atom->x;
-  int nlocal = atom->nlocal;
-
-  int npage = 0;
-  int npnt = 0;
-
-  for (i = 0; i < nlocal; i++) {
-
-    if (pgsize - npnt < oneatom) {
-      npnt = 0;
-      npage++;
-      if (npage == maxpage) add_pages(npage);
-    }
-
-    neighptr = &pages[npage][npnt];
-    n = 0;
-
-    xtmp = x[i][0];
-    ytmp = x[i][1];
-    ztmp = x[i][2];
-
-    // loop over full neighbor list
-
-    neighs = firstneigh_full[i];
-    nfull = numneigh_full[i];
-
-    for (k = 0; k < nfull; k++) {
-      j = neighs[k];
-      if (j < nlocal) {
-	if (i > j) continue;
-      } else {
-	if (x[j][2] < ztmp) continue;
-	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
-	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
-      }
-      neighptr[n++] = j;
-    }
-
-    firstneigh[i] = neighptr;
-    numneigh[i] = n;
-    npnt += n;
-    if (npnt >= pgsize)
-      error->one("Neighbor list overflow, boost neigh_modify one or page");
-  }
-}
diff --git a/src/neigh_respa.cpp b/src/neigh_respa.cpp
index a37275f37b5ae0a7c1e00ed841a75e315e2df5bb..38bb3232e7fb03286609b49e6a83d90ef5a404f4 100644
--- a/src/neigh_respa.cpp
+++ b/src/neigh_respa.cpp
@@ -12,6 +12,7 @@
 ------------------------------------------------------------------------- */
 
 #include "neighbor.h"
+#include "neigh_list.h"
 #include "atom.h"
 #include "error.h"
 
@@ -24,14 +25,11 @@ using namespace LAMMPS_NS;
    pair added if j is ghost (also stored by proc owning j)
 ------------------------------------------------------------------------- */
 
-void Neighbor::respa_nsq_no_newton()
+void Neighbor::respa_nsq_no_newton(NeighList *list)
 {
-  int i,j,itype,jtype,which;
-  int n_inner,n_middle,n;
+  int i,j,n,itype,jtype,which,n_inner,n_middle;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr_inner;
-  int *neighptr_middle;
-  int *neighptr;
+  int *neighptr,*neighptr_inner,*neighptr_middle;
 
   double **x = atom->x;
   int *type = atom->type;
@@ -41,6 +39,27 @@ void Neighbor::respa_nsq_no_newton()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+
+  NeighList *listinner = list->listinner;
+  int *numneigh_inner = listinner->numneigh;
+  int **firstneigh_inner = listinner->firstneigh;
+  int **pages_inner = listinner->pages;
+
+  NeighList *listmiddle;
+  int *numneigh_middle,**firstneigh_middle,**pages_middle;
+  int respamiddle = list->respamiddle;
+  if (respamiddle) {
+    listmiddle = list->listmiddle;
+    numneigh_middle = listmiddle->numneigh;
+    firstneigh_middle = listmiddle->firstneigh;
+    pages_middle = listmiddle->pages;
+  }
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
   int npage_inner = 0;
@@ -53,7 +72,7 @@ void Neighbor::respa_nsq_no_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
     neighptr = &pages[npage][npnt];
     n = 0;
@@ -61,16 +80,18 @@ void Neighbor::respa_nsq_no_newton()
     if (pgsize - npnt_inner < oneatom) {
       npnt_inner = 0;
       npage_inner++;
-      if (npage_inner == maxpage_inner) add_pages_inner(npage_inner);
+      if (npage_inner == listinner->maxpage)
+	pages_inner = listinner->add_pages();
     }
     neighptr_inner = &pages_inner[npage_inner][npnt_inner];
     n_inner = 0;
 
-    if (respa == 2) {
+    if (respamiddle) {
       if (pgsize - npnt_middle < oneatom) {
 	npnt_middle = 0;
 	npage_middle++;
-	if (npage_middle == maxpage_middle) add_pages_middle(npage_middle);
+	if (npage_middle == listmiddle->maxpage)
+	  pages_middle = listmiddle->add_pages();
       }
       neighptr_middle = &pages_middle[npage_middle][npnt_middle];
       n_middle = 0;
@@ -84,9 +105,9 @@ void Neighbor::respa_nsq_no_newton()
     // loop over remaining atoms, owned and ghost
 
     for (j = i+1; j < nall; j++) {
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
       jtype = type[j];
+      if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
       delx = xtmp - x[j][0];
       dely = ytmp - x[j][1];
       delz = ztmp - x[j][2];
@@ -103,15 +124,17 @@ void Neighbor::respa_nsq_no_newton()
 	  else if (which > 0) neighptr_inner[n_inner++] = which*nall + j;
         }
 
-        if (respa == 2 && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
+        if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
 	  if (which == 0) neighptr_middle[n_middle++] = j;
 	  else if (which > 0) neighptr_middle[n_middle++] = which*nall + j;
         }
       }
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
@@ -122,7 +145,7 @@ void Neighbor::respa_nsq_no_newton()
     if (npnt_inner >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
 
-    if (respa == 2) {
+    if (respamiddle) {
       firstneigh_middle[i] = neighptr_middle;
       numneigh_middle[i] = n_middle;
       npnt_middle += n_middle;
@@ -130,6 +153,8 @@ void Neighbor::respa_nsq_no_newton()
 	error->one("Neighbor list overflow, boost neigh_modify one or page");
     }
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -140,14 +165,11 @@ void Neighbor::respa_nsq_no_newton()
    decision based on itag,jtag tests
 ------------------------------------------------------------------------- */
 
-void Neighbor::respa_nsq_newton()
+void Neighbor::respa_nsq_newton(NeighList *list)
 {
-  int i,j,itype,jtype,itag,jtag,which;
-  int n_inner,n_middle,n;
+  int i,j,n,itype,jtype,itag,jtag,which,n_inner,n_middle;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr_inner;
-  int *neighptr_middle;
-  int *neighptr;
+  int *neighptr,*neighptr_inner,*neighptr_middle;
 
   double **x = atom->x;
   int *tag = atom->tag;
@@ -158,6 +180,27 @@ void Neighbor::respa_nsq_newton()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+
+  NeighList *listinner = list->listinner;
+  int *numneigh_inner = listinner->numneigh;
+  int **firstneigh_inner = listinner->firstneigh;
+  int **pages_inner = listinner->pages;
+
+  NeighList *listmiddle;
+  int *numneigh_middle,**firstneigh_middle,**pages_middle;
+  int respamiddle = list->respamiddle;
+  if (respamiddle) {
+    listmiddle = list->listmiddle;
+    numneigh_middle = listmiddle->numneigh;
+    firstneigh_middle = listmiddle->firstneigh;
+    pages_middle = listmiddle->pages;
+  }
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
   int npage_inner = 0;
@@ -170,7 +213,7 @@ void Neighbor::respa_nsq_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
     neighptr = &pages[npage][npnt];
     n = 0;
@@ -178,16 +221,18 @@ void Neighbor::respa_nsq_newton()
     if (pgsize - npnt_inner < oneatom) {
       npnt_inner = 0;
       npage_inner++;
-      if (npage_inner == maxpage_inner) add_pages_inner(npage_inner);
+      if (npage_inner == listinner->maxpage)
+	pages_inner = listinner->add_pages();
     }
     neighptr_inner = &pages_inner[npage_inner][npnt_inner];
     n_inner = 0;
 
-    if (respa == 2) {
+    if (respamiddle) {
       if (pgsize - npnt_middle < oneatom) {
 	npnt_middle = 0;
 	npage_middle++;
-	if (npage_middle == maxpage_middle) add_pages_middle(npage_middle);
+	if (npage_middle == listmiddle->maxpage)
+	  pages_middle = listmiddle->add_pages();
       }
       neighptr_middle = &pages_middle[npage_middle][npnt_middle];
       n_middle = 0;
@@ -216,9 +261,9 @@ void Neighbor::respa_nsq_newton()
 	}
       }
 
-      if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
       jtype = type[j];
+      if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
       delx = xtmp - x[j][0];
       dely = ytmp - x[j][1];
       delz = ztmp - x[j][2];
@@ -235,15 +280,18 @@ void Neighbor::respa_nsq_newton()
 	  else if (which > 0) neighptr_inner[n_inner++] = which*nall + j;
         }
 
-        if (respa == 2 && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
+        if (respamiddle && 
+	    rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
 	  if (which == 0) neighptr_middle[n_middle++] = j;
 	  else if (which > 0) neighptr_middle[n_middle++] = which*nall + j;
         }
       }
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
@@ -254,7 +302,7 @@ void Neighbor::respa_nsq_newton()
     if (npnt_inner >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
 
-    if (respa == 2) {
+    if (respamiddle) {
       firstneigh_middle[i] = neighptr_middle;
       numneigh_middle[i] = n_middle;
       npnt_middle += n_middle;
@@ -262,6 +310,8 @@ void Neighbor::respa_nsq_newton()
 	error->one("Neighbor list overflow, boost neigh_modify one or page");
     }
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -272,14 +322,11 @@ void Neighbor::respa_nsq_newton()
    pair stored by me if j is ghost (also stored by proc owning j)
 ------------------------------------------------------------------------- */
 
-void Neighbor::respa_bin_no_newton()
+void Neighbor::respa_bin_no_newton(NeighList *list)
 {
-  int i,j,k,itype,jtype,ibin,which;
-  int n_inner,n_middle,n;
+  int i,j,k,n,itype,jtype,ibin,which,n_inner,n_middle;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr_inner;
-  int *neighptr_middle;
-  int *neighptr;
+  int *neighptr,*neighptr_inner,*neighptr_middle;
 
   // bin local & ghost atoms
 
@@ -295,6 +342,29 @@ void Neighbor::respa_bin_no_newton()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  NeighList *listinner = list->listinner;
+  int *numneigh_inner = listinner->numneigh;
+  int **firstneigh_inner = listinner->firstneigh;
+  int **pages_inner = listinner->pages;
+
+  NeighList *listmiddle;
+  int *numneigh_middle,**firstneigh_middle,**pages_middle;
+  int respamiddle = list->respamiddle;
+  if (respamiddle) {
+    listmiddle = list->listmiddle;
+    numneigh_middle = listmiddle->numneigh;
+    firstneigh_middle = listmiddle->firstneigh;
+    pages_middle = listmiddle->pages;
+  }
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
   int npage_inner = 0;
@@ -307,7 +377,7 @@ void Neighbor::respa_bin_no_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
     neighptr = &pages[npage][npnt];
     n = 0;
@@ -315,16 +385,18 @@ void Neighbor::respa_bin_no_newton()
     if (pgsize - npnt_inner < oneatom) {
       npnt_inner = 0;
       npage_inner++;
-      if (npage_inner == maxpage_inner) add_pages_inner(npage_inner);
+      if (npage_inner == listinner->maxpage)
+	pages_inner = listinner->add_pages();
     }
     neighptr_inner = &pages_inner[npage_inner][npnt_inner];
     n_inner = 0;
 
-    if (respa == 2) {
+    if (respamiddle) {
       if (pgsize - npnt_middle < oneatom) {
 	npnt_middle = 0;
 	npage_middle++;
-	if (npage_middle == maxpage_middle) add_pages_middle(npage_middle);
+	if (npage_middle == listmiddle->maxpage)
+	  pages_middle = listmiddle->add_pages();
       }
       neighptr_middle = &pages_middle[npage_middle][npnt_middle];
       n_middle = 0;
@@ -344,9 +416,10 @@ void Neighbor::respa_bin_no_newton()
     for (k = 0; k < nstencil; k++) {
       for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
 	if (j <= i) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
 
 	jtype = type[j];
+	if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
 	delz = ztmp - x[j][2];
@@ -363,7 +436,8 @@ void Neighbor::respa_bin_no_newton()
 	    else if (which > 0) neighptr_inner[n_inner++] = which*nall + j;
 	  }
 
-	  if (respa == 2 && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
+	  if (respamiddle && 
+	      rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
 	    if (which == 0) neighptr_middle[n_middle++] = j;
 	    else if (which > 0) neighptr_middle[n_middle++] = which*nall + j;
 	  }
@@ -371,8 +445,10 @@ void Neighbor::respa_bin_no_newton()
       }
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
@@ -383,7 +459,7 @@ void Neighbor::respa_bin_no_newton()
     if (npnt_inner >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
 
-    if (respa == 2) {
+    if (respamiddle) {
       firstneigh_middle[i] = neighptr_middle;
       numneigh_middle[i] = n_middle;
       npnt_middle += n_middle;
@@ -391,6 +467,8 @@ void Neighbor::respa_bin_no_newton()
 	error->one("Neighbor list overflow, boost neigh_modify one or page");
     }
   }
+
+  list->inum = inum;
 }
       
 /* ----------------------------------------------------------------------
@@ -400,14 +478,11 @@ void Neighbor::respa_bin_no_newton()
    every pair stored exactly once by some processor
 ------------------------------------------------------------------------- */
 
-void Neighbor::respa_bin_newton()
+void Neighbor::respa_bin_newton(NeighList *list)
 {
-  int i,j,k,itype,jtype,ibin,which;
-  int n_inner,n_middle,n;
+  int i,j,k,n,itype,jtype,ibin,which,n_inner,n_middle;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr_inner;
-  int *neighptr_middle;
-  int *neighptr;
+  int *neighptr,*neighptr_inner,*neighptr_middle;
 
   // bin local & ghost atoms
 
@@ -423,6 +498,29 @@ void Neighbor::respa_bin_newton()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  NeighList *listinner = list->listinner;
+  int *numneigh_inner = listinner->numneigh;
+  int **firstneigh_inner = listinner->firstneigh;
+  int **pages_inner = listinner->pages;
+
+  NeighList *listmiddle;
+  int *numneigh_middle,**firstneigh_middle,**pages_middle;
+  int respamiddle = list->respamiddle;
+  if (respamiddle) {
+    listmiddle = list->listmiddle;
+    numneigh_middle = listmiddle->numneigh;
+    firstneigh_middle = listmiddle->firstneigh;
+    pages_middle = listmiddle->pages;
+  }
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
   int npage_inner = 0;
@@ -435,7 +533,7 @@ void Neighbor::respa_bin_newton()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
     neighptr = &pages[npage][npnt];
     n = 0;
@@ -443,16 +541,18 @@ void Neighbor::respa_bin_newton()
     if (pgsize - npnt_inner < oneatom) {
       npnt_inner = 0;
       npage_inner++;
-      if (npage_inner == maxpage_inner) add_pages_inner(npage_inner);
+      if (npage_inner == listinner->maxpage)
+	pages_inner = listinner->add_pages();
     }
     neighptr_inner = &pages_inner[npage_inner][npnt_inner];
     n_inner = 0;
 
-    if (respa == 2) {
+    if (respamiddle) {
       if (pgsize - npnt_middle < oneatom) {
 	npnt_middle = 0;
 	npage_middle++;
-	if (npage_middle == maxpage_middle) add_pages_middle(npage_middle);
+	if (npage_middle == listmiddle->maxpage)
+	  pages_middle = listmiddle->add_pages();
       }
       neighptr_middle = &pages_middle[npage_middle][npnt_middle];
       n_middle = 0;
@@ -472,10 +572,11 @@ void Neighbor::respa_bin_newton()
 	if (x[j][2] < ztmp) continue;
 	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
 	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
       }
 
       jtype = type[j];
+      if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
       delx = xtmp - x[j][0];
       dely = ytmp - x[j][1];
       delz = ztmp - x[j][2];
@@ -492,7 +593,8 @@ void Neighbor::respa_bin_newton()
 	  else if (which > 0) neighptr_inner[n_inner++] = which*nall + j;
         }
 
-        if (respa == 2 && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
+        if (respamiddle && 
+	    rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
 	  if (which == 0) neighptr_middle[n_middle++] = j;
 	  else if (which > 0) neighptr_middle[n_middle++] = which*nall + j;
         }
@@ -504,9 +606,9 @@ void Neighbor::respa_bin_newton()
     ibin = coord2bin(x[i]);
     for (k = 0; k < nstencil; k++) {
       for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
-
 	jtype = type[j];
+	if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
 	delz = ztmp - x[j][2];
@@ -523,7 +625,8 @@ void Neighbor::respa_bin_newton()
 	    else if (which > 0) neighptr_inner[n_inner++] = which*nall + j;
 	  }
 
-	  if (respa == 2 && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
+	  if (respamiddle && 
+	      rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
 	    if (which == 0) neighptr_middle[n_middle++] = j;
 	    else if (which > 0) neighptr_middle[n_middle++] = which*nall + j;
 	  }
@@ -531,8 +634,10 @@ void Neighbor::respa_bin_newton()
       }
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
@@ -543,7 +648,7 @@ void Neighbor::respa_bin_newton()
     if (npnt_inner >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
 
-    if (respa == 2) {
+    if (respamiddle) {
       firstneigh_middle[i] = neighptr_middle;
       numneigh_middle[i] = n_middle;
       npnt_middle += n_middle;
@@ -551,6 +656,8 @@ void Neighbor::respa_bin_newton()
 	error->one("Neighbor list overflow, boost neigh_modify one or page");
     }
   }
+
+  list->inum = inum;
 }
 
 /* ----------------------------------------------------------------------
@@ -560,14 +667,11 @@ void Neighbor::respa_bin_newton()
    every pair stored exactly once by some processor
 ------------------------------------------------------------------------- */
 
-void Neighbor::respa_bin_newton_tri()
+void Neighbor::respa_bin_newton_tri(NeighList *list)
 {
-  int i,j,k,itype,jtype,ibin,which;
-  int n_inner,n_middle,n;
+  int i,j,k,n,itype,jtype,ibin,which,n_inner,n_middle;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
-  int *neighptr_inner;
-  int *neighptr_middle;
-  int *neighptr;
+  int *neighptr,*neighptr_inner,*neighptr_middle;
 
   // bin local & ghost atoms
 
@@ -583,6 +687,29 @@ void Neighbor::respa_bin_newton_tri()
   int nall = atom->nlocal + atom->nghost;
   int molecular = atom->molecular;
 
+  int *ilist = list->ilist;
+  int *numneigh = list->numneigh;
+  int **firstneigh = list->firstneigh;
+  int **pages = list->pages;
+  int nstencil = list->nstencil;
+  int *stencil = list->stencil;
+
+  NeighList *listinner = list->listinner;
+  int *numneigh_inner = listinner->numneigh;
+  int **firstneigh_inner = listinner->firstneigh;
+  int **pages_inner = listinner->pages;
+
+  NeighList *listmiddle;
+  int *numneigh_middle,**firstneigh_middle,**pages_middle;
+  int respamiddle = list->respamiddle;
+  if (respamiddle) {
+    listmiddle = list->listmiddle;
+    numneigh_middle = listmiddle->numneigh;
+    firstneigh_middle = listmiddle->firstneigh;
+    pages_middle = listmiddle->pages;
+  }
+
+  int inum = 0;
   int npage = 0;
   int npnt = 0;
   int npage_inner = 0;
@@ -595,7 +722,7 @@ void Neighbor::respa_bin_newton_tri()
     if (pgsize - npnt < oneatom) {
       npnt = 0;
       npage++;
-      if (npage == maxpage) add_pages(npage);
+      if (npage == list->maxpage) pages = list->add_pages();
     }
     neighptr = &pages[npage][npnt];
     n = 0;
@@ -603,16 +730,18 @@ void Neighbor::respa_bin_newton_tri()
     if (pgsize - npnt_inner < oneatom) {
       npnt_inner = 0;
       npage_inner++;
-      if (npage_inner == maxpage_inner) add_pages_inner(npage_inner);
+      if (npage_inner == listinner->maxpage)
+	pages_inner = listinner->add_pages();
     }
     neighptr_inner = &pages_inner[npage_inner][npnt_inner];
     n_inner = 0;
 
-    if (respa == 2) {
+    if (respamiddle) {
       if (pgsize - npnt_middle < oneatom) {
 	npnt_middle = 0;
 	npage_middle++;
-	if (npage_middle == maxpage_middle) add_pages_middle(npage_middle);
+	if (npage_middle == listmiddle->maxpage)
+	  pages_middle = listmiddle->add_pages();
       }
       neighptr_middle = &pages_middle[npage_middle][npnt_middle];
       n_middle = 0;
@@ -634,9 +763,10 @@ void Neighbor::respa_bin_newton_tri()
 	if (x[j][2] < ztmp) continue;
 	if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
 	if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] <= xtmp) continue;
-	if (exclude && exclusion(i,j,type,mask,molecule)) continue;
 
 	jtype = type[j];
+	if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
+
 	delx = xtmp - x[j][0];
 	dely = ytmp - x[j][1];
 	delz = ztmp - x[j][2];
@@ -653,7 +783,8 @@ void Neighbor::respa_bin_newton_tri()
 	    else if (which > 0) neighptr_inner[n_inner++] = which*nall + j;
 	  }
 
-	  if (respa == 2 && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
+	  if (respamiddle &&
+	      rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
 	    if (which == 0) neighptr_middle[n_middle++] = j;
 	    else if (which > 0) neighptr_middle[n_middle++] = which*nall + j;
 	  }
@@ -661,8 +792,10 @@ void Neighbor::respa_bin_newton_tri()
       }
     }
 
+    ilist[inum] = i;
     firstneigh[i] = neighptr;
     numneigh[i] = n;
+    inum++;
     npnt += n;
     if (npnt >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
@@ -673,7 +806,7 @@ void Neighbor::respa_bin_newton_tri()
     if (npnt_inner >= pgsize)
       error->one("Neighbor list overflow, boost neigh_modify one or page");
 
-    if (respa == 2) {
+    if (respamiddle) {
       firstneigh_middle[i] = neighptr_middle;
       numneigh_middle[i] = n_middle;
       npnt_middle += n_middle;
@@ -681,4 +814,6 @@ void Neighbor::respa_bin_newton_tri()
 	error->one("Neighbor list overflow, boost neigh_modify one or page");
     }
   }
+
+  list->inum = inum;
 }
diff --git a/src/neigh_stencil.cpp b/src/neigh_stencil.cpp
index 89f8895c27f0042dd9c502ebd48df9f194db27bb..7f2170a022e1c9a7138c1ca6f0ba12546a0b5f78 100644
--- a/src/neigh_stencil.cpp
+++ b/src/neigh_stencil.cpp
@@ -12,29 +12,29 @@
 ------------------------------------------------------------------------- */
 
 #include "neighbor.h"
+#include "neigh_list.h"
 #include "atom.h"
 #include "memory.h"
 
 using namespace LAMMPS_NS;
 
-enum{NSQ,BIN,MULTI};     // also in neighbor.cpp
-
 /* ----------------------------------------------------------------------
    routines to create a stencil = list of bin offsets
    stencil = bins whose closest corner to central bin is within cutoff
    sx,sy,sz = bin bounds = furthest the stencil could possibly extend
    3d creates xyz stencil, 2d creates xy stencil
-   for half neigh list with partial Newton:
+   for half list with newton off:
      stencil is all surrounding bins
      stencil includes self
-   for half neigh list with full Newton:
+     regardless of triclinic
+   for half list with newton on:
      stencil is bins to the "upper right" of central bin
      stencil does not include self
-   for half neigh list with triclinic:
+   for half list with triclinic:
      stencil is all bins in z-plane of self and above, but not below
      in 2d is all bins in y-plane of self and above, but not below
      stencil includes self
-   for full neigh list:
+   for full list:
      stencil is all surrounding bins including self
      regardless of newton on/off or triclinic
    for multi:
@@ -45,139 +45,65 @@ enum{NSQ,BIN,MULTI};     // also in neighbor.cpp
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_allocate(int sx, int sy, int sz)
+void Neighbor::stencil_half_bin_2d_no_newton(NeighList *list,
+					     int sx, int sy, int sz)
 {
-  int i;
-
-  // for 2d, sz = 0
-
-  int nmax = (2*sz+1) * (2*sy+1) * (2*sx+1);
-
-  if (half) {
-    if (style == BIN) {
-      if (nmax > maxstencil) {
-	maxstencil = nmax;
-	memory->sfree(stencil);
-	stencil = (int *) memory->smalloc(nmax*sizeof(int),"neigh:stencil");
-      }
-
-    } else {
-      int n = atom->ntypes;
-      if (nstencil_multi == NULL) {
-	maxstencil_multi = 0;
-	nstencil_multi = new int[n+1];
-	stencil_multi = new int*[n+1];
-	distsq_multi = new double*[n+1];
-	for (i = 1; i <= n; i++) {
-	  nstencil_multi[i] = 0;
-	  stencil_multi[i] = NULL;
-	  distsq_multi[i] = NULL;
-	}
-      }
-      if (nmax > maxstencil_multi) {
-	maxstencil_multi = nmax;
-	for (int i = 1; i <= n; i++) {
-	  memory->sfree(stencil_multi[i]);
-	  memory->sfree(distsq_multi[i]);
-	  stencil_multi[i] = (int *)
-	    memory->smalloc(nmax*sizeof(int),"neigh:stencil_multi");
-	  distsq_multi[i] = (double *) memory->smalloc(nmax*sizeof(double),
-						       "neigh:distsq_multi");
-	}
-      }
-    }
-  }
+  int i,j;
+  int *stencil = list->stencil;
+  int nstencil = 0;
 
-  if (full) {
-    if (style == BIN) {
-      if (nmax > maxstencil_full) {
-	maxstencil_full = nmax;
-	memory->sfree(stencil_full);
-	stencil_full = (int *) memory->smalloc(nmax*sizeof(int),
-					       "neigh:stencil_full");
-      }
+  for (j = -sy; j <= sy; j++)
+    for (i = -sx; i <= sx; i++)
+      if (bin_distance(i,j,0) < cutneighmaxsq)
+	stencil[nstencil++] = j*mbinx + i;
 
-    } else {
-      int n = atom->ntypes;
-      if (nstencil_full_multi == NULL) {
-	maxstencil_full_multi = 0;
-	nstencil_full_multi = new int[n+1];
-	stencil_full_multi = new int*[n+1];
-	distsq_full_multi = new double*[n+1];
-	for (i = 1; i <= n; i++) {
-	  nstencil_full_multi[i] = 0;
-	  stencil_full_multi[i] = NULL;
-	  distsq_full_multi[i] = NULL;
-	}
-      }
-      if (nmax > maxstencil_full_multi) {
-	maxstencil_full_multi = nmax;
-	for (int i = 1; i <= n; i++) {
-	  memory->sfree(stencil_full_multi[i]);
-	  memory->sfree(distsq_full_multi[i]);
-	  stencil_full_multi[i] = (int *)
-	    memory->smalloc(nmax*sizeof(int),"neigh:stencil_full_multi");
-	  distsq_full_multi[i] = 
-	    (double *) memory->smalloc(nmax*sizeof(double),
-				       "neigh:distsq_full_multi");
-	}
-      }
-    }
-  }
+  list->nstencil = nstencil;
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_none(int sx, int sy, int sz) {}
-
-/* ---------------------------------------------------------------------- */
-
-void Neighbor::stencil_half_3d_no_newton(int sx, int sy, int sz)
+void Neighbor::stencil_half_bin_3d_no_newton(NeighList *list,
+					     int sx, int sy, int sz)
 {
   int i,j,k;
-  nstencil = 0;
+  int *stencil = list->stencil;
+  int nstencil = 0;
 
   for (k = -sz; k <= sz; k++)
     for (j = -sy; j <= sy; j++)
       for (i = -sx; i <= sx; i++)
 	if (bin_distance(i,j,k) < cutneighmaxsq)
 	  stencil[nstencil++] = k*mbiny*mbinx + j*mbinx + i;
+
+  list->nstencil = nstencil;
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_3d_no_newton_multi(int sx, int sy, int sz)
+void Neighbor::stencil_half_bin_2d_newton(NeighList *list,
+					  int sx, int sy, int sz)
 {
-  int i,j,k,n;
-  double rsq,typesq;
-  int *s;
-  double *distsq;
+  int i,j;
+  int *stencil = list->stencil;
+  int nstencil = 0;
 
-  int ntypes = atom->ntypes;
-  for (int itype = 1; itype <= ntypes; itype++) {
-    typesq = cuttypesq[itype];
-    s = stencil_multi[itype];
-    distsq = distsq_multi[itype];
-    n = 0;
-    for (k = -sz; k <= sz; k++)
-      for (j = -sy; j <= sy; j++)
-	for (i = -sx; i <= sx; i++) {
-	  rsq = bin_distance(i,j,k);
-	  if (rsq < typesq) {
-	    distsq[n] = rsq;
-	    s[n++] = k*mbiny*mbinx + j*mbinx + i;
-	  }
-	}
-    nstencil_multi[itype] = n;
-  }
+  for (j = 0; j <= sy; j++)
+    for (i = -sx; i <= sx; i++)
+      if (j > 0 || (j == 0 && i > 0))
+	if (bin_distance(i,j,0) < cutneighmaxsq)
+	  stencil[nstencil++] = j*mbinx + i;
+
+  list->nstencil = nstencil;
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_3d_newton(int sx, int sy, int sz)
+void Neighbor::stencil_half_bin_3d_newton(NeighList *list,
+					  int sx, int sy, int sz)
 {
   int i,j,k;
-  nstencil = 0;
+  int *stencil = list->stencil;
+  int nstencil = 0;
 
   for (k = 0; k <= sz; k++)
     for (j = -sy; j <= sy; j++)
@@ -185,142 +111,124 @@ void Neighbor::stencil_half_3d_newton(int sx, int sy, int sz)
 	if (k > 0 || j > 0 || (j == 0 && i > 0))
 	  if (bin_distance(i,j,k) < cutneighmaxsq)
 	    stencil[nstencil++] = k*mbiny*mbinx + j*mbinx + i;
+
+  list->nstencil = nstencil;
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_3d_newton_multi(int sx, int sy, int sz)
+void Neighbor::stencil_half_bin_2d_newton_tri(NeighList *list,
+					      int sx, int sy, int sz)
 {
-  int i,j,k,n;
-  double rsq,typesq;
-  int *s;
-  double *distsq;
+  int i,j;
+  int *stencil = list->stencil;
+  int nstencil = 0;
 
-  int ntypes = atom->ntypes;
-  for (int itype = 1; itype <= ntypes; itype++) {
-    typesq = cuttypesq[itype];
-    s = stencil_multi[itype];
-    distsq = distsq_multi[itype];
-    n = 0;
-    for (k = 0; k <= sz; k++)
-      for (j = -sy; j <= sy; j++)
-	for (i = -sx; i <= sx; i++)
-	  if (k > 0 || j > 0 || (j == 0 && i > 0)) {
-	    rsq = bin_distance(i,j,k);
-	    if (rsq < typesq) {
-	      distsq[n] = rsq;
-	      s[n++] = k*mbiny*mbinx + j*mbinx + i;
-	    }
-	  }
-    nstencil_multi[itype] = n;
-  }
+  for (j = 0; j <= sy; j++)
+    for (i = -sx; i <= sx; i++)
+      if (bin_distance(i,j,0) < cutneighmaxsq)
+	stencil[nstencil++] = j*mbinx + i;
+
+  list->nstencil = nstencil;
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_3d_newton_tri(int sx, int sy, int sz)
+void Neighbor::stencil_half_bin_3d_newton_tri(NeighList *list,
+					      int sx, int sy, int sz)
 {
   int i,j,k;
-  nstencil = 0;
+  int *stencil = list->stencil;
+  int nstencil = 0;
 
   for (k = 0; k <= sz; k++)
     for (j = -sy; j <= sy; j++)
       for (i = -sx; i <= sx; i++)
 	if (bin_distance(i,j,k) < cutneighmaxsq)
 	  stencil[nstencil++] = k*mbiny*mbinx + j*mbinx + i;
+
+  list->nstencil = nstencil;
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_3d_newton_multi_tri(int sx, int sy, int sz)
+void Neighbor::stencil_half_multi_2d_no_newton(NeighList *list,
+					       int sx, int sy, int sz)
 {
-  int i,j,k,n;
+  int i,j,n;
   double rsq,typesq;
   int *s;
   double *distsq;
 
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
   int ntypes = atom->ntypes;
   for (int itype = 1; itype <= ntypes; itype++) {
     typesq = cuttypesq[itype];
     s = stencil_multi[itype];
     distsq = distsq_multi[itype];
     n = 0;
-    for (k = 0; k <= sz; k++)
-      for (j = -sy; j <= sy; j++)
-	for (i = -sx; i <= sx; i++) {
-	  rsq = bin_distance(i,j,k);
-	  if (rsq < typesq) {
-	    distsq[n] = rsq;
-	    s[n++] = k*mbiny*mbinx + j*mbinx + i;
-	  }
+    for (j = -sy; j <= sy; j++)
+      for (i = -sx; i <= sx; i++) {
+	rsq = bin_distance(i,j,0);
+	if (rsq < typesq) {
+	  distsq[n] = rsq;
+	  s[n++] = j*mbinx + i;
 	}
+      }
     nstencil_multi[itype] = n;
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_2d_no_newton(int sx, int sy, int sz)
+void Neighbor::stencil_half_multi_3d_no_newton(NeighList *list,
+					       int sx, int sy, int sz)
 {
-  int i,j;
-  nstencil = 0;
-
-  for (j = -sy; j <= sy; j++)
-    for (i = -sx; i <= sx; i++)
-      if (bin_distance(i,j,0) < cutneighmaxsq)
-	stencil[nstencil++] = j*mbinx + i;
-}
-
-/* ---------------------------------------------------------------------- */
-
-void Neighbor::stencil_half_2d_no_newton_multi(int sx, int sy, int sz)
-{
-  int i,j,n;
+  int i,j,k,n;
   double rsq,typesq;
   int *s;
   double *distsq;
 
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
   int ntypes = atom->ntypes;
   for (int itype = 1; itype <= ntypes; itype++) {
     typesq = cuttypesq[itype];
     s = stencil_multi[itype];
     distsq = distsq_multi[itype];
     n = 0;
-    for (j = -sy; j <= sy; j++)
-      for (i = -sx; i <= sx; i++) {
-	rsq = bin_distance(i,j,0);
-	if (rsq < typesq) {
-	  distsq[n] = rsq;
-	  s[n++] = j*mbinx + i;
+    for (k = -sz; k <= sz; k++)
+      for (j = -sy; j <= sy; j++)
+	for (i = -sx; i <= sx; i++) {
+	  rsq = bin_distance(i,j,k);
+	  if (rsq < typesq) {
+	    distsq[n] = rsq;
+	    s[n++] = k*mbiny*mbinx + j*mbinx + i;
+	  }
 	}
-      }
     nstencil_multi[itype] = n;
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_2d_newton(int sx, int sy, int sz)
-{
-  int i,j;
-  nstencil = 0;
-
-  for (j = 0; j <= sy; j++)
-    for (i = -sx; i <= sx; i++)
-      if (j > 0 || (j == 0 && i > 0))
-	if (bin_distance(i,j,0) < cutneighmaxsq)
-	  stencil[nstencil++] = j*mbinx + i;
-}
-
-/* ---------------------------------------------------------------------- */
-
-void Neighbor::stencil_half_2d_newton_multi(int sx, int sy, int sz)
+void Neighbor::stencil_half_multi_2d_newton(NeighList *list,
+					    int sx, int sy, int sz)
 {
   int i,j,n;
   double rsq,typesq;
   int *s;
   double *distsq;
 
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
   int ntypes = atom->ntypes;
   for (int itype = 1; itype <= ntypes; itype++) {
     typesq = cuttypesq[itype];
@@ -342,26 +250,52 @@ void Neighbor::stencil_half_2d_newton_multi(int sx, int sy, int sz)
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_2d_newton_tri(int sx, int sy, int sz)
+void Neighbor::stencil_half_multi_3d_newton(NeighList *list,
+					    int sx, int sy, int sz)
 {
-  int i,j;
-  nstencil = 0;
+  int i,j,k,n;
+  double rsq,typesq;
+  int *s;
+  double *distsq;
 
-  for (j = 0; j <= sy; j++)
-    for (i = -sx; i <= sx; i++)
-      if (bin_distance(i,j,0) < cutneighmaxsq)
-	stencil[nstencil++] = j*mbinx + i;
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
+  int ntypes = atom->ntypes;
+  for (int itype = 1; itype <= ntypes; itype++) {
+    typesq = cuttypesq[itype];
+    s = stencil_multi[itype];
+    distsq = distsq_multi[itype];
+    n = 0;
+    for (k = 0; k <= sz; k++)
+      for (j = -sy; j <= sy; j++)
+	for (i = -sx; i <= sx; i++)
+	  if (k > 0 || j > 0 || (j == 0 && i > 0)) {
+	    rsq = bin_distance(i,j,k);
+	    if (rsq < typesq) {
+	      distsq[n] = rsq;
+	      s[n++] = k*mbiny*mbinx + j*mbinx + i;
+	    }
+	  }
+    nstencil_multi[itype] = n;
+  }
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_half_2d_newton_multi_tri(int sx, int sy, int sz)
+void Neighbor::stencil_half_multi_2d_newton_tri(NeighList *list,
+						int sx, int sy, int sz)
 {
   int i,j,n;
   double rsq,typesq;
   int *s;
   double *distsq;
 
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
   int ntypes = atom->ntypes;
   for (int itype = 1; itype <= ntypes; itype++) {
     typesq = cuttypesq[itype];
@@ -380,36 +314,28 @@ void Neighbor::stencil_half_2d_newton_multi_tri(int sx, int sy, int sz)
   }
 }
 
-/* ---------------------------------------------------------------------- */
-
-void Neighbor::stencil_full_3d(int sx, int sy, int sz)
-{
-  int i,j,k;
-  nstencil_full = 0;
-
-  for (k = -sz; k <= sz; k++)
-    for (j = -sy; j <= sy; j++)
-      for (i = -sx; i <= sx; i++)
-	if (bin_distance(i,j,k) < cutneighmaxsq)
-	  stencil_full[nstencil_full++] = k*mbiny*mbinx + j*mbinx + i;
-}
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_full_3d_multi(int sx, int sy, int sz)
+void Neighbor::stencil_half_multi_3d_newton_tri(NeighList *list,
+						int sx, int sy, int sz)
 {
   int i,j,k,n;
   double rsq,typesq;
   int *s;
   double *distsq;
 
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
   int ntypes = atom->ntypes;
   for (int itype = 1; itype <= ntypes; itype++) {
     typesq = cuttypesq[itype];
-    s = stencil_full_multi[itype];
-    distsq = distsq_full_multi[itype];
+    s = stencil_multi[itype];
+    distsq = distsq_multi[itype];
     n = 0;
-    for (k = -sz; k <= sz; k++)
+    for (k = 0; k <= sz; k++)
       for (j = -sy; j <= sy; j++)
 	for (i = -sx; i <= sx; i++) {
 	  rsq = bin_distance(i,j,k);
@@ -418,37 +344,65 @@ void Neighbor::stencil_full_3d_multi(int sx, int sy, int sz)
 	    s[n++] = k*mbiny*mbinx + j*mbinx + i;
 	  }
 	}
-    nstencil_full_multi[itype] = n;
+    nstencil_multi[itype] = n;
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_full_2d(int sx, int sy, int sz)
+void Neighbor::stencil_full_bin_2d(NeighList *list,
+				   int sx, int sy, int sz)
 {
   int i,j;
-  nstencil_full = 0;
+  int *stencil = list->stencil;
+  int nstencil = 0;
 
   for (j = -sy; j <= sy; j++)
     for (i = -sx; i <= sx; i++)
       if (bin_distance(i,j,0) < cutneighmaxsq)
-	stencil_full[nstencil_full++] = j*mbinx + i;
+	stencil[nstencil++] = j*mbinx + i;
+
+  list->nstencil = nstencil;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void Neighbor::stencil_full_bin_3d(NeighList *list,
+				   int sx, int sy, int sz)
+{
+  int i,j,k;
+  int *stencil = list->stencil;
+  int nstencil = 0;
+
+  for (k = -sz; k <= sz; k++)
+    for (j = -sy; j <= sy; j++)
+      for (i = -sx; i <= sx; i++)
+	if (bin_distance(i,j,k) < cutneighmaxsq)
+	  stencil[nstencil++] = k*mbiny*mbinx + j*mbinx + i;
+
+  list->nstencil = nstencil;
 }
 
+
 /* ---------------------------------------------------------------------- */
 
-void Neighbor::stencil_full_2d_multi(int sx, int sy, int sz)
+void Neighbor::stencil_full_multi_2d(NeighList *list,
+				     int sx, int sy, int sz)
 {
   int i,j,n;
   double rsq,typesq;
   int *s;
   double *distsq;
 
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
   int ntypes = atom->ntypes;
   for (int itype = 1; itype <= ntypes; itype++) {
     typesq = cuttypesq[itype];
-    s = stencil_full_multi[itype];
-    distsq = distsq_full_multi[itype];
+    s = stencil_multi[itype];
+    distsq = distsq_multi[itype];
     n = 0;
     for (j = -sy; j <= sy; j++)
       for (i = -sx; i <= sx; i++) {
@@ -458,6 +412,39 @@ void Neighbor::stencil_full_2d_multi(int sx, int sy, int sz)
 	  s[n++] = j*mbinx + i;
 	}
       }
-    nstencil_full_multi[itype] = n;
+    nstencil_multi[itype] = n;
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void Neighbor::stencil_full_multi_3d(NeighList *list,
+				     int sx, int sy, int sz)
+{
+  int i,j,k,n;
+  double rsq,typesq;
+  int *s;
+  double *distsq;
+
+  int *nstencil_multi = list->nstencil_multi;
+  int **stencil_multi = list->stencil_multi;
+  double **distsq_multi = list->distsq_multi;
+
+  int ntypes = atom->ntypes;
+  for (int itype = 1; itype <= ntypes; itype++) {
+    typesq = cuttypesq[itype];
+    s = stencil_multi[itype];
+    distsq = distsq_multi[itype];
+    n = 0;
+    for (k = -sz; k <= sz; k++)
+      for (j = -sy; j <= sy; j++)
+	for (i = -sx; i <= sx; i++) {
+	  rsq = bin_distance(i,j,k);
+	  if (rsq < typesq) {
+	    distsq[n] = rsq;
+	    s[n++] = k*mbiny*mbinx + j*mbinx + i;
+	  }
+	}
+    nstencil_multi[itype] = n;
   }
 }
diff --git a/src/neighbor.cpp b/src/neighbor.cpp
index dc42db9d52679301249be4e78686b79ac99dba39..4e562b7affd5d949c6ea32822377d58d8d057228 100644
--- a/src/neighbor.cpp
+++ b/src/neighbor.cpp
@@ -21,6 +21,8 @@
 #include "string.h"
 #include "limits.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "atom.h"
 #include "atom_vec.h"
 #include "comm.h"
@@ -39,17 +41,18 @@
 
 using namespace LAMMPS_NS;
 
-#define PGDELTA 1
+#define RQDELTA 1
+#define EXDELTA 1
+
 #define LB_FACTOR 1.5
 #define SMALL 1.0e-6
-#define EXDELTA 1
 #define BIG 1.0e20
 #define CUT2BIN_RATIO 100
 
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 
-enum{NSQ,BIN,MULTI};     // also in neigh_stencil.cpp
+enum{NSQ,BIN,MULTI};     // also in neigh_list.cpp
 
 /* ---------------------------------------------------------------------- */
 
@@ -65,18 +68,23 @@ Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp)
   pgsize = 10000;
   oneatom = 2000;
 
-  maxlocal = 0;
-    
   cutneighsq = NULL;
   cuttype = NULL;
   cuttypesq = NULL;
   fixchecklist = NULL;
 
-  // last neighbor info
+  // coords at last neighboring
 
   maxhold = 0;
   xhold = NULL;
 
+  // binning
+
+  maxhead = 0;
+  binhead = NULL;
+  maxbin = 0;
+  bins = NULL;
+
   // pair exclusion list info
 
   nex_type = maxex_type = 0;
@@ -89,66 +97,24 @@ Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp)
   nex_mol = maxex_mol = 0;
   ex_mol_group = ex_mol_bit = NULL;
 
-  // bin info
-
-  maxhead = 0;
-  binhead = NULL;
-  maxbin = 0;
-  bins = NULL;
-
-  nstencil = maxstencil = 0;
-  stencil = NULL;
-  nstencil_full = maxstencil_full = 0;
-  stencil_full = NULL;
-
-  maxstencil_multi = 0;
-  nstencil_multi = NULL;
-  stencil_multi = NULL;
-  distsq_multi = NULL;
-
-  maxstencil_full_multi = 0;
-  nstencil_full_multi = NULL;
-  stencil_full_multi = NULL;
-  distsq_full_multi = NULL;
-
-  // half neighbor list info
+  // pair lists
 
-  half = half_command = 0;
-  numneigh = NULL;
-  firstneigh = NULL;
-  maxpage = 0;
-  pages = NULL;
-
-  // full neighbor list info
-
-  full = 0;
-  numneigh_full = NULL;
-  firstneigh_full = NULL;
-  maxpage_full = 0;
-  pages_full = NULL;
-
-  // shear history neighbor list info
+  maxlocal = 0;
 
-  fix_history = NULL;
-  firsttouch = NULL;
-  firstshear = NULL;
-  maxpage_history = 0;
-  pages_touch = NULL;
-  pages_shear = NULL;
+  nlist = 0;
+  lists = NULL;
+  pair_build = NULL;
+  stencil_create = NULL;
+  blist = glist = slist = NULL;
 
-  // multiple respa neighbor list info
+  nrequest = maxrequest = 0;
+  requests = NULL;
 
-  respa = 0;
-  numneigh_inner = NULL;
-  firstneigh_inner = NULL;
-  numneigh_middle = NULL;
-  firstneigh_middle = NULL;
-  maxpage_inner = 0;
-  maxpage_middle = 0;
-  pages_inner = NULL;
-  pages_middle = NULL;
+  old_style = BIN;
+  old_nrequest = 0;
+  old_requests = NULL;
 
-  // bond list info
+  // bond lists
 
   maxbond = 0;
   bondlist = NULL;
@@ -167,10 +133,13 @@ Neighbor::~Neighbor()
   memory->destroy_2d_double_array(cutneighsq);
   delete [] cuttype;
   delete [] cuttypesq;
-
   delete [] fixchecklist;
+
   memory->destroy_2d_double_array(xhold);
 
+  memory->sfree(binhead);
+  memory->sfree(bins);
+
   memory->sfree(ex1_type);
   memory->sfree(ex2_type);
   memory->destroy_2d_int_array(ex_type);
@@ -183,54 +152,23 @@ Neighbor::~Neighbor()
   memory->sfree(ex_mol_group);
   delete [] ex_mol_bit;
 
-  memory->sfree(binhead);
-  memory->sfree(bins);
-
-  memory->sfree(stencil);
-  memory->sfree(stencil_full);
+  for (int i = 0; i < nlist; i++) delete lists[i];
+  delete [] lists;
+  delete [] pair_build;
+  delete [] stencil_create;
+  delete [] blist;
+  delete [] glist;
+  delete [] slist;
 
-  if (nstencil_multi) {
-    for (int i = 1; i <= atom->ntypes; i++) {
-      memory->sfree(stencil_multi[i]);
-      memory->sfree(distsq_multi[i]);
-    }
-    delete [] nstencil_multi;
-    delete [] stencil_multi;
-    delete [] distsq_multi;
-  }
-  if (nstencil_full_multi) {
-    for (int i = 1; i <= atom->ntypes; i++) {
-      memory->sfree(stencil_full_multi[i]);
-      memory->sfree(distsq_full_multi[i]);
-    }
-    delete [] nstencil_full_multi;
-    delete [] stencil_full_multi;
-    delete [] distsq_full_multi;
-  }
+  for (int i = 0; i < nrequest; i++) delete requests[i];
+  memory->sfree(requests);
+  for (int i = 0; i < old_nrequest; i++) delete old_requests[i];
+  memory->sfree(old_requests);
 
   memory->destroy_2d_int_array(bondlist);
   memory->destroy_2d_int_array(anglelist);
   memory->destroy_2d_int_array(dihedrallist);
   memory->destroy_2d_int_array(improperlist);
-
-  memory->sfree(numneigh);
-  memory->sfree(firstneigh);
-  clear_pages();
-
-  memory->sfree(numneigh_full);
-  memory->sfree(firstneigh_full);
-  clear_pages_full();
-
-  memory->sfree(firsttouch);
-  memory->sfree(firstshear);
-  clear_pages_history();
-
-  memory->sfree(numneigh_inner);
-  memory->sfree(firstneigh_inner);
-  memory->sfree(numneigh_middle);
-  memory->sfree(firstneigh_middle);
-  clear_pages_inner();
-  clear_pages_middle();
 }
 
 /* ---------------------------------------------------------------------- */
@@ -242,6 +180,7 @@ void Neighbor::init()
   ncalls = ndanger = 0;
   dimension = domain->dimension;
   triclinic = domain->triclinic;
+  newton_pair = force->newton_pair;
 
   // error check
 
@@ -335,8 +274,23 @@ void Neighbor::init()
 
   if (force->kspace) special_flag[1] = special_flag[2] = special_flag[3] = 2;
 
+  // rRESPA cutoffs
+
+  int respa = 0;
+  if (update->whichflag == 0 && strcmp(update->integrate_style,"respa") == 0) {
+    if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
+    if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
+  }
+
+  if (respa) {
+    double *cut_respa = ((Respa *) update->integrate)->cutoff;
+    cut_inner_sq = (cut_respa[1] + skin) * (cut_respa[1] + skin);
+    cut_middle_sq = (cut_respa[3] + skin) * (cut_respa[3] + skin);
+    cut_middle_inside_sq = (cut_respa[0] - skin) * (cut_respa[0] - skin);
+  }
+
   // ------------------------------------------------------------------
-  // memory management
+  // xhold, bins, exclusion lists
 
   // free xhold and bins if not needed for this run
 
@@ -349,9 +303,7 @@ void Neighbor::init()
   if (style == NSQ) {
     memory->sfree(bins);
     memory->sfree(binhead);
-    memory->sfree(stencil);
-    memory->sfree(stencil_full);
-    maxbin = maxhead = maxstencil = maxstencil_full = 0;
+    maxbin = maxhead = 0;
     binhead = NULL;
     bins = NULL;
   }
@@ -417,252 +369,275 @@ void Neighbor::init()
   }
 
   // ------------------------------------------------------------------
-  // neighbor list flags and memory allocation/deallocation
+  // pairwise lists
 
-  // determine whether to build half and full lists
-  // query pair,fix,compute for their requirements
+  // test if pairwise lists need to be re-created
+  // no need to re-create if:
+  // neigh style has not changed and current requests = old requests
 
-  half_once = full_once = 0;
-  half_every = full_every = 0;
-  if (force->pair) half_every = force->pair->neigh_half_every;
-  if (force->pair) full_every = force->pair->neigh_full_every;
+  int same = 1;
+  if (style != old_style) same = 0;
+  if (nrequest != old_nrequest) same = 0;
+  else
+    for (i = 0; i < nrequest; i++)
+      if (requests[i]->identical(old_requests[i]) == 0) same = 0;
 
-  for (i = 0; i < modify->nfix; i++) {
-    if (modify->fix[i]->neigh_half_every) half_every = 1;
-    if (modify->fix[i]->neigh_full_every) full_every = 1;
-    if (modify->fix[i]->neigh_half_once) half_once = 1;
-    if (modify->fix[i]->neigh_full_once) full_once = 1;
-  }
+  printf("SAME %d\n",same);
 
-  for (i = 0; i < modify->ncompute; i++) {
-    if (modify->compute[i]->neigh_half_once) half_once = 1;
-    if (modify->compute[i]->neigh_full_once) full_once = 1;
-  }
+  // if old and new are not the same, create new pairwise lists
 
-  half = full = 0;
-  if (half_every || half_once || half_command) half = 1;
-  if (full_every || full_once) full = 1;
+  if (!same) {
 
-  // determine whether to build granular history lists
-  // fix_history = granular shear history fix
-  
-  fix_history = NULL;
-  if (force->pair_match("gran/history") || force->pair_match("gran/hertzian"))
-    for (i = 0; i < modify->nfix; i++)
-      if (strcmp(modify->fix[i]->style,"SHEAR_HISTORY") == 0) 
-	fix_history = (FixShearHistory *) modify->fix[i];
+    // delete old lists and create new ones
 
-  // determine whether to build extra rRESPA lists
-  // respa = 1,2 if rRESPA requires inner,middle neighbor lists
-  // set neighbor cutoffs for multiple lists
+    for (i = 0; i < nlist; i++) delete lists[i];
+    delete [] lists;
+    delete [] pair_build;
+    delete [] stencil_create;
 
-  respa = 0;
-  if (update->whichflag == 0 && strcmp(update->integrate_style,"respa") == 0) {
-    if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
-    if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
-  }
+    nlist = nrequest;
+    lists = new NeighList*[nlist];
+    pair_build = new PairPtr[nlist];
+    stencil_create = new StencilPtr[nlist];
 
-  if (respa && half_every == 0)
-    error->all("Cannot use rRESPA with full neighbor lists");
+    // create individual lists, one per request
+    // copy dnum setting from request to list
+    // pass list ptr back to requestor (except for Command class)
 
-  if (respa) {
-    double *cut_respa = ((Respa *) update->integrate)->cutoff;
-    cut_inner_sq = (cut_respa[1] + skin) * (cut_respa[1] + skin);
-    cut_middle_sq = (cut_respa[3] + skin) * (cut_respa[3] + skin);
-    cut_middle_inside_sq = (cut_respa[0] - skin) * (cut_respa[0] - skin);
-  }
+    for (i = 0; i < nlist; i++) {
+      lists[i] = new NeighList(lmp,pgsize);
+      lists[i]->index = i;
+      lists[i]->dnum = requests[i]->dnum;
+
+      if (requests[i]->pair) {
+	Pair *pair = (Pair *) requests[i]->requestor;
+	pair->init_list(requests[i]->id,lists[i]);
+      } else if (requests[i]->fix) {
+	Fix *fix = (Fix *) requests[i]->requestor;
+	fix->init_list(requests[i]->id,lists[i]);
+      } else if (requests[i]->compute) {
+	Compute *compute = (Compute *) requests[i]->requestor;
+	compute->init_list(requests[i]->id,lists[i]);
+      }
+    }
 
-  // zero atom-length numneigh and firstneigh arrays
-  // will be (re)allocated on first build()
+    // detect lists that are connected to other lists
+    // skip: point this list at request->otherlist, copy skip ptrs from request
+    // copy: point this list at request->otherlist
+    // half_from_full: point this list at preceeding full list
+    // granhistory: set preceeding list's listgranhistory to this list
+    //   also set precedding list's ptr to FixShearHistory
+    // respaouter: point this list at preceeding 1/2 inner/middle lists
+    // pair and half and non-skip: if there is a pair full non-skip list,
+    //   change this list to half_from_full and point at the full list
+    // fix/compute requests:
+    //   kind of request = half or full
+    //   occasional or not doesn't matter
+    //   if non-skip pair list of same kind exists, become copy of that list
+    //   else if request is half and non-skip pair full exists,
+    //     become half_from_full of that list
+    //   else do nothing and the fix/compute list will be built directly
+
+    for (i = 0; i < nlist; i++) {
+      if (requests[i]->skip) {
+	lists[i]->listskip = lists[requests[i]->otherlist];
+	lists[i]->iskip = requests[i]->iskip;
+	lists[i]->ijskip = requests[i]->ijskip;
+      }
 
-  maxlocal = 0;
+      if (requests[i]->copy)
+	lists[i]->listcopy = lists[requests[i]->otherlist];
 
-  memory->sfree(numneigh);
-  memory->sfree(firstneigh);
-  memory->sfree(numneigh_full);
-  memory->sfree(firstneigh_full);
-  memory->sfree(firsttouch);
-  memory->sfree(firstshear);
-  memory->sfree(numneigh_inner);
-  memory->sfree(firstneigh_inner);
-  memory->sfree(numneigh_middle);
-  memory->sfree(firstneigh_middle);
-
-  numneigh = numneigh_full = numneigh_inner = numneigh_middle = NULL;
-  firstneigh = firstneigh_full = NULL;
-  firsttouch = NULL;
-  firstshear = NULL;
-  firstneigh_inner = firstneigh_middle = NULL;
-
-  // clear old neighbor lists if no longer needed (whether exist or not)
-
-  if (half == 0) clear_pages();
-  if (full == 0) clear_pages_full();
-  if (fix_history == NULL) clear_pages_history();
-  if (respa == 0) clear_pages_inner();
-  if (respa == 0 || respa == 1) clear_pages_middle();
-
-  // setup new neighbor lists
-  // only if they don't exist so memory will persist from run to run
-
-  if (half && pages == NULL) add_pages(0);
-  if (full && pages_full == NULL) add_pages_full(0);
-  if (fix_history && pages_touch == NULL) add_pages_history(0);
-  if (respa >= 1 && pages_inner == NULL) add_pages_inner(0);
-  if (respa == 2 && pages_middle == NULL) add_pages_middle(0);
-
-  // set ptrs to half/full/multi/triclinic build & stencil functions
-
-  if (half) {
-    if (fix_history) {
-      if (style == NSQ) {
-	if (force->newton_pair == 0) 
-	  half_build = &Neighbor::granular_nsq_no_newton;
-	else half_build = &Neighbor::granular_nsq_newton;
-      } else if (style == BIN) {
-	if (force->newton_pair == 0) {
-	  half_build = &Neighbor::granular_bin_no_newton;
-	  if (dimension == 3)
-	    half_stencil = &Neighbor::stencil_half_3d_no_newton;
-	  else
-	    half_stencil = &Neighbor::stencil_half_2d_no_newton;
-	} else if (triclinic) {
-	  half_build = &Neighbor::granular_bin_newton_tri;
-	  if (dimension == 3)
-	    half_stencil = &Neighbor::stencil_half_3d_newton_tri;
-	  else
-	    half_stencil = &Neighbor::stencil_half_2d_newton_tri;
+      if (requests[i]->half_from_full) lists[i]->listfull = lists[i-1];
+
+      if (requests[i]->granhistory) {
+	lists[i-1]->listgranhistory = lists[i];
+	for (int ifix = 0; ifix < modify->nfix; ifix++)
+	  if (strcmp(modify->fix[ifix]->style,"SHEAR_HISTORY") == 0) 
+	    lists[i-1]->fix_history = (FixShearHistory *) modify->fix[ifix];
+      }
+
+      if (requests[i]->respaouter) {
+	if (requests[i-1]->respainner) {
+	  lists[i]->respamiddle = 0;
+	  lists[i]->listinner = lists[i-1];
 	} else {
-	  half_build = &Neighbor::granular_bin_newton;
-	  if (dimension == 3)
-	    half_stencil = &Neighbor::stencil_half_3d_newton;
-	  else
-	    half_stencil = &Neighbor::stencil_half_2d_newton;
+	  lists[i]->respamiddle = 1;
+	  lists[i]->listmiddle = lists[i-1];
+	  lists[i]->listinner = lists[i-2];
 	}
-      } else error->all("Neighbor multi not allowed with granular");
-
-    } else if (respa) {
-      if (style == NSQ) {
-	if (force->newton_pair == 0) 
-	  half_build = &Neighbor::respa_nsq_no_newton;
-	else half_build = &Neighbor::respa_nsq_newton;
-      } else if (style == BIN) {
-	if (force->newton_pair == 0) {
-	  half_build = &Neighbor::respa_bin_no_newton;
-	  if (dimension == 3)
-	    half_stencil = &Neighbor::stencil_half_3d_no_newton;
-	  else
-	    half_stencil = &Neighbor::stencil_half_2d_no_newton;
-	} else if (triclinic) {
-	  half_build = &Neighbor::respa_bin_newton_tri;
-	  if (dimension == 3)
-	    half_stencil = &Neighbor::stencil_half_3d_newton_tri;
-	  else
-	    half_stencil = &Neighbor::stencil_half_2d_newton_tri;
-	} else {
-	  half_build = &Neighbor::respa_bin_newton;
-	  if (dimension == 3)
-	    half_stencil = &Neighbor::stencil_half_3d_newton;
-	  else
-	    half_stencil = &Neighbor::stencil_half_2d_newton;
+      }
+
+      if (requests[i]->pair && requests[i]->half && requests[i]->skip == 0) {
+	for (j = 0; j < nlist; j++)
+	  if (requests[i]->pair && requests[j]->full && 
+	      requests[j]->skip == 0) break;
+	if (j < nlist) {
+	  requests[i]->half = 0;
+	  requests[i]->half_from_full = 1;
+	  lists[i]->listfull = lists[j];
 	}
-      } else error->all("Neighbor multi not allowed with rRESPA");
+      }
 
-    } else {
-      if (style == NSQ) {
-	if (force->newton_pair == 0) {
-	  if (full_every) half_build = &Neighbor::half_full_no_newton;
-	  else half_build = &Neighbor::half_nsq_no_newton;
-	} else {
-	  if (full_every) half_build = &Neighbor::half_full_newton;
-	  else half_build = &Neighbor::half_nsq_newton;
+      if (requests[i]->fix || requests[i]->compute) {
+	for (j = 0; j < nlist; j++) {
+	  if (requests[j]->pair && requests[j]->skip == 0 &&
+	      requests[j]->half && requests[i]->half) break;
+	  if (requests[j]->pair && requests[j]->skip == 0 &&
+	      requests[j]->full && requests[i]->full) break;
 	}
-      } else if (style == BIN) {
-	if (force->newton_pair == 0) {
-	  if (full_every) {
-	    half_build = &Neighbor::half_full_no_newton;
-	    half_stencil = &Neighbor::stencil_none;
-	  } else {
-	    half_build = &Neighbor::half_bin_no_newton;
-	    if (dimension == 3)
-	      half_stencil = &Neighbor::stencil_half_3d_no_newton;
-	    else
-	      half_stencil = &Neighbor::stencil_half_2d_no_newton;
-	  }
+	if (j < nlist) {
+	  requests[i]->copy = 1;
+	  lists[i]->listcopy = lists[j];
 	} else {
-	  if (full_every) {
-	    half_build = &Neighbor::half_full_newton;
-	    half_stencil = &Neighbor::stencil_none;
-	  } else if (triclinic) {
-	    half_build = &Neighbor::half_bin_newton_tri;
-	    if (dimension == 3)
-	      half_stencil = &Neighbor::stencil_half_3d_newton_tri;
-	    else
-	      half_stencil = &Neighbor::stencil_half_2d_newton_tri;
-	  } else {
-	    half_build = &Neighbor::half_bin_newton;
-	    if (dimension == 3)
-	      half_stencil = &Neighbor::stencil_half_3d_newton;
-	    else
-	      half_stencil = &Neighbor::stencil_half_2d_newton;
-	  }
-	}
-      } else if (style == MULTI) {
-	if (force->newton_pair == 0) {
-	  if (full_every) {
-	    half_build = &Neighbor::half_full_no_newton;
-	    half_stencil = &Neighbor::stencil_none;
-	  } else {
-	    half_build = &Neighbor::half_bin_no_newton_multi;
-	    if (dimension == 3)
-	      half_stencil = &Neighbor::stencil_half_3d_no_newton_multi;
-	    else
-	      half_stencil = &Neighbor::stencil_half_2d_no_newton_multi;
+	  for (j = 0; j < nlist; j++) {
+	    if (requests[j]->pair && requests[j]->skip == 0 &&
+		requests[j]->full && requests[i]->half) break;
 	  }
-	} else {
-	  if (full_every) {
-	    half_build = &Neighbor::half_full_newton;
-	    half_stencil = &Neighbor::stencil_none;
-	  } else if (triclinic) {
-	    half_build = &Neighbor::half_bin_newton_multi_tri;
-	    if (dimension == 3)
-	      half_stencil = &Neighbor::stencil_half_3d_newton_multi_tri;
-	    else
-	      half_stencil = &Neighbor::stencil_half_2d_newton_multi_tri;
-	  } else {
-	    half_build = &Neighbor::half_bin_newton_multi;
-	    if (dimension == 3)
-	      half_stencil = &Neighbor::stencil_half_3d_newton_multi;
-	    else
-	      half_stencil = &Neighbor::stencil_half_2d_newton_multi;
+	  if (j < nlist) {
+	    requests[i]->half = 0;
+	    requests[i]->half_from_full = 1;
+	    lists[i]->listfull = lists[j];
 	  }
 	}
       }
     }
 
-  } else half_build = NULL;
-
-  if (full) {
-    if (style == NSQ) full_build = &Neighbor::full_nsq;
-    else if (style == BIN) {
-      full_build = &Neighbor::full_bin;
-      if (dimension == 3)
-	full_stencil = &Neighbor::stencil_full_3d;
-      else
-	full_stencil = &Neighbor::stencil_full_2d;
-    } else {
-      full_build = &Neighbor::full_bin_multi;
-      if (dimension == 3)
-	full_stencil = &Neighbor::stencil_full_3d_multi;
-      else
-	full_stencil = &Neighbor::stencil_full_2d_multi;
+    // set ptrs to pair_build and stencil_create functions for each list
+    // ptrs set to NULL if not set explicitly
+
+    for (i = 0; i < nlist; i++) {
+      choose_build(i,requests[i]);
+      if (style != NSQ) choose_stencil(i,requests[i]);
+      else stencil_create[i] = NULL;
+    }
+
+    // set each list's build/grow/stencil flags based on neigh request
+    // buildflag = 1 if its pair_build() invoked every reneighbor
+    // growflag = 1 if it stores atom-based arrays and pages
+    // stencilflag = 1 if it stores stencil arrays
+
+    for (i = 0; i < nlist; i++) {
+      lists[i]->buildflag = 1;
+      if (pair_build[i] == NULL) lists[i]->buildflag = 0;
+      if (requests[i]->occasional) lists[i]->buildflag = 0;
+
+      lists[i]->growflag = 1;
+      if (requests[i]->copy) lists[i]->growflag = 0;
+
+      lists[i]->stencilflag = 1;
+      if (style == NSQ) lists[i]->stencilflag = 0;
+      if (stencil_create[i] == NULL) lists[i]->stencilflag = 0;
+    }
+
+    // DEBUG: print list attributes
+
+    for (i = 0; i < nlist; i++) lists[i]->print_attributes();
+    
+    // allocate atom arrays and 1st pages of lists that store them
+
+    for (i = 0; i < nlist; i++)
+      if (lists[i]->growflag) {
+	lists[i]->grow(maxlocal);
+	lists[i]->add_pages();
+      }
+
+    // setup 3 vectors of pairwise neighbor lists
+    // blist = lists whose pair_build() is invoked every reneighbor
+    // glist = lists who store atom arrays which are used every reneighbor
+    // slist = lists who store stencil arrays which are used every reneighbor
+    // blist and glist vectors are used by neighbor::build()
+    // slist vector is used by neighbor::setup_bins()
+
+    nblist = nglist = nslist = 0;
+    delete [] blist;
+    delete [] glist;
+    delete [] slist;
+    blist = new int[nlist];
+    glist = new int[nlist];
+    slist = new int[nlist];
+
+    for (i = 0; i < nlist; i++) {
+      if (lists[i]->buildflag) blist[nblist++] = i;
+      if (lists[i]->growflag && requests[i]->occasional == 0)
+	glist[nglist++] = i;
+      if (lists[i]->stencilflag && requests[i]->occasional == 0)
+	slist[nslist++] = i;
+    }
+
+    // DEBUG: print lists of lists
+
+    if (comm->me == 0) {
+      printf("Build lists = %d: ",nblist);
+      for (i = 0; i < nblist; i++) printf("%d ",blist[i]);
+      printf("\n");
+      printf("Grow lists = %d: ",nglist);
+      for (i = 0; i < nglist; i++) printf("%d ",glist[i]);
+      printf("\n");
+      printf("Stencil lists = %d: ",nslist);
+      for (i = 0; i < nslist; i++) printf("%d ",slist[i]);
+      printf("\n");
+    }
+
+    // reorder build vector if necessary
+    // relevant for lists that copy/skip/half-full from parent
+    // the derived lst must appear in blist after the parent list
+    // no occasional lists are in build vector
+    // swap two lists within blist when dependency is mis-ordered
+    // done when entire pass thru blist results in no swaps
+
+    int done = 0;
+    while (!done) {
+      done = 1;
+      for (i = 0; i < nblist; i++) {
+	NeighList *ptr = NULL;
+	if (lists[blist[i]]->listfull) ptr = lists[blist[i]]->listfull;
+	if (lists[blist[i]]->listcopy) ptr = lists[blist[i]]->listcopy;
+	if (lists[blist[i]]->listskip) ptr = lists[blist[i]]->listskip;
+	if (ptr == NULL) continue;
+	for (m = 0; m < nlist; m++)
+	  if (ptr == lists[m]) break;
+	for (j = 0; j < nblist; j++)
+	  if (m == blist[j]) break;
+	if (j < i) continue;
+	int tmp = blist[i];
+	blist[i] = blist[j];
+	blist[j] = tmp;
+	done = 0;
+	break;
+      }
+    }
+
+    // DEBUG: print lists of lists
+
+    if (comm->me == 0) {
+      printf("Build lists = %d: ",nblist);
+      for (i = 0; i < nblist; i++) printf("%d ",blist[i]);
+      printf("\n");
+      printf("Grow lists = %d: ",nglist);
+      for (i = 0; i < nglist; i++) printf("%d ",glist[i]);
+      printf("\n");
+      printf("Stencil lists = %d: ",nslist);
+      for (i = 0; i < nslist; i++) printf("%d ",slist[i]);
+      printf("\n");
     }
-  } else full_build = NULL;
+  }
+
+  // delete old requests
+  // copy current requests and style to old for next run
+  
+  for (i = 0; i < old_nrequest; i++) delete old_requests[i];
+  memory->sfree(old_requests);
+  old_nrequest = nrequest;
+  old_requests = requests;
+  nrequest = maxrequest = 0;
+  requests = NULL;
+  old_style = style;
 
   // ------------------------------------------------------------------
-  // bond neighbor lists
+  // topology lists
 
-  // 1st time allocation of bond lists
+  // 1st time allocation of topology lists
 
   if (atom->molecular && atom->nbonds && maxbond == 0) {
     if (nprocs == 1) maxbond = atom->nbonds;
@@ -692,7 +667,7 @@ void Neighbor::init()
       memory->create_2d_int_array(maximproper,5,"neigh:improperlist");
   }
 
-  // set flags that determine which bond neighboring routines to use
+  // set flags that determine which topology neighboring routines to use
   // SHAKE sets bonds and angles negative
   // bond_quartic sets bonds to 0
   // delete_bonds sets all interactions negative
@@ -738,7 +713,7 @@ void Neighbor::init()
     }
   }
 
-  // set ptrs to intra-molecular build functions
+  // set ptrs to topology build functions
 
   if (bond_off) bond_build = &Neighbor::bond_partial;
   else bond_build = &Neighbor::bond_all;
@@ -752,7 +727,7 @@ void Neighbor::init()
   if (improper_off) improper_build = &Neighbor::improper_partial;
   else improper_build = &Neighbor::improper_all;
 
-  // set intra-molecular neighbor list counts to 0
+  // set topology neighbor list counts to 0
   // in case all are turned off but potential is still defined
 
   nbondlist = nanglelist = ndihedrallist = nimproperlist = 0;
@@ -760,6 +735,149 @@ void Neighbor::init()
 
 /* ---------------------------------------------------------------------- */
 
+int Neighbor::request(void *requestor)
+{
+  if (nrequest == maxrequest) {
+    maxrequest += RQDELTA;
+    requests = (NeighRequest **) 
+      memory->srealloc(requests,maxrequest*sizeof(NeighRequest *),
+		       "neighbor:requests");
+  }
+
+  requests[nrequest] = new NeighRequest(lmp);
+  requests[nrequest]->requestor = requestor;
+  nrequest++;
+  return nrequest-1;
+}
+
+
+/* ----------------------------------------------------------------------
+   determine which pair_build function each neigh list needs
+   based on settings of neigh request
+   skip or copy -> single function
+   half_from_full, half, full, gran, respaouter -> choose by newton and tri
+     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" b/c skip,copy can be set in addition to half,full,etc
+------------------------------------------------------------------------- */
+
+void Neighbor::choose_build(int index, NeighRequest *rq)
+{
+  PairPtr pb = NULL;
+
+  if (rq->skip) pb = &Neighbor::skip_from;
+
+  else if (rq->copy) pb = &Neighbor::copy_from;
+
+  else if (rq->half_from_full) {
+    if (newton_pair == 0) pb = &Neighbor::half_full_no_newton;
+    else if (newton_pair == 1) pb = &Neighbor::half_full_newton;
+
+  } else if (rq->half) {
+    if (style == NSQ) {
+      if (newton_pair == 0) pb = &Neighbor::half_nsq_no_newton;
+      else if (newton_pair == 1) pb = &Neighbor::half_nsq_newton;
+    } else if (style == BIN) {
+      if (newton_pair == 0) pb = &Neighbor::half_bin_no_newton;
+      else if (triclinic == 0) pb = &Neighbor::half_bin_newton;
+      else if (triclinic == 1) pb = &Neighbor::half_bin_newton_tri;
+    } else if (style == MULTI) {
+      if (newton_pair == 0) pb = &Neighbor::half_multi_no_newton;
+      else if (triclinic == 0) pb = &Neighbor::half_multi_newton;
+      else if (triclinic == 1) pb = &Neighbor::half_multi_newton_tri;
+    }
+
+  } else if (rq->full) {
+    if (style == NSQ) pb = &Neighbor::full_nsq;
+    else if (style == BIN) pb = &Neighbor::full_bin;
+    else if (style == MULTI) pb = &Neighbor::full_multi;
+
+  } else if (rq->gran) {
+    if (style == NSQ) {
+      if (newton_pair == 0) pb = &Neighbor::granular_nsq_no_newton;
+      else if (newton_pair == 1) pb = &Neighbor::granular_nsq_newton;
+    } else if (style == BIN) {
+      if (newton_pair == 0) pb = &Neighbor::granular_bin_no_newton;
+      else if (triclinic == 0) pb = &Neighbor::granular_bin_newton;
+      else if (triclinic == 1) pb = &Neighbor::granular_bin_newton_tri;
+    } else if (style == MULTI)
+      error->all("Neighbor multi not yet enabled for granular");
+
+  } else if (rq->respaouter) {
+    if (style == NSQ) {
+      if (newton_pair == 0) pb = &Neighbor::respa_nsq_no_newton;
+      else if (newton_pair == 1) pb = &Neighbor::respa_nsq_newton;
+    } else if (style == BIN) {
+      if (newton_pair == 0) pb = &Neighbor::respa_bin_no_newton;
+      else if (triclinic == 0) pb = &Neighbor::respa_bin_newton;
+      else if (triclinic == 1) pb = &Neighbor::respa_bin_newton_tri;
+    } else if (style == MULTI)
+      error->all("Neighbor multi not yet enabled for rRESPA");
+  }
+
+  pair_build[index] = pb;
+}
+
+/* ----------------------------------------------------------------------
+   determine which stencil_create function each neigh list needs
+   based on settings of neigh request, only called if style != NSQ
+   skip or copy or half_from_full -> no stencil
+   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(int index, NeighRequest *rq)
+{
+  StencilPtr sc = NULL;
+
+  if (rq->skip || rq->copy || rq->half_from_full) sc = NULL;
+
+  else if (rq->half || rq->gran || rq->respaouter) {
+    if (style == BIN) {
+      if (newton_pair == 0) {
+	if (dimension == 2) sc = &Neighbor::stencil_half_bin_2d_no_newton;
+	else if (dimension == 3) sc = &Neighbor::stencil_half_bin_3d_no_newton;
+      } else if (triclinic == 0) {
+	if (dimension == 2) sc = &Neighbor::stencil_half_bin_2d_newton;
+	else if (dimension == 3) sc = &Neighbor::stencil_half_bin_3d_newton;
+      } else if (triclinic == 1) {
+	if (dimension == 2) sc = &Neighbor::stencil_half_bin_2d_newton_tri;
+	else if (dimension == 3) 
+	  sc = &Neighbor::stencil_half_bin_3d_newton_tri;
+      }
+    } else if (style == MULTI) {
+      if (newton_pair == 0) {
+	if (dimension == 2) sc = &Neighbor::stencil_half_multi_2d_no_newton;
+	else if (dimension == 3)
+	  sc = &Neighbor::stencil_half_multi_3d_no_newton;
+      } else if (triclinic == 0) {
+	if (dimension == 2) sc = &Neighbor::stencil_half_multi_2d_newton;
+	else if (dimension == 3) sc = &Neighbor::stencil_half_multi_3d_newton;
+      } else if (triclinic == 1) {
+	if (dimension == 2) sc = &Neighbor::stencil_half_multi_2d_newton_tri;
+	else if (dimension == 3) 
+	  sc = &Neighbor::stencil_half_multi_3d_newton_tri;
+      }
+    }
+
+  } else if (rq->full) {
+    if (style == BIN) {
+      if (dimension == 2) sc = &Neighbor::stencil_full_bin_2d;
+      else if (dimension == 3) sc = &Neighbor::stencil_full_bin_3d;
+    } else if (style == MULTI) {
+      if (dimension == 2) sc = &Neighbor::stencil_full_multi_2d;
+      else if (dimension == 3) sc = &Neighbor::stencil_full_multi_3d;
+    }
+  }
+
+  stencil_create[index] = sc;
+}
+
+/* ---------------------------------------------------------------------- */
+
 int Neighbor::decide()
 {
   if (must_check) {
@@ -800,19 +918,17 @@ int Neighbor::check_distance()
 }
 
 /* ----------------------------------------------------------------------
-   build all needed neighbor lists every few timesteps
-   half, full, bond lists are created as needed
+   build all perpetual neighbor lists every few timesteps
+   pairwise & topology lists are created as needed
 ------------------------------------------------------------------------- */
 
 void Neighbor::build()
 {
+  int i;
+
   ago = 0;
   ncalls++;
 
-  // store current nlocal used on this build (used by fix shear/history)
-
-  nlocal_neighbor = atom->nlocal;
-
   // store current atom positions if needed
 
   if (dist_check) {
@@ -823,66 +939,22 @@ void Neighbor::build()
       memory->destroy_2d_double_array(xhold);
       xhold = memory->create_2d_double_array(maxhold,3,"neigh:xhold");
     }
-    for (int i = 0; i < nlocal; i++) {
+    for (i = 0; i < nlocal; i++) {
       xhold[i][0] = x[i][0];
       xhold[i][1] = x[i][1];
       xhold[i][2] = x[i][2];
     }
   }
 
-  // extend atom arrays if necessary
-  // check half/full instead of half_every/full_every so memory will be
-  //   allocated correctly whenever build_half() and build_full() are called
+  // if necessary, extend atom arrays in pairwise lists
+  // only done for lists with growflag set which are used every reneighbor
 
   if (atom->nlocal > maxlocal) {
     maxlocal = atom->nmax;
-
-    if (half) {
-      memory->sfree(numneigh);
-      memory->sfree(firstneigh);
-      numneigh = (int *)
-	memory->smalloc(maxlocal*sizeof(int),"neigh:numneigh");
-      firstneigh = (int **)
-	memory->smalloc(maxlocal*sizeof(int *),"neigh:firstneigh");
-    }
-
-    if (full) {
-      memory->sfree(numneigh_full);
-      memory->sfree(firstneigh_full);
-      numneigh_full = (int *)
-	memory->smalloc(maxlocal*sizeof(int),"neigh:numneigh_full");
-      firstneigh_full = (int **)
-      memory->smalloc(maxlocal*sizeof(int *),"neigh:firstneigh_full");
-    }
-
-    if (fix_history) {
-      memory->sfree(firsttouch);
-      memory->sfree(firstshear);
-      firsttouch = (int **) 
-	memory->smalloc(maxlocal*sizeof(int *),"neigh:firsttouch");
-      firstshear = (double **)
-	memory->smalloc(maxlocal*sizeof(double *),"neigh:firstshear");
-    }
-
-    if (respa) {
-      memory->sfree(numneigh_inner);
-      memory->sfree(firstneigh_inner);
-      numneigh_inner = (int *)
-	memory->smalloc(maxlocal*sizeof(int),"neigh:numneigh_inner");
-      firstneigh_inner = (int **)
-	memory->smalloc(maxlocal*sizeof(int *),"neigh:firstneigh_inner");
-      if (respa == 2) {
-	memory->sfree(numneigh_middle);
-	memory->sfree(firstneigh_middle);
-	numneigh_middle = (int *)
-	  memory->smalloc(maxlocal*sizeof(int),"neigh:numneigh_middle");
-	firstneigh_middle = (int **)
-	  memory->smalloc(maxlocal*sizeof(int *),"neigh:firstneigh_middle");
-      }
-    }
+    for (i = 0; i < nglist; i++) lists[glist[i]]->grow(maxlocal);
   }
 
-  // extend bin list if necessary
+  // extend atom bin list if necessary
 
   if (style != NSQ && atom->nmax > maxbin) {
     maxbin = atom->nmax;
@@ -890,11 +962,22 @@ void Neighbor::build()
     bins = (int *) memory->smalloc(maxbin*sizeof(int),"bins");
   }
 
-  // list construction for pairs and bonds
-  // full comes first in case half is built from full
+  // invoke building of pair and molecular neighbor lists
+  // only done for pairwise lists with buildflag set
 
-  if (full_every) (this->*full_build)();
-  if (half_every) (this->*half_build)();
+  for (i = 0; i < nblist; i++)
+    (this->*pair_build[blist[i]])(lists[blist[i]]);
+
+  /*
+  if (comm->me == 0) {
+    for (int m = 0; m < nlist; m++) {
+      int num = 0;
+      for (i = 0; i < lists[m]->inum; i++) 
+	num += lists[m]->numneigh[lists[m]->ilist[i]];
+      printf("List %d length = %d\n",m,num);
+    }
+  }
+  */
 
   if (atom->molecular) {
     if (atom->nbonds) (this->*bond_build)();
@@ -905,21 +988,21 @@ void Neighbor::build()
 }
 
 /* ----------------------------------------------------------------------
-   one-time call to build a half neighbor list made by other classes
+   build a single non-active pairwise neighbor list indexed by I
+   called by other classes when needed occasionally
 ------------------------------------------------------------------------- */
 
-void Neighbor::build_half()
+void Neighbor::build_one(int i)
 {
-  (this->*half_build)();
-}
+  // grow atom arrays and update stencils depending on growflag & stencilflag
 
-/* ----------------------------------------------------------------------
-   one-time call to build a full neighbor list made by other classes
-------------------------------------------------------------------------- */
+  if (lists[i]->growflag) lists[i]->grow(maxlocal);
+  if (lists[i]->stencilflag) {
+    lists[i]->stencil_allocate(smax,style);
+    (this->*stencil_create[i])(lists[i],sx,sy,sz);
+  }
 
-void Neighbor::build_full()
-{
-  (this->*full_build)();
+  (this->*pair_build[i])(lists[i]);
 }
 
 /* ----------------------------------------------------------------------
@@ -941,8 +1024,6 @@ void Neighbor::build_full()
    mbinlo = lowest global bin any of my ghost atoms could fall into
    mbinhi = highest global bin any of my ghost atoms could fall into
    mbin = number of bins I need in a dimension
-   stencil() = bin offsets in 1d sense for stencil of surrounding bins
-   stencil_full() = bin offsets in 1d sense for stencil for full neighbor list
 ------------------------------------------------------------------------- */
 
 void Neighbor::setup_bins()
@@ -1089,23 +1170,25 @@ void Neighbor::setup_bins()
 
   // create stencil of bins to search over in neighbor list construction
   // sx,sy,sz = max range of stencil extent
+  // smax = 
   // stencil is empty if cutneighmax = 0.0
 
-  int sx = static_cast<int> (cutneighmax*bininvx);
+  sx = static_cast<int> (cutneighmax*bininvx);
   if (sx*binsizex < cutneighmax) sx++;
-  int sy = static_cast<int> (cutneighmax*bininvy);
+  sy = static_cast<int> (cutneighmax*bininvy);
   if (sy*binsizey < cutneighmax) sy++;
-  int sz = static_cast<int> (cutneighmax*bininvz);
+  sz = static_cast<int> (cutneighmax*bininvz);
   if (sz*binsizez < cutneighmax) sz++;
   if (dimension == 2) sz = 0;
+  smax = (2*sx+1) * (2*sy+1) * (2*sz+1);
 
-  // allocate stencil memory and create stencil(s)
-  // check half/full instead of half_every/full_every so stencils will be
-  //   allocated correctly whenever build_half() and build_full() are called
+  // create stencils for pairwise neighbor lists
+  // only done for lists with stencilflag and buildflag set
 
-  stencil_allocate(sx,sy,sz);
-  if (half) (this->*half_stencil)(sx,sy,sz);
-  if (full) (this->*full_stencil)(sx,sy,sz);
+  for (int i = 0; i < nslist; i++) {
+    lists[slist[i]]->stencil_allocate(smax,style);
+    (this->*stencil_create[slist[i]])(lists[slist[i]],sx,sy,sz);
+  }
 }
 
 /* ----------------------------------------------------------------------
@@ -1218,7 +1301,7 @@ void Neighbor::modify_params(int narg, char **arg)
       } else if (strcmp(arg[iarg+1],"molecule") == 0) {
 	if (iarg+3 > narg) error->all("Illegal neigh_modify command");
 	if (atom->molecular == 0) {
-	  char *str =
+	  char *str = (char *)
 	    "Must use molecular atom style with neigh_modify exclude molecule";
 	  error->all(str);
 	}
@@ -1243,170 +1326,6 @@ void Neighbor::modify_params(int narg, char **arg)
   }
 }
 
-/* ----------------------------------------------------------------------
-   return # of bytes of allocated memory
-------------------------------------------------------------------------- */
-
-int Neighbor::memory_usage()
-{
-  int bytes = 0;
-
-  bytes += maxhold*3 * sizeof(double);
-
-  if (style == NSQ) {
-    bytes += maxbin * sizeof(int);
-    bytes += maxhead * sizeof(int);
-    bytes += maxstencil * sizeof(int);
-    bytes += maxstencil_full * sizeof(int);
-  }
-
-  if (half) {
-    bytes += maxlocal * sizeof(int);
-    bytes += maxlocal * sizeof(int *);
-    bytes += maxpage*pgsize * sizeof(int);
-  }
-
-  if (full) {
-    bytes += maxlocal * sizeof(int);
-    bytes += maxlocal * sizeof(int *);
-    bytes += maxpage_full*pgsize * sizeof(int);
-  }
-
-  if (fix_history) {
-    bytes += maxlocal * sizeof(int *);
-    bytes += maxlocal * sizeof(double *);
-    bytes += maxpage_history*pgsize * sizeof(int);
-    bytes += maxpage_history*pgsize*3 * sizeof(double);
-  }
-
-  if (respa) {
-    bytes += maxlocal * sizeof(int);
-    bytes += maxlocal * sizeof(int *);
-    bytes += maxpage_inner*pgsize * sizeof(int);
-    if (respa == 2) {
-      bytes += maxlocal * sizeof(int);
-      bytes += maxlocal * sizeof(int *);
-      bytes += maxpage_middle*pgsize * sizeof(int);
-    }
-  }
-
-  bytes += maxbond*3 * sizeof(int);
-  bytes += maxangle*4 * sizeof(int);
-  bytes += maxdihedral*5 * sizeof(int);
-  bytes += maximproper*5 * sizeof(int);
-
-  return bytes;
-}
-
-/* ----------------------------------------------------------------------
-   add pages to half/full/granular/rRESPA neighbor lists, starting at npage
-------------------------------------------------------------------------- */
-
-void Neighbor::add_pages(int npage)
-{
-  maxpage += PGDELTA;
-  pages = (int **) 
-    memory->srealloc(pages,maxpage*sizeof(int *),"neigh:pages");
-  for (int i = npage; i < maxpage; i++)
-    pages[i] = (int *) memory->smalloc(pgsize*sizeof(int),"neigh:pages[i]");
-}
-
-void Neighbor::add_pages_full(int npage)
-{
-  maxpage_full += PGDELTA;
-  pages_full = (int **) 
-    memory->srealloc(pages_full,maxpage_full*sizeof(int *),"neigh:pages_full");
-  for (int i = npage; i < maxpage_full; i++)
-    pages_full[i] =
-      (int *) memory->smalloc(pgsize*sizeof(int),"neigh:pages_full[i]");
-}
-
-void Neighbor::add_pages_history(int npage)
-{
-  maxpage_history += PGDELTA;
-  pages_touch = (int **)
-    memory->srealloc(pages_touch,maxpage_history*sizeof(int *),
-		     "neigh:pages_touch");
-  pages_shear = (double **)
-    memory->srealloc(pages_shear,maxpage_history*sizeof(double *),
-		     "neigh:pages_shear");
-  for (int i = npage; i < maxpage_history; i++) {
-    pages_touch[i] = (int *)
-      memory->smalloc(pgsize*sizeof(int),"neigh:pages_touch[i]");
-    pages_shear[i] = (double *)
-      memory->smalloc(3*pgsize*sizeof(double),"neigh:pages_shear[i]");
-  }
-}
-
-void Neighbor::add_pages_inner(int npage_inner)
-{
-  maxpage_inner += PGDELTA;
-  pages_inner = (int **) 
-    memory->srealloc(pages_inner,maxpage_inner*sizeof(int *),
-		     "neigh:pages_inner");
-  for (int i = npage_inner; i < maxpage_inner; i++)
-    pages_inner[i] = 
-      (int *) memory->smalloc(pgsize*sizeof(int),"neigh:pages_inner[i]");
-}
-
-void Neighbor::add_pages_middle(int npage_middle)
-{
-  maxpage_middle += PGDELTA;
-  pages_middle = (int **) 
-    memory->srealloc(pages_middle,maxpage_middle*sizeof(int *),
-		     "neigh:pages_middle");
-  for (int i = npage_middle; i < maxpage_middle; i++)
-    pages_middle[i] = 
-      (int *) memory->smalloc(pgsize*sizeof(int),"neigh:pages_middle[i]");
-}
-
-/* ----------------------------------------------------------------------
-   clear half/full/granular/rRESPA neighbor lists
-------------------------------------------------------------------------- */
-
-void Neighbor::clear_pages()
-{
-  for (int i = 0; i < maxpage; i++) memory->sfree(pages[i]);
-  memory->sfree(pages);
-  pages = NULL;
-  maxpage = 0;
-}
-
-void Neighbor::clear_pages_full()
-{
-  for (int i = 0; i < maxpage_full; i++) memory->sfree(pages_full[i]);
-  memory->sfree(pages_full);
-  pages_full = NULL;
-  maxpage_full = 0;
-}
-
-void Neighbor::clear_pages_history()
-{
-  for (int i = 0; i < maxpage_history; i++) memory->sfree(pages_touch[i]);
-  for (int i = 0; i < maxpage_history; i++) memory->sfree(pages_shear[i]);
-  memory->sfree(pages_touch);
-  memory->sfree(pages_shear);
-  pages_touch = NULL;
-  pages_shear = NULL;
-  maxpage_history = 0;
-}
-
-void Neighbor::clear_pages_inner()
-{
-  for (int i = 0; i < maxpage_inner; i++) memory->sfree(pages_inner[i]);
-  memory->sfree(pages_inner);
-  pages_inner = NULL;
-  maxpage_inner = 0;
-}
-
-void Neighbor::clear_pages_middle()
-{
-  for (int i = 0; i < maxpage_middle; i++) memory->sfree(pages_middle[i]);
-  memory->sfree(pages_middle);
-  pages_middle = NULL;
-  maxpage_middle = 0;
-}
-
 /* ----------------------------------------------------------------------
    determine if atom j is in special list of atom i
    if it is not, return 0
@@ -1526,11 +1445,12 @@ int Neighbor::coord2bin(double *x)
    return 1 if should be excluded, 0 if included
 ------------------------------------------------------------------------- */
 
-int Neighbor::exclusion(int i, int j, int *type, int *mask, int *molecule)
+int Neighbor::exclusion(int i, int j, int itype, int jtype, 
+			int *mask, int *molecule)
 {
   int m;
 
-  if (nex_type && ex_type[type[i]][type[j]]) return 1;
+  if (nex_type && ex_type[itype][jtype]) return 1;
 
   if (nex_group) {
     for (m = 0; m < nex_group; m++) {
@@ -1547,3 +1467,28 @@ int Neighbor::exclusion(int i, int j, int *type, int *mask, int *molecule)
 
   return 0;
 }
+
+/* ----------------------------------------------------------------------
+   return # of bytes of allocated memory
+------------------------------------------------------------------------- */
+
+int Neighbor::memory_usage()
+{
+  int bytes = 0;
+
+  bytes += maxhold*3 * sizeof(double);
+
+  if (style != NSQ) {
+    bytes += maxbin * sizeof(int);
+    bytes += maxhead * sizeof(int);
+  }
+
+  for (int i = 0; i < nlist; i++) bytes += lists[i]->memory_usage();
+
+  bytes += maxbond*3 * sizeof(int);
+  bytes += maxangle*4 * sizeof(int);
+  bytes += maxdihedral*5 * sizeof(int);
+  bytes += maximproper*5 * sizeof(int);
+
+  return bytes;
+}
diff --git a/src/neighbor.h b/src/neighbor.h
index 4766f5cb2c5e907e9ac3c8c441075e3e76aef191..a4b8d2b8b714d81c6b4b58a20e8f9d186ddba0ce 100644
--- a/src/neighbor.h
+++ b/src/neighbor.h
@@ -20,7 +20,7 @@ namespace LAMMPS_NS {
 
 class Neighbor : protected Pointers {
  public:
-  int style;                       // 0 = nsq, 1 = binned
+  int style;                       // 0,1,2 = nsq, bin, multi
   int every;                       // build every this many steps
   int delay;                       // delay build for this many steps
   int dist_check;                  // 0 = always build, 1 = only if 1/2 dist
@@ -34,54 +34,38 @@ class Neighbor : protected Pointers {
 
   int ncalls;                      // # of times build has been called
   int ndanger;                     // # of dangerous builds
-  int nlocal_neighbor;             // nlocal at last build
 
-  int half;                        // 0/1 if half pair list ever built
-  int full;                        // 0/1 if full pair list ever built
-  int half_every;                  // 0/1 if half list built every step
-  int full_every;                  // 0/1 if full list built every step
-  int half_once;                   // 0/1 if half pair list built occasionally
-  int full_once;                   // 0/1 if full pair list built occasionally
-  int half_command;                // 0/1 if command requires half list
+  int nrequest;                    // requests for pairwise neighbor lists
+  class NeighRequest **requests;   // from Pair, Fix, Compute, Command classes
+  int maxrequest;
 
-  int *numneigh;                   // # of half neighbors for each atom
-  int **firstneigh;                // ptr to 1st half neighbor of each atom
-
-  int *numneigh_full;              // # of full neighbors for each atom
-  int **firstneigh_full;           // ptr to 1st full neighbor of each atom
+  int old_style;                   // previous run info to avoid
+  int old_nrequest;                // re-creation of pairwise neighbor lists
+  class NeighRequest **old_requests;
+  
+  int nlist;                       // pairwise neighbor lists
+  class NeighList **lists;
 
   int nbondlist;                   // list of bonds to compute
   int **bondlist;
-
   int nanglelist;                  // list of angles to compute
   int **anglelist;
-
   int ndihedrallist;               // list of dihedrals to compute
   int **dihedrallist;
-
   int nimproperlist;               // list of impropers to compute
   int **improperlist;
-                                   // granular neighbor list
-  int **firsttouch;                // ptr to first touch flag for each atom
-  double **firstshear;             // ptr to first shear values for each atom
-
-                                   // rRESPA neighbor lists
-  int *numneigh_inner;             // # of inner pair neighbors for each atom
-  int **firstneigh_inner;          // ptr to inner 1st neigh of each atom
-  int *numneigh_middle;            // # of middle pair neighbors for each atom
-  int **firstneigh_middle;         // ptr to middle 1st neigh of each atom
 
   Neighbor(class LAMMPS *);
   ~Neighbor();
   void init();
+  int request(void *);        // another class requests a neighbor list
   int decide();               // decide whether to build or not
   int check_distance();       // check max distance moved since last build
   void setup_bins();          // setup bins based on box and cutoff
-  void build();               // create all neighbor lists (half,full,bond)
-  void build_half();          // one-time creation of half neighbor list
-  void build_full();          // one-time creation of full neighbor list
+  void build();               // create all neighbor lists (pair,bond)
+  void build_one(int);        // create a single neighbor list
   void set(int, char **);     // set neighbor style and skin distance
-  void modify_params(int, char**);  // modify parameters of neighbor build
+  void modify_params(int, char**);  // modify parameters that control builds
   int memory_usage();         // tally memory usage
   
  private:
@@ -120,55 +104,19 @@ class Neighbor : protected Pointers {
   double binsizex,binsizey,binsizez;  // bin sizes and inverse sizes
   double bininvx,bininvy,bininvz;
 
+  int sx,sy,sz,smax;               // bin stencil extents
+
   int dimension;                   // 2/3 for 2d/3d
   int triclinic;                   // 0 if domain is orthog, 1 if triclinic
+  int newton_pair;                 // 0 if newton off, 1 if on for pairwise
+
   double *bboxlo,*bboxhi;          // copy of full domain bounding box
 
-  int nstencil;                    // # of bins in half neighbor stencil
-  int *stencil;                    // list of bin offsets
-  int maxstencil;                  // max size of stencil
-
-  int nstencil_full;               // # of bins in full neighbor stencil
-  int *stencil_full;               // list of bin offsets
-  int maxstencil_full;             // max size of stencil
-
-  int *nstencil_multi;             // # bins in each type-based multi stencil
-  int **stencil_multi;             // list of bin offsets in each stencil
-  double **distsq_multi;           // sq distances to bins in each stencil
-  int maxstencil_multi;            // max sizes of stencils
-
-  int *nstencil_full_multi;        // # bins in full type-based multi stencil
-  int **stencil_full_multi;        // list of bin offsets in each stencil
-  double **distsq_full_multi;      // sq distances to bins in each stencil
-  int maxstencil_full_multi;       // max sizes of stencils
-
-  int **pages;                     // half neighbor list pages
-  int maxpage;                     // # of half pages currently allocated
-
-  int **pages_full;                // full neighbor list pages
-  int maxpage_full;                // # of full pages currently allocated
-
-                                         // granular neighbor list
-  class FixShearHistory *fix_history;    // NULL if history not needed
-                                         // else is ptr to fix shear history
-  int **pages_touch;               // pages of touch flags
-  double **pages_shear;            // pages of shear values
-  int maxpage_history;             // # of history pages currently allocated
-
-                                   // rRESPA neighbor lists
-  int respa;                       // 0 = single neighbor list
-                                   // 1 = additional inner list
-                                   // 2 = additional inner and middle list
   double inner[2],middle[2];       // rRESPA cutoffs for extra lists
   double cut_inner_sq;		   // outer cutoff for inner neighbor list
   double cut_middle_sq;            // outer cutoff for middle neighbor list
   double cut_middle_inside_sq;     // inner cutoff for middle neighbor list
 
-  int **pages_inner;               // inner neighbor list pages
-  int maxpage_inner;               // # of inner pages currently allocated
-  int **pages_middle;              // middle neighbor list pages
-  int maxpage_middle;              // # of middle pages currently allocated
-
   int special_flag[4];             // flags for 1-2, 1-3, 1-4 neighbors
 
   int exclude;                     // 0 if no type/group exclusions, 1 if yes
@@ -188,100 +136,100 @@ class Neighbor : protected Pointers {
   int *ex_mol_group;               // molecule group #'s to exclude
   int *ex_mol_bit;                 // molecule group bits to exclude
 
-  typedef void (Neighbor::*FnPtr)();
-  FnPtr half_build;                   // ptr to half pair list functions
-  FnPtr full_build;                   // ptr to full pair list functions
+  int nblist,nglist,nslist;    // # of pairwise neigh lists of various kinds
+  int *blist;                  // lists to build every reneighboring
+  int *glist;                  // lists to grow atom arrays every reneigh
+  int *slist;                  // lists to grow stencil arrays every reneigh
 
-  void half_nsq_no_newton();          // fns for half neighbor lists
-  void half_nsq_newton();
+  void bin_atoms();                     // bin all atoms
+  double bin_distance(int, int, int);   // distance between binx
+  int coord2bin(double *);              // mapping atom coord to a bin
+  int find_special(int, int);           // look for special neighbor
+  int exclusion(int, int, int, int, int *, int *);  // test for pair exclusion
+  void choose_build(int, class NeighRequest *);
+  void choose_stencil(int, class NeighRequest *);
 
-  void half_bin_no_newton();
-  void half_bin_no_newton_multi();
-  void half_bin_newton();
-  void half_bin_newton_multi();
-  void half_bin_newton_tri();
-  void half_bin_newton_multi_tri();
+  // pairwise build functions
 
-  void half_full_no_newton();
-  void half_full_newton();
+  typedef void (Neighbor::*PairPtr)(class NeighList *);
+  PairPtr *pair_build;
 
-  void full_nsq();                    // fns for full neighbor lists
-  void full_bin();
-  void full_bin_multi();
+  void half_nsq_no_newton(class NeighList *);
+  void half_nsq_newton(class NeighList *);
 
-  void granular_nsq_no_newton();      // fns for granular neighbor lists
-  void granular_nsq_newton();
-  void granular_bin_no_newton();
-  void granular_bin_newton();
-  void granular_bin_newton_tri();
+  void half_bin_no_newton(class NeighList *);
+  void half_bin_newton(class NeighList *);
+  void half_bin_newton_tri(class NeighList *);
 
-  void respa_nsq_no_newton();         // fns for respa neighbor lists
-  void respa_nsq_newton();
-  void respa_bin_no_newton();
-  void respa_bin_newton();
-  void respa_bin_newton_tri();
+  void half_multi_no_newton(class NeighList *);
+  void half_multi_newton(class NeighList *);
+  void half_multi_newton_tri(class NeighList *);
 
-  FnPtr bond_build;                   // ptr to bond list functions
-  void bond_all();                    // bond list with all bonds
-  void bond_partial();                // exclude certain bonds
+  void full_nsq(class NeighList *);
+  void full_bin(class NeighList *);
+  void full_multi(class NeighList *);
 
-  FnPtr angle_build;                  // ptr to angle list functions
-  void angle_all();                   // angle list with all angles
-  void angle_partial();               // exclude certain angles
+  void half_full_no_newton(class NeighList *);
+  void half_full_newton(class NeighList *);
+  void skip_from(class NeighList *);
+  void copy_from(class NeighList *);
 
-  FnPtr dihedral_build;               // ptr to dihedral list functions
-  void dihedral_all();                // dihedral list with all dihedrals
-  void dihedral_partial();            // exclude certain dihedrals
+  void granular_nsq_no_newton(class NeighList *);
+  void granular_nsq_newton(class NeighList *);
+  void granular_bin_no_newton(class NeighList *);
+  void granular_bin_newton(class NeighList *);
+  void granular_bin_newton_tri(class NeighList *);
 
-  FnPtr improper_build;               // ptr to improper list functions
-  void improper_all();                // improper list with all impropers
-  void improper_partial();            // exclude certain impropers
+  void respa_nsq_no_newton(class NeighList *);
+  void respa_nsq_newton(class NeighList *);
+  void respa_bin_no_newton(class NeighList *);
+  void respa_bin_newton(class NeighList *);
+  void respa_bin_newton_tri(class NeighList *);
 
-  void add_pages(int);                // add neigh list pages
-  void add_pages_full(int);
-  void add_pages_history(int);
-  void add_pages_inner(int);
-  void add_pages_middle(int);
+  // pairwise stencil creation functions
 
-  void clear_pages();                 // clear all neigh list pages
-  void clear_pages_full();
-  void clear_pages_history();
-  void clear_pages_inner();
-  void clear_pages_middle();
+  typedef void (Neighbor::*StencilPtr)(class NeighList *, int, int, int);
+  StencilPtr *stencil_create;
 
-  void bin_atoms();                     // bin all atoms
-  double bin_distance(int, int, int);   // distance between binx
-  int coord2bin(double *);              // mapping atom coord to a bin
-  int find_special(int, int);           // look for special neighbor
-  int exclusion(int, int, int *, int *, int *);  // test for pair exclusion
+  void stencil_half_bin_2d_no_newton(class NeighList *, int, int, int);
+  void stencil_half_bin_3d_no_newton(class NeighList *, int, int, int);
+  void stencil_half_bin_2d_newton(class NeighList *, int, int, int);
+  void stencil_half_bin_3d_newton(class NeighList *, int, int, int);
+  void stencil_half_bin_2d_newton_tri(class NeighList *, int, int, int);
+  void stencil_half_bin_3d_newton_tri(class NeighList *, int, int, int);
 
-  typedef void (Neighbor::*SFnPtr)(int, int, int);
-  SFnPtr half_stencil;                // ptr to half stencil functions
-  SFnPtr full_stencil;                // ptr to full stencil functions
+  void stencil_half_multi_2d_no_newton(class NeighList *, int, int, int);
+  void stencil_half_multi_3d_no_newton(class NeighList *, int, int, int);
+  void stencil_half_multi_2d_newton(class NeighList *, int, int, int);
+  void stencil_half_multi_3d_newton(class NeighList *, int, int, int);
+  void stencil_half_multi_2d_newton_tri(class NeighList *, int, int, int);
+  void stencil_half_multi_3d_newton_tri(class NeighList *, int, int, int);
 
-  void stencil_allocate(int, int, int);
+  void stencil_full_bin_2d(class NeighList *, int, int, int);
+  void stencil_full_bin_3d(class NeighList *, int, int, int);
+  void stencil_full_multi_2d(class NeighList *, int, int, int);
+  void stencil_full_multi_3d(class NeighList *, int, int, int);
 
-  void stencil_none(int, int, int);   // fns for stencil creation
+  // topology build functions
 
-  void stencil_half_3d_no_newton(int, int, int);
-  void stencil_half_3d_no_newton_multi(int, int, int);
-  void stencil_half_3d_newton(int, int, int);
-  void stencil_half_3d_newton_multi(int, int, int);
-  void stencil_half_3d_newton_tri(int, int, int);
-  void stencil_half_3d_newton_multi_tri(int, int, int);
+  typedef void (Neighbor::*BondPtr)();   // ptrs to topology build functions
 
-  void stencil_half_2d_no_newton(int, int, int);
-  void stencil_half_2d_no_newton_multi(int, int, int);
-  void stencil_half_2d_newton(int, int, int);
-  void stencil_half_2d_newton_multi(int, int, int);
-  void stencil_half_2d_newton_tri(int, int, int);
-  void stencil_half_2d_newton_multi_tri(int, int, int);
+  BondPtr bond_build;                 // ptr to bond list functions
+  void bond_all();                    // bond list with all bonds
+  void bond_partial();                // exclude certain bonds
 
-  void stencil_full_3d(int, int, int);
-  void stencil_full_3d_multi(int, int, int);
+  BondPtr angle_build;                // ptr to angle list functions
+  void angle_all();                   // angle list with all angles
+  void angle_partial();               // exclude certain angles
+
+  BondPtr dihedral_build;             // ptr to dihedral list functions
+  void dihedral_all();                // dihedral list with all dihedrals
+  void dihedral_partial();            // exclude certain dihedrals
+
+  BondPtr improper_build;             // ptr to improper list functions
+  void improper_all();                // improper list with all impropers
+  void improper_partial();            // exclude certain impropers
 
-  void stencil_full_2d(int, int, int);
-  void stencil_full_2d_multi(int, int, int);
 };
 
 }
diff --git a/src/output.cpp b/src/output.cpp
index fd5d765c11131ae8b07d9d929a41659af39f5049..4e850d903ac5c80bfc6121274655da45edd3f14a 100644
--- a/src/output.cpp
+++ b/src/output.cpp
@@ -49,21 +49,21 @@ Output::Output(LAMMPS *lmp) : Pointers(lmp)
   // create 2 default computes for temp and pressure
 
   char **newarg = new char*[4];
-  newarg[0] = "thermo_temp";
-  newarg[1] = "all";
-  newarg[2] = "temp";
+  newarg[0] = (char *) "thermo_temp";
+  newarg[1] = (char *) "all";
+  newarg[2] = (char *) "temp";
   modify->add_compute(3,newarg);
-  newarg[0] = "thermo_pressure";
-  newarg[1] = "all";
-  newarg[2] = "pressure";
-  newarg[3] = "thermo_temp";
+  newarg[0] = (char *) "thermo_pressure";
+  newarg[1] = (char *) "all";
+  newarg[2] = (char *) "pressure";
+  newarg[3] = (char *) "thermo_temp";
   modify->add_compute(4,newarg);
   delete [] newarg;
 
   // create default Thermo class
 
   newarg = new char*[1];
-  newarg[0] = "one";
+  newarg[0] = (char *) "one";
   thermo = new Thermo(lmp,1,newarg);
   delete [] newarg;
     
diff --git a/src/pair.cpp b/src/pair.cpp
index b7278c634b80e53a1bc0898ad74f739f53789df9..02a9ec576274602300a4e5b719ae20d31d4ff715 100644
--- a/src/pair.cpp
+++ b/src/pair.cpp
@@ -25,6 +25,8 @@
 #include "pair.h"
 #include "pair_soft.h"
 #include "atom.h"
+#include "neighbor.h"
+#include "neigh_list.h"
 #include "domain.h"
 #include "comm.h"
 #include "force.h"
@@ -46,8 +48,6 @@ Pair::Pair(LAMMPS *lmp) : Pointers(lmp)
   eng_vdwl = eng_coul = 0.0;
 
   comm_forward = comm_reverse = 0;
-  neigh_half_every = 1;
-  neigh_full_every = 0;
 
   single_enable = 1;
   respa_enable = 0;
@@ -123,11 +123,21 @@ void Pair::init()
     error->warning("Using pair tail corrections with nonperiodic system");
 
   if (!allocated) error->all("All pair coeffs are not set");
+
+  // I,I coeffs must be set
+  // init_one() will check if I,J is set explicitly or inferred by mixing
+
   for (i = 1; i <= atom->ntypes; i++)
     if (setflag[i][i] == 0) error->all("All pair coeffs are not set");
 
+  // style-specific initialization
+
   init_style();
 
+  // call init_one() for each I,J
+  // set cutsq for each I,J, used to neighbor
+  // cutforce = max of all I,J cutoffs
+
   double cut;
   cutforce = 0.0;
   etail = ptail = 0.0;
@@ -147,6 +157,29 @@ void Pair::init()
     }
 }
 
+/* ----------------------------------------------------------------------
+   init specific to a pair style
+   specific pair style can override this function
+     if needs its own error checks
+     if needs another kind of neighbor list
+   request default neighbor list = half list
+------------------------------------------------------------------------- */
+
+void Pair::init_style()
+{
+  int irequest = neighbor->request(this);
+}
+
+/* ----------------------------------------------------------------------
+   neighbor callback to inform pair style of neighbor list to use
+   specific pair style can override this function
+------------------------------------------------------------------------- */
+
+void Pair::init_list(int which, NeighList *ptr)
+{
+  list = ptr;
+}
+
 /* ----------------------------------------------------------------------
    mixing of pair potential prefactors (epsilon)
 ------------------------------------------------------------------------- */
@@ -181,34 +214,25 @@ double Pair::mix_distance(double sig1, double sig2)
 }
 
 /* ----------------------------------------------------------------------
-   compute pair virial via pair own/ghost forces 
+   compute pair virial via own/ghost forces
+   at this point, only pairwise forces have been accumulated in atom->f
 ------------------------------------------------------------------------- */
 
 void Pair::virial_compute()
 {
   double **x = atom->x;
-  double **f_pair = update->f_pair;
+  double **f = atom->f;
   int nall = atom->nlocal + atom->nghost;
 
   // sum over own & ghost atoms
 
   for (int i = 0; i < nall; i++) {
-    virial[0] += f_pair[i][0]*x[i][0];
-    virial[1] += f_pair[i][1]*x[i][1];
-    virial[2] += f_pair[i][2]*x[i][2];
-    virial[3] += f_pair[i][1]*x[i][0];
-    virial[4] += f_pair[i][2]*x[i][0];
-    virial[5] += f_pair[i][2]*x[i][1];
-  }
-
-  // add pair forces into total force
-
-  double **f = atom->f;
-
-  for (int i = 0; i < nall; i++) {
-    f[i][0] += f_pair[i][0];
-    f[i][1] += f_pair[i][1];
-    f[i][2] += f_pair[i][2];
+    virial[0] += f[i][0]*x[i][0];
+    virial[1] += f[i][1]*x[i][1];
+    virial[2] += f[i][2]*x[i][2];
+    virial[3] += f[i][1]*x[i][0];
+    virial[4] += f[i][2]*x[i][0];
+    virial[5] += f[i][2]*x[i][1];
   }
 }
 
diff --git a/src/pair.h b/src/pair.h
index 00f10c03972e5b0ccf3605809ac33b90ef597dcf..342c844e9bac1119736873566ffb7aa6223e973e 100644
--- a/src/pair.h
+++ b/src/pair.h
@@ -29,8 +29,6 @@ class Pair : protected Pointers {
 
   int comm_forward;              // size of forward communication (0 if none)
   int comm_reverse;              // size of reverse communication (0 if none)
-  int neigh_half_every;          // 0/1 = if needs half neighbor list
-  int neigh_full_every;          // 0/1 = if needs full neighbor list
 
   int single_enable;             // 1 if single() routine exists
   int respa_enable;              // 1 if inner/middle/outer rRESPA routines
@@ -40,11 +38,17 @@ class Pair : protected Pointers {
   double etail,ptail;            // energy/pressure tail corrections
   double etail_ij,ptail_ij;
 
+  class NeighList *list;         // standard neighbor list used by most pairs
+  class NeighList *listhalf;     // half list used by some pairs
+  class NeighList *listfull;     // full list used by some pairs
+  class NeighList *listgranhistory;  // granular history list used by some
+  class NeighList *listinner;    // rRESPA lists used by some pairs
+  class NeighList *listmiddle;
+  class NeighList *listouter;
+
   struct One {                   // single interaction between 2 atoms
     double fforce;
     double eng_vdwl,eng_coul;
-    double fx,fy,fz;
-    double tix,tiy,tiz,tjx,tjy,tjz;
   };
 
   Pair(class LAMMPS *);
@@ -63,17 +67,20 @@ class Pair : protected Pointers {
   // general child-class methods
 
   virtual void compute(int, int) = 0;
-  virtual void settings(int, char **) = 0;
-  virtual void coeff(int, char **) = 0;
-
-  virtual double init_one(int, int) {return 0.0;}
-  virtual void init_style() {}
   virtual void compute_inner() {}
   virtual void compute_middle() {}
   virtual void compute_outer(int, int) {}
+
   virtual void single(int, int, int, int,
 		      double, double, double, int, One &) {}
 
+  virtual void settings(int, char **) = 0;
+  virtual void coeff(int, char **) = 0;
+
+  virtual void init_style();
+  virtual void init_list(int, class NeighList *);
+  virtual double init_one(int, int) {return 0.0;}
+
   virtual void write_restart(FILE *) {}
   virtual void read_restart(FILE *) {}
   virtual void write_restart_settings(FILE *) {}
@@ -88,6 +95,9 @@ class Pair : protected Pointers {
   // specific child-class methods for certain Pair styles
   
   virtual void single_embed(int, int, double &) {}
+
+  virtual void *extract_ptr(char *) {return NULL;}
+
   virtual void extract_charmm(double ***, double ***,
 			      double ***, double ***, int *) {}
   virtual void extract_dipole(double ***) {}
diff --git a/src/pair_buck.cpp b/src/pair_buck.cpp
index 5fe48f4189d81e3245def0fef088e06a9dd11135..67d919177b1902bd99c964a80ae7b183bca2ae20 100644
--- a/src/pair_buck.cpp
+++ b/src/pair_buck.cpp
@@ -18,9 +18,8 @@
 #include "atom.h"
 #include "comm.h"
 #include "force.h"
-#include "update.h"
+#include "neigh_list.h"
 #include "memory.h"
-#include "neighbor.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
@@ -55,37 +54,41 @@ PairBuck::~PairBuck()
 
 void PairBuck::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r6inv,forcebuck,fforce,factor_lj;
   double phibuck,r,rexp;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
diff --git a/src/pair_buck_coul_cut.cpp b/src/pair_buck_coul_cut.cpp
index 9348c0f693dd1757c4531b744fdf98c359877608..955b98c7cd4a505166cde1fae7abf12bd90f08cc 100644
--- a/src/pair_buck_coul_cut.cpp
+++ b/src/pair_buck_coul_cut.cpp
@@ -22,9 +22,9 @@
 #include "atom.h"
 #include "comm.h"
 #include "force.h"
-#include "update.h"
-#include "memory.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "memory.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
@@ -62,19 +62,17 @@ PairBuckCoulCut::~PairBuckCoulCut()
 
 void PairBuckCoulCut::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r6inv,forcecoul,forcebuck,fforce,factor_coul,factor_lj;
   double factor,phicoul,phibuck,r,rexp;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = eng_coul = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   double *q = atom->q;
   int *type = atom->type;
   int nlocal = atom->nlocal;
@@ -84,19 +82,25 @@ void PairBuckCoulCut::compute(int eflag, int vflag)
   int newton_pair = force->newton_pair;
   double qqrd2e = force->qqrd2e;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     qtmp = q[i];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_coul = factor_lj = 1.0;
       else {
@@ -258,6 +262,18 @@ void PairBuckCoulCut::coeff(int narg, char **arg)
   if (count == 0) error->all("Incorrect args for pair coefficients");
 }
 
+/* ----------------------------------------------------------------------
+   init specific to this pair style
+------------------------------------------------------------------------- */
+
+void PairBuckCoulCut::init_style()
+{
+  if (!atom->q_flag)
+    error->all("Pair style buck/coul/cut requires atom attribute q");
+
+  int irequest = neighbor->request(this);
+}
+
 /* ----------------------------------------------------------------------
    init for one type pair i,j and corresponding j,i
 ------------------------------------------------------------------------- */
@@ -291,16 +307,6 @@ double PairBuckCoulCut::init_one(int i, int j)
   return cut;
 }
 
-/* ----------------------------------------------------------------------
-   init specific to this pair style
-------------------------------------------------------------------------- */
-
-void PairBuckCoulCut::init_style()
-{
-  if (!atom->q_flag)
-    error->all("Pair style buck/coul/cut requires atom attribute q");
-}
-
 /* ----------------------------------------------------------------------
   proc 0 writes to restart file
 ------------------------------------------------------------------------- */
diff --git a/src/pair_buck_coul_cut.h b/src/pair_buck_coul_cut.h
index 6bf81731f7e5db25aaec6a1f302d52c696889467..06fd27c7819dd4699b4dbf001f854d6373384324 100644
--- a/src/pair_buck_coul_cut.h
+++ b/src/pair_buck_coul_cut.h
@@ -25,8 +25,8 @@ class PairBuckCoulCut : public Pair {
   void compute(int, int);
   void settings(int, char **);
   void coeff(int, char **);
-  double init_one(int, int);
   void init_style();
+  double init_one(int, int);
   void write_restart(FILE *);
   void read_restart(FILE *);
   void write_restart_settings(FILE *);
diff --git a/src/pair_coul_cut.cpp b/src/pair_coul_cut.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ba5f6a44eff3f0aa32c782b8ed070aeb76134375
--- /dev/null
+++ b/src/pair_coul_cut.cpp
@@ -0,0 +1,313 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, 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 "math.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "pair_coul_cut.h"
+#include "atom.h"
+#include "comm.h"
+#include "force.h"
+#include "neighbor.h"
+#include "neigh_list.h"
+#include "memory.h"
+#include "error.h"
+
+using namespace LAMMPS_NS;
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+/* ---------------------------------------------------------------------- */
+
+PairCoulCut::PairCoulCut(LAMMPS *lmp) : Pair(lmp) {}
+
+/* ---------------------------------------------------------------------- */
+
+PairCoulCut::~PairCoulCut()
+{
+  if (allocated) {
+    memory->destroy_2d_int_array(setflag);
+    memory->destroy_2d_double_array(cutsq);
+
+    memory->destroy_2d_double_array(cut);
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairCoulCut::compute(int eflag, int vflag)
+{
+  int i,j,ii,jj,inum,jnum,itype,jtype;
+  double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
+  double rsq,r2inv,rinv,forcecoul,fforce,factor_coul,phicoul;
+  int *ilist,*jlist,*numneigh,**firstneigh;
+
+  eng_coul = 0.0;
+  if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
+
+  double **x = atom->x;
+  double **f = atom->f;
+  double *q = atom->q;
+  int *type = atom->type;
+  int nlocal = atom->nlocal;
+  int nall = atom->nlocal + atom->nghost;
+  double *special_coul = force->special_coul;
+  int newton_pair = force->newton_pair;
+  double qqrd2e = force->qqrd2e;
+
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
+  // loop over neighbors of my atoms
+
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
+    qtmp = q[i];
+    xtmp = x[i][0];
+    ytmp = x[i][1];
+    ztmp = x[i][2];
+    itype = type[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
+
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
+
+      if (j < nall) factor_coul = 1.0;
+      else {
+	factor_coul = special_coul[j/nall];
+	j %= nall;
+      }
+
+      delx = xtmp - x[j][0];
+      dely = ytmp - x[j][1];
+      delz = ztmp - x[j][2];
+      rsq = delx*delx + dely*dely + delz*delz;
+      jtype = type[j];
+
+      if (rsq < cutsq[itype][jtype]) {
+	r2inv = 1.0/rsq;
+	rinv = sqrt(r2inv);
+	forcecoul = qqrd2e * qtmp*q[j]*rinv;
+	fforce = factor_coul*forcecoul * r2inv;
+
+	f[i][0] += delx*fforce;
+	f[i][1] += dely*fforce;
+	f[i][2] += delz*fforce;
+	if (newton_pair || j < nlocal) {
+	  f[j][0] -= delx*fforce;
+	  f[j][1] -= dely*fforce;
+	  f[j][2] -= delz*fforce;
+	}
+
+	if (eflag) {
+	  phicoul = qqrd2e * qtmp*q[j]*rinv;
+	  if (newton_pair || j < nlocal) eng_coul += factor_coul*phicoul;
+	  else eng_coul += 0.5*factor_coul*phicoul;
+	}
+
+	if (vflag == 1) {
+	  if (newton_pair == 0 && j >= nlocal) fforce *= 0.5;
+	  virial[0] += delx*delx*fforce;
+	  virial[1] += dely*dely*fforce;
+	  virial[2] += delz*delz*fforce;
+	  virial[3] += delx*dely*fforce;
+	  virial[4] += delx*delz*fforce;
+	  virial[5] += dely*delz*fforce;
+	}
+      }
+    }
+  }
+  if (vflag == 2) virial_compute();
+}
+
+/* ----------------------------------------------------------------------
+   allocate all arrays
+------------------------------------------------------------------------- */
+
+void PairCoulCut::allocate()
+{
+  allocated = 1;
+  int n = atom->ntypes;
+
+  setflag = memory->create_2d_int_array(n+1,n+1,"pair:setflag");
+  for (int i = 1; i <= n; i++)
+    for (int j = i; j <= n; j++)
+      setflag[i][j] = 0;
+
+  cutsq = memory->create_2d_double_array(n+1,n+1,"pair:cutsq");
+
+  cut = memory->create_2d_double_array(n+1,n+1,"pair:cut");
+}
+
+/* ----------------------------------------------------------------------
+   global settings
+------------------------------------------------------------------------- */
+
+void PairCoulCut::settings(int narg, char **arg)
+{
+  if (narg != 1) error->all("Illegal pair_style command");
+
+  cut_global = atof(arg[0]);
+
+  // reset cutoffs that have been explicitly set
+
+  if (allocated) {
+    int i,j;
+    for (i = 1; i <= atom->ntypes; i++)
+      for (j = i+1; j <= atom->ntypes; j++)
+	if (setflag[i][j]) cut[i][j] = cut_global;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   set coeffs for one or more type pairs
+------------------------------------------------------------------------- */
+
+void PairCoulCut::coeff(int narg, char **arg)
+{
+  if (narg < 2 || narg > 3) error->all("Incorrect args for pair coefficients");
+  if (!allocated) allocate();
+
+  int ilo,ihi,jlo,jhi;
+  force->bounds(arg[0],atom->ntypes,ilo,ihi);
+  force->bounds(arg[1],atom->ntypes,jlo,jhi);
+
+  double cut_one = cut_global;
+  if (narg == 3) cut_one = atof(arg[2]);
+
+  int count = 0;
+  for (int i = ilo; i <= ihi; i++) {
+    for (int j = MAX(jlo,i); j <= jhi; j++) {
+      cut[i][j] = cut_one;
+      setflag[i][j] = 1;
+      count++;
+    }
+  }
+
+  if (count == 0) error->all("Incorrect args for pair coefficients");
+}
+
+
+/* ----------------------------------------------------------------------
+   init specific to this pair style
+------------------------------------------------------------------------- */
+
+void PairCoulCut::init_style()
+{
+  if (!atom->q_flag)
+    error->all("Pair style coul/cut requires atom attribute q");
+
+  int irequest = neighbor->request(this);
+}
+
+/* ----------------------------------------------------------------------
+   init for one type pair i,j and corresponding j,i
+------------------------------------------------------------------------- */
+
+double PairCoulCut::init_one(int i, int j)
+{
+  if (setflag[i][j] == 0)
+    cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
+
+  return cut[i][j];
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairCoulCut::write_restart(FILE *fp)
+{
+  write_restart_settings(fp);
+
+  int i,j;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      fwrite(&setflag[i][j],sizeof(int),1,fp);
+      if (setflag[i][j]) fwrite(&cut[i][j],sizeof(double),1,fp);
+    }
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairCoulCut::read_restart(FILE *fp)
+{
+  read_restart_settings(fp);
+  allocate();
+
+  int i,j;
+  int me = comm->me;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
+      MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
+      if (setflag[i][j]) {
+	if (me == 0) fread(&cut[i][j],sizeof(double),1,fp);
+	MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
+      }
+    }
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairCoulCut::write_restart_settings(FILE *fp)
+{
+  fwrite(&cut_global,sizeof(double),1,fp);
+  fwrite(&offset_flag,sizeof(int),1,fp);
+  fwrite(&mix_flag,sizeof(int),1,fp);
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairCoulCut::read_restart_settings(FILE *fp)
+{
+  if (comm->me == 0) {
+    fread(&cut_global,sizeof(double),1,fp);
+    fread(&offset_flag,sizeof(int),1,fp);
+    fread(&mix_flag,sizeof(int),1,fp);
+  }
+  MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
+  MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
+  MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairCoulCut::single(int i, int j, int itype, int jtype,
+			      double rsq, double factor_coul, double factor_lj,
+			      int eflag, One &one)
+{
+  double r2inv,rinv,forcecoul,phicoul;
+
+  r2inv = 1.0/rsq;
+  rinv = sqrt(r2inv);
+  forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*rinv;
+  one.fforce = factor_coul*forcecoul * r2inv;
+
+  if (eflag) {
+    phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*rinv;
+    one.eng_coul = factor_coul*phicoul;
+    one.eng_vdwl = 0.0;
+  }
+}
diff --git a/src/compute_etotal_atom.h b/src/pair_coul_cut.h
similarity index 55%
rename from src/compute_etotal_atom.h
rename to src/pair_coul_cut.h
index b5c171e2ac74850a2ca2aa7264e8a5a4eab9b8a5..9b6a0fca4927ea5cd5e8d20cabbf5e292bbaa710 100644
--- a/src/compute_etotal_atom.h
+++ b/src/pair_coul_cut.h
@@ -11,25 +11,33 @@
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
-#ifndef COMPUTE_ETOTAL_ATOM_H
-#define COMPUTE_ETOTAL_ATOM_H
+#ifndef PAIR_COUL_CUT_H
+#define PAIR_COUL_CUT_H
 
-#include "compute.h"
+#include "pair.h"
 
 namespace LAMMPS_NS {
 
-class ComputeEtotalAtom : public Compute {
+class PairCoulCut : public Pair {
  public:
-  ComputeEtotalAtom(class LAMMPS *, int, char **);
-  ~ComputeEtotalAtom();
-  void init();
-  void compute_peratom();
-  int memory_usage();
+  PairCoulCut(class LAMMPS *);
+  ~PairCoulCut();
+  void compute(int, int);
+  void settings(int, char **);
+  void coeff(int, char **);
+  void init_style();
+  double init_one(int, int);
+  void write_restart(FILE *);
+  void read_restart(FILE *);
+  void write_restart_settings(FILE *);
+  void read_restart_settings(FILE *);
+  void single(int, int, int, int, double, double, double, int, One &);
 
  private:
-  int nmax;
-  double *etotal;
-  Compute *compute_epair;
+  double cut_global;
+  double **cut;
+
+  void allocate();
 };
 
 }
diff --git a/src/pair_hybrid.cpp b/src/pair_hybrid.cpp
index 80f77a74dee94bfd2ded1940ab082f3b04f50f9f..df69770d7776f5d60000185f77cd05fcaacb13be 100644
--- a/src/pair_hybrid.cpp
+++ b/src/pair_hybrid.cpp
@@ -11,13 +11,6 @@
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
-/* ----------------------------------------------------------------------
-   Contributing authors: 
-     James Fischer (High Performance Technologies, Inc)
-     Vincent Natoli (Stone Ridge Technology)
-     David Richie (Stone Ridge Technology)
-------------------------------------------------------------------------- */
-
 #include "math.h"
 #include "string.h"
 #include "ctype.h"
@@ -26,6 +19,7 @@
 #include "force.h"
 #include "pair.h"
 #include "neighbor.h"
+#include "neigh_request.h"
 #include "update.h"
 #include "comm.h"
 #include "memory.h"
@@ -33,8 +27,6 @@
 
 using namespace LAMMPS_NS;
 
-#define NEIGHEXTRA 10000
-
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 
@@ -58,265 +50,32 @@ PairHybrid::~PairHybrid()
 
   if (allocated) {
     memory->destroy_2d_int_array(setflag);
-    memory->destroy_2d_int_array(map);
     memory->destroy_2d_double_array(cutsq);
-
-    delete [] nnlist;
-    delete [] maxneigh;
-    for (int m = 0; m < nstyles; m++) memory->sfree(nlist[m]);
-    delete [] nlist;
-
-    delete [] nnlist_full;
-    delete [] maxneigh_full;
-    for (int m = 0; m < nstyles; m++) memory->sfree(nlist_full[m]);
-    delete [] nlist_full;
-
-    for (int m = 0; m < nstyles; m++) delete [] firstneigh[m];
-    delete [] firstneigh;
-    for (int m = 0; m < nstyles; m++) delete [] numneigh[m];
-    delete [] numneigh;
-
-    for (int m = 0; m < nstyles; m++) delete [] firstneigh_full[m];
-    delete [] firstneigh_full;
-    for (int m = 0; m < nstyles; m++) delete [] numneigh_full[m];
-    delete [] numneigh_full;
+    memory->destroy_2d_int_array(nmap);
+    memory->destroy_3d_int_array(map);
   }
 }
 
-/* ---------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------
+  call each sub-style's compute function
+  accumulate sub-style energy/virial in hybrid's energy/virial
+  for vflag = 1:
+    each sub-style computes own virial[6]
+    sum sub-style virial[6] to hybrid's virial[6]
+  for vflag = 2:
+    call sub-style compute() with vflag % 2
+      to prevent sub-style from calling virial_compute()
+    hybrid calls virial_compute() on final accumulated f
+------------------------------------------------------------------------- */
 
 void PairHybrid::compute(int eflag, int vflag)
 {
-  int i,j,k,m,n,jfull,nneigh;
-  int *neighs,*mapi;
-  double **f_original;
-
-  // save ptrs to original neighbor lists
-
-  int **firstneigh_original = neighbor->firstneigh;
-  int *numneigh_original = neighbor->numneigh;
-  int **firstneigh_full_original = neighbor->firstneigh_full;
-  int *numneigh_full_original = neighbor->numneigh_full;
-
-  // if this is re-neighbor step, create sub-style lists
-
-  if (neighbor->ago == 0) {
-    int *type = atom->type;
-    int nlocal = atom->nlocal;
-    int nall = atom->nlocal + atom->nghost;
-
-    // realloc per-atom per-style firstneigh/numneigh half/full if necessary
-
-    if (nlocal > maxlocal) {
-      maxlocal = nlocal;
-      if (neigh_half_every) {
-	for (m = 0; m < nstyles; m++) {
-	  delete [] firstneigh[m];
-	  delete [] numneigh[m];
-	}
-	for (m = 0; m < nstyles; m++) {
-	  firstneigh[m] = new int*[maxlocal];
-	  numneigh[m] = new int[maxlocal];
-	}
-      }
-      if (neigh_full_every) {
-	for (m = 0; m < nstyles; m++) {
-	  delete [] firstneigh_full[m];
-	  delete [] numneigh_full[m];
-	}
-	for (m = 0; m < nstyles; m++) {
-	  firstneigh_full[m] = new int*[maxlocal];
-	  numneigh_full[m] = new int[maxlocal];
-	}
-      }
-    }
-
-    // nnlist[] = length of each sub-style half list
-    // nnlist_full[] = length of each sub-style full list
-    // count from half and/or full list depending on what sub-styles use
-
-    for (m = 0; m < nstyles; m++) nnlist[m] = nnlist_full[m] = 0;
-
-    if (neigh_half_every && neigh_full_every) {
-      for (i = 0; i < nlocal; i++) {
-	mapi = map[type[i]];
-	neighs = firstneigh_original[i];
-	nneigh = numneigh_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = neighs[k];
-	  if (j >= nall) j %= nall;
-	  m = mapi[type[j]];
-	  if (styles[m] && styles[m]->neigh_half_every) nnlist[m]++;
-	}
-	neighs = firstneigh_full_original[i];
-	nneigh = numneigh_full_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = neighs[k];
-	  if (j >= nall) j %= nall;
-	  m = mapi[type[j]];
-	  if (styles[m] && styles[m]->neigh_full_every) nnlist_full[m]++;
-	}
-      }
-
-    } else if (neigh_half_every) {
-      for (i = 0; i < nlocal; i++) {
-	mapi = map[type[i]];
-	neighs = firstneigh_original[i];
-	nneigh = numneigh_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = neighs[k];
-	  if (j >= nall) j %= nall;
-	  nnlist[mapi[type[j]]]++;
-	}
-      }
-
-    } else if (neigh_full_every) {
-      for (i = 0; i < nlocal; i++) {
-	mapi = map[type[i]];
-	neighs = firstneigh_full_original[i];
-	nneigh = numneigh_full_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = neighs[k];
-	  if (j >= nall) j %= nall;
-	  nnlist_full[mapi[type[j]]]++;
-	}
-      }
-    }
-
-    // realloc sub-style nlist and nlist_full if necessary
-
-    if (neigh_half_every) {
-      for (m = 0; m < nstyles; m++) {
-	if (nnlist[m] > maxneigh[m]) {
-	  memory->sfree(nlist[m]);
-	  maxneigh[m] = nnlist[m] + NEIGHEXTRA;
-	  nlist[m] = (int *)
-	    memory->smalloc(maxneigh[m]*sizeof(int),"pair_hybrid:nlist");
-	}
-	nnlist[m] = 0;
-      }
-    }
-    if (neigh_full_every) {
-      for (m = 0; m < nstyles; m++) {
-	if (nnlist_full[m] > maxneigh_full[m]) {
-	  memory->sfree(nlist_full[m]);
-	  maxneigh_full[m] = nnlist_full[m] + NEIGHEXTRA;
-	  nlist_full[m] = (int *)
-	    memory->smalloc(maxneigh_full[m]*sizeof(int),
-			    "pair_hybrid:nlist_full");
-	}
-	nnlist_full[m] = 0;
-      }
-    }
-
-    // load sub-style half/full list with values from original lists
-    // load from half and/or full list depending on what sub-styles use
-
-    if (neigh_half_every && neigh_full_every) {
-      for (i = 0; i < nlocal; i++) {
-	for (m = 0; m < nstyles; m++) {
-	  firstneigh[m][i] = &nlist[m][nnlist[m]];
-	  numneigh[m][i] = nnlist[m];
-	  firstneigh_full[m][i] = &nlist_full[m][nnlist_full[m]];
-	  numneigh_full[m][i] = nnlist_full[m];
-	}
-	mapi = map[type[i]];
-	neighs = firstneigh_original[i];
-	nneigh = numneigh_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = jfull = neighs[k];
-	  if (j >= nall) j %= nall;
-	  m = mapi[type[j]];
-	  if (styles[m] && styles[m]->neigh_half_every)
-	    nlist[m][nnlist[m]++] = jfull;
-	}
-	neighs = firstneigh_full_original[i];
-	nneigh = numneigh_full_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = jfull = neighs[k];
-	  if (j >= nall) j %= nall;
-	  m = mapi[type[j]];
-	  if (styles[m] && styles[m]->neigh_full_every)
-	    nlist_full[m][nnlist_full[m]++] = jfull;
-	}
-	for (m = 0; m < nstyles; m++) {
-	  numneigh[m][i] = nnlist[m] - numneigh[m][i];
-	  numneigh_full[m][i] = nnlist_full[m] - numneigh_full[m][i];
-	}
-      }
-
-    } else if (neigh_half_every) {
-      for (i = 0; i < nlocal; i++) {
-	for (m = 0; m < nstyles; m++) {
-	  firstneigh[m][i] = &nlist[m][nnlist[m]];
-	  numneigh[m][i] = nnlist[m];
-	}
-	mapi = map[type[i]];
-	neighs = firstneigh_original[i];
-	nneigh = numneigh_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = jfull = neighs[k];
-	  if (j >= nall) j %= nall;
-	  m = mapi[type[j]];
-	  nlist[m][nnlist[m]++] = jfull;
-	}
-	for (m = 0; m < nstyles; m++)
-	  numneigh[m][i] = nnlist[m] - numneigh[m][i];
-      }
-
-    } else if (neigh_full_every) {
-      for (i = 0; i < nlocal; i++) {
-	for (m = 0; m < nstyles; m++) {
-	  firstneigh_full[m][i] = &nlist_full[m][nnlist_full[m]];
-	  numneigh_full[m][i] = nnlist_full[m];
-	}
-	mapi = map[type[i]];
-	neighs = firstneigh_full_original[i];
-	nneigh = numneigh_full_original[i];
-	for (k = 0; k < nneigh; k++) {
-	  j = jfull = neighs[k];
-	  if (j >= nall) j %= nall;
-	  m = mapi[type[j]];
-	  nlist_full[m][nnlist_full[m]++] = jfull;
-	}
-	for (m = 0; m < nstyles; m++)
-	  numneigh_full[m][i] = nnlist_full[m] - numneigh_full[m][i];
-      }
-    }
-  }
-  
-  // call each sub-style's compute function
-  // set neighbor->firstneigh/numneigh to sub-style lists before call
-  //   set half or full or both depending on what sub-style uses
-  // for vflag = 1:
-  //   sub-style accumulates in its virial[6]
-  //   sum sub-style virial[6] to hybrid's virial[6]
-  // for vflag = 2:
-  //   set atom->f to update->f_pair so sub-style will sum its f to f_pair
-  //   call sub-style compute() with vflag % 2 to prevent sub-style
-  //     from calling virial_compute()
-  //   reset atom->f to stored f_original
-  //   call hybrid virial_compute() which will use update->f_pair
-  // accumulate sub-style energy,virial in hybrid's energy,virial
+  int m,n;
 
   eng_vdwl = eng_coul = 0.0;
   if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
 
-  if (vflag == 2) {
-    f_original = atom->f;
-    atom->f = update->f_pair;
-  }
-
   for (m = 0; m < nstyles; m++) {
-    if (styles[m] == NULL) continue;
-    if (styles[m]->neigh_half_every) {
-      neighbor->firstneigh = firstneigh[m];
-      neighbor->numneigh = numneigh[m];
-    } 
-    if (styles[m]->neigh_full_every) {
-      neighbor->firstneigh_full = firstneigh_full[m];
-      neighbor->numneigh_full = numneigh_full[m];
-    }
     styles[m]->compute(eflag,vflag % 2);
     if (eflag) {
       eng_vdwl += styles[m]->eng_vdwl;
@@ -325,17 +84,7 @@ void PairHybrid::compute(int eflag, int vflag)
     if (vflag == 1) for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
   }
 
-  if (vflag == 2) {
-    atom->f = f_original;
-    virial_compute();
-  }
-
-  // restore ptrs to original neighbor lists
-
-  neighbor->firstneigh = firstneigh_original;
-  neighbor->numneigh = numneigh_original;
-  neighbor->firstneigh_full = firstneigh_full_original;
-  neighbor->numneigh_full = numneigh_full_original;
+  if (vflag == 2) virial_compute();
 }
 
 /* ----------------------------------------------------------------------
@@ -347,11 +96,6 @@ void PairHybrid::allocate()
   allocated = 1;
   int n = atom->ntypes;
 
-  map = memory->create_2d_int_array(n+1,n+1,"pair:map");
-  for (int i = 1; i <= n; i++)
-    for (int j = i; j <= n; j++)
-      map[i][j] = -1;
-
   setflag = memory->create_2d_int_array(n+1,n+1,"pair:setflag");
   for (int i = 1; i <= n; i++)
     for (int j = i; j <= n; j++)
@@ -359,27 +103,11 @@ void PairHybrid::allocate()
 
   cutsq = memory->create_2d_double_array(n+1,n+1,"pair:cutsq");
 
-  nnlist = new int[nstyles];
-  maxneigh = new int[nstyles];
-  nlist = new int*[nstyles];
-  for (int m = 0; m < nstyles; m++) maxneigh[m] = 0;
-  for (int m = 0; m < nstyles; m++) nlist[m] = NULL;
-
-  nnlist_full = new int[nstyles];
-  maxneigh_full = new int[nstyles];
-  nlist_full = new int*[nstyles];
-  for (int m = 0; m < nstyles; m++) maxneigh_full[m] = 0;
-  for (int m = 0; m < nstyles; m++) nlist_full[m] = NULL;
-
-  maxlocal = 0;
-  firstneigh = new int**[nstyles];
-  numneigh = new int*[nstyles];
-  for (int m = 0; m < nstyles; m++) firstneigh[m] = NULL;
-  for (int m = 0; m < nstyles; m++) numneigh[m] = NULL;
-  firstneigh_full = new int**[nstyles];
-  numneigh_full = new int*[nstyles];
-  for (int m = 0; m < nstyles; m++) firstneigh_full[m] = NULL;
-  for (int m = 0; m < nstyles; m++) numneigh_full[m] = NULL;
+  nmap = memory->create_2d_int_array(n+1,n+1,"pair:nmap");
+  map = memory->create_3d_int_array(n+1,n+1,nstyles,"pair:map");
+  for (int i = 1; i <= n; i++)
+    for (int j = i; j <= n; j++)
+      nmap[i][j] = 0;
 }
 
 /* ----------------------------------------------------------------------
@@ -403,15 +131,17 @@ void PairHybrid::settings(int narg, char **arg)
 
   if (allocated) {
     memory->destroy_2d_int_array(setflag);
-    memory->destroy_2d_int_array(map);
     memory->destroy_2d_double_array(cutsq);
+    memory->destroy_2d_int_array(nmap);
+    memory->destroy_3d_int_array(map);
   }
   allocated = 0;
 
   // count sub-styles by skipping numeric args
   // one exception is 1st arg of style "table", which is non-numeric word
 
-  nstyles = i = 0;
+  nstyles = 0;
+  i = 0;
   while (i < narg) {
     if (strcmp(arg[i],"table") == 0) i++;
     i++;
@@ -425,16 +155,19 @@ void PairHybrid::settings(int narg, char **arg)
   keywords = new char*[nstyles];
 
   // allocate each sub-style and call its settings() with subset of args
-  // define subset of sub-styles by skipping numeric args
+  // define subset of args for a sub-style by skipping numeric args
   // one exception is 1st arg of style "table", which is non-numeric word
 
-  nstyles = i = 0;
+  nstyles = 0;
+  i = 0;
   while (i < narg) {
     for (m = 0; m < nstyles; m++)
       if (strcmp(arg[i],keywords[m]) == 0) 
 	error->all("Pair style hybrid cannot use same pair style twice");
     if (strcmp(arg[i],"hybrid") == 0) 
       error->all("Pair style hybrid cannot have hybrid as an argument");
+    if (strcmp(arg[i],"none") == 0) 
+      error->all("Pair style hybrid cannot have none as an argument");
     styles[nstyles] = force->new_pair(arg[i]);
     keywords[nstyles] = new char[strlen(arg[i])+1];
     strcpy(keywords[nstyles],arg[i]);
@@ -442,7 +175,7 @@ void PairHybrid::settings(int narg, char **arg)
     if (strcmp(arg[i],"table") == 0) i++;
     i++;
     while (i < narg && !isalpha(arg[i][0])) i++;
-    if (styles[nstyles]) styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]);
+    styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]);
     nstyles++;
   }
 
@@ -453,14 +186,6 @@ void PairHybrid::settings(int narg, char **arg)
     if (styles[m]) comm_reverse = MAX(comm_reverse,styles[m]->comm_reverse);
   }
 
-  // neigh_every = 1 if any sub-style = 1
-
-  neigh_half_every = neigh_full_every = 0;
-  for (m = 0; m < nstyles; m++) {
-    if (styles[m] && styles[m]->neigh_half_every) neigh_half_every = 1;
-    if (styles[m] && styles[m]->neigh_full_every) neigh_full_every = 1;
-  }
-
   // single_enable = 0 if any sub-style = 0
 
   for (m = 0; m < nstyles; m++)
@@ -480,12 +205,18 @@ void PairHybrid::coeff(int narg, char **arg)
   force->bounds(arg[0],atom->ntypes,ilo,ihi);
   force->bounds(arg[1],atom->ntypes,jlo,jhi);
 
-  // 3rd arg = pair style name
+  // 3rd arg = pair sub-style name
+  // allow for "none" as valid sub-style name
 
   int m;
   for (m = 0; m < nstyles; m++)
     if (strcmp(arg[2],keywords[m]) == 0) break;
-  if (m == nstyles) error->all("Pair coeff for hybrid has invalid style");
+
+  int none = 0;
+  if (m == nstyles) {
+    if (strcmp(arg[2],"none") == 0) none = 1;
+    else error->all("Pair coeff for hybrid has invalid style");
+  }
 
   // move 1st/2nd args to 2nd/3rd args
 
@@ -494,29 +225,36 @@ void PairHybrid::coeff(int narg, char **arg)
 
   // invoke sub-style coeff() starting with 1st arg
 
-  if (styles[m]) styles[m]->coeff(narg-1,&arg[1]);
+  if (!none) styles[m]->coeff(narg-1,&arg[1]);
 
-  // if pair style only allows one pair coeff call (with * * and type mapping)
-  // then unset any old setflag/map assigned to that style first
+  // if sub-style only allows one pair coeff call (with * * and type mapping)
+  // then unset setflag/map assigned to that style before setting it below
   // in case pair coeff for this sub-style is being called for 2nd time
 
-  if (styles[m] && styles[m]->one_coeff)
+  if (!none && styles[m]->one_coeff)
     for (int i = 1; i <= atom->ntypes; i++)
       for (int j = i; j <= atom->ntypes; j++)
-	if (map[i][j] == m) {
-	  map[i][j] = -1;
+	if (nmap[i][j] && map[i][j][0] == m) {
 	  setflag[i][j] = 0;
+	  nmap[i][j] = 0;
 	}
 
-  // set hybrid map & setflag only if substyle set its setflag
-  // if sub-style is NULL for "none", still set setflag
+  // set setflag and which type pairs map to which sub-style
+  // if sub-style is none: set hybrid subflag, wipe out map
+  // else: set hybrid setflag & map only if substyle setflag is set
+  //   previous mappings are wiped out
 
   int count = 0;
   for (int i = ilo; i <= ihi; i++) {
     for (int j = MAX(jlo,i); j <= jhi; j++) {
-      if (styles[m] == NULL || styles[m]->setflag[i][j]) {
-	map[i][j] = m;
+      if (none) {
 	setflag[i][j] = 1;
+	nmap[i][j] = 0;
+	count++;
+      } else if (styles[m]->setflag[i][j]) {
+	setflag[i][j] = 1;
+	nmap[i][j] = 1;
+	map[i][j][0] = m;
 	count++;
       }
     }
@@ -526,54 +264,169 @@ void PairHybrid::coeff(int narg, char **arg)
 }
 
 /* ----------------------------------------------------------------------
-   init for one type pair i,j and corresponding j,i
+   init specific to this pair style
 ------------------------------------------------------------------------- */
 
-double PairHybrid::init_one(int i, int j)
+void PairHybrid::init_style()
 {
-  // if i,j is set explicity, call its sub-style
-  // if i,j is not set and i,i sub-style = j,j sub-style
-  // then set map[i][j] to this sub-style and call sub-style for init/mixing
-  // else i,j has not been set by user
-  // check for special case = style none
-
-  double cut = 0.0;
-  if (setflag[i][j]) {
-    if (styles[map[i][j]]) {
-      cut = styles[map[i][j]]->init_one(i,j);
-      styles[map[i][j]]->cutsq[i][j] = 
-	styles[map[i][j]]->cutsq[j][i] = cut*cut;
-      if (tail_flag) {
-	etail_ij = styles[map[i][j]]->etail_ij;
-	ptail_ij = styles[map[i][j]]->ptail_ij;
+  int i,m,itype,jtype,used,istyle,skip;
+
+  // error if a sub-style is not used
+
+  int ntypes = atom->ntypes;
+
+  for (istyle = 0; istyle < nstyles; istyle++) {
+    used = 0;
+    for (itype = 1; itype <= ntypes; itype++)
+      for (jtype = itype; jtype <= ntypes; jtype++)
+	for (m = 0; m < nmap[itype][jtype]; m++)
+	  if (map[itype][jtype][m] == istyle) used = 1;
+    if (used == 0) error->all("Pair hybrid sub-style is not used");
+  }
+
+  // each sub-style makes its neighbor list request(s)
+
+  for (istyle = 0; istyle < nstyles; istyle++) styles[istyle]->init_style();
+
+  // create skip lists for each neigh request
+
+  for (i = 0; i < neighbor->nrequest; i++) {
+
+    // only relevant for half, full, gran, respaouter lists
+
+    if (neighbor->requests[i]->granhistory) continue;
+    if (neighbor->requests[i]->respamiddle) continue;
+    if (neighbor->requests[i]->respainner) continue;
+    if (neighbor->requests[i]->half_from_full) continue;
+
+    // find associated sub-style
+
+    for (istyle = 0; istyle < nstyles; istyle++)
+      if (styles[istyle] == neighbor->requests[i]->requestor) break;
+
+    // allocate iskip and ijskip
+    // initialize so as to skip all pair types
+    // set ijskip = 0 if type pair matches any entry in sub-style map
+    // set ijskip = 0 if mixing will assign type pair to this sub-style
+    //   will occur if both I,I and J,J are assigned to single sub-style
+    //   and sub-style for both I,I and J,J match istyle
+    // set iskip = 1 only if all ijskip for itype are 1
+
+    int *iskip = new int[ntypes+1];
+    int **ijskip = memory->create_2d_int_array(ntypes+1,ntypes+1,
+					       "pair_hybrid:ijskip");
+
+    for (itype = 1; itype <= ntypes; itype++)
+      for (jtype = 1; jtype <= ntypes; jtype++)
+	ijskip[itype][jtype] = 1;
+
+    for (itype = 1; itype <= ntypes; itype++)
+      for (jtype = itype; jtype <= ntypes; jtype++) {
+	for (m = 0; m < nmap[itype][jtype]; m++)
+	  if (map[itype][jtype][m] == istyle) 
+	    ijskip[itype][jtype] = ijskip[jtype][itype] = 0;
+	if (nmap[itype][itype] == 1 && map[itype][itype][0] == istyle &&
+	    nmap[jtype][jtype] == 1 && map[jtype][jtype][0] == istyle)
+	  ijskip[itype][jtype] = ijskip[jtype][itype] = 0;
       }
+
+    for (itype = 1; itype <= ntypes; itype++) {
+      iskip[itype] = 1;
+      for (jtype = 1; jtype <= ntypes; jtype++)
+	if (ijskip[itype][jtype] == 0) iskip[itype] = 0;
     }
-  } else if (map[i][i] == map[j][j]) {
-    map[i][j] = map[i][i];
-    if (styles[map[i][j]]) {
-      cut = styles[map[i][j]]->init_one(i,j);
-      styles[map[i][j]]->cutsq[i][j] = 
-	styles[map[i][j]]->cutsq[j][i] = cut*cut;
-      if (tail_flag) {
-	etail_ij = styles[map[i][j]]->etail_ij;
-	ptail_ij = styles[map[i][j]]->ptail_ij;
-      }
+
+    // if any skipping occurs
+    // set request->skip and copy iskip and ijskip into request
+    // else delete iskip and ijskip
+
+    skip = 0;
+    for (itype = 1; itype <= ntypes; itype++)
+      for (jtype = 1; jtype <= ntypes; jtype++)
+	if (ijskip[itype][jtype] == 1) skip = 1;
+
+    if (skip) {
+      neighbor->requests[i]->skip = 1;
+      neighbor->requests[i]->iskip = iskip;
+      neighbor->requests[i]->ijskip = ijskip;
+    } else {
+      delete [] iskip;
+      memory->destroy_2d_int_array(ijskip);
     }
-  } else error->all("All pair coeffs are not set");
+  }
 
-  map[j][i] = map[i][j];
+  // combine sub-style neigh list requests and create new ones if needed
 
-  return cut;
+  modify_requests();
 }
 
 /* ----------------------------------------------------------------------
-   init specific to this pair style
+   init for one type pair i,j and corresponding j,i
 ------------------------------------------------------------------------- */
 
-void PairHybrid::init_style()
+double PairHybrid::init_one(int i, int j)
 {
-  for (int m = 0; m < nstyles; m++)
-    if (styles[m]) styles[m]->init_style();
+  // if I,J is not set explicitly:
+  // perform mixing only if I,I sub-style = J,J sub-style
+  // also require I,I and J,J both are assigned to single sub-style
+
+  if (setflag[i][j] == 0) {
+    if (nmap[i][i] != 1 || nmap[j][j] != 1 || map[i][i][0] != map[j][j][0])
+      error->one("All pair coeffs are not set");
+    nmap[i][j] = 1;
+    map[i][j][0] = map[i][i][0];
+  }
+
+  // call init/mixing for all sub-styles of I,J
+  // set cutsq in sub-style just as pair::init_one() does
+  // sum tail corrections for I,J
+  // compute max cutoff
+  // if sub-style = none, cutmax of 0.0 will be returned
+
+  double cutmax = 0.0;
+  if (tail_flag) etail_ij = ptail_ij = 0.0;
+
+  for (int k = 0; k < nmap[i][j]; k++) {
+    map[j][i][k] = map[i][j][k];
+    double cut = styles[map[i][j][k]]->init_one(i,j);
+    styles[map[i][j][k]]->cutsq[i][j] = 
+      styles[map[i][j][k]]->cutsq[j][i] = cut*cut;
+    if (tail_flag) {
+      etail_ij += styles[map[i][j][k]]->etail_ij;
+      ptail_ij += styles[map[i][j][k]]->ptail_ij;
+    }
+    cutmax = MAX(cutmax,cut);
+  }
+
+  return cutmax;
+}
+
+/* ----------------------------------------------------------------------
+   combine sub-style neigh list requests and create new ones if needed
+------------------------------------------------------------------------- */
+
+void PairHybrid::modify_requests()
+{
+  int i,j;
+
+  // if list is skip list, look for non-skip list of same kind
+  // if one exists, point at that one
+  // else make new non-skip request of same kind and point at that one
+
+  for (i = 0; i < neighbor->nrequest; i++) {
+    if (neighbor->requests[i]->skip == 0) continue;
+
+    for (j = 0; j < neighbor->nrequest; j++)
+      if (neighbor->requests[i]->same_kind(neighbor->requests[j]) &&
+	  neighbor->requests[j]->skip == 0) break;
+
+    if (j < neighbor->nrequest) neighbor->requests[i]->otherlist = j;
+    else {
+      int irequest = neighbor->request(this);
+      neighbor->requests[irequest]->copy_kind(neighbor->requests[i]);
+      neighbor->requests[i]->otherlist = irequest;
+    }
+  }
 }
 
 /* ----------------------------------------------------------------------
@@ -584,14 +437,14 @@ void PairHybrid::write_restart(FILE *fp)
 {
   fwrite(&nstyles,sizeof(int),1,fp);
 
-  // each sub-style writes its settings
+  // each sub-style writes its settings, but no coeff info
 
   int n;
   for (int m = 0; m < nstyles; m++) {
     n = strlen(keywords[m]) + 1;
     fwrite(&n,sizeof(int),1,fp);
     fwrite(keywords[m],sizeof(char),n,fp);
-    if (styles[m]) styles[m]->write_restart_settings(fp);
+    styles[m]->write_restart_settings(fp);
   }
 }
 
@@ -601,8 +454,6 @@ void PairHybrid::write_restart(FILE *fp)
 
 void PairHybrid::read_restart(FILE *fp)
 {
-  allocate();
-
   int me = comm->me;
   if (me == 0) fread(&nstyles,sizeof(int),1,fp);
   MPI_Bcast(&nstyles,1,MPI_INT,0,world);
@@ -610,7 +461,8 @@ void PairHybrid::read_restart(FILE *fp)
   styles = new Pair*[nstyles];
   keywords = new char*[nstyles];
   
-  // each sub-style is created via new_pair() and reads its settings
+  // each sub-style is created via new_pair()
+  // each reads its settings, but no coeff info
 
   int n;
   for (int m = 0; m < nstyles; m++) {
@@ -620,31 +472,56 @@ void PairHybrid::read_restart(FILE *fp)
     if (me == 0) fread(keywords[m],sizeof(char),n,fp);
     MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
     styles[m] = force->new_pair(keywords[m]);
-    if (styles[m]) styles[m]->read_restart_settings(fp);
+    styles[m]->read_restart_settings(fp);
   }
 }
 
-/* ---------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------
+   call sub-style to compute single interaction
+   since overlay could have multiple sub-styles, sum results explicitly
+------------------------------------------------------------------------- */
 
 void PairHybrid::single(int i, int j, int itype, int jtype,
 			double rsq, double factor_coul, double factor_lj,
 			int eflag, One &one)
 {
-  if (map[itype][jtype] == -1)
+  if (nmap[itype][jtype] == 0)
     error->one("Invoked pair single on pair style none");
 
-  styles[map[itype][jtype]]->
-    single(i,j,itype,jtype,rsq,factor_coul,factor_lj,eflag,one);
+  double fforce = 0.0;
+  double eng_vdwl = 0.0;
+  double eng_coul = 0.0;
+
+  for (int m = 0; m < nmap[itype][jtype]; m++) {
+    styles[map[itype][jtype][m]]->
+      single(i,j,itype,jtype,rsq,factor_coul,factor_lj,eflag,one);
+    fforce += one.fforce;
+    eng_vdwl += one.eng_vdwl;
+    eng_coul += one.eng_coul;
+  }
+
+  one.fforce = fforce;
+  one.eng_vdwl = eng_vdwl;
+  one.eng_coul = eng_coul;
 }
 
-/* ---------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------
+   call sub-style to compute single embedding interaction
+   since overlay could have multiple sub-styles, sum results explicitly
+------------------------------------------------------------------------- */
 
 void PairHybrid::single_embed(int i, int itype, double &phi)
 {
-  if (map[itype][itype] == -1)
+  if (nmap[itype][itype] == 0)
     error->one("Invoked pair single on pair style none");
   
-  styles[map[itype][itype]]->single_embed(i,itype,phi);
+  phi = 0.0;
+  double phi_single;
+
+  for (int m = 0; m < nmap[itype][itype]; m++) {
+    styles[map[itype][itype][m]]->single_embed(i,itype,phi_single);
+    phi += phi_single;
+  }
 }
 
 /* ----------------------------------------------------------------------
@@ -656,20 +533,16 @@ void PairHybrid::single_embed(int i, int itype, double &phi)
 void PairHybrid::modify_params(int narg, char **arg)
 {
   Pair::modify_params(narg,arg);
-  for (int m = 0; m < nstyles; m++)
-    if (styles[m]) styles[m]->modify_params(narg,arg);
+  for (int m = 0; m < nstyles; m++) styles[m]->modify_params(narg,arg);
 }
 
 /* ----------------------------------------------------------------------
-   memory usage of sub-style firstneigh, numneigh, neighbor list
-   add in memory usage of each sub-style itself
+   memory usage of each sub-style
 ------------------------------------------------------------------------- */
 
 int PairHybrid::memory_usage()
 {
-  int bytes = nstyles*maxlocal * (sizeof(int *) + sizeof(int));
-  for (int m = 0; m < nstyles; m++) bytes += maxneigh[m] * sizeof(int);
-  for (int m = 0; m < nstyles; m++)
-    if (styles[m]) bytes += styles[m]->memory_usage();
+  int bytes = 0;
+  for (int m = 0; m < nstyles; m++) bytes += styles[m]->memory_usage();
   return bytes;
 }
diff --git a/src/pair_hybrid.h b/src/pair_hybrid.h
index 2686e007300d1112820d3b5de24fdd9347663d2d..ab828a1d72b651a52428ac229fc791b7b2695d26 100644
--- a/src/pair_hybrid.h
+++ b/src/pair_hybrid.h
@@ -21,17 +21,17 @@ namespace LAMMPS_NS {
 
 class PairHybrid : public Pair {
  public:
-  int nstyles;                  // # of different pair styles
-  Pair **styles;                // class list for each Pair style
-  char **keywords;              // sub-style name for each Pair style
+  int nstyles;                  // # of different sub-styles
+  Pair **styles;                // list of Pair style classes
+  char **keywords;              // style name of each Pair style
 
   PairHybrid(class LAMMPS *);
   ~PairHybrid();
   void compute(int, int);
   void settings(int, char **);
-  void coeff(int, char **);
-  double init_one(int, int);
+  virtual void coeff(int, char **);
   void init_style();
+  double init_one(int, int);
   void write_restart(FILE *);
   void read_restart(FILE *);
   void single(int, int, int, int, double, double, double, int, One &);
@@ -39,24 +39,12 @@ class PairHybrid : public Pair {
   void modify_params(int narg, char **arg);
   int memory_usage();
 
- private:
-  int **map;                    // which style each itype,jtype points to
-
-  int *nnlist;                  // # of half neighs in sub-style neigh lists
-  int *maxneigh;                // max # of neighs sub-style lists can store
-  int **nlist;                  // half neigh list for each sub-style
-
-  int *nnlist_full;             // # of full neighs in sub-style neigh lists
-  int *maxneigh_full;           // max # of neighs sub-style lists can store
-  int **nlist_full;             // full neigh list for each sub-style
-
-  int ***firstneigh;            // each sub-style's per-atom firstneigh
-  int **numneigh;               // each sub-style's per-atom numneigh
-  int ***firstneigh_full;       // each sub-style's per-atom firstneigh_full
-  int **numneigh_full;          // each sub-style's per-atom numneigh_full
-  int maxlocal;                 // max length of each ss's firstneigh,numneigh
+ protected:
+  int **nmap;                   // # of sub-styles itype,jtype points to
+  int ***map;                   // list of sub-styles itype,jtype points to
 
   void allocate();
+  virtual void modify_requests();
 };
 
 }
diff --git a/src/pair_lj_cut.cpp b/src/pair_lj_cut.cpp
index dc342a13b70c9e7d7aaa83d8262cfbab85565ed1..af2743af5c1d7890462748509122b5d91e64f14b 100644
--- a/src/pair_lj_cut.cpp
+++ b/src/pair_lj_cut.cpp
@@ -24,6 +24,8 @@
 #include "comm.h"
 #include "force.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
 #include "update.h"
 #include "integrate.h"
 #include "respa.h"
@@ -65,36 +67,40 @@ PairLJCut::~PairLJCut()
 
 void PairLJCut::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r6inv,forcelj,fforce,factor_lj,philj;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
@@ -149,21 +155,24 @@ void PairLJCut::compute(int eflag, int vflag)
 
 void PairLJCut::compute_inner()
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
-  double rsq,r2inv,r6inv,forcelj,fforce,factor_lj;
-  double rsw;
-  int *neighs;
-  double **f;
+  double rsq,r2inv,r6inv,forcelj,fforce,factor_lj,rsw;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
-  f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
   
+  inum = listinner->inum;
+  ilist = listinner->ilist;
+  numneigh = listinner->numneigh;
+  firstneigh = listinner->firstneigh;
+
   double cut_out_on = cut_respa[0];
   double cut_out_off = cut_respa[1];
   
@@ -173,16 +182,17 @@ void PairLJCut::compute_inner()
   
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh_inner[i];
-    numneigh = neighbor->numneigh_inner[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
       
       if (j < nall) factor_lj = 1.0;
       else {
@@ -223,21 +233,24 @@ void PairLJCut::compute_inner()
 
 void PairLJCut::compute_middle()
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
-  double rsq,r2inv,r6inv,forcelj,fforce,factor_lj;
-  double rsw;
-  int *neighs;
-  double **f;
+  double rsq,r2inv,r6inv,forcelj,fforce,factor_lj,rsw;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
-  f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = listmiddle->inum;
+  ilist = listmiddle->ilist;
+  numneigh = listmiddle->numneigh;
+  firstneigh = listmiddle->firstneigh;
+
   double cut_in_off = cut_respa[0];
   double cut_in_on = cut_respa[1];
   double cut_out_on = cut_respa[2];
@@ -252,16 +265,17 @@ void PairLJCut::compute_middle()
 
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh_middle[i];
-    numneigh = neighbor->numneigh_middle[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
@@ -306,24 +320,27 @@ void PairLJCut::compute_middle()
 
 void PairLJCut::compute_outer(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
-  double rsq,r2inv,r6inv,forcelj,fforce,factor_lj,philj;
-  double rsw;
-  int *neighs;
-  double **f;
+  double rsq,r2inv,r6inv,forcelj,fforce,factor_lj,philj,rsw;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = listouter->inum;
+  ilist = listouter->ilist;
+  numneigh = listouter->numneigh;
+  firstneigh = listouter->firstneigh;
+
   double cut_in_off = cut_respa[2];
   double cut_in_on = cut_respa[3];
 
@@ -333,16 +350,17 @@ void PairLJCut::compute_outer(int eflag, int vflag)
 
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
@@ -487,6 +505,62 @@ void PairLJCut::coeff(int narg, char **arg)
   if (count == 0) error->all("Incorrect args for pair coefficients");
 }
 
+/* ----------------------------------------------------------------------
+   init specific to this pair style
+------------------------------------------------------------------------- */
+
+void PairLJCut::init_style()
+{
+  // request regular or rRESPA neighbor lists
+
+  int irequest;
+
+  if (update->whichflag == 0 && strcmp(update->integrate_style,"respa") == 0) {
+    int respa = 0;
+    if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
+    if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
+
+    if (respa == 0) irequest = neighbor->request(this);
+    else if (respa == 1) {
+      irequest = neighbor->request(this);
+      neighbor->requests[irequest]->id = 1;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respainner = 1;
+      irequest = neighbor->request(this);
+      neighbor->requests[irequest]->id = 3;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respaouter = 1;
+    } else {
+      irequest = neighbor->request(this);
+      neighbor->requests[irequest]->id = 1;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respainner = 1;
+      irequest = neighbor->request(this);
+      neighbor->requests[irequest]->id = 2;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respamiddle = 1;
+      irequest = neighbor->request(this);
+      neighbor->requests[irequest]->id = 3;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respaouter = 1;
+    }
+
+  } else irequest = neighbor->request(this);
+}
+
+/* ----------------------------------------------------------------------
+   neighbor callback to inform pair style of neighbor list to use
+   regular or rRESPA
+------------------------------------------------------------------------- */
+
+void PairLJCut::init_list(int id, NeighList *ptr)
+{
+  if (id == 0) list = ptr;
+  else if (id == 1) listinner = ptr;
+  else if (id == 2) listmiddle = ptr;
+  else if (id == 3) listouter = ptr;
+}
+
 /* ----------------------------------------------------------------------
    init for one type pair i,j and corresponding j,i
 ------------------------------------------------------------------------- */
diff --git a/src/pair_lj_cut.h b/src/pair_lj_cut.h
index e89a4d0bddd6951362c89a69c29c101fa3071cf7..a91dec05ab956e0383f4ddae39a8c521a66774e2 100644
--- a/src/pair_lj_cut.h
+++ b/src/pair_lj_cut.h
@@ -25,6 +25,8 @@ class PairLJCut : public Pair {
   void compute(int, int);
   void settings(int, char **);
   void coeff(int, char **);
+  void init_style();
+  void init_list(int, class NeighList *);
   double init_one(int, int);
   void write_restart(FILE *);
   void read_restart(FILE *);
diff --git a/src/pair_lj_cut_coul_cut.cpp b/src/pair_lj_cut_coul_cut.cpp
index 9993f0edd7754cb9f0be99476bedef4147cbdf51..5c0d08a4dba0de28549c86c73046bb3402ad2ca4 100644
--- a/src/pair_lj_cut_coul_cut.cpp
+++ b/src/pair_lj_cut_coul_cut.cpp
@@ -19,9 +19,9 @@
 #include "atom.h"
 #include "comm.h"
 #include "force.h"
-#include "update.h"
-#include "memory.h"
 #include "neighbor.h"
+#include "neigh_list.h"
+#include "memory.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
@@ -59,19 +59,17 @@ PairLJCutCoulCut::~PairLJCutCoulCut()
 
 void PairLJCutCoulCut::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r6inv,forcecoul,forcelj,fforce,factor_coul,factor_lj;
   double factor,phicoul,philj;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = eng_coul = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   double *q = atom->q;
   int *type = atom->type;
   int nlocal = atom->nlocal;
@@ -81,19 +79,25 @@ void PairLJCutCoulCut::compute(int eflag, int vflag)
   int newton_pair = force->newton_pair;
   double qqrd2e = force->qqrd2e;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     qtmp = q[i];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_coul = factor_lj = 1.0;
       else {
@@ -250,6 +254,18 @@ void PairLJCutCoulCut::coeff(int narg, char **arg)
   if (count == 0) error->all("Incorrect args for pair coefficients");
 }
 
+/* ----------------------------------------------------------------------
+   init specific to this pair style
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulCut::init_style()
+{
+  if (!atom->q_flag)
+    error->all("Pair style lj/cut/coul/cut requires atom attribute q");
+
+  int irequest = neighbor->request(this);
+}
+
 /* ----------------------------------------------------------------------
    init for one type pair i,j and corresponding j,i
 ------------------------------------------------------------------------- */
@@ -316,16 +332,6 @@ double PairLJCutCoulCut::init_one(int i, int j)
   return cut;
 }
 
-/* ----------------------------------------------------------------------
-   init specific to this pair style
-------------------------------------------------------------------------- */
-
-void PairLJCutCoulCut::init_style()
-{
-  if (!atom->q_flag)
-    error->all("Pair style lj/cut/coul/cut requires atom attribute q");
-}
-
 /* ----------------------------------------------------------------------
   proc 0 writes to restart file
 ------------------------------------------------------------------------- */
diff --git a/src/pair_lj_cut_coul_cut.h b/src/pair_lj_cut_coul_cut.h
index 8e027e5ac9ac04091c176a3f25f8a9b0bb12080e..8af68331cbdc927aa738a47ba749bbb5d1458097 100644
--- a/src/pair_lj_cut_coul_cut.h
+++ b/src/pair_lj_cut_coul_cut.h
@@ -25,8 +25,8 @@ class PairLJCutCoulCut : public Pair {
   virtual void compute(int, int);
   virtual void settings(int, char **);
   void coeff(int, char **);
-  double init_one(int, int);
   void init_style();
+  double init_one(int, int);
   virtual void write_restart(FILE *);
   virtual void read_restart(FILE *);
   virtual void write_restart_settings(FILE *);
diff --git a/src/pair_lj_cut_coul_debye.cpp b/src/pair_lj_cut_coul_debye.cpp
index 4331a11e612c9e94625eb60445a523b9c712c35c..f4c28e6dba23dff225c06feb7b01a5331d038eb1 100644
--- a/src/pair_lj_cut_coul_debye.cpp
+++ b/src/pair_lj_cut_coul_debye.cpp
@@ -15,10 +15,9 @@
 #include "stdlib.h"
 #include "pair_lj_cut_coul_debye.h"
 #include "atom.h"
-#include "neighbor.h"
+#include "neigh_list.h"
 #include "force.h"
 #include "comm.h"
-#include "update.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
@@ -31,20 +30,18 @@ PairLJCutCoulDebye::PairLJCutCoulDebye(LAMMPS *lmp) : PairLJCutCoulCut(lmp) {}
 
 void PairLJCutCoulDebye::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r6inv,forcecoul,forcelj,fforce,factor_coul,factor_lj;
   double factor,phicoul,philj;
   double r,rinv,screening;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = eng_coul = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   double *q = atom->q;
   int *type = atom->type;
   int nlocal = atom->nlocal;
@@ -54,19 +51,25 @@ void PairLJCutCoulDebye::compute(int eflag, int vflag)
   int newton_pair = force->newton_pair;
   double qqrd2e = force->qqrd2e;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     qtmp = q[i];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_coul = factor_lj = 1.0;
       else {
diff --git a/src/pair_lj_expand.cpp b/src/pair_lj_expand.cpp
index 3050307ead8ecb9629c054b9dd698bb826b6b63d..f43d8d62bfcd9ef99084e8c78289944c933ec257 100644
--- a/src/pair_lj_expand.cpp
+++ b/src/pair_lj_expand.cpp
@@ -18,9 +18,8 @@
 #include "atom.h"
 #include "comm.h"
 #include "force.h"
-#include "update.h"
+#include "neigh_list.h"
 #include "memory.h"
-#include "neighbor.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
@@ -56,37 +55,41 @@ PairLJExpand::~PairLJExpand()
 
 void PairLJExpand::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r6inv,forcelj,fforce,factor_lj,philj;
   double r,rshift,rshiftsq;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
diff --git a/src/pair_lj_smooth.cpp b/src/pair_lj_smooth.cpp
index 0ee2c06649f6bb881d36f5722a6300a576d1a07e..5a70395d24a0948e64c244c9024b9a04af42e277 100644
--- a/src/pair_lj_smooth.cpp
+++ b/src/pair_lj_smooth.cpp
@@ -22,8 +22,7 @@
 #include "atom.h"
 #include "comm.h"
 #include "force.h"
-#include "neighbor.h"
-#include "update.h"
+#include "neigh_list.h"
 #include "memory.h"
 #include "error.h"
 
@@ -66,38 +65,42 @@ PairLJSmooth::~PairLJSmooth()
 
 void PairLJSmooth::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r6inv,r,forcelj,fforce,factor_lj,philj;
   double t,tsq,fskin;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
   
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
   
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
   
-  // loop over neighbors of my atoms
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
   
-  for (i = 0; i < nlocal; i++) {
+  // loop over neighbors of my atoms
+
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
-    
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
-      
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
+
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
+
       if (j < nall) factor_lj = 1.0;
       else {
 	factor_lj = special_lj[j/nall];
diff --git a/src/pair_morse.cpp b/src/pair_morse.cpp
index f09d29c509554e886af2f9134752c774fc191c14..66cc36ec0175b1d76f7675af465ea43ebbaf9f63 100644
--- a/src/pair_morse.cpp
+++ b/src/pair_morse.cpp
@@ -18,9 +18,8 @@
 #include "atom.h"
 #include "comm.h"
 #include "force.h"
-#include "update.h"
+#include "neigh_list.h"
 #include "memory.h"
-#include "neighbor.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
@@ -53,36 +52,40 @@ PairMorse::~PairMorse()
 
 void PairMorse::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r,dr,dexp,fforce,factor_lj,phi;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
diff --git a/src/pair_soft.cpp b/src/pair_soft.cpp
index 744c77795299dcdff3e95953791127c436f24b83..afd46c6dfdfaa09d17e4320f72a8759dca0095f6 100644
--- a/src/pair_soft.cpp
+++ b/src/pair_soft.cpp
@@ -19,8 +19,8 @@
 #include "comm.h"
 #include "force.h"
 #include "update.h"
+#include "neigh_list.h"
 #include "memory.h"
-#include "neighbor.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
@@ -54,11 +54,10 @@ PairSoft::~PairSoft()
 
 void PairSoft::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
   double r,rsq,arg,fforce,factor_lj,philj;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   // set current prefactor
   // for minimization, set to prestop
@@ -78,27 +77,32 @@ void PairSoft::compute(int eflag, int vflag)
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
diff --git a/src/pair_table.cpp b/src/pair_table.cpp
index 7972d42db53e4d7fb3584309533e864b9565bfa2..f59a20d1ea5b09afb87d31a370045997dd5c1bf0 100644
--- a/src/pair_table.cpp
+++ b/src/pair_table.cpp
@@ -22,9 +22,8 @@
 #include "pair_table.h"
 #include "atom.h"
 #include "force.h"
-#include "update.h"
 #include "comm.h"
-#include "neighbor.h"
+#include "neigh_list.h"
 #include "memory.h"
 #include "error.h"
 
@@ -70,11 +69,10 @@ PairTable::~PairTable()
 
 void PairTable::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype,itable;
+  int i,j,ii,jj,inum,jnum,itype,jtype,itable;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
   double fforce,factor_lj,phi,fraction,value,a,b;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
   Table *tb;
   float rsq_single;
   int *int_rsq = (int *) &rsq_single;
@@ -82,27 +80,32 @@ void PairTable::compute(int eflag, int vflag)
   eng_vdwl = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_lj = force->special_lj;
   int newton_pair = force->newton_pair;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_lj = 1.0;
       else {
diff --git a/src/pair_yukawa.cpp b/src/pair_yukawa.cpp
index b6db7c04e297e1b2b4e4910ac9dddfdbfd7bcc04..f709917477362a9b60af6f8dd7f5da358847b4f4 100644
--- a/src/pair_yukawa.cpp
+++ b/src/pair_yukawa.cpp
@@ -15,10 +15,9 @@
 #include "stdlib.h"
 #include "pair_yukawa.h"
 #include "atom.h"
-#include "neighbor.h"
 #include "force.h"
 #include "comm.h"
-#include "update.h"
+#include "neigh_list.h"
 #include "memory.h"
 #include "error.h"
 
@@ -50,36 +49,40 @@ PairYukawa::~PairYukawa()
 
 void PairYukawa::compute(int eflag, int vflag)
 {
-  int i,j,k,numneigh,itype,jtype;
+  int i,j,ii,jj,inum,jnum,itype,jtype;
   double xtmp,ytmp,ztmp,delx,dely,delz;
   double rsq,r2inv,r,rinv,screening,forceyukawa,fforce,factor_coul,phi;
-  int *neighs;
-  double **f;
+  int *ilist,*jlist,*numneigh,**firstneigh;
 
   eng_coul = 0.0;
   if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
 
-  if (vflag == 2) f = update->f_pair;
-  else f = atom->f;
   double **x = atom->x;
+  double **f = atom->f;
   int *type = atom->type;
   int nlocal = atom->nlocal;
   int nall = atom->nlocal + atom->nghost;
   double *special_coul = force->special_coul;
   int newton_pair = force->newton_pair;
 
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+  
   // loop over neighbors of my atoms
 
-  for (i = 0; i < nlocal; i++) {
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     itype = type[i];
-    neighs = neighbor->firstneigh[i];
-    numneigh = neighbor->numneigh[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
 
-    for (k = 0; k < numneigh; k++) {
-      j = neighs[k];
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
 
       if (j < nall) factor_coul = 1.0;
       else {
diff --git a/src/respa.cpp b/src/respa.cpp
index 39a66cb9411440e7aac03ad9795a8c5fc37036e5..3ba4a4f6defe691fdc3f1551eb1fc732442454c7 100644
--- a/src/respa.cpp
+++ b/src/respa.cpp
@@ -255,9 +255,9 @@ void Respa::init()
   // will delete it at end of run
 
   char **fixarg = new char*[4];
-  fixarg[0] = "RESPA";
-  fixarg[1] = "all";
-  fixarg[2] = "RESPA";
+  fixarg[0] = (char *) "RESPA";
+  fixarg[1] = (char *) "all";
+  fixarg[2] = (char *) "RESPA";
   fixarg[3] = new char[8];
   sprintf(fixarg[3],"%d",nlevels);
   modify->add_fix(4,fixarg);
diff --git a/src/style.h b/src/style.h
index 43f44000ca9f9bfd003f7008e76740b7e2b28185..9cdf05bac74416600a08332dd3409f4365578a64 100644
--- a/src/style.h
+++ b/src/style.h
@@ -76,16 +76,17 @@ CommandStyle(write_restart,WriteRestart)
 #endif
 
 #ifdef ComputeInclude
+#include "compute_attribute_atom.h"
 #include "compute_centro_atom.h"
 #include "compute_coord_atom.h"
 #include "compute_ebond_atom.h"
 #include "compute_epair_atom.h"
-#include "compute_etotal_atom.h"
 #include "compute_ke_atom.h"
 #include "compute_pressure.h"
 #include "compute_rotate_dipole.h"
 #include "compute_rotate_gran.h"
 #include "compute_stress_atom.h"
+#include "compute_sum_atom.h"
 #include "compute_temp.h"
 #include "compute_temp_deform.h"
 #include "compute_temp_partial.h"
@@ -96,16 +97,17 @@ CommandStyle(write_restart,WriteRestart)
 #endif
 
 #ifdef ComputeClass
+ComputeStyle(attribute/atom,ComputeAttributeAtom)
 ComputeStyle(centro/atom,ComputeCentroAtom)
 ComputeStyle(coord/atom,ComputeCoordAtom)
 ComputeStyle(ebond/atom,ComputeEbondAtom)
 ComputeStyle(epair/atom,ComputeEpairAtom)
-ComputeStyle(etotal/atom,ComputeEtotalAtom)
 ComputeStyle(ke/atom,ComputeKEAtom)
 ComputeStyle(pressure,ComputePressure)
 ComputeStyle(rotate/dipole,ComputeRotateDipole)
 ComputeStyle(rotate/gran,ComputeRotateGran)
 ComputeStyle(stress/atom,ComputeStressAtom)
+ComputeStyle(sum/atom,ComputeSumAtom)
 ComputeStyle(temp,ComputeTemp)
 ComputeStyle(temp/deform,ComputeTempDeform)
 ComputeStyle(temp/partial,ComputeTempPartial)
@@ -137,6 +139,7 @@ DumpStyle(xyz,DumpXYZ)
 
 #ifdef FixInclude
 #include "fix_add_force.h"
+#include "fix_ave_atom.h"
 #include "fix_ave_force.h"
 #include "fix_ave_spatial.h"
 #include "fix_ave_time.h"
@@ -186,6 +189,7 @@ DumpStyle(xyz,DumpXYZ)
 
 #ifdef FixClass
 FixStyle(addforce,FixAddForce)
+FixStyle(ave/atom,FixAveAtom)
 FixStyle(aveforce,FixAveForce)
 FixStyle(ave/spatial,FixAveSpatial)
 FixStyle(ave/time,FixAveTime)
@@ -270,7 +274,9 @@ MinimizeStyle(sd,MinSD)
 #ifdef PairInclude
 #include "pair_buck.h"
 #include "pair_buck_coul_cut.h"
+#include "pair_coul_cut.h"
 #include "pair_hybrid.h"
+#include "pair_hybrid_overlay.h"
 #include "pair_lj_cut.h"
 #include "pair_lj_cut_coul_cut.h"
 #include "pair_lj_cut_coul_debye.h"
@@ -285,7 +291,9 @@ MinimizeStyle(sd,MinSD)
 #ifdef PairClass
 PairStyle(buck,PairBuck)
 PairStyle(buck/coul/cut,PairBuckCoulCut)
+PairStyle(coul/cut,PairCoulCut)
 PairStyle(hybrid,PairHybrid)
+PairStyle(hybrid/overlay,PairHybridOverlay)
 PairStyle(lj/cut,PairLJCut)
 PairStyle(lj/cut/coul/cut,PairLJCutCoulCut)
 PairStyle(lj/cut/coul/debye,PairLJCutCoulDebye)
@@ -315,7 +323,7 @@ RegionStyle(sphere,RegSphere)
 RegionStyle(union,RegUnion)
 #endif
 
-// style files for optional packages
+// style files for standard packages
 
 #include "style_asphere.h"
 #include "style_class2.h"
@@ -331,8 +339,7 @@ RegionStyle(union,RegUnion)
 #include "style_poems.h"
 #include "style_xtc.h"
 
-//#include "style_extra.h"
-
-// user add-ons
+// user add-ons: individual classes and packages
 
 #include "style_user.h"
+#include "style_user_packages.h"
diff --git a/src/style_kspace.h b/src/style_kspace.h
index 52cae87bdb42ae3534b1c694b7fb9bbf1feb0d5c..8c7244afb9d3684fbbe0e51a1e6dd3cfe7f55bdb 100644
--- a/src/style_kspace.h
+++ b/src/style_kspace.h
@@ -25,6 +25,7 @@ KSpaceStyle(pppm/tip4p,PPPMTIP4P)
 
 #ifdef PairInclude
 #include "pair_buck_coul_long.h"
+#include "pair_coul_long.h"
 #include "pair_lj_cut_coul_long.h"
 #include "pair_lj_cut_coul_long_tip4p.h"
 #include "pair_lj_charmm_coul_long.h"
@@ -32,6 +33,7 @@ KSpaceStyle(pppm/tip4p,PPPMTIP4P)
 
 #ifdef PairClass
 PairStyle(buck/coul/long,PairBuckCoulLong)
+PairStyle(coul/long,PairCoulLong)
 PairStyle(lj/cut/coul/long,PairLJCutCoulLong)
 PairStyle(lj/cut/coul/long/tip4p,PairLJCutCoulLongTIP4P)
 PairStyle(lj/charmm/coul/long,PairLJCharmmCoulLong)
diff --git a/src/style_user.h b/src/style_user.h
index b4eeb828b4e385b477ed32b588cfd3e34f2742cf..cb024f6ee921119148ee9e731f4e2556b58a8912 100644
--- a/src/style_user.h
+++ b/src/style_user.h
@@ -11,6 +11,7 @@
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
+// add a style class to LAMMPS by adding 2 lines to this file
 // add new include files in appropriate Include ifdef
 // add new style keywords and class names in appropriate Class ifdef
 // see style.h for examples
@@ -73,7 +74,7 @@
 #endif
 
 #ifdef IntegrateClass
-#endif
+# endif
 
 #ifdef KSpaceInclude
 #endif
@@ -85,7 +86,7 @@
 #endif
 
 #ifdef MinimizeClass
-# endif
+#endif
 
 #ifdef PairInclude
 #endif
diff --git a/src/thermo.cpp b/src/thermo.cpp
index 9898059454d389e0df93d50734625edf39f5c486..33f47619bca93e1c350500b358a127dc21667cc6 100644
--- a/src/thermo.cpp
+++ b/src/thermo.cpp
@@ -120,10 +120,10 @@ Thermo::Thermo(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
   index_temp = index_press = index_drot = index_grot = -1;
   internal_drot = internal_grot = 0;
 
-  id_temp = "thermo_temp";
-  id_press = "thermo_pressure";
-  id_drot = "thermo_rotate_dipole";
-  id_grot = "thermo_rotate_gran";
+  id_temp = (char *) "thermo_temp";
+  id_press = (char *) "thermo_pressure";
+  id_drot = (char *) "thermo_rotate_dipole";
+  id_grot = (char *) "thermo_rotate_gran";
 
   // count fields in line
   // allocate per-field memory
@@ -137,22 +137,22 @@ Thermo::Thermo(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
   // temperature and pressure always exist b/c Output class created them
 
   if (index_drot >= 0) {
-    create_compute(id_drot,"rotate/dipole",NULL);
+    create_compute(id_drot,(char *) "rotate/dipole",NULL);
     internal_drot = 1;
   }
   if (index_grot >= 0) {
-    create_compute(id_grot,"rotate/gran",NULL);
+    create_compute(id_grot,(char *) "rotate/gran",NULL);
     internal_grot = 1;
   }
 
   // format strings
 
-  format_multi = "---------------- Step %8d ----- "
-                 "CPU = %11.4f (sec) ----------------";
-  format_int_one_def = "%8d";
-  format_int_multi_def = "%14d";
-  format_g_def = "%12.8g";
-  format_f_def = "%14.4f";
+  format_multi = (char *) "---------------- Step %8d ----- "
+                          "CPU = %11.4f (sec) ----------------";
+  format_int_one_def = (char *) "%8d";
+  format_int_multi_def = (char *) "%14d";
+  format_g_def = (char *) "%12.8g";
+  format_f_def = (char *) "%14.4f";
   format_int_user = NULL;
   format_float_user = NULL;
 
@@ -398,17 +398,17 @@ void Thermo::modify_params(int narg, char **arg)
       if (temperature->igroup != 0 && comm->me == 0)
 	error->warning("Temperature for thermo pressure is not for group all");
 
-      // reset id_pre of pressure to new temp ID
+      // reset id_pre[0] of pressure to new temp ID
       // either pressure currently being used by thermo or "thermo_pressure"
 
       if (index_press >= 0) {
 	icompute = modify->find_compute(id_compute[index_press]);
 	if (icompute < 0) error->all("Press ID for thermo does not exist");
-      } else icompute = modify->find_compute("thermo_pressure");
+      } else icompute = modify->find_compute((char *) "thermo_pressure");
 
-      delete [] modify->compute[icompute]->id_pre;
-      modify->compute[icompute]->id_pre = new char[n];
-      strcpy(modify->compute[icompute]->id_pre,arg[iarg+1]);
+      delete [] modify->compute[icompute]->id_pre[0];
+      modify->compute[icompute]->id_pre[0] = new char[n];
+      strcpy(modify->compute[icompute]->id_pre[0],arg[iarg+1]);
 
       iarg += 2;
 
@@ -427,13 +427,13 @@ void Thermo::modify_params(int narg, char **arg)
       if (pressure->pressflag == 0)
 	error->all("Thermo_modify press ID does not compute pressure");
 
-      // if id_pre of new pressure is not being computed, add to compute list
-      // swap it with pressure in list so id_pre will be computed first
+      // if id_pre[0] of new pressure not being computed, add to compute list
+      // swap it with pressure in list so id_pre[0] will be computed first
       // OK to call add_compute with "which" acting as index
 
       int which = compute_which[index_press];
       int ncompute_current = ncompute;
-      icompute = add_compute(pressure->id_pre,which);
+      icompute = add_compute(pressure->id_pre[0],which);
       if (icompute == ncompute_current) {
 	int iswap = compute_which[index_press];
 	compute_which[index_press] = compute_which[icompute];
@@ -554,7 +554,6 @@ void Thermo::modify_params(int narg, char **arg)
 
 /* ----------------------------------------------------------------------
    allocate all per-field memory
-   allow each c_ID to imply 2 Compute objects (if it has id_pre)
 ------------------------------------------------------------------------- */
 
 void Thermo::allocate()
@@ -577,9 +576,9 @@ void Thermo::allocate()
   arg_object = new int[n];
 
   ncompute = 0;
-  id_compute = new char*[2*n];
-  compute_which = new int[2*n];
-  computes = new Compute*[2*n];
+  id_compute = NULL;
+  compute_which = NULL;
+  computes = NULL;
 
   nfix = 0;
   id_fix = new char*[n];
@@ -611,9 +610,9 @@ void Thermo::deallocate()
   delete [] arg_object;
 
   for (int i = 0; i < ncompute; i++) delete [] id_compute[i];
-  delete [] id_compute;
-  delete [] compute_which;
-  delete [] computes;
+  memory->sfree(id_compute);
+  memory->sfree(compute_which);
+  memory->sfree(computes);
 
   for (int i = 0; i < nfix; i++) delete [] id_fix[i];
   delete [] id_fix;
@@ -760,7 +759,7 @@ void Thermo::parse_fields(char *str)
     // compute value = c_ID, fix value = f_ID, variable value = v_ID
     // if no trailing [], then arg is set to 0, else arg is between []
     // copy = at most 8 chars of ID to pass to addfield
-    // for compute, if has pre-compute object, first add it to list
+    // if Compute has pre-computes, first add them to list
 
     } else if ((strncmp(word,"c_",2) == 0) || (strncmp(word,"f_",2) == 0) ||
 	       (strncmp(word,"v_",2) == 0)) {
@@ -790,8 +789,10 @@ void Thermo::parse_fields(char *str)
 	if (arg_object[nfield] > 0 && 
 	    arg_object[nfield] > modify->compute[n]->size_vector)
 	  error->all("Thermo compute ID vector is not large enough");
-	if (modify->compute[n]->id_pre)
-	  int tmp = add_compute(modify->compute[n]->id_pre,arg_object[nfield]);
+	if (modify->compute[n]->npre)
+	  for (int ic = 0; ic < modify->compute[n]->npre; ic++)
+	    int tmp = add_compute(modify->compute[n]->id_pre[ic],
+				  arg_object[nfield]);
 	field2object[nfield] = add_compute(id,arg_object[nfield]);
 	addfield(copy,&Thermo::compute_compute,FLOAT);
 
@@ -820,7 +821,7 @@ void Thermo::parse_fields(char *str)
    add field to list of quantities to print
 ------------------------------------------------------------------------- */
 
-void Thermo::addfield(char *key, FnPtr func, int typeflag)
+void Thermo::addfield(const char *key, FnPtr func, int typeflag)
 {
   strcpy(keyword[nfield],key);
   vfunc[nfield] = func;
@@ -830,13 +831,15 @@ void Thermo::addfield(char *key, FnPtr func, int typeflag)
 
 /* ----------------------------------------------------------------------
    add compute ID to list of Compute objects to call
-   if already in list, do not add, just return location, else add to list
+   return index of where this Compute is in list
+   if already in list, do not add, just return index, else add to list
    convert index into which param
      index = 0 -> scalar, index >= 1 -> vector
      which = 1 -> scalar only, which = 2 -> vector only, which = 3 -> both
+   change which param if Compute is in list with different which param
 ------------------------------------------------------------------------- */
 
-int Thermo::add_compute(char *id, int index)
+int Thermo::add_compute(const char *id, int index)
 {
   int icompute;
   for (icompute = 0; icompute < ncompute; icompute++)
@@ -849,6 +852,16 @@ int Thermo::add_compute(char *id, int index)
     }
   if (icompute < ncompute) return icompute;
 
+  id_compute = (char **)
+    memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),
+		     "thermo:id_compute");
+  compute_which = (int *)
+    memory->srealloc(compute_which,(ncompute+1)*sizeof(int),
+		     "thermo:compute_which");
+  computes = (Compute **) 
+    memory->srealloc(computes,(ncompute+1)*sizeof(Compute *),
+		     "thermo:computes");
+
   int n = strlen(id) + 1;
   id_compute[ncompute] = new char[n];
   strcpy(id_compute[ncompute],id);
@@ -862,7 +875,7 @@ int Thermo::add_compute(char *id, int index)
    add fix ID to list of Fix objects to call
 ------------------------------------------------------------------------- */
 
-int Thermo::add_fix(char *id)
+int Thermo::add_fix(const char *id)
 {
   int n = strlen(id) + 1;
   id_fix[nfix] = new char[n];
@@ -875,7 +888,7 @@ int Thermo::add_fix(char *id)
    add variable ID to list of Variables to evaluate
 ------------------------------------------------------------------------- */
 
-int Thermo::add_variable(char *id)
+int Thermo::add_variable(const char *id)
 {
   int n = strlen(id) + 1;
   id_variable[nvariable] = new char[n];
@@ -892,7 +905,7 @@ void Thermo::create_compute(char *id, char *cstyle, char *extra)
 {
   char **newarg = new char*[4];
   newarg[0] = id;
-  newarg[1] = "all";
+  newarg[1] = (char *) "all";
   newarg[2] = cstyle;
   if (extra) newarg[3] = extra;
   if (extra) modify->add_compute(4,newarg);
diff --git a/src/thermo.h b/src/thermo.h
index d5e00ae106d28012eb11a2b9d5bb263c0661bd59..e1bf0f22d7e1b72ef9218e42c2258ff569ef9f28 100644
--- a/src/thermo.h
+++ b/src/thermo.h
@@ -100,13 +100,13 @@ class Thermo : protected Pointers {
   void deallocate();
 
   void parse_fields(char *);
-  int add_compute(char *, int);
-  int add_fix(char *);
-  int add_variable(char *);
+  int add_compute(const char *, int);
+  int add_fix(const char *);
+  int add_variable(const char *);
   void create_compute(char *, char *, char *);
 
   typedef void (Thermo::*FnPtr)();
-  void addfield(char *, FnPtr, int);
+  void addfield(const char *, FnPtr, int);
   FnPtr *vfunc;                // list of ptrs to functions
 
   void compute_compute();      // functions that compute a single value
diff --git a/src/universe.cpp b/src/universe.cpp
index baa1266ecf302d619c827751cd62b4bc4cc1a82e..6a9d9db0bbc2da6e9e1079e5ed178d10534d6525 100644
--- a/src/universe.cpp
+++ b/src/universe.cpp
@@ -26,7 +26,7 @@ using namespace LAMMPS_NS;
 
 Universe::Universe(LAMMPS *lmp, MPI_Comm communicator) : Pointers(lmp)
 {
-  version = "22 Jun 2007";
+  version = (char *) "22 Jun 2007";
 
   uworld = communicator;
   MPI_Comm_rank(uworld,&me);
diff --git a/src/update.cpp b/src/update.cpp
index d24d580c66bf5d473720f033242550105558fffc..a3b7879483ea4fca55acedba3488af6dd6b2fb50 100644
--- a/src/update.cpp
+++ b/src/update.cpp
@@ -41,19 +41,16 @@ Update::Update(LAMMPS *lmp) : Pointers(lmp)
   firststep = laststep = 0;
   beginstep = endstep = 0;
 
-  maxpair = 0;
-  f_pair = NULL;
-
   unit_style = NULL;
   set_units("lj");
 
-  str = "verlet";
+  str = (char *) "verlet";
   n = strlen(str) + 1;
   integrate_style = new char[n];
   strcpy(integrate_style,str);
   integrate = new Verlet(lmp,0,NULL);
 
-  str = "cg";
+  str = (char *) "cg";
   n = strlen(str) + 1;
   minimize_style = new char[n];
   strcpy(minimize_style,str);
@@ -64,8 +61,6 @@ Update::Update(LAMMPS *lmp) : Pointers(lmp)
 
 Update::~Update()
 {
-  memory->destroy_2d_double_array(f_pair);
-
   delete [] unit_style;
 
   delete [] integrate_style;
@@ -93,7 +88,7 @@ void Update::init()
 
 /* ---------------------------------------------------------------------- */
 
-void Update::set_units(char *style)
+void Update::set_units(const char *style)
 {
   // physical constants from:
   // http://physics.nist.gov/cuu/Constants/Table/allascii.txt
@@ -190,7 +185,7 @@ void Update::create_minimize(int narg, char **arg)
 
 int Update::memory_usage()
 {
-  int bytes = maxpair*3 * sizeof(double);
+  int bytes = 0;
   if (whichflag == 0) bytes += integrate->memory_usage();
   else if (whichflag == 1) bytes += minimize->memory_usage();
   return bytes;
diff --git a/src/update.h b/src/update.h
index b28c35b279b4a36e55e81738e09724c41b9c9002..0373bf69030c9e807826a17b597bdb086e2e73df 100644
--- a/src/update.h
+++ b/src/update.h
@@ -30,9 +30,6 @@ class Update : protected Pointers {
   int first_update;               // 0 before initial update, 1 after
   int max_eval;                   // max force evaluations for minimizer
 
-  double **f_pair;                // used by pair to compute force & virial
-  int maxpair;
-
   char *unit_style;
 
   class Integrate *integrate;
@@ -44,7 +41,7 @@ class Update : protected Pointers {
   Update(class LAMMPS *);
   ~Update();
   void init();
-  void set_units(char *);
+  void set_units(const char *);
   void create_integrate(int, char **);
   void create_minimize(int, char **);
   int memory_usage();
diff --git a/src/variable.cpp b/src/variable.cpp
index e920ad4be18603ee0c5a21f8b16b3a853098ca85..cb7311647f4fe3325b195b3c3b38b28941ff946a 100644
--- a/src/variable.cpp
+++ b/src/variable.cpp
@@ -217,7 +217,7 @@ void Variable::set(char *name, char *value)
 {
   char **newarg = new char*[3];
   newarg[0] = name;
-  newarg[1] = "index";
+  newarg[1] = (char *) "index";
   newarg[2] = value;
   set(3,newarg);
   delete [] newarg;
@@ -697,28 +697,32 @@ double Variable::evaluate(char *str, Tree *tree)
       modify->compute[icompute]->init();
 
       // call compute() if index = 0, else compute_vector()
-      // make pre-call to Compute object's id_pre if it is defined
+      // make pre-call to Compute object's pre-compute(s) if defined
 
       int index = atoi(arg);
       if (index == 0) {
 	if (modify->compute[icompute]->scalar_flag == 0)
 	  error->all("Variable compute ID does not compute scalar info");
-	if (modify->compute[icompute]->id_pre) {
-	  int ipre = modify->find_compute(modify->compute[icompute]->id_pre);
-	  if (ipre < 0) error->all("Could not pre-compute in variable");
-	  answer = modify->compute[ipre]->compute_scalar();
-	}
+	if (modify->compute[icompute]->npre)
+	  for (int ic = 0; ic < modify->compute[icompute]->npre; ic++) {
+	    int ipre = 
+	      modify->find_compute(modify->compute[icompute]->id_pre[ic]);
+	    if (ipre < 0) error->all("Could not pre-compute in variable");
+	    double tmp = modify->compute[ipre]->compute_scalar();
+	  }
 	answer = modify->compute[icompute]->compute_scalar();
       } else if (index > 0) {
 	if (modify->compute[icompute]->vector_flag == 0)
 	  error->all("Variable compute ID does not compute scalar info");
 	if (index > modify->compute[icompute]->size_vector)
 	  error->all("Variable compute ID vector is not large enough");
-	if (modify->compute[icompute]->id_pre) {
-	  int ipre = modify->find_compute(modify->compute[icompute]->id_pre);
-	  if (ipre < 0) error->all("Could not pre-compute in variable");
-	  modify->compute[ipre]->compute_vector();
-	}
+	if (modify->compute[icompute]->npre)
+	  for (int ic = 0; ic < modify->compute[icompute]->npre; ic++) {
+	    int ipre = 
+	      modify->find_compute(modify->compute[icompute]->id_pre[ic]);
+	    if (ipre < 0) error->all("Could not pre-compute in variable");
+	    modify->compute[ipre]->compute_vector();
+	  }
 	modify->compute[icompute]->compute_vector();
 	answer = modify->compute[icompute]->vector[index-1];
       } else error->all("Invalid compute ID index in variable");
diff --git a/src/velocity.cpp b/src/velocity.cpp
index 7167c10b2a71c168dc5152b2c8fea45a18eb4bad..138891fc309650f411199112a130b8210aa5a17a 100644
--- a/src/velocity.cpp
+++ b/src/velocity.cpp
@@ -131,9 +131,9 @@ void Velocity::create(int narg, char **arg)
   int tflag = 0;
   if (temperature == NULL) {
     char **arg = new char*[3];
-    arg[0] = "velocity_temp";
+    arg[0] = (char *) "velocity_temp";
     arg[1] = group->names[igroup];
-    arg[2] = "temp";
+    arg[2] = (char *) "temp";
     temperature = new ComputeTemp(lmp,3,arg);
     tflag = 1;
     delete [] arg;
@@ -215,7 +215,7 @@ void Velocity::create(int narg, char **arg)
     MPI_Allreduce(&idmax,&idmaxall,1,MPI_INT,MPI_MAX,world);
 
     if (idminall != 1 || idmaxall != natoms) {
-      char *str = "Cannot use velocity create loop all with non-contiguous atom IDs";
+      char *str = (char *) "Cannot use velocity create loop all with non-contiguous atom IDs";
       error->all(str);
     }
     
@@ -390,9 +390,9 @@ void Velocity::scale(int narg, char **arg)
   int tflag = 0;
   if (temperature == NULL) {
     char **arg = new char*[3];
-    arg[0] = "velocity_temp";
+    arg[0] = (char *) "velocity_temp";
     arg[1] = group->names[igroup];
-    arg[2] = "temp";
+    arg[2] = (char *) "temp";
     temperature = new ComputeTemp(lmp,3,arg);
     tflag = 1;
     delete [] arg;
diff --git a/src/verlet.cpp b/src/verlet.cpp
index 5d4ff28b8731d13bb2042bf55fe175e3ab2cdd2f..fe48c8ccd865761766cc8e0003dc68e73bc2d93a 100644
--- a/src/verlet.cpp
+++ b/src/verlet.cpp
@@ -93,21 +93,13 @@ void Verlet::init()
 
   // set flags for what arrays to clear in force_clear()
   // need to clear torques if array exists
-  // don't need to clear f_pair if atom_style is only granular (no virial)
 
   torqueflag = 0;
   if (atom->torque_flag) torqueflag = 1;
-  pairflag = 1;
-  if (strcmp(atom->atom_style,"granular") == 0) pairflag = 0;
 
   // orthogonal vs triclinic simulation box
 
   triclinic = domain->triclinic;
-
-  // local copies of Update quantities
-
-  maxpair = update->maxpair;
-  f_pair = update->f_pair;
 }
 
 /* ----------------------------------------------------------------------
@@ -139,6 +131,8 @@ void Verlet::setup()
   int vflag = virial_style;
   force_clear(vflag);
   
+  if (force->pair) force->pair->compute(eflag,vflag);
+
   if (atom->molecular) {
     if (force->bond) force->bond->compute(eflag,vflag);
     if (force->angle) force->angle->compute(eflag,vflag);
@@ -146,8 +140,6 @@ void Verlet::setup()
     if (force->improper) force->improper->compute(eflag,vflag);
   }
 
-  if (force->pair) force->pair->compute(eflag,vflag);
-
   if (force->kspace) {
     force->kspace->setup();
     force->kspace->compute(eflag,vflag);
@@ -233,6 +225,12 @@ void Verlet::iterate(int n)
     force_clear(vflag);
 
     timer->stamp();
+
+    if (force->pair) {
+      force->pair->compute(eflag,vflag);
+      timer->stamp(TIME_PAIR);
+    }
+
     if (atom->molecular) {
       if (force->bond) force->bond->compute(eflag,vflag);
       if (force->angle) force->angle->compute(eflag,vflag);
@@ -241,11 +239,6 @@ void Verlet::iterate(int n)
       timer->stamp(TIME_BOND);
     }
 
-    if (force->pair) {
-      force->pair->compute(eflag,vflag);
-      timer->stamp(TIME_PAIR);
-    }
-
     if (force->kspace) {
       force->kspace->compute(eflag,vflag);
       timer->stamp(TIME_KSPACE);
@@ -305,23 +298,6 @@ void Verlet::force_clear(int vflag)
       torque[i][2] = 0.0;
     }
   }
-
-  // clear f_pair array if using it this timestep to compute virial
-
-  if (vflag == 2 && pairflag) {
-    if (atom->nmax > maxpair) {
-      maxpair = atom->nmax;
-      memory->destroy_2d_double_array(f_pair);
-      f_pair = memory->create_2d_double_array(maxpair,3,"verlet:f_pair");
-      update->maxpair = maxpair;
-      update->f_pair = f_pair;
-    }
-    for (i = 0; i < nall; i++) {
-      f_pair[i][0] = 0.0;
-      f_pair[i][1] = 0.0;
-      f_pair[i][2] = 0.0;
-    }
-  }
 }
 
 /* ----------------------------------------------------------------------
diff --git a/src/verlet.h b/src/verlet.h
index f63cf539f3388448ff03448743c99991beb55029..a0c31dbd7b66fbb4ce7436a21ffeb4726419fe5f 100644
--- a/src/verlet.h
+++ b/src/verlet.h
@@ -35,9 +35,7 @@ class Verlet : public Integrate {
   int *next_fix_virial;             // next timestep they need it
   int triclinic;                    // 0 if domain is orthog, 1 if triclinic
 
-  int pairflag,torqueflag;          // arrays to zero out every step
-  int maxpair;                      // local copies of Update quantities
-  double **f_pair;
+  int torqueflag;                   // arrays to zero out every step
 
   void force_clear(int);
   int fix_virial(int);