Merge pull request #3234 from lammps/variable-vector-wildcard

add support for wildcards in variable vectors
This commit is contained in:
Axel Kohlmeyer
2022-04-26 18:21:46 -04:00
committed by GitHub
7 changed files with 201 additions and 95 deletions

View File

@ -25,7 +25,7 @@ Syntax
f_ID = global scalar calculated by a fix with ID f_ID = global scalar calculated by a fix with ID
f_ID[I] = Ith component of global vector calculated by a fix with ID, I can include wildcard (see below) f_ID[I] = Ith component of global vector calculated by a fix with ID, I can include wildcard (see below)
v_name = global value calculated by an equal-style variable with name v_name = global value calculated by an equal-style variable with name
v_name[I] = Ith component of a vector-style variable with name v_name[I] = Ith component of a vector-style variable with name, I can include wildcard (see below)
* zero or more keyword/arg pairs may be appended * zero or more keyword/arg pairs may be appended
* keyword = *type* or *ave* or *start* or *prefactor* or *file* or *overwrite* or *title1* or *title2* or *title3* * keyword = *type* or *ave* or *start* or *prefactor* or *file* or *overwrite* or *title1* or *title2* or *title3*
@ -105,20 +105,21 @@ individual fixes for info on which ones produce such values.
ones that can be used with this fix. Variables of style *atom* cannot ones that can be used with this fix. Variables of style *atom* cannot
be used, since they produce per-atom values. be used, since they produce per-atom values.
Note that for values from a compute or fix, the bracketed index I can ----------
be specified using a wildcard asterisk with the index to effectively
specify multiple values. This takes the form "\*" or "\*n" or "n\*" or For input values from a compute or fix or variable , the bracketed
"m\*n". If N = the size of the vector (for *mode* = scalar) or the index I can be specified using a wildcard asterisk with the index to
number of columns in the array (for *mode* = vector), then an asterisk effectively specify multiple values. This takes the form "\*" or
with no numeric values means all indices from 1 to N. A leading "\*n" or "n\*" or "m\*n". If N = the size of the vector, then an
asterisk means all indices from 1 to n (inclusive). A trailing asterisk with no numeric values means all indices from 1 to N. A
asterisk means all indices from n to N (inclusive). A middle asterisk leading asterisk means all indices from 1 to n (inclusive). A
means all indices from m to n (inclusive). trailing asterisk means all indices from n to N (inclusive). A middle
asterisk means all indices from m to n (inclusive).
Using a wildcard is the same as if the individual elements of the Using a wildcard is the same as if the individual elements of the
vector had been listed one by one. E.g. these 2 fix ave/correlate vector had been listed one by one. E.g. these 2 fix ave/correlate
commands are equivalent, since the :doc:`compute pressure <compute_pressure>` command creates a global vector with 6 commands are equivalent, since the :doc:`compute pressure
values. <compute_pressure>` command creates a global vector with 6 values.
.. code-block:: LAMMPS .. code-block:: LAMMPS
@ -128,6 +129,14 @@ values.
c_myPress[1] c_myPress[2] c_myPress[3] & c_myPress[1] c_myPress[2] c_myPress[3] &
c_myPress[4] c_myPress[5] c_myPress[6] c_myPress[4] c_myPress[5] c_myPress[6]
.. note::
For a vector-style variable, only the wildcard forms "\*n" or
"m\*n" are allowed. You must specify the upper bound, because
vector-style variable lengths are not determined until the variable
is evaluated. If n is specified larger than the vector length
turns out to be, zeroes are output for missing vector values.
---------- ----------
The *Nevery*, *Nrepeat*, and *Nfreq* arguments specify on what The *Nevery*, *Nrepeat*, and *Nfreq* arguments specify on what

View File

