diff --git a/doc/compute_msd.txt b/doc/compute_msd.txt index 9ada35314caf83184b020ead539b0a11ff766f24..c95f5a8b6b072b5dd1577730f2b3a7a6647fd158 100644 --- a/doc/compute_msd.txt +++ b/doc/compute_msd.txt @@ -15,14 +15,15 @@ compute ID group-ID msd keyword values ... :pre ID, group-ID are documented in "compute"_compute.html command :ulb,l msd = style name of this compute command :l zero or more keyword/value pairs may be appended :l -keyword = {com} :l - {com} value = {yes} or {no} :pre +keyword = {com} or {average} :l + {com} value = {yes} or {no} + {average} value = {yes} or {no} :pre :ule [Examples:] compute 1 all msd -compute 1 upper msd com yes :pre +compute 1 upper msd com yes average yes :pre [Description:] @@ -41,13 +42,19 @@ averaged over atoms in the group. The slope of the mean-squared displacement (MSD) versus time is proportional to the diffusion coefficient of the diffusing atoms. -The displacement of an atom is from its original position at the time -the compute command was issued. The value of the displacement will be +The displacement of an atom is from its reference position. This is +normally the original position at the time +the compute command was issued, unless the {average} keyword is set to {yes}. +The value of the displacement will be 0.0 for atoms not in the specified compute group. If the {com} option is set to {yes} then the effect of any drift in -the center-of-mass of the group of atoms is subtracted out before xhe -displacment of each atom is calcluated. +the center-of-mass of the group of atoms is subtracted out before the +displacment of each atom is calculated. + +If the {average} option is set to {yes} then the reference position of +an atom is a running average of the atom position over all the calls +to the msd calculation since the compute was invoked. IMPORTANT NOTE: Initial coordinates are stored in "unwrapped" form, by using the image flags associated with each atom. See the "dump @@ -62,7 +69,13 @@ to be continuous when running from a "restart file"_read_restart.html, then you should use the same ID for this compute, as in the original run. This is so that the fix this compute creates to store per-atom quantities will also have the same ID, and thus be initialized -correctly with time=0 atom coordinates from the restart file. +correctly with atom reference positions from the restart file. +When {average} is set to yes, then the atom reference positions +are restored correctly, but not the number of samples used +obtain them. As a result, the reference positions from the restart +file are combined with subsequent positions as if they were from a +single sample, instead of many, which will change the values of msd +somewhat. [Output info:] @@ -86,4 +99,4 @@ msd/chunk"_compute_msd_chunk.html [Default:] -The option default is com = no. +The option default are com = no, average = no. diff --git a/src/compute_msd.cpp b/src/compute_msd.cpp index 0d35a886202e3b3281cf814e096410e1576de1d3..7200da83f41d791769e607902bf2a44caa5e2abe 100644 --- a/src/compute_msd.cpp +++ b/src/compute_msd.cpp @@ -38,6 +38,7 @@ ComputeMSD::ComputeMSD(LAMMPS *lmp, int narg, char **arg) : // optional args comflag = 0; + avflag = 0; int iarg = 3; while (iarg < narg) { @@ -47,10 +48,16 @@ ComputeMSD::ComputeMSD(LAMMPS *lmp, int narg, char **arg) : else if (strcmp(arg[iarg+1],"yes") == 0) comflag = 1; else error->all(FLERR,"Illegal compute msd command"); iarg += 2; + } else if (strcmp(arg[iarg],"average") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal compute msd command"); + if (strcmp(arg[iarg+1],"no") == 0) avflag = 0; + else if (strcmp(arg[iarg+1],"yes") == 0) avflag = 1; + else error->all(FLERR,"Illegal compute msd command"); + iarg += 2; } else error->all(FLERR,"Illegal compute msd command"); } - // create a new fix STORE style + // create a new fix STORE style for reference positions // id = compute-ID + COMPUTE_STORE, fix group = compute group int n = strlen(id) + strlen("_COMPUTE_STORE") + 1; @@ -97,6 +104,11 @@ ComputeMSD::ComputeMSD(LAMMPS *lmp, int narg, char **arg) : xoriginal[i][2] -= cm[2]; } } + + // initialize counter for average positions if requested + + if (avflag) naverage = 1; + } // displacement vector @@ -120,7 +132,7 @@ ComputeMSD::~ComputeMSD() void ComputeMSD::init() { - // set fix which stores original atom coords + // set fix which stores reference atom coords int ifix = modify->find_fix(id_fix); if (ifix < 0) error->all(FLERR,"Could not find compute msd fix ID"); @@ -144,8 +156,8 @@ void ComputeMSD::compute_vector() if (comflag) group->xcm(igroup,masstotal,cm); else cm[0] = cm[1] = cm[2] = 0.0; - // dx,dy,dz = displacement of atom from original position - // original unwrapped position is stored by fix + // dx,dy,dz = displacement of atom from reference position + // reference unwrapped position is stored by fix // relative to center of mass if comflag is set // for triclinic, need to unwrap current atom coord via h matrix @@ -167,35 +179,63 @@ void ComputeMSD::compute_vector() double msd[4]; msd[0] = msd[1] = msd[2] = msd[3] = 0.0; + + + double xtmp, ytmp, ztmp; + if (domain->triclinic == 0) { for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { xbox = (image[i] & IMGMASK) - IMGMAX; ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; zbox = (image[i] >> IMG2BITS) - IMGMAX; - dx = x[i][0] + xbox*xprd - cm[0] - xoriginal[i][0]; - dy = x[i][1] + ybox*yprd - cm[1] - xoriginal[i][1]; - dz = x[i][2] + zbox*zprd - cm[2] - xoriginal[i][2]; + xtmp = x[i][0] + xbox*xprd - cm[0]; + ytmp = x[i][1] + ybox*yprd - cm[1]; + ztmp = x[i][2] + zbox*zprd - cm[2]; + dx = xtmp - xoriginal[i][0]; + dy = ytmp - xoriginal[i][1]; + dz = ztmp - xoriginal[i][2]; msd[0] += dx*dx; msd[1] += dy*dy; msd[2] += dz*dz; msd[3] += dx*dx + dy*dy + dz*dz; - } + // use running average position for reference if requested + + if (avflag) { + double navfac = 1.0/(naverage+1); + xoriginal[i][0] = (xoriginal[i][0]*naverage + xtmp)*navfac; + xoriginal[i][1] = (xoriginal[i][1]*naverage + ytmp)*navfac; + xoriginal[i][2] = (xoriginal[i][2]*naverage + ztmp)*navfac; + naverage++; + } + } } else { for (int i = 0; i < nlocal; i++) if (mask[i] & groupbit) { xbox = (image[i] & IMGMASK) - IMGMAX; ybox = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; zbox = (image[i] >> IMG2BITS) - IMGMAX; - dx = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox - - cm[0] - xoriginal[i][0]; - dy = x[i][1] + h[1]*ybox + h[3]*zbox - cm[1] - xoriginal[i][1]; - dz = x[i][2] + h[2]*zbox - cm[2] - xoriginal[i][2]; + xtmp = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox - cm[0]; + ytmp = x[i][1] + h[1]*ybox + h[3]*zbox - cm[1]; + ztmp = x[i][2] + h[2]*zbox - cm[2]; + dx = xtmp - xoriginal[i][0]; + dy = ytmp - xoriginal[i][1]; + dz = ztmp - xoriginal[i][2]; msd[0] += dx*dx; msd[1] += dy*dy; msd[2] += dz*dz; msd[3] += dx*dx + dy*dy + dz*dz; + + // use running average position for reference if requested + + if (avflag) { + double navfac = 1.0/(naverage+1); + xoriginal[i][0] = (xoriginal[i][0]*naverage + xtmp)*navfac; + xoriginal[i][1] = (xoriginal[i][0]*naverage + xtmp)*navfac; + xoriginal[i][2] = (xoriginal[i][0]*naverage + xtmp)*navfac; + naverage++; + } } } diff --git a/src/compute_msd.h b/src/compute_msd.h index 29d25ceb5385af02087ee699b6448c281ada661c..63abf4c4eb60018ac147046d7d12096e83c20208 100644 --- a/src/compute_msd.h +++ b/src/compute_msd.h @@ -33,7 +33,9 @@ class ComputeMSD : public Compute { void set_arrays(int); protected: - int comflag; + int comflag; // comflag = 1 if reference moves with center of mass + int avflag; // avflag = 1 if using average position as reference + int naverage; // number of samples for average position bigint nmsd; double masstotal; char *id_fix;