modernize parsing in fix tmd, add support for comments and empty lines

This commit is contained in:
Axel Kohlmeyer
2022-03-31 07:36:50 -04:00
parent 33b6466611
commit 52b563a83e
2 changed files with 72 additions and 57 deletions

View File

@ -29,10 +29,10 @@ Description
"""""""""""
Perform targeted molecular dynamics (TMD) on a group of atoms. A
holonomic constraint is used to force the atoms to move towards (or
away from) the target configuration. The parameter "rho" is
monotonically decreased (or increased) from its initial value to
rho_final at the end of the run.
holonomic constraint is used to force the atoms to move towards (or away
from) the target configuration. The parameter "rho" is monotonically
decreased (or increased) from its initial value to rho_final at the end
of the run.
Rho has distance units and is a measure of the root-mean-squared
distance (RMSD) between the current configuration of the atoms in the
@ -55,22 +55,25 @@ a .gz suffix). The format of the target file1 is as follows:
The first 3 lines may or may not be needed, depending on the format of
the atoms to follow. If image flags are included with the atoms, the
first 3 lo/hi lines must appear in the file. If image flags are not
included, the first 3 lines should not appear. The 3 lines contain the
first 3 lo/hi lines **must** appear in the file. If image flags are not
included, the first 3 lines **must not** appear. The 3 lines contain the
simulation box dimensions for the atom coordinates, in the same format
as in a LAMMPS data file (see the :doc:`read_data <read_data>` command).
The remaining lines each contain an atom ID and its target x,y,z
coordinates. The atom lines (all or none of them) can optionally be
followed by 3 integer values: nx,ny,nz. For periodic dimensions, they
followed by 3 integer values: nx,ny,nz.For periodic dimensions, they
specify which image of the box the atom is considered to be in, i.e. a
value of N (positive or negative) means add N times the box length to
the coordinate to get the true value.
the coordinate to get the true value. Those 3 integers either must
be given for all atoms or none.
The atom lines can be listed in any order, but every atom in the group
must be listed in the file. Atoms not in the fix group may also be
listed; they will be ignored.
Comments starting with '#' and empty lines may be included as well.
TMD statistics are written to file2 every N timesteps, unless N is
specified as 0, which means no statistics.

View File

@ -27,6 +27,7 @@
#include "memory.h"
#include "modify.h"
#include "respa.h"
#include "tokenizer.h"
#include "update.h"
#include <cmath>
@ -268,10 +269,8 @@ void FixTMD::initial_integrate(int /*vflag*/)
work_lambda += lambda*(rho_target - rho_old);
if (!(update->ntimestep % nfileevery) &&
(previous_stat != update->ntimestep)) {
fprintf(fp,
BIGINT_FORMAT " %g %g %g %g %g %g %g\n",
update->ntimestep,rho_target,rho_old,
gamma_back,gamma_forward,lambda,work_lambda,work_analytical);
fmt::print(fp, "{} {} {} {} {} {} {} {}\n", update->ntimestep,rho_target,rho_old,
gamma_back,gamma_forward,lambda,work_lambda,work_analytical);
fflush(fp);
previous_stat = update->ntimestep;
}
@ -392,7 +391,7 @@ void FixTMD::readfile(char *file)
char *buffer = new char[CHUNK*MAXLINE];
char *next,*bufptr;
int i,m,n,nlines,imageflag,ix,iy,iz;
int i,m,nlines,imageflag,ix,iy,iz;
tagint itag;
double x,y,z,xprd,yprd,zprd;
@ -422,53 +421,66 @@ void FixTMD::readfile(char *file)
for (i = 0; i < nlines; i++) {
next = strchr(bufptr,'\n');
*next = '\0';
if (firstline) {
if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+xlo\\s+xhi")) {
double lo,hi;
n = sscanf(bufptr,"%lg %lg",&lo,&hi);
if (n != 2)
error->all(FLERR,"Incorrect format in TMD target file");
xprd = hi - lo;
bufptr = next + 1;
continue;
} else if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+ylo\\s+yhi")) {
double lo,hi;
n = sscanf(bufptr,"%lg %lg",&lo,&hi);
if (n != 2)
error->all(FLERR,"Incorrect format in TMD target file");
yprd = hi - lo;
bufptr = next + 1;
continue;
} else if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+zlo\\s+zhi")) {
double lo,hi;
n = sscanf(bufptr,"%lg %lg",&lo,&hi);
if (n != 2)
error->all(FLERR,"Incorrect format in TMD target file");
zprd = hi - lo;
bufptr = next + 1;
continue;
} else if (utils::trim_and_count_words(bufptr) == 4) {
if (xprd >= 0.0 || yprd >= 0.0 || zprd >= 0.0)
error->all(FLERR,"Incorrect format in TMD target file");
imageflag = 0;
firstline = 0;
} else if (utils::trim_and_count_words(bufptr) == 7) {
if (xprd < 0.0 || yprd < 0.0 || zprd < 0.0)
error->all(FLERR,"Incorrect format in TMD target file");
imageflag = 1;
firstline = 0;
} else error->all(FLERR,"Incorrect format in TMD target file");
// trim comments and skip empty lines
char *comment = strchr(bufptr,'#');
if (comment) *comment = '\0';
if (!strlen(bufptr)) {
bufptr = next + 1;
continue;
}
if (imageflag)
n = 7 - sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg %d %d %d",
&itag,&x,&y,&z,&ix,&iy,&iz);
else
n = 4 - sscanf(bufptr,TAGINT_FORMAT " %lg %lg %lg",&itag,&x,&y,&z);
if (firstline) {
try {
ValueTokenizer values(bufptr);
if (n != 0) {
error->all(FLERR,"Incorrectly formatted line in TMD target file");
if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+xlo\\s+xhi")) {
auto lo = values.next_double();
auto hi = values.next_double();
xprd = hi - lo;
bufptr = next + 1;
continue;
} else if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+ylo\\s+yhi")) {
auto lo = values.next_double();
auto hi = values.next_double();
yprd = hi - lo;
bufptr = next + 1;
continue;
} else if (utils::strmatch(bufptr,"^\\s*\\f+\\s+\\f+\\s+zlo\\s+zhi")) {
auto lo = values.next_double();
auto hi = values.next_double();
zprd = hi - lo;
bufptr = next + 1;
continue;
} else if (utils::trim_and_count_words(bufptr) == 4) {
if (xprd >= 0.0 || yprd >= 0.0 || zprd >= 0.0)
throw TokenizerException("must use imageflags when providing box boundaries", bufptr);
imageflag = 0;
firstline = 0;
} else if (utils::trim_and_count_words(bufptr) == 7) {
if (xprd < 0.0 || yprd < 0.0 || zprd < 0.0)
throw TokenizerException("Invalid box boundaries","");
imageflag = 1;
firstline = 0;
} else throw TokenizerException("unknown data", bufptr);
}
catch (std::exception &e) {
error->all(FLERR,"Incorrect format in TMD target file: {}", e.what());
}
}
try {
ValueTokenizer values(bufptr);
itag = values.next_tagint();
x = values.next_double();
y = values.next_double();
z = values.next_double();
if (imageflag) {
ix = values.next_int();
iy = values.next_int();
iz = values.next_int();
}
} catch (std::exception &e) {
error->all(FLERR,"Incorrectly formatted line in TMD target file: {}", e.what());
bufptr = next + 1;
continue;
}