@ -32,7 +32,7 @@ Syntax
f_ID = scalar or vector calculated by a fix with ID f_ID = scalar or vector calculated by a fix with ID
f_ID[I] = Ith component of vector or Ith column of array calculated by a fix with ID, I can include wildcard (see below) f_ID[I] = Ith component of vector or Ith column of array calculated by a fix with ID, I can include wildcard (see below)
v_name = value(s) calculated by an equal-style or vector-style or atom-style variable with name v_name = value(s) calculated by an equal-style or vector-style or atom-style variable with name
v_name[I] = value calculated by a vector-style variable with name v_name[I] = value calculated by a vector-style variable with name, I can include wildcard (see below)
* zero or more keyword/arg pairs may be appended * zero or more keyword/arg pairs may be appended
* keyword = *mode* or *file* or *ave* or *start* or *beyond* or *overwrite* or *title1* or *title2* or *title3* * keyword = *mode* or *file* or *ave* or *start* or *beyond* or *overwrite* or *title1* or *title2* or *title3*
@ -120,27 +120,6 @@ If *mode* = vector, then the input values must be vectors, or arrays
with a bracketed term appended, indicating the Ith column of the array with a bracketed term appended, indicating the Ith column of the array
is used. is used.
Note that for values from a compute or fix, the bracketed index I can
be specified using a wildcard asterisk with the index to effectively
specify multiple values. This takes the form "\*" or "\*n" or "n\*" or
"m\*n". If N = the size of the vector (for *mode* = scalar) or the
number of columns in the array (for *mode* = vector), then an asterisk
with no numeric values means all indices from 1 to N. A leading
asterisk means all indices from 1 to n (inclusive). A trailing
asterisk means all indices from n to N (inclusive). A middle asterisk
means all indices from m to n (inclusive).
Using a wildcard is the same as if the individual elements of the
vector or columns of the array had been listed one by one. E.g. these
2 fix ave/histo commands are equivalent, since the :doc:`compute com/chunk <compute_com_chunk>` command creates a global array with
3 columns:
.. code-block:: LAMMPS
compute myCOM all com/chunk
fix 1 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[*] file tmp1.com mode vector
fix 2 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[1] c_myCOM[2] c_myCOM[3] file tmp2.com mode vector
If the fix ave/histo/weight command is used, exactly two values must If the fix ave/histo/weight command is used, exactly two values must
be specified. If the values are vectors, they must be the same be specified. If the values are vectors, they must be the same
length. The first value (a scalar or vector) is what is histogrammed length. The first value (a scalar or vector) is what is histogrammed
@ -153,6 +132,38 @@ the first vector.
---------- ----------
For input values from a compute or fix or variable, the bracketed
index I can be specified using a wildcard asterisk with the index to
effectively specify multiple values. This takes the form "\*" or
"\*n" or "n\*" or "m\*n". If N = the size of the vector (for *mode* =
scalar) or the number of columns in the array (for *mode* = vector),
then an asterisk with no numeric values means all indices from 1 to N.
A leading asterisk means all indices from 1 to n (inclusive). A
trailing asterisk means all indices from n to N (inclusive). A middle
asterisk means all indices from m to n (inclusive).
Using a wildcard is the same as if the individual elements of the
vector or columns of the array had been listed one by one. E.g. these
2 fix ave/histo commands are equivalent, since the :doc:`compute
com/chunk <compute_com_chunk>` command creates a global array with 3
columns:
.. code-block:: LAMMPS
compute myCOM all com/chunk
fix 1 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[*] file tmp1.com mode vector
fix 2 all ave/histo 100 1 100 -10.0 10.0 100 c_myCOM[1] c_myCOM[2] c_myCOM[3] file tmp2.com mode vector
.. note::
For a vector-style variable, only the wildcard forms "\*n" or
"m\*n" are allowed. You must specify the upper bound, because
vector-style variable lengths are not determined until the variable
is evaluated. If n is specified larger than the vector length
turns out to be, zeroes are output for missing vector values.
----------
The *Nevery*, *Nrepeat*, and *Nfreq* arguments specify on what The *Nevery*, *Nrepeat*, and *Nfreq* arguments specify on what
timesteps the input values will be used in order to contribute to the timesteps the input values will be used in order to contribute to the
histogram. The final histogram is generated on timesteps that are histogram. The final histogram is generated on timesteps that are

View File

