add support to flag failed arguments for calls to expand_args()

This commit is contained in:
Axel Kohlmeyer
2025-01-17 10:40:34 -05:00
parent 5a45ef6994
commit b9dbfc6eb2
4 changed files with 78 additions and 48 deletions

View File

@ -68,7 +68,7 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
} else break;
}
if (nvalues == 0)
error->all(FLERR,"No values from computes, fixes, or variables used in fix ave/time command");
error->all(FLERR, 6, "No values from computes, fixes, or variables used in fix ave/time command");
// parse optional keywords
@ -79,7 +79,8 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
int expand = 0;
char **earg;
nvalues = utils::expand_args(FLERR,nvalues,&arg[6],mode,earg,lmp);
int *amap;
nvalues = utils::expand_args(FLERR,nvalues,&arg[6],mode,earg,lmp,&amap);
key2col.clear();
if (earg != &arg[6]) expand = 1;
@ -97,9 +98,10 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
key2col[arg[i]] = i;
if ((val.which == ArgInfo::NONE) || (val.which == ArgInfo::UNKNOWN) || (argi.get_dim() > 1))
error->all(FLERR,"Invalid fix ave/time argument: {}", arg[i]);
error->all(FLERR, amap[i]+6,"Invalid fix ave/time argument: {}", arg[i]);
val.argindex = argi.get_index1();
val.iarg = amap[i] + 6;
val.varlen = 0;
val.offcol = 0;
val.id = argi.get_name();
@ -122,9 +124,9 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
// for fix inputs, check that fix frequency is acceptable
// set variable_length if any compute is variable length
if (nevery <= 0) error->all(FLERR,"Illegal fix ave/time nevery value: {}", nevery);
if (nrepeat <= 0) error->all(FLERR,"Illegal fix ave/time nrepeat value: {}", nrepeat);
if (nfreq <= 0) error->all(FLERR,"Illegal fix ave/time nfreq value: {}", nfreq);
if (nevery <= 0) error->all(FLERR, 3, "Illegal fix ave/time nevery value: {}", nevery);
if (nrepeat <= 0) error->all(FLERR, 4, "Illegal fix ave/time nrepeat value: {}", nrepeat);
if (nfreq <= 0) error->all(FLERR, 5, "Illegal fix ave/time nfreq value: {}", nfreq);
if (nfreq % nevery || nrepeat*nevery > nfreq)
error->all(FLERR,"Inconsistent fix ave/time nevery/nrepeat/nfreq values");
if (ave != RUNNING && overwrite)
@ -134,25 +136,29 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
if ((val.which == ArgInfo::COMPUTE) && (mode == SCALAR)) {
val.val.c = modify->get_compute_by_id(val.id);
if (!val.val.c) error->all(FLERR,"Compute ID {} for fix ave/time does not exist", val.id);
if (!val.val.c)
error->all(FLERR, val.iarg, "Compute ID {} for fix ave/time does not exist", val.id);
if (val.argindex == 0 && (val.val.c->scalar_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate a scalar", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate a scalar", val.id);
if (val.argindex && (val.val.c->vector_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate a vector", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate a vector", val.id);
if (val.argindex && (val.argindex > val.val.c->size_vector) &&
(val.val.c->size_vector_variable == 0))
error->all(FLERR, "Fix ave/time compute {} vector is accessed out-of-range", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} vector is accessed out-of-range",
val.id);
if (val.argindex && val.val.c->size_vector_variable) val.varlen = 1;
} else if ((val.which == ArgInfo::COMPUTE) && (mode == VECTOR)) {
val.val.c = modify->get_compute_by_id(val.id);
if (!val.val.c) error->all(FLERR,"Compute ID {} for fix ave/time does not exist", val.id);
if (!val.val.c)
error->all(FLERR, val.iarg, "Compute ID {} for fix ave/time does not exist", val.id);
if ((val.argindex == 0) && (val.val.c->vector_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate a vector", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate a vector", val.id);
if (val.argindex && (val.val.c->array_flag == 0))
error->all(FLERR,"Fix ave/time compute {} does not calculate an array", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} does not calculate an array", val.id);
if (val.argindex && (val.argindex > val.val.c->size_array_cols))
error->all(FLERR,"Fix ave/time compute {} array is accessed out-of-range", val.id);
error->all(FLERR, val.iarg, "Fix ave/time compute {} array is accessed out-of-range",
val.id);
if ((val.argindex == 0) && (val.val.c->size_vector_variable)) val.varlen = 1;
if (val.argindex && (val.val.c->size_array_rows_variable)) val.varlen = 1;
@ -1042,7 +1048,7 @@ void FixAveTime::options(int iarg, int narg, char **arg)
if (strcmp(arg[iarg],"file") == 0) fp = fopen(arg[iarg+1],"w");
else fp = fopen(arg[iarg+1],"a");
if (fp == nullptr)
error->one(FLERR,"Cannot open fix ave/time file {}: {}",
error->one(FLERR, iarg+1, "Cannot open fix ave/time file {}: {}",
arg[iarg+1], utils::getsyserror());
}
iarg += 2;
@ -1051,12 +1057,13 @@ void FixAveTime::options(int iarg, int narg, char **arg)
if (strcmp(arg[iarg+1],"one") == 0) ave = ONE;
else if (strcmp(arg[iarg+1],"running") == 0) ave = RUNNING;
else if (strcmp(arg[iarg+1],"window") == 0) ave = WINDOW;
else error->all(FLERR,"Unknown fix ave/time ave keyword {}", arg[iarg+1]);
else error->all(FLERR, iarg+1, "Unknown fix ave/time ave keyword {}", arg[iarg+1]);
if (ave == WINDOW) {
if (iarg+3 > narg) utils::missing_cmd_args(FLERR, "fix ave/time ave window", error);
nwindow = utils::inumeric(FLERR,arg[iarg+2],false,lmp);
if (nwindow <= 0)
error->all(FLERR,"Illegal fix ave/time ave window argument {}; must be > 0", nwindow);
error->all(FLERR, iarg+2, "Illegal fix ave/time ave window argument {}; must be > 0",
nwindow);
}
iarg += 2;
if (ave == WINDOW) iarg++;

View File

@ -43,6 +43,7 @@ class FixAveTime : public Fix {
struct value_t {
int which; // type of data: COMPUTE, FIX, VARIABLE
int argindex; // 1-based index if data is vector, else 0
int iarg; // argument index in original argument list
int varlen; // 1 if value is from variable-length compute
int offcol;
std::string id; // compute/fix/variable ID

View File

@ -136,7 +136,7 @@ std::string utils::point_to_error(Input *input, int failed)
{
if (input) {
std::string cmdline = "--> parsed line: ";
int indicator = cmdline.size(); // error indicator points to command by default
int indicator = cmdline.size(); // error indicator points to command by default
cmdline += input->command;
cmdline += ' ';
@ -156,7 +156,8 @@ std::string utils::point_to_error(Input *input, int failed)
cmdline += inputarg;
cmdline += '"';
}
} else cmdline += inputarg;
} else
cmdline += inputarg;
cmdline += ' ';
}
// construct and append error indicator line
@ -165,7 +166,8 @@ std::string utils::point_to_error(Input *input, int failed)
cmdline += std::string(strlen(input->arg[failed]), '^');
cmdline += '\n';
return cmdline;
} else return std::string("(Failed command line text not available)");
} else
return std::string("(Failed command line text not available)");
}
/* specialization for the case of just a single string argument */
@ -682,14 +684,14 @@ tagint utils::tnumeric(const char *file, int line, const char *str, bool do_abor
// clang-format off
template <typename TYPE>
void utils::bounds(const char *file, int line, const std::string &str,
bigint nmin, bigint nmax, TYPE &nlo, TYPE &nhi, Error *error)
bigint nmin, bigint nmax, TYPE &nlo, TYPE &nhi, Error *error, int failed)
{
nlo = nhi = -1;
// check for illegal characters
size_t found = str.find_first_not_of("*-0123456789");
if (found != std::string::npos) {
if (error) error->all(file, line, "Invalid range string: {}", str);
if (error) error->all(file, line, failed, "Invalid range string: {}", str);
return;
}
@ -712,23 +714,23 @@ void utils::bounds(const char *file, int line, const std::string &str,
if (error) {
if ((nlo <= 0) || (nhi <= 0))
error->all(file, line, "Invalid range string: {}", str);
error->all(file, line, failed, "Invalid range string: {}", str);
if (nlo < nmin)
error->all(file, line, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nmax);
error->all(file, line, failed, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nmax);
else if (nhi > nmax)
error->all(file, line, "Numeric index {} is out of bounds ({}-{})", nhi, nmin, nmax);
error->all(file, line, failed, "Numeric index {} is out of bounds ({}-{})", nhi, nmin, nmax);
else if (nlo > nhi)
error->all(file, line, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nhi);
error->all(file, line, failed, "Numeric index {} is out of bounds ({}-{})", nlo, nmin, nhi);
}
}
template void utils::bounds<>(const char *, int, const std::string &,
bigint, bigint, int &, int &, Error *);
bigint, bigint, int &, int &, Error *, int);
template void utils::bounds<>(const char *, int, const std::string &,
bigint, bigint, long &, long &, Error *);
bigint, bigint, long &, long &, Error *, int);
template void utils::bounds<>(const char *, int, const std::string &,
bigint, bigint, long long &, long long &, Error *);
bigint, bigint, long long &, long long &, Error *, int);
// clang-format on
/* ----------------------------------------------------------------------
@ -768,7 +770,7 @@ template void utils::bounds_typelabel<>(const char *, int, const std::string &,
------------------------------------------------------------------------- */
int utils::expand_args(const char *file, int line, int narg, char **arg, int mode, char **&earg,
LAMMPS *lmp)
LAMMPS *lmp, int **argmap)
{
int iarg;
@ -783,10 +785,16 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
return narg;
}
// determine argument offset
int ioffset = 0;
for (int i = 0; i < lmp->input->narg; ++i)
if (lmp->input->arg[i] == arg[0]) ioffset = i;
// maxarg should always end up equal to newarg, so caller can free earg
int maxarg = narg - iarg;
earg = (char **) lmp->memory->smalloc(maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->smalloc(maxarg * sizeof(char *), "expand_args:earg");
int *amap = (int *) lmp->memory->smalloc(maxarg * sizeof(int), "expand_args:amap");
int newarg = 0, expandflag, nlo, nhi, nmax;
std::string id, wc, tail;
@ -849,16 +857,18 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
// expand wild card string to nlo/nhi numbers
if (expandflag) {
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error);
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error, iarg + ioffset);
if (newarg + nhi - nlo + 1 > maxarg) {
maxarg += nhi - nlo + 1;
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "expand_args:earg");
amap = (int *) lmp->memory->srealloc(amap, maxarg * sizeof(char *), "expand_args:amap");
}
for (int index = nlo; index <= nhi; index++) {
earg[newarg] =
utils::strdup(fmt::format("{}:{}:{}[{}]{}", gridid[0], gridid[1], id, index, tail));
amap[newarg] = iarg;
newarg++;
}
}
@ -936,7 +946,7 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
if (index >= 0) {
if (mode == 0 && lmp->input->variable->vectorstyle(index)) {
utils::bounds(file, line, wc, 1, MAXSMALLINT, nlo, nhi, lmp->error);
utils::bounds(file, line, wc, 1, MAXSMALLINT, nlo, nhi, lmp->error, iarg + ioffset);
if (nhi < MAXSMALLINT) {
nmax = nhi;
expandflag = 1;
@ -968,11 +978,12 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
// expand wild card string to nlo/nhi numbers
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error);
utils::bounds(file, line, wc, 1, nmax, nlo, nhi, lmp->error, iarg + ioffset);
if (newarg + nhi - nlo + 1 > maxarg) {
maxarg += nhi - nlo + 1;
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "expand_args:earg");
amap = (int *) lmp->memory->srealloc(amap, maxarg * sizeof(char *), "expand_args:amap");
}
for (int index = nlo; index <= nhi; index++) {
@ -980,6 +991,7 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
earg[newarg] = utils::strdup(fmt::format("{}2_{}[{}]{}", word[0], id, index, tail));
else
earg[newarg] = utils::strdup(fmt::format("{}_{}[{}]{}", word[0], id, index, tail));
amap[newarg] = iarg;
newarg++;
}
}
@ -990,14 +1002,17 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
if (!expandflag) {
if (newarg == maxarg) {
maxarg++;
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "input:earg");
earg = (char **) lmp->memory->srealloc(earg, maxarg * sizeof(char *), "expand_args:earg");
amap = (int *) lmp->memory->srealloc(amap, maxarg * sizeof(char *), "expand_args:amap");
}
earg[newarg] = utils::strdup(word);
amap[newarg] = iarg;
newarg++;
}
}
// printf("NEWARG %d\n",newarg); for (int i = 0; i < newarg; i++) printf(" arg %d: %s\n",i,earg[i]);
if (argmap && *argmap) *argmap = amap;
// fprintf(stderr, "NEWARG %d\n",newarg); for (int i = 0; i < newarg; i++) printf(" arg %d: %s %d\n",i,earg[i], amap ? amap[i] : -1);
return newarg;
}

