diff --git a/src/atom.cpp b/src/atom.cpp index 838d67deec835e45f59f70e551cbed643c0aff9c..9303fdafd6d9605d42b393d821f4b446f134674c 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -15,6 +15,7 @@ #include "stdio.h" #include "stdlib.h" #include "string.h" +#include "limits.h" #include "atom.h" #include "style_atom.h" #include "atom_vec.h" @@ -52,7 +53,8 @@ Atom::Atom(LAMMPS *lmp) : Pointers(lmp) extra_bond_per_atom = 0; firstgroupname = NULL; - sortfreq = 0; + sortfreq = 1000; + userbinsize = 0.0; maxbin = maxnext = 0; binhead = NULL; next = permute = NULL; @@ -307,15 +309,10 @@ void Atom::init() void Atom::setup() { - // setup for sorting - // binsize = user setting or 1/2 of neighbor cutoff + // setup bins for sorting + // cannot do this in init() because uses neighbor cutoff - if (sortfreq > 0) { - double binsize; - if (userbinsize > 0.0) binsize = userbinsize; - else binsize = 0.5 * neighbor->cutneighmax; - bininv = 1.0/binsize; - } + if (sortfreq > 0) setup_sort_bins(); } /* ---------------------------------------------------------------------- @@ -1331,37 +1328,20 @@ void Atom::first_reorder() /* ---------------------------------------------------------------------- perform spatial sort of atoms within my sub-domain + always called between comm->exchange() and comm->borders() + don't have to worry about clearing/setting atom->map since done in comm ------------------------------------------------------------------------- */ void Atom::sort() { int i,m,n,ix,iy,iz,ibin,empty,ndone; - // setup local bins, grow arrays as necessary - - double *sublo = domain->sublo; - double *subhi = domain->subhi; + // re-setup sort bins if needed - int nbinx = static_cast<int> ((subhi[0]-sublo[0]) * bininv); - int nbiny = static_cast<int> ((subhi[1]-sublo[1]) * bininv); - int nbinz = static_cast<int> ((subhi[2]-sublo[2]) * bininv); - - nbinx = MAX(nbinx,1); - nbinx = MAX(nbiny,1); - nbinx = MAX(nbinz,1); - - int nbins = nbinx*nbiny*nbinz; + if (domain->box_change) setup_sort_bins(); if (nbins == 1) return; - // reallocate per-bin memory if needed - - if (nbins > maxbin) { - memory->sfree(binhead); - maxbin = nbins; - binhead = (int *) memory->smalloc(maxbin*sizeof(int),"sort:binhead"); - } - - // reallocate per-atom memory if needed + // reallocate per-atom vectors if needed if (nlocal > maxnext) { memory->sfree(next); @@ -1380,9 +1360,9 @@ void Atom::sort() for (i = 0; i < nbins; i++) binhead[i] = -1; for (i = nlocal-1; i >= 0; i--) { - ix = static_cast<int> ((x[i][0]-sublo[0])*bininv); - iy = static_cast<int> ((x[i][1]-sublo[1])*bininv); - iz = static_cast<int> ((x[i][2]-sublo[2])*bininv); + ix = static_cast<int> ((x[i][0]-bboxlo[0])*bininv); + iy = static_cast<int> ((x[i][1]-bboxlo[1])*bininv); + iz = static_cast<int> ((x[i][2]-bboxlo[2])*bininv); ix = MAX(ix,0); iy = MAX(iy,0); iz = MAX(iz,0); @@ -1433,16 +1413,68 @@ void Atom::sort() // sanity check that current = permute - int flag = 0; - for (i = 0; i < nlocal; i++) - if (current[i] != permute[i]) flag = 1; - int flagall; - MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); - if (flagall) error->all("Atom sort did not operate correctly"); + //int flag = 0; + //for (i = 0; i < nlocal; i++) + // if (current[i] != permute[i]) flag = 1; + //int flagall; + //MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world); + //if (flagall) error->all("Atom sort did not operate correctly"); // set next timestep for sorting to take place - nextsort += sortfreq; + nextsort = (update->ntimestep/sortfreq)*sortfreq + sortfreq; +} + +/* ---------------------------------------------------------------------- + setup bins for spatial sorting of atoms +------------------------------------------------------------------------- */ + +void Atom::setup_sort_bins() +{ + // binsize = user setting or 1/2 of neighbor cutoff + // neighbor cutoff can be 0.0 + + double binsize; + if (userbinsize > 0.0) binsize = userbinsize; + else binsize = 0.5 * neighbor->cutneighmax; + if (binsize == 0.0) error->all("Atom sorting has bin size = 0.0"); + + bininv = 1.0/binsize; + + // nbin xyz = local bins + // bbox lo/hi = bounding box of my sub-domain + + if (domain->triclinic) + domain->bbox(domain->sublo_lamda,domain->subhi_lamda,bboxlo,bboxhi); + else { + bboxlo[0] = domain->sublo[0]; + bboxlo[1] = domain->sublo[1]; + bboxlo[2] = domain->sublo[2]; + bboxhi[0] = domain->subhi[0]; + bboxhi[1] = domain->subhi[1]; + bboxhi[2] = domain->subhi[2]; + } + + nbinx = static_cast<int> ((bboxhi[0]-bboxlo[0]) * bininv); + nbiny = static_cast<int> ((bboxhi[1]-bboxlo[1]) * bininv); + nbinz = static_cast<int> ((bboxhi[2]-bboxlo[2]) * bininv); + + nbinx = MAX(nbinx,1); + nbinx = MAX(nbiny,1); + nbinx = MAX(nbinz,1); + + if (1.0*nbinx*nbiny*nbinz > INT_MAX) + error->one("Too many atom sorting bins"); + + nbins = nbinx*nbiny*nbinz; + + // reallocate per-bin memory if needed + + if (nbins > maxbin) { + memory->sfree(binhead); + maxbin = nbins; + binhead = (int *) memory->smalloc(maxbin*sizeof(int),"atom:binhead"); + } } /* ---------------------------------------------------------------------- diff --git a/src/atom.h b/src/atom.h index 0ee3608e1394d76f4acf6bf0c28a26963d83e9d7..f54dd890411546a8e963fa92b57d24b44b574dab 100644 --- a/src/atom.h +++ b/src/atom.h @@ -196,16 +196,21 @@ class Atom : protected Pointers { // spatial sorting of atoms - int maxbin; // # of bins memory is allocated for + int nbins; // # of sorting bins + int nbinx,nbiny,nbinz; // bins in each dimension + int maxbin; // max # of bins int maxnext; // max size of next,permute int *binhead; // 1st atom in each bin int *next; // next atom in bin int *permute; // permutation vector double userbinsize; // sorting bin size double bininv; + double bboxlo[3],bboxhi[3]; // bounding box of my sub-domain int memlength; // allocated size of memstr char *memstr; // string of array names already counted + + void setup_sort_bins(); }; } diff --git a/src/min.cpp b/src/min.cpp index 2df35433f129ba05799f4dd008283f565c12a791..4bd825050850c0b2fbcf1320af1aba9acc7fb84c 100644 --- a/src/min.cpp +++ b/src/min.cpp @@ -203,12 +203,14 @@ void Min::setup() // acquire ghosts // build neighbor lists + atom->setup(); if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); comm->exchange(); + if (atom->sortfreq > 0) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); neighbor->build(); @@ -407,6 +409,8 @@ double Min::energy_force(int resetflag) } timer->stamp(); comm->exchange(); + if (atom->sortfreq > 0 && + update->ntimestep >= atom->nextsort) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); timer->stamp(TIME_COMM); diff --git a/src/neighbor.cpp b/src/neighbor.cpp index f3aed41f557bc30fae34cfa872f0665d873fc89f..1aa2743687f6045ab5aab365618b13f56c58968a 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -1255,6 +1255,8 @@ void Neighbor::setup_bins() // memory for bin ptrs + if (1.0*mbinx*mbiny*mbinz > INT_MAX) error->one("Too many neighbor bins"); + mbins = mbinx*mbiny*mbinz; if (mbins > maxhead) { maxhead = mbins; diff --git a/src/respa.cpp b/src/respa.cpp index 01bfdb35d9769b75b978090908cdf8965acf3345..8d89cbbe13b78ddc1f7c6fd0182a5ac5f5f6697b 100644 --- a/src/respa.cpp +++ b/src/respa.cpp @@ -316,12 +316,14 @@ void Respa::setup() // acquire ghosts // build neighbor lists + atom->setup(); if (triclinic) domain->x2lamda(atom->nlocal); domain->pbc(); domain->reset_box(); comm->setup(); if (neighbor->style) neighbor->setup_bins(); comm->exchange(); + if (atom->sortfreq > 0) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); neighbor->build(); @@ -503,6 +505,8 @@ void Respa::recurse(int ilevel) } timer->stamp(); comm->exchange(); + if (atom->sortfreq > 0 && + update->ntimestep >= atom->nextsort) atom->sort(); comm->borders(); if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost); timer->stamp(TIME_COMM);