Renamed to multi2, initial stencil edits

This commit is contained in:
Joel Clemmer
2020-11-10 16:39:56 -07:00
parent 12288630f5
commit 943a187be7
35 changed files with 845 additions and 702 deletions

View File

@ -76,7 +76,7 @@ Comm::Comm(LAMMPS *lmp) : Pointers(lmp)
grid2proc = nullptr;
xsplit = ysplit = zsplit = nullptr;
rcbnew = 0;
multi_tiered = 0;
multi2 = 0;
// use of OpenMP threads
// query OpenMP for number of threads/process set by user at run-time
@ -242,9 +242,9 @@ void Comm::init()
for (int i = 0; i < nfix; i++)
if (fix[i]->maxexchange_dynamic) maxexchange_fix_dynamic = 1;
// Can't used multi/tiered communication with Newton off
if (force->newton == 0 && multi_tiered)
error->all(FLERR,"Cannot use multi/tiered communication with Newton off");
// Can't used multi2 communication with Newton off
if (force->newton == 0 && multi2)
error->all(FLERR,"Cannot use multi2 communication with Newton off");
}
/* ----------------------------------------------------------------------
@ -331,10 +331,10 @@ void Comm::modify_params(int narg, char **arg)
for (i=nlo; i<=nhi; ++i)
cutusermulti[i] = cut;
iarg += 3;
} else if (strcmp(arg[iarg],"cutoff/tiered") == 0) {
} else if (strcmp(arg[iarg],"cutoff/multi2") == 0) {
if (mode == Comm::SINGLE)
error->all(FLERR,"Use cutoff/tiered in mode multi only");
multi_tiered = 1;
error->all(FLERR,"Use cutoff/multi2 in mode multi only");
multi2 = 1;
iarg += 1;
} else if (strcmp(arg[iarg],"vel") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal comm_modify command");

View File

@ -161,7 +161,7 @@ class Comm : protected Pointers {
int (*)(int, char *, int &, int *&, char *&, void *),
int, char *&, int, void *, int);
void rendezvous_stats(int, int, int, int, int, int, bigint);
int multi_tiered; // 1 if multi cutoff is intra-type cutoff
int multi2; // 1 if multi cutoff is intra-type cutoff
public:
enum{MULTIPLE};

View File

@ -174,8 +174,8 @@ void CommBrick::setup()
cutghost[0] = cutghost[1] = cutghost[2] = cut;
if (mode == Comm::MULTI) {
if (multi_tiered) {
// If using tiered binlists, use the itype-itype interaction distance for communication
if (multi2) {
// If using multi2 binlists, use the itype-itype interaction distance for communication
double **cutneighsq = neighbor->cutneighsq;
for (i = 1; i <= ntypes; i++) {
cut = 0.0;

View File

@ -176,8 +176,8 @@ void CommTiled::setup()
if (mode == Comm::MULTI) {
double cut;
if (multi_tiered) {
// If using tiered binlists, use the itype-itype interaction distance for communication
if (multi2) {
// If using multi2 binlists, use the itype-itype interaction distance for communication
double **cutneighsq = neighbor->cutneighsq;
for (i = 1; i <= ntypes; i++) {
cut = 0.0;

View File

@ -31,6 +31,21 @@ NBin::NBin(LAMMPS *lmp) : Pointers(lmp)
bins = nullptr;
atom2bin = nullptr;
nbinx_tiered = nullptr; nbiny_tiered = nullptr; nbinz_tiered = nullptr;
mbins_tiered = nullptr;
mbinx_tiered = nullptr; mbiny_tiered = nullptr, mbinz_tiered = nullptr;
mbinxlo_tiered = nullptr;
mbinylo_tiered = nullptr;
mbinzlo_tiered = nullptr;
binsizex_tiered = nullptr; binsizey_tiered = nullptr; binsizez_tiered = nullptr;
bininvx_tiered = nullptr; bininvy_tiered = nullptr; bininvz_tiered = nullptr;
binhead_tiered = nullptr;
bins_tiered = nullptr;
atom2bin_tiered = nullptr;
maxbins_tiered = nullptr;
maxtypes = 0;
neighbor->last_setup_bins = -1;
// geometry settings
@ -48,6 +63,37 @@ NBin::~NBin()
memory->destroy(binhead);
memory->destroy(bins);
memory->destroy(atom2bin);
if (!bins_tiered) return;
memory->destroy(nbinx_tiered);
memory->destroy(nbiny_tiered);
memory->destroy(nbinz_tiered);
memory->destroy(mbins_tiered);
memory->destroy(mbinx_tiered);
memory->destroy(mbiny_tiered);
memory->destroy(mbinz_tiered);
memory->destroy(mbinxlo_tiered);
memory->destroy(mbinylo_tiered);
memory->destroy(mbinzlo_tiered);
memory->destroy(binsizex_tiered);
memory->destroy(binsizey_tiered);
memory->destroy(binsizez_tiered);
memory->destroy(bininvx_tiered);
memory->destroy(bininvy_tiered);
memory->destroy(bininvz_tiered);
for (int n = 1; n <= maxtypes; n++) {
memory->destroy(binhead_tiered[n]);
memory->destroy(bins_tiered[n]);
memory->destroy(atom2bin_tiered[n]);
}
delete [] binhead_tiered;
delete [] bins_tiered;
delete [] atom2bin_tiered;
memory->destroy(maxbins_tiered);
}
/* ---------------------------------------------------------------------- */
@ -77,95 +123,3 @@ void NBin::copy_neighbor_info()
if (cutoff_custom > 0.0) cutneighmax = cutoff_custom;
}
/* ----------------------------------------------------------------------
setup for bin_atoms()
------------------------------------------------------------------------- */
void NBin::bin_atoms_setup(int nall)
{
// binhead = per-bin vector, mbins in length
// add 1 bin for USER-INTEL package
if (mbins > maxbin) {
maxbin = mbins;
memory->destroy(binhead);
memory->create(binhead,maxbin,"neigh:binhead");
}
// bins and atom2bin = per-atom vectors
// for both local and ghost atoms
if (nall > maxatom) {
maxatom = nall;
memory->destroy(bins);
memory->create(bins,maxatom,"neigh:bins");
memory->destroy(atom2bin);
memory->create(atom2bin,maxatom,"neigh:atom2bin");
}
}
/* ----------------------------------------------------------------------
convert atom coords into local bin #
for orthogonal, only ghost atoms will have coord >= bboxhi or coord < bboxlo
take special care to insure ghosts are in correct bins even w/ roundoff
hi ghost atoms = nbin,nbin+1,etc
owned atoms = 0 to nbin-1
lo ghost atoms = -1,-2,etc
this is necessary so that both procs on either side of PBC
treat a pair of atoms straddling the PBC in a consistent way
for triclinic, doesn't matter since stencil & neigh list built differently
------------------------------------------------------------------------- */
int NBin::coord2bin(double *x)
{
int ix,iy,iz;
if (!std::isfinite(x[0]) || !std::isfinite(x[1]) || !std::isfinite(x[2]))
error->one(FLERR,"Non-numeric positions - simulation unstable");
if (x[0] >= bboxhi[0])
ix = static_cast<int> ((x[0]-bboxhi[0])*bininvx) + nbinx;
else if (x[0] >= bboxlo[0]) {
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx);
ix = MIN(ix,nbinx-1);
} else
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx) - 1;
if (x[1] >= bboxhi[1])
iy = static_cast<int> ((x[1]-bboxhi[1])*bininvy) + nbiny;
else if (x[1] >= bboxlo[1]) {
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy);
iy = MIN(iy,nbiny-1);
} else
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy) - 1;
if (x[2] >= bboxhi[2])
iz = static_cast<int> ((x[2]-bboxhi[2])*bininvz) + nbinz;
else if (x[2] >= bboxlo[2]) {
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz);
iz = MIN(iz,nbinz-1);
} else
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz) - 1;
return (iz-mbinzlo)*mbiny*mbinx + (iy-mbinylo)*mbinx + (ix-mbinxlo);
}
/* ----------------------------------------------------------------------
to be overridden by NBinType
------------------------------------------------------------------------- */
int NBin::coord2bin(double * x, int itype)
{
error->all(FLERR,"coord2bin(x, itype) not available.\n");
return -1;
}
/* ---------------------------------------------------------------------- */
double NBin::memory_usage()
{
double bytes = 0;
bytes += maxbin*sizeof(int);
bytes += 2*maxatom*sizeof(int);
return bytes;
}

