update variable doc page to explain new behavior

This commit is contained in:
Steve Plimpton
2023-05-08 09:48:27 -06:00
parent 49ac79fcdd
commit 200f740c06

View File

@ -1285,18 +1285,19 @@ with a leading $ sign (e.g. $x or ${abc}) versus with a leading "v\_"
(e.g. v_x or v_abc). The former can be used in any input script
command, including a variable command. The input script parser
evaluates the reference variable immediately and substitutes its value
into the command. As explained on the :doc:`Commands parse <Commands_parse>` doc page, you can also use un-named
"immediate" variables for this purpose. For example, a string like
this $((xlo+xhi)/2+sqrt(v_area)) in an input script command evaluates
the string between the parenthesis as an equal-style variable formula.
into the command. As explained on the :doc:`Commands parse
<Commands_parse>` doc page, you can also use un-named "immediate"
variables for this purpose. For example, a string like this
$((xlo+xhi)/2+sqrt(v_area)) in an input script command evaluates the
string between the parenthesis as an equal-style variable formula.
Referencing a variable with a leading "v\_" is an optional or required
kind of argument for some commands (e.g. the :doc:`fix ave/chunk <fix_ave_chunk>` or :doc:`dump custom <dump>` or
:doc:`thermo_style <thermo_style>` commands) if you wish it to evaluate
a variable periodically during a run. It can also be used in a
variable formula if you wish to reference a second variable. The
second variable will be evaluated whenever the first variable is
evaluated.
kind of argument for some commands (e.g. the :doc:`fix ave/chunk
<fix_ave_chunk>` or :doc:`dump custom <dump>` or :doc:`thermo_style
<thermo_style>` commands) if you wish it to evaluate a variable
periodically during a run. It can also be used in a variable formula
if you wish to reference a second variable. The second variable will
be evaluated whenever the first variable is evaluated.
As an example, suppose you use this command in your input script to
define the variable "v" as
@ -1309,8 +1310,9 @@ before a run where the simulation box size changes. You might think
this will assign the initial volume to the variable "v". That is not
the case. Rather it assigns a formula which evaluates the volume
(using the thermo_style keyword "vol") to the variable "v". If you
use the variable "v" in some other command like :doc:`fix ave/time <fix_ave_time>` then the current volume of the box will be
evaluated continuously during the run.
use the variable "v" in some other command like :doc:`fix ave/time
<fix_ave_time>` then the current volume of the box will be evaluated
continuously during the run.
If you want to store the initial volume of the system, you can do it
this way:
@ -1347,132 +1349,75 @@ will occur when the formula for "vratio" is evaluated later.
Variable Accuracy
"""""""""""""""""
Obviously, LAMMPS attempts to evaluate variables containing formulas
(\ *equal* and *atom* style variables) accurately whenever the
evaluation is performed. Depending on what is included in the
formula, this may require invoking a :doc:`compute <compute>`, either
directly or indirectly via a thermo keyword, or accessing a value
previously calculated by a compute, or accessing a value calculated
and stored by a :doc:`fix <fix>`. If the compute is one that calculates
the pressure or energy of the system, then these quantities need to be
tallied during the evaluation of the interatomic potentials (pair,
bond, etc) on timesteps that the variable will need the values.
Obviously, LAMMPS attempts to evaluate variables which contain
formulas (\ *equal* and *vector* and *atom* style variables)
accurately whenever the evaluation is performed. Depending on what is
included in the formula, this may require invoking a :doc:`compute
<compute>`, either directly or indirectly via a thermo keyword, or
accessing a value previously calculated by a compute, or accessing a
value calculated and stored by a :doc:`fix <fix>`. If the compute is
one that calculates the energy or pressure of the system, then the
corresponding energy or virial quantities need to be tallied during
the evaluation of the interatomic potentials (pair, bond, etc) on any
timestep that the variable needs the tallies. An input script can
also request variables be evaluated before or after or in between
runs, e.g. by including them in a :doc:`print <print>` command.
LAMMPS keeps track of all of this during a :doc:`run <run>` or :doc:`energy minimization <minimize>`. An error will be generated if you
attempt to evaluate a variable on timesteps when it cannot produce
accurate values. For example, if a :doc:`thermo_style custom <thermo_style>` command prints a variable which accesses
values stored by a :doc:`fix ave/time <fix_ave_time>` command and the
timesteps on which thermo output is generated are not multiples of the
averaging frequency used in the fix command, then an error will occur.
LAMMPS keeps track of all of this as it performs a doc:`run <run>` or
:doc:`minimize <minimize>` simulation, as well as in between
simulations. An error will be generated if you attempt to evaluate a
variable when LAMMPS knows it cannot produce accurate values. For
example, if a :doc:`thermo_style custom <thermo_style>` command prints
a variable which accesses values stored by a :doc:`fix ave/time
<fix_ave_time>` command and the timesteps on which thermo output is
generated are not multiples of the averaging frequency used in the fix
command, then an error will occur.
An input script can also request variables be evaluated before or
after or in between runs, e.g. by including them in a
:doc:`print <print>` command. In this case, if a compute is needed to
evaluate a variable (either directly or indirectly), LAMMPS will not
invoke the compute, but it will use a value previously calculated by
the compute, and can do this only if it was invoked on the current
timestep. Fixes will always provide a quantity needed by a variable,
but the quantity may or may not be current. This leads to one of
three kinds of behavior:
However, there are two special cases to be aware when a variable
requires invocation of a compute (directly or indirectly). The first
is if the variable is evaluated before the first doc:`run <run>` or
:doc:`minimize <minimize>` command in the input script. In this case,
LAMMPS will generate an error. This is because many computes require
initializations which have not yet taken place. One example is the
calculation of degrees of freedom for temperature computes. Another
example are the computes mentioned above which require tallying of
energy or virial quantities; these values are not tallied until the
first simulation begins.
(1) The variable may be evaluated accurately. If it contains
references to a compute or fix, and these values were calculated on
the last timestep of a preceding run, then they will be accessed and
used by the variable and the result will be accurate.
The second special case is when a variable that depends on a compute
is evaluated in between doc:`run <run>` or :doc:`minimize <minimize>`
commands. It is possible for other input script commands issued
following the previous run, but before the variable is evaluated, to
change the system. For example, the doc:`delete_atoms <delete_atoms>`
command could be used to remove atoms. Since the compute will not
re-initialize itself until the next simulation or it may depend on
energy/virial computations performed before the system was changed, it
will potentially generate an incorrect answer when evaluated. Note
that LAMMPS will not generate an error in this case; the evaluated
variable may simply be incorrect.
(2) LAMMPS may not be able to evaluate the variable and will generate
an error message stating so. For example, if the variable requires a
quantity from a :doc:`compute <compute>` that has not been invoked on
the current timestep, LAMMPS will generate an error. This means, for
example, that such a variable cannot be evaluated before the first run
has occurred. Likewise, in between runs, a variable containing a
compute cannot be evaluated unless the compute was invoked on the last
timestep of the preceding run, e.g. by thermodynamic output.
One way to get around this problem is to perform a 0-timestep run
before using the variable. For example, these commands
The way to get around both of these special cases is to perform a
0-timestep run before evaluating the variable. For example, these
commands
.. code-block:: LAMMPS
variable t equal temp
print "Initial temperature = $t"
# delete_atoms random fraction 0.5 yes all NULL 49839
# run 0
variable t equal temp # this thermo keyword invokes a temperature compute
print "Temperature of system = $t"
run 1000
will generate an error if the run is the first run specified in the
input script, because generating a value for the "t" variable requires
a compute for calculating the temperature to be invoked.
will generate an error if the "run 1000" command is the first
simulation in the input script. If there were a previous run, these
commands will print the correct temperature of the system. But if the
:doc:`delete_atoms <delete_atoms>` command is uncommented, the printed
temperature will be incorrect, because information stored by
temperature compute is no longer valid.
However, this sequence of commands would be fine:
.. code-block:: LAMMPS
run 0
variable t equal temp
print "Initial temperature = $t"
run 1000
The 0-timestep run initializes and invokes various computes, including
the one for temperature, so that the value it stores is current and
can be accessed by the variable "t" after the run has completed. Note
that a 0-timestep run does not alter the state of the system, so it
does not change the input state for the 1000-timestep run that
follows. Also note that the 0-timestep run must actually use and
invoke the compute in question (e.g. via :doc:`thermo <thermo_style>` or
:doc:`dump <dump>` output) in order for it to enable the compute to be
used in a variable after the run. Thus if you are trying to print a
variable that uses a compute you have defined, you can ensure it is
invoked on the last timestep of the preceding run by including it in
thermodynamic output.
Unlike computes, :doc:`fixes <fix>` will never generate an error if
their values are accessed by a variable in between runs. They always
return some value to the variable. However, the value may not be what
you expect if the fix has not yet calculated the quantity of interest
or it is not current. For example, the :doc:`fix indent <fix_indent>`
command stores the force on the indenter. But this is not computed
until a run is performed. Thus if a variable attempts to print this
value before the first run, zeroes will be output. Again, performing
a 0-timestep run before printing the variable has the desired effect.
(3) The variable may be evaluated incorrectly and LAMMPS may have no
way to detect this has occurred. Consider the following sequence of
commands:
.. code-block:: LAMMPS
pair_coeff 1 1 1.0 1.0
run 1000
pair_coeff 1 1 1.5 1.0
variable e equal pe
print "Final potential energy = $e"
The first run is performed using one setting for the pairwise
potential defined by the :doc:`pair_style <pair_style>` and
:doc:`pair_coeff <pair_coeff>` commands. The potential energy is
evaluated on the final timestep and stored by the :doc:`compute pe
<compute_pe>` compute (this is done by the :doc:`thermo_style
<thermo_style>` command). Then a pair coefficient is changed,
altering the potential energy of the system. When the potential
energy is printed via the "e" variable, LAMMPS will use the potential
energy value stored by the :doc:`compute pe <compute_pe>` compute,
thinking it is current. There are many other commands which could
alter the state of the system between runs, causing a variable to
evaluate incorrectly.
The solution to this issue is the same as for case (2) above, namely
perform a 0-timestep run before the variable is evaluated to ensure
the system is up-to-date. For example, this sequence of commands
would print a potential energy that reflected the changed pairwise
coefficient:
.. code-block:: LAMMPS
pair_coeff 1 1 1.0 1.0
run 1000
pair_coeff 1 1 1.5 1.0
run 0
variable e equal pe
print "Final potential energy = $e"
Both these issues are resolved, if the "run 0" command is uncommented.
This is because the "run 0" simulation will initialize (or
re-initialize) the temperature compute correctly.
----------
@ -1482,11 +1427,12 @@ Restrictions
Indexing any formula element by global atom ID, such as an atom value,
requires the :doc:`atom style <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 :doc:`atom_modify map <atom_modify>` command can override the default, e.g. for
with molecular information create global maps. The :doc:`atom_modify
map <atom_modify>` command can override the default, e.g. for
atomic-style atom styles.
All *universe*\ - and *uloop*\ -style variables defined in an input script
must have the same number of values.
All *universe*\ - and *uloop*\ -style variables defined in an input
script must have the same number of values.
Related commands
""""""""""""""""