diff --git a/doc/src/Developer_utils.rst b/doc/src/Developer_utils.rst index 9c6ef67945..aceecd7a46 100644 --- a/doc/src/Developer_utils.rst +++ b/doc/src/Developer_utils.rst @@ -211,6 +211,9 @@ Convenience functions .. doxygenfunction:: logmesg(LAMMPS *lmp, const std::string &mesg) :project: progguide +.. doxygenfunction:: errorurl + :project: progguide + .. doxygenfunction:: flush_buffers(LAMMPS *lmp) :project: progguide diff --git a/doc/src/Errors.rst b/doc/src/Errors.rst index 5975c22c41..3e8ebc7f8e 100644 --- a/doc/src/Errors.rst +++ b/doc/src/Errors.rst @@ -11,6 +11,7 @@ them. :maxdepth: 1 Errors_common + Errors_details Errors_bugs Errors_debug Errors_messages diff --git a/doc/src/Errors_details.rst b/doc/src/Errors_details.rst new file mode 100644 index 0000000000..70fe0e90ff --- /dev/null +++ b/doc/src/Errors_details.rst @@ -0,0 +1,27 @@ +Detailed discussion of errors and warnings +========================================== + +Many errors or warnings are self-explanatory and thus straightforward to +resolve. However, there are also cases, where there is no single cause +and explanation, where LAMMPS can only detect symptoms of an error but +not the exact cause, or where the explanation needs to be more detailed than +what can be fit into a message printed by the program. The following are +discussions of such cases. + +.. _err0001: + +Unknown identifier in data file +------------------------------- + +This error happens when LAMMPS encounters a line of text in an unexpected format +while reading a data file. This is most commonly cause by inconsistent header and +section data. The header section informs LAMMPS how many entries or lines are expected in the +various sections (like Atoms, Masses, Pair Coeffs, *etc.*\ ) of the data file. +If there is a mismatch, LAMMPS will either keep reading beyond the end of a section +or stop reading before the section has ended. + +Such a mismatch can happen unexpectedly when the first line of the data +is *not* a comment as required by the format. That would result in +LAMMPS expecting, for instance, 0 atoms because the "atoms" header line +is treated as a comment. + diff --git a/doc/src/fix_nve.rst b/doc/src/fix_nve.rst index da2184c99f..dc17f844cd 100644 --- a/doc/src/fix_nve.rst +++ b/doc/src/fix_nve.rst @@ -35,6 +35,10 @@ consistent with the microcanonical ensemble (NVE) provided there are (full) periodic boundary conditions and no other "manipulations" of the system (e.g. fixes that modify forces or velocities). +This fix invokes the velocity form of the +Störmer-Verlet time integration algorithm (velocity-Verlet). Other +time integration options can be invoked using the :doc:`run_style ` command. + ---------- .. include:: accel_styles.rst @@ -57,7 +61,7 @@ Restrictions Related commands """""""""""""""" -:doc:`fix nvt `, :doc:`fix npt ` +:doc:`fix nvt `, :doc:`fix npt `, :doc:`run_style ` Default """"""" diff --git a/doc/src/group.rst b/doc/src/group.rst index 1720ecfe1a..9d93e949f9 100644 --- a/doc/src/group.rst +++ b/doc/src/group.rst @@ -258,11 +258,17 @@ assignment is made at the beginning of the minimization, but not during the iterations of the minimizer. The point in the timestep at which atoms are assigned to a dynamic -group is after the initial stage of velocity Verlet time integration -has been performed, and before neighbor lists or forces are computed. -This is the point in the timestep where atom positions have just -changed due to the time integration, so the region criterion should be -accurate, if applied. +group is after interatomic forces have been computed, but before any +fixes which alter forces or otherwise update the system have been +invoked. This means that atom positions have been updated, neighbor +lists and ghost atoms are current, and both intermolecular and +intramolecular forces have been calculated based on the new +coordinates. Thus the region criterion, if applied, should be +accurate. Also, any computes invoked by an atom-style variable should +use updated information for that timestep, e.g. potential energy/atom +or coordination number/atom. Similarly, fixes or computes which are +invoked after that point in the timestep, should operate on the new +group of atoms. .. note:: diff --git a/doc/src/run_style.rst b/doc/src/run_style.rst index fd63c82b90..8becbec671 100644 --- a/doc/src/run_style.rst +++ b/doc/src/run_style.rst @@ -67,7 +67,8 @@ Description Choose the style of time integrator used for molecular dynamics simulations performed by LAMMPS. -The *verlet* style is a standard velocity-Verlet integrator. +The *verlet* style is the velocity form of the +Störmer-Verlet time integration algorithm (velocity-Verlet) ---------- diff --git a/src/INTEL/verlet_lrt_intel.cpp b/src/INTEL/verlet_lrt_intel.cpp index 0d8eb2e468..4102510c66 100644 --- a/src/INTEL/verlet_lrt_intel.cpp +++ b/src/INTEL/verlet_lrt_intel.cpp @@ -215,7 +215,7 @@ void VerletLRTIntel::run(int n) int n_pre_neighbor = modify->n_pre_neighbor; int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; - int n_post_force = modify->n_post_force; + int n_post_force = modify->n_post_force_any; int n_end_of_step = modify->n_end_of_step; if (atom->sortfreq > 0) sortflag = 1; diff --git a/src/KOKKOS/dynamical_matrix_kokkos.cpp b/src/KOKKOS/dynamical_matrix_kokkos.cpp index dc180a1743..7b85a3766d 100644 --- a/src/KOKKOS/dynamical_matrix_kokkos.cpp +++ b/src/KOKKOS/dynamical_matrix_kokkos.cpp @@ -159,7 +159,7 @@ void DynamicalMatrixKokkos::update_force() { int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; - int n_post_force = modify->n_post_force; + int n_post_force = modify->n_post_force_any; lmp->kokkos->auto_sync = 0; diff --git a/src/KOKKOS/third_order_kokkos.cpp b/src/KOKKOS/third_order_kokkos.cpp index 2aeb9152a1..56c9295e70 100644 --- a/src/KOKKOS/third_order_kokkos.cpp +++ b/src/KOKKOS/third_order_kokkos.cpp @@ -160,7 +160,7 @@ void ThirdOrderKokkos::update_force() { int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; - int n_post_force = modify->n_post_force; + int n_post_force = modify->n_post_force_any; lmp->kokkos->auto_sync = 0; diff --git a/src/KOKKOS/verlet_kokkos.cpp b/src/KOKKOS/verlet_kokkos.cpp index 2d142edd83..1816415b47 100644 --- a/src/KOKKOS/verlet_kokkos.cpp +++ b/src/KOKKOS/verlet_kokkos.cpp @@ -271,7 +271,7 @@ void VerletKokkos::run(int n) int n_post_neighbor = modify->n_post_neighbor; int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; - int n_post_force = modify->n_post_force; + int n_post_force = modify->n_post_force_any; int n_end_of_step = modify->n_end_of_step; lmp->kokkos->auto_sync = 0; diff --git a/src/MC/fix_atom_swap.cpp b/src/MC/fix_atom_swap.cpp index 2f8cd64169..a231a94990 100644 --- a/src/MC/fix_atom_swap.cpp +++ b/src/MC/fix_atom_swap.cpp @@ -532,7 +532,7 @@ double FixAtomSwap::energy_full() if (force->kspace) force->kspace->compute(eflag, vflag); - if (modify->n_post_force) modify->post_force(vflag); + if (modify->n_post_force_any) modify->post_force(vflag); update->eflag_global = update->ntimestep; double total_energy = c_pe->compute_scalar(); diff --git a/src/MC/fix_charge_regulation.cpp b/src/MC/fix_charge_regulation.cpp index a5a2eaff82..81f722bb6c 100644 --- a/src/MC/fix_charge_regulation.cpp +++ b/src/MC/fix_charge_regulation.cpp @@ -1129,7 +1129,7 @@ double FixChargeRegulation::energy_full() { if (force->kspace) force->kspace->compute(eflag, vflag); if (modify->n_pre_reverse) modify->pre_reverse(eflag,vflag); - if (modify->n_post_force) modify->post_force(vflag); + if (modify->n_post_force_any) modify->post_force(vflag); update->eflag_global = update->ntimestep; double total_energy = c_pe->compute_scalar(); diff --git a/src/MC/fix_gcmc.cpp b/src/MC/fix_gcmc.cpp index f6ed234c07..835d049bc6 100644 --- a/src/MC/fix_gcmc.cpp +++ b/src/MC/fix_gcmc.cpp @@ -2321,7 +2321,7 @@ double FixGCMC::energy_full() // but Modify::pre_reverse() is needed for INTEL if (modify->n_pre_reverse) modify->pre_reverse(eflag,vflag); - if (modify->n_post_force) modify->post_force(vflag); + if (modify->n_post_force_any) modify->post_force(vflag); // NOTE: all fixes with energy_global_flag set and which // operate at pre_force() or post_force() diff --git a/src/MC/fix_mol_swap.cpp b/src/MC/fix_mol_swap.cpp index c93f0093a8..c23ceb7d36 100644 --- a/src/MC/fix_mol_swap.cpp +++ b/src/MC/fix_mol_swap.cpp @@ -390,7 +390,7 @@ double FixMolSwap::energy_full() if (force->kspace) force->kspace->compute(eflag,vflag); - if (modify->n_post_force) modify->post_force(vflag); + if (modify->n_post_force_any) modify->post_force(vflag); update->eflag_global = update->ntimestep; double total_energy = c_pe->compute_scalar(); diff --git a/src/OPENMP/respa_omp.cpp b/src/OPENMP/respa_omp.cpp index c6500185ad..93eb3c41ef 100644 --- a/src/OPENMP/respa_omp.cpp +++ b/src/OPENMP/respa_omp.cpp @@ -77,7 +77,7 @@ void RespaOMP::setup(int flag) mesg += fmt::format(" {}:{}", ilevel + 1, step[ilevel]); mesg += "\n r-RESPA fixes :"; - for (int l = 0; l < modify->n_post_force_respa; ++l) { + for (int l = 0; l < modify->n_post_force_respa_any; ++l) { Fix *f = modify->get_fix_by_index(modify->list_post_force_respa[l]); if (f->respa_level >= 0) mesg += fmt::format(" {}:{}[{}]", MIN(f->respa_level + 1, nlevels), f->style, f->id); @@ -420,7 +420,7 @@ void RespaOMP::recurse(int ilevel) timer->stamp(Timer::COMM); } timer->stamp(); - if (modify->n_post_force_respa) + if (modify->n_post_force_respa_any) modify->post_force_respa(vflag,ilevel,iloop); modify->final_integrate_respa(ilevel,iloop); timer->stamp(Timer::MODIFY); diff --git a/src/PHONON/dynamical_matrix.cpp b/src/PHONON/dynamical_matrix.cpp index 3723a7a467..8f667f51f2 100644 --- a/src/PHONON/dynamical_matrix.cpp +++ b/src/PHONON/dynamical_matrix.cpp @@ -431,7 +431,7 @@ void DynamicalMatrix::update_force() force_clear(); int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; - int n_post_force = modify->n_post_force; + int n_post_force = modify->n_post_force_any; if (n_pre_force) { modify->pre_force(vflag); diff --git a/src/PHONON/third_order.cpp b/src/PHONON/third_order.cpp index 76d90c65bd..bbd6818b95 100644 --- a/src/PHONON/third_order.cpp +++ b/src/PHONON/third_order.cpp @@ -487,7 +487,7 @@ void ThirdOrder::update_force() neighbor->ago = 0; if (modify->get_fix_by_id("package_intel")) neighbor->decide(); force_clear(); - int n_post_force = modify->n_post_force; + int n_post_force = modify->n_post_force_any; int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; diff --git a/src/REPLICA/verlet_split.cpp b/src/REPLICA/verlet_split.cpp index 95cd54119c..661b86129c 100644 --- a/src/REPLICA/verlet_split.cpp +++ b/src/REPLICA/verlet_split.cpp @@ -300,7 +300,7 @@ void VerletSplit::run(int n) int n_pre_neighbor = modify->n_pre_neighbor; int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; - int n_post_force = modify->n_post_force; + int n_post_force = modify->n_post_force_any; int n_end_of_step = modify->n_end_of_step; if (atom->sortfreq > 0) sortflag = 1; diff --git a/src/compute_cluster_atom.cpp b/src/compute_cluster_atom.cpp index 07a0c700ee..c2cb2816d3 100644 --- a/src/compute_cluster_atom.cpp +++ b/src/compute_cluster_atom.cpp @@ -30,8 +30,6 @@ using namespace LAMMPS_NS; -enum { CLUSTER, MASK, COORDS }; - /* ---------------------------------------------------------------------- */ ComputeClusterAtom::ComputeClusterAtom(LAMMPS *lmp, int narg, char **arg) : @@ -44,7 +42,7 @@ ComputeClusterAtom::ComputeClusterAtom(LAMMPS *lmp, int narg, char **arg) : peratom_flag = 1; size_peratom_cols = 0; - comm_forward = 3; + comm_forward = 1; nmax = 0; } @@ -117,22 +115,6 @@ void ComputeClusterAtom::compute_peratom() numneigh = list->numneigh; firstneigh = list->firstneigh; - // if update->post_integrate set: - // a dynamic group in FixGroup is invoking a variable with this compute - // thus ghost atom coords need to be up-to-date after initial_integrate() - - if (update->post_integrate) { - commflag = COORDS; - comm->forward_comm(this); - } - - // if group is dynamic, insure ghost atom masks are current - - if (group->dynamic[igroup]) { - commflag = MASK; - comm->forward_comm(this); - } - // every atom starts in its own cluster, with clusterID = atomID tagint *tag = atom->tag; @@ -153,7 +135,6 @@ void ComputeClusterAtom::compute_peratom() // iterate until no changes in my atoms // then check if any proc made changes - commflag = CLUSTER; double **x = atom->x; int change, done, anychange; @@ -209,25 +190,9 @@ int ComputeClusterAtom::pack_forward_comm(int n, int *list, double *buf, int /*p int i, j, m; m = 0; - if (commflag == CLUSTER) { - for (i = 0; i < n; i++) { - j = list[i]; - buf[m++] = clusterID[j]; - } - } else if (commflag == MASK) { - int *mask = atom->mask; - for (i = 0; i < n; i++) { - j = list[i]; - buf[m++] = ubuf(mask[j]).d; - } - } else if (commflag == COORDS) { - double **x = atom->x; - for (i = 0; i < n; i++) { - j = list[i]; - buf[m++] = x[j][0]; - buf[m++] = x[j][1]; - buf[m++] = x[j][2]; - } + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = clusterID[j]; } return m; @@ -241,19 +206,7 @@ void ComputeClusterAtom::unpack_forward_comm(int n, int first, double *buf) m = 0; last = first + n; - if (commflag == CLUSTER) { - for (i = first; i < last; i++) clusterID[i] = buf[m++]; - } else if (commflag == MASK) { - int *mask = atom->mask; - for (i = first; i < last; i++) mask[i] = (int) ubuf(buf[m++]).i; - } else if (commflag == COORDS) { - double **x = atom->x; - for (i = first; i < last; i++) { - x[i][0] = buf[m++]; - x[i][1] = buf[m++]; - x[i][2] = buf[m++]; - } - } + for (i = first; i < last; i++) clusterID[i] = buf[m++]; } /* ---------------------------------------------------------------------- diff --git a/src/compute_coord_atom.cpp b/src/compute_coord_atom.cpp index f41a4eee4b..7bf749b1be 100644 --- a/src/compute_coord_atom.cpp +++ b/src/compute_coord_atom.cpp @@ -259,14 +259,16 @@ void ComputeCoordAtom::compute_peratom() j = jlist[jj]; j &= NEIGHMASK; - jtype = type[j]; - delx = xtmp - x[j][0]; - dely = ytmp - x[j][1]; - delz = ztmp - x[j][2]; - rsq = delx * delx + dely * dely + delz * delz; - if (rsq < cutsq) { - for (m = 0; m < ncol; m++) - if (jtype >= typelo[m] && jtype <= typehi[m]) count[m] += 1.0; + if (mask[j] & jgroupbit) { + jtype = type[j]; + delx = xtmp - x[j][0]; + dely = ytmp - x[j][1]; + delz = ztmp - x[j][2]; + rsq = delx * delx + dely * dely + delz * delz; + if (rsq < cutsq) { + for (m = 0; m < ncol; m++) + if (jtype >= typelo[m] && jtype <= typehi[m]) count[m] += 1.0; + } } } } diff --git a/src/fix_group.cpp b/src/fix_group.cpp index 163f46b781..00deab3ef8 100644 --- a/src/fix_group.cpp +++ b/src/fix_group.cpp @@ -43,6 +43,8 @@ FixGroup::FixGroup(LAMMPS *lmp, int narg, char **arg) : gbit = group->bitmask[group->find(dgroupid)]; gbitinverse = group->inversemask[group->find(dgroupid)]; + comm_forward = 1; + // process optional args regionflag = 0; @@ -107,8 +109,6 @@ FixGroup::~FixGroup() int FixGroup::setmask() { int mask = 0; - mask |= POST_INTEGRATE; - mask |= POST_INTEGRATE_RESPA; return mask; } @@ -144,31 +144,6 @@ void FixGroup::init() if (iprop < 0 || cols) error->all(FLERR, "Group dynamic command custom property vector does not exist"); } - - // warn if any FixGroup is not at tail end of all post_integrate fixes - - Fix **fix = modify->fix; - int *fmask = modify->fmask; - int nfix = modify->nfix; - - int n = 0; - for (int i = 0; i < nfix; i++) - if (POST_INTEGRATE & fmask[i]) n++; - int warn = 0; - for (int i = 0; i < nfix; i++) { - if (POST_INTEGRATE & fmask[i]) { - for (int j = i + 1; j < nfix; j++) { - if (POST_INTEGRATE & fmask[j]) { - if (strstr(fix[j]->id, "GROUP_") != fix[j]->id) warn = 1; - } - } - } - } - - if (warn && comm->me == 0) - error->warning(FLERR, - "One or more dynamic groups may not be " - "updated at correct point in timestep"); } /* ---------------------------------------------------------------------- @@ -182,7 +157,7 @@ void FixGroup::setup(int /*vflag*/) /* ---------------------------------------------------------------------- */ -void FixGroup::post_integrate() +void FixGroup::post_force(int /*vflag*/) { // only assign atoms to group on steps that are multiples of nevery @@ -191,9 +166,9 @@ void FixGroup::post_integrate() /* ---------------------------------------------------------------------- */ -void FixGroup::post_integrate_respa(int ilevel, int /*iloop*/) +void FixGroup::post_force_respa(int vflag, int ilevel, int /*iloop*/) { - if (ilevel == nlevels_respa - 1) post_integrate(); + if (ilevel == nlevels_respa - 1) post_force(vflag); } /* ---------------------------------------------------------------------- */ @@ -203,22 +178,20 @@ void FixGroup::set_group() int nlocal = atom->nlocal; // invoke atom-style variable if defined - // set post_integrate flag to 1, then unset after - // this is for any compute to check if it needs to - // operate differently due to invocation this early in timestep - // e.g. perform ghost comm update due to atoms having just moved + // NOTE: after variable invocation could reset invoked computes to not-invoked + // this would avoid an issue where other post-force fixes + // change the compute result since it will not be re-invoked at end-of-step, + // e.g. if compute pe/atom includes pe contributions from fixes double *var = nullptr; int *ivector = nullptr; double *dvector = nullptr; if (varflag) { - update->post_integrate = 1; modify->clearstep_compute(); - memory->create(var, nlocal, "fix/group:varvalue"); + memory->create(var, nlocal, "fix/group:var"); input->variable->compute_atom(ivar, igroup, var, 1, 0); modify->addstep_compute(update->ntimestep + nevery); - update->post_integrate = 0; } // set ptr to custom atom vector @@ -232,8 +205,6 @@ void FixGroup::set_group() // set mask for each atom // only in group if in parent group, in region, variable is non-zero - // if compute, fix, etc needs updated masks of ghost atoms, - // it must do forward_comm() to update them double **x = atom->x; int *mask = atom->mask; @@ -258,6 +229,41 @@ void FixGroup::set_group() } if (varflag) memory->destroy(var); + + // insure ghost atom masks are also updated + + comm->forward_comm(this); +} + +/* ---------------------------------------------------------------------- */ + +int FixGroup::pack_forward_comm(int n, int *list, double *buf, int /*pbc_flag*/, int * /*pbc*/) +{ + int i, j, m; + + int *mask = atom->mask; + + m = 0; + for (i = 0; i < n; i++) { + j = list[i]; + buf[m++] = ubuf(mask[j]).d; + } + + return m; +} + +/* ---------------------------------------------------------------------- */ + +void FixGroup::unpack_forward_comm(int n, int first, double *buf) +{ + int i, m, last; + + m = 0; + last = first + n; + + int *mask = atom->mask; + + for (i = first; i < last; i++) mask[i] = (int) ubuf(buf[m++]).i; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_group.h b/src/fix_group.h index fb9d361b4e..ea8af4e5d5 100644 --- a/src/fix_group.h +++ b/src/fix_group.h @@ -31,8 +31,10 @@ class FixGroup : public Fix { int setmask() override; void init() override; void setup(int) override; - void post_integrate() override; - void post_integrate_respa(int, int) override; + void post_force(int) override; + void post_force_respa(int, int, int) override; + int pack_forward_comm(int, int *, double *, int, int *) override; + void unpack_forward_comm(int, int, double *) override; void *extract(const char *, int &) override; private: diff --git a/src/modify.cpp b/src/modify.cpp index fa4c8fd01b..90b911b9ab 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -51,20 +51,22 @@ Modify::Modify(LAMMPS *lmp) : Pointers(lmp) nfix = maxfix = 0; n_initial_integrate = n_post_integrate = 0; n_pre_exchange = n_pre_neighbor = n_post_neighbor = 0; - n_pre_force = n_pre_reverse = n_post_force = 0; + n_pre_force = n_pre_reverse = n_post_force_any = 0; n_final_integrate = n_end_of_step = 0; n_energy_couple = n_energy_global = n_energy_atom = 0; n_initial_integrate_respa = n_post_integrate_respa = 0; - n_pre_force_respa = n_post_force_respa = n_final_integrate_respa = 0; + n_pre_force_respa = n_post_force_respa_any = n_final_integrate_respa = 0; n_min_pre_exchange = n_min_pre_force = n_min_pre_reverse = 0; n_min_post_force = n_min_energy = 0; + n_timeflag = -1; fix = nullptr; fmask = nullptr; list_initial_integrate = list_post_integrate = nullptr; list_pre_exchange = list_pre_neighbor = list_post_neighbor = nullptr; - list_pre_force = list_pre_reverse = list_post_force = nullptr; + list_pre_force = list_pre_reverse = nullptr; + list_post_force = list_post_force_group = nullptr; list_final_integrate = list_end_of_step = nullptr; list_energy_couple = list_energy_global = list_energy_atom = nullptr; list_initial_integrate_respa = list_post_integrate_respa = nullptr; @@ -139,6 +141,7 @@ Modify::~Modify() delete[] list_pre_force; delete[] list_pre_reverse; delete[] list_post_force; + delete[] list_post_force_group; delete[] list_final_integrate; delete[] list_end_of_step; delete[] list_energy_couple; @@ -221,6 +224,7 @@ void Modify::init() list_init(PRE_FORCE, n_pre_force, list_pre_force); list_init(PRE_REVERSE, n_pre_reverse, list_pre_reverse); list_init(POST_FORCE, n_post_force, list_post_force); + list_init_post_force_group(n_post_force_group, list_post_force_group); list_init(FINAL_INTEGRATE, n_final_integrate, list_final_integrate); list_init_end_of_step(END_OF_STEP, n_end_of_step, list_end_of_step); list_init_energy_couple(n_energy_couple, list_energy_couple); @@ -241,6 +245,11 @@ void Modify::init() list_init(MIN_POST_FORCE, n_min_post_force, list_min_post_force); list_init(MIN_ENERGY, n_min_energy, list_min_energy); + // two post_force_any counters used by integrators add in post_force_group + + n_post_force_any = n_post_force + n_post_force_group; + n_post_force_respa_any = n_post_force_respa + n_post_force_group; + // create list of computes that store invocation times list_init_compute(); @@ -441,11 +450,19 @@ void Modify::pre_reverse(int eflag, int vflag) /* ---------------------------------------------------------------------- post_force call, only for relevant fixes + first call any instances of fix GROUP if they exist + they are not in n_post_force count ------------------------------------------------------------------------- */ void Modify::post_force(int vflag) { - for (int i = 0; i < n_post_force; i++) fix[list_post_force[i]]->post_force(vflag); + if (n_post_force_group) { + for (int i = 0; i < n_post_force_group; i++) fix[list_post_force_group[i]]->post_force(vflag); + } + + if (n_post_force) { + for (int i = 0; i < n_post_force; i++) fix[list_post_force[i]]->post_force(vflag); + } } /* ---------------------------------------------------------------------- @@ -585,12 +602,20 @@ void Modify::pre_force_respa(int vflag, int ilevel, int iloop) /* ---------------------------------------------------------------------- rRESPA post_force call, only for relevant fixes + first call any instances of fix GROUP if they exist ------------------------------------------------------------------------- */ void Modify::post_force_respa(int vflag, int ilevel, int iloop) { - for (int i = 0; i < n_post_force_respa; i++) - fix[list_post_force_respa[i]]->post_force_respa(vflag, ilevel, iloop); + if (n_post_force_group) { + for (int i = 0; i < n_post_force_group; i++) + fix[list_post_force_group[i]]->post_force_respa(vflag, ilevel, iloop); + } + + if (n_post_force_respa) { + for (int i = 0; i < n_post_force_respa; i++) + fix[list_post_force_respa[i]]->post_force_respa(vflag, ilevel, iloop); + } } /* ---------------------------------------------------------------------- @@ -1716,6 +1741,25 @@ void Modify::list_init_energy_atom(int &n, int *&list) if (fix[i]->energy_peratom_flag && fix[i]->thermo_energy) list[n++] = i; } +/* ---------------------------------------------------------------------- + create list of fix indices for fix GROUP + are invoked first in post_force() or post_force_respa() +------------------------------------------------------------------------- */ + +void Modify::list_init_post_force_group(int &n, int *&list) +{ + delete[] list; + + n = 0; + for (int i = 0; i < nfix; i++) + if (strcmp(fix[i]->style, "GROUP") == 0) n++; + list = new int[n]; + + n = 0; + for (int i = 0; i < nfix; i++) + if (strcmp(fix[i]->style, "GROUP") == 0) list[n++] = i; +} + /* ---------------------------------------------------------------------- create list of compute indices for computes which store invocation times ------------------------------------------------------------------------- */ diff --git a/src/modify.h b/src/modify.h index 0ad0d1fb33..303ec65124 100644 --- a/src/modify.h +++ b/src/modify.h @@ -33,11 +33,11 @@ class Modify : protected Pointers { public: int n_initial_integrate, n_post_integrate, n_pre_exchange; int n_pre_neighbor, n_post_neighbor; - int n_pre_force, n_pre_reverse, n_post_force; + int n_pre_force, n_pre_reverse, n_post_force_any; int n_final_integrate, n_end_of_step; int n_energy_couple, n_energy_global, n_energy_atom; int n_initial_integrate_respa, n_post_integrate_respa; - int n_pre_force_respa, n_post_force_respa, n_final_integrate_respa; + int n_pre_force_respa, n_post_force_respa_any, n_final_integrate_respa; int n_min_pre_exchange, n_min_pre_neighbor, n_min_post_neighbor; int n_min_pre_force, n_min_pre_reverse, n_min_post_force, n_min_energy; @@ -147,11 +147,16 @@ class Modify : protected Pointers { double memory_usage(); protected: + // internal fix counts + + int n_post_force, n_post_force_group, n_post_force_respa; + // lists of fixes to apply at different stages of timestep int *list_initial_integrate, *list_post_integrate; int *list_pre_exchange, *list_pre_neighbor, *list_post_neighbor; - int *list_pre_force, *list_pre_reverse, *list_post_force; + int *list_pre_force, *list_pre_reverse; + int *list_post_force, *list_post_force_group; int *list_final_integrate, *list_end_of_step; int *list_energy_couple, *list_energy_global, *list_energy_atom; int *list_initial_integrate_respa, *list_post_integrate_respa; @@ -187,6 +192,8 @@ class Modify : protected Pointers { void list_init_energy_couple(int &, int *&); void list_init_energy_global(int &, int *&); void list_init_energy_atom(int &, int *&); + void list_init_post_force_group(int &, int *&); + void list_init_post_force_respa_group(int &, int *&); void list_init_dofflag(int &, int *&); void list_init_compute(); diff --git a/src/read_data.cpp b/src/read_data.cpp index 5505b5a5a0..b77394bcb3 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -744,9 +744,9 @@ void ReadData::command(int narg, char **arg) break; } if (i == nfix) - error->all(FLERR,"Unknown identifier in data file: {}",keyword); + error->all(FLERR,"Unknown identifier in data file: {}{}", keyword, utils::errorurl(1)); - } else error->all(FLERR,"Unknown identifier in data file: {}",keyword); + } else error->all(FLERR,"Unknown identifier in data file: {}{}", keyword, utils::errorurl(1)); parse_keyword(0); } diff --git a/src/respa.cpp b/src/respa.cpp index 9aca8a9427..5a715d737f 100644 --- a/src/respa.cpp +++ b/src/respa.cpp @@ -372,7 +372,7 @@ void Respa::setup(int flag) mesg += fmt::format(" {}:{}", ilevel + 1, step[ilevel]); mesg += "\n r-RESPA fixes :"; - for (int l = 0; l < modify->n_post_force_respa; ++l) { + for (int l = 0; l < modify->n_post_force_respa_any; ++l) { Fix *f = modify->get_fix_by_index(modify->list_post_force_respa[l]); if (f->respa_level >= 0) mesg += fmt::format(" {}:{}[{}]", MIN(f->respa_level + 1, nlevels), f->style, f->id); @@ -704,7 +704,7 @@ void Respa::recurse(int ilevel) timer->stamp(Timer::COMM); } timer->stamp(); - if (modify->n_post_force_respa) modify->post_force_respa(vflag, ilevel, iloop); + if (modify->n_post_force_respa_any) modify->post_force_respa(vflag, ilevel, iloop); modify->final_integrate_respa(ilevel, iloop); timer->stamp(Timer::MODIFY); } diff --git a/src/update.cpp b/src/update.cpp index 3870f6d38e..297053e39d 100644 --- a/src/update.cpp +++ b/src/update.cpp @@ -60,7 +60,6 @@ Update::Update(LAMMPS *lmp) : Pointers(lmp) beginstep = endstep = 0; restrict_output = 0; setupflag = 0; - post_integrate = 0; multireplica = 0; eflag_global = vflag_global = -1; diff --git a/src/update.h b/src/update.h index afcafb87cb..c3e79b72a2 100644 --- a/src/update.h +++ b/src/update.h @@ -35,7 +35,6 @@ class Update : protected Pointers { int max_eval; // max force evaluations for minimizer int restrict_output; // 1 if output should not write dump/restart int setupflag; // set when setup() is computing forces - int post_integrate; // 1 if now at post_integrate() in timestep int multireplica; // 1 if min across replicas, else 0 int dt_default; // 1 if dt is at default value, else 0 diff --git a/src/utils.cpp b/src/utils.cpp index 91804055fd..0d0bc91227 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -137,6 +137,11 @@ void utils::fmtargs_logmesg(LAMMPS *lmp, fmt::string_view format, fmt::format_ar } } +std::string utils::errorurl(int errorcode) +{ + return fmt::format("\nFor more information see https://docs.lammps.org/err{:04d}", errorcode); +} + void utils::flush_buffers(LAMMPS *lmp) { if (lmp->screen) fflush(lmp->screen); diff --git a/src/utils.h b/src/utils.h index fc39eef3c0..4dbb2fb8bb 100644 --- a/src/utils.h +++ b/src/utils.h @@ -74,6 +74,18 @@ namespace utils { void logmesg(LAMMPS *lmp, const std::string &mesg); + /*! Return text redirecting the user to a specific paragraph in the manual + * + * The LAMMPS manual contains detailed detailed explanations for errors and + * warnings where a simple error message may not be sufficient. These can + * be reached through URLs with a numeric code. This function creates the + * corresponding text to be included into the error message that redirects + * the user to that URL. + * + * \param errorcode number pointing to a paragraph in the manual */ + + std::string errorurl(int errorcode); + /*! Flush output buffers * * This function calls fflush() on screen and logfile FILE pointers diff --git a/src/verlet.cpp b/src/verlet.cpp index 342dc3d951..15e1ab0800 100644 --- a/src/verlet.cpp +++ b/src/verlet.cpp @@ -237,7 +237,7 @@ void Verlet::run(int n) int n_post_neighbor = modify->n_post_neighbor; int n_pre_force = modify->n_pre_force; int n_pre_reverse = modify->n_pre_reverse; - int n_post_force = modify->n_post_force; + int n_post_force_any = modify->n_post_force_any; int n_end_of_step = modify->n_end_of_step; if (atom->sortfreq > 0) sortflag = 1; @@ -344,7 +344,7 @@ void Verlet::run(int n) // force modifications, final time integration, diagnostics - if (n_post_force) modify->post_force(vflag); + if (n_post_force_any) modify->post_force(vflag); modify->final_integrate(); if (n_end_of_step) modify->end_of_step(); timer->stamp(Timer::MODIFY);