View File

@ -22,6 +22,9 @@ class NBin : protected Pointers {
public:
int istyle; // 1-N index into binnames
bigint last_bin; // last timestep atoms were binned
double cutoff_custom; // cutoff set by requestor
// Variables for NBinStandard
int nbinx,nbiny,nbinz; // # of global bins
int mbins; // # of local bins and offset on this proc
@ -35,35 +38,32 @@ class NBin : protected Pointers {
int *bins; // index of next atom in same bin
int *atom2bin; // bin assignment for each atom (local+ghost)
double cutoff_custom; // cutoff set by requestor
// Analogues for NBinMultimulti2
// Analogues for NBinType
int * nbinx_type, * nbiny_type, * nbinz_type;
int * mbins_type;
int * mbinx_type, * mbiny_type, * mbinz_type;
int * mbinxlo_type, * mbinylo_type, * mbinzlo_type;
double * binsizex_type, * binsizey_type, * binsizez_type;
double * bininvx_type, * bininvy_type, * bininvz_type;
int *nbinx_multi2, *nbiny_multi2, *nbinz_multi2;
int *mbins_multi2;
int *mbinx_multi2, *mbiny_multi2, *mbinz_multi2;
int *mbinxlo_multi2, *mbinylo_multi2, *mbinzlo_multi2;
double *binsizex_multi2, *binsizey_multi2, *binsizez_multi2;
double *bininvx_multi2, *bininvy_multi2, *bininvz_multi2;
int ** binhead_type;
int ** bins_type;
int ** atom2bin_type;
int **binhead_multi2;
int **bins_multi2;
int **atom2bin_multi2;
NBin(class LAMMPS *);
~NBin();
void post_constructor(class NeighRequest *);
virtual void copy_neighbor_info();
virtual void bin_atoms_setup(int);
double memory_usage();
virtual void bin_atoms_setup(int) = 0;
virtual void setup_bins(int) = 0;
virtual void bin_atoms() = 0;
virtual double memory_usage() {return 0.0;}
// Kokkos package
int kokkos; // 1 if class stores Kokkos data
// For NBinType
virtual int coord2bin(double *, int);
protected:
@ -81,12 +81,23 @@ class NBin : protected Pointers {
int dimension;
int triclinic;
int maxbin; // size of binhead array
// data for standard NBin
int maxatom; // size of bins array
// data for standard NBin
int maxbin; // size of binhead array
// data for multi/multi2 NBin
int maxtypes; // size of multi2 arrays
int * maxbins_multi2; // size of 2nd dimension of binhead_multi2 array
// methods
int coord2bin(double *);
int coord2bin(double *, int);
};
}

414
src/nbin_multi2.cpp Normal file
View File

@ -0,0 +1,414 @@
/* ----------------------------------------------------------------------
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 "nbin_multi2.h"
#include "neighbor.h"
#include "atom.h"
#include "group.h"
#include "domain.h"
#include "comm.h"
#include "update.h"
#include "error.h"
#include "memory.h"
using namespace LAMMPS_NS;
#define SMALL 1.0e-6
#define CUT2BIN_RATIO 100
/* ---------------------------------------------------------------------- */
NBinMulti2::NBinMulti2(LAMMPS *lmp) : NBin(lmp) {}
/* ----------------------------------------------------------------------
setup for bin_atoms()
------------------------------------------------------------------------- */
void NBinMulti2::bin_atoms_setup(int nall)
{
// binhead_multi2[n] = per-bin vector mbins in length mbins_multi2[n]
for (int n = 1; n <= maxtypes; n++) {
if (mbins_multi2[n] > maxbins_multi2[n]) {
maxbins_multi2[n] = mbins_multi2[n];
memory->destroy(binhead_multi2[n]);
memory->create(binhead_multi2[n], mbins_multi2[n], "neigh:mbins_multi2");
}
}
// bins_multi2[n] and atom2bin_multi2[n] = per-atom vectors
// for both local and ghost atoms
if (nall > maxatom) {
maxatom = nall;
for (int n = 1; n <= maxtypes; n++) {
memory->destroy(bins_multi2[n]);
memory->destroy(atom2bin_multi2[n]);
memory->create(bins_multi2[n], maxatom, "neigh:bin_multi2");
memory->create(atom2bin_multi2[n], maxatom, "neigh:atom2bin_multi2");
}
}
}
/* ---------------------------------------------------------------------
Identify index of type with smallest cutoff
------------------------------------------------------------------------ */
int NBinMulti2::itype_min() {
int itypemin = 1;
double ** cutneighsq;
cutneighsq = neighbor->cutneighsq;
for (int n = 1; n <= atom->ntypes; n++) {
if (cutneighsq[n][n] < cutneighsq[itypemin][itypemin]) {
itypemin = n;
}
}
return itypemin;
}
/* ----------------------------------------------------------------------
setup neighbor binning geometry
---------------------------------------------------------------------- */
void NBinMulti2::setup_bins(int style)
{
int n;
int itypemin;
// Initialize arrays
if (atom->ntypes > maxtypes) {
// Clear any/all memory for existing types
for (n = 1; n <= maxtypes; n++) {
memory->destroy(atom2bin_multi2[n]);
memory->destroy(binhead_multi2[n]);
memory->destroy(bins_multi2[n]);
}
delete [] atom2bin_multi2;
delete [] binhead_multi2;
delete [] bins_multi2;
// Realloacte at updated maxtypes
maxtypes = atom->ntypes;
atom2bin_multi2 = new int*[maxtypes+1]();
binhead_multi2 = new int*[maxtypes+1]();
bins_multi2 = new int*[maxtypes+1]();
memory->destroy(nbinx_multi2);
memory->destroy(nbiny_multi2);
memory->destroy(nbinz_multi2);
memory->create(nbinx_multi2, maxtypes+1, "neigh:nbinx_multi2");
memory->create(nbiny_multi2, maxtypes+1, "neigh:nbiny_multi2");
memory->create(nbinz_multi2, maxtypes+1, "neigh:nbinz_multi2");
memory->destroy(mbins_multi2);
memory->destroy(mbinx_multi2);
memory->destroy(mbiny_multi2);
memory->destroy(mbinz_multi2);
memory->create(mbins_multi2, maxtypes+1, "neigh:mbins_multi2");
memory->create(mbinx_multi2, maxtypes+1, "neigh:mbinx_multi2");
memory->create(mbiny_multi2, maxtypes+1, "neigh:mbiny_multi2");
memory->create(mbinz_multi2, maxtypes+1, "neigh:mbinz_multi2");
memory->destroy(mbinxlo_multi2);
memory->destroy(mbinylo_multi2);
memory->destroy(mbinzlo_multi2);
memory->create(mbinxlo_multi2, maxtypes+1, "neigh:mbinxlo_multi2");
memory->create(mbinylo_multi2, maxtypes+1, "neigh:mbinylo_multi2");
memory->create(mbinzlo_multi2, maxtypes+1, "neigh:mbinzlo_multi2");
memory->destroy(binsizex_multi2);
memory->destroy(binsizey_multi2);
memory->destroy(binsizez_multi2);
memory->create(binsizex_multi2, maxtypes+1, "neigh:binsizex_multi2");
memory->create(binsizey_multi2, maxtypes+1, "neigh:binsizey_multi2");
memory->create(binsizez_multi2, maxtypes+1, "neigh:binsizez_multi2");
memory->destroy(bininvx_multi2);
memory->destroy(bininvy_multi2);
memory->destroy(bininvz_multi2);
memory->create(bininvx_multi2, maxtypes+1, "neigh:bininvx_multi2");
memory->create(bininvy_multi2, maxtypes+1, "neigh:bininvy_multi2");
memory->create(bininvz_multi2, maxtypes+1, "neigh:bininvz_multi2");
memory->destroy(maxbins_multi2);
memory->create(maxbins_multi2, maxtypes+1, "neigh:maxbins_multi2");
// make sure reallocation occurs in bin_atoms_setup()
for (n = 1; n <= maxtypes; n++) {
maxbins_multi2[n] = 0;
}
maxatom = 0;
}
itypemin = itype_min();
// bbox = size of bbox of entire domain
// bsubbox lo/hi = bounding box of my subdomain extended by comm->cutghost
// for triclinic:
// bbox bounds all 8 corners of tilted box
// subdomain is in lamda coords
// include dimension-dependent extension via comm->cutghost
// domain->bbox() converts lamda extent to box coords and computes bbox
double bbox[3],bsubboxlo[3],bsubboxhi[3];
double *cutghost = comm->cutghost;
if (triclinic == 0) {
bsubboxlo[0] = domain->sublo[0] - cutghost[0];
bsubboxlo[1] = domain->sublo[1] - cutghost[1];
bsubboxlo[2] = domain->sublo[2] - cutghost[2];
bsubboxhi[0] = domain->subhi[0] + cutghost[0];
bsubboxhi[1] = domain->subhi[1] + cutghost[1];
bsubboxhi[2] = domain->subhi[2] + cutghost[2];
} else {
double lo[3],hi[3];
lo[0] = domain->sublo_lamda[0] - cutghost[0];
lo[1] = domain->sublo_lamda[1] - cutghost[1];
lo[2] = domain->sublo_lamda[2] - cutghost[2];
hi[0] = domain->subhi_lamda[0] + cutghost[0];
hi[1] = domain->subhi_lamda[1] + cutghost[1];
hi[2] = domain->subhi_lamda[2] + cutghost[2];
domain->bbox(lo,hi,bsubboxlo,bsubboxhi);
}
bbox[0] = bboxhi[0] - bboxlo[0];
bbox[1] = bboxhi[1] - bboxlo[1];
bbox[2] = bboxhi[2] - bboxlo[2];
// For each type...
for (n = 1; n <= atom->ntypes; n++) {
// binsize_user only relates to smallest type
// optimal bin size is roughly 1/2 the type-type cutoff
// special case of all cutoffs = 0.0, binsize = box size
double binsize_optimal;
if (n == itypemin && binsizeflag) binsize_optimal = binsize_user;
else binsize_optimal = 0.5*sqrt(neighbor->cutneighsq[n][n]);
if (binsize_optimal == 0.0) binsize_optimal = bbox[0];
double binsizeinv = 1.0/binsize_optimal;
// test for too many global bins in any dimension due to huge global domain
if (bbox[0]*binsizeinv > MAXSMALLINT || bbox[1]*binsizeinv > MAXSMALLINT ||
bbox[2]*binsizeinv > MAXSMALLINT)
error->all(FLERR,"Domain too large for neighbor bins");
// create actual bins
// always have one bin even if cutoff > bbox
// for 2d, nbinz_multi2[n] = 1
nbinx_multi2[n] = static_cast<int> (bbox[0]*binsizeinv);
nbiny_multi2[n] = static_cast<int> (bbox[1]*binsizeinv);
if (dimension == 3) nbinz_multi2[n] = static_cast<int> (bbox[2]*binsizeinv);
else nbinz_multi2[n] = 1;
if (nbinx_multi2[n] == 0) nbinx_multi2[n] = 1;
if (nbiny_multi2[n] == 0) nbiny_multi2[n] = 1;
if (nbinz_multi2[n] == 0) nbinz_multi2[n] = 1;
// compute actual bin size for nbins to fit into box exactly
// error if actual bin size << cutoff, since will create a zillion bins
// this happens when nbin = 1 and box size << cutoff
// typically due to non-periodic, flat system in a particular dim
// in that extreme case, should use NSQ not BIN neighbor style
binsizex_multi2[n] = bbox[0]/nbinx_multi2[n];
binsizey_multi2[n] = bbox[1]/nbiny_multi2[n];
binsizez_multi2[n] = bbox[2]/nbinz_multi2[n];
bininvx_multi2[n] = 1.0 / binsizex_multi2[n];
bininvy_multi2[n] = 1.0 / binsizey_multi2[n];
bininvz_multi2[n] = 1.0 / binsizez_multi2[n];
if (binsize_optimal*bininvx_multi2[n] > CUT2BIN_RATIO ||
binsize_optimal*bininvy_multi2[n] > CUT2BIN_RATIO ||
binsize_optimal*bininvz_multi2[n] > CUT2BIN_RATIO)
error->all(FLERR,"Cannot use neighbor bins - box size << cutoff");
// mbinlo/hi = lowest and highest global bins my ghost atoms could be in
// coord = lowest and highest values of coords for my ghost atoms
// static_cast(-1.5) = -1, so subract additional -1
// add in SMALL for round-off safety
int mbinxhi,mbinyhi,mbinzhi;
double coord;
coord = bsubboxlo[0] - SMALL*bbox[0];
mbinxlo_multi2[n] = static_cast<int> ((coord-bboxlo[0])*bininvx_multi2[n]);
if (coord < bboxlo[0]) mbinxlo_multi2[n] = mbinxlo_multi2[n] - 1;
coord = bsubboxhi[0] + SMALL*bbox[0];
mbinxhi = static_cast<int> ((coord-bboxlo[0])*bininvx_multi2[n]);
coord = bsubboxlo[1] - SMALL*bbox[1];
mbinylo_multi2[n] = static_cast<int> ((coord-bboxlo[1])*bininvy_multi2[n]);
if (coord < bboxlo[1]) mbinylo_multi2[n] = mbinylo_multi2[n] - 1;
coord = bsubboxhi[1] + SMALL*bbox[1];
mbinyhi = static_cast<int> ((coord-bboxlo[1])*bininvy_multi2[n]);
if (dimension == 3) {
coord = bsubboxlo[2] - SMALL*bbox[2];
mbinzlo_multi2[n] = static_cast<int> ((coord-bboxlo[2])*bininvz_multi2[n]);
if (coord < bboxlo[2]) mbinzlo_multi2[n] = mbinzlo_multi2[n] - 1;
coord = bsubboxhi[2] + SMALL*bbox[2];
mbinzhi = static_cast<int> ((coord-bboxlo[2])*bininvz_multi2[n]);
}
// extend bins by 1 to insure stencil extent is included
// for 2d, only 1 bin in z
mbinxlo_multi2[n] = mbinxlo_multi2[n] - 1;
mbinxhi = mbinxhi + 1;
mbinx_multi2[n] = mbinxhi - mbinxlo_multi2[n] + 1;
mbinylo_multi2[n] = mbinylo_multi2[n] - 1;
mbinyhi = mbinyhi + 1;
mbiny_multi2[n] = mbinyhi - mbinylo_multi2[n] + 1;
if (dimension == 3) {
mbinzlo_multi2[n] = mbinzlo_multi2[n] - 1;
mbinzhi = mbinzhi + 1;
} else mbinzlo_multi2[n] = mbinzhi = 0;
mbinz_multi2[n] = mbinzhi - mbinzlo_multi2[n] + 1;
bigint bbin = ((bigint) mbinx_multi2[n])
* ((bigint) mbiny_multi2[n]) * ((bigint) mbinz_multi2[n]) + 1;
if (bbin > MAXSMALLINT) error->one(FLERR,"Too many neighbor bins");
mbins_multi2[n] = bbin;
}
}
/* ----------------------------------------------------------------------
bin owned and ghost atoms by type
------------------------------------------------------------------------- */
void NBinMulti2::bin_atoms()
{
int i,ibin,n;
last_bin = update->ntimestep;
for (n = 1; n <= maxtypes; n++) {
for (i = 0; i < mbins_multi2[n]; i++) binhead_multi2[n][i] = -1;
}
// bin in reverse order so linked list will be in forward order
// also puts ghost atoms at end of list, which is necessary
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (includegroup) {
int bitmask = group->bitmask[includegroup];
for (i = nall-1; i >= nlocal; i--) {
if (mask[i] & bitmask) {
n = type[i];
ibin = coord2bin(x[i], n);
atom2bin_multi2[n][i] = ibin;
bins_multi2[n][i] = binhead_multi2[n][ibin];
binhead_multi2[n][ibin] = i;
}
}
for (i = atom->nfirst-1; i >= 0; i--) {
n = type[i];
ibin = coord2bin(x[i], n);
atom2bin_multi2[n][i] = ibin;
bins_multi2[n][i] = binhead_multi2[n][ibin];
binhead_multi2[n][ibin] = i;
}
} else {
for (i = nall-1; i >= 0; i--) {
n = type[i];
ibin = coord2bin(x[i], n);
atom2bin_multi2[n][i] = ibin;
bins_multi2[n][i] = binhead_multi2[n][ibin];
binhead_multi2[n][ibin] = i;
}
}
}
/* ----------------------------------------------------------------------
convert atom coords into local bin # for a particular type
for orthogonal, only ghost atoms will have coord >= bboxhi or coord < bboxlo
take special care to insure ghosts are in correct bins even w/ roundoff
hi ghost atoms = nbin,nbin+1,etc
owned atoms = 0 to nbin-1
lo ghost atoms = -1,-2,etc
this is necessary so that both procs on either side of PBC
treat a pair of atoms straddling the PBC in a consistent way
for triclinic, doesn't matter since stencil & neigh list built differently
------------------------------------------------------------------------- */
int NBinMulti2::coord2bin(double *x, int it)
{
int ix,iy,iz;
int ibin;
if (!std::isfinite(x[0]) || !std::isfinite(x[1]) || !std::isfinite(x[2]))
error->one(FLERR,"Non-numeric positions - simulation unstable");
if (x[0] >= bboxhi[0])
ix = static_cast<int> ((x[0]-bboxhi[0])*bininvx_multi2[it]) + nbinx_multi2[it];
else if (x[0] >= bboxlo[0]) {
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx_multi2[it]);
ix = MIN(ix,nbinx_multi2[it]-1);
} else
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx_multi2[it]) - 1;
if (x[1] >= bboxhi[1])
iy = static_cast<int> ((x[1]-bboxhi[1])*bininvy_multi2[it]) + nbiny_multi2[it];
else if (x[1] >= bboxlo[1]) {
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy_multi2[it]);
iy = MIN(iy,nbiny_multi2[it]-1);
} else
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy_multi2[it]) - 1;
if (x[2] >= bboxhi[2])
iz = static_cast<int> ((x[2]-bboxhi[2])*bininvz_multi2[it]) + nbinz_multi2[it];
else if (x[2] >= bboxlo[2]) {
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz_multi2[it]);
iz = MIN(iz,nbinz_multi2[it]-1);
} else
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz_multi2[it]) - 1;
ibin = (iz-mbinzlo_multi2[it])*mbiny_multi2[it]*mbinx_multi2[it]
+ (iy-mbinylo_multi2[it])*mbinx_multi2[it]
+ (ix-mbinxlo_multi2[it]);
return ibin;
}
/* ---------------------------------------------------------------------- */
double NBinMulti2::memory_usage()
{
double bytes = 0;
for (int m = 1; m < maxtypes; m++) {
bytes += maxbins_multi2[m]*sizeof(int);
bytes += 2*maxatom*sizeof(int);
}
return bytes;
}

