Merge pull request #3771 from lammps/variable-current

Change how variables check if computes are current
This commit is contained in:
Axel Kohlmeyer
2023-05-12 19:26:36 -04:00
committed by GitHub
10 changed files with 159 additions and 253 deletions

View File

@ -1420,132 +1420,75 @@ will occur when the formula for "vratio" is evaluated later.
Variable Accuracy Variable Accuracy
""""""""""""""""" """""""""""""""""
Obviously, LAMMPS attempts to evaluate variables containing formulas Obviously, LAMMPS attempts to evaluate variables which contain
(\ *equal* and *atom* style variables) accurately whenever the formulas (\ *equal* and *vector* and *atom* style variables)
evaluation is performed. Depending on what is included in the accurately whenever the evaluation is performed. Depending on what is
formula, this may require invoking a :doc:`compute <compute>`, either included in the formula, this may require invoking a :doc:`compute
directly or indirectly via a thermo keyword, or accessing a value <compute>`, either directly or indirectly via a thermo keyword, or
previously calculated by a compute, or accessing a value calculated accessing a value previously calculated by a compute, or accessing a
and stored by a :doc:`fix <fix>`. If the compute is one that calculates value calculated and stored by a :doc:`fix <fix>`. If the compute is
the pressure or energy of the system, then these quantities need to be one that calculates the energy or pressure of the system, then the
tallied during the evaluation of the interatomic potentials (pair, corresponding energy or virial quantities need to be tallied during
bond, etc) on timesteps that the variable will need the values. 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 LAMMPS keeps track of all of this as it performs a doc:`run <run>` or
attempt to evaluate a variable on timesteps when it cannot produce :doc:`minimize <minimize>` simulation, as well as in between
accurate values. For example, if a :doc:`thermo_style custom <thermo_style>` command prints a variable which accesses simulations. An error will be generated if you attempt to evaluate a
values stored by a :doc:`fix ave/time <fix_ave_time>` command and the variable when LAMMPS knows it cannot produce accurate values. For
timesteps on which thermo output is generated are not multiples of the example, if a :doc:`thermo_style custom <thermo_style>` command prints
averaging frequency used in the fix command, then an error will occur. 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 However, there are two special cases to be aware when a variable
after or in between runs, e.g. by including them in a requires invocation of a compute (directly or indirectly). The first
:doc:`print <print>` command. In this case, if a compute is needed to is if the variable is evaluated before the first doc:`run <run>` or
evaluate a variable (either directly or indirectly), LAMMPS will not :doc:`minimize <minimize>` command in the input script. In this case,
invoke the compute, but it will use a value previously calculated by LAMMPS will generate an error. This is because many computes require
the compute, and can do this only if it was invoked on the current initializations which have not yet taken place. One example is the
timestep. Fixes will always provide a quantity needed by a variable, calculation of degrees of freedom for temperature computes. Another
but the quantity may or may not be current. This leads to one of example are the computes mentioned above which require tallying of
three kinds of behavior: energy or virial quantities; these values are not tallied until the
first simulation begins.
(1) The variable may be evaluated accurately. If it contains The second special case is when a variable that depends on a compute
references to a compute or fix, and these values were calculated on is evaluated in between doc:`run <run>` or :doc:`minimize <minimize>`
the last timestep of a preceding run, then they will be accessed and commands. It is possible for other input script commands issued
used by the variable and the result will be accurate. 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 The way to get around both of these special cases is to perform a
an error message stating so. For example, if the variable requires a 0-timestep run before evaluating the variable. For example, these
quantity from a :doc:`compute <compute>` that has not been invoked on commands
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
.. code-block:: LAMMPS .. code-block:: LAMMPS
variable t equal temp # delete_atoms random fraction 0.5 yes all NULL 49839
print "Initial temperature = $t" # run 0
variable t equal temp # this thermo keyword invokes a temperature compute
print "Temperature of system = $t"
run 1000 run 1000
will generate an error if the run is the first run specified in the will generate an error if the "run 1000" command is the first
input script, because generating a value for the "t" variable requires simulation in the input script. If there were a previous run, these
a compute for calculating the temperature to be invoked. 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: Both these issues are resolved, if the "run 0" command is uncommented.
This is because the "run 0" simulation will initialize (or
.. code-block:: LAMMPS re-initialize) the temperature compute correctly.
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"
---------- ----------
@ -1555,11 +1498,12 @@ Restrictions
Indexing any formula element by global atom ID, such as an atom value, 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 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 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. atomic-style atom styles.
All *universe*\ - and *uloop*\ -style variables defined in an input script All *universe*\ - and *uloop*\ -style variables defined in an input
must have the same number of values. script must have the same number of values.
Related commands Related commands
"""""""""""""""" """"""""""""""""

