revise/refacor Type Label section parsing and Atoms section parsing

- do not ignore numeric type in Type Label sections
- refuse invalid numeric types that will overflow arrays
- check for duplicate numeric type entries or non-unique labels
- better error messages
- use Tokenizer class instead of sscanf()
This commit is contained in:
Axel Kohlmeyer
2022-09-04 01:01:36 -04:00
parent 389c87ab7e
commit ad8a931fe4
5 changed files with 77 additions and 73 deletions

View File

@ -87,7 +87,7 @@ are updated by the AtomVec class as needed.
* instances of classes derived from the AtomVec base
* class, which correspond to the selected atom style.
*
* \param lmp pointer to the base LAMMPS class */
* \param _lmp pointer to the base LAMMPS class */
Atom::Atom(LAMMPS *_lmp) : Pointers(_lmp)
{
@ -1186,17 +1186,36 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset,
avec->data_atom(xdata,imagedata,values,typestr);
if (id_offset) tag[nlocal-1] += id_offset;
if (mol_offset) molecule[nlocal-1] += mol_offset;
if (!isdigit(typestr[0])) {
if (!atom->labelmapflag) error->one(FLERR,"Invalid Atoms section in data file");
type[nlocal-1] = lmap->find(typestr,Atom::ATOM);
if (type[nlocal-1] == -1) error->one(FLERR,"Invalid Atoms section in data file");
} else {
type[nlocal-1] = utils::inumeric(FLERR,typestr.c_str(),true,lmp);
if (labelflag) type[nlocal-1] = ilabel[type[nlocal-1]-1];
// clang-format on
switch (utils::is_type(typestr)) {
case 0: { // numeric
int itype = utils::inumeric(FLERR, typestr.c_str(), true, lmp);
if ((itype < 1) || (itype > ntypes))
error->one(FLERR, "Invalid atom type {} in Atoms section of data file: {}", itype,
buf);
type[nlocal - 1] = itype;
if (labelflag) type[nlocal - 1] = ilabel[itype - 1];
break;
}
case 1: { // type label
if (!atom->labelmapflag)
error->one(FLERR, "Invalid Atoms section line in data file: {}", buf);
type[nlocal - 1] = lmap->find(typestr, Atom::ATOM);
if (type[nlocal - 1] == -1)
error->one(FLERR, "Invalid Atoms section line in data file: {}", buf);
break;
}
default: // invalid
error->one(FLERR, "Invalid Atoms section line in data file: {}", buf);
break;
}
// clang-format off
if (type_offset) type[nlocal-1] += type_offset;
if (type[nlocal-1] <= 0 || type[nlocal-1] > ntypes)
error->one(FLERR,"Invalid atom type in Atoms section of data file");
error->one(FLERR,"Invalid atom type {} in Atoms section of data file", typestr);
}
}
buf = next + 1;

View File

@ -82,6 +82,8 @@ enum{NONE, APPEND, VALUE, MERGE};
static const char *suffixes[] = {"/cuda", "/gpu", "/opt", "/omp", "/kk", "/coul/cut", "/coul/long",
"/coul/msm", "/coul/dsf", "/coul/debye", "/coul/charmm", nullptr};
static const char *labeltypes[] = {"Atom", "Bond", "Angle", "Dihedral", "Improper" };
// clang-format on
/* ---------------------------------------------------------------------- */
ReadData::ReadData(LAMMPS *_lmp) : Command(_lmp), fp(nullptr), coeffarg(nullptr), lmap(nullptr)
@ -1322,9 +1324,7 @@ void ReadData::atoms()
eof = utils::read_lines_from_file(fp, nchunk, MAXLINE, buffer, me, world);
if (eof) error->all(FLERR, "Unexpected end of data file");
if (tlabelflag && !lmap->is_complete(Atom::ATOM))
error->all(FLERR,
"Label map is incomplete: "
"all types must be assigned a unique type label");
error->all(FLERR, "Label map is incomplete: all types must be assigned a unique type label");
atom->data_atoms(nchunk, buffer, id_offset, mol_offset, toffset, shiftflag, shift, tlabelflag,
lmap->lmap2lmap.atom);
nread += nchunk;
@ -2144,21 +2144,38 @@ void ReadData::typelabels(int mode)
int eof = utils::read_lines_from_file(fp, lntypes, MAXLINE, buf, me, world);
if (eof) error->all(FLERR, "Unexpected end of data file");
char *next;
char *original = buf;
char *typelabel = new char[MAXLINE];
char *next;
for (int i = 0; i < lntypes; i++) {
next = strchr(buf, '\n');
*next = '\0';
int rv = sscanf(buf, "%*d %s", typelabel);
if (rv != 1) error->all(FLERR, "Invalid data file section: Type Labels");
if (isdigit(typelabel[0])) error->all(FLERR, "Type labels cannot start with a number");
(*labels)[i] = typelabel;
(*labels_map)[typelabel] = i + 1;
auto values = Tokenizer(buf).as_vector();
int nwords = values.size();
for (std::size_t ii = 0; ii < values.size(); ++ii) {
if (utils::strmatch(values[ii],"^#")) {
nwords = ii;
break;
}
}
if (nwords != 2)
error->all(FLERR, "Invalid format in section: {} Type Labels: {}", labeltypes[mode], buf);
if (utils::is_type(values[1]) != 1) error->all(FLERR, "Invalid type label {}", values[1]);
int itype = utils::inumeric(FLERR, values[0], false, lmp);
if ((itype < 1) || (itype > lntypes))
error->all(FLERR, "Invalid type {} in section: {} Type Labels: {}", labeltypes[mode], buf);
(*labels)[itype - 1] = values[1];
(*labels_map)[values[1]] = itype;
buf = next + 1;
}
delete[] original;
delete[] typelabel;
for (int i = 0; i < lntypes; ++i) {
if ((*labels)[i].empty())
error->all(FLERR, "{} Type Labels map is incomplete", labeltypes[mode]);
}
if ((int)(*labels_map).size() != lntypes)
error->all(FLERR, "{} Type Labels map is incomplete", labeltypes[mode]);
// merge this read_data label map to atom class
// determine mapping to let labels override numeric types