View File

@ -13,36 +13,32 @@
#ifdef NBIN_CLASS
NBinStyle(bytype,
NBinBytype,
NB_BYTYPE)
NBinStyle(multi2,
NBinMulti2,
NB_MULTI2)
#else
#ifndef LMP_NBIN_BYTYPE_H
#define LMP_NBIN_BYTYPE_H
#ifndef LMP_NBIN_MULTI2_H
#define LMP_NBIN_MULTI2_H
#include "nbin.h"
namespace LAMMPS_NS {
class NBinBytype : public NBin {
class NBinMulti2 : public NBin {
public:
NBinBytype(class LAMMPS *);
~NBinBytype();
NBinMulti2(class LAMMPS *);
~NBinMulti2() {}
void bin_atoms_setup(int);
void setup_bins(int);
void bin_atoms();
int coord2bin(double *x, int itype);
bigint memory_usage();
double memory_usage();
private:
int maxtypes;
int * maxbins_type;
void setup_types();
int coord2bin(double *, int);
int itype_min();
};

View File

@ -1,464 +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 "nbin_bytype.h"
#include "neighbor.h"
#include "atom.h"
#include "group.h"
#include "domain.h"
#include "comm.h"
#include "update.h"
#include "error.h"
#include "memory.h"
using namespace LAMMPS_NS;
#define SMALL 1.0e-6
#define CUT2BIN_RATIO 100
/* ---------------------------------------------------------------------- */
NBinBytype::NBinBytype(LAMMPS *lmp) : NBin(lmp) {
nbinx_type = NULL; nbiny_type = NULL; nbinz_type = NULL;
mbins_type = NULL;
mbinx_type = NULL; mbiny_type = NULL, mbinz_type = NULL;
mbinxlo_type = NULL;
mbinylo_type = NULL;
mbinzlo_type = NULL;
binsizex_type = NULL; binsizey_type = NULL; binsizez_type = NULL;
bininvx_type = NULL; bininvy_type = NULL; bininvz_type = NULL;
binhead_type = NULL;
bins_type = NULL;
atom2bin_type = NULL;
maxtypes = 0;
maxbins_type = NULL;
}
NBinBytype::~NBinBytype() {
memory->destroy(nbinx_type);
memory->destroy(nbiny_type);
memory->destroy(nbinz_type);
memory->destroy(mbins_type);
memory->destroy(mbinx_type);
memory->destroy(mbiny_type);
memory->destroy(mbinz_type);
memory->destroy(mbinxlo_type);
memory->destroy(mbinylo_type);
memory->destroy(mbinzlo_type);
memory->destroy(binsizex_type);
memory->destroy(binsizey_type);
memory->destroy(binsizez_type);
memory->destroy(bininvx_type);
memory->destroy(bininvy_type);
memory->destroy(bininvz_type);
for (int n = 1; n <= maxtypes; n++) {
memory->destroy(binhead_type[n]);
memory->destroy(bins_type[n]);
memory->destroy(atom2bin_type[n]);
}
delete [] binhead_type;
delete [] bins_type;
delete [] atom2bin_type;
memory->destroy(maxbins_type);
}
/* ----------------------------------------------------------------------
arrange storage for types
allows ntypes to change, but not currently expected after initialisation
------------------------------------------------------------------------- */
void NBinBytype::setup_types() {
int n;
if (atom->ntypes > maxtypes) {
// Clear any/all memory for existing types
for (n = 1; n <= maxtypes; n++) {
memory->destroy(atom2bin_type[n]);
memory->destroy(binhead_type[n]);
memory->destroy(bins_type[n]);
}
delete [] atom2bin_type;
delete [] binhead_type;
delete [] bins_type;
// Realloacte at updated maxtypes
maxtypes = atom->ntypes;
atom2bin_type = new int*[maxtypes+1]();
binhead_type = new int*[maxtypes+1]();
bins_type = new int*[maxtypes+1]();
memory->destroy(nbinx_type);
memory->destroy(nbiny_type);
memory->destroy(nbinz_type);
memory->create(nbinx_type, maxtypes+1, "nBinType:nbinx_type");
memory->create(nbiny_type, maxtypes+1, "nBinType:nbiny_type");
memory->create(nbinz_type, maxtypes+1, "nBinType:nbinz_type");
memory->destroy(mbins_type);
memory->destroy(mbinx_type);
memory->destroy(mbiny_type);
memory->destroy(mbinz_type);
memory->create(mbins_type, maxtypes+1, "nBinType:mbins_type");
memory->create(mbinx_type, maxtypes+1, "nBinType:mbinx_type");
memory->create(mbiny_type, maxtypes+1, "nBinType:mbiny_type");
memory->create(mbinz_type, maxtypes+1, "nBinType:mbinz_type");
memory->destroy(mbinxlo_type);
memory->destroy(mbinylo_type);
memory->destroy(mbinzlo_type);
memory->create(mbinxlo_type, maxtypes+1, "nBinType:mbinxlo_type");
memory->create(mbinylo_type, maxtypes+1, "nBinType:mbinylo_type");
memory->create(mbinzlo_type, maxtypes+1, "nBinType:mbinzlo_type");
memory->destroy(binsizex_type);
memory->destroy(binsizey_type);
memory->destroy(binsizez_type);
memory->create(binsizex_type, maxtypes+1, "nBinType:binsizex_type");
memory->create(binsizey_type, maxtypes+1, "nBinType:binsizey_type");
memory->create(binsizez_type, maxtypes+1, "nBinType:binsizez_type");
memory->destroy(bininvx_type);
memory->destroy(bininvy_type);
memory->destroy(bininvz_type);
memory->create(bininvx_type, maxtypes+1, "nBinType:bininvx_type");
memory->create(bininvy_type, maxtypes+1, "nBinType:bininvy_type");
memory->create(bininvz_type, maxtypes+1, "nBinType:bininvz_type");
memory->destroy(maxbins_type);
memory->create(maxbins_type, maxtypes+1, "nBinType:maxbins_type");
// make sure reallocation occurs in bin_atoms_setup()
for (n = 1; n <= maxtypes; n++) {
maxbins_type[n] = 0;
}
maxatom = 0;
}
}
/* ---------------------------------------------------------------------
identify index of type with smallest cutoff
--------------------------------------------------------------------- */
int NBinBytype::itype_min() {
int itypemin = 1;
double ** cutneighsq;
cutneighsq = neighbor->cutneighsq;
for (int n = 1; n <= atom->ntypes; n++) {
if (cutneighsq[n][n] < cutneighsq[itypemin][itypemin]) {
itypemin = n;
}
}
return itypemin;
}
/* ----------------------------------------------------------------------
setup neighbor binning geometry
---------------------------------------------------------------------- */
void NBinBytype::setup_bins(int style)
{
int n;
int itypemin;
setup_types();
itypemin = itype_min();
// bbox = size of bbox of entire domain
// bsubbox lo/hi = bounding box of my subdomain extended by comm->cutghost
// for triclinic:
// bbox bounds all 8 corners of tilted box
// subdomain is in lamda coords
// include dimension-dependent extension via comm->cutghost
// domain->bbox() converts lamda extent to box coords and computes bbox
double bbox[3],bsubboxlo[3],bsubboxhi[3];
double *cutghost = comm->cutghost;
if (triclinic == 0) {
bsubboxlo[0] = domain->sublo[0] - cutghost[0];
bsubboxlo[1] = domain->sublo[1] - cutghost[1];
bsubboxlo[2] = domain->sublo[2] - cutghost[2];
bsubboxhi[0] = domain->subhi[0] + cutghost[0];
bsubboxhi[1] = domain->subhi[1] + cutghost[1];
bsubboxhi[2] = domain->subhi[2] + cutghost[2];
} else {
double lo[3],hi[3];
lo[0] = domain->sublo_lamda[0] - cutghost[0];
lo[1] = domain->sublo_lamda[1] - cutghost[1];
lo[2] = domain->sublo_lamda[2] - cutghost[2];
hi[0] = domain->subhi_lamda[0] + cutghost[0];
hi[1] = domain->subhi_lamda[1] + cutghost[1];
hi[2] = domain->subhi_lamda[2] + cutghost[2];
domain->bbox(lo,hi,bsubboxlo,bsubboxhi);
}
bbox[0] = bboxhi[0] - bboxlo[0];
bbox[1] = bboxhi[1] - bboxlo[1];
bbox[2] = bboxhi[2] - bboxlo[2];
// For each type...
for (n = 1; n <= atom->ntypes; n++) {
// binsize_user only relates to smallest type
// optimal bin size is roughly 1/2 the type-type cutoff
// special case of all cutoffs = 0.0, binsize = box size
double binsize_optimal;
if (n == itypemin && binsizeflag) binsize_optimal = binsize_user;
else binsize_optimal = 0.5*sqrt(neighbor->cutneighsq[n][n]);
if (binsize_optimal == 0.0) binsize_optimal = bbox[0];
double binsizeinv = 1.0/binsize_optimal;
// test for too many global bins in any dimension due to huge global domain
if (bbox[0]*binsizeinv > MAXSMALLINT || bbox[1]*binsizeinv > MAXSMALLINT ||
bbox[2]*binsizeinv > MAXSMALLINT)
error->all(FLERR,"Domain too large for neighbor bins");
// create actual bins
// always have one bin even if cutoff > bbox
// for 2d, nbinz_type[n] = 1
nbinx_type[n] = static_cast<int> (bbox[0]*binsizeinv);
nbiny_type[n] = static_cast<int> (bbox[1]*binsizeinv);
if (dimension == 3) nbinz_type[n] = static_cast<int> (bbox[2]*binsizeinv);
else nbinz_type[n] = 1;
if (nbinx_type[n] == 0) nbinx_type[n] = 1;
if (nbiny_type[n] == 0) nbiny_type[n] = 1;
if (nbinz_type[n] == 0) nbinz_type[n] = 1;
// compute actual bin size for nbins to fit into box exactly
// error if actual bin size << cutoff, since will create a zillion bins
// this happens when nbin = 1 and box size << cutoff
// typically due to non-periodic, flat system in a particular dim
// in that extreme case, should use NSQ not BIN neighbor style
binsizex_type[n] = bbox[0]/nbinx_type[n];
binsizey_type[n] = bbox[1]/nbiny_type[n];
binsizez_type[n] = bbox[2]/nbinz_type[n];
bininvx_type[n] = 1.0 / binsizex_type[n];
bininvy_type[n] = 1.0 / binsizey_type[n];
bininvz_type[n] = 1.0 / binsizez_type[n];
if (binsize_optimal*bininvx_type[n] > CUT2BIN_RATIO ||
binsize_optimal*bininvy_type[n] > CUT2BIN_RATIO ||
binsize_optimal*bininvz_type[n] > CUT2BIN_RATIO)
error->all(FLERR,"Cannot use neighbor bins - box size << cutoff");
// mbinlo/hi = lowest and highest global bins my ghost atoms could be in
// coord = lowest and highest values of coords for my ghost atoms
// static_cast(-1.5) = -1, so subract additional -1
// add in SMALL for round-off safety
int mbinxhi,mbinyhi,mbinzhi;
double coord;
coord = bsubboxlo[0] - SMALL*bbox[0];
mbinxlo_type[n] = static_cast<int> ((coord-bboxlo[0])*bininvx_type[n]);
if (coord < bboxlo[0]) mbinxlo_type[n] = mbinxlo_type[n] - 1;
coord = bsubboxhi[0] + SMALL*bbox[0];
mbinxhi = static_cast<int> ((coord-bboxlo[0])*bininvx_type[n]);
coord = bsubboxlo[1] - SMALL*bbox[1];
mbinylo_type[n] = static_cast<int> ((coord-bboxlo[1])*bininvy_type[n]);
if (coord < bboxlo[1]) mbinylo_type[n] = mbinylo_type[n] - 1;
coord = bsubboxhi[1] + SMALL*bbox[1];
mbinyhi = static_cast<int> ((coord-bboxlo[1])*bininvy_type[n]);
if (dimension == 3) {
coord = bsubboxlo[2] - SMALL*bbox[2];
mbinzlo_type[n] = static_cast<int> ((coord-bboxlo[2])*bininvz_type[n]);
if (coord < bboxlo[2]) mbinzlo_type[n] = mbinzlo_type[n] - 1;
coord = bsubboxhi[2] + SMALL*bbox[2];
mbinzhi = static_cast<int> ((coord-bboxlo[2])*bininvz_type[n]);
}
// extend bins by 1 to insure stencil extent is included
// for 2d, only 1 bin in z
mbinxlo_type[n] = mbinxlo_type[n] - 1;
mbinxhi = mbinxhi + 1;
mbinx_type[n] = mbinxhi - mbinxlo_type[n] + 1;
mbinylo_type[n] = mbinylo_type[n] - 1;
mbinyhi = mbinyhi + 1;
mbiny_type[n] = mbinyhi - mbinylo_type[n] + 1;
if (dimension == 3) {
mbinzlo_type[n] = mbinzlo_type[n] - 1;
mbinzhi = mbinzhi + 1;
} else mbinzlo_type[n] = mbinzhi = 0;
mbinz_type[n] = mbinzhi - mbinzlo_type[n] + 1;
bigint bbin = ((bigint) mbinx_type[n])
* ((bigint) mbiny_type[n]) * ((bigint) mbinz_type[n]) + 1;
if (bbin > MAXSMALLINT) error->one(FLERR,"Too many neighbor bins");
mbins_type[n] = bbin;
}
}
/* ----------------------------------------------------------------------
bin owned and ghost atoms by type
------------------------------------------------------------------------- */
void NBinBytype::bin_atoms()
{
int i,ibin,n;
last_bin = update->ntimestep;
for (n = 1; n <= maxtypes; n++) {
for (i = 0; i < mbins_type[n]; i++) binhead_type[n][i] = -1;
}
// bin in reverse order so linked list will be in forward order
// also puts ghost atoms at end of list, which is necessary
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (includegroup) {
int bitmask = group->bitmask[includegroup];
for (i = nall-1; i >= nlocal; i--) {
if (mask[i] & bitmask) {
n = type[i];
ibin = coord2bin(x[i], n);
atom2bin_type[n][i] = ibin;
bins_type[n][i] = binhead_type[n][ibin];
binhead_type[n][ibin] = i;
}
}
for (i = atom->nfirst-1; i >= 0; i--) {
n = type[i];
ibin = coord2bin(x[i], n);
atom2bin_type[n][i] = ibin;
bins_type[n][i] = binhead_type[n][ibin];
binhead_type[n][ibin] = i;
}
} else {
for (i = nall-1; i >= 0; i--) {
n = type[i];
ibin = coord2bin(x[i], n);
atom2bin_type[n][i] = ibin;
bins_type[n][i] = binhead_type[n][ibin];
binhead_type[n][ibin] = i;
}
}
}
/* ----------------------------------------------------------------------
allocate/reallocate vectors
------------------------------------------------------------------------- */
void NBinBytype::bin_atoms_setup(int nall) {
// all atom2bin, bins must be of length nall
if (nall > maxatom) {
for (int n = 1; n <= maxtypes; n++) {
memory->destroy(bins_type[n]);
memory->destroy(atom2bin_type[n]);
memory->create(bins_type[n], nall, "NBinBytype:bin_type");
memory->create(atom2bin_type[n], nall, "NBinBytype:atom2bin_type");
}
maxatom = nall;
}
for (int n = 1; n <= maxtypes; n++) {
if (mbins_type[n] > maxbins_type[n]) {
maxbins_type[n] = mbins_type[n];
memory->destroy(binhead_type[n]);
memory->create(binhead_type[n], mbins_type[n], "NBinBytype:mbins_type");
}
}
}
/* ----------------------------------------------------------------------
convert atom coords into local bin # for bin type it
------------------------------------------------------------------------- */
int NBinBytype::coord2bin(double *x, int it)
{
int ix,iy,iz;
int ibin;
if (!std::isfinite(x[0]) || !std::isfinite(x[1]) || !std::isfinite(x[2]))
error->one(FLERR,"Non-numeric positions - simulation unstable");
if (x[0] >= bboxhi[0])
ix = static_cast<int> ((x[0]-bboxhi[0])*bininvx_type[it]) + nbinx_type[it];
else if (x[0] >= bboxlo[0]) {
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx_type[it]);
ix = MIN(ix,nbinx_type[it]-1);
} else
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx_type[it]) - 1;
if (x[1] >= bboxhi[1])
iy = static_cast<int> ((x[1]-bboxhi[1])*bininvy_type[it]) + nbiny_type[it];
else if (x[1] >= bboxlo[1]) {
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy_type[it]);
iy = MIN(iy,nbiny_type[it]-1);
} else
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy_type[it]) - 1;
if (x[2] >= bboxhi[2])
iz = static_cast<int> ((x[2]-bboxhi[2])*bininvz_type[it]) + nbinz_type[it];
else if (x[2] >= bboxlo[2]) {
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz_type[it]);
iz = MIN(iz,nbinz_type[it]-1);
} else
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz_type[it]) - 1;
ibin = (iz-mbinzlo_type[it])*mbiny_type[it]*mbinx_type[it]
+ (iy-mbinylo_type[it])*mbinx_type[it]
+ (ix-mbinxlo_type[it]);
return ibin;
}
/* ----------------------------------------------------------------------
tot up for types
---------------------------------------------------------------------- */
bigint NBinBytype::memory_usage()
{
bigint bytes = 0;
for (int m = 1; m < maxtypes; m++) {
bytes += 2*maxatom*sizeof(int);
bytes += maxbins_type[m]*sizeof(int);
}
return bytes;
}