View File

@ -294,21 +294,15 @@ int DumpVTK::count()
} }
// invoke Computes for per-atom quantities // invoke Computes for per-atom quantities
// only if within a run or minimize // cannot invoke before first run, otherwise invoke if necessary
// else require that computes are current
// this prevents a compute from being invoked by the WriteDump class
if (ncompute) { if (ncompute) {
if (update->whichflag == 0) { if (update->first_update == 0)
for (i = 0; i < ncompute; i++) error->all(FLERR,"Dump compute cannot be invoked before first run");
if (compute[i]->invoked_peratom != update->ntimestep) for (i = 0; i < ncompute; i++) {
error->all(FLERR,"Compute used in dump between runs is not current"); if (!(compute[i]->invoked_flag & Compute::INVOKED_PERATOM)) {
} else { compute[i]->compute_peratom();
for (i = 0; i < ncompute; i++) { compute[i]->invoked_flag |= Compute::INVOKED_PERATOM;
if (!(compute[i]->invoked_flag & Compute::INVOKED_PERATOM)) {
compute[i]->compute_peratom();
compute[i]->invoked_flag |= Compute::INVOKED_PERATOM;
}
} }
} }
} }

View File

@ -556,21 +556,15 @@ int DumpCustom::count()
} }
// invoke Computes for per-atom quantities // invoke Computes for per-atom quantities
// only if within a run or minimize // cannot invoke before first run, otherwise invoke if necessary
// else require that computes are current
// this prevents a compute from being invoked by the WriteDump class
if (ncompute) { if (ncompute) {
if (update->whichflag == 0) { if (update->first_update == 0)
for (i = 0; i < ncompute; i++) error->all(FLERR,"Dump compute cannot be invoked before first run");
if (compute[i]->invoked_peratom != update->ntimestep) for (i = 0; i < ncompute; i++) {
error->all(FLERR,"Compute used in dump between runs is not current"); if (!(compute[i]->invoked_flag & Compute::INVOKED_PERATOM)) {
} else { compute[i]->compute_peratom();
for (i = 0; i < ncompute; i++) { compute[i]->invoked_flag |= Compute::INVOKED_PERATOM;
if (!(compute[i]->invoked_flag & Compute::INVOKED_PERATOM)) {
compute[i]->compute_peratom();
compute[i]->invoked_flag |= Compute::INVOKED_PERATOM;
}
} }
} }
} }

View File

@ -522,21 +522,15 @@ int DumpGrid::count()
} }
// invoke Computes for per-grid quantities // invoke Computes for per-grid quantities
// only if within a run or minimize // cannot invoke before first run, otherwise invoke if necessary
// else require that computes are current
// this prevents a compute from being invoked by the WriteDump class
if (ncompute) { if (ncompute) {
if (update->whichflag == 0) { if (update->first_update == 0)
for (i = 0; i < ncompute; i++) error->all(FLERR,"Dump compute cannot be invoked before first run");
if (compute[i]->invoked_pergrid != update->ntimestep) for (i = 0; i < ncompute; i++) {
error->all(FLERR,"Compute {} used in dump between runs is not current", compute[i]->id); if (!(compute[i]->invoked_flag & Compute::INVOKED_PERGRID)) {
} else { compute[i]->compute_pergrid();
for (i = 0; i < ncompute; i++) { compute[i]->invoked_flag |= Compute::INVOKED_PERGRID;
if (!(compute[i]->invoked_flag & Compute::INVOKED_PERGRID)) {
compute[i]->compute_pergrid();
compute[i]->invoked_flag |= Compute::INVOKED_PERGRID;
}
} }
} }
} }

View File

@ -664,20 +664,14 @@ void DumpImage::write()
} }
// invoke Compute for per-grid quantities // invoke Compute for per-grid quantities
// only if within a run or minimize // cannot invoke before first run, otherwise invoke if necessary
// else require the compute is current
// this prevents the compute from being invoked by the WriteDump class
if (grid_compute) { if (grid_compute) {
if (update->whichflag == 0) { if (update->first_update == 0)
if (grid_compute->invoked_pergrid != update->ntimestep) error->all(FLERR,"Grid compute used in dump image cannot be invoked before first run");
error->all(FLERR,"Grid compute {} used in dump image between runs is not current", if (!(grid_compute->invoked_flag & Compute::INVOKED_PERGRID)) {
grid_compute->id); grid_compute->compute_pergrid();
} else { grid_compute->invoked_flag |= Compute::INVOKED_PERGRID;
if (!(grid_compute->invoked_flag & Compute::INVOKED_PERGRID)) {
grid_compute->compute_pergrid();
grid_compute->invoked_flag |= Compute::INVOKED_PERGRID;
}
} }
} }

