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:
@ -24,8 +24,8 @@ Examples
|
|||||||
|
|
||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
labelmap atom 3 carbon
|
labelmap atom 3 carbon 4 'c3"' 5 "c1'" 6 "c#"
|
||||||
labelmap bond 1 carbonyl 2 nitrile
|
labelmap bond 1 carbonyl 2 nitrile 3 """ c1'-c2" """
|
||||||
labelmap atom $(label(carbon)) C # change type label from 'carbon' to 'C'
|
labelmap atom $(label(carbon)) C # change type label from 'carbon' to 'C'
|
||||||
labelmap clear
|
labelmap clear
|
||||||
labelmap write mymap.include
|
labelmap write mymap.include
|
||||||
@ -46,29 +46,33 @@ Bond Type Labels, etc. See the :doc:`Howto type labels
|
|||||||
labels can be used.
|
labels can be used.
|
||||||
|
|
||||||
Valid type labels may contain any alphanumeric character, but must not
|
Valid type labels may contain any alphanumeric character, but must not
|
||||||
start with a number. They can also contain other standard ASCII
|
start with a number, a '#', or a '*' character. They may contain other
|
||||||
characters such as angular or square brackets '<' and '>' or '[' and
|
standard ASCII characters such as angular or square brackets '<' and '>'
|
||||||
']', parenthesis '(' and ')', dash '-', underscore '_', plus '+' and
|
or '[' and ']', parenthesis '(' and ')', dash '-', underscore '_', plus
|
||||||
equals '=' signs and more. Note that type labels must be put in
|
'+' and equals '=' signs and more. The must not contain blanks or any
|
||||||
quotation marks if they contain the '#' character when used in a context
|
other whitespace. Note that type labels must be put in single or double
|
||||||
where the '#' character would be interpreted as starting a comment like
|
quotation marks if they contain the '#' character, or a double (") or
|
||||||
in the LAMMPS input file.
|
single quotation mark ("). If the label contains both, single and double
|
||||||
|
quotes, triple quotation (""") must be used. When using quotation
|
||||||
|
marks, the LAMMPS input parser may require adding leading or trailing
|
||||||
|
blanks so it can identify the quotation marks. Those blanks will be
|
||||||
|
removed when defining the label.
|
||||||
|
|
||||||
A *labelmap* command can only modify the label map for one type-kind
|
A *labelmap* command can only modify the label map for one type-kind
|
||||||
(atom types, bond types, etc). Any number of numeric-type/type-label
|
(atom types, bond types, etc). Any number of numeric-type/type-label
|
||||||
pairs may follow. If a type label already exists for a given numeric
|
pairs may follow. If a type label already exists for the same numeric
|
||||||
type, it will be overwritten. Type labels must be unique; assigning
|
type, it will be overwritten. Type labels must be unique; assigning the
|
||||||
the same type label to multiple numeric types is not allowed. In some
|
same type label to multiple numeric types is not allowed. In some
|
||||||
cases, such as when reading and writing data files, it is required
|
cases, such as when reading and writing data files, it is required that
|
||||||
that when type labels are used, that there is a label defined for
|
when type labels are used, that there is a label defined for *every*
|
||||||
*every* numeric type.
|
numeric type.
|
||||||
|
|
||||||
The *clear* option resets the labelmap and thus discards all previous
|
The *clear* option resets the labelmap and thus discards all previous
|
||||||
settings.
|
settings.
|
||||||
|
|
||||||
The *write* option takes a filename as argument and writes the current
|
The *write* option takes a filename as argument and writes the current
|
||||||
label mappings to a file as labelmap commands, so the file can be copied
|
label mappings to a file as labelmap commands, so the file can be copied
|
||||||
into a different LAMMPS input file or read using the :doc:`include
|
into a new LAMMPS input file or read in using the :doc:`include
|
||||||
<include>` command.
|
<include>` command.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|||||||
37
src/atom.cpp
37
src/atom.cpp
@ -87,7 +87,7 @@ are updated by the AtomVec class as needed.
|
|||||||
* instances of classes derived from the AtomVec base
|
* instances of classes derived from the AtomVec base
|
||||||
* class, which correspond to the selected atom style.
|
* 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)
|
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);
|
avec->data_atom(xdata,imagedata,values,typestr);
|
||||||
if (id_offset) tag[nlocal-1] += id_offset;
|
if (id_offset) tag[nlocal-1] += id_offset;
|
||||||
if (mol_offset) molecule[nlocal-1] += mol_offset;
|
if (mol_offset) molecule[nlocal-1] += mol_offset;
|
||||||
if (!isdigit(typestr[0])) {
|
// clang-format on
|
||||||
if (!atom->labelmapflag) error->one(FLERR,"Invalid Atoms section in data file");
|
switch (utils::is_type(typestr)) {
|
||||||
type[nlocal-1] = lmap->find(typestr,Atom::ATOM);
|
|
||||||
if (type[nlocal-1] == -1) error->one(FLERR,"Invalid Atoms section in data file");
|
case 0: { // numeric
|
||||||
} else {
|
int itype = utils::inumeric(FLERR, typestr.c_str(), true, lmp);
|
||||||
type[nlocal-1] = utils::inumeric(FLERR,typestr.c_str(),true,lmp);
|
if ((itype < 1) || (itype > ntypes))
|
||||||
if (labelflag) type[nlocal-1] = ilabel[type[nlocal-1]-1];
|
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_offset) type[nlocal-1] += type_offset;
|
||||||
if (type[nlocal-1] <= 0 || type[nlocal-1] > ntypes)
|
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;
|
buf = next + 1;
|
||||||
|
|||||||
@ -82,6 +82,8 @@ enum{NONE, APPEND, VALUE, MERGE};
|
|||||||
static const char *suffixes[] = {"/cuda", "/gpu", "/opt", "/omp", "/kk", "/coul/cut", "/coul/long",
|
static const char *suffixes[] = {"/cuda", "/gpu", "/opt", "/omp", "/kk", "/coul/cut", "/coul/long",
|
||||||
"/coul/msm", "/coul/dsf", "/coul/debye", "/coul/charmm", nullptr};
|
"/coul/msm", "/coul/dsf", "/coul/debye", "/coul/charmm", nullptr};
|
||||||
|
|
||||||
|
static const char *labeltypes[] = {"Atom", "Bond", "Angle", "Dihedral", "Improper" };
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
ReadData::ReadData(LAMMPS *_lmp) : Command(_lmp), fp(nullptr), coeffarg(nullptr), lmap(nullptr)
|
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);
|
eof = utils::read_lines_from_file(fp, nchunk, MAXLINE, buffer, me, world);
|
||||||
if (eof) error->all(FLERR, "Unexpected end of data file");
|
if (eof) error->all(FLERR, "Unexpected end of data file");
|
||||||
if (tlabelflag && !lmap->is_complete(Atom::ATOM))
|
if (tlabelflag && !lmap->is_complete(Atom::ATOM))
|
||||||
error->all(FLERR,
|
error->all(FLERR, "Label map is incomplete: all types must be assigned a unique type label");
|
||||||
"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,
|
atom->data_atoms(nchunk, buffer, id_offset, mol_offset, toffset, shiftflag, shift, tlabelflag,
|
||||||
lmap->lmap2lmap.atom);
|
lmap->lmap2lmap.atom);
|
||||||
nread += nchunk;
|
nread += nchunk;
|
||||||
@ -2144,21 +2144,38 @@ void ReadData::typelabels(int mode)
|
|||||||
int eof = utils::read_lines_from_file(fp, lntypes, MAXLINE, buf, me, world);
|
int eof = utils::read_lines_from_file(fp, lntypes, MAXLINE, buf, me, world);
|
||||||
if (eof) error->all(FLERR, "Unexpected end of data file");
|
if (eof) error->all(FLERR, "Unexpected end of data file");
|
||||||
|
|
||||||
char *next;
|
|
||||||
char *original = buf;
|
char *original = buf;
|
||||||
char *typelabel = new char[MAXLINE];
|
char *next;
|
||||||
for (int i = 0; i < lntypes; i++) {
|
for (int i = 0; i < lntypes; i++) {
|
||||||
next = strchr(buf, '\n');
|
next = strchr(buf, '\n');
|
||||||
*next = '\0';
|
*next = '\0';
|
||||||
int rv = sscanf(buf, "%*d %s", typelabel);
|
auto values = Tokenizer(buf).as_vector();
|
||||||
if (rv != 1) error->all(FLERR, "Invalid data file section: Type Labels");
|
int nwords = values.size();
|
||||||
if (isdigit(typelabel[0])) error->all(FLERR, "Type labels cannot start with a number");
|
for (std::size_t ii = 0; ii < values.size(); ++ii) {
|
||||||
(*labels)[i] = typelabel;
|
if (utils::strmatch(values[ii],"^#")) {
|
||||||
(*labels_map)[typelabel] = i + 1;
|
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;
|
buf = next + 1;
|
||||||
}
|
}
|
||||||
delete[] original;
|
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
|
// merge this read_data label map to atom class
|
||||||
// determine mapping to let labels override numeric types
|
// determine mapping to let labels override numeric types
|
||||||
|
|||||||
@ -49,42 +49,6 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override { LAMMPSTest::TearDown(); }
|
void TearDown() override { LAMMPSTest::TearDown(); }
|
||||||
|
|
||||||
void atomic_system(const std::string &atom_style, const std::string units = "real")
|
|
||||||
{
|
|
||||||
BEGIN_HIDE_OUTPUT();
|
|
||||||
command("atom_style " + atom_style);
|
|
||||||
command("atom_modify map array");
|
|
||||||
command("units " + units);
|
|
||||||
command("lattice sc 1.0 origin 0.125 0.125 0.125");
|
|
||||||
command("region box block 0 2 0 2 0 2");
|
|
||||||
command("create_box 8 box");
|
|
||||||
command("create_atoms 1 box");
|
|
||||||
command("mass * 1.0");
|
|
||||||
command("region left block 0.0 1.0 INF INF INF INF");
|
|
||||||
command("region right block 1.0 2.0 INF INF INF INF");
|
|
||||||
command("region top block INF INF 0.0 1.0 INF INF");
|
|
||||||
command("region bottom block INF INF 1.0 2.0 INF INF");
|
|
||||||
command("region front block INF INF INF INF 0.0 1.0");
|
|
||||||
command("region back block INF INF INF 1.0 2.0 INF");
|
|
||||||
command("group top region top");
|
|
||||||
command("group bottom region bottom");
|
|
||||||
END_HIDE_OUTPUT();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool molecular_system()
|
|
||||||
{
|
|
||||||
if (info->has_style("atom", "full")) {
|
|
||||||
BEGIN_HIDE_OUTPUT();
|
|
||||||
command("variable input_dir index \"" STRINGIFY(TEST_INPUT_FOLDER) "\"");
|
|
||||||
command("include \"${input_dir}/in.fourmol\"");
|
|
||||||
command("group allwater molecule 3:6");
|
|
||||||
command("region half block 0.0 INF INF INF INF INF");
|
|
||||||
END_HIDE_OUTPUT();
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(SetTest, NoBoxAtoms)
|
TEST_F(SetTest, NoBoxAtoms)
|
||||||
|
|||||||
@ -316,7 +316,7 @@ TEST_F(SetTest, SpinPackage)
|
|||||||
constexpr double vx = 0.1;
|
constexpr double vx = 0.1;
|
||||||
constexpr double vy = 0.5;
|
constexpr double vy = 0.5;
|
||||||
constexpr double vz = -0.1;
|
constexpr double vz = -0.1;
|
||||||
constexpr double norm = 1.0 / sqrt(vx * vx + vy * vy + vz * vz);
|
const double norm = 1.0 / sqrt(vx * vx + vy * vy + vz * vz);
|
||||||
ASSERT_EQ(atom->sp[0][0], vx * norm);
|
ASSERT_EQ(atom->sp[0][0], vx * norm);
|
||||||
ASSERT_EQ(atom->sp[0][1], vy * norm);
|
ASSERT_EQ(atom->sp[0][1], vy * norm);
|
||||||
ASSERT_EQ(atom->sp[0][2], vz * norm);
|
ASSERT_EQ(atom->sp[0][2], vz * norm);
|
||||||
|
|||||||
Reference in New Issue
Block a user