@ -25,7 +25,7 @@ Syntax
f_ID = global scalar or vector calculated by a fix with ID f_ID = global scalar or vector calculated by a fix with ID
f_ID[I] = Ith component of global vector or Ith column of global array calculated by a fix with ID, I can include wildcard (see below) f_ID[I] = Ith component of global vector or Ith column of global array calculated by a fix with ID, I can include wildcard (see below)
v_name = value(s) calculated by an equal-style or vector-style variable with name v_name = value(s) calculated by an equal-style or vector-style variable with name
v_name[I] = value calculated by a vector-style variable with name v_name[I] = value calculated by a vector-style variable with name, I can include wildcard (see below)
* zero or more keyword/arg pairs may be appended * zero or more keyword/arg pairs may be appended
* keyword = *mode* or *file* or *ave* or *start* or *off* or *overwrite* or *title1* or *title2* or *title3* * keyword = *mode* or *file* or *ave* or *start* or *off* or *overwrite* or *title1* or *title2* or *title3*
@ -113,20 +113,23 @@ with a bracketed term appended, indicating the Ith column of the array
is used. All vectors must be the same length, which is the length of is used. All vectors must be the same length, which is the length of
the vector or number of rows in the array. the vector or number of rows in the array.
Note that for values from a compute or fix, the bracketed index I can ----------
be specified using a wildcard asterisk with the index to effectively
specify multiple values. This takes the form "\*" or "\*n" or "n\*" or For input values from a compute or fix or variable, the bracketed
"m\*n". If N = the size of the vector (for *mode* = scalar) or the index I can be specified using a wildcard asterisk with the index to
number of columns in the array (for *mode* = vector), then an asterisk effectively specify multiple values. This takes the form "\*" or
with no numeric values means all indices from 1 to N. A leading "\*n" or "n\*" or "m\*n". If N = the size of the vector (for *mode* =
asterisk means all indices from 1 to n (inclusive). A trailing scalar) or the number of columns in the array (for *mode* = vector),
asterisk means all indices from n to N (inclusive). A middle asterisk then an asterisk with no numeric values means all indices from 1 to N.
means all indices from m to n (inclusive). A leading asterisk means all indices from 1 to n (inclusive). A
trailing asterisk means all indices from n to N (inclusive). A middle
asterisk means all indices from m to n (inclusive).
Using a wildcard is the same as if the individual elements of the Using a wildcard is the same as if the individual elements of the
vector or columns of the array had been listed one by one. E.g. these vector or columns of the array had been listed one by one. E.g. these
2 fix ave/time commands are equivalent, since the :doc:`compute rdf <compute_rdf>` command creates, in this case, a global array 2 fix ave/time commands are equivalent, since the :doc:`compute rdf
with 3 columns, each of length 50: <compute_rdf>` command creates, in this case, a global array with 3
columns, each of length 50:
.. code-block:: LAMMPS .. code-block:: LAMMPS
@ -134,6 +137,14 @@ with 3 columns, each of length 50:
fix 1 all ave/time 100 1 100 c_myRDF[*] file tmp1.rdf mode vector fix 1 all ave/time 100 1 100 c_myRDF[*] file tmp1.rdf mode vector
fix 2 all ave/time 100 1 100 c_myRDF[1] c_myRDF[2] c_myRDF[3] file tmp2.rdf mode vector fix 2 all ave/time 100 1 100 c_myRDF[1] c_myRDF[2] c_myRDF[3] file tmp2.rdf mode vector
.. note::
For a vector-style variable, only the wildcard forms "\*n" or
"m\*n" are allowed. You must specify the upper bound, because
vector-style variable lengths are not determined until the variable
is evaluated. If n is specified larger than the vector length
turns out to be, zeroes are output for missing vector values.
---------- ----------
The *Nevery*, *Nrepeat*, and *Nfreq* arguments specify on what The *Nevery*, *Nrepeat*, and *Nfreq* arguments specify on what
@ -169,9 +180,12 @@ asterisk to effectively specify multiple values.
Note that there is a :doc:`compute reduce <compute_reduce>` command Note that there is a :doc:`compute reduce <compute_reduce>` command
which can sum per-atom quantities into a global scalar or vector which which can sum per-atom quantities into a global scalar or vector which
can thus be accessed by fix ave/time. Or it can be a compute defined can thus be accessed by fix ave/time. Or it can be a compute defined
not in your input script, but by :doc:`thermodynamic output <thermo_style>` or other fixes such as :doc:`fix nvt <fix_nh>` or :doc:`fix temp/rescale <fix_temp_rescale>`. See not in your input script, but by :doc:`thermodynamic output
the doc pages for these commands which give the IDs of these computes. <thermo_style>` or other fixes such as :doc:`fix nvt <fix_nh>` or
Users can also write code for their own compute styles and :doc:`add them to LAMMPS <Modify>`. :doc:`fix temp/rescale <fix_temp_rescale>`. See the doc pages for
these commands which give the IDs of these computes. Users can also
write code for their own compute styles and :doc:`add them to LAMMPS
<Modify>`.
If a value begins with "f\_", a fix ID must follow which has been If a value begins with "f\_", a fix ID must follow which has been
previously defined in the input script. If *mode* = scalar, then if previously defined in the input script. If *mode* = scalar, then if

View File

@ -85,7 +85,7 @@ Syntax
f_ID[I] = Ith component of global vector calculated by a fix with ID, I can include wildcard (see below) f_ID[I] = Ith component of global vector calculated by a fix with ID, I can include wildcard (see below)
f_ID[I][J] = I,J component of global array calculated by a fix with ID f_ID[I][J] = I,J component of global array calculated by a fix with ID
v_name = value calculated by an equal-style variable with name v_name = value calculated by an equal-style variable with name
v_name[I] = value calculated by a vector-style variable with name v_name[I] = value calculated by a vector-style variable with name, I can include wildcard (see below)
Examples Examples
"""""""" """"""""
@ -348,16 +348,15 @@ dimensions *lx*, *ly*, *lz*, *yz*, *xz*, *xy*\ .
---------- ----------
For output values from a compute or fix, the bracketed index I used to For output values from a compute or fix or variable, the bracketed
index a vector, as in *c_ID[I]* or *f_ID[I]*, can be specified index I used to index a vector, as in *c_ID[I]* or *f_ID[I]* or
using a wildcard asterisk with the index to effectively specify *v_name[I]*, can be specified using a wildcard asterisk with the index
multiple values. This takes the form "\*" or "\*n" or "n\*" or "m\*n". to effectively specify multiple values. This takes the form "\*" or
If N = the size of the vector (for *mode* = scalar) or the number of "\*n" or "n\*" or "m\*n". If N = the size of the vector, then an
columns in the array (for *mode* = vector), then an asterisk with no asterisk with no numeric values means all indices from 1 to N. A
numeric values means all indices from 1 to N. A leading asterisk leading asterisk means all indices from 1 to n (inclusive). A
means all indices from 1 to n (inclusive). A trailing asterisk means trailing asterisk means all indices from n to N (inclusive). A middle
all indices from n to N (inclusive). A middle asterisk means all asterisk means all indices from m to n (inclusive).
indices from m to n (inclusive).
Using a wildcard is the same as if the individual elements of the Using a wildcard is the same as if the individual elements of the
vector had been listed one by one. E.g. these 2 thermo_style commands vector had been listed one by one. E.g. these 2 thermo_style commands
@ -372,6 +371,15 @@ creates a global vector with 6 values.
c_myTemp[1] c_myTemp[2] c_myTemp[3] & c_myTemp[1] c_myTemp[2] c_myTemp[3] &
c_myTemp[4] c_myTemp[5] c_myTemp[6] c_myTemp[4] c_myTemp[5] c_myTemp[6]
.. note::
For a vector-style variable, only the wildcard forms "\*n" or
"m\*n" are allowed. You must specify the upper bound, because
vector-style variable lengths are not determined until the variable
is evaluated. If n is specified larger than the vector length
turns out to be, zeroes are output for missing vector values.
---------- ----------
The *c_ID* and *c_ID[I]* and *c_ID[I][J]* keywords allow global values The *c_ID* and *c_ID[I]* and *c_ID[I][J]* keywords allow global values

View File

@ -136,5 +136,6 @@ variable C46 equal v_F46+v_B[20]
variable C56 equal v_F56+v_B[21] variable C56 equal v_F56+v_B[21]
thermo ${nthermo} thermo ${nthermo}
thermo_style custom step temp pe press density f_avt f_avp f_avpe v_F11 v_F22 v_F33 v_F44 v_F55 v_F66 v_F12 v_F13 v_F23 v_B[1] v_B[2] v_B[3] v_B[4] v_B[5] v_B[6] v_B[7] v_B[8] v_B[12] thermo_style custom step temp pe press density f_avt f_avp f_avpe v_F11 v_F22 v_F33 v_F44 v_F55 v_F66 v_F12 v_F13 v_F23 v_B[*8] v_B[12]
thermo_modify norm no thermo_modify norm no

View File

@ -19,11 +19,13 @@
#include "error.h" #include "error.h"
#include "fix.h" #include "fix.h"
#include "fmt/chrono.h" #include "fmt/chrono.h"
#include "input.h"
#include "memory.h" #include "memory.h"
#include "modify.h" #include "modify.h"
#include "text_file_reader.h" #include "text_file_reader.h"
#include "universe.h" #include "universe.h"
#include "update.h" #include "update.h"
#include "variable.h"
#include <cctype> #include <cctype>
#include <cerrno> #include <cerrno>
@ -631,7 +633,7 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
// match compute, fix, or custom property array reference with a '*' wildcard // match compute, fix, or custom property array reference with a '*' wildcard
// number range in the first pair of square brackets // number range in the first pair of square brackets
if (strmatch(word, "^[cf]_\\w+\\[\\d*\\*\\d*\\]") || if (strmatch(word, "^[cfv]_\\w+\\[\\d*\\*\\d*\\]") ||
strmatch(word, "^[id]2_\\w+\\[\\d*\\*\\d*\\]")) { strmatch(word, "^[id]2_\\w+\\[\\d*\\*\\d*\\]")) {
// split off the compute/fix/property ID, the wildcard and trailing text // split off the compute/fix/property ID, the wildcard and trailing text
@ -692,6 +694,23 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
} }
} }
// vector variable
} else if (word[0] == 'v') {
int index = lmp->input->variable->find(id.c_str());
// check for global vector/array, peratom array, local array
if (index >= 0) {
if (mode == 0 && lmp->input->variable->vectorstyle(index)) {
utils::bounds(file, line, wc, 1, MAXSMALLINT, nlo, nhi, lmp->error);
if (nhi < MAXSMALLINT) {
nmax = nhi;
expandflag = 1;
}
}
}
// only match custom array reference with a '*' wildcard // only match custom array reference with a '*' wildcard
// number range in the first pair of square brackets // number range in the first pair of square brackets
@ -716,6 +735,7 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
if (expandflag) { if (expandflag) {
// expand wild card string to nlo/nhi numbers // 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);
if (newarg + nhi - nlo + 1 > maxarg) { if (newarg + nhi - nlo + 1 > maxarg) {

View File

@ -128,52 +128,95 @@ TEST_F(Advanced_utils, expand_args)
args = new char *[oarg]; args = new char *[oarg];
args[0] = utils::strdup("v_step"); args[0] = utils::strdup("v_step");
args[1] = utils::strdup("c_temp"); args[1] = utils::strdup("c_temp");
args[2] = utils::strdup("f_1[2*]"); args[2] = utils::strdup("f_1[*]");
args[3] = utils::strdup("c_temp[2*4]"); args[3] = utils::strdup("c_temp[2*4]");
args[4] = utils::strdup("v_temp[*4]"); args[4] = utils::strdup("v_temp[*4]");
args[5] = utils::strdup("c_rdf[*]"); args[5] = utils::strdup("c_gofr[3*]");
args[6] = utils::strdup("c_rdf[1][*]"); args[6] = utils::strdup("c_gofr[1][*]");
args[7] = utils::strdup("c_rdf[*][2]"); args[7] = utils::strdup("c_gofr[*2][2]");
args[8] = utils::strdup("c_rdf[*][*]"); args[8] = utils::strdup("c_gofr[*][*]");
auto narg = utils::expand_args(FLERR, oarg, args, 0, earg, lmp); auto narg = utils::expand_args(FLERR, oarg, args, 0, earg, lmp);
EXPECT_EQ(narg, 12); EXPECT_EQ(narg, 16);
EXPECT_STREQ(earg[0], "v_step"); EXPECT_STREQ(earg[0], "v_step");
EXPECT_STREQ(earg[1], "c_temp"); EXPECT_STREQ(earg[1], "c_temp");
EXPECT_STREQ(earg[2], "f_1[2]"); EXPECT_STREQ(earg[2], "f_1[1]");
EXPECT_STREQ(earg[3], "f_1[3]"); EXPECT_STREQ(earg[3], "f_1[2]");
EXPECT_STREQ(earg[4], "c_temp[2]"); EXPECT_STREQ(earg[4], "f_1[3]");
EXPECT_STREQ(earg[5], "c_temp[3]"); EXPECT_STREQ(earg[5], "c_temp[2]");
EXPECT_STREQ(earg[6], "c_temp[4]"); EXPECT_STREQ(earg[6], "c_temp[3]");
EXPECT_STREQ(earg[7], "v_temp[*4]"); EXPECT_STREQ(earg[7], "c_temp[4]");
EXPECT_STREQ(earg[8], "c_rdf[*]"); EXPECT_STREQ(earg[8], "v_temp[1]");
EXPECT_STREQ(earg[9], "c_rdf[1][*]"); EXPECT_STREQ(earg[9], "v_temp[2]");
EXPECT_STREQ(earg[10], "c_rdf[*][2]"); EXPECT_STREQ(earg[10], "v_temp[3]");
EXPECT_STREQ(earg[11], "c_rdf[*][*]"); EXPECT_STREQ(earg[11], "v_temp[4]");
EXPECT_STREQ(earg[12], "c_gofr[3*]");
EXPECT_STREQ(earg[13], "c_gofr[1][*]");
EXPECT_STREQ(earg[14], "c_gofr[*2][2]");
EXPECT_STREQ(earg[15], "c_gofr[*][*]");
for (int i = 0; i < narg; ++i) for (int i = 0; i < narg; ++i)
delete[] earg[i]; delete[] earg[i];
lmp->memory->sfree(earg); lmp->memory->sfree(earg);
narg = utils::expand_args(FLERR, oarg, args, 1, earg, lmp); narg = utils::expand_args(FLERR, oarg, args, 1, earg, lmp);
EXPECT_EQ(narg, oarg); EXPECT_EQ(narg, 16);
EXPECT_NE(args, earg); EXPECT_NE(args, earg);
EXPECT_STREQ(earg[0], "v_step"); EXPECT_STREQ(earg[0], "v_step");
EXPECT_STREQ(earg[1], "c_temp"); EXPECT_STREQ(earg[1], "c_temp");
EXPECT_STREQ(earg[2], "f_1[2*]"); EXPECT_STREQ(earg[2], "f_1[*]");
EXPECT_STREQ(earg[3], "c_temp[2*4]"); EXPECT_STREQ(earg[3], "c_temp[2*4]");
EXPECT_STREQ(earg[4], "v_temp[*4]"); EXPECT_STREQ(earg[4], "v_temp[*4]");
EXPECT_STREQ(earg[5], "c_rdf[*]"); EXPECT_STREQ(earg[5], "c_gofr[3]");
EXPECT_STREQ(earg[6], "c_rdf[1][*]"); EXPECT_STREQ(earg[6], "c_gofr[4]");
EXPECT_STREQ(earg[7], "c_rdf[*][2]"); EXPECT_STREQ(earg[7], "c_gofr[5]");
EXPECT_STREQ(earg[8], "c_rdf[*][*]"); EXPECT_STREQ(earg[8], "c_gofr[1][*]");
EXPECT_STREQ(earg[9], "c_gofr[1][2]");
EXPECT_STREQ(earg[10], "c_gofr[2][2]");
EXPECT_STREQ(earg[11], "c_gofr[1][*]");
EXPECT_STREQ(earg[12], "c_gofr[2][*]");
EXPECT_STREQ(earg[13], "c_gofr[3][*]");
EXPECT_STREQ(earg[14], "c_gofr[4][*]");
EXPECT_STREQ(earg[15], "c_gofr[5][*]");
for (int i = 0; i < oarg; ++i)
delete[] args[i];
delete[] args;
for (int i = 0; i < narg; ++i) for (int i = 0; i < narg; ++i)
delete[] earg[i]; delete[] earg[i];
lmp->memory->sfree(earg); lmp->memory->sfree(earg);
args[3][9] = '9';
TEST_FAILURE("ERROR: Numeric index 9 is out of bounds \\(1-6\\).*",
utils::expand_args(FLERR, oarg, args, 0, earg, lmp););
args[3][9] = '4';
args[5][7] = '9';
TEST_FAILURE("ERROR: Numeric index 9 is out of bounds \\(1-5\\).*",
utils::expand_args(FLERR, oarg, args, 1, earg, lmp););
args[5][7] = '3';
delete[] args[4];
args[4] = utils::strdup("v_temp[2*]");
narg = utils::expand_args(FLERR, oarg, args, 0, earg, lmp);
EXPECT_EQ(narg, 13);
EXPECT_STREQ(earg[0], "v_step");
EXPECT_STREQ(earg[1], "c_temp");
EXPECT_STREQ(earg[2], "f_1[1]");
EXPECT_STREQ(earg[3], "f_1[2]");
EXPECT_STREQ(earg[4], "f_1[3]");
EXPECT_STREQ(earg[5], "c_temp[2]");
EXPECT_STREQ(earg[6], "c_temp[3]");
EXPECT_STREQ(earg[7], "c_temp[4]");
EXPECT_STREQ(earg[8], "v_temp[2*]");
EXPECT_STREQ(earg[9], "c_gofr[3*]");
EXPECT_STREQ(earg[10], "c_gofr[1][*]");
EXPECT_STREQ(earg[11], "c_gofr[*2][2]");
EXPECT_STREQ(earg[12], "c_gofr[*][*]");
for (int i = 0; i < narg; ++i)
delete[] earg[i];
lmp->memory->sfree(earg);
for (int i = 0; i < oarg; ++i)
delete[] args[i];
delete[] args;
} }
} // namespace LAMMPS_NS } // namespace LAMMPS_NS