From f039c00442ea4e43ce3e031368b04015f41bdeb4 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Wed, 27 Jul 2022 17:13:46 -0600 Subject: [PATCH 01/22] add dump skip option --- src/AMOEBA/pair_amoeba.cpp | 10 ++ src/MANYBODY/pair_eam.cpp | 11 ++ src/dump.cpp | 98 +++++++++----- src/dump.h | 4 + src/fix_pair.cpp | 271 +++++++++++++++++++++++++++++++++++++ src/fix_pair.h | 54 ++++++++ 6 files changed, 417 insertions(+), 31 deletions(-) create mode 100644 src/fix_pair.cpp create mode 100644 src/fix_pair.h diff --git a/src/AMOEBA/pair_amoeba.cpp b/src/AMOEBA/pair_amoeba.cpp index be5f9c73df..1d37b3c85b 100644 --- a/src/AMOEBA/pair_amoeba.cpp +++ b/src/AMOEBA/pair_amoeba.cpp @@ -2077,6 +2077,16 @@ void *PairAmoeba::extract(const char *str, int &dim) if (strcmp(str,"opbend_pentic") == 0) return (void *) &opbend_pentic; if (strcmp(str,"opbend_sextic") == 0) return (void *) &opbend_sextic; + // requests from FixPair + + if (strcmp(str,"uind") == 0) { + dim = 3; + return (void *) uind; + } else if (strcmp(str,"uinp") == 0) { + dim = 3; + return (void *) uinp; + } + return nullptr; } diff --git a/src/MANYBODY/pair_eam.cpp b/src/MANYBODY/pair_eam.cpp index 834c71a947..031d41387b 100644 --- a/src/MANYBODY/pair_eam.cpp +++ b/src/MANYBODY/pair_eam.cpp @@ -933,5 +933,16 @@ void *PairEAM::extract(const char *str, int &dim) { dim = 2; if (strcmp(str,"scale") == 0) return (void *) scale; + + // requests from FixPair + + if (strcmp(str,"rho") == 0) { + dim = 0; + return (void *) rho; + } else if (strcmp(str,"fp") == 0) { + dim = 0; + return (void *) fp; + } + return nullptr; } diff --git a/src/dump.cpp b/src/dump.cpp index 9a8bac052a..3062763d89 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -20,11 +20,13 @@ #include "error.h" #include "fix.h" #include "group.h" +#include "input.h" #include "irregular.h" #include "memory.h" #include "modify.h" #include "output.h" #include "update.h" +#include "variable.h" #include @@ -87,6 +89,9 @@ Dump::Dump(LAMMPS *lmp, int /*narg*/, char **arg) : Pointers(lmp) delay_flag = 0; write_header_flag = 1; + skipflag = 0; + skipvar = nullptr; + maxfiles = -1; numfiles = 0; fileidx = 0; @@ -165,6 +170,8 @@ Dump::~Dump() delete[] refresh; + delete[] skipvar; + // format_column_user is deallocated by child classes that use it memory->destroy(buf); @@ -298,6 +305,15 @@ void Dump::init() else error->all(FLERR,"Dump could not find refresh compute ID"); } + // if skipflag, check skip variable + + if (skipflag) { + skipindex = input->variable->find(skipvar); + if (skipindex < 0) error->all(FLERR,"Dump skip variable not found"); + if (!input->variable->equalstyle(skipindex)) + error->all(FLERR,"Variable for dump skip is invalid style"); + } + // preallocation for PBC copies if requested if (pbcflag && atom->nlocal > maxpbc) pbc_allocate(); @@ -359,6 +375,15 @@ void Dump::write() nme = count(); + // if skip condition is defined and met, just return + // do it after count() b/c that invoked computes + // NOTE: for multifile, will have already opened file + + if (skipflag) { + double value = input->variable->compute_equal(skipindex); + if (value != 0.0) return; + } + // ntotal = total # of dump lines in snapshot // nmax = max # of dump lines on any proc @@ -1044,6 +1069,12 @@ void Dump::modify_params(int narg, char **arg) append_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; + } else if (strcmp(arg[iarg],"balance") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); + if (nprocs > 1) + balance_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); + iarg += 2; + } else if (strcmp(arg[iarg],"buffer") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); buffer_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); @@ -1051,6 +1082,32 @@ void Dump::modify_params(int narg, char **arg) error->all(FLERR,"Dump_modify buffer yes not allowed for this style"); iarg += 2; + } else if (strcmp(arg[iarg],"colname") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); + if (strcmp(arg[iarg+1],"default") == 0) { + for (auto item : keyword_user) item.clear(); + iarg += 2; + } else { + if (iarg+3 > narg) error->all(FLERR,"Illegal dump_modify command"); + int icol = -1; + if (utils::is_integer(arg[iarg + 1])) { + icol = utils::inumeric(FLERR,arg[iarg + 1],false,lmp); + if (icol < 0) icol = keyword_user.size() + icol + 1; + icol--; + } else { + try { + icol = key2col.at(arg[iarg + 1]); + } catch (std::out_of_range &) { + icol = -1; + } + } + if ((icol < 0) || (icol >= (int)keyword_user.size())) + error->all(FLERR, "Incorrect dump_modify arguments: {} {} {}", + arg[iarg], arg[iarg+1], arg[iarg+2]); + keyword_user[icol] = arg[iarg+2]; + iarg += 3; + } + } else if (strcmp(arg[iarg],"delay") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); delaystep = utils::bnumeric(FLERR,arg[iarg+1],false,lmp); @@ -1131,31 +1188,6 @@ void Dump::modify_params(int narg, char **arg) flush_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; - } else if (strcmp(arg[iarg],"colname") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (strcmp(arg[iarg+1],"default") == 0) { - for (auto item : keyword_user) item.clear(); - iarg += 2; - } else { - if (iarg+3 > narg) error->all(FLERR,"Illegal dump_modify command"); - int icol = -1; - if (utils::is_integer(arg[iarg + 1])) { - icol = utils::inumeric(FLERR,arg[iarg + 1],false,lmp); - if (icol < 0) icol = keyword_user.size() + icol + 1; - icol--; - } else { - try { - icol = key2col.at(arg[iarg + 1]); - } catch (std::out_of_range &) { - icol = -1; - } - } - if ((icol < 0) || (icol >= (int)keyword_user.size())) - error->all(FLERR, "Incorrect dump_modify arguments: {} {} {}", - arg[iarg], arg[iarg+1], arg[iarg+2]); - keyword_user[icol] = arg[iarg+2]; - iarg += 3; - } } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); @@ -1212,6 +1244,7 @@ void Dump::modify_params(int narg, char **arg) fileidx = 0; } iarg += 2; + } else if (strcmp(arg[iarg],"nfile") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (!multiproc) @@ -1254,6 +1287,15 @@ void Dump::modify_params(int narg, char **arg) pbcflag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; + } else if (strcmp(arg[iarg],"skip") == 0) { + if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); + skipflag = 1; + if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) { + delete[] skipvar; + skipvar = utils::strdup(&arg[iarg+1][2]); + } else error->all(FLERR,"Illegal dump_modify command"); + iarg += 2; + } else if (strcmp(arg[iarg],"sort") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); if (strcmp(arg[iarg+1],"off") == 0) sort_flag = 0; @@ -1274,12 +1316,6 @@ void Dump::modify_params(int narg, char **arg) } iarg += 2; - } else if (strcmp(arg[iarg],"balance") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); - if (nprocs > 1) - balance_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); - iarg += 2; - } else if (strcmp(arg[iarg],"time") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); time_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); diff --git a/src/dump.h b/src/dump.h index 90866a3567..ecff27f7dd 100644 --- a/src/dump.h +++ b/src/dump.h @@ -91,6 +91,10 @@ class Dump : protected Pointers { char *refresh; // compute ID to invoke refresh() on int irefresh; // index of compute + int skipflag; // 1 if skip condition defined + char *skipvar; // name of variable to check for skip condition + int skipindex; // index of skip variable + char boundstr[9]; // encoding of boundary flags char *format; // format string for the file write diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp new file mode 100644 index 0000000000..4171164cac --- /dev/null +++ b/src/fix_pair.cpp @@ -0,0 +1,271 @@ +// clang-format off +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include "fix_pair.h" + +#include "atom.h" +#include "dump.h" +#include "error.h" +#include "force.h" +#include "fix.h" +#include "input.h" +#include "memory.h" +#include "pair.h" +#include "output.h" +#include "variable.h" +#include "update.h" +#include "variable.h" + +#include + +using namespace LAMMPS_NS; +using namespace FixConst; + +/* ---------------------------------------------------------------------- */ + +FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : + Fix(lmp, narg, arg) +{ + if (narg < 7) error->all(FLERR,"Illegal fix pair command"); + + nevery = utils::inumeric(FLERR,arg[3],false,lmp); + if (nevery < 1) error->all(FLERR,"Illegal fix pair command"); + + int n = strlen(arg[4]) + 1; + pairname = new char[n]; + strcpy(pairname,arg[4]); + pstyle = force->pair_match(pairname,1,0); + if (pstyle == nullptr) error->all(FLERR,"Fix pair pair style not found"); + + nfield = (narg-5) / 2; + fieldname = new char*[nfield]; + trigger = new int[nfield]; + + nfield = 0; + int iarg = 5; + + while (iarg < narg) { + if (iarg+2 > narg) error->all(FLERR,"Illegal fix pair command"); + n = strlen(arg[iarg]) + 1; + fieldname[nfield] = new char[n]; + strcpy(fieldname[nfield],arg[iarg]); + int flag = utils::inumeric(FLERR,arg[iarg+1],true,lmp); + if (flag == 0) trigger[nfield] = 0; + else if (flag == 1) trigger[nfield] = 1; + else error->all(FLERR,"Illegal fix pair command"); + nfield++; + iarg += 2; + } + + // set trigger names = fieldname + "_flag" + + triggername = new char*[nfield]; + + for (int ifield = 0; ifield < nfield; ifield++) { + if (trigger[ifield] == 0) triggername[ifield] = nullptr; + else { + n = strlen(fieldname[ifield]) + 6; + triggername[ifield] = new char[n]; + sprintf(triggername[ifield],"%s_flag",fieldname[ifield]); + } + } + + // extract all fields just to get number of per-atom values, ptrs may be NULL + // also check if triggername can be extracted as a scalar value + + triggerptr = new int*[nfield]; + + int columns,dim; + ncols = 0; + + for (int ifield = 0; ifield < nfield; ifield++) { + void *tmp = pstyle->extract(fieldname[ifield],columns); + //if (!tmp) + // error->all(FLERR,"Fix pair pair style cannot extract {}",fieldname[ifield]); + if (columns) ncols += columns; + else ncols++; + if (trigger[ifield]) { + triggerptr[ifield] = (int *) pstyle->extract(triggername[ifield],dim); + if (!triggerptr[ifield]) + error->all(FLERR,"Fix pair pair style cannot extract {}", + triggername[ifield]); + if (dim) error->all(FLERR,"Fix pair pair style {} is not a scalar", + triggername[ifield]); + } + } + + // settings + // freq = 1 since vector/array always have values + // allows user to specify nevery = 0 for a dump + // which this fix outputs whenever it wants + + peratom_flag = 1; + if (ncols == 1) size_peratom_cols = 0; + else size_peratom_cols = ncols; + peratom_freq = nevery; + + // perform initial allocation of atom-based array + // register with Atom class + + vector = nullptr; + array = nullptr; + grow_arrays(atom->nmax); + atom->add_callback(Atom::GROW); + + // zero the vector/array since dump may access it on timestep 0 + // zero the vector/array since a variable may access it before first run + + int nlocal = atom->nlocal; + + if (ncols == 0) { + for (int i = 0; i < nlocal; i++) + vector[i] = 0.0; + } else { + for (int i = 0; i < nlocal; i++) + for (int m = 0; m < ncols; m++) + array[i][m] = 0.0; + } +} + +/* ---------------------------------------------------------------------- */ + +FixPair::~FixPair() +{ + // unregister callbacks to this fix from Atom class + + atom->delete_callback(id,Atom::GROW); + + delete [] pairname; + for (int ifield = 0; ifield < nfield; ifield++) { + delete [] fieldname[ifield]; + delete [] triggername[ifield]; + } + + delete [] fieldname; + delete [] trigger; + delete [] triggername; + delete [] triggerptr; + + if (ncols == 0) memory->destroy(vector); + else memory->destroy(array); +} + +/* ---------------------------------------------------------------------- */ + +int FixPair::setmask() +{ + int mask = 0; + mask |= PRE_FORCE; + mask |= POST_FORCE; + return mask; +} + +/* ---------------------------------------------------------------------- */ + +void FixPair::init() +{ + // make sure pair style still exists + + pstyle = force->pair_match(pairname,1,0); + if (pstyle == nullptr) error->all(FLERR,"Fix pair pair style not found"); +} + +/* ---------------------------------------------------------------------- + trigger pair style computation on steps which are multiples of Nevery +------------------------------------------------------------------------- */ + +void FixPair::pre_force(int /*vflag*/) +{ + if (update->ntimestep % nevery) return; + + // set pair style triggers + + for (int ifield = 0; ifield < nfield; ifield++) + if (trigger[ifield]) *(triggerptr[ifield]) = 1; +} + +/* ---------------------------------------------------------------------- + extract results from pair style +------------------------------------------------------------------------- */ + +void FixPair::post_force(int /*vflag*/) +{ + if (update->ntimestep % nevery) return; + + // extract pair style fields one by one + // store their values in this fix + + int nlocal = atom->nlocal; + + int icol = 0; + int columns; + + for (int ifield = 0; ifield < nfield; ifield++) { + void *pvoid = pstyle->extract(fieldname[ifield],columns); + if (pvoid == nullptr) + error->all(FLERR,"Fix pair pair style cannot extract {}",fieldname[ifield]); + + if (columns == 0) { + double *pvector = (double *) pvoid; + if (ncols == 0) { + for (int i = 0; i < nlocal; i++) + vector[i] = pvector[i]; + } else { + for (int i = 0; i < nlocal; i++) + array[i][icol] = pvector[i]; + } + icol++; + + } else { + double **parray = (double **) pvoid; + for (int i = 0; i < nlocal; i++) + for (int m = 0; m < columns; m++) { + array[i][icol] = parray[i][m]; + icol++; + } + } + } + + // unset pair style triggers + + for (int ifield = 0; ifield < nfield; ifield++) + if (trigger[ifield]) *(triggerptr[ifield]) = 0; +} + +/* ---------------------------------------------------------------------- + allocate atom-based vector or array +------------------------------------------------------------------------- */ + +void FixPair::grow_arrays(int nmax) +{ + if (ncols == 0) { + memory->grow(vector,nmax,"store/state:vector"); + vector_atom = vector; + } else { + memory->grow(array,nmax,ncols,"store/state:array"); + array_atom = array; + } +} + +/* ---------------------------------------------------------------------- + memory usage of local atom-based vector or array +------------------------------------------------------------------------- */ + +double FixPair::memory_usage() +{ + double bytes = 0.0; + if (ncols == 0) bytes += (double)atom->nmax * sizeof(double); + else bytes += (double)atom->nmax*ncols * sizeof(double); + return bytes; +} diff --git a/src/fix_pair.h b/src/fix_pair.h new file mode 100644 index 0000000000..3e32b11544 --- /dev/null +++ b/src/fix_pair.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef FIX_CLASS +// clang-format off +FixStyle(pair,FixPair); +// clang-format on +#else + +#ifndef LMP_FIX_PAIR_H +#define LMP_FIX_PAIR_H + +#include "fix.h" + +namespace LAMMPS_NS { + +class FixPair : public Fix { + public: + FixPair(class LAMMPS *, int, char **); + ~FixPair() override; + int setmask() override; + void init() override; + void pre_force(int) override; + void post_force(int) override; + + void grow_arrays(int) override; + double memory_usage() override; + + private: + int nevery,nfield,ncols; + char *pairname; + char **fieldname,**triggername; + int *trigger; + int **triggerptr; + + class Pair *pstyle; + double *vector; + double **array; +}; + +} // namespace LAMMPS_NS + +#endif +#endif From 348feddcb65d4c79bff3c6c1ce909ea1aab266f1 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Thu, 28 Jul 2022 12:45:20 -0600 Subject: [PATCH 02/22] new fix pair and dump_modify skip commands --- doc/src/Commands_all.rst | 4 +- doc/src/Commands_fix.rst | 1 + doc/src/compute_pair.rst | 4 +- doc/src/dump_modify.rst | 24 ++++++++- doc/src/fix.rst | 1 + doc/src/fix_pair.rst | 104 +++++++++++++++++++++++++++++++++++++ doc/src/pair_amoeba.rst | 12 +++++ doc/src/pair_eam.rst | 25 +++++++-- src/AMOEBA/pair_amoeba.cpp | 5 +- src/MANYBODY/pair_eam.cpp | 5 +- src/dump.cpp | 15 +++--- src/fix_pair.cpp | 27 +++++++--- src/fix_pair.h | 2 + 13 files changed, 206 insertions(+), 23 deletions(-) create mode 100644 doc/src/fix_pair.rst diff --git a/doc/src/Commands_all.rst b/doc/src/Commands_all.rst index 5e309c3ed0..fdde1f8e6c 100644 --- a/doc/src/Commands_all.rst +++ b/doc/src/Commands_all.rst @@ -15,7 +15,9 @@ General commands ================ -An alphabetic list of general LAMMPS commands. +An alphabetic list of general LAMMPS commands. Note that style +commands with many variants, can be more easily accessed via the small +table above. .. table_from_list:: :columns: 5 diff --git a/doc/src/Commands_fix.rst b/doc/src/Commands_fix.rst index cb61cbe17b..c5c2fb7cba 100644 --- a/doc/src/Commands_fix.rst +++ b/doc/src/Commands_fix.rst @@ -165,6 +165,7 @@ OPT. * :doc:`orient/fcc ` * :doc:`orient/eco ` * :doc:`pafi ` + * :doc:`pair ` * :doc:`phonon ` * :doc:`pimd ` * :doc:`planeforce ` diff --git a/doc/src/compute_pair.rst b/doc/src/compute_pair.rst index b43c4bd6d7..e399b61aba 100644 --- a/doc/src/compute_pair.rst +++ b/doc/src/compute_pair.rst @@ -93,7 +93,9 @@ Restrictions Related commands """""""""""""""" -:doc:`compute pe `, :doc:`compute bond ` +:doc:`compute pe `, :doc:`compute bond `, +:doc:`fix pair ` + Default """"""" diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index fd916beb4e..0dcb4f198f 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -17,7 +17,7 @@ Syntax * one or more keyword/value pairs may be appended * these keywords apply to various dump styles -* keyword = *append* or *at* or *balance* or *buffer* or *delay* or *element* or *every* or *every/time* or *fileper* or *first* or *flush* or *format* or *header* or *image* or *label* or *maxfiles* or *nfile* or *pad* or *pbc* or *precision* or *region* or *refresh* or *scale* or *sfactor* or *sort* or *tfactor* or *thermo* or *thresh* or *time* or *units* or *unwrap* +* keyword = *append* or *at* or *balance* or *buffer* or *delay* or *element* or *every* or *every/time* or *fileper* or *first* or *flush* or *format* or *header* or *image* or *label* or *maxfiles* or *nfile* or *pad* or *pbc* or *precision* or *region* or *refresh* or *scale* or *sfactor* or *skip* or *sort* or *tfactor* or *thermo* or *thresh* or *time* or *units* or *unwrap* .. parsed-literal:: @@ -65,6 +65,8 @@ Syntax *refresh* arg = c_ID = compute ID that supports a refresh operation *scale* arg = *yes* or *no* *sfactor* arg = coordinate scaling factor (> 0.0) + *skip* arg = v_name + v_name = variable with name which evaluates to non-zero (skip) or 0 *sort* arg = *off* or *id* or N or -N off = no sorting of per-atom lines within a snapshot id = sort per-atom lines by atom ID @@ -678,10 +680,28 @@ most effective when the typical magnitude of position data is between ---------- +The *skip* keyword can be used with all dump styles. It allows a dump +snapshot to be skipped (not written to the dump file), if a condition +is met. The condition is computed by an :doc:`equal-style variable +`, which should be specified as v_name, where name is the +variable name. If the variable evaulation returns a non-zero value, +then the dump snapshot is skipped. If it returns zero, the dump +proceeds as usual. Note that :doc:`equal-style variable ` +can contain Boolean operators which effectively evaluate as a true +(non-zero) or false (zero) result. + +The *skip* keyword can be useful for debugging purposes, e.g. to dump +only on a particular timestep. Or to limit output to conditions of +interest, e.g. only when the force on some atom exceeds a threshold +value. + +---------- + The *sort* keyword determines whether lines of per-atom output in a snapshot are sorted or not. A sort value of *off* means they will typically be written in indeterminate order, either in serial or -parallel. This is the case even in serial if the :doc:`atom_modify sort ` option is turned on, which it is by default, to +parallel. This is the case even in serial if the :doc:`atom_modify +sort ` option is turned on, which it is by default, to improve performance. A sort value of *id* means sort the output by atom ID. A sort value of N or -N means sort the output by the value in the Nth column of per-atom info in either ascending or descending diff --git a/doc/src/fix.rst b/doc/src/fix.rst index 2ec4437b39..acddb2f351 100644 --- a/doc/src/fix.rst +++ b/doc/src/fix.rst @@ -307,6 +307,7 @@ accelerated styles exist. * :doc:`orient/fcc ` - add grain boundary migration force for FCC * :doc:`orient/eco ` - add generalized grain boundary migration force * :doc:`pafi ` - constrained force averages on hyper-planes to compute free energies (PAFI) +* :doc:`pair ` - access per-atom info from pair styles * :doc:`phonon ` - calculate dynamical matrix from MD simulations * :doc:`pimd ` - Feynman path integral molecular dynamics * :doc:`planeforce ` - constrain atoms to move in a plane diff --git a/doc/src/fix_pair.rst b/doc/src/fix_pair.rst new file mode 100644 index 0000000000..c8734299d4 --- /dev/null +++ b/doc/src/fix_pair.rst @@ -0,0 +1,104 @@ +.. index:: fix pair + +fix pair command +======================= + +Syntax +"""""" + +.. parsed-literal:: + + fix ID group-ID pair N pairstyle name flag ... + +* ID, group-ID are documented in :doc:`fix ` command +* pair = style name of this fix command +* N = invoke this fix once every N timesteps +* pairstyle = name of pair style to extract info from (e.g. eam) +* one or more name/flag pairs can be listed +* name = name of quantity the pair style allows extraction of +* flag = 1 if pair style needs to be triggered to produce data for name, 0 if not + +Examples +"""""""" + +.. code-block:: LAMMPS + + fix request all pair 100 eam rho 0 + fix request all pair 100 amoeba uind 0 uinp 0 + + +Description +""""""""""" + +Extract per-atom quantities from a pair style and store them in this +fix so they can be accessed by other LAMMPS commands, e.g. by a +:doc:`dump ` command or by another :doc:`fix `, +:doc:`compute `, or :doc:`variable ` command. + +These are example use cases: + +* extract per-atom density from :doc:`pair_style eam ` to a dump file +* extract induced dipoles from :doc:`pair_style amoeba ` to a dump file +* extract accuracy metrics from a machine-learned potential to trigger output when +a condition is met (see the :doc:`dump_modify skip ` command) + +The *N* argument determines how often the fix is invoked. + +The *pairstyle* argument is the name of the pair style. It can be a +sub-style used in a :doc:`pair_style hybrid ` command. + +One or more *name/flag* pairs of arguments follow. Each *name* is a +per-atom quantity which the pair style must recognize as an extraction +request. See the doc pages for individual :doc:`pair_styles +` to see what fix pair requests (if any) they support. + +The *flag* setting determines whether this fix will also request that +the pair style compute the named quantity to be extracted. If the +quantity is always computed by the pair style, no request is needed; +specify *flag* = 0. If the quantity is not always computed (e.g. it +is expensive to calculate), then specify *flag* = 1. This fix will +then request the quantity only on timesteps it is needed. Again, see +the doc pages for individual :doc:`pair_styles ` to +determine which fix pair requests (if any) need to be triggered with a +*flag* = 1 setting. + +The per-atom data extracted from the pair style is stored by this fix +as either a per-atom vector or array. If there is only one *name* +argument specified and the pair style computes a single value for each +atom, then this fix stores it as a per-atom vector. Otherwise a +per-atom array is created, with its data in the order of the *name* +arguments. + +For example, :doc:`pair_style amoeba ` allows extraction +of two named quantities: "uind" and "uinp", both of which are +3-vectors for each atom, i.e. dipole moments. If this fix specifies +"uind" and "uinp" (in that order), then a 6-column per-atom array will +be created. Columns 1-3 will store the "uind" values; columns 4-6 +will store the "uinp" values. + +Restart, fix_modify, output, run start/stop, minimize info +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +No information about this fix is written to :doc:`binary restart files +`. None of the :doc:`fix_modify ` options are +relevant to this fix. + +As explained above, this fix produces a per-atom vector or array which +can be accessed by various :doc:`output commands `. If +an array is produced, the number of columns is the sum of the number +of per-atom quantities produced by each *name* argument requested from +the pair style. + +Restrictions +"""""""""""" +none + +Related commands +"""""""""""""""" + +:doc:`compute pair ` + +Default +""""""" + +none diff --git a/doc/src/pair_amoeba.rst b/doc/src/pair_amoeba.rst index a58eb2fabc..b41cb9815b 100644 --- a/doc/src/pair_amoeba.rst +++ b/doc/src/pair_amoeba.rst @@ -156,6 +156,18 @@ settings. ---------- +The *amoeba* and *hippo* pair styles support extraction of two +per-atom quantities by the :doc:`fix pair ` command. This +allows the quantities to be output to files by the :doc:`dump ` +or otherwise processed by other LAMMPS commamds. + +The names of the two quantites are "uind" and "uinp" for the induced +dipole moments for each atom. Neither quantity needs to be triggered +by the :doc:`fix pair ` command in order for these pair +styles to calculate it. + +---------- + Mixing, shift, table, tail correction, restart, rRESPA info """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/doc/src/pair_eam.rst b/doc/src/pair_eam.rst index fd05d7189e..4ba926362f 100644 --- a/doc/src/pair_eam.rst +++ b/doc/src/pair_eam.rst @@ -444,6 +444,18 @@ identical to the FS EAM files (see above). ---------- +The eam, eam/alloy, eam/fs, and eam/he pair styles support extraction +of two per-atom quantities by the :doc:`fix pair ` command. +This allows the quantities to be output to files by the :doc:`dump +` or otherwise processed by other LAMMPS commamds. + +The names of the two quantites are "rho" and "fp" for the density and +derivative of the embedding energy for each atom. Neither quantity +needs to be triggered by the :doc:`fix pair ` command in +order for these pair styles to calculate it. + +---------- + .. include:: accel_styles.rst ---------- @@ -459,21 +471,26 @@ a pair_coeff command with I != J arguments for the eam styles. This pair style does not support the :doc:`pair_modify ` shift, table, and tail options. -The eam pair styles do not write their information to :doc:`binary restart files `, since it is stored in tabulated potential files. -Thus, you need to re-specify the pair_style and pair_coeff commands in -an input script that reads a restart file. +The eam pair styles do not write their information to :doc:`binary +restart files `, since it is stored in tabulated potential +files. Thus, you need to re-specify the pair_style and pair_coeff +commands in an input script that reads a restart file. The eam pair styles can only be used via the *pair* keyword of the :doc:`run_style respa ` command. They do not support the *inner*, *middle*, *outer* keywords. + + + ---------- Restrictions """""""""""" All of these styles are part of the MANYBODY package. They are only -enabled if LAMMPS was built with that package. See the :doc:`Build package ` page for more info. +enabled if LAMMPS was built with that package. See the :doc:`Build +package ` page for more info. Related commands """""""""""""""" diff --git a/src/AMOEBA/pair_amoeba.cpp b/src/AMOEBA/pair_amoeba.cpp index 1d37b3c85b..8229684d29 100644 --- a/src/AMOEBA/pair_amoeba.cpp +++ b/src/AMOEBA/pair_amoeba.cpp @@ -2077,7 +2077,10 @@ void *PairAmoeba::extract(const char *str, int &dim) if (strcmp(str,"opbend_pentic") == 0) return (void *) &opbend_pentic; if (strcmp(str,"opbend_sextic") == 0) return (void *) &opbend_sextic; - // requests from FixPair + // peratom requests from FixPair + // return dim = # of quantites per atom + // 0 = per-atom vector + // 1 or more = # of columns in per-atom array if (strcmp(str,"uind") == 0) { dim = 3; diff --git a/src/MANYBODY/pair_eam.cpp b/src/MANYBODY/pair_eam.cpp index 031d41387b..2534386225 100644 --- a/src/MANYBODY/pair_eam.cpp +++ b/src/MANYBODY/pair_eam.cpp @@ -934,7 +934,10 @@ void *PairEAM::extract(const char *str, int &dim) dim = 2; if (strcmp(str,"scale") == 0) return (void *) scale; - // requests from FixPair + // peratom requests from FixPair + // return dim = # of quantites per atom + // 0 = per-atom vector + // 1 or more = # of columns in per-atom array if (strcmp(str,"rho") == 0) { dim = 0; diff --git a/src/dump.cpp b/src/dump.cpp index 3062763d89..13e3bcdfcc 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -345,11 +345,6 @@ void Dump::write() if (delay_flag && update->ntimestep < delaystep) return; - // if file per timestep, open new file - - if (multifile) openfile(); - if (fp) clearerr(fp); - // simulation box bounds if (domain->triclinic == 0) { @@ -376,14 +371,20 @@ void Dump::write() nme = count(); // if skip condition is defined and met, just return - // do it after count() b/c that invoked computes - // NOTE: for multifile, will have already opened file + // do this after count() b/c it invokes computes, + // so caller can trigger future invocation of needed computes if (skipflag) { double value = input->variable->compute_equal(skipindex); if (value != 0.0) return; } + // if file per timestep, open new file + // do this after skip check, so no file is opened if skip occurs + + if (multifile) openfile(); + if (fp) clearerr(fp); + // ntotal = total # of dump lines in snapshot // nmax = max # of dump lines on any proc diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp index 4171164cac..c4c81a4bda 100644 --- a/src/fix_pair.cpp +++ b/src/fix_pair.cpp @@ -81,18 +81,19 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : } } - // extract all fields just to get number of per-atom values, ptrs may be NULL + // extract all fields just to get number of per-atom values + // returned data ptr may be NULL, if pair style has not allocated field yet + // check for recognized field cannot be done until post_force() // also check if triggername can be extracted as a scalar value triggerptr = new int*[nfield]; - int columns,dim; + int dim; ncols = 0; for (int ifield = 0; ifield < nfield; ifield++) { - void *tmp = pstyle->extract(fieldname[ifield],columns); - //if (!tmp) - // error->all(FLERR,"Fix pair pair style cannot extract {}",fieldname[ifield]); + int columns = 0; // set in case fieldname not recognized by pstyle + void *pvoid = pstyle->extract(fieldname[ifield],columns); if (columns) ncols += columns; else ncols++; if (trigger[ifield]) { @@ -175,12 +176,26 @@ int FixPair::setmask() void FixPair::init() { - // make sure pair style still exists + // insure pair style still exists pstyle = force->pair_match(pairname,1,0); if (pstyle == nullptr) error->all(FLERR,"Fix pair pair style not found"); } +/* ---------------------------------------------------------------------- */ + +void FixPair::setup(int vflag) +{ + post_force(vflag); +} + +/* ---------------------------------------------------------------------- */ + +void FixPair::setup_pre_force(int vflag) +{ + pre_force(vflag); +} + /* ---------------------------------------------------------------------- trigger pair style computation on steps which are multiples of Nevery ------------------------------------------------------------------------- */ diff --git a/src/fix_pair.h b/src/fix_pair.h index 3e32b11544..a9927cf477 100644 --- a/src/fix_pair.h +++ b/src/fix_pair.h @@ -30,6 +30,8 @@ class FixPair : public Fix { ~FixPair() override; int setmask() override; void init() override; + void setup(int) override; + void setup_pre_force(int) override; void pre_force(int) override; void post_force(int) override; From a4f4efcea0e69b2fd6cca50746c33d3d759f3ead Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Thu, 28 Jul 2022 13:31:58 -0600 Subject: [PATCH 03/22] fix a couple typos and alphabetizing error --- doc/src/dump_modify.rst | 59 +++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index 0dcb4f198f..a1f12b9eb9 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -178,6 +178,28 @@ extra buffering. ---------- +The *colname* keyword can be used to change the default header keyword +for dump styles: *atom*, *custom*, and *cfg* and their compressed, ADIOS, +and MPIIO variants. The setting for *ID string* replaces the default +text with the provided string. *ID* can be a positive integer when it +represents the column number counting from the left, a negative integer +when it represents the column number from the right (i.e. -1 is the last +column/keyword), or a custom dump keyword (or compute, fix, property, or +variable reference) and then it replaces the string for that specific +keyword. For *atom* dump styles only the keywords "id", "type", "x", +"y", "z", "ix", "iy", "iz" can be accessed via string regardless of +whether scaled or unwrapped coordinates were enabled or disabled, and +it always assumes 8 columns for indexing regardless of whether image +flags are enabled or not. For dump style *cfg* only changes to the +"auxiliary" keywords (6th or later keyword) will become visible. + +The *colname* keyword can be used multiple times. If multiple *colname* +settings refer to the same keyword, the last setting has precedence. A +setting of *default* clears all previous settings, reverting all values +to their default names. + +---------- + The *delay* keyword applies to all dump styles. No snapshots will be output until the specified *Dstep* timestep or later. Specifying *Dstep* < 0 is the same as turning off the delay setting. This is a @@ -359,7 +381,7 @@ always occur if the current timestep is a multiple of $N$, the frequency specified in the :doc:`dump ` command or :doc:`dump_modify every ` command, including timestep 0. It will also always occur if the current simulation time is a multiple -of *Delta*, the time interval specified in the doc:`dump_modify +of *Delta*, the time interval specified in the :doc:`dump_modify every/time ` command. But if this is not the case, a dump snapshot will only be written if @@ -367,10 +389,10 @@ the setting of this keyword is *yes*\ . If it is *no*, which is the default, then it will not be written. Note that if the argument to the :doc:`dump_modify every -` doc:`dump_modify every/time ` commands is -a variable and not a numeric value, then specifying *first yes* is the -only way to write a dump snapshot on the first timestep after the dump -command is invoked. +` or doc:`dump_modify every/time ` commands +is a variable and not a numeric value, then specifying *first yes* is +the only way to write a dump snapshot on the first timestep after the +dump command is invoked. ---------- @@ -382,28 +404,6 @@ performed with dump style *xtc*\ . ---------- -The *colname* keyword can be used to change the default header keyword -for dump styles: *atom*, *custom*, and *cfg* and their compressed, ADIOS, -and MPIIO variants. The setting for *ID string* replaces the default -text with the provided string. *ID* can be a positive integer when it -represents the column number counting from the left, a negative integer -when it represents the column number from the right (i.e. -1 is the last -column/keyword), or a custom dump keyword (or compute, fix, property, or -variable reference) and then it replaces the string for that specific -keyword. For *atom* dump styles only the keywords "id", "type", "x", -"y", "z", "ix", "iy", "iz" can be accessed via string regardless of -whether scaled or unwrapped coordinates were enabled or disabled, and -it always assumes 8 columns for indexing regardless of whether image -flags are enabled or not. For dump style *cfg* only changes to the -"auxiliary" keywords (6th or later keyword) will become visible. - -The *colname* keyword can be used multiple times. If multiple *colname* -settings refer to the same keyword, the last setting has precedence. A -setting of *default* clears all previous settings, reverting all values -to their default names. - ----------- - The *format* keyword can be used to change the default numeric format output by the text-based dump styles: *atom*, *local*, *custom*, *cfg*, and *xyz* styles, and their MPIIO variants. Only the *line* or *none* @@ -747,8 +747,9 @@ are written to the dump file or included in the image. The possible attributes that can be tested for are the same as those that can be specified in the :doc:`dump custom ` command, with the exception of the *element* attribute, since it is not a numeric value. Note -that a different attributes can be used than those output by the :doc:`dump custom ` command. E.g. you can output the coordinates and -stress of atoms whose energy is above some threshold. +that a different attributes can be used than those output by the +:doc:`dump custom ` command. E.g. you can output the +coordinates and stress of atoms whose energy is above some threshold. If an atom-style variable is used as the attribute, then it can produce continuous numeric values or effective Boolean 0/1 values From 4de0944f8bb007c6b031045757770646c3d47ea0 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Thu, 28 Jul 2022 15:24:58 -0600 Subject: [PATCH 04/22] streamlined string ops --- src/fix_pair.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp index c4c81a4bda..fafc86d903 100644 --- a/src/fix_pair.cpp +++ b/src/fix_pair.cpp @@ -42,9 +42,7 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : nevery = utils::inumeric(FLERR,arg[3],false,lmp); if (nevery < 1) error->all(FLERR,"Illegal fix pair command"); - int n = strlen(arg[4]) + 1; - pairname = new char[n]; - strcpy(pairname,arg[4]); + pairname = utils::strdup(arg[4]); pstyle = force->pair_match(pairname,1,0); if (pstyle == nullptr) error->all(FLERR,"Fix pair pair style not found"); @@ -57,9 +55,7 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : while (iarg < narg) { if (iarg+2 > narg) error->all(FLERR,"Illegal fix pair command"); - n = strlen(arg[iarg]) + 1; - fieldname[nfield] = new char[n]; - strcpy(fieldname[nfield],arg[iarg]); + fieldname[nfield] = utils::strdup(arg[iarg]); int flag = utils::inumeric(FLERR,arg[iarg+1],true,lmp); if (flag == 0) trigger[nfield] = 0; else if (flag == 1) trigger[nfield] = 1; @@ -75,9 +71,8 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : for (int ifield = 0; ifield < nfield; ifield++) { if (trigger[ifield] == 0) triggername[ifield] = nullptr; else { - n = strlen(fieldname[ifield]) + 6; - triggername[ifield] = new char[n]; - sprintf(triggername[ifield],"%s_flag",fieldname[ifield]); + auto str = fmt::format("%s_flag", fieldname[ifield]); + triggername[nfield] = utils::strdup(str); } } From b8f4efcb6a703cbaf9f5451954b024a7afbf18c9 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Thu, 28 Jul 2022 16:53:39 -0600 Subject: [PATCH 05/22] pre-existing bug fix for delay option with dump computes for pe/virial --- src/dump.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/dump.cpp b/src/dump.cpp index 13e3bcdfcc..048a3712ab 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -341,10 +341,6 @@ void Dump::write() imageint *imagehold; double **xhold,**vhold; - // if timestep < delaystep, just return - - if (delay_flag && update->ntimestep < delaystep) return; - // simulation box bounds if (domain->triclinic == 0) { @@ -370,9 +366,12 @@ void Dump::write() nme = count(); + // if timestep < delaystep, just return // if skip condition is defined and met, just return - // do this after count() b/c it invokes computes, - // so caller can trigger future invocation of needed computes + // must do both these tests after count() b/c it invokes computes, + // this enables caller to trigger future invocation of needed computes + + if (delay_flag && update->ntimestep < delaystep) return; if (skipflag) { double value = input->variable->compute_equal(skipindex); From 842b5b365e7638b2df9e5391f2d6fe61a18cad74 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Thu, 28 Jul 2022 17:12:31 -0600 Subject: [PATCH 06/22] doc page clarifications --- doc/src/fix_pair.rst | 18 +++++++++--------- doc/src/pair_eam.rst | 9 +++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/doc/src/fix_pair.rst b/doc/src/fix_pair.rst index c8734299d4..19a57ca48e 100644 --- a/doc/src/fix_pair.rst +++ b/doc/src/fix_pair.rst @@ -52,15 +52,15 @@ per-atom quantity which the pair style must recognize as an extraction request. See the doc pages for individual :doc:`pair_styles ` to see what fix pair requests (if any) they support. -The *flag* setting determines whether this fix will also request that -the pair style compute the named quantity to be extracted. If the -quantity is always computed by the pair style, no request is needed; -specify *flag* = 0. If the quantity is not always computed (e.g. it -is expensive to calculate), then specify *flag* = 1. This fix will -then request the quantity only on timesteps it is needed. Again, see -the doc pages for individual :doc:`pair_styles ` to -determine which fix pair requests (if any) need to be triggered with a -*flag* = 1 setting. +The *flag* setting determines whether this fix will also trigger the +pair style to compute the named quantity so it can be extracted. If +the quantity is always computed by the pair style, no trigger is +needed; specify *flag* = 0. If the quantity is not always computed +(e.g. it is expensive to calculate), then specify *flag* = 1. This +will trigger the quantity to be calculated only on timesteps it is +needed. Again, see the doc pages for individual :doc:`pair_styles +` to determine which fix pair requests (if any) need to be +triggered with a *flag* = 1 setting. The per-atom data extracted from the pair style is stored by this fix as either a per-atom vector or array. If there is only one *name* diff --git a/doc/src/pair_eam.rst b/doc/src/pair_eam.rst index 4ba926362f..7e3b1b3a3f 100644 --- a/doc/src/pair_eam.rst +++ b/doc/src/pair_eam.rst @@ -444,10 +444,11 @@ identical to the FS EAM files (see above). ---------- -The eam, eam/alloy, eam/fs, and eam/he pair styles support extraction -of two per-atom quantities by the :doc:`fix pair ` command. -This allows the quantities to be output to files by the :doc:`dump -` or otherwise processed by other LAMMPS commamds. +The *eam*, *eam/alloy*, *eam/fs*, and *eam/he* pair styles support +extraction of two per-atom quantities by the :doc:`fix pair +` command. This allows the quantities to be output to files +by the :doc:`dump ` or otherwise processed by other LAMMPS +commamds. The names of the two quantites are "rho" and "fp" for the density and derivative of the embedding energy for each atom. Neither quantity From ec4c458c7e8f316a587332297fcbd52cd76c85cc Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Fri, 29 Jul 2022 10:54:42 -0600 Subject: [PATCH 07/22] add Pair::extract_atom() method --- src/AMOEBA/pair_amoeba.cpp | 21 +++++++++++++++------ src/AMOEBA/pair_amoeba.h | 1 + src/MANYBODY/pair_eam.cpp | 21 +++++++++++++++------ src/MANYBODY/pair_eam.h | 1 + src/fix_pair.cpp | 6 +++--- src/pair.h | 1 + 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/AMOEBA/pair_amoeba.cpp b/src/AMOEBA/pair_amoeba.cpp index 8229684d29..1ea4450432 100644 --- a/src/AMOEBA/pair_amoeba.cpp +++ b/src/AMOEBA/pair_amoeba.cpp @@ -2077,16 +2077,25 @@ void *PairAmoeba::extract(const char *str, int &dim) if (strcmp(str,"opbend_pentic") == 0) return (void *) &opbend_pentic; if (strcmp(str,"opbend_sextic") == 0) return (void *) &opbend_sextic; - // peratom requests from FixPair - // return dim = # of quantites per atom - // 0 = per-atom vector - // 1 or more = # of columns in per-atom array + return nullptr; +} +/* ---------------------------------------------------------------------- + peratom requests from FixPair + return ptr to requested data + also return ncol = # of quantites per atom + 0 = per-atom vector + 1 or more = # of columns in per-atom array + return NULL if str is not recognized +---------------------------------------------------------------------- */ + +void *PairAmoeba::extract_peratom(const char *str, int &ncol) +{ if (strcmp(str,"uind") == 0) { - dim = 3; + ncol = 3; return (void *) uind; } else if (strcmp(str,"uinp") == 0) { - dim = 3; + ncol = 3; return (void *) uinp; } diff --git a/src/AMOEBA/pair_amoeba.h b/src/AMOEBA/pair_amoeba.h index 7b0719bca0..869a5aff4f 100644 --- a/src/AMOEBA/pair_amoeba.h +++ b/src/AMOEBA/pair_amoeba.h @@ -50,6 +50,7 @@ class PairAmoeba : public Pair { void unpack_reverse_grid(int, void *, int, int *) override; void *extract(const char *, int &) override; + void *extract_peratom(const char *, int &) override; double memory_usage() override; protected: diff --git a/src/MANYBODY/pair_eam.cpp b/src/MANYBODY/pair_eam.cpp index 2534386225..b14d47f7f0 100644 --- a/src/MANYBODY/pair_eam.cpp +++ b/src/MANYBODY/pair_eam.cpp @@ -934,16 +934,25 @@ void *PairEAM::extract(const char *str, int &dim) dim = 2; if (strcmp(str,"scale") == 0) return (void *) scale; - // peratom requests from FixPair - // return dim = # of quantites per atom - // 0 = per-atom vector - // 1 or more = # of columns in per-atom array + return nullptr; +} +/* ---------------------------------------------------------------------- + peratom requests from FixPair + return ptr to requested data + also return ncol = # of quantites per atom + 0 = per-atom vector + 1 or more = # of columns in per-atom array + return NULL if str is not recognized +---------------------------------------------------------------------- */ + +void *PairEAM::extract_peratom(const char *str, int &ncol) +{ if (strcmp(str,"rho") == 0) { - dim = 0; + ncol = 0; return (void *) rho; } else if (strcmp(str,"fp") == 0) { - dim = 0; + ncol = 0; return (void *) fp; } diff --git a/src/MANYBODY/pair_eam.h b/src/MANYBODY/pair_eam.h index 3589ab4ab0..11ab969d18 100644 --- a/src/MANYBODY/pair_eam.h +++ b/src/MANYBODY/pair_eam.h @@ -53,6 +53,7 @@ class PairEAM : public Pair { double init_one(int, int) override; double single(int, int, int, int, double, double, double, double &) override; void *extract(const char *, int &) override; + void *extract_peratom(const char *, int &) override; int pack_forward_comm(int, int *, double *, int, int *) override; void unpack_forward_comm(int, int, double *) override; diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp index fafc86d903..bc918c468c 100644 --- a/src/fix_pair.cpp +++ b/src/fix_pair.cpp @@ -83,15 +83,15 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : triggerptr = new int*[nfield]; - int dim; ncols = 0; for (int ifield = 0; ifield < nfield; ifield++) { int columns = 0; // set in case fieldname not recognized by pstyle - void *pvoid = pstyle->extract(fieldname[ifield],columns); + void *pvoid = pstyle->extract_peratom(fieldname[ifield],columns); if (columns) ncols += columns; else ncols++; if (trigger[ifield]) { + int dim; triggerptr[ifield] = (int *) pstyle->extract(triggername[ifield],dim); if (!triggerptr[ifield]) error->all(FLERR,"Fix pair pair style cannot extract {}", @@ -222,7 +222,7 @@ void FixPair::post_force(int /*vflag*/) int columns; for (int ifield = 0; ifield < nfield; ifield++) { - void *pvoid = pstyle->extract(fieldname[ifield],columns); + void *pvoid = pstyle->extract_peratom(fieldname[ifield],columns); if (pvoid == nullptr) error->all(FLERR,"Fix pair pair style cannot extract {}",fieldname[ifield]); diff --git a/src/pair.h b/src/pair.h index 048abb6bb9..8cda065e19 100644 --- a/src/pair.h +++ b/src/pair.h @@ -215,6 +215,7 @@ class Pair : protected Pointers { // specific child-class methods for certain Pair styles virtual void *extract(const char *, int &) { return nullptr; } + virtual void *extract_peratom(const char *, int &) { return nullptr; } virtual void swap_eam(double *, double **) {} virtual void reset_dt() {} virtual void min_xf_pointers(int, double **, double **) {} From 4d062f70cef07cb1608540fea7b486af019cf233 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Wed, 31 Aug 2022 10:09:59 -0600 Subject: [PATCH 08/22] bug fix for per-atom vector output of fix pair --- src/fix_pair.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp index bc918c468c..68d05fdd57 100644 --- a/src/fix_pair.cpp +++ b/src/fix_pair.cpp @@ -124,7 +124,7 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : int nlocal = atom->nlocal; - if (ncols == 0) { + if (ncols == 1) { for (int i = 0; i < nlocal; i++) vector[i] = 0.0; } else { @@ -153,7 +153,7 @@ FixPair::~FixPair() delete [] triggername; delete [] triggerptr; - if (ncols == 0) memory->destroy(vector); + if (ncols == 1) memory->destroy(vector); else memory->destroy(array); } @@ -228,7 +228,7 @@ void FixPair::post_force(int /*vflag*/) if (columns == 0) { double *pvector = (double *) pvoid; - if (ncols == 0) { + if (ncols == 1) { for (int i = 0; i < nlocal; i++) vector[i] = pvector[i]; } else { @@ -259,7 +259,7 @@ void FixPair::post_force(int /*vflag*/) void FixPair::grow_arrays(int nmax) { - if (ncols == 0) { + if (ncols == 1) { memory->grow(vector,nmax,"store/state:vector"); vector_atom = vector; } else { @@ -275,7 +275,7 @@ void FixPair::grow_arrays(int nmax) double FixPair::memory_usage() { double bytes = 0.0; - if (ncols == 0) bytes += (double)atom->nmax * sizeof(double); + if (ncols == 1) bytes += (double)atom->nmax * sizeof(double); else bytes += (double)atom->nmax*ncols * sizeof(double); return bytes; } From f9c49620b3327fcc239b2956dc257cbd3f4acfd3 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Fri, 2 Sep 2022 09:38:24 -0600 Subject: [PATCH 09/22] add minimization support --- src/fix_pair.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++---- src/fix_pair.h | 6 ++++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp index 68d05fdd57..cb2ccf9ef2 100644 --- a/src/fix_pair.cpp +++ b/src/fix_pair.cpp @@ -101,15 +101,18 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : } } - // settings - // freq = 1 since vector/array always have values - // allows user to specify nevery = 0 for a dump - // which this fix outputs whenever it wants + // if set peratom_freq = Nevery, then cannot access the per-atom + // values as part of thermo output during minimiziation + // at different frequency or on last step of minimization + // instead set peratom_freq = 1 + // ok, since vector/array always have values + // but requires the vector/array be persisted between Nevery steps + // since it may be accessed peratom_flag = 1; if (ncols == 1) size_peratom_cols = 0; else size_peratom_cols = ncols; - peratom_freq = nevery; + peratom_freq = 1; // perform initial allocation of atom-based array // register with Atom class @@ -163,7 +166,9 @@ int FixPair::setmask() { int mask = 0; mask |= PRE_FORCE; + mask |= MIN_PRE_FORCE; mask |= POST_FORCE; + mask |= MIN_POST_FORCE; return mask; } @@ -205,6 +210,13 @@ void FixPair::pre_force(int /*vflag*/) if (trigger[ifield]) *(triggerptr[ifield]) = 1; } +/* ---------------------------------------------------------------------- */ + +void FixPair::min_pre_force(int vflag) +{ + pre_force(vflag); +} + /* ---------------------------------------------------------------------- extract results from pair style ------------------------------------------------------------------------- */ @@ -253,6 +265,13 @@ void FixPair::post_force(int /*vflag*/) if (trigger[ifield]) *(triggerptr[ifield]) = 0; } +/* ---------------------------------------------------------------------- */ + +void FixPair::min_post_force(int vflag) +{ + post_force(vflag); +} + /* ---------------------------------------------------------------------- allocate atom-based vector or array ------------------------------------------------------------------------- */ @@ -268,6 +287,52 @@ void FixPair::grow_arrays(int nmax) } } +/* ---------------------------------------------------------------------- + copy values within local atom-based array +------------------------------------------------------------------------- */ + +void FixPair::copy_arrays(int i, int j, int /*delflag*/) +{ + if (ncols == 1) { + vector[j] = vector[i]; + } else { + for (int m = 0; m < ncols; m++) + array[j][m] = array[i][m]; + } +} + +/* ---------------------------------------------------------------------- + pack values in local atom-based array for exchange with another proc +------------------------------------------------------------------------- */ + +int FixPair::pack_exchange(int i, double *buf) +{ + if (ncols == 1) { + buf[0] = vector[i]; + } else { + for (int m = 0; m < ncols; m++) + buf[m] = array[i][m]; + } + + return ncols; +} + +/* ---------------------------------------------------------------------- + unpack values in local atom-based array from exchange with another proc +------------------------------------------------------------------------- */ + +int FixPair::unpack_exchange(int nlocal, double *buf) +{ + if (ncols == 1) { + vector[nlocal] = buf[0]; + } else { + for (int m = 0; m < ncols; m++) + array[nlocal][m] = buf[m]; + } + + return ncols; +} + /* ---------------------------------------------------------------------- memory usage of local atom-based vector or array ------------------------------------------------------------------------- */ diff --git a/src/fix_pair.h b/src/fix_pair.h index a9927cf477..c4d0bb593c 100644 --- a/src/fix_pair.h +++ b/src/fix_pair.h @@ -33,9 +33,15 @@ class FixPair : public Fix { void setup(int) override; void setup_pre_force(int) override; void pre_force(int) override; + void min_pre_force(int) override; void post_force(int) override; + void min_post_force(int) override; void grow_arrays(int) override; + void copy_arrays(int, int, int) override; + int pack_exchange(int, double *) override; + int unpack_exchange(int, double *) override; + double memory_usage() override; private: From 7f4fe0d3ad9bd44a78b979f1e7aaf5ee82a5b007 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 9 Sep 2022 17:29:11 -0400 Subject: [PATCH 10/22] whitespace --- src/dump.cpp | 2 +- src/fix_pair.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dump.cpp b/src/dump.cpp index 0acbe3025a..91833d017f 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -310,7 +310,7 @@ void Dump::init() if (skipflag) { skipindex = input->variable->find(skipvar); if (skipindex < 0) error->all(FLERR,"Dump skip variable not found"); - if (!input->variable->equalstyle(skipindex)) + if (!input->variable->equalstyle(skipindex)) error->all(FLERR,"Variable for dump skip is invalid style"); } diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp index cb2ccf9ef2..3c967e2cfa 100644 --- a/src/fix_pair.cpp +++ b/src/fix_pair.cpp @@ -93,7 +93,7 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : if (trigger[ifield]) { int dim; triggerptr[ifield] = (int *) pstyle->extract(triggername[ifield],dim); - if (!triggerptr[ifield]) + if (!triggerptr[ifield]) error->all(FLERR,"Fix pair pair style cannot extract {}", triggername[ifield]); if (dim) error->all(FLERR,"Fix pair pair style {} is not a scalar", @@ -102,7 +102,7 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : } // if set peratom_freq = Nevery, then cannot access the per-atom - // values as part of thermo output during minimiziation + // values as part of thermo output during minimiziation // at different frequency or on last step of minimization // instead set peratom_freq = 1 // ok, since vector/array always have values @@ -155,7 +155,7 @@ FixPair::~FixPair() delete [] trigger; delete [] triggername; delete [] triggerptr; - + if (ncols == 1) memory->destroy(vector); else memory->destroy(array); } @@ -225,7 +225,7 @@ void FixPair::post_force(int /*vflag*/) { if (update->ntimestep % nevery) return; - // extract pair style fields one by one + // extract pair style fields one by one // store their values in this fix int nlocal = atom->nlocal; @@ -235,12 +235,12 @@ void FixPair::post_force(int /*vflag*/) for (int ifield = 0; ifield < nfield; ifield++) { void *pvoid = pstyle->extract_peratom(fieldname[ifield],columns); - if (pvoid == nullptr) + if (pvoid == nullptr) error->all(FLERR,"Fix pair pair style cannot extract {}",fieldname[ifield]); if (columns == 0) { double *pvector = (double *) pvoid; - if (ncols == 1) { + if (ncols == 1) { for (int i = 0; i < nlocal; i++) vector[i] = pvector[i]; } else { From 610848599ca0ffe38d9b6bbb91b6c41c2ba90c2a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 9 Sep 2022 18:42:32 -0400 Subject: [PATCH 11/22] reappy bugfix that was lost from moving the "colname" section --- src/dump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dump.cpp b/src/dump.cpp index 91833d017f..7769d0e0d4 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -1085,7 +1085,7 @@ void Dump::modify_params(int narg, char **arg) } else if (strcmp(arg[iarg],"colname") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); 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) error->all(FLERR,"Illegal dump_modify command"); From 6898ead5b762388464fce7da3e6c034d315c0a2e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 9 Sep 2022 18:43:20 -0400 Subject: [PATCH 12/22] remove redundant code created by merge --- src/dump.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/dump.cpp b/src/dump.cpp index 7769d0e0d4..c8768c5fb6 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -1190,32 +1190,6 @@ void Dump::modify_params(int narg, char **arg) flush_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; - } 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(); - iarg += 2; - } else { - if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "dump_modify colname", error); - int icol = -1; - if (utils::is_integer(arg[iarg + 1])) { - icol = utils::inumeric(FLERR,arg[iarg + 1],false,lmp); - if (icol < 0) icol = keyword_user.size() + icol + 1; - icol--; - } else { - try { - icol = key2col.at(arg[iarg + 1]); - } catch (std::out_of_range &) { - icol = -1; - } - } - if ((icol < 0) || (icol >= (int)keyword_user.size())) - error->all(FLERR, "Incorrect dump_modify arguments: {} {} {}", - arg[iarg], arg[iarg+1], arg[iarg+2]); - keyword_user[icol] = arg[iarg+2]; - iarg += 3; - } - } else if (strcmp(arg[iarg],"format") == 0) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "dump_modify format", error); From 9e7df0f8e1694d6159c57c1a96c01e3cb4679fa9 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 9 Sep 2022 18:44:07 -0400 Subject: [PATCH 13/22] correctly compute communication buffers also for the case that size_one changes --- src/dump.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/dump.cpp b/src/dump.cpp index c8768c5fb6..0f93c7a1c6 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -398,12 +398,12 @@ void Dump::write() // use nmax to insure filewriter proc can receive info from others // limit nmax*size_one to int since used as arg in MPI calls - if (nmax > maxbuf) { + if (nmax*size_one > maxbuf) { if ((bigint) nmax * size_one > MAXSMALLINT) error->all(FLERR,"Too much per-proc info for dump"); - maxbuf = nmax; + maxbuf = nmax * size_one; memory->destroy(buf); - memory->create(buf,maxbuf*size_one,"dump:buf"); + memory->create(buf,maxbuf,"dump:buf"); } // insure ids buffer is sized for sorting @@ -492,7 +492,7 @@ void Dump::write() if (filewriter) { for (int iproc = 0; iproc < nclusterprocs; iproc++) { if (iproc) { - MPI_Irecv(buf,maxbuf*size_one,MPI_DOUBLE,me+iproc,0,world,&request); + MPI_Irecv(buf,maxbuf,MPI_DOUBLE,me+iproc,0,world,&request); MPI_Send(&tmp,0,MPI_INT,me+iproc,0,world); MPI_Wait(&request,&status); MPI_Get_count(&status,MPI_DOUBLE,&nlines); @@ -774,10 +774,10 @@ void Dump::sort() int nmax; MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world); - if (nmax > maxbuf) { - maxbuf = nmax; + if (nmax*size_one > maxbuf) { + maxbuf = nmax * size_one; memory->destroy(buf); - memory->create(buf,maxbuf*size_one,"dump:buf"); + memory->create(buf,maxbuf,"dump:buf"); } // copy data from bufsort to buf using index @@ -958,12 +958,12 @@ void Dump::balance() int nmax; MPI_Allreduce(&nme_balance,&nmax,1,MPI_INT,MPI_MAX,world); - if (nmax > maxbuf) maxbuf = nmax; + if (nmax*size_one > maxbuf) maxbuf = nmax*size_one; // allocate a second buffer for balanced data double* buf_balance; - memory->create(buf_balance,maxbuf*size_one,"dump:buf_balance"); + memory->create(buf_balance,maxbuf,"dump:buf_balance"); // compute from which procs I am receiving atoms // post recvs first @@ -1370,7 +1370,7 @@ void Dump::pbc_allocate() double Dump::memory_usage() { - double bytes = memory->usage(buf,size_one*maxbuf); + double bytes = memory->usage(buf,maxbuf); bytes += memory->usage(sbuf,maxsbuf); if (sort_flag) { if (sortcol == 0) bytes += memory->usage(ids,maxids); From aad464275d055e885847a80b2d65d073d2070af5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 9 Sep 2022 18:44:28 -0400 Subject: [PATCH 14/22] changing scale or image keywords resets user keywords --- src/dump_atom.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp index ef567abdb2..8daf2d1d0a 100644 --- a/src/dump_atom.cpp +++ b/src/dump_atom.cpp @@ -131,10 +131,12 @@ int DumpAtom::modify_param(int narg, char **arg) if (strcmp(arg[0],"scale") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); scale_flag = utils::logical(FLERR,arg[1],false,lmp); + for (auto &item : keyword_user) item.clear(); return 2; } else if (strcmp(arg[0],"image") == 0) { if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); image_flag = utils::logical(FLERR,arg[1],false,lmp); + for (auto &item : keyword_user) item.clear(); return 2; } return 0; From 41f28f783f832e630191218113f9118b3cca4ebd Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 9 Sep 2022 18:44:42 -0400 Subject: [PATCH 15/22] more tests --- unittest/formats/test_dump_atom.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/unittest/formats/test_dump_atom.cpp b/unittest/formats/test_dump_atom.cpp index 6fe4d0e1ae..683578d04f 100644 --- a/unittest/formats/test_dump_atom.cpp +++ b/unittest/formats/test_dump_atom.cpp @@ -794,6 +794,13 @@ TEST_F(DumpAtomTest, colname) command("run 10 post no"); command("dump_modify id colname default"); command("run 10 post no"); + command("dump_modify id colname id AtomID colname 3 x-scaled colname -4 z-scaled"); + command("dump_modify id scale no image yes"); + command("run 10 post no"); + command("dump_modify id colname id AtomID colname 3 X colname -4 Z colname ix img_x"); + command("run 10 post no"); + command("dump_modify id colname default"); + command("run 10 post no"); command("undump id"); END_HIDE_OUTPUT(); @@ -810,6 +817,18 @@ TEST_F(DumpAtomTest, colname) for (int i = 0; i < expected.size(); ++i) ASSERT_THAT(values[i], Eq(expected[i])); + values = extract_items(dump_file, "ATOMS id type x y z ix iy iz"); + expected = {"1 1 0 0 0 0 0 0", "1 1 0 0 0 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 y Z img_x iy iz"); + expected = {"1 1 0 0 0 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); } From 74fea2bc704e3890e1612865d00a1471ba51b3d5 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 9 Sep 2022 18:48:30 -0400 Subject: [PATCH 16/22] update docs --- doc/src/dump_modify.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index ce6b336f02..a827cc8a91 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -432,7 +432,8 @@ flags are enabled or not. For dump style *cfg* only changes to the The *colname* keyword can be used multiple times. If multiple *colname* settings refer to the same keyword, the last setting has precedence. A setting of *default* clears all previous settings, reverting all values -to their default names. +to their default names. Using the *scale* or *image* keyword will also +reset all header keywords to their default values. ---------- @@ -522,6 +523,8 @@ boundary twice and is really two box lengths to the left of its current coordinate. Note that for dump style *custom* these various values can be printed in the dump file by using the appropriate atom attributes in the dump command itself. +Using this keyword will reset all custom header names set with +*dump_modify colname*. ---------- @@ -695,6 +698,8 @@ value of *yes* means atom coords are written in normalized units from (tilted), then all atom coords will still be between 0.0 and 1.0. A value of *no* means they are written in absolute distance units (e.g., :math:`\mathrm{\mathring A}` or :math:`\sigma`). +Using this keyword will reset all custom header names set with +*dump_modify colname*. ---------- From f700da5ac3f7b0dc37425b3094398aa9aa4ff746 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 10 Sep 2022 04:24:40 -0400 Subject: [PATCH 17/22] remove redundant section --- doc/src/dump_modify.rst | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index a827cc8a91..55af43f54c 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -178,6 +178,9 @@ extra buffering. ---------- + +.. versionadded:: 4May2022 + The *colname* keyword can be used to change the default header keyword for dump styles: *atom*, *custom*, and *cfg* and their compressed, ADIOS, and MPIIO variants. The setting for *ID string* replaces the default @@ -412,31 +415,6 @@ performed with dump style *xtc*\ . ---------- -.. versionadded:: 4May2022 - -The *colname* keyword can be used to change the default header keyword -for dump styles: *atom*, *custom*, and *cfg* and their compressed, ADIOS, -and MPIIO variants. The setting for *ID string* replaces the default -text with the provided string. *ID* can be a positive integer when it -represents the column number counting from the left, a negative integer -when it represents the column number from the right (i.e. -1 is the last -column/keyword), or a custom dump keyword (or compute, fix, property, or -variable reference) and then it replaces the string for that specific -keyword. For *atom* dump styles only the keywords "id", "type", "x", -"y", "z", "ix", "iy", "iz" can be accessed via string regardless of -whether scaled or unwrapped coordinates were enabled or disabled, and -it always assumes 8 columns for indexing regardless of whether image -flags are enabled or not. For dump style *cfg* only changes to the -"auxiliary" keywords (6th or later keyword) will become visible. - -The *colname* keyword can be used multiple times. If multiple *colname* -settings refer to the same keyword, the last setting has precedence. A -setting of *default* clears all previous settings, reverting all values -to their default names. Using the *scale* or *image* keyword will also -reset all header keywords to their default values. - ----------- - The *format* keyword can be used to change the default numeric format output by the text-based dump styles: *atom*, *local*, *custom*, *cfg*, and *xyz* styles, and their MPIIO variants. Only the *line* or *none* From 4cca198adf68356aa86dac09f0dcfc63e2d547ab Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 10 Sep 2022 04:35:13 -0400 Subject: [PATCH 18/22] fix issues from moving code and incorrect merge conflict resolution --- src/dump.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/dump.cpp b/src/dump.cpp index 0f93c7a1c6..36b2763d88 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -169,7 +169,6 @@ Dump::~Dump() delete[] format_bigint_user; delete[] refresh; - delete[] skipvar; // format_column_user is deallocated by child classes that use it @@ -1070,7 +1069,7 @@ void Dump::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"balance") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "dump_modify balance", error); if (nprocs > 1) balance_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); iarg += 2; @@ -1083,12 +1082,12 @@ void Dump::modify_params(int narg, char **arg) iarg += 2; } else if (strcmp(arg[iarg],"colname") == 0) { - if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command"); + 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(); iarg += 2; } else { - if (iarg+3 > narg) error->all(FLERR,"Illegal dump_modify command"); + if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "dump_modify colname", error); int icol = -1; if (utils::is_integer(arg[iarg + 1])) { icol = utils::inumeric(FLERR,arg[iarg + 1],false,lmp); @@ -1318,12 +1317,6 @@ void Dump::modify_params(int narg, char **arg) } iarg += 2; - } else if (strcmp(arg[iarg],"balance") == 0) { - if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "dump_modify blance", error); - if (nprocs > 1) - balance_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); - iarg += 2; - } else if (strcmp(arg[iarg],"time") == 0) { if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "dump_modify time", error); time_flag = utils::logical(FLERR,arg[iarg+1],false,lmp); From 73b44c3b18543e1d612420d4d7d76b1dac108d24 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sat, 10 Sep 2022 04:35:39 -0400 Subject: [PATCH 19/22] add some versionadded markers --- doc/src/dump_modify.rst | 5 ++++- doc/src/fix_pair.rst | 4 +++- doc/src/pair_amoeba.rst | 2 ++ doc/src/pair_eam.rst | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index 55af43f54c..7c98492893 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -199,7 +199,8 @@ flags are enabled or not. For dump style *cfg* only changes to the The *colname* keyword can be used multiple times. If multiple *colname* settings refer to the same keyword, the last setting has precedence. A setting of *default* clears all previous settings, reverting all values -to their default names. +to their default names. Using the *scale* or *image* keyword will also +reset all header keywords to their default values. ---------- @@ -696,6 +697,8 @@ most effective when the typical magnitude of position data is between ---------- +.. versionadded:: TBD + The *skip* keyword can be used with all dump styles. It allows a dump snapshot to be skipped (not written to the dump file), if a condition is met. The condition is computed by an :doc:`equal-style variable diff --git a/doc/src/fix_pair.rst b/doc/src/fix_pair.rst index 19a57ca48e..b1d3010be0 100644 --- a/doc/src/fix_pair.rst +++ b/doc/src/fix_pair.rst @@ -30,6 +30,8 @@ Examples Description """"""""""" +.. versionadded:: TBD + Extract per-atom quantities from a pair style and store them in this fix so they can be accessed by other LAMMPS commands, e.g. by a :doc:`dump ` command or by another :doc:`fix `, @@ -40,7 +42,7 @@ These are example use cases: * extract per-atom density from :doc:`pair_style eam ` to a dump file * extract induced dipoles from :doc:`pair_style amoeba ` to a dump file * extract accuracy metrics from a machine-learned potential to trigger output when -a condition is met (see the :doc:`dump_modify skip ` command) + a condition is met (see the :doc:`dump_modify skip ` command) The *N* argument determines how often the fix is invoked. diff --git a/doc/src/pair_amoeba.rst b/doc/src/pair_amoeba.rst index b41cb9815b..22ec2281dd 100644 --- a/doc/src/pair_amoeba.rst +++ b/doc/src/pair_amoeba.rst @@ -156,6 +156,8 @@ settings. ---------- +.. versionadded:: TBD + The *amoeba* and *hippo* pair styles support extraction of two per-atom quantities by the :doc:`fix pair ` command. This allows the quantities to be output to files by the :doc:`dump ` diff --git a/doc/src/pair_eam.rst b/doc/src/pair_eam.rst index 7e3b1b3a3f..bb8433f101 100644 --- a/doc/src/pair_eam.rst +++ b/doc/src/pair_eam.rst @@ -444,6 +444,8 @@ identical to the FS EAM files (see above). ---------- +.. versionadded:: TBD + The *eam*, *eam/alloy*, *eam/fs*, and *eam/he* pair styles support extraction of two per-atom quantities by the :doc:`fix pair ` command. This allows the quantities to be output to files From e415eddee504c84cec37fdfa085607e0ce13a541 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 14 Sep 2022 14:16:22 -0400 Subject: [PATCH 20/22] spelling and improved consistency with other doc pages --- doc/src/dump_modify.rst | 16 +++++------ doc/src/fix_pair.rst | 32 ++++++++++++--------- doc/src/pair_amoeba.rst | 16 +++++------ doc/src/pair_eam.rst | 13 ++++----- doc/utils/sphinx-config/false_positives.txt | 2 ++ 5 files changed, 42 insertions(+), 37 deletions(-) diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index eddf36c44c..275ad26325 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -702,7 +702,7 @@ The *skip* keyword can be used with all dump styles. It allows a dump snapshot to be skipped (not written to the dump file), if a condition is met. The condition is computed by an :doc:`equal-style variable `, which should be specified as v_name, where name is the -variable name. If the variable evaulation returns a non-zero value, +variable name. If the variable evaluation returns a non-zero value, then the dump snapshot is skipped. If it returns zero, the dump proceeds as usual. Note that :doc:`equal-style variable ` can contain Boolean operators which effectively evaluate as a true @@ -718,12 +718,12 @@ value. The *sort* keyword determines whether lines of per-atom output in a snapshot are sorted or not. A sort value of *off* means they will typically be written in indeterminate order, either in serial or -parallel. This is the case even in serial if the :doc:`atom_modify -sort ` option is turned on, which it is by default, to -improve performance. A sort value of *id* means sort the output by -atom ID. A sort value of N or -N means sort the output by the value -in the Nth column of per-atom info in either ascending or descending -order. +parallel. This is the case even in serial if the :doc:`atom_modify sort +` option is turned on, which it is by default, to improve +performance. A sort value of *id* means sort the output by atom ID. A +sort value of :math:`N` or :math:`-N` means sort the output by the value +in the :math:`N`\ th column of per-atom info in either ascending or +descending order. The dump *local* style cannot be sorted by atom ID, since there are typically multiple lines of output per atom. Some dump styles, such @@ -766,7 +766,7 @@ attributes that can be tested for are the same as those that can be specified in the :doc:`dump custom ` command, with the exception of the *element* attribute, since it is not a numeric value. Note that a different attributes can be used than those output by the -:doc:`dump custom ` command. E.g. you can output the +:doc:`dump custom ` command. For example, you can output the coordinates and stress of atoms whose energy is above some threshold. If an atom-style variable is used as the attribute, then it can diff --git a/doc/src/fix_pair.rst b/doc/src/fix_pair.rst index b1d3010be0..0718be5d3c 100644 --- a/doc/src/fix_pair.rst +++ b/doc/src/fix_pair.rst @@ -8,12 +8,12 @@ Syntax .. parsed-literal:: - fix ID group-ID pair N pairstyle name flag ... + fix ID group-ID pair N pstyle name flag ... * ID, group-ID are documented in :doc:`fix ` command * pair = style name of this fix command * N = invoke this fix once every N timesteps -* pairstyle = name of pair style to extract info from (e.g. eam) +* pstyle = name of pair style to extract info from (e.g. eam) * one or more name/flag pairs can be listed * name = name of quantity the pair style allows extraction of * flag = 1 if pair style needs to be triggered to produce data for name, 0 if not @@ -46,7 +46,7 @@ These are example use cases: The *N* argument determines how often the fix is invoked. -The *pairstyle* argument is the name of the pair style. It can be a +The *pstyle* argument is the name of the pair style. It can be a sub-style used in a :doc:`pair_style hybrid ` command. One or more *name/flag* pairs of arguments follow. Each *name* is a @@ -55,11 +55,11 @@ request. See the doc pages for individual :doc:`pair_styles ` to see what fix pair requests (if any) they support. The *flag* setting determines whether this fix will also trigger the -pair style to compute the named quantity so it can be extracted. If -the quantity is always computed by the pair style, no trigger is -needed; specify *flag* = 0. If the quantity is not always computed -(e.g. it is expensive to calculate), then specify *flag* = 1. This -will trigger the quantity to be calculated only on timesteps it is +pair style to compute the named quantity so it can be extracted. If the +quantity is always computed by the pair style, no trigger is needed; +specify *flag* = 0. If the quantity is not always computed +(e.g. because it is expensive to calculate), then specify *flag* = 1. +This will trigger the quantity to be calculated only on timesteps it is needed. Again, see the doc pages for individual :doc:`pair_styles ` to determine which fix pair requests (if any) need to be triggered with a *flag* = 1 setting. @@ -71,12 +71,16 @@ atom, then this fix stores it as a per-atom vector. Otherwise a per-atom array is created, with its data in the order of the *name* arguments. -For example, :doc:`pair_style amoeba ` allows extraction -of two named quantities: "uind" and "uinp", both of which are -3-vectors for each atom, i.e. dipole moments. If this fix specifies -"uind" and "uinp" (in that order), then a 6-column per-atom array will -be created. Columns 1-3 will store the "uind" values; columns 4-6 -will store the "uinp" values. +For example, :doc:`pair_style amoeba ` allows extraction of +two named quantities: "uind" and "uinp", both of which are 3-vectors for +each atom, i.e. dipole moments. In the example below a 6-column per-atom +array will be created. Columns 1-3 will store the "uind" values; +columns 4-6 will store the "uinp" values. + +.. code-block:: LAMMPS + + pair_style amoeba + fix ex all pair amoeba 10 uind 0 uinp 0 Restart, fix_modify, output, run start/stop, minimize info """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/doc/src/pair_amoeba.rst b/doc/src/pair_amoeba.rst index 22ec2281dd..44a14f0f45 100644 --- a/doc/src/pair_amoeba.rst +++ b/doc/src/pair_amoeba.rst @@ -158,15 +158,15 @@ settings. .. versionadded:: TBD -The *amoeba* and *hippo* pair styles support extraction of two -per-atom quantities by the :doc:`fix pair ` command. This -allows the quantities to be output to files by the :doc:`dump ` -or otherwise processed by other LAMMPS commamds. +The *amoeba* and *hippo* pair styles support extraction of two per-atom +quantities by the :doc:`fix pair ` command. This allows the +quantities to be output to files by the :doc:`dump ` or otherwise +processed by other LAMMPS commands. -The names of the two quantites are "uind" and "uinp" for the induced -dipole moments for each atom. Neither quantity needs to be triggered -by the :doc:`fix pair ` command in order for these pair -styles to calculate it. +The names of the two quantities are "uind" and "uinp" for the induced +dipole moments for each atom. Neither quantity needs to be triggered by +the :doc:`fix pair ` command in order for these pair styles to +calculate it. ---------- diff --git a/doc/src/pair_eam.rst b/doc/src/pair_eam.rst index bb8433f101..af936a6bc9 100644 --- a/doc/src/pair_eam.rst +++ b/doc/src/pair_eam.rst @@ -447,15 +447,14 @@ identical to the FS EAM files (see above). .. versionadded:: TBD The *eam*, *eam/alloy*, *eam/fs*, and *eam/he* pair styles support -extraction of two per-atom quantities by the :doc:`fix pair -` command. This allows the quantities to be output to files -by the :doc:`dump ` or otherwise processed by other LAMMPS -commamds. +extraction of two per-atom quantities by the :doc:`fix pair ` +command. This allows the quantities to be output to files by the +:doc:`dump ` or otherwise processed by other LAMMPS commands. -The names of the two quantites are "rho" and "fp" for the density and +The names of the two quantities are "rho" and "fp" for the density and derivative of the embedding energy for each atom. Neither quantity -needs to be triggered by the :doc:`fix pair ` command in -order for these pair styles to calculate it. +needs to be triggered by the :doc:`fix pair ` command in order +for these pair styles to calculate it. ---------- diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index c6c6a2de6a..15316b4f09 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -3581,7 +3581,9 @@ UEF ufm Uhlenbeck Ui +uind uInfParallel +uinp uk ul ulb From a52c4a55375d9737b8d569de5513f52f97dabcc0 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 14 Sep 2022 14:35:57 -0400 Subject: [PATCH 21/22] improve error messages --- src/fix_pair.cpp | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/fix_pair.cpp b/src/fix_pair.cpp index 3c967e2cfa..6f98ad2790 100644 --- a/src/fix_pair.cpp +++ b/src/fix_pair.cpp @@ -37,14 +37,14 @@ using namespace FixConst; FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { - if (narg < 7) error->all(FLERR,"Illegal fix pair command"); + if (narg < 7) utils::missing_cmd_args(FLERR, "fix pair", error); nevery = utils::inumeric(FLERR,arg[3],false,lmp); - if (nevery < 1) error->all(FLERR,"Illegal fix pair command"); + if (nevery < 1) error->all(FLERR,"Illegal fix pair every value: {}", nevery); pairname = utils::strdup(arg[4]); pstyle = force->pair_match(pairname,1,0); - if (pstyle == nullptr) error->all(FLERR,"Fix pair pair style not found"); + if (pstyle == nullptr) error->all(FLERR,"Pair style {} for fix pair not found", pairname); nfield = (narg-5) / 2; fieldname = new char*[nfield]; @@ -54,12 +54,12 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : int iarg = 5; while (iarg < narg) { - if (iarg+2 > narg) error->all(FLERR,"Illegal fix pair command"); + if (iarg+2 > narg) utils::missing_cmd_args(FLERR, fmt::format("fix pair {}", arg[iarg]), error); fieldname[nfield] = utils::strdup(arg[iarg]); int flag = utils::inumeric(FLERR,arg[iarg+1],true,lmp); if (flag == 0) trigger[nfield] = 0; else if (flag == 1) trigger[nfield] = 1; - else error->all(FLERR,"Illegal fix pair command"); + else error->all(FLERR,"Illegal fix pair {} command flag: {}", arg[iarg], arg[iarg+1]); nfield++; iarg += 2; } @@ -70,10 +70,7 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : for (int ifield = 0; ifield < nfield; ifield++) { if (trigger[ifield] == 0) triggername[ifield] = nullptr; - else { - auto str = fmt::format("%s_flag", fieldname[ifield]); - triggername[nfield] = utils::strdup(str); - } + else triggername[nfield] = utils::strdup(fmt::format("{}_flag", fieldname[ifield])); } // extract all fields just to get number of per-atom values @@ -94,10 +91,10 @@ FixPair::FixPair(LAMMPS *lmp, int narg, char **arg) : int dim; triggerptr[ifield] = (int *) pstyle->extract(triggername[ifield],dim); if (!triggerptr[ifield]) - error->all(FLERR,"Fix pair pair style cannot extract {}", - triggername[ifield]); - if (dim) error->all(FLERR,"Fix pair pair style {} is not a scalar", - triggername[ifield]); + error->all(FLERR,"Fix pair pair style cannot extract {}", triggername[ifield]); + if (dim) + error->all(FLERR,"Fix pair pair style {} trigger {} is not a scalar", + pairname, triggername[ifield]); } } @@ -145,16 +142,16 @@ FixPair::~FixPair() atom->delete_callback(id,Atom::GROW); - delete [] pairname; + delete[] pairname; for (int ifield = 0; ifield < nfield; ifield++) { - delete [] fieldname[ifield]; - delete [] triggername[ifield]; + delete[] fieldname[ifield]; + delete[] triggername[ifield]; } - delete [] fieldname; - delete [] trigger; - delete [] triggername; - delete [] triggerptr; + delete[] fieldname; + delete[] trigger; + delete[] triggername; + delete[] triggerptr; if (ncols == 1) memory->destroy(vector); else memory->destroy(array); @@ -179,7 +176,7 @@ void FixPair::init() // insure pair style still exists pstyle = force->pair_match(pairname,1,0); - if (pstyle == nullptr) error->all(FLERR,"Fix pair pair style not found"); + if (pstyle == nullptr) error->all(FLERR,"Pair style {} for fix pair not found", pairname); } /* ---------------------------------------------------------------------- */ From 2997fff361620e203ef83f4a84da0281ce2c5d3e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 14 Sep 2022 16:48:33 -0400 Subject: [PATCH 22/22] update version strings --- doc/src/dump_modify.rst | 2 +- doc/src/fix_pair.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index 275ad26325..7b16a9ce4d 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -696,7 +696,7 @@ most effective when the typical magnitude of position data is between ---------- -.. versionadded:: TBD +.. versionadded:: 15Sep2022 The *skip* keyword can be used with all dump styles. It allows a dump snapshot to be skipped (not written to the dump file), if a condition diff --git a/doc/src/fix_pair.rst b/doc/src/fix_pair.rst index 0718be5d3c..abb44718cd 100644 --- a/doc/src/fix_pair.rst +++ b/doc/src/fix_pair.rst @@ -30,7 +30,7 @@ Examples Description """"""""""" -.. versionadded:: TBD +.. versionadded:: 15Sep2022 Extract per-atom quantities from a pair style and store them in this fix so they can be accessed by other LAMMPS commands, e.g. by a