diff --git a/.github/workflows/compile-msvc.yml b/.github/workflows/compile-msvc.yml index 216f465568..3ec5fc4cb0 100644 --- a/.github/workflows/compile-msvc.yml +++ b/.github/workflows/compile-msvc.yml @@ -3,9 +3,11 @@ name: "Native Windows Compilation and Unit Tests" on: push: - branches: [ develop ] + branches: + - develop pull_request: - branches: [ $default-branch ] + branches: + - develop workflow_dispatch: diff --git a/.github/workflows/unittest-macos.yml b/.github/workflows/unittest-macos.yml index aba0570f2b..2d29eac83e 100644 --- a/.github/workflows/unittest-macos.yml +++ b/.github/workflows/unittest-macos.yml @@ -3,9 +3,11 @@ name: "Unittest for MacOS" on: push: - branches: [ develop ] + branches: + - develop pull_request: - branches: [ $default-branch ] + branches: + - develop workflow_dispatch: diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index 85475ef16a..f2291b231e 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -652,7 +652,7 @@ short-range or long-range interactions. * :doc:`pair_style lj/cut/dipole/cut ` * :doc:`pair_style lj/cut/dipole/long ` * :doc:`pair_style lj/long/dipole/long ` -* :doc: `angle_style dipole ` +* :doc:`angle_style dipole ` * examples/dipole ---------- @@ -1404,7 +1404,7 @@ This package has :ref:`specific installation instructions ` on the :doc * src/MACHDYN: filenames -> commands * src/MACHDYN/README -* doc/PDF/MACHDYN_LAMMPS_userguide.pdf +* `doc/PDF/MACHDYN_LAMMPS_userguide.pdf `_ * examples/PACKAGES/machdyn * https://www.lammps.org/movies.html#smd @@ -2703,7 +2703,7 @@ Dynamics, Ernst Mach Institute, Germany). * src/SPH: filenames -> commands * src/SPH/README -* doc/PDF/SPH_LAMMPS_userguide.pdf +* `doc/PDF/SPH_LAMMPS_userguide.pdf `_ * examples/PACKAGES/sph * https://www.lammps.org/movies.html#sph diff --git a/doc/src/compute_property_atom.rst b/doc/src/compute_property_atom.rst index 2e9619062e..dad83ee79c 100644 --- a/doc/src/compute_property_atom.rst +++ b/doc/src/compute_property_atom.rst @@ -198,8 +198,8 @@ Related commands """""""""""""""" :doc:`dump custom `, :doc:`compute reduce `, -:doc::doc:`fix ave/atom `, :doc:`fix ave/chunk -:doc:`, `fix property/atom ` +:doc:`fix ave/atom `, :doc:`fix ave/chunk` +:doc:``, `fix property/atom ` Default """"""" diff --git a/doc/src/compute_stress_atom.rst b/doc/src/compute_stress_atom.rst index 08f7e3032e..3b21fbf102 100644 --- a/doc/src/compute_stress_atom.rst +++ b/doc/src/compute_stress_atom.rst @@ -222,6 +222,26 @@ result. I.e. the last 2 columns of thermo output will be the same: ` command, since those are contributions to the global system pressure. +The compute stress/atom can be used in a number of ways. Here is an +example to compute a 1-d pressure profile in z-direction across the +complete simulation box. You will need to adjust the number of bins and the +selections for time averaging to your specific simulation. This assumes +that the dimensions of the simulation cell does not change. + +.. code-block:: LAMMPS + + # set number of bins + variable nbins index 20 + variable fraction equal 1.0/v_nbins + # define bins as chunks + compute cchunk all chunk/atom bin/1d x lower ${fraction} units reduced + compute stress all stress/atom NULL + # apply conversion to pressure early since we have no variable style for processing chunks + variable press atom -(c_stress[1]+c_stress[2]+c_stress[3])/(3.0*vol*${fraction}) + compute binpress all reduce/chunk cchunk sum v_press + fix avg all ave/time 10 40 400 c_binpress mode vector file ave_stress.txt + + Output info """"""""""" diff --git a/doc/src/dump.rst b/doc/src/dump.rst index bd57ef0353..13332e2bc3 100644 --- a/doc/src/dump.rst +++ b/doc/src/dump.rst @@ -62,7 +62,7 @@ Syntax * ID = user-assigned name for the dump * group-ID = ID of the group of atoms to be dumped * style = *atom* or *atom/gz* or *atom/zstd* or *atom/mpiio* or *cfg* or *cfg/gz* or *cfg/zstd* or *cfg/mpiio* or *cfg/uef* or *custom* or *custom/gz* or *custom/zstd* or *custom/mpiio* or *dcd* or *h5md* or *image* or *local* or *local/gz* or *local/zstd* or *molfile* or *movie* or *netcdf* or *netcdf/mpiio* or *vtk* or *xtc* or *xyz* or *xyz/gz* or *xyz/zstd* or *xyz/mpiio* or *yaml* -* N = dump every this many timesteps +* N = dump on timesteps which are a multiple of N * file = name of file to write dump info to * args = list of arguments for a particular style @@ -176,14 +176,15 @@ Examples Description """"""""""" -Dump a snapshot of atom quantities to one or more files every :math:`N` -timesteps in one of several styles. The *image* and *movie* styles are -the exception: the *image* style renders a JPG, PNG, or PPM image file -of the atom configuration every :math:`N` timesteps while the *movie* style -combines and compresses them into a movie file; both are discussed in -detail on the :doc:`dump image ` page. The timesteps on -which dump output is written can also be controlled by a variable. -See the :doc:`dump_modify every ` command. +Dump a snapshot of atom quantities to one or more files once every +:math:`N` timesteps in one of several styles. The *image* and *movie* +styles are the exception: the *image* style renders a JPG, PNG, or PPM +image file of the atom configuration every :math:`N` timesteps while +the *movie* style combines and compresses them into a movie file; both +are discussed in detail on the :doc:`dump image ` page. +The timesteps on which dump output is written can also be controlled +by a variable. See the :doc:`dump_modify every ` +command. Only information for atoms in the specified group is dumped. The :doc:`dump_modify thresh and region and refresh ` commands @@ -485,21 +486,29 @@ popular molecular viewing program. ---------- -Dumps are performed on timesteps that are a multiple of :math:`N` (including -timestep 0) and on the last timestep of a minimization if the -minimization converges. Note that this means a dump will not be +Dumps are performed on timesteps that are a multiple of :math:`N` +(including timestep 0) and on the last timestep of a minimization if +the minimization converges. Note that this means a dump will not be performed on the initial timestep after the dump command is invoked, -if the current timestep is not a multiple of :math:`N`. This behavior can be -changed via the :doc:`dump_modify first ` command, which -can also be useful if the dump command is invoked after a minimization -ended on an arbitrary timestep. :math:`N` can be changed between runs by -using the :doc:`dump_modify every ` command (not allowed -for *dcd* style). The :doc:`dump_modify every ` command -also allows a variable to be used to determine the sequence of -timesteps on which dump files are written. In this mode a dump on the -first timestep of a run will also not be written unless the +if the current timestep is not a multiple of :math:`N`. This behavior +can be changed via the :doc:`dump_modify first ` command, +which can also be useful if the dump command is invoked after a +minimization ended on an arbitrary timestep. + +The value of :math:`N` can be changed between runs by using the +:doc:`dump_modify every ` command (not allowed for *dcd* +style). The :doc:`dump_modify every ` command also +allows a variable to be used to determine the sequence of timesteps on +which dump files are written. In this mode a dump on the first +timestep of a run will also not be written unless the :doc:`dump_modify first ` command is used. +If you instead want to dump snapshots based on simulation time (in +time units of the :doc:`units` command), the :doc:`dump_modify +every/time ` command can be used. This can be useful +when the timestep size varies during a simulation run, e.g. by use of +the :doc:`fix dt/reset ` command. + The specified filename determines how the dump file(s) is written. The default is to write one large text file, which is opened when the dump command is invoked and closed when an :doc:`undump ` diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index d3611e0ba9..b791395259 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -35,10 +35,10 @@ Syntax *element* args = E1 E2 ... EN, where N = # of atom types E1,...,EN = element name (e.g., C or Fe or Ga) *every* arg = N - N = dump every this many timesteps + N = dump on timesteps which are a multiple of N N can be a variable (see below) *every/time* arg = Delta - Delta = dump every this interval in simulation time (time units) + Delta = dump once every Delta interval of simulation time (time units) Delta can be a variable (see below) *fileper* arg = Np Np = write one file for every this many processors @@ -207,13 +207,10 @@ will be accepted. ---------- The *every* keyword can be used with any dump style except the *dcd* -and *xtc* styles. It does two things. It specifies that the interval -between dump snapshots will be set in timesteps, which is the default -if the *every* or *every/time* keywords are not used. See the -*every/time* keyword for how to specify the interval in simulation -time, i.e. in time units of the :doc:`units ` command. The -*every* keyword also sets the interval value, which overrides the dump -frequency originally specified by the :doc:`dump ` command. +and *xtc* styles. It specifies that the output of dump snapshots will +now be performed on timesteps which are a multiple of a new :math:`N` +value, This overrides the dump frequency originally specified by the +:doc:`dump ` command. The *every* keyword can be specified in one of two ways. It can be a numeric value in which case it must be > 0. Or it can be an @@ -273,6 +270,17 @@ in file tmp.times: ---------- +The *every/time* keyword can be used with any dump style except the +*dcd* and *xtc* styles. It changes the frequency of dump snapshots +from being based on the current timestep to being determined by +elapsed simulation time, i.e. in time units of the :doc:`units +` command, and specifies *Delta* for the interval between +snapshots. This can be useful when the timestep size varies during a +simulation run, e.g. by use of the :doc:`fix dt/reset ` +command. The default is to perform output on timesteps which a +multiples of specified timestep value :math:`N`; see the *every* +keyword. + The *every/time* keyword can be used with any dump style except the *dcd* and *xtc* styles. It does two things. It specifies that the interval between dump snapshots will be set in simulation time diff --git a/doc/src/fix_orient_eco.rst b/doc/src/fix_orient_eco.rst index b2fc71f1f7..2a2580f3cc 100644 --- a/doc/src/fix_orient_eco.rst +++ b/doc/src/fix_orient_eco.rst @@ -98,7 +98,7 @@ to track the grain boundary motion throughout the simulation. Restart, fix_modify, output, run start/stop, minimize info """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" -No information about this fix is written to :doc: `binary restart +No information about this fix is written to :doc:`binary restart files `. The :doc:`fix_modify ` *energy* option is supported by diff --git a/doc/src/pair_harmonic_cut.rst b/doc/src/pair_harmonic_cut.rst index ab719ee3d6..6b28db5fda 100644 --- a/doc/src/pair_harmonic_cut.rst +++ b/doc/src/pair_harmonic_cut.rst @@ -33,7 +33,8 @@ Style *harmonic/cut* computes pairwise repulsive-only harmonic interactions with E = k (r_c - r)^2 \qquad r < r_c -:math:`r_c` is the cutoff. +where :math:`r_c` is the cutoff. Note that the usual 1/2 factor is +included in :math:`k`. The following coefficients must be defined for each pair of atoms types via the :doc:`pair_coeff ` command as in the examples @@ -41,7 +42,7 @@ above, or in the data file or restart files read by the :doc:`read_data ` or :doc:`read_restart ` commands: -* :math:`k` (energy units) +* :math:`k` (energy/distance^2 units) * :math:`r_c` (distance units) ---------- diff --git a/doc/src/pair_mesocnt.rst b/doc/src/pair_mesocnt.rst index e150c66721..4833ea6eb8 100644 --- a/doc/src/pair_mesocnt.rst +++ b/doc/src/pair_mesocnt.rst @@ -92,7 +92,7 @@ segments. Friction forces are a function of the relative velocity between a segment and its neighboring approximate chain (even in *segment* mode) and only act along the axes of the interacting segment and chain. In this potential, friction forces acting per unit length -of a nanotube segent are modelled as a shifted logistic function: +of a nanotube segment are modelled as a shifted logistic function: .. math:: diff --git a/lib/gpu/lal_pre_cuda_hip.h b/lib/gpu/lal_pre_cuda_hip.h index ec666a2863..92af47a4b7 100644 --- a/lib/gpu/lal_pre_cuda_hip.h +++ b/lib/gpu/lal_pre_cuda_hip.h @@ -134,7 +134,7 @@ int2 qt = tex1Dfetch(q_tex,i); \ ans=__hiloint2double(qt.y, qt.x); \ } - #elseif defined(__HIP_PLATFORM_SPIRV__) + #elif defined(__HIP_PLATFORM_SPIRV__) #define fetch4(ans,i,pos_tex) tex1Dfetch(&ans, pos_tex, i); #define fetch(ans,i,q_tex) tex1Dfetch(&ans, q_tex,i); #else diff --git a/src/ADIOS/dump_custom_adios.cpp b/src/ADIOS/dump_custom_adios.cpp index 211a550f5e..305f3d3032 100644 --- a/src/ADIOS/dump_custom_adios.cpp +++ b/src/ADIOS/dump_custom_adios.cpp @@ -219,7 +219,7 @@ void DumpCustomADIOS::init_style() delete[] columns; std::string combined; int icol = 0; - for (auto item : utils::split_words(columns_default)) { + for (const auto &item : utils::split_words(columns_default)) { if (combined.size()) combined += " "; if (keyword_user[icol].size()) combined += keyword_user[icol]; diff --git a/src/AMOEBA/pair_amoeba.cpp b/src/AMOEBA/pair_amoeba.cpp index bf52524567..1f1baa0280 100644 --- a/src/AMOEBA/pair_amoeba.cpp +++ b/src/AMOEBA/pair_amoeba.cpp @@ -134,6 +134,14 @@ PairAmoeba::PairAmoeba(LAMMPS *lmp) : Pair(lmp) id_pole = id_udalt = id_upalt = nullptr; + memset(special_hal, 0 , sizeof(special_hal)); + memset(special_repel, 0 , sizeof(special_repel)); + memset(special_disp, 0 , sizeof(special_disp)); + memset(special_mpole, 0 , sizeof(special_mpole)); + memset(special_polar_pscale, 0 , sizeof(special_polar_pscale)); + memset(special_polar_piscale, 0 , sizeof(special_polar_piscale)); + memset(special_polar_wscale, 0 , sizeof(special_polar_wscale)); + nualt = 0; first_flag = 1; first_flag_compute = 1; diff --git a/src/AMOEBA/pair_amoeba.h b/src/AMOEBA/pair_amoeba.h index 84bc480062..ad80a74879 100644 --- a/src/AMOEBA/pair_amoeba.h +++ b/src/AMOEBA/pair_amoeba.h @@ -99,13 +99,13 @@ class PairAmoeba : public Pair { int poltyp; - double special_hal[5]; - double special_repel[5]; - double special_disp[5]; - double special_mpole[5]; - double special_polar_pscale[5]; - double special_polar_piscale[5]; - double special_polar_wscale[5]; + double special_hal[8]; + double special_repel[8]; + double special_disp[8]; + double special_mpole[8]; + double special_polar_pscale[8]; + double special_polar_piscale[8]; + double special_polar_wscale[8]; double polar_dscale, polar_uscale; diff --git a/src/MPIIO/dump_atom_mpiio.cpp b/src/MPIIO/dump_atom_mpiio.cpp index c275b387db..87ef2b0342 100644 --- a/src/MPIIO/dump_atom_mpiio.cpp +++ b/src/MPIIO/dump_atom_mpiio.cpp @@ -236,7 +236,7 @@ void DumpAtomMPIIO::init_style() int icol = 0; columns.clear(); - for (auto item : utils::split_words(default_columns)) { + for (const auto &item : utils::split_words(default_columns)) { if (columns.size()) columns += " "; if (keyword_user[icol].size()) columns += keyword_user[icol]; diff --git a/src/MPIIO/dump_custom_mpiio.cpp b/src/MPIIO/dump_custom_mpiio.cpp index 678ee3dadd..a5b2a681d3 100644 --- a/src/MPIIO/dump_custom_mpiio.cpp +++ b/src/MPIIO/dump_custom_mpiio.cpp @@ -207,7 +207,7 @@ void DumpCustomMPIIO::init_style() delete[] columns; std::string combined; int icol = 0; - for (auto item : utils::split_words(columns_default)) { + for (const auto &item : utils::split_words(columns_default)) { if (combined.size()) combined += " "; if (keyword_user[icol].size()) combined += keyword_user[icol]; diff --git a/src/PLUGIN/plugin.cpp b/src/PLUGIN/plugin.cpp index 6b11ac269f..5451cd31e2 100644 --- a/src/PLUGIN/plugin.cpp +++ b/src/PLUGIN/plugin.cpp @@ -448,7 +448,7 @@ int plugin_get_num_plugins() int plugin_find(const char *style, const char *name) { int i = 0; - for (auto entry : pluginlist) { + for (const auto &entry : pluginlist) { if ((strcmp(style, entry.style) == 0) && (strcmp(name, entry.name) == 0)) return i; ++i; } diff --git a/src/SPIN/fix_nve_spin.cpp b/src/SPIN/fix_nve_spin.cpp index b075c2f88b..e578462526 100644 --- a/src/SPIN/fix_nve_spin.cpp +++ b/src/SPIN/fix_nve_spin.cpp @@ -431,22 +431,21 @@ void FixNVESpin::initial_integrate(int /*vflag*/) } } } - } else if (sector_flag == 0) { // serial seq. update + } else { // serial seq. update comm->forward_comm(); // comm. positions of ghost atoms - for (int i = 0; i < nlocal; i++) { // advance quarter s for nlocal-1 + for (int i = 0; i < nlocal; i++) { // advance quarter s for nlocal-1 if (mask[i] & groupbit) { ComputeInteractionsSpin(i); AdvanceSingleSpin(i); } } - for (int i = nlocal-1; i >= 0; i--) { // advance quarter s for nlocal-1 + for (int i = nlocal-1; i >= 0; i--) { // advance quarter s for nlocal-1 if (mask[i] & groupbit) { ComputeInteractionsSpin(i); AdvanceSingleSpin(i); } } - } else error->all(FLERR,"Illegal fix nve/spin command"); - + } } /* ---------------------------------------------------------------------- diff --git a/src/compute_reduce_chunk.cpp b/src/compute_reduce_chunk.cpp index 1749503254..5236917688 100644 --- a/src/compute_reduce_chunk.cpp +++ b/src/compute_reduce_chunk.cpp @@ -323,7 +323,7 @@ void ComputeReduceChunk::compute_one(int m, double *vchunk, int nstride) { // initialize per-chunk values in accumulation vector - for (int i = 0; i < nchunk; i += nstride) vchunk[i] = initvalue; + for (int i = 0; i < nvalues*nchunk; i += nstride) vchunk[i] = initvalue; // loop over my atoms // use peratom input and chunk ID of each atom to update vector diff --git a/src/dump.cpp b/src/dump.cpp index c4b4cc02e9..247da8595a 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -1067,10 +1067,12 @@ void Dump::modify_params(int narg, char **arg) if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { delete[] output->var_dump[idump]; output->var_dump[idump] = utils::strdup(&arg[iarg+1][2]); + output->last_dump[idump] = -1; n = 0; } else { n = utils::inumeric(FLERR,arg[iarg+1],false,lmp); if (n <= 0) error->all(FLERR, "Invalid dump_modify every argument: {}", n); + output->next_dump[idump] = (update->ntimestep/n)*n+n; } output->mode_dump[idump] = 0; output->every_dump[idump] = n; @@ -1134,7 +1136,7 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"colname") == 0) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "dump_modify colname", error); if (strcmp(arg[iarg+1],"default") == 0) { - for (auto item : keyword_user) item.clear(); + for (auto &item : keyword_user) item.clear(); iarg += 2; } else { if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "dump_modify colname", error); diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp index f52ba94f33..ef567abdb2 100644 --- a/src/dump_atom.cpp +++ b/src/dump_atom.cpp @@ -80,7 +80,7 @@ void DumpAtom::init_style() int icol = 0; columns.clear(); - for (auto item : utils::split_words(default_columns)) { + for (const auto &item : utils::split_words(default_columns)) { if (columns.size()) columns += " "; if (keyword_user[icol].size()) columns += keyword_user[icol]; else columns += item; diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index 1e7ad367ec..2417a05c2c 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -241,7 +241,7 @@ void DumpCustom::init_style() delete[] columns; std::string combined; int icol = 0; - for (auto item : utils::split_words(columns_default)) { + for (const auto &item : utils::split_words(columns_default)) { if (combined.size()) combined += " "; if (keyword_user[icol].size()) combined += keyword_user[icol]; else combined += item; diff --git a/src/dump_local.cpp b/src/dump_local.cpp index bf26890b05..b7a390a749 100644 --- a/src/dump_local.cpp +++ b/src/dump_local.cpp @@ -161,7 +161,7 @@ void DumpLocal::init_style() delete[] columns; std::string combined; int icol = 0; - for (auto item : utils::split_words(columns_default)) { + for (const auto &item : utils::split_words(columns_default)) { if (combined.size()) combined += " "; if (keyword_user[icol].size()) combined += keyword_user[icol]; else combined += item; diff --git a/src/fix_ave_chunk.cpp b/src/fix_ave_chunk.cpp index f3242cac54..9d378f2e0c 100644 --- a/src/fix_ave_chunk.cpp +++ b/src/fix_ave_chunk.cpp @@ -260,45 +260,36 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : for (int i = 0; i < nvalues; i++) { if (which[i] == ArgInfo::COMPUTE) { - int icompute = modify->find_compute(ids[i]); - if (icompute < 0) - error->all(FLERR,"Compute ID for fix ave/chunk does not exist"); - if (modify->compute[icompute]->peratom_flag == 0) - error->all(FLERR,"Fix ave/chunk compute does not " - "calculate per-atom values"); - if (argindex[i] == 0 && - modify->compute[icompute]->size_peratom_cols != 0) - error->all(FLERR,"Fix ave/chunk compute does not " - "calculate a per-atom vector"); - if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0) - error->all(FLERR,"Fix ave/chunk compute does not " - "calculate a per-atom array"); - if (argindex[i] && - argindex[i] > modify->compute[icompute]->size_peratom_cols) - error->all(FLERR, - "Fix ave/chunk compute vector is accessed out-of-range"); + auto icompute = modify->get_compute_by_id(ids[i]); + if (!icompute) + error->all(FLERR,"Compute ID {} for fix ave/chunk does not exist",ids[i]); + if (icompute->peratom_flag == 0) + error->all(FLERR,"Fix ave/chunk compute {} does not calculate per-atom values",ids[i]); + if (argindex[i] == 0 && (icompute->size_peratom_cols != 0)) + error->all(FLERR,"Fix ave/chunk compute {} does not calculate a per-atom vector",ids[i]); + if (argindex[i] && (icompute->size_peratom_cols == 0)) + error->all(FLERR,"Fix ave/chunk compute {} does not calculate a per-atom array",ids[i]); + if (argindex[i] && (argindex[i] > icompute->size_peratom_cols)) + error->all(FLERR,"Fix ave/chunk compute {} vector is accessed out-of-range",ids[i]); } else if (which[i] == ArgInfo::FIX) { - int ifix = modify->find_fix(ids[i]); - if (ifix < 0) - error->all(FLERR,"Fix ID for fix ave/chunk does not exist"); - if (modify->fix[ifix]->peratom_flag == 0) - error->all(FLERR, - "Fix ave/chunk fix does not calculate per-atom values"); - if (argindex[i] == 0 && modify->fix[ifix]->size_peratom_cols != 0) - error->all(FLERR, - "Fix ave/chunk fix does not calculate a per-atom vector"); - if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0) - error->all(FLERR, - "Fix ave/chunk fix does not calculate a per-atom array"); - if (argindex[i] && argindex[i] > modify->fix[ifix]->size_peratom_cols) - error->all(FLERR,"Fix ave/chunk fix vector is accessed out-of-range"); + auto ifix = modify->get_fix_by_id(ids[i]); + if (!ifix) + error->all(FLERR, "Fix ID {} for fix ave/chunk does not exist",ids[i]); + if (ifix->peratom_flag == 0) + error->all(FLERR, "Fix ave/chunk fix {} does not calculate per-atom values",ids[i]); + if (argindex[i] == 0 && (ifix->size_peratom_cols != 0)) + error->all(FLERR, "Fix ave/chunk fix {} does not calculate a per-atom vector",ids[i]); + if (argindex[i] && (ifix->size_peratom_cols == 0)) + error->all(FLERR, "Fix ave/chunk fix {} does not calculate a per-atom array",ids[i]); + if (argindex[i] && argindex[i] > ifix->size_peratom_cols) + error->all(FLERR,"Fix ave/chunk fix {} vector is accessed out-of-range",ids[i]); } else if (which[i] == ArgInfo::VARIABLE) { int ivariable = input->variable->find(ids[i]); if (ivariable < 0) - error->all(FLERR,"Variable name for fix ave/chunk does not exist"); + error->all(FLERR,"Variable name {} for fix ave/chunk does not exist",ids[i]); if (input->variable->atomstyle(ivariable) == 0) - error->all(FLERR,"Fix ave/chunk variable is not atom-style variable"); + error->all(FLERR,"Fix ave/chunk variable {} is not atom-style variable",ids[i]); } } @@ -306,14 +297,12 @@ FixAveChunk::FixAveChunk(LAMMPS *lmp, int narg, char **arg) : // only if nrepeat > 1 or ave = RUNNING/WINDOW, // so that locking spans multiple timesteps - int icompute = modify->find_compute(idchunk); - if (icompute < 0) - error->all(FLERR,"Chunk/atom compute does not exist for fix ave/chunk"); - cchunk = dynamic_cast( modify->compute[icompute]); - if (strcmp(cchunk->style,"chunk/atom") != 0) - error->all(FLERR,"Fix ave/chunk does not use chunk/atom compute"); + cchunk = dynamic_cast(modify->get_compute_by_id(idchunk)); + if (!cchunk) + error->all(FLERR,"Chunk/atom compute {} does not exist or is " + "incorrect style for fix ave/chunk",idchunk); - if (nrepeat > 1 || ave == RUNNING || ave == WINDOW) cchunk->lockcount++; + if ((nrepeat > 1) || (ave == RUNNING) || (ave == WINDOW)) cchunk->lockcount++; lockforever = 0; // print file comment lines @@ -430,9 +419,8 @@ FixAveChunk::~FixAveChunk() // decrement lock counter in compute chunk/atom, it if still exists if (nrepeat > 1 || ave == RUNNING || ave == WINDOW) { - int icompute = modify->find_compute(idchunk); - if (icompute >= 0) { - cchunk = dynamic_cast( modify->compute[icompute]); + cchunk = dynamic_cast(modify->get_compute_by_id(idchunk)); + if (cchunk) { if (ave == RUNNING || ave == WINDOW) cchunk->unlock(this); cchunk->lockcount--; } diff --git a/src/fix_ave_time.cpp b/src/fix_ave_time.cpp index 010170e149..1a437783e7 100644 --- a/src/fix_ave_time.cpp +++ b/src/fix_ave_time.cpp @@ -678,7 +678,7 @@ void FixAveTime::invoke_scalar(bigint ntimestep) if (!yaml_header || overwrite) { yaml_header = true; fputs("keywords: ['Step', ", fp); - for (auto k : keyword) fmt::print(fp, "'{}', ", k); + for (const auto &k : keyword) fmt::print(fp, "'{}', ", k); fputs("]\ndata:\n", fp); } fmt::print(fp, " - [{}, ", ntimestep); @@ -900,7 +900,7 @@ void FixAveTime::invoke_vector(bigint ntimestep) if (!yaml_header || overwrite) { yaml_header = true; fputs("keywords: [", fp); - for (auto k : keyword) fmt::print(fp, "'{}', ", k); + for (const auto &k : keyword) fmt::print(fp, "'{}', ", k); fputs("]\ndata:\n", fp); } fmt::print(fp, " {}:\n", ntimestep); diff --git a/src/fix_box_relax.cpp b/src/fix_box_relax.cpp index 7988657339..756a62bb51 100644 --- a/src/fix_box_relax.cpp +++ b/src/fix_box_relax.cpp @@ -46,7 +46,7 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), id_temp(nullptr), id_press(nullptr), tflag(0), pflag(0) { - if (narg < 5) error->all(FLERR,"Illegal fix box/relax command"); + if (narg < 5) utils::missing_cmd_args(FLERR, "fix box/relax", error); scalar_flag = 1; extscalar = 1; @@ -89,7 +89,7 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (strcmp(arg[iarg],"iso") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax iso", error); pcouple = XYZ; p_target[0] = p_target[1] = p_target[2] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[0] = p_flag[1] = p_flag[2] = 1; @@ -99,7 +99,7 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : } iarg += 2; } else if (strcmp(arg[iarg],"aniso") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax aniso", error); pcouple = NONE; p_target[0] = p_target[1] = p_target[2] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[0] = p_flag[1] = p_flag[2] = 1; @@ -109,7 +109,7 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : } iarg += 2; } else if (strcmp(arg[iarg],"tri") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax tri", error); pcouple = NONE; scalexy = scalexz = scaleyz = 0; p_target[0] = p_target[1] = p_target[2] = utils::numeric(FLERR,arg[iarg+1],false,lmp); @@ -123,46 +123,43 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"x") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax x", error); p_target[0] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[0] = 1; deviatoric_flag = 1; iarg += 2; } else if (strcmp(arg[iarg],"y") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax y", error); p_target[1] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[1] = 1; deviatoric_flag = 1; iarg += 2; } else if (strcmp(arg[iarg],"z") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax z", error); p_target[2] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[2] = 1; deviatoric_flag = 1; iarg += 2; - if (dimension == 2) - error->all(FLERR,"Invalid fix box/relax command for a 2d simulation"); + if (dimension == 2) error->all(FLERR,"Fix box/relax z not allowed for a 2d simulation"); } else if (strcmp(arg[iarg],"yz") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax yz", error); p_target[3] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[3] = 1; deviatoric_flag = 1; scaleyz = 0; iarg += 2; - if (dimension == 2) - error->all(FLERR,"Invalid fix box/relax command for a 2d simulation"); + if (dimension == 2) error->all(FLERR,"Fix box/relax yz not allowed for a 2d simulation"); } else if (strcmp(arg[iarg],"xz") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax xz", error); p_target[4] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[4] = 1; deviatoric_flag = 1; scalexz = 0; iarg += 2; - if (dimension == 2) - error->all(FLERR,"Invalid fix box/relax command for a 2d simulation"); + if (dimension == 2) error->all(FLERR,"Fix box/relax xz not allowed for a 2d simulation"); } else if (strcmp(arg[iarg],"xy") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax xy", error); p_target[5] = utils::numeric(FLERR,arg[iarg+1],false,lmp); p_flag[5] = 1; deviatoric_flag = 1; @@ -170,49 +167,50 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : iarg += 2; } else if (strcmp(arg[iarg],"couple") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax couple", error); if (strcmp(arg[iarg+1],"xyz") == 0) pcouple = XYZ; else if (strcmp(arg[iarg+1],"xy") == 0) pcouple = XY; else if (strcmp(arg[iarg+1],"yz") == 0) pcouple = YZ; else if (strcmp(arg[iarg+1],"xz") == 0) pcouple = XZ; else if (strcmp(arg[iarg+1],"none") == 0) pcouple = NONE; - else error->all(FLERR,"Illegal fix box/relax command"); + else error->all(FLERR,"Illegal fix box/relax couple command: {} unknown", arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"dilate") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax dilate", error); if (strcmp(arg[iarg+1],"all") == 0) allremap = 1; else if (strcmp(arg[iarg+1],"partial") == 0) allremap = 0; - else error->all(FLERR,"Illegal fix box/relax command"); + else error->all(FLERR,"Illegal fix box/relax dilate command: {} unkown", arg[iarg+1]); iarg += 2; } else if (strcmp(arg[iarg],"vmax") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax vmax", error); vmax = utils::numeric(FLERR,arg[iarg+1],false,lmp); + if (vmax <= 0.0) error->all(FLERR,"Fix box/relax vmax value {} must be > 0", vmax); iarg += 2; } else if (strcmp(arg[iarg],"nreset") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax nreset", error); nreset_h0 = utils::inumeric(FLERR,arg[iarg+1],false,lmp); - if (nreset_h0 < 0) error->all(FLERR,"Illegal fix box/relax command"); + if (nreset_h0 < 0) error->all(FLERR,"Fix box/relax nreset value {} must be >= 0", nreset_h0); iarg += 2; } else if (strcmp(arg[iarg],"scalexy") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax scalexy", error); scalexy = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scalexz") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax scalexz", error); scalexz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"scaleyz") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "fix box/relax scaleyz", error); scaleyz = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; } else if (strcmp(arg[iarg],"fixedpoint") == 0) { - if (iarg+4 > narg) error->all(FLERR,"Illegal fix box/relax command"); + if (iarg+4 > narg) utils::missing_cmd_args(FLERR, "fix box/relax fixedpoint", error); fixedpoint[0] = utils::numeric(FLERR,arg[iarg+1],false,lmp); fixedpoint[1] = utils::numeric(FLERR,arg[iarg+2],false,lmp); fixedpoint[2] = utils::numeric(FLERR,arg[iarg+3],false,lmp); iarg += 4; - } else error->all(FLERR,"Illegal fix box/relax command"); + } else error->all(FLERR,"Unknown fix box/relax keyword {}", arg[iarg]); } if (p_flag[0]) box_change |= BOX_CHANGE_X; @@ -245,61 +243,55 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : // require periodicity in tensile dimension if (p_flag[0] && domain->xperiodic == 0) - error->all(FLERR,"Cannot use fix box/relax on a non-periodic dimension"); + error->all(FLERR,"Cannot use fix box/relax with non-periodic x dimension"); if (p_flag[1] && domain->yperiodic == 0) - error->all(FLERR,"Cannot use fix box/relax on a non-periodic dimension"); + error->all(FLERR,"Cannot use fix box/relax with non-periodic y dimension"); if (p_flag[2] && domain->zperiodic == 0) - error->all(FLERR,"Cannot use fix box/relax on a non-periodic dimension"); + error->all(FLERR,"Cannot use fix box/relax with non-periodic z dimension"); // require periodicity in 2nd dim of off-diagonal tilt component if (p_flag[3] && domain->zperiodic == 0) - error->all(FLERR, - "Cannot use fix box/relax on a 2nd non-periodic dimension"); + error->all(FLERR, "Cannot use fix box/relax yz with non-periodic z dimension"); if (p_flag[4] && domain->zperiodic == 0) - error->all(FLERR, - "Cannot use fix box/relax on a 2nd non-periodic dimension"); + error->all(FLERR, "Cannot use fix box/relax xz with non-periodic z dimension"); if (p_flag[5] && domain->yperiodic == 0) - error->all(FLERR, - "Cannot use fix box/relax on a 2nd non-periodic dimension"); + error->all(FLERR, "Cannot use fix box/relax xz with non-periodic y dimension"); if (scaleyz == 1 && domain->zperiodic == 0) - error->all(FLERR,"Cannot use fix box/relax " - "with tilt factor scaling on a 2nd non-periodic dimension"); + error->all(FLERR,"Cannot use fix box/relax with yz tilt factor scaling " + "with non-periodic z dimension"); if (scalexz == 1 && domain->zperiodic == 0) - error->all(FLERR,"Cannot use fix box/relax " - "with tilt factor scaling on a 2nd non-periodic dimension"); + error->all(FLERR,"Cannot use fix box/relax with xz tilt factor scaling " + "with non-periodic z dimension"); if (scalexy == 1 && domain->yperiodic == 0) - error->all(FLERR,"Cannot use fix box/relax " - "with tilt factor scaling on a 2nd non-periodic dimension"); + error->all(FLERR,"Cannot use fix box/relax with xy tilt factor scaling " + "with non-periodic y dimension"); if (p_flag[3] && scaleyz == 1) - error->all(FLERR,"Cannot use fix box/relax with " - "both relaxation and scaling on a tilt factor"); + error->all(FLERR,"Cannot use fix box/relax with both yz relaxation " + "and scaling on yz tilt factor"); if (p_flag[4] && scalexz == 1) - error->all(FLERR,"Cannot use fix box/relax with " - "both relaxation and scaling on a tilt factor"); + error->all(FLERR,"Cannot use fix box/relax with both xy relaxation " + "and scaling on xz tilt factor"); if (p_flag[5] && scalexy == 1) - error->all(FLERR,"Cannot use fix box/relax with " - "both relaxation and scaling on a tilt factor"); + error->all(FLERR,"Cannot use fix box/relax with both xy relaxation " + "and scaling on xy tilt factor"); if (!domain->triclinic && (p_flag[3] || p_flag[4] || p_flag[5])) - error->all(FLERR,"Can not specify Pxy/Pxz/Pyz in " - "fix box/relax with non-triclinic box"); + error->all(FLERR,"Cannot specify Pxy/Pxz/Pyz in fix box/relax with non-triclinic box"); if (pcouple == XYZ && dimension == 3 && (p_target[0] != p_target[1] || p_target[0] != p_target[2])) - error->all(FLERR,"Invalid fix box/relax pressure settings"); + error->all(FLERR,"Fix box/relax pressure for x, y, and z must be the same with couple xyz"); if (pcouple == XYZ && dimension == 2 && p_target[0] != p_target[1]) - error->all(FLERR,"Invalid fix box/relax pressure settings"); + error->all(FLERR,"Fix box/relax pressure for x and y must be the same with couple xyz"); if (pcouple == XY && p_target[0] != p_target[1]) - error->all(FLERR,"Invalid fix box/relax pressure settings"); + error->all(FLERR,"Fix box/relax pressure for x and y must be the same with couple xy"); if (pcouple == YZ && p_target[1] != p_target[2]) - error->all(FLERR,"Invalid fix box/relax pressure settings"); + error->all(FLERR,"Fix box/relax pressure for y and z must be the same with couple yz"); if (pcouple == XZ && p_target[0] != p_target[2]) - error->all(FLERR,"Invalid fix box/relax pressure settings"); - - if (vmax <= 0.0) error->all(FLERR,"Illegal fix box/relax command"); + error->all(FLERR,"Fix box/relax pressure for x and z must be the same with couple xz"); // pstyle = TRICLINIC if any off-diagonal term is controlled -> 6 dof // else pstyle = ISO if XYZ coupling or XY coupling in 2d -> 1 dof @@ -315,7 +307,7 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : // and thus its KE/temperature contribution should use group all id_temp = utils::strdup(std::string(id) + "_temp"); - modify->add_compute(fmt::format("{} all temp",id_temp)); + temperature = modify->add_compute(fmt::format("{} all temp",id_temp)); tflag = 1; // create a new compute pressure style (virial only) @@ -323,7 +315,7 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : // pass id_temp as 4th arg to pressure constructor id_press = utils::strdup(std::string(id) + "_press"); - modify->add_compute(fmt::format("{} all pressure {} virial",id_press, id_temp)); + pressure = modify->add_compute(fmt::format("{} all pressure {} virial", id_press, id_temp)); pflag = 1; dimension = domain->dimension; @@ -337,14 +329,14 @@ FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) : FixBoxRelax::~FixBoxRelax() { - delete [] rfix; + delete[] rfix; // delete temperature and pressure if fix created them if (tflag) modify->delete_compute(id_temp); if (pflag) modify->delete_compute(id_press); - delete [] id_temp; - delete [] id_press; + delete[] id_temp; + delete[] id_press; } /* ---------------------------------------------------------------------- */ @@ -362,15 +354,13 @@ void FixBoxRelax::init() { // set temperature and pressure ptrs - int icompute = modify->find_compute(id_temp); - if (icompute < 0) - error->all(FLERR,"Temperature ID for fix box/relax does not exist"); - temperature = modify->compute[icompute]; + temperature = modify->get_compute_by_id(id_temp); + if (!temperature) + error->all(FLERR,"Temperature compute ID {} for fix box/relax does not exist", id_temp); - icompute = modify->find_compute(id_press); - if (icompute < 0) - error->all(FLERR,"Pressure ID for fix box/relax does not exist"); - pressure = modify->compute[icompute]; + pressure = modify->get_compute_by_id(id_press); + if (!pressure) + error->all(FLERR,"Pressure compute ID {} for fix box/relax does not exist", id_press); pv2e = 1.0 / force->nktv2p; @@ -380,7 +370,7 @@ void FixBoxRelax::init() // detect if any rigid fixes exist so rigid bodies move when box is remapped // rfix[] = indices to each fix rigid - delete [] rfix; + delete[] rfix; nrigid = 0; rfix = nullptr; @@ -742,49 +732,49 @@ void FixBoxRelax::couple() int FixBoxRelax::modify_param(int narg, char **arg) { if (strcmp(arg[0],"temp") == 0) { - if (narg < 2) error->all(FLERR,"Illegal fix_modify command"); + if (narg < 2) utils::missing_cmd_args(FLERR, "fix_modify", error); if (tflag) { modify->delete_compute(id_temp); tflag = 0; } - delete [] id_temp; + delete[] id_temp; id_temp = utils::strdup(arg[1]); - int icompute = modify->find_compute(arg[1]); - if (icompute < 0) - error->all(FLERR,"Could not find fix_modify temperature ID"); - temperature = modify->compute[icompute]; + temperature = modify->get_compute_by_id(id_temp); + if (!temperature) + error->all(FLERR,"Could not find fix_modify {} temperature compute ID {}", id, id_temp); if (temperature->tempflag == 0) - error->all(FLERR, - "Fix_modify temperature ID does not compute temperature"); + error->all(FLERR, "Fix_modify {} temperature compute {} does not compute temperature", + id, id_temp); if (temperature->igroup != 0 && comm->me == 0) - error->warning(FLERR,"Temperature for fix modify is not for group all"); + error->warning(FLERR,"Temperature compute {} for fix modify {} is not for group all", + id, id_temp); // reset id_temp of pressure to new temperature ID - icompute = modify->find_compute(id_press); - if (icompute < 0) - error->all(FLERR,"Pressure ID for fix modify does not exist"); - modify->compute[icompute]->reset_extra_compute_fix(id_temp); + pressure = modify->get_compute_by_id(id_press); + if (!pressure) + error->all(FLERR,"Pressure compute ID {} for fix modify {} does not exist", id_press, id); + pressure->reset_extra_compute_fix(id_temp); return 2; } else if (strcmp(arg[0],"press") == 0) { - if (narg < 2) error->all(FLERR,"Illegal fix_modify command"); + if (narg < 2) utils::missing_cmd_args(FLERR, "fix_modify", error); if (pflag) { modify->delete_compute(id_press); pflag = 0; } - delete [] id_press; + delete[] id_press; id_press = utils::strdup(arg[1]); - int icompute = modify->find_compute(arg[1]); - if (icompute < 0) error->all(FLERR,"Could not find fix_modify pressure ID"); - pressure = modify->compute[icompute]; + pressure = modify->get_compute_by_id(id_press); + if (!pressure) + error->all(FLERR,"Could not find fix_modify {} compute pressure ID {}", id, id_press); if (pressure->pressflag == 0) - error->all(FLERR,"Fix_modify pressure ID does not compute pressure"); + error->all(FLERR,"Fix_modify {} pressure compute {} does not compute pressure", id, id_press); return 2; } return 0; diff --git a/src/fix_spring_chunk.cpp b/src/fix_spring_chunk.cpp index 411f056645..7d316af50d 100644 --- a/src/fix_spring_chunk.cpp +++ b/src/fix_spring_chunk.cpp @@ -38,7 +38,7 @@ FixSpringChunk::FixSpringChunk(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg), idchunk(nullptr), idcom(nullptr), com0(nullptr), fcom(nullptr) { - if (narg != 6) error->all(FLERR,"Illegal fix spring/chunk command"); + if (narg != 6) utils::missing_cmd_args(FLERR, "fix spring/chunk", error); restart_global = 1; scalar_flag = 1; @@ -66,15 +66,14 @@ FixSpringChunk::~FixSpringChunk() // decrement lock counter in compute chunk/atom, it if still exists - int icompute = modify->find_compute(idchunk); - if (icompute >= 0) { - cchunk = dynamic_cast( modify->compute[icompute]); + cchunk = dynamic_cast(modify->get_compute_by_id(idchunk)); + if (cchunk) { cchunk->unlock(this); cchunk->lockcount--; } - delete [] idchunk; - delete [] idcom; + delete[] idchunk; + delete[] idcom; } /* ---------------------------------------------------------------------- */ @@ -94,24 +93,19 @@ void FixSpringChunk::init() { // current indices for idchunk and idcom - int icompute = modify->find_compute(idchunk); - if (icompute < 0) - error->all(FLERR,"Chunk/atom compute does not exist for fix spring/chunk"); - cchunk = dynamic_cast( modify->compute[icompute]); - if (strcmp(cchunk->style,"chunk/atom") != 0) - error->all(FLERR,"Fix spring/chunk does not use chunk/atom compute"); + cchunk = dynamic_cast(modify->get_compute_by_id(idchunk)); + if (!cchunk) + error->all(FLERR,"Chunk/atom compute {} does not exist or is not chunk/atom style", idchunk); - icompute = modify->find_compute(idcom); - if (icompute < 0) - error->all(FLERR,"Com/chunk compute does not exist for fix spring/chunk"); - ccom = dynamic_cast( modify->compute[icompute]); - if (strcmp(ccom->style,"com/chunk") != 0) - error->all(FLERR,"Fix spring/chunk does not use com/chunk compute"); + ccom = dynamic_cast(modify->get_compute_by_id(idcom)); + if (!ccom) + error->all(FLERR,"Com/chunk compute {} does not exist or is not com/chunk style", idcom); // check that idchunk is consistent with ccom->idchunk - if (strcmp(idchunk,ccom->idchunk) != 0) - error->all(FLERR,"Fix spring chunk chunkID not same as comID chunkID"); + if (ccom && (strcmp(idchunk,ccom->idchunk) != 0)) + error->all(FLERR,"Fix spring/chunk chunk ID {} not the same as compute com/chunk chunk ID {}", + idchunk, ccom->idchunk); if (utils::strmatch(update->integrate_style,"^respa")) { ilevel_respa = (dynamic_cast( update->integrate))->nlevels-1; @@ -268,21 +262,18 @@ void FixSpringChunk::restart(char *buf) memory->destroy(com0); memory->destroy(fcom); - int icompute = modify->find_compute(idchunk); - if (icompute < 0) - error->all(FLERR,"Chunk/atom compute does not exist for fix spring/chunk"); - cchunk = dynamic_cast( modify->compute[icompute]); - if (strcmp(cchunk->style,"chunk/atom") != 0) - error->all(FLERR,"Fix spring/chunk does not use chunk/atom compute"); + cchunk = dynamic_cast(modify->get_compute_by_id(idchunk)); + if (!cchunk) + error->all(FLERR,"Chunk/atom compute {} does not exist or is not chunk/atom style", idchunk); + nchunk = cchunk->setup_chunks(); cchunk->compute_ichunk(); memory->create(com0,nchunk,3,"spring/chunk:com0"); memory->create(fcom,nchunk,3,"spring/chunk:fcom"); - printf("restart chunks:%d computed chunks: %d\n",n,nchunk); if (n != nchunk) { if (comm->me == 0) - error->warning(FLERR,"Number of chunks has changed. Cannot use restart"); + error->warning(FLERR,"Number of chunks changed from {} to {}. Cannot use restart", n, nchunk); memory->destroy(com0); memory->destroy(fcom); nchunk = 1; diff --git a/src/fmt/format.h b/src/fmt/format.h index 7c607dbd30..49b7fb6d3f 100644 --- a/src/fmt/format.h +++ b/src/fmt/format.h @@ -1625,7 +1625,9 @@ auto snprintf_float(T value, int precision, float_specs specs, template using convert_float_result = - conditional_t::value || sizeof(T) == sizeof(double), + conditional_t::value || + std::numeric_limits::digits == + std::numeric_limits::digits, double, T>; template diff --git a/src/thermo.cpp b/src/thermo.cpp index c4a914e3a3..518deab618 100644 --- a/src/thermo.cpp +++ b/src/thermo.cpp @@ -629,7 +629,7 @@ void Thermo::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg], "colname") == 0) { if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "thermo_modify colname", error); if (strcmp(arg[iarg + 1], "default") == 0) { - for (auto item : keyword_user) item.clear(); + for (auto &item : keyword_user) item.clear(); iarg += 2; } else { if (iarg + 3 > narg) utils::missing_cmd_args(FLERR, "thermo_modify colname", error); @@ -658,7 +658,7 @@ void Thermo::modify_params(int narg, char **arg) format_int_user.clear(); format_bigint_user.clear(); format_float_user.clear(); - for (auto item : format_column_user) item.clear(); + for (auto &item : format_column_user) item.clear(); iarg += 2; continue; } @@ -747,7 +747,7 @@ void Thermo::allocate() int i = 0; key2col.clear(); - for (auto item : utils::split_words(line)) { key2col[item] = i++; } + for (const auto &item : utils::split_words(line)) { key2col[item] = i++; } } /* ---------------------------------------------------------------------- diff --git a/unittest/formats/test_dump_atom.cpp b/unittest/formats/test_dump_atom.cpp index 12dd8bee8a..0140b1a9e4 100644 --- a/unittest/formats/test_dump_atom.cpp +++ b/unittest/formats/test_dump_atom.cpp @@ -21,7 +21,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include #include +#include using ::testing::Eq; @@ -108,6 +110,22 @@ public: END_HIDE_OUTPUT(); return fmt::format("{}.txt", binary_file); } + + std::vector extract_items(const std::string &file, const std::string &item) + { + std::string match = fmt::format("^ITEM: {}$", item); + std::vector values; + + std::ifstream dump(file); + for (std::string buffer; std::getline(dump, buffer); /* */) { + buffer = utils::trim(buffer); + if (utils::strmatch(buffer, match)) { + std::getline(dump, buffer); + values.push_back(buffer); + } + } + return values; + } }; TEST_F(DumpAtomTest, run0) @@ -680,8 +698,185 @@ TEST_F(DumpAtomTest, binary_write_dump) delete_file(reference); delete_file(dump_file); } + +//------------------------------------------------------------------------------------------------- +// dump_modify +//------------------------------------------------------------------------------------------------- + +TEST_F(DumpAtomTest, delay) +{ + auto dump_file = dump_filename("delay"); + BEGIN_HIDE_OUTPUT(); + command("dump id all atom 10 " + dump_file); + command("dump_modify id delay 20"); + command("run 50 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + std::vector expected, values; + values = extract_items(dump_file, "TIMESTEP"); + expected = {"20", "30", "40", "50"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + delete_file(dump_file); } +TEST_F(DumpAtomTest, colname) +{ + auto dump_file = dump_filename("colname"); + BEGIN_HIDE_OUTPUT(); + command("group one id 1"); + command("dump id one atom 10 " + dump_file); + command("run 5 post no"); + command("dump_modify id colname id AtomID colname 3 x-scaled colname -1 z-scaled"); + command("run 10 post no"); + command("dump_modify id colname default"); + command("run 10 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + std::vector expected, values; + values = extract_items(dump_file, "ATOMS id type xs ys zs"); + expected = {"1 1 0 0 0", "1 1 0 0 0"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + values = extract_items(dump_file, "ATOMS AtomID type x-scaled ys z-scaled"); + expected = {"1 1 0 0 0"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + delete_file(dump_file); +} + +TEST_F(DumpAtomTest, units_time) +{ + auto dump_file = dump_filename("units_time"); + BEGIN_HIDE_OUTPUT(); + command("dump id all atom 10 " + dump_file); + command("dump_modify id units yes time yes"); + command("run 30 post no"); + command("timestep 0.01"); + command("run 30 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + std::vector expected, values; + values = extract_items(dump_file, "TIME"); + expected = {"0", "0.05", "0.1", "0.15", "0.25", "0.35", "0.45"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + values = extract_items(dump_file, "UNITS"); + expected = {"lj"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + delete_file(dump_file); +} + +TEST_F(DumpAtomTest, every) +{ + auto dump_file = dump_filename("every"); + BEGIN_HIDE_OUTPUT(); + command("dump id all atom 10 " + dump_file); + command("run 20 post no"); + command("dump_modify id every 5"); + command("run 15 post no"); + command("dump_modify id every 10"); + command("run 25 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + std::vector expected, values; + values = extract_items(dump_file, "TIMESTEP"); + expected = {"0", "10", "20", "25", "30", "35", "40", "50", "60"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + delete_file(dump_file); + + BEGIN_HIDE_OUTPUT(); + command("reset_timestep 0"); + command("dump id all atom 1 " + dump_file); + command("variable next equal (step+1)*(step+1)"); + command("dump_modify id every v_next"); + command("run 50 post no"); + command("variable next equal logfreq(10,7,10)"); + command("dump_modify id every v_next"); + command("run 100 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + values = extract_items(dump_file, "TIMESTEP"); + expected = {"1", "4", "25", "60", "70", "100"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + delete_file(dump_file); +} + +TEST_F(DumpAtomTest, every_time) +{ + auto dump_file = dump_filename("every_time"); + BEGIN_HIDE_OUTPUT(); + command("dump id all atom 10 " + dump_file); + command("dump_modify id every/time 0.1"); + command("run 40 post no"); + command("timestep 0.01"); + command("run 20 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + std::vector expected, values; + values = extract_items(dump_file, "TIMESTEP"); + expected = {"0", "20", "40", "50", "60"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + delete_file(dump_file); +} + +TEST_F(DumpAtomTest, header) +{ + auto dump_file = dump_filename("header"); + BEGIN_HIDE_OUTPUT(); + command("reset_timestep 5"); + command("dump id all atom 10 " + dump_file); + command("dump_modify id first no header yes"); + command("run 40 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + std::vector expected, values; + values = extract_items(dump_file, "TIMESTEP"); + expected = {"10", "20", "30", "40"}; + ASSERT_EQ(values.size(), expected.size()); + for (int i = 0; i < expected.size(); ++i) + ASSERT_THAT(values[i], Eq(expected[i])); + + BEGIN_HIDE_OUTPUT(); + command("dump id all atom 10 " + dump_file); + command("dump_modify id header no"); + command("run 40 post no"); + command("undump id"); + END_HIDE_OUTPUT(); + + values = extract_items(dump_file, "TIMESTEP"); + ASSERT_EQ(values.size(), 0); + delete_file(dump_file); +} +} // namespace LAMMPS_NS + int main(int argc, char **argv) { MPI_Init(&argc, &argv); diff --git a/unittest/python/python-pizza.py b/unittest/python/python-pizza.py index 745816d8e1..fd28ff9129 100644 --- a/unittest/python/python-pizza.py +++ b/unittest/python/python-pizza.py @@ -9,7 +9,15 @@ DEFAULT_STYLE_EXAMPLE_LOG=os.path.join('melt', 'log.*.melt.g++.1') MULTI_STYLE_EXAMPLE_LOG=os.path.join('peptide', 'log.27Nov18.peptide.g++.1') sys.path.insert(1,PIZZA_DIR) -import dump +# dump class uses NumPy, so only load and test dump if NumPy is available +has_numpy = False +try: + import numpy + has_numpy = True + import dump +except: + pass + import log class Logfiles(unittest.TestCase): @@ -112,6 +120,7 @@ class PythonDump(unittest.TestCase): def tearDown(self): del self.lmp + @unittest.skipIf(not has_numpy,"Missing the NumPy python module") def testDumpCustom(self): dumpfile = os.path.join(os.path.abspath('.'), 'dump.custom') self.lmp.command('shell cd ' + os.environ['TEST_INPUT_DIR'])