View File

@ -325,21 +325,15 @@ int DumpLocal::count()
int i; int i;
// invoke Computes for local quantities // invoke Computes for local quantities
// only if within a run or minimize // cannot invoke before first run, otherwise invoke if necessary
// else require that computes are current
// this prevents a compute from being invoked by the WriteDump class
if (ncompute) { if (ncompute) {
if (update->whichflag == 0) { if (update->first_update == 0)
for (i = 0; i < ncompute; i++) error->all(FLERR,"Dump compute cannot be invoked before first run");
if (compute[i]->invoked_local != update->ntimestep) for (i = 0; i < ncompute; i++) {
error->all(FLERR,"Compute used in dump between runs is not current"); if (!(compute[i]->invoked_flag & Compute::INVOKED_LOCAL)) {
} else { compute[i]->compute_local();
for (i = 0; i < ncompute; i++) { compute[i]->invoked_flag |= Compute::INVOKED_LOCAL;
if (!(compute[i]->invoked_flag & Compute::INVOKED_LOCAL)) {
compute[i]->compute_local();
compute[i]->invoked_flag |= Compute::INVOKED_LOCAL;
}
} }
} }
} }

View File

@ -22,6 +22,7 @@
#include "group.h" #include "group.h"
#include "input.h" #include "input.h"
#include "modify.h" #include "modify.h"
#include "update.h"
#include "variable.h" #include "variable.h"
#include <cmath> #include <cmath>
@ -92,6 +93,14 @@ void ResetAtomsImage::command(int narg, char **arg)
"c_ifmax_r_i_f[*] c_ifmin_r_i_f[*]"); "c_ifmax_r_i_f[*] c_ifmin_r_i_f[*]");
// trigger computes // trigger computes
// need to ensure update->first_update = 1
// to allow this input script command prior to first run/minimize
// this is b/c internal variables are evaulated which invoke computes
// that will trigger an error unless first_update = 1
// reset update->first_update when done
int first_update_saved = update->first_update;
update->first_update = 1;
frags->compute_peratom(); frags->compute_peratom();
chunk->compute_peratom(); chunk->compute_peratom();
@ -100,6 +109,8 @@ void ResetAtomsImage::command(int narg, char **arg)
ifmax->compute_array(); ifmax->compute_array();
cdist->compute_peratom(); cdist->compute_peratom();
update->first_update = first_update_saved;
// reset image flags for atoms in group // reset image flags for atoms in group
const int *const mask = atom->mask; const int *const mask = atom->mask;

View File

