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,9 +269,7 @@ 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,
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';
// trim comments and skip empty lines
char *comment = strchr(bufptr,'#');
if (comment) *comment = '\0';
if (!strlen(bufptr)) {
bufptr = next + 1;
continue;
}
if (firstline) {
try {
ValueTokenizer values(bufptr);
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");
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")) {
double lo,hi;
n = sscanf(bufptr,"%lg %lg",&lo,&hi);
if (n != 2)
error->all(FLERR,"Incorrect format in TMD target file");
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")) {
double lo,hi;
n = sscanf(bufptr,"%lg %lg",&lo,&hi);
if (n != 2)
error->all(FLERR,"Incorrect format in TMD target file");
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)
error->all(FLERR,"Incorrect format in TMD target file");
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)
error->all(FLERR,"Incorrect format in TMD target file");
throw TokenizerException("Invalid box boundaries","");
imageflag = 1;
firstline = 0;
} else error->all(FLERR,"Incorrect format in TMD target file");
} else throw TokenizerException("unknown data", bufptr);
}
catch (std::exception &e) {
error->all(FLERR,"Incorrect format in TMD target file: {}", e.what());
}
}
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 (n != 0) {
error->all(FLERR,"Incorrectly formatted line in TMD target file");
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;
}