|
|
|
|
@ -21,6 +21,7 @@
|
|
|
|
|
#include "force.h"
|
|
|
|
|
#include "pair.h"
|
|
|
|
|
#include "update.h"
|
|
|
|
|
#include "memory.h"
|
|
|
|
|
#include "modify.h"
|
|
|
|
|
#include "error.h"
|
|
|
|
|
|
|
|
|
|
@ -31,35 +32,343 @@
|
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
|
using namespace FixConst;
|
|
|
|
|
|
|
|
|
|
enum{DEFAULT,NPARTNER,PERPARTNER}; // also set in fix neigh/history
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FixNeighHistoryOMP::FixNeighHistoryOMP(class LAMMPS *lmp,int narg,char **argv)
|
|
|
|
|
: FixNeighHistory(lmp,narg,argv) {
|
|
|
|
|
|
|
|
|
|
if (onesided)
|
|
|
|
|
error->all(FLERR,"tri/lj and line/lj are not supported by USER-OMP");
|
|
|
|
|
if (!newton_pair)
|
|
|
|
|
error->all(FLERR,"Newton off for granular is not supported by USER-OMP");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
copy partner info from neighbor data structs (NDS) to atom arrays
|
|
|
|
|
should be called whenever NDS store current history info
|
|
|
|
|
and need to transfer the info to owned atoms
|
|
|
|
|
e.g. when atoms migrate to new procs, new neigh list built, or between runs
|
|
|
|
|
when atoms may be added or deleted (NDS becomes out-of-date)
|
|
|
|
|
the next post_neighbor() will put this info back into new NDS
|
|
|
|
|
called during run before atom exchanges, including for restart files
|
|
|
|
|
called at end of run via post_run()
|
|
|
|
|
do not call during setup of run (setup_pre_exchange)
|
|
|
|
|
b/c there is no guarantee of a current NDS (even on continued run)
|
|
|
|
|
if run command does a 2nd run with pre = no, then no neigh list
|
|
|
|
|
will be built, but old neigh list will still have the info
|
|
|
|
|
|
|
|
|
|
the USER-OMP version only supports newton on
|
|
|
|
|
copy partner info from neighbor data structs (NDS) to atom arrays
|
|
|
|
|
should be called whenever NDS store current history info
|
|
|
|
|
and need to transfer the info to owned atoms
|
|
|
|
|
e.g. when atoms migrate to new procs, new neigh list built, or between runs
|
|
|
|
|
when atoms may be added or deleted (NDS becomes out-of-date)
|
|
|
|
|
the next post_neighbor() will put this info back into new NDS
|
|
|
|
|
called during run before atom exchanges, including for restart files
|
|
|
|
|
called at end of run via post_run()
|
|
|
|
|
do not call during setup of run (setup_pre_exchange)
|
|
|
|
|
b/c there is no guarantee of a current NDS (even on continued run)
|
|
|
|
|
if run command does a 2nd run with pre = no, then no neigh list
|
|
|
|
|
will be built, but old neigh list will still have the info
|
|
|
|
|
onesided and newton on and newton off versions
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
// below is the pre_exchange() function from the parent class
|
|
|
|
|
// void FixNeighHistory::pre_exchange()
|
|
|
|
|
// {
|
|
|
|
|
// if (onesided) pre_exchange_onesided();
|
|
|
|
|
// else if (newton_pair) pre_exchange_newton();
|
|
|
|
|
// else pre_exchange_no_newton();
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
|
onesided version for sphere contact with line/tri particles
|
|
|
|
|
neighbor list has I = sphere, J = line/tri
|
|
|
|
|
only store history info with spheres
|
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void FixNeighHistoryOMP::pre_exchange()
|
|
|
|
|
void FixNeighHistoryOMP::pre_exchange_onesided()
|
|
|
|
|
{
|
|
|
|
|
const int nthreads = comm->nthreads;
|
|
|
|
|
const int nlocal = atom->nlocal;
|
|
|
|
|
maxpartner = 0;
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp parallel default(none)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
const int tid = omp_get_thread_num();
|
|
|
|
|
#else
|
|
|
|
|
const int tid = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int i,j,ii,jj,m,n,inum,jnum;
|
|
|
|
|
int *ilist,*jlist,*numneigh,**firstneigh;
|
|
|
|
|
int *allflags;
|
|
|
|
|
double *allvalues,*onevalues;
|
|
|
|
|
|
|
|
|
|
// NOTE: all operations until very end are with:
|
|
|
|
|
// nlocal_neigh <= current nlocal
|
|
|
|
|
// b/c previous neigh list was built with nlocal_neigh
|
|
|
|
|
// nlocal can be larger if other fixes added atoms at this pre_exchange()
|
|
|
|
|
|
|
|
|
|
// clear per-thread paged data structures
|
|
|
|
|
|
|
|
|
|
MyPage <tagint> &ipg = ipage_atom[tid];
|
|
|
|
|
MyPage <double> &dpg = dpage_atom[tid];
|
|
|
|
|
ipg.reset();
|
|
|
|
|
dpg.reset();
|
|
|
|
|
|
|
|
|
|
// each thread works on a fixed chunk of local and ghost atoms.
|
|
|
|
|
const int ldelta = 1 + nlocal_neigh/nthreads;
|
|
|
|
|
const int lfrom = tid*ldelta;
|
|
|
|
|
const int lmax = lfrom +ldelta;
|
|
|
|
|
const int lto = (lmax > nlocal_neigh) ? nlocal_neigh : lmax;
|
|
|
|
|
|
|
|
|
|
// 1st loop over neighbor list, I = sphere, J = tri
|
|
|
|
|
// only calculate npartner for each owned spheres
|
|
|
|
|
|
|
|
|
|
for (i = lfrom; i < lto; i++) npartner[i] = 0;
|
|
|
|
|
|
|
|
|
|
tagint *tag = atom->tag;
|
|
|
|
|
NeighList *list = pair->list;
|
|
|
|
|
inum = list->inum;
|
|
|
|
|
ilist = list->ilist;
|
|
|
|
|
numneigh = list->numneigh;
|
|
|
|
|
firstneigh = list->firstneigh;
|
|
|
|
|
|
|
|
|
|
for (ii = 0; ii < inum; ii++) {
|
|
|
|
|
i = ilist[ii];
|
|
|
|
|
jlist = firstneigh[i];
|
|
|
|
|
jnum = numneigh[i];
|
|
|
|
|
allflags = firstflag[i];
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < jnum; jj++)
|
|
|
|
|
if (allflags[jj])
|
|
|
|
|
if ((i >= lfrom) && (i < lto)) npartner[i]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get page chunks to store atom IDs and shear history for my atoms
|
|
|
|
|
|
|
|
|
|
for (ii = 0; ii < inum; ii++) {
|
|
|
|
|
i = ilist[ii];
|
|
|
|
|
if ((i >= lfrom) && (i < lto)) {
|
|
|
|
|
n = npartner[i];
|
|
|
|
|
partner[i] = ipg.get(n);
|
|
|
|
|
valuepartner[i] = dpg.get(dnum*n);
|
|
|
|
|
if (partner[i] == NULL || valuepartner[i] == NULL)
|
|
|
|
|
error->one(FLERR,"Neighbor history overflow, boost neigh_modify one");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2nd loop over neighbor list
|
|
|
|
|
// store partner IDs and values for owned+ghost atoms
|
|
|
|
|
// re-zero npartner to use as counter
|
|
|
|
|
|
|
|
|
|
for (i = lfrom; i < lto; i++) npartner[i] = 0;
|
|
|
|
|
|
|
|
|
|
for (ii = 0; ii < inum; ii++) {
|
|
|
|
|
i = ilist[ii];
|
|
|
|
|
jlist = firstneigh[i];
|
|
|
|
|
jnum = numneigh[i];
|
|
|
|
|
allflags = firstflag[i];
|
|
|
|
|
allvalues = firstvalue[i];
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < jnum; jj++) {
|
|
|
|
|
if (allflags[jj]) {
|
|
|
|
|
onevalues = &allvalues[dnum*jj];
|
|
|
|
|
j = jlist[jj];
|
|
|
|
|
j &= NEIGHMASK;
|
|
|
|
|
|
|
|
|
|
if ((i >= lfrom) && (i < lto)) {
|
|
|
|
|
m = npartner[i]++;
|
|
|
|
|
partner[i][m] = tag[j];
|
|
|
|
|
memcpy(&valuepartner[i][dnum*m],onevalues,dnumbytes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set maxpartner = max # of partners of any owned atom
|
|
|
|
|
maxpartner = m = 0;
|
|
|
|
|
for (i = lfrom; i < lto; i++)
|
|
|
|
|
m = MAX(m,npartner[i]);
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp critical
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
maxpartner = MAX(m,maxpartner);
|
|
|
|
|
comm->maxexchange_fix =MAX(comm->maxexchange_fix,(dnum+1)*maxpartner+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// zero npartner values from previous nlocal_neigh to current nlocal
|
|
|
|
|
for (int i = nlocal_neigh; i < nlocal; ++i) npartner[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void FixNeighHistoryOMP::pre_exchange_newton()
|
|
|
|
|
{
|
|
|
|
|
const int nthreads = comm->nthreads;
|
|
|
|
|
maxpartner = 0;
|
|
|
|
|
for (int i = 0; i < nall_neigh; i++) npartner[i] = 0;
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp parallel default(none)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
const int tid = omp_get_thread_num();
|
|
|
|
|
#else
|
|
|
|
|
const int tid = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int i,j,ii,jj,m,n,inum,jnum;
|
|
|
|
|
int *ilist,*jlist,*numneigh,**firstneigh;
|
|
|
|
|
int *allflags;
|
|
|
|
|
double *allvalues,*onevalues,*jvalues;
|
|
|
|
|
|
|
|
|
|
MyPage <tagint> &ipg = ipage_atom[tid];
|
|
|
|
|
MyPage <double> &dpg = dpage_atom[tid];
|
|
|
|
|
ipg.reset();
|
|
|
|
|
dpg.reset();
|
|
|
|
|
|
|
|
|
|
// 1st loop over neighbor list
|
|
|
|
|
// calculate npartner for each owned+ghost atom
|
|
|
|
|
|
|
|
|
|
tagint *tag = atom->tag;
|
|
|
|
|
|
|
|
|
|
NeighList *list = pair->list;
|
|
|
|
|
inum = list->inum;
|
|
|
|
|
ilist = list->ilist;
|
|
|
|
|
numneigh = list->numneigh;
|
|
|
|
|
firstneigh = list->firstneigh;
|
|
|
|
|
|
|
|
|
|
// each thread works on a fixed chunk of local and ghost atoms.
|
|
|
|
|
const int ldelta = 1 + nlocal_neigh/nthreads;
|
|
|
|
|
const int lfrom = tid*ldelta;
|
|
|
|
|
const int lmax = lfrom +ldelta;
|
|
|
|
|
const int lto = (lmax > nlocal_neigh) ? nlocal_neigh : lmax;
|
|
|
|
|
|
|
|
|
|
for (ii = 0; ii < inum; ii++) {
|
|
|
|
|
i = ilist[ii];
|
|
|
|
|
jlist = firstneigh[i];
|
|
|
|
|
jnum = numneigh[i];
|
|
|
|
|
allflags = firstflag[i];
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < jnum; jj++) {
|
|
|
|
|
if (allflags[jj]) {
|
|
|
|
|
if ((i >= lfrom) && (i < lto))
|
|
|
|
|
npartner[i]++;
|
|
|
|
|
|
|
|
|
|
j = jlist[jj];
|
|
|
|
|
j &= NEIGHMASK;
|
|
|
|
|
if ((j >= lfrom) && (j < lto))
|
|
|
|
|
npartner[j]++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp barrier
|
|
|
|
|
{;}
|
|
|
|
|
|
|
|
|
|
// perform reverse comm to augment owned npartner counts with ghost counts
|
|
|
|
|
|
|
|
|
|
#pragma omp master
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
commflag = NPARTNER;
|
|
|
|
|
comm->reverse_comm_fix(this,0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get page chunks to store atom IDs and shear history for my atoms
|
|
|
|
|
|
|
|
|
|
for (ii = 0; ii < inum; ii++) {
|
|
|
|
|
i = ilist[ii];
|
|
|
|
|
if ((i >= lfrom) && (i < lto)) {
|
|
|
|
|
n = npartner[i];
|
|
|
|
|
partner[i] = ipg.get(n);
|
|
|
|
|
valuepartner[i] = dpg.get(dnum*n);
|
|
|
|
|
if (partner[i] == NULL || valuepartner[i] == NULL)
|
|
|
|
|
error->one(FLERR,"Neighbor history overflow, boost neigh_modify one");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp master
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
for (i = nlocal_neigh; i < nall_neigh; i++) {
|
|
|
|
|
n = npartner[i];
|
|
|
|
|
partner[i] = ipg.get(n);
|
|
|
|
|
valuepartner[i] = dpg.get(dnum*n);
|
|
|
|
|
if (partner[i] == NULL || valuepartner[i] == NULL) {
|
|
|
|
|
error->one(FLERR,"Neighbor history overflow, boost neigh_modify one");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2nd loop over neighbor list
|
|
|
|
|
// store partner IDs and values for owned+ghost atoms
|
|
|
|
|
// re-zero npartner to use as counter
|
|
|
|
|
|
|
|
|
|
for (i = lfrom; i < lto; i++) npartner[i] = 0;
|
|
|
|
|
|
|
|
|
|
for (ii = 0; ii < inum; ii++) {
|
|
|
|
|
i = ilist[ii];
|
|
|
|
|
jlist = firstneigh[i];
|
|
|
|
|
jnum = numneigh[i];
|
|
|
|
|
allflags = firstflag[i];
|
|
|
|
|
allvalues = firstvalue[i];
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < jnum; jj++) {
|
|
|
|
|
if (allflags[jj]) {
|
|
|
|
|
onevalues = &allvalues[dnum*jj];
|
|
|
|
|
j = jlist[jj];
|
|
|
|
|
j &= NEIGHMASK;
|
|
|
|
|
|
|
|
|
|
if ((i >= lfrom) && (i < lto)) {
|
|
|
|
|
m = npartner[i]++;
|
|
|
|
|
partner[i][m] = tag[j];
|
|
|
|
|
memcpy(&valuepartner[i][dnum*m],onevalues,dnumbytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((j >= lfrom) && (j < lto)) {
|
|
|
|
|
m = npartner[j]++;
|
|
|
|
|
partner[j][m] = tag[i];
|
|
|
|
|
jvalues = &valuepartner[j][dnum*m];
|
|
|
|
|
for (n = 0; n < dnum; n++) jvalues[n] = -onevalues[n];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp barrier
|
|
|
|
|
{;}
|
|
|
|
|
|
|
|
|
|
#pragma omp master
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
// perform reverse comm to augment
|
|
|
|
|
// owned atom partner/valuepartner with ghost info
|
|
|
|
|
// use variable variant b/c size of packed data can be arbitrarily large
|
|
|
|
|
// if many touching neighbors for large particle
|
|
|
|
|
|
|
|
|
|
commflag = PERPARTNER;
|
|
|
|
|
comm->reverse_comm_fix_variable(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set maxpartner = max # of partners of any owned atom
|
|
|
|
|
m = 0;
|
|
|
|
|
for (i = lfrom; i < lto; i++)
|
|
|
|
|
m = MAX(m,npartner[i]);
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp critical
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
maxpartner = MAX(m,maxpartner);
|
|
|
|
|
comm->maxexchange_fix = MAX(comm->maxexchange_fix,4*maxpartner+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// zero npartner values from previous nlocal_neigh to current nlocal
|
|
|
|
|
|
|
|
|
|
int nlocal = atom->nlocal;
|
|
|
|
|
for (int i = nlocal_neigh; i < nlocal; i++) npartner[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void FixNeighHistoryOMP::pre_exchange_no_newton()
|
|
|
|
|
{
|
|
|
|
|
const int nthreads = comm->nthreads;
|
|
|
|
|
maxpartner = 0;
|
|
|
|
|
@ -77,7 +386,7 @@ void FixNeighHistoryOMP::pre_exchange()
|
|
|
|
|
|
|
|
|
|
int i,j,ii,jj,m,n,inum,jnum;
|
|
|
|
|
int *ilist,*jlist,*numneigh,**firstneigh;
|
|
|
|
|
int *allflags,**firstflag;
|
|
|
|
|
int *allflags;
|
|
|
|
|
double *allvalues,*onevalues,*jvalues;
|
|
|
|
|
|
|
|
|
|
MyPage <tagint> &ipg = ipage_atom[tid];
|
|
|
|
|
@ -96,9 +405,6 @@ void FixNeighHistoryOMP::pre_exchange()
|
|
|
|
|
numneigh = list->numneigh;
|
|
|
|
|
firstneigh = list->firstneigh;
|
|
|
|
|
|
|
|
|
|
int nlocal_neigh = 0;
|
|
|
|
|
if (inum) nlocal_neigh = ilist[inum-1] + 1;
|
|
|
|
|
|
|
|
|
|
// each thread works on a fixed chunk of local and ghost atoms.
|
|
|
|
|
const int ldelta = 1 + nlocal_neigh/nthreads;
|
|
|
|
|
const int lfrom = tid*ldelta;
|
|
|
|
|
@ -158,7 +464,7 @@ void FixNeighHistoryOMP::pre_exchange()
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < jnum; jj++) {
|
|
|
|
|
if (allflags[jj]) {
|
|
|
|
|
onevalues = &allvalues[3*jj];
|
|
|
|
|
onevalues = &allvalues[dnum*jj];
|
|
|
|
|
j = jlist[jj];
|
|
|
|
|
j &= NEIGHMASK;
|
|
|
|
|
|
|
|
|
|
@ -179,13 +485,119 @@ void FixNeighHistoryOMP::pre_exchange()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set maxpartner = max # of partners of any owned atom
|
|
|
|
|
maxpartner = m = 0;
|
|
|
|
|
m = 0;
|
|
|
|
|
for (i = lfrom; i < lto; i++)
|
|
|
|
|
m = MAX(m,npartner[i]);
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp critical
|
|
|
|
|
#endif
|
|
|
|
|
maxpartner = MAX(m,maxpartner);
|
|
|
|
|
{
|
|
|
|
|
maxpartner = MAX(m,maxpartner);
|
|
|
|
|
comm->maxexchange_fix = MAX(comm->maxexchange_fix,(dnum+1)*maxpartner+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void FixNeighHistoryOMP::post_neighbor()
|
|
|
|
|
{
|
|
|
|
|
const int nthreads = comm->nthreads;
|
|
|
|
|
maxpartner = 0;
|
|
|
|
|
const int nlocal = atom->nlocal;
|
|
|
|
|
const int nall = nlocal + atom->nghost;
|
|
|
|
|
nlocal_neigh = nlocal;
|
|
|
|
|
nall_neigh = nall;
|
|
|
|
|
|
|
|
|
|
// realloc firstflag and firstvalue if needed
|
|
|
|
|
|
|
|
|
|
if (maxatom < nlocal) {
|
|
|
|
|
memory->sfree(firstflag);
|
|
|
|
|
memory->sfree(firstvalue);
|
|
|
|
|
maxatom = nall;
|
|
|
|
|
firstflag = (int **)
|
|
|
|
|
memory->smalloc(maxatom*sizeof(int *),"neighbor_history:firstflag");
|
|
|
|
|
firstvalue = (double **)
|
|
|
|
|
memory->smalloc(maxatom*sizeof(double *),"neighbor_history:firstvalue");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
#pragma omp parallel default(none)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#if defined(_OPENMP)
|
|
|
|
|
const int tid = omp_get_thread_num();
|
|
|
|
|
#else
|
|
|
|
|
const int tid = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int i,j,ii,jj,m,nn,np,inum,jnum,rflag;
|
|
|
|
|
tagint jtag;
|
|
|
|
|
int *ilist,*jlist,*numneigh,**firstneigh;
|
|
|
|
|
int *allflags;
|
|
|
|
|
double *allvalues;
|
|
|
|
|
|
|
|
|
|
MyPage <tagint> &ipg = ipage_atom[tid];
|
|
|
|
|
MyPage <double> &dpg = dpage_atom[tid];
|
|
|
|
|
ipg.reset();
|
|
|
|
|
dpg.reset();
|
|
|
|
|
|
|
|
|
|
// 1st loop over neighbor list
|
|
|
|
|
// calculate npartner for each owned atom
|
|
|
|
|
|
|
|
|
|
tagint *tag = atom->tag;
|
|
|
|
|
|
|
|
|
|
NeighList *list = pair->list;
|
|
|
|
|
inum = list->inum;
|
|
|
|
|
ilist = list->ilist;
|
|
|
|
|
numneigh = list->numneigh;
|
|
|
|
|
firstneigh = list->firstneigh;
|
|
|
|
|
|
|
|
|
|
// each thread works on a fixed chunk of local and ghost atoms.
|
|
|
|
|
const int ldelta = 1 + inum/nthreads;
|
|
|
|
|
const int lfrom = tid*ldelta;
|
|
|
|
|
const int lmax = lfrom +ldelta;
|
|
|
|
|
const int lto = (lmax > inum) ? inum : lmax;
|
|
|
|
|
|
|
|
|
|
for (ii = lfrom; ii < lto; ii++) {
|
|
|
|
|
i = ilist[ii];
|
|
|
|
|
jlist = firstneigh[i];
|
|
|
|
|
jnum = numneigh[i];
|
|
|
|
|
firstflag[i] = allflags = ipg.get(jnum);
|
|
|
|
|
firstvalue[i] = allvalues = dpg.get(jnum*dnum);
|
|
|
|
|
np = npartner[i];
|
|
|
|
|
nn = 0;
|
|
|
|
|
|
|
|
|
|
for (jj = 0; jj < jnum; jj++) {
|
|
|
|
|
j = jlist[jj];
|
|
|
|
|
rflag = sbmask(j);
|
|
|
|
|
j &= NEIGHMASK;
|
|
|
|
|
jlist[jj] = j;
|
|
|
|
|
|
|
|
|
|
// rflag = 1 if r < radsum in npair_size() method
|
|
|
|
|
// preserve neigh history info if tag[j] is in old-neigh partner list
|
|
|
|
|
// this test could be more geometrically precise for two sphere/line/tri
|
|
|
|
|
|
|
|
|
|
if (rflag) {
|
|
|
|
|
jtag = tag[j];
|
|
|
|
|
for (m = 0; m < np; m++)
|
|
|
|
|
if (partner[i][m] == jtag) break;
|
|
|
|
|
if (m < np) {
|
|
|
|
|
allflags[jj] = 1;
|
|
|
|
|
memcpy(&allvalues[nn],&valuepartner[i][dnum*m],dnumbytes);
|
|
|
|
|
} else {
|
|
|
|
|
allflags[jj] = 0;
|
|
|
|
|
memcpy(&allvalues[nn],zeroes,dnumbytes);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
allflags[jj] = 0;
|
|
|
|
|
memcpy(&allvalues[nn],zeroes,dnumbytes);
|
|
|
|
|
}
|
|
|
|
|
nn += dnum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|