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
"""""""""""""""""
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.
----------
@ -1555,11 +1498,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
""""""""""""""""

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@
#include "group.h"
#include "input.h"
#include "modify.h"
#include "update.h"
#include "variable.h"
#include <cmath>
@ -92,6 +93,14 @@ void ResetAtomsImage::command(int narg, char **arg)
"c_ifmax_r_i_f[*] c_ifmin_r_i_f[*]");
// 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();
chunk->compute_peratom();
@ -100,6 +109,8 @@ void ResetAtomsImage::command(int narg, char **arg)
ifmax->compute_array();
cdist->compute_peratom();
update->first_update = first_update_saved;
// reset image flags for atoms in group
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)
@ -1126,18 +1126,16 @@ void Thermo::check_temp(const std::string &keyword)
if (!temperature)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init temperature",
keyword);
if (update->whichflag == 0) {
if (temperature->invoked_scalar != update->ntimestep)
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current",
temperature->style, temperature->id);
} else if (!(temperature->invoked_flag & Compute::INVOKED_SCALAR)) {
if (update->first_update == 0)
error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
if (!(temperature->invoked_flag & Compute::INVOKED_SCALAR)) {
temperature->compute_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)
@ -1147,47 +1145,41 @@ void Thermo::check_pe(const std::string &keyword)
if (!pe)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init potential energy",
keyword);
if (update->whichflag == 0) {
if (pe->invoked_scalar != update->ntimestep)
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current",
pe->style, pe->id);
} else {
if (update->first_update == 0)
error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
if (!(pe->invoked_flag & Compute::INVOKED_SCALAR)) {
pe->compute_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)
{
if (!pressure)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init press", keyword);
if (update->whichflag == 0) {
if (pressure->invoked_scalar != update->ntimestep)
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current",
pressure->style, pressure->id);
} else if (!(pressure->invoked_flag & Compute::INVOKED_SCALAR)) {
if (update->first_update == 0)
error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
if (!(pressure->invoked_flag & Compute::INVOKED_SCALAR)) {
pressure->compute_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)
{
if (!pressure)
error->all(FLERR, "Thermo keyword {} in variable requires thermo to use/init press", keyword);
if (update->whichflag == 0) {
if (pressure->invoked_vector != update->ntimestep)
error->all(FLERR, "Compute {} {} used in variable thermo keyword between runs is not current",
pressure->style, pressure->id);
} else if (!(pressure->invoked_flag & Compute::INVOKED_VECTOR)) {
if (update->first_update == 0)
error->all(FLERR,"Thermo keyword {} cannot be invoked before first run",keyword);
if (!(pressure->invoked_flag & Compute::INVOKED_VECTOR)) {
pressure->compute_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
// 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):
// check if energy was tallied on this timestep and set pe->invoked_flag
// 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 (update->whichflag == 0) {
if (compute->invoked_scalar != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_SCALAR)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_SCALAR)) {
compute->compute_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 &&
compute->size_vector_variable == 0)
print_var_error(FLERR,"Variable formula compute vector is accessed out-of-range",ivar,0);
if (update->whichflag == 0) {
if (compute->invoked_vector != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_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);
if (index2 > compute->size_array_cols)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) {
if (compute->invoked_array != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_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);
if (compute->size_vector == 0)
print_var_error(FLERR,"Variable formula compute vector is zero length",ivar);
if (update->whichflag == 0) {
if (compute->invoked_vector != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_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);
if (compute->size_array_rows == 0)
print_var_error(FLERR,"Variable formula compute array is zero length",ivar);
if (update->whichflag == 0) {
if (compute->invoked_array != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_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 &&
compute->size_peratom_cols == 0) {
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_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)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_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);
if (treetype == VECTOR)
print_var_error(FLERR,"Per-atom compute in vector-style variable formula",ivar);
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_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);
if (index1 > compute->size_peratom_cols)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
compute->compute_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);
}
if (index == 0 && compute->vector_flag) {
if (update->whichflag == 0) {
if (compute->invoked_vector != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_VECTOR)) {
compute->compute_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) {
if (index > compute->size_array_cols)
print_var_error(FLERR,"Variable formula compute array is accessed out-of-range",ivar,0);
if (update->whichflag == 0) {
if (compute->invoked_array != update->ntimestep)
print_var_error(FLERR,"Compute used in variable between runs is not current",ivar);
} else if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
if (update->first_update == 0)
print_var_error(FLERR,"Variable formula compute cannot be invoked before first run",ivar);
if (!(compute->invoked_flag & Compute::INVOKED_ARRAY)) {
compute->compute_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_2d_p);
#if !defined(SWIGLUA)
%cstring_output_maxsize(char *buffer, int buf_size);
#endif
%{