diff --git a/src/USER-REAXC/fix_qeq_reax.cpp b/src/USER-REAXC/fix_qeq_reax.cpp
index ba96d7b211137170a381508ec29f5df7182de5fa..6323d5138afa5c1fbbdae159de4ea3521b57e1f0 100644
--- a/src/USER-REAXC/fix_qeq_reax.cpp
+++ b/src/USER-REAXC/fix_qeq_reax.cpp
@@ -322,13 +322,14 @@ void FixQEqReax::init()
     error->all(FLERR,"Must use pair_style reax/c with fix qeq/reax");
 
   // need a half neighbor list w/ Newton off and ghost neighbors
-  // built whenever re-neighboring occurs
+  // make it occasional if QeQ not performed every timestep
 
   int irequest = neighbor->request(this);
   neighbor->requests[irequest]->pair = 0;
   neighbor->requests[irequest]->fix = 1;
   neighbor->requests[irequest]->newton = 2;
   neighbor->requests[irequest]->ghost = 1;
+  if (nevery) neighbor->requests[irequest]->occasional = 1;
 
   init_shielding();
   init_taper();
@@ -523,12 +524,14 @@ void FixQEqReax::compute_H()
   tagint *tag = atom->tag;
   x = atom->x;
 
+  if (nevery > 1) neighbor->build_one(list->index);
   inum = list->inum;
   ilist = list->ilist;
   numneigh = list->numneigh;
   firstneigh = list->firstneigh;
 
   // fill in the H matrix