View File

@ -29,6 +29,33 @@ using namespace LAMMPS_NS;
NBinStandard::NBinStandard(LAMMPS *lmp) : NBin(lmp) {}
/* ----------------------------------------------------------------------
setup for bin_atoms()
------------------------------------------------------------------------- */
void NBinStandard::bin_atoms_setup(int nall)
{
// binhead = per-bin vector, mbins in length
// add 1 bin for USER-INTEL package
if (mbins > maxbin) {
maxbin = mbins;
memory->destroy(binhead);
memory->create(binhead,maxbin,"neigh:binhead");
}
// bins and atom2bin = per-atom vectors
// for both local and ghost atoms
if (nall > maxatom) {
maxatom = nall;
memory->destroy(bins);
memory->create(bins,maxatom,"neigh:bins");
memory->destroy(atom2bin);
memory->create(atom2bin,maxatom,"neigh:atom2bin");
}
}
/* ----------------------------------------------------------------------
setup neighbor binning geometry
bin numbering in each dimension is global:
@ -230,3 +257,61 @@ void NBinStandard::bin_atoms()
}
}
}
/* ----------------------------------------------------------------------
convert atom coords into local bin #
for orthogonal, only ghost atoms will have coord >= bboxhi or coord < bboxlo
take special care to insure ghosts are in correct bins even w/ roundoff
hi ghost atoms = nbin,nbin+1,etc
owned atoms = 0 to nbin-1
lo ghost atoms = -1,-2,etc
this is necessary so that both procs on either side of PBC
treat a pair of atoms straddling the PBC in a consistent way
for triclinic, doesn't matter since stencil & neigh list built differently
------------------------------------------------------------------------- */
int NBinStandard::coord2bin(double *x)
{
int ix,iy,iz;
if (!std::isfinite(x[0]) || !std::isfinite(x[1]) || !std::isfinite(x[2]))
error->one(FLERR,"Non-numeric positions - simulation unstable");
if (x[0] >= bboxhi[0])
ix = static_cast<int> ((x[0]-bboxhi[0])*bininvx) + nbinx;
else if (x[0] >= bboxlo[0]) {
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx);
ix = MIN(ix,nbinx-1);
} else
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx) - 1;
if (x[1] >= bboxhi[1])
iy = static_cast<int> ((x[1]-bboxhi[1])*bininvy) + nbiny;
else if (x[1] >= bboxlo[1]) {
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy);
iy = MIN(iy,nbiny-1);
} else
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy) - 1;
if (x[2] >= bboxhi[2])
iz = static_cast<int> ((x[2]-bboxhi[2])*bininvz) + nbinz;
else if (x[2] >= bboxlo[2]) {
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz);
iz = MIN(iz,nbinz-1);
} else
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz) - 1;
return (iz-mbinzlo)*mbiny*mbinx + (iy-mbinylo)*mbinx + (ix-mbinxlo);
}
/* ---------------------------------------------------------------------- */
double NBinStandard::memory_usage()
{
double bytes = 0;
bytes += maxbin*sizeof(int);
bytes += 2*maxatom*sizeof(int);
return bytes;
}

