diff --git a/doc/src/read_data.rst b/doc/src/read_data.rst index 847b44057d..16c98794a1 100755 --- a/doc/src/read_data.rst +++ b/doc/src/read_data.rst @@ -623,20 +623,23 @@ integers (1, not 1.0). Type labels can be used to make data files more general, by defining atom, bond, etc. types in terms of user-provided strings instead of -numbers. If a type label section exists for a given interaction, the -numeric types listed in the *Atoms*, *Bonds*, etc. section are first -converted into their corresponding type label before being read into -LAMMPS; type labels cannot be directly substituted for numeric types -used in data files. Data files can also be used to populate the -default label map; if the type label does not already exist, the type -label is created as a new type and assigned to the default label map. -The corresponding interaction coefficients listed in the data file are -associated to this type. When reading multiple data files, or if the -default label map already exists, there must be enough space in the -per-type data arrays to create new types; see the *extra/atom/types* -keyword for how to reserve extra space for new types. Note that, in -this case, the numeric-to-label mapping within a data file does not -necessary correspond to that of the simulation; the :doc:`write_data ` +numbers. If a type label section exists for any one interaction +(atom, bond, angle, dihedral or improper), then all types must be +assigned a type label for all interactions. All type label sections +must come before any section that includes types. The numeric types +listed in the *Atoms*, *Bonds*, etc. section are first converted into +their corresponding type label before being read into LAMMPS; type +labels cannot be directly substituted for numeric types used in data +files. Data files assign all types to the default label map; if the +type label does not already exist, the type label is created as a new +type and assigned to the default label map. The corresponding +interaction coefficients listed in the data file are associated to +this type. There must be enough space in the per-type data +arrays to create new types; see the *extra/atom/types* keyword for how +to reserve extra space for new types, e.g., when reading multiple data +files. Note that, in this case, the numeric-to-label mapping within a +data file does not necessary correspond to that of the simulation; +once the default label map is fully defined, the :doc:`write_data ` command can be used to print out the default label map at a given point in a simulation. See the :doc:`labelmap ` command for more discussion on how to use type label maps. diff --git a/doc/src/write_data.rst b/doc/src/write_data.rst index 3e52322111..e6edd1d36a 100755 --- a/doc/src/write_data.rst +++ b/doc/src/write_data.rst @@ -108,7 +108,9 @@ from :doc:`fix property/atom `. The *nolabelmap* keyword requests that the default label map should not be written to the data file (see the Type Label sections of -:doc:`read_data ` command for details). +:doc:`read_data ` command for details). By default, if the +default label map is fully defined, i.e. every atom, bond, etc. type +has an associated type label, it is written to the data file. The *pair* keyword lets you specify in what format the pair coefficient information is written into the data file. If the value diff --git a/src/label_map.cpp b/src/label_map.cpp index 0096105e7b..b7a8479737 100755 --- a/src/label_map.cpp +++ b/src/label_map.cpp @@ -237,12 +237,46 @@ int LabelMap::search(std::string mylabel, std::vector labels, int n return -1; } +/* ---------------------------------------------------------------------- + check if all types have been assigned a type label +------------------------------------------------------------------------- */ + +int LabelMap::is_complete() +{ + for (int i = 0; i < natomtypes; i++) + if (typelabel[i].empty()) return 0; + + if (force->bond) + for (int i = 0; i < nbondtypes; i++) + if (btypelabel[i].empty()) return 0; + + if (force->angle) + for (int i = 0; i < nangletypes; i++) + if (atypelabel[i].empty()) return 0; + + if (force->dihedral) + for (int i = 0; i < ndihedraltypes; i++) + if (dtypelabel[i].empty()) return 0; + + if (force->improper) + for (int i = 0; i < nimpropertypes; i++) + if (itypelabel[i].empty()) return 0; + + return 1; +} + /* ---------------------------------------------------------------------- proc 0 writes to data file ------------------------------------------------------------------------- */ void LabelMap::write_data(FILE *fp) { + if (!is_complete()) { + error->warning(FLERR,"Default label map is incomplete. " + "Assign all type labels to write to data file."); + return; + } + fmt::print(fp,"\nAtom Type Labels\n\n"); for (int i = 0; i < natomtypes; i++) fmt::print(fp,"{} {}\n",i+1,typelabel[i]); diff --git a/src/label_map.h b/src/label_map.h index 402fd210f5..5553402e9b 100755 --- a/src/label_map.h +++ b/src/label_map.h @@ -48,6 +48,7 @@ class LabelMap : protected Pointers { int find_or_create(std::string, std::vector &, int); // look up type or create new type int find(std::string, int); // find numeric type of type label int search(std::string, std::vector, int); // look up type index + int is_complete(); // check if all types are assigned // input/output for atom class label map diff --git a/src/read_data.cpp b/src/read_data.cpp index 06f7dfa1fd..f444012403 100755 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -1279,6 +1279,9 @@ void ReadData::atoms() nchunk = MIN(natoms-nread,CHUNK); eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); if (eof) error->all(FLERR,"Unexpected end of data file"); + if (labelflag && !lmap->is_complete()) + error->all(FLERR,"Label map is incomplete. " + "All types must be assigned a type label."); atom->data_atoms(nchunk,buffer,id_offset,mol_offset,toffset, shiftflag,shift,labelflag,lmap->lmap2lmap.atom); nread += nchunk; @@ -1378,6 +1381,9 @@ void ReadData::bonds(int firstpass) nchunk = MIN(nbonds-nread,CHUNK); eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); if (eof) error->all(FLERR,"Unexpected end of data file"); + if (labelflag && !lmap->is_complete()) + error->all(FLERR,"Label map is incomplete. " + "All types must be assigned a type label."); atom->data_bonds(nchunk,buffer,count,id_offset,boffset, labelflag,lmap->lmap2lmap.bond); nread += nchunk; @@ -1453,6 +1459,9 @@ void ReadData::angles(int firstpass) nchunk = MIN(nangles-nread,CHUNK); eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); if (eof) error->all(FLERR,"Unexpected end of data file"); + if (labelflag && !lmap->is_complete()) + error->all(FLERR,"Label map is incomplete. " + "All types must be assigned a type label."); atom->data_angles(nchunk,buffer,count,id_offset,aoffset, labelflag,lmap->lmap2lmap.angle); nread += nchunk; @@ -1528,6 +1537,9 @@ void ReadData::dihedrals(int firstpass) nchunk = MIN(ndihedrals-nread,CHUNK); eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); if (eof) error->all(FLERR,"Unexpected end of data file"); + if (labelflag && !lmap->is_complete()) + error->all(FLERR,"Label map is incomplete. " + "All types must be assigned a type label."); atom->data_dihedrals(nchunk,buffer,count,id_offset,doffset, labelflag,lmap->lmap2lmap.dihedral); nread += nchunk; @@ -1603,6 +1615,9 @@ void ReadData::impropers(int firstpass) nchunk = MIN(nimpropers-nread,CHUNK); eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer); if (eof) error->all(FLERR,"Unexpected end of data file"); + if (labelflag && !lmap->is_complete()) + error->all(FLERR,"Label map is incomplete. " + "All types must be assigned a type label."); atom->data_impropers(nchunk,buffer,count,id_offset,ioffset, labelflag,lmap->lmap2lmap.improper); nread += nchunk; @@ -1798,6 +1813,9 @@ void ReadData::mass() int eof = comm->read_lines_from_file(fp,ntypes,MAXLINE,buf); if (eof) error->all(FLERR,"Unexpected end of data file"); + if (labelflag && !lmap->is_complete()) + error->all(FLERR,"Label map is incomplete. " + "All types must be assigned a type label."); char *original = buf; for (int i = 0; i < ntypes; i++) { @@ -1983,7 +2001,8 @@ void ReadData::typelabels(std::vector &mytypelabel, int myntypes, i for (int i = 0; i < myntypes; i++) { next = strchr(buf,'\n'); *next = '\0'; - sscanf(buf,"%*d %s",typelabel); + 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"); mytypelabel[i] = typelabel; buf = next + 1; @@ -2164,6 +2183,10 @@ void ReadData::skip_lines(bigint n) void ReadData::parse_coeffs(char *line, const char *addstr, int dupflag, int noffset, int offset, int *ilabel) { + if (labelflag && !lmap->is_complete()) + error->all(FLERR,"Label map is incomplete. " + "All types must be assigned a type label."); + settypeflag = 1; char *ptr; if ((ptr = strchr(line,'#'))) *ptr = '\0';