+
   m_fill = 0;
   r_sqr = 0;
   for( ii = 0; ii < inum; ii++ ) {
diff --git a/src/delete_atoms.cpp b/src/delete_atoms.cpp
index 2db870416a75468fdf60289657bc25a24615f2c8..2501917d85194b75f8a9e5351fc0996f479e173b 100644
--- a/src/delete_atoms.cpp
+++ b/src/delete_atoms.cpp
@@ -266,8 +266,7 @@ void DeleteAtoms::delete_overlap(int narg, char **arg)
     error->all(FLERR,"Delete_atoms cutoff > neighbor cutoff");
 
   // setup domain, communication and neighboring
-  // acquire ghosts
-  // build neighbor list based on earlier request
+  // acquire ghosts and build standard neighbor lists
 
   if (domain->triclinic) domain->x2lamda(atom->nlocal);
   domain->pbc();
@@ -277,6 +276,9 @@ void DeleteAtoms::delete_overlap(int narg, char **arg)
   comm->exchange();
   comm->borders();
   if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
+  neighbor->build();
+
+  // build neighbor list this command needs based on earlier request
 
   NeighList *list = neighbor->lists[irequest];
   neighbor->build_one(irequest);
diff --git a/src/neigh_full.cpp b/src/neigh_full.cpp
index 9732d734f3554d4a057fa6116eb4e5a4116068a4..2eaf99d8e4b20125b237a5f6b1a2718fb52b3264 100644
--- a/src/neigh_full.cpp
+++ b/src/neigh_full.cpp
@@ -247,7 +247,7 @@ void Neighbor::full_bin(NeighList *list)
 
   // bin owned & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
@@ -355,7 +355,7 @@ void Neighbor::full_bin_ghost(NeighList *list)
 
   // bin owned & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
diff --git a/src/neigh_half_bin.cpp b/src/neigh_half_bin.cpp
index 9bba2e6ef02b2b8019438ab835f74c64455bfadd..349deddae108140504a957b784e1454a037284ce 100644
--- a/src/neigh_half_bin.cpp
+++ b/src/neigh_half_bin.cpp
@@ -38,7 +38,7 @@ void Neighbor::half_bin_no_newton(NeighList *list)
 
   // bin local & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
@@ -151,7 +151,7 @@ void Neighbor::half_bin_no_newton_ghost(NeighList *list)
 
   // bin local & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
@@ -291,7 +291,7 @@ void Neighbor::half_bin_newton(NeighList *list)
 
   // bin local & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
@@ -433,7 +433,7 @@ void Neighbor::half_bin_newton_tri(NeighList *list)
 
   // bin local & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
diff --git a/src/neigh_list.cpp b/src/neigh_list.cpp
index 24570258de23fb78b9595b7b4b31ef1613fd2ef4..dc925a6f90f5801919ae2eb19ea6a3e8dcab9e12 100644
--- a/src/neigh_list.cpp
+++ b/src/neigh_list.cpp
@@ -42,6 +42,8 @@ NeighList::NeighList(LAMMPS *lmp) :
 
   dnum = 0;
 
+  last_build = -1;
+
   iskip = NULL;
   ijskip = NULL;
 
diff --git a/src/neigh_list.h b/src/neigh_list.h
index 0329c140407f9492d82ac2e7d939d48119f063d4..f7fecce9b8d5978b9b9559595a8e965b5fa2edf7 100644
--- a/src/neigh_list.h
+++ b/src/neigh_list.h
@@ -45,6 +45,8 @@ class NeighList : protected Pointers {
   MyPage<int> *ipage;              // pages of neighbor indices
   MyPage<double> *dpage;           // pages of neighbor doubles, if dnum > 0
 
+  bigint last_build;           // timestep of last build for occasional lists
+
   // atom types to skip when building list
   // iskip,ijskip are just ptrs to corresponding request
 
diff --git a/src/neigh_respa.cpp b/src/neigh_respa.cpp
index 91f85de6ea412e9432da56ff8c87471de3c167c7..777534746b1d26c98c56cbca23522444702809f8 100644
--- a/src/neigh_respa.cpp
+++ b/src/neigh_respa.cpp
@@ -378,7 +378,7 @@ void Neighbor::respa_bin_no_newton(NeighList *list)
 
   // bin local & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
@@ -548,7 +548,7 @@ void Neighbor::respa_bin_newton(NeighList *list)
 
   // bin local & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
@@ -765,7 +765,7 @@ void Neighbor::respa_bin_newton_tri(NeighList *list)
 
   // bin local & ghost atoms
 
-  bin_atoms();
+  if (binatomflag) bin_atoms();
 
   double **x = atom->x;
   int *type = atom->type;
diff --git a/src/neighbor.cpp b/src/neighbor.cpp
index bc96075dd909c91046f356c2134bf58631c23d63..c38d8db7aa1c1b86c5d9902bc55ac10925f6c119 100644
--- a/src/neighbor.cpp
+++ b/src/neighbor.cpp
@@ -83,6 +83,7 @@ Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp)
   binsizeflag = 0;
   build_once = 0;
   cluster_check = 0;
+  binatomflag = 1;
 
   cutneighsq = NULL;
   cutneighghostsq = NULL;
@@ -508,27 +509,6 @@ void Neighbor::init()
     // detect lists that are connected to other lists
     // if-then-else sequence and processed flag is important
     //   since don't want to re-process skip or copy lists further down
-    //   skip list needs to have granhistory or respa info added
-    // copy: point this list at request->otherlist, could be a skip list
-    // skip: point this list at request->otherlist, copy skip info from request
-    //   also set granular and respa info if applicable
-    // half_from_full: point this list at preceeding full list
-    // granhistory: set preceeding list's listgranhistory to this list
-    //   also set preceeding list's ptr to FixShearHistory
-    // respaouter: point this list at preceeding 1/2 inner/middle lists
-    // pair and half: if there is a full non-occasional non-skip list
-    //   change this list to half_from_full and point at the full list
-    //   parent could be copy list or pair or fix
-    // fix/compute requests:
-    //   whether request is occasional or not doesn't matter
-    //   if request = half and non-skip pair half/respaouter exists,
-    //     become copy of that list if cudable flag matches
-    //   if request = full and non-skip pair full exists,
-    //     become copy of that list if cudable flag matches
-    //   if request = half and non-skip pair full exists,
-    //     become half_from_full of that list if cudable flag matches
-    //   if no matches, do nothing, fix/compute list will be built directly
-    //   ok if parent is copy list
 
     int processed;
 
@@ -536,20 +516,32 @@ void Neighbor::init()
       if (!lists[i]) continue;
       processed = 0;
 
+      // copy: point this list at request->otherlist, could be a skip list
+
       if (requests[i]->copy) {
         lists[i]->listcopy = lists[requests[i]->otherlist];
         processed = 1;
 
+      // skip: point this list at request->otherlist,
+      //       copy skip info from request
+      // skip list still needs to have granhistory or respa info added below
+
       } else if (requests[i]->skip) {
         lists[i]->listskip = lists[requests[i]->otherlist];
         lists[i]->copy_skip_info(requests[i]->iskip,requests[i]->ijskip);
         processed = 1;
 
+      // half_from_full: point this list at full list that comes right before
+      //   will only be case if pair style requested one after other
+
       } else if (requests[i]->half_from_full) {
         lists[i]->listfull = lists[i-1];
         processed = 1;
       }
 
+      // granhistory: set preceeding list's listgranhistory to this list
+      //               also set preceeding list's ptr to FixShearHistory
+
       if (requests[i]->granhistory) {
         lists[i-1]->listgranhistory = lists[i];
         for (int ifix = 0; ifix < modify->nfix; ifix++)
@@ -557,6 +549,8 @@ void Neighbor::init()
             lists[i-1]->fix_history = (FixShearHistory *) modify->fix[ifix];
         processed = 1;
 
+      // respaouter: point this list at preceeding 1/2 inner/middle lists
+
       } else if (requests[i]->respaouter) {
         if (requests[i-1]->respainner) {
           lists[i]->respamiddle = 0;
@@ -571,6 +565,10 @@ void Neighbor::init()
 
       if (processed) continue;
 
+      // pair and half: if there is a full non-occasional non-skip list
+      //   change this list to half_from_full and point at the full list
+      //   parent could be copy list or pair or fix
+
       if (requests[i]->pair && requests[i]->half) {
         for (j = 0; j < nrequest; j++) {
           if (!lists[j]) continue;
@@ -583,6 +581,18 @@ void Neighbor::init()
           lists[i]->listfull = lists[j];
         }
         
+      // fix/compute requests:
+      // whether request is occasional or not doesn't matter
+      // if request = half and non-skip pair half/respaouter exists,
+      //   become copy of that list if cudable flag matches
+      // if request = full and non-skip pair full exists,
+      //   become copy of that list if cudable flag matches
+      // if request = half and non-skip pair full exists,
+      //   become half_from_full of that list if cudable flag matches
+      // if no matches, do nothing
+      //   fix/compute list will be built independently as needed
+      // ok if parent is itself a copy list
+
       } else if (requests[i]->fix || requests[i]->compute) {
         for (j = 0; j < nrequest; j++) {
           if (!lists[j]) continue;
@@ -1349,8 +1359,8 @@ int Neighbor::check_distance()
 }
 
 /* ----------------------------------------------------------------------
-   build all perpetual neighbor lists every few timesteps
-   pairwise & topology lists are created as needed
+   build perpetuals neighbor lists
+   called at setup and every few timesteps during run or minimization
    topology lists only built if topoflag = 1, USER-CUDA calls with topoflag = 0
 ------------------------------------------------------------------------- */
 
@@ -1419,12 +1429,12 @@ void Neighbor::build(int topoflag)
     memory->create(bins,maxbin,"bins");
   }
 
-  // check that neighbor list with special bond flags will not overflow
+  // check that using special bond flags will not overflow neigh lists
 
   if (atom->nlocal+atom->nghost > NEIGHMASK)
     error->one(FLERR,"Too many local+ghost atoms for neighbor list");
 
-  // invoke building of pair and molecular neighbor lists
+  // invoke building of pair and molecular topology neighbor lists
   // only for pairwise lists with buildflag set
   // blist is for standard neigh lists, otherwise is a Kokkos list
 
@@ -1455,9 +1465,22 @@ void Neighbor::build_topology()
    called by other classes
 ------------------------------------------------------------------------- */
 
-void Neighbor::build_one(int i)
+void Neighbor::build_one(int i, int preflag)
 {
-  // update stencils and grow atom arrays and bins as needed
+  // no need to build if already built since last re-neighbor
+  // preflag is set by fix bond/create and fix bond/swap
+  //   b/c they invoke build_one() on same step neigh list is re-built,
+  //   but before re-build, so need to use ">" instead of ">="
+
+  if (preflag) {
+    if (lists[i]->last_build > lastcall) return;
+  } else {
+    if (lists[i]->last_build >= lastcall) return;
+  }
+
+  lists[i]->last_build = update->ntimestep;
+
+  // update stencils and grow atom arrays as needed
   // only for relevant settings of stencilflag and growflag
   // grow atom array for this list to current size of perpetual lists
 
@@ -1468,42 +1491,14 @@ void Neighbor::build_one(int i)
 
   if (lists[i]->growflag) lists[i]->grow(maxatom);
 
-  // extend atom bin list if necessary
-
-  if (style != NSQ && atom->nmax > maxbin) {
-    maxbin = atom->nmax;
-    memory->destroy(bins);
-    memory->create(bins,maxbin,"bins");
-  }
-
-  // check that neighbor list with special bond flags will not overflow
-
-  if (atom->nlocal+atom->nghost > NEIGHMASK)
-    error->one(FLERR,"Too many local+ghost atoms for neighbor list");
-
-  // when occasional list built, LAMMPS can crash if atoms have moved too far
-  // why is this? maybe b/c this list is derived from some now out-of-date list?
-  // give warning if this is the case
-  // no easy workaround b/c all neighbor lists really need to be rebuilt
-  // solution is for input script to check more often for rebuild
-  // only check_distance if running a simulation, not between simulations
-  // comment out for now
-  //   is sometimes giving warning when there is no issue
-  //   e.g. when a variable uses a fix with an occasional neigh list
-  //   at the beginning of a timestep (e.g. fix move) where
-  //   all neigh lists are about to be re-built anyway
-
-  /*
-  int flag = 0;
-  if (dist_check && update->whichflag) flag = check_distance();
-  if (flag && me == 0) {
-    printf("BUILD ONE ERROR: %ld\n",update->ntimestep);
-    error->warning(FLERR,"Building an occasional neighbor list when "
-                   "atoms may have moved too far");
-  }
-  */
+  // build list I, turning off atom binning
+  // binning results from last re-neighbor should be used instead
+  // if re-bin now, atoms may have moved outside of proc domain & bin extent,
+  //   leading to errors or even a crash
 
+  binatomflag = 0;
   (this->*pair_build[i])(lists[i]);
+  binatomflag = 1;
 }
 
 /* ----------------------------------------------------------------------
diff --git a/src/neighbor.h b/src/neighbor.h
index ec6881d56db6a10477692a3df9fc3a6d02c361ea..3c0c4af88935122c1550c3803bd7d82656b09147 100644
--- a/src/neighbor.h
+++ b/src/neighbor.h
@@ -75,7 +75,7 @@ class Neighbor : protected Pointers {
   void setup_bins();                // setup bins based on box and cutoff
   virtual void build(int topoflag=1);  // create all neighbor lists (pair,bond)
   virtual void build_topology();    // create all topology neighbor lists
-  void build_one(int);              // create a single neighbor list
+  void build_one(int, int preflag=0);  // create a single neighbor list
   void set(int, char **);           // set neighbor style and skin distance
   void modify_params(int, char**);  // modify parameters that control builds
   bigint memory_usage();
@@ -107,6 +107,9 @@ class Neighbor : protected Pointers {
   double boxlo_hold[3],boxhi_hold[3];  // box size at last neighbor build
   double corners_hold[8][3];           // box corners at last neighbor build
 
+  int binatomflag;                 // bin atoms or not when build neigh list
+                                   // turned off by build_one()
+
   int nbinx,nbiny,nbinz;           // # of global bins
   int *bins;                       // ptr to next atom in each bin
   int maxbin;                      // size of bins array