View File

@ -30,8 +30,14 @@ class NBinStandard : public NBin {
public:
NBinStandard(class LAMMPS *);
~NBinStandard() {}
void bin_atoms_setup(int);
void setup_bins(int);
void bin_atoms();
double memory_usage();
private:
int coord2bin(double *);
};
}

View File

@ -1620,12 +1620,12 @@ int Neighbor::choose_bin(NeighRequest *rq)
if (!rq->kokkos_device != !(mask & NB_KOKKOS_DEVICE)) continue;
if (!rq->kokkos_host != !(mask & NB_KOKKOS_HOST)) continue;
// neighbor style is BIN or MULTI or MULTI/TIERED and must match
// neighbor style is BIN or MULTI or MULTI2 and must match
if (style == Neighbor::BIN || style == Neighbor::MULTI) {
if (!(mask & NB_STANDARD)) continue;
} else if (style == Neighbor::MULTI_TIERED) {
if (!(mask & NB_MULTI_TIERED)) continue;
} else if (style == Neighbor::MULTI2) {
if (!(mask & NB_MULTI2)) continue;
}
return i+1;
@ -1698,14 +1698,14 @@ int Neighbor::choose_stencil(NeighRequest *rq)
if (!rq->ghost != !(mask & NS_GHOST)) continue;
if (!rq->ssa != !(mask & NS_SSA)) continue;
// neighbor style is one of BIN, MULTI, or MULT/TIERED and must match
// neighbor style is one of BIN, MULTI, or MULTI2 and must match
if (style == Neighbor::BIN) {
if (!(mask & NS_BIN)) continue;
} else if (style == Neighbor::MULTI) {
if (!(mask & NS_MULTI)) continue;
} else if (style == Neighbor::MULT_TIERED) {
if (!(mask & NS_MULT_TIERED)) continue;
} else if (style == Neighbor::MULTI2) {
if (!(mask & NS_MULTI2)) continue;
}
// dimension is 2 or 3 and must match
@ -1835,7 +1835,7 @@ int Neighbor::choose_pair(NeighRequest *rq)
if (!rq->halffull != !(mask & NP_HALF_FULL)) continue;
if (!rq->off2on != !(mask & NP_OFF2ON)) continue;
// neighbor style is one of NSQ, BIN, MULTI, or MULTI/TIERED and must match
// neighbor style is one of NSQ, BIN, MULTI, or MULTI2 and must match
if (style == Neighbor::NSQ) {
if (!(mask & NP_NSQ)) continue;
@ -1843,8 +1843,8 @@ int Neighbor::choose_pair(NeighRequest *rq)
if (!(mask & NP_BIN)) continue;
} else if (style == Neighbor::MULTI) {
if (!(mask & NP_MULTI)) continue;
} else if (style == Neighbor::MULT_TIERED) {
if (!(mask & NP_MULT_TIERED)) continue;
} else if (style == Neighbor::MULTI2) {
if (!(mask & NP_MULTI2)) continue;
}
// domain triclinic flag is on or off and must match
@ -2211,7 +2211,7 @@ void Neighbor::set(int narg, char **arg)
if (strcmp(arg[1],"nsq") == 0) style = Neighbor::NSQ;
else if (strcmp(arg[1],"bin") == 0) style = Neighbor::BIN;
else if (strcmp(arg[1],"multi") == 0) style = Neighbor::MULTI;
else if (strcmp(arg[1],"multi/tiered") == 0) style = Neighbor::MULT_TIERED;
else if (strcmp(arg[1],"multi2") == 0) style = Neighbor::MULTI2;
else error->all(FLERR,"Illegal neighbor command");
if (style == Neighbor::MULTI && lmp->citeme) lmp->citeme->add(cite_neigh_multi);

