From adf1beea74c605ce570e0af95109702a10292ab2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 28 Oct 2021 14:23:27 -0400 Subject: [PATCH] add mechanism to check for known data file section names using this mechanism we can reject custom section names that will conflict with existing section names and thus avoid misleading errors. apply this also to fix property atom, where the section name is determined by the fix ID. in addition, allow to specify NULL as section name, which will use the fix ID. --- doc/src/read_data.rst | 4 +- src/fix_property_atom.cpp | 10 ++- src/read_data.cpp | 129 +++++++++++++++++++------------------- src/read_data.h | 1 + 4 files changed, 76 insertions(+), 68 deletions(-) diff --git a/doc/src/read_data.rst b/doc/src/read_data.rst index ff212a579a..24f882b658 100644 --- a/doc/src/read_data.rst +++ b/doc/src/read_data.rst @@ -254,7 +254,9 @@ the fix defines the syntax of the header line(s) and section that it reads from the data file. Note that the *header-string* can be specified as NULL, in which case no header lines are passed to the fix. This means the fix can infer the length of its Section from -standard header settings, such as the number of atoms. +standard header settings, such as the number of atoms. Also the +*section-string* may be specified as NULL, and in that case the fix +ID is used as section name. The formatting of individual lines in the data file (indentation, spacing between words and numbers) is not important except that header diff --git a/src/fix_property_atom.cpp b/src/fix_property_atom.cpp index f90d83af4b..f7b9662c24 100644 --- a/src/fix_property_atom.cpp +++ b/src/fix_property_atom.cpp @@ -18,6 +18,7 @@ #include "comm.h" #include "error.h" #include "memory.h" +#include "read_data.h" #include "tokenizer.h" #include @@ -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) diff --git a/src/read_data.cpp b/src/read_data.cpp index 0c7af243ac..7e5d49e65c 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -39,6 +39,8 @@ #include #include +#include +#include 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 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; diff --git a/src/read_data.h b/src/read_data.h index 3374f48be0..090e70484b 100644 --- a/src/read_data.h +++ b/src/read_data.h @@ -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;