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;