View File

@ -20,7 +20,7 @@ namespace LAMMPS_NS {
class Neighbor : protected Pointers {
public:
enum{NSQ,BIN,MULTI,MULTI_TIERED};
enum{NSQ,BIN,MULTI,MULTI2};
int style; // 0,1,2 = nsq, bin, multi
int every; // build every this many steps
int delay; // delay build for this many steps
@ -239,7 +239,7 @@ namespace NeighConst {
static const int NB_KOKKOS_DEVICE = 1<<1;
static const int NB_KOKKOS_HOST = 1<<2;
static const int NB_SSA = 1<<3;
static const int NB_MULTI_TIERED = 1<<4;
static const int NB_MULTI2 = 1<<4;
static const int NB_STANDARD = 1<<5;
static const int NS_BIN = 1<<0;
@ -254,7 +254,7 @@ namespace NeighConst {
static const int NS_TRI = 1<<9;
static const int NS_GHOST = 1<<10;
static const int NS_SSA = 1<<11;
static const int NS_MULTI_TIERED = 1<<12;
static const int NS_MULTI2 = 1<<12;
static const int NP_NSQ = 1<<0;
static const int NP_BIN = 1<<1;
@ -281,7 +281,7 @@ namespace NeighConst {
static const int NP_SKIP = 1<<22;
static const int NP_HALF_FULL = 1<<23;
static const int NP_OFF2ON = 1<<24;
static const int NP_MULTI_TIERED = 1<<25;
static const int NP_MULTI2 = 1<<25;
}
}

View File

@ -51,6 +51,15 @@ using namespace LAMMPS_NS;
stencil follows same rules for half/full, newton on/off, triclinic
cutoff is not cutneighmaxsq, but max cutoff for that atom type
no versions that allow ghost on (any need for it?)
for multi/tiered:
create one stencil for each itype-jtype pairing
stencils do not generally follow the same rules for half/full or newton on/off
whole stencils including all surrounding bins are always used except
for same-type stencils with newton on which uses a split stencil
for orthogonal boxes, a split stencil includes bins to the "upper right" of central bin
for triclinic, a split stencil includes bins in the z (3D) or y (2D) plane of self and above
cutoff is not cutneighmaxsq, but max cutoff for that atom type
no versions that allow ghost on (any need for it?)
------------------------------------------------------------------------- */
NStencil::NStencil(LAMMPS *lmp) : Pointers(lmp)
@ -65,6 +74,11 @@ NStencil::NStencil(LAMMPS *lmp) : Pointers(lmp)
stencil_multi = nullptr;
distsq_multi = nullptr;
stencil_split = nullptr;
stencil_skip = nullptr;
stencil_bin_type = nullptr;
stencil_cut = nullptr;
dimension = domain->dimension;
}
@ -75,7 +89,7 @@ NStencil::~NStencil()
memory->destroy(stencil);
memory->destroy(stencilxyz);
if (!stencil_multi) return;
if (stencil_multi) {
int n = atom->ntypes;
for (int i = 1; i <= n; i++) {
@ -87,6 +101,34 @@ NStencil::~NStencil()
delete [] distsq_multi;
}
if (stencil_multi_tiered) {
int n = atom->ntypes;
memory->destroy(nstencil_multi_tiered);
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= n; j++) {
if (! stencil_skip[i][j])
memory->destroy(stencil_multi_tiered[i][j]);
}
delete [] stencil_multi_tiered[i];
}
delete [] stencil_multi_tiered;
memory->destroy(maxstencil_multi_tiered);
memory->destroy(stencil_split);
memory->destroy(stencil_skip);
memory->destroy(stencil_bin_type);
memory->destroy(stencil_cut);
memory->destroy(sx_multi_tiered);
memory->destroy(sy_multi_tiered);
memory->destroy(sz_multi_tiered);
memory->destroy(binsizex_multi_tiered);
memory->destroy(binsizey_multi_tiered);
memory->destroy(binsizez_multi_tiered);
}
}
/* ---------------------------------------------------------------------- */
void NStencil::post_constructor(NeighRequest *nrq)
@ -105,6 +147,7 @@ void NStencil::copy_neighbor_info()
cutneighmax = neighbor->cutneighmax;
cutneighmaxsq = neighbor->cutneighmaxsq;
cuttypesq = neighbor->cuttypesq;
cutneighsq = neighbor->cutneighsq;
// overwrite Neighbor cutoff with custom value set by requestor
// only works for style = BIN (checked by Neighbor class)
@ -132,6 +175,23 @@ void NStencil::copy_bin_info()
bininvz = nb->bininvz;
}
/* ----------------------------------------------------------------------
copy needed info for a given type from NBin class to this stencil class
------------------------------------------------------------------------- */
void NStencil::copy_bin_info_multi_tiered(int type)
{
mbinx = nb->mbinx_tiered[type];
mbiny = nb->mbiny_tiered[type];
mbinz = nb->mbinz_tiered[type];
binsizex = nb->binsizex_tiered[type];
binsizey = nb->binsizey_tiered[type];
binsizez = nb->binsizez_tiered[type];
bininvx = nb->bininvx_tiered[type];
bininvy = nb->bininvy_tiered[type];
bininvz = nb->bininvz_tiered[type];
}
/* ----------------------------------------------------------------------
insure NBin data is current
insure stencils are allocated large enough
@ -139,6 +199,8 @@ void NStencil::copy_bin_info()
void NStencil::create_setup()
{
if (neighstyle != Neighbor::MULTI_TIERED){
if (nb) copy_bin_info();
last_stencil = update->ntimestep;
@ -195,6 +257,76 @@ void NStencil::create_setup()
}
}
}
} else {
int i, j, bin_type, smax;
double stencil_range;
int n = atom->ntypes;
// Allocate arrays to store stencil information
memory->create(stencil_split, n, n,
"neighstencil:stencil_split");"
memory->create(stencil_skip, n, n,
"neighstencil:stencil_skip");"
memory->create(stencil_bin_type, n, n,
"neighstencil:stencil_bin_type");"
memory->create(stencil_cut, n, n,
"neighstencil:stencil_cut");"
memory->create(sx_multi_tiered, n, n,
"neighstencil:sx_multi_tiered");"
memory->create(sy_multi_tiered, n, n,
"neighstencil:sy_multi_tiered");"
memory->create(sz_multi_tiered, n, n,
"neighstencil:sz_multi_tiered");"
memory->create(binsizex_multi_tiered, n, n,
"neighstencil:binsizex_multi_tiered");"
memory->create(binsizey_multi_tiered, n, n,
"neighstencil:binsizey_multi_tiered");"
memory->create(binsizez_multi_tiered, n, n,
"neighstencil:binsizez_multi_tiered");"
// Determine which stencils need to be built
set_stencil_properties();
for (i = 1; i <= n; ++i) {
for (j = 1; j <= n; ++j) {
// Skip creation of unused stencils
if (stencil_skip[i][j]) continue;
// Copy bin info for this particular pair of types
bin_type = stencil_bin_type[i][j];
copy_bin_info_bytype(bin_type);
binsizex_multi_tiered[i][j] = binsizex;
binsizey_multi_tiered[i][j] = binsizey;
binsizez_multi_tiered[i][j] = binsizez;
stencil_range = stencil_cut[i][j];
sx = static_cast<int> (stencil_range*bininvx);
if (sx*binsizex < stencil_range) sx++;
sy = static_cast<int> (stencil_range*bininvy);
if (sy*binsizey < stencil_range) sy++;
sz = static_cast<int> (stencil_range*bininvz);
if (sz*binsizez < stencil_range) sz++;
sx_multi_tiered[i][j] = sx;
sy_multi_tiered[i][j] = sy;
sz_multi_tiered[i][j] = sz;
smax = ((2*sx+1) * (2*sy+1) * (2*sz+1));
if (smax > maxstencil_multi_tiered[i][j]) {
maxstencil_multi_tiered[i][j] = smax;
memory->destroy(stencil_multi_tiered[i][j]);
memory->create(stencil_multi_tiered[i][j], smax,
"neighstencil::stencil_multi_tiered");
}
}
}
}
}
/* ----------------------------------------------------------------------
@ -231,6 +363,10 @@ double NStencil::memory_usage()
} else if (neighstyle == Neighbor::MULTI) {
bytes += atom->ntypes*maxstencil_multi * sizeof(int);
bytes += atom->ntypes*maxstencil_multi * sizeof(double);
} else if (neighstyle == Neighbor::MULTI_TIERED) {
bytes += atom->ntypes*maxstencil_multi * sizeof(int);
bytes += atom->ntypes*maxstencil_multi * sizeof(int);
bytes += atom->ntypes*maxstencil_multi * sizeof(double);
}
return bytes;
}

View File

@ -29,14 +29,22 @@ class NStencil : protected Pointers {
int **stencilxyz; // bin offsets in xyz dims
int *nstencil_multi; // # bins in each type-based multi stencil
int **stencil_multi; // list of bin offsets in each stencil
int ** nstencil_multi_tiered; // # bins bins in each itype-jtype tiered multi stencil
int *** stencil_multi_tiered; // list of bin offsets in each tiered multi stencil
int ** maxstencil_type; // max
double **distsq_multi; // sq distances to bins in each stencil
int sx,sy,sz; // extent of stencil in each dim
int **sx_multi_tiered; // analogs for multi tiered
int **sy_multi_tiered;
int **sz_multi_tiered;
double cutoff_custom; // cutoff set by requestor
// BYTYPE stencils
int ** nstencil_type; // No. of bins for stencil[itype][jtype]
int *** stencil_type; // Stencil for [itype][jtype]
// Arrays to store options for multi/tiered itype-jtype stencils
bool **stencil_half; // flag creation of a half stencil for itype-jtype
bool **stencil_skip; // skip creation of itype-jtype stencils (for newton on)
int **stencil_bin_type; // what type to use for bin information
double **stencil_cut; // cutoff used for stencil size
NStencil(class LAMMPS *);
virtual ~NStencil();
@ -57,6 +65,7 @@ class NStencil : protected Pointers {
double cutneighmax;
double cutneighmaxsq;
double *cuttypesq;
double *cutneighsq;
// data from NBin class
@ -64,6 +73,12 @@ class NStencil : protected Pointers {
double binsizex,binsizey,binsizez;
double bininvx,bininvy,bininvz;
// analogs for multi-tiered
double **binsizex_multi_tiered;
double **binsizey_multi_tiered;
double **binsizez_multi_tiered;
// data common to all NStencil variants
int xyzflag; // 1 if stencilxyz is allocated
@ -76,6 +91,11 @@ class NStencil : protected Pointers {
void copy_bin_info(); // copy info from NBin class
double bin_distance(int, int, int); // distance between bin corners
// methods for multi/tiered NStencil
void copy_bin_info_multi_tiered(int); // copy mult/tiered info from NBin class
void set_stencil_properties(); // determine which stencils to build and how
};
}

View File

@ -46,23 +46,9 @@ NStencilFullBytype3d::~NStencilFullBytype3d() {
}
}
/* ---------------------------------------------------------------------- */
void NStencilFullBytype3d::copy_bin_info_bytype(int itype) {
mbinx = nb->mbinx_type[itype];
mbiny = nb->mbiny_type[itype];
mbinz = nb->mbinz_type[itype];
binsizex = nb->binsizex_type[itype];
binsizey = nb->binsizey_type[itype];
binsizez = nb->binsizez_type[itype];
bininvx = nb->bininvx_type[itype];
bininvy = nb->bininvy_type[itype];
bininvz = nb->bininvz_type[itype];
}
/* ---------------------------------------------------------------------- */
INCORPORTE INTO CREATE THEN DELETE, NOTE NAME OF CUTNEIGHMAX ETC
int NStencilFullBytype3d::copy_neigh_info_bytype(int itype) {
cutneighmaxsq = neighbor->cutneighsq[itype][itype];
@ -104,13 +90,13 @@ void NStencilFullBytype3d::create_setup()
maxstencil_type[itype][jtype] = 0;
}
}
}
} MOVE TO PARENT CLASS
// like -> like => use standard newtoff stencil at bin
for (itype = 1; itype <= maxtypes; ++itype) {
copy_bin_info_bytype(itype);
smax = copy_neigh_info_bytype(itype);
smax = copy_neigh_info_bytype(itype); uses cutneighsq[itype][itype] to create s's
if (smax > maxstencil_type[itype][itype]) {
maxstencil_type[itype][itype] = smax;
memory->destroy(stencil_type[itype][itype]);
@ -127,7 +113,7 @@ void NStencilFullBytype3d::create_setup()
for (itype = 1; itype <= maxtypes; ++itype) {
for (jtype = 1; jtype <= maxtypes; ++jtype) {
if (itype == jtype) continue;
if (cuttypesq[itype] <= cuttypesq[jtype]) {
if (cuttypesq[itype] <= cuttypesq[jtype]) { This does work to say which prticle is smller
// Potential destroy/create problem?
nstencil_type[itype][jtype] = nstencil_type[jtype][jtype];
stencil_type[itype][jtype] = stencil_type[jtype][jtype];
@ -136,7 +122,7 @@ void NStencilFullBytype3d::create_setup()
copy_bin_info_bytype(jtype);
// smax = copy_neigh_info_bytype(jtype);
cutneighmaxsq = cuttypesq[jtype];
cutneighmaxsq = cuttypesq[jtype]; Does it need to be this big? Can't I use cutneighsq[i][j]?
cutneighmax = sqrt(cutneighmaxsq);
sx = static_cast<int> (cutneighmax*bininvx);
if (sx*binsizex < cutneighmax) sx++;

View File

@ -13,15 +13,15 @@
#ifdef NSTENCIL_CLASS
NStencilStyle(full/bytype/3d,
NStencilFullBytype3d,
NS_FULL | NS_BYTYPE | NS_3D |
NStencilStyle(full/multi/tiered/3d,
NStencilFullMultiTiered3d,
NS_FULL | NS_Multi_Tiered | NS_3D |
NS_NEWTON | NS_NEWTOFF | NS_ORTHO | NS_TRI)
#else
#ifndef LMP_NSTENCIL_FULL_BYTYPE_3D_H
#define LMP_NSTENCIL_FULL_BYTYPE_3D_H
#ifndef LMP_NSTENCIL_FULL_MULTI_TIERED_3D_H
#define LMP_NSTENCIL_FULL_MULTI_TIERED_3D_H
#include "nstencil.h"
@ -37,7 +37,6 @@ class NStencilFullBytype3d : public NStencil {
private:
int ** maxstencil_type;
void copy_bin_info_bytype(int);
int copy_neigh_info_bytype(int);
void create_newtoff(int, int, double);