@ -1118,7 +1118,7 @@ int Thermo::add_variable(const char *id)
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
check whether temperature compute is defined, available, and current check whether temperature compute is defined, active, and needs invoking
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Thermo::check_temp(const std::string &keyword) void Thermo::check_temp(const std::string &keyword)
@ -1126,18 +1126,16 @@ void Thermo::check_temp(const std::string &keyword)
if (!temperature) if (!temperature)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init temperature", error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init temperature",
keyword); keyword);
if (update->whichflag == 0) { if (update->first_update == 0)
if (temperature->invoked_scalar != update->ntimestep) error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current", if (!(temperature->invoked_flag & Compute::INVOKED_SCALAR)) {
temperature->style, temperature->id);
} else if (!(temperature->invoked_flag & Compute::INVOKED_SCALAR)) {
temperature->compute_scalar(); temperature->compute_scalar();
temperature->invoked_flag |= Compute::INVOKED_SCALAR; temperature->invoked_flag |= Compute::INVOKED_SCALAR;
} }
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
check whether potential energy compute is defined, available, and current check whether potential energy compute is defined, active, and needs invoking
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Thermo::check_pe(const std::string &keyword) void Thermo::check_pe(const std::string &keyword)
@ -1147,47 +1145,41 @@ void Thermo::check_pe(const std::string &keyword)
if (!pe) if (!pe)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init potential energy", error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init potential energy",
keyword); keyword);
if (update->whichflag == 0) { if (update->first_update == 0)
if (pe->invoked_scalar != update->ntimestep) error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current", if (!(pe->invoked_flag & Compute::INVOKED_SCALAR)) {
pe->style, pe->id);
} else {
pe->compute_scalar(); pe->compute_scalar();
pe->invoked_flag |= Compute::INVOKED_SCALAR; pe->invoked_flag |= Compute::INVOKED_SCALAR;
} }
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
check whether scalar pressure compute is defined, available, and current check whether scalar pressure compute is defined, active, and needs invoking
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Thermo::check_press_scalar(const std::string &keyword) void Thermo::check_press_scalar(const std::string &keyword)
{ {
if (!pressure) if (!pressure)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init press", keyword); error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init press", keyword);
if (update->whichflag == 0) { if (update->first_update == 0)
if (pressure->invoked_scalar != update->ntimestep) error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current", if (!(pressure->invoked_flag & Compute::INVOKED_SCALAR)) {
pressure->style, pressure->id);
} else if (!(pressure->invoked_flag & Compute::INVOKED_SCALAR)) {
pressure->compute_scalar(); pressure->compute_scalar();
pressure->invoked_flag |= Compute::INVOKED_SCALAR; pressure->invoked_flag |= Compute::INVOKED_SCALAR;
} }
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
check whether pressure tensor compute is defined, available, and current check whether tensor pressure compute is defined, active, and needs invoking
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void Thermo::check_press_vector(const std::string &keyword) void Thermo::check_press_vector(const std::string &keyword)
{ {
if (!pressure) if (!pressure)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init press", keyword); error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init press", keyword);
if (update->whichflag == 0) { if (update->first_update == 0)
if (pressure->invoked_vector != update->ntimestep) error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current", if (!(pressure->invoked_flag & Compute::INVOKED_VECTOR)) {
pressure->style, pressure->id);
} else if (!(pressure->invoked_flag & Compute::INVOKED_VECTOR)) {
pressure->compute_vector(); pressure->compute_vector();
pressure->invoked_flag |= Compute::INVOKED_VECTOR; pressure->invoked_flag |= Compute::INVOKED_VECTOR;
} }
@ -1214,8 +1206,6 @@ int Thermo::evaluate_keyword(const std::string &word, double *answer)
// invoke a lo-level thermo routine to compute the variable value // invoke a lo-level thermo routine to compute the variable value
// if keyword requires a compute, error if thermo doesn't use the compute // if keyword requires a compute, error if thermo doesn't use the compute
// if inbetween runs and needed compute is not current, error
// if in middle of run and needed compute is not current, invoke it
// for keywords that use energy (evdwl, ebond, etc): // for keywords that use energy (evdwl, ebond, etc):
// check if energy was tallied on this timestep and set pe->invoked_flag // check if energy was tallied on this timestep and set pe->invoked_flag
// this will trigger next timestep for energy tallying via addstep() // this will trigger next timestep for energy tallying via addstep()

View File

