#include "fix_srd.h"
#include <mpi.h>
#include <cmath>
#include <cstring>
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "atom_vec_line.h"
#include "atom_vec_tri.h"
#include "group.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "neighbor.h"
#include "comm.h"
#include "modify.h"
#include "fix_deform.h"
#include "fix_wall_srd.h"
#include "random_mars.h"
#include "random_park.h"
#include "math_const.h"
#include "citeme.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
using namespace FixConst;
using namespace MathConst;
enum{SLIP,NOSLIP};
enum{SPHERE,ELLIPSOID,LINE,TRIANGLE,WALL};
enum{INSIDE_ERROR,INSIDE_WARN,INSIDE_IGNORE};
enum{BIG_MOVE,SRD_MOVE,SRD_ROTATE};
enum{CUBIC_ERROR,CUBIC_WARN};
enum{SHIFT_NO,SHIFT_YES,SHIFT_POSSIBLE};
#define EINERTIA 0.2
#define ATOMPERBIN 30
#define BIG 1.0e20
#define VBINSIZE 5
#define TOLERANCE 0.00001
#define MAXITER 20
static const char cite_fix_srd[] =
"fix srd command:\n\n"
"@Article{Petersen10,\n"
" author = {M. K. Petersen, J. B. Lechman, S. J. Plimpton, G. S. Grest, P. J. in 't Veld, P. R. Schunk},\n"
" title = {Mesoscale Hydrodynamics via Stochastic Rotation Dynamics: Comparison with Lennard-Jones Fluid},"
" journal = {J.~Chem.~Phys.},\n"
" year = 2010,\n"
" volume = 132,\n"
" pages = {174106}\n"
"}\n\n";
FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg),
wallfix(NULL), wallwhich(NULL), xwall(NULL), xwallhold(NULL),
vwall(NULL), fwall(NULL), avec_ellipsoid(NULL), avec_line(NULL),
avec_tri(NULL), random(NULL), randomshift(NULL), flocal(NULL),
tlocal(NULL), biglist(NULL), binhead(NULL), binnext(NULL), sbuf1(NULL),
sbuf2(NULL), rbuf1(NULL), rbuf2(NULL), nbinbig(NULL), binbig(NULL),
binsrd(NULL), stencil(NULL)
{
if (lmp->citeme) lmp->citeme->add(cite_fix_srd);
if (narg < 8) error->all(FLERR,"Illegal fix srd command");
restart_pbc = 1;
vector_flag = 1;
size_vector = 12;
global_freq = 1;
extvector = 0;
nevery = force->inumeric(FLERR,arg[3]);
bigexist = 1;
if (strcmp(arg[4],"NULL") == 0) bigexist = 0;
else biggroup = group->find(arg[4]);
temperature_srd = force->numeric(FLERR,arg[5]);
gridsrd = force->numeric(FLERR,arg[6]);
int seed = force->inumeric(FLERR,arg[7]);
lamdaflag = 0;
collidestyle = NOSLIP;
overlap = 0;
insideflag = INSIDE_ERROR;
exactflag = 1;
radfactor = 1.0;
maxbounceallow = 0;
gridsearch = gridsrd;
cubicflag = CUBIC_ERROR;
cubictol = 0.01;
shiftuser = SHIFT_NO;
shiftseed = 0;
tstat = 0;
rescale_rotate = rescale_collide = 1;
int iarg = 8;
while (iarg < narg) {
if (strcmp(arg[iarg],"lamda") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
lamda = force->numeric(FLERR,arg[iarg+1]);
lamdaflag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"collision") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"slip") == 0) collidestyle = SLIP;
else if (strcmp(arg[iarg+1],"noslip") == 0) collidestyle = NOSLIP;
else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"overlap") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"yes") == 0) overlap = 1;
else if (strcmp(arg[iarg+1],"no") == 0) overlap = 0;
else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"inside") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"error") == 0) insideflag = INSIDE_ERROR;
else if (strcmp(arg[iarg+1],"warn") == 0) insideflag = INSIDE_WARN;
else if (strcmp(arg[iarg+1],"ignore") == 0) insideflag = INSIDE_IGNORE;
else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"exact") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"yes") == 0) exactflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) exactflag = 0;
else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"radius") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
radfactor = force->numeric(FLERR,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"bounce") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
maxbounceallow = force->inumeric(FLERR,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"search") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
gridsearch = force->numeric(FLERR,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"cubic") == 0) {
if (iarg+3 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"error") == 0) cubicflag = CUBIC_ERROR;
else if (strcmp(arg[iarg+1],"warn") == 0) cubicflag = CUBIC_WARN;
else error->all(FLERR,"Illegal fix srd command");
cubictol = force->numeric(FLERR,arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"shift") == 0) {
if (iarg+3 > narg) error->all(FLERR,"Illegal fix srd command");
else if (strcmp(arg[iarg+1],"no") == 0) shiftuser = SHIFT_NO;
else if (strcmp(arg[iarg+1],"yes") == 0) shiftuser = SHIFT_YES;
else if (strcmp(arg[iarg+1],"possible") == 0) shiftuser = SHIFT_POSSIBLE;
else error->all(FLERR,"Illegal fix srd command");
shiftseed = force->inumeric(FLERR,arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"tstat") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"no") == 0) tstat = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) tstat = 1;
else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"rescale") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"no") == 0)
rescale_rotate = rescale_collide = 0;
else if (strcmp(arg[iarg+1],"yes") == 0)
rescale_rotate = rescale_collide = 1;
else if (strcmp(arg[iarg+1],"rotate") == 0) {
rescale_rotate = 1;
rescale_collide = 0;
} else if (strcmp(arg[iarg+1],"collide") == 0) {
rescale_rotate = 0;
rescale_collide = 1;
}
else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else error->all(FLERR,"Illegal fix srd command");
}
if (nevery <= 0) error->all(FLERR,"Illegal fix srd command");
if (bigexist && biggroup < 0)
error->all(FLERR,"Could not find fix srd group ID");
if (gridsrd <= 0.0) error->all(FLERR,"Illegal fix srd command");
if (temperature_srd <= 0.0) error->all(FLERR,"Illegal fix srd command");
if (seed <= 0) error->all(FLERR,"Illegal fix srd command");
if (radfactor <= 0.0) error->all(FLERR,"Illegal fix srd command");
if (maxbounceallow < 0) error->all(FLERR,"Illegal fix srd command");
if (lamdaflag && lamda <= 0.0) error->all(FLERR,"Illegal fix srd command");
if (gridsearch <= 0.0) error->all(FLERR,"Illegal fix srd command");
if (cubictol < 0.0 || cubictol > 1.0)
error->all(FLERR,"Illegal fix srd command");
if ((shiftuser == SHIFT_YES || shiftuser == SHIFT_POSSIBLE) &&
shiftseed <= 0) error->all(FLERR,"Illegal fix srd command");
me = comm->me;
nprocs = comm->nprocs;
random = new RanMars(lmp,seed + me);
if (shiftuser == SHIFT_YES || shiftuser == SHIFT_POSSIBLE)
randomshift = new RanPark(lmp,shiftseed);
else randomshift = NULL;
if (bigexist) biggroupbit = group->bitmask[biggroup];
else biggroupbit = 0;
nmax = 0;
binhead = NULL;
maxbin1 = 0;
binnext = NULL;
maxbuf = 0;
sbuf1 = sbuf2 = rbuf1 = rbuf2 = NULL;
shifts[0].maxvbin = shifts[1].maxvbin = 0;
shifts[0].vbin = shifts[1].vbin = NULL;
shifts[0].maxbinsq = shifts[1].maxbinsq = 0;
for (int ishift = 0; ishift < 2; ishift++)
for (int iswap = 0; iswap < 6; iswap++)
shifts[ishift].bcomm[iswap].sendlist =
shifts[ishift].bcomm[iswap].recvlist = NULL;
maxbin2 = 0;
nbinbig = NULL;
binbig = NULL;
binsrd = NULL;
nstencil = maxstencil = 0;
stencil = NULL;
maxbig = 0;
biglist = NULL;
stats_flag = 1;
for (int i = 0; i < size_vector; i++) stats_all[i] = 0.0;
initflag = 0;
srd_bin_temp = 0.0;
srd_bin_count = 0;
avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
avec_line = (AtomVecLine *) atom->style_match("line");
avec_tri = (AtomVecTri *) atom->style_match("tri");
if (collidestyle == SLIP) comm_reverse = 3;
else comm_reverse = 6;
force_reneighbor = 1;
}
FixSRD::~FixSRD()
{
delete random;
delete randomshift;
memory->destroy(binhead);
memory->destroy(binnext);
memory->destroy(sbuf1);
memory->destroy(sbuf2);
memory->destroy(rbuf1);
memory->destroy(rbuf2);
memory->sfree(shifts[0].vbin);
memory->sfree(shifts[1].vbin);
for (int ishift = 0; ishift < 2; ishift++)
for (int iswap = 0; iswap < 6; iswap++) {
memory->destroy(shifts[ishift].bcomm[iswap].sendlist);
memory->destroy(shifts[ishift].bcomm[iswap].recvlist);
}
memory->destroy(nbinbig);
memory->destroy(binbig);
memory->destroy(binsrd);
memory->destroy(stencil);
memory->sfree(biglist);
}
int FixSRD::setmask()
{
int mask = 0;
mask |= PRE_NEIGHBOR;
mask |= POST_FORCE;
return mask;
}
void FixSRD::init()
{
if (force->newton_pair == 0)
error->all(FLERR,"Fix srd requires newton pair on");
if (bigexist && comm->ghost_velocity == 0)
error->all(FLERR,"Fix srd requires ghost atoms store velocity");
if (bigexist && collidestyle == NOSLIP && !atom->torque_flag)
error->all(FLERR,"Fix srd no-slip requires atom attribute torque");
if (initflag && update->dt != dt_big)
error->all(FLERR,"Cannot change timestep once fix srd is setup");
if (comm->style != 0)
error->universe_all(FLERR,"Fix srd can only currently be used with "
"comm_style brick");
triclinic = domain->triclinic;
wallexist = 0;
for (int m = 0; m < modify->nfix; m++) {
if (strcmp(modify->fix[m]->style,"wall/srd") == 0) {
if (wallexist) error->all(FLERR,"Cannot use fix wall/srd more than once");
wallexist = 1;
wallfix = (FixWallSRD *) modify->fix[m];
nwall = wallfix->nwall;
wallvarflag = wallfix->varflag;
wallwhich = wallfix->wallwhich;
xwall = wallfix->xwall;
xwallhold = wallfix->xwallhold;
vwall = wallfix->vwall;
fwall = wallfix->fwall;
walltrigger = 0.5 * neighbor->skin;
if (wallfix->overlap && overlap == 0 && me == 0)
error->warning(FLERR,
"Fix SRD walls overlap but fix srd overlap not set");
}
}
change_size = change_shape = deformflag = 0;
if (domain->nonperiodic == 2) change_size = 1;
for (int i = 0; i < modify->nfix; i++) {
if (modify->fix[i]->box_change_size) change_size = 1;
if (modify->fix[i]->box_change_shape) change_shape = 1;
if (strcmp(modify->fix[i]->style,"deform") == 0) {
deformflag = 1;
FixDeform *deform = (FixDeform *) modify->fix[i];
if (deform->box_change_shape && deform->remapflag != Domain::V_REMAP)
error->all(FLERR,"Using fix srd with inconsistent "
"fix deform remap option");
}
}
if (deformflag && tstat == 0 && me == 0)
error->warning(FLERR,
"Using fix srd with box deformation but no SRD thermostat");
dimension = domain->dimension;
parameterize();
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double vsq;
nrescale = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),v[i]);
}
}
int all;
MPI_Allreduce(&nrescale,&all,1,MPI_INT,MPI_SUM,world);
if (me == 0) {
if (screen)
fprintf(screen," # of rescaled SRD velocities = %d\n",all);
if (logfile)
fprintf(logfile," # of rescaled SRD velocities = %d\n",all);
}
velocity_stats(igroup);
if (bigexist) velocity_stats(biggroup);
nrescale = 0;
bouncemaxnum = 0;
bouncemax = 0;
reneighcount = 0;
initflag = 1;
next_reneighbor = -1;
}
void FixSRD::setup(int )
{
setup_bounds();
if (dist_srd_reneigh < nevery*dt_big*vmax && me == 0)
error->warning(FLERR,
"Fix srd SRD moves may trigger frequent reneighboring");
if (bigexist || wallexist) {
setup_search_bins();
setup_search_stencil();
} else nbins2 = 0;
reneighflag = BIG_MOVE;
pre_neighbor();
}
void FixSRD::pre_neighbor()
{
int i,j,m,ix,iy,iz,jx,jy,jz,ibin,jbin,lo,hi;
double rsq,cutbinsq;
if (atom->nmax > nmax) {
nmax = atom->nmax;
memory->destroy(binsrd);
memory->destroy(binnext);
memory->create(binsrd,nmax,"fix/srd:binsrd");
memory->create(binnext,nmax,"fix/srd:binnext");
}
if (bigexist || wallexist) {
if (bigexist) {
if (biggroup == atom->firstgroup) nbig = atom->nfirst + atom->nghost;
else {
int *mask = atom->mask;
int nlocal = atom->nlocal;
nbig = atom->nghost;
for (i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) nbig++;
}
} else nbig = 0;
int ninfo = nbig;
if (wallexist) ninfo += nwall;
if (ninfo > maxbig) {
maxbig = ninfo;
memory->destroy(biglist);
biglist = (Big *) memory->smalloc(maxbig*sizeof(Big),"fix/srd:biglist");
}
if (bigexist) {
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (biggroup == atom->firstgroup) nlocal = atom->nfirst;
nbig = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) biglist[nbig++].index = i;
int nall = atom->nlocal + atom->nghost;
for (i = atom->nlocal; i < nall; i++)
if (mask[i] & biggroupbit) biglist[nbig++].index = i;
big_static();
}
if (wallexist) {
for (m = 0; m < nwall; m++) {
biglist[nbig+m].index = m;
biglist[nbig+m].type = WALL;
}
wallfix->wall_params(1);
}
}
if (change_size) setup_bounds();
if (change_size) setup_velocity_bins();
if ((change_size || change_shape) && (bigexist || wallexist)) {
setup_search_bins();
setup_search_stencil();
}
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int nfirst = nlocal;
if (bigexist && biggroup == atom->firstgroup) nfirst = atom->nfirst;
if (bigexist || wallexist)
for (i = 0; i < nbins2; i++)
nbinbig[i] = 0;
if (bigexist) {
i = nbig = 0;
while (i < nall) {
if (mask[i] & biggroupbit) {
ix = static_cast<int> ((x[i][0]-xblo2)*bininv2x);
iy = static_cast<int> ((x[i][1]-yblo2)*bininv2y);
iz = static_cast<int> ((x[i][2]-zblo2)*bininv2z);
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (ix < 0 || ix >= nbin2x || iy < 0 || iy >= nbin2y ||
iz < 0 || iz >= nbin2z)
error->one(FLERR,"Fix SRD: bad search bin assignment");
cutbinsq = biglist[nbig].cutbinsq;
for (j = 0; j < nstencil; j++) {
jx = ix + stencil[j][0];
jy = iy + stencil[j][1];
jz = iz + stencil[j][2];
if (jx < 0 || jx >= nbin2x || jy < 0 || jy >= nbin2y ||
jz < 0 || jz >= nbin2z) {
if (screen) {
fprintf(screen,"Big particle " TAGINT_FORMAT " %d %g %g %g\n",
atom->tag[i],i,x[i][0],x[i][1],x[i][2]);
fprintf(screen,"Bin indices: %d %d %d, %d %d %d, %d %d %d\n",
ix,iy,iz,jx,jy,jz,nbin2x,nbin2y,nbin2z);
}
error->one(FLERR,"Fix SRD: bad stencil bin for big particle");
}
rsq = point_bin_distance(x[i],jx,jy,jz);
if (rsq < cutbinsq) {
jbin = ibin + stencil[j][3];
if (nbinbig[jbin] == ATOMPERBIN)
error->one(FLERR,"Fix SRD: too many big particles in bin");
binbig[jbin][nbinbig[jbin]++] = nbig;
}
}
nbig++;
}
i++;
if (i == nfirst) i = nlocal;
}
}
if (wallexist) {
double delta = 0.0;
if (wallvarflag) delta = walltrigger;
for (m = 0; m < nwall; m++) {
int dim = wallwhich[m] / 2;
int side = wallwhich[m] % 2;
if (dim == 0) {
if (side == 0) {
hi = static_cast<int> ((xwall[m]+delta-xblo2)*bininv2x);
if (hi < 0) continue;
if (hi >= nbin2x) error->all(FLERR,
"Fix SRD: bad search bin assignment");
lo = 0;
} else {
lo = static_cast<int> ((xwall[m]-delta-xblo2)*bininv2x);
if (lo >= nbin2x) continue;
if (lo < 0) error->all(FLERR,"Fix SRD: bad search bin assignment");
hi = nbin2x-1;
}
for (ix = lo; ix <= hi; ix++)
for (iy = 0; iy < nbin2y; iy++)
for (iz = 0; iz < nbin2z; iz++) {
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (nbinbig[ibin] == ATOMPERBIN)
error->all(FLERR,"Fix SRD: too many walls in bin");
binbig[ibin][nbinbig[ibin]++] = nbig+m;
}
} else if (dim == 1) {
if (side == 0) {
hi = static_cast<int> ((xwall[m]+delta-yblo2)*bininv2y);
if (hi < 0) continue;
if (hi >= nbin2y) error->all(FLERR,
"Fix SRD: bad search bin assignment");
lo = 0;
} else {
lo = static_cast<int> ((xwall[m]-delta-yblo2)*bininv2y);
if (lo >= nbin2y) continue;
if (lo < 0) error->all(FLERR,"Fix SRD: bad search bin assignment");
hi = nbin2y-1;
}
for (iy = lo; iy <= hi; iy++)
for (ix = 0; ix < nbin2x; ix++)
for (iz = 0; iz < nbin2z; iz++) {
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (nbinbig[ibin] == ATOMPERBIN)
error->all(FLERR,"Fix SRD: too many walls in bin");
binbig[ibin][nbinbig[ibin]++] = nbig+m;
}
} else if (dim == 2) {
if (side == 0) {
hi = static_cast<int> ((xwall[m]+delta-zblo2)*bininv2z);
if (hi < 0) continue;
if (hi >= nbin2z) error->all(FLERR,
"Fix SRD: bad search bin assignment");
lo = 0;
} else {
lo = static_cast<int> ((xwall[m]-delta-zblo2)*bininv2z);
if (lo >= nbin2z) continue;
if (lo < 0) error->all(FLERR,"Fix SRD: bad search bin assignment");
hi = nbin2z-1;
}
for (iz = lo; iz < hi; iz++)
for (ix = 0; ix < nbin2x; ix++)
for (iy = 0; iy < nbin2y; iy++) {
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (nbinbig[ibin] == ATOMPERBIN)
error->all(FLERR,"Fix SRD: too many walls in bin");
binbig[ibin][nbinbig[ibin]++] = nbig+m;
}
}
}
}
if (reneighflag == SRD_ROTATE) reset_velocities();
if (reneighflag == SRD_MOVE) reneighcount++;
reneighflag = BIG_MOVE;
}
void FixSRD::post_force(int )
{
int i,m,ix,iy,iz;
stats_flag = 0;
ncheck = ncollide = nbounce = ninside = 0;
double **f = atom->f;
double **torque = atom->torque;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (bigexist == 0) nall = 0;
for (i = nlocal; i < nall; i++)
f[i][0] = f[i][1] = f[i][2] = 0.0;
if (collidestyle == NOSLIP)
for (i = nlocal; i < nall; i++)
torque[i][0] = torque[i][1] = torque[i][2] = 0.0;
int *mask = atom->mask;
double **x = atom->x;
double **v = atom->v;
if (bigexist || wallexist) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
x[i][0] += dt_big*v[i][0];
x[i][1] += dt_big*v[i][1];
x[i][2] += dt_big*v[i][2];
ix = static_cast<int> ((x[i][0]-xblo2)*bininv2x);
iy = static_cast<int> ((x[i][1]-yblo2)*bininv2y);
iz = static_cast<int> ((x[i][2]-zblo2)*bininv2z);
binsrd[i] = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (ix < 0 || ix >= nbin2x || iy < 0 || iy >= nbin2y ||
iz < 0 || iz >= nbin2z) {
if (screen) {
fprintf(screen,"SRD particle " TAGINT_FORMAT
" on step " BIGINT_FORMAT "\n",
atom->tag[i],update->ntimestep);
fprintf(screen,"v = %g %g %g\n",v[i][0],v[i][1],v[i][2]);
fprintf(screen,"x = %g %g %g\n",x[i][0],x[i][1],x[i][2]);
fprintf(screen,"ix,iy,iz nx,ny,nz = %d %d %d %d %d %d\n",
ix,iy,iz,nbin2x,nbin2y,nbin2z);
}
error->one(FLERR,"Fix SRD: bad bin assignment for SRD advection");
}
}
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
x[i][0] += dt_big*v[i][0];
x[i][1] += dt_big*v[i][1];
x[i][2] += dt_big*v[i][2];
}
}
if (bigexist || wallexist) {
if (bigexist) big_dynamic();
if (wallexist) wallfix->wall_params(0);
if (overlap) collisions_multi();
else collisions_single();
}
if (bigexist) {
flocal = f;
tlocal = torque;
comm->reverse_comm_fix(this);
}
int flag = 0;
if (triclinic) domain->x2lamda(nlocal);
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (x[i][0] < srdlo_reneigh[0] || x[i][0] > srdhi_reneigh[0] ||
x[i][1] < srdlo_reneigh[1] || x[i][1] > srdhi_reneigh[1] ||
x[i][2] < srdlo_reneigh[2] || x[i][2] > srdhi_reneigh[2]) flag = 1;
}
if (triclinic) domain->lamda2x(nlocal);
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall) {
next_reneighbor = update->ntimestep + 1;
reneighflag = SRD_MOVE;
}
if (wallexist) {
for (m = 0; m < nwall; m++)
if (fabs(xwall[m]-xwallhold[m]) > walltrigger)
next_reneighbor = update->ntimestep + 1;
}
if ((update->ntimestep+1) % nevery == 0) {
next_reneighbor = update->ntimestep + 1;
reneighflag = SRD_ROTATE;
}
}
void FixSRD::reset_velocities()
{
int i,j,n,ix,iy,iz,ibin,axis,sign,irandom;
double u[3],vsum[3];
double vsq,tbin,scale;
double *vave,*xlamda;
double vstream[3];
if (shiftflag) {
double *boxlo;
if (triclinic == 0) boxlo = domain->boxlo;
else boxlo = domain->boxlo_lamda;
shifts[1].corner[0] = boxlo[0] - binsize1x*randomshift->uniform();
shifts[1].corner[1] = boxlo[1] - binsize1y*randomshift->uniform();
if (dimension == 3)
shifts[1].corner[2] = boxlo[2] - binsize1z*randomshift->uniform();
else shifts[1].corner[2] = boxlo[2];
setup_velocity_shift(1,1);
}
double *corner = shifts[shiftflag].corner;
int *binlo = shifts[shiftflag].binlo;
int *binhi = shifts[shiftflag].binhi;
int nbins = shifts[shiftflag].nbins;
int nbinx = shifts[shiftflag].nbinx;
int nbiny = shifts[shiftflag].nbiny;
BinAve *vbin = shifts[shiftflag].vbin;
int *mask = atom->mask;
double **x = atom->x;
double **v = atom->v;
int nlocal = atom->nlocal;
if (triclinic) domain->x2lamda(nlocal);
for (i = 0; i < nbins; i++) binhead[i] = -1;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
ix = static_cast<int> ((x[i][0]-corner[0])*bininv1x);
ix = MAX(ix,binlo[0]);
ix = MIN(ix,binhi[0]);
iy = static_cast<int> ((x[i][1]-corner[1])*bininv1y);
iy = MAX(iy,binlo[1]);
iy = MIN(iy,binhi[1]);
iz = static_cast<int> ((x[i][2]-corner[2])*bininv1z);
iz = MAX(iz,binlo[2]);
iz = MIN(iz,binhi[2]);
ibin = (iz-binlo[2])*nbiny*nbinx + (iy-binlo[1])*nbinx + (ix-binlo[0]);
binnext[i] = binhead[ibin];
binhead[ibin] = i;
}
if (triclinic) domain->lamda2x(nlocal);
for (i = 0; i < nbins; i++) {
n = 0;
vsum[0] = vsum[1] = vsum[2] = 0.0;
for (j = binhead[i]; j >= 0; j = binnext[j]) {
vsum[0] += v[j][0];
vsum[1] += v[j][1];
vsum[2] += v[j][2];
n++;
}
vbin[i].vsum[0] = vsum[0];
vbin[i].vsum[1] = vsum[1];
vbin[i].vsum[2] = vsum[2];
vbin[i].n = n;
if (vbin[i].owner) vbin[i].random = random->uniform();
else vbin[i].random = 0.0;
}
if (shifts[shiftflag].commflag) vbin_comm(shiftflag);
double tfactor = force->mvv2e * mass_srd / (dimension * force->boltz);
int dof_temp = 1;
int dof_tstat;
if (tstat) {
if (deformflag) dof_tstat = dof_temp = 0;
else dof_tstat = 1;
}
srd_bin_temp = 0.0;
srd_bin_count = 0;
if (dimension == 2) axis = 2;
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
for (i = 0; i < nbins; i++) {
vbin[i].value[0] = 0.0;
n = vbin[i].n;
if (n == 0) continue;
vave = vbin[i].vsum;
vave[0] /= n;
vave[1] /= n;
vave[2] /= n;
irandom = static_cast<int> (6.0*vbin[i].random);
sign = irandom % 2;
if (dimension == 3) axis = irandom / 2;
vsq = 0.0;
for (j = binhead[i]; j >= 0; j = binnext[j]) {
if (axis == 0) {
u[0] = v[j][0]-vave[0];
u[1] = sign ? v[j][2]-vave[2] : vave[2]-v[j][2];
u[2] = sign ? vave[1]-v[j][1] : v[j][1]-vave[1];
} else if (axis == 1) {
u[1] = v[j][1]-vave[1];
u[0] = sign ? v[j][2]-vave[2] : vave[2]-v[j][2];
u[2] = sign ? vave[0]-v[j][0] : v[j][0]-vave[0];
} else {
u[2] = v[j][2]-vave[2];
u[1] = sign ? v[j][0]-vave[0] : vave[0]-v[j][0];
u[0] = sign ? vave[1]-v[j][1] : v[j][1]-vave[1];
}
vsq += u[0]*u[0] + u[1]*u[1] + u[2]*u[2];
v[j][0] = u[0] + vave[0];
v[j][1] = u[1] + vave[1];
v[j][2] = u[2] + vave[2];
}
if (n > 1) vbin[i].value[0] = vsq;
}
if (shifts[shiftflag].commflag) xbin_comm(shiftflag,1);
if (tstat) {
for (i = 0; i < nbins; i++){
n = vbin[i].n;
if (n <= 1) continue;
vave = vbin[i].vsum;
if (deformflag) {
xlamda = vbin[i].xctr;
vstream[0] = h_rate[0]*xlamda[0] + h_rate[5]*xlamda[1] +
h_rate[4]*xlamda[2] + h_ratelo[0];
vstream[1] = h_rate[1]*xlamda[1] + h_rate[3]*xlamda[2] + h_ratelo[1];
vstream[2] = h_rate[2]*xlamda[2] + h_ratelo[2];
} else {
vstream[0] = vave[0];
vstream[1] = vave[1];
vstream[2] = vave[2];
}
tbin = vbin[i].value[0]/(n-dof_tstat) * tfactor;
scale = sqrt(temperature_srd/tbin);
vsq = 0.0;
for (j = binhead[i]; j >= 0; j = binnext[j]) {
u[0] = (v[j][0] - vave[0]) * scale;
u[1] = (v[j][1] - vave[1]) * scale;
u[2] = (v[j][2] - vave[2]) * scale;
vsq += u[0]*u[0] + u[1]*u[1] + u[2]*u[2];
v[j][0] = u[0] + vstream[0];
v[j][1] = u[1] + vstream[1];
v[j][2] = u[2] + vstream[2];
}
vbin[i].value[0] = vsq;
}
if (shifts[shiftflag].commflag) xbin_comm(shiftflag,1);
}
for (i = 0; i < nbins; i++){
if (vbin[i].owner) {
if (vbin[i].n > 1) {
srd_bin_temp += vbin[i].value[0]/(vbin[i].n-dof_temp);
srd_bin_count++;
}
}
}
srd_bin_temp *= tfactor;
if (rescale_rotate) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),v[i]);
}
}
}
}
void FixSRD::vbin_comm(int ishift)
{
BinComm *bcomm1,*bcomm2;
MPI_Request request1,request2;
BinAve *vbin = shifts[ishift].vbin;
int *procgrid = comm->procgrid;
int iswap = 0;
for (int idim = 0; idim < dimension; idim++) {
bcomm1 = &shifts[ishift].bcomm[iswap++];
bcomm2 = &shifts[ishift].bcomm[iswap++];
if (procgrid[idim] == 1) {
if (bcomm1->nsend)
vbin_pack(vbin,bcomm1->nsend,bcomm1->sendlist,sbuf1);
if (bcomm2->nsend)
vbin_pack(vbin,bcomm2->nsend,bcomm2->sendlist,sbuf2);
if (bcomm1->nrecv)
vbin_unpack(sbuf1,vbin,bcomm1->nrecv,bcomm1->recvlist);
if (bcomm2->nrecv)
vbin_unpack(sbuf2,vbin,bcomm2->nrecv,bcomm2->recvlist);
} else {
if (bcomm1->nrecv)
MPI_Irecv(rbuf1,bcomm1->nrecv*VBINSIZE,MPI_DOUBLE,bcomm1->recvproc,0,
world,&request1);
if (bcomm2->nrecv)
MPI_Irecv(rbuf2,bcomm2->nrecv*VBINSIZE,MPI_DOUBLE,bcomm2->recvproc,0,
world,&request2);
if (bcomm1->nsend) {
vbin_pack(vbin,bcomm1->nsend,bcomm1->sendlist,sbuf1);
MPI_Send(sbuf1,bcomm1->nsend*VBINSIZE,MPI_DOUBLE,
bcomm1->sendproc,0,world);
}
if (bcomm2->nsend) {
vbin_pack(vbin,bcomm2->nsend,bcomm2->sendlist,sbuf2);
MPI_Send(sbuf2,bcomm2->nsend*VBINSIZE,MPI_DOUBLE,
bcomm2->sendproc,0,world);
}
if (bcomm1->nrecv) {
MPI_Wait(&request1,MPI_STATUS_IGNORE);
vbin_unpack(rbuf1,vbin,bcomm1->nrecv,bcomm1->recvlist);
}
if (bcomm2->nrecv) {
MPI_Wait(&request2,MPI_STATUS_IGNORE);
vbin_unpack(rbuf2,vbin,bcomm2->nrecv,bcomm2->recvlist);
}
}
}
}
void FixSRD::vbin_pack(BinAve *vbin, int n, int *list, double *buf)
{
int j;
int m = 0;
for (int i = 0; i < n; i++) {
j = list[i];
buf[m++] = vbin[j].n;
buf[m++] = vbin[j].vsum[0];
buf[m++] = vbin[j].vsum[1];
buf[m++] = vbin[j].vsum[2];
buf[m++] = vbin[j].random;
}
}
void FixSRD::vbin_unpack(double *buf, BinAve *vbin, int n, int *list)
{
int j;
int m = 0;
for (int i = 0; i < n; i++) {
j = list[i];
vbin[j].n += static_cast<int> (buf[m++]);
vbin[j].vsum[0] += buf[m++];
vbin[j].vsum[1] += buf[m++];
vbin[j].vsum[2] += buf[m++];
vbin[j].random += buf[m++];
}
}
void FixSRD::xbin_comm(int ishift, int nval)
{
BinComm *bcomm1,*bcomm2;
MPI_Request request1,request2;
BinAve *vbin = shifts[ishift].vbin;
int *procgrid = comm->procgrid;
int iswap = 0;
for (int idim = 0; idim < dimension; idim++) {
bcomm1 = &shifts[ishift].bcomm[iswap++];
bcomm2 = &shifts[ishift].bcomm[iswap++];
if (procgrid[idim] == 1) {
if (bcomm1->nsend)
xbin_pack(vbin,bcomm1->nsend,bcomm1->sendlist,sbuf1,nval);
if (bcomm2->nsend)
xbin_pack(vbin,bcomm2->nsend,bcomm2->sendlist,sbuf2,nval);
if (bcomm1->nrecv)
xbin_unpack(sbuf1,vbin,bcomm1->nrecv,bcomm1->recvlist,nval);
if (bcomm2->nrecv)
xbin_unpack(sbuf2,vbin,bcomm2->nrecv,bcomm2->recvlist,nval);
} else {
if (bcomm1->nrecv)
MPI_Irecv(rbuf1,bcomm1->nrecv*nval,MPI_DOUBLE,bcomm1->recvproc,0,
world,&request1);
if (bcomm2->nrecv)
MPI_Irecv(rbuf2,bcomm2->nrecv*nval,MPI_DOUBLE,bcomm2->recvproc,0,
world,&request2);
if (bcomm1->nsend) {
xbin_pack(vbin,bcomm1->nsend,bcomm1->sendlist,sbuf1,nval);
MPI_Send(sbuf1,bcomm1->nsend*nval,MPI_DOUBLE,
bcomm1->sendproc,0,world);
}
if (bcomm2->nsend) {
xbin_pack(vbin,bcomm2->nsend,bcomm2->sendlist,sbuf2,nval);
MPI_Send(sbuf2,bcomm2->nsend*nval,MPI_DOUBLE,
bcomm2->sendproc,0,world);
}
if (bcomm1->nrecv) {
MPI_Wait(&request1,MPI_STATUS_IGNORE);
xbin_unpack(rbuf1,vbin,bcomm1->nrecv,bcomm1->recvlist,nval);
}
if (bcomm2->nrecv) {
MPI_Wait(&request2,MPI_STATUS_IGNORE);
xbin_unpack(rbuf2,vbin,bcomm2->nrecv,bcomm2->recvlist,nval);
}
}
}
}
void FixSRD::xbin_pack(BinAve *vbin, int n, int *list, double *buf, int nval)
{
int j, k;
int m = 0;
for (int i = 0; i < n; i++) {
j = list[i];
for (k = 0; k < nval; k++)
buf[m++] = vbin[j].value[k];
}
}
void FixSRD::xbin_unpack(double *buf, BinAve *vbin, int n, int *list, int nval)
{
int j, k;
int m = 0;
for (int i = 0; i < n; i++) {
j = list[i];
for (k = 0; k < nval; k++)
vbin[j].value[k] += buf[m++];
}
}
void FixSRD::collisions_single()
{
int i,j,k,m,type,nbig,ibin,ibounce,inside,collide_flag;
double dt,t_remain;
double norm[3],xscoll[3],xbcoll[3],vsnew[3];
Big *big;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (!(mask[i] & groupbit)) continue;
ibin = binsrd[i];
if (nbinbig[ibin] == 0) continue;
ibounce = 0;
collide_flag = 1;
dt = dt_big;
while (collide_flag) {
nbig = nbinbig[ibin];
if (ibounce == 0) ncheck += nbig;
collide_flag = 0;
for (m = 0; m < nbig; m++) {
k = binbig[ibin][m];
big = &biglist[k];
j = big->index;
type = big->type;
if (type == SPHERE) inside = inside_sphere(x[i],x[j],big);
else if (type == ELLIPSOID) inside = inside_ellipsoid(x[i],x[j],big);
else inside = inside_wall(x[i],j);
if (inside) {
if (exactflag) {
if (type == SPHERE)
t_remain = collision_sphere_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else if (type == ELLIPSOID)
t_remain = collision_ellipsoid_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else
t_remain = collision_wall_exact(x[i],j,v[i],xscoll,xbcoll,norm);
} else {
t_remain = 0.5*dt;
if (type == SPHERE)
collision_sphere_inexact(x[i],x[j],big,xscoll,xbcoll,norm);
else if (type == ELLIPSOID)
collision_ellipsoid_inexact(x[i],x[j],big,xscoll,xbcoll,norm);
else
collision_wall_inexact(x[i],j,xscoll,xbcoll,norm);
}
#ifdef SRD_DEBUG
if (update->ntimestep == SRD_DEBUG_TIMESTEP &&
atom->tag[i] == SRD_DEBUG_ATOMID)
print_collision(i,j,ibounce,t_remain,dt,xscoll,xbcoll,norm,type);
#endif
if (t_remain > dt) {
ninside++;
if (insideflag == INSIDE_ERROR || insideflag == INSIDE_WARN) {
char str[128];
if (type != WALL) {
sprintf(str,
"SRD particle " TAGINT_FORMAT " started "
"inside big particle " TAGINT_FORMAT
" on step " BIGINT_FORMAT " bounce %d",
atom->tag[i],atom->tag[j],update->ntimestep,ibounce+1);
if (insideflag == INSIDE_ERROR) error->one(FLERR,str);
error->warning(FLERR,str);
} else {
sprintf(str,
"SRD particle " TAGINT_FORMAT " started "
"inside wall %d on step " BIGINT_FORMAT " bounce %d",
atom->tag[i],j,update->ntimestep,ibounce+1);
if (insideflag == INSIDE_ERROR) error->one(FLERR,str);
error->warning(FLERR,str);
}
}
break;
}
if (collidestyle == SLIP) {
if (type != WALL) slip(v[i],v[j],x[j],big,xscoll,norm,vsnew);
else slip_wall(v[i],j,norm,vsnew);
} else {
if (type != WALL) noslip(v[i],v[j],x[j],big,-1, xscoll,norm,vsnew);
else noslip(v[i],NULL,x[j],big,j,xscoll,norm,vsnew);
}
if (dimension == 2) vsnew[2] = 0.0;
if (rescale_collide) {
double vsq = vsnew[0]*vsnew[0] + vsnew[1]*vsnew[1] +
vsnew[2]*vsnew[2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),vsnew);
}
}
if (collidestyle == SLIP && type == SPHERE)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],NULL);
else if (type != WALL)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],torque[j]);
else if (type == WALL)
force_wall(v[i],vsnew,j);
ibin = binsrd[i] = update_srd(i,t_remain,xscoll,vsnew,x[i],v[i]);
if (ibounce == 0) ncollide++;
ibounce++;
if (ibounce < maxbounceallow || maxbounceallow == 0)
collide_flag = 1;
dt = t_remain;
break;
}
}
}
nbounce += ibounce;
if (maxbounceallow && ibounce >= maxbounceallow) bouncemaxnum++;
if (ibounce > bouncemax) bouncemax = ibounce;
}
}
void FixSRD::collisions_multi()
{
int i,j,k,m,type,nbig,ibin,ibounce,inside,jfirst,typefirst,jlast;
double dt,t_remain,t_first;
double norm[3],xscoll[3],xbcoll[3],vsnew[3];
double normfirst[3],xscollfirst[3],xbcollfirst[3];
Big *big;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (!(mask[i] & groupbit)) continue;
ibin = binsrd[i];
if (nbinbig[ibin] == 0) continue;
ibounce = 0;
jlast = -1;
dt = dt_big;
while (1) {
nbig = nbinbig[ibin];
if (ibounce == 0) ncheck += nbig;
t_first = 0.0;
for (m = 0; m < nbig; m++) {
k = binbig[ibin][m];
big = &biglist[k];
j = big->index;
if (j == jlast) continue;
type = big->type;
if (type == SPHERE)
inside = inside_sphere(x[i],x[j],big);
else if (type == ELLIPSOID)
inside = inside_ellipsoid(x[i],x[j],big);
else if (type == LINE)
inside = inside_line(x[i],x[j],v[i],v[j],big,dt);
else if (type == TRIANGLE)
inside = inside_tri(x[i],x[j],v[i],v[j],big,dt);
else
inside = inside_wall(x[i],j);
if (inside) {
if (type == SPHERE)
t_remain = collision_sphere_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else if (type == ELLIPSOID)
t_remain = collision_ellipsoid_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else if (type == LINE)
t_remain = collision_line_exact(x[i],x[j],v[i],v[j],big,dt,
xscoll,xbcoll,norm);
else if (type == TRIANGLE)
t_remain = collision_tri_exact(x[i],x[j],v[i],v[j],big,dt,
xscoll,xbcoll,norm);
else
t_remain = collision_wall_exact(x[i],j,v[i],xscoll,xbcoll,norm);
#ifdef SRD_DEBUG
if (update->ntimestep == SRD_DEBUG_TIMESTEP &&
atom->tag[i] == SRD_DEBUG_ATOMID)
print_collision(i,j,ibounce,t_remain,dt,xscoll,xbcoll,norm,type);
#endif
if (t_remain > dt || t_remain < 0.0) {
ninside++;
if (insideflag == INSIDE_ERROR || insideflag == INSIDE_WARN) {
char str[128];
if (type != WALL) {
sprintf(str,
"SRD particle " TAGINT_FORMAT " started "
"inside big particle " TAGINT_FORMAT
" on step " BIGINT_FORMAT " bounce %d",
atom->tag[i],atom->tag[j],update->ntimestep,ibounce+1);
if (insideflag == INSIDE_ERROR) error->one(FLERR,str);
error->warning(FLERR,str);
} else {
sprintf(str,
"SRD particle " TAGINT_FORMAT " started "
"inside wall %d on step " BIGINT_FORMAT " bounce %d",
atom->tag[i],j,update->ntimestep,ibounce+1);
if (insideflag == INSIDE_ERROR) error->one(FLERR,str);
error->warning(FLERR,str);
}
}
t_first = 0.0;
break;
}
if (t_remain > t_first) {
t_first = t_remain;
jfirst = j;
typefirst = type;
xscollfirst[0] = xscoll[0];
xscollfirst[1] = xscoll[1];
xscollfirst[2] = xscoll[2];
xbcollfirst[0] = xbcoll[0];
xbcollfirst[1] = xbcoll[1];
xbcollfirst[2] = xbcoll[2];
normfirst[0] = norm[0];
normfirst[1] = norm[1];
normfirst[2] = norm[2];
}
}
}
if (t_first == 0.0) break;
j = jlast = jfirst;
type = typefirst;
xscoll[0] = xscollfirst[0];
xscoll[1] = xscollfirst[1];
xscoll[2] = xscollfirst[2];
xbcoll[0] = xbcollfirst[0];
xbcoll[1] = xbcollfirst[1];
xbcoll[2] = xbcollfirst[2];
norm[0] = normfirst[0];
norm[1] = normfirst[1];
norm[2] = normfirst[2];
if (collidestyle == SLIP) {
if (type != WALL) slip(v[i],v[j],x[j],big,xscoll,norm,vsnew);
else slip_wall(v[i],j,norm,vsnew);
} else {
if (type != WALL) noslip(v[i],v[j],x[j],big,-1,xscoll,norm,vsnew);
else noslip(v[i],NULL,x[j],big,j,xscoll,norm,vsnew);
}
if (dimension == 2) vsnew[2] = 0.0;
if (rescale_collide) {
double vsq = vsnew[0]*vsnew[0] + vsnew[1]*vsnew[1] + vsnew[2]*vsnew[2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),vsnew);
}
}
if (collidestyle == SLIP && type == SPHERE)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],NULL);
else if (type != WALL)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],torque[j]);
else if (type == WALL)
force_wall(v[i],vsnew,j);
ibin = binsrd[i] = update_srd(i,t_first,xscoll,vsnew,x[i],v[i]);
if (ibounce == 0) ncollide++;
ibounce++;
if (ibounce == maxbounceallow) break;
dt = t_first;
}
nbounce += ibounce;
if (maxbounceallow && ibounce >= maxbounceallow) bouncemaxnum++;
if (ibounce > bouncemax) bouncemax = ibounce;
}
}
int FixSRD::inside_sphere(double *xs, double *xb, Big *big)
{
double dx,dy,dz;
dx = xs[0] - xb[0];
dy = xs[1] - xb[1];
dz = xs[2] - xb[2];
if (dx*dx + dy*dy + dz*dz <= big->radsq) return 1;
return 0;
}
int FixSRD::inside_ellipsoid(double *xs, double *xb, Big *big)
{
double x,y,z;
double *ex = big->ex;
double *ey = big->ey;
double *ez = big->ez;
double xs_xb[3];
xs_xb[0] = xs[0] - xb[0];
xs_xb[1] = xs[1] - xb[1];
xs_xb[2] = xs[2] - xb[2];
x = xs_xb[0]*ex[0] + xs_xb[1]*ex[1] + xs_xb[2]*ex[2];
y = xs_xb[0]*ey[0] + xs_xb[1]*ey[1] + xs_xb[2]*ey[2];
z = xs_xb[0]*ez[0] + xs_xb[1]*ez[1] + xs_xb[2]*ez[2];
if (x*x*big->aradsqinv + y*y*big->bradsqinv + z*z*big->cradsqinv <= 1.0)
return 1;
return 0;
}
int FixSRD::inside_line(double *xs, double *xb, double *vs, double *vb,
Big *big, double dt_step)
{
double pmc0[2],pmc1[2],n0[2],n1[2];
xs1[0] = xs[0];
xs1[1] = xs[1];
xb1[0] = xb[0];
xb1[1] = xb[1];
xs0[0] = xs1[0] - dt_step*vs[0];
xs0[1] = xs1[1] - dt_step*vs[1];
xb0[0] = xb1[0] - dt_step*vb[0];
xb0[1] = xb1[1] - dt_step*vb[1];
theta1 = big->theta;
theta0 = theta1 - dt_step*big->omega[2];
pmc0[0] = xs0[0] - xb0[0];
pmc0[1] = xs0[1] - xb0[1];
n0[0] = sin(theta0);
n0[1] = -cos(theta0);
pmc1[0] = xs1[0] - xb1[0];
pmc1[1] = xs1[1] - xb1[1];
n1[0] = sin(theta1);
n1[1] = -cos(theta1);
double side0 = pmc0[0]*n0[0] + pmc0[1]*n0[1];
double side1 = pmc1[0]*n1[0] + pmc1[1]*n1[1];
if (side0 <= 0.0 || side1 >= 0.0) return 0;
tfraction = newton_raphson(0.0,1.0);
xsc[0] = xs0[0] + tfraction*(xs1[0]-xs0[0]);
xsc[1] = xs0[1] + tfraction*(xs1[1]-xs0[1]);
xbc[0] = xb0[0] + tfraction*(xb1[0]-xb0[0]);
xbc[1] = xb0[1] + tfraction*(xb1[1]-xb0[1]);
double delx = xsc[0] - xbc[0];
double dely = xsc[1] - xbc[1];
double rsq = delx*delx + dely*dely;
if (rsq > 0.25*big->length*big->length) return 0;
nbc[0] = sin(theta0 + tfraction*(theta1-theta0));
nbc[1] = -cos(theta0 + tfraction*(theta1-theta0));
return 1;
}
int FixSRD::inside_tri(double *xs, double *xb, double *vs, double *vb,
Big *big, double dt_step)
{
double pmc0[3],pmc1[3],n0[3];
double n1_n0[3],pmc1_pmc0[3];
double excoll[3],eycoll[3],ezcoll[3];
double dc1[3],dc2[3],dc3[3];
double c1[3],c2[3],c3[3];
double c2mc1[3],c3mc2[3],c1mc3[3];
double pvec[3],xproduct[3];
double *omega = big->omega;
double *n1 = big->norm;
n0[0] = n1[0] - dt_step*(omega[1]*n1[2] - omega[2]*n1[1]);
n0[1] = n1[1] - dt_step*(omega[2]*n1[0] - omega[0]*n1[2]);
n0[2] = n1[2] - dt_step*(omega[0]*n1[1] - omega[1]*n1[0]);
pmc0[0] = xs[0] - dt_step*vs[0] - xb[0] + dt_step*vb[0];
pmc0[1] = xs[1] - dt_step*vs[1] - xb[1] + dt_step*vb[1];
pmc0[2] = xs[2] - dt_step*vs[2] - xb[2] + dt_step*vb[2];
pmc1[0] = xs[0] - xb[0];
pmc1[1] = xs[1] - xb[1];
pmc1[2] = xs[2] - xb[2];
double side0 = MathExtra::dot3(pmc0,n0);
double side1 = MathExtra::dot3(pmc1,n1);
if (side0 <= 0.0 || side1 >= 0.0) return 0;
n1_n0[0] = n1[0]-n0[0];
n1_n0[1] = n1[1]-n0[1];
n1_n0[2] = n1[2]-n0[2];
pmc1_pmc0[0] = pmc1[0]-pmc0[0];
pmc1_pmc0[1] = pmc1[1]-pmc0[1];
pmc1_pmc0[2] = pmc1[2]-pmc0[2];
double a = MathExtra::dot3(pmc1_pmc0,n1_n0);
double b = MathExtra::dot3(pmc1_pmc0,n0) + MathExtra::dot3(n1_n0,pmc0);
double c = MathExtra::dot3(pmc0,n0);
if (a == 0.0) {
double dot0 = MathExtra::dot3(pmc0,n0);
double dot1 = MathExtra::dot3(pmc1,n0);
double root = -dot0 / (dot1 - dot0);
tfraction = root;
} else {
double term = sqrt(b*b - 4.0*a*c);
double root1 = (-b + term) / (2.0*a);
double root2 = (-b - term) / (2.0*a);
if (0.0 <= root1 && root1 <= 1.0) tfraction = root1;
else if (0.0 <= root2 && root2 <= 1.0) tfraction = root2;
else error->one(FLERR,"Bad quadratic solve for particle/tri collision");
}
AtomVecTri::Bonus *tbonus;
tbonus = avec_tri->bonus;
double *ex = big->ex;
double *ey = big->ey;
double *ez = big->ez;
int index = atom->tri[big->index];
double *c1body = tbonus[index].c1;
double *c2body = tbonus[index].c2;
double *c3body = tbonus[index].c3;
double dt = (1.0-tfraction)*dt_step;
xsc[0] = xs[0] - dt*vs[0];
xsc[1] = xs[1] - dt*vs[1];
xsc[2] = xs[2] - dt*vs[2];
xbc[0] = xb[0] - dt*vb[0];
xbc[1] = xb[1] - dt*vb[1];
xbc[2] = xb[2] - dt*vb[2];
excoll[0] = ex[0] - dt*(omega[1]*ex[2] - omega[2]*ex[1]);
excoll[1] = ex[1] - dt*(omega[2]*ex[0] - omega[0]*ex[2]);
excoll[2] = ex[2] - dt*(omega[0]*ex[1] - omega[1]*ex[0]);
eycoll[0] = ey[0] - dt*(omega[1]*ey[2] - omega[2]*ey[1]);
eycoll[1] = ey[1] - dt*(omega[2]*ey[0] - omega[0]*ey[2]);
eycoll[2] = ey[2] - dt*(omega[0]*ey[1] - omega[1]*ey[0]);
ezcoll[0] = ez[0] - dt*(omega[1]*ez[2] - omega[2]*ez[1]);
ezcoll[1] = ez[1] - dt*(omega[2]*ez[0] - omega[0]*ez[2]);
ezcoll[2] = ez[2] - dt*(omega[0]*ez[1] - omega[1]*ez[0]);
MathExtra::matvec(excoll,eycoll,ezcoll,c1body,dc1);
MathExtra::matvec(excoll,eycoll,ezcoll,c2body,dc2);
MathExtra::matvec(excoll,eycoll,ezcoll,c3body,dc3);
MathExtra::add3(xbc,dc1,c1);
MathExtra::add3(xbc,dc2,c2);
MathExtra::add3(xbc,dc3,c3);
MathExtra::sub3(c2,c1,c2mc1);
MathExtra::sub3(c3,c2,c3mc2);
MathExtra::sub3(c1,c3,c1mc3);
MathExtra::cross3(c2mc1,c3mc2,nbc);
MathExtra::norm3(nbc);
MathExtra::sub3(xsc,c1,pvec);
MathExtra::cross3(c2mc1,pvec,xproduct);
if (MathExtra::dot3(xproduct,nbc) < 0.0) return 0;
MathExtra::sub3(xsc,c2,pvec);
MathExtra::cross3(c3mc2,pvec,xproduct);
if (MathExtra::dot3(xproduct,nbc) < 0.0) return 0;
MathExtra::sub3(xsc,c3,pvec);
MathExtra::cross3(c1mc3,pvec,xproduct);
if (MathExtra::dot3(xproduct,nbc) < 0.0) return 0;
return 1;
}
int FixSRD::inside_wall(double *xs, int iwall)
{
int dim = wallwhich[iwall] / 2;
int side = wallwhich[iwall] % 2;
if (side == 0 && xs[dim] < xwall[iwall]) return 1;
if (side && xs[dim] > xwall[iwall]) return 1;
return 0;
}
double FixSRD::collision_sphere_exact(double *xs, double *xb,
double *vs, double *vb, Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double vs_dot_vs,vb_dot_vb,vs_dot_vb;
double vs_dot_xb,vb_dot_xs,vs_dot_xs,vb_dot_xb;
double xs_dot_xs,xb_dot_xb,xs_dot_xb;
double a,b,c,scale;
vs_dot_vs = vs[0]*vs[0] + vs[1]*vs[1] + vs[2]*vs[2];
vb_dot_vb = vb[0]*vb[0] + vb[1]*vb[1] + vb[2]*vb[2];
vs_dot_vb = vs[0]*vb[0] + vs[1]*vb[1] + vs[2]*vb[2];
vs_dot_xb = vs[0]*xb[0] + vs[1]*xb[1] + vs[2]*xb[2];
vb_dot_xs = vb[0]*xs[0] + vb[1]*xs[1] + vb[2]*xs[2];
vs_dot_xs = vs[0]*xs[0] + vs[1]*xs[1] + vs[2]*xs[2];
vb_dot_xb = vb[0]*xb[0] + vb[1]*xb[1] + vb[2]*xb[2];
xs_dot_xs = xs[0]*xs[0] + xs[1]*xs[1] + xs[2]*xs[2];
xb_dot_xb = xb[0]*xb[0] + xb[1]*xb[1] + xb[2]*xb[2];
xs_dot_xb = xs[0]*xb[0] + xs[1]*xb[1] + xs[2]*xb[2];
a = vs_dot_vs + vb_dot_vb - 2.0*vs_dot_vb;
b = 2.0 * (vs_dot_xb + vb_dot_xs - vs_dot_xs - vb_dot_xb);
c = xs_dot_xs + xb_dot_xb - 2.0*xs_dot_xb - big->radsq;
double dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);
xscoll[0] = xs[0] - dt*vs[0];
xscoll[1] = xs[1] - dt*vs[1];
xscoll[2] = xs[2] - dt*vs[2];
xbcoll[0] = xb[0] - dt*vb[0];
xbcoll[1] = xb[1] - dt*vb[1];
xbcoll[2] = xb[2] - dt*vb[2];
norm[0] = xscoll[0] - xbcoll[0];
norm[1] = xscoll[1] - xbcoll[1];
norm[2] = xscoll[2] - xbcoll[2];
scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
norm[0] *= scale;
norm[1] *= scale;
norm[2] *= scale;
return dt;
}
void FixSRD::collision_sphere_inexact(double *xs, double *xb,
Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double scale;
norm[0] = xs[0] - xb[0];
norm[1] = xs[1] - xb[1];
norm[2] = xs[2] - xb[2];
scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
norm[0] *= scale;
norm[1] *= scale;
norm[2] *= scale;
xscoll[0] = xb[0] + big->radius*norm[0];
xscoll[1] = xb[1] + big->radius*norm[1];
xscoll[2] = xb[2] + big->radius*norm[2];
xbcoll[0] = xb[0];
xbcoll[1] = xb[1];
xbcoll[2] = xb[2];
}
double FixSRD::collision_ellipsoid_exact(double *xs, double *xb,
double *vs, double *vb, Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double vs_vb[3],xs_xb[3],omega_ex[3],omega_ey[3],omega_ez[3];
double excoll[3],eycoll[3],ezcoll[3],delta[3],xbody[3],nbody[3];
double ax,bx,cx,ay,by,cy,az,bz,cz;
double a,b,c;
double *omega = big->omega;
double *ex = big->ex;
double *ey = big->ey;
double *ez = big->ez;
vs_vb[0] = vs[0]-vb[0]; vs_vb[1] = vs[1]-vb[1]; vs_vb[2] = vs[2]-vb[2];
xs_xb[0] = xs[0]-xb[0]; xs_xb[1] = xs[1]-xb[1]; xs_xb[2] = xs[2]-xb[2];
MathExtra::cross3(omega,ex,omega_ex);
MathExtra::cross3(omega,ey,omega_ey);
MathExtra::cross3(omega,ez,omega_ez);
ax = vs_vb[0]*omega_ex[0] + vs_vb[1]*omega_ex[1] + vs_vb[2]*omega_ex[2];
bx = -(vs_vb[0]*ex[0] + vs_vb[1]*ex[1] + vs_vb[2]*ex[2]);
bx -= xs_xb[0]*omega_ex[0] + xs_xb[1]*omega_ex[1] + xs_xb[2]*omega_ex[2];
cx = xs_xb[0]*ex[0] + xs_xb[1]*ex[1] + xs_xb[2]*ex[2];
ay = vs_vb[0]*omega_ey[0] + vs_vb[1]*omega_ey[1] + vs_vb[2]*omega_ey[2];
by = -(vs_vb[0]*ey[0] + vs_vb[1]*ey[1] + vs_vb[2]*ey[2]);
by -= xs_xb[0]*omega_ey[0] + xs_xb[1]*omega_ey[1] + xs_xb[2]*omega_ey[2];
cy = xs_xb[0]*ey[0] + xs_xb[1]*ey[1] + xs_xb[2]*ey[2];
az = vs_vb[0]*omega_ez[0] + vs_vb[1]*omega_ez[1] + vs_vb[2]*omega_ez[2];
bz = -(vs_vb[0]*ez[0] + vs_vb[1]*ez[1] + vs_vb[2]*ez[2]);
bz -= xs_xb[0]*omega_ez[0] + xs_xb[1]*omega_ez[1] + xs_xb[2]*omega_ez[2];
cz = xs_xb[0]*ez[0] + xs_xb[1]*ez[1] + xs_xb[2]*ez[2];
a = (bx*bx + 2.0*ax*cx)*big->aradsqinv +
(by*by + 2.0*ay*cy)*big->bradsqinv +
(bz*bz + 2.0*az*cz)*big->cradsqinv;
b = 2.0 * (bx*cx*big->aradsqinv + by*cy*big->bradsqinv +
bz*cz*big->cradsqinv);
c = cx*cx*big->aradsqinv + cy*cy*big->bradsqinv +
cz*cz*big->cradsqinv - 1.0;
double dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);
xscoll[0] = xs[0] - dt*vs[0];
xscoll[1] = xs[1] - dt*vs[1];
xscoll[2] = xs[2] - dt*vs[2];
xbcoll[0] = xb[0] - dt*vb[0];
xbcoll[1] = xb[1] - dt*vb[1];
xbcoll[2] = xb[2] - dt*vb[2];
excoll[0] = ex[0] - dt*(omega[1]*ex[2] - omega[2]*ex[1]);
excoll[1] = ex[1] - dt*(omega[2]*ex[0] - omega[0]*ex[2]);
excoll[2] = ex[2] - dt*(omega[0]*ex[1] - omega[1]*ex[0]);
eycoll[0] = ey[0] - dt*(omega[1]*ey[2] - omega[2]*ey[1]);
eycoll[1] = ey[1] - dt*(omega[2]*ey[0] - omega[0]*ey[2]);
eycoll[2] = ey[2] - dt*(omega[0]*ey[1] - omega[1]*ey[0]);
ezcoll[0] = ez[0] - dt*(omega[1]*ez[2] - omega[2]*ez[1]);
ezcoll[1] = ez[1] - dt*(omega[2]*ez[0] - omega[0]*ez[2]);
ezcoll[2] = ez[2] - dt*(omega[0]*ez[1] - omega[1]*ez[0]);
MathExtra::sub3(xscoll,xbcoll,delta);
MathExtra::transpose_matvec(excoll,eycoll,ezcoll,delta,xbody);
nbody[0] = xbody[0]*big->aradsqinv;
nbody[1] = xbody[1]*big->bradsqinv;
nbody[2] = xbody[2]*big->cradsqinv;
MathExtra::matvec(excoll,eycoll,ezcoll,nbody,norm);
MathExtra::norm3(norm);
return dt;
}
void FixSRD::collision_ellipsoid_inexact(double *xs, double *xb,
Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double xs_xb[3],delta[3],xbody[3],nbody[3];
double *ex = big->ex;
double *ey = big->ey;
double *ez = big->ez;
MathExtra::sub3(xs,xb,xs_xb);
double x = MathExtra::dot3(xs_xb,ex);
double y = MathExtra::dot3(xs_xb,ey);
double z = MathExtra::dot3(xs_xb,ez);
double scale = 1.0/sqrt(x*x*big->aradsqinv + y*y*big->bradsqinv +
z*z*big->cradsqinv);
x *= scale;
y *= scale;
z *= scale;
xscoll[0] = x*ex[0] + y*ey[0] + z*ez[0] + xb[0];
xscoll[1] = x*ex[1] + y*ey[1] + z*ez[1] + xb[1];
xscoll[2] = x*ex[2] + y*ey[2] + z*ez[2] + xb[2];
xbcoll[0] = xb[0];
xbcoll[1] = xb[1];
xbcoll[2] = xb[2];
MathExtra::sub3(xscoll,xbcoll,delta);
MathExtra::transpose_matvec(ex,ey,ez,delta,xbody);
nbody[0] = xbody[0]*big->aradsqinv;
nbody[1] = xbody[1]*big->bradsqinv;
nbody[2] = xbody[2]*big->cradsqinv;
MathExtra::matvec(ex,ey,ez,nbody,norm);
MathExtra::norm3(norm);
}
double FixSRD::collision_line_exact(double * , double * ,
double * , double * , Big * ,
double dt_step,
double *xscoll, double *xbcoll,
double *norm)
{
xscoll[0] = xsc[0];
xscoll[1] = xsc[1];
xscoll[2] = 0.0;
xbcoll[0] = xbc[0];
xbcoll[1] = xbc[1];
xbcoll[2] = 0.0;
norm[0] = nbc[0];
norm[1] = nbc[1];
norm[2] = 0.0;
return (1.0-tfraction)*dt_step;
}
double FixSRD::collision_tri_exact(double * , double * ,
double * , double * , Big * ,
double dt_step,
double *xscoll, double *xbcoll,
double *norm)
{
xscoll[0] = xsc[0];
xscoll[1] = xsc[1];
xscoll[2] = xsc[2];
xbcoll[0] = xbc[0];
xbcoll[1] = xbc[1];
xbcoll[2] = xbc[2];
norm[0] = nbc[0];
norm[1] = nbc[1];
norm[2] = nbc[2];
return (1.0-tfraction)*dt_step;
}
double FixSRD::collision_wall_exact(double *xs, int iwall, double *vs,
double *xscoll, double *xbcoll,
double *norm)
{
int dim = wallwhich[iwall] / 2;
double dt = (xs[dim] - xwall[iwall]) / (vs[dim] - vwall[iwall]);
xscoll[0] = xs[0] - dt*vs[0];
xscoll[1] = xs[1] - dt*vs[1];
xscoll[2] = xs[2] - dt*vs[2];
xbcoll[0] = xbcoll[1] = xbcoll[2] = 0.0;
xbcoll[dim] = xwall[iwall] - dt*vwall[iwall];
int side = wallwhich[iwall] % 2;
norm[0] = norm[1] = norm[2] = 0.0;
if (side == 0) norm[dim] = 1.0;
else norm[dim] = -1.0;
return dt;
}
void FixSRD::collision_wall_inexact(double *xs, int iwall, double *xscoll,
double *xbcoll, double *norm)
{
int dim = wallwhich[iwall] / 2;
xscoll[0] = xs[0];
xscoll[1] = xs[1];
xscoll[2] = xs[2];
xscoll[dim] = xwall[iwall];
xbcoll[0] = xbcoll[1] = xbcoll[2] = 0.0;
xbcoll[dim] = xwall[iwall];
int side = wallwhich[iwall] % 2;
norm[0] = norm[1] = norm[2] = 0.0;
if (side == 0) norm[dim] = 1.0;
else norm[dim] = -1.0;
}
void FixSRD::slip(double *vs, double *vb, double *xb, Big *big,
double *xsurf, double *norm, double *vsnew)
{
double r1,r2,vnmag,vs_dot_n,vsurf_dot_n;
double tangent[3],vsurf[3];
double *omega = big->omega;
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
if (vnmag*vnmag <= vmaxsq) break;
}
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent[0] = vs[0] - vs_dot_n*norm[0];
tangent[1] = vs[1] - vs_dot_n*norm[1];
tangent[2] = vs[2] - vs_dot_n*norm[2];
vsurf[0] = vb[0] + omega[1]*(xsurf[2]-xb[2]) - omega[2]*(xsurf[1]-xb[1]);
vsurf[1] = vb[1] + omega[2]*(xsurf[0]-xb[0]) - omega[0]*(xsurf[2]-xb[2]);
vsurf[2] = vb[2] + omega[0]*(xsurf[1]-xb[1]) - omega[1]*(xsurf[0]-xb[0]);
vsurf_dot_n = vsurf[0]*norm[0] + vsurf[1]*norm[1] + vsurf[2]*norm[2];
vsnew[0] = (vnmag+vsurf_dot_n)*norm[0] + tangent[0];
vsnew[1] = (vnmag+vsurf_dot_n)*norm[1] + tangent[1];
vsnew[2] = (vnmag+vsurf_dot_n)*norm[2] + tangent[2];
}
void FixSRD::slip_wall(double *vs, int iwall, double *norm, double *vsnew)
{
double vs_dot_n,scale,r1,r2,vnmag,vtmag1,vtmag2;
double tangent1[3],tangent2[3];
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent1[0] = vs[0] - vs_dot_n*norm[0];
tangent1[1] = vs[1] - vs_dot_n*norm[1];
tangent1[2] = vs[2] - vs_dot_n*norm[2];
scale = 1.0/sqrt(tangent1[0]*tangent1[0] + tangent1[1]*tangent1[1] +
tangent1[2]*tangent1[2]);
tangent1[0] *= scale;
tangent1[1] *= scale;
tangent1[2] *= scale;
tangent2[0] = norm[1]*tangent1[2] - norm[2]*tangent1[1];
tangent2[1] = norm[2]*tangent1[0] - norm[0]*tangent1[2];
tangent2[2] = norm[0]*tangent1[1] - norm[1]*tangent1[0];
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
vtmag1 = sigma * random->gaussian();
vtmag2 = sigma * random->gaussian();
if (vnmag*vnmag + vtmag1*vtmag1 + vtmag2*vtmag2 <= vmaxsq) break;
}
vsnew[0] = vnmag*norm[0] + vtmag1*tangent1[0] + vtmag2*tangent2[0];
vsnew[1] = vnmag*norm[1] + vtmag1*tangent1[1] + vtmag2*tangent2[1];
vsnew[2] = vnmag*norm[2] + vtmag1*tangent1[2] + vtmag2*tangent2[2];
int dim = wallwhich[iwall] / 2;
vsnew[dim] += vwall[iwall];
}
void FixSRD::noslip(double *vs, double *vb, double *xb, Big *big, int iwall,
double *xsurf, double *norm, double *vsnew)
{
double vs_dot_n,scale,r1,r2,vnmag,vtmag1,vtmag2;
double tangent1[3],tangent2[3];
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent1[0] = vs[0] - vs_dot_n*norm[0];
tangent1[1] = vs[1] - vs_dot_n*norm[1];
tangent1[2] = vs[2] - vs_dot_n*norm[2];
scale = 1.0/sqrt(tangent1[0]*tangent1[0] + tangent1[1]*tangent1[1] +
tangent1[2]*tangent1[2]);
tangent1[0] *= scale;
tangent1[1] *= scale;
tangent1[2] *= scale;
tangent2[0] = norm[1]*tangent1[2] - norm[2]*tangent1[1];
tangent2[1] = norm[2]*tangent1[0] - norm[0]*tangent1[2];
tangent2[2] = norm[0]*tangent1[1] - norm[1]*tangent1[0];
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
vtmag1 = sigma * random->gaussian();
vtmag2 = sigma * random->gaussian();
if (vnmag*vnmag + vtmag1*vtmag1 + vtmag2*vtmag2 <= vmaxsq) break;
}
vsnew[0] = vnmag*norm[0] + vtmag1*tangent1[0] + vtmag2*tangent2[0];
vsnew[1] = vnmag*norm[1] + vtmag1*tangent1[1] + vtmag2*tangent2[1];
vsnew[2] = vnmag*norm[2] + vtmag1*tangent1[2] + vtmag2*tangent2[2];
if (big->type == WALL) {
int dim = wallwhich[iwall] / 2;
vsnew[dim] += vwall[iwall];
} else {
double *omega = big->omega;
vsnew[0] += vb[0] + omega[1]*(xsurf[2]-xb[2]) - omega[2]*(xsurf[1]-xb[1]);
vsnew[1] += vb[1] + omega[2]*(xsurf[0]-xb[0]) - omega[0]*(xsurf[2]-xb[2]);
vsnew[2] += vb[2] + omega[0]*(xsurf[1]-xb[1]) - omega[1]*(xsurf[0]-xb[0]);
}
}
void FixSRD::force_torque(double *vsold, double *vsnew,
double *xs, double *xb,
double *fb, double *tb)
{
double dpdt[3],xs_xb[3];
double factor = mass_srd / dt_big / force->ftm2v;
dpdt[0] = factor * (vsnew[0] - vsold[0]);
dpdt[1] = factor * (vsnew[1] - vsold[1]);
dpdt[2] = factor * (vsnew[2] - vsold[2]);
fb[0] -= dpdt[0];
fb[1] -= dpdt[1];
fb[2] -= dpdt[2];
if (tb) {
xs_xb[0] = xs[0]-xb[0];
xs_xb[1] = xs[1]-xb[1];
xs_xb[2] = xs[2]-xb[2];
tb[0] -= xs_xb[1]*dpdt[2] - xs_xb[2]*dpdt[1];
tb[1] -= xs_xb[2]*dpdt[0] - xs_xb[0]*dpdt[2];
tb[2] -= xs_xb[0]*dpdt[1] - xs_xb[1]*dpdt[0];
}
}
void FixSRD::force_wall(double *vsold, double *vsnew, int iwall)
{
double dpdt[3];
double factor = mass_srd / dt_big / force->ftm2v;
dpdt[0] = factor * (vsnew[0] - vsold[0]);
dpdt[1] = factor * (vsnew[1] - vsold[1]);
dpdt[2] = factor * (vsnew[2] - vsold[2]);
fwall[iwall][0] -= dpdt[0];
fwall[iwall][1] -= dpdt[1];
fwall[iwall][2] -= dpdt[2];
}
int FixSRD::update_srd(int i, double dt, double *xscoll, double *vsnew,
double *xs, double *vs)
{
int ix,iy,iz;
vs[0] = vsnew[0];
vs[1] = vsnew[1];
vs[2] = vsnew[2];
xs[0] = xscoll[0] + dt*vsnew[0];
xs[1] = xscoll[1] + dt*vsnew[1];
xs[2] = xscoll[2] + dt*vsnew[2];
if (triclinic) domain->x2lamda(xs,xs);
if (xs[0] < srdlo[0] || xs[0] > srdhi[0] ||
xs[1] < srdlo[1] || xs[1] > srdhi[1] ||
xs[2] < srdlo[2] || xs[2] > srdhi[2]) {
if (screen) {
error->warning(FLERR,"Fix srd particle moved outside valid domain");
fprintf(screen," particle " TAGINT_FORMAT
" on proc %d at timestep " BIGINT_FORMAT,
atom->tag[i],me,update->ntimestep);
fprintf(screen," xnew %g %g %g\n",xs[0],xs[1],xs[2]);
fprintf(screen," srdlo/hi x %g %g\n",srdlo[0],srdhi[0]);
fprintf(screen," srdlo/hi y %g %g\n",srdlo[1],srdhi[1]);
fprintf(screen," srdlo/hi z %g %g\n",srdlo[2],srdhi[2]);
}
}
if (triclinic) domain->lamda2x(xs,xs);
ix = static_cast<int> ((xs[0]-xblo2)*bininv2x);
iy = static_cast<int> ((xs[1]-yblo2)*bininv2y);
iz = static_cast<int> ((xs[2]-zblo2)*bininv2z);
return iz*nbin2y*nbin2x + iy*nbin2x + ix;
}
void FixSRD::parameterize()
{
dt_big = update->dt;
dt_srd = nevery * update->dt;
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
AtomVecLine::Bonus *lbonus;
if (avec_line) lbonus = avec_line->bonus;
AtomVecTri::Bonus *tbonus;
if (avec_tri) tbonus = avec_tri->bonus;
double *radius = atom->radius;
int *ellipsoid = atom->ellipsoid;
int *line = atom->line;
int *tri = atom->tri;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int any_ellipsoids = 0;
int any_lines = 0;
int any_tris = 0;
maxbigdiam = 0.0;
minbigdiam = BIG;
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) {
if (radius && radius[i] > 0.0) {
maxbigdiam = MAX(maxbigdiam,2.0*radius[i]);
minbigdiam = MIN(minbigdiam,2.0*radius[i]);
} else if (ellipsoid && ellipsoid[i] >= 0) {
any_ellipsoids = 1;
double *shape = ebonus[ellipsoid[i]].shape;
maxbigdiam = MAX(maxbigdiam,2.0*shape[0]);
maxbigdiam = MAX(maxbigdiam,2.0*shape[1]);
maxbigdiam = MAX(maxbigdiam,2.0*shape[2]);
minbigdiam = MIN(minbigdiam,2.0*shape[0]);
minbigdiam = MIN(minbigdiam,2.0*shape[1]);
minbigdiam = MIN(minbigdiam,2.0*shape[2]);
} else if (line && line[i] >= 0) {
any_lines = 1;
double length = lbonus[line[i]].length;
maxbigdiam = MAX(maxbigdiam,length);
minbigdiam = MIN(minbigdiam,length);
} else if (tri && tri[i] >= 0) {
any_tris = 1;
double length1 = MathExtra::len3(tbonus[tri[i]].c1);
double length2 = MathExtra::len3(tbonus[tri[i]].c2);
double length3 = MathExtra::len3(tbonus[tri[i]].c3);
double length = MAX(length1,length2);
length = MAX(length,length3);
maxbigdiam = MAX(maxbigdiam,length);
minbigdiam = MIN(minbigdiam,length);
} else
error->one(FLERR,"Big particle in fix srd cannot be point particle");
}
double tmp = maxbigdiam;
MPI_Allreduce(&tmp,&maxbigdiam,1,MPI_DOUBLE,MPI_MAX,world);
tmp = minbigdiam;
MPI_Allreduce(&tmp,&minbigdiam,1,MPI_DOUBLE,MPI_MIN,world);
maxbigdiam *= radfactor;
minbigdiam *= radfactor;
int itmp = any_ellipsoids;
MPI_Allreduce(&itmp,&any_ellipsoids,1,MPI_INT,MPI_MAX,world);
itmp = any_lines;
MPI_Allreduce(&itmp,&any_lines,1,MPI_INT,MPI_MAX,world);
itmp = any_tris;
MPI_Allreduce(&itmp,&any_tris,1,MPI_INT,MPI_MAX,world);
if (any_lines && overlap == 0)
error->all(FLERR,"Cannot use lines with fix srd unless overlap is set");
if (any_tris && overlap == 0)
error->all(FLERR,"Cannot use tris with fix srd unless overlap is set");
if (any_ellipsoids == 0 && any_lines == 0 && any_tris == 0 &&
collidestyle == SLIP) torqueflag = 0;
else torqueflag = 1;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int flag = 0;
mass_srd = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) {
if (mass_srd == 0.0) mass_srd = rmass[i];
else if (rmass[i] != mass_srd) flag = 1;
} else {
if (mass_srd == 0.0) mass_srd = mass[type[i]];
else if (mass[type[i]] != mass_srd) flag = 1;
}
}
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_MAX,world);
if (flagall)
error->all(FLERR,"Fix srd requires SRD particles all have same mass");
if (lamdaflag == 0)
lamda = dt_srd * sqrt(force->boltz*temperature_srd/mass_srd/force->mvv2e);
else
temperature_srd = force->mvv2e *
(lamda/dt_srd)*(lamda/dt_srd) * mass_srd/force->boltz;
sigma = lamda/dt_srd;
dmax = 4.0*lamda;
vmax = dmax/dt_srd;
vmaxsq = vmax*vmax;
double volbig = 0.0;
double WIDTH = 1.0;
if (dimension == 3) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) {
if (radius && radius[i] > 0.0) {
double r = radfactor * radius[i];
volbig += 4.0/3.0*MY_PI * r*r*r;;
} else if (ellipsoid && ellipsoid[i] >= 0) {
double *shape = ebonus[ellipsoid[i]].shape;
volbig += 4.0/3.0*MY_PI * shape[0]*shape[1]*shape[2] *
radfactor*radfactor*radfactor;
} else if (tri && tri[i] >= 0) {
double *c1 = tbonus[tri[i]].c1;
double *c2 = tbonus[tri[i]].c2;
double *c3 = tbonus[tri[i]].c3;
double c2mc1[3],c3mc1[3],cross[3];
MathExtra::sub3(c2,c1,c2mc1);
MathExtra::sub3(c3,c1,c3mc1);
MathExtra::cross3(c2mc1,c3mc1,cross);
volbig += 0.5 * MathExtra::len3(cross);
}
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) {
if (radius && radius[i] > 0.0) {
double r = radfactor * radius[i];
volbig += MY_PI * r*r;
} else if (ellipsoid && ellipsoid[i] >= 0) {
double *shape = ebonus[ellipsoid[i]].shape;
volbig += MY_PI * shape[0]*shape[1] * radfactor*radfactor;
} else if (line && line[i] >= 0) {
double length = lbonus[line[i]].length;
volbig += length * WIDTH;
}
}
}
tmp = volbig;
MPI_Allreduce(&tmp,&volbig,1,MPI_DOUBLE,MPI_SUM,world);
bigint mbig = 0;
if (bigexist) mbig = group->count(biggroup);
bigint nsrd = group->count(igroup);
mass_big = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) {
if (rmass) mass_big += rmass[i];
else mass_big += mass[type[i]];
}
tmp = mass_big;
MPI_Allreduce(&tmp,&mass_big,1,MPI_DOUBLE,MPI_SUM,world);
double density_big = 0.0;
if (bigexist) density_big = mass_big / volbig;
double volsrd,density_srd;
if (dimension == 3) {
volsrd = (domain->xprd * domain->yprd * domain->zprd) - volbig;
density_srd = nsrd * mass_srd /
(domain->xprd*domain->yprd*domain->zprd - volbig);
} else {
volsrd = (domain->xprd * domain->yprd) - volbig;
density_srd = nsrd * mass_srd /
(domain->xprd*domain->yprd - volbig);
}
double mdratio = density_big/density_srd;
setup_velocity_bins();
double binsize3x = binsize1x;
double binsize3y = binsize1y;
double binsize3z = binsize1z;
if (triclinic) {
binsize3x = binsize1x * domain->xprd;
binsize3y = binsize1y * domain->yprd;
binsize3z = binsize1z * domain->zprd;
}
double ncell;
if (dimension == 3)
ncell = volsrd / (binsize3x*binsize3y*binsize3z);
else
ncell = volsrd / (binsize3x*binsize3y);
srd_per_cell = (double) nsrd / ncell;
double viscosity;
if (dimension == 3)
viscosity = gridsrd*gridsrd/(18.0*dt_srd) *
(1.0-(1.0-exp(-srd_per_cell))/srd_per_cell) +
(force->boltz*temperature_srd*dt_srd/(4.0*mass_srd*force->mvv2e)) *
((srd_per_cell+2.0)/(srd_per_cell-1.0));
else
viscosity =
(force->boltz*temperature_srd*dt_srd/(2.0*mass_srd*force->mvv2e)) *
(srd_per_cell/(srd_per_cell-1.0 + exp(-srd_per_cell)) - 1.0) +
(gridsrd*gridsrd)/(12.0*dt_srd) *
((srd_per_cell-1.0 + exp(-srd_per_cell))/srd_per_cell);
viscosity *= force->xxt2kmu;
if (me == 0) {
if (screen) {
fprintf(screen,"SRD info:\n");
fprintf(screen,
" SRD/big particles = " BIGINT_FORMAT " " BIGINT_FORMAT "\n",
nsrd,mbig);
fprintf(screen," big particle diameter max/min = %g %g\n",
maxbigdiam,minbigdiam);
fprintf(screen," SRD temperature & lamda = %g %g\n",
temperature_srd,lamda);
fprintf(screen," SRD max distance & max velocity = %g %g\n",dmax,vmax);
fprintf(screen," SRD grid counts: %d %d %d\n",nbin1x,nbin1y,nbin1z);
fprintf(screen," SRD grid size: request, actual (xyz) = %g, %g %g %g\n",
gridsrd,binsize3x,binsize3y,binsize3z);
fprintf(screen," SRD per actual grid cell = %g\n",srd_per_cell);
fprintf(screen," SRD viscosity = %g\n",viscosity);
fprintf(screen," big/SRD mass density ratio = %g\n",mdratio);
}
if (logfile) {
fprintf(logfile,"SRD info:\n");
fprintf(logfile,
" SRD/big particles = " BIGINT_FORMAT " " BIGINT_FORMAT "\n",
nsrd,mbig);
fprintf(logfile," big particle diameter max/min = %g %g\n",
maxbigdiam,minbigdiam);
fprintf(logfile," SRD temperature & lamda = %g %g\n",
temperature_srd,lamda);
fprintf(logfile," SRD max distance & max velocity = %g %g\n",dmax,vmax);
fprintf(logfile," SRD grid counts: %d %d %d\n",nbin1x,nbin1y,nbin1z);
fprintf(logfile," SRD grid size: request, actual (xyz) = %g, %g %g %g\n",
gridsrd,binsize3x,binsize3y,binsize3z);
fprintf(logfile," SRD per actual grid cell = %g\n",srd_per_cell);
fprintf(logfile," SRD viscosity = %g\n",viscosity);
fprintf(logfile," big/SRD mass density ratio = %g\n",mdratio);
}
}
if (nbin1x < comm->procgrid[0] || nbin1y < comm->procgrid[1] ||
nbin1z < comm->procgrid[2])
error->all(FLERR,"Fewer SRD bins than processors in some dimension");
int tolflag = 0;
if (binsize3y/binsize3x > 1.0+cubictol ||
binsize3x/binsize3y > 1.0+cubictol) tolflag = 1;
if (dimension == 3) {
if (binsize3z/binsize3x > 1.0+cubictol ||
binsize3x/binsize3z > 1.0+cubictol) tolflag = 1;
}
if (tolflag) {
if (cubicflag == CUBIC_ERROR)
error->all(FLERR,"SRD bins for fix srd are not cubic enough");
if (me == 0)
error->warning(FLERR,"SRD bins for fix srd are not cubic enough");
}
tolflag = 0;
if (binsize3x/gridsrd > 1.0+cubictol || gridsrd/binsize3x > 1.0+cubictol)
tolflag = 1;
if (binsize3y/gridsrd > 1.0+cubictol || gridsrd/binsize3y > 1.0+cubictol)
tolflag = 1;
if (dimension == 3) {
if (binsize3z/gridsrd > 1.0+cubictol || gridsrd/binsize3z > 1.0+cubictol)
tolflag = 1;
}
if (tolflag) {
if (cubicflag == CUBIC_ERROR)
error->all(FLERR,"SRD bin size for fix srd differs from user request");
if (me == 0)
error->warning(FLERR,
"SRD bin size for fix srd differs from user request");
}
double maxgridsrd = MAX(binsize3x,binsize3y);
if (dimension == 3) maxgridsrd = MAX(maxgridsrd,binsize3z);
shiftflag = 0;
if (lamda < 0.6*maxgridsrd && shiftuser == SHIFT_NO)
error->all(FLERR,"Fix srd lamda must be >= 0.6 of SRD grid size");
else if (lamda < 0.6*maxgridsrd && shiftuser == SHIFT_POSSIBLE) {
shiftflag = 1;
if (me == 0)
error->warning(FLERR,"SRD bin shifting turned on due to small lamda");
} else if (shiftuser == SHIFT_YES) shiftflag = 1;
if (bigexist && maxgridsrd > 0.25 * minbigdiam && me == 0)
error->warning(FLERR,"Fix srd grid size > 1/4 of big particle diameter");
if (viscosity < 0.0 && me == 0)
error->warning(FLERR,"Fix srd viscosity < 0.0 due to low SRD density");
if (bigexist && dt_big*vmax > minbigdiam && me == 0)
error->warning(FLERR,"Fix srd particles may move > big particle diameter");
}
void FixSRD::big_static()
{
int i;
double rad,arad,brad,crad,length,length1,length2,length3;
double *shape,*c1,*c2,*c3;
double c2mc1[3],c3mc1[3];
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
AtomVecLine::Bonus *lbonus;
if (avec_line) lbonus = avec_line->bonus;
AtomVecTri::Bonus *tbonus;
if (avec_tri) tbonus = avec_tri->bonus;
double *radius = atom->radius;
int *ellipsoid = atom->ellipsoid;
int *line = atom->line;
int *tri = atom->tri;
double skinhalf = 0.5 * neighbor->skin;
for (int k = 0; k < nbig; k++) {
i = biglist[k].index;
if (radius && radius[i] > 0.0) {
biglist[k].type = SPHERE;
rad = radfactor*radius[i];
biglist[k].radius = rad;
biglist[k].radsq = rad*rad;
biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf);
} else if (ellipsoid && ellipsoid[i] >= 0) {
shape = ebonus[ellipsoid[i]].shape;
biglist[k].type = ELLIPSOID;
arad = radfactor*shape[0];
brad = radfactor*shape[1];
crad = radfactor*shape[2];
biglist[k].aradsqinv = 1.0/(arad*arad);
biglist[k].bradsqinv = 1.0/(brad*brad);
biglist[k].cradsqinv = 1.0/(crad*crad);
rad = MAX(arad,brad);
rad = MAX(rad,crad);
biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf);
} else if (line && line[i] >= 0) {
length = lbonus[line[i]].length;
biglist[k].type = LINE;
biglist[k].length = length;
rad = 0.5*length;
biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf);
} else if (tri && tri[i] >= 0) {
biglist[k].type = TRIANGLE;
c1 = tbonus[tri[i]].c1;
c2 = tbonus[tri[i]].c2;
c3 = tbonus[tri[i]].c3;
MathExtra::sub3(c2,c1,c2mc1);
MathExtra::sub3(c3,c1,c3mc1);
MathExtra::cross3(c2mc1,c3mc1,biglist[k].normbody);
length1 = MathExtra::len3(c1);
length2 = MathExtra::len3(c2);
length3 = MathExtra::len3(c3);
rad = MAX(length1,length2);
rad = MAX(rad,length3);
biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf);
}
}
}
void FixSRD::big_dynamic()
{
int i;
double *shape,*quat,*inertia;
double inertiaone[3];
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
AtomVecLine::Bonus *lbonus;
if (avec_line) lbonus = avec_line->bonus;
AtomVecTri::Bonus *tbonus;
if (avec_tri) tbonus = avec_tri->bonus;
double **omega = atom->omega;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *ellipsoid = atom->ellipsoid;
int *line = atom->line;
int *tri = atom->tri;
for (int k = 0; k < nbig; k++) {
i = biglist[k].index;
if (biglist[k].type == SPHERE) {
biglist[k].omega[0] = omega[i][0];
biglist[k].omega[1] = omega[i][1];
biglist[k].omega[2] = omega[i][2];
} else if (biglist[k].type == ELLIPSOID) {
quat = ebonus[ellipsoid[i]].quat;
MathExtra::q_to_exyz(quat,biglist[k].ex,biglist[k].ey,biglist[k].ez);
shape = ebonus[ellipsoid[i]].shape;
inertiaone[0] = EINERTIA*rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]);
inertiaone[1] = EINERTIA*rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]);
inertiaone[2] = EINERTIA*rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]);
MathExtra::angmom_to_omega(angmom[i],
biglist[k].ex,biglist[k].ey,biglist[k].ez,
inertiaone,biglist[k].omega);
} else if (biglist[k].type == LINE) {
biglist[k].theta = lbonus[line[i]].theta;
biglist[k].omega[0] = omega[i][0];
biglist[k].omega[1] = omega[i][1];
biglist[k].omega[2] = omega[i][2];
} else if (biglist[k].type == TRIANGLE) {
quat = tbonus[tri[i]].quat;
MathExtra::q_to_exyz(quat,biglist[k].ex,biglist[k].ey,biglist[k].ez);
inertia = tbonus[tri[i]].inertia;
MathExtra::angmom_to_omega(angmom[i],
biglist[k].ex,biglist[k].ey,biglist[k].ez,
inertia,biglist[k].omega);
MathExtra::matvec(biglist[k].ex,biglist[k].ey,biglist[k].ez,
biglist[k].normbody,biglist[k].norm);
MathExtra::norm3(biglist[k].norm);
}
}
}
void FixSRD::setup_bounds()
{
double length0,length1,length2;
if (triclinic) {
double *h_inv = domain->h_inv;
length0 = sqrt(h_inv[0]*h_inv[0] + h_inv[5]*h_inv[5] + h_inv[4]*h_inv[4]);
length1 = sqrt(h_inv[1]*h_inv[1] + h_inv[3]*h_inv[3]);
length2 = h_inv[2];
}
double cut = MAX(neighbor->cutneighmax,comm->cutghostuser);
double onemove = dt_big*vmax;
if (bigexist) {
dist_ghost = cut + 0.5*neighbor->skin;
dist_srd = cut - 0.5*neighbor->skin - 0.5*maxbigdiam;
dist_srd_reneigh = dist_srd - onemove;
} else if (wallexist) {
dist_ghost = 4*onemove;
dist_srd = 4*onemove;
dist_srd_reneigh = 4*onemove - onemove;
} else {
dist_ghost = dist_srd = 0.0;
double subsize;
if (triclinic == 0) {
subsize = domain->prd[0]/comm->procgrid[0];
subsize = MIN(subsize,domain->prd[1]/comm->procgrid[1]);
if (dimension == 3)
subsize = MIN(subsize,domain->prd[2]/comm->procgrid[2]);
} else {
subsize = 1.0/comm->procgrid[0]/length0;
subsize = MIN(subsize,1.0/comm->procgrid[1]/length1);
if (dimension == 3)
subsize = MIN(subsize,1.0/comm->procgrid[2]/length2);
}
dist_srd_reneigh = subsize - onemove;
}
if (triclinic == 0) {
srdlo[0] = domain->sublo[0] - dist_srd;
srdhi[0] = domain->subhi[0] + dist_srd;
srdlo[1] = domain->sublo[1] - dist_srd;
srdhi[1] = domain->subhi[1] + dist_srd;
srdlo[2] = domain->sublo[2] - dist_srd;
srdhi[2] = domain->subhi[2] + dist_srd;
srdlo_reneigh[0] = domain->sublo[0] - dist_srd_reneigh;
srdhi_reneigh[0] = domain->subhi[0] + dist_srd_reneigh;
srdlo_reneigh[1] = domain->sublo[1] - dist_srd_reneigh;
srdhi_reneigh[1] = domain->subhi[1] + dist_srd_reneigh;
srdlo_reneigh[2] = domain->sublo[2] - dist_srd_reneigh;
srdhi_reneigh[2] = domain->subhi[2] + dist_srd_reneigh;
} else {
srdlo[0] = domain->sublo_lamda[0] - dist_srd*length0;
srdhi[0] = domain->subhi_lamda[0] + dist_srd*length0;
srdlo[1] = domain->sublo_lamda[1] - dist_srd*length1;
srdhi[1] = domain->subhi_lamda[1] + dist_srd*length1;
srdlo[2] = domain->sublo_lamda[2] - dist_srd*length2;
srdhi[2] = domain->subhi_lamda[2] + dist_srd*length2;
srdlo_reneigh[0] = domain->sublo_lamda[0] - dist_srd_reneigh*length0;
srdhi_reneigh[0] = domain->subhi_lamda[0] + dist_srd_reneigh*length0;
srdlo_reneigh[1] = domain->sublo_lamda[1] - dist_srd_reneigh*length1;
srdhi_reneigh[1] = domain->subhi_lamda[1] + dist_srd_reneigh*length1;
srdlo_reneigh[2] = domain->sublo_lamda[2] - dist_srd_reneigh*length2;
srdhi_reneigh[2] = domain->subhi_lamda[2] + dist_srd_reneigh*length2;
}
}
void FixSRD::setup_velocity_bins()
{
nbin1x = static_cast<int> (domain->xprd/gridsrd + 0.5);
nbin1y = static_cast<int> (domain->yprd/gridsrd + 0.5);
nbin1z = static_cast<int> (domain->zprd/gridsrd + 0.5);
if (dimension == 2) nbin1z = 1;
if (nbin1x == 0) nbin1x = 1;
if (nbin1y == 0) nbin1y = 1;
if (nbin1z == 0) nbin1z = 1;
if (triclinic == 0) {
binsize1x = domain->xprd / nbin1x;
binsize1y = domain->yprd / nbin1y;
binsize1z = domain->zprd / nbin1z;
bininv1x = 1.0/binsize1x;
bininv1y = 1.0/binsize1y;
bininv1z = 1.0/binsize1z;
} else {
binsize1x = 1.0 / nbin1x;
binsize1y = 1.0 / nbin1y;
binsize1z = 1.0 / nbin1z;
bininv1x = nbin1x;
bininv1y = nbin1y;
bininv1z = nbin1z;
}
nbins1 = nbin1x*nbin1y*nbin1z;
double *boxlo;
if (triclinic == 0) boxlo = domain->boxlo;
else boxlo = domain->boxlo_lamda;
shifts[0].corner[0] = boxlo[0];
shifts[0].corner[1] = boxlo[1];
shifts[0].corner[2] = boxlo[2];
setup_velocity_shift(0,0);
shifts[1].corner[0] = boxlo[0];
shifts[1].corner[1] = boxlo[1];
shifts[1].corner[2] = boxlo[2];
setup_velocity_shift(1,0);
int max = shifts[0].nbins;
max = MAX(max,shifts[1].nbins);
if (max > maxbin1) {
memory->destroy(binhead);
maxbin1 = max;
memory->create(binhead,max,"fix/srd:binhead");
}
max = 0;
for (int ishift = 0; ishift < 2; ishift++)
for (int iswap = 0; iswap < 2*dimension; iswap++) {
max = MAX(max,shifts[ishift].bcomm[iswap].nsend);
max = MAX(max,shifts[ishift].bcomm[iswap].nrecv);
}
if (max > maxbuf) {
memory->destroy(sbuf1);
memory->destroy(sbuf2);
memory->destroy(rbuf1);
memory->destroy(rbuf2);
maxbuf = max;
memory->create(sbuf1,max*VBINSIZE,"fix/srd:sbuf");
memory->create(sbuf2,max*VBINSIZE,"fix/srd:sbuf");
memory->create(rbuf1,max*VBINSIZE,"fix/srd:rbuf");
memory->create(rbuf2,max*VBINSIZE,"fix/srd:rbuf");
}
shifts[0].commflag = 0;
if (nbin1x % comm->procgrid[0]) shifts[0].commflag = 1;
if (nbin1y % comm->procgrid[1]) shifts[0].commflag = 1;
if (nbin1z % comm->procgrid[2]) shifts[0].commflag = 1;
shifts[1].commflag = 1;
}
void FixSRD::setup_velocity_shift(int ishift, int dynamic)
{
int i,j,k,m,id,nsend;
int *sendlist;
BinComm *first,*second;
BinAve *vbin;
double *sublo,*subhi;
if (triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
int *binlo = shifts[ishift].binlo;
int *binhi = shifts[ishift].binhi;
double *corner = shifts[ishift].corner;
int *procgrid = comm->procgrid;
int *myloc = comm->myloc;
binlo[0] = static_cast<int> ((sublo[0]-corner[0])*bininv1x);
binlo[1] = static_cast<int> ((sublo[1]-corner[1])*bininv1y);
binlo[2] = static_cast<int> ((sublo[2]-corner[2])*bininv1z);
if (dimension == 2) shifts[ishift].binlo[2] = 0;
binhi[0] = static_cast<int> ((subhi[0]-corner[0])*bininv1x);
binhi[1] = static_cast<int> ((subhi[1]-corner[1])*bininv1y);
binhi[2] = static_cast<int> ((subhi[2]-corner[2])*bininv1z);
if (dimension == 2) shifts[ishift].binhi[2] = 0;
if (ishift == 0) {
if (myloc[0]*nbin1x % procgrid[0] == 0)
binlo[0] = myloc[0]*nbin1x/procgrid[0];
if (myloc[1]*nbin1y % procgrid[1] == 0)
binlo[1] = myloc[1]*nbin1y/procgrid[1];
if (myloc[2]*nbin1z % procgrid[2] == 0)
binlo[2] = myloc[2]*nbin1z/procgrid[2];
if ((myloc[0]+1)*nbin1x % procgrid[0] == 0)
binhi[0] = (myloc[0]+1)*nbin1x/procgrid[0] - 1;
if ((myloc[1]+1)*nbin1y % procgrid[1] == 0)
binhi[1] = (myloc[1]+1)*nbin1y/procgrid[1] - 1;
if ((myloc[2]+1)*nbin1z % procgrid[2] == 0)
binhi[2] = (myloc[2]+1)*nbin1z/procgrid[2] - 1;
}
int nbinx = binhi[0] - binlo[0] + 1;
int nbiny = binhi[1] - binlo[1] + 1;
int nbinz = binhi[2] - binlo[2] + 1;
if (ishift == 1 && dynamic == 0) {
nbinx++;
nbiny++;
if (dimension == 3) nbinz++;
}
int nbins = nbinx*nbiny*nbinz;
int nbinxy = nbinx*nbiny;
int nbinsq = nbinx*nbiny;
nbinsq = MAX(nbiny*nbinz,nbinsq);
nbinsq = MAX(nbinx*nbinz,nbinsq);
shifts[ishift].nbins = nbins;
shifts[ishift].nbinx = nbinx;
shifts[ishift].nbiny = nbiny;
shifts[ishift].nbinz = nbinz;
int reallocflag = 0;
if (dynamic == 0 && nbinsq > shifts[ishift].maxbinsq) {
shifts[ishift].maxbinsq = nbinsq;
reallocflag = 1;
}
if (dynamic == 0) {
shifts[ishift].bcomm[0].sendproc = comm->procneigh[0][0];
shifts[ishift].bcomm[0].recvproc = comm->procneigh[0][1];
shifts[ishift].bcomm[1].sendproc = comm->procneigh[0][1];
shifts[ishift].bcomm[1].recvproc = comm->procneigh[0][0];
shifts[ishift].bcomm[2].sendproc = comm->procneigh[1][0];
shifts[ishift].bcomm[2].recvproc = comm->procneigh[1][1];
shifts[ishift].bcomm[3].sendproc = comm->procneigh[1][1];
shifts[ishift].bcomm[3].recvproc = comm->procneigh[1][0];
shifts[ishift].bcomm[4].sendproc = comm->procneigh[2][0];
shifts[ishift].bcomm[4].recvproc = comm->procneigh[2][1];
shifts[ishift].bcomm[5].sendproc = comm->procneigh[2][1];
shifts[ishift].bcomm[5].recvproc = comm->procneigh[2][0];
}
first = &shifts[ishift].bcomm[0];
second = &shifts[ishift].bcomm[1];
first->nsend = first->nrecv = second->nsend = second->nrecv = nbiny*nbinz;
if (ishift == 0) {
if (myloc[0]*nbin1x % procgrid[0] == 0)
first->nsend = second->nrecv = 0;
if ((myloc[0]+1)*nbin1x % procgrid[0] == 0)
second->nsend = first->nrecv = 0;
} else {
if (domain->xperiodic == 0) {
if (myloc[0] == 0) first->nsend = second->nrecv = 0;
if (myloc[0] == procgrid[0]-1) second->nsend = first->nrecv = 0;
}
}
if (reallocflag) {
memory->destroy(first->sendlist);
memory->destroy(first->recvlist);
memory->destroy(second->sendlist);
memory->destroy(second->recvlist);
memory->create(first->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(first->recvlist,nbinsq,"fix/srd:sendlist");
memory->create(second->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(second->recvlist,nbinsq,"fix/srd:sendlist");
}
m = 0;
i = 0;
for (j = 0; j < nbiny; j++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
first->sendlist[m] = second->recvlist[m] = id;
m++;
}
m = 0;
i = nbinx-1;
for (j = 0; j < nbiny; j++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
second->sendlist[m] = first->recvlist[m] = id;
m++;
}
first = &shifts[ishift].bcomm[2];
second = &shifts[ishift].bcomm[3];
first->nsend = first->nrecv = second->nsend = second->nrecv = nbinx*nbinz;
if (ishift == 0) {
if (myloc[1]*nbin1y % procgrid[1] == 0)
first->nsend = second->nrecv = 0;
if ((myloc[1]+1)*nbin1y % procgrid[1] == 0)
second->nsend = first->nrecv = 0;
} else {
if (domain->yperiodic == 0) {
if (myloc[1] == 0) first->nsend = second->nrecv = 0;
if (myloc[1] == procgrid[1]-1) second->nsend = first->nrecv = 0;
}
}
if (reallocflag) {
memory->destroy(first->sendlist);
memory->destroy(first->recvlist);
memory->destroy(second->sendlist);
memory->destroy(second->recvlist);
memory->create(first->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(first->recvlist,nbinsq,"fix/srd:sendlist");
memory->create(second->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(second->recvlist,nbinsq,"fix/srd:sendlist");
}
m = 0;
j = 0;
for (i = 0; i < nbinx; i++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
first->sendlist[m] = second->recvlist[m] = id;
m++;
}
m = 0;
j = nbiny-1;
for (i = 0; i < nbinx; i++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
second->sendlist[m] = first->recvlist[m] = id;
m++;
}
if (dimension == 3) {
first = &shifts[ishift].bcomm[4];
second = &shifts[ishift].bcomm[5];
first->nsend = first->nrecv = second->nsend = second->nrecv = nbinx*nbiny;
if (ishift == 0) {
if (myloc[2]*nbin1z % procgrid[2] == 0)
first->nsend = second->nrecv = 0;
if ((myloc[2]+1)*nbin1z % procgrid[2] == 0)
second->nsend = first->nrecv = 0;
} else {
if (domain->zperiodic == 0) {
if (myloc[2] == 0) first->nsend = second->nrecv = 0;
if (myloc[2] == procgrid[2]-1) second->nsend = first->nrecv = 0;
}
}
if (reallocflag) {
memory->destroy(first->sendlist);
memory->destroy(first->recvlist);
memory->destroy(second->sendlist);
memory->destroy(second->recvlist);
memory->create(first->sendlist,nbinx*nbiny,"fix/srd:sendlist");
memory->create(first->recvlist,nbinx*nbiny,"fix/srd:sendlist");
memory->create(second->sendlist,nbinx*nbiny,"fix/srd:sendlist");
memory->create(second->recvlist,nbinx*nbiny,"fix/srd:sendlist");
}
m = 0;
k = 0;
for (i = 0; i < nbinx; i++)
for (j = 0; j < nbiny; j++) {
id = k*nbinxy + j*nbinx + i;
first->sendlist[m] = second->recvlist[m] = id;
m++;
}
m = 0;
k = nbinz-1;
for (i = 0; i < nbinx; i++)
for (j = 0; j < nbiny; j++) {
id = k*nbinxy + j*nbinx + i;
second->sendlist[m] = first->recvlist[m] = id;
m++;
}
}
if (dynamic == 0 && nbins > shifts[ishift].maxvbin) {
memory->destroy(shifts[ishift].vbin);
shifts[ishift].maxvbin = nbins;
shifts[ishift].vbin = (BinAve *)
memory->smalloc(nbins*sizeof(BinAve),"fix/srd:vbin");
}
vbin = shifts[ishift].vbin;
for (i = 0; i < nbins; i++) vbin[i].owner = 1;
for (int iswap = 0; iswap < 2*dimension; iswap++) {
if (shifts[ishift].bcomm[iswap].sendproc > me) continue;
if (shifts[ishift].bcomm[iswap].sendproc == me && iswap % 2 == 0) continue;
nsend = shifts[ishift].bcomm[iswap].nsend;
sendlist = shifts[ishift].bcomm[iswap].sendlist;
for (m = 0; m < nsend; m++) vbin[sendlist[m]].owner = 0;
}
if (tstat && deformflag) {
m = 0;
for (k = 0; k < nbinz; k++)
for (j = 0; j < nbiny; j++)
for (i = 0; i < nbinx; i++) {
vbin[m].xctr[0] = corner[0] + (i+binlo[0]+0.5)/nbin1x;
vbin[m].xctr[1] = corner[1] + (j+binlo[1]+0.5)/nbin1y;
vbin[m].xctr[2] = corner[2] + (k+binlo[2]+0.5)/nbin1z;
m++;
}
}
}
void FixSRD::setup_search_bins()
{
double subboxlo[3],subboxhi[3];
if (triclinic == 0) {
subboxlo[0] = domain->sublo[0] - dist_ghost;
subboxlo[1] = domain->sublo[1] - dist_ghost;
subboxlo[2] = domain->sublo[2] - dist_ghost;
subboxhi[0] = domain->subhi[0] + dist_ghost;
subboxhi[1] = domain->subhi[1] + dist_ghost;
subboxhi[2] = domain->subhi[2] + dist_ghost;
} else {
double *h_inv = domain->h_inv;
double length0,length1,length2;
length0 = sqrt(h_inv[0]*h_inv[0] + h_inv[5]*h_inv[5] + h_inv[4]*h_inv[4]);
length1 = sqrt(h_inv[1]*h_inv[1] + h_inv[3]*h_inv[3]);
length2 = h_inv[2];
double lo[3],hi[3];
lo[0] = domain->sublo_lamda[0] - dist_ghost*length0;
lo[1] = domain->sublo_lamda[1] - dist_ghost*length1;
lo[2] = domain->sublo_lamda[2] - dist_ghost*length2;
hi[0] = domain->subhi_lamda[0] + dist_ghost*length0;
hi[1] = domain->subhi_lamda[1] + dist_ghost*length1;
hi[2] = domain->subhi_lamda[2] + dist_ghost*length2;
domain->bbox(lo,hi,subboxlo,subboxhi);
}
nbin2x = static_cast<int> ((subboxhi[0] - subboxlo[0]) / gridsearch);
nbin2y = static_cast<int> ((subboxhi[1] - subboxlo[1]) / gridsearch);
nbin2z = static_cast<int> ((subboxhi[2] - subboxlo[2]) / gridsearch);
if (dimension == 2) nbin2z = 1;
if (nbin2x == 0) nbin2x = 1;
if (nbin2y == 0) nbin2y = 1;
if (nbin2z == 0) nbin2z = 1;
binsize2x = (subboxhi[0] - subboxlo[0]) / nbin2x;
binsize2y = (subboxhi[1] - subboxlo[1]) / nbin2y;
binsize2z = (subboxhi[2] - subboxlo[2]) / nbin2z;
bininv2x = 1.0/binsize2x;
bininv2y = 1.0/binsize2y;
bininv2z = 1.0/binsize2z;
double radmax = 0.5*maxbigdiam + 0.5*neighbor->skin;
int nx = static_cast<int> (radmax/binsize2x) + 1;
int ny = static_cast<int> (radmax/binsize2y) + 1;
int nz = static_cast<int> (radmax/binsize2z) + 1;
if (dimension == 2) nz = 0;
nbin2x += 2*nx;
nbin2y += 2*ny;
nbin2z += 2*nz;
xblo2 = subboxlo[0] - nx*binsize2x;
yblo2 = subboxlo[1] - ny*binsize2y;
zblo2 = subboxlo[2] - nz*binsize2z;
if (dimension == 2) zblo2 = domain->boxlo[2];
nbins2 = nbin2x*nbin2y*nbin2z;
if (nbins2 > maxbin2) {
memory->destroy(nbinbig);
memory->destroy(binbig);
maxbin2 = nbins2;
memory->create(nbinbig,nbins2,"fix/srd:nbinbig");
memory->create(binbig,nbins2,ATOMPERBIN,"fix/srd:binbig");
}
}
void FixSRD::setup_search_stencil()
{
double radmax = 0.5*maxbigdiam + 0.5*neighbor->skin;
double radsq = radmax*radmax;
int nx = static_cast<int> (radmax/binsize2x) + 1;
int ny = static_cast<int> (radmax/binsize2y) + 1;
int nz = static_cast<int> (radmax/binsize2z) + 1;
if (dimension == 2) nz = 0;
int max = (2*nx+1) * (2*ny+1) * (2*nz+1);
if (max > maxstencil) {
memory->destroy(stencil);
maxstencil = max;
memory->create(stencil,max,4,"fix/srd:stencil");
}
nstencil = 0;
for (int k = -nz; k <= nz; k++)
for (int j = -ny; j <= ny; j++)
for (int i = -nx; i <= nx; i++)
if (bin_bin_distance(i,j,k) < radsq) {
stencil[nstencil][0] = i;
stencil[nstencil][1] = j;
stencil[nstencil][2] = k;
stencil[nstencil][3] = k*nbin2y*nbin2x + j*nbin2x + i;
nstencil++;
}
}
double FixSRD::point_bin_distance(double *x, int i, int j, int k)
{
double delx,dely,delz;
double xlo = xblo2 + i*binsize2x;
double xhi = xlo + binsize2x;
double ylo = yblo2 + j*binsize2y;
double yhi = ylo + binsize2y;
double zlo = zblo2 + k*binsize2z;
double zhi = zlo + binsize2z;
if (x[0] < xlo) delx = xlo - x[0];
else if (x[0] > xhi) delx = x[0] - xhi;
else delx = 0.0;
if (x[1] < ylo) dely = ylo - x[1];
else if (x[1] > yhi) dely = x[1] - yhi;
else dely = 0.0;
if (x[2] < zlo) delz = zlo - x[2];
else if (x[2] > zhi) delz = x[2] - zhi;
else delz = 0.0;
return (delx*delx + dely*dely + delz*delz);
}
double FixSRD::bin_bin_distance(int i, int j, int k)
{
double delx,dely,delz;
if (i > 0) delx = (i-1)*binsize2x;
else if (i == 0) delx = 0.0;
else delx = (i+1)*binsize2x;
if (j > 0) dely = (j-1)*binsize2y;
else if (j == 0) dely = 0.0;
else dely = (j+1)*binsize2y;
if (k > 0) delz = (k-1)*binsize2z;
else if (k == 0) delz = 0.0;
else delz = (k+1)*binsize2z;
return (delx*delx + dely*dely + delz*delz);
}
int FixSRD::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (torqueflag) {
for (i = first; i < last; i++) {
buf[m++] = flocal[i][0];
buf[m++] = flocal[i][1];
buf[m++] = flocal[i][2];
buf[m++] = tlocal[i][0];
buf[m++] = tlocal[i][1];
buf[m++] = tlocal[i][2];
}
} else {
for (i = first; i < last; i++) {
buf[m++] = flocal[i][0];
buf[m++] = flocal[i][1];
buf[m++] = flocal[i][2];
}
}
return m;
}
void FixSRD::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
if (torqueflag) {
for (i = 0; i < n; i++) {
j = list[i];
flocal[j][0] += buf[m++];
flocal[j][1] += buf[m++];
flocal[j][2] += buf[m++];
tlocal[j][0] += buf[m++];
tlocal[j][1] += buf[m++];
tlocal[j][2] += buf[m++];
}
} else {
for (i = 0; i < n; i++) {
j = list[i];
flocal[j][0] += buf[m++];
flocal[j][1] += buf[m++];
flocal[j][2] += buf[m++];
}
}
}
double FixSRD::compute_vector(int n)
{
if (stats_flag == 0) {
stats[0] = ncheck;
stats[1] = ncollide;
stats[2] = nbounce;
stats[3] = ninside;
stats[4] = nrescale;
stats[5] = nbins2;
stats[6] = nbins1;
stats[7] = srd_bin_count;
stats[8] = srd_bin_temp;
stats[9] = bouncemaxnum;
stats[10] = bouncemax;
stats[11] = reneighcount;
MPI_Allreduce(stats,stats_all,10,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(&stats[10],&stats_all[10],1,MPI_DOUBLE,MPI_MAX,world);
if (stats_all[7] != 0.0) stats_all[8] /= stats_all[7];
stats_all[6] /= nprocs;
stats_flag = 1;
}
return stats_all[n];
}
void FixSRD::velocity_stats(int groupnum)
{
int bitmask = group->bitmask[groupnum];
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double vone;
double vave = 0.0;
double vmax = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & bitmask) {
vone = sqrt(v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
vave += vone;
if (vone > vmax) vmax = vone;
}
double all;
MPI_Allreduce(&vave,&all,1,MPI_DOUBLE,MPI_SUM,world);
double count = group->count(groupnum);
if (count != 0.0) vave = all/count;
else vave = 0.0;
MPI_Allreduce(&vmax,&all,1,MPI_DOUBLE,MPI_MAX,world);
vmax = all;
if (me == 0) {
if (screen)
fprintf(screen," ave/max %s velocity = %g %g\n",
group->names[groupnum],vave,vmax);
if (logfile)
fprintf(logfile," ave/max %s velocity = %g %g\n",
group->names[groupnum],vave,vmax);
}
}
double FixSRD::newton_raphson(double t1, double t2)
{
double f1,df,tlo,thi;
lineside(t1,f1,df);
if (f1 < 0.0) {
tlo = t1;
thi = t2;
} else {
thi = t1;
tlo = t2;
}
double f;
double t = 0.5*(t1+t2);
double dtold = fabs(t2-t1);
double dt = dtold;
lineside(t,f,df);
double temp;
for (int i = 0; i < MAXITER; i++) {
if ((((t-thi)*df - f)*((t-tlo)*df - f) > 0.0) ||
(fabs(2.0*f) > fabs(dtold*df))) {
dtold = dt;
dt = 0.5 * (thi-tlo);
t = tlo + dt;
if (tlo == t) return t;
} else {
dtold = dt;
dt = f / df;
temp = t;
t -= dt;
if (temp == t) return t;
}
if (fabs(dt) < TOLERANCE) return t;
lineside(t,f,df);
if (f < 0.0) tlo = t;
else thi = t;
}
return t;
}
void FixSRD::lineside(double t, double &f, double &df)
{
double p[2],c[2];
p[0] = xs0[0] + (xs1[0]-xs0[0])*t;
p[1] = xs0[1] + (xs1[1]-xs0[1])*t;
c[0] = xb0[0] + (xb1[0]-xb0[0])*t;
c[1] = xb0[1] + (xb1[1]-xb0[1])*t;
double dtheta = theta1 - theta0;
double theta = theta0 + dtheta*t;
double cosT = cos(theta);
double sinT = sin(theta);
f = (p[1]-c[1]) * cosT - (p[0]-c[0]) * sinT;
df = ((xs1[1]-xs0[1]) - (xb1[1]-xb0[1]))*cosT - (p[1]-c[1])*sinT*dtheta -
((xs1[0]-xs0[0]) - (xb1[0]-xb0[0]))*sinT - (p[0]-c[0])*cosT*dtheta;
}
void FixSRD::triside(double t, double &f, double &df)
{
double p[2],c[2];
p[0] = xs0[0] + (xs1[0]-xs0[0])*t;
p[1] = xs0[1] + (xs1[1]-xs0[1])*t;
c[0] = xb0[0] + (xb1[0]-xb0[0])*t;
c[1] = xb0[1] + (xb1[1]-xb0[1])*t;
double dtheta = theta1 - theta0;
double theta = theta0 + dtheta*t;
double cosT = cos(theta);
double sinT = sin(theta);
f = (p[1]-c[1]) * cosT - (p[0]-c[0]) * sinT;
df = ((xs1[1]-xs0[1]) - (xb1[1]-xb0[1]))*cosT - (p[1]-c[1])*sinT*dtheta -
((xs1[0]-xs0[0]) - (xb1[0]-xb0[0]))*sinT - (p[0]-c[0])*cosT*dtheta;
}
double FixSRD::memory_usage()
{
double bytes = 0.0;
bytes += (shifts[0].nbins + shifts[1].nbins) * sizeof(BinAve);
bytes += nmax * sizeof(int);
if (bigexist) {
bytes += nbins2 * sizeof(int);
bytes += nbins2*ATOMPERBIN * sizeof(int);
}
bytes += nmax * sizeof(int);
return bytes;
}
double FixSRD::distance(int i, int j)
{
double dx = atom->x[i][0] - atom->x[j][0];
double dy = atom->x[i][1] - atom->x[j][1];
double dz = atom->x[i][2] - atom->x[j][2];
return sqrt(dx*dx + dy*dy + dz*dz);
}
void FixSRD::print_collision(int i, int j, int ibounce,
double t_remain, double dt,
double *xscoll, double *xbcoll, double *norm,
int type)
{
double xsstart[3],xbstart[3];
double **x = atom->x;
double **v = atom->v;
if (type != WALL) {
printf("COLLISION between SRD " TAGINT_FORMAT
" and BIG " TAGINT_FORMAT "\n",atom->tag[i],atom->tag[j]);
printf(" bounce # = %d\n",ibounce+1);
printf(" local indices: %d %d\n",i,j);
printf(" timestep = %g\n",dt);
printf(" time remaining post-collision = %g\n",t_remain);
xsstart[0] = x[i][0] - dt*v[i][0];
xsstart[1] = x[i][1] - dt*v[i][1];
xsstart[2] = x[i][2] - dt*v[i][2];
xbstart[0] = x[j][0] - dt*v[j][0];
xbstart[1] = x[j][1] - dt*v[j][1];
xbstart[2] = x[j][2] - dt*v[j][2];
printf(" SRD start position = %g %g %g\n",
xsstart[0],xsstart[1],xsstart[2]);
printf(" BIG start position = %g %g %g\n",
xbstart[0],xbstart[1],xbstart[2]);
printf(" SRD coll position = %g %g %g\n",
xscoll[0],xscoll[1],xscoll[2]);
printf(" BIG coll position = %g %g %g\n",
xbcoll[0],xbcoll[1],xbcoll[2]);
printf(" SRD end position = %g %g %g\n",x[i][0],x[i][1],x[i][2]);
printf(" BIG end position = %g %g %g\n",x[j][0],x[j][1],x[j][2]);
printf(" SRD vel = %g %g %g\n",v[i][0],v[i][1],v[i][2]);
printf(" BIG vel = %g %g %g\n",v[j][0],v[j][1],v[j][2]);
printf(" surf norm = %g %g %g\n",norm[0],norm[1],norm[2]);
double rstart = sqrt((xsstart[0]-xbstart[0])*(xsstart[0]-xbstart[0]) +
(xsstart[1]-xbstart[1])*(xsstart[1]-xbstart[1]) +
(xsstart[2]-xbstart[2])*(xsstart[2]-xbstart[2]));
double rcoll = sqrt((xscoll[0]-xbcoll[0])*(xscoll[0]-xbcoll[0]) +
(xscoll[1]-xbcoll[1])*(xscoll[1]-xbcoll[1]) +
(xscoll[2]-xbcoll[2])*(xscoll[2]-xbcoll[2]));
double rend = sqrt((x[i][0]-x[j][0])*(x[i][0]-x[j][0]) +
(x[i][1]-x[j][1])*(x[i][1]-x[j][1]) +
(x[i][2]-x[j][2])*(x[i][2]-x[j][2]));
printf(" separation at start = %g\n",rstart);
printf(" separation at coll = %g\n",rcoll);
printf(" separation at end = %g\n",rend);
} else {
int dim = wallwhich[j] / 2;
printf("COLLISION between SRD " TAGINT_FORMAT " and WALL %d\n",
atom->tag[i],j);
printf(" bounce # = %d\n",ibounce+1);
printf(" local indices: %d %d\n",i,j);
printf(" timestep = %g\n",dt);
printf(" time remaining post-collision = %g\n",t_remain);
xsstart[0] = x[i][0] - dt*v[i][0];
xsstart[1] = x[i][1] - dt*v[i][1];
xsstart[2] = x[i][2] - dt*v[i][2];
xbstart[0] = xbstart[1] = xbstart[2] = 0.0;
xbstart[dim] = xwall[j] - dt*vwall[j];
printf(" SRD start position = %g %g %g\n",
xsstart[0],xsstart[1],xsstart[2]);
printf(" WALL start position = %g\n",xbstart[dim]);
printf(" SRD coll position = %g %g %g\n",
xscoll[0],xscoll[1],xscoll[2]);
printf(" WALL coll position = %g\n",xbcoll[dim]);
printf(" SRD end position = %g %g %g\n",x[i][0],x[i][1],x[i][2]);
printf(" WALL end position = %g\n",xwall[j]);
printf(" SRD vel = %g %g %g\n",v[i][0],v[i][1],v[i][2]);
printf(" WALL vel = %g\n",vwall[j]);
printf(" surf norm = %g %g %g\n",norm[0],norm[1],norm[2]);
double rstart = xsstart[dim]-xbstart[dim];
double rcoll = xscoll[dim]-xbcoll[dim];
double rend = x[dim][0]-xwall[j];
printf(" separation at start = %g\n",rstart);
printf(" separation at coll = %g\n",rcoll);
printf(" separation at end = %g\n",rend);
}
}