Page MenuHomec4science

fix_viscosity.cpp
No OneTemporary

File Metadata

Created
Wed, Jun 26, 10:55

fix_viscosity.cpp

/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "fix_viscosity.h"
#include "atom.h"
#include "domain.h"
#include "error.h"
#include "update.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
FixViscosity::FixViscosity(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (narg != 7) error->all("Illegal fix viscosity command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
if (nevery <= 0) error->all("Illegal fix viscosity command");
scalar_flag = 1;
scalar_vector_freq = nevery;
extscalar = 0;
if (strcmp(arg[4],"x") == 0) vdim = 0;
else if (strcmp(arg[4],"y") == 0) vdim = 1;
else if (strcmp(arg[4],"z") == 0) vdim = 2;
else error->all("Illegal fix viscosity command");
if (strcmp(arg[5],"x") == 0) pdim = 0;
else if (strcmp(arg[5],"y") == 0) pdim = 1;
else if (strcmp(arg[5],"z") == 0) pdim = 2;
else error->all("Illegal fix viscosity command");
nbin = atoi(arg[6]);
if (nbin < 3) error->all("Illegal fix viscosity command");
flux = 0.0;
}
/* ---------------------------------------------------------------------- */
int FixViscosity::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixViscosity::init()
{
// set bounds of 2 slabs in pdim
// only necessary for static box, else re-computed in end_of_step()
// lo bin is always bottom bin
// if nbin even, hi bin is just below half height
// if nbin odd, hi bin straddles half height
if (domain->box_change == 0) {
prd = domain->prd[pdim];
boxlo = domain->boxlo[pdim];
boxhi = domain->boxhi[pdim];
double binsize = (boxhi-boxlo) / nbin;
slablo_lo = boxlo;
slablo_hi = boxlo + binsize;
slabhi_lo = boxlo + ((nbin-1)/2)*binsize;
slabhi_hi = boxlo + ((nbin-1)/2 + 1)*binsize;
}
periodicity = domain->periodicity[pdim];
}
/* ---------------------------------------------------------------------- */
void FixViscosity::end_of_step()
{
int i;
double p,coord;
MPI_Status status;
struct {
double value;
int proc;
} mine[2],all[2];
// if box changes, recompute bounds of 2 slabs in pdim
if (domain->box_change) {
prd = domain->prd[pdim];
boxlo = domain->boxlo[pdim];
boxhi = domain->boxhi[pdim];
double binsize = (boxhi-boxlo) / nbin;
slablo_lo = boxlo;
slablo_hi = boxlo + binsize;
slabhi_lo = boxlo + ((nbin-1)/2)*binsize;
slabhi_hi = boxlo + ((nbin-1)/2 + 1)*binsize;
}
// ipos,ineg = my 2 atoms with most pos/neg momenta in bottom/top slabs
// map atom back into periodic box if necessary
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int ipos = -1;
int ineg = -1;
double pmin = BIG;
double pmax = -BIG;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (mass) p = mass[type[i]] * v[i][vdim];
else p = rmass[i] * v[i][vdim];
coord = x[i][pdim];
if (coord < boxlo && periodicity) coord += prd;
else if (coord >= boxhi && periodicity) coord -= prd;
if (coord >= slablo_lo && coord < slablo_hi) {
if (p > pmax) {
pmax = p;
ipos = i;
}
}
if (coord >= slabhi_lo && coord < slabhi_hi) {
if (p < pmin) {
pmin = p;
ineg = i;
}
}
}
// find 2 global atoms with most pos/neg momenta in bottom/top slabs
// MAXLOC also communicates which procs own them
mine[0].value = pmax;
mine[0].proc = me;
mine[1].value = -pmin;
mine[1].proc = me;
MPI_Allreduce(mine,all,2,MPI_DOUBLE_INT,MPI_MAXLOC,world);
// exchange momenta between the 2 particles
// if I own both particles just swap, else point2point comm of mass,vel
double sbuf[2],rbuf[2];
if (me == all[0].proc && me == all[1].proc) {
sbuf[0] = v[ineg][vdim];
if (mass) sbuf[1] = mass[type[ineg]];
else sbuf[1] = rmass[ineg];
rbuf[0] = v[ipos][vdim];
if (mass) rbuf[1] = mass[type[ipos]];
else rbuf[1] = rmass[ipos];
v[ineg][vdim] = rbuf[0] * rbuf[1]/sbuf[1];
v[ipos][vdim] = sbuf[0] * sbuf[1]/rbuf[1];
} else if (me == all[0].proc) {
sbuf[0] = v[ipos][vdim];
if (mass) sbuf[1] = mass[type[ipos]];
else sbuf[1] = rmass[ipos];
MPI_Sendrecv(sbuf,2,MPI_DOUBLE,all[1].proc,0,
rbuf,2,MPI_DOUBLE,all[1].proc,0,world,&status);
v[ipos][vdim] = rbuf[0] * rbuf[1]/sbuf[1];
} else if (me == all[1].proc) {
sbuf[0] = v[ineg][vdim];
if (mass) sbuf[1] = mass[type[ineg]];
else sbuf[1] = rmass[ineg];
MPI_Sendrecv(sbuf,2,MPI_DOUBLE,all[0].proc,0,
rbuf,2,MPI_DOUBLE,all[0].proc,0,world,&status);
v[ineg][vdim] = rbuf[0] * rbuf[1]/sbuf[1];
}
// tally momentum flux
// sign of all[1].value was flipped for MPI_Allreduce
flux += all[0].value + all[1].value;
}
/* ---------------------------------------------------------------------- */
double FixViscosity::compute_scalar()
{
return flux;
}

Event Timeline