@ -1505,10 +1505,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (nbracket == 0 && compute->scalar_flag && lowercase) { if (nbracket == 0 && compute->scalar_flag && lowercase) {
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_scalar != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_SCALAR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_SCALAR)) {
compute->compute_scalar(); compute->compute_scalar();
compute->invoked_flag |= Compute::INVOKED_SCALAR; compute->invoked_flag |= Compute::INVOKED_SCALAR;
} }
@ -1528,10 +1527,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (index1 > compute->size_vector && if (index1 > compute->size_vector &&
compute->size_vector_variable == 0) compute->size_vector_variable == 0)
print_var_error(FLERR,"Variable formula compute vector is accessed out-of-range",ivar,0); print_var_error(FLERR,"Variable formula compute vector is accessed out-of-range",ivar,0);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_vector != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_vector(); compute->compute_vector();
compute->invoked_flag |= Compute::INVOKED_VECTOR; compute->invoked_flag |= Compute::INVOKED_VECTOR;
} }
@ -1555,10 +1553,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0); print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (index2 > compute->size_array_cols) if (index2 > compute->size_array_cols)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0); print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_array != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_array(); compute->compute_array();
compute->invoked_flag |= Compute::INVOKED_ARRAY; compute->invoked_flag |= Compute::INVOKED_ARRAY;
} }
@ -1583,10 +1580,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
print_var_error(FLERR,"Compute global vector in atom-style variable formula",ivar); print_var_error(FLERR,"Compute global vector in atom-style variable formula",ivar);
if (compute->size_vector == 0) if (compute->size_vector == 0)
print_var_error(FLERR,"Variable formula compute vector is zero length",ivar); print_var_error(FLERR,"Variable formula compute vector is zero length",ivar);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_vector != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_vector(); compute->compute_vector();
compute->invoked_flag |= Compute::INVOKED_VECTOR; compute->invoked_flag |= Compute::INVOKED_VECTOR;
} }
@ -1608,10 +1604,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
print_var_error(FLERR,"Compute global vector in atom-style variable formula",ivar); print_var_error(FLERR,"Compute global vector in atom-style variable formula",ivar);
if (compute->size_array_rows == 0) if (compute->size_array_rows == 0)
print_var_error(FLERR,"Variable formula compute array is zero length",ivar); print_var_error(FLERR,"Variable formula compute array is zero length",ivar);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_array != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_array(); compute->compute_array();
compute->invoked_flag |= Compute::INVOKED_ARRAY; compute->invoked_flag |= Compute::INVOKED_ARRAY;
} }
@ -1628,10 +1623,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
} else if (nbracket == 1 && compute->peratom_flag && } else if (nbracket == 1 && compute->peratom_flag &&
compute->size_peratom_cols == 0) { compute->size_peratom_cols == 0) {
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_peratom != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom(); compute->compute_peratom();
compute->invoked_flag |= Compute::INVOKED_PERATOM; compute->invoked_flag |= Compute::INVOKED_PERATOM;
} }
@ -1646,10 +1640,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
if (index2 > compute->size_peratom_cols) if (index2 > compute->size_peratom_cols)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0); print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_peratom != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom(); compute->compute_peratom();
compute->invoked_flag |= Compute::INVOKED_PERATOM; compute->invoked_flag |= Compute::INVOKED_PERATOM;
} }
@ -1670,10 +1663,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
print_var_error(FLERR,"Per-atom compute in equal-style variable formula",ivar); print_var_error(FLERR,"Per-atom compute in equal-style variable formula",ivar);
if (treetype == VECTOR) if (treetype == VECTOR)
print_var_error(FLERR,"Per-atom compute in vector-style variable formula",ivar); print_var_error(FLERR,"Per-atom compute in vector-style variable formula",ivar);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_peratom != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom(); compute->compute_peratom();
compute->invoked_flag |= Compute::INVOKED_PERATOM; compute->invoked_flag |= Compute::INVOKED_PERATOM;
} }
@ -1695,10 +1687,9 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
print_var_error(FLERR,"Per-atom compute in vector-style variable formula",ivar); print_var_error(FLERR,"Per-atom compute in vector-style variable formula",ivar);
if (index1 > compute->size_peratom_cols) if (index1 > compute->size_peratom_cols)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0); print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_peratom != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_peratom(); compute->compute_peratom();
compute->invoked_flag |= Compute::INVOKED_PERATOM; compute->invoked_flag |= Compute::INVOKED_PERATOM;
} }
@ -4163,10 +4154,9 @@ int Variable::special_function(char *word, char *contents, Tree **tree, Tree **t
print_var_error(FLERR,mesg,ivar); print_var_error(FLERR,mesg,ivar);
} }
if (index == 0 && compute->vector_flag) { if (index == 0 && compute->vector_flag) {
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_vector != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_vector(); compute->compute_vector();
compute->invoked_flag |= Compute::INVOKED_VECTOR; compute->invoked_flag |= Compute::INVOKED_VECTOR;
} }
@ -4175,10 +4165,9 @@ int Variable::special_function(char *word, char *contents, Tree **tree, Tree **t
} else if (index && compute->array_flag) { } else if (index && compute->array_flag) {
if (index > compute->size_array_cols) if (index > compute->size_array_cols)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0); print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) { if (update->first_update == 0)
if (compute->invoked_array != update->ntimestep) print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar); if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_array(); compute->compute_array();
compute->invoked_flag |= Compute::INVOKED_ARRAY; compute->invoked_flag |= Compute::INVOKED_ARRAY;
} }

View File

@ -18,7 +18,9 @@
%pointer_cast(void *, double *, void_p_to_double_p); %pointer_cast(void *, double *, void_p_to_double_p);
%pointer_cast(void *, double **, void_p_to_double_2d_p); %pointer_cast(void *, double **, void_p_to_double_2d_p);
#if !defined(SWIGLUA)
%cstring_output_maxsize(char *buffer, int buf_size); %cstring_output_maxsize(char *buffer, int buf_size);
#endif
%{ %{