From f039c00442ea4e43ce3e031368b04015f41bdeb4 Mon Sep 17 00:00:00 2001 From: Steve Plimpton Date: Wed, 27 Jul 2022 17:13:46 -0600 Subject: [PATCH] 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