Merge pull request #3012 from akohlmey/reserved_data_section_keywords

Check for reserved data section keywords - update fix processing for data files
This commit is contained in:
Axel Kohlmeyer
2021-10-28 19:52:27 -04:00
committed by GitHub
7 changed files with 129 additions and 115 deletions

View File

@ -30,18 +30,19 @@
#include "fix_cmap.h"
#include <cmath>
#include <cstring>
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "force.h"
#include "comm.h"
#include "domain.h"
#include "error.h"
#include "force.h"
#include "math_const.h"
#include "memory.h"
#include "error.h"
#include "respa.h"
#include "tokenizer.h"
#include "update.h"
#include <cmath>
#include <cstring>
using namespace LAMMPS_NS;
using namespace FixConst;
@ -1043,12 +1044,24 @@ void FixCMAP::bc_interpol(double x1, double x2, int low1, int low2, double *gs,
void FixCMAP::read_data_header(char *line)
{
if (strstr(line,"crossterms")) {
sscanf(line,BIGINT_FORMAT,&ncmap);
} else error->all(FLERR,"Invalid read data header line for fix cmap");
ValueTokenizer values(line);
// didn't set in constructor because this fix could be defined
// before newton command
try {
ncmap = values.next_bigint();
if (values.count() == 2) {
if (values.next_string() != "crossterms")
throw TokenizerException("invalid format",utils::trim(line));
} else if (values.count() == 3) {
if ((values.next_string() != "cmap") || (values.next_string() != "crossterms"))
throw TokenizerException("invalid format",utils::trim(line));
} else {
throw TokenizerException("valid format",utils::trim(line));
}
} catch (std::exception &e) {
error->all(FLERR,"Invalid read data header line for fix cmap: {}", e.what());
}
// not set in constructor because this fix could be defined before newton command
newton_bond = force->newton_bond;
}
@ -1064,26 +1077,28 @@ void FixCMAP::read_data_section(char *keyword, int n, char *buf,
{
int m,tmp,itype;
tagint atom1,atom2,atom3,atom4,atom5;
char *next;
next = strchr(buf,'\n');
*next = '\0';
int nwords = utils::count_words(utils::trim_comment(buf));
*next = '\n';
if (nwords != 7)
error->all(FLERR,"Incorrect {} format in data file",keyword);
auto lines = utils::split_lines(buf);
if (lines.size() == 0) return;
// loop over lines of CMAP crossterms
// tokenize the line into values
// add crossterm to one of my atoms, depending on newton_bond
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
*next = '\0';
sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT
" " TAGINT_FORMAT " " TAGINT_FORMAT,
&tmp,&itype,&atom1,&atom2,&atom3,&atom4,&atom5);
for (const auto &line : lines) {
ValueTokenizer values(line);
try {
values.skip();
itype = values.next_int();
atom1 = values.next_tagint();
atom2 = values.next_tagint();
atom3 = values.next_tagint();
atom4 = values.next_tagint();
atom5 = values.next_tagint();
if (values.has_next()) throw TokenizerException("too many items",line);
} catch (std::exception &e) {
error->all(FLERR,"Incorrect format of CMAP section: {}", e.what());
}
atom1 += id_offset;
atom2 += id_offset;
@ -1092,8 +1107,7 @@ void FixCMAP::read_data_section(char *keyword, int n, char *buf,
atom5 += id_offset;
if ((m = atom->map(atom1)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
if (num_crossterm[m] == CMAPMAX) error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
@ -1104,8 +1118,7 @@ void FixCMAP::read_data_section(char *keyword, int n, char *buf,
}
if ((m = atom->map(atom2)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
if (num_crossterm[m] == CMAPMAX) error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
@ -1116,8 +1129,7 @@ void FixCMAP::read_data_section(char *keyword, int n, char *buf,
}
if ((m = atom->map(atom3)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
if (num_crossterm[m] == CMAPMAX) error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
@ -1128,8 +1140,7 @@ void FixCMAP::read_data_section(char *keyword, int n, char *buf,
}
if ((m = atom->map(atom4)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
if (num_crossterm[m] == CMAPMAX) error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
@ -1140,8 +1151,7 @@ void FixCMAP::read_data_section(char *keyword, int n, char *buf,
}
if ((m = atom->map(atom5)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
if (num_crossterm[m] == CMAPMAX) error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
@ -1150,8 +1160,6 @@ void FixCMAP::read_data_section(char *keyword, int n, char *buf,
crossterm_atom5[m][num_crossterm[m]] = atom5;
num_crossterm[m]++;
}
buf = next + 1;
}
}
@ -1169,7 +1177,7 @@ bigint FixCMAP::read_data_skip_lines(char * /*keyword*/)
void FixCMAP::write_data_header(FILE *fp, int /*mth*/)
{
fprintf(fp,BIGINT_FORMAT " cmap crossterms\n",ncmap);
fmt::print(fp,"{} crossterms\n",ncmap);
}
/* ----------------------------------------------------------------------
@ -1247,11 +1255,9 @@ void FixCMAP::write_data_section(int /*mth*/, FILE *fp,
int n, double **buf, int index)
{
for (int i = 0; i < n; i++)
fprintf(fp,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT
" " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT "\n",
index+i,(int) ubuf(buf[i][0]).i,(tagint) ubuf(buf[i][1]).i,
(tagint) ubuf(buf[i][2]).i,(tagint) ubuf(buf[i][3]).i,
(tagint) ubuf(buf[i][4]).i,(tagint) ubuf(buf[i][5]).i);
fmt::print(fp,"{} {} {} {} {} {} {}\n",
index+i,ubuf(buf[i][0]).i, ubuf(buf[i][1]).i, ubuf(buf[i][2]).i,
ubuf(buf[i][3]).i,ubuf(buf[i][4]).i,ubuf(buf[i][5]).i);
}
// ----------------------------------------------------------------------

View File

@ -18,6 +18,7 @@
#include "comm.h"
#include "error.h"
#include "memory.h"
#include "read_data.h"
#include "tokenizer.h"
#include <cstring>
@ -54,8 +55,7 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) :
while (iarg < narg) {
if (strcmp(arg[iarg],"mol") == 0) {
if (atom->molecule_flag)
error->all(FLERR,"Fix property/atom mol when atom_style "
"already has molecule attribute");
error->all(FLERR,"Fix property/atom mol when atom_style already has molecule attribute");
if (molecule_flag)
error->all(FLERR,"Fix property/atom cannot specify mol twice");
styles[nvalue] = MOLECULE;
@ -95,6 +95,8 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) :
index[nvalue] = atom->find_custom(&arg[iarg][2],flag,ncols);
if (index[nvalue] >= 0)
error->all(FLERR,"Fix property/atom vector name already exists");
if (ReadData::is_data_section(id))
error->all(FLERR,"Fix property/atom fix ID must not be a data file section name");
index[nvalue] = atom->add_custom(&arg[iarg][2],0,0);
cols[nvalue] = 0;
values_peratom++;
@ -107,6 +109,8 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) :
index[nvalue] = atom->find_custom(&arg[iarg][2],flag,ncols);
if (index[nvalue] >= 0)
error->all(FLERR,"Fix property/atom vector name already exists");
if (ReadData::is_data_section(id))
error->all(FLERR,"Fix property/atom fix ID must not be a data file section name");
index[nvalue] = atom->add_custom(&arg[iarg][2],1,0);
cols[nvalue] = 0;
values_peratom++;
@ -122,6 +126,8 @@ FixPropertyAtom::FixPropertyAtom(LAMMPS *lmp, int narg, char **arg) :
which = atom->find_custom(&arg[iarg][3],flag,ncols);
if (which >= 0)
error->all(FLERR,"Fix property/atom array name {} already exists", &arg[iarg][3]);
if (ReadData::is_data_section(id))
error->all(FLERR,"Fix property/atom fix ID must not be a data file section name");
ncols = utils::inumeric(FLERR,arg[iarg+1],true,lmp);
if (ncols < 1)

View File

@ -39,6 +39,8 @@
#include <cctype>
#include <cstring>
#include <string>
#include <unordered_set>
using namespace LAMMPS_NS;
@ -49,9 +51,27 @@ static constexpr int DELTA = 4; // must be 2 or larger
static constexpr int MAXBODY = 32; // max # of lines in one body
// customize for new sections
// change when add to header::section_keywords
static constexpr int NSECTIONS = 25;
static std::unordered_set<std::string> section_keywords = {
"Atoms", "Velocities", "Ellipsoids", "Lines", "Triangles", "Bodies",
"Bonds", "Angles", "Dihedrals", "Impropers",
"Masses", "Pair Coeffs", "PairIJ Coeffs", "Bond Coeffs", "Angle Coeffs",
"Dihedral Coeffs", "Improper Coeffs",
"BondBond Coeffs", "BondAngle Coeffs", "MiddleBondTorsion Coeffs",
"EndBondTorsion Coeffs", "AngleTorsion Coeffs",
"AngleAngleTorsion Coeffs", "BondBond13 Coeffs", "AngleAngle Coeffs"
};
// function to check whether a string is a known data section name
// made a static class member, so it can be called from other classes
bool ReadData::is_data_section(const std::string &keyword)
{
return section_keywords.count(keyword) > 0;
}
// clang-format off
enum{NONE,APPEND,VALUE,MERGE};
// pair style suffixes to ignore
@ -266,18 +286,19 @@ void ReadData::command(int narg, char **arg)
if (iarg+4 > narg)
error->all(FLERR,"Illegal read_data command");
memory->grow(fix_index,nfix+1,"read_data:fix_index");
fix_header = (char **)
memory->srealloc(fix_header,(nfix+1)*sizeof(char *),
"read_data:fix_header");
fix_section = (char **)
memory->srealloc(fix_section,(nfix+1)*sizeof(char *),
"read_data:fix_section");
fix_header = (char **) memory->srealloc(fix_header,(nfix+1)*sizeof(char *),
"read_data:fix_header");
fix_section = (char **) memory->srealloc(fix_section,(nfix+1)*sizeof(char *),
"read_data:fix_section");
if (is_data_section(arg[iarg+3]))
error->all(FLERR,"Custom data section name {} for fix {} collides with existing "
"data section",arg[iarg+3],arg[iarg+1]);
fix_index[nfix] = modify->find_fix(arg[iarg+1]);
if (fix_index[nfix] < 0)
error->all(FLERR,"Fix ID for read_data does not exist");
if (fix_index[nfix] < 0) error->all(FLERR,"Fix ID for read_data does not exist");
if (strcmp(arg[iarg+2],"NULL") == 0) fix_header[nfix] = nullptr;
else fix_header[nfix] = utils::strdup(arg[iarg+2]);
fix_section[nfix] = utils::strdup(arg[iarg+3]);
if (strcmp(arg[iarg+3],"NULL") == 0) fix_section[nfix] = utils::strdup(arg[iarg+1]);
else fix_section[nfix] = utils::strdup(arg[iarg+3]);
nfix++;
iarg += 4;
@ -521,6 +542,7 @@ void ReadData::command(int narg, char **arg)
"from currently defined atom style");
atoms();
} else skip_lines(natoms);
} else if (strcmp(keyword,"Velocities") == 0) {
if (atomflag == 0)
error->all(FLERR,"Must read Atoms before Velocities");
@ -529,52 +551,50 @@ void ReadData::command(int narg, char **arg)
} else if (strcmp(keyword,"Bonds") == 0) {
topoflag = bondflag = 1;
if (nbonds == 0)
error->all(FLERR,"Invalid data file section: Bonds");
if (nbonds == 0) error->all(FLERR,"Invalid data file section: Bonds");
if (atomflag == 0) error->all(FLERR,"Must read Atoms before Bonds");
bonds(firstpass);
} else if (strcmp(keyword,"Angles") == 0) {
topoflag = angleflag = 1;
if (nangles == 0)
error->all(FLERR,"Invalid data file section: Angles");
if (nangles == 0) error->all(FLERR,"Invalid data file section: Angles");
if (atomflag == 0) error->all(FLERR,"Must read Atoms before Angles");
angles(firstpass);
} else if (strcmp(keyword,"Dihedrals") == 0) {
topoflag = dihedralflag = 1;
if (ndihedrals == 0)
error->all(FLERR,"Invalid data file section: Dihedrals");
if (ndihedrals == 0) error->all(FLERR,"Invalid data file section: Dihedrals");
if (atomflag == 0) error->all(FLERR,"Must read Atoms before Dihedrals");
dihedrals(firstpass);
} else if (strcmp(keyword,"Impropers") == 0) {
topoflag = improperflag = 1;
if (nimpropers == 0)
error->all(FLERR,"Invalid data file section: Impropers");
if (nimpropers == 0) error->all(FLERR,"Invalid data file section: Impropers");
if (atomflag == 0) error->all(FLERR,"Must read Atoms before Impropers");
impropers(firstpass);
} else if (strcmp(keyword,"Ellipsoids") == 0) {
ellipsoidflag = 1;
if (!avec_ellipsoid)
error->all(FLERR,"Invalid data file section: Ellipsoids");
if (atomflag == 0)
error->all(FLERR,"Must read Atoms before Ellipsoids");
if (!avec_ellipsoid) error->all(FLERR,"Invalid data file section: Ellipsoids");
if (atomflag == 0) error->all(FLERR,"Must read Atoms before Ellipsoids");
if (firstpass)
bonus(nellipsoids,(AtomVec *) avec_ellipsoid,"ellipsoids");
else skip_lines(nellipsoids);
} else if (strcmp(keyword,"Lines") == 0) {
lineflag = 1;
if (!avec_line)
error->all(FLERR,"Invalid data file section: Lines");
if (!avec_line) error->all(FLERR,"Invalid data file section: Lines");
if (atomflag == 0) error->all(FLERR,"Must read Atoms before Lines");
if (firstpass) bonus(nlines,(AtomVec *) avec_line,"lines");
else skip_lines(nlines);
} else if (strcmp(keyword,"Triangles") == 0) {
triflag = 1;
if (!avec_tri)
error->all(FLERR,"Invalid data file section: Triangles");
if (!avec_tri) error->all(FLERR,"Invalid data file section: Triangles");
if (atomflag == 0) error->all(FLERR,"Must read Atoms before Triangles");
if (firstpass) bonus(ntris,(AtomVec *) avec_tri,"triangles");
else skip_lines(ntris);
} else if (strcmp(keyword,"Bodies") == 0) {
bodyflag = 1;
if (!avec_body)
@ -655,6 +675,7 @@ void ReadData::command(int narg, char **arg)
error->all(FLERR,"Must define angle_style before BondBond Coeffs");
if (firstpass) anglecoeffs(1);
else skip_lines(nangletypes);
} else if (strcmp(keyword,"BondAngle Coeffs") == 0) {
if (atom->avec->angles_allow == 0)
error->all(FLERR,"Invalid data file section: BondAngle Coeffs");
@ -665,46 +686,41 @@ void ReadData::command(int narg, char **arg)
} else if (strcmp(keyword,"MiddleBondTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
error->all(FLERR,
"Invalid data file section: MiddleBondTorsion Coeffs");
error->all(FLERR,"Invalid data file section: MiddleBondTorsion Coeffs");
if (force->dihedral == nullptr)
error->all(FLERR,
"Must define dihedral_style before "
"MiddleBondTorsion Coeffs");
error->all(FLERR,"Must define dihedral_style before MiddleBondTorsion Coeffs");
if (firstpass) dihedralcoeffs(1);
else skip_lines(ndihedraltypes);
} else if (strcmp(keyword,"EndBondTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
error->all(FLERR,"Invalid data file section: EndBondTorsion Coeffs");
if (force->dihedral == nullptr)
error->all(FLERR,
"Must define dihedral_style before EndBondTorsion Coeffs");
error->all(FLERR,"Must define dihedral_style before EndBondTorsion Coeffs");
if (firstpass) dihedralcoeffs(2);
else skip_lines(ndihedraltypes);
} else if (strcmp(keyword,"AngleTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
error->all(FLERR,"Invalid data file section: AngleTorsion Coeffs");
if (force->dihedral == nullptr)
error->all(FLERR,
"Must define dihedral_style before AngleTorsion Coeffs");
error->all(FLERR,"Must define dihedral_style before AngleTorsion Coeffs");
if (firstpass) dihedralcoeffs(3);
else skip_lines(ndihedraltypes);
} else if (strcmp(keyword,"AngleAngleTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
error->all(FLERR,
"Invalid data file section: AngleAngleTorsion Coeffs");
error->all(FLERR,"Invalid data file section: AngleAngleTorsion Coeffs");
if (force->dihedral == nullptr)
error->all(FLERR,
"Must define dihedral_style before "
"AngleAngleTorsion Coeffs");
error->all(FLERR,"Must define dihedral_style before AngleAngleTorsion Coeffs");
if (firstpass) dihedralcoeffs(4);
else skip_lines(ndihedraltypes);
} else if (strcmp(keyword,"BondBond13 Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
error->all(FLERR,"Invalid data file section: BondBond13 Coeffs");
if (force->dihedral == nullptr)
error->all(FLERR,
"Must define dihedral_style before BondBond13 Coeffs");
error->all(FLERR,"Must define dihedral_style before BondBond13 Coeffs");
if (firstpass) dihedralcoeffs(5);
else skip_lines(ndihedraltypes);
@ -712,8 +728,7 @@ void ReadData::command(int narg, char **arg)
if (atom->avec->impropers_allow == 0)
error->all(FLERR,"Invalid data file section: AngleAngle Coeffs");
if (force->improper == nullptr)
error->all(FLERR,
"Must define improper_style before AngleAngle Coeffs");
error->all(FLERR,"Must define improper_style before AngleAngle Coeffs");
if (firstpass) impropercoeffs(1);
else skip_lines(nimpropertypes);
@ -724,8 +739,7 @@ void ReadData::command(int narg, char **arg)
for (i = 0; i < nfix; i++)
if (strcmp(keyword,fix_section[i]) == 0) {
if (firstpass) fix(fix_index[i],keyword);
else skip_lines(modify->fix[fix_index[i]]->
read_data_skip_lines(keyword));
else skip_lines(modify->fix[fix_index[i]]->read_data_skip_lines(keyword));
parse_keyword(0);
break;
}
@ -882,8 +896,7 @@ void ReadData::command(int narg, char **arg)
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (natoms != atom->natoms)
error->all(FLERR,
"Read_data shrink wrap did not assign all atoms correctly");
error->all(FLERR,"Read_data shrink wrap did not assign all atoms correctly");
}
// restore old styles, when reading with nocoeff flag given
@ -947,17 +960,6 @@ void ReadData::header(int firstpass)
atom->nimpropertypes = extra_improper_types;
}
// customize for new sections
const char *section_keywords[NSECTIONS] =
{"Atoms","Velocities","Ellipsoids","Lines","Triangles","Bodies",
"Bonds","Angles","Dihedrals","Impropers",
"Masses","Pair Coeffs","PairIJ Coeffs","Bond Coeffs","Angle Coeffs",
"Dihedral Coeffs","Improper Coeffs",
"BondBond Coeffs","BondAngle Coeffs","MiddleBondTorsion Coeffs",
"EndBondTorsion Coeffs","AngleTorsion Coeffs",
"AngleAngleTorsion Coeffs","BondBond13 Coeffs","AngleAngle Coeffs"};
// skip 1st line of file
if (me == 0) {
@ -1186,9 +1188,7 @@ void ReadData::header(int firstpass)
// check that exiting string is a valid section keyword
parse_keyword(1);
for (n = 0; n < NSECTIONS; n++)
if (strcmp(keyword,section_keywords[n]) == 0) break;
if (n == NSECTIONS)
if (!is_data_section(keyword))
error->all(FLERR,"Unknown identifier in data file: {}",keyword);
// error checks on header values
@ -1730,8 +1730,7 @@ void ReadData::bodies(int firstpass, AtomVec *ptr)
error->one(FLERR,"Too many values in body lines in data file");
if (onebody+1 > MAXBODY)
error->one(FLERR,
"Too many lines in one body in data file - boost MAXBODY");
error->one(FLERR,"Too many lines in one body in data file - boost MAXBODY");
nchunk++;
nline += onebody+1;

View File

@ -29,6 +29,7 @@ class ReadData : public Command {
ReadData(class LAMMPS *);
~ReadData();
void command(int, char **);
static bool is_data_section(const std::string &);
private:
int me, compressed;