diff --git a/doc/src/Developer_utils.rst b/doc/src/Developer_utils.rst index db47a9e3c3..a9969b7543 100644 --- a/doc/src/Developer_utils.rst +++ b/doc/src/Developer_utils.rst @@ -56,11 +56,11 @@ String to number conversions with validity check These functions should be used to convert strings to numbers. They are are strongly preferred over C library calls like ``atoi()`` or -``atof()`` since they check if the **entire** provided string is a valid +``atof()`` since they check if the **entire** string is a valid (floating-point or integer) number, and will error out instead of silently returning the result of a partial conversion or zero in cases -where the string is not a valid number. This behavior allows to more -easily detect typos or issues when processing input files. +where the string is not a valid number. This behavior improves +detecting typos or issues when processing input files. Similarly the :cpp:func:`logical() ` function will convert a string into a boolean and will only accept certain words. @@ -76,19 +76,34 @@ strings for compliance without conversion. ---------- -.. doxygenfunction:: numeric +.. doxygenfunction:: numeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp) :project: progguide -.. doxygenfunction:: inumeric +.. doxygenfunction:: numeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) :project: progguide -.. doxygenfunction:: bnumeric +.. doxygenfunction:: inumeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp) :project: progguide -.. doxygenfunction:: tnumeric +.. doxygenfunction:: inumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) :project: progguide -.. doxygenfunction:: logical +.. doxygenfunction:: bnumeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp) + :project: progguide + +.. doxygenfunction:: bnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) + :project: progguide + +.. doxygenfunction:: tnumeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp) + :project: progguide + +.. doxygenfunction:: tnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) + :project: progguide + +.. doxygenfunction:: logical(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp) + :project: progguide + +.. doxygenfunction:: logical(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) :project: progguide diff --git a/doc/src/Developer_write.rst b/doc/src/Developer_write.rst index c3df6ad6bb..bdc6559060 100644 --- a/doc/src/Developer_write.rst +++ b/doc/src/Developer_write.rst @@ -55,7 +55,7 @@ of each timestep. First of all, implement a constructor: if (narg < 4) error->all(FLERR,"Illegal fix print/vel command"); - nevery = force->inumeric(FLERR,arg[3]); + nevery = utils::inumeric(FLERR,arg[3],false,lmp); if (nevery <= 0) error->all(FLERR,"Illegal fix print/vel command"); } diff --git a/src/KOKKOS/atom_vec_angle_kokkos.cpp b/src/KOKKOS/atom_vec_angle_kokkos.cpp index c713427aa7..18de4d46cb 100644 --- a/src/KOKKOS/atom_vec_angle_kokkos.cpp +++ b/src/KOKKOS/atom_vec_angle_kokkos.cpp @@ -1630,7 +1630,7 @@ void AtomVecAngleKokkos::create_atom(int itype, double *coord) ------------------------------------------------------------------------- */ void AtomVecAngleKokkos::data_atom(double *coord, imageint imagetmp, - char **values) + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); @@ -1663,9 +1663,10 @@ void AtomVecAngleKokkos::data_atom(double *coord, imageint imagetmp, initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecAngleKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecAngleKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - h_molecule(nlocal) = utils::inumeric(FLERR,values[0],true,lmp); + h_molecule(nlocal) = utils::inumeric(FLERR,values[offset],true,lmp); h_num_bond(nlocal) = 0; h_num_angle(nlocal) = 0; return 1; diff --git a/src/KOKKOS/atom_vec_angle_kokkos.h b/src/KOKKOS/atom_vec_angle_kokkos.h index 9de0c043eb..9bc7753889 100644 --- a/src/KOKKOS/atom_vec_angle_kokkos.h +++ b/src/KOKKOS/atom_vec_angle_kokkos.h @@ -51,8 +51,8 @@ class AtomVecAngleKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, tagint, char **); - int data_atom_hybrid(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_atomic_kokkos.cpp b/src/KOKKOS/atom_vec_atomic_kokkos.cpp index eec2486763..891ebb51c2 100644 --- a/src/KOKKOS/atom_vec_atomic_kokkos.cpp +++ b/src/KOKKOS/atom_vec_atomic_kokkos.cpp @@ -821,8 +821,8 @@ void AtomVecAtomicKokkos::create_atom(int itype, double *coord) initialize other atom quantities ------------------------------------------------------------------------- */ -void AtomVecAtomicKokkos::data_atom(double *coord, tagint imagetmp, - char **values) +void AtomVecAtomicKokkos::data_atom(double *coord, imageint imagetmp, + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); diff --git a/src/KOKKOS/atom_vec_atomic_kokkos.h b/src/KOKKOS/atom_vec_atomic_kokkos.h index 231c95cd3b..1197bc04e7 100644 --- a/src/KOKKOS/atom_vec_atomic_kokkos.h +++ b/src/KOKKOS/atom_vec_atomic_kokkos.h @@ -44,7 +44,7 @@ class AtomVecAtomicKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, tagint, char **); + void data_atom(double *, imageint, const std::vector &); void pack_data(double **); void write_data(FILE *, int, double **); double memory_usage(); diff --git a/src/KOKKOS/atom_vec_bond_kokkos.cpp b/src/KOKKOS/atom_vec_bond_kokkos.cpp index 7582a01730..3655d894c9 100644 --- a/src/KOKKOS/atom_vec_bond_kokkos.cpp +++ b/src/KOKKOS/atom_vec_bond_kokkos.cpp @@ -1056,7 +1056,7 @@ void AtomVecBondKokkos::create_atom(int itype, double *coord) ------------------------------------------------------------------------- */ void AtomVecBondKokkos::data_atom(double *coord, imageint imagetmp, - char **values) + const std::vector &values) { int nlocal = atomKK->nlocal; if (nlocal == nmax) grow(0); @@ -1088,9 +1088,10 @@ void AtomVecBondKokkos::data_atom(double *coord, imageint imagetmp, initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecBondKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecBondKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - h_molecule(nlocal) = utils::inumeric(FLERR,values[0],true,lmp); + h_molecule(nlocal) = utils::inumeric(FLERR,values[offset],true,lmp); h_num_bond(nlocal) = 0; return 1; } diff --git a/src/KOKKOS/atom_vec_bond_kokkos.h b/src/KOKKOS/atom_vec_bond_kokkos.h index 350aeef2d7..a9bc5a1092 100644 --- a/src/KOKKOS/atom_vec_bond_kokkos.h +++ b/src/KOKKOS/atom_vec_bond_kokkos.h @@ -45,8 +45,8 @@ class AtomVecBondKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, tagint, char **); - int data_atom_hybrid(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_charge_kokkos.cpp b/src/KOKKOS/atom_vec_charge_kokkos.cpp index 3bb0985afe..7de36ffd5d 100644 --- a/src/KOKKOS/atom_vec_charge_kokkos.cpp +++ b/src/KOKKOS/atom_vec_charge_kokkos.cpp @@ -955,7 +955,7 @@ void AtomVecChargeKokkos::create_atom(int itype, double *coord) ------------------------------------------------------------------------- */ void AtomVecChargeKokkos::data_atom(double *coord, imageint imagetmp, - char **values) + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); @@ -987,9 +987,10 @@ void AtomVecChargeKokkos::data_atom(double *coord, imageint imagetmp, initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecChargeKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecChargeKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - h_q[nlocal] = utils::numeric(FLERR,values[0],true,lmp); + h_q[nlocal] = utils::numeric(FLERR,values[offset],true,lmp); return 1; } diff --git a/src/KOKKOS/atom_vec_charge_kokkos.h b/src/KOKKOS/atom_vec_charge_kokkos.h index 2e1ba97e8d..866b836350 100644 --- a/src/KOKKOS/atom_vec_charge_kokkos.h +++ b/src/KOKKOS/atom_vec_charge_kokkos.h @@ -46,8 +46,8 @@ class AtomVecChargeKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, tagint, char **); - int data_atom_hybrid(int , char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int , const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_dpd_kokkos.cpp b/src/KOKKOS/atom_vec_dpd_kokkos.cpp index e02631f89e..cf7ad9d533 100644 --- a/src/KOKKOS/atom_vec_dpd_kokkos.cpp +++ b/src/KOKKOS/atom_vec_dpd_kokkos.cpp @@ -1716,8 +1716,8 @@ void AtomVecDPDKokkos::create_atom(int itype, double *coord) initialize other atom quantities ------------------------------------------------------------------------- */ -void AtomVecDPDKokkos::data_atom(double *coord, tagint imagetmp, - char **values) +void AtomVecDPDKokkos::data_atom(double *coord, imageint imagetmp, + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); @@ -1759,9 +1759,10 @@ void AtomVecDPDKokkos::data_atom(double *coord, tagint imagetmp, initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecDPDKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecDPDKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - h_dpdTheta(nlocal) = utils::numeric(FLERR,values[0],true,lmp); + h_dpdTheta(nlocal) = utils::numeric(FLERR,values[offset],true,lmp); atomKK->modified(Host,DPDTHETA_MASK); diff --git a/src/KOKKOS/atom_vec_dpd_kokkos.h b/src/KOKKOS/atom_vec_dpd_kokkos.h index c7d523cb34..2168fa630c 100644 --- a/src/KOKKOS/atom_vec_dpd_kokkos.h +++ b/src/KOKKOS/atom_vec_dpd_kokkos.h @@ -54,8 +54,8 @@ class AtomVecDPDKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, tagint, char **); - int data_atom_hybrid(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_full_kokkos.cpp b/src/KOKKOS/atom_vec_full_kokkos.cpp index cd5316cc73..b75c33e046 100644 --- a/src/KOKKOS/atom_vec_full_kokkos.cpp +++ b/src/KOKKOS/atom_vec_full_kokkos.cpp @@ -1488,7 +1488,7 @@ void AtomVecFullKokkos::create_atom(int itype, double *coord) ------------------------------------------------------------------------- */ void AtomVecFullKokkos::data_atom(double *coord, imageint imagetmp, - char **values) + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); @@ -1525,10 +1525,11 @@ void AtomVecFullKokkos::data_atom(double *coord, imageint imagetmp, initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecFullKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecFullKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - h_molecule(nlocal) = utils::inumeric(FLERR,values[0],true,lmp); - h_q(nlocal) = utils::numeric(FLERR,values[1],true,lmp); + h_molecule(nlocal) = utils::inumeric(FLERR,values[offset],true,lmp); + h_q(nlocal) = utils::numeric(FLERR,values[offset+1],true,lmp); h_num_bond(nlocal) = 0; h_num_angle(nlocal) = 0; h_num_dihedral(nlocal) = 0; diff --git a/src/KOKKOS/atom_vec_full_kokkos.h b/src/KOKKOS/atom_vec_full_kokkos.h index c751eb840d..b5ce032c4f 100644 --- a/src/KOKKOS/atom_vec_full_kokkos.h +++ b/src/KOKKOS/atom_vec_full_kokkos.h @@ -45,8 +45,8 @@ class AtomVecFullKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, tagint, char **); - int data_atom_hybrid(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_hybrid_kokkos.cpp b/src/KOKKOS/atom_vec_hybrid_kokkos.cpp index 6b9f6852ad..22ce80478c 100644 --- a/src/KOKKOS/atom_vec_hybrid_kokkos.cpp +++ b/src/KOKKOS/atom_vec_hybrid_kokkos.cpp @@ -970,7 +970,8 @@ void AtomVecHybridKokkos::create_atom(int itype, double *coord) grow() occurs here so arrays for all sub-styles are grown ------------------------------------------------------------------------- */ -void AtomVecHybridKokkos::data_atom(double *coord, imageint imagetmp, char **values) +void AtomVecHybridKokkos::data_atom(double *coord, imageint imagetmp, + const std::vector &values) { atomKK->sync(Host,X_MASK|TAG_MASK|TYPE_MASK|IMAGE_MASK|MASK_MASK|V_MASK|OMEGA_MASK/*|ANGMOM_MASK*/); @@ -1009,7 +1010,7 @@ void AtomVecHybridKokkos::data_atom(double *coord, imageint imagetmp, char **val int m = 5; for (int k = 0; k < nstyles; k++) - m += styles[k]->data_atom_hybrid(nlocal,&values[m]); + m += styles[k]->data_atom_hybrid(nlocal,values,m); atom->nlocal++; } @@ -1018,21 +1019,21 @@ void AtomVecHybridKokkos::data_atom(double *coord, imageint imagetmp, char **val unpack one line from Velocities section of data file ------------------------------------------------------------------------- */ -void AtomVecHybridKokkos::data_vel(int m, char **values) +void AtomVecHybridKokkos::data_vel(int m, const std::vector &values) { atomKK->sync(Host,V_MASK); - h_v(m,0) = utils::numeric(FLERR,values[0],true,lmp); - h_v(m,1) = utils::numeric(FLERR,values[1],true,lmp); - h_v(m,2) = utils::numeric(FLERR,values[2],true,lmp); + int ivalue = 1; + h_v(m,0) = utils::numeric(FLERR,values[ivalue++],true,lmp); + h_v(m,1) = utils::numeric(FLERR,values[ivalue++],true,lmp); + h_v(m,2) = utils::numeric(FLERR,values[ivalue++],true,lmp); atomKK->modified(Host,V_MASK); // each sub-style parses sub-style specific values - int n = 3; for (int k = 0; k < nstyles; k++) - n += styles[k]->data_vel_hybrid(m,&values[n]); + ivalue += styles[k]->data_vel_hybrid(m,values,ivalue); } /* ---------------------------------------------------------------------- diff --git a/src/KOKKOS/atom_vec_hybrid_kokkos.h b/src/KOKKOS/atom_vec_hybrid_kokkos.h index 4c1907ddc6..567b98695f 100644 --- a/src/KOKKOS/atom_vec_hybrid_kokkos.h +++ b/src/KOKKOS/atom_vec_hybrid_kokkos.h @@ -57,9 +57,9 @@ class AtomVecHybridKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, imageint, char **); - int data_atom_hybrid(int, char **) {return 0;} - void data_vel(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int) {return 0;} + void data_vel(int, const std::vector &); void pack_data(double **); void write_data(FILE *, int, double **); void pack_vel(double **); diff --git a/src/KOKKOS/atom_vec_kokkos.cpp b/src/KOKKOS/atom_vec_kokkos.cpp index 1255712a21..931cd8d8f4 100644 --- a/src/KOKKOS/atom_vec_kokkos.cpp +++ b/src/KOKKOS/atom_vec_kokkos.cpp @@ -1016,12 +1016,13 @@ void AtomVecKokkos::unpack_reverse(int n, int *list, double *buf) * unpack one line from Velocities section of data file * ------------------------------------------------------------------------- */ -void AtomVecKokkos::data_vel(int m, char **values) +void AtomVecKokkos::data_vel(int m, const std::vector &values) { double **v = atom->v; - v[m][0] = utils::numeric(FLERR,values[0],true,lmp); - v[m][1] = utils::numeric(FLERR,values[1],true,lmp); - v[m][2] = utils::numeric(FLERR,values[2],true,lmp); + int ivalue = 1; + v[m][0] = utils::numeric(FLERR,values[ivalue++],true,lmp); + v[m][1] = utils::numeric(FLERR,values[ivalue++],true,lmp); + v[m][2] = utils::numeric(FLERR,values[ivalue++],true,lmp); atomKK->modified(Host,V_MASK); } diff --git a/src/KOKKOS/atom_vec_kokkos.h b/src/KOKKOS/atom_vec_kokkos.h index c596d80e94..20dd41dd75 100644 --- a/src/KOKKOS/atom_vec_kokkos.h +++ b/src/KOKKOS/atom_vec_kokkos.h @@ -44,7 +44,7 @@ class AtomVecKokkos : public AtomVec { virtual void unpack_comm_vel(int, int, double *); virtual int pack_reverse(int, int, double *); virtual void unpack_reverse(int, int *, double *); - virtual void data_vel(int, char **); + virtual void data_vel(int, const std::vector &); virtual void pack_vel(double **); virtual void write_vel(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_molecular_kokkos.cpp b/src/KOKKOS/atom_vec_molecular_kokkos.cpp index 016e3f80e3..c4e75c1da7 100644 --- a/src/KOKKOS/atom_vec_molecular_kokkos.cpp +++ b/src/KOKKOS/atom_vec_molecular_kokkos.cpp @@ -1889,7 +1889,7 @@ void AtomVecMolecularKokkos::create_atom(int itype, double *coord) ------------------------------------------------------------------------- */ void AtomVecMolecularKokkos::data_atom(double *coord, imageint imagetmp, - char **values) + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); @@ -1924,9 +1924,10 @@ void AtomVecMolecularKokkos::data_atom(double *coord, imageint imagetmp, initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecMolecularKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecMolecularKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - h_molecule(nlocal) = utils::inumeric(FLERR,values[0],true,lmp); + h_molecule(nlocal) = utils::inumeric(FLERR,values[offset],true,lmp); h_num_bond(nlocal) = 0; h_num_angle(nlocal) = 0; h_num_dihedral(nlocal) = 0; diff --git a/src/KOKKOS/atom_vec_molecular_kokkos.h b/src/KOKKOS/atom_vec_molecular_kokkos.h index fab833469c..abd04f905b 100644 --- a/src/KOKKOS/atom_vec_molecular_kokkos.h +++ b/src/KOKKOS/atom_vec_molecular_kokkos.h @@ -51,8 +51,8 @@ class AtomVecMolecularKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, tagint, char **); - int data_atom_hybrid(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_sphere_kokkos.cpp b/src/KOKKOS/atom_vec_sphere_kokkos.cpp index 6b29af824a..0b722e8563 100644 --- a/src/KOKKOS/atom_vec_sphere_kokkos.cpp +++ b/src/KOKKOS/atom_vec_sphere_kokkos.cpp @@ -2543,7 +2543,8 @@ void AtomVecSphereKokkos::create_atom(int itype, double *coord) initialize other atom quantities ------------------------------------------------------------------------- */ -void AtomVecSphereKokkos::data_atom(double *coord, imageint imagetmp, char **values) +void AtomVecSphereKokkos::data_atom(double *coord, imageint imagetmp, + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); @@ -2590,13 +2591,14 @@ void AtomVecSphereKokkos::data_atom(double *coord, imageint imagetmp, char **val initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecSphereKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecSphereKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - radius[nlocal] = 0.5 * utils::numeric(FLERR,values[0],true,lmp); + radius[nlocal] = 0.5 * utils::numeric(FLERR,values[offset],true,lmp); if (radius[nlocal] < 0.0) error->one(FLERR,"Invalid radius in Atoms section of data file"); - double density = utils::numeric(FLERR,values[1],true,lmp); + double density = utils::numeric(FLERR,values[offset+1],true,lmp); if (density <= 0.0) error->one(FLERR,"Invalid density in Atoms section of data file"); @@ -2615,15 +2617,16 @@ int AtomVecSphereKokkos::data_atom_hybrid(int nlocal, char **values) unpack one line from Velocities section of data file ------------------------------------------------------------------------- */ -void AtomVecSphereKokkos::data_vel(int m, char **values) +void AtomVecSphereKokkos::data_vel(int m, const std::vector &values) { + int ivalue = 1; atomKK->sync(Host,V_MASK|OMEGA_MASK); - h_v(m,0) = utils::numeric(FLERR,values[0],true,lmp); - h_v(m,1) = utils::numeric(FLERR,values[1],true,lmp); - h_v(m,2) = utils::numeric(FLERR,values[2],true,lmp); - h_omega(m,0) = utils::numeric(FLERR,values[3],true,lmp); - h_omega(m,1) = utils::numeric(FLERR,values[4],true,lmp); - h_omega(m,2) = utils::numeric(FLERR,values[5],true,lmp); + h_v(m,0) = utils::numeric(FLERR,values[ivalue++],true,lmp); + h_v(m,1) = utils::numeric(FLERR,values[ivalue++],true,lmp); + h_v(m,2) = utils::numeric(FLERR,values[ivalue++],true,lmp); + h_omega(m,0) = utils::numeric(FLERR,values[ivalue++],true,lmp); + h_omega(m,1) = utils::numeric(FLERR,values[ivalue++],true,lmp); + h_omega(m,2) = utils::numeric(FLERR,values[ivalue++],true,lmp); atomKK->modified(Host,V_MASK|OMEGA_MASK); } @@ -2631,12 +2634,13 @@ void AtomVecSphereKokkos::data_vel(int m, char **values) unpack hybrid quantities from one line in Velocities section of data file ------------------------------------------------------------------------- */ -int AtomVecSphereKokkos::data_vel_hybrid(int m, char **values) +int AtomVecSphereKokkos::data_vel_hybrid(int m, const std::vector &values, + int offset) { atomKK->sync(Host,OMEGA_MASK); - omega[m][0] = utils::numeric(FLERR,values[0],true,lmp); - omega[m][1] = utils::numeric(FLERR,values[1],true,lmp); - omega[m][2] = utils::numeric(FLERR,values[2],true,lmp); + omega[m][0] = utils::numeric(FLERR,values[offset],true,lmp); + omega[m][1] = utils::numeric(FLERR,values[offset+1],true,lmp); + omega[m][2] = utils::numeric(FLERR,values[offset+2],true,lmp); atomKK->modified(Host,OMEGA_MASK); return 3; } diff --git a/src/KOKKOS/atom_vec_sphere_kokkos.h b/src/KOKKOS/atom_vec_sphere_kokkos.h index 72eb7a665e..a9ba4baa24 100644 --- a/src/KOKKOS/atom_vec_sphere_kokkos.h +++ b/src/KOKKOS/atom_vec_sphere_kokkos.h @@ -58,10 +58,10 @@ class AtomVecSphereKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, imageint, char **); - int data_atom_hybrid(int, char **); - void data_vel(int, char **); - int data_vel_hybrid(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int); + void data_vel(int, const std::vector &); + int data_vel_hybrid(int, const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/KOKKOS/atom_vec_spin_kokkos.cpp b/src/KOKKOS/atom_vec_spin_kokkos.cpp index c8f0663806..039c08f31c 100644 --- a/src/KOKKOS/atom_vec_spin_kokkos.cpp +++ b/src/KOKKOS/atom_vec_spin_kokkos.cpp @@ -1056,7 +1056,7 @@ void AtomVecSpinKokkos::create_atom(int itype, double *coord) ------------------------------------------------------------------------- */ void AtomVecSpinKokkos::data_atom(double *coord, imageint imagetmp, - char **values) + const std::vector &values) { int nlocal = atom->nlocal; if (nlocal == nmax) grow(0); @@ -1098,12 +1098,13 @@ void AtomVecSpinKokkos::data_atom(double *coord, imageint imagetmp, initialize other atom quantities for this sub-style ------------------------------------------------------------------------- */ -int AtomVecSpinKokkos::data_atom_hybrid(int nlocal, char **values) +int AtomVecSpinKokkos::data_atom_hybrid(int nlocal, const std::vector &values, + int offset) { - h_sp(nlocal,3) = utils::numeric(FLERR,values[0],true,lmp); - h_sp(nlocal,0) = utils::numeric(FLERR,values[1],true,lmp); - h_sp(nlocal,1) = utils::numeric(FLERR,values[2],true,lmp); - h_sp(nlocal,2) = utils::numeric(FLERR,values[3],true,lmp); + h_sp(nlocal,3) = utils::numeric(FLERR,values[offset],true,lmp); + h_sp(nlocal,0) = utils::numeric(FLERR,values[offset+1],true,lmp); + h_sp(nlocal,1) = utils::numeric(FLERR,values[offset+2],true,lmp); + h_sp(nlocal,2) = utils::numeric(FLERR,values[offset+3],true,lmp); double inorm = 1.0/sqrt(sp[nlocal][0]*sp[nlocal][0] + sp[nlocal][1]*sp[nlocal][1] + sp[nlocal][2]*sp[nlocal][2]); diff --git a/src/KOKKOS/atom_vec_spin_kokkos.h b/src/KOKKOS/atom_vec_spin_kokkos.h index 6438da9eaa..38d206c007 100644 --- a/src/KOKKOS/atom_vec_spin_kokkos.h +++ b/src/KOKKOS/atom_vec_spin_kokkos.h @@ -45,8 +45,8 @@ class AtomVecSpinKokkos : public AtomVecKokkos { int pack_restart(int, double *); int unpack_restart(double *); void create_atom(int, double *); - void data_atom(double *, imageint, char **); - int data_atom_hybrid(int, char **); + void data_atom(double *, imageint, const std::vector &); + int data_atom_hybrid(int, const std::vector &, int); void pack_data(double **); int pack_data_hybrid(int, double *); void write_data(FILE *, int, double **); diff --git a/src/ML-IAP/mliap_descriptor_so3.cpp b/src/ML-IAP/mliap_descriptor_so3.cpp index e8bedea377..48748d8565 100644 --- a/src/ML-IAP/mliap_descriptor_so3.cpp +++ b/src/ML-IAP/mliap_descriptor_so3.cpp @@ -125,28 +125,27 @@ void MLIAPDescriptorSO3::read_paramfile(char *paramfilename) // check for keywords with one value per element - if (strcmp(skeywd.c_str(), "elems") == 0 || strcmp(skeywd.c_str(), "radelems") == 0 || - strcmp(skeywd.c_str(), "welems") == 0) { + if ((skeywd == "elems") || (skeywd == "radelems") || (skeywd == "welems")) { if (nelementsflag == 0 || nwords != nelements + 1) error->all(FLERR, "Incorrect SO3 parameter file"); - if (strcmp(skeywd.c_str(), "elems") == 0) { + if (skeywd == "elems") { for (int ielem = 0; ielem < nelements; ielem++) { elements[ielem] = utils::strdup(skeyval); if (ielem < nelements - 1) skeyval = p.next(); } elementsflag = 1; - } else if (strcmp(skeywd.c_str(), "radelems") == 0) { + } else if (skeywd == "radelems") { for (int ielem = 0; ielem < nelements; ielem++) { - radelem[ielem] = utils::numeric(FLERR, skeyval.c_str(), false, lmp); + radelem[ielem] = utils::numeric(FLERR, skeyval, false, lmp); if (ielem < nelements - 1) skeyval = p.next(); } radelemflag = 1; - } else if (strcmp(skeywd.c_str(), "welems") == 0) { + } else if (skeywd == "welems") { for (int ielem = 0; ielem < nelements; ielem++) { - wjelem[ielem] = utils::numeric(FLERR, skeyval.c_str(), false, lmp); + wjelem[ielem] = utils::numeric(FLERR, skeyval, false, lmp); if (ielem < nelements - 1) skeyval = p.next(); } wjelemflag = 1; @@ -158,23 +157,23 @@ void MLIAPDescriptorSO3::read_paramfile(char *paramfilename) if (nwords != 2) error->all(FLERR, "Incorrect SO3 parameter file"); - if (strcmp(skeywd.c_str(), "nelems") == 0) { - nelements = utils::inumeric(FLERR, skeyval.c_str(), false, lmp); + if (skeywd == "nelems") { + nelements = utils::inumeric(FLERR, skeyval, false, lmp); elements = new char *[nelements]; memory->create(radelem, nelements, "mliap_so3_descriptor:radelem"); memory->create(wjelem, nelements, "mliap_so3_descriptor:wjelem"); nelementsflag = 1; - } else if (strcmp(skeywd.c_str(), "rcutfac") == 0) { - rcutfac = utils::numeric(FLERR, skeyval.c_str(), false, lmp); + } else if (skeywd == "rcutfac") { + rcutfac = utils::numeric(FLERR, skeyval, false, lmp); rcutfacflag = 1; - } else if (strcmp(skeywd.c_str(), "nmax") == 0) { - nmax = utils::inumeric(FLERR, skeyval.c_str(), false, lmp); + } else if (skeywd == "nmax") { + nmax = utils::inumeric(FLERR, skeyval, false, lmp); nmaxflag = 1; - } else if (strcmp(skeywd.c_str(), "lmax") == 0) { - lmax = utils::inumeric(FLERR, skeyval.c_str(), false, lmp); + } else if (skeywd == "lmax") { + lmax = utils::inumeric(FLERR, skeyval, false, lmp); lmaxflag = 1; - } else if (strcmp(skeywd.c_str(), "alpha") == 0) { - alpha = utils::numeric(FLERR, skeyval.c_str(), false, lmp); + } else if (skeywd == "alpha") { + alpha = utils::numeric(FLERR, skeyval, false, lmp); alphaflag = 1; } else error->all(FLERR, "Incorrect SO3 parameter file"); diff --git a/src/ML-RANN/pair_rann.cpp b/src/ML-RANN/pair_rann.cpp index 3e97b638dc..97a3478332 100644 --- a/src/ML-RANN/pair_rann.cpp +++ b/src/ML-RANN/pair_rann.cpp @@ -440,7 +440,7 @@ void PairRANN::read_mass(const std::vector &line1, const std::vecto if (nelements == -1)error->one(filename,linenum-1,"atom types must be defined before mass in potential file."); for (int i=0;i line,std::vector l if (nelements == -1)error->one(filename,linenum-1,"atom types must be defined before fingerprints per element in potential file."); for (i=0;i line,std::vectorn_body_type!=nwords-1) {error->one(filename,linenum,"invalid fingerprint for element combination");} k++; - fingerprints[i][i1]->init(atomtypes,utils::inumeric(filename,linenum,line1[k++].c_str(),true,lmp)); + fingerprints[i][i1]->init(atomtypes,utils::inumeric(filename,linenum,line1[k++],true,lmp)); fingerprintcount[i]++; } delete[] atomtypes; @@ -523,7 +523,7 @@ void PairRANN::read_fingerprint_constants(std::vector line,std::vec for (j=0;jatomtypes[j]!=atomtypes[j]) {break;} if (j==n_body_type-1) { - if (line[nwords-3].compare(fingerprints[i][k]->style)==0 && utils::inumeric(filename,linenum,line[nwords-2].c_str(),true,lmp)==fingerprints[i][k]->id) { + if (line[nwords-3].compare(fingerprints[i][k]->style)==0 && utils::inumeric(filename,linenum,line[nwords-2],true,lmp)==fingerprints[i][k]->id) { found=true; i1 = k; break; @@ -542,7 +542,7 @@ void PairRANN::read_network_layers(std::vector line,std::vectorone(filename,linenum-1,"atom types must be defined before network layers in potential file."); for (i=0;ione(filename,linenum,"invalid number of network layers"); delete[] net[i].dimensions; weightdefined[i] = new bool [net[i].layers]; @@ -570,9 +570,9 @@ void PairRANN::read_layer_size(std::vector line,std::vectorone(filename,linenum-1,"networklayers for each atom type must be defined before the corresponding layer sizes."); - int j = utils::inumeric(filename,linenum,line[2].c_str(),true,lmp); + int j = utils::inumeric(filename,linenum,line[2],true,lmp); if (j>=net[i].layers || j<0) {error->one(filename,linenum,"invalid layer in layer size definition");}; - net[i].dimensions[j]= utils::inumeric(filename,linenum,line1[0].c_str(),true,lmp); + net[i].dimensions[j]= utils::inumeric(filename,linenum,line1[0],true,lmp); return; } } @@ -587,7 +587,7 @@ void PairRANN::read_weight(std::vector line,std::vectorone(filename,*linenum-1,"networklayers must be defined before weights."); - i=utils::inumeric(filename,*linenum,line[2].c_str(),true,lmp); + i=utils::inumeric(filename,*linenum,line[2],true,lmp); if (i>=net[l].layers || i<0)error->one(filename,*linenum-1,"invalid weight layer"); if (net[l].dimensions[i]==0 || net[l].dimensions[i+1]==0) error->one(filename,*linenum-1,"network layer sizes must be defined before corresponding weight"); net[l].Weights[i] = new double[net[l].dimensions[i]*net[l].dimensions[i+1]]; @@ -595,7 +595,7 @@ void PairRANN::read_weight(std::vector line,std::vectorone(filename,*linenum,"invalid weights per line"); for (k=0;k line,std::vectorone(filename,*linenum,"invalid weights per line"); for (k=0;k line,std::vector for (l=0;lone(filename,*linenum-1,"networklayers must be defined before biases."); - i=utils::inumeric(filename,*linenum,line[2].c_str(),true,lmp); + i=utils::inumeric(filename,*linenum,line[2],true,lmp); if (i>=net[l].layers || i<0)error->one(filename,*linenum-1,"invalid bias layer"); if (net[l].dimensions[i]==0) error->one(filename,*linenum-1,"network layer sizes must be defined before corresponding bias"); biasdefined[l][i] = true; net[l].Biases[i] = new double[net[l].dimensions[i+1]]; - net[l].Biases[i][0] = utils::numeric(filename,*linenum,line1[0].c_str(),true,lmp); + net[l].Biases[i][0] = utils::numeric(filename,*linenum,line1[0],true,lmp); for (j=1;jone(filename,*linenum,"unexpected end of potential file!"); (*linenum)++; Tokenizer values1 = Tokenizer(linetemp,": ,\t_\n"); line1 = values1.as_vector(); - net[l].Biases[i][j] = utils::numeric(filename,*linenum,line1[0].c_str(),true,lmp); + net[l].Biases[i][j] = utils::numeric(filename,*linenum,line1[0],true,lmp); } return; } @@ -680,10 +680,10 @@ void PairRANN::read_screening(std::vector line,std::vectorone(filename,linenum-1,"unrecognized screening keyword"); delete[] atomtypes; diff --git a/src/ML-SNAP/pair_snap.cpp b/src/ML-SNAP/pair_snap.cpp index 1eb078bc61..eafb27f5ba 100644 --- a/src/ML-SNAP/pair_snap.cpp +++ b/src/ML-SNAP/pair_snap.cpp @@ -570,8 +570,8 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) else elementflags[jelem] = 1; - radelem[jelem] = utils::numeric(FLERR,words[1].c_str(),false,lmp); - wjelem[jelem] = utils::numeric(FLERR,words[2].c_str(),false,lmp); + radelem[jelem] = utils::numeric(FLERR,words[1],false,lmp); + wjelem[jelem] = utils::numeric(FLERR,words[2],false,lmp); if (comm->me == 0) utils::logmesg(lmp,"SNAP Element = {}, Radius {}, Weight {}\n", @@ -672,34 +672,33 @@ void PairSNAP::read_files(char *coefffilename, char *paramfilename) utils::logmesg(lmp,"SNAP keyword {} {}\n",keywd,keyval); if (keywd == "rcutfac") { - rcutfac = utils::numeric(FLERR,keyval.c_str(),false,lmp); + rcutfac = utils::numeric(FLERR,keyval,false,lmp); rcutfacflag = 1; } else if (keywd == "twojmax") { - twojmax = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + twojmax = utils::inumeric(FLERR,keyval,false,lmp); twojmaxflag = 1; } else if (keywd == "rfac0") - rfac0 = utils::numeric(FLERR,keyval.c_str(),false,lmp); + rfac0 = utils::numeric(FLERR,keyval,false,lmp); else if (keywd == "rmin0") - rmin0 = utils::numeric(FLERR,keyval.c_str(),false,lmp); + rmin0 = utils::numeric(FLERR,keyval,false,lmp); else if (keywd == "switchflag") - switchflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + switchflag = utils::inumeric(FLERR,keyval,false,lmp); else if (keywd == "bzeroflag") - bzeroflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + bzeroflag = utils::inumeric(FLERR,keyval,false,lmp); else if (keywd == "quadraticflag") - quadraticflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + quadraticflag = utils::inumeric(FLERR,keyval,false,lmp); else if (keywd == "chemflag") - chemflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + chemflag = utils::inumeric(FLERR,keyval,false,lmp); else if (keywd == "bnormflag") - bnormflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + bnormflag = utils::inumeric(FLERR,keyval,false,lmp); else if (keywd == "wselfallflag") - wselfallflag = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + wselfallflag = utils::inumeric(FLERR,keyval,false,lmp); else if (keywd == "chunksize") - chunksize = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + chunksize = utils::inumeric(FLERR,keyval,false,lmp); else if (keywd == "parallelthresh") - parallel_thresh = utils::inumeric(FLERR,keyval.c_str(),false,lmp); + parallel_thresh = utils::inumeric(FLERR,keyval,false,lmp); else - error->all(FLERR,"Unknown parameter '{}' in SNAP " - "parameter file", keywd); + error->all(FLERR,"Unknown parameter '{}' in SNAP parameter file", keywd); } if (rcutfacflag == 0 || twojmaxflag == 0) diff --git a/src/atom.cpp b/src/atom.cpp index d4a2a431ca..aece451b9b 100644 --- a/src/atom.cpp +++ b/src/atom.cpp @@ -29,6 +29,7 @@ #include "modify.h" #include "molecule.h" #include "neighbor.h" +#include "tokenizer.h" #include "update.h" #include "variable.h" @@ -1057,6 +1058,7 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, double *coord; char *next; + // use the first line to detect and validate the number of words/tokens per line next = strchr(buf,'\n'); *next = '\0'; int nwords = utils::trim_and_count_words(buf); @@ -1065,8 +1067,6 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, if (nwords != avec->size_data_atom && nwords != avec->size_data_atom + 3) error->all(FLERR,"Incorrect atom format in data file"); - char **values = new char*[nwords]; - // set bounds for my proc // if periodic and I am lo/hi proc, adjust bounds by EPSILON // insures all data atoms will be owned even with round-off @@ -1137,15 +1137,10 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); - - for (m = 0; m < nwords; m++) { - buf += strspn(buf," \t\n\r\f"); - buf[strcspn(buf," \t\n\r\f")] = '\0'; - if (strlen(buf) == 0) - error->all(FLERR,"Incorrect atom format in data file"); - values[m] = buf; - buf += strlen(buf)+1; - } + *next = '\0'; + auto values = Tokenizer(utils::trim_comment(buf)).as_vector(); + if (values.size() != nwords) + error->all(FLERR, "Incorrect atom format in data file: {}", utils::trim(buf)); int imx = 0, imy = 0, imz = 0; if (imageflag) { @@ -1192,7 +1187,6 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, buf = next + 1; } - delete [] values; } /* ---------------------------------------------------------------------- @@ -1204,7 +1198,6 @@ void Atom::data_atoms(int n, char *buf, tagint id_offset, tagint mol_offset, void Atom::data_vels(int n, char *buf, tagint id_offset) { int j,m; - tagint tagdata; char *next; next = strchr(buf,'\n'); @@ -1215,31 +1208,24 @@ void Atom::data_vels(int n, char *buf, tagint id_offset) if (nwords != avec->size_data_vel) error->all(FLERR,"Incorrect velocity format in data file"); - char **values = new char*[nwords]; - // loop over lines of atom velocities // tokenize the line into values // if I own atom tag, unpack its values for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); + *next = '\0'; + auto values = Tokenizer(utils::trim_comment(buf)).as_vector(); + if (values.size() != nwords) + error->all(FLERR, "Incorrect atom format in data file: {}", utils::trim(buf)); - for (j = 0; j < nwords; j++) { - buf += strspn(buf," \t\n\r\f"); - buf[strcspn(buf," \t\n\r\f")] = '\0'; - values[j] = buf; - buf += strlen(buf)+1; - } - - tagdata = ATOTAGINT(values[0]) + id_offset; + tagint tagdata = utils::tnumeric(FLERR,values[0],false,lmp) + id_offset; if (tagdata <= 0 || tagdata > map_tag_max) error->one(FLERR,"Invalid atom ID in Velocities section of data file"); - if ((m = map(tagdata)) >= 0) avec->data_vel(m,&values[1]); + if ((m = map(tagdata)) >= 0) avec->data_vel(m,values); buf = next + 1; } - - delete [] values; } /* ---------------------------------------------------------------------- @@ -1252,18 +1238,25 @@ void Atom::data_vels(int n, char *buf, tagint id_offset) void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype,rv; + int m,itype; tagint atom1,atom2; char *next; int newton_bond = force->newton_bond; + auto location = "Bonds section of data file"; for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - rv = sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2); - if (rv != 4) - error->one(FLERR,"Incorrect format of Bonds section in data file"); + try { + ValueTokenizer values(utils::trim_comment(buf)); + values.next_int(); + itype = values.next_int(); + atom1 = values.next_tagint(); + atom2 = values.next_tagint(); + if (values.has_next()) throw TokenizerException("Too many tokens",""); + } catch (TokenizerException &e) { + error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf)); + } if (id_offset) { atom1 += id_offset; atom2 += id_offset; @@ -1272,9 +1265,9 @@ void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset, if ((atom1 <= 0) || (atom1 > map_tag_max) || (atom2 <= 0) || (atom2 > map_tag_max) || (atom1 == atom2)) - error->one(FLERR,"Invalid atom ID in Bonds section of data file"); + error->one(FLERR,"Invalid atom ID in {}: {}", location, utils::trim(buf)); if (itype <= 0 || itype > nbondtypes) - error->one(FLERR,"Invalid bond type in Bonds section of data file"); + error->one(FLERR,"Invalid bond type in {}: {}", location, utils::trim(buf)); if ((m = map(atom1)) >= 0) { if (count) count[m]++; else { @@ -1309,18 +1302,26 @@ void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset, void Atom::data_angles(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype,rv; + int m,itype; tagint atom1,atom2,atom3; char *next; int newton_bond = force->newton_bond; + auto location = "Angles section of data file"; for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - rv = sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2,&atom3); - if (rv != 5) - error->one(FLERR,"Incorrect format of Angles section in data file"); + try { + ValueTokenizer values(utils::trim_comment(buf)); + values.next_int(); + itype = values.next_int(); + atom1 = values.next_tagint(); + atom2 = values.next_tagint(); + atom3 = values.next_tagint(); + if (values.has_next()) throw TokenizerException("Too many tokens",""); + } catch (TokenizerException &e) { + error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf)); + } if (id_offset) { atom1 += id_offset; atom2 += id_offset; @@ -1332,9 +1333,9 @@ void Atom::data_angles(int n, char *buf, int *count, tagint id_offset, (atom2 <= 0) || (atom2 > map_tag_max) || (atom3 <= 0) || (atom3 > map_tag_max) || (atom1 == atom2) || (atom1 == atom3) || (atom2 == atom3)) - error->one(FLERR,"Invalid atom ID in Angles section of data file"); + error->one(FLERR,"Invalid atom ID in {}: {}", location, utils::trim(buf)); if (itype <= 0 || itype > nangletypes) - error->one(FLERR,"Invalid angle type in Angles section of data file"); + error->one(FLERR,"Invalid angle type in {}: {}", location, utils::trim(buf)); if ((m = map(atom2)) >= 0) { if (count) count[m]++; else { @@ -1381,19 +1382,27 @@ void Atom::data_angles(int n, char *buf, int *count, tagint id_offset, void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype,rv; + int m,itype; tagint atom1,atom2,atom3,atom4; char *next; int newton_bond = force->newton_bond; + auto location = "Dihedrals section of data file"; for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - rv = sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT - " " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2,&atom3,&atom4); - if (rv != 6) - error->one(FLERR,"Incorrect format of Dihedrals section in data file"); + try { + ValueTokenizer values(utils::trim_comment(buf)); + values.next_int(); + itype = values.next_int(); + atom1 = values.next_tagint(); + atom2 = values.next_tagint(); + atom3 = values.next_tagint(); + atom4 = values.next_tagint(); + if (values.has_next()) throw TokenizerException("Too many tokens",""); + } catch (TokenizerException &e) { + error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf)); + } if (id_offset) { atom1 += id_offset; atom2 += id_offset; @@ -1408,10 +1417,9 @@ void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset, (atom4 <= 0) || (atom4 > map_tag_max) || (atom1 == atom2) || (atom1 == atom3) || (atom1 == atom4) || (atom2 == atom3) || (atom2 == atom4) || (atom3 == atom4)) - error->one(FLERR,"Invalid atom ID in Dihedrals section of data file"); + error->one(FLERR, "Invalid atom ID in {}: {}", location, utils::trim(buf)); if (itype <= 0 || itype > ndihedraltypes) - error->one(FLERR, - "Invalid dihedral type in Dihedrals section of data file"); + error->one(FLERR, "Invalid dihedral type in {}: {}", location, utils::trim(buf)); if ((m = map(atom2)) >= 0) { if (count) count[m]++; else { @@ -1472,19 +1480,27 @@ void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset, void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset, int type_offset) { - int m,tmp,itype,rv; + int m,itype; tagint atom1,atom2,atom3,atom4; char *next; int newton_bond = force->newton_bond; + auto location = "Impropers section of data file"; for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); *next = '\0'; - rv = sscanf(buf,"%d %d " - TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT, - &tmp,&itype,&atom1,&atom2,&atom3,&atom4); - if (rv != 6) - error->one(FLERR,"Incorrect format of Impropers section in data file"); + try { + ValueTokenizer values(utils::trim_comment(buf)); + values.next_int(); + itype = values.next_int(); + atom1 = values.next_tagint(); + atom2 = values.next_tagint(); + atom3 = values.next_tagint(); + atom4 = values.next_tagint(); + if (values.has_next()) throw TokenizerException("Too many tokens",""); + } catch (TokenizerException &e) { + error->one(FLERR,"{} in {}: {}", e.what(), location, utils::trim(buf)); + } if (id_offset) { atom1 += id_offset; atom2 += id_offset; @@ -1499,10 +1515,9 @@ void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset, (atom4 <= 0) || (atom4 > map_tag_max) || (atom1 == atom2) || (atom1 == atom3) || (atom1 == atom4) || (atom2 == atom3) || (atom2 == atom4) || (atom3 == atom4)) - error->one(FLERR,"Invalid atom ID in Impropers section of data file"); + error->one(FLERR, "Invalid atom ID in {}: {}", location, utils::trim(buf)); if (itype <= 0 || itype > nimpropertypes) - error->one(FLERR, - "Invalid improper type in Impropers section of data file"); + error->one(FLERR, "Invalid improper type in {}: {}", location, utils::trim(buf)); if ((m = map(atom2)) >= 0) { if (count) count[m]++; else { @@ -1561,7 +1576,7 @@ void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset, void Atom::data_bonus(int n, char *buf, AtomVec *avec_bonus, tagint id_offset) { - int j,m,tagdata; + int j,m; char *next; next = strchr(buf,'\n'); @@ -1572,35 +1587,28 @@ void Atom::data_bonus(int n, char *buf, AtomVec *avec_bonus, tagint id_offset) if (nwords != avec_bonus->size_data_bonus) error->all(FLERR,"Incorrect bonus data format in data file"); - char **values = new char*[nwords]; - // loop over lines of bonus atom data // tokenize the line into values // if I own atom tag, unpack its values for (int i = 0; i < n; i++) { next = strchr(buf,'\n'); + *next = '\0'; + auto values = Tokenizer(utils::trim_comment(buf)).as_vector(); + if (values.size() != nwords) + error->all(FLERR, "Incorrect atom format in data file: {}", utils::trim(buf)); - for (j = 0; j < nwords; j++) { - buf += strspn(buf," \t\n\r\f"); - buf[strcspn(buf," \t\n\r\f")] = '\0'; - values[j] = buf; - buf += strlen(buf)+1; - } - - tagdata = ATOTAGINT(values[0]) + id_offset; + tagint tagdata = utils::tnumeric(FLERR,values[0],false,lmp) + id_offset; if (tagdata <= 0 || tagdata > map_tag_max) error->one(FLERR,"Invalid atom ID in Bonus section of data file"); // ok to call child's data_atom_bonus() method thru parent avec_bonus, // since data_bonus() was called with child ptr, and method is virtual - if ((m = map(tagdata)) >= 0) avec_bonus->data_atom_bonus(m,&values[1]); + if ((m = map(tagdata)) >= 0) avec_bonus->data_atom_bonus(m,values); buf = next + 1; } - - delete [] values; } /* ---------------------------------------------------------------------- @@ -1612,12 +1620,8 @@ void Atom::data_bonus(int n, char *buf, AtomVec *avec_bonus, tagint id_offset) void Atom::data_bodies(int n, char *buf, AtomVec *avec_body, tagint id_offset) { - int j,m,nvalues,tagdata,ninteger,ndouble; - - int maxint = 0; - int maxdouble = 0; - int *ivalues = nullptr; - double *dvalues = nullptr; + std::vector ivalues; + std::vector dvalues; if (!unique_tags) unique_tags = new std::set; @@ -1626,69 +1630,51 @@ void Atom::data_bodies(int n, char *buf, AtomVec *avec_body, tagint id_offset) // else skip values for (int i = 0; i < n; i++) { - buf += strspn(buf," \t\n\r\f"); - buf[strcspn(buf," \t\n\r\f")] = '\0'; - tagdata = utils::tnumeric(FLERR,buf,false,lmp) + id_offset; - buf += strlen(buf)+1; + char *next = strchr(buf,'\n'); + *next = '\0'; - if (tagdata <= 0 || tagdata > map_tag_max) - error->one(FLERR,"Invalid atom ID in Bodies section of data file"); + auto values = Tokenizer(utils::trim_comment(buf)).as_vector(); + tagint tagdata = utils::tnumeric(FLERR,values[0],false,lmp) + id_offset; + int ninteger = utils::inumeric(FLERR,values[1],false,lmp); + int ndouble = utils::inumeric(FLERR,values[2],false,lmp); if (unique_tags->find(tagdata) == unique_tags->end()) unique_tags->insert(tagdata); else error->one(FLERR,"Duplicate atom ID in Bodies section of data file"); - buf += strspn(buf," \t\n\r\f"); - buf[strcspn(buf," \t\n\r\f")] = '\0'; - ninteger = utils::inumeric(FLERR,buf,false,lmp); - buf += strlen(buf)+1; + buf = next + 1; + int m = map(tagdata); + if (m >= 0) { + ivalues.resize(ninteger); + dvalues.resize(ndouble); - buf += strspn(buf," \t\n\r\f"); - buf[strcspn(buf," \t\n\r\f")] = '\0'; - ndouble = utils::inumeric(FLERR,buf,false,lmp); - buf += strlen(buf)+1; - - if ((m = map(tagdata)) >= 0) { - if (ninteger > maxint) { - delete [] ivalues; - maxint = ninteger; - ivalues = new int[maxint]; - } - if (ndouble > maxdouble) { - delete [] dvalues; - maxdouble = ndouble; - dvalues = new double[maxdouble]; - } - - for (j = 0; j < ninteger; j++) { + for (int j = 0; j < ninteger; j++) { buf += strspn(buf," \t\n\r\f"); buf[strcspn(buf," \t\n\r\f")] = '\0'; ivalues[j] = utils::inumeric(FLERR,buf,false,lmp); buf += strlen(buf)+1; } - for (j = 0; j < ndouble; j++) { + for (int j = 0; j < ndouble; j++) { buf += strspn(buf," \t\n\r\f"); buf[strcspn(buf," \t\n\r\f")] = '\0'; dvalues[j] = utils::numeric(FLERR,buf,false,lmp); buf += strlen(buf)+1; } - avec_body->data_body(m,ninteger,ndouble,ivalues,dvalues); + avec_body->data_body(m,ninteger,ndouble,ivalues.data(),dvalues.data()); } else { - nvalues = ninteger + ndouble; // number of values to skip - for (j = 0; j < nvalues; j++) { + int nvalues = ninteger + ndouble; // number of values to skip + for (int j = 0; j < nvalues; j++) { buf += strspn(buf," \t\n\r\f"); buf[strcspn(buf," \t\n\r\f")] = '\0'; buf += strlen(buf)+1; } } + buf += strspn(buf," \t\n\r\f"); } - - delete [] ivalues; - delete [] dvalues; } /* ---------------------------------------------------------------------- @@ -1743,17 +1729,20 @@ void Atom::set_mass(const char *file, int line, const char *str, int type_offset int itype; double mass_one; - int n = sscanf(str,"%d %lg",&itype,&mass_one); - if (n != 2) error->all(file,line,"Invalid mass line in data file"); - itype += type_offset; + try { + ValueTokenizer values(utils::trim_comment(str)); + itype = values.next_int() + type_offset; + mass_one = values.next_double(); + if (values.has_next()) throw TokenizerException("Too many tokens", ""); - if (itype < 1 || itype > ntypes) - error->all(file,line,"Invalid type for mass set"); + if (itype < 1 || itype > ntypes) throw TokenizerException("Invalid atom type", ""); + if (mass_one <= 0.0) throw TokenizerException("Invalid mass value", ""); + } catch (TokenizerException &e) { + error->all(file,line,"{} in Masses section of data file: {}", e.what(), utils::trim(str)); + } mass[itype] = mass_one; mass_setflag[itype] = 1; - - if (mass[itype] <= 0.0) error->all(file,line,"Invalid mass value"); } /* ---------------------------------------------------------------------- diff --git a/src/atom_vec.cpp b/src/atom_vec.cpp index 5ebaf41ebb..aa646ecabb 100644 --- a/src/atom_vec.cpp +++ b/src/atom_vec.cpp @@ -1707,7 +1707,7 @@ void AtomVec::create_atom(int itype, double *coord) initialize other peratom quantities ------------------------------------------------------------------------- */ -void AtomVec::data_atom(double *coord, imageint imagetmp, char **values) +void AtomVec::data_atom(double *coord, imageint imagetmp, const std::vector &values) { int m,n,datatype,cols; void *pdata; @@ -1890,18 +1890,18 @@ void AtomVec::write_data(FILE *fp, int n, double **buf) unpack one line from Velocities section of data file ------------------------------------------------------------------------- */ -void AtomVec::data_vel(int ilocal, char **values) +void AtomVec::data_vel(int ilocal, const std::vector &values) { int m,n,datatype,cols; void *pdata; double **v = atom->v; - v[ilocal][0] = utils::numeric(FLERR,values[0],true,lmp); - v[ilocal][1] = utils::numeric(FLERR,values[1],true,lmp); - v[ilocal][2] = utils::numeric(FLERR,values[2],true,lmp); + int ivalue = 1; + v[ilocal][0] = utils::numeric(FLERR,values[ivalue++],true,lmp); + v[ilocal][1] = utils::numeric(FLERR,values[ivalue++],true,lmp); + v[ilocal][2] = utils::numeric(FLERR,values[ivalue++],true,lmp); if (ndata_vel > 2) { - int ivalue = 3; for (n = 2; n < ndata_vel; n++) { pdata = mdata_vel.pdata[n]; datatype = mdata_vel.datatype[n]; diff --git a/src/atom_vec.h b/src/atom_vec.h index 0a86d1122c..6bc7f23532 100644 --- a/src/atom_vec.h +++ b/src/atom_vec.h @@ -124,9 +124,9 @@ class AtomVec : protected Pointers { virtual void create_atom(int, double *); virtual void create_atom_post(int) {} - virtual void data_atom(double *, imageint, char **); + virtual void data_atom(double *, imageint, const std::vector &); virtual void data_atom_post(int) {} - virtual void data_atom_bonus(int, char **) {} + virtual void data_atom_bonus(int, const std::vector &) {} virtual void data_body(int, int, int, int *, double *) {} virtual void data_bonds_post(int, int, tagint, tagint, tagint) {} @@ -136,7 +136,7 @@ class AtomVec : protected Pointers { virtual void pack_data_pre(int) {} virtual void pack_data_post(int) {} - virtual void data_vel(int, char **); + virtual void data_vel(int, const std::vector &); virtual void pack_vel(double **); virtual void write_vel(FILE *, int, double **); @@ -166,8 +166,8 @@ class AtomVec : protected Pointers { virtual int unpack_reverse_hybrid(int, int *, double *) { return 0; } virtual int pack_border_hybrid(int, int *, double *) { return 0; } virtual int unpack_border_hybrid(int, int, double *) { return 0; } - virtual int data_atom_hybrid(int, char **) { return 0; } - virtual int data_vel_hybrid(int, char **) { return 0; } + virtual int data_atom_hybrid(int, const std::vector &, int) { return 0; } + virtual int data_vel_hybrid(int, const std::vector &, int) { return 0; } virtual int pack_data_hybrid(int, double *) { return 0; } virtual int write_data_hybrid(FILE *, double *) { return 0; } virtual int pack_vel_hybrid(int, double *) { return 0; } diff --git a/src/atom_vec_ellipsoid.cpp b/src/atom_vec_ellipsoid.cpp index 38c4893f61..6c39e4cfaf 100644 --- a/src/atom_vec_ellipsoid.cpp +++ b/src/atom_vec_ellipsoid.cpp @@ -381,7 +381,7 @@ int AtomVecEllipsoid::unpack_restart_bonus(int ilocal, double *buf) unpack one line from Ellipsoids section of data file ------------------------------------------------------------------------- */ -void AtomVecEllipsoid::data_atom_bonus(int m, char **values) +void AtomVecEllipsoid::data_atom_bonus(int m, const std::vector & values) { if (ellipsoid[m]) error->one(FLERR,"Assigning ellipsoid parameters to non-ellipsoid atom"); @@ -389,17 +389,18 @@ void AtomVecEllipsoid::data_atom_bonus(int m, char **values) if (nlocal_bonus == nmax_bonus) grow_bonus(); double *shape = bonus[nlocal_bonus].shape; - shape[0] = 0.5 * utils::numeric(FLERR,values[0],true,lmp); - shape[1] = 0.5 * utils::numeric(FLERR,values[1],true,lmp); - shape[2] = 0.5 * utils::numeric(FLERR,values[2],true,lmp); + int ivalue = 1; + shape[0] = 0.5 * utils::numeric(FLERR,values[ivalue++],true,lmp); + shape[1] = 0.5 * utils::numeric(FLERR,values[ivalue++],true,lmp); + shape[2] = 0.5 * utils::numeric(FLERR,values[ivalue++],true,lmp); if (shape[0] <= 0.0 || shape[1] <= 0.0 || shape[2] <= 0.0) error->one(FLERR,"Invalid shape in Ellipsoids section of data file"); double *quat = bonus[nlocal_bonus].quat; - quat[0] = utils::numeric(FLERR,values[3],true,lmp); - quat[1] = utils::numeric(FLERR,values[4],true,lmp); - quat[2] = utils::numeric(FLERR,values[5],true,lmp); - quat[3] = utils::numeric(FLERR,values[6],true,lmp); + quat[0] = utils::numeric(FLERR,values[ivalue++],true,lmp); + quat[1] = utils::numeric(FLERR,values[ivalue++],true,lmp); + quat[2] = utils::numeric(FLERR,values[ivalue++],true,lmp); + quat[3] = utils::numeric(FLERR,values[ivalue++],true,lmp); MathExtra::qnormalize(quat); // reset ellipsoid mass diff --git a/src/atom_vec_ellipsoid.h b/src/atom_vec_ellipsoid.h index 6a77d9886c..bb50944f30 100644 --- a/src/atom_vec_ellipsoid.h +++ b/src/atom_vec_ellipsoid.h @@ -48,7 +48,7 @@ class AtomVecEllipsoid : public AtomVec { int size_restart_bonus(); int pack_restart_bonus(int, double *); int unpack_restart_bonus(int, double *); - void data_atom_bonus(int, char **); + void data_atom_bonus(int, const std::vector &); double memory_usage_bonus(); void create_atom_post(int); diff --git a/src/atom_vec_line.cpp b/src/atom_vec_line.cpp index bfc6c7e6d7..e15bc61f2f 100644 --- a/src/atom_vec_line.cpp +++ b/src/atom_vec_line.cpp @@ -337,16 +337,17 @@ int AtomVecLine::unpack_restart_bonus(int ilocal, double *buf) unpack one line from Lines section of data file ------------------------------------------------------------------------- */ -void AtomVecLine::data_atom_bonus(int m, char **values) +void AtomVecLine::data_atom_bonus(int m, const std::vector &values) { if (line[m]) error->one(FLERR,"Assigning line parameters to non-line atom"); if (nlocal_bonus == nmax_bonus) grow_bonus(); - double x1 = utils::numeric(FLERR,values[0],true,lmp); - double y1 = utils::numeric(FLERR,values[1],true,lmp); - double x2 = utils::numeric(FLERR,values[2],true,lmp); - double y2 = utils::numeric(FLERR,values[3],true,lmp); + int ivalue = 1; + double x1 = utils::numeric(FLERR,values[ivalue++],true,lmp); + double y1 = utils::numeric(FLERR,values[ivalue++],true,lmp); + double x2 = utils::numeric(FLERR,values[ivalue++],true,lmp); + double y2 = utils::numeric(FLERR,values[ivalue++],true,lmp); double dx = x2 - x1; double dy = y2 - y1; double length = sqrt(dx*dx + dy*dy); diff --git a/src/atom_vec_line.h b/src/atom_vec_line.h index 176cfc0dd9..5903349700 100644 --- a/src/atom_vec_line.h +++ b/src/atom_vec_line.h @@ -48,7 +48,7 @@ class AtomVecLine : public AtomVec { int size_restart_bonus(); int pack_restart_bonus(int, double *); int unpack_restart_bonus(int, double *); - void data_atom_bonus(int, char **); + void data_atom_bonus(int, const std::vector &); double memory_usage_bonus(); void create_atom_post(int); diff --git a/src/atom_vec_tri.cpp b/src/atom_vec_tri.cpp index 6a1cad5f5c..4b1ee0d921 100644 --- a/src/atom_vec_tri.cpp +++ b/src/atom_vec_tri.cpp @@ -470,22 +470,23 @@ int AtomVecTri::unpack_restart_bonus(int ilocal, double *buf) unpack one line from Tris section of data file ------------------------------------------------------------------------- */ -void AtomVecTri::data_atom_bonus(int m, char **values) +void AtomVecTri::data_atom_bonus(int m, const std::vector &values) { if (tri[m]) error->one(FLERR,"Assigning tri parameters to non-tri atom"); if (nlocal_bonus == nmax_bonus) grow_bonus(); double c1[3],c2[3],c3[3]; - c1[0] = utils::numeric(FLERR,values[0],true,lmp); - c1[1] = utils::numeric(FLERR,values[1],true,lmp); - c1[2] = utils::numeric(FLERR,values[2],true,lmp); - c2[0] = utils::numeric(FLERR,values[3],true,lmp); - c2[1] = utils::numeric(FLERR,values[4],true,lmp); - c2[2] = utils::numeric(FLERR,values[5],true,lmp); - c3[0] = utils::numeric(FLERR,values[6],true,lmp); - c3[1] = utils::numeric(FLERR,values[7],true,lmp); - c3[2] = utils::numeric(FLERR,values[8],true,lmp); + int ivalue = 1; + c1[0] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c1[1] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c1[2] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c2[0] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c2[1] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c2[2] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c3[0] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c3[1] = utils::numeric(FLERR,values[ivalue++],true,lmp); + c3[2] = utils::numeric(FLERR,values[ivalue++],true,lmp); // check for duplicate points diff --git a/src/atom_vec_tri.h b/src/atom_vec_tri.h index 36ec8d6948..f9f0bae386 100644 --- a/src/atom_vec_tri.h +++ b/src/atom_vec_tri.h @@ -50,7 +50,7 @@ class AtomVecTri : public AtomVec { int size_restart_bonus(); int pack_restart_bonus(int, double *); int unpack_restart_bonus(int, double *); - void data_atom_bonus(int, char **); + void data_atom_bonus(int, const std::vector &); double memory_usage_bonus(); void create_atom_post(int); diff --git a/src/read_data.cpp b/src/read_data.cpp index 7e5d49e65c..89b3ecadec 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -35,6 +35,7 @@ #include "molecule.h" #include "pair.h" #include "special.h" +#include "tokenizer.h" #include "update.h" #include @@ -1088,37 +1089,32 @@ void ReadData::header(int firstpass) } else if (utils::strmatch(line,"^\\s*\\d+\\s+atom\\s+types\\s")) { rv = sscanf(line,"%d",&ntypes); if (rv != 1) - error->all(FLERR,"Could not parse 'atom types' line " - "in data file header"); + error->all(FLERR,"Could not parse 'atom types' line in data file header"); if (addflag == NONE) atom->ntypes = ntypes + extra_atom_types; } else if (utils::strmatch(line,"\\s*\\d+\\s+bond\\s+types\\s")) { rv = sscanf(line,"%d",&nbondtypes); if (rv != 1) - error->all(FLERR,"Could not parse 'bond types' line " - "in data file header"); + error->all(FLERR,"Could not parse 'bond types' line in data file header"); if (addflag == NONE) atom->nbondtypes = nbondtypes + extra_bond_types; } else if (utils::strmatch(line,"^\\s*\\d+\\s+angle\\s+types\\s")) { rv = sscanf(line,"%d",&nangletypes); if (rv != 1) - error->all(FLERR,"Could not parse 'angle types' line " - "in data file header"); + error->all(FLERR,"Could not parse 'angle types' line in data file header"); if (addflag == NONE) atom->nangletypes = nangletypes + extra_angle_types; } else if (utils::strmatch(line,"^\\s*\\d+\\s+dihedral\\s+types\\s")) { rv = sscanf(line,"%d",&ndihedraltypes); if (rv != 1) - error->all(FLERR,"Could not parse 'dihedral types' line " - "in data file header"); + error->all(FLERR,"Could not parse 'dihedral types' line in data file header"); if (addflag == NONE) atom->ndihedraltypes = ndihedraltypes + extra_dihedral_types; } else if (utils::strmatch(line,"^\\s*\\d+\\s+improper\\s+types\\s")) { rv = sscanf(line,"%d",&nimpropertypes); if (rv != 1) - error->all(FLERR,"Could not parse 'improper types' line " - "in data file header"); + error->all(FLERR,"Could not parse 'improper types' line in data file header"); if (addflag == NONE) atom->nimpropertypes = nimpropertypes + extra_improper_types; @@ -1658,12 +1654,12 @@ void ReadData::bonus(bigint nbonus, AtomVec *ptr, const char *type) read all body data variable amount of info per body, described by ninteger and ndouble to find atoms, must build atom map if not a molecular system - if not firstpass, just read past data, but no processing of data + if not firstpass, just read past body data and only process body header ------------------------------------------------------------------------- */ void ReadData::bodies(int firstpass, AtomVec *ptr) { - int m,nchunk,nline,nmax,ninteger,ndouble,nword,ncount,onebody,tmp,rv; + int m,nchunk,nline,nmax,ninteger,ndouble,nword,ncount,onebody; char *eof; int mapflag = 0; @@ -1677,11 +1673,11 @@ void ReadData::bodies(int firstpass, AtomVec *ptr) // nchunk = actual # read bigint nread = 0; - bigint natoms = nbodies; + bigint nblocks = nbodies; - while (nread < natoms) { - if (natoms-nread > CHUNK) nmax = CHUNK; - else nmax = natoms-nread; + while (nread < nblocks) { + if (nblocks-nread > CHUNK) nmax = CHUNK; + else nmax = nblocks-nread; if (me == 0) { nchunk = 0; @@ -1690,11 +1686,25 @@ void ReadData::bodies(int firstpass, AtomVec *ptr) while (nchunk < nmax && nline <= CHUNK-MAXBODY) { eof = utils::fgets_trunc(&buffer[m],MAXLINE,fp); + const char *buf = &buffer[m]; if (eof == nullptr) error->one(FLERR,"Unexpected end of data file"); - rv = sscanf(&buffer[m],"%d %d %d",&tmp,&ninteger,&ndouble); - if (rv != 3) - error->one(FLERR,"Incorrect format in Bodies section of data file"); - m += strlen(&buffer[m]); + try { + auto values = ValueTokenizer(utils::trim_comment(buf)); + tagint tagdata = values.next_tagint() + id_offset; + ninteger = values.next_int(); + ndouble = values.next_double(); + if (tagdata <= 0 || tagdata > atom->map_tag_max) + throw TokenizerException("Invalid atom ID in body header", utils::trim(buf)); + if (ninteger < 0) + throw TokenizerException("Invalid number of integers", utils::trim(buf)); + if (ndouble < 0) + throw TokenizerException("Invalid number of doubles", utils::trim(buf)); + if (values.has_next()) + throw TokenizerException("Too many tokens in body header", utils::trim(buf)); + } catch (TokenizerException &e) { + error->one(FLERR,std::string(e.what()) + " while reading Bodies section of data file"); + } + m += strlen(buf); // read lines one at a time into buffer and count words // count to ninteger and ndouble until have enough lines @@ -1754,7 +1764,7 @@ void ReadData::bodies(int firstpass, AtomVec *ptr) } if (me == 0 && firstpass) - utils::logmesg(lmp," {} bodies\n",natoms); + utils::logmesg(lmp," {} bodies\n",nblocks); } /* ---------------------------------------------------------------------- */ diff --git a/src/utils.cpp b/src/utils.cpp index f70a60da7c..eabe86adbc 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -298,12 +298,9 @@ std::string utils::check_packages_for_style(const std::string &style, const std: called by various commands to check validity of their arguments ------------------------------------------------------------------------- */ -int utils::logical(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +int utils::logical(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp) { - int n = 0; - - if (str) n = strlen(str); - if (n == 0) { + if (str.empty()) { const char msg[] = "Expected boolean parameter instead of NULL or empty string " "in input script or data file"; if (do_abort) @@ -332,18 +329,28 @@ int utils::logical(const char *file, int line, const char *str, bool do_abort, L return rv; } +/* ---------------------------------------------------------------------- + wrapper for logical() that accepts a char pointer instead of a string +------------------------------------------------------------------------- */ + +int utils::logical(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +{ + if (str) + return logical(file, line, std::string(str), do_abort, lmp); + else + return logical(file, line, std::string(""), do_abort, lmp); +} + /* ---------------------------------------------------------------------- read a floating point value from a string generate an error if not a legitimate floating point value called by various commands to check validity of their arguments ------------------------------------------------------------------------- */ -double utils::numeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +double utils::numeric(const char *file, int line, const std::string &str, bool do_abort, + LAMMPS *lmp) { - int n = 0; - - if (str) n = strlen(str); - if (n == 0) { + if (str.empty()) { const char msg[] = "Expected floating point parameter instead of" " NULL or empty string in input script or data file"; if (do_abort) @@ -367,18 +374,27 @@ double utils::numeric(const char *file, int line, const char *str, bool do_abort return atof(buf.c_str()); } +/* ---------------------------------------------------------------------- + wrapper for numeric() that accepts a char pointer instead of a string +------------------------------------------------------------------------- */ + +double utils::numeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +{ + if (str) + return numeric(file, line, std::string(str), do_abort, lmp); + else + return numeric(file, line, std::string(""), do_abort, lmp); +} + /* ---------------------------------------------------------------------- read an integer value from a string generate an error if not a legitimate integer value called by various commands to check validity of their arguments ------------------------------------------------------------------------- */ -int utils::inumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +int utils::inumeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp) { - int n = 0; - - if (str) n = strlen(str); - if (n == 0) { + if (str.empty()) { const char msg[] = "Expected integer parameter instead of" " NULL or empty string in input script or data file"; if (do_abort) @@ -402,18 +418,28 @@ int utils::inumeric(const char *file, int line, const char *str, bool do_abort, return atoi(buf.c_str()); } +/* ---------------------------------------------------------------------- + wrapper for inumeric() that accepts a char pointer instead of a string +------------------------------------------------------------------------- */ + +int utils::inumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +{ + if (str) + return inumeric(file, line, std::string(str), do_abort, lmp); + else + return inumeric(file, line, std::string(""), do_abort, lmp); +} + /* ---------------------------------------------------------------------- read a big integer value from a string generate an error if not a legitimate integer value called by various commands to check validity of their arguments ------------------------------------------------------------------------- */ -bigint utils::bnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +bigint utils::bnumeric(const char *file, int line, const std::string &str, bool do_abort, + LAMMPS *lmp) { - int n = 0; - - if (str) n = strlen(str); - if (n == 0) { + if (str.empty()) { const char msg[] = "Expected integer parameter instead of" " NULL or empty string in input script or data file"; if (do_abort) @@ -437,18 +463,28 @@ bigint utils::bnumeric(const char *file, int line, const char *str, bool do_abor return ATOBIGINT(buf.c_str()); } +/* ---------------------------------------------------------------------- + wrapper for bnumeric() that accepts a char pointer instead of a string +------------------------------------------------------------------------- */ + +bigint utils::bnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +{ + if (str) + return bnumeric(file, line, std::string(str), do_abort, lmp); + else + return bnumeric(file, line, std::string(""), do_abort, lmp); +} + /* ---------------------------------------------------------------------- read a tag integer value from a string generate an error if not a legitimate integer value called by various commands to check validity of their arguments ------------------------------------------------------------------------- */ -tagint utils::tnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +tagint utils::tnumeric(const char *file, int line, const std::string &str, bool do_abort, + LAMMPS *lmp) { - int n = 0; - - if (str) n = strlen(str); - if (n == 0) { + if (str.empty()) { const char msg[] = "Expected integer parameter instead of" " NULL or empty string in input script or data file"; if (do_abort) @@ -472,6 +508,18 @@ tagint utils::tnumeric(const char *file, int line, const char *str, bool do_abor return ATOTAGINT(buf.c_str()); } +/* ---------------------------------------------------------------------- + wrapper for tnumeric() that accepts a char pointer instead of a string +------------------------------------------------------------------------- */ + +tagint utils::tnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp) +{ + if (str) + return tnumeric(file, line, std::string(str), do_abort, lmp); + else + return tnumeric(file, line, std::string(""), do_abort, lmp); +} + /* ---------------------------------------------------------------------- compute bounds implied by numeric str with a possible wildcard asterisk ------------------------------------------------------------------------- */ diff --git a/src/utils.h b/src/utils.h index 1feee26f27..47a4ace5f9 100644 --- a/src/utils.h +++ b/src/utils.h @@ -169,6 +169,17 @@ namespace utils { * \param lmp pointer to top-level LAMMPS class instance * \return 1 if string resolves to "true", otherwise 0 */ + int logical(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp); + + /*! \overload + * + * \param file name of source file for error message + * \param line line number in source file for error message + * \param str string to be converted to logical + * \param do_abort determines whether to call Error::one() or Error::all() + * \param lmp pointer to top-level LAMMPS class instance + * \return 1 if string resolves to "true", otherwise 0 */ + int logical(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp); /*! Convert a string to a floating point number while checking @@ -181,6 +192,17 @@ namespace utils { * \param lmp pointer to top-level LAMMPS class instance * \return double precision floating point number */ + double numeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp); + + /*! \overload + * + * \param file name of source file for error message + * \param line line number in source file for error message + * \param str string to be converted to number + * \param do_abort determines whether to call Error::one() or Error::all() + * \param lmp pointer to top-level LAMMPS class instance + * \return double precision floating point number */ + double numeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp); /*! Convert a string to an integer number while checking @@ -193,6 +215,17 @@ namespace utils { * \param lmp pointer to top-level LAMMPS class instance * \return integer number (regular int) */ + int inumeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp); + + /*! \overload + * + * \param file name of source file for error message + * \param line line number in source file for error message + * \param str string to be converted to number + * \param do_abort determines whether to call Error::one() or Error::all() + * \param lmp pointer to top-level LAMMPS class instance + * \return double precision floating point number */ + int inumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp); /*! Convert a string to an integer number while checking @@ -205,6 +238,17 @@ namespace utils { * \param lmp pointer to top-level LAMMPS class instance * \return integer number (bigint) */ + bigint bnumeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp); + + /*! \overload + * + * \param file name of source file for error message + * \param line line number in source file for error message + * \param str string to be converted to number + * \param do_abort determines whether to call Error::one() or Error::all() + * \param lmp pointer to top-level LAMMPS class instance + * \return double precision floating point number */ + bigint bnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp); /*! Convert a string to an integer number while checking @@ -217,6 +261,17 @@ namespace utils { * \param lmp pointer to top-level LAMMPS class instance * \return integer number (tagint) */ + tagint tnumeric(const char *file, int line, const std::string &str, bool do_abort, LAMMPS *lmp); + + /*! \overload + * + * \param file name of source file for error message + * \param line line number in source file for error message + * \param str string to be converted to number + * \param do_abort determines whether to call Error::one() or Error::all() + * \param lmp pointer to top-level LAMMPS class instance + * \return double precision floating point number */ + tagint tnumeric(const char *file, int line, const char *str, bool do_abort, LAMMPS *lmp); /*! Compute index bounds derived from a string with a possible wildcard diff --git a/unittest/formats/test_input_convert.cpp b/unittest/formats/test_input_convert.cpp index 0ff6878b13..5930824735 100644 --- a/unittest/formats/test_input_convert.cpp +++ b/unittest/formats/test_input_convert.cpp @@ -49,6 +49,15 @@ TEST_F(InputConvertTest, logical) EXPECT_EQ(utils::logical(FLERR, "off", false, lmp), 0); EXPECT_EQ(utils::logical(FLERR, "0", false, lmp), 0); + EXPECT_EQ(utils::logical(FLERR, std::string("yes"), false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, std::string("true"), false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, std::string("on"), false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, std::string("1"), false, lmp), 1); + EXPECT_EQ(utils::logical(FLERR, std::string("no"), false, lmp), 0); + EXPECT_EQ(utils::logical(FLERR, std::string("false"), false, lmp), 0); + EXPECT_EQ(utils::logical(FLERR, std::string("off"), false, lmp), 0); + EXPECT_EQ(utils::logical(FLERR, std::string("0"), false, lmp), 0); + TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", utils::logical(FLERR, "YES", false, lmp);); TEST_FAILURE(".*ERROR: Expected boolean parameter instead of.*", @@ -94,6 +103,15 @@ TEST_F(InputConvertTest, numeric) EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "10000000000", false, lmp), 1e10); EXPECT_DOUBLE_EQ(utils::numeric(FLERR, "2.56E+3", false, lmp), 2560); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string("0"), false, lmp), 0); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string("0.1"), false, lmp), 0.1); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string("-.232"), false, lmp), -0.232); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string(".2e5"), false, lmp), 20000.0); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string("2.5e-10"), false, lmp), 2.5e-10); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string("+0.3"), false, lmp), 0.3); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string("10000000000"), false, lmp), 1e10); + EXPECT_DOUBLE_EQ(utils::numeric(FLERR, std::string("2.56E+3"), false, lmp), 2560); + TEST_FAILURE(".*ERROR: Expected floating point.*", utils::numeric(FLERR, "yay", false, lmp);); TEST_FAILURE(".*ERROR: Expected floating point.*", utils::numeric(FLERR, "", false, lmp);); TEST_FAILURE(".*ERROR: Expected floating point.*", utils::numeric(FLERR, nullptr, false, lmp);); @@ -110,6 +128,13 @@ TEST_F(InputConvertTest, inumeric) EXPECT_EQ(utils::inumeric(FLERR, "-0", false, lmp), 0); EXPECT_EQ(utils::inumeric(FLERR, "0100", false, lmp), 100); + EXPECT_EQ(utils::inumeric(FLERR, std::string("0"), false, lmp), 0); + EXPECT_EQ(utils::inumeric(FLERR, std::string("-1"), false, lmp), -1); + EXPECT_EQ(utils::inumeric(FLERR, std::string("10000"), false, lmp), 10000); + EXPECT_EQ(utils::inumeric(FLERR, std::string("-532410"), false, lmp), -532410); + EXPECT_EQ(utils::inumeric(FLERR, std::string("-0"), false, lmp), 0); + EXPECT_EQ(utils::inumeric(FLERR, std::string("0100"), false, lmp), 100); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "yay", false, lmp);); TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "0.1", false, lmp);); TEST_FAILURE(".*ERROR: Expected integer.*", utils::inumeric(FLERR, "1.1", false, lmp);); @@ -128,6 +153,13 @@ TEST_F(InputConvertTest, bnumeric) EXPECT_EQ(utils::bnumeric(FLERR, "-0", false, lmp), 0); EXPECT_EQ(utils::bnumeric(FLERR, "0100", false, lmp), 100); + EXPECT_EQ(utils::bnumeric(FLERR, std::string("0"), false, lmp), 0); + EXPECT_EQ(utils::bnumeric(FLERR, std::string("-1"), false, lmp), -1); + EXPECT_EQ(utils::bnumeric(FLERR, std::string("10000"), false, lmp), 10000); + EXPECT_EQ(utils::bnumeric(FLERR, std::string("-532410"), false, lmp), -532410); + EXPECT_EQ(utils::bnumeric(FLERR, std::string("-0"), false, lmp), 0); + EXPECT_EQ(utils::bnumeric(FLERR, std::string("0100"), false, lmp), 100); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "yay", false, lmp);); TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "0.1", false, lmp);); TEST_FAILURE(".*ERROR: Expected integer.*", utils::bnumeric(FLERR, "1.1", false, lmp);); @@ -146,6 +178,13 @@ TEST_F(InputConvertTest, tnumeric) EXPECT_EQ(utils::tnumeric(FLERR, "-0", false, lmp), 0); EXPECT_EQ(utils::tnumeric(FLERR, "0100", false, lmp), 100); + EXPECT_EQ(utils::tnumeric(FLERR, std::string("0"), false, lmp), 0); + EXPECT_EQ(utils::tnumeric(FLERR, std::string("-1"), false, lmp), -1); + EXPECT_EQ(utils::tnumeric(FLERR, std::string("10000"), false, lmp), 10000); + EXPECT_EQ(utils::tnumeric(FLERR, std::string("-532410"), false, lmp), -532410); + EXPECT_EQ(utils::tnumeric(FLERR, std::string("-0"), false, lmp), 0); + EXPECT_EQ(utils::tnumeric(FLERR, std::string("0100"), false, lmp), 100); + TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "yay", false, lmp);); TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "0.1", false, lmp);); TEST_FAILURE(".*ERROR: Expected integer.*", utils::tnumeric(FLERR, "1.1", false, lmp););