View File

@ -336,11 +336,12 @@ namespace utils {
* \param nmax largest allowed upper bound
* \param nlo lower bound
* \param nhi upper bound
* \param error pointer to Error class for out-of-bounds messages */
* \param error pointer to Error class for out-of-bounds messages
* \param failed argument index with failed expansion (optional) */
template <typename TYPE>
void bounds(const char *file, int line, const std::string &str, bigint nmin, bigint nmax,
TYPE &nlo, TYPE &nhi, Error *error);
TYPE &nlo, TYPE &nhi, Error *error, int failed = -2); // -2 = Error::NOPOINTER
/*! Same as utils::bounds(), but string may be a typelabel
*
@ -386,17 +387,23 @@ This functions adds the following case to :cpp:func:`utils::bounds() <LAMMPS_NS:
* caller. Otherwise arg and earg will point to the same address
* and no explicit de-allocation is needed by the caller.
*
* \param file name of source file for error message
* \param line line number in source file for error message
* \param narg number of arguments in current list
* \param arg argument list, possibly containing wildcards
* \param mode select between global vectors(=0) and arrays (=1)
* \param earg new argument list with wildcards expanded
* \param lmp pointer to top-level LAMMPS class instance
* The *argmap* pointer may be used to return an array of integers
* mapping the arguments after the expansion to their original index.
* If this pointer is NULL (the default) than this map is not created.
* Otherwise, it must be deallocated by the calling code.
*
* \param file name of source file for error message
* \param line line number in source file for error message
* \param narg number of arguments in current list
* \param arg argument list, possibly containing wildcards
* \param mode select between global vectors(=0) and arrays (=1)
* \param earg new argument list with wildcards expanded
* \param lmp pointer to top-level LAMMPS class instance
* \param argmap pointer integer list mapping the expanded indices to the input (optional)
* \return number of arguments in expanded list */
int expand_args(const char *file, int line, int narg, char **arg, int mode, char **&earg,
LAMMPS *lmp);
LAMMPS *lmp, int **argmap = nullptr);
/*! Expand type label string into its equivalent numeric type
*