/* ---------------------------------------------------------------------- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator https://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 "fix_nve_limit.h" #include "atom.h" #include "comm.h" #include "error.h" #include "force.h" #include "modify.h" #include "respa.h" #include "update.h" #include using namespace LAMMPS_NS; using namespace FixConst; /* ---------------------------------------------------------------------- */ FixNVELimit::FixNVELimit(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { if (narg != 4) error->all(FLERR,"Illegal fix nve/limit command"); time_integrate = 1; scalar_flag = 1; global_freq = 1; extscalar = 1; dynamic_group_allow = 1; xlimit = utils::numeric(FLERR,arg[3],false,lmp); ncount = 0; } /* ---------------------------------------------------------------------- */ int FixNVELimit::setmask() { int mask = 0; mask |= INITIAL_INTEGRATE; mask |= FINAL_INTEGRATE; mask |= INITIAL_INTEGRATE_RESPA; mask |= FINAL_INTEGRATE_RESPA; return mask; } /* ---------------------------------------------------------------------- */ void FixNVELimit::init() { dtv = update->dt; dtf = 0.5 * update->dt * force->ftm2v; vlimitsq = (xlimit/dtv) * (xlimit/dtv); ncount = 0; if (utils::strmatch(update->integrate_style,"^respa")) step_respa = ((Respa *) update->integrate)->step; // warn if using fix shake, which will lead to invalid constraint forces for (int i = 0; i < modify->nfix; i++) if (utils::strmatch(modify->fix[i]->style,"^shake") || utils::strmatch(modify->fix[i]->style,"^rattle")) { if (comm->me == 0) error->warning(FLERR,"Should not use fix nve/limit with fix shake or fix rattle"); } } /* ---------------------------------------------------------------------- allow for both per-type and per-atom mass ------------------------------------------------------------------------- */ void FixNVELimit::initial_integrate(int /*vflag*/) { double dtfm,vsq,scale; double **x = atom->x; double **v = atom->v; double **f = atom->f; double *mass = atom->mass; double *rmass = atom->rmass; int *type = atom->type; int *mask = atom->mask; int nlocal = atom->nlocal; if (igroup == atom->firstgroup) nlocal = atom->nfirst; if (rmass) { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dtfm = dtf / rmass[i]; v[i][0] += dtfm * f[i][0]; v[i][1] += dtfm * f[i][1]; v[i][2] += dtfm * f[i][2]; vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]; if (vsq > vlimitsq) { ncount++; scale = sqrt(vlimitsq/vsq); v[i][0] *= scale; v[i][1] *= scale; v[i][2] *= scale; } x[i][0] += dtv * v[i][0]; x[i][1] += dtv * v[i][1]; x[i][2] += dtv * v[i][2]; } } } else { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dtfm = dtf / mass[type[i]]; v[i][0] += dtfm * f[i][0]; v[i][1] += dtfm * f[i][1]; v[i][2] += dtfm * f[i][2]; vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]; if (vsq > vlimitsq) { ncount++; scale = sqrt(vlimitsq/vsq); v[i][0] *= scale; v[i][1] *= scale; v[i][2] *= scale; } x[i][0] += dtv * v[i][0]; x[i][1] += dtv * v[i][1]; x[i][2] += dtv * v[i][2]; } } } } /* ---------------------------------------------------------------------- */ void FixNVELimit::final_integrate() { double dtfm,vsq,scale; double **v = atom->v; double **f = atom->f; double *mass = atom->mass; double *rmass = atom->rmass; int *type = atom->type; int *mask = atom->mask; int nlocal = atom->nlocal; if (igroup == atom->firstgroup) nlocal = atom->nfirst; if (rmass) { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dtfm = dtf / rmass[i]; v[i][0] += dtfm * f[i][0]; v[i][1] += dtfm * f[i][1]; v[i][2] += dtfm * f[i][2]; vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]; if (vsq > vlimitsq) { ncount++; scale = sqrt(vlimitsq/vsq); v[i][0] *= scale; v[i][1] *= scale; v[i][2] *= scale; } } } } else { for (int i = 0; i < nlocal; i++) { if (mask[i] & groupbit) { dtfm = dtf / mass[type[i]]; v[i][0] += dtfm * f[i][0]; v[i][1] += dtfm * f[i][1]; v[i][2] += dtfm * f[i][2]; vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]; if (vsq > vlimitsq) { ncount++; scale = sqrt(vlimitsq/vsq); v[i][0] *= scale; v[i][1] *= scale; v[i][2] *= scale; } } } } } /* ---------------------------------------------------------------------- */ void FixNVELimit::initial_integrate_respa(int vflag, int ilevel, int /*iloop*/) { dtv = step_respa[ilevel]; dtf = 0.5 * step_respa[ilevel] * force->ftm2v; if (ilevel == 0) initial_integrate(vflag); else final_integrate(); } /* ---------------------------------------------------------------------- */ void FixNVELimit::final_integrate_respa(int ilevel, int /*iloop*/) { dtf = 0.5 * step_respa[ilevel] * force->ftm2v; final_integrate(); } /* ---------------------------------------------------------------------- */ void FixNVELimit::reset_dt() { dtv = update->dt; dtf = 0.5 * update->dt * force->ftm2v; vlimitsq = (xlimit/dtv) * (xlimit/dtv); } /* ---------------------------------------------------------------------- energy of indenter interaction ------------------------------------------------------------------------- */ double FixNVELimit::compute_scalar() { double one = ncount; double all; MPI_Allreduce(&one,&all,1,MPI_DOUBLE,MPI_SUM,world); return all; }