git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@1351 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp 2008-01-08 23:13:53 +00:00
parent 57c7db4eb1
commit 1022815b1b
4 changed files with 435 additions and 264 deletions

View File

@ -25,7 +25,7 @@
<I>universe</I> args = one or more strings
<I>uloop</I> args = N = integer size of loop
<I>equal</I> or <I>atom</I> args = one formula containing numbers, thermo keywords, math operations, group functions, atom values and vectors, compute and fix references, other variables
numbers = 0.0, -5.4, 2.8e-4, etc
numbers = 0.0, 100, -5.4, 2.8e-4, etc
thermo keywords = vol, ke, press, etc from <A HREF = "thermo_style.html">thermo_style</A>
math operations = (), -x, x+y, x-y, x*y, x/y, x^y, sqrt(x), exp(x), ln(x)
group functions = count(group), mass(group), charge(group),
@ -35,9 +35,9 @@
vx[N], vy[N], vz[N], fx[N], fy[N], fz[N]
atom vector = mass[], x[], y[], z[],
vx[], vy[], vz[], fx[], fy[], fz[]
compute references = c_ID, c_ID[N]
fix references = f_ID, f_ID[N]
other variables = v_abc, v_x, etc
compute references = c_ID, c_ID[2], c_ID[N], c_ID[N][2], c_ID[], c_ID[][2]
fix references = f_ID, f_ID[2], f_ID[N], f_ID[N][2], f_ID[], f_ID[][2]
other variables = v_abc, v_abc[N], v_abc[]
</PRE>
</UL>
@ -210,24 +210,25 @@ operations, group functions, atom values, atom vectors, compute
references, fix references, and references to other variables.
</P>
<DIV ALIGN=center><TABLE BORDER=1 >
<TR><TD >Number</TD><TD > 0.2, 1.0e20, -15.4, etc</TD></TR>
<TR><TD >Number</TD><TD > 0.2, 100, 1.0e20, -15.4, etc</TD></TR>
<TR><TD >Thermo keywords</TD><TD > vol, pe, ebond, etc</TD></TR>
<TR><TD >Math operations</TD><TD > (), -x, x+y, x-y, x*y, x/y, x^y, sqrt(x), exp(x), ln(x)</TD></TR>
<TR><TD >Group functions</TD><TD > count(ID), mass(ID), charge(ID), xcm(ID,dim), vcm(ID,dim), fcm(ID,dim), bound(ID,dir), gyration(ID)</TD></TR>
<TR><TD >Atom values</TD><TD > mass[N], x[N], y[N], z[N], vx[N], vy[N], vz[N], fx[N], fy[N], fz[N]</TD></TR>
<TR><TD >Atom vectors</TD><TD > mass[], x[], y[], z[], vx[], vy[], vz[], fx[], fy[], fz[]</TD></TR>
<TR><TD >Compute references</TD><TD > c_ID, c_ID[N]</TD></TR>
<TR><TD >Fix references</TD><TD > f_ID, f_ID[N]</TD></TR>
<TR><TD >Other variables</TD><TD > v_abc, v_x, etc
<TR><TD >Compute references</TD><TD > c_ID, c_ID[2], c_ID[N], c_ID[N][2], c_ID[], c_ID[][2]</TD></TR>
<TR><TD >Fix references</TD><TD > f_ID, f_ID[2], f_ID[N], f_ID[N][2], f_ID[], f_ID[][2]</TD></TR>
<TR><TD >Other variables</TD><TD > v_abc, v_abc[N], v_abc[]
</TD></TR></TABLE></DIV>
<P>Note that a formula for equal-style variables cannot use any formula
element that produces per-atom values. This includes atom vectors, a
compute that produces per-atom values, a fix that produces per-atoms
values, or an atom-style variable. A formula for an atom-style
variables can use these elements, as well as elements that produce a
global scalar or vector, e.g. a compute or fix that produces global
quantities.
<P>Note that formula elements that contain empty brackets, such as an
atom vector, produce per-atom values. All other formula elements
produce a global value.
</P>
<P>A formula for equal-style variables cannot use any formula element
that produces per-atom values. A formula for an atom-style variable
can use formula elements that produce either global values or per-atom
values.
</P>
<P>The thermo keywords allowed in a formula are those defined by the
"thermo_style custom" command. Since many thermodyanmic quantities
@ -262,50 +263,65 @@ gyration</A> command for a definition of the formula.
desired atom-ID, e.g. x[243]., which means use the x coordinate of
the atom with ID=243.
</P>
<P>Atom vectors take no argument. They generate one value per atom, so
that a reference like x[] means the x-coord of each atom will be
used when evaluating the variable.
<P>Atom vectors use empty brackets, i.e. they take no argument. They
generate one value per atom, so that a reference like x[] means the
x-coord of each atom will be used when evaluating the variable.
</P>
<P>Compute references access global scalar or vector quantities or
per-atom scalar or vector quantities calculated by a
<P>Compute references access one or more quantities calculated by a
<A HREF = "compute.html">compute</A>. The ID in the reference should be replaced by
the actual ID of the compute defined elsewhere in the input script.
See the <A HREF = "compute.html">compute</A> command for details. Any specific
compute will either generate global or per-atom values, so there
is no amiguity as to which is used.
See the doc pages for individual computes to see which ones calculate
global versus per-atom quantities. If the compute reference contains
empty brackets, then per-atom values calculated by the compute are
accessed. Otherwise a single value (global or per-atom) calculated by
the compute is accessed.
</P>
<P>If <I>c_ID</I> is used as a keyword, then the scalar quantity calculated by
the compute is used (global or per-atom). If <I>c_ID[N]</I> is used,
then one component of the vector quantity calculated by the compute is
used (global or per-atom). N should be an integer from 1-M, where M
is the length of the vector calculated by the compute.
<P>The different kinds of compute references are as follows. M is a
positive integer <= the number of vector values calculated by the
compute. N is a global atom ID (positive integer).
</P>
<P>Fix references access global scalar or vector quantities or per-atom
scalar or vector quantities calculated by a <A HREF = "fix.html">fix</A>. The ID in
the reference should be replaced by the actual ID of the fix defined
elsewhere in the input script. See the doc pages for individual fixes
to see which ones compute what kind of quantities. Any specific fix
compute will either generate global or per-atom values, so there is no
amiguity as to which is used. Some fixes only generate quantities on
certain timesteps. If a variable attempts to access the fix on
non-allowed timesteps, an error is generated. For example, the <A HREF = "fix_ave_time.html">fix
ave/time</A> command may only generate averaged
quantities every 100 steps. See the <A HREF = "fix.html">fix</A> command for
details.
<DIV ALIGN=center><TABLE BORDER=1 >
<TR><TD >c_ID</TD><TD > scalar value of a global compute</TD></TR>
<TR><TD >c_ID[2]</TD><TD > vector component of a global compute</TD></TR>
<TR><TD >c_ID[N]</TD><TD > single atom's scalar value of a per-atom compute</TD></TR>
<TR><TD >c_ID[N][M]</TD><TD > single atom's vector component of a per-atom compute</TD></TR>
<TR><TD >c_ID[]</TD><TD > per-atom scalar from a per-atom compute</TD></TR>
<TR><TD >c_ID[][M]</TD><TD > per-atom vector component from a per-atom compute
</TD></TR></TABLE></DIV>
<P>Fix references access one or more quantities calculated by a
<A HREF = "fix.html">fix</A>. The ID in the reference should be replaced by
the actual ID of the fix defined elsewhere in the input script.
See the doc pages for individual computes to see which ones calculate
global versus per-atom quantities. If the compute reference contains
empty brackets, then per-atom values calculated by the compute are
accessed. Otherwise a single value (global or per-atom) calculated by
the compute is accessed.
</P>
<P>If <I>f_ID</I> is used as a keyword, then the scalar quantity calculated by
the fix is used (global or per-atom). If <I>f_ID[N]</I> is used, then
one component of the vector quantity calculated by the fix is used
(global or per-atom). N should be an integer from 1-M, where M is the
length of the vector calculated by the fix.
<P>Note that some fixes only generate quantities on certain timesteps.
If a variable attempts to access the fix on non-allowed timesteps, an
error is generated. For example, the <A HREF = "fix_ave_time.html">fix ave/time</A>
command may only generate averaged quantities every 100 steps. See
the doc pages for individual fix commands for details.
</P>
<P>The different kinds of fix references are exactly the same as the
compute references listed in the above table, where "c_" is replaced
by "f_", and the word "compute" is replaced by "fix".
</P>
<P>The current values of other variables can be accessed by prepending a
"v_" to the variable name. This will cause that variable to be
evaulated. Note that <I>equal</I> style variables generate single values
and <I>atom</I> style variables generate one value per atom. Thus an
atom-style variable cannot be referenced by the formula for an
equal-style variable, but the converse is allowed.
evaulated. Atom-style variables generate per-atom values; all other
styles of variables generate a single scalar value.
</P>
<P>The different kinds of variable references are as follows. N is a
global atom ID (positive integer).
</P>
<DIV ALIGN=center><TABLE BORDER=1 >
<TR><TD >v_ID</TD><TD > scalar value of a non atom-style variable</TD></TR>
<TR><TD >v_ID[N]</TD><TD > single atom's scalar value from an atom-style variable</TD></TR>
<TR><TD >v_ID[]</TD><TD > per-atom value from an atom-style variable
</TD></TR></TABLE></DIV>
<P>IMPORTANT NOTE: If you define variables in circular manner like this:
</P>
<PRE>variable a equal v_b
@ -359,11 +375,11 @@ the first case, but would change dynamically for the second case.
<P><B>Restrictions:</B>
</P>
<P>The use of atom values in <I>equal</I> or <I>atom</I> style variables requires
the atom style to use a global mapping in order to look up the vector
indices. By default, only atom styles with molecular information
create global maps. The <A HREF = "atom_modify.html">atom_modify map</A> command
can override the default.
<P>Indexing any formula element by global atom ID, such as an atom value,
requires the atom style to use a global mapping in order to look up
the vector indices. By default, only atom styles with molecular
information create global maps. The <A HREF = "atom_modify.html">atom_modify
map</A> command can override the default.
</P>
<P>All <I>universe</I>- and <I>uloop</I>-style variables defined in an input script
must have the same number of values.

View File

@ -20,7 +20,7 @@ style = {index} or {loop} or {world} or {universe} or {uloop} or {equal} or {ato
{universe} args = one or more strings
{uloop} args = N = integer size of loop
{equal} or {atom} args = one formula containing numbers, thermo keywords, math operations, group functions, atom values and vectors, compute and fix references, other variables
numbers = 0.0, -5.4, 2.8e-4, etc
numbers = 0.0, 100, -5.4, 2.8e-4, etc
thermo keywords = vol, ke, press, etc from "thermo_style"_thermo_style.html
math operations = (), -x, x+y, x-y, x*y, x/y, x^y, sqrt(x), exp(x), ln(x)
group functions = count(group), mass(group), charge(group),
@ -30,9 +30,9 @@ style = {index} or {loop} or {world} or {universe} or {uloop} or {equal} or {ato
vx\[N\], vy\[N\], vz\[N\], fx\[N\], fy\[N\], fz\[N\]
atom vector = mass\[\], x\[\], y\[\], z\[\],
vx\[\], vy\[\], vz\[\], fx\[\], fy\[\], fz\[\]
compute references = c_ID, c_ID\[N\]
fix references = f_ID, f_ID\[N\]
other variables = v_abc, v_x, etc :pre
compute references = c_ID, c_ID\[2\], c_ID\[N\], c_ID\[N\]\[2\], c_ID\[\], c_ID\[\]\[2\]
fix references = f_ID, f_ID\[2\], f_ID\[N\], f_ID\[N\]\[2\], f_ID\[\], f_ID\[\]\[2\]
other variables = v_abc, v_abc\[N\], v_abc\[\] :pre
:ule
[Examples:]
@ -203,7 +203,7 @@ Specifically, an formula can contain numbers, thermo keywords, math
operations, group functions, atom values, atom vectors, compute
references, fix references, and references to other variables.
Number: 0.2, 1.0e20, -15.4, etc
Number: 0.2, 100, 1.0e20, -15.4, etc
Thermo keywords: vol, pe, ebond, etc
Math operations: (), -x, x+y, x-y, x*y, x/y, x^y, sqrt(x), exp(x), ln(x)
Group functions: count(ID), mass(ID), charge(ID), xcm(ID,dim), \
@ -212,17 +212,18 @@ Atom values: mass\[N\], x\[N\], y\[N\], z\[N\], \
vx\[N\], vy\[N\], vz\[N\], fx\[N\], fy\[N\], fz\[N\]
Atom vectors: mass\[\], x\[\], y\[\], z\[\], \
vx\[\], vy\[\], vz\[\], fx\[\], fy\[\], fz\[\]
Compute references: c_ID, c_ID\[N\]
Fix references: f_ID, f_ID\[N\]
Other variables: v_abc, v_x, etc :tb(s=:)
Compute references: c_ID, c_ID\[2\], c_ID\[N\], c_ID\[N\]\[2\], c_ID\[\], c_ID\[\]\[2\]
Fix references: f_ID, f_ID\[2\], f_ID\[N\], f_ID\[N\]\[2\], f_ID\[\], f_ID\[\]\[2\]
Other variables: v_abc, v_abc\[N\], v_abc\[\] :tb(s=:)
Note that a formula for equal-style variables cannot use any formula
element that produces per-atom values. This includes atom vectors, a
compute that produces per-atom values, a fix that produces per-atoms
values, or an atom-style variable. A formula for an atom-style
variables can use these elements, as well as elements that produce a
global scalar or vector, e.g. a compute or fix that produces global
quantities.
Note that formula elements that contain empty brackets, such as an
atom vector, produce per-atom values. All other formula elements
produce a global value.
A formula for equal-style variables cannot use any formula element
that produces per-atom values. A formula for an atom-style variable
can use formula elements that produce either global values or per-atom
values.
The thermo keywords allowed in a formula are those defined by the
"thermo_style custom" command. Since many thermodyanmic quantities
@ -257,49 +258,60 @@ Atom values take a single integer argument from 1-N, which is the
desired atom-ID, e.g. x\[243\]., which means use the x coordinate of
the atom with ID=243.
Atom vectors take no argument. They generate one value per atom, so
that a reference like x\[\] means the x-coord of each atom will be
used when evaluating the variable.
Atom vectors use empty brackets, i.e. they take no argument. They
generate one value per atom, so that a reference like x\[\] means the
x-coord of each atom will be used when evaluating the variable.
Compute references access global scalar or vector quantities or
per-atom scalar or vector quantities calculated by a
Compute references access one or more quantities calculated by a
"compute"_compute.html. The ID in the reference should be replaced by
the actual ID of the compute defined elsewhere in the input script.
See the "compute"_compute.html command for details. Any specific
compute will either generate global or per-atom values, so there
is no amiguity as to which is used.
See the doc pages for individual computes to see which ones calculate
global versus per-atom quantities. If the compute reference contains
empty brackets, then per-atom values calculated by the compute are
accessed. Otherwise a single value (global or per-atom) calculated by
the compute is accessed.
If {c_ID} is used as a keyword, then the scalar quantity calculated by
the compute is used (global or per-atom). If {c_ID\[N\]} is used,
then one component of the vector quantity calculated by the compute is
used (global or per-atom). N should be an integer from 1-M, where M
is the length of the vector calculated by the compute.
The different kinds of compute references are as follows. M is a
positive integer <= the number of vector values calculated by the
compute. N is a global atom ID (positive integer).
Fix references access global scalar or vector quantities or per-atom
scalar or vector quantities calculated by a "fix"_fix.html. The ID in
the reference should be replaced by the actual ID of the fix defined
elsewhere in the input script. See the doc pages for individual fixes
to see which ones compute what kind of quantities. Any specific fix
compute will either generate global or per-atom values, so there is no
amiguity as to which is used. Some fixes only generate quantities on
certain timesteps. If a variable attempts to access the fix on
non-allowed timesteps, an error is generated. For example, the "fix
ave/time"_fix_ave_time.html command may only generate averaged
quantities every 100 steps. See the "fix"_fix.html command for
details.
c_ID: scalar value of a global compute
c_ID\[2\]: vector component of a global compute
c_ID\[N\]: single atom's scalar value of a per-atom compute
c_ID\[N\]\[M\]: single atom's vector component of a per-atom compute
c_ID\[\]: per-atom scalar from a per-atom compute
c_ID\[\]\[M\]: per-atom vector component from a per-atom compute :tb(s=:)
If {f_ID} is used as a keyword, then the scalar quantity calculated by
the fix is used (global or per-atom). If {f_ID\[N\]} is used, then
one component of the vector quantity calculated by the fix is used
(global or per-atom). N should be an integer from 1-M, where M is the
length of the vector calculated by the fix.
Fix references access one or more quantities calculated by a
"fix"_fix.html. The ID in the reference should be replaced by
the actual ID of the fix defined elsewhere in the input script.
See the doc pages for individual computes to see which ones calculate
global versus per-atom quantities. If the compute reference contains
empty brackets, then per-atom values calculated by the compute are
accessed. Otherwise a single value (global or per-atom) calculated by
the compute is accessed.
Note that some fixes only generate quantities on certain timesteps.
If a variable attempts to access the fix on non-allowed timesteps, an
error is generated. For example, the "fix ave/time"_fix_ave_time.html
command may only generate averaged quantities every 100 steps. See
the doc pages for individual fix commands for details.
The different kinds of fix references are exactly the same as the
compute references listed in the above table, where "c_" is replaced
by "f_", and the word "compute" is replaced by "fix".
The current values of other variables can be accessed by prepending a
"v_" to the variable name. This will cause that variable to be
evaulated. Note that {equal} style variables generate single values
and {atom} style variables generate one value per atom. Thus an
atom-style variable cannot be referenced by the formula for an
equal-style variable, but the converse is allowed.
evaulated. Atom-style variables generate per-atom values; all other
styles of variables generate a single scalar value.
The different kinds of variable references are as follows. N is a
global atom ID (positive integer).
v_ID: scalar value of a non atom-style variable
v_ID\[N\]: single atom's scalar value from an atom-style variable
v_ID\[\]: per-atom value from an atom-style variable :tb(s=:)
IMPORTANT NOTE: If you define variables in circular manner like this:
@ -354,11 +366,11 @@ the first case, but would change dynamically for the second case.
[Restrictions:]
The use of atom values in {equal} or {atom} style variables requires
the atom style to use a global mapping in order to look up the vector
indices. By default, only atom styles with molecular information
create global maps. The "atom_modify map"_atom_modify.html command
can override the default.
Indexing any formula element by global atom ID, such as an atom value,
requires the atom style to use a global mapping in order to look up
the vector indices. By default, only atom styles with molecular
information create global maps. The "atom_modify
map"_atom_modify.html command can override the default.
All {universe}- and {uloop}-style variables defined in an input script
must have the same number of values.

View File

@ -494,7 +494,7 @@ void Variable::copy(int narg, char **from, char **to)
}
/* ----------------------------------------------------------------------
recursive evaluation of a "string"
recursive evaluation of a string str
string is a equal-style or atom-style formula containing one or more items:
number = 0.0, -5.45, 2.8e-4, ...
thermo keyword = ke, vol, atoms, ...
@ -502,9 +502,9 @@ void Variable::copy(int narg, char **from, char **to)
group function = count(group), mass(group), xcm(group,x), ...
atom value = x[123], y[3], vx[34], ...
atom vector = x[], y[], vx[], ...
compute = c_mytemp, c_thermo_pressure[3], ...
fix = f_indent, f_setforce[3], ...
variable = v_a, v_myvar, ...
compute = c_ID, c_ID[2], c_ID[], c_ID[][2], c_ID[N], c_ID[N][2]
fix = f_ID, f_ID[2], f_ID[], f_ID[][2], f_ID[N], f_ID[N][2]
variable = v_name, v_name[], v_name[N]
if tree ptr passed in, return ptr to parse tree created for formula
if no tree ptr passed in, return value of string as double
------------------------------------------------------------------------- */
@ -513,6 +513,7 @@ double Variable::evaluate(char *str, Tree **tree)
{
int op,opprevious;
double value1,value2;
char onechar;
double argstack[MAXLEVEL];
Tree *treestack[MAXLEVEL];
@ -525,13 +526,15 @@ double Variable::evaluate(char *str, Tree **tree)
int expect = ARG;
while (1) {
char onechar = str[i];
onechar = str[i];
// whitespace: just skip
if (isspace(onechar)) i++;
// ----------------
// parentheses: recursively evaluate contents of parens
// ----------------
else if (onechar == '(') {
if (expect == OP) error->all("Invalid syntax in variable formula");
@ -551,7 +554,9 @@ double Variable::evaluate(char *str, Tree **tree)
delete [] contents;
// ----------------
// number: push value onto stack
// ----------------
} else if (isdigit(onechar) || onechar == '.') {
if (expect == OP) error->all("Invalid syntax in variable formula");
@ -578,13 +583,16 @@ double Variable::evaluate(char *str, Tree **tree)
delete [] number;
// ----------------
// letter: c_ID, f_ID, v_name, exp(), xcm(,), x[234], x[], vol
// ----------------
} else if (islower(onechar)) {
if (expect == OP) error->all("Invalid syntax in variable formula");
expect = OP;
// istop = end of word, assumed to be alphanumeric or underscore
// istop = end of word
// word = all alphanumeric or underscore
int istart = i;
while (isalnum(str[i]) || str[i] == '_') i++;
@ -595,7 +603,9 @@ double Variable::evaluate(char *str, Tree **tree)
strncpy(word,&str[istart],n);
word[n] = '\0';
// ----------------
// compute
// ----------------
if (strncmp(word,"c_",2) == 0) {
n = strlen(word) - 2 + 1;
@ -605,78 +615,119 @@ double Variable::evaluate(char *str, Tree **tree)
if (update->first_update == 0)
error->all("Compute in variable formula before initial run");
int icompute;
for (icompute = 0; icompute < modify->ncompute; icompute++)
if (strcmp(id,modify->compute[icompute]->id) == 0) break;
if (icompute == modify->ncompute)
error->all("Invalid compute ID in variable formula");
int icompute = modify->find_compute(id);
if (icompute < 0) error->all("Invalid compute ID in variable formula");
Compute *compute = modify->compute[icompute];
delete [] id;
int index = 0;
if (str[i] == '[') {
i = int_between_brackets(str,i,index,0);
// parse zero or one or two trailing brackets
// point i beyond last bracket
// nbracket = # of bracket pairs
// index1,index2 = int inside each bracket pair, 0 if empty
int nbracket,index1,index2;
if (str[i] != '[') nbracket = 0;
else {
nbracket = 1;
i = int_between_brackets(str,i,index1,1);
i++;
if (str[i] == '[') {
nbracket = 2;
i = int_between_brackets(str,i,index2,0);
i++;
}
}
// global or per-atom scalar compute
// c_ID = global scalar
if (index == 0) {
if (compute->scalar_flag) {
if (!(compute->invoked & INVOKED_SCALAR))
value1 = compute->compute_scalar();
else value1 = compute->scalar;
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
if (nbracket == 0 && compute->scalar_flag) {
} else if (compute->peratom_flag && compute->size_peratom == 0) {
if (tree == NULL)
error->all("Per-atom compute in equal-style variable formula");
if (!(compute->invoked & INVOKED_PERATOM))
compute->compute_peratom();
if (!(compute->invoked & INVOKED_SCALAR))
value1 = compute->compute_scalar();
else value1 = compute->scalar;
if (tree) {
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = compute->scalar_atom;
newtree->nstride = 1;
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else error->all("Mismatched compute in variable formula");
} else argstack[nargstack++] = value1;
// global or per-atom vector compute
// c_ID[2] = global vector
} else {
if (compute->vector_flag) {
if (index > compute->size_vector)
} else if (nbracket == 1 && index1 > 0 && compute->vector_flag) {
if (index1 > compute->size_vector)
error->all("Compute vector in variable formula is too small");
if (!(compute->invoked & INVOKED_VECTOR)) compute->compute_vector();
value1 = compute->vector[index-1];
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
} else if (compute->peratom_flag && compute->size_peratom) {
if (tree == NULL)
error->all("Per-atom compute in equal-style variable formula");
if (index > compute->size_peratom)
error->all("Compute vector in variable formula is too small");
if (!(compute->invoked & INVOKED_PERATOM))
compute->compute_peratom();
if (!(compute->invoked & INVOKED_VECTOR)) compute->compute_vector();
value1 = compute->vector[index1-1];
if (tree) {
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = &compute->vector_atom[0][index-1];
newtree->nstride = compute->size_peratom;
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else error->all("Mismatched compute in variable formula");
}
} else argstack[nargstack++] = value1;
// c_ID[] = per-atom scalar
} else if (nbracket == 1 && index1 == 0 &&
compute->peratom_flag && compute->size_peratom == 0) {
if (tree == NULL)
error->all("Per-atom compute in equal-style variable formula");
if (!(compute->invoked & INVOKED_PERATOM))
compute->compute_peratom();
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = compute->scalar_atom;
newtree->nstride = 1;
treestack[ntreestack++] = newtree;
// c_ID[N] = global value from per-atom scalar
} else if (nbracket == 1 && index1 > 0 &&
compute->peratom_flag && compute->size_peratom == 0) {
if (!(compute->invoked & INVOKED_PERATOM))
compute->compute_peratom();
peratom2global(1,NULL,compute->scalar_atom,1,index1,
tree,treestack,ntreestack,argstack,nargstack);
// c_ID[][2] = per-atom vector
} else if (nbracket == 2 && index1 == 0 && index2 > 0 &&
compute->peratom_flag) {
if (tree == NULL)
error->all("Per-atom compute in equal-style variable formula");
if (index2 > compute->size_peratom)
error->all("Compute vector in variable formula is too small");
if (!(compute->invoked & INVOKED_PERATOM))
compute->compute_peratom();
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = &compute->vector_atom[0][index2-1];
newtree->nstride = compute->size_peratom;
treestack[ntreestack++] = newtree;
// c_ID[N][2] = global value from per-atom vector
} else if (nbracket == 2 && index1 > 0 && index2 > 0 &&
compute->peratom_flag) {
if (index2 > compute->size_peratom)
error->all("Compute vector in variable formula is too small");
if (!(compute->invoked & INVOKED_PERATOM))
compute->compute_peratom();
peratom2global(1,NULL,&compute->vector_atom[0][index2-1],
compute->size_peratom,index1,
tree,treestack,ntreestack,argstack,nargstack);
} else error->all("Mismatched compute in variable formula");
// ----------------
// fix
// ----------------
} else if (strncmp(word,"f_",2) == 0) {
n = strlen(word) - 2 + 1;
@ -686,77 +737,120 @@ double Variable::evaluate(char *str, Tree **tree)
if (update->first_update == 0)
error->all("Fix in variable formula before initial run");
int ifix;
for (ifix = 0; ifix < modify->nfix; ifix++)
if (strcmp(id,modify->fix[ifix]->id) == 0) break;
if (ifix == modify->nfix)
error->all("Invalid fix ID in variable formula");
int ifix = modify->find_fix(id);
if (ifix < 0) error->all("Invalid fix ID in variable formula");
Fix *fix = modify->fix[ifix];
delete [] id;
int index = 0;
if (str[i] == '[') {
i = int_between_brackets(str,i,index,0);
// parse zero or one or two trailing brackets
// point i beyond last bracket
// nbracket = # of bracket pairs
// index1,index2 = int inside each bracket pair, 0 if empty
int nbracket,index1,index2;
if (str[i] != '[') nbracket = 0;
else {
nbracket = 1;
i = int_between_brackets(str,i,index1,1);
i++;
if (str[i] == '[') {
nbracket = 2;
i = int_between_brackets(str,i,index2,0);
i++;
}
}
// global or per-atom scalar fix
// f_ID = global scalar
if (index == 0) {
if (fix->scalar_flag) {
if (update->ntimestep % fix->scalar_vector_freq)
error->all("Fix in variable not computed at compatible time");
value1 = fix->compute_scalar();
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
if (nbracket == 0 && fix->scalar_flag) {
} else if (fix->peratom_flag && fix->size_peratom == 0) {
if (tree == NULL)
error->all("Per-atom fix in equal-style variable formula");
if (update->ntimestep % fix->peratom_freq)
error->all("Fix in variable not computed at compatible time");
if (update->ntimestep % fix->scalar_vector_freq)
error->all("Fix in variable not computed at compatible time");
value1 = fix->compute_scalar();
if (tree) {
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = fix->scalar_atom;
newtree->nstride = 1;
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else error->all("Mismatched fix in variable formula");
} else argstack[nargstack++] = value1;
// global or per-atom vector fix
// f_ID[2] = global vector
} else {
if (fix->vector_flag) {
if (index > fix->size_vector)
} else if (nbracket == 1 && index1 > 0 && fix->vector_flag) {
if (index1 > fix->size_vector)
error->all("Fix vector in variable formula is too small");
value1 = fix->compute_vector(index-1);
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
} else if (fix->peratom_flag && fix->size_peratom) {
if (tree == NULL)
error->all("Per-atom fix in equal-style variable formula");
if (index > fix->size_peratom)
error->all("Fix vector in variable formula is too small");
if (update->ntimestep % fix->peratom_freq)
error->all("Fix in variable not computed at compatible time");
if (update->ntimestep % fix->scalar_vector_freq)
error->all("Fix in variable not computed at compatible time");
value1 = fix->compute_vector(index1-1);
if (tree) {
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = &fix->vector_atom[0][index-1];
newtree->nstride = fix->size_peratom;
newtree->type = VALUE;
newtree->value = value1;
treestack[ntreestack++] = newtree;
} else error->all("Mismatched fix in variable formula");
}
} else argstack[nargstack++] = value1;
// f_ID[] = per-atom scalar
} else if (nbracket == 1 && index1 == 0 &&
fix->peratom_flag && fix->size_peratom == 0) {
if (tree == NULL)
error->all("Per-atom fix in equal-style variable formula");
if (update->ntimestep % fix->peratom_freq)
error->all("Fix in variable not computed at compatible time");
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = fix->scalar_atom;
newtree->nstride = 1;
treestack[ntreestack++] = newtree;
// f_ID[N] = global value from per-atom scalar
} else if (nbracket == 1 && index1 > 0 &&
fix->peratom_flag && fix->size_peratom == 0) {
if (update->ntimestep % fix->peratom_freq)
error->all("Fix in variable not computed at compatible time");
peratom2global(1,NULL,fix->scalar_atom,1,index1,
tree,treestack,ntreestack,argstack,nargstack);
// f_ID[][2] = per-atom vector
} else if (nbracket == 2 && index1 == 0 && index2 > 0 &&
fix->peratom_flag) {
if (tree == NULL)
error->all("Per-atom fix in equal-style variable formula");
if (index2 > fix->size_peratom)
error->all("Fix vector in variable formula is too small");
if (update->ntimestep % fix->peratom_freq)
error->all("Fix in variable not computed at compatible time");
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = &fix->vector_atom[0][index2-1];
newtree->nstride = fix->size_peratom;
treestack[ntreestack++] = newtree;
// f_ID[N][2] = global value from per-atom vector
} else if (nbracket == 2 && index1 > 0 && index2 > 0 &&
fix->peratom_flag) {
if (index2 > fix->size_peratom)
error->all("Fix vector in variable formula is too small");
if (update->ntimestep % fix->peratom_freq)
error->all("Fix in variable not computed at compatible time");
peratom2global(1,NULL,&fix->vector_atom[0][index2-1],
fix->size_peratom,index1,
tree,treestack,ntreestack,argstack,nargstack);
} else error->all("Mismatched fix in variable formula");
// ----------------
// variable
// ----------------
} else if (strncmp(word,"v_",2) == 0) {
n = strlen(word) - 2 + 1;
@ -764,29 +858,65 @@ double Variable::evaluate(char *str, Tree **tree)
strcpy(id,&word[2]);
int ivar = find(id);
if (ivar == -1) error->all("Invalid variable name in variable formula");
char *var = retrieve(id);
if (var == NULL && style[ivar] != ATOM)
error->all("Invalid variable evaluation in variable formula");
if (ivar < 0) error->all("Invalid variable name in variable formula");
if (tree) {
Tree *newtree;
if (style[ivar] != ATOM) {
newtree = new Tree();
// parse zero or one trailing brackets
// point i beyond last bracket
// nbracket = # of bracket pairs
// index = int inside bracket, 0 if empty
int nbracket,index;
if (str[i] != '[') nbracket = 0;
else {
nbracket = 1;
i = int_between_brackets(str,i,index,1);
i++;
}
// v_name = non atom-style variable = global value
if (nbracket == 0 && style[ivar] != ATOM) {
char *var = retrieve(id);
if (var == NULL)
error->all("Invalid variable evaluation in variable formula");
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = atof(var);
} else double tmp = evaluate(data[ivar][0],&newtree);
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = atof(var);
// v_name[] = atom-style variable
} else if (nbracket && index == 0 && style[ivar] == ATOM) {
if (tree == NULL)
error->all("Atom-style variable in equal-style variable formula");
Tree *newtree;
double tmp = evaluate(data[ivar][0],&newtree);
treestack[ntreestack++] = newtree;
} else {
if (style[ivar] == ATOM)
error->all("Atom-style variable in equal-style variable formula");
argstack[nargstack++] = atof(var);
}
// v_name[N] = global value from atom-style variable
// compute the per-atom variable in result
// use peratom2global to extract single value from result
} else if (nbracket && index > 0 && style[ivar] == ATOM) {
double *result = (double *)
memory->smalloc(atom->nlocal*sizeof(double),"variable:result");
compute_atom(ivar,0,result,1,0);
peratom2global(1,NULL,result,1,index,
tree,treestack,ntreestack,argstack,nargstack);
memory->sfree(result);
} else error->all("Mismatched variable in variable formula");
delete [] id;
// ----------------
// math/group function or atom value/vector or thermo keyword
// ----------------
} else {
@ -805,22 +935,27 @@ double Variable::evaluate(char *str, Tree **tree)
delete [] contents;
// ----------------
// atom value or vector
// ----------------
} else if (str[i] == '[') {
int id;
i = int_between_brackets(str,i,id,1);
i++;
// ID between brackets exists, atom value
// empty brackets, atom vector
// ID between brackets exists: atom value
// empty brackets: atom vector
if (id > 0)
atom_value(word,id,tree,treestack,ntreestack,argstack,nargstack);
peratom2global(0,word,NULL,0,id,
tree,treestack,ntreestack,argstack,nargstack);
else
atom_vector(word,tree,treestack,ntreestack);
// ----------------
// thermo keyword
// ----------------
} else {
if (update->first_update == 0)
@ -838,7 +973,9 @@ double Variable::evaluate(char *str, Tree **tree)
delete [] word;
// ----------------
// math operator, including end-of-string
// ----------------
} else if (strchr("+-*/^\0",onechar)) {
if (onechar == '+') op = ADD;
@ -1001,8 +1138,8 @@ int Variable::find_matching_paren(char *str, int i,char *&contents)
/* ----------------------------------------------------------------------
find int between brackets and set index to its value
if emptyflag and brackets empty, set index to 0
else if brackets empty, is an error
if emptyflag, then brackets can be empty (index = 0)
else if not emptyflag and brackets empty, is an error
else contents of brackets must be positive int
i = left bracket
return loc of right bracket
@ -1211,40 +1348,45 @@ int Variable::group_function(char *word, char *contents, Tree **tree,
}
/* ----------------------------------------------------------------------
process an atom value in formula
extract a global value from a per-atom quantity in a formula
flag = 0 -> word is an atom vector
flag = 1 -> vector is a per-atom compute or fix quantity with nstride
id = positive global ID of atom, converted to local index
push result onto tree or arg stack
word = atom vector
index = positive global ID of atom
customize by adding an atom vector: mass,x,y,z,vx,vy,vz,fx,fy,fz
------------------------------------------------------------------------- */
void Variable::atom_value(char *word, int id, Tree **tree,
Tree **treestack, int &ntreestack,
double *argstack, int &nargstack)
void Variable::peratom2global(int flag, char *word,
double *vector, int nstride, int id,
Tree **tree, Tree **treestack, int &ntreestack,
double *argstack, int &nargstack)
{
if (atom->map_style == 0)
error->all("Atom value in variable formula without atom map");
error->all("Indexed per-atom vector in variable formula without atom map");
int index = atom->map(id);
double mine;
if (index >= 0 && index < atom->nlocal) {
if (strcmp(word,"mass") == 0) {
if (atom->mass) mine = atom->mass[atom->type[index]];
else mine = atom->rmass[index];
}
else if (strcmp(word,"x") == 0) mine = atom->x[index][0];
else if (strcmp(word,"y") == 0) mine = atom->x[index][1];
else if (strcmp(word,"z") == 0) mine = atom->x[index][2];
else if (strcmp(word,"vx") == 0) mine = atom->v[index][0];
else if (strcmp(word,"vy") == 0) mine = atom->v[index][1];
else if (strcmp(word,"vz") == 0) mine = atom->v[index][2];
else if (strcmp(word,"fx") == 0) mine = atom->f[index][0];
else if (strcmp(word,"fy") == 0) mine = atom->f[index][1];
else if (strcmp(word,"fz") == 0) mine = atom->f[index][2];
else error->one("Invalid atom vector in variable formula");
if (flag == 0) {
if (strcmp(word,"mass") == 0) {
if (atom->mass) mine = atom->mass[atom->type[index]];
else mine = atom->rmass[index];
}
else if (strcmp(word,"x") == 0) mine = atom->x[index][0];
else if (strcmp(word,"y") == 0) mine = atom->x[index][1];
else if (strcmp(word,"z") == 0) mine = atom->x[index][2];
else if (strcmp(word,"vx") == 0) mine = atom->v[index][0];
else if (strcmp(word,"vy") == 0) mine = atom->v[index][1];
else if (strcmp(word,"vz") == 0) mine = atom->v[index][2];
else if (strcmp(word,"fx") == 0) mine = atom->f[index][0];
else if (strcmp(word,"fy") == 0) mine = atom->f[index][1];
else if (strcmp(word,"fz") == 0) mine = atom->f[index][2];
else error->one("Invalid atom vector in variable formula");
} else mine = vector[index*nstride];
} else mine = 0.0;

View File

@ -60,7 +60,8 @@ class Variable : protected Pointers {
int int_between_brackets(char *, int, int &, int);
int math_function(char *, char *, Tree **, Tree **, int &, double *, int &);
int group_function(char *, char *, Tree **, Tree **, int &, double *, int &);
void atom_value(char *, int, Tree **, Tree **, int &, double *, int &);
void peratom2global(int, char *, double *, int, int,
Tree **, Tree **, int &, double *, int &);
void atom_vector(char *, Tree **